diff --git a/src/stackFrame.h b/src/stackFrame.h index 6231d661..3f6b02f1 100644 --- a/src/stackFrame.h +++ b/src/stackFrame.h @@ -66,6 +66,7 @@ class StackFrame { bool unwindStub(instruction_t* entry, const char* name, uintptr_t& pc, uintptr_t& sp, uintptr_t& fp); bool unwindCompiled(NMethod* nm, uintptr_t& pc, uintptr_t& sp, uintptr_t& fp); + bool unwindAtomicStub(const void*& pc); void adjustSP(const void* entry, const void* pc, uintptr_t& sp); diff --git a/src/stackFrame_aarch64.cpp b/src/stackFrame_aarch64.cpp index 26ef2766..742b2b4b 100644 --- a/src/stackFrame_aarch64.cpp +++ b/src/stackFrame_aarch64.cpp @@ -151,6 +151,19 @@ bool StackFrame::unwindCompiled(NMethod* nm, uintptr_t& pc, uintptr_t& sp, uintp return true; } +bool StackFrame::unwindAtomicStub(const void*& pc) { + // VM threads may call generated atomic stubs, which are not normally walkable + const void* lr = (const void*)link(); + if (VMStructs::libjvm()->contains(lr)) { + NMethod* nm = CodeHeap::findNMethod(pc); + if (nm != NULL && strncmp(nm->name(), "Stub", 4) == 0) { + pc = lr; + return true; + } + } + return false; +} + void StackFrame::adjustSP(const void* entry, const void* pc, uintptr_t& sp) { instruction_t* ip = (instruction_t*)pc; if (ip > entry && (ip[-1] == 0xa9bf27ff || (ip[-1] == 0xd63f0100 && ip[-2] == 0xa9bf27ff))) { diff --git a/src/stackFrame_arm.cpp b/src/stackFrame_arm.cpp index cb91d0e2..125067c1 100644 --- a/src/stackFrame_arm.cpp +++ b/src/stackFrame_arm.cpp @@ -101,6 +101,11 @@ bool StackFrame::unwindCompiled(NMethod* nm, uintptr_t& pc, uintptr_t& sp, uintp return true; } +bool StackFrame::unwindAtomicStub(const void*& pc) { + // Not needed + return false; +} + void StackFrame::adjustSP(const void* entry, const void* pc, uintptr_t& sp) { // Not needed } diff --git a/src/stackFrame_i386.cpp b/src/stackFrame_i386.cpp index cc0a4dea..8c3538b3 100644 --- a/src/stackFrame_i386.cpp +++ b/src/stackFrame_i386.cpp @@ -116,6 +116,11 @@ bool StackFrame::unwindCompiled(NMethod* nm, uintptr_t& pc, uintptr_t& sp, uintp return false; } +bool StackFrame::unwindAtomicStub(const void*& pc) { + // Not needed + return false; +} + void StackFrame::adjustSP(const void* entry, const void* pc, uintptr_t& sp) { // Not needed } diff --git a/src/stackFrame_loongarch64.cpp b/src/stackFrame_loongarch64.cpp index c9c30933..237eca2c 100644 --- a/src/stackFrame_loongarch64.cpp +++ b/src/stackFrame_loongarch64.cpp @@ -82,6 +82,11 @@ bool StackFrame::unwindCompiled(NMethod* nm, uintptr_t& pc, uintptr_t& sp, uintp return false; } +bool StackFrame::unwindAtomicStub(const void*& pc) { + // Not needed + return false; +} + void StackFrame::adjustSP(const void* entry, const void* pc, uintptr_t& sp) { // Not yet implemented } diff --git a/src/stackFrame_ppc64.cpp b/src/stackFrame_ppc64.cpp index d1163505..a0c7a114 100644 --- a/src/stackFrame_ppc64.cpp +++ b/src/stackFrame_ppc64.cpp @@ -127,6 +127,11 @@ bool StackFrame::unwindCompiled(NMethod* nm, uintptr_t& pc, uintptr_t& sp, uintp return true; } +bool StackFrame::unwindAtomicStub(const void*& pc) { + // Not needed + return false; +} + void StackFrame::adjustSP(const void* entry, const void* pc, uintptr_t& sp) { // Not needed } diff --git a/src/stackFrame_riscv64.cpp b/src/stackFrame_riscv64.cpp index 6cd647e3..edcbbe3f 100644 --- a/src/stackFrame_riscv64.cpp +++ b/src/stackFrame_riscv64.cpp @@ -82,6 +82,11 @@ bool StackFrame::unwindCompiled(NMethod* nm, uintptr_t& pc, uintptr_t& sp, uintp return false; } +bool StackFrame::unwindAtomicStub(const void*& pc) { + // Not needed + return false; +} + void StackFrame::adjustSP(const void* entry, const void* pc, uintptr_t& sp) { // Not yet implemented } diff --git a/src/stackFrame_x64.cpp b/src/stackFrame_x64.cpp index 1991cc65..4e333b98 100644 --- a/src/stackFrame_x64.cpp +++ b/src/stackFrame_x64.cpp @@ -144,6 +144,11 @@ bool StackFrame::unwindCompiled(NMethod* nm, uintptr_t& pc, uintptr_t& sp, uintp return false; } +bool StackFrame::unwindAtomicStub(const void*& pc) { + // Not needed + return false; +} + void StackFrame::adjustSP(const void* entry, const void* pc, uintptr_t& sp) { // Not needed } diff --git a/src/stackWalker.cpp b/src/stackWalker.cpp index 8a27ca8f..431759b7 100644 --- a/src/stackWalker.cpp +++ b/src/stackWalker.cpp @@ -58,12 +58,12 @@ int StackWalker::walkFP(void* ucontext, const void** callchain, int max_depth, S uintptr_t sp; uintptr_t bottom = (uintptr_t)&sp + MAX_WALK_SIZE; + StackFrame frame(ucontext); if (ucontext == NULL) { pc = __builtin_return_address(0); fp = (uintptr_t)__builtin_frame_address(1); sp = (uintptr_t)__builtin_frame_address(0); } else { - StackFrame frame(ucontext); pc = (const void*)frame.pc(); fp = frame.fp(); sp = frame.sp(); @@ -73,7 +73,7 @@ int StackWalker::walkFP(void* ucontext, const void** callchain, int max_depth, S // Walk until the bottom of the stack or until the first Java frame while (depth < max_depth) { - if (CodeHeap::contains(pc)) { + if (CodeHeap::contains(pc) && !(depth == 0 && frame.unwindAtomicStub(pc))) { java_ctx->set(pc, sp, fp); break; } @@ -124,7 +124,7 @@ int StackWalker::walkDwarf(void* ucontext, const void** callchain, int max_depth // Walk until the bottom of the stack or until the first Java frame while (depth < max_depth) { - if (CodeHeap::contains(pc)) { + if (CodeHeap::contains(pc) && !(depth == 0 && frame.unwindAtomicStub(pc))) { const void* page_start = (const void*)((uintptr_t)pc & ~0xfffUL); frame.adjustSP(page_start, pc, sp); java_ctx->set(pc, sp, fp);