Skip to content

Commit

Permalink
[ELF] Do not create multiple NOTE segments
Browse files Browse the repository at this point in the history
  • Loading branch information
rui314 committed Sep 12, 2022
1 parent 428aac7 commit cda57cf
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 12 deletions.
6 changes: 2 additions & 4 deletions elf/output-chunks.cc
Expand Up @@ -213,8 +213,7 @@ static std::vector<ElfPhdr<E>> create_phdr(Context<E> &ctx) {
if (ctx.interp)
define(PT_INTERP, PF_R, 1, ctx.interp);

// Create a PT_NOTE for each group of SHF_NOTE sections with the same
// alignment requirement.
// Create a PT_NOTE for SHF_NOTE sections.
for (i64 i = 0, end = ctx.chunks.size(); i < end;) {
Chunk<E> *first = ctx.chunks[i++];
if (!is_note(first))
Expand All @@ -225,8 +224,7 @@ static std::vector<ElfPhdr<E>> create_phdr(Context<E> &ctx) {
define(PT_NOTE, flags, alignment, first);

while (i < end && is_note(ctx.chunks[i]) &&
to_phdr_flags(ctx, ctx.chunks[i]) == flags &&
ctx.chunks[i]->shdr.sh_addralign == alignment)
to_phdr_flags(ctx, ctx.chunks[i]) == flags)
append(ctx.chunks[i++]);
}

Expand Down
15 changes: 11 additions & 4 deletions elf/passes.cc
Expand Up @@ -1287,14 +1287,21 @@ void clear_padding(Context<E> &ctx) {
// sections in a single seek.
//
// .note sections are also placed at the beginning so that they are
// included in a core crash dump even if it's truncated by ulimit. In
// included in a core crash dump even if it's truncated by ulimit. In
// particular, if .note.gnu.build-id is in a truncated core file, you
// can at least identify which executable has crashed.
//
// A PT_NOTE segment will contain multiple .note sections if exists,
// but there's no way to represent a gap between .note sections.
// Therefore, we sort .note sections by decreasing alignment
// requirement. I believe each .note section size is a multiple of its
// alignment, so by sorting them by alignment, we should be able to
// avoid a gap between .note sections.
//
// .toc is placed right after .got for PPC64. PPC-specific .toc section
// contains data that may be accessed with a 16-bit offset relative to
// %r2. %r2 is set to .got + 0x8000. Therefore, .toc needs to be within
// [.got, .got + 0x10000).
// %r2. %r2 is set to .got + 32 KiB. Therefore, .toc needs to be within
// [.got, .got + 64 KiB).
//
// Other file layouts are possible, but this layout is chosen to keep
// the number of segments as few as possible.
Expand Down Expand Up @@ -1346,7 +1353,7 @@ void sort_output_sections(Context<E> &ctx) {

auto get_rank2 = [&](Chunk<E> *chunk) -> i64 {
if (chunk->shdr.sh_type == SHT_NOTE)
return chunk->shdr.sh_addralign;
return -chunk->shdr.sh_addralign;

if (chunk->name == ".toc")
return 2;
Expand Down
3 changes: 1 addition & 2 deletions test/elf/note.sh
Expand Up @@ -45,8 +45,7 @@ grep -Eq '.note.baz\s+NOTE.+000008 00 A 0 0 8' $t/log
grep -Eq '.note.nonalloc\s+NOTE.+000008 00 0 0 1' $t/log

readelf --segments $t/exe > $t/log
fgrep -q '01 .note.bar' $t/log
fgrep -q '02 .note.baz .note.foo' $t/log
grep -Fq '01 .note.baz .note.foo .note.bar' $t/log
! grep -q 'NOTE.*0x0000000000000000 0x0000000000000000' $t/log || false

echo OK
3 changes: 1 addition & 2 deletions test/elf/note2.sh
Expand Up @@ -39,7 +39,6 @@ EOF
./mold -static -o $t/exe $t/a.o $t/b.o $t/c.o $t/d.o

readelf --segments $t/exe > $t/log
fgrep -q '01 .note.b' $t/log
fgrep -q '02 .note.a .note.c' $t/log
grep -Fq '01 .note.a .note.c .note.b' $t/log

echo OK

0 comments on commit cda57cf

Please sign in to comment.