Skip to content

Commit 4227136

Browse files
committed
runtime/jni/nativeStack/TestNativeStack.java fails on Windows AArch64 (openjdk#15)
1 parent a9c93f8 commit 4227136

File tree

3 files changed

+110
-92
lines changed

3 files changed

+110
-92
lines changed

src/hotspot/os/windows/os_windows.cpp

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
}

src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.inline.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,17 @@
2626
#define OS_CPU_WINDOWS_AARCH64_OS_WINDOWS_AARCH64_INLINE_HPP
2727

2828
#include "runtime/os.hpp"
29+
#include "os_windows.hpp"
2930

3031
inline bool os::register_code_area(char *low, char *high) {
3132
// Using Vectored Exception Handling
3233
return true;
3334
}
3435

36+
#define HAVE_PLATFORM_PRINT_NATIVE_STACK 1
37+
inline bool os::platform_print_native_stack(outputStream* st, const void* context,
38+
char *buf, int buf_size, address& lastpc) {
39+
return os::win32::platform_print_native_stack(st, context, buf, buf_size, lastpc);
40+
}
41+
3542
#endif // OS_CPU_WINDOWS_AARCH64_OS_WINDOWS_AARCH64_INLINE_HPP

src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp

Lines changed: 0 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -197,98 +197,6 @@ bool handle_FLT_exception(struct _EXCEPTION_POINTERS* exceptionInfo) {
197197
}
198198
#endif
199199

200-
#ifdef HAVE_PLATFORM_PRINT_NATIVE_STACK
201-
/*
202-
* Windows/x64 does not use stack frames the way expected by Java:
203-
* [1] in most cases, there is no frame pointer. All locals are addressed via RSP
204-
* [2] in rare cases, when alloca() is used, a frame pointer is used, but this may
205-
* not be RBP.
206-
* See http://msdn.microsoft.com/en-us/library/ew5tede7.aspx
207-
*
208-
* So it's not possible to print the native stack using the
209-
* while (...) {... fr = os::get_sender_for_C_frame(&fr); }
210-
* loop in vmError.cpp. We need to roll our own loop.
211-
*/
212-
bool os::win32::platform_print_native_stack(outputStream* st, const void* context,
213-
char *buf, int buf_size, address& lastpc)
214-
{
215-
CONTEXT ctx;
216-
if (context != nullptr) {
217-
memcpy(&ctx, context, sizeof(ctx));
218-
} else {
219-
RtlCaptureContext(&ctx);
220-
}
221-
222-
st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)");
223-
224-
STACKFRAME stk;
225-
memset(&stk, 0, sizeof(stk));
226-
stk.AddrStack.Offset = ctx.Rsp;
227-
stk.AddrStack.Mode = AddrModeFlat;
228-
stk.AddrFrame.Offset = ctx.Rbp;
229-
stk.AddrFrame.Mode = AddrModeFlat;
230-
stk.AddrPC.Offset = ctx.Rip;
231-
stk.AddrPC.Mode = AddrModeFlat;
232-
233-
// Ensure we consider dynamically loaded dll's
234-
SymbolEngine::refreshModuleList();
235-
236-
int count = 0;
237-
address lastpc_internal = 0;
238-
while (count++ < StackPrintLimit) {
239-
intptr_t* sp = (intptr_t*)stk.AddrStack.Offset;
240-
intptr_t* fp = (intptr_t*)stk.AddrFrame.Offset; // NOT necessarily the same as ctx.Rbp!
241-
address pc = (address)stk.AddrPC.Offset;
242-
243-
if (pc != nullptr) {
244-
if (count == 2 && lastpc_internal == pc) {
245-
// Skip it -- StackWalk64() may return the same PC
246-
// (but different SP) on the first try.
247-
} else {
248-
// Don't try to create a frame(sp, fp, pc) -- on WinX64, stk.AddrFrame
249-
// may not contain what Java expects, and may cause the frame() constructor
250-
// to crash. Let's just print out the symbolic address.
251-
frame::print_C_frame(st, buf, buf_size, pc);
252-
// print source file and line, if available
253-
char buf[128];
254-
int line_no;
255-
if (SymbolEngine::get_source_info(pc, buf, sizeof(buf), &line_no)) {
256-
st->print(" (%s:%d)", buf, line_no);
257-
} else {
258-
st->print(" (no source info available)");
259-
}
260-
st->cr();
261-
}
262-
lastpc_internal = pc;
263-
}
264-
265-
PVOID p = WindowsDbgHelp::symFunctionTableAccess64(GetCurrentProcess(), stk.AddrPC.Offset);
266-
if (!p) {
267-
// StackWalk64() can't handle this PC. Calling StackWalk64 again may cause crash.
268-
lastpc = lastpc_internal;
269-
break;
270-
}
271-
272-
BOOL result = WindowsDbgHelp::stackWalk64(
273-
IMAGE_FILE_MACHINE_AMD64, // __in DWORD MachineType,
274-
GetCurrentProcess(), // __in HANDLE hProcess,
275-
GetCurrentThread(), // __in HANDLE hThread,
276-
&stk, // __inout LP STACKFRAME64 StackFrame,
277-
&ctx); // __inout PVOID ContextRecord,
278-
279-
if (!result) {
280-
break;
281-
}
282-
}
283-
if (count > StackPrintLimit) {
284-
st->print_cr("...<more frames>...");
285-
}
286-
st->cr();
287-
288-
return true;
289-
}
290-
#endif // HAVE_PLATFORM_PRINT_NATIVE_STACK
291-
292200
address os::fetch_frame_from_context(const void* ucVoid,
293201
intptr_t** ret_sp, intptr_t** ret_fp) {
294202

0 commit comments

Comments
 (0)