* object.cc (Sized_relobj::do_layout): Change to call layout_gnu_stack
[external/binutils.git] / gold / object.cc
index be6294c..7d50514 100644 (file)
@@ -1,6 +1,6 @@
 // object.cc -- support for an object file for linking in gold
 
-// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -231,6 +231,25 @@ Object::handle_gnu_warning_section(const char* name, unsigned int shndx,
   return false;
 }
 
+// If NAME is the name of the special section which indicates that
+// this object was compiled with -fstack-split, mark it accordingly.
+
+bool
+Object::handle_split_stack_section(const char* name)
+{
+  if (strcmp(name, ".note.GNU-split-stack") == 0)
+    {
+      this->uses_split_stack_ = true;
+      return true;
+    }
+  if (strcmp(name, ".note.GNU-no-split-stack") == 0)
+    {
+      this->has_no_split_stack_ = true;
+      return true;
+    }
+  return false;
+}
+
 // Class Relobj
 
 // To copy the symbols data read from the file to a local data structure.
@@ -296,8 +315,8 @@ Relobj::is_section_name_included(const char* name)
           && strstr(name, "personality")) 
       || (is_prefix_of(".data", name) 
           &&  strstr(name, "personality")) 
-      || (is_prefix_of(".gnu.linkonce.d", name) && 
-            strstr(name, "personality")))
+      || (is_prefix_of(".gnu.linkonce.d", name)
+         && strstr(name, "personality")))
     {
       return true; 
     }
@@ -336,14 +355,12 @@ Sized_relobj<size, big_endian>::~Sized_relobj()
 }
 
 // Set up an object file based on the file header.  This sets up the
-// target and reads the section information.
+// section information.
 
 template<int size, bool big_endian>
 void
-Sized_relobj<size, big_endian>::setup(Target *target)
+Sized_relobj<size, big_endian>::do_setup()
 {
-  this->set_target(target);
-
   const unsigned int shnum = this->elf_file_.shnum();
   this->set_shnum(shnum);
 }
@@ -917,16 +934,16 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
   const unsigned int shnum = this->shnum();
   bool is_gc_pass_one = ((parameters->options().gc_sections() 
                           && !symtab->gc()->is_worklist_ready())
-                         || (parameters->options().icf()
+                         || (parameters->options().icf_enabled()
                              && !symtab->icf()->is_icf_ready()));
  
   bool is_gc_pass_two = ((parameters->options().gc_sections() 
                           && symtab->gc()->is_worklist_ready())
-                         || (parameters->options().icf()
+                         || (parameters->options().icf_enabled()
                              && symtab->icf()->is_icf_ready()));
 
   bool is_gc_or_icf = (parameters->options().gc_sections()
-                       || parameters->options().icf()); 
+                       || parameters->options().icf_enabled()); 
 
   // Both is_gc_pass_one and is_gc_pass_two should not be true.
   gold_assert(!(is_gc_pass_one  && is_gc_pass_two));
@@ -1111,6 +1128,22 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
              omit[i] = true;
             }
 
+         // The .note.GNU-split-stack section is also special.  It
+         // indicates that the object was compiled with
+         // -fsplit-stack.
+         if (this->handle_split_stack_section(name))
+           {
+             if (!parameters->options().relocatable()
+                 && !parameters->options().shared())
+               omit[i] = true;
+           }
+
+         // Skip attributes section.
+         if (parameters->target().is_attributes_section(name))
+           {
+             omit[i] = true;
+           }
+
           bool discard = omit[i];
           if (!discard)
             {
@@ -1147,6 +1180,14 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
             {
               symtab->gc()->worklist().push(Section_id(this, i)); 
             }
+          // If the section name XXX can be represented as a C identifier
+          // it cannot be discarded if there are references to
+          // __start_XXX and __stop_XXX symbols.  These need to be
+          // specially handled.
+          if (is_cident(name))
+            {
+              symtab->gc()->add_cident_section(name, Section_id(this, i));
+            }
         }
 
       // When doing a relocatable link we are going to copy input
@@ -1211,7 +1252,7 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
               }
         }
 
-      if (is_gc_pass_two && parameters->options().icf())
+      if (is_gc_pass_two && parameters->options().icf_enabled())
         {
           if (out_sections[i] == NULL)
             {
@@ -1280,7 +1321,7 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
         }
     }
 
-  if (!is_gc_pass_one)
+  if (!is_gc_pass_two)
     layout->layout_gnu_stack(seen_gnu_stack, gnu_stack_flags);
 
   // When doing a relocatable link handle the reloc sections at the
@@ -1349,7 +1390,7 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
                                                   reloc_type[i],
                                                   &offset);
       out_sections[i] = os;
-      if (offset == -1)
+      if (os == NULL || offset == -1)
        {
          // An object can contain at most one section holding exception
          // frame information.
@@ -1363,7 +1404,7 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
       // If this section requires special handling, and if there are
       // relocs that apply to it, then we must do the special handling
       // before we apply the relocs.
-      if (offset == -1 && reloc_shndx[i] != 0)
+      if (os != NULL && offset == -1 && reloc_shndx[i] != 0)
        this->set_relocs_must_follow_section_writes();
     }
 
@@ -1494,6 +1535,7 @@ Sized_relobj<size, big_endian>::do_count_local_symbols(Stringpool* pool,
   unsigned int dyncount = 0;
   // Skip the first, dummy, symbol.
   psyms += sym_size;
+  bool discard_all = parameters->options().discard_all();
   bool discard_locals = parameters->options().discard_locals();
   for (unsigned int i = 1; i < loccount; ++i, psyms += sym_size)
     {
@@ -1517,7 +1559,7 @@ Sized_relobj<size, big_endian>::do_count_local_symbols(Stringpool* pool,
       // Decide whether this symbol should go into the output file.
 
       if ((shndx < shnum && out_sections[shndx] == NULL)
-         || (shndx == this->discarded_eh_frame_shndx_))
+         || shndx == this->discarded_eh_frame_shndx_)
         {
          lv.set_no_output_symtab_entry();
           gold_assert(!lv.needs_output_dynsym_entry());
@@ -1540,6 +1582,21 @@ Sized_relobj<size, big_endian>::do_count_local_symbols(Stringpool* pool,
          continue;
        }
 
+      const char* name = pnames + sym.get_st_name();
+
+      // If needed, add the symbol to the dynamic symbol table string pool.
+      if (lv.needs_output_dynsym_entry())
+        {
+          dynpool->add(name, true, NULL);
+          ++dyncount;
+        }
+
+      if (discard_all)
+       {
+         lv.set_no_output_symtab_entry();
+         continue;
+       }
+
       // If --discard-locals option is used, discard all temporary local
       // symbols.  These symbols start with system-specific local label
       // prefixes, typically .L for ELF system.  We want to be compatible
@@ -1552,7 +1609,6 @@ Sized_relobj<size, big_endian>::do_count_local_symbols(Stringpool* pool,
       //   - the symbol has a name.
       //
       // We do not discard a symbol if it needs a dynamic symbol entry.
-      const char* name = pnames + sym.get_st_name();
       if (discard_locals
          && sym.get_st_type() != elfcpp::STT_FILE
          && !lv.needs_output_dynsym_entry()
@@ -1562,16 +1618,17 @@ Sized_relobj<size, big_endian>::do_count_local_symbols(Stringpool* pool,
          continue;
        }
 
+      // Discard the local symbol if -retain_symbols_file is specified
+      // and the local symbol is not in that file.
+      if (!parameters->options().should_retain_symbol(name))
+        {
+          lv.set_no_output_symtab_entry();
+          continue;
+        }
+
       // Add the symbol to the symbol table string pool.
       pool->add(name, true, NULL);
       ++count;
-
-      // If needed, add the symbol to the dynamic symbol table string pool.
-      if (lv.needs_output_dynsym_entry())
-        {
-          dynpool->add(name, true, NULL);
-          ++dyncount;
-        }
     }
 
   this->output_local_symbol_count_ = count;
@@ -1642,7 +1699,15 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index,
               os = folded_obj->output_section(folded.second);
               gold_assert(os != NULL);
               secoffset = folded_obj->get_output_section_offset(folded.second);
-              gold_assert(secoffset != invalid_address);
+
+             // This could be a relaxed input section.
+              if (secoffset == invalid_address)
+               {
+                 const Output_relaxed_input_section* relaxed_section =
+                   os->find_relaxed_input_section(folded_obj, folded.second);
+                 gold_assert(relaxed_section != NULL);
+                 secoffset = relaxed_section->address() - os->address();
+               }
             }
 
          if (os == NULL)
@@ -1676,12 +1741,18 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index,
                }
              else if (!os->find_starting_output_address(this, shndx, &start))
                {
-                 // This is a section symbol, but apparently not one
-                 // in a merged section.  Just use the start of the
-                 // output section.  This happens with relocatable
-                 // links when the input object has section symbols
-                 // for arbitrary non-merge sections.
-                 lv.set_output_value(os->address());
+                 // This is a section symbol, but apparently not one in a
+                 // merged section.  First check to see if this is a relaxed
+                 // input section.  If so, use its address.  Otherwise just
+                 // use the start of the output section.  This happens with
+                 // relocatable links when the input object has section
+                 // symbols for arbitrary non-merge sections.
+                 const Output_section_data* posd =
+                   os->find_relaxed_input_section(this, shndx);
+                 if (posd != NULL)
+                   lv.set_output_value(posd->address());
+                 else
+                   lv.set_output_value(os->address());
                }
              else
                {
@@ -2059,16 +2130,6 @@ Sized_relobj<size, big_endian>::do_get_global_symbol_counts(
 bool
 Input_objects::add_object(Object* obj)
 {
-  // Set the global target from the first object file we recognize.
-  Target* target = obj->target();
-  if (!parameters->target_valid())
-    set_parameters_target(target);
-  else if (target != &parameters->target())
-    {
-      obj->error(_("incompatible target"));
-      return false;
-    }
-
   // Print the filename if the -t/--trace option is selected.
   if (parameters->options().trace())
     gold_info("%s", obj->name().c_str());
@@ -2093,7 +2154,8 @@ Input_objects::add_object(Object* obj)
     }
 
   // Add this object to the cross-referencer if requested.
-  if (parameters->options().user_set_print_symbol_counts())
+  if (parameters->options().user_set_print_symbol_counts()
+      || parameters->options().cref())
     {
       if (this->cref_ == NULL)
        this->cref_ = new Cref();
@@ -2109,15 +2171,15 @@ Input_objects::add_object(Object* obj)
 void
 Input_objects::check_dynamic_dependencies() const
 {
+  bool issued_copy_dt_needed_error = false;
   for (Dynobj_list::const_iterator p = this->dynobj_list_.begin();
        p != this->dynobj_list_.end();
        ++p)
     {
       const Dynobj::Needed& needed((*p)->needed());
       bool found_all = true;
-      for (Dynobj::Needed::const_iterator pneeded = needed.begin();
-          pneeded != needed.end();
-          ++pneeded)
+      Dynobj::Needed::const_iterator pneeded;
+      for (pneeded = needed.begin(); pneeded != needed.end(); ++pneeded)
        {
          if (this->sonames_.find(*pneeded) == this->sonames_.end())
            {
@@ -2126,6 +2188,25 @@ Input_objects::check_dynamic_dependencies() const
            }
        }
       (*p)->set_has_unknown_needed_entries(!found_all);
+
+      // --copy-dt-needed-entries aka --add-needed is a GNU ld option
+      // --that gold does not support.  However, they cause no trouble
+      // --unless there is a DT_NEEDED entry that we don't know about;
+      // --warn only in that case.
+      if (!found_all
+         && !issued_copy_dt_needed_error
+         && (parameters->options().copy_dt_needed_entries()
+             || parameters->options().add_needed()))
+       {
+         const char* optname;
+         if (parameters->options().copy_dt_needed_entries())
+           optname = "--copy-dt-needed-entries";
+         else
+           optname = "--add-needed";
+         gold_error(_("%s is not supported but is required for %s in %s"),
+                    optname, (*pneeded).c_str(), (*p)->name().c_str());
+         issued_copy_dt_needed_error = true;
+       }
     }
 }
 
@@ -2134,7 +2215,8 @@ Input_objects::check_dynamic_dependencies() const
 void
 Input_objects::archive_start(Archive* archive)
 {
-  if (parameters->options().user_set_print_symbol_counts())
+  if (parameters->options().user_set_print_symbol_counts()
+      || parameters->options().cref())
     {
       if (this->cref_ == NULL)
        this->cref_ = new Cref();
@@ -2147,7 +2229,8 @@ Input_objects::archive_start(Archive* archive)
 void
 Input_objects::archive_stop(Archive* archive)
 {
-  if (parameters->options().user_set_print_symbol_counts())
+  if (parameters->options().user_set_print_symbol_counts()
+      || parameters->options().cref())
     this->cref_->add_archive_stop(archive);
 }
 
@@ -2161,6 +2244,15 @@ Input_objects::print_symbol_counts(const Symbol_table* symtab) const
     this->cref_->print_symbol_counts(symtab);
 }
 
+// Print a cross reference table.
+
+void
+Input_objects::print_cref(const Symbol_table* symtab, FILE* f) const
+{
+  if (parameters->options().cref() && this->cref_ != NULL)
+    this->cref_->print_cref(symtab, f);
+}
+
 // Relocate_info methods.
 
 // Return a string describing the location of a relocation.  This is
@@ -2219,7 +2311,8 @@ using namespace gold;
 template<int size, bool big_endian>
 Object*
 make_elf_sized_object(const std::string& name, Input_file* input_file,
-                     off_t offset, const elfcpp::Ehdr<size, big_endian>& ehdr)
+                     off_t offset, const elfcpp::Ehdr<size, big_endian>& ehdr,
+                     bool* punconfigured)
 {
   Target* target = select_target(ehdr.get_e_machine(), size, big_endian,
                                 ehdr.get_e_ident()[elfcpp::EI_OSABI],
@@ -2227,6 +2320,18 @@ make_elf_sized_object(const std::string& name, Input_file* input_file,
   if (target == NULL)
     gold_fatal(_("%s: unsupported ELF machine number %d"),
               name.c_str(), ehdr.get_e_machine());
+
+  if (!parameters->target_valid())
+    set_parameters_target(target);
+  else if (target != &parameters->target())
+    {
+      if (punconfigured != NULL)
+       *punconfigured = true;
+      else
+       gold_error(_("%s: incompatible target"), name.c_str());
+      return NULL;
+    }
+
   return target->make_elf_object<size, big_endian>(name, input_file, offset,
                                                   ehdr);
 }
@@ -2243,7 +2348,7 @@ is_elf_object(Input_file* input_file, off_t offset,
              const unsigned char** start, int *read_size)
 {
   off_t filesize = input_file->file().filesize();
-  int want = elfcpp::Elf_sizes<64>::ehdr_size;
+  int want = elfcpp::Elf_recognizer::max_header_size;
   if (filesize - offset < want)
     want = filesize - offset;
 
@@ -2252,15 +2357,7 @@ is_elf_object(Input_file* input_file, off_t offset,
   *start = p;
   *read_size = want;
 
-  if (want < 4)
-    return false;
-
-  static unsigned char elfmagic[4] =
-    {
-      elfcpp::ELFMAG0, elfcpp::ELFMAG1,
-      elfcpp::ELFMAG2, elfcpp::ELFMAG3
-    };
-  return memcmp(p, elfmagic, 4) == 0;
+  return elfcpp::Elf_recognizer::is_elf_file(p, want);
 }
 
 // Read an ELF file and return the appropriate instance of Object.
@@ -2273,63 +2370,24 @@ make_elf_object(const std::string& name, Input_file* input_file, off_t offset,
   if (punconfigured != NULL)
     *punconfigured = false;
 
-  if (bytes < elfcpp::EI_NIDENT)
-    {
-      gold_error(_("%s: ELF file too short"), name.c_str());
-      return NULL;
-    }
-
-  int v = p[elfcpp::EI_VERSION];
-  if (v != elfcpp::EV_CURRENT)
-    {
-      if (v == elfcpp::EV_NONE)
-       gold_error(_("%s: invalid ELF version 0"), name.c_str());
-      else
-       gold_error(_("%s: unsupported ELF version %d"), name.c_str(), v);
-      return NULL;
-    }
-
-  int c = p[elfcpp::EI_CLASS];
-  if (c == elfcpp::ELFCLASSNONE)
-    {
-      gold_error(_("%s: invalid ELF class 0"), name.c_str());
-      return NULL;
-    }
-  else if (c != elfcpp::ELFCLASS32
-          && c != elfcpp::ELFCLASS64)
-    {
-      gold_error(_("%s: unsupported ELF class %d"), name.c_str(), c);
-      return NULL;
-    }
-
-  int d = p[elfcpp::EI_DATA];
-  if (d == elfcpp::ELFDATANONE)
+  std::string error;
+  bool big_endian = false;
+  int size = 0;
+  if (!elfcpp::Elf_recognizer::is_valid_header(p, bytes, &size,
+                                               &big_endian, &error))
     {
-      gold_error(_("%s: invalid ELF data encoding"), name.c_str());
-      return NULL;
-    }
-  else if (d != elfcpp::ELFDATA2LSB
-          && d != elfcpp::ELFDATA2MSB)
-    {
-      gold_error(_("%s: unsupported ELF data encoding %d"), name.c_str(), d);
+      gold_error(_("%s: %s"), name.c_str(), error.c_str());
       return NULL;
     }
 
-  bool big_endian = d == elfcpp::ELFDATA2MSB;
-
-  if (c == elfcpp::ELFCLASS32)
+  if (size == 32)
     {
-      if (bytes < elfcpp::Elf_sizes<32>::ehdr_size)
-       {
-         gold_error(_("%s: ELF file too short"), name.c_str());
-         return NULL;
-       }
       if (big_endian)
        {
 #ifdef HAVE_TARGET_32_BIG
          elfcpp::Ehdr<32, true> ehdr(p);
          return make_elf_sized_object<32, true>(name, input_file,
-                                                offset, ehdr);
+                                                offset, ehdr, punconfigured);
 #else
          if (punconfigured != NULL)
            *punconfigured = true;
@@ -2345,7 +2403,7 @@ make_elf_object(const std::string& name, Input_file* input_file, off_t offset,
 #ifdef HAVE_TARGET_32_LITTLE
          elfcpp::Ehdr<32, false> ehdr(p);
          return make_elf_sized_object<32, false>(name, input_file,
-                                                 offset, ehdr);
+                                                 offset, ehdr, punconfigured);
 #else
          if (punconfigured != NULL)
            *punconfigured = true;
@@ -2357,19 +2415,14 @@ make_elf_object(const std::string& name, Input_file* input_file, off_t offset,
 #endif
        }
     }
-  else
+  else if (size == 64)
     {
-      if (bytes < elfcpp::Elf_sizes<64>::ehdr_size)
-       {
-         gold_error(_("%s: ELF file too short"), name.c_str());
-         return NULL;
-       }
       if (big_endian)
        {
 #ifdef HAVE_TARGET_64_BIG
          elfcpp::Ehdr<64, true> ehdr(p);
          return make_elf_sized_object<64, true>(name, input_file,
-                                                offset, ehdr);
+                                                offset, ehdr, punconfigured);
 #else
          if (punconfigured != NULL)
            *punconfigured = true;
@@ -2385,7 +2438,7 @@ make_elf_object(const std::string& name, Input_file* input_file, off_t offset,
 #ifdef HAVE_TARGET_64_LITTLE
          elfcpp::Ehdr<64, false> ehdr(p);
          return make_elf_sized_object<64, false>(name, input_file,
-                                                 offset, ehdr);
+                                                 offset, ehdr, punconfigured);
 #else
          if (punconfigured != NULL)
            *punconfigured = true;
@@ -2397,6 +2450,8 @@ make_elf_object(const std::string& name, Input_file* input_file, off_t offset,
 #endif
        }
     }
+  else
+    gold_unreachable();
 }
 
 // Instantiate the templates we need.
@@ -2469,4 +2524,48 @@ template
 struct Relocate_info<64, true>;
 #endif
 
+#ifdef HAVE_TARGET_32_LITTLE
+template
+void
+Xindex::initialize_symtab_xindex<32, false>(Object*, unsigned int);
+
+template
+void
+Xindex::read_symtab_xindex<32, false>(Object*, unsigned int,
+                                     const unsigned char*);
+#endif
+
+#ifdef HAVE_TARGET_32_BIG
+template
+void
+Xindex::initialize_symtab_xindex<32, true>(Object*, unsigned int);
+
+template
+void
+Xindex::read_symtab_xindex<32, true>(Object*, unsigned int,
+                                    const unsigned char*);
+#endif
+
+#ifdef HAVE_TARGET_64_LITTLE
+template
+void
+Xindex::initialize_symtab_xindex<64, false>(Object*, unsigned int);
+
+template
+void
+Xindex::read_symtab_xindex<64, false>(Object*, unsigned int,
+                                     const unsigned char*);
+#endif
+
+#ifdef HAVE_TARGET_64_BIG
+template
+void
+Xindex::initialize_symtab_xindex<64, true>(Object*, unsigned int);
+
+template
+void
+Xindex::read_symtab_xindex<64, true>(Object*, unsigned int,
+                                    const unsigned char*);
+#endif
+
 } // End namespace gold.