From bd79db3930f192f6742e29a63a6d1c3bc3dd3385 Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Wed, 14 Jun 2023 08:28:39 +0000 Subject: [PATCH] 8309613: [Windows] hs_err files sometimes miss information about the code containing the error Reviewed-by: dholmes, stuefe --- src/hotspot/os/aix/os_aix.hpp | 2 +- src/hotspot/os/windows/os_windows.hpp | 2 +- src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp | 2 +- .../os_cpu/aix_ppc/os_aix_ppc.inline.hpp | 4 +- .../os_cpu/windows_x86/os_windows_x86.cpp | 9 ++-- .../windows_x86/os_windows_x86.inline.hpp | 4 +- src/hotspot/share/runtime/os.hpp | 2 +- src/hotspot/share/runtime/os.inline.hpp | 2 +- src/hotspot/share/utilities/debug.cpp | 3 +- src/hotspot/share/utilities/vmError.cpp | 41 ++++++++++++++++++- 10 files changed, 56 insertions(+), 15 deletions(-) diff --git a/src/hotspot/os/aix/os_aix.hpp b/src/hotspot/os/aix/os_aix.hpp index ecd181f8989..9756734efd2 100644 --- a/src/hotspot/os/aix/os_aix.hpp +++ b/src/hotspot/os/aix/os_aix.hpp @@ -172,7 +172,7 @@ class os::Aix { // Returns true if ok, false if error. static bool get_meminfo(meminfo_t* pmi); - static bool platform_print_native_stack(outputStream* st, const void* context, char *buf, int buf_size); + static bool platform_print_native_stack(outputStream* st, const void* context, char *buf, int buf_size, address& lastpc); static void* resolve_function_descriptor(void* p); }; diff --git a/src/hotspot/os/windows/os_windows.hpp b/src/hotspot/os/windows/os_windows.hpp index 937843593ff..2f90da71554 100644 --- a/src/hotspot/os/windows/os_windows.hpp +++ b/src/hotspot/os/windows/os_windows.hpp @@ -48,7 +48,7 @@ class os::win32 { static void print_uptime_info(outputStream* st); static bool platform_print_native_stack(outputStream* st, const void* context, - char *buf, int buf_size); + char *buf, int buf_size, address& lastpc); static bool register_code_area(char *low, char *high); diff --git a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp index 4b24426b199..3882ed67703 100644 --- a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp +++ b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp @@ -516,7 +516,7 @@ int os::extra_bang_size_in_bytes() { return 0; } -bool os::Aix::platform_print_native_stack(outputStream* st, const void* context, char *buf, int buf_size) { +bool os::Aix::platform_print_native_stack(outputStream* st, const void* context, char *buf, int buf_size, address& lastpc) { AixNativeCallstack::print_callstack_for_context(st, (const ucontext_t*)context, true, buf, (size_t) buf_size); return true; } diff --git a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.inline.hpp b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.inline.hpp index c20654bbdc1..43dd7a92dc1 100644 --- a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.inline.hpp +++ b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.inline.hpp @@ -30,8 +30,8 @@ #define HAVE_PLATFORM_PRINT_NATIVE_STACK 1 inline bool os::platform_print_native_stack(outputStream* st, const void* context, - char *buf, int buf_size) { - return os::Aix::platform_print_native_stack(st, context, buf, buf_size); + char *buf, int buf_size, address& lastpc) { + return os::Aix::platform_print_native_stack(st, context, buf, buf_size, lastpc); } #define HAVE_FUNCTION_DESCRIPTORS 1 diff --git a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp index 1bb742f59ea..73b8a46126d 100644 --- a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp +++ b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp @@ -224,7 +224,7 @@ bool os::win32::register_code_area(char *low, char *high) { * loop in vmError.cpp. We need to roll our own loop. */ bool os::win32::platform_print_native_stack(outputStream* st, const void* context, - char *buf, int buf_size) + char *buf, int buf_size, address& lastpc) { CONTEXT ctx; if (context != nullptr) { @@ -245,14 +245,14 @@ bool os::win32::platform_print_native_stack(outputStream* st, const void* contex stk.AddrPC.Mode = AddrModeFlat; int count = 0; - address lastpc = 0; + address lastpc_internal = 0; while (count++ < StackPrintLimit) { intptr_t* sp = (intptr_t*)stk.AddrStack.Offset; intptr_t* fp = (intptr_t*)stk.AddrFrame.Offset; // NOT necessarily the same as ctx.Rbp! address pc = (address)stk.AddrPC.Offset; if (pc != nullptr) { - if (count == 2 && lastpc == pc) { + if (count == 2 && lastpc_internal == pc) { // Skip it -- StackWalk64() may return the same PC // (but different SP) on the first try. } else { @@ -268,12 +268,13 @@ bool os::win32::platform_print_native_stack(outputStream* st, const void* contex } st->cr(); } - lastpc = pc; + lastpc_internal = pc; } PVOID p = WindowsDbgHelp::symFunctionTableAccess64(GetCurrentProcess(), stk.AddrPC.Offset); if (!p) { // StackWalk64() can't handle this PC. Calling StackWalk64 again may cause crash. + lastpc = lastpc_internal; break; } diff --git a/src/hotspot/os_cpu/windows_x86/os_windows_x86.inline.hpp b/src/hotspot/os_cpu/windows_x86/os_windows_x86.inline.hpp index f69cbecbb70..f7622611da7 100644 --- a/src/hotspot/os_cpu/windows_x86/os_windows_x86.inline.hpp +++ b/src/hotspot/os_cpu/windows_x86/os_windows_x86.inline.hpp @@ -31,8 +31,8 @@ #ifdef AMD64 #define HAVE_PLATFORM_PRINT_NATIVE_STACK 1 inline bool os::platform_print_native_stack(outputStream* st, const void* context, - char *buf, int buf_size) { - return os::win32::platform_print_native_stack(st, context, buf, buf_size); + char *buf, int buf_size, address& lastpc) { + return os::win32::platform_print_native_stack(st, context, buf, buf_size, lastpc); } #endif diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index 6a275beb18e..49c56b3375e 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -1008,7 +1008,7 @@ class os: AllStatic { public: inline static bool platform_print_native_stack(outputStream* st, const void* context, - char *buf, int buf_size); + char *buf, int buf_size, address& lastpc); // debugging support (mostly used by debug.cpp but also fatal error handler) static bool find(address pc, outputStream* st = tty); // OS specific function to make sense out of an address diff --git a/src/hotspot/share/runtime/os.inline.hpp b/src/hotspot/share/runtime/os.inline.hpp index 6c7569643c2..d5cd1b92230 100644 --- a/src/hotspot/share/runtime/os.inline.hpp +++ b/src/hotspot/share/runtime/os.inline.hpp @@ -35,7 +35,7 @@ #ifndef HAVE_PLATFORM_PRINT_NATIVE_STACK inline bool os::platform_print_native_stack(outputStream* st, const void* context, - char *buf, int buf_size) { + char *buf, int buf_size, address& lastpc) { return false; } #endif diff --git a/src/hotspot/share/utilities/debug.cpp b/src/hotspot/share/utilities/debug.cpp index 4fd3b48456e..f0047396512 100644 --- a/src/hotspot/share/utilities/debug.cpp +++ b/src/hotspot/share/utilities/debug.cpp @@ -654,7 +654,8 @@ extern "C" JNIEXPORT void pns(void* sp, void* fp, void* pc) { // print native st extern "C" JNIEXPORT void pns2() { // print native stack Command c("pns2"); static char buf[O_BUFLEN]; - if (os::platform_print_native_stack(tty, nullptr, buf, sizeof(buf))) { + address lastpc = nullptr; + if (os::platform_print_native_stack(tty, nullptr, buf, sizeof(buf), lastpc)) { // We have printed the native stack in platform-specific code, // so nothing else to do in this case. } else { diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index c8d0b93744e..2bcc1ddc221 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -387,6 +387,27 @@ static bool print_code(outputStream* st, Thread* thread, address pc, bool is_cra return false; } +// Like above, but only try to figure out a short name. Return nullptr if not found. +static const char* find_code_name(address pc) { + if (Interpreter::contains(pc)) { + InterpreterCodelet* codelet = Interpreter::codelet_containing(pc); + if (codelet != nullptr) { + return codelet->description(); + } + } else { + StubCodeDesc* desc = StubCodeDesc::desc_for(pc); + if (desc != nullptr) { + return desc->name(); + } else { + CodeBlob* cb = CodeCache::find_blob(pc); + if (cb != nullptr) { + return cb->name(); + } + } + } + return nullptr; +} + /** * Gets the caller frame of `fr`. * @@ -675,6 +696,10 @@ void VMError::report(outputStream* st, bool _verbose) { // don't allocate large buffer on stack static char buf[O_BUFLEN]; + // Native stack trace may get stuck. We try to handle the last pc if it + // belongs to VM generated code. + address lastpc = nullptr; + BEGIN STEP("printing fatal error message") @@ -963,9 +988,16 @@ void VMError::report(outputStream* st, bool _verbose) { st->cr(); STEP_IF("printing native stack (with source info)", _verbose) - if (os::platform_print_native_stack(st, _context, buf, sizeof(buf))) { + if (os::platform_print_native_stack(st, _context, buf, sizeof(buf), lastpc)) { // We have printed the native stack in platform-specific code // Windows/x64 needs special handling. + // Stack walking may get stuck. Try to find the calling code. + if (lastpc != nullptr) { + const char* name = find_code_name(lastpc); + if (name != nullptr) { + st->print_cr("The last pc belongs to %s (printed below).", name); + } + } } else { frame fr = _context ? os::fetch_frame_from_context(_context) : os::current_frame(); @@ -1070,6 +1102,13 @@ void VMError::report(outputStream* st, bool _verbose) { // value outside the range. int limit = MIN2(ErrorLogPrintCodeLimit, printed_capacity); if (limit > 0) { + // Check if a pc was found by native stack trace above. + if (lastpc != nullptr) { + if (print_code(st, _thread, lastpc, true, printed, printed_capacity)) { + printed_len++; + } + } + // Scan the native stack if (!_print_native_stack_used) { // Only try to print code of the crashing frame since