Hi,
I am currently having an issue with FirmRCA'S root-cause analysis engine (reversenolog). It crashes with a segmentation fault whenever the reverse-execution trace it is walking contains an ARM exclusive load/store instruction (STREX). I have reproduced this specifically in zephyr binaries.
From my inspection it seems to stem from the fact that strex_resolver/ldrex_resolver (and their B/D/H variants, plus the matching _post_res and _vs_handler functions) are unfinished stubs in src/src/handler_arm.c. They're wired into the instruction dispatch tables (src/src/re_insttable_arm.c) and are reachable (disassemble.c explicitly classifies STREX*/LDREX* as instructions to analyze) but the handler bodies just log a TODO and do nothing:
// src/src/handler_arm.c
void strex_resolver(re_list_t* inst, re_list_t* re_deflist, re_list_t* re_uselist){
LOG(stdout, "Please fill strex_resolver\n"); // line 2643 — never implemented
}
void ldrex_resolver(re_list_t* inst, re_list_t* re_deflist, re_list_t* re_uselist){
LOG(stdout, "Please fill ldrex_resolver \n"); // line 1168 — never implemented
}
The same TODO-only pattern repeats for all 8 variants:
| Instruction |
*_resolver |
*_post_res |
*_vs_handler |
| STREX |
handler_arm.c:2642 |
handler_arm.c:5507 |
handler_arm.c:9164 |
| STREXB |
handler_arm.c:2646 |
handler_arm.c:5511 |
handler_arm.c:9170 |
| STREXD |
handler_arm.c:2650 |
handler_arm.c:5515 |
handler_arm.c:9176 |
| STREXH |
handler_arm.c:2654 |
handler_arm.c:5519 |
handler_arm.c:9182 |
| LDREX |
handler_arm.c:1167 |
handler_arm.c:4187 |
handler_arm.c:7160 |
| LDREXB |
handler_arm.c:1171 |
handler_arm.c:4191 |
handler_arm.c:7166 |
| LDREXD |
handler_arm.c:1175 |
handler_arm.c:4195 |
handler_arm.c:7172 |
| LDREXH |
handler_arm.c:1179 |
handler_arm.c:4199 |
handler_arm.c:7178 |
With no real resolver, these instructions fall through to the generic operand-handling path, which assumes every ARM_OP_MEM/ARM_OP_REG destination operand consumes a slot in the recorded memory-access trace. For STREX Rd, Rt, [Rn] (store Rt to [Rn], then write a success/fail flag into Rd), that means the generic handler expects 2 access-trace entries (one for the status-flag register write and one for the actual memory store) but the trace only ever contains 1 real memory access, since the register write is not a memory access at all and correctly never gets recorded.
I believe as a result an integer underflow occurs in src/src/re_dsmanager.c:1192 which then follows a segmentation fault.
Hi,
I am currently having an issue with FirmRCA'S root-cause analysis engine (
reversenolog). It crashes with a segmentation fault whenever the reverse-execution trace it is walking contains an ARM exclusive load/store instruction (STREX). I have reproduced this specifically in zephyr binaries.From my inspection it seems to stem from the fact that
strex_resolver/ldrex_resolver(and theirB/D/Hvariants, plus the matching_post_resand_vs_handlerfunctions) are unfinished stubs insrc/src/handler_arm.c. They're wired into the instruction dispatch tables (src/src/re_insttable_arm.c) and are reachable (disassemble.cexplicitly classifiesSTREX*/LDREX*as instructions to analyze) but the handler bodies just log a TODO and do nothing:The same TODO-only pattern repeats for all 8 variants:
With no real resolver, these instructions fall through to the generic operand-handling path, which assumes every
ARM_OP_MEM/ARM_OP_REGdestination operand consumes a slot in the recorded memory-access trace. ForSTREX Rd, Rt, [Rn](storeRtto[Rn], then write a success/fail flag intoRd), that means the generic handler expects 2 access-trace entries (one for the status-flag register write and one for the actual memory store) but the trace only ever contains 1 real memory access, since the register write is not a memory access at all and correctly never gets recorded.I believe as a result an integer underflow occurs in
src/src/re_dsmanager.c:1192which then follows a segmentation fault.