* gas/elf/elf.exp (groupautob): Don't run on xtensa.
[deliverable/binutils-gdb.git] / gold / archive.cc
index 4411033eb52243bd59f1fcea1e63335d1e809126..541a49456a51a672fef7a2df0db95930b3ee5976 100644 (file)
 #include "readsyms.h"
 #include "symtab.h"
 #include "object.h"
+#include "layout.h"
 #include "archive.h"
 #include "plugin.h"
+#include "incremental.h"
 
 namespace gold
 {
@@ -88,7 +90,8 @@ Archive::Archive(const std::string& name, Input_file* input_file,
   : name_(name), input_file_(input_file), armap_(), armap_names_(),
     extended_names_(), armap_checked_(), seen_offsets_(), members_(),
     is_thin_archive_(is_thin_archive), included_member_(false),
-    nested_archives_(), dirpath_(dirpath), task_(task), num_members_(0)
+    nested_archives_(), dirpath_(dirpath), task_(task), num_members_(0),
+    incremental_info_(NULL)
 {
   this->no_export_ =
     parameters->options().check_excluded_libs(input_file->found_name());
@@ -563,7 +566,7 @@ Archive::get_elf_object_for_member(off_t off, bool* punconfigured)
       return NULL;
     }
 
-  Object *obj = make_elf_object((std::string(this->input_file_->filename())
+  Objectobj = make_elf_object((std::string(this->input_file_->filename())
                                 + "(" + member_name + ")"),
                                input_file, memoff, ehdr, read_size,
                                punconfigured);
@@ -602,20 +605,11 @@ Archive::read_symbols(off_t off)
   this->members_[off] = member;
 }
 
-// When we see a symbol in an archive we might decide to include the member,
-// not include the member or be undecided.  This enum represents these
-// possibilities.
-
-enum Should_include
-{
- SHOULD_INCLUDE_NO,
- SHOULD_INCLUDE_YES,
- SHOULD_INCLUDE_UNKNOWN
-};
-
-static Should_include
-should_include_member(Symbol_table* symtab, const char* sym_name, Symbol** symp,
-                      std::string* why, char** tmpbufp, size_t* tmpbuflen)
+Archive::Should_include
+Archive::should_include_member(Symbol_table* symtab, Layout* layout,
+                              const char* sym_name, Symbol** symp,
+                              std::string* why, char** tmpbufp,
+                               size_t* tmpbuflen)
 {
   // In an object file, and therefore in an archive map, an
   // '@' in the name separates the symbol name from the
@@ -658,20 +652,29 @@ should_include_member(Symbol_table* symtab, const char* sym_name, Symbol** symp,
   if (sym == NULL)
     {
       // Check whether the symbol was named in a -u option.
-      if (!parameters->options().is_undefined(sym_name))
-       return SHOULD_INCLUDE_UNKNOWN;
-      else
+      if (parameters->options().is_undefined(sym_name))
         {
           *why = "-u ";
           *why += sym_name;
         }
+      else if (layout->script_options()->is_referenced(sym_name))
+       {
+         size_t alc = 100 + strlen(sym_name);
+         char* buf = new char[alc];
+         snprintf(buf, alc, _("script or expression reference to %s"),
+                  sym_name);
+         *why = buf;
+         delete[] buf;
+       }
+      else
+       return Archive::SHOULD_INCLUDE_UNKNOWN;
     }
   else if (!sym->is_undefined())
-    return SHOULD_INCLUDE_NO;
+    return Archive::SHOULD_INCLUDE_NO;
   else if (sym->binding() == elfcpp::STB_WEAK)
-    return SHOULD_INCLUDE_UNKNOWN;
+    return Archive::SHOULD_INCLUDE_UNKNOWN;
 
-  return SHOULD_INCLUDE_YES;
+  return Archive::SHOULD_INCLUDE_YES;
 }
 
 // Select members from the archive and add them to the link.  We walk
@@ -735,14 +738,15 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout,
 
           Symbol* sym;
           std::string why;
-          Should_include t = should_include_member(symtab, sym_name,
-                                                   &sym, &why, &tmpbuf,
-                                                   &tmpbuflen);
+          Archive::Should_include t =
+           Archive::should_include_member(symtab, layout, sym_name, &sym,
+                                          &why, &tmpbuf, &tmpbuflen);
 
-         if (t == SHOULD_INCLUDE_NO || t == SHOULD_INCLUDE_YES)
+         if (t == Archive::SHOULD_INCLUDE_NO
+              || t == Archive::SHOULD_INCLUDE_YES)
            this->armap_checked_[i] = true;
 
-         if (t != SHOULD_INCLUDE_YES)
+         if (t != Archive::SHOULD_INCLUDE_YES)
            continue;
 
          // We want to include this object in the link.
@@ -840,9 +844,9 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
   std::map<off_t, Archive_member>::const_iterator p = this->members_.find(off);
   if (p != this->members_.end())
     {
-      Object *obj = p->second.obj_;
+      Objectobj = p->second.obj_;
 
-      Read_symbols_data *sd = p->second.sd_;
+      Read_symbols_datasd = p->second.sd_;
       if (mapfile != NULL)
         mapfile->report_include_archive_member(obj->name(), sym, why);
       if (input_objects->add_object(obj))
@@ -862,11 +866,7 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
       && this->searched_for()
       && obj == NULL
       && unconfigured)
-    {
-      if (obj != NULL)
-       delete obj;
-      return false;
-    }
+    return false;
 
   if (obj == NULL)
     return true;
@@ -883,13 +883,23 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
     }
 
   if (!input_objects->add_object(obj))
-    delete obj;
+    {
+      // If this is an external member of a thin archive, unlock the
+      // file.
+      if (obj->offset() == 0)
+       obj->unlock(this->task_);
+      delete obj;
+    }
   else
     {
-      Read_symbols_data sd;
-      obj->read_symbols(&sd);
-      obj->layout(symtab, layout, &sd);
-      obj->add_symbols(symtab, &sd, layout);
+      {
+       if (layout->incremental_inputs() != NULL)
+         layout->incremental_inputs()->report_object(obj, this);
+       Read_symbols_data sd;
+       obj->read_symbols(&sd);
+       obj->layout(symtab, layout, &sd);
+       obj->add_symbols(symtab, &sd, layout);
+      }
 
       // If this is an external member of a thin archive, unlock the file
       // for the next task.
@@ -946,6 +956,11 @@ Add_archive_symbols::locks(Task_locker* tl)
 void
 Add_archive_symbols::run(Workqueue* workqueue)
 {
+  // For an incremental link, begin recording layout information.
+  Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs();
+  if (incremental_inputs != NULL)
+    incremental_inputs->report_archive_begin(this->archive_);
+
   bool added = this->archive_->add_symbols(this->symtab_, this->layout_,
                                           this->input_objects_,
                                           this->mapfile_);
@@ -972,10 +987,171 @@ Add_archive_symbols::run(Workqueue* workqueue)
     this->input_group_->add_archive(this->archive_);
   else
     {
+      // For an incremental link, finish recording the layout information.
+      Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs();
+      if (incremental_inputs != NULL)
+       incremental_inputs->report_archive_end(this->archive_);
+
       // We no longer need to know about this archive.
       delete this->archive_;
       this->archive_ = NULL;
     }
 }
 
+// Class Lib_group static variables.
+unsigned int Lib_group::total_lib_groups;
+unsigned int Lib_group::total_members;
+unsigned int Lib_group::total_members_loaded;
+
+Lib_group::Lib_group(const Input_file_lib* lib, Task* task)
+  : lib_(lib), task_(task), members_()
+{
+  this->members_.resize(lib->size());
+}
+
+// Select members from the lib group and add them to the link.  We walk
+// through the the members, and check if each one up should be included.
+// If the object says it should be included, we do so.  We have to do
+// this in a loop, since including one member may create new undefined
+// symbols which may be satisfied by other members.
+
+void
+Lib_group::add_symbols(Symbol_table* symtab, Layout* layout,
+                       Input_objects* input_objects)
+{
+  ++Lib_group::total_lib_groups;
+
+  Lib_group::total_members += this->members_.size();
+
+  bool added_new_object;
+  do
+    {
+      added_new_object = false;
+      unsigned int i = 0;
+      while (i < this->members_.size())
+       {
+         const Archive_member& member = this->members_[i];
+         Object* obj = member.obj_;
+         std::string why;
+
+          // Skip files with no symbols. Plugin objects have
+          // member.sd_ == NULL.
+          if (obj != NULL
+             && (member.sd_ == NULL || member.sd_->symbol_names != NULL))
+            {
+             Archive::Should_include t = obj->should_include_member(symtab,
+                                                                    layout,
+                                                                    member.sd_,
+                                                                    &why);
+
+             if (t != Archive::SHOULD_INCLUDE_YES)
+               {
+                 ++i;
+                 continue;
+               }
+
+             this->include_member(symtab, layout, input_objects, member);
+
+             added_new_object = true;
+           }
+          else
+            {
+              if (member.sd_ != NULL)
+               {
+                 // The file must be locked in order to destroy the views
+                 // associated with it.
+                 gold_assert(obj != NULL);
+                 obj->lock(this->task_);
+                 delete member.sd_;
+                 obj->unlock(this->task_);
+               }
+            }
+
+         this->members_[i] = this->members_.back();
+         this->members_.pop_back();
+       }
+    }
+  while (added_new_object);
+}
+
+// Include a lib group member in the link.
+
+void
+Lib_group::include_member(Symbol_table* symtab, Layout* layout,
+                         Input_objects* input_objects,
+                         const Archive_member& member)
+{
+  ++Lib_group::total_members_loaded;
+
+  Object* obj = member.obj_;
+  gold_assert(obj != NULL);
+
+  Pluginobj* pluginobj = obj->pluginobj();
+  if (pluginobj != NULL)
+    {
+      pluginobj->add_symbols(symtab, NULL, layout);
+      return;
+    }
+
+  Read_symbols_data* sd = member.sd_;
+  gold_assert(sd != NULL);
+  obj->lock(this->task_);
+  if (input_objects->add_object(obj))
+    {
+      // FIXME: Record incremental link info for --start-lib/--end-lib.
+      if (layout->incremental_inputs() != NULL)
+       layout->incremental_inputs()->report_object(obj, NULL);
+      obj->layout(symtab, layout, sd);
+      obj->add_symbols(symtab, sd, layout);
+    }
+  delete sd;
+  // Unlock the file for the next task.
+  obj->unlock(this->task_);
+}
+
+// Print statistical information to stderr.  This is used for --stats.
+
+void
+Lib_group::print_stats()
+{
+  fprintf(stderr, _("%s: lib groups: %u\n"),
+          program_name, Lib_group::total_lib_groups);
+  fprintf(stderr, _("%s: total lib groups members: %u\n"),
+          program_name, Lib_group::total_members);
+  fprintf(stderr, _("%s: loaded lib groups members: %u\n"),
+          program_name, Lib_group::total_members_loaded);
+}
+
+Task_token*
+Add_lib_group_symbols::is_runnable()
+{
+  if (this->readsyms_blocker_ != NULL && this->readsyms_blocker_->is_blocked())
+    return this->readsyms_blocker_;
+  if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
+    return this->this_blocker_;
+  return NULL;
+}
+
+void
+Add_lib_group_symbols::locks(Task_locker* tl)
+{
+  tl->add(this, this->next_blocker_);
+}
+
+void
+Add_lib_group_symbols::run(Workqueue*)
+{
+  this->lib_->add_symbols(this->symtab_, this->layout_, this->input_objects_);
+
+  // FIXME: Record incremental link info for --start_lib/--end_lib.
+}
+
+Add_lib_group_symbols::~Add_lib_group_symbols()
+{
+  if (this->this_blocker_ != NULL)
+    delete this->this_blocker_;
+  // next_blocker_ is deleted by the task associated with the next
+  // input file.
+}
+
 } // End namespace gold.
This page took 0.026722 seconds and 4 git commands to generate.