[llvm-profgen] Enable all AArch64 instructions for disassembly (#204619)

llvm-profgen builds its MCSubtargetInfo from
`ObjectFile::getFeatures()`. For AArch64 ELF objects this often produces
an empty feature set, so the disassembler falls back to the baseline
Armv8.0-A ISA and rejects valid feature-gated instructions such as LSE
atomics and RCPC loads.

`llvm-objdump` already handles this by [adding +all for AArch64
disassembly](https://github.com/llvm/llvm-project/blob/1e2d1bbc12f6a5f5931c77d39894ee1b8679f5f8/llvm/tools/llvm-objdump/llvm-objdump.cpp#L2823-L2824)
when neither -mattr nor -mcpu is specified. Match that behavior in
`llvm-profgen` so valid AArch64 instructions are not reported as invalid
and their addresses are preserved in profgen's code and branch maps.

Add a regression test covering an AArch64 binary containing `ldaddal`
and `ldapr` without object-level feature metadata.

---------

Co-authored-by: Kunal Pathak <kupathak@fb.com>
This commit is contained in:
Kunal PathakandKunal Pathak authored and GitHub committed 2026-06-22 11:39:28 -07:00
1 parent 04baf7ed88
commit 738fecbc68
2 files changed
+56

No files matched your search

@@ -0,0 +1,46 @@
# REQUIRES: aarch64-registered-target
# RUN: yaml2obj %s -o %t.exe
# RUN: llvm-profgen --binary=%t.exe --output=/dev/null --show-disassembly-only 2>&1 \
# RUN: | FileCheck %s
# CHECK-NOT: invalid instructions
# CHECK: Disassembly of section .text
# CHECK-NOT: <unknown>
# CHECK: <foo>:
# CHECK-NEXT: {{[0-9a-f]+}}: ldaddal w0, w1, [x2]
# CHECK-NEXT: {{[0-9a-f]+}}: ldapr x3, [x4]
# CHECK-NEXT: {{[0-9a-f]+}}: ret
# CHECK-NOT: <unknown>
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_AARCH64
Entry: 0x0000000000401000
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
Address: 0x0000000000401000
AddressAlign: 0x4
## ldaddal w0, w1, [x2]
## ldapr x3, [x4]
## ret
Content: 4100E0B883C0BFF8C0035FD6
ProgramHeaders:
- Type: PT_LOAD
Flags: [ PF_X, PF_R ]
VAddr: 0x0000000000400000
Align: 0x1000
FirstSec: .text
LastSec: .text
Symbols:
- Name: foo
Type: STT_FUNC
Section: .text
Binding: STB_GLOBAL
Value: 0x0000000000401000
Size: 0x000000000000000C
@@ -745,6 +745,16 @@ void ProfiledBinary::setUpDisassembler(const ObjectFile *Obj) {
Expected<SubtargetFeatures> Features = Obj->getFeatures();
if (!Features)
exitWithError(Features.takeError(), FileName);
// AArch64 object files do not generally carry complete ISA feature metadata,
// so the subtarget would default to the baseline (Armv8.0-A) feature set.
// That disassembler cannot decode feature-gated instructions (LSE atomics,
// RCPC loads, SVE, ...) that are pervasive in modern AArch64 binaries; they
// would be miscounted as "invalid instructions" and, worse, their addresses
// would be absent from the code/branch maps used for sample attribution.
// Enable all instructions so the disassembler recognizes whatever the
// compiler emitted, matching llvm-objdump's default for AArch64.
if (TheTriple.isAArch64())
Features->AddFeature("+all");
STI.reset(
TheTarget->createMCSubtargetInfo(TheTriple, "", Features->getString()));
if (!STI)