opcodes/
[deliverable/binutils-gdb.git] / gold / object.cc
index e43ffdca2b6d819f4d0c5a1ffa9eb4164b5450f6..3a4f9f8c70e09343d158bcaca72f148f3841c394 100644 (file)
@@ -48,7 +48,8 @@ namespace gold
 
 // Struct Read_symbols_data.
 
-// Destroy any remaining File_view objects.
+// Destroy any remaining File_view objects and buffers of decompressed
+// sections.
 
 Read_symbols_data::~Read_symbols_data()
 {
@@ -330,7 +331,9 @@ Relobj::is_section_name_included(const char* name)
       || (is_prefix_of(".text", name)
          && strstr(name, "personality"))
       || (is_prefix_of(".data", name)
-         &&  strstr(name, "personality"))
+         && strstr(name, "personality"))
+      || (is_prefix_of(".sdata", name)
+         && strstr(name, "personality"))
       || (is_prefix_of(".gnu.linkonce.d", name)
          && strstr(name, "personality")))
     {
@@ -510,6 +513,64 @@ Sized_relobj_file<size, big_endian>::check_eh_frame_flags(
          && (shdr->get_sh_flags() & elfcpp::SHF_ALLOC) != 0);
 }
 
+// Find the section header with the given name.
+
+template<int size, bool big_endian>
+const unsigned char*
+Sized_relobj_file<size, big_endian>::find_shdr(
+    const unsigned char* pshdrs,
+    const char* name,
+    const char* names,
+    section_size_type names_size,
+    const unsigned char* hdr) const
+{
+  const unsigned int shnum = this->shnum();
+  const unsigned char* hdr_end = pshdrs + This::shdr_size * shnum;
+  size_t sh_name = 0;
+
+  while (1)
+    {
+      if (hdr)
+       {
+         // We found HDR last time we were called, continue looking.
+         typename This::Shdr shdr(hdr);
+         sh_name = shdr.get_sh_name();
+       }
+      else
+       {
+         // Look for the next occurrence of NAME in NAMES.
+         // The fact that .shstrtab produced by current GNU tools is
+         // string merged means we shouldn't have both .not.foo and
+         // .foo in .shstrtab, and multiple .foo sections should all
+         // have the same sh_name.  However, this is not guaranteed
+         // by the ELF spec and not all ELF object file producers may
+         // be so clever.
+         size_t len = strlen(name) + 1;
+         const char *p = sh_name ? names + sh_name + len : names;
+         p = reinterpret_cast<const char*>(memmem(p, names_size - (p - names),
+                                                  name, len));
+         if (p == NULL)
+           return NULL;
+         sh_name = p - names;
+         hdr = pshdrs;
+         if (sh_name == 0)
+           return hdr;
+       }
+
+      hdr += This::shdr_size;
+      while (hdr < hdr_end)
+       {
+         typename This::Shdr shdr(hdr);
+         if (shdr.get_sh_name() == sh_name)
+           return hdr;
+         hdr += This::shdr_size;
+       }
+      hdr = NULL;
+      if (sh_name == 0)
+       return hdr;
+    }
+}
+
 // Return whether there is a GNU .eh_frame section, given the section
 // headers and the section names.
 
@@ -520,26 +581,18 @@ Sized_relobj_file<size, big_endian>::find_eh_frame(
     const char* names,
     section_size_type names_size) const
 {
-  const unsigned int shnum = this->shnum();
-  const unsigned char* p = pshdrs + This::shdr_size;
-  for (unsigned int i = 1; i < shnum; ++i, p += This::shdr_size)
+  const unsigned char* s = NULL;
+
+  while (1)
     {
-      typename This::Shdr shdr(p);
-      if (this->check_eh_frame_flags(&shdr))
-       {
-         if (shdr.get_sh_name() >= names_size)
-           {
-             this->error(_("bad section name offset for section %u: %lu"),
-                         i, static_cast<unsigned long>(shdr.get_sh_name()));
-             continue;
-           }
+      s = this->find_shdr(pshdrs, ".eh_frame", names, names_size, s);
+      if (s == NULL)
+       return false;
 
-         const char* name = names + shdr.get_sh_name();
-         if (strcmp(name, ".eh_frame") == 0)
-           return true;
-       }
+      typename This::Shdr shdr(s);
+      if (this->check_eh_frame_flags(&shdr))
+       return true;
     }
-  return false;
 }
 
 // Return TRUE if this is a section whose contents will be needed in the
