Open toshipiazza opened 3 years ago
Another curious thing is that, when I open bn_llil_test_app for the first time in binja, test_allocframe() infers FP as the first argument (I changed that to void in the snippets above). Specifically, binja infers
int32_t test_allocframe(int32_t arg1 @ FP)
This happens even when I add FP to GetCalleeSavedRegisters
in arch_hexagon.cc
I'm pretty sure the issue lies with Binja's analysis. Either it expects callee-saved regs and LR/FP to be manipulated with LLIL push and pops, or it cannot handle LLIL_SPLIT_REG and LLIL_SET_SPLIT_REG.
To be sure, I modified lift_L4_return() and lift_S2_allocframe() to use straightforward push and pop's, and produced the following IL's:
LLIL:
0 @ 00000020 push(LR)
1 @ 00000020 push(FP)
2 @ 00000020 FP = SP {__saved_FP}
3 @ 00000020 SP = SP - 8
4 @ 00000024 temp0.d = 0x100
5 @ 00000024 R0 = temp0.d
6 @ 00000028 SP = FP
7 @ 00000028 FP = pop
8 @ 00000028 LR = pop
9 @ 00000028 <return> jump(LR)
HLIL:
00000028 return 0x100
FP is no longer inferred as an implicit argument to the function, as well.
Yeah, I also encountered optimization problems with LLIL_SPLIT_REG
.
TempReg::CopyFromTemp
in plugin/packet_context.cc
also uses split registers, so I experimented a bit, and changed the split reg computation to two SetRegister
s with a logical shift:
void TempReg::CopyFromTemp(BinaryNinja::LowLevelILFunction &il) {
ExprId expr;
if (size_ == 1) {
expr = il.SetRegister(1, reg_, il.Register(1, LLIL_TEMP(reg_)));
il.AddInstruction(expr);
} else if (size_ == 4) {
expr = il.SetRegister(4, reg_, il.Register(4, LLIL_TEMP(reg_)));
il.AddInstruction(expr);
} else {
CHECK_EQ(size_, 8);
il.AddInstruction(il.SetRegister(
4, reg_, il.LowPart(4, il.Register(8, LLIL_TEMP(reg_)))));
il.AddInstruction(il.SetRegister(
4, reg_ + 1,
il.LowPart(4, il.LogicalShiftRight(8, il.Register(8, LLIL_TEMP(reg_)),
il.Const(1, 32)))));
}
}
However, I wasn't too happy with the results, so I didn't push the change.
The autogenerated LLIL for e.g. allocframe() and dealloc_return() manipulate LLIL_SPLIT_REG(LR, FP), and those refs don't seem to be elided in HLIL.
Example code (test_allocframe() in bn_llil_test_app):
LLIL:
Resulting HLIL:
I'd expect output more like
Looking at a different x86 binary, it seems that RBP and all callee-saved registers are eliminated somewhere between LLIL and MLIL.