@@ -6281,3 +6281,106 @@ const void* os::get_saved_assert_context(const void** sigInfo) {
62816281 *sigInfo = nullptr ;
62826282 return nullptr ;
62836283}
6284+
6285+ /*
6286+ * Windows/x64 does not use stack frames the way expected by Java:
6287+ * [1] in most cases, there is no frame pointer. All locals are addressed via RSP
6288+ * [2] in rare cases, when alloca() is used, a frame pointer is used, but this may
6289+ * not be RBP.
6290+ * See http://msdn.microsoft.com/en-us/library/ew5tede7.aspx
6291+ *
6292+ * So it's not possible to print the native stack using the
6293+ * while (...) {... fr = os::get_sender_for_C_frame(&fr); }
6294+ * loop in vmError.cpp. We need to roll our own loop.
6295+ * This implementation works for Windows AArch64 as well.
6296+ */
6297+ bool os::win32::platform_print_native_stack (outputStream* st, const void * context,
6298+ char *buf, int buf_size, address& lastpc)
6299+ {
6300+ CONTEXT ctx;
6301+ if (context != nullptr ) {
6302+ memcpy (&ctx, context, sizeof (ctx));
6303+ } else {
6304+ RtlCaptureContext (&ctx);
6305+ }
6306+
6307+ st->print_cr (" Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)" );
6308+
6309+ DWORD machine_type;
6310+ STACKFRAME stk;
6311+ memset (&stk, 0 , sizeof (stk));
6312+ stk.AddrStack .Mode = AddrModeFlat;
6313+ stk.AddrFrame .Mode = AddrModeFlat;
6314+ stk.AddrPC .Mode = AddrModeFlat;
6315+
6316+ #if defined(_M_AMD64)
6317+ stk.AddrStack .Offset = ctx.Rsp ;
6318+ stk.AddrFrame .Offset = ctx.Rbp ;
6319+ stk.AddrPC .Offset = ctx.Rip ;
6320+ machine_type = IMAGE_FILE_MACHINE_AMD64;
6321+ #elif defined(_M_ARM64)
6322+ stk.AddrStack .Offset = ctx.Sp ;
6323+ stk.AddrFrame .Offset = ctx.Fp ;
6324+ stk.AddrPC .Offset = ctx.Pc ;
6325+ machine_type = IMAGE_FILE_MACHINE_ARM64;
6326+ #else
6327+ #error unknown architecture
6328+ #endif
6329+
6330+ // Ensure we consider dynamically loaded DLLs
6331+ SymbolEngine::refreshModuleList ();
6332+
6333+ int count = 0 ;
6334+ address lastpc_internal = 0 ;
6335+ while (count++ < StackPrintLimit) {
6336+ intptr_t * sp = (intptr_t *)stk.AddrStack .Offset ;
6337+ intptr_t * fp = (intptr_t *)stk.AddrFrame .Offset ; // NOT necessarily the same as ctx.Rbp!
6338+ address pc = (address)stk.AddrPC .Offset ;
6339+
6340+ if (pc != nullptr ) {
6341+ if (count == 2 && lastpc_internal == pc) {
6342+ // Skip it -- StackWalk64() may return the same PC
6343+ // (but different SP) on the first try.
6344+ } else {
6345+ // Don't try to create a frame(sp, fp, pc) -- on WinX64, stk.AddrFrame
6346+ // may not contain what Java expects, and may cause the frame() constructor
6347+ // to crash. Let's just print out the symbolic address.
6348+ frame::print_C_frame (st, buf, buf_size, pc);
6349+ // print source file and line, if available
6350+ char buf[128 ];
6351+ int line_no;
6352+ if (SymbolEngine::get_source_info (pc, buf, sizeof (buf), &line_no)) {
6353+ st->print (" (%s:%d)" , buf, line_no);
6354+ } else {
6355+ st->print (" (no source info available)" );
6356+ }
6357+ st->cr ();
6358+ }
6359+ lastpc_internal = pc;
6360+ }
6361+
6362+ PVOID p = WindowsDbgHelp::symFunctionTableAccess64 (GetCurrentProcess (), stk.AddrPC .Offset );
6363+ if (!p) {
6364+ // StackWalk64() can't handle this PC. Calling StackWalk64 again may cause crash.
6365+ lastpc = lastpc_internal;
6366+ break ;
6367+ }
6368+
6369+ BOOL result = WindowsDbgHelp::stackWalk64 (
6370+ machine_type, // __in DWORD MachineType,
6371+ GetCurrentProcess (), // __in HANDLE hProcess,
6372+ GetCurrentThread (), // __in HANDLE hThread,
6373+ &stk, // __inout LP STACKFRAME64 StackFrame,
6374+ &ctx); // __inout PVOID ContextRecord,
6375+
6376+ if (!result) {
6377+ break ;
6378+ }
6379+ }
6380+ if (count > StackPrintLimit) {
6381+ st->print_cr (" ...<more frames>..." );
6382+ }
6383+ st->cr ();
6384+
6385+ return true ;
6386+ }
0 commit comments