mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 03:58:21 +00:00
8376264: Mixed jstack could not unwind optimized frame
This commit is contained in:
parent
a3b1aa9f7d
commit
9a8c7ec857
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021, NTT DATA.
|
||||
* Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2026, NTT DATA.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -219,16 +219,3 @@ JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_get
|
||||
DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj));
|
||||
return parser->get_bp_cfa_offset();
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser
|
||||
* Method: isBPOffsetAvailable
|
||||
* Signature: ()Z
|
||||
*/
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_isBPOffsetAvailable
|
||||
(JNIEnv *env, jobject this_obj) {
|
||||
DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj));
|
||||
return parser->is_bp_offset_available();
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, NTT DATA.
|
||||
* Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2026, NTT DATA.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -99,12 +99,11 @@ bool DwarfParser::process_cie(unsigned char *start_of_entry, uint32_t id) {
|
||||
|
||||
// Clear state
|
||||
_current_pc = 0L;
|
||||
_cfa_reg = RSP;
|
||||
_cfa_reg = MAX_VALUE;
|
||||
_return_address_reg = RA;
|
||||
_cfa_offset = 0;
|
||||
_ra_cfa_offset = 0;
|
||||
_bp_cfa_offset = 0;
|
||||
_bp_offset_available = false;
|
||||
_ra_cfa_offset = 8;
|
||||
_bp_cfa_offset = INT_MAX;
|
||||
|
||||
parse_dwarf_instructions(0L, static_cast<uintptr_t>(-1L), end);
|
||||
|
||||
@ -119,8 +118,8 @@ void DwarfParser::parse_dwarf_instructions(uintptr_t begin, uintptr_t pc, const
|
||||
/* for remember state */
|
||||
enum DWARF_Register rem_cfa_reg = MAX_VALUE;
|
||||
int rem_cfa_offset = 0;
|
||||
int rem_ra_cfa_offset = 0;
|
||||
int rem_bp_cfa_offset = 0;
|
||||
int rem_ra_cfa_offset = 8;
|
||||
int rem_bp_cfa_offset = INT_MAX;
|
||||
|
||||
while ((_buf < end) && (_current_pc < pc)) {
|
||||
unsigned char op = *_buf++;
|
||||
@ -147,7 +146,6 @@ void DwarfParser::parse_dwarf_instructions(uintptr_t begin, uintptr_t pc, const
|
||||
enum DWARF_Register reg = static_cast<enum DWARF_Register>(opa);
|
||||
if (reg == RBP) {
|
||||
_bp_cfa_offset = operand1 * _data_factor;
|
||||
_bp_offset_available = true;
|
||||
} else if (reg == RA) {
|
||||
_ra_cfa_offset = operand1 * _data_factor;
|
||||
}
|
||||
@ -184,6 +182,14 @@ void DwarfParser::parse_dwarf_instructions(uintptr_t begin, uintptr_t pc, const
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x07: { // DW_CFA_undefined
|
||||
enum DWARF_Register reg = static_cast<enum DWARF_Register>(read_leb(false));
|
||||
// We are only interested in BP here because CFA and RA should not be undefined.
|
||||
if (reg == RBP) {
|
||||
_bp_cfa_offset = INT_MAX;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x0d: {// DW_CFA_def_cfa_register
|
||||
_cfa_reg = static_cast<enum DWARF_Register>(read_leb(false));
|
||||
break;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, NTT DATA.
|
||||
* Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2026, NTT DATA.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -73,7 +73,6 @@ class DwarfParser {
|
||||
int _cfa_offset;
|
||||
int _ra_cfa_offset;
|
||||
int _bp_cfa_offset;
|
||||
bool _bp_offset_available;
|
||||
|
||||
uintptr_t read_leb(bool sign);
|
||||
uint64_t get_entry_length();
|
||||
@ -86,15 +85,14 @@ class DwarfParser {
|
||||
DwarfParser(lib_info *lib) : _lib(lib),
|
||||
_buf(NULL),
|
||||
_encoding(0),
|
||||
_cfa_reg(RSP),
|
||||
_cfa_reg(MAX_VALUE),
|
||||
_return_address_reg(RA),
|
||||
_code_factor(0),
|
||||
_data_factor(0),
|
||||
_current_pc(0L),
|
||||
_cfa_offset(0),
|
||||
_ra_cfa_offset(0),
|
||||
_bp_cfa_offset(0),
|
||||
_bp_offset_available(false) {};
|
||||
_ra_cfa_offset(8),
|
||||
_bp_cfa_offset(INT_MAX) {};
|
||||
|
||||
~DwarfParser() {}
|
||||
bool process_dwarf(const uintptr_t pc);
|
||||
@ -102,7 +100,6 @@ class DwarfParser {
|
||||
int get_cfa_offset() { return _cfa_offset; }
|
||||
int get_ra_cfa_offset() { return _ra_cfa_offset; }
|
||||
int get_bp_cfa_offset() { return _bp_cfa_offset; }
|
||||
bool is_bp_offset_available() { return _bp_offset_available; }
|
||||
|
||||
bool is_in(long pc) {
|
||||
return (_lib->exec_start <= pc) && (pc < _lib->exec_end);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Red Hat Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -81,11 +81,7 @@ class LinuxCDebugger implements CDebugger {
|
||||
String cpu = dbg.getCPU();
|
||||
if (cpu.equals("amd64")) {
|
||||
AMD64ThreadContext context = (AMD64ThreadContext) thread.getContext();
|
||||
Address sp = context.getRegisterAsAddress(AMD64ThreadContext.RSP);
|
||||
if (sp == null) return null;
|
||||
Address pc = context.getRegisterAsAddress(AMD64ThreadContext.RIP);
|
||||
if (pc == null) return null;
|
||||
return LinuxAMD64CFrame.getTopFrame(dbg, sp, pc, context);
|
||||
return LinuxAMD64CFrame.getTopFrame(dbg, context);
|
||||
} else if (cpu.equals("ppc64")) {
|
||||
PPC64ThreadContext context = (PPC64ThreadContext) thread.getContext();
|
||||
Address sp = context.getRegisterAsAddress(PPC64ThreadContext.SP);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, NTT DATA.
|
||||
* Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2026, NTT DATA.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -66,9 +66,15 @@ public class DwarfParser {
|
||||
processDwarf0(pc.asLongValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if BP offset is declared in DWARF instructions.
|
||||
*/
|
||||
public boolean isBPOffsetAvailable() {
|
||||
return getBasePointerOffsetFromCFA() != Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
public native int getCFARegister();
|
||||
public native int getCFAOffset();
|
||||
public native int getReturnAddressOffsetFromCFA();
|
||||
public native int getBasePointerOffsetFromCFA();
|
||||
public native boolean isBPOffsetAvailable();
|
||||
}
|
||||
|
||||
@ -40,8 +40,9 @@ public final class LinuxAMD64CFrame extends BasicCFrame {
|
||||
private static LinuxAMD64CFrame getFrameFromReg(LinuxDebugger dbg, Function<Integer, Address> getreg) {
|
||||
Address rip = getreg.apply(AMD64ThreadContext.RIP);
|
||||
Address rsp = getreg.apply(AMD64ThreadContext.RSP);
|
||||
Address rbp = getreg.apply(AMD64ThreadContext.RBP);
|
||||
Address libptr = dbg.findLibPtrByAddress(rip);
|
||||
Address cfa = getreg.apply(AMD64ThreadContext.RBP);
|
||||
Address cfa = null;
|
||||
DwarfParser dwarf = null;
|
||||
|
||||
if (libptr != null) { // Native frame
|
||||
@ -52,61 +53,34 @@ public final class LinuxAMD64CFrame extends BasicCFrame {
|
||||
// DWARF processing should succeed when the frame is native
|
||||
// but it might fail if Common Information Entry (CIE) has language
|
||||
// personality routine and/or Language Specific Data Area (LSDA).
|
||||
return new LinuxAMD64CFrame(dbg, rsp, cfa, rip, dwarf, true);
|
||||
return new LinuxAMD64CFrame(dbg, rsp, rbp, cfa, rip, dwarf, true);
|
||||
}
|
||||
|
||||
cfa = getreg.apply(dwarf.getCFARegister())
|
||||
.addOffsetTo(dwarf.getCFAOffset());
|
||||
}
|
||||
|
||||
return (cfa == null) ? null
|
||||
: new LinuxAMD64CFrame(dbg, rsp, cfa, rip, dwarf);
|
||||
return (rbp == null && cfa == null)
|
||||
? null
|
||||
: new LinuxAMD64CFrame(dbg, rsp, rbp, cfa, rip, dwarf);
|
||||
}
|
||||
|
||||
public static LinuxAMD64CFrame getTopFrame(LinuxDebugger dbg, Address rip, ThreadContext context) {
|
||||
public static LinuxAMD64CFrame getTopFrame(LinuxDebugger dbg, ThreadContext context) {
|
||||
return getFrameFromReg(dbg, context::getRegisterAsAddress);
|
||||
}
|
||||
|
||||
public static LinuxAMD64CFrame getTopFrame(LinuxDebugger dbg, Address rsp, Address rip, ThreadContext context) {
|
||||
Address libptr = dbg.findLibPtrByAddress(rip);
|
||||
Address cfa = context.getRegisterAsAddress(AMD64ThreadContext.RBP);
|
||||
DwarfParser dwarf = null;
|
||||
|
||||
if (libptr != null) { // Native frame
|
||||
dwarf = new DwarfParser(libptr);
|
||||
try {
|
||||
dwarf.processDwarf(rip);
|
||||
} catch (DebuggerException e) {
|
||||
// DWARF processing should succeed when the frame is native
|
||||
// but it might fail if Common Information Entry (CIE) has language
|
||||
// personality routine and/or Language Specific Data Area (LSDA).
|
||||
return new LinuxAMD64CFrame(dbg, rsp, cfa, rip, dwarf, true);
|
||||
}
|
||||
|
||||
cfa = context.getRegisterAsAddress(dwarf.getCFARegister())
|
||||
.addOffsetTo(dwarf.getCFAOffset());
|
||||
}
|
||||
|
||||
return (cfa == null) ? null
|
||||
: new LinuxAMD64CFrame(dbg, rsp, cfa, rip, dwarf);
|
||||
private LinuxAMD64CFrame(LinuxDebugger dbg, Address rsp, Address rbp, Address cfa, Address rip, DwarfParser dwarf) {
|
||||
this(dbg, rsp, rbp, cfa, rip, dwarf, false);
|
||||
}
|
||||
|
||||
private LinuxAMD64CFrame(LinuxDebugger dbg, Address rsp, Address cfa, Address rip, DwarfParser dwarf) {
|
||||
this(dbg, rsp, cfa, rip, dwarf, false);
|
||||
}
|
||||
|
||||
private LinuxAMD64CFrame(LinuxDebugger dbg, Address rsp, Address cfa, Address rip, DwarfParser dwarf, boolean finalFrame) {
|
||||
this(dbg, rsp, cfa, rip, dwarf, finalFrame, false);
|
||||
}
|
||||
|
||||
private LinuxAMD64CFrame(LinuxDebugger dbg, Address rsp, Address cfa, Address rip, DwarfParser dwarf, boolean finalFrame, boolean use1ByteBeforeToLookup) {
|
||||
private LinuxAMD64CFrame(LinuxDebugger dbg, Address rsp, Address rbp, Address cfa, Address rip, DwarfParser dwarf, boolean use1ByteBeforeToLookup) {
|
||||
super(dbg.getCDebugger());
|
||||
this.rsp = rsp;
|
||||
this.rbp = rbp;
|
||||
this.cfa = cfa;
|
||||
this.rip = rip;
|
||||
this.dbg = dbg;
|
||||
this.dwarf = dwarf;
|
||||
this.finalFrame = finalFrame;
|
||||
this.use1ByteBeforeToLookup = use1ByteBeforeToLookup;
|
||||
}
|
||||
|
||||
@ -126,14 +100,16 @@ public final class LinuxAMD64CFrame extends BasicCFrame {
|
||||
}
|
||||
|
||||
public Address localVariableBase() {
|
||||
return cfa;
|
||||
return (dwarf != null && dwarf.isBPOffsetAvailable())
|
||||
? cfa.addOffsetTo(dwarf.getBasePointerOffsetFromCFA())
|
||||
: rbp;
|
||||
}
|
||||
|
||||
private Address getNextPC(boolean useDwarf) {
|
||||
private Address getNextPC() {
|
||||
try {
|
||||
long offs = useDwarf ? dwarf.getReturnAddressOffsetFromCFA()
|
||||
: ADDRESS_SIZE;
|
||||
return cfa.getAddressAt(offs);
|
||||
return dwarf == null
|
||||
? rbp.getAddressAt(ADDRESS_SIZE) // Java frame
|
||||
: cfa.getAddressAt(dwarf.getReturnAddressOffsetFromCFA()); // Native frame
|
||||
} catch (UnmappedAddressException | UnalignedAddressException e) {
|
||||
return null;
|
||||
}
|
||||
@ -144,41 +120,40 @@ public final class LinuxAMD64CFrame extends BasicCFrame {
|
||||
// nextCFA must be greater than current CFA, if frame is native.
|
||||
// Java interpreter frames can share the CFA (frame pointer).
|
||||
return nextCFA != null &&
|
||||
(!isNative || (isNative && nextCFA.greaterThan(cfa)));
|
||||
(!isNative || (isNative && nextCFA.greaterThanOrEqual(cfa)));
|
||||
}
|
||||
|
||||
private Address getNextRSP() {
|
||||
// next RSP should be previous slot of return address.
|
||||
var bp = dwarf == null ? cfa.addOffsetTo(ADDRESS_SIZE) // top of BP points callser BP
|
||||
: cfa.addOffsetTo(dwarf.getReturnAddressOffsetFromCFA());
|
||||
return bp.addOffsetTo(ADDRESS_SIZE);
|
||||
return dwarf == null ? rbp.addOffsetTo(2 * ADDRESS_SIZE) // Java frame - skip saved BP and RA
|
||||
: cfa.addOffsetTo(dwarf.getReturnAddressOffsetFromCFA())
|
||||
.addOffsetTo(ADDRESS_SIZE); // Native frame
|
||||
}
|
||||
|
||||
private Address getNextCFA(DwarfParser nextDwarf, ThreadContext context, Address senderFP, Address senderPC) {
|
||||
private Address getNextCFA(DwarfParser nextDwarf, Address senderFP, Address senderPC) {
|
||||
Address nextCFA;
|
||||
boolean isNative = false;
|
||||
|
||||
if (senderFP == null) {
|
||||
senderFP = cfa.getAddressAt(0); // RBP by default
|
||||
}
|
||||
|
||||
if (VM.getVM().getCodeCache().contains(senderPC)) { // Next frame is Java
|
||||
nextCFA = (dwarf == null) ? senderFP // Current frame is Java
|
||||
: cfa.getAddressAt(dwarf.getBasePointerOffsetFromCFA()); // Current frame is Native
|
||||
if (nextDwarf == null) { // Next frame is Java
|
||||
return null;
|
||||
} else { // Next frame is Native
|
||||
if (VM.getVM().getCodeCache().contains(pc())) { // Current frame is Java
|
||||
nextCFA = senderFP.addOffsetTo(-nextDwarf.getBasePointerOffsetFromCFA());
|
||||
} else { // Current frame is Native
|
||||
if (nextDwarf == null) { // maybe runtime entrypoint (_start())
|
||||
throw new DebuggerException("nextDwarf is null even though native call");
|
||||
if (dwarf == null) { // Current frame is Java
|
||||
int nextCFAReg = nextDwarf.getCFARegister();
|
||||
if (nextCFAReg == AMD64ThreadContext.RBP) {
|
||||
nextCFA = nextDwarf.isBPOffsetAvailable()
|
||||
? rbp.getAddressAt(0) // We can use cfa as BP in Java frame
|
||||
.addOffsetTo(-nextDwarf.getBasePointerOffsetFromCFA())
|
||||
: rbp;
|
||||
} else if (nextCFAReg == AMD64ThreadContext.RSP) {
|
||||
nextCFA = senderFP.addOffsetTo(2 * ADDRESS_SIZE) // skip BP and RA to get caller SP
|
||||
.addOffsetTo(nextDwarf.getCFAOffset());
|
||||
} else {
|
||||
throw new DebuggerException("Unsupported CFA register: " + nextCFAReg);
|
||||
}
|
||||
|
||||
} else { // Current frame is Native
|
||||
isNative = true;
|
||||
int nextCFAReg = nextDwarf.getCFARegister();
|
||||
if (nextCFAReg == AMD64ThreadContext.RBP) {
|
||||
Address rbp = dwarf.isBPOffsetAvailable() ? cfa.addOffsetTo(dwarf.getBasePointerOffsetFromCFA())
|
||||
: context.getRegisterAsAddress(AMD64ThreadContext.RBP);
|
||||
Address nextRBP = rbp.getAddressAt(0);
|
||||
Address nextRBP = getNextRBP(senderFP);
|
||||
nextCFA = nextRBP.addOffsetTo(-nextDwarf.getBasePointerOffsetFromCFA());
|
||||
} else if (nextCFAReg == AMD64ThreadContext.RSP) {
|
||||
nextCFA = getNextRSP().addOffsetTo(nextDwarf.getCFAOffset());
|
||||
@ -188,14 +163,6 @@ public final class LinuxAMD64CFrame extends BasicCFrame {
|
||||
}
|
||||
}
|
||||
|
||||
// Sanity check for next CFA address
|
||||
try {
|
||||
nextCFA.getAddressAt(0);
|
||||
} catch (Exception e) {
|
||||
// return null if next CFA address is invalid
|
||||
return null;
|
||||
}
|
||||
|
||||
if (dbg.isSignalTrampoline(senderPC)) {
|
||||
// Return without frame check if sender is signal trampoline.
|
||||
return nextCFA;
|
||||
@ -204,6 +171,18 @@ public final class LinuxAMD64CFrame extends BasicCFrame {
|
||||
}
|
||||
}
|
||||
|
||||
private Address getNextRBP(Address senderFP) {
|
||||
if (senderFP != null) {
|
||||
return senderFP;
|
||||
} else if (dwarf == null) { // Current frame is Java
|
||||
return rbp.getAddressAt(0);
|
||||
} else { // Current frame is Native
|
||||
return dwarf.isBPOffsetAvailable()
|
||||
? cfa.getAddressAt(dwarf.getBasePointerOffsetFromCFA())
|
||||
: rbp;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CFrame sender(ThreadProxy th) {
|
||||
return sender(th, null, null, null);
|
||||
@ -211,10 +190,6 @@ public final class LinuxAMD64CFrame extends BasicCFrame {
|
||||
|
||||
@Override
|
||||
public CFrame sender(ThreadProxy th, Address sp, Address fp, Address pc) {
|
||||
if (finalFrame) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (dbg.isSignalTrampoline(pc())) {
|
||||
// RSP points signal context
|
||||
// https://github.com/torvalds/linux/blob/v6.17/arch/x86/kernel/signal.c#L94
|
||||
@ -227,8 +202,7 @@ public final class LinuxAMD64CFrame extends BasicCFrame {
|
||||
if (nextRSP == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Address nextPC = pc != null ? pc : getNextPC(dwarf != null);
|
||||
Address nextPC = pc != null ? pc : getNextPC();
|
||||
if (nextPC == null) {
|
||||
return null;
|
||||
}
|
||||
@ -251,11 +225,16 @@ public final class LinuxAMD64CFrame extends BasicCFrame {
|
||||
}
|
||||
}
|
||||
|
||||
Address nextRBP = getNextRBP(fp);
|
||||
|
||||
try {
|
||||
Address nextCFA = getNextCFA(nextDwarf, context, fp, nextPC);
|
||||
return new LinuxAMD64CFrame(dbg, nextRSP, nextCFA, nextPC, nextDwarf, false, fallback);
|
||||
Address nextCFA = getNextCFA(nextDwarf, fp, nextPC);
|
||||
return (nextCFA == null && nextRBP == null)
|
||||
? null
|
||||
: new LinuxAMD64CFrame(dbg, nextRSP, nextRBP, nextCFA, nextPC, nextDwarf, fallback);
|
||||
} catch (DebuggerException _) {
|
||||
return null;
|
||||
return nextRBP == null ? null
|
||||
: new LinuxAMD64CFrame(dbg, nextRSP, nextRBP, null, nextPC, null, fallback);
|
||||
}
|
||||
}
|
||||
|
||||
@ -279,16 +258,16 @@ public final class LinuxAMD64CFrame extends BasicCFrame {
|
||||
|
||||
@Override
|
||||
public Frame toFrame() {
|
||||
return new AMD64Frame(rsp, cfa, rip);
|
||||
return new AMD64Frame(rsp, localVariableBase(), rip);
|
||||
}
|
||||
|
||||
// package/class internals only
|
||||
private static final int ADDRESS_SIZE = 8;
|
||||
private Address rsp;
|
||||
private Address rbp;
|
||||
private Address rip;
|
||||
private Address cfa;
|
||||
private LinuxDebugger dbg;
|
||||
private DwarfParser dwarf;
|
||||
private boolean finalFrame;
|
||||
private boolean use1ByteBeforeToLookup;
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ import jdk.test.lib.util.CoreUtils;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8374482
|
||||
* @bug 8374482 8376264
|
||||
* @requires (os.family == "linux") & (vm.hasSA)
|
||||
* @requires os.arch == "amd64"
|
||||
* @library /test/lib
|
||||
@ -61,6 +61,7 @@ public class TestJhsdbJstackMixedCore {
|
||||
|
||||
out.shouldContain("<signal handler called>");
|
||||
out.shouldContain("Java_jdk_test_lib_apps_LingeredApp_crash");
|
||||
out.shouldContain("* jdk.test.lib.apps.LingeredApp.crash()");
|
||||
}
|
||||
|
||||
public static void main(String... args) throws Throwable {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user