8334430: Clean up nativeInst_x86.*
Reviewed-by: jwaters, jiefu
This commit is contained in:
parent
8bc2fbe578
commit
6f860f8f6f
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -41,143 +41,6 @@ void NativeInstruction::wrote(int offset) {
|
|||||||
ICache::invalidate_word(addr_at(offset));
|
ICache::invalidate_word(addr_at(offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ASSERT
|
|
||||||
void NativeLoadGot::report_and_fail() const {
|
|
||||||
tty->print_cr("Addr: " INTPTR_FORMAT " Code: %x %x %x", p2i(instruction_address()),
|
|
||||||
(has_rex ? ubyte_at(0) : 0), ubyte_at(rex_size), ubyte_at(rex_size + 1));
|
|
||||||
fatal("not a indirect rip mov to rbx");
|
|
||||||
}
|
|
||||||
|
|
||||||
void NativeLoadGot::verify() const {
|
|
||||||
if (has_rex) {
|
|
||||||
int rex = ubyte_at(0);
|
|
||||||
if (rex != rex_prefix && rex != rex_b_prefix) {
|
|
||||||
report_and_fail();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int inst = ubyte_at(rex_size);
|
|
||||||
if (inst != instruction_code) {
|
|
||||||
report_and_fail();
|
|
||||||
}
|
|
||||||
int modrm = ubyte_at(rex_size + 1);
|
|
||||||
if (modrm != modrm_rbx_code && modrm != modrm_rax_code) {
|
|
||||||
report_and_fail();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
intptr_t NativeLoadGot::data() const {
|
|
||||||
return *(intptr_t *) got_address();
|
|
||||||
}
|
|
||||||
|
|
||||||
address NativePltCall::destination() const {
|
|
||||||
NativeGotJump* jump = nativeGotJump_at(plt_jump());
|
|
||||||
return jump->destination();
|
|
||||||
}
|
|
||||||
|
|
||||||
address NativePltCall::plt_entry() const {
|
|
||||||
return return_address() + displacement();
|
|
||||||
}
|
|
||||||
|
|
||||||
address NativePltCall::plt_jump() const {
|
|
||||||
address entry = plt_entry();
|
|
||||||
// Virtual PLT code has move instruction first
|
|
||||||
if (((NativeGotJump*)entry)->is_GotJump()) {
|
|
||||||
return entry;
|
|
||||||
} else {
|
|
||||||
return nativeLoadGot_at(entry)->next_instruction_address();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
address NativePltCall::plt_load_got() const {
|
|
||||||
address entry = plt_entry();
|
|
||||||
if (!((NativeGotJump*)entry)->is_GotJump()) {
|
|
||||||
// Virtual PLT code has move instruction first
|
|
||||||
return entry;
|
|
||||||
} else {
|
|
||||||
// Static PLT code has move instruction second (from c2i stub)
|
|
||||||
return nativeGotJump_at(entry)->next_instruction_address();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
address NativePltCall::plt_c2i_stub() const {
|
|
||||||
address entry = plt_load_got();
|
|
||||||
// This method should be called only for static calls which has C2I stub.
|
|
||||||
NativeLoadGot* load = nativeLoadGot_at(entry);
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
address NativePltCall::plt_resolve_call() const {
|
|
||||||
NativeGotJump* jump = nativeGotJump_at(plt_jump());
|
|
||||||
address entry = jump->next_instruction_address();
|
|
||||||
if (((NativeGotJump*)entry)->is_GotJump()) {
|
|
||||||
return entry;
|
|
||||||
} else {
|
|
||||||
// c2i stub 2 instructions
|
|
||||||
entry = nativeLoadGot_at(entry)->next_instruction_address();
|
|
||||||
return nativeGotJump_at(entry)->next_instruction_address();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NativePltCall::reset_to_plt_resolve_call() {
|
|
||||||
set_destination_mt_safe(plt_resolve_call());
|
|
||||||
}
|
|
||||||
|
|
||||||
void NativePltCall::set_destination_mt_safe(address dest) {
|
|
||||||
// rewriting the value in the GOT, it should always be aligned
|
|
||||||
NativeGotJump* jump = nativeGotJump_at(plt_jump());
|
|
||||||
address* got = (address *) jump->got_address();
|
|
||||||
*got = dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NativePltCall::set_stub_to_clean() {
|
|
||||||
NativeLoadGot* method_loader = nativeLoadGot_at(plt_c2i_stub());
|
|
||||||
NativeGotJump* jump = nativeGotJump_at(method_loader->next_instruction_address());
|
|
||||||
method_loader->set_data(0);
|
|
||||||
jump->set_jump_destination((address)-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NativePltCall::verify() const {
|
|
||||||
// Make sure code pattern is actually a call rip+off32 instruction.
|
|
||||||
int inst = ubyte_at(0);
|
|
||||||
if (inst != instruction_code) {
|
|
||||||
tty->print_cr("Addr: " INTPTR_FORMAT " Code: 0x%x", p2i(instruction_address()),
|
|
||||||
inst);
|
|
||||||
fatal("not a call rip+off32");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
address NativeGotJump::destination() const {
|
|
||||||
address *got_entry = (address *) got_address();
|
|
||||||
return *got_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ASSERT
|
|
||||||
void NativeGotJump::report_and_fail() const {
|
|
||||||
tty->print_cr("Addr: " INTPTR_FORMAT " Code: %x %x %x", p2i(instruction_address()),
|
|
||||||
(has_rex() ? ubyte_at(0) : 0), ubyte_at(rex_size()), ubyte_at(rex_size() + 1));
|
|
||||||
fatal("not a indirect rip jump");
|
|
||||||
}
|
|
||||||
|
|
||||||
void NativeGotJump::verify() const {
|
|
||||||
if (has_rex()) {
|
|
||||||
int rex = ubyte_at(0);
|
|
||||||
if (rex != rex_prefix) {
|
|
||||||
report_and_fail();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int inst = ubyte_at(rex_size());
|
|
||||||
if (inst != instruction_code) {
|
|
||||||
report_and_fail();
|
|
||||||
}
|
|
||||||
int modrm = ubyte_at(rex_size() + 1);
|
|
||||||
if (modrm != modrm_code) {
|
|
||||||
report_and_fail();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void NativeCall::verify() {
|
void NativeCall::verify() {
|
||||||
// Make sure code pattern is actually a call imm32 instruction.
|
// Make sure code pattern is actually a call imm32 instruction.
|
||||||
int inst = ubyte_at(0);
|
int inst = ubyte_at(0);
|
||||||
@ -565,28 +428,6 @@ void NativeJump::patch_verified_entry(address entry, address verified_entry, add
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
address NativeFarJump::jump_destination() const {
|
|
||||||
NativeMovConstReg* mov = nativeMovConstReg_at(addr_at(0));
|
|
||||||
return (address)mov->data();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NativeFarJump::verify() {
|
|
||||||
if (is_far_jump()) {
|
|
||||||
NativeMovConstReg* mov = nativeMovConstReg_at(addr_at(0));
|
|
||||||
NativeInstruction* jmp = nativeInstruction_at(mov->next_instruction_address());
|
|
||||||
if (jmp->is_jump_reg()) return;
|
|
||||||
}
|
|
||||||
fatal("not a jump instruction");
|
|
||||||
}
|
|
||||||
|
|
||||||
void NativePopReg::insert(address code_pos, Register reg) {
|
|
||||||
assert(reg->encoding() < 8, "no space for REX");
|
|
||||||
assert(NativePopReg::instruction_size == sizeof(char), "right address unit for update");
|
|
||||||
*code_pos = (u_char)(instruction_code | reg->encoding());
|
|
||||||
ICache::invalidate_range(code_pos, instruction_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NativeIllegalInstruction::insert(address code_pos) {
|
void NativeIllegalInstruction::insert(address code_pos) {
|
||||||
assert(NativeIllegalInstruction::instruction_size == sizeof(short), "right address unit for update");
|
assert(NativeIllegalInstruction::instruction_size == sizeof(short), "right address unit for update");
|
||||||
*(short *)code_pos = instruction_code;
|
*(short *)code_pos = instruction_code;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -37,7 +37,6 @@
|
|||||||
// - - NativeMovRegMem
|
// - - NativeMovRegMem
|
||||||
// - - NativeMovRegMemPatching
|
// - - NativeMovRegMemPatching
|
||||||
// - - NativeJump
|
// - - NativeJump
|
||||||
// - - NativeFarJump
|
|
||||||
// - - NativeIllegalOpCode
|
// - - NativeIllegalOpCode
|
||||||
// - - NativeGeneralJump
|
// - - NativeGeneralJump
|
||||||
// - - NativeReturn
|
// - - NativeReturn
|
||||||
@ -64,7 +63,6 @@ class NativeInstruction {
|
|||||||
inline bool is_return();
|
inline bool is_return();
|
||||||
inline bool is_jump();
|
inline bool is_jump();
|
||||||
inline bool is_jump_reg();
|
inline bool is_jump_reg();
|
||||||
inline bool is_far_jump();
|
|
||||||
inline bool is_cond_jump();
|
inline bool is_cond_jump();
|
||||||
inline bool is_safepoint_poll();
|
inline bool is_safepoint_poll();
|
||||||
inline bool is_mov_literal64();
|
inline bool is_mov_literal64();
|
||||||
@ -104,47 +102,6 @@ inline NativeInstruction* nativeInstruction_at(address address) {
|
|||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
class NativePltCall: public NativeInstruction {
|
|
||||||
public:
|
|
||||||
enum Intel_specific_constants {
|
|
||||||
instruction_code = 0xE8,
|
|
||||||
instruction_size = 5,
|
|
||||||
instruction_offset = 0,
|
|
||||||
displacement_offset = 1,
|
|
||||||
return_address_offset = 5
|
|
||||||
};
|
|
||||||
address instruction_address() const { return addr_at(instruction_offset); }
|
|
||||||
address next_instruction_address() const { return addr_at(return_address_offset); }
|
|
||||||
address displacement_address() const { return addr_at(displacement_offset); }
|
|
||||||
int displacement() const { return (jint) int_at(displacement_offset); }
|
|
||||||
address return_address() const { return addr_at(return_address_offset); }
|
|
||||||
address destination() const;
|
|
||||||
address plt_entry() const;
|
|
||||||
address plt_jump() const;
|
|
||||||
address plt_load_got() const;
|
|
||||||
address plt_resolve_call() const;
|
|
||||||
address plt_c2i_stub() const;
|
|
||||||
void set_stub_to_clean();
|
|
||||||
|
|
||||||
void reset_to_plt_resolve_call();
|
|
||||||
void set_destination_mt_safe(address dest);
|
|
||||||
|
|
||||||
void verify() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline NativePltCall* nativePltCall_at(address address) {
|
|
||||||
NativePltCall* call = (NativePltCall*) address;
|
|
||||||
#ifdef ASSERT
|
|
||||||
call->verify();
|
|
||||||
#endif
|
|
||||||
return call;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline NativePltCall* nativePltCall_before(address addr) {
|
|
||||||
address at = addr - NativePltCall::instruction_size;
|
|
||||||
return nativePltCall_at(at);
|
|
||||||
}
|
|
||||||
|
|
||||||
class NativeCall;
|
class NativeCall;
|
||||||
inline NativeCall* nativeCall_at(address address);
|
inline NativeCall* nativeCall_at(address address);
|
||||||
// The NativeCall is an abstraction for accessing/manipulating native call imm32/rel32off
|
// The NativeCall is an abstraction for accessing/manipulating native call imm32/rel32off
|
||||||
@ -426,57 +383,6 @@ class NativeLoadAddress: public NativeMovRegMem {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// destination is rbx or rax
|
|
||||||
// mov rbx, [rip + offset]
|
|
||||||
class NativeLoadGot: public NativeInstruction {
|
|
||||||
#ifdef AMD64
|
|
||||||
static const bool has_rex = true;
|
|
||||||
static const int rex_size = 1;
|
|
||||||
#else
|
|
||||||
static const bool has_rex = false;
|
|
||||||
static const int rex_size = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum Intel_specific_constants {
|
|
||||||
rex_prefix = 0x48,
|
|
||||||
rex_b_prefix = 0x49,
|
|
||||||
instruction_code = 0x8b,
|
|
||||||
modrm_rbx_code = 0x1d,
|
|
||||||
modrm_rax_code = 0x05,
|
|
||||||
instruction_length = 6 + rex_size,
|
|
||||||
offset_offset = 2 + rex_size
|
|
||||||
};
|
|
||||||
|
|
||||||
int rip_offset() const { return int_at(offset_offset); }
|
|
||||||
address return_address() const { return addr_at(instruction_length); }
|
|
||||||
address got_address() const { return return_address() + rip_offset(); }
|
|
||||||
|
|
||||||
#ifdef ASSERT
|
|
||||||
void report_and_fail() const;
|
|
||||||
address instruction_address() const { return addr_at(0); }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public:
|
|
||||||
address next_instruction_address() const { return return_address(); }
|
|
||||||
intptr_t data() const;
|
|
||||||
void set_data(intptr_t data) {
|
|
||||||
intptr_t *addr = (intptr_t *) got_address();
|
|
||||||
*addr = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_ONLY( void verify() const );
|
|
||||||
};
|
|
||||||
|
|
||||||
inline NativeLoadGot* nativeLoadGot_at(address addr) {
|
|
||||||
NativeLoadGot* load = (NativeLoadGot*) addr;
|
|
||||||
#ifdef ASSERT
|
|
||||||
load->verify();
|
|
||||||
#endif
|
|
||||||
return load;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jump rel32off
|
|
||||||
|
|
||||||
class NativeJump: public NativeInstruction {
|
class NativeJump: public NativeInstruction {
|
||||||
public:
|
public:
|
||||||
enum Intel_specific_constants {
|
enum Intel_specific_constants {
|
||||||
@ -532,26 +438,6 @@ inline NativeJump* nativeJump_at(address address) {
|
|||||||
return jump;
|
return jump;
|
||||||
}
|
}
|
||||||
|
|
||||||
// far jump reg
|
|
||||||
class NativeFarJump: public NativeInstruction {
|
|
||||||
public:
|
|
||||||
address jump_destination() const;
|
|
||||||
|
|
||||||
// Creation
|
|
||||||
inline friend NativeFarJump* nativeFarJump_at(address address);
|
|
||||||
|
|
||||||
void verify();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
inline NativeFarJump* nativeFarJump_at(address address) {
|
|
||||||
NativeFarJump* jump = (NativeFarJump*)(address);
|
|
||||||
#ifdef ASSERT
|
|
||||||
jump->verify();
|
|
||||||
#endif
|
|
||||||
return jump;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handles all kinds of jump on Intel. Long/far, conditional/unconditional
|
// Handles all kinds of jump on Intel. Long/far, conditional/unconditional
|
||||||
class NativeGeneralJump: public NativeInstruction {
|
class NativeGeneralJump: public NativeInstruction {
|
||||||
public:
|
public:
|
||||||
@ -585,61 +471,6 @@ inline NativeGeneralJump* nativeGeneralJump_at(address address) {
|
|||||||
return jump;
|
return jump;
|
||||||
}
|
}
|
||||||
|
|
||||||
class NativeGotJump: public NativeInstruction {
|
|
||||||
enum Intel_specific_constants {
|
|
||||||
rex_prefix = 0x41,
|
|
||||||
instruction_code = 0xff,
|
|
||||||
modrm_code = 0x25,
|
|
||||||
instruction_size = 6,
|
|
||||||
rip_offset = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
bool has_rex() const { return ubyte_at(0) == rex_prefix; }
|
|
||||||
int rex_size() const { return has_rex() ? 1 : 0; }
|
|
||||||
|
|
||||||
address return_address() const { return addr_at(instruction_size + rex_size()); }
|
|
||||||
int got_offset() const { return (jint) int_at(rip_offset + rex_size()); }
|
|
||||||
|
|
||||||
#ifdef ASSERT
|
|
||||||
void report_and_fail() const;
|
|
||||||
address instruction_address() const { return addr_at(0); }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public:
|
|
||||||
address got_address() const { return return_address() + got_offset(); }
|
|
||||||
address next_instruction_address() const { return return_address(); }
|
|
||||||
bool is_GotJump() const { return ubyte_at(rex_size()) == instruction_code; }
|
|
||||||
|
|
||||||
address destination() const;
|
|
||||||
void set_jump_destination(address dest) {
|
|
||||||
address *got_entry = (address *) got_address();
|
|
||||||
*got_entry = dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_ONLY( void verify() const; )
|
|
||||||
};
|
|
||||||
|
|
||||||
inline NativeGotJump* nativeGotJump_at(address addr) {
|
|
||||||
NativeGotJump* jump = (NativeGotJump*)(addr);
|
|
||||||
debug_only(jump->verify());
|
|
||||||
return jump;
|
|
||||||
}
|
|
||||||
|
|
||||||
class NativePopReg : public NativeInstruction {
|
|
||||||
public:
|
|
||||||
enum Intel_specific_constants {
|
|
||||||
instruction_code = 0x58,
|
|
||||||
instruction_size = 1,
|
|
||||||
instruction_offset = 0,
|
|
||||||
data_offset = 1,
|
|
||||||
next_instruction_offset = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
// Insert a pop instruction
|
|
||||||
static void insert(address code_pos, Register reg);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class NativeIllegalInstruction: public NativeInstruction {
|
class NativeIllegalInstruction: public NativeInstruction {
|
||||||
public:
|
public:
|
||||||
enum Intel_specific_constants {
|
enum Intel_specific_constants {
|
||||||
@ -702,7 +533,6 @@ inline bool NativeInstruction::is_jump_reg() {
|
|||||||
if (ubyte_at(0) == Assembler::REX_B) pos = 1;
|
if (ubyte_at(0) == Assembler::REX_B) pos = 1;
|
||||||
return ubyte_at(pos) == 0xFF && (ubyte_at(pos + 1) & 0xF0) == 0xE0;
|
return ubyte_at(pos) == 0xFF && (ubyte_at(pos + 1) & 0xF0) == 0xE0;
|
||||||
}
|
}
|
||||||
inline bool NativeInstruction::is_far_jump() { return is_mov_literal64(); }
|
|
||||||
inline bool NativeInstruction::is_cond_jump() { return (int_at(0) & 0xF0FF) == 0x800F /* long jump */ ||
|
inline bool NativeInstruction::is_cond_jump() { return (int_at(0) & 0xF0FF) == 0x800F /* long jump */ ||
|
||||||
(ubyte_at(0) & 0xF0) == 0x70; /* short jump */ }
|
(ubyte_at(0) & 0xF0) == 0x70; /* short jump */ }
|
||||||
inline bool NativeInstruction::is_safepoint_poll() {
|
inline bool NativeInstruction::is_safepoint_poll() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user