Skip to content

reversenolog segfaults on ARM exclusive load/store instructions (STREX/LDREX family) #3

Description

@mathewduong

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions