aboutsummaryrefslogtreecommitdiff
path: root/gold/layout.cc
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2020-10-13 05:18:13 -0700
committerH.J. Lu <hjl.tools@gmail.com>2020-10-13 05:18:24 -0700
commit6bf4a34047452f882c5cc66bd85812ee1bb5a41c (patch)
tree2d96b0c8ef59de1d9e026497798470bc9504bb08 /gold/layout.cc
parentaac1d94f19492fb6bea7193497bce599952c429d (diff)
downloadgdb-6bf4a34047452f882c5cc66bd85812ee1bb5a41c.zip
gdb-6bf4a34047452f882c5cc66bd85812ee1bb5a41c.tar.gz
gdb-6bf4a34047452f882c5cc66bd85812ee1bb5a41c.tar.bz2
gold: Properly align the NT_GNU_PROPERTY_TYPE_0 note
The NT_GNU_PROPERTY_TYPE_0 note should be aligned to 8 bytes for 64-bit ELF as specified by gABI. A note section can be only placed in a PT_NOTE segment with the same alignment. PR gold/22914 PR gold/23535 * layout.cc (Layout::attach_allocated_section_to_segment): Place a note section in a PT_NOTE segment with the same alignment. Set the alignment of the PT_NOTE segment from the alignment of the note section. (Layout::create_note): Align the NT_GNU_PROPERTY_TYPE_0 note to 8 bytes for 64-bit ELF. (Layout::segment_precedes): Place segments with larger alignments first. * output.cc (Output_segment::Output_segment): Initialize align_. * output.h (Output_segment): Add align, set_align and align_. * testsuite/Makefile.am (gnu_property_test.stdout): Pass -lhSWn to $(TEST_READELF). (gnu_property_test): Pass --build-id to ld. * testsuite/Makefile.in: Regenerated. * testsuite/gnu_property_test.sh (check_alignment): New. Use check_alignment to check the NT_GNU_PROPERTY_TYPE_0 note alignment. Verify that there are 2 PT_NOTE segments.
Diffstat (limited to 'gold/layout.cc')
-rw-r--r--gold/layout.cc15
1 files changed, 14 insertions, 1 deletions
diff --git a/gold/layout.cc b/gold/layout.cc
index 13e533a..8563f11 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -2062,12 +2062,15 @@ Layout::attach_allocated_section_to_segment(const Target* target,
// segment.
if (os->type() == elfcpp::SHT_NOTE)
{
+ uint64_t os_align = os->addralign();
+
// See if we already have an equivalent PT_NOTE segment.
for (p = this->segment_list_.begin();
p != segment_list_.end();
++p)
{
if ((*p)->type() == elfcpp::PT_NOTE
+ && (*p)->align() == os_align
&& (((*p)->flags() & elfcpp::PF_W)
== (seg_flags & elfcpp::PF_W)))
{
@@ -2081,6 +2084,7 @@ Layout::attach_allocated_section_to_segment(const Target* target,
Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE,
seg_flags);
oseg->add_output_section_to_nonload(os, seg_flags);
+ oseg->set_align(os_align);
}
}
@@ -3184,6 +3188,10 @@ Layout::create_note(const char* name, int note_type,
#else
const int size = 32;
#endif
+ // The NT_GNU_PROPERTY_TYPE_0 note is aligned to the pointer size.
+ const int addralign = ((note_type == elfcpp::NT_GNU_PROPERTY_TYPE_0
+ ? parameters->target().get_size()
+ : size) / 8);
// The contents of the .note section.
size_t namesz = strlen(name) + 1;
@@ -3247,7 +3255,7 @@ Layout::create_note(const char* name, int note_type,
return NULL;
Output_section_data* posd = new Output_data_const_buffer(buffer, notehdrsz,
- size / 8,
+ addralign,
"** note header");
os->add_output_section_data(posd);
@@ -3705,6 +3713,11 @@ Layout::segment_precedes(const Output_segment* seg1,
{
if (type1 != type2)
return type1 < type2;
+ uint64_t align1 = seg1->align();
+ uint64_t align2 = seg2->align();
+ // Place segments with larger alignments first.
+ if (align1 != align2)
+ return align1 > align2;
gold_assert(flags1 != flags2
|| this->script_options_->saw_phdrs_clause());
return flags1 < flags2;