views:

348

answers:

5

I have a 3rd party source code that I have to investigate. I want to see in what order the functions are called but I don't want to waste my time typing:

printf("Entered into %s", __FUNCTION__)

and

printf("Exited from %s", __FUNCTION__)

for each function, nor do I want to touch any source file.

Do you have any suggestions? Is there a compiler flag that automagically does this for me?

Clarifications to the comments:

  • I will cross-compile the source to run it on ARM.
  • I will compile it with gcc.
  • I don't want to analyze the static code. I want to trace the runtime. So doxygen will not make my life easier.
  • I have the source and I can compile it.
  • I don't want to use Aspect Oriented Programming.

EDIT: I found that 'frame' command in the gdb prompt prints the current frame (or, function name, you could say) at that point in time. Perhaps, it is possible (using gdb scripts) to call 'frame' command everytime a function is called. What do you think?

+1  A: 

If you're using gcc, the magic compiler flag is -g. Compile with debugging symbols, run the program under gdb, and generate stack traces. You could also use ptrace, but it's probably a lot easier to just use gdb.

William Pursell
As fas as I know, stack trace is the state of the function call stack at a specific moment. Can I output the function names of the called functions in sequence into a file using the stack trace option in gdb?
bmm
+2  A: 

Agree with William, use gdb to see the run time flow.
There are some static code analyzer which can tell which functions call which and can give you some call flow graph. One tool is "Understand C++" (support C/C++) but thats not free i guess. But you can find similar tools.

Adil
sparse, "semantic parser", has a graphing utility. It generates a graphviz file which can be converted to a graphic. http://sparse.wiki.kernel.org/index.php/Main_Page
Tim Schaeffer
What is the exact option flag for gdb, that will enable it to print each function that is being called at that moment?
bmm
A: 

Use /Gh (Enable _penter Hook Function) and /GH (Enable _pexit Hook Function) compiler switches (if you can compile the sources ofcourse)

NOTE: you won't be able to use those macro's. See here ("you will need to get the function address (in EIP register) and compare it against addresses in the map file that can be generated by the linker (assuming no rebasing has occurred). It'll be very slow though.")

PoweRoy
Thanks PoweRoy. Do you know the corresponding compiler flag for gcc? Or what is the name of this technique, so that I can google it?
bmm
Don't know for gcc, '-g' from William looks the same. I searched for 'c++ enter/exit function hook' on google: http://gcc.gnu.org/onlinedocs/gccint/Function-Entry.html
PoweRoy
+1  A: 

You said "nor do I want to touch any source file"... fair game if you let a script do it for you?

Run this on all your .cpp files

sed 's/^{/{ENTRY/'

So that it transforms them into this:

void foo()
{ENTRY
  // code here
}

Put this in a header that can be #included by every unit:

#define ENTRY EntryRaiiObject obj ## __LINE__ (__FUNCTION__);

struct EntryRaiiObject {
  EntryRaiiObject(const char *f) : f_(f) { printf("Entered into %s", f_); }
  ~EntryRaiiObject() { printf("Exited from %s", f_); }
  const char *f_;
};

You may have to get fancier with the sed script. You can also put the ENTRY macro anywhere else you want to probe, like some deeply nested inner scope of a function.

Dan
+4  A: 

Besides the usual debugger and aspect-oriented programming techniques, you can also inject your own instrumentation functions using gcc's -finstrument-functions command line options. You'll have to implement your own __cyg_profile_func_enter() and __cyg_profile_func_exit() functions (declare these as extern "C" in C++).

They provide a means to track what function was called from where. However, the interface is a bit difficult to use since the address of the function being called and its call site are passed instead of a function name, for example. You could log the addresses, and then pull the corresponding names from the symbol table using something like objdump --syms or nm, assuming of course the symbols haven't been stripped from the binaries in question.

It may just be easier to use gdb. YMMV. :)

Void
Exactly what I was looking for :)
bmm