From Wikipedia, the free encyclopedia
// g++ -Wall -g -o t ./CheckPrintCall.cxx; ./t; echo '---------'; nm -ACln ./t | grep -E 'main|CheckPrintCall|func'
// objdump -d -g ./t # Show disassembly code (-d) and debug info (-g).
// ## Show disassembly code (-d) and display the corresponding source filenames
// ## and line numbers (-l) (executable should be compiled with '-g' flag!) and
// ## demangle symbol names (-C) and display source code (-S).
// objdump -CSld ./t | less
// kill -usr1 `pgrep '^t$'`
#include <iostream>
#include <signal.h>
#include <stdlib.h>
#define CHECK_PRINT_CALL(level) \
{ \
void* frame = __builtin_frame_address(level); \
if (!frame) \
{ \
cout << "*** BOTTOM OF FRAMES ***" << endl; \
return; \
} \
cout << "LEVEL " << level << " | FRAME " << frame << " | " << \
"RETURN " << __builtin_return_address(level) << endl; \
}
__attribute__ ((__noinline__))
void CheckPrintCall()
{
using std::cout;
using std::endl;
cout << "*** TOP OF FRAMES ***" << endl;
// Don't prepend zero before each number or it will be treated as octal number.
CHECK_PRINT_CALL( 0);
CHECK_PRINT_CALL( 1);
CHECK_PRINT_CALL( 2);
CHECK_PRINT_CALL( 3);
CHECK_PRINT_CALL( 4);
CHECK_PRINT_CALL( 5);
CHECK_PRINT_CALL( 6);
CHECK_PRINT_CALL( 7);
CHECK_PRINT_CALL( 8);
CHECK_PRINT_CALL( 9);
CHECK_PRINT_CALL(10);
CHECK_PRINT_CALL(11);
CHECK_PRINT_CALL(12);
CHECK_PRINT_CALL(13);
CHECK_PRINT_CALL(14);
CHECK_PRINT_CALL(15);
CHECK_PRINT_CALL(16);
CHECK_PRINT_CALL(17);
CHECK_PRINT_CALL(18);
CHECK_PRINT_CALL(19);
CHECK_PRINT_CALL(20);
CHECK_PRINT_CALL(21);
CHECK_PRINT_CALL(22);
CHECK_PRINT_CALL(23);
CHECK_PRINT_CALL(24);
CHECK_PRINT_CALL(25);
CHECK_PRINT_CALL(26);
CHECK_PRINT_CALL(27);
CHECK_PRINT_CALL(28);
CHECK_PRINT_CALL(29);
CHECK_PRINT_CALL(30);
CHECK_PRINT_CALL(31);
// cout << " . ." << endl;
// cout << " . ." << endl;
// cout << " . ." << endl;
cout << "(there could be more frames not printed out)" << endl;
}
void func5() { CheckPrintCall(); }
void func4() { func5(); }
void func3() { func4(); }
void func2() { func3(); }
void func1() { func2(); }
void sighand(int signum)
{
std::cout << "b ++++++++++++" << std::endl;
CheckPrintCall();
std::cout << "e ++++++++++++" << std::endl;
}
int main(int argc, char** argv)
{
// asm("movl %eax,%ebx");
func1();
signal(SIGUSR1, sighand);
getchar();
return 0;
}