User:Justin545/CheckPrintCall.cxx

//  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;
}