Fix problem where mixed section types can cause internal error during a -r link.
authorCary Coutant <ccoutant@gmail.com>
Mon, 2 Apr 2018 23:12:10 +0000 (16:12 -0700)
committerCary Coutant <ccoutant@gmail.com>
Tue, 3 Apr 2018 02:07:04 +0000 (19:07 -0700)
During a -r (or --emit-relocs) link, if two sections had the same name but
different section types, gold would put relocations for both sections into
the same relocation section even though the data sections remained separate.

For .eh_frame sections, when one section is PROGBITS and another is
X86_64_UNWIND, we really should be using the UNWIND section type and
combining the sections anyway.  For other sections, we should be
creating one relocation section for each output data section.

gold/
PR gold/23016
* incremental.cc (can_incremental_update): Check for unwind section
type.
* layout.h (Layout::layout): Add sh_type parameter.
* layout.cc (Layout::layout): Likewise.
(Layout::layout_reloc): Create new output reloc section if data
section does not already have one.
(Layout::layout_eh_frame): Check for unwind section type.
(Layout::make_eh_frame_section): Use unwind section type for .eh_frame
and .eh_frame_hdr.
* object.h (Sized_relobj_file::Shdr_write): New typedef.
(Sized_relobj_file::layout_section): Add sh_type parameter.
(Sized_relobj_file::Deferred_layout::Deferred_layout): Add sh_type
parameter.
* object.cc (Sized_relobj_file::check_eh_frame_flags): Check for
unwind section type.
(Sized_relobj_file::layout_section): Add sh_type parameter; pass it
to Layout::layout.
(Sized_relobj_file::do_layout): Make local copy of sh_type.
Force .eh_frame sections to unwind section type.
Pass sh_type to layout_section.
(Sized_relobj_file<size, big_endian>::do_layout_deferred_sections):
Pass sh_type to layout_section.
* output.cc (Output_section::Output_section): Initialize reloc_section_.
* output.h (Output_section::reloc_section): New method.
(Output_section::set_reloc_section): New method.
(Output_section::reloc_section_): New data member.
* target.h (Target::unwind_section_type): New method.
(Target::Target_info::unwind_section_type): New data member.

* aarch64.cc (aarch64_info): Add unwind_section_type.
* arm.cc (arm_info, arm_nacl_info): Likewise.
* i386.cc (i386_info, i386_nacl_info, iamcu_info): Likewise.
* mips.cc (mips_info, mips_nacl_info): Likewise.
* powerpc.cc (powerpc_info): Likewise.
* s390.cc (s390_info): Likewise.
* sparc.cc (sparc_info): Likewise.
* tilegx.cc (tilegx_info): Likewise.
* x86_64.cc (x86_64_info, x86_64_nacl_info): Likewise.

* testsuite/Makefile.am (pr23016_1, pr23016_2): New test cases.
* testsuite/Makefile.in: Regenerate.
* testsuite/testfile.cc: Add unwind_section_type.
* testsuite/pr23016_1.sh: New test script.
* testsuite/pr23016_1a.s: New source file.
* testsuite/pr23016_1b.s: New source file.
* testsuite/pr23016_2.sh: New test script.
* testsuite/pr23016_2a.s: New source file.
* testsuite/pr23016_2b.s: New source file.

27 files changed:
gold/ChangeLog
gold/aarch64.cc
gold/arm.cc
gold/i386.cc
gold/incremental.cc
gold/layout.cc
gold/layout.h
gold/mips.cc
gold/object.cc
gold/object.h
gold/output.cc
gold/output.h
gold/powerpc.cc
gold/s390.cc
gold/sparc.cc
gold/target.h
gold/testsuite/Makefile.am
gold/testsuite/Makefile.in
gold/testsuite/pr23016_1.sh [new file with mode: 0755]
gold/testsuite/pr23016_1a.s [new file with mode: 0644]
gold/testsuite/pr23016_1b.s [new file with mode: 0644]
gold/testsuite/pr23016_2.sh [new file with mode: 0755]
gold/testsuite/pr23016_2a.s [new file with mode: 0644]
gold/testsuite/pr23016_2b.s [new file with mode: 0644]
gold/testsuite/testfile.cc
gold/tilegx.cc
gold/x86_64.cc

