summaryrefslogtreecommitdiff
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)
downloadbinutils-gdb-bce5a025d2ed7eda2c5bbb85bd9b33333ca5d556.tar.gz
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 a97a3d003af..2841bc02dba 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 ecb400b2743..4dd207fe096 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 6c57af5b37b..848924757e3 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 564e616ccbe..725b9429eb6 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 417a7399574..21f060c945b 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 f5fe805ea78..2eb7b7c8429 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 0c34d3db195..806f6e53b01 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 543a23462f7..ee2c037ad53 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 0c8f7e2598a..0dbb0cbe12d 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 c92e030c2ea..9fb9b306280 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 0a34a2af21e..1701db1c99f 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 c7545ca81f6..c2458831e36 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 f6d589c6ea7..39bda353a43 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 3542ee6d301..1043056d021 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 8551afd4be5..1abcb4125f1 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 059d2d02c7d..da2f6bbc78c 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 cf0b970eaa1..7140df64d0d 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 3bddc124748..48e5b9e2fcc 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 00000000000..f909a9bcfc3
--- /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 00000000000..02de7e7d026
--- /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 00000000000..6f1d88868ba
--- /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 00000000000..952188c1a2d
--- /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 00000000000..383c90d7e41
--- /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 00000000000..8de90952eb0
--- /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 d79f10da98c..da83b3b4f45 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 595c9e6b198..696fcd6e140 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 a8140602b02..603ac300f72 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.