I received an answer from HexRays support which has a solution which does not rely on parsing the C string retrieved by GetType(ea)
.
Let's imagine we start with a function prototype:
int __cdecl main(int argc, const char **argv, const char **envp)
That's from an ELF file, x86 abi; stuff is passed on the stack.
Then, I can do the following:
Python>from idaapi import *
Python>tif = tinfo_t()
Python>get_tinfo2(here(), tif)
True
Python>funcdata = func_type_data_t()
Python>tif.get_func_details(funcdata)
True
Python>funcdata.size()
3
Python>for i in xrange(funcdata.size()):
Python> print "Arg %d: %s (of type %s, and of location: %s)" % (i, funcdata[i].name, print_tinfo('', 0, 0, PRTYPE_1LINE, funcdata[i].type, '', ''), funcdata[i].argloc.atype())
Python>
Arg 0: argc (of type int, and of location: 1)
Arg 1: argv (of type const char **, and of location: 1)
Arg 2: envp (of type const char **, and of location: 1)
Note that it tells me the location type is 1
, which corresponds
to 'stack':
https://www.hex-rays.com/products/ida/support/sdkdoc/group___a_l_o_c__.html
Now, let's assume I change the prototype to this:
.text:0804ABA1 ; int __usercall main@<eip>(int argc@<eax>, const char **argv@<esp>, const char **envp@<edx>)
Then:
Python>get_tinfo2(here(), tif)
True
Python>tif.get_func_details(funcdata)
True
Python>for i in xrange(funcdata.size()):
Python> print "Arg %d: %s (of type %s, and of location: %s)" % (i, funcdata[i].name, print_tinfo('', 0, 0, PRTYPE_1LINE, funcdata[i].type, '', ''), funcdata[i].argloc.atype())
Python>
Arg 0: argc (of type int, and of location: 3)
Arg 1: argv (of type const char **, and of location: 3)
Arg 2: envp (of type const char **, and of location: 3)
Argument location type is 3
now, which corresponds to 'inside
register'.
(Then, I would have to use reg1()
to retrieve the actual
register number to know what register the argument is
passed in)
Credit goes to Arnaud of Hex Rays.