Add icf_virtual_function_folding_test to check_PROGRAMS.
[binutils-gdb.git] / gold / layout.cc
index 13c7f7eab0d7d7b1836a4316951ee2917b2bb117..2ffbdf49770288e42a7cb2ab9c0825adaf260e56 100644 (file)
@@ -1,6 +1,6 @@
 // layout.cc -- lay out output file sections for 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.
@@ -352,6 +352,11 @@ Layout::include_section(Sized_relobj<size, big_endian>*, const char* name,
           if (is_prefix_of(".gnu.lto_", name))
             return false;
         }
+      // The GNU linker strips .gnu_debuglink sections, so we do too.
+      // This is a feature used to keep debugging information in
+      // separate files.
+      if (strcmp(name, ".gnu_debuglink") == 0)
+       return false;
       return true;
 
     default:
@@ -497,13 +502,27 @@ Layout::choose_output_section(const Relobj* relobj, const char* name,
       Script_sections* ss = this->script_options_->script_sections();
       const char* file_name = relobj == NULL ? NULL : relobj->name().c_str();
       Output_section** output_section_slot;
-      name = ss->output_section_name(file_name, name, &output_section_slot);
+      Script_sections::Section_type script_section_type;
+      name = ss->output_section_name(file_name, name, &output_section_slot,
+                                    &script_section_type);
       if (name == NULL)
        {
          // The SECTIONS clause says to discard this input section.
          return NULL;
        }
 
+      // We can only handle script section types ST_NONE and ST_NOLOAD.
+      switch (script_section_type)
+       {
+       case Script_sections::ST_NONE:
+         break;
+       case Script_sections::ST_NOLOAD:
+         flags &= elfcpp::SHF_ALLOC;
+         break;
+       default:
+         gold_unreachable();
+       }
+
       // If this is an orphan section--one not mentioned in the linker
       // script--then OUTPUT_SECTION_SLOT will be NULL, and we do the
       // default processing below.
@@ -528,6 +547,25 @@ Layout::choose_output_section(const Relobj* relobj, const char* name,
                                      is_dynamic_linker_section, is_relro,
                                      is_last_relro, is_first_non_relro);
          os->set_found_in_sections_clause();
+
+         // Special handling for NOLOAD sections.
+         if (script_section_type == Script_sections::ST_NOLOAD)
+           {
+             os->set_is_noload();
+
+             // The constructor of Output_section sets addresses of non-ALLOC
+             // sections to 0 by default.  We don't want that for NOLOAD
+             // sections even if they have no SHF_ALLOC flag.
+             if ((os->flags() & elfcpp::SHF_ALLOC) == 0
+                 && os->is_address_valid())
+               {
+                 gold_assert(os->address() == 0
+                             && !os->is_offset_valid()
+                             && !os->is_data_size_valid());
+                 os->reset_address_and_file_offset();
+               }
+           }
+
          *output_section_slot = os;
          return os;
        }
