diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2020-10-13 05:18:13 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2020-10-13 05:18:24 -0700 |
commit | 6bf4a34047452f882c5cc66bd85812ee1bb5a41c (patch) | |
tree | 2d96b0c8ef59de1d9e026497798470bc9504bb08 /gold/layout.cc | |
parent | aac1d94f19492fb6bea7193497bce599952c429d (diff) | |
download | gdb-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.cc | 15 |
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; |