Merge GNU_PROPERTY_AARCH64_FEATURE_1_AND

We used to merge only x86 properties in .note.gnu.property, so an ARM64
output lost GNU_PROPERTY_AARCH64_FEATURE_1_AND even if all its inputs
were compiled with -mbranch-protection. We now AND-merge it as GNU ld
and lld do, and merge x86 properties only on x86.
This commit is contained in:
Rui Ueyama committed 2026-10-09 10:15:15 +09:00
1 parent 442f2d57a2
commit 38b10b4391
5 files changed
+62 -14

No files matched your search

+21 -11
View File
@@ -2,7 +2,7 @@
use std::collections::{BTreeMap, BTreeSet};
use crate::arch::Target;
use crate::arch::{Family, Target};
use crate::chunks::ChunkHeader;
use crate::context::Context;
use crate::elf::*;
@@ -46,15 +46,21 @@ pub fn update_shdr<E: Target>(ctx: &mut Context<E>) {
// Merge values for each key
let mut map: BTreeMap<u32, u32> = BTreeMap::new();
for key in keys {
if (GNU_PROPERTY_X86_UINT32_AND_LO..=GNU_PROPERTY_X86_UINT32_AND_HI).contains(&key) {
if (E::IS_X86
&& (GNU_PROPERTY_X86_UINT32_AND_LO..=GNU_PROPERTY_X86_UINT32_AND_HI).contains(&key))
|| (E::FAMILY == Family::Arm64 && key == GNU_PROPERTY_AARCH64_FEATURE_1_AND)
{
// An AND feature is set if all input objects have the property and
// the feature.
map.insert(key, files.iter().fold(u32::MAX, |acc, f| acc & value(f, key)));
} else if (GNU_PROPERTY_X86_UINT32_OR_LO..=GNU_PROPERTY_X86_UINT32_OR_HI).contains(&key) {
} else if E::IS_X86
&& (GNU_PROPERTY_X86_UINT32_OR_LO..=GNU_PROPERTY_X86_UINT32_OR_HI).contains(&key)
{
// An OR feature is set if some input object has the feature.
map.insert(key, files.iter().fold(0, |acc, f| acc | value(f, key)));
} else if (GNU_PROPERTY_X86_UINT32_OR_AND_LO..=GNU_PROPERTY_X86_UINT32_OR_AND_HI)
.contains(&key)
} else if E::IS_X86
&& (GNU_PROPERTY_X86_UINT32_OR_AND_LO..=GNU_PROPERTY_X86_UINT32_OR_AND_HI)
.contains(&key)
{
// An OR-AND feature is set if all input object files have the property
// and some of them have the feature.
@@ -64,13 +70,17 @@ pub fn update_shdr<E: Target>(ctx: &mut Context<E>) {
}
}
if ctx.args.z_ibt {
*map.entry(GNU_PROPERTY_X86_FEATURE_1_AND).or_insert(0) |= GNU_PROPERTY_X86_FEATURE_1_IBT;
if E::IS_X86 {
if ctx.args.z_ibt {
*map.entry(GNU_PROPERTY_X86_FEATURE_1_AND).or_insert(0) |=
GNU_PROPERTY_X86_FEATURE_1_IBT;
}
if ctx.args.z_shstk {
*map.entry(GNU_PROPERTY_X86_FEATURE_1_AND).or_insert(0) |=
GNU_PROPERTY_X86_FEATURE_1_SHSTK;
}
*map.entry(GNU_PROPERTY_X86_ISA_1_NEEDED).or_insert(0) |= ctx.args.z_x86_64_isa_level;
}
if ctx.args.z_shstk {
*map.entry(GNU_PROPERTY_X86_FEATURE_1_AND).or_insert(0) |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
}
*map.entry(GNU_PROPERTY_X86_ISA_1_NEEDED).or_insert(0) |= ctx.args.z_x86_64_isa_level;
// Serialize the map
let contents: Vec<(u32, u32)> = map.into_iter().filter(|&(_, v)| v != 0).collect();
+5
View File
@@ -264,6 +264,11 @@ pub const GNU_PROPERTY_X86_ISA_1_V2: u32 = 2;
pub const GNU_PROPERTY_X86_ISA_1_V3: u32 = 4;
pub const GNU_PROPERTY_X86_ISA_1_V4: u32 = 8;
pub const GNU_PROPERTY_AARCH64_FEATURE_1_AND: u32 = 0xc0000000;
pub const GNU_PROPERTY_AARCH64_FEATURE_1_BTI: u32 = 1;
pub const GNU_PROPERTY_AARCH64_FEATURE_1_PAC: u32 = 2;
pub const GNU_PROPERTY_AARCH64_FEATURE_1_GCS: u32 = 4;
pub const ELFCOMPRESS_NONE: u32 = 0;
pub const ELFCOMPRESS_ZLIB: u32 = 1;
pub const ELFCOMPRESS_ZSTD: u32 = 2;
+1 -1
View File
@@ -174,7 +174,7 @@ pub fn create_synthetic_sections<E: Target>(ctx: &mut Context<E>) {
chunks.push(ChunkId::Verneed);
chunks.push(ChunkId::NotePackage);
if E::IS_X86 {
if E::IS_X86 || E::FAMILY == Family::Arm64 {
ctx.note_property = Some(NotePropertySection::<E>::new());
chunks.push(ChunkId::NoteProperty);
}
+2 -2
View File
@@ -34,7 +34,7 @@ use std::collections::HashMap;
use mold_common::util::align_to;
use crate::arch::Target;
use crate::arch::{Family, Target};
use crate::chunks::comdat_group::ComdatGroupSection;
use crate::chunks::note_property::NotePropertySection;
use crate::chunks::output_section::{self, OutputSection};
@@ -109,7 +109,7 @@ fn create_synthetic_sections<E: Target>(ctx: &mut Context<E>) {
ChunkId::Symtab,
ChunkId::Shstrtab,
]);
if E::IS_X86 {
if E::IS_X86 || E::FAMILY == Family::Arm64 {
ctx.note_property = Some(NotePropertySection::<E>::new());
ctx.chunks.push(ChunkId::NoteProperty);
}
+33
View File
@@ -0,0 +1,33 @@
#!/usr/bin/env bash
. $(dirname $0)/common.inc
test_cflags -mbranch-protection=standard || skip
cat <<EOF | $CC -mbranch-protection=standard -c -o $t/a.o -xc -
void _start() {}
EOF
cat <<EOF | $CC -mbranch-protection=standard -c -o $t/b.o -xc -
void foo() {}
EOF
cat <<EOF | $CC -mbranch-protection=bti -c -o $t/c.o -xc -
void bar() {}
EOF
cat <<EOF | $CC -mbranch-protection=none -c -o $t/d.o -xc -
void baz() {}
EOF
./mold -o $t/exe1 $t/a.o $t/b.o
readelf -n $t/exe1 | grep 'AArch64 feature: BTI, PAC'
readelf -W --segments $t/exe1 | grep -w GNU_PROPERTY
./mold -o $t/exe2 $t/a.o $t/b.o $t/c.o
readelf -n $t/exe2 | grep 'AArch64 feature: BTI$'
./mold -o $t/exe3 $t/a.o $t/b.o $t/c.o $t/d.o
readelf -n $t/exe3 | not grep 'AArch64 feature'
./mold -r -o $t/e.o $t/a.o $t/b.o
readelf -n $t/e.o | grep 'AArch64 feature: BTI, PAC'