Description
Lifting a whole statically-linked firmware image to CIR aborts inside vendored ClangIR with:
Diag Error: ClangIR code gen Not Yet Implemented: emitDeclRefLValue: static local
Assertion failed: (isValid()), function getPointer, file Address.h, line 91.
The message is a misnomer: in this ClangIR (clang/lib/CIR/CodeGen/CIRGenExpr.cpp, emitDeclRefLValue) the errorNYI("emitDeclRefLValue: static local") branch is taken for any local variable / parameter DeclRefExpr that is missing from the function's localDeclMap — not only genuine static locals. The errorNYI then returns an invalid Address, and the immediate getPointer() use aborts at Address.h:91.
Key observations:
- It only reproduces in the whole-program lift. The function implicated in the failure lifts cleanly when decompiled on its own (and together with its direct callers), so it is not a defect in that function's own lifting.
- The emitted C (
-print-tu) for the implicated function shows no genuine function-scope static locals and no duplicate-arity declarations.
- The result is non-deterministic between runs (see the existing
unordered_set iteration-order non-determinism in decomp), so the specific function/variable can vary.
This is independent of CIR emission order: the name-ordered emission added in #276 does not prevent it.
How to reproduce
Using the in-tree statically-linked firmware firmwares/output/ventilator/controller-firmware.elf:
# 1. Serialize the whole program to P-Code JSON
bash scripts/ghidra/decompile-headless.sh \
--input firmwares/output/ventilator/controller-firmware.elf \
--output /tmp/controller-firmware.json
# 2. Lift the whole program to CIR -> aborts
patchir-decomp -input /tmp/controller-firmware.json -emit-cir -output /tmp/controller
# Diag Error: ... Not Yet Implemented: emitDeclRefLValue: static local
# Assertion failed: (isValid()), function getPointer, file Address.h, line 91.
Contrast — the same function lifts cleanly in isolation (no abort):
bash scripts/ghidra/decompile-headless.sh \
--input firmwares/output/ventilator/controller-firmware.elf \
--function strncmp --output /tmp/strncmp.json
patchir-decomp -input /tmp/strncmp.json -emit-cir -output /tmp/strncmp # OK
Description
Lifting a whole statically-linked firmware image to CIR aborts inside vendored ClangIR with:
The message is a misnomer: in this ClangIR (
clang/lib/CIR/CodeGen/CIRGenExpr.cpp,emitDeclRefLValue) theerrorNYI("emitDeclRefLValue: static local")branch is taken for any local variable / parameterDeclRefExprthat is missing from the function'slocalDeclMap— not only genuinestaticlocals. TheerrorNYIthen returns an invalidAddress, and the immediategetPointer()use aborts atAddress.h:91.Key observations:
-print-tu) for the implicated function shows no genuine function-scopestaticlocals and no duplicate-arity declarations.unordered_setiteration-order non-determinism in decomp), so the specific function/variable can vary.This is independent of CIR emission order: the name-ordered emission added in #276 does not prevent it.
How to reproduce
Using the in-tree statically-linked firmware
firmwares/output/ventilator/controller-firmware.elf:Contrast — the same function lifts cleanly in isolation (no abort):
bash scripts/ghidra/decompile-headless.sh \ --input firmwares/output/ventilator/controller-firmware.elf \ --function strncmp --output /tmp/strncmp.json patchir-decomp -input /tmp/strncmp.json -emit-cir -output /tmp/strncmp # OK