10

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']]
14

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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