Add icf_virtual_function_folding_test to check_PROGRAMS.
[binutils-gdb.git] / gold / layout.cc
index 52989a5b1a803cd2ab524605aa4f7874573de1ed..2ffbdf49770288e42a7cb2ab9c0825adaf260e56 100644 (file)
@@ -502,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.
@@ -533,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;
        }
@@ -582,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)
@@ -1136,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;
 }
 
@@ -3240,7 +3301,7 @@ 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 add_debug, bool dynrel_includes_plt)
 {
   Output_data_dynamic* odyn = this->dynamic_data_;
   if (odyn == NULL)
@@ -3261,8 +3322,12 @@ Layout::add_target_dynamic_tags(bool use_rel, const Output_data* plt_got,
     {
       odyn->add_section_address(use_rel ? elfcpp::DT_REL : elfcpp::DT_RELA,
                                dyn_rel);
-      odyn->add_section_size(use_rel ? elfcpp::DT_RELSZ : elfcpp::DT_RELASZ,
-                            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;
@@ -3565,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