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(),