macho: AArch64 uses local temporary symbols for sections

This commit is contained in:
Philip Craig
2026-03-10 16:55:56 +10:00
parent 9e3d5b1e88
commit 3abdbbd97a
6 changed files with 44 additions and 25 deletions
@@ -18,10 +18,10 @@ Segment { name: "", address: 0, size: 2ca, permissions: RWX }
11: Section { segment: "__DWARF", name: "__debug_line", address: 288, size: 42, align: 1, kind: Debug, flags: MachO { flags: 2000000 } }
Symbols
0: Symbol { name: "ltmp0", address: 0, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } }
0: Symbol { name: "ltmp0", address: 0, size: 0, kind: Section, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } }
1: Symbol { name: "l_.str", address: 34, size: 0, kind: Data, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } }
2: Symbol { name: "ltmp1", address: 34, size: 0, kind: Data, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } }
3: Symbol { name: "ltmp2", address: 268, size: 0, kind: Unknown, section: Section(SectionIndex(a)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } }
2: Symbol { name: "ltmp1", address: 34, size: 0, kind: Section, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } }
3: Symbol { name: "ltmp2", address: 268, size: 0, kind: Section, section: Section(SectionIndex(a)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } }
4: Symbol { name: "_main", address: 0, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Dynamic, weak: false, flags: MachO { n_desc: 0 } }
5: Symbol { name: "_printf", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: MachO { n_desc: 0 } }
@@ -48,5 +48,4 @@ Export { name: "_main", address: 0 }
Symbol map
0x0 "_main"
0x34 "ltmp1"
0x268 "ltmp2"
0x34 "l_.str"
@@ -10,10 +10,10 @@ Segment { name: "", address: 0, size: 68, permissions: RWX }
3: Section { segment: "__LD", name: "__compact_unwind", address: 48, size: 20, align: 8, kind: Unknown, flags: MachO { flags: 2000000 } }
Symbols
0: Symbol { name: "ltmp0", address: 0, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } }
0: Symbol { name: "ltmp0", address: 0, size: 0, kind: Section, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } }
1: Symbol { name: "l_.str", address: 34, size: 0, kind: Data, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } }
2: Symbol { name: "ltmp1", address: 34, size: 0, kind: Data, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } }
3: Symbol { name: "ltmp2", address: 48, size: 0, kind: Unknown, section: Section(SectionIndex(3)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } }
2: Symbol { name: "ltmp1", address: 34, size: 0, kind: Section, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } }
3: Symbol { name: "ltmp2", address: 48, size: 0, kind: Section, section: Section(SectionIndex(3)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } }
4: Symbol { name: "_main", address: 0, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Dynamic, weak: false, flags: MachO { n_desc: 0 } }
5: Symbol { name: "_printf", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: MachO { n_desc: 0 } }
@@ -33,5 +33,4 @@ Export { name: "_main", address: 0 }
Symbol map
0x0 "_main"
0x34 "ltmp1"
0x48 "ltmp2"
0x34 "l_.str"
@@ -9,8 +9,8 @@ Segment { name: "", address: 0, size: 48, permissions: RWX }
2: Section { segment: "__DATA", name: "__data", address: 28, size: 20, align: 1, kind: Data, flags: MachO { flags: 0 } }
Symbols
0: Symbol { name: "ltmp0", address: 0, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } }
1: Symbol { name: "ltmp1", address: 28, size: 0, kind: Data, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } }
0: Symbol { name: "ltmp0", address: 0, size: 0, kind: Section, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } }
1: Symbol { name: "ltmp1", address: 28, size: 0, kind: Section, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } }
2: Symbol { name: "_data", address: 28, size: 0, kind: Data, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } }
3: Symbol { name: "_g0", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: MachO { n_desc: 0 } }
4: Symbol { name: "_g1", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: MachO { n_desc: 0 } }
@@ -42,5 +42,4 @@ Import { library: "", name: "_g0" }
Import { library: "", name: "_g1" }
Symbol map
0x0 "ltmp0"
0x28 "_data"
+24 -11
View File
@@ -12,7 +12,7 @@ use crate::read::{
SymbolMapEntry, SymbolScope, SymbolSection,
};
use super::{MachHeader, MachOFile};
use super::{MachHeader, MachOFile, Section};
/// A table of symbol entries in a Mach-O file.
///
@@ -370,17 +370,30 @@ where
self.section()
.index()
.and_then(|index| self.file.section_internal(index).ok())
.map(|section| match section.kind {
SectionKind::Text => SymbolKind::Text,
SectionKind::Data
| SectionKind::ReadOnlyData
| SectionKind::ReadOnlyString
| SectionKind::UninitializedData
| SectionKind::Common => SymbolKind::Data,
SectionKind::Tls | SectionKind::UninitializedTls | SectionKind::TlsVariables => {
SymbolKind::Tls
.map(|section| {
if let Ok(name) = self.name_bytes() {
// Heuristic to match LLVM's convention for section symbols; may misclassify.
if self.is_local()
&& name.len() > 4
&& name.starts_with(b"ltmp")
&& name[4..].iter().all(|b| b.is_ascii_digit())
&& self.address() == section.section.addr(self.file.endian).into()
{
return SymbolKind::Section;
}
}
match section.kind {
SectionKind::Text => SymbolKind::Text,
SectionKind::Data
| SectionKind::ReadOnlyData
| SectionKind::ReadOnlyString
| SectionKind::UninitializedData
| SectionKind::Common => SymbolKind::Data,
SectionKind::Tls
| SectionKind::UninitializedTls
| SectionKind::TlsVariables => SymbolKind::Tls,
_ => SymbolKind::Unknown,
}
_ => SymbolKind::Unknown,
})
.unwrap_or(SymbolKind::Unknown)
}
+7 -1
View File
@@ -483,7 +483,13 @@ impl<'a> Object<'a> {
// Since we don't actually emit the symbol kind, we validate it here too.
match symbol.kind {
SymbolKind::Text | SymbolKind::Data | SymbolKind::Tls | SymbolKind::Unknown => {}
SymbolKind::File | SymbolKind::Section => continue,
SymbolKind::Section => {
// AArch64 needs temporary section symbols for relative relocations.
if self.architecture != Architecture::Aarch64 {
continue;
}
}
SymbolKind::File => continue,
SymbolKind::Label => {
return Err(Error(format!(
"unimplemented symbol `{}` kind {:?}",
+3
View File
@@ -572,6 +572,9 @@ impl<'a> Object<'a> {
}
let name = if self.format == BinaryFormat::Coff {
section.name.clone()
} else if self.format == BinaryFormat::MachO {
// Use LLVM's convention for section symbols.
format!("ltmp{}", section_id.0).into_bytes()
} else {
Vec::new()
};