Skip to content

Commit 3f3d63d

Browse files
committed
8294211: Zero: Decode arch-specific error context if possible
Reviewed-by: stuefe, luhenry
1 parent f502ab8 commit 3f3d63d

File tree

4 files changed

+147
-26
lines changed

4 files changed

+147
-26
lines changed

src/hotspot/cpu/zero/globals_zero.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,11 @@ define_pd_global(bool, CompactStrings, true);
8383
"Use fast method entry code for empty methods") \
8484
\
8585
product(bool, UseFastAccessorMethods, true, \
86-
"Use fast method entry code for accessor methods")
86+
"Use fast method entry code for accessor methods") \
87+
\
88+
product(bool, DecodeErrorContext, false, DIAGNOSTIC, \
89+
"Try to decode the architecture-specific context for better " \
90+
"diagnostics")
8791

8892
// end of ARCH_FLAGS
8993

src/hotspot/cpu/zero/vm_version_zero.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,17 @@ void VM_Version::initialize() {
116116
FLAG_SET_DEFAULT(UseVectorizedMismatchIntrinsic, false);
117117
}
118118

119+
// Enable error context decoding on known platforms
120+
#if defined(IA32) || defined(AMD64) || defined(ARM) || \
121+
defined(AARCH64) || defined(PPC) || defined(RISCV) || \
122+
defined(S390)
123+
if (FLAG_IS_DEFAULT(DecodeErrorContext)) {
124+
FLAG_SET_DEFAULT(DecodeErrorContext, true);
125+
}
126+
#else
127+
UNSUPPORTED_OPTION(DecodeErrorContext);
128+
#endif
129+
119130
// Not implemented
120131
UNSUPPORTED_OPTION(UseCompiler);
121132
#ifdef ASSERT

