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.
This commit is contained in:
Cary Coutant 2018-04-02 16:12:10 -07:00
parent 8849a5e9ed
commit bce5a025d2
27 changed files with 395 additions and 69 deletions

View 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

View 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.

View 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>

View 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

View 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.

View 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

View 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()

View 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.

View 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_);
}

View 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];

View 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

View 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

View 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

View 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>

View 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

View 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)

View 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

View 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

87
gold/testsuite/pr23016_1.sh Executable file
View File

@ -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

View File

@ -0,0 +1,3 @@
.section .eh_frame,"aw",@progbits
.globl x
.quad x

View File

@ -0,0 +1,3 @@
.section .eh_frame,"aw",@unwind
.globl y
.quad y

57
gold/testsuite/pr23016_2.sh Executable file
View File

@ -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

View File

@ -0,0 +1,3 @@
.section one,"aw",@progbits
.globl x
.quad x

View File

@ -0,0 +1,3 @@
.section one,"aw",@note
.globl y
.quad y

View 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.

View 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

View 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.