Let's say I have the following function in IDA:int __usercall function<eax>(char* message<ebp>, unsigned int count<edi>)What's the fastest way to extract the argument information using IDAPython, such that I get the following:[['char*', 'message', 'ebp'],['unsigned int','count','edi']]Not that it also needs to handle situations like:void *__usercall sub_4508B0@<rax>(void *(__usercall *function)@<rax>(int one@<eax>)@<rax>);Which should give me something along the lines of:[['void * ...', 'function', 'rax']]
Extracting arguments from IDA
ida;disassembly;idapython;python
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)TruePython>funcdata = func_type_data_t()Python>tif.get_func_details(funcdata)TruePython>funcdata.size()3Python>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 correspondsto 'stack':https://www.hex-rays.com/products/ida/support/sdkdoc/group___a_l_o_c__.htmlNow, 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)TruePython>tif.get_func_details(funcdata)TruePython>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 'insideregister'.(Then, I would have to use reg1() to retrieve the actualregister number to know what register the argument ispassed in)Credit goes to Arnaud of Hex Rays.