aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCary Coutant <ccoutant@gmail.com>2018-04-02 16:12:10 -0700
committerCary Coutant <ccoutant@gmail.com>2018-04-02 19:07:04 -0700
commitbce5a025d2ed7eda2c5bbb85bd9b33333ca5d556 (patch)
tree92912c522de8e45805825292a4a94e50f753584c
parent8849a5e9edda5f00d727490c7bb8be3c616742ae (diff)
downloadgdb-bce5a025d2ed7eda2c5bbb85bd9b33333ca5d556.zip
gdb-bce5a025d2ed7eda2c5bbb85bd9b33333ca5d556.tar.gz
gdb-bce5a025d2ed7eda2c5bbb85bd9b33333ca5d556.tar.bz2
Fix problem where mixed section types can cause internal error during a -r link.
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.
-rw-r--r--gold/ChangeLog52
-rw-r--r--gold/aarch64.cc4
-rw-r--r--gold/arm.cc2
-rw-r--r--gold/i386.cc3
-rw-r--r--gold/incremental.cc7
-rw-r--r--gold/layout.cc48
-rw-r--r--gold/layout.h3
-rw-r--r--gold/mips.cc2
-rw-r--r--gold/object.cc76
-rw-r--r--gold/object.h12
-rw-r--r--gold/output.cc3
-rw-r--r--gold/output.h12
-rw-r--r--gold/powerpc.cc4
-rw-r--r--gold/s390.cc2
-rw-r--r--gold/sparc.cc2
-rw-r--r--gold/target.h8
-rw-r--r--gold/testsuite/Makefile.am26
-rw-r--r--gold/testsuite/Makefile.in33
-rwxr-xr-xgold/testsuite/pr23016_1.sh87
-rw-r--r--gold/testsuite/pr23016_1a.s3
-rw-r--r--gold/testsuite/pr23016_1b.s3
-rwxr-xr-xgold/testsuite/pr23016_2.sh57
-rw-r--r--gold/testsuite/pr23016_2a.s3
-rw-r--r--gold/testsuite/pr23016_2b.s3
-rw-r--r--gold/testsuite/testfile.cc1
-rw-r--r--gold/tilegx.cc4
-rw-r--r--gold/x86_64.cc4
27 files changed, 395 insertions, 69 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index a97a3d0..2841bc0 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -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
diff --git a/gold/aarch64.cc b/gold/aarch64.cc
index ecb400b..4dd207f 100644
--- a/gold/aarch64.cc
+++ b/gold/aarch64.cc
@@ -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.
diff --git a/gold/arm.cc b/gold/arm.cc
index 6c57af5..8489247 100644
--- a/gold/arm.cc
+++ b/gold/arm.cc
@@ -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>
diff --git a/gold/i386.cc b/gold/i386.cc
index 564e616..725b942 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -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
diff --git a/gold/incremental.cc b/gold/incremental.cc
index 417a739..21f060c 100644
--- a/gold/incremental.cc
+++ b/gold/incremental.cc
@@ -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.
diff --git a/gold/layout.cc b/gold/layout.cc
index f5fe805..2eb7b7c 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -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
diff --git a/gold/layout.h b/gold/layout.h
index 0c34d3d..806f6e5 100644
--- a/gold/layout.h
+++ b/gold/layout.h
@@ -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()
diff --git a/gold/mips.cc b/gold/mips.cc
index 543a234..ee2c037 100644
--- a/gold/mips.cc
+++ b/gold/mips.cc
@@ -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.
diff --git a/gold/object.cc b/gold/object.cc
index 0c8f7e2..0dbb0cb 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -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_);
}
diff --git a/gold/object.h b/gold/object.h
index c92e030..9fb9b30 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -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];
diff --git a/gold/output.cc b/gold/output.cc
index 0a34a2a..1701db1 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -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
diff --git a/gold/output.h b/gold/output.h
index c7545ca..c245883 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -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
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index f6d589c..39bda35 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -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
diff --git a/gold/s390.cc b/gold/s390.cc
index 3542ee6..1043056 100644
--- a/gold/s390.cc
+++ b/gold/s390.cc
@@ -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>
diff --git a/gold/sparc.cc b/gold/sparc.cc
index 8551afd..1abcb41 100644
--- a/gold/sparc.cc
+++ b/gold/sparc.cc
@@ -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
diff --git a/gold/target.h b/gold/target.h
index 059d2d0..da2f6bb 100644
--- a/gold/target.h
+++ b/gold/target.h
@@ -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)
diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am
index cf0b970..7140df6 100644
--- a/gold/testsuite/Makefile.am
+++ b/gold/testsuite/Makefile.am
@@ -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
diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in
index 3bddc12..48e5b9e 100644
--- a/gold/testsuite/Makefile.in
+++ b/gold/testsuite/Makefile.in
@@ -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
index 0000000..f909a9b
--- /dev/null
+++ b/gold/testsuite/pr23016_1.sh
@@ -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
index 0000000..02de7e7
--- /dev/null
+++ b/gold/testsuite/pr23016_1a.s
@@ -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
index 0000000..6f1d888
--- /dev/null
+++ b/gold/testsuite/pr23016_1b.s
@@ -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
index 0000000..952188c
--- /dev/null
+++ b/gold/testsuite/pr23016_2.sh
@@ -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
index 0000000..383c90d
--- /dev/null
+++ b/gold/testsuite/pr23016_2a.s
@@ -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
index 0000000..8de9095
--- /dev/null
+++ b/gold/testsuite/pr23016_2b.s
@@ -0,0 +1,3 @@
+ .section one,"aw",@note
+ .globl y
+ .quad y
diff --git a/gold/testsuite/testfile.cc b/gold/testsuite/testfile.cc
index d79f10d..da83b3b 100644
--- a/gold/testsuite/testfile.cc
+++ b/gold/testsuite/testfile.cc
@@ -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.
diff --git a/gold/tilegx.cc b/gold/tilegx.cc
index 595c9e6..696fcd6 100644
--- a/gold/tilegx.cc
+++ b/gold/tilegx.cc
@@ -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
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index a814060..603ac30 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -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.