How to get stack args to be properly recognized by decompiler? #5782
-
I'm working on the Xtensa processor and when function arguments spill over to the stack, it seems that much of ghidra handles it properly, but something is feeding wrong info to the decompiler somehow. I'm looking for the proper magic to make everything work as it should (I'm sure I'm just missing something). First off, the Xtensa passes the first 6 arguments in a2, a3, a4, a5, a6, a7, and any subsequent arguments on the stack (a1 is the stack pointer). This function is stuffing the 7 arguments into a structure and setting the rest to 0x10. The disassembly looks like:
The entry for param_7 was not automatically discovered. I added that with the decompiler's edit function signature and hit '+' to add an additional parameter. That part of ghidra understood the spill onto the stack and added param_7 at address 0 on the stack frame (from a1 as we entered the function). The "entry" instruction at a2f94 subtracts 0x20 from the stack to build the local frame. The l32i.n at a2fa9 loads a8 from a1+0x20, which skips over the stack frame to get to the argument properly. The decompiler produces this: undefined4 * { param_1[4] = param_6; which is treating param_7 as a local variable uStack224, which has a stack offset of -0xe0. That's 0x20 - 0x100, which seems like it might be significant... In my .cspec file, after declaring a2-a7 as possible args, the stack is specified with:
Any suggestions what I should look into to try to understand why the decompiler thinks that stack arguments are local variables? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
I did discover that the PcodeOps generated for the entry instruction was poorly crafted. Instead of just subtracting a constant from the stack pointer, it was shifting the bitfield from the instruction and zero extending that, then subtracting the result. So, it seems that the stack analysis didn't fold constants together (unsurprising) and gave up trying to determine what the current stack offset was, so it couldn't determine when a stack reference was really accessing a register. |
Beta Was this translation helpful? Give feedback.
I did discover that the PcodeOps generated for the entry instruction was poorly crafted. Instead of just subtracting a constant from the stack pointer, it was shifting the bitfield from the instruction and zero extending that, then subtracting the result. So, it seems that the stack analysis didn't fold constants together (unsurprising) and gave up trying to determine what the current stack offset was, so it couldn't determine when a stack reference was really accessing a register.
I have improved my sleigh so that now the "entry" instruction produces PcodeOp to directly subtract a constant from the stack pointer and now the decompiler understands the stack argument references.