@@ -577,19 +615,40 @@ Layout::layout(Sized_relobj<size, big_endian>* object, unsigned int shndx,
 
   Output_section* os;
 
+  // Sometimes .init_array*, .preinit_array* and .fini_array* do not have
+  // correct section types.  Force them here.
+  elfcpp::Elf_Word sh_type = shdr.get_sh_type();
+  if (sh_type == elfcpp::SHT_PROGBITS)
+    {
+      static const char init_array_prefix[] = ".init_array";
+      static const char preinit_array_prefix[] = ".preinit_array";
+      static const char fini_array_prefix[] = ".fini_array";
+      static size_t init_array_prefix_size = sizeof(init_array_prefix) - 1;
+      static size_t preinit_array_prefix_size =
+       sizeof(preinit_array_prefix) - 1;
+      static size_t fini_array_prefix_size = sizeof(fini_array_prefix) - 1;
+
+      if (strncmp(name, init_array_prefix, init_array_prefix_size) == 0)
+       sh_type = elfcpp::SHT_INIT_ARRAY;
+      else if (strncmp(name, preinit_array_prefix, preinit_array_prefix_size)
+              == 0)
+       sh_type = elfcpp::SHT_PREINIT_ARRAY;
+      else if (strncmp(name, fini_array_prefix, fini_array_prefix_size) == 0)
+       sh_type = elfcpp::SHT_FINI_ARRAY;
+    }
+
   // In a relocatable link a grouped section must not be combined with
   // any other sections.
   if (parameters->options().relocatable()
       && (shdr.get_sh_flags() & elfcpp::SHF_GROUP) != 0)
     {
       name = this->namepool_.add(name, true, NULL);
-      os = this->make_output_section(name, shdr.get_sh_type(),
-                                    shdr.get_sh_flags(), false, false,
-                                    false, false, false);
+      os = this->make_output_section(name, sh_type, shdr.get_sh_flags(), false,
+                                    false, false, false, false);
     }
   else
     {
-      os = this->choose_output_section(object, name, shdr.get_sh_type(),
+      os = this->choose_output_section(object, name, sh_type,
                                       shdr.get_sh_flags(), true, false,
                                       false, false, false, false);
       if (os == NULL)
@@ -1131,13 +1190,20 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
 // Make an output section for a script.
 
 Output_section*
-Layout::make_output_section_for_script(const char* name)
+Layout::make_output_section_for_script(
+    const char* name,
+    Script_sections::Section_type section_type)
 {
   name = this->namepool_.add(name, false, NULL);
+  elfcpp::Elf_Xword sh_flags = elfcpp::SHF_ALLOC;
+  if (section_type == Script_sections::ST_NOLOAD)
+    sh_flags = 0;
   Output_section* os = this->make_output_section(name, elfcpp::SHT_PROGBITS,
-                                                elfcpp::SHF_ALLOC, false,
+                                                sh_flags, false,
                                                 false, false, false, false);
   os->set_found_in_sections_clause();
+  if (section_type == Script_sections::ST_NOLOAD)
+    os->set_is_noload();
   return os;
 }
 
@@ -1232,16 +1298,13 @@ Layout::define_section_symbols(Symbol_table* symtab)
        ++p)
     {
       const char* const name = (*p)->name();
-      if (name[strspn(name,
-                     ("0123456789"
-                      "ABCDEFGHIJKLMNOPWRSTUVWXYZ"
-                      "abcdefghijklmnopqrstuvwxyz"
-                      "_"))]
-         == '\0')
+      if (is_cident(name))
        {
          const std::string name_string(name);
-         const std::string start_name("__start_" + name_string);
-         const std::string stop_name("__stop_" + name_string);
+         const std::string start_name(cident_section_start_prefix
+                                       + name_string);
+         const std::string stop_name(cident_section_stop_prefix
+                                      + name_string);
 
          symtab->define_in_output_data(start_name.c_str(),
                                        NULL, // version
@@ -1399,8 +1462,15 @@ Layout::clean_up_after_relaxation()
        p != this->section_list_.end();
        ++p)
     {
-      (*p)->reset_address_and_file_offset();
       (*p)->restore_states();
+
+      // If an input section changes size because of relaxation,
+      // we need to adjust the section offsets of all input sections.
+      // after such a section.
+      if ((*p)->section_offsets_need_adjustment())
+       (*p)->adjust_section_offsets();
+
+      (*p)->reset_address_and_file_offset();
     }
   
   // Reset special output object address and file offsets.
@@ -3209,6 +3279,99 @@ Layout::create_interp(const Target* target)
     }
 }
 
+// Add dynamic tags for the PLT and the dynamic relocs.  This is
+// called by the target-specific code.  This does nothing if not doing
+// a dynamic link.
+
+// USE_REL is true for REL relocs rather than RELA relocs.
+
+// If PLT_GOT is not NULL, then DT_PLTGOT points to it.
+
+// If PLT_REL is not NULL, it is used for DT_PLTRELSZ, and DT_JMPREL,
+// and we also set DT_PLTREL.  We use PLT_REL's output section, since
+// some targets have multiple reloc sections in PLT_REL.
+
+// If DYN_REL is not NULL, it is used for DT_REL/DT_RELA,
+// DT_RELSZ/DT_RELASZ, DT_RELENT/DT_RELAENT.
+
+// If ADD_DEBUG is true, we add a DT_DEBUG entry when generating an
+// executable.
+
+void
+Layout::add_target_dynamic_tags(bool use_rel, const Output_data* plt_got,
+                               const Output_data* plt_rel,
+                               const Output_data_reloc_generic* dyn_rel,
+                               bool add_debug, bool dynrel_includes_plt)
+{
+  Output_data_dynamic* odyn = this->dynamic_data_;
+  if (odyn == NULL)
+    return;
+
+  if (plt_got != NULL && plt_got->output_section() != NULL)
+    odyn->add_section_address(elfcpp::DT_PLTGOT, plt_got);
+
+  if (plt_rel != NULL && plt_rel->output_section() != NULL)
+    {
+      odyn->add_section_size(elfcpp::DT_PLTRELSZ, plt_rel->output_section());
+      odyn->add_section_address(elfcpp::DT_JMPREL, plt_rel->output_section());
+      odyn->add_constant(elfcpp::DT_PLTREL,
+                        use_rel ? elfcpp::DT_REL : elfcpp::DT_RELA);
+    }
+
+  if (dyn_rel != NULL && dyn_rel->output_section() != NULL)
+    {
+      odyn->add_section_address(use_rel ? elfcpp::DT_REL : elfcpp::DT_RELA,
+                               dyn_rel);
+      if (plt_rel != NULL && dynrel_includes_plt)
+       odyn->add_section_size(use_rel ? elfcpp::DT_RELSZ : elfcpp::DT_RELASZ,
+                              dyn_rel, plt_rel);
+      else
+       odyn->add_section_size(use_rel ? elfcpp::DT_RELSZ : elfcpp::DT_RELASZ,
+                              dyn_rel);
+      const int size = parameters->target().get_size();
+      elfcpp::DT rel_tag;
+      int rel_size;
+      if (use_rel)
+       {
+         rel_tag = elfcpp::DT_RELENT;
+         if (size == 32)
+           rel_size = Reloc_types<elfcpp::SHT_REL, 32, false>::reloc_size;
+         else if (size == 64)
+           rel_size = Reloc_types<elfcpp::SHT_REL, 64, false>::reloc_size;
+         else
+           gold_unreachable();
+       }
+      else
+       {
+         rel_tag = elfcpp::DT_RELAENT;
+         if (size == 32)
+           rel_size = Reloc_types<elfcpp::SHT_RELA, 32, false>::reloc_size;
+         else if (size == 64)
+           rel_size = Reloc_types<elfcpp::SHT_RELA, 64, false>::reloc_size;
+         else
+           gold_unreachable();
+       }
+      odyn->add_constant(rel_tag, rel_size);
+
+      if (parameters->options().combreloc())
+       {
+         size_t c = dyn_rel->relative_reloc_count();
+         if (c > 0)
+           odyn->add_constant((use_rel
+                               ? elfcpp::DT_RELCOUNT
+                               : elfcpp::DT_RELACOUNT),
+                              c);
+       }
+    }
+
+  if (add_debug && !parameters->options().shared())
+    {
+      // The value of the DT_DEBUG tag is filled in by the dynamic
+      // linker at run time, and used by the debugger.
+      odyn->add_constant(elfcpp::DT_DEBUG, 0);
+    }
+}
+
 // Finish the .dynamic section and PT_DYNAMIC segment.
 
 void
@@ -3355,6 +3518,12 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
       // Add a DT_TEXTREL for compatibility with older loaders.
       odyn->add_constant(elfcpp::DT_TEXTREL, 0);
       flags |= elfcpp::DF_TEXTREL;
+
+      if (parameters->options().text())
+       gold_error(_("read-only segment has dynamic relocations"));
+      else if (parameters->options().warn_shared_textrel()
+              && parameters->options().shared())
+       gold_warning(_("shared library text segment is not shareable"));
     }
   if (parameters->options().shared() && this->has_static_tls())
     flags |= elfcpp::DF_STATIC_TLS;
@@ -3461,9 +3630,9 @@ const Layout::Section_name_mapping Layout::section_name_mapping[] =
   MAPPING_INIT(".gnu.linkonce.lr.", ".lrodata"),
   MAPPING_INIT(".gnu.linkonce.l.", ".ldata"),
   MAPPING_INIT(".gnu.linkonce.lb.", ".lbss"),
-  MAPPING_INIT(".ARM.extab.", ".ARM.extab"),
+  MAPPING_INIT(".ARM.extab", ".ARM.extab"),
   MAPPING_INIT(".gnu.linkonce.armextab.", ".ARM.extab"),
-  MAPPING_INIT(".ARM.exidx.", ".ARM.exidx"),
+  MAPPING_INIT(".ARM.exidx", ".ARM.exidx"),
   MAPPING_INIT(".gnu.linkonce.armexidx.", ".ARM.exidx"),
 };
 #undef MAPPING_INIT