librz/bin/elf: improve ARM Thumb symbols detection (#6502)

Co-authored-by: Anton Kochkov <anton.kochkov@gmail.com>
This commit is contained in:
NOT XVilka 2026-06-14 17:25:00 +08:00 committed by GitHub
parent 3aebd94478
commit 323e707114
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 45 additions and 11 deletions

View file

@ -98,22 +98,20 @@ static Elf_(Word) get_number_of_symbols_from_section(ELFOBJ *bin) {
}
static bool is_special_arm_symbol(ELFOBJ *bin, Elf_(Sym) * sym, const char *name) {
if (!name) {
// ARM/AArch64 mapping symbols are named "$<char>" optionally followed by
// ".<suffix>" (e.g. "$t", "$d.realdata"). The ABI specifies STT_NOTYPE, but
// some toolchains emit them as STT_FUNC/STT_OBJECT (e.g. Motorola P2K
// firmware), so only the name shape and local binding are checked, like
// binutils' bfd_is_arm_special_symbol_name() with BFD_ARM_SPECIAL_SYM_TYPE_ANY.
if (!name || name[0] != '$' || !name[1]) {
return false;
}
if (name[0] != '$') {
if (name[2] != '\0' && name[2] != '.') {
return false;
}
if (name[1] == 'a' || name[1] == 't' || name[1] == 'd' || name[1] == 'x') {
return (name[2] == '\0' || name[2] == '.') &&
ELF_ST_TYPE(sym->st_info) == STT_NOTYPE &&
ELF_ST_BIND(sym->st_info) == STB_LOCAL &&
ELF_ST_VISIBILITY(sym->st_info) == STV_DEFAULT;
}
return false;
return ELF_ST_BIND(sym->st_info) == STB_LOCAL;
}
static bool is_special_symbol(ELFOBJ *bin, Elf_(Sym) * sym, const char *name) {

View file

@ -1469,6 +1469,18 @@ static void select_flag_space(RzCore *core, RzBinSymbol *symbol) {
}
}
// True if the binary carries ARM/AArch64 mapping symbols ($a/$t/$d/$x).
static bool has_arm_mapping_symbols(RzPVector /*<RzBinSymbol *>*/ *symbols) {
void **it;
rz_pvector_foreach (symbols, it) {
RzBinSymbol *symbol = *it;
if (symbol->name && is_special_symbol(symbol)) {
return true;
}
}
return false;
}
RZ_API bool rz_core_bin_apply_symbols(RzCore *core, RzBinFile *binfile, bool va) {
rz_return_val_if_fail(core && binfile, false);
RzBinObject *o = binfile->o;
@ -1488,6 +1500,13 @@ RZ_API bool rz_core_bin_apply_symbols(RzCore *core, RzBinFile *binfile, bool va)
void **iter;
void **it;
RzBinSymbol *symbol;
// Mapping symbols authoritatively describe the instruction set of each code
// region, so when present the address-parity heuristic in handle_arm_symbol()
// must be disabled: such binaries place Thumb functions at even addresses,
// where the heuristic would wrongly force ARM mode (see issue #4357).
bool arm_mapping_symbols = is_arm && has_arm_mapping_symbols(symbols);
rz_pvector_foreach (symbols, it) {
symbol = *it;
if (!symbol->name) {
@ -1512,7 +1531,8 @@ RZ_API bool rz_core_bin_apply_symbols(RzCore *core, RzBinFile *binfile, bool va)
// applied to FUNC symbols by handle_arm_symbol().
} else {
// TODO: provide separate API in RzBinPlugin to let plugins handle analysis hints/metadata
if (is_arm) {
// Address-parity heuristic only when no mapping symbols (see above).
if (is_arm && !arm_mapping_symbols) {
handle_arm_symbol(core, o, symbol, va);
}
select_flag_space(core, symbol);

View file

@ -119,3 +119,19 @@ str r1, [r7]
ldr r3, [r7, 4]
EOF
RUN
NAME=ELF: big-endian ARM, mapping symbols typed STT_FUNC/STT_OBJECT
FILE=bins/elf/analysis/2048-P2K-AHI_EP1.elf
CMDS=<<EOF
s 0x81f0
pi 6
EOF
EXPECT=<<EOF
movs r1, 0
lsls r2, r1, 2
ldr r3, [r0, r2]
ldr r2, [r5, r2]
cmp r3, r2
beq 0x8200
EOF
RUN