--- old/src/cpu/x86/vm/nativeInst_x86.cpp 2016-11-03 14:16:03.000000000 -0700 +++ new/src/cpu/x86/vm/nativeInst_x86.cpp 2016-11-03 14:16:03.000000000 -0700 @@ -39,6 +39,124 @@ ICache::invalidate_word(addr_at(offset)); } +void NativeLoadGot::report_and_fail() const { + tty->print_cr("Addr: " INTPTR_FORMAT, p2i(instruction_address())); + fatal("not a indirect rip mov to rbx"); +} + +void NativeLoadGot::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_rbx_code && modrm != modrm_rax_code) { + report_and_fail(); + } +} + +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; +} + +void NativeGotJump::verify() const { + 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 indirect rip jump"); + } +} + void NativeCall::verify() { // Make sure code pattern is actually a call imm32 instruction. int inst = ubyte_at(0); @@ -422,7 +540,12 @@ void NativeJump::verify() { if (*(u_char*)instruction_address() != instruction_code) { - fatal("not a jump instruction"); + // far jump + NativeMovConstReg* mov = nativeMovConstReg_at(instruction_address()); + NativeInstruction* jmp = nativeInstruction_at(mov->next_instruction_address()); + if (!jmp->is_jump_reg()) { + fatal("not a jump instruction"); + } } } @@ -514,6 +637,20 @@ } +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");