37 |
37 |
38 void NativeInstruction::wrote(int offset) { |
38 void NativeInstruction::wrote(int offset) { |
39 ICache::invalidate_word(addr_at(offset)); |
39 ICache::invalidate_word(addr_at(offset)); |
40 } |
40 } |
41 |
41 |
|
42 void NativeLoadGot::report_and_fail() const { |
|
43 tty->print_cr("Addr: " INTPTR_FORMAT, p2i(instruction_address())); |
|
44 fatal("not a indirect rip mov to rbx"); |
|
45 } |
|
46 |
|
47 void NativeLoadGot::verify() const { |
|
48 if (has_rex) { |
|
49 int rex = ubyte_at(0); |
|
50 if (rex != rex_prefix) { |
|
51 report_and_fail(); |
|
52 } |
|
53 } |
|
54 |
|
55 int inst = ubyte_at(rex_size); |
|
56 if (inst != instruction_code) { |
|
57 report_and_fail(); |
|
58 } |
|
59 int modrm = ubyte_at(rex_size + 1); |
|
60 if (modrm != modrm_rbx_code && modrm != modrm_rax_code) { |
|
61 report_and_fail(); |
|
62 } |
|
63 } |
|
64 |
|
65 intptr_t NativeLoadGot::data() const { |
|
66 return *(intptr_t *) got_address(); |
|
67 } |
|
68 |
|
69 address NativePltCall::destination() const { |
|
70 NativeGotJump* jump = nativeGotJump_at(plt_jump()); |
|
71 return jump->destination(); |
|
72 } |
|
73 |
|
74 address NativePltCall::plt_entry() const { |
|
75 return return_address() + displacement(); |
|
76 } |
|
77 |
|
78 address NativePltCall::plt_jump() const { |
|
79 address entry = plt_entry(); |
|
80 // Virtual PLT code has move instruction first |
|
81 if (((NativeGotJump*)entry)->is_GotJump()) { |
|
82 return entry; |
|
83 } else { |
|
84 return nativeLoadGot_at(entry)->next_instruction_address(); |
|
85 } |
|
86 } |
|
87 |
|
88 address NativePltCall::plt_load_got() const { |
|
89 address entry = plt_entry(); |
|
90 if (!((NativeGotJump*)entry)->is_GotJump()) { |
|
91 // Virtual PLT code has move instruction first |
|
92 return entry; |
|
93 } else { |
|
94 // Static PLT code has move instruction second (from c2i stub) |
|
95 return nativeGotJump_at(entry)->next_instruction_address(); |
|
96 } |
|
97 } |
|
98 |
|
99 address NativePltCall::plt_c2i_stub() const { |
|
100 address entry = plt_load_got(); |
|
101 // This method should be called only for static calls which has C2I stub. |
|
102 NativeLoadGot* load = nativeLoadGot_at(entry); |
|
103 return entry; |
|
104 } |
|
105 |
|
106 address NativePltCall::plt_resolve_call() const { |
|
107 NativeGotJump* jump = nativeGotJump_at(plt_jump()); |
|
108 address entry = jump->next_instruction_address(); |
|
109 if (((NativeGotJump*)entry)->is_GotJump()) { |
|
110 return entry; |
|
111 } else { |
|
112 // c2i stub 2 instructions |
|
113 entry = nativeLoadGot_at(entry)->next_instruction_address(); |
|
114 return nativeGotJump_at(entry)->next_instruction_address(); |
|
115 } |
|
116 } |
|
117 |
|
118 void NativePltCall::reset_to_plt_resolve_call() { |
|
119 set_destination_mt_safe(plt_resolve_call()); |
|
120 } |
|
121 |
|
122 void NativePltCall::set_destination_mt_safe(address dest) { |
|
123 // rewriting the value in the GOT, it should always be aligned |
|
124 NativeGotJump* jump = nativeGotJump_at(plt_jump()); |
|
125 address* got = (address *) jump->got_address(); |
|
126 *got = dest; |
|
127 } |
|
128 |
|
129 void NativePltCall::set_stub_to_clean() { |
|
130 NativeLoadGot* method_loader = nativeLoadGot_at(plt_c2i_stub()); |
|
131 NativeGotJump* jump = nativeGotJump_at(method_loader->next_instruction_address()); |
|
132 method_loader->set_data(0); |
|
133 jump->set_jump_destination((address)-1); |
|
134 } |
|
135 |
|
136 void NativePltCall::verify() const { |
|
137 // Make sure code pattern is actually a call rip+off32 instruction. |
|
138 int inst = ubyte_at(0); |
|
139 if (inst != instruction_code) { |
|
140 tty->print_cr("Addr: " INTPTR_FORMAT " Code: 0x%x", p2i(instruction_address()), |
|
141 inst); |
|
142 fatal("not a call rip+off32"); |
|
143 } |
|
144 } |
|
145 |
|
146 address NativeGotJump::destination() const { |
|
147 address *got_entry = (address *) got_address(); |
|
148 return *got_entry; |
|
149 } |
|
150 |
|
151 void NativeGotJump::verify() const { |
|
152 int inst = ubyte_at(0); |
|
153 if (inst != instruction_code) { |
|
154 tty->print_cr("Addr: " INTPTR_FORMAT " Code: 0x%x", p2i(instruction_address()), |
|
155 inst); |
|
156 fatal("not a indirect rip jump"); |
|
157 } |
|
158 } |
|
159 |
42 void NativeCall::verify() { |
160 void NativeCall::verify() { |
43 // Make sure code pattern is actually a call imm32 instruction. |
161 // Make sure code pattern is actually a call imm32 instruction. |
44 int inst = ubyte_at(0); |
162 int inst = ubyte_at(0); |
45 if (inst != instruction_code) { |
163 if (inst != instruction_code) { |
46 tty->print_cr("Addr: " INTPTR_FORMAT " Code: 0x%x", p2i(instruction_address()), |
164 tty->print_cr("Addr: " INTPTR_FORMAT " Code: 0x%x", p2i(instruction_address()), |
512 // Invalidate. Opteron requires a flush after every write. |
635 // Invalidate. Opteron requires a flush after every write. |
513 n_jump->wrote(0); |
636 n_jump->wrote(0); |
514 |
637 |
515 } |
638 } |
516 |
639 |
|
640 address NativeFarJump::jump_destination() const { |
|
641 NativeMovConstReg* mov = nativeMovConstReg_at(addr_at(0)); |
|
642 return (address)mov->data(); |
|
643 } |
|
644 |
|
645 void NativeFarJump::verify() { |
|
646 if (is_far_jump()) { |
|
647 NativeMovConstReg* mov = nativeMovConstReg_at(addr_at(0)); |
|
648 NativeInstruction* jmp = nativeInstruction_at(mov->next_instruction_address()); |
|
649 if (jmp->is_jump_reg()) return; |
|
650 } |
|
651 fatal("not a jump instruction"); |
|
652 } |
|
653 |
517 void NativePopReg::insert(address code_pos, Register reg) { |
654 void NativePopReg::insert(address code_pos, Register reg) { |
518 assert(reg->encoding() < 8, "no space for REX"); |
655 assert(reg->encoding() < 8, "no space for REX"); |
519 assert(NativePopReg::instruction_size == sizeof(char), "right address unit for update"); |
656 assert(NativePopReg::instruction_size == sizeof(char), "right address unit for update"); |
520 *code_pos = (u_char)(instruction_code | reg->encoding()); |
657 *code_pos = (u_char)(instruction_code | reg->encoding()); |
521 ICache::invalidate_range(code_pos, instruction_size); |
658 ICache::invalidate_range(code_pos, instruction_size); |