index a97a3d003afff0bd2b543ea2f5a21b5226b438da..2841bc02dba10329753cdc63798ea32b1f6cc9a1 100644 (file)
@@ -1,3 +1,55 @@
+2018-04-02  Cary Coutant  <ccoutant@gmail.com>
+
+       PR gold/23016
+       * incremental.cc (can_incremental_update): Check for unwind section
+       type.
+       * layout.h (Layout::layout): Add sh_type parameter.
+       * layout.cc (Layout::layout): Likewise.
+       (Layout::layout_reloc): Create new output reloc section if data
+       section does not already have one.
+       (Layout::layout_eh_frame): Check for unwind section type.
+       (Layout::make_eh_frame_section): Use unwind section type for .eh_frame
+       and .eh_frame_hdr.
+       * object.h (Sized_relobj_file::Shdr_write): New typedef.
+       (Sized_relobj_file::layout_section): Add sh_type parameter.
+       (Sized_relobj_file::Deferred_layout::Deferred_layout): Add sh_type
+       parameter.
+       * object.cc (Sized_relobj_file::check_eh_frame_flags): Check for
+       unwind section type.
+       (Sized_relobj_file::layout_section): Add sh_type parameter; pass it
+       to Layout::layout.
+       (Sized_relobj_file::do_layout): Make local copy of sh_type.
+       Force .eh_frame sections to unwind section type.
+       Pass sh_type to layout_section.
+       (Sized_relobj_file<size, big_endian>::do_layout_deferred_sections):
+       Pass sh_type to layout_section.
+       * output.cc (Output_section::Output_section): Initialize reloc_section_.
+       * output.h (Output_section::reloc_section): New method.
+       (Output_section::set_reloc_section): New method.
+       (Output_section::reloc_section_): New data member.
+       * target.h (Target::unwind_section_type): New method.
+       (Target::Target_info::unwind_section_type): New data member.
+
+       * aarch64.cc (aarch64_info): Add unwind_section_type.
+       * arm.cc (arm_info, arm_nacl_info): Likewise.
+       * i386.cc (i386_info, i386_nacl_info, iamcu_info): Likewise.
+       * mips.cc (mips_info, mips_nacl_info): Likewise.
+       * powerpc.cc (powerpc_info): Likewise.
+       * s390.cc (s390_info): Likewise.
+       * sparc.cc (sparc_info): Likewise.
+       * tilegx.cc (tilegx_info): Likewise.
+       * x86_64.cc (x86_64_info, x86_64_nacl_info): Likewise.
+
+       * testsuite/Makefile.am (pr23016_1, pr23016_2): New test cases.
+       * testsuite/Makefile.in: Regenerate.
+       * testsuite/testfile.cc: Add unwind_section_type.
+       * testsuite/pr23016_1.sh: New test script.
+       * testsuite/pr23016_1a.s: New source file.
+       * testsuite/pr23016_1b.s: New source file.
+       * testsuite/pr23016_2.sh: New test script.
+       * testsuite/pr23016_2a.s: New source file.
+       * testsuite/pr23016_2b.s: New source file.
+
 2018-03-28  Cary Coutant  <ccoutant@gmail.com>
 
        PR gold/21423
index ecb400b27439e2846008ef6ef2d324a80cf6935c..4dd207fe096e0e39f30e3b87314c6b62e4563194 100644 (file)
@@ -3565,6 +3565,7 @@ const Target::Target_info Target_aarch64<64, false>::aarch64_info =
   NULL,                        // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 template<>
@@ -3593,6 +3594,7 @@ const Target::Target_info Target_aarch64<32, false>::aarch64_info =
   NULL,                        // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 template<>
@@ -3621,6 +3623,7 @@ const Target::Target_info Target_aarch64<64, true>::aarch64_info =
   NULL,                        // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 template<>
@@ -3649,6 +3652,7 @@ const Target::Target_info Target_aarch64<32, true>::aarch64_info =
   NULL,                        // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 // Get the GOT section, creating it if necessary.
index 6c57af5b37bafa2ccb4e67695dcd50f535a7a8c3..848924757e31cd7e605a864d65c2eaf609a37d29 100644 (file)
@@ -3062,6 +3062,7 @@ const Target::Target_info Target_arm<big_endian>::arm_info =
   "aeabi",             // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 // Arm relocate functions class
@@ -13056,6 +13057,7 @@ const Target::Target_info Target_arm_nacl<big_endian>::arm_nacl_info =
   "aeabi",             // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 template<bool big_endian>
index 564e616ccbe333876ac1d9cb970e8439b96bb5d0..725b9429eb6c4d4b5553b9b8f0ba5e54e7bed6a4 100644 (file)
@@ -925,6 +925,7 @@ const Target::Target_info Target_i386::i386_info =
   NULL,                        // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 // Get the GOT section, creating it if necessary.
@@ -4203,6 +4204,7 @@ const Target::Target_info Target_i386_nacl::i386_nacl_info =
   NULL,                        // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 #define        NACLMASK        0xe0            // 32-byte alignment mask
@@ -4440,6 +4442,7 @@ const Target::Target_info Target_iamcu::iamcu_info =
   NULL,                        // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 class Target_selector_iamcu : public Target_selector
index 417a7399574dfbe05bf2fc8c0ee437d3ee39674a..21f060c945bc4603b60333d61f59547e9a1370ad 100644 (file)
@@ -173,8 +173,8 @@ Incremental_binary::error(const char* format, ...) const
 
 // Return TRUE if a section of type SH_TYPE can be updated in place
 // during an incremental update.  We can update sections of type PROGBITS,
-// NOBITS, INIT_ARRAY, FINI_ARRAY, PREINIT_ARRAY, and NOTE.  All others
-// will be regenerated.
+// NOBITS, INIT_ARRAY, FINI_ARRAY, PREINIT_ARRAY, NOTE, and
+// (processor-specific) unwind sections.  All others will be regenerated.
 
 bool
 can_incremental_update(unsigned int sh_type)
@@ -184,7 +184,8 @@ can_incremental_update(unsigned int sh_type)
          || sh_type == elfcpp::SHT_INIT_ARRAY
          || sh_type == elfcpp::SHT_FINI_ARRAY
          || sh_type == elfcpp::SHT_PREINIT_ARRAY
-         || sh_type == elfcpp::SHT_NOTE);
+         || sh_type == elfcpp::SHT_NOTE
+         || sh_type == parameters->target().unwind_section_type());
 }
 
 // Find the .gnu_incremental_inputs section and related sections.
