mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-27 18:50:07 +00:00
8377947: Test serviceability/sa/TestJhsdbJstackMixedCore.java failed on linux-x64
Reviewed-by: cjplummer, kevinw
This commit is contained in:
parent
8ba3de9834
commit
32cc7f1f57
@ -205,7 +205,7 @@ extern "C"
|
||||
JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_getReturnAddressOffsetFromCFA
|
||||
(JNIEnv *env, jobject this_obj) {
|
||||
DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj));
|
||||
return parser->get_ra_cfa_offset();
|
||||
return parser->get_offset_from_cfa(RA);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -217,5 +217,5 @@ extern "C"
|
||||
JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_getBasePointerOffsetFromCFA
|
||||
(JNIEnv *env, jobject this_obj) {
|
||||
DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj));
|
||||
return parser->get_bp_cfa_offset();
|
||||
return parser->get_offset_from_cfa(RBP);
|
||||
}
|
||||
|
||||
@ -24,10 +24,32 @@
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <stack>
|
||||
|
||||
#include "dwarf.hpp"
|
||||
#include "libproc_impl.h"
|
||||
|
||||
DwarfParser::DwarfParser(lib_info *lib) : _lib(lib),
|
||||
_buf(NULL),
|
||||
_encoding(0),
|
||||
_code_factor(0),
|
||||
_data_factor(0),
|
||||
_current_pc(0L) {
|
||||
init_state(_initial_state);
|
||||
init_state(_state);
|
||||
}
|
||||
|
||||
void DwarfParser::init_state(struct DwarfState& st) {
|
||||
st.cfa_reg = MAX_VALUE;
|
||||
st.return_address_reg = MAX_VALUE;
|
||||
st.cfa_offset = 0;
|
||||
|
||||
st.offset_from_cfa.clear();
|
||||
for (int reg = 0; reg < MAX_VALUE; reg++) {
|
||||
st.offset_from_cfa[static_cast<enum DWARF_Register>(reg)] = INT_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
/* from read_leb128() in dwarf.c in binutils */
|
||||
uintptr_t DwarfParser::read_leb(bool sign) {
|
||||
uintptr_t result = 0L;
|
||||
@ -82,7 +104,7 @@ bool DwarfParser::process_cie(unsigned char *start_of_entry, uint32_t id) {
|
||||
|
||||
_code_factor = read_leb(false);
|
||||
_data_factor = static_cast<int>(read_leb(true));
|
||||
_return_address_reg = static_cast<enum DWARF_Register>(*_buf++);
|
||||
enum DWARF_Register initial_ra = static_cast<enum DWARF_Register>(*_buf++);
|
||||
|
||||
if (strpbrk(augmentation_string, "LP") != NULL) {
|
||||
// Language personality routine (P) and Language Specific Data Area (LSDA:L)
|
||||
@ -99,14 +121,12 @@ bool DwarfParser::process_cie(unsigned char *start_of_entry, uint32_t id) {
|
||||
|
||||
// Clear state
|
||||
_current_pc = 0L;
|
||||
_cfa_reg = MAX_VALUE;
|
||||
_return_address_reg = RA;
|
||||
_cfa_offset = 0;
|
||||
_ra_cfa_offset = 8;
|
||||
_bp_cfa_offset = INT_MAX;
|
||||
init_state(_state);
|
||||
_state.return_address_reg = initial_ra;
|
||||
|
||||
parse_dwarf_instructions(0L, static_cast<uintptr_t>(-1L), end);
|
||||
|
||||
_initial_state = _state;
|
||||
_buf = orig_pos;
|
||||
return true;
|
||||
}
|
||||
@ -114,12 +134,7 @@ bool DwarfParser::process_cie(unsigned char *start_of_entry, uint32_t id) {
|
||||
void DwarfParser::parse_dwarf_instructions(uintptr_t begin, uintptr_t pc, const unsigned char *end) {
|
||||
uintptr_t operand1;
|
||||
_current_pc = begin;
|
||||
|
||||
/* for remember state */
|
||||
enum DWARF_Register rem_cfa_reg = MAX_VALUE;
|
||||
int rem_cfa_offset = 0;
|
||||
int rem_ra_cfa_offset = 8;
|
||||
int rem_bp_cfa_offset = INT_MAX;
|
||||
std::stack<struct DwarfState> remember_state;
|
||||
|
||||
while ((_buf < end) && (_current_pc < pc)) {
|
||||
unsigned char op = *_buf++;
|
||||
@ -138,21 +153,17 @@ void DwarfParser::parse_dwarf_instructions(uintptr_t begin, uintptr_t pc, const
|
||||
}
|
||||
break;
|
||||
case 0x0c: // DW_CFA_def_cfa
|
||||
_cfa_reg = static_cast<enum DWARF_Register>(read_leb(false));
|
||||
_cfa_offset = read_leb(false);
|
||||
_state.cfa_reg = static_cast<enum DWARF_Register>(read_leb(false));
|
||||
_state.cfa_offset = read_leb(false);
|
||||
break;
|
||||
case 0x80: {// DW_CFA_offset
|
||||
operand1 = read_leb(false);
|
||||
enum DWARF_Register reg = static_cast<enum DWARF_Register>(opa);
|
||||
if (reg == RBP) {
|
||||
_bp_cfa_offset = operand1 * _data_factor;
|
||||
} else if (reg == RA) {
|
||||
_ra_cfa_offset = operand1 * _data_factor;
|
||||
}
|
||||
_state.offset_from_cfa[reg] = operand1 * _data_factor;
|
||||
break;
|
||||
}
|
||||
case 0xe: // DW_CFA_def_cfa_offset
|
||||
_cfa_offset = read_leb(false);
|
||||
_state.cfa_offset = read_leb(false);
|
||||
break;
|
||||
case 0x40: // DW_CFA_advance_loc
|
||||
if (_current_pc != 0L) {
|
||||
@ -184,28 +195,28 @@ void DwarfParser::parse_dwarf_instructions(uintptr_t begin, uintptr_t pc, const
|
||||
}
|
||||
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;
|
||||
}
|
||||
_state.offset_from_cfa[reg] = INT_MAX;
|
||||
break;
|
||||
}
|
||||
case 0x0d: {// DW_CFA_def_cfa_register
|
||||
_cfa_reg = static_cast<enum DWARF_Register>(read_leb(false));
|
||||
case 0x0d: // DW_CFA_def_cfa_register
|
||||
_state.cfa_reg = static_cast<enum DWARF_Register>(read_leb(false));
|
||||
break;
|
||||
}
|
||||
case 0x0a: // DW_CFA_remember_state
|
||||
rem_cfa_reg = _cfa_reg;
|
||||
rem_cfa_offset = _cfa_offset;
|
||||
rem_ra_cfa_offset = _ra_cfa_offset;
|
||||
rem_bp_cfa_offset = _bp_cfa_offset;
|
||||
remember_state.push(_state);
|
||||
break;
|
||||
case 0x0b: // DW_CFA_restore_state
|
||||
_cfa_reg = rem_cfa_reg;
|
||||
_cfa_offset = rem_cfa_offset;
|
||||
_ra_cfa_offset = rem_ra_cfa_offset;
|
||||
_bp_cfa_offset = rem_bp_cfa_offset;
|
||||
if (remember_state.empty()) {
|
||||
print_debug("DWARF Error: DW_CFA_restore_state with empty stack.\n");
|
||||
return;
|
||||
}
|
||||
_state = remember_state.top();
|
||||
remember_state.pop();
|
||||
break;
|
||||
case 0xc0: {// DW_CFA_restore
|
||||
enum DWARF_Register reg = static_cast<enum DWARF_Register>(opa);
|
||||
_state.offset_from_cfa[reg] = _initial_state.offset_from_cfa[reg];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
print_debug("DWARF: Unknown opcode: 0x%x\n", op);
|
||||
return;
|
||||
|
||||
@ -26,6 +26,8 @@
|
||||
#ifndef _DWARF_HPP_
|
||||
#define _DWARF_HPP_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "libproc_impl.h"
|
||||
|
||||
/*
|
||||
@ -55,6 +57,13 @@ enum DWARF_Register {
|
||||
MAX_VALUE
|
||||
};
|
||||
|
||||
struct DwarfState {
|
||||
enum DWARF_Register cfa_reg;
|
||||
enum DWARF_Register return_address_reg;
|
||||
int cfa_offset;
|
||||
std::map<enum DWARF_Register, int> offset_from_cfa;
|
||||
};
|
||||
|
||||
/*
|
||||
* DwarfParser finds out CFA (Canonical Frame Address) from DWARF in ELF binary.
|
||||
* Also Return Address (RA) and Base Pointer (BP) are calculated from CFA.
|
||||
@ -64,16 +73,14 @@ class DwarfParser {
|
||||
const lib_info *_lib;
|
||||
unsigned char *_buf;
|
||||
unsigned char _encoding;
|
||||
enum DWARF_Register _cfa_reg;
|
||||
enum DWARF_Register _return_address_reg;
|
||||
unsigned int _code_factor;
|
||||
int _data_factor;
|
||||
|
||||
uintptr_t _current_pc;
|
||||
int _cfa_offset;
|
||||
int _ra_cfa_offset;
|
||||
int _bp_cfa_offset;
|
||||
struct DwarfState _initial_state;
|
||||
struct DwarfState _state;
|
||||
|
||||
void init_state(struct DwarfState& st);
|
||||
uintptr_t read_leb(bool sign);
|
||||
uint64_t get_entry_length();
|
||||
bool process_cie(unsigned char *start_of_entry, uint32_t id);
|
||||
@ -82,24 +89,12 @@ class DwarfParser {
|
||||
unsigned int get_pc_range();
|
||||
|
||||
public:
|
||||
DwarfParser(lib_info *lib) : _lib(lib),
|
||||
_buf(NULL),
|
||||
_encoding(0),
|
||||
_cfa_reg(MAX_VALUE),
|
||||
_return_address_reg(RA),
|
||||
_code_factor(0),
|
||||
_data_factor(0),
|
||||
_current_pc(0L),
|
||||
_cfa_offset(0),
|
||||
_ra_cfa_offset(8),
|
||||
_bp_cfa_offset(INT_MAX) {};
|
||||
|
||||
DwarfParser(lib_info *lib);
|
||||
~DwarfParser() {}
|
||||
bool process_dwarf(const uintptr_t pc);
|
||||
enum DWARF_Register get_cfa_register() { return _cfa_reg; }
|
||||
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; }
|
||||
enum DWARF_Register get_cfa_register() { return _state.cfa_reg; }
|
||||
int get_cfa_offset() { return _state.cfa_offset; }
|
||||
int get_offset_from_cfa(enum DWARF_Register reg) { return _state.offset_from_cfa[reg]; }
|
||||
|
||||
bool is_in(long pc) {
|
||||
return (_lib->exec_start <= pc) && (pc < _lib->exec_end);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user