|
Ruby
2.0.0p594(2014-10-27revision48167)
|
00001 /********************************************************************** 00002 00003 vm_dump.c - 00004 00005 $Author: usa $ 00006 00007 Copyright (C) 2004-2007 Koichi Sasada 00008 00009 **********************************************************************/ 00010 00011 00012 #include "ruby/ruby.h" 00013 #include "addr2line.h" 00014 #include "vm_core.h" 00015 #include "internal.h" 00016 00017 /* see vm_insnhelper.h for the values */ 00018 #ifndef VMDEBUG 00019 #define VMDEBUG 0 00020 #endif 00021 00022 #define MAX_POSBUF 128 00023 00024 #define VM_CFP_CNT(th, cfp) \ 00025 ((rb_control_frame_t *)((th)->stack + (th)->stack_size) - (rb_control_frame_t *)(cfp)) 00026 00027 static void 00028 control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp) 00029 { 00030 ptrdiff_t pc = -1; 00031 ptrdiff_t ep = cfp->ep - th->stack; 00032 char ep_in_heap = ' '; 00033 char posbuf[MAX_POSBUF+1]; 00034 int line = 0; 00035 00036 const char *magic, *iseq_name = "-", *selfstr = "-", *biseq_name = "-"; 00037 VALUE tmp; 00038 00039 if (cfp->block_iseq != 0 && BUILTIN_TYPE(cfp->block_iseq) != T_NODE) { 00040 biseq_name = ""; /* RSTRING(cfp->block_iseq->location.label)->ptr; */ 00041 } 00042 00043 if (ep < 0 || (size_t)ep > th->stack_size) { 00044 ep = (ptrdiff_t)cfp->ep; 00045 ep_in_heap = 'p'; 00046 } 00047 00048 switch (VM_FRAME_TYPE(cfp)) { 00049 case VM_FRAME_MAGIC_TOP: 00050 magic = "TOP"; 00051 break; 00052 case VM_FRAME_MAGIC_METHOD: 00053 magic = "METHOD"; 00054 break; 00055 case VM_FRAME_MAGIC_CLASS: 00056 magic = "CLASS"; 00057 break; 00058 case VM_FRAME_MAGIC_BLOCK: 00059 magic = "BLOCK"; 00060 break; 00061 case VM_FRAME_MAGIC_CFUNC: 00062 magic = "CFUNC"; 00063 break; 00064 case VM_FRAME_MAGIC_PROC: 00065 magic = "PROC"; 00066 break; 00067 case VM_FRAME_MAGIC_LAMBDA: 00068 magic = "LAMBDA"; 00069 break; 00070 case VM_FRAME_MAGIC_IFUNC: 00071 magic = "IFUNC"; 00072 break; 00073 case VM_FRAME_MAGIC_EVAL: 00074 magic = "EVAL"; 00075 break; 00076 case VM_FRAME_MAGIC_RESCUE: 00077 magic = "RESCUE"; 00078 break; 00079 case 0: 00080 magic = "------"; 00081 break; 00082 default: 00083 magic = "(none)"; 00084 break; 00085 } 00086 00087 if (0) { 00088 tmp = rb_inspect(cfp->self); 00089 selfstr = StringValueCStr(tmp); 00090 } 00091 else { 00092 selfstr = ""; 00093 } 00094 00095 if (cfp->iseq != 0) { 00096 if (RUBY_VM_IFUNC_P(cfp->iseq)) { 00097 iseq_name = "<ifunc>"; 00098 } 00099 else { 00100 pc = cfp->pc - cfp->iseq->iseq_encoded; 00101 iseq_name = RSTRING_PTR(cfp->iseq->location.label); 00102 line = rb_vm_get_sourceline(cfp); 00103 if (line) { 00104 snprintf(posbuf, MAX_POSBUF, "%s:%d", RSTRING_PTR(cfp->iseq->location.path), line); 00105 } 00106 } 00107 } 00108 else if (cfp->me) { 00109 iseq_name = rb_id2name(cfp->me->def->original_id); 00110 snprintf(posbuf, MAX_POSBUF, ":%s", iseq_name); 00111 line = -1; 00112 } 00113 00114 fprintf(stderr, "c:%04"PRIdPTRDIFF" ", 00115 ((rb_control_frame_t *)(th->stack + th->stack_size) - cfp)); 00116 if (pc == -1) { 00117 fprintf(stderr, "p:---- "); 00118 } 00119 else { 00120 fprintf(stderr, "p:%04"PRIdPTRDIFF" ", pc); 00121 } 00122 fprintf(stderr, "s:%04"PRIdPTRDIFF" ", cfp->sp - th->stack); 00123 fprintf(stderr, ep_in_heap == ' ' ? "e:%06"PRIdPTRDIFF" " : "E:%06"PRIxPTRDIFF" ", ep % 10000); 00124 fprintf(stderr, "%-6s", magic); 00125 if (line) { 00126 fprintf(stderr, " %s", posbuf); 00127 } 00128 if (VM_FRAME_TYPE_FINISH_P(cfp)) { 00129 fprintf(stderr, " [FINISH]"); 00130 } 00131 if (0) { 00132 fprintf(stderr, " \t"); 00133 fprintf(stderr, "iseq: %-24s ", iseq_name); 00134 fprintf(stderr, "self: %-24s ", selfstr); 00135 fprintf(stderr, "%-1s ", biseq_name); 00136 } 00137 fprintf(stderr, "\n"); 00138 } 00139 00140 void 00141 rb_vmdebug_stack_dump_raw(rb_thread_t *th, rb_control_frame_t *cfp) 00142 { 00143 #if 0 00144 VALUE *sp = cfp->sp, *ep = cfp->ep; 00145 VALUE *p, *st, *t; 00146 00147 fprintf(stderr, "-- stack frame ------------\n"); 00148 for (p = st = th->stack; p < sp; p++) { 00149 fprintf(stderr, "%04ld (%p): %08"PRIxVALUE, (long)(p - st), p, *p); 00150 00151 t = (VALUE *)*p; 00152 if (th->stack <= t && t < sp) { 00153 fprintf(stderr, " (= %ld)", (long)((VALUE *)GC_GUARDED_PTR_REF(t) - th->stack)); 00154 } 00155 00156 if (p == ep) 00157 fprintf(stderr, " <- ep"); 00158 00159 fprintf(stderr, "\n"); 00160 } 00161 #endif 00162 00163 fprintf(stderr, "-- Control frame information " 00164 "-----------------------------------------------\n"); 00165 while ((void *)cfp < (void *)(th->stack + th->stack_size)) { 00166 control_frame_dump(th, cfp); 00167 cfp++; 00168 } 00169 fprintf(stderr, "\n"); 00170 } 00171 00172 void 00173 rb_vmdebug_stack_dump_raw_current(void) 00174 { 00175 rb_thread_t *th = GET_THREAD(); 00176 rb_vmdebug_stack_dump_raw(th, th->cfp); 00177 } 00178 00179 void 00180 rb_vmdebug_env_dump_raw(rb_env_t *env, VALUE *ep) 00181 { 00182 int i; 00183 fprintf(stderr, "-- env --------------------\n"); 00184 00185 while (env) { 00186 fprintf(stderr, "--\n"); 00187 for (i = 0; i < env->env_size; i++) { 00188 fprintf(stderr, "%04d: %08"PRIxVALUE" (%p)", -env->local_size + i, env->env[i], 00189 (void *)&env->env[i]); 00190 if (&env->env[i] == ep) 00191 fprintf(stderr, " <- ep"); 00192 fprintf(stderr, "\n"); 00193 } 00194 00195 if (env->prev_envval != 0) { 00196 GetEnvPtr(env->prev_envval, env); 00197 } 00198 else { 00199 env = 0; 00200 } 00201 } 00202 fprintf(stderr, "---------------------------\n"); 00203 } 00204 00205 void 00206 rb_vmdebug_proc_dump_raw(rb_proc_t *proc) 00207 { 00208 rb_env_t *env; 00209 char *selfstr; 00210 VALUE val = rb_inspect(proc->block.self); 00211 selfstr = StringValueCStr(val); 00212 00213 fprintf(stderr, "-- proc -------------------\n"); 00214 fprintf(stderr, "self: %s\n", selfstr); 00215 GetEnvPtr(proc->envval, env); 00216 rb_vmdebug_env_dump_raw(env, proc->block.ep); 00217 } 00218 00219 void 00220 rb_vmdebug_stack_dump_th(VALUE thval) 00221 { 00222 rb_thread_t *th; 00223 GetThreadPtr(thval, th); 00224 rb_vmdebug_stack_dump_raw(th, th->cfp); 00225 } 00226 00227 #if VMDEBUG > 2 00228 00229 /* copy from vm.c */ 00230 static VALUE * 00231 vm_base_ptr(rb_control_frame_t *cfp) 00232 { 00233 rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); 00234 VALUE *bp = prev_cfp->sp + cfp->iseq->local_size + 1; 00235 00236 if (cfp->iseq->type == ISEQ_TYPE_METHOD) { 00237 bp += 1; 00238 } 00239 return bp; 00240 } 00241 00242 static void 00243 vm_stack_dump_each(rb_thread_t *th, rb_control_frame_t *cfp) 00244 { 00245 int i; 00246 00247 VALUE rstr; 00248 VALUE *sp = cfp->sp; 00249 VALUE *ep = cfp->ep; 00250 00251 int argc = 0, local_size = 0; 00252 const char *name; 00253 rb_iseq_t *iseq = cfp->iseq; 00254 00255 if (iseq == 0) { 00256 if (RUBYVM_CFUNC_FRAME_P(cfp)) { 00257 name = rb_id2name(cfp->me->called_id); 00258 } 00259 else { 00260 name = "?"; 00261 } 00262 } 00263 else if (RUBY_VM_IFUNC_P(iseq)) { 00264 name = "<ifunc>"; 00265 } 00266 else { 00267 argc = iseq->argc; 00268 local_size = iseq->local_size; 00269 name = RSTRING_PTR(iseq->location.label); 00270 } 00271 00272 /* stack trace header */ 00273 00274 if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_METHOD|| 00275 VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_TOP || 00276 VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_BLOCK || 00277 VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CLASS || 00278 VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_PROC || 00279 VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA|| 00280 VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CFUNC || 00281 VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_IFUNC || 00282 VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_EVAL || 00283 VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_RESCUE) 00284 { 00285 00286 VALUE *ptr = ep - local_size; 00287 00288 control_frame_dump(th, cfp); 00289 00290 for (i = 0; i < argc; i++) { 00291 rstr = rb_inspect(*ptr); 00292 fprintf(stderr, " arg %2d: %8s (%p)\n", i, StringValueCStr(rstr), 00293 (void *)ptr++); 00294 } 00295 for (; i < local_size - 1; i++) { 00296 rstr = rb_inspect(*ptr); 00297 fprintf(stderr, " local %2d: %8s (%p)\n", i, StringValueCStr(rstr), 00298 (void *)ptr++); 00299 } 00300 00301 ptr = vm_base_ptr(cfp); 00302 for (; ptr < sp; ptr++, i++) { 00303 if (*ptr == Qundef) { 00304 rstr = rb_str_new2("undef"); 00305 } 00306 else { 00307 rstr = rb_inspect(*ptr); 00308 } 00309 fprintf(stderr, " stack %2d: %8s (%"PRIdPTRDIFF")\n", i, StringValueCStr(rstr), 00310 (ptr - th->stack)); 00311 } 00312 } 00313 else if (VM_FRAME_TYPE_FINISH_P(cfp)) { 00314 if ((th)->stack + (th)->stack_size > (VALUE *)(cfp + 1)) { 00315 vm_stack_dump_each(th, cfp + 1); 00316 } 00317 else { 00318 /* SDR(); */ 00319 } 00320 } 00321 else { 00322 rb_bug("unsupport frame type: %08lx", VM_FRAME_TYPE(cfp)); 00323 } 00324 } 00325 #endif 00326 00327 void 00328 rb_vmdebug_debug_print_register(rb_thread_t *th) 00329 { 00330 rb_control_frame_t *cfp = th->cfp; 00331 ptrdiff_t pc = -1; 00332 ptrdiff_t ep = cfp->ep - th->stack; 00333 ptrdiff_t cfpi; 00334 00335 if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) { 00336 pc = cfp->pc - cfp->iseq->iseq_encoded; 00337 } 00338 00339 if (ep < 0 || (size_t)ep > th->stack_size) { 00340 ep = -1; 00341 } 00342 00343 cfpi = ((rb_control_frame_t *)(th->stack + th->stack_size)) - cfp; 00344 fprintf(stderr, " [PC] %04"PRIdPTRDIFF", [SP] %04"PRIdPTRDIFF", [EP] %04"PRIdPTRDIFF", [CFP] %04"PRIdPTRDIFF"\n", 00345 pc, (cfp->sp - th->stack), ep, cfpi); 00346 } 00347 00348 void 00349 rb_vmdebug_thread_dump_regs(VALUE thval) 00350 { 00351 rb_thread_t *th; 00352 GetThreadPtr(thval, th); 00353 rb_vmdebug_debug_print_register(th); 00354 } 00355 00356 void 00357 rb_vmdebug_debug_print_pre(rb_thread_t *th, rb_control_frame_t *cfp) 00358 { 00359 rb_iseq_t *iseq = cfp->iseq; 00360 00361 if (iseq != 0) { 00362 VALUE *seq = iseq->iseq; 00363 ptrdiff_t pc = cfp->pc - iseq->iseq_encoded; 00364 int i; 00365 00366 for (i=0; i<(int)VM_CFP_CNT(th, cfp); i++) { 00367 printf(" "); 00368 } 00369 printf("| "); 00370 /* printf("%3"PRIdPTRDIFF" ", VM_CFP_CNT(th, cfp)); */ 00371 if (pc >= 0) { 00372 rb_iseq_disasm_insn(0, seq, (size_t)pc, iseq, 0); 00373 } 00374 } 00375 00376 #if VMDEBUG > 3 00377 fprintf(stderr, " (1)"); 00378 rb_vmdebug_debug_print_register(th); 00379 #endif 00380 } 00381 00382 void 00383 rb_vmdebug_debug_print_post(rb_thread_t *th, rb_control_frame_t *cfp 00384 #if OPT_STACK_CACHING 00385 , VALUE reg_a, VALUE reg_b 00386 #endif 00387 ) 00388 { 00389 #if VMDEBUG > 9 00390 SDR2(cfp); 00391 #endif 00392 00393 #if VMDEBUG > 3 00394 fprintf(stderr, " (2)"); 00395 rb_vmdebug_debug_print_register(th); 00396 #endif 00397 /* stack_dump_raw(th, cfp); */ 00398 00399 #if VMDEBUG > 2 00400 /* stack_dump_thobj(th); */ 00401 vm_stack_dump_each(th, th->cfp); 00402 00403 #if OPT_STACK_CACHING 00404 { 00405 VALUE rstr; 00406 rstr = rb_inspect(reg_a); 00407 fprintf(stderr, " sc reg A: %s\n", StringValueCStr(rstr)); 00408 rstr = rb_inspect(reg_b); 00409 fprintf(stderr, " sc reg B: %s\n", StringValueCStr(rstr)); 00410 } 00411 #endif 00412 printf 00413 ("--------------------------------------------------------------\n"); 00414 #endif 00415 } 00416 00417 VALUE 00418 rb_vmdebug_thread_dump_state(VALUE self) 00419 { 00420 rb_thread_t *th; 00421 rb_control_frame_t *cfp; 00422 GetThreadPtr(self, th); 00423 cfp = th->cfp; 00424 00425 fprintf(stderr, "Thread state dump:\n"); 00426 fprintf(stderr, "pc : %p, sp : %p\n", (void *)cfp->pc, (void *)cfp->sp); 00427 fprintf(stderr, "cfp: %p, ep : %p\n", (void *)cfp, (void *)cfp->ep); 00428 00429 return Qnil; 00430 } 00431 00432 #ifndef HAVE_BACKTRACE 00433 #define HAVE_BACKTRACE 0 00434 #endif 00435 #if HAVE_BACKTRACE 00436 # include <execinfo.h> 00437 #elif defined(_WIN32) 00438 # include <imagehlp.h> 00439 # ifndef SYMOPT_DEBUG 00440 # define SYMOPT_DEBUG 0x80000000 00441 # endif 00442 # ifndef MAX_SYM_NAME 00443 # define MAX_SYM_NAME 2000 00444 typedef struct { 00445 DWORD64 Offset; 00446 WORD Segment; 00447 ADDRESS_MODE Mode; 00448 } ADDRESS64; 00449 typedef struct { 00450 DWORD64 Thread; 00451 DWORD ThCallbackStack; 00452 DWORD ThCallbackBStore; 00453 DWORD NextCallback; 00454 DWORD FramePointer; 00455 DWORD64 KiCallUserMode; 00456 DWORD64 KeUserCallbackDispatcher; 00457 DWORD64 SystemRangeStart; 00458 DWORD64 KiUserExceptionDispatcher; 00459 DWORD64 StackBase; 00460 DWORD64 StackLimit; 00461 DWORD64 Reserved[5]; 00462 } KDHELP64; 00463 typedef struct { 00464 ADDRESS64 AddrPC; 00465 ADDRESS64 AddrReturn; 00466 ADDRESS64 AddrFrame; 00467 ADDRESS64 AddrStack; 00468 ADDRESS64 AddrBStore; 00469 void *FuncTableEntry; 00470 DWORD64 Params[4]; 00471 BOOL Far; 00472 BOOL Virtual; 00473 DWORD64 Reserved[3]; 00474 KDHELP64 KdHelp; 00475 } STACKFRAME64; 00476 typedef struct { 00477 ULONG SizeOfStruct; 00478 ULONG TypeIndex; 00479 ULONG64 Reserved[2]; 00480 ULONG Index; 00481 ULONG Size; 00482 ULONG64 ModBase; 00483 ULONG Flags; 00484 ULONG64 Value; 00485 ULONG64 Address; 00486 ULONG Register; 00487 ULONG Scope; 00488 ULONG Tag; 00489 ULONG NameLen; 00490 ULONG MaxNameLen; 00491 char Name[1]; 00492 } SYMBOL_INFO; 00493 typedef struct { 00494 DWORD SizeOfStruct; 00495 void *Key; 00496 DWORD LineNumber; 00497 char *FileName; 00498 DWORD64 Address; 00499 } IMAGEHLP_LINE64; 00500 typedef void *PREAD_PROCESS_MEMORY_ROUTINE64; 00501 typedef void *PFUNCTION_TABLE_ACCESS_ROUTINE64; 00502 typedef void *PGET_MODULE_BASE_ROUTINE64; 00503 typedef void *PTRANSLATE_ADDRESS_ROUTINE64; 00504 # endif 00505 00506 static void 00507 dump_thread(void *arg) 00508 { 00509 HANDLE dbghelp; 00510 BOOL (WINAPI *pSymInitialize)(HANDLE, const char *, BOOL); 00511 BOOL (WINAPI *pSymCleanup)(HANDLE); 00512 BOOL (WINAPI *pStackWalk64)(DWORD, HANDLE, HANDLE, STACKFRAME64 *, void *, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64, PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64); 00513 DWORD64 (WINAPI *pSymGetModuleBase64)(HANDLE, DWORD64); 00514 BOOL (WINAPI *pSymFromAddr)(HANDLE, DWORD64, DWORD64 *, SYMBOL_INFO *); 00515 BOOL (WINAPI *pSymGetLineFromAddr64)(HANDLE, DWORD64, DWORD *, IMAGEHLP_LINE64 *); 00516 HANDLE (WINAPI *pOpenThread)(DWORD, BOOL, DWORD); 00517 DWORD tid = *(DWORD *)arg; 00518 HANDLE ph; 00519 HANDLE th; 00520 00521 dbghelp = LoadLibrary("dbghelp.dll"); 00522 if (!dbghelp) return; 00523 pSymInitialize = (BOOL (WINAPI *)(HANDLE, const char *, BOOL))GetProcAddress(dbghelp, "SymInitialize"); 00524 pSymCleanup = (BOOL (WINAPI *)(HANDLE))GetProcAddress(dbghelp, "SymCleanup"); 00525 pStackWalk64 = (BOOL (WINAPI *)(DWORD, HANDLE, HANDLE, STACKFRAME64 *, void *, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64, PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64))GetProcAddress(dbghelp, "StackWalk64"); 00526 pSymGetModuleBase64 = (DWORD64 (WINAPI *)(HANDLE, DWORD64))GetProcAddress(dbghelp, "SymGetModuleBase64"); 00527 pSymFromAddr = (BOOL (WINAPI *)(HANDLE, DWORD64, DWORD64 *, SYMBOL_INFO *))GetProcAddress(dbghelp, "SymFromAddr"); 00528 pSymGetLineFromAddr64 = (BOOL (WINAPI *)(HANDLE, DWORD64, DWORD *, IMAGEHLP_LINE64 *))GetProcAddress(dbghelp, "SymGetLineFromAddr64"); 00529 pOpenThread = (HANDLE (WINAPI *)(DWORD, BOOL, DWORD))GetProcAddress(GetModuleHandle("kernel32.dll"), "OpenThread"); 00530 if (pSymInitialize && pSymCleanup && pStackWalk64 && pSymGetModuleBase64 && 00531 pSymFromAddr && pSymGetLineFromAddr64 && pOpenThread) { 00532 SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES); 00533 ph = GetCurrentProcess(); 00534 pSymInitialize(ph, NULL, TRUE); 00535 th = pOpenThread(THREAD_SUSPEND_RESUME|THREAD_GET_CONTEXT, FALSE, tid); 00536 if (th) { 00537 if (SuspendThread(th) != (DWORD)-1) { 00538 CONTEXT context; 00539 memset(&context, 0, sizeof(context)); 00540 context.ContextFlags = CONTEXT_FULL; 00541 if (GetThreadContext(th, &context)) { 00542 char libpath[MAX_PATH]; 00543 char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; 00544 SYMBOL_INFO *info = (SYMBOL_INFO *)buf; 00545 DWORD mac; 00546 STACKFRAME64 frame; 00547 memset(&frame, 0, sizeof(frame)); 00548 #if defined(_M_AMD64) || defined(__x86_64__) 00549 mac = IMAGE_FILE_MACHINE_AMD64; 00550 frame.AddrPC.Mode = AddrModeFlat; 00551 frame.AddrPC.Offset = context.Rip; 00552 frame.AddrFrame.Mode = AddrModeFlat; 00553 frame.AddrFrame.Offset = context.Rbp; 00554 frame.AddrStack.Mode = AddrModeFlat; 00555 frame.AddrStack.Offset = context.Rsp; 00556 #elif defined(_M_IA64) || defined(__ia64__) 00557 mac = IMAGE_FILE_MACHINE_IA64; 00558 frame.AddrPC.Mode = AddrModeFlat; 00559 frame.AddrPC.Offset = context.StIIP; 00560 frame.AddrBStore.Mode = AddrModeFlat; 00561 frame.AddrBStore.Offset = context.RsBSP; 00562 frame.AddrStack.Mode = AddrModeFlat; 00563 frame.AddrStack.Offset = context.IntSp; 00564 #else /* i386 */ 00565 mac = IMAGE_FILE_MACHINE_I386; 00566 frame.AddrPC.Mode = AddrModeFlat; 00567 frame.AddrPC.Offset = context.Eip; 00568 frame.AddrFrame.Mode = AddrModeFlat; 00569 frame.AddrFrame.Offset = context.Ebp; 00570 frame.AddrStack.Mode = AddrModeFlat; 00571 frame.AddrStack.Offset = context.Esp; 00572 #endif 00573 00574 while (pStackWalk64(mac, ph, th, &frame, &context, NULL, 00575 NULL, NULL, NULL)) { 00576 DWORD64 addr = frame.AddrPC.Offset; 00577 IMAGEHLP_LINE64 line; 00578 DWORD64 displacement; 00579 DWORD tmp; 00580 00581 if (addr == frame.AddrReturn.Offset || addr == 0 || 00582 frame.AddrReturn.Offset == 0) 00583 break; 00584 00585 memset(buf, 0, sizeof(buf)); 00586 info->SizeOfStruct = sizeof(SYMBOL_INFO); 00587 info->MaxNameLen = MAX_SYM_NAME; 00588 if (pSymFromAddr(ph, addr, &displacement, info)) { 00589 if (GetModuleFileName((HANDLE)(uintptr_t)pSymGetModuleBase64(ph, addr), libpath, sizeof(libpath))) 00590 fprintf(stderr, "%s", libpath); 00591 fprintf(stderr, "(%s+0x%I64x)", 00592 info->Name, displacement); 00593 } 00594 fprintf(stderr, " [0x%p]", (void *)(VALUE)addr); 00595 memset(&line, 0, sizeof(line)); 00596 line.SizeOfStruct = sizeof(line); 00597 if (pSymGetLineFromAddr64(ph, addr, &tmp, &line)) 00598 fprintf(stderr, " %s:%lu", line.FileName, line.LineNumber); 00599 fprintf(stderr, "\n"); 00600 } 00601 } 00602 00603 ResumeThread(th); 00604 } 00605 CloseHandle(th); 00606 } 00607 pSymCleanup(ph); 00608 } 00609 FreeLibrary(dbghelp); 00610 } 00611 #endif 00612 00613 void 00614 rb_vm_bugreport(void) 00615 { 00616 #ifdef __linux__ 00617 # define PROC_MAPS_NAME "/proc/self/maps" 00618 #endif 00619 #ifdef PROC_MAPS_NAME 00620 enum {other_runtime_info = 1}; 00621 #else 00622 enum {other_runtime_info = 0}; 00623 #endif 00624 const rb_vm_t *const vm = GET_VM(); 00625 00626 #if defined __APPLE__ 00627 fputs("-- Crash Report log information " 00628 "--------------------------------------------\n" 00629 " See Crash Report log file under the one of following:\n" 00630 " * ~/Library/Logs/CrashReporter\n" 00631 " * /Library/Logs/CrashReporter\n" 00632 " * ~/Library/Logs/DiagnosticReports\n" 00633 " * /Library/Logs/DiagnosticReports\n" 00634 " the more detail of.\n" 00635 "\n", 00636 stderr); 00637 #endif 00638 if (vm) { 00639 SDR(); 00640 rb_backtrace_print_as_bugreport(); 00641 fputs("\n", stderr); 00642 } 00643 00644 #if HAVE_BACKTRACE || defined(_WIN32) 00645 fprintf(stderr, "-- C level backtrace information " 00646 "-------------------------------------------\n"); 00647 00648 { 00649 #if HAVE_BACKTRACE 00650 #define MAX_NATIVE_TRACE 1024 00651 static void *trace[MAX_NATIVE_TRACE]; 00652 int n = backtrace(trace, MAX_NATIVE_TRACE); 00653 char **syms = backtrace_symbols(trace, n); 00654 00655 if (syms) { 00656 #ifdef USE_ELF 00657 rb_dump_backtrace_with_lines(n, trace, syms); 00658 #else 00659 int i; 00660 for (i=0; i<n; i++) { 00661 fprintf(stderr, "%s\n", syms[i]); 00662 } 00663 #endif 00664 free(syms); 00665 } 00666 #elif defined(_WIN32) 00667 DWORD tid = GetCurrentThreadId(); 00668 HANDLE th = (HANDLE)_beginthread(dump_thread, 0, &tid); 00669 if (th != (HANDLE)-1) 00670 WaitForSingleObject(th, INFINITE); 00671 #endif 00672 } 00673 00674 fprintf(stderr, "\n"); 00675 #endif /* HAVE_BACKTRACE */ 00676 00677 if (other_runtime_info || vm) { 00678 fprintf(stderr, "-- Other runtime information " 00679 "-----------------------------------------------\n\n"); 00680 } 00681 if (vm) { 00682 int i; 00683 VALUE name; 00684 long len; 00685 const int max_name_length = 1024; 00686 # define LIMITED_NAME_LENGTH(s) \ 00687 (((len = RSTRING_LEN(s)) > max_name_length) ? max_name_length : (int)len) 00688 00689 name = vm->progname; 00690 fprintf(stderr, "* Loaded script: %.*s\n", 00691 LIMITED_NAME_LENGTH(name), RSTRING_PTR(name)); 00692 fprintf(stderr, "\n"); 00693 fprintf(stderr, "* Loaded features:\n\n"); 00694 for (i=0; i<RARRAY_LEN(vm->loaded_features); i++) { 00695 name = RARRAY_PTR(vm->loaded_features)[i]; 00696 if (RB_TYPE_P(name, T_STRING)) { 00697 fprintf(stderr, " %4d %.*s\n", i, 00698 LIMITED_NAME_LENGTH(name), RSTRING_PTR(name)); 00699 } 00700 else { 00701 fprintf(stderr, " %4d #<%s:%p>\n", i, 00702 rb_class2name(CLASS_OF(name)), (void *)name); 00703 } 00704 } 00705 fprintf(stderr, "\n"); 00706 } 00707 00708 { 00709 #ifdef PROC_MAPS_NAME 00710 { 00711 FILE *fp = fopen(PROC_MAPS_NAME, "r"); 00712 if (fp) { 00713 fprintf(stderr, "* Process memory map:\n\n"); 00714 00715 while (!feof(fp)) { 00716 char buff[0x100]; 00717 size_t rn = fread(buff, 1, 0x100, fp); 00718 if (fwrite(buff, 1, rn, stderr) != rn) 00719 break; 00720 } 00721 00722 fclose(fp); 00723 fprintf(stderr, "\n\n"); 00724 } 00725 } 00726 #endif /* __linux__ */ 00727 } 00728 } 00729
1.7.6.1