bbdebug.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #include "bbdebug.h"
  2. #include "bbarray.h"
  3. #include <bbmonkey.h>
  4. #if _WIN32
  5. #include <windows.h>
  6. #include <thread>
  7. #endif
  8. #include <signal.h>
  9. typedef void(*dbEmit_t)(void*);
  10. namespace bbDB{
  11. int nextSeq;
  12. bbDBContext *currentContext;
  13. #if !_WIN32
  14. void breakHandler( int sig ){
  15. currentContext->stopped=1;
  16. }
  17. #endif
  18. void sighandler( int sig ){
  19. const char *err="Unknown signal";
  20. switch( sig ){
  21. case SIGSEGV:err="Memory access violation";break;
  22. case SIGILL:err="Illegal instruction";break;
  23. case SIGFPE:err="Floating point exception";break;
  24. #if !_WIN32
  25. case SIGBUS:err="Bus error";
  26. #endif
  27. }
  28. #ifndef NDEBUG
  29. error( err );
  30. exit( 0 );
  31. #endif
  32. bb_printf( "Caught signal:%s\n",err );
  33. exit( -1 );
  34. }
  35. void init(){
  36. currentContext=new bbDBContext;
  37. currentContext->init();
  38. signal( SIGSEGV,sighandler );
  39. signal( SIGILL,sighandler );
  40. signal( SIGFPE,sighandler );
  41. #if !_WIN32
  42. signal( SIGBUS,sighandler );
  43. #endif
  44. #ifndef NDEBUG
  45. #if _WIN32
  46. if( HANDLE breakEvent=OpenEvent( EVENT_ALL_ACCESS,false,"MX2_BREAK_EVENT" ) ){
  47. // bb_printf( "Found BREAK_EVENT!\n" );fflush( stdout );
  48. std::thread( [=](){
  49. for( ;; ){
  50. WaitForSingleObject( breakEvent,INFINITE );
  51. // bb_printf( "received Break event!\n" );fflush( stdout );
  52. currentContext->stopped=1;
  53. }
  54. } ).detach();
  55. }
  56. #else
  57. signal( SIGTSTP,breakHandler );
  58. #endif
  59. #endif
  60. }
  61. void emitVar( bbDBVar *v ){
  62. bbString id=v->name;
  63. bbString type=v->type->type();
  64. bbString value=v->type->value( v->var );
  65. bbString t=id+":"+type+"="+value+"\n";
  66. bb_printf( "%s",t.c_str() );
  67. }
  68. void emitStack(){
  69. bbDBVar *ev=currentContext->locals;
  70. for( bbDBFrame *f=currentContext->frames;f;f=f->succ ){
  71. bb_printf( ">%s;%s;%i;%i\n",f->decl,f->srcFile,f->srcPos>>12,f->seq );
  72. for( bbDBVar *v=f->locals;v!=ev;++v ){
  73. emitVar( v );
  74. }
  75. ev=f->locals;
  76. }
  77. }
  78. void stop(){
  79. //currentContext->stopped=1; //stop on *next* stmt.
  80. stopped(); //stop on DebugStop() stmt.
  81. }
  82. void emit( const char *e ){
  83. if( const char *p=strchr( e,':' ) ){
  84. dbEmit_t dbEmit=(dbEmit_t)( strtol( p+1,0,16 ) );
  85. dbEmit( (void*)strtol( e,0,16 ) );
  86. }else{
  87. bbGCNode *node=(bbGCNode*)strtoll( e,0,16 );
  88. node->dbEmit();
  89. }
  90. puts( "" );
  91. fflush( stdout );
  92. }
  93. void stopped(){
  94. bb_printf( "{{!DEBUG!}}\n" );
  95. emitStack();
  96. bb_printf( "\n" );
  97. fflush( stdout );
  98. for(;;){
  99. char buf[256];
  100. char *e=fgets( buf,256,stdin );
  101. if( !e ) exit( -1 );
  102. switch( e[0] ){
  103. case 'r':currentContext->stopped=0;currentContext->stepMode=0;return;
  104. case 'e':currentContext->stopped=1;currentContext->stepMode=0;return;
  105. case 's':currentContext->stopped=1;currentContext->stepMode='s';return;
  106. case 'l':currentContext->stopped=0;currentContext->stepMode='l';return;
  107. case '@':emit( e+1 );continue;
  108. case 'q':exit( 0 );return;
  109. }
  110. bb_printf( "Unrecognized debug cmd: %s\n",buf );fflush( stdout );
  111. exit( -1 );
  112. }
  113. }
  114. void error( bbString msg ){
  115. bb_printf( "\n%s\n",msg.c_str() );
  116. stopped();
  117. }
  118. bbArray<bbString> stack(){
  119. int n=0;
  120. for( bbDBFrame *frame=currentContext->frames;frame;frame=frame->succ ) ++n;
  121. //TODO: Fix GC issues! Can't have a free local like this in case bbString ctors cause gc sweep!!!!
  122. bbArray<bbString> st=bbArray<bbString>( n );
  123. int i=0;
  124. for( bbDBFrame *frame=currentContext->frames;frame;frame=frame->succ ){
  125. st[i++]=BB_T( frame->srcFile )+" ["+bbString( frame->srcPos>>12 )+"] "+frame->decl;
  126. }
  127. return st;
  128. }
  129. }
  130. void bbDBContext::init(){
  131. if( !localsBuf ) localsBuf=new bbDBVar[16384];
  132. locals=localsBuf;
  133. frames=nullptr;
  134. stopped=0;
  135. }
  136. bbDBContext::~bbDBContext(){
  137. delete[] localsBuf;
  138. }
  139. bbString bbDBValue( bbString *p ){
  140. bbString t=*p,dd="";
  141. if( t.length()>100 ){
  142. t=t.slice( 0,100 );
  143. dd="...";
  144. }
  145. t=t.replace( "\"","~q" );
  146. t=t.replace( "\n","~n" );
  147. t=t.replace( "\r","~r" );
  148. t=t.replace( "\t","~t" );
  149. return BB_T("\"")+t+"\""+dd;
  150. }