1

I want to create a tool that help analyzing certain code. One feature is analyzing calls that are made through a global function pointer. The first parameter is usually a constant pointer, which I want to retrieve the value of. While I could just hard-code the register this parameter is passed in, I would like to get used to the Ghidra API sufficiently to have it tell me which register it is.

So this is what I already have: I look up the global function pointer using ptr = program.getSymbols("gImportantFunctionPointer").next(), then I retrieve the signature using sig = (FunctionSignature)((Pointer)l.getDataAt(ptr.getAddress()).getDataType()).getDataType();. I do unterstand that the FunctionSignature object is processor independent and thus can't determine the register allocation. I already tried to create a FunctionPrototype object, as it has a promising constructor accepting a CompilerSpec and a FunctionSignature, which feels like exactly what you need to determine parameter storage, but if that FunctionPrototype is "backed by FunctionSignature", the method getParam(idx) just returns null.

As I am dealing with a function pointer, I am looking for ways not involving accessing any actual functions stored in the binary. While of course there is a "default implementation" I could use as reference, I'd rather learn a way that can get directly from the signature to the parameter locations without requiring to find an actual function that has the same type. It must be possible in some way, because the decompiler is able to decompile invocations of any function pointer, but I didn't yet find any convenient way (and I don't even know whether there is) in the Ghidra API.

1 Answer 1

1

There seems to be no ready-made function to solve the question, but looking at the implemenation of the function editor points out the way how to do it. I wrote this utilitiy function to get the parameter and return locations for a given function prototype:

import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.FunctionSignature;
import ghidra.program.model.listing.Program;
import ghidra.program.model.listing.VariableStorage;

class Utilities
{
    public static DataType[] getTypeList(FunctionSignature sig)
    {
        DataType[] types = new DataType[sig.getArguments().length + 1];
        types[0] = sig.getReturnType();
        for (int i = 0; i < sig.getArguments().length; i++)
            types[i + 1] = sig.getArguments()[i].getDataType();
        return types;
    }

    public static VariableStorage[] getStorageLocations(
            Program program,
            FunctionSignature sig,
            boolean include_auto)
    {
        return program.getCompilerSpec()
                      .getCallingConvention(sig.getCallingConventionName())
                      .getStorageLocations(program,
                                           getTypeList(sig),
                                           include_auto);
    }

}

The key point is the method getStorageLocations on the PrototypeModel interface. The first element of the array returned describes the return value - all other elements the parameters.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.