I am implementing a backtrace function in C, which can output caller’s info. like this
ebp:0x00007b28 eip:0x00100869 args:0x00000000 0x00640000 0x00007b58 0x00100082
But how can I know the count of arguments of the caller?
Thank you very much
Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.
Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.
Lost your password? Please enter your email address. You will receive a link and will create a new password via email.
Please briefly explain why you feel this question should be reported.
Please briefly explain why you feel this answer should be reported.
Please briefly explain why you feel this user should be reported.
You can deduce the numbers of arguments a function uses in 32bit x86 code under some circumstances.
If the code has been compiled to use framepointers, then a given function’s stackframe extends between (highest address)
EBPand (lowest address / stack top)ESP. Immediately above the stack end atEBPyou find the return address, and again above that you’ll have, if your code is using the C calling convention (cdecl), consecutively,arg[0...].That means:
arg[0]at[EBP + 4],arg[1]at[EBP + 8 ], and so on.When you disassemble function, look for instructions referencing
[EBP + ...]and you know they access function arguments. The highest offset value used tells you how many there are.This is of course somewhat simplified; arguments with sizes different from 32bits, code that doesn’t use
cdeclbut e.g.fastcall, code where the framepointer has been optimized makes the method trip, at least partially.Another option, again for
cdeclfunctions, is to look at the return address (location of thecallinto the func you’re interested in), and disassemble around there; you will, in many cases, find a sequencepush argN; push ...; push arg0; call yourFuncand you can deduce how many arguments were passed in this instance. That’s in fact the only way (from the code alone) to test how many arguments were passed to functions likeprintf()in a particular instance.Again, not perfect – these days, compilers often preallocate stackspace and then use
movto write arguments instead of pushing them (on some CPUs, this is better since sequences ofpushinstructions have dependencies on each other due to each modifying the stackpointers).Since all these methods are heuristic this requires quite a bit of coding to automate. If compiler-generated debugging information is available, use that – it’s faster.
Edit: There’s another useful heuristic that can be done; Compiler-generated code for function calling often looks like this:
The
addinstruction is there to clean up stackspace used for arguments. From the size of the immediate operand, you know how much space the args this code gave tofunctionhas used, and by implication (assuming they’re all 32bit, for example), you know how many there were.This is particularly simple given you already have the address of said
addinstruction if you have working backtrace code – the instruction at the return address is thisadd. So you can often get away with simply trying to disassemble the (single) instruction at the return address, and see if it’s anadd ESP, ...(sometimes it’s asub ESP, -...) and if so, calculate the number of arguments passed from the immediate operand. The code for that is much simpler than having to pull in a full disassembly library.