Function "Bob" calls function "Janice". Currently, I'm at an address in function "Janice" and can easily do idc.GetFunctionName(ea) to get the name Janice. However, I also want to get the caller function Bob's name. How would I go about doing this efficiently considering I'm currently within function Janice? Thanks.
Generally speaking this question as it asked is a bit ambiguous. The answer can be divided by 2 general parts, getting a caller in the debug session and determining the potential caller list during static analysis.
Getting a potential caller list during static analysis
As @blabb wrote in most cases it is possible and can be done with IDA scripting capabilities.
Here is IDAPython example which will print all references to the callee (which is equivalent to press x on the callee name in IDA) assuming that your cursor is within the "Janice" function:
import idautils import idc print "Code references" for ref in idautils.CodeRefsTo(idc.GetFunctionAttr(idc.ScreenEA(), idc.FUNCATTR_START), 1): print ref print "Data references" for ref in idautils.DataRefsTo(idc.GetFunctionAttr(idc.ScreenEA(), idc.FUNCATTR_START)): print ref
Of course demangling should be applied to get a more human-readable name as @blabb wrote if needed.
It should be taken in account that this script (exactly as the pressing x on the callee) does not solve the indirect call issue, but shows all references to the function which may help to trace the indirect call.
Getting a specific caller during a debug session
This is a bit trickier and much more architecture dependent (for example in ARM you have LR register with return address which will help you in most cases if you stopped at the start of "Janice" function and it is not contaminated yet), you'll need to
- Stop in the "Janice" function on the breakpoint
- Determine the placement of return address
- Conclude the specific caller from it
The script which will do it is a bit more complex and unfortunately I have no time to debug it for now, so I'll just list the IDAPython APIs which will probably help you to solve the problem:
idaapi.get_func(ea) # get the function object of func_t type idaapi.get_frame(pfn) #gets the function frame structure of struc_t type idaapi.frame_off_retaddr(pfn) # AFAIK gets the offset of return address of the structure
janice could have been called by bob or it could be a mob of other zillion prospective callers
you have to check each xrefto a sample showing the first xrefto below note you may need to demangle in some cases
auto ip,fname,fxref,fxrefname,fxrefdname; ip = ScreenEA(); fname = GetFunctionName(ip); fxref = RfirstB0(ip); fxrefname = GetFunctionName(fxref); Message("ScreenEa is in function %s and it is called first by %s\n" , fname , fxrefname); fxrefdname = Demangle(fxrefname,GetLongPrm(INF_LONG_DN)); Message("ScreenEa is in function %s and it is called first by %s\n" , fname , fxrefdname);
result as screenshot (see the actual code xref and the message window)