Mercurial > hg > truffle
comparison src/os_cpu/windows_x86/vm/os_windows_x86.cpp @ 12199:38f750491293
8022335: Native stack walk while generating hs_err does not work on Windows x64
Summary: Use WinDbg API StackWalk64()
Reviewed-by: zgu, dholmes
author | iklam |
---|---|
date | Fri, 06 Sep 2013 08:42:42 -0700 |
parents | 980532a806a5 |
children | cefad50507d8 de6a9e811145 |
comparison
equal
deleted
inserted
replaced
12198:baa7927dfbd2 | 12199:38f750491293 |
---|---|
27 #include "classfile/classLoader.hpp" | 27 #include "classfile/classLoader.hpp" |
28 #include "classfile/systemDictionary.hpp" | 28 #include "classfile/systemDictionary.hpp" |
29 #include "classfile/vmSymbols.hpp" | 29 #include "classfile/vmSymbols.hpp" |
30 #include "code/icBuffer.hpp" | 30 #include "code/icBuffer.hpp" |
31 #include "code/vtableStubs.hpp" | 31 #include "code/vtableStubs.hpp" |
32 #include "decoder_windows.hpp" | |
32 #include "interpreter/interpreter.hpp" | 33 #include "interpreter/interpreter.hpp" |
33 #include "jvm_windows.h" | 34 #include "jvm_windows.h" |
34 #include "memory/allocation.inline.hpp" | 35 #include "memory/allocation.inline.hpp" |
35 #include "mutex_windows.inline.hpp" | 36 #include "mutex_windows.inline.hpp" |
36 #include "nativeInst_x86.hpp" | 37 #include "nativeInst_x86.hpp" |
325 | 326 |
326 #endif // AMD64 | 327 #endif // AMD64 |
327 | 328 |
328 cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap; | 329 cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap; |
329 | 330 |
331 #ifdef AMD64 | |
332 /* | |
333 * Windows/x64 does not use stack frames the way expected by Java: | |
334 * [1] in most cases, there is no frame pointer. All locals are addressed via RSP | |
335 * [2] in rare cases, when alloca() is used, a frame pointer is used, but this may | |
336 * not be RBP. | |
337 * See http://msdn.microsoft.com/en-us/library/ew5tede7.aspx | |
338 * | |
339 * So it's not possible to print the native stack using the | |
340 * while (...) {... fr = os::get_sender_for_C_frame(&fr); } | |
341 * loop in vmError.cpp. We need to roll our own loop. | |
342 */ | |
343 bool os::platform_print_native_stack(outputStream* st, void* context, | |
344 char *buf, int buf_size) | |
345 { | |
346 CONTEXT ctx; | |
347 if (context != NULL) { | |
348 memcpy(&ctx, context, sizeof(ctx)); | |
349 } else { | |
350 RtlCaptureContext(&ctx); | |
351 } | |
352 | |
353 st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)"); | |
354 | |
355 STACKFRAME stk; | |
356 memset(&stk, 0, sizeof(stk)); | |
357 stk.AddrStack.Offset = ctx.Rsp; | |
358 stk.AddrStack.Mode = AddrModeFlat; | |
359 stk.AddrFrame.Offset = ctx.Rbp; | |
360 stk.AddrFrame.Mode = AddrModeFlat; | |
361 stk.AddrPC.Offset = ctx.Rip; | |
362 stk.AddrPC.Mode = AddrModeFlat; | |
363 | |
364 int count = 0; | |
365 address lastpc = 0; | |
366 while (count++ < StackPrintLimit) { | |
367 intptr_t* sp = (intptr_t*)stk.AddrStack.Offset; | |
368 intptr_t* fp = (intptr_t*)stk.AddrFrame.Offset; // NOT necessarily the same as ctx.Rbp! | |
369 address pc = (address)stk.AddrPC.Offset; | |
370 | |
371 if (pc != NULL && sp != NULL && fp != NULL) { | |
372 if (count == 2 && lastpc == pc) { | |
373 // Skip it -- StackWalk64() may return the same PC | |
374 // (but different SP) on the first try. | |
375 } else { | |
376 // Don't try to create a frame(sp, fp, pc) -- on WinX64, stk.AddrFrame | |
377 // may not contain what Java expects, and may cause the frame() constructor | |
378 // to crash. Let's just print out the symbolic address. | |
379 frame::print_C_frame(st, buf, buf_size, pc); | |
380 st->cr(); | |
381 } | |
382 lastpc = pc; | |
383 } else { | |
384 break; | |
385 } | |
386 | |
387 PVOID p = WindowsDbgHelp::SymFunctionTableAccess64(GetCurrentProcess(), stk.AddrPC.Offset); | |
388 if (!p) { | |
389 // StackWalk64() can't handle this PC. Calling StackWalk64 again may cause crash. | |
390 break; | |
391 } | |
392 | |
393 BOOL result = WindowsDbgHelp::StackWalk64( | |
394 IMAGE_FILE_MACHINE_AMD64, // __in DWORD MachineType, | |
395 GetCurrentProcess(), // __in HANDLE hProcess, | |
396 GetCurrentThread(), // __in HANDLE hThread, | |
397 &stk, // __inout LP STACKFRAME64 StackFrame, | |
398 &ctx, // __inout PVOID ContextRecord, | |
399 NULL, // __in_opt PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, | |
400 WindowsDbgHelp::pfnSymFunctionTableAccess64(), | |
401 // __in_opt PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, | |
402 WindowsDbgHelp::pfnSymGetModuleBase64(), | |
403 // __in_opt PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, | |
404 NULL); // __in_opt PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress | |
405 | |
406 if (!result) { | |
407 break; | |
408 } | |
409 } | |
410 if (count > StackPrintLimit) { | |
411 st->print_cr("...<more frames>..."); | |
412 } | |
413 st->cr(); | |
414 | |
415 return true; | |
416 } | |
417 #endif // AMD64 | |
418 | |
330 ExtendedPC os::fetch_frame_from_context(void* ucVoid, | 419 ExtendedPC os::fetch_frame_from_context(void* ucVoid, |
331 intptr_t** ret_sp, intptr_t** ret_fp) { | 420 intptr_t** ret_sp, intptr_t** ret_fp) { |
332 | 421 |
333 ExtendedPC epc; | 422 ExtendedPC epc; |
334 CONTEXT* uc = (CONTEXT*)ucVoid; | 423 CONTEXT* uc = (CONTEXT*)ucVoid; |
399 typedef intptr_t* get_fp_func (); | 488 typedef intptr_t* get_fp_func (); |
400 get_fp_func* func = CAST_TO_FN_PTR(get_fp_func*, | 489 get_fp_func* func = CAST_TO_FN_PTR(get_fp_func*, |
401 StubRoutines::x86::get_previous_fp_entry()); | 490 StubRoutines::x86::get_previous_fp_entry()); |
402 if (func == NULL) return frame(); | 491 if (func == NULL) return frame(); |
403 intptr_t* fp = (*func)(); | 492 intptr_t* fp = (*func)(); |
493 if (fp == NULL) { | |
494 return frame(); | |
495 } | |
404 #else | 496 #else |
405 intptr_t* fp = _get_previous_fp(); | 497 intptr_t* fp = _get_previous_fp(); |
406 #endif // AMD64 | 498 #endif // AMD64 |
407 | 499 |
408 frame myframe((intptr_t*)os::current_stack_pointer(), | 500 frame myframe((intptr_t*)os::current_stack_pointer(), |