index f5fe805ea7870ed3172de158a9f214af2da7435c..2eb7b7c8429484b49ab55ad95e7322cec2c32638 100644 (file)
@@ -1153,15 +1153,14 @@ template<int size, bool big_endian>
 Output_section*
 Layout::layout(Sized_relobj_file<size, big_endian>* object, unsigned int shndx,
               const char* name, const elfcpp::Shdr<size, big_endian>& shdr,
-              unsigned int reloc_shndx, unsigned int, off_t* off)
+              unsigned int sh_type, unsigned int reloc_shndx,
+              unsigned int, off_t* off)
 {
   *off = 0;
 
   if (!this->include_section(object, name, shdr))
     return NULL;
 
-  elfcpp::Elf_Word sh_type = shdr.get_sh_type();
-
   // In a relocatable link a grouped section must not be combined with
   // any other sections.
   Output_section* os;
@@ -1315,7 +1314,7 @@ Layout::insert_section_segment_map(Const_section_id secn,
 
 template<int size, bool big_endian>
 Output_section*
-Layout::layout_reloc(Sized_relobj_file<size, big_endian>* object,
+Layout::layout_reloc(Sized_relobj_file<size, big_endian>*,
                     unsigned int,
                     const elfcpp::Shdr<size, big_endian>& shdr,
                     Output_section* data_section,
@@ -1335,24 +1334,19 @@ Layout::layout_reloc(Sized_relobj_file<size, big_endian>* object,
     gold_unreachable();
   name += data_section->name();
 
-  // In a relocatable link relocs for a grouped section must not be
-  // combined with other reloc sections.
-  Output_section* os;
-  if (!parameters->options().relocatable()
-      || (data_section->flags() & elfcpp::SHF_GROUP) == 0)
-    os = this->choose_output_section(object, name.c_str(), sh_type,
-                                    shdr.get_sh_flags(), false,
-                                    ORDER_INVALID, false, true, false);
-  else
+  // If the output data section already has a reloc section, use that;
+  // otherwise, make a new one.
+  Output_section* os = data_section->reloc_section();
+  if (os == NULL)
     {
       const char* n = this->namepool_.add(name.c_str(), true, NULL);
       os = this->make_output_section(n, sh_type, shdr.get_sh_flags(),
                                     ORDER_INVALID, false);
+      os->set_should_link_to_symtab();
+      os->set_info_section(data_section);
+      data_section->set_reloc_section(os);
     }
 
-  os->set_should_link_to_symtab();
-  os->set_info_section(data_section);
-
   Output_section_data* posd;
   if (sh_type == elfcpp::SHT_REL)
     {
@@ -1442,8 +1436,11 @@ Layout::layout_eh_frame(Sized_relobj_file<size, big_endian>* object,
                        unsigned int reloc_shndx, unsigned int reloc_type,
                        off_t* off)
 {
+  const unsigned int unwind_section_type =
+      parameters->target().unwind_section_type();
+
   gold_assert(shdr.get_sh_type() == elfcpp::SHT_PROGBITS
-             || shdr.get_sh_type() == elfcpp::SHT_X86_64_UNWIND);
+             || shdr.get_sh_type() == unwind_section_type);
   gold_assert((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0);
 
   Output_section* os = this->make_eh_frame_section(object);
@@ -1530,10 +1527,11 @@ Layout::finalize_eh_frame_section()
 Output_section*
 Layout::make_eh_frame_section(const Relobj* object)
 {
-  // FIXME: On x86_64, this could use SHT_X86_64_UNWIND rather than
-  // SHT_PROGBITS.
+  const unsigned int unwind_section_type =
+      parameters->target().unwind_section_type();
+
   Output_section* os = this->choose_output_section(object, ".eh_frame",
-                                                  elfcpp::SHT_PROGBITS,
+                                                  unwind_section_type,
                                                   elfcpp::SHF_ALLOC, false,
                                                   ORDER_EHFRAME, false, false,
                                                   false);
@@ -1551,7 +1549,7 @@ Layout::make_eh_frame_section(const Relobj* object)
        {
          Output_section* hdr_os =
            this->choose_output_section(NULL, ".eh_frame_hdr",
-                                       elfcpp::SHT_PROGBITS,
+                                       unwind_section_type,
                                        elfcpp::SHF_ALLOC, false,
                                        ORDER_EHFRAME, false, false,
                                        false);
@@ -5915,7 +5913,7 @@ Layout::layout<32, false>(Sized_relobj_file<32, false>* object,
                          unsigned int shndx,
                          const char* name,
                          const elfcpp::Shdr<32, false>& shdr,
-                         unsigned int, unsigned int, off_t*);
+                         unsigned int, unsigned int, unsigned int, off_t*);
 #endif
 
 #ifdef HAVE_TARGET_32_BIG
@@ -5925,7 +5923,7 @@ Layout::layout<32, true>(Sized_relobj_file<32, true>* object,
                         unsigned int shndx,
                         const char* name,
                         const elfcpp::Shdr<32, true>& shdr,
-                        unsigned int, unsigned int, off_t*);
+                        unsigned int, unsigned int, unsigned int, off_t*);
 #endif
 
 #ifdef HAVE_TARGET_64_LITTLE
@@ -5935,7 +5933,7 @@ Layout::layout<64, false>(Sized_relobj_file<64, false>* object,
                          unsigned int shndx,
                          const char* name,
                          const elfcpp::Shdr<64, false>& shdr,
-                         unsigned int, unsigned int, off_t*);
+                         unsigned int, unsigned int, unsigned int, off_t*);
 #endif
 
 #ifdef HAVE_TARGET_64_BIG
@@ -5945,7 +5943,7 @@ Layout::layout<64, true>(Sized_relobj_file<64, true>* object,
                         unsigned int shndx,
                         const char* name,
                         const elfcpp::Shdr<64, true>& shdr,
-                        unsigned int, unsigned int, off_t*);
+                        unsigned int, unsigned int, unsigned int, off_t*);
 #endif
 
 #ifdef HAVE_TARGET_32_LITTLE
index 0c34d3db1950eeeca2801a28a3240c7b27ad8f78..806f6e53b01ac28650e6bdddb5b5d371e21873d8 100644 (file)
@@ -537,7 +537,8 @@ class Layout
   Output_section*
   layout(Sized_relobj_file<size, big_endian> *object, unsigned int shndx,
         const char* name, const elfcpp::Shdr<size, big_endian>& shdr,
-        unsigned int reloc_shndx, unsigned int reloc_type, off_t* offset);
+        unsigned int sh_type, unsigned int reloc_shndx,
+        unsigned int reloc_type, off_t* offset);
 
   std::map<Section_id, unsigned int>*
   get_section_order_map()
index 543a23462f71c140809770f28d531ed2dec99210..ee2c037ad538f07f137c1ff0de2bd20df1dcd9ef 100644 (file)
@@ -12633,6 +12633,7 @@ const Target::Target_info Target_mips<size, big_endian>::mips_info =
   NULL,                 // attributes_vendor
   "__start",           // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 template<int size, bool big_endian>
@@ -12673,6 +12674,7 @@ const Target::Target_info Target_mips_nacl<size, big_endian>::mips_nacl_info =
   NULL,                 // attributes_vendor
   "_start",             // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 // Target selector for Mips.  Note this is never instantiated directly.
index 0c8f7e2598a0aa118d7ee5a13f1f59fb0fed7cd6..0dbb0cbe12dc34ca20b5416d28a80d634a9f5cf2 100644 (file)
@@ -574,7 +574,7 @@ Sized_relobj_file<size, big_endian>::check_eh_frame_flags(
 {
   elfcpp::Elf_Word sh_type = shdr->get_sh_type();
   return ((sh_type == elfcpp::SHT_PROGBITS
-          || sh_type == elfcpp::SHT_X86_64_UNWIND)
+          || sh_type == parameters->target().unwind_section_type())
          && (shdr->get_sh_flags() & elfcpp::SHF_ALLOC) != 0);
 }
 
@@ -1252,12 +1252,13 @@ Sized_relobj_file<size, big_endian>::layout_section(
     unsigned int shndx,
     const char* name,
     const typename This::Shdr& shdr,
+    unsigned int sh_type,
     unsigned int reloc_shndx,
     unsigned int reloc_type)
 {
   off_t offset;
-  Output_section* os = layout->layout(this, shndx, name, shdr,
-                                         reloc_shndx, reloc_type, &offset);
+  Output_section* os = layout->layout(this, shndx, name, shdr, sh_type,
+                                     reloc_shndx, reloc_type, &offset);
 
   this->output_sections()[shndx] = os;
   if (offset == -1)
@@ -1337,6 +1338,8 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
                                               Layout* layout,
                                               Read_symbols_data* sd)
 {
+  const unsigned int unwind_section_type =
+      parameters->target().unwind_section_type();
   const unsigned int shnum = this->shnum();
 
   /* Should this function be called twice?  */
@@ -1522,15 +1525,17 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
   for (unsigned int i = 1; i < shnum; ++i, pshdrs += This::shdr_size)
     {
       typename This::Shdr shdr(pshdrs);
+      const unsigned int sh_name = shdr.get_sh_name();
+      unsigned int sh_type = shdr.get_sh_type();
 
-      if (shdr.get_sh_name() >= section_names_size)
+      if (sh_name >= section_names_size)
        {
          this->error(_("bad section name offset for section %u: %lu"),
-                     i, static_cast<unsigned long>(shdr.get_sh_name()));
+                     i, static_cast<unsigned long>(sh_name));
          return;
        }
 
-      const char* name = pnames + shdr.get_sh_name();
+      const char* name = pnames + sh_name;
 
       if (!is_pass_two)
        {
@@ -1568,7 +1573,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
          bool discard = omit[i];
          if (!discard)
            {
-             if (shdr.get_sh_type() == elfcpp::SHT_GROUP)
+             if (sh_type == elfcpp::SHT_GROUP)
                {
                  if (!this->include_section_group(symtab, layout, i, name,
                                                   shdrs, pnames,
@@ -1588,7 +1593,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
          Incremental_inputs* incremental_inputs = layout->incremental_inputs();
          if (incremental_inputs != NULL
              && !discard
-             && can_incremental_update(shdr.get_sh_type()))
+             && can_incremental_update(sh_type))
            {
              off_t sh_size = shdr.get_sh_size();
              section_size_type uncompressed_size;
@@ -1610,8 +1615,8 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
        {
          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)
+             || sh_type == elfcpp::SHT_INIT_ARRAY
+             || sh_type == elfcpp::SHT_FINI_ARRAY)
            {
              symtab->gc()->worklist().push_back(Section_id(this, i));
            }
@@ -1632,14 +1637,14 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
       // reloc sections and process them later. Garbage collection is
       // not triggered when relocatable code is desired.
       if (emit_relocs
-         && (shdr.get_sh_type() == elfcpp::SHT_REL
-             || shdr.get_sh_type() == elfcpp::SHT_RELA))
+         && (sh_type == elfcpp::SHT_REL
+             || sh_type == elfcpp::SHT_RELA))
        {
          reloc_sections.push_back(i);
          continue;
        }
 
-      if (relocatable && shdr.get_sh_type() == elfcpp::SHT_GROUP)
+      if (relocatable && sh_type == elfcpp::SHT_GROUP)
        continue;
 
       // The .eh_frame section is special.  It holds exception frame
@@ -1648,26 +1653,30 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
       // sections so that the exception frame reader can reliably
       // determine which sections are being discarded, and discard the
       // corresponding information.
-      if (!relocatable
-         && strcmp(name, ".eh_frame") == 0
-         && this->check_eh_frame_flags(&shdr))
+      if (this->check_eh_frame_flags(&shdr)
+         && strcmp(name, ".eh_frame") == 0)
        {
-         if (is_pass_one)
+         // If the target has a special unwind section type, let's
+         // canonicalize it here.
+         sh_type = unwind_section_type;
+         if (!relocatable)
            {
-             if (this->is_deferred_layout())
-               out_sections[i] = reinterpret_cast<Output_section*>(2);
+             if (is_pass_one)
+               {
+                 if (this->is_deferred_layout())
+                   out_sections[i] = reinterpret_cast<Output_section*>(2);
+                 else
+                   out_sections[i] = reinterpret_cast<Output_section*>(1);
+                 out_section_offsets[i] = invalid_address;
+               }
+             else if (this->is_deferred_layout())
+               this->deferred_layout_.push_back(
+                   Deferred_layout(i, name, sh_type, pshdrs,
+                                   reloc_shndx[i], reloc_type[i]));
              else
-               out_sections[i] = reinterpret_cast<Output_section*>(1);
-             out_section_offsets[i] = invalid_address;
+               eh_frame_sections.push_back(i);
+             continue;
            }
-         else if (this->is_deferred_layout())
-           this->deferred_layout_.push_back(Deferred_layout(i, name,
-                                                            pshdrs,
-                                                            reloc_shndx[i],
-                                                            reloc_type[i]));
-         else
-           eh_frame_sections.push_back(i);
-         continue;
        }
 
       if (is_pass_two && parameters->options().gc_sections())
@@ -1731,7 +1740,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
           && this->is_deferred_layout()
           && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
        {
-         this->deferred_layout_.push_back(Deferred_layout(i, name,
+         this->deferred_layout_.push_back(Deferred_layout(i, name, sh_type,
                                                           pshdrs,
                                                           reloc_shndx[i],
                                                           reloc_type[i]));
@@ -1760,7 +1769,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
        {
          // When garbage collection is switched on the actual layout
          // only happens in the second call.
-         this->layout_section(layout, i, name, shdr, reloc_shndx[i],
+         this->layout_section(layout, i, name, shdr, sh_type, reloc_shndx[i],
                               reloc_type[i]);
 
          // When generating a .gdb_index section, we do additional
@@ -1838,7 +1847,8 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
          // to defer the relocation section, too.
          const char* name = pnames + shdr.get_sh_name();
          this->deferred_layout_relocs_.push_back(
-             Deferred_layout(i, name, pshdr, 0, elfcpp::SHT_NULL));
+             Deferred_layout(i, name, shdr.get_sh_type(), pshdr, 0,
+                             elfcpp::SHT_NULL));
          out_sections[i] = reinterpret_cast<Output_section*>(2);
          out_section_offsets[i] = invalid_address;
          continue;
@@ -1949,7 +1959,7 @@ Sized_relobj_file<size, big_endian>::do_layout_deferred_sections(Layout* layout)
        continue;
 
       this->layout_section(layout, deferred->shndx_, deferred->name_.c_str(),
-                          shdr, deferred->reloc_shndx_,
+                          shdr, shdr.get_sh_type(), deferred->reloc_shndx_,
                           deferred->reloc_type_);
     }
 
index c92e030c2eac86957ef5d8338d5a26cced67cf69..9fb9b306280c0fad0b4d234f862d5b347d81ed12 100644 (file)
@@ -2591,6 +2591,7 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
   static const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
   static const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
   typedef elfcpp::Shdr<size, big_endian> Shdr;
+  typedef elfcpp::Shdr_write<size, big_endian> Shdr_write;
 
   // To keep track of discarded comdat sections, we need to map a member
   // section index to the object and section index of the corresponding
@@ -2635,8 +2636,8 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
   // Layout an input section.
   void
   layout_section(Layout* layout, unsigned int shndx, const char* name,
-                 const typename This::Shdr& shdr, unsigned int reloc_shndx,
-                 unsigned int reloc_type);
+                 const typename This::Shdr& shdr, unsigned int sh_type,
+                 unsigned int reloc_shndx, unsigned int reloc_type);
 
   // Layout an input .eh_frame section.
   void
@@ -2798,15 +2799,18 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
   {
     static const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
     Deferred_layout(unsigned int shndx, const char* name,
+                    unsigned int sh_type,
                     const unsigned char* pshdr,
                     unsigned int reloc_shndx, unsigned int reloc_type)
-      : shndx_(shndx), name_(name), reloc_shndx_(reloc_shndx),
+      : name_(name), shndx_(shndx), reloc_shndx_(reloc_shndx),
         reloc_type_(reloc_type)
     {
+      typename This::Shdr_write shdr(this->shdr_data_);
       memcpy(this->shdr_data_, pshdr, shdr_size);
+      shdr.put_sh_type(sh_type);
     }
-    unsigned int shndx_;
     std::string name_;
+    unsigned int shndx_;
     unsigned int reloc_shndx_;
     unsigned int reloc_type_;
     unsigned char shdr_data_[shdr_size];
index 0a34a2af21e3258b9a70eae3be6232b0b1f5cd67..1701db1c99f18f5a0f8645ff2d548d7961098cc5 100644 (file)
@@ -2395,7 +2395,8 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
     lookup_maps_(new Output_section_lookup_maps),
     free_list_(),
     free_space_fill_(NULL),
-    patch_space_(0)
+    patch_space_(0),
+    reloc_section_(NULL)
 {
   // An unallocated section has no address.  Forcing this means that
   // we don't need special treatment for symbols defined in debug
index c7545ca81f6b98345112b1cd4ead3d9d62e6fcd2..c2458831e3671278ce999be99f3d1be14c625716 100644 (file)
@@ -4136,6 +4136,16 @@ class Output_section : public Output_data
   input_sections()
   { return this->input_sections_; }
 
+  // For -r and --emit-relocs, we need to keep track of the associated
+  // relocation section.
+  Output_section*
+  reloc_section() const
+  { return this->reloc_section_; }
+
+  void
+  set_reloc_section(Output_section* os)
+  { this->reloc_section_ = os; }
+
  protected:
   // Return the output section--i.e., the object itself.
   Output_section*
@@ -4623,6 +4633,8 @@ class Output_section : public Output_data
   Output_fill* free_space_fill_;
   // Amount added as patch space for incremental linking.
   off_t patch_space_;
+  // Associated relocation section, when emitting relocations.
+  Output_section* reloc_section_;
 };
 
 // An output segment.  PT_LOAD segments are built from collections of
index f6d589c6ea7b2d103d687bbf00d1ee1c89f3790b..39bda353a4385bda4bfa60e874b01b68470806d9 100644 (file)
@@ -1625,6 +1625,7 @@ Target::Target_info Target_powerpc<32, true>::powerpc_info =
   NULL,                        // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 template<>
@@ -1653,6 +1654,7 @@ Target::Target_info Target_powerpc<32, false>::powerpc_info =
   NULL,                        // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 template<>
@@ -1681,6 +1683,7 @@ Target::Target_info Target_powerpc<64, true>::powerpc_info =
   NULL,                        // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 template<>
@@ -1709,6 +1712,7 @@ Target::Target_info Target_powerpc<64, false>::powerpc_info =
   NULL,                        // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 inline bool
index 3542ee6d3019619264c3179729932787fc08aae0..1043056d021c9ba71cc74fed7c2d6790ad775452 100644 (file)
@@ -827,6 +827,7 @@ Target::Target_info Target_s390<32>::s390_info =
   NULL,                        // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 template<>
@@ -855,6 +856,7 @@ Target::Target_info Target_s390<64>::s390_info =
   NULL,                        // attributes_vendor
   "_start",            // entry_symbol_name
   64,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 template<int size>
index 8551afd4be580a5fdd695d991cb6f61ee6201912..1abcb4125f1fedeb71dc4e0514af4ea411975b65 100644 (file)
@@ -499,6 +499,7 @@ Target::Target_info Target_sparc<32, true>::sparc_info =
   NULL,                        // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 template<>
@@ -527,6 +528,7 @@ Target::Target_info Target_sparc<64, true>::sparc_info =
   NULL,                        // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 // We have to take care here, even when operating in little-endian
index 059d2d02c7d2b784d419e5f28ea47a64f1c3fc7a..da2f6bbc78c7eb65d70367480add47d0aa96566c 100644 (file)
@@ -474,6 +474,11 @@ class Target
   hash_entry_size() const
   { return this->pti_->hash_entry_size; }
 
+  // Return the section type to use for unwind sections.
+  unsigned int
+  unwind_section_type() const
+  { return this->pti_->unwind_section_type; }
+
   // Whether the target has a custom set_dynsym_indexes method.
   bool
   has_custom_set_dynsym_indexes() const
@@ -562,6 +567,9 @@ class Target
     // Size (in bits) of SHT_HASH entry. Always equal to 32, except for
     // 64-bit S/390.
     const int hash_entry_size;
+    // Processor-specific section type for ".eh_frame" (unwind) sections.
+    // SHT_PROGBITS if there is no special section type.
+    const unsigned int unwind_section_type;
   };
 
   Target(const Target_info* pti)
index cf0b970eaa1adf2a09351eee1fe7d82a66225974..7140df64d0d48dc9346699aee5d9f4414e4c3ab9 100644 (file)
@@ -1211,6 +1211,32 @@ x32_overflow_pc32.err: x32_overflow_pc32.o gcctestdir/ld
          exit 1; \
        fi
 
+check_SCRIPTS += pr23016_1.sh
+check_DATA += pr23016_1.stdout pr23016_1r.stdout
+pr23016_1.stdout: pr23016_1.o
+       $(TEST_READELF) -rSW $< >$@ 2>/dev/null
+pr23016_1.o: pr23016_1a.o pr23016_1b.o gcctestdir/ld
+       gcctestdir/ld -r -o $@ pr23016_1a.o pr23016_1b.o
+pr23016_1r.stdout: pr23016_1r.o
+       $(TEST_READELF) -rSW $< >$@ 2>/dev/null
+pr23016_1r.o: pr23016_1a.o pr23016_1b.o gcctestdir/ld
+       gcctestdir/ld -r -o $@ pr23016_1b.o pr23016_1a.o
+pr23016_1a.o: pr23016_1a.s
+       $(TEST_AS) -o $@ $<
+pr23016_1b.o: pr23016_1b.s
+       $(TEST_AS) -o $@ $<
+
+check_SCRIPTS += pr23016_2.sh
+check_DATA += pr23016_2.stdout
+pr23016_2.stdout: pr23016_2.o
+       $(TEST_READELF) -rW $< >$@ 2>/dev/null
+pr23016_2.o: pr23016_2a.o pr23016_2b.o gcctestdir/ld
+       gcctestdir/ld -r -o $@ pr23016_2a.o pr23016_2b.o
+pr23016_2a.o: pr23016_2a.s
+       $(TEST_AS) -o $@ $<
+pr23016_2b.o: pr23016_2b.s
+       $(TEST_AS) -o $@ $<
+
 endif DEFAULT_TARGET_X86_64
 
 if DEFAULT_TARGET_X86_64_OR_X32
index 3bddc12474854392b1cb1ad44f9783e53d0fcd0f..48e5b9e2fcca9870d114206121faad6fe54fe21b 100644 (file)
@@ -252,7 +252,9 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_29 = x86_64_mov_to_lea.sh \
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     x86_64_indirect_call_to_direct.sh \
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     x86_64_overflow_pc32.sh \
-@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     x32_overflow_pc32.sh
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     x32_overflow_pc32.sh \
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     pr23016_1.sh \
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     pr23016_2.sh
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_30 = x86_64_mov_to_lea1.stdout \
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     x86_64_mov_to_lea2.stdout \
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     x86_64_mov_to_lea3.stdout \
@@ -270,7 +272,10 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     x86_64_indirect_call_to_direct1.stdout \
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     x86_64_indirect_jump_to_direct1.stdout \
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     x86_64_overflow_pc32.err \
-@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     x32_overflow_pc32.err
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     x32_overflow_pc32.err \
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     pr23016_1.stdout \
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     pr23016_1r.stdout \
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     pr23016_2.stdout
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_31 = x86_64_mov_to_lea1 \
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     x86_64_mov_to_lea2 \
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     x86_64_mov_to_lea3 \
@@ -5269,6 +5274,10 @@ x86_64_overflow_pc32.sh.log: x86_64_overflow_pc32.sh
        @p='x86_64_overflow_pc32.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 x32_overflow_pc32.sh.log: x32_overflow_pc32.sh
        @p='x32_overflow_pc32.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
+pr23016_1.sh.log: pr23016_1.sh
+       @p='pr23016_1.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
+pr23016_2.sh.log: pr23016_2.sh
+       @p='pr23016_2.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 i386_mov_to_lea.sh.log: i386_mov_to_lea.sh
        @p='i386_mov_to_lea.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 file_in_many_sections_test.sh.log: file_in_many_sections_test.sh
@@ -6489,6 +6498,26 @@ uninstall-am:
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@       rm -f $@; \
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@       exit 1; \
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     fi
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@pr23016_1.stdout: pr23016_1.o
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     $(TEST_READELF) -rSW $< >$@ 2>/dev/null
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@pr23016_1.o: pr23016_1a.o pr23016_1b.o gcctestdir/ld
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     gcctestdir/ld -r -o $@ pr23016_1a.o pr23016_1b.o
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@pr23016_1r.stdout: pr23016_1r.o
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     $(TEST_READELF) -rSW $< >$@ 2>/dev/null
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@pr23016_1r.o: pr23016_1a.o pr23016_1b.o gcctestdir/ld
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     gcctestdir/ld -r -o $@ pr23016_1b.o pr23016_1a.o
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@pr23016_1a.o: pr23016_1a.s
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     $(TEST_AS) -o $@ $<
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@pr23016_1b.o: pr23016_1b.s
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     $(TEST_AS) -o $@ $<
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@pr23016_2.stdout: pr23016_2.o
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     $(TEST_READELF) -rW $< >$@ 2>/dev/null
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@pr23016_2.o: pr23016_2a.o pr23016_2b.o gcctestdir/ld
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     gcctestdir/ld -r -o $@ pr23016_2a.o pr23016_2b.o
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@pr23016_2a.o: pr23016_2a.s
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     $(TEST_AS) -o $@ $<
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@pr23016_2b.o: pr23016_2b.s
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@     $(TEST_AS) -o $@ $<
 
 @DEFAULT_TARGET_X86_64_OR_X32_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@pr20216a.so: pr20216_gd.o pr20216_ld.o gcctestdir/ld
 @DEFAULT_TARGET_X86_64_OR_X32_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@      $(LINK) -Bgcctestdir/ -shared pr20216_gd.o pr20216_ld.o
diff --git a/gold/testsuite/pr23016_1.sh b/gold/testsuite/pr23016_1.sh
new file mode 100755 (executable)
index 0000000..f909a9b
--- /dev/null
@@ -0,0 +1,87 @@
+#!/bin/sh
+
+# pr23016_1.sh -- check that .eh_frame sections and their relocations
+# are merged together even when mixing SHT_PROGBITS and SHT_X86_64_UNWIND.
+
+# Copyright (C) 2018 Free Software Foundation, Inc.
+# Written by Cary Coutant <ccoutant@gmail.com>.
+
+# This file is part of gold.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+set -e
+
+check() {
+  awk -v "FILE=$1" '
+  BEGIN {
+      progbits = 0;
+      unwind = 0;
+      ehframe_rel = 0;
+      relocx = 0;
+      relocy = 0;
+    }
+  /\.eh_frame *PROGBITS/ {
+      progbits++;
+    }
+  /\.eh_frame *X86_64_UNWIND/ {
+      unwind++;
+    }
+  /^Relocation section .\.rela\.eh_frame/ {
+      ehframe_rel++;
+    }
+  /R_X86_64_64.*x \+ 0/ {
+      relocx++;
+    }
+  /R_X86_64_64.*y \+ 0/ {
+      relocy++;
+    }
+  END {
+      errs = 0;
+      if (progbits != 0)
+       {
+         printf "%s: There should be no .eh_frame sections of type PROGBITS.\n", FILE;
+         errs++;
+       }
+      if (unwind != 1)
+       {
+         printf "%s: There should be exactly one .eh_frame section of type X86_64_UNWIND.\n", FILE;
+         errs++;
+       }
+      if (ehframe_rel != 1)
+       {
+         printf "%s: There should be exactly one .rela.eh_frame relocation section.\n", FILE;
+         errs++;
+       }
+      if (relocx != 1)
+       {
+         printf "%s: There should be exactly one relocation for x.\n", FILE;
+         errs++;
+       }
+      if (relocy != 1)
+       {
+         printf "%s: There should be exactly one relocation for y.\n", FILE;
+         errs++;
+       }
+      exit errs;
+    }
+  ' $1
+}
+
+check pr23016_1.stdout
+check pr23016_1r.stdout
+
+exit 0
diff --git a/gold/testsuite/pr23016_1a.s b/gold/testsuite/pr23016_1a.s
new file mode 100644 (file)
index 0000000..02de7e7
--- /dev/null
@@ -0,0 +1,3 @@
+       .section .eh_frame,"aw",@progbits
+       .globl x
+       .quad x
diff --git a/gold/testsuite/pr23016_1b.s b/gold/testsuite/pr23016_1b.s
new file mode 100644 (file)
index 0000000..6f1d888
--- /dev/null
@@ -0,0 +1,3 @@
+       .section .eh_frame,"aw",@unwind
+       .globl y
+       .quad y
diff --git a/gold/testsuite/pr23016_2.sh b/gold/testsuite/pr23016_2.sh
new file mode 100755 (executable)
index 0000000..952188c
--- /dev/null
@@ -0,0 +1,57 @@
+#!/bin/sh
+
+# pr23016_2.sh -- check that relocations get written to separate sections
+# when data sections of the same name are not merged.
+
+# Copyright (C) 2018 Free Software Foundation, Inc.
+# Written by Cary Coutant <ccoutant@gmail.com>.
+
+# This file is part of gold.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+set -e
+
+awk '
+BEGIN {
+    sect = 0;
+    relocx = 0;
+    relocy = 0;
+  }
+/^Relocation section .\.relaone/ {
+    sect += 1;
+  }
+/R_X86_64_64.*x \+ 0/ {
+    relocx += sect;
+  }
+/R_X86_64_64.*y \+ 0/ {
+    relocy = sect;
+  }
+END {
+    if (relocx != 1)
+      {
+       printf "Relocation for x should be in first relocation section.\n";
+       exit 1;
+      }
+    if (relocy != 2)
+      {
+       printf "Relocation for y should be in second relocation section.\n";
+       exit 1;
+      }
+  }
+' pr23016_2.stdout
+
+exit 0
diff --git a/gold/testsuite/pr23016_2a.s b/gold/testsuite/pr23016_2a.s
new file mode 100644 (file)
index 0000000..383c90d
--- /dev/null
@@ -0,0 +1,3 @@
+       .section one,"aw",@progbits
+       .globl x
+       .quad x
diff --git a/gold/testsuite/pr23016_2b.s b/gold/testsuite/pr23016_2b.s
new file mode 100644 (file)
index 0000000..8de9095
--- /dev/null
@@ -0,0 +1,3 @@
+       .section one,"aw",@note
+       .globl y
+       .quad y
index d79f10da98c8afd5d43857aa905f3bf15d91b6ff..da83b3b4f4594e474c3226a5f3acddff5dc98a44 100644 (file)
@@ -118,6 +118,7 @@ const Target::Target_info Target_test<size, big_endian>::test_target_info =
   NULL,                                        // attributes_vendor
   "_start",                            // entry_symbol_name
   32,                                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,                        // unwind_section_type
 };
 
 // The test targets.
index 595c9e6b198191de82963a9f76d5bc9a79272621..696fcd6e1407ed27c872954b0176fae3d847734d 100644 (file)
@@ -688,6 +688,7 @@ const Target::Target_info Target_tilegx<64, false>::tilegx_info =
   NULL,                 // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 template<>
@@ -716,6 +717,7 @@ const Target::Target_info Target_tilegx<32, false>::tilegx_info =
   NULL,                 // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 template<>
@@ -744,6 +746,7 @@ const Target::Target_info Target_tilegx<64, true>::tilegx_info =
   NULL,                 // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 template<>
@@ -772,6 +775,7 @@ const Target::Target_info Target_tilegx<32, true>::tilegx_info =
   NULL,                  // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_PROGBITS,        // unwind_section_type
 };
 
 // tilegx relocation handlers
index a8140602b02913c0b33786c7f3ca7060e8a69051..603ac300f72f1b1ab37b3c2332528b5ce06d302e 100644 (file)
@@ -1273,6 +1273,7 @@ const Target::Target_info Target_x86_64<64>::x86_64_info =
   NULL,                        // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_X86_64_UNWIND,   // unwind_section_type
 };
 
 template<>
@@ -1301,6 +1302,7 @@ const Target::Target_info Target_x86_64<32>::x86_64_info =
   NULL,                        // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_X86_64_UNWIND,   // unwind_section_type
 };
 
 // This is called when a new output section is created.  This is where
@@ -5578,6 +5580,7 @@ const Target::Target_info Target_x86_64_nacl<64>::x86_64_nacl_info =
   NULL,                        // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_X86_64_UNWIND,   // unwind_section_type
 };
 
 template<>
@@ -5606,6 +5609,7 @@ const Target::Target_info Target_x86_64_nacl<32>::x86_64_nacl_info =
   NULL,                        // attributes_vendor
   "_start",            // entry_symbol_name
   32,                  // hash_entry_size
+  elfcpp::SHT_X86_64_UNWIND,   // unwind_section_type
 };
 
 #define        NACLMASK        0xe0            // 32-byte alignment mask.