gimli
gimli copied to clipboard
Support GNU extensions to CFI
http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html
DW_CFA_GNU_args_size | 0x2e | The DW_CFA_GNU_args_size instruction takes an unsigned LEB128 operand representing an argument size. This instruction specifies the total of the size of the arguments which have been pushed onto the stack. |
DW_CFA_GNU_negative_offset_extended | 0x2f | The DW_CFA_def_cfa_sf instruction takes two operands: an unsigned LEB128 value representing a register number and an unsigned LEB128 which represents the magnitude of the offset. This instruction is identical to DW_CFA_offset_extended_sf except that the operand is subtracted to produce the offset. This instructions is obsoleted by DW_CFA_offset_extended_sf. |
I think the first one is an assertion?
The second one is obsolete, but we should probably support it for backwards compatibility.
There's also DW_EH_PE_indirect
which (AFAICT) means that the resulting pointer is actually an indirect pointer to the resulting pointer. Seems safe. Might not want to support this one.
So I looked up DW_CFA_GNU_args_size
since unwind-rs ran into issues with executables using it. LLVM's libunwind (which I base most of my findings on because I find the code much cleaner than GCC's).
-
When it encounters it, it stores the result in spExtraArgSize, and then in info.gp.
-
When it needs to set the IP register, it additionally increments the SP register by that value.
I suppose we could add an sp_extra_arg_size
field to UnwindTableRow, and unwinders would be expected to reimplement the second step?
When it needs to set the IP register, it additionally increments the SP register by that value.
To clarify, this function is not used internally right? So this only affects binaries that manually adjust IP in their unwind handlers (which I don't remember encountering so far)?
this function is used by other functions, like _Unwind_SetIP (used by the rust eh_personality function), _Unwind_FindEnclosingFunction, etc...
Most binaries adjust ther IP in their unwind handler, that's the whole point of how catch works :P
Weird, now I'm confused why it worked when I just ignored DW_CFA_GNU_args_size
?
🤷♂️
BTW, do you remember which program generates a DW_CFA_GNU_args_size ? I just dwarfdump'd the unwind-rs demo, and it seems to not have any.
No, sorry.
Another useful call frame instruction that is a GNU extension is DW_CFA_GNU_window_save
- the reason is that it has an alias, DW_CFA_AARCH64_negate_ra_state
, which is necessary to support unwinding through functions that use the Pointer Authentication extension to the Arm architecture.