undefined parameter types in high function signature recovery
See original GitHub issueDescribe the bug
The function fons__tt_getPixelHeightScale
in the clang executable (attached) has 2 parameters i.e. pointer and float. The signature of the function in the source code is: float fons__tt_getPixelHeightScale(FONSttFontImpl *font, float size)
Whereas ghidra recovers param1 as undefined4
and param2 as undefined8
. I am getting the parameters from the Local Symbol Map after lifting the function as High Function. Can someone explain, why is the output from ghidra not compatible with the source?
To Reproduce Steps to reproduce the behavior:
-
Run ghidra in headless mode and execute the python script below:
-
res = ifc.decompileFunction(func, 60, monitor) high_func = res.getHighFunction() if high_func != None: lsm = high_func.getLocalSymbolMap() symbols = lsm.getSymbols() for i, symbol in enumerate(symbols): if symbol.isParameter(): fw.write("paramname: {}, paramtype: {}, paramsize:{}\n".format(symbol.name,str(symbol.dataType),str(symbol.getSize())))
-
the output of the above code is as follows:
paramname: param_1, paramtype: undefined4, paramsize:4
paramname: param_2, paramtype: undefined8, paramsize:8
Expected behavior
paramname: param_1, paramtype: FONSttFontImpl *, paramsize:8
paramname: param_2, paramtype: float, paramsize:4
or at least
paramname: param_1, paramtype: undefined8 , paramsize:8
paramname: param_2, paramtype: float, paramsize:4
Is there anyway to improve the recovery from ghidra? Screenshots The executable is attached. mrpt__libmrpt-nanogui_clang_O0.zip
**Environment **
- OS: Ubuntu 18.04.6 LTS, Kernel: Linux 4.15.0-171-generic, Architecture: x86-64
- Java Version: openjdk version “11.0.14.1”
- Ghidra Version: 10.0.2
- Ghidra Origin: official ghidra-sre.org distro from https://github.com/NationalSecurityAgency/ghidra/releases
Additional context
Issue Analytics
- State:
- Created a year ago
- Comments:16 (7 by maintainers)
If I understand correctly, the concern is that Ghidra is recovering the function signature
float func(void *, float)
asfloat func(float, void *)
.While these two function signatures are distinct in C, they are not distinct under any of the major x86-64 ABIs. On both Linux (SysV) and Windows, the
void *
will be passed in a general purpose register (RDI on Linux, RCX on Windows), and thefloat
will be passed in XMM0. They are therefore indistinguishable from the perspective of the calling convention. If Ghidra does not have access to detailed function signature information (from e.g. C++ demangling or DWARF debug data), it will simply guess that there’s one float parameter and one integer parameter. There’s no way to know how those two parameters should be ordered relative to each other from the assembly code alone.The order in which the arguments are loaded in the caller, or stored in the callee, cannot be used to definitely determine parameter order. Compilers are free to load arguments in any order, and are free to store the arguments as local variables on the stack any way they like (or even not at all!). Therefore, Ghidra cannot rely on those kinds of signals to recover parameter order.
I can’t promise anything, but it’s not expected to be a large fix and we’re actively working on it.