Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatically adding Enter/Exit Function Logs to a Project

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?

like image 835
Benji Mizrahi Avatar asked Feb 17 '10 15:02

Benji Mizrahi


People also ask

How do you implement an exit in C++?

In C++, you can exit a program in these ways: Call the exit function. Call the abort function. Execute a return statement from main .

What is the function of exit ()?

The exit () function is used to break out of a loop. This function causes an immediate termination of the entire program done by the operation system.

Which header file is used for exit () function?

The function has been defined under the stdlib. h header file, which must be included while using the exit() function.


2 Answers

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. :)

like image 142
Void Avatar answered Sep 23 '22 12:09

Void


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.

like image 41
Dan Avatar answered Sep 21 '22 12:09

Dan