@@ -651,39 +704,46 @@ build_compressed_section_map(
   return uncompressed_map;
 }
 
+// Stash away info for a number of special sections.
+// Return true if any of the sections found require local symbols to be read.
+
+template<int size, bool big_endian>
+bool
+Sized_relobj_file<size, big_endian>::do_find_special_sections(
+    Read_symbols_data* sd)
+{
+  const unsigned char* const pshdrs = sd->section_headers->data();
+  const unsigned char* namesu = sd->section_names->data();
+  const char* names = reinterpret_cast<const char*>(namesu);
+
+  if (this->find_eh_frame(pshdrs, names, sd->section_names_size))
+    this->has_eh_frame_ = true;
+
+  if (memmem(names, sd->section_names_size, ".zdebug_", 8) != NULL)
+    this->compressed_sections_
+      = build_compressed_section_map(pshdrs, this->shnum(), names,
+                                    sd->section_names_size, this);
+  return (this->has_eh_frame_
+         || (!parameters->options().relocatable()
+             && parameters->options().gdb_index()
+             && (memmem(names, sd->section_names_size, "debug_info", 12) == 0
+                 || memmem(names, sd->section_names_size, "debug_types",
+                           13) == 0)));
+}
+
 // Read the sections and symbols from an object file.
 
 template<int size, bool big_endian>
 void
 Sized_relobj_file<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
 {
-  bool need_local_symbols = false;
-
   this->read_section_data(&this->elf_file_, sd);
 
   const unsigned char* const pshdrs = sd->section_headers->data();
 
   this->find_symtab(pshdrs);
 
-  const unsigned char* namesu = sd->section_names->data();
-  const char* names = reinterpret_cast<const char*>(namesu);
-  if (memmem(names, sd->section_names_size, ".eh_frame", 10) != NULL)
-    {
-      if (this->find_eh_frame(pshdrs, names, sd->section_names_size))
-       this->has_eh_frame_ = true;
-    }
-  if (memmem(names, sd->section_names_size, ".zdebug_", 8) != NULL)
-    this->compressed_sections_ =
-       build_compressed_section_map(pshdrs, this->shnum(), names,
-                                    sd->section_names_size, this);
-
-  if (this->has_eh_frame_
-      || (!parameters->options().relocatable()
-         && parameters->options().gdb_index()
-         && (memmem(names, sd->section_names_size, "debug_info", 12) == 0
-             || memmem(names, sd->section_names_size, "debug_types",
-                       13) == 0)))
-    need_local_symbols = true;
+  bool need_local_symbols = this->do_find_special_sections(sd);
 
   sd->symbols = NULL;
   sd->symbols_size = 0;
@@ -1164,15 +1224,19 @@ Sized_relobj_file<size, big_endian>::layout_eh_frame_section(
 // whether they should be included in the link.  If they should, we
 // pass them to the Layout object, which will return an output section
 // and an offset.
-// During garbage collection (--gc-sections) and identical code folding
-// (--icf), this function is called twice.  When it is called the first
-// time, it is for setting up some sections as roots to a work-list for
-// --gc-sections and to do comdat processing.  Actual layout happens the
-// second time around after all the relevant sections have been determined.
-// The first time, is_worklist_ready or is_icf_ready is false. It is then
-// set to true after the garbage collection worklist or identical code
-// folding is processed and the relevant sections to be kept are
-// determined.  Then, this function is called again to layout the sections.
+// This function is called twice sometimes, two passes, when mapping
+// of input sections to output sections must be delayed.
+// This is true for the following :
+// * Garbage collection (--gc-sections): Some input sections will be
+// discarded and hence the assignment must wait until the second pass.
+// In the first pass,  it is for setting up some sections as roots to
+// a work-list for --gc-sections and to do comdat processing.
+// * Identical Code Folding (--icf=<safe,all>): Some input sections
+// will be folded and hence the assignment must wait.
+// * Using plugins to map some sections to unique segments: Mapping
+// some sections to unique segments requires mapping them to unique
+// output sections too.  This can be done via plugins now and this
+// information is not available in the first pass.
 
 template<int size, bool big_endian>
 void
@@ -1181,26 +1245,44 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
                                               Read_symbols_data* sd)
 {
   const unsigned int shnum = this->shnum();
-  bool is_gc_pass_one = ((parameters->options().gc_sections()
-                         && !symtab->gc()->is_worklist_ready())
-                        || (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_enabled()
-                            && symtab->icf()->is_icf_ready()));
+  /* Should this function be called twice?  */
+  bool is_two_pass = (parameters->options().gc_sections()
+                     || parameters->options().icf_enabled()
+                     || layout->is_unique_segment_for_sections_specified());
 
-  bool is_gc_or_icf = (parameters->options().gc_sections()
-                      || parameters->options().icf_enabled());
+  /* Only one of is_pass_one and is_pass_two is true.  Both are false when
+     a two-pass approach is not needed.  */
+  bool is_pass_one = false;
+  bool is_pass_two = false;
 
-  // Both is_gc_pass_one and is_gc_pass_two should not be true.
-  gold_assert(!(is_gc_pass_one  && is_gc_pass_two));
+  Symbols_data* gc_sd = NULL;
 
+  /* Check if do_layout needs to be two-pass.  If so, find out which pass
+     should happen.  In the first pass, the data in sd is saved to be used
+     later in the second pass.  */
+  if (is_two_pass)
+    {
+      gc_sd = this->get_symbols_data();
+      if (gc_sd == NULL)
+       {
+         gold_assert(sd != NULL);
+         is_pass_one = true;
+       }
+      else
+       {
+         if (parameters->options().gc_sections())
+           gold_assert(symtab->gc()->is_worklist_ready());
+         if (parameters->options().icf_enabled())
+           gold_assert(symtab->icf()->is_icf_ready()); 
+         is_pass_two = true;
+       }
+    }
+    
   if (shnum == 0)
     return;
-  Symbols_data* gc_sd = NULL;
-  if (is_gc_pass_one)
+
+  if (is_pass_one)
     {
       // During garbage collection save the symbols data to use it when
       // re-entering this function.
@@ -1208,10 +1290,6 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
       this->copy_symbols_data(gc_sd, sd, This::shdr_size * shnum);
       this->set_symbols_data(gc_sd);
     }
-  else if (is_gc_pass_two)
-    {
-      gc_sd = this->get_symbols_data();
-    }
 
   const unsigned char* section_headers_data = NULL;
   section_size_type section_names_size;
@@ -1220,7 +1298,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
   const unsigned char* symbol_names_data = NULL;
   section_size_type symbol_names_size;
 
-  if (is_gc_or_icf)
+  if (is_two_pass)
     {
       section_headers_data = gc_sd->section_headers_data;
       section_names_size = gc_sd->section_names_size;
@@ -1246,9 +1324,9 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
   const unsigned char* pshdrs;
 
   // Get the section names.
-  const unsigned char* pnamesu = (is_gc_or_icf)
-                                ? gc_sd->section_names_data
-                                : sd->section_names->data();
+  const unsigned char* pnamesu = (is_two_pass
+                                 ? gc_sd->section_names_data
+                                 : sd->section_names->data());
 
   const char* pnames = reinterpret_cast<const char*>(pnamesu);
 
@@ -1298,7 +1376,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
   Output_sections& out_sections(this->output_sections());
   std::vector<Address>& out_section_offsets(this->section_offsets());
 
-  if (!is_gc_pass_two)
+  if (!is_pass_two)
     {
       out_sections.resize(shnum);
       out_section_offsets.resize(shnum);
@@ -1308,7 +1386,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
   // do here.
   if (this->input_file()->just_symbols())
     {
-      if (!is_gc_pass_two)
+      if (!is_pass_two)
        {
          delete sd->section_headers;
          sd->section_headers = NULL;
@@ -1360,7 +1438,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
 
       const char* name = pnames + shdr.get_sh_name();
 
-      if (!is_gc_pass_two)
+      if (!is_pass_two)
        {
          if (this->handle_gnu_warning_section(name, i, symtab))
            {
@@ -1434,9 +1512,10 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
            }
        }
 
-      if (is_gc_pass_one && parameters->options().gc_sections())
+      if (is_pass_one && parameters->options().gc_sections())
        {
          if (this->is_section_name_included(name)
+             || layout->keep_input_section (this, name)
              || shdr.get_sh_type() == elfcpp::SHT_INIT_ARRAY
              || shdr.get_sh_type() == elfcpp::SHT_FINI_ARRAY)
            {
@@ -1479,7 +1558,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
          && strcmp(name, ".eh_frame") == 0
          && this->check_eh_frame_flags(&shdr))
        {
-         if (is_gc_pass_one)
+         if (is_pass_one)
            {
              out_sections[i] = reinterpret_cast<Output_section*>(1);
              out_section_offsets[i] = invalid_address;
@@ -1494,7 +1573,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
          continue;
        }
 
-      if (is_gc_pass_two && parameters->options().gc_sections())
+      if (is_pass_two && parameters->options().gc_sections())
        {
          // This is executed during the second pass of garbage
          // collection. do_layout has been called before and some
@@ -1519,7 +1598,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
              }
        }
 
-      if (is_gc_pass_two && parameters->options().icf_enabled())
+      if (is_pass_two && parameters->options().icf_enabled())
        {
          if (out_sections[i] == NULL)
            {
@@ -1553,7 +1632,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
       // should_defer_layout should be false.
       if (should_defer_layout && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
        {
-         gold_assert(!is_gc_pass_two);
+         gold_assert(!is_pass_two);
          this->deferred_layout_.push_back(Deferred_layout(i, name,
                                                           pshdrs,
                                                           reloc_shndx[i],
@@ -1568,11 +1647,11 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
       // During gc_pass_two if a section that was previously deferred is
       // found, do not layout the section as layout_deferred_sections will
       // do it later from gold.cc.
-      if (is_gc_pass_two
+      if (is_pass_two
          && (out_sections[i] == reinterpret_cast<Output_section*>(2)))
        continue;
 
-      if (is_gc_pass_one)
+      if (is_pass_one)
        {
          // This is during garbage collection. The out_sections are
          // assigned in the second call to this function.
@@ -1603,7 +1682,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
        }
     }
 
-  if (!is_gc_pass_two)
+  if (!is_pass_two)
     layout->layout_gnu_stack(seen_gnu_stack, gnu_stack_flags, this);
 
   // When doing a relocatable link handle the reloc sections at the
@@ -1612,7 +1691,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
   if (emit_relocs)
     this->size_relocatable_relocs();
 
-  gold_assert(!(is_gc_or_icf) || reloc_sections.empty());
+  gold_assert(!is_two_pass || reloc_sections.empty());
 
   for (std::vector<unsigned int>::const_iterator p = reloc_sections.begin();
        p != reloc_sections.end();
@@ -1659,7 +1738,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
     }
 
   // Handle the .eh_frame sections at the end.
-  gold_assert(!is_gc_pass_one || eh_frame_sections.empty());
+  gold_assert(!is_pass_one || eh_frame_sections.empty());
   for (std::vector<unsigned int>::const_iterator p = eh_frame_sections.begin();
        p != eh_frame_sections.end();
        ++p)
@@ -1682,7 +1761,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
 
   // When building a .gdb_index section, scan the .debug_info and
   // .debug_types sections.
-  gold_assert(!is_gc_pass_one
+  gold_assert(!is_pass_one
              || (debug_info_sections.empty() && debug_types_sections.empty()));
   for (std::vector<unsigned int>::const_iterator p
           = debug_info_sections.begin();
@@ -1703,7 +1782,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
                               i, reloc_shndx[i], reloc_type[i]);
     }
 
-  if (is_gc_pass_two)
+  if (is_pass_two)
     {
       delete[] gc_sd->section_headers_data;
       delete[] gc_sd->section_names_data;
@@ -2033,7 +2112,8 @@ Sized_relobj_file<size, big_endian>::do_count_local_symbols(Stringpool* pool,
          continue;
        }
 
-      if (sym.get_st_type() == elfcpp::STT_SECTION)
+      if (sym.get_st_type() == elfcpp::STT_SECTION
+         || !this->adjust_local_symbol(&lv))
        {
          lv.set_no_output_symtab_entry();
          gold_assert(!lv.needs_output_dynsym_entry());
This page took 0.029963 seconds and 4 git commands to generate.