src/hotspot/os/posix/signals_posix.cpp

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -602,12 +602,6 @@ int JVM_HANDLE_XXX_SIGNAL(int sig, siginfo_t* info,
602602
if (uc != NULL) {
603603
if (S390_ONLY(sig == SIGILL || sig == SIGFPE) NOT_S390(false)) {
604604
pc = (address)info->si_addr;
605-
} else if (ZERO_ONLY(true) NOT_ZERO(false)) {
606-
// Non-arch-specific Zero code does not really know the pc.
607-
// This can be alleviated by making arch-specific os::Posix::ucontext_get_pc
608-
// available for Zero for known architectures. But for generic Zero
609-
// code, it would still remain unknown.
610-
pc = NULL;
611605
} else {
612606
pc = os::Posix::ucontext_get_pc(uc);
613607
}
@@ -664,12 +658,7 @@ int JVM_HANDLE_XXX_SIGNAL(int sig, siginfo_t* info,
664658

665659
// Invoke fatal error handling.
666660
if (!signal_was_handled && abort_if_unrecognized) {
667-
// For Zero, we ignore the crash context, because:
668-
// a) The crash would be in C++ interpreter code, so context is not really relevant;
669-
// b) Generic Zero code would not be able to parse it, so when generic error
670-
// reporting code asks e.g. about frames on stack, Zero would experience
671-
// a secondary ShouldNotCallThis() crash.
672-
VMError::report_and_die(t, sig, pc, info, NOT_ZERO(ucVoid) ZERO_ONLY(NULL));
661+
VMError::report_and_die(t, sig, pc, info, ucVoid);
673662
// VMError should not return.
674663
ShouldNotReachHere();
675664
}

src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp

Lines changed: 130 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -87,24 +87,130 @@ char* os::non_memory_address_word() {
8787
}
8888

8989
address os::Posix::ucontext_get_pc(const ucontext_t* uc) {
90-
ShouldNotCallThis();
91-
return NULL; // silence compile warnings
90+
if (DecodeErrorContext) {
91+
#if defined(IA32)
92+
return (address)uc->uc_mcontext.gregs[REG_EIP];
93+
#elif defined(AMD64)
94+
return (address)uc->uc_mcontext.gregs[REG_RIP];
95+
#elif defined(ARM)
96+
return (address)uc->uc_mcontext.arm_pc;
97+
#elif defined(AARCH64)
98+
return (address)uc->uc_mcontext.pc;
99+
#elif defined(PPC)
100+
return (address)uc->uc_mcontext.regs->nip;
101+
#elif defined(RISCV)
102+
return (address)uc->uc_mcontext.__gregs[REG_PC];
103+
#elif defined(S390)
104+
return (address)uc->uc_mcontext.psw.addr;
105+
#else
106+
// Non-arch-specific Zero code does not really know the PC.
107+
// If possible, add the arch-specific definition in this method.
108+
fatal("Cannot handle ucontext_get_pc");
109+
#endif
110+
}
111+
112+
// Answer the default and hope for the best
113+
return nullptr;
92114
}
93115

94-
void os::Posix::ucontext_set_pc(ucontext_t * uc, address pc) {
116+
void os::Posix::ucontext_set_pc(ucontext_t* uc, address pc) {
95117
ShouldNotCallThis();
96118
}
97119

120+
intptr_t* os::Linux::ucontext_get_sp(const ucontext_t* uc) {
121+
if (DecodeErrorContext) {
122+
#if defined(IA32)
123+
return (intptr_t*)uc->uc_mcontext.gregs[REG_UESP];
124+
#elif defined(AMD64)
125+
return (intptr_t*)uc->uc_mcontext.gregs[REG_RSP];
126+
#elif defined(ARM)
127+
return (intptr_t*)uc->uc_mcontext.arm_sp;
128+
#elif defined(AARCH64)
129+
return (intptr_t*)uc->uc_mcontext.sp;
130+
#elif defined(PPC)
131+
return (intptr_t*)uc->uc_mcontext.regs->gpr[1/*REG_SP*/];
132+
#elif defined(RISCV)
133+
return (intptr_t*)uc->uc_mcontext.__gregs[REG_SP];
134+
#elif defined(S390)
135+
return (intptr_t*)uc->uc_mcontext.gregs[15/*REG_SP*/];
136+
#else
137+
// Non-arch-specific Zero code does not really know the SP.
138+
// If possible, add the arch-specific definition in this method.
139+
fatal("Cannot handle ucontext_get_sp");
140+
#endif
141+
}
142+
143+
// Answer the default and hope for the best
144+
return nullptr;
145+
}
146+
147+
intptr_t* os::Linux::ucontext_get_fp(const ucontext_t* uc) {
148+
if (DecodeErrorContext) {
149+
#if defined(IA32)
150+
return (intptr_t*)uc->uc_mcontext.gregs[REG_EBP];
151+
#elif defined(AMD64)
152+
return (intptr_t*)uc->uc_mcontext.gregs[REG_RBP];
153+
#elif defined(ARM)
154+
return (intptr_t*)uc->uc_mcontext.arm_fp;
155+
#elif defined(AARCH64)
156+
return (intptr_t*)uc->uc_mcontext.regs[29 /* REG_FP */];
157+
#elif defined(PPC)
158+
return nullptr;
159+
#elif defined(RISCV)
160+
return (intptr_t*)uc->uc_mcontext.__gregs[8 /* REG_FP */];
161+
#elif defined(S390)
162+
return nullptr;
163+
#else
164+
// Non-arch-specific Zero code does not really know the FP.
165+
// If possible, add the arch-specific definition in this method.
166+
fatal("Cannot handle ucontext_get_fp");
167+
#endif
168+
}
169+
170+
// Answer the default and hope for the best
171+
return nullptr;
172+
}
173+
98174
address os::fetch_frame_from_context(const void* ucVoid,
99175
intptr_t** ret_sp,
100176
intptr_t** ret_fp) {
101-
ShouldNotCallThis();
102-
return NULL; // silence compile warnings
177+
address epc;
178+
const ucontext_t* uc = (const ucontext_t*)ucVoid;
179+
180+
if (uc != NULL) {
181+
epc = os::Posix::ucontext_get_pc(uc);
182+
if (ret_sp) {
183+
*ret_sp = (intptr_t*) os::Linux::ucontext_get_sp(uc);
184+
}
185+
if (ret_fp) {
186+
*ret_fp = (intptr_t*) os::Linux::ucontext_get_fp(uc);
187+
}
188+
} else {
189+
epc = NULL;
190+
if (ret_sp) {
191+
*ret_sp = nullptr;
192+
}
193+
if (ret_fp) {
194+
*ret_fp = nullptr;
195+
}
196+
}
197+
198+
return epc;
103199
}
104200

105201
frame os::fetch_frame_from_context(const void* ucVoid) {
106-
ShouldNotCallThis();
107-
return frame(NULL, NULL); // silence compile warnings
202+
// This code is only called from error handler to get PC and SP.
203+
// We don't have the ready ZeroFrame* at this point, so fake the
204+
// frame with bare minimum.
205+
if (ucVoid != NULL) {
206+
const ucontext_t* uc = (const ucontext_t*)ucVoid;
207+
frame dummy = frame();
208+
dummy.set_pc(os::Posix::ucontext_get_pc(uc));
209+
dummy.set_sp((intptr_t*)os::Linux::ucontext_get_sp(uc));
210+
return dummy;
211+
} else {
212+
return frame(nullptr, nullptr);
213+
}
108214
}
109215

110216
bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
@@ -288,16 +394,27 @@ size_t os::current_stack_size() {
288394
/////////////////////////////////////////////////////////////////////////////
289395
// helper functions for fatal error handler
290396

291-
void os::print_context(outputStream* st, const void* context) {
292-
ShouldNotCallThis();
397+
void os::print_context(outputStream* st, const void* ucVoid) {
398+
st->print_cr("No context information.");
293399
}
294400

295-
void os::print_tos_pc(outputStream *st, const void *context) {
296-
ShouldNotCallThis();
401+
void os::print_tos_pc(outputStream *st, const void* ucVoid) {
402+
const ucontext_t* uc = (const ucontext_t*)ucVoid;
403+
404+
address sp = (address)os::Linux::ucontext_get_sp(uc);
405+
print_tos(st, sp);
406+
st->cr();
407+
408+
// Note: it may be unsafe to inspect memory near pc. For example, pc may
409+
// point to garbage if entry point in an nmethod is corrupted. Leave
410+
// this at the end, and hope for the best.
411+
address pc = os::Posix::ucontext_get_pc(uc);
412+
print_instructions(st, pc, sizeof(char));
413+
st->cr();
297414
}
298415

299-
void os::print_register_info(outputStream *st, const void *context) {
300-
ShouldNotCallThis();
416+
void os::print_register_info(outputStream *st, const void* ucVoid) {
417+
st->print_cr("No register info.");
301418
}
302419

303420
/////////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)