tags:

views:

122

answers:

3

I have the following question and from a systems perspective want to know how to achieve this easily and efficiently.

Given a task 'abc' that has been built with debug information and a global variable "TRACE" that is normally set to 0, I would like to print out to file 'log' the address of each function that is called between the time that TRACE is set to 1 and back again to 0.

I was considering doing this through a front-loading / boot-strapping task that I'd develop which looks at the instructions for a common pattern of jump/frame pointer push, writing down the address and then mapping addresses to function names from the symbolic debug information in abc. There could be better system level ways to do this without a front-loader though, and I'm not sure what is most feasible.

Any implemented techniques out there?

+1  A: 

Make sure you've looked into the __func__ or __FUNCTION__ predefined identifiers. They provide a string literal of the function/method name you are currently executing.

Brent Arias
+3  A: 

One possibility is to preprocess the source before compiling it. This preprocessing would add code at the beginning of each function that would check the TRACE global and, if set, write to the log. As Mystagogue said, the compiler has preprocessor macros that expand to the name of the function.

You might also look at some profiling tools. Some of them have functionality close to what you're asking for. For example, some will sample the entire callstack periodically, which can tell you a lot about the code flow without actually logging every call.

Adrian McCarthy
Preprocessing sources might be one of the cheapest ways to do it.
Dummy00001
We need to log every call. I could use dtrace to get high-frequency periodic stacks, but this is not going to do the trick. Preprocessing sources might, but our binaries are already reaching the 32-bit 4 gig limit. Thanks
Aesis Sui'Generis
+2  A: 

Looking for a common prologue/epilogue won't work in the presence of frame-pointer omission and tail call optimization. Also, modern optimizers like to split functions into several chunks and merge common tail chunks of different functions.

There is no standard solution.

For Microsoft compiler, check out _penter and _pexit hooks. For GCC, look at -finstrument-functions option and friends.

Also, on x86 Windows you can use a monitor such as WinApiOverride32. It's primarily intended for monitoring DLL and system API calls, but you can generate a description file from your application's map file and monitor internal functions as well.

(Edited: added link to GCC option.)

atzz
I agree - thanks for the feedback. Debugger 'dbx' seems to be able to do this, though, so I don't think there is tail call optimization - or how could dbx figure it out?If the debugger can do it, we should be able to. Problem is it's obviously not practical to have this loaded in dbx in a production environment, so the idea was to do the minimum work needed in a similar front-loading task which can say when the binaries are calling out to functions. Even at worst case scenario I could record all jumps, which would also show (albeit noisy) intra-function flow.
Aesis Sui'Generis
I am hopeful for the -finstrument-functions :) will investigate further.. much thanks
Aesis Sui'Generis