AArch64 LSE atomics and LDAPR do not decode
- Langage dominant
- Python
- Étoiles
- 379
- Forks
- 129
- Merge moyen
- 11 h 45 min
- PR mergées (30 j)
- 8
Description
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
VEX does not decode the ARMv8.1-A LSE atomic instructions or ARMv8.3-A `LDAPR`, so a block containing one lifts to `size=0` with `Ijk_NoDecode`.
```python
import pyvex, archinfo
a = archinfo.ArchAArch64()
for name, bs in [
("ret", bytes.fromhex("c0035fd6")),
("swpal w0,w1,[x2]", bytes.fromhex("4180e0b8")),
("ldaddal w0,w1,[x2]", bytes.fromhex("4100e0b8")),
("ldapr w0,[x1]", bytes.fromhex("20c0bfb8")),
("casal w0,w1,[x2]", bytes.fromhex("41fce088")),
]:
irsb = pyvex.lift(bs, 0x400000, a)
print(name, irsb.size, irsb.jumpkind)
```
```
ret 4 Ijk_Ret
swpal w0,w1,[x2] 0 Ijk_NoDecode
ldaddal w0,w1,[x2] 0 Ijk_NoDecode
ldapr w0,[x1] 0 Ijk_NoDecode
casal w0,w1,[x2] 0 Ijk_NoDecode
```
LSE has been baseline since ARMv8.1 and is emitted by default by current toolchains — GCC and Clang select it under `-moutline-atomics` helpers and directly under `-march=armv8.1-a` or later, and it is pervasive in Apple Silicon binaries and in distribution builds targeting v8.2+.
The consequence goes beyond the block. In `CFGFast`, a function whose terminal block ends in an undecodable instruction, is non-returning, and has fewer than four blocks is deleted by `drop_bad_functions`. So a real, symbol-named function containing one atomic can vanish from `kb.functions` entirely rather than merely being truncated. I hit this while auditing function recovery on AArch64 Mach-O: of 34 functions that disappeared despite the loader explicitly naming them, 28 went that way, and disassembly confirmed each dropped block ends exactly at an LSE or `LDAPR` instruction. Affected functions included GHC RTS entry points and ordinary C++ methods.
There is a related gap on the angr side — `drop_bad_functions` only spares addresses in `_function_addresses_from_symbols`, so a loader-supplied function hint does not protect one — which I am filing separately. But repairing that guard alone would only keep these as truncated one-block functions. Decoding the instructions is the substantive fix.
Reproduced against pyvex at `90e9094c`; the relevant decoder is libVEX's AArch64 front end, unchanged in the three commits to current master.
Guide de contribution
Aucun guide de contribution indexé pour ce dépôt
Piste de recherche
Start by running the provided pyvex/archinfo script against AArch64 bytes to reproduce size=0 and Ijk_NoDecode. The issue points to libVEX's AArch64 front end as the relevant decoder. Done means ARMv8.1-A LSE atomics and ARMv8.3-A LDAPR decode instead of producing Ijk_NoDecode, with coverage for the listed instructions.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- c, python
- Domaine
- compilers, reverse-engineering
- Type d'issue
- Bug
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Activité
- Active
- Clarté
- Clairement spécifiée
- Accessibilité débutants
- 50/100