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. #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=0x10000000;
  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";
  23. case SIGFPE:err="Floating point exception";
  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( "Break event!\n" );fflush( stdout );
  52. currentContext->stopped=0x10000000;
  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=0;
  80. }
  81. void emit( const char *e ){
  82. if( const char *p=strchr( e,':' ) ){
  83. dbEmit_t dbEmit=(dbEmit_t)( strtol( p+1,0,16 ) );
  84. dbEmit( (void*)strtol( e,0,16 ) );
  85. }else{
  86. bbGCNode *node=(bbGCNode*)strtol( e,0,16 );
  87. node->dbEmit();
  88. }
  89. puts( "" );
  90. fflush( stdout );
  91. }
  92. void stopped(){
  93. bb_printf( "{{!DEBUG!}}\n" );
  94. emitStack();
  95. bb_printf( "\n" );
  96. fflush( stdout );
  97. for(;;){
  98. char buf[256];
  99. char *e=fgets( buf,256,stdin );
  100. if( !e ) exit( -1 );
  101. switch( e[0] ){
  102. case 's':currentContext->stopped=0;return;
  103. case 'e':currentContext->stopped=1;return;
  104. case 'l':currentContext->stopped=-1;return;
  105. case 'r':currentContext->stopped=-0x10000000;return;
  106. case '@':emit( e+1 );continue;
  107. case 'q':exit( 0 );return;
  108. }
  109. bb_printf( "Unrecognized debug cmd: %s\n",buf );fflush( stdout );
  110. exit( -1 );
  111. }
  112. }
  113. void error( bbString msg ){
  114. bb_printf( "\n%s\n",msg.c_str() );
  115. stopped();
  116. }
  117. bbArray<bbString> stack(){
  118. int n=0;
  119. for( bbDBFrame *frame=currentContext->frames;frame;frame=frame->succ ) ++n;
  120. //TODO: Fix GC issues! Can't have a free local like this in case bbString ctors cause gc sweep!!!!
  121. bbArray<bbString> st=bbArray<bbString>( n );
  122. int i=0;
  123. for( bbDBFrame *frame=currentContext->frames;frame;frame=frame->succ ){
  124. st[i++]=BB_T( frame->srcFile )+" ["+bbString( frame->srcPos>>12 )+"] "+frame->decl;
  125. }
  126. return st;
  127. }
  128. }
  129. void bbDBContext::init(){
  130. if( !localsBuf ) localsBuf=new bbDBVar[16384];
  131. locals=localsBuf;
  132. frames=nullptr;
  133. stopped=0;
  134. }
  135. bbDBContext::~bbDBContext(){
  136. delete[] localsBuf;
  137. }
  138. bbString bbDBValue( bbString *p ){
  139. bbString t=*p,dd="";
  140. if( t.length()>100 ){
  141. t=t.slice( 0,100 );
  142. dd="...";
  143. }
  144. t=t.replace( "\"","~q" );
  145. t=t.replace( "\n","~n" );
  146. t=t.replace( "\r","~r" );
  147. t=t.replace( "\t","~t" );
  148. return BB_T("\"")+t+"\""+dd;
  149. }