GP-6966: post-review
GP-6966: in review
GP-6966: not all tests pass, but...
GP-6966: better messaging
GP-6966: mods for x64dbg
GP-6966: docs (GP-6972)
GP-6966: fixes for linux->windows
GP-6966: fix for exit; fix for WINDBG_DIR
In ARM Thumb, function pointers are used with an offset. For example,
let's consider this C program:
static void fn(void) {}
__attribute__((noinline, optimize("O0")))
static void call_function(void (*callback)(void)) {
callback();
}
void call_fn_through_reference(void) {
call_function(fn);
}
Function call_fn_through_reference actually gives the address fn + 1 in
the first parameter of call_function, when this code is compiled in ARM
Thumb mode. In such a situation, Ghidra's decompiler produced:
void call_fn_through_reference(void)
{
call_function((void *)0x10189);
return;
}
The rules which were applied included both:
- rule constantptr, which converted the constant 0x10189 to
(#0x0 -> #0x10188) + #0x1 (opcodes PTRSUB and INT_ADD) ;
- rule ptrsubundo, which converted this expression to
(#0x0 + #0x10188) + #0x1 (later simplified to #0x10189).
The second rule cancelled the first one. In this case, rule ptrsubundo
should not be applied as the expression involving PTRSUB targets a valid
location.
Nevertheless, TypePointer::isPtrsubMatching(off=0x10188, extra=1, multiplier=0)
returned false. This is due to the fact that even though the size of
symbol fn was adjusted to be 2 (in method DecompileCallback::encodeFunction in
Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileCallback.java
), the actual type is "pointer to a TypeCode which size is 1", so
extra >= subType->getSize() and the method returned false.
Fix TypePointer::isPtrsubMatching to return true when a pointer to some
code is encountered with extra >= 0. This makes Ghidra's decompiler now
produce:
void call_fn_through_reference(void)
{
call_function(fn + 1);
return;
}
Fixes: https://github.com/NationalSecurityAgency/ghidra/issues/8471
Fixes: 34adcff830 ("GP-4782 Refactor RulePtrsubUndo")