diff --git a/packages/devel/mold/patches/mold-999.01-fix-strip-on-armv7.patch b/packages/devel/mold/patches/mold-999.01-fix-strip-on-armv7.patch new file mode 100644 index 0000000000..8bb7c21b23 --- /dev/null +++ b/packages/devel/mold/patches/mold-999.01-fix-strip-on-armv7.patch @@ -0,0 +1,164 @@ +From 610042a8e927106cb2d852fba2a90faa0d0e050f Mon Sep 17 00:00:00 2001 +From: Rui Ueyama +Date: Fri, 21 Oct 2022 07:08:09 +0800 +Subject: [PATCH] [ELF] Set .ARM.exidx's sh_link to .text + +GNU binutil's strip command doesn't like an .ARM.exidx section with +sh_link set to 0. arm-linux-gnueabihf-strip actually crashes on my +machine when the command is run on such a file. + +https://github.com/rui314/mold/issues/801 +--- + elf/arch-arm32.cc | 56 +++++++++++++++++++++++++++++-------------- + elf/mold.h | 2 +- + elf/output-chunks.cc | 4 ++-- + elf/passes.cc | 2 +- + test/elf/exception.sh | 8 +++++++ + 5 files changed, 50 insertions(+), 22 deletions(-) + +diff --git a/elf/arch-arm32.cc b/elf/arch-arm32.cc +index 46e45d43d..bea510763 100644 +--- a/elf/arch-arm32.cc ++++ b/elf/arch-arm32.cc +@@ -552,14 +552,6 @@ void RangeExtensionThunk::copy_buf(Context &ctx) { + } + } + +-template +-static OutputSection *find_exidx_section(Context &ctx) { +- for (std::unique_ptr> &osec : ctx.output_sections) +- if (osec->shdr.sh_type == SHT_ARM_EXIDX) +- return osec.get(); +- return nullptr; +-} +- + // ARM executables use an .ARM.exidx section to look up an exception + // handling record for the current instruction pointer. The table needs + // to be sorted by their addresses. +@@ -569,13 +561,7 @@ static OutputSection *find_exidx_section(Context &ctx) { + // likely that it's due to some historical reason. + // + // This function sorts .ARM.exidx records. +-void sort_arm_exidx(Context &ctx) { +- Timer t(ctx, "sort_arm_exidx"); +- +- OutputSection *osec = find_exidx_section(ctx); +- if (!osec) +- return; +- ++static void sort_exidx(Context &ctx, OutputSection &osec) { + // .ARM.exidx records consists of a signed 31-bit relative address + // and a 32-bit value. The relative address indicates the start + // address of a function that the record covers. The value is one of +@@ -595,11 +581,11 @@ void sort_arm_exidx(Context &ctx) { + ul32 val; + }; + +- if (osec->shdr.sh_size % sizeof(Entry)) ++ if (osec.shdr.sh_size % sizeof(Entry)) + Fatal(ctx) << "invalid .ARM.exidx section size"; + +- Entry *ent = (Entry *)(ctx.buf + osec->shdr.sh_offset); +- i64 num_entries = osec->shdr.sh_size / sizeof(Entry); ++ Entry *ent = (Entry *)(ctx.buf + osec.shdr.sh_offset); ++ i64 num_entries = osec.shdr.sh_size / sizeof(Entry); + + // Entry's addresses are relative to themselves. In order to sort + // records by addresses, we first translate them so that the addresses +@@ -628,4 +614,38 @@ void sort_arm_exidx(Context &ctx) { + }); + } + ++void fixup_arm_exidx_section(Context &ctx) { ++ Timer t(ctx, "fixup_arm_exidx_section"); ++ ++ auto find_exidx = [&]() -> OutputSection * { ++ for (std::unique_ptr> &osec : ctx.output_sections) ++ if (osec->shdr.sh_type == SHT_ARM_EXIDX) ++ return osec.get(); ++ return nullptr; ++ }; ++ ++ OutputSection *exidx = find_exidx(); ++ if (!exidx) ++ return; ++ ++ // Sort .ARM.exidx contents ++ sort_exidx(ctx, *exidx); ++ ++ // .ARM.exidx's sh_link should be set to the .text section index. ++ // Runtime doesn't care about it, but the binutils's strip command does. ++ if (ctx.shdr) { ++ auto find_text = [&]() -> OutputSection * { ++ for (std::unique_ptr> &osec : ctx.output_sections) ++ if (osec->name == ".text") ++ return osec.get(); ++ return nullptr; ++ }; ++ ++ if (OutputSection *text = find_exidx()) { ++ exidx->shdr.sh_link = text->shndx; ++ ctx.shdr->copy_buf(ctx); ++ } ++ } ++} ++ + } // namespace mold::elf +diff --git a/elf/mold.h b/elf/mold.h +index 11938270e..c8bac2b4e 100644 +--- a/elf/mold.h ++++ b/elf/mold.h +@@ -1434,7 +1434,7 @@ template void write_dependency_file(Context &); + // arch-arm32.cc + // + +-void sort_arm_exidx(Context &ctx); ++void fixup_arm_exidx_section(Context &ctx); + + // + // arch-riscv64.cc +diff --git a/elf/output-chunks.cc b/elf/output-chunks.cc +index 54562feb2..0d1d0dcfd 100644 +--- a/elf/output-chunks.cc ++++ b/elf/output-chunks.cc +@@ -847,9 +847,9 @@ get_output_name(Context &ctx, std::string_view name, u64 flags) { + + if ((name == ".rodata" || name.starts_with(".rodata.")) && (flags & SHF_MERGE)) + return (flags & SHF_STRINGS) ? ".rodata.str" : ".rodata.cst"; +- if (name == ".ARM.exidx" || name.starts_with(".ARM.exidx.")) ++ if (name.starts_with(".ARM.exidx")) + return ".ARM.exidx"; +- if (name == ".ARM.extab" || name.starts_with(".ARM.extab.")) ++ if (name.starts_with(".ARM.extab")) + return ".ARM.extab"; + + if (ctx.arg.z_keep_text_section_prefix) { +diff --git a/elf/passes.cc b/elf/passes.cc +index 713a06a84..4bffc3dbd 100644 +--- a/elf/passes.cc ++++ b/elf/passes.cc +@@ -1102,7 +1102,7 @@ void copy_chunks(Context &ctx) { + report_undef_errors(ctx); + + if constexpr (std::is_same_v) +- sort_arm_exidx(ctx); ++ fixup_arm_exidx_section(ctx); + } + + template +diff --git a/test/elf/exception.sh b/test/elf/exception.sh +index 6832966f0..c584c99fa 100755 +--- a/test/elf/exception.sh ++++ b/test/elf/exception.sh +@@ -65,3 +65,11 @@ if [ $MACHINE = x86_64 -o $MACHINE = aarch64 ]; then + $CXX -B. -o $t/exe10 $t/e.o -no-pie + $QEMU $t/exe10 + fi ++ ++$CXX -B. -o $t/exe11 $t/b.o -pie ++$STRIP $t/exe11 ++$QEMU $t/exe11 ++ ++$CXX -B. -o $t/exe12 $t/c.o -no-pie ++$STRIP $t/exe12 ++$QEMU $t/exe12