+2020-10-13 H.J. Lu <hongjiu.lu@intel.com>
+
+ 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.
+
2020-10-13 H.J. Lu <hongjiu.lu@intel.com>
PR gold/21452
// 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)))
{
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);
}
}
#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;
return NULL;
Output_section_data* posd = new Output_data_const_buffer(buffer, notehdrsz,
- size / 8,
+ addralign,
"** note header");
os->add_output_section_data(posd);
{
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;
: vaddr_(0),
paddr_(0),
memsz_(0),
+ align_(0),
max_align_(0),
min_p_align_(0),
offset_(0),
offset() const
{ return this->offset_; }
+ // Return the segment alignment.
+ uint64_t
+ align() const
+ { return this->align_; }
+
+ // Set the segment alignment.
+ void
+ set_align(uint64_t align)
+ { this->align_ = align; }
+
// Whether this is a segment created to hold large data sections.
bool
is_large_data_segment() const
uint64_t paddr_;
// The size of the segment in memory.
uint64_t memsz_;
+ // The segment alignment.
+ uint64_t align_;
// The maximum section alignment. The is_max_align_known_ field
// indicates whether this has been finalized.
uint64_t max_align_;
check_DATA += gnu_property_test.stdout
MOSTLYCLEANFILES += gnu_property_test
gnu_property_test.stdout: gnu_property_test
- $(TEST_READELF) -n $< >$@
+ $(TEST_READELF) -lhSWn $< >$@
gnu_property_test: gcctestdir/ld gnu_property_a.o gnu_property_b.o gnu_property_c.o
- gcctestdir/ld -o $@ gnu_property_a.o gnu_property_b.o gnu_property_c.o
+ gcctestdir/ld --build-id -o $@ gnu_property_a.o gnu_property_b.o gnu_property_c.o
gnu_property_main.o: gnu_property_main.c
$(COMPILE) -c -o $@ $<
gnu_property_a.o: gnu_property_a.S
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_x86_64_bnd_2.o: exception_test_2.cc gcctestdir/as
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -Wa,-madd-bnd-prefix -o $@ $<
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@gnu_property_test.stdout: gnu_property_test
-@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -n $< >$@
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -lhSWn $< >$@
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@gnu_property_test: gcctestdir/ld gnu_property_a.o gnu_property_b.o gnu_property_c.o
-@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld -o $@ gnu_property_a.o gnu_property_b.o gnu_property_c.o
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld --build-id -o $@ gnu_property_a.o gnu_property_b.o gnu_property_c.o
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@gnu_property_main.o: gnu_property_main.c
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -o $@ $<
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@gnu_property_a.o: gnu_property_a.S
fi
}
+check_alignment ()
+{
+ if egrep -q "Class:[ \t]+ELF64" "$1"
+ then
+ align=8
+ else
+ align=4
+ fi
+ if ! egrep -q ".note.gnu.property[ \t]+NOTE.*$align$" "$1"
+ then
+ echo "Wrong .note.gnu.property alignment in $1:"
+ egrep ".note.gnu.property[ \t]+NOTE.*$align" "$1"
+ exit 1
+ fi
+}
+
+check_alignment gnu_property_test.stdout
+
check_count gnu_property_test.stdout "GNU\s*0x[0-9a-f]*\s*NT_GNU_PROPERTY_TYPE_0" 1
+check_count gnu_property_test.stdout "^ NOTE" 2
+
check gnu_property_test.stdout "stack size: 0x111100"
check gnu_property_test.stdout "no copy on protected"
check gnu_property_test.stdout "x86 ISA used: i486, SSE2, SSE4_2, AVX512CD"