From eb6c213f2a9aa8a101b2b52a791be369d165e6a9 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Thu, 16 Nov 2023 11:33:10 +0900 Subject: [PATCH] Add --spare-program-headers This is a new experimental flag to make room at the end of PHDR so that post-processing tools can add more entries as needed. Fixes https://github.com/rui314/mold/issues/1148 --- elf/cmdline.cc | 5 +++++ elf/mold.h | 1 + elf/output-chunks.cc | 1 + test/elf/spare-program-headers.sh | 25 +++++++++++++++++++++++++ 4 files changed, 32 insertions(+) create mode 100755 test/elf/spare-program-headers.sh diff --git a/elf/cmdline.cc b/elf/cmdline.cc index 5261835da..cd250bec5 100644 --- a/elf/cmdline.cc +++ b/elf/cmdline.cc @@ -141,6 +141,8 @@ inline const char helpmsg[] = R"( --sort-common Ignored --sort-section Ignored --spare-dynamic-tags NUMBER Reserve give number of tags in .dynamic section + --spare-program-headers NUMBER + Reserve give number of slots in the program header --start-lib Give following object files in-archive-file semantics --end-lib End the effect of --start-lib --stats Print input statistics @@ -606,6 +608,9 @@ std::vector parse_nonpositional_args(Context &ctx) { ctx.arg.shared = true; } else if (read_arg("spare-dynamic-tags")) { ctx.arg.spare_dynamic_tags = parse_number(ctx, "spare-dynamic-tags", arg); + } else if (read_arg("spare-program-headers")) { + ctx.arg.spare_program_headers + = parse_number(ctx, "spare-program-headers", arg); } else if (read_flag("start-lib")) { remaining.push_back("--start-lib"); } else if (read_flag("start-stop")) { diff --git a/elf/mold.h b/elf/mold.h index ecafca93e..8b7ad4c5a 100644 --- a/elf/mold.h +++ b/elf/mold.h @@ -1700,6 +1700,7 @@ struct Context { bool z_text = false; i64 filler = -1; i64 spare_dynamic_tags = 5; + i64 spare_program_headers = 0; i64 thread_count = 0; i64 z_stack_size = 0; u64 shuffle_sections_seed; diff --git a/elf/output-chunks.cc b/elf/output-chunks.cc index f05539831..6b667222b 100644 --- a/elf/output-chunks.cc +++ b/elf/output-chunks.cc @@ -352,6 +352,7 @@ static std::vector> create_phdr(Context &ctx) { } } + vec.resize(vec.size() + ctx.arg.spare_program_headers); return vec; } diff --git a/test/elf/spare-program-headers.sh b/test/elf/spare-program-headers.sh new file mode 100755 index 000000000..782925a19 --- /dev/null +++ b/test/elf/spare-program-headers.sh @@ -0,0 +1,25 @@ +#!/bin/bash +. $(dirname $0)/common.inc + +cat < +int main() { + printf("Hello world\n"); +} +EOF + +$CC -B. -o $t/exe1 $t/a.o +$QEMU $t/exe1 | grep -q 'Hello world' +[ "$(readelf -Wl $t/exe1 | grep NULL | wc -l)" -eq 0 ] + +$CC -B. -o $t/exe2 $t/a.o -Wl,--spare-program-headers=0 +$QEMU $t/exe2 | grep -q 'Hello world' +[ "$(readelf -Wl $t/exe2 | grep NULL | wc -l)" -eq 0 ] + +$CC -B. -o $t/exe3 $t/a.o -Wl,--spare-program-headers=1 +$QEMU $t/exe3 | grep -q 'Hello world' +[ "$(readelf -Wl $t/exe3 | grep NULL | wc -l)" -eq 1 ] + +$CC -B. -o $t/exe4 $t/a.o -Wl,--spare-program-headers=5 +$QEMU $t/exe4 | grep -q 'Hello world' +[ "$(readelf -Wl $t/exe4 | grep NULL | wc -l)" -eq 5 ]