I somewhat recently stumbled upon a somewhat annoying pattern while traversing a RISCV-32 program. It looked just a little like this in the Listing:
**************************************************************
* FUNCTION *
**************************************************************
undefined example_fn()
undefined <UNASSIGNED> <RETURN>
example
ef b2 86 fb jal t0,prologue_stub_t0 void prologue_stub_t0(void)
<...SNIP...>
6f b0 86 f9 j epilogue_stub_ret void epilogue_stub_ret(void)
And like this in the Decompiler:
void example_fn(undefined1 *param_1,int param_2)
{
int iVar1;
undefined4 uVar1;
undefined4 uVar2;
iVar1 = prologue_stub_t0();
uVar1 = 0x12;
if (iVar1 == extraout_a1){
uVar1 = 0x17;
}
uVar2 = epilogue_stub_ret(uVar1);
return uVar2;
}
So where were these jalr,
and j
instructions going? To outlined callee-saved register preservation and restoration: