1
1
mirror of https://github.com/rui314/mold.git synced 2024-09-11 13:06:59 +03:00

Emit PT_GNU_PROPERTY program header if .note.gnu.property is present

It looks like Linux kernel reads this program header to enable BTI on ARM64.
This commit is contained in:
Rui Ueyama 2024-08-15 12:51:57 +09:00
parent c2956484ca
commit 23bc92c66f
6 changed files with 43 additions and 23 deletions

View File

@ -722,7 +722,11 @@ u64 get_eflags(Context<E> &ctx) {
void fixup_arm_exidx_section(Context<E> &ctx) {
Timer t(ctx, "fixup_arm_exidx_section");
OutputSection<E> *osec = find_section(ctx, SHT_ARM_EXIDX);
Chunk<E> *chunk = find_chunk(ctx, SHT_ARM_EXIDX);
if (!chunk)
return;
OutputSection<E> *osec = chunk->to_osec();
if (!osec)
return;
@ -780,7 +784,7 @@ void fixup_arm_exidx_section(Context<E> &ctx) {
// .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) {
if (Chunk<E> *text = find_section(ctx, ".text")) {
if (Chunk<E> *text = find_chunk(ctx, ".text")) {
osec->shdr.sh_link = text->shndx;
ctx.shdr->copy_buf(ctx);
}

View File

@ -191,6 +191,7 @@ enum : u32 {
PT_GNU_EH_FRAME = 0x6474e550,
PT_GNU_STACK = 0x6474e551,
PT_GNU_RELRO = 0x6474e552,
PT_GNU_PROPERTY = 0x6474e553,
PT_OPENBSD_RANDOMIZE = 0x65a3dbe6,
PT_ARM_EXIDX = 0x70000001,
PT_RISCV_ATTRIBUTES = 0x70000003,

View File

@ -341,10 +341,10 @@ template <typename E> u64 get_dtp_addr(const ElfPhdr<E> &);
//
template <typename E>
OutputSection<E> *find_section(Context<E> &ctx, u32 sh_type);
Chunk<E> *find_chunk(Context<E> &ctx, u32 sh_type);
template <typename E>
OutputSection<E> *find_section(Context<E> &ctx, std::string_view name);
Chunk<E> *find_chunk(Context<E> &ctx, std::string_view name);
template <typename E>
u64 get_eflags(Context<E> &ctx) {

View File

@ -25,20 +25,18 @@ static u32 elf_hash(std::string_view name) {
}
template <typename E>
OutputSection<E> *find_section(Context<E> &ctx, u32 sh_type) {
Chunk<E> *find_chunk(Context<E> &ctx, u32 sh_type) {
for (Chunk<E> *chunk : ctx.chunks)
if (OutputSection<E> *osec = chunk->to_osec())
if (osec->shdr.sh_type == sh_type)
return osec;
if (chunk->shdr.sh_type == sh_type)
return chunk;
return nullptr;
}
template <typename E>
OutputSection<E> *find_section(Context<E> &ctx, std::string_view name) {
Chunk<E> *find_chunk(Context<E> &ctx, std::string_view name) {
for (Chunk<E> *chunk : ctx.chunks)
if (OutputSection<E> *osec = chunk->to_osec())
if (osec->name == name)
return osec;
if (chunk->name == name)
return chunk;
return nullptr;
}
@ -267,6 +265,10 @@ static std::vector<ElfPhdr<E>> create_phdr(Context<E> &ctx) {
if (ctx.eh_frame_hdr)
define(PT_GNU_EH_FRAME, PF_R, ctx.eh_frame_hdr);
// Add PT_GNU_PROPERTY
if (Chunk<E> *chunk = find_chunk(ctx, ".note.gnu.property"))
define(PT_GNU_PROPERTY, PF_R, chunk);
// Add PT_GNU_STACK, which is a marker segment that doesn't really
// contain any segments. It controls executable bit of stack area.
{
@ -293,8 +295,8 @@ static std::vector<ElfPhdr<E>> create_phdr(Context<E> &ctx) {
// Create a PT_ARM_EDXIDX
if constexpr (is_arm32<E>)
if (OutputSection<E> *osec = find_section(ctx, SHT_ARM_EXIDX))
define(PT_ARM_EXIDX, PF_R, osec);
if (Chunk<E> *chunk = find_chunk(ctx, SHT_ARM_EXIDX))
define(PT_ARM_EXIDX, PF_R, chunk);
// Create a PT_RISCV_ATTRIBUTES
if constexpr (is_riscv<E>)
@ -734,19 +736,19 @@ static std::vector<Word<E>> create_dynamic_section(Context<E> &ctx) {
define(DT_STRSZ, ctx.dynstr->shdr.sh_size);
}
if (find_section(ctx, SHT_INIT_ARRAY)) {
if (find_chunk(ctx, SHT_INIT_ARRAY)) {
define(DT_INIT_ARRAY, ctx.__init_array_start->value);
define(DT_INIT_ARRAYSZ,
ctx.__init_array_end->value - ctx.__init_array_start->value);
}
if (find_section(ctx, SHT_PREINIT_ARRAY)) {
if (find_chunk(ctx, SHT_PREINIT_ARRAY)) {
define(DT_PREINIT_ARRAY, ctx.__preinit_array_start->value);
define(DT_PREINIT_ARRAYSZ,
ctx.__preinit_array_end->value - ctx.__preinit_array_start->value);
}
if (find_section(ctx, SHT_FINI_ARRAY)) {
if (find_chunk(ctx, SHT_FINI_ARRAY)) {
define(DT_FINI_ARRAY, ctx.__fini_array_start->value);
define(DT_FINI_ARRAYSZ,
ctx.__fini_array_end->value - ctx.__fini_array_start->value);
@ -2949,8 +2951,8 @@ template class RelocSection<E>;
template class ComdatGroupSection<E>;
template class GnuDebuglinkSection<E>;
template OutputSection<E> *find_section(Context<E> &, u32);
template OutputSection<E> *find_section(Context<E> &, std::string_view);
template Chunk<E> *find_chunk(Context<E> &, u32);
template Chunk<E> *find_chunk(Context<E> &, std::string_view);
template i64 to_phdr_flags(Context<E> &ctx, Chunk<E> *chunk);
template ElfSym<E> to_output_esym(Context<E> &, Symbol<E> &, u32, U32<E> *);

View File

@ -1271,10 +1271,13 @@ void fixup_ctors_in_init_array(Context<E> &ctx) {
}
};
if (OutputSection<E> *osec = find_section(ctx, ".init_array"))
fixup(*osec);
if (OutputSection<E> *osec = find_section(ctx, ".fini_array"))
fixup(*osec);
if (Chunk<E> *chunk = find_chunk(ctx, ".init_array"))
if (OutputSection<E> *osec = chunk->to_osec())
fixup(*osec);
if (Chunk<E> *chunk = find_chunk(ctx, ".fini_array"))
if (OutputSection<E> *osec = chunk->to_osec())
fixup(*osec);
}
template <typename T>

10
test/gnu-property.sh Normal file
View File

@ -0,0 +1,10 @@
#!/bin/bash
. $(dirname $0)/common.inc
cat <<EOF | $CC -o $t/a.o -c -xc -
int main() {}
EOF
$CC -B. -o $t/exe $t/a.o -no-pie
readelf -W --sections $t/exe | grep -Fqw .note.gnu.property || skip
readelf -W --segments $t/exe | grep -qw GNU_PROPERTY