bbdebug.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #include "bbdebug.h"
  2. #include "bbarray.h"
  3. #include <bbmonkey.h>
  4. #if _WIN32
  5. #include <windows.h>
  6. #include <thread>
  7. #else
  8. #include <signal.h>
  9. #endif
  10. typedef void(*dbEmit_t)(void*);
  11. namespace bbDB{
  12. int nextSeq;
  13. bbDBContext *currentContext;
  14. #if !_WIN32
  15. void breakHandler( int sig ){
  16. currentContext->stopped=0x10000000;
  17. }
  18. #endif
  19. void sighandler( int sig ){
  20. const char *err="Unknown signal";
  21. switch( sig ){
  22. case SIGSEGV:err="Memory access violation";break;
  23. case SIGILL:err="Illegal instruction";
  24. case SIGFPE:err="Floating point exception";
  25. #if !_WIN32
  26. case SIGBUS:err="Bus error";
  27. #endif
  28. }
  29. #ifndef NDEBUG
  30. error( err );
  31. exit( 0 );
  32. #endif
  33. bb_printf( "Caught signal:%s\n",err );
  34. exit( -1 );
  35. }
  36. void init(){
  37. currentContext=new bbDBContext;
  38. currentContext->init();
  39. signal( SIGSEGV,sighandler );
  40. signal( SIGILL,sighandler );
  41. signal( SIGFPE,sighandler );
  42. #if !_WIN32
  43. signal( SIGBUS,sighandler );
  44. #endif
  45. #ifndef NDEBUG
  46. #if _WIN32
  47. if( HANDLE breakEvent=OpenEvent( EVENT_ALL_ACCESS,false,"MX2_BREAK_EVENT" ) ){
  48. // bb_printf( "Found BREAK_EVENT!\n" );fflush( stdout );
  49. std::thread( [=](){
  50. for( ;; ){
  51. WaitForSingleObject( breakEvent,INFINITE );
  52. // bb_printf( "Break event!\n" );fflush( stdout );
  53. currentContext->stopped=0x10000000;
  54. }
  55. } ).detach();
  56. }
  57. #else
  58. signal( SIGTSTP,breakHandler );
  59. #endif
  60. #endif
  61. }
  62. void emitVar( bbDBVar *v ){
  63. bbString id=v->name;
  64. bbString type=v->type->type();
  65. bbString value=v->type->value( v->var );
  66. bbString t=id+":"+type+"="+value+"\n";
  67. bb_printf( "%s",t.c_str() );
  68. }
  69. void emitStack(){
  70. bbDBVar *ev=currentContext->locals;
  71. for( bbDBFrame *f=currentContext->frames;f;f=f->succ ){
  72. bb_printf( ">%s;%s;%i;%i\n",f->decl,f->srcFile,f->srcPos>>12,f->seq );
  73. for( bbDBVar *v=f->locals;v!=ev;++v ){
  74. emitVar( v );
  75. }
  76. ev=f->locals;
  77. }
  78. }
  79. void stop(){
  80. currentContext->stopped=0;
  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*)strtol( 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 's':currentContext->stopped=0;return;
  104. case 'e':currentContext->stopped=1;return;
  105. case 'l':currentContext->stopped=-1;return;
  106. case 'r':currentContext->stopped=-0x10000000;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. }