bbdebug.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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. #ifdef __EMSCRIPTEN__
  10. #include <emscripten.h>
  11. #endif
  12. typedef void(*dbEmit_t)(void*);
  13. #if BB_THREADS
  14. namespace bbGC{
  15. extern const char *state;
  16. void suspendThreads();
  17. void resumeThreads();
  18. }
  19. #endif
  20. namespace bbDB{
  21. #if BB_THREADS
  22. std::atomic_int nextSeq;
  23. thread_local bbDBContext *currentContext;
  24. #else
  25. int nextSeq;
  26. bbDBContext *currentContext;
  27. #endif
  28. bbDBContext mainContext;
  29. #if !_WIN32
  30. void breakHandler( int sig ){
  31. currentContext->stopped=1;
  32. }
  33. #endif
  34. //Note: doesn't work on non-mainthread on at least windows.
  35. //
  36. void sighandler( int sig ){
  37. const char *err="SIGNAL: Unknown signal";
  38. switch( sig ){
  39. case SIGSEGV:err="SIGNAL: Memory access violation";break;
  40. case SIGILL:err= "SIGNAL: Illegal instruction";break;
  41. case SIGFPE:err= "SIGNAL: Floating point exception";break;
  42. #if !_WIN32
  43. case SIGBUS:err= "SIGNAL: Bus error";break;
  44. #endif
  45. }
  46. char buf[160];
  47. #ifdef BB_THREADS
  48. sprintf( buf,"Monkey 2 Runtime error: %s\nGC state=%s\n",err,bbGC::state );
  49. #else
  50. sprintf( buf,"Monkey 2 Runtime error: %s\n",err );
  51. #endif
  52. bb_printf( buf );
  53. #ifdef NDEBUG
  54. #ifdef _WIN32
  55. MessageBoxA( 0,buf,"Monkey 2 Runtime Error",MB_OK );
  56. #endif
  57. exit( -1 );
  58. #endif
  59. stopped();
  60. }
  61. void init(){
  62. mainContext.init();
  63. currentContext=&mainContext;
  64. signal( SIGSEGV,sighandler );
  65. signal( SIGILL,sighandler );
  66. signal( SIGFPE,sighandler );
  67. #if !_WIN32
  68. signal( SIGBUS,sighandler );
  69. #endif
  70. #ifndef NDEBUG
  71. #if _WIN32
  72. if( HANDLE breakEvent=OpenEvent( EVENT_ALL_ACCESS,false,"MX2_BREAK_EVENT" ) ){
  73. // bb_printf( "Found BREAK_EVENT!\n" );fflush( stdout );
  74. std::thread( [=](){
  75. for( ;; ){
  76. WaitForSingleObject( breakEvent,INFINITE );
  77. // bb_printf( "received Break event!\n" );fflush( stdout );
  78. currentContext->stopped=1;
  79. }
  80. } ).detach();
  81. }
  82. #else
  83. signal( SIGTSTP,breakHandler );
  84. #endif
  85. #endif
  86. }
  87. void emit( const char *e ){
  88. if( const char *p=strchr( e,':' ) ){
  89. dbEmit_t dbEmit=(dbEmit_t)( strtol( p+1,0,16 ) );
  90. dbEmit( (void*)strtol( e,0,16 ) );
  91. }else{
  92. bbGCNode *node=(bbGCNode*)strtoll( e,0,16 );
  93. node->dbEmit();
  94. }
  95. puts( "" );
  96. fflush( stdout );
  97. }
  98. void emitVar( bbDBVar *v ){
  99. bbString id=v->name;
  100. bbString type=v->type->type();
  101. bbString value=v->type->value( v->var );
  102. bbString t=id+":"+type+"="+value+"\n";
  103. bb_printf( "%s",t.c_str() );
  104. }
  105. void emitStack(){
  106. bbDBVar *ev=currentContext->locals;
  107. for( bbDBFrame *f=currentContext->frames;f;f=f->succ ){
  108. bb_printf( ">%s;%s;%i;%i\n",f->decl,f->srcFile,f->srcPos>>12,f->seq );
  109. for( bbDBVar *v=f->locals;v!=ev;++v ){
  110. emitVar( v );
  111. }
  112. ev=f->locals;
  113. }
  114. }
  115. void error( bbString msg ){
  116. #if _WIN32
  117. MessageBoxW( 0,bbWString( msg ),L"Monkey 2 Runtime Error",MB_OK );
  118. #else
  119. bb_print( msg );
  120. #endif
  121. stopped();
  122. }
  123. void stopped(){
  124. #ifdef NDEBUG
  125. exit( -1 );
  126. #endif
  127. #ifdef BB_THREADS
  128. bbGC::suspendThreads();
  129. #endif
  130. #ifdef __EMSCRIPTEN__
  131. emscripten_pause_main_loop();
  132. #endif
  133. bb_printf( "{{!DEBUG!}}\n" );
  134. emitStack();
  135. bb_printf( "\n" );
  136. fflush( stdout );
  137. for(;;){
  138. char buf[256];
  139. char *e=fgets( buf,256,stdin );
  140. if( !e ) exit( -1 );
  141. #ifdef BB_THREADS
  142. bbGC::resumeThreads();
  143. #endif
  144. #ifdef __EMSCRIPTEN__
  145. emscripten_resume_main_loop();
  146. #endif
  147. switch( e[0] ){
  148. case 'r':currentContext->stopped=0;currentContext->stepMode=0;break;
  149. case 'e':currentContext->stopped=1;currentContext->stepMode=0;break;
  150. case 's':currentContext->stopped=1;currentContext->stepMode='s';break;
  151. case 'l':currentContext->stopped=0;currentContext->stepMode='l';break;
  152. case '@':emit( e+1 );continue;
  153. case 'q':exit( 0 );break;
  154. default:
  155. bb_printf( "Unrecognized debug cmd: %s\n",buf );fflush( stdout );
  156. exit( -1 );
  157. }
  158. return;
  159. }
  160. }
  161. bbArray<bbString> stack(){
  162. int n=0;
  163. for( bbDBFrame *frame=currentContext->frames;frame;frame=frame->succ ) ++n;
  164. //TODO: Fix GC issues! Can't have a free local like this in case bbString ctors cause gc sweep!!!!
  165. bbArray<bbString> st=bbArray<bbString>( n );
  166. int i=0;
  167. for( bbDBFrame *frame=currentContext->frames;frame;frame=frame->succ ){
  168. st[i++]=BB_T( frame->srcFile )+" ["+bbString( frame->srcPos>>12 )+"] "+frame->decl;
  169. }
  170. return st;
  171. }
  172. void stop(){
  173. //currentContext->stopped=1; //stop on *next* stmt.
  174. stopped(); //stop on DebugStop() stmt.
  175. }
  176. }
  177. void bbDBContext::init(){
  178. if( !localsBuf ) localsBuf=new bbDBVar[16384];
  179. locals=localsBuf;
  180. frames=nullptr;
  181. stepMode=0;
  182. stopped=0;
  183. }
  184. bbDBContext::~bbDBContext(){
  185. delete[] localsBuf;
  186. }
  187. bbString bbDBValue( bbString *p ){
  188. bbString t=*p,dd="";
  189. if( t.length()>100 ){
  190. t=t.slice( 0,100 );
  191. dd="...";
  192. }
  193. t=t.replace( "\"","~q" );
  194. t=t.replace( "\n","~n" );
  195. t=t.replace( "\r","~r" );
  196. t=t.replace( "\t","~t" );
  197. return BB_T("\"")+t+"\""+dd;
  198. }