8343343: Misc crash dump improvements on more platforms after JDK-8294160

Co-authored-by: Boris Ulasevich <bulasevich@openjdk.org>
Reviewed-by: mbaesken, jkern, dlong
This commit is contained in:
Martin Doerr 2024-11-06 19:36:20 +00:00
parent d20ccd1aef
commit e33dc13567
14 changed files with 68 additions and 213 deletions

View File

@ -123,13 +123,13 @@ frame os::fetch_frame_from_context(const void* ucVoid) {
intptr_t* sp;
intptr_t* fp;
address epc = fetch_frame_from_context(ucVoid, &sp, &fp);
// Avoid crash during crash if pc broken.
if (epc) {
frame fr(sp, epc, frame::kind::unknown);
return fr;
if (epc == nullptr || !is_readable_pointer(epc)) {
// Try to recover from calling into bad memory
// Assume new frame has not been set up, the same as
// compiled frame stack bang
return fetch_compiled_frame_from_context(ucVoid);
}
frame fr(sp);
return fr;
return frame(sp, epc, frame::kind::unknown);
}
frame os::fetch_compiled_frame_from_context(const void* ucVoid) {
@ -447,23 +447,6 @@ void os::print_context(outputStream *st, const void *context) {
st->cr();
}
void os::print_tos_pc(outputStream *st, const void *context) {
if (context == nullptr) return;
const ucontext_t* uc = (const ucontext_t*)context;
address sp = (address)os::Aix::ucontext_get_sp(uc);
print_tos(st, sp);
st->cr();
// Note: it may be unsafe to inspect memory near pc. For example, pc may
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::Posix::ucontext_get_pc(uc);
print_instructions(st, pc);
st->cr();
}
void os::print_register_info(outputStream *st, const void *context, int& continuation) {
const int register_count = 32 /* r0-r32 */ + 3 /* pc, lr, sp */;
int n = continuation;

View File

@ -159,6 +159,12 @@ frame os::fetch_frame_from_context(const void* ucVoid) {
intptr_t* sp;
intptr_t* fp;
address epc = fetch_frame_from_context(ucVoid, &sp, &fp);
if (!is_readable_pointer(epc)) {
// Try to recover from calling into bad memory
// Assume new frame has not been set up, the same as
// compiled frame stack bang
return fetch_compiled_frame_from_context(ucVoid);
}
return frame(sp, fp, epc);
}
@ -442,23 +448,6 @@ void os::print_context(outputStream *st, const void *context) {
st->cr();
}
void os::print_tos_pc(outputStream *st, const void *context) {
if (context == nullptr) return;
const ucontext_t* uc = (const ucontext_t*)context;
address sp = (address)os::Bsd::ucontext_get_sp(uc);
print_tos(st, sp);
st->cr();
// Note: it may be unsafe to inspect memory near pc. For example, pc may
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::Posix::ucontext_get_pc(uc);
print_instructions(st, pc);
st->cr();
}
void os::print_register_info(outputStream *st, const void *context, int& continuation) {
const int register_count = 29 /* x0-x28 */ + 3 /* fp, lr, sp */;
int n = continuation;

View File

@ -333,6 +333,12 @@ frame os::fetch_frame_from_context(const void* ucVoid) {
intptr_t* sp;
intptr_t* fp;
address epc = fetch_frame_from_context(ucVoid, &sp, &fp);
if (!is_readable_pointer(epc)) {
// Try to recover from calling into bad memory
// Assume new frame has not been set up, the same as
// compiled frame stack bang
return fetch_compiled_frame_from_context(ucVoid);
}
return frame(sp, fp, epc);
}
@ -836,23 +842,6 @@ void os::print_context(outputStream *st, const void *context) {
st->cr();
}
void os::print_tos_pc(outputStream *st, const void *context) {
if (context == nullptr) return;
const ucontext_t* uc = (const ucontext_t*)context;
address sp = (address)os::Bsd::ucontext_get_sp(uc);
print_tos(st, sp);
st->cr();
// Note: it may be unsafe to inspect memory near pc. For example, pc may
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::Posix::ucontext_get_pc(uc);
print_instructions(st, pc);
st->cr();
}
void os::print_register_info(outputStream *st, const void *context, int& continuation) {
const int register_count = AMD64_ONLY(16) NOT_AMD64(8);
int n = continuation;

View File

@ -228,10 +228,6 @@ void os::print_context(outputStream* st, const void* context) {
ShouldNotCallThis();
}
void os::print_tos_pc(outputStream *st, const void *context) {
ShouldNotCallThis();
}
void os::print_register_info(outputStream *st, const void *context, int& continuation) {
ShouldNotCallThis();
}

View File

@ -354,23 +354,6 @@ void os::print_context(outputStream *st, const void *context) {
st->cr();
}
void os::print_tos_pc(outputStream *st, const void *context) {
if (context == nullptr) return;
const ucontext_t* uc = (const ucontext_t*)context;
address sp = (address)os::Linux::ucontext_get_sp(uc);
print_tos(st, sp);
st->cr();
// Note: it may be unsafe to inspect memory near pc. For example, pc may
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::fetch_frame_from_context(uc).pc();
print_instructions(st, pc);
st->cr();
}
void os::print_register_info(outputStream *st, const void *context, int& continuation) {
const int register_count = 32 /* r0-r31 */;
int n = continuation;

View File

@ -188,9 +188,27 @@ frame os::fetch_frame_from_context(const void* ucVoid) {
intptr_t* sp;
intptr_t* fp;
address epc = fetch_frame_from_context(ucVoid, &sp, &fp);
if (!is_readable_pointer(epc)) {
// Try to recover from calling into bad memory
// Assume new frame has not been set up, the same as
// compiled frame stack bang
return fetch_compiled_frame_from_context(ucVoid);
}
return frame(sp, fp, epc);
}
frame os::fetch_compiled_frame_from_context(const void* ucVoid) {
const ucontext_t* uc = (const ucontext_t*)ucVoid;
// In compiled code, the stack banging is performed before LR
// has been saved in the frame. LR is live, and SP and FP
// belong to the caller.
intptr_t* fp = os::Linux::ucontext_get_fp(uc);
intptr_t* sp = os::Linux::ucontext_get_sp(uc);
address pc = (address)(uc->uc_mcontext.arm_lr
- NativeInstruction::instruction_size);
return frame(sp, fp, pc);
}
frame os::get_sender_for_C_frame(frame* fr) {
#ifdef __thumb__
// We can't reliably get anything from a thumb C frame.
@ -474,23 +492,6 @@ void os::print_context(outputStream *st, const void *context) {
st->cr();
}
void os::print_tos_pc(outputStream *st, const void *context) {
if (context == nullptr) return;
const ucontext_t* uc = (const ucontext_t*)context;
address sp = (address)os::Linux::ucontext_get_sp(uc);
print_tos(st, sp);
st->cr();
// Note: it may be unsafe to inspect memory near pc. For example, pc may
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::Posix::ucontext_get_pc(uc);
print_instructions(st, pc);
st->cr();
}
void os::print_register_info(outputStream *st, const void *context, int& continuation) {
const int register_count = ARM_REGS_IN_CONTEXT;
int n = continuation;

View File

@ -155,6 +155,12 @@ frame os::fetch_frame_from_context(const void* ucVoid) {
intptr_t* sp;
intptr_t* fp;
address epc = fetch_frame_from_context(ucVoid, &sp, &fp);
if (!is_readable_pointer(epc)) {
// Try to recover from calling into bad memory
// Assume new frame has not been set up, the same as
// compiled frame stack bang
return fetch_compiled_frame_from_context(ucVoid);
}
return frame(sp, epc, frame::kind::unknown);
}
@ -461,23 +467,6 @@ void os::print_context(outputStream *st, const void *context) {
st->cr();
}
void os::print_tos_pc(outputStream *st, const void *context) {
if (context == nullptr) return;
const ucontext_t* uc = (const ucontext_t*)context;
address sp = (address)os::Linux::ucontext_get_sp(uc);
print_tos(st, sp);
st->cr();
// Note: it may be unsafe to inspect memory near pc. For example, pc may
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::Posix::ucontext_get_pc(uc);
print_instructions(st, pc);
st->cr();
}
void os::print_register_info(outputStream *st, const void *context, int& continuation) {
const int register_count = 32 /* r0-r32 */ + 3 /* pc, lr, ctr */;
int n = continuation;

View File

@ -352,23 +352,6 @@ void os::print_context(outputStream *st, const void *context) {
st->cr();
}
void os::print_tos_pc(outputStream *st, const void *context) {
if (context == nullptr) return;
const ucontext_t* uc = (const ucontext_t*)context;
address sp = (address)os::Linux::ucontext_get_sp(uc);
print_tos(st, sp);
st->cr();
// Note: it may be unsafe to inspect memory near pc. For example, pc may
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::fetch_frame_from_context(uc).pc();
print_instructions(st, pc);
st->cr();
}
void os::print_register_info(outputStream *st, const void *context, int& continuation) {
const int register_count = 32;
int n = continuation;

View File

@ -140,6 +140,12 @@ frame os::fetch_frame_from_context(const void* ucVoid) {
intptr_t* sp;
intptr_t* fp;
address epc = fetch_frame_from_context(ucVoid, &sp, &fp);
if (!is_readable_pointer(epc)) {
// Try to recover from calling into bad memory
// Assume new frame has not been set up, the same as
// compiled frame stack bang
return fetch_compiled_frame_from_context(ucVoid);
}
return frame(sp, epc);
}
@ -442,23 +448,6 @@ void os::print_context(outputStream *st, const void *context) {
st->cr();
}
void os::print_tos_pc(outputStream *st, const void *context) {
if (context == nullptr) return;
const ucontext_t* uc = (const ucontext_t*)context;
address sp = (address)os::Linux::ucontext_get_sp(uc);
print_tos(st, sp);
st->cr();
// Note: it may be unsafe to inspect memory near pc. For example, pc may
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::Posix::ucontext_get_pc(uc);
print_instructions(st, pc);
st->cr();
}
void os::print_register_info(outputStream *st, const void *context, int& continuation) {
const int register_count = 16 /* r0-r15 */ + 1 /* pc */;
int n = continuation;

View File

@ -578,23 +578,6 @@ void os::print_context(outputStream *st, const void *context) {
st->cr();
}
void os::print_tos_pc(outputStream *st, const void *context) {
if (context == nullptr) return;
const ucontext_t* uc = (const ucontext_t*)context;
address sp = (address)os::Linux::ucontext_get_sp(uc);
print_tos(st, sp);
st->cr();
// Note: it may be unsafe to inspect memory near pc. For example, pc may
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::fetch_frame_from_context(uc).pc();
print_instructions(st, pc);
st->cr();
}
void os::print_register_info(outputStream *st, const void *context, int& continuation) {
const int register_count = AMD64_ONLY(16) NOT_AMD64(8);
int n = continuation;

View File

@ -376,21 +376,6 @@ void os::print_context(outputStream* st, const void* ucVoid) {
st->print_cr("No context information.");
}
void os::print_tos_pc(outputStream *st, const void* ucVoid) {
const ucontext_t* uc = (const ucontext_t*)ucVoid;
address sp = (address)os::Linux::ucontext_get_sp(uc);
print_tos(st, sp);
st->cr();
// Note: it may be unsafe to inspect memory near pc. For example, pc may
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::Posix::ucontext_get_pc(uc);
print_instructions(st, pc);
st->cr();
}
void os::print_register_info(outputStream *st, const void *context, int& continuation) {
st->print_cr("No register info.");
}

View File

@ -205,24 +205,6 @@ void os::print_context(outputStream *st, const void *context) {
st->cr();
}
void os::print_tos_pc(outputStream *st, const void *context) {
if (context == nullptr) return;
const CONTEXT* uc = (const CONTEXT*)context;
address sp = (address)uc->Sp;
print_tos(st, sp);
st->cr();
// Note: it may be unsafe to inspect memory near pc. For example, pc may
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = (address)uc->Pc;
st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc);
print_hex_dump(st, pc - 32, pc + 32, sizeof(char), /* print_ascii=*/false);
st->cr();
}
void os::print_register_info(outputStream *st, const void *context, int& continuation) {
const int register_count = 29 /* X0-X28 */;
int n = continuation;

View File

@ -464,23 +464,6 @@ void os::print_context(outputStream *st, const void *context) {
st->cr();
}
void os::print_tos_pc(outputStream *st, const void *context) {
if (context == nullptr) return;
const CONTEXT* uc = (const CONTEXT*)context;
address sp = (address)uc->REG_SP;
print_tos(st, sp);
st->cr();
// Note: it may be unsafe to inspect memory near pc. For example, pc may
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::fetch_frame_from_context(uc).pc();
print_instructions(st, pc);
st->cr();
}
void os::print_register_info(outputStream *st, const void *context, int& continuation) {
const int register_count = AMD64_ONLY(16) NOT_AMD64(8);
int n = continuation;

View File

@ -1083,6 +1083,26 @@ void os::print_dhm(outputStream* st, const char* startStr, long sec) {
st->print_cr("%s %ld days %ld:%02ld hours", startStr, days, hours, minutes);
}
void os::print_tos_pc(outputStream* st, const void* context) {
if (context == nullptr) return;
// First of all, carefully determine sp without inspecting memory near pc.
// See comment below.
intptr_t* sp = nullptr;
fetch_frame_from_context(context, &sp, nullptr);
print_tos(st, (address)sp);
st->cr();
// Note: it may be unsafe to inspect memory near pc. For example, pc may
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
// This version of fetch_frame_from_context finds the caller pc if the actual
// one is bad.
address pc = fetch_frame_from_context(context).pc();
print_instructions(st, pc);
st->cr();
}
void os::print_tos(outputStream* st, address sp) {
st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", p2i(sp));
print_hex_dump(st, sp, sp + 512, sizeof(intptr_t));