Bug Summary

File:jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp
Warning:line 541, column 21
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name nativeInst_x86.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/libjvm/objs/precompiled -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D _GNU_SOURCE -D _REENTRANT -D LIBC=gnu -D LINUX -D VM_LITTLE_ENDIAN -D _LP64=1 -D ASSERT -D CHECK_UNHANDLED_OOPS -D TARGET_ARCH_x86 -D INCLUDE_SUFFIX_OS=_linux -D INCLUDE_SUFFIX_CPU=_x86 -D INCLUDE_SUFFIX_COMPILER=_gcc -D TARGET_COMPILER_gcc -D AMD64 -D HOTSPOT_LIB_ARCH="amd64" -D COMPILER1 -D COMPILER2 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc/adfiles -I /home/daniel/Projects/java/jdk/src/hotspot/share -I /home/daniel/Projects/java/jdk/src/hotspot/os/linux -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix -I /home/daniel/Projects/java/jdk/src/hotspot/cpu/x86 -I /home/daniel/Projects/java/jdk/src/hotspot/os_cpu/linux_x86 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc -I /home/daniel/Projects/java/jdk/src/hotspot/share/precompiled -I /home/daniel/Projects/java/jdk/src/hotspot/share/include -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix/include -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base/linux -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjimage -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc/adfiles -I /home/daniel/Projects/java/jdk/src/hotspot/share -I /home/daniel/Projects/java/jdk/src/hotspot/os/linux -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix -I /home/daniel/Projects/java/jdk/src/hotspot/cpu/x86 -I /home/daniel/Projects/java/jdk/src/hotspot/os_cpu/linux_x86 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc -D _FORTIFY_SOURCE=2 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-format-zero-length -Wno-unused-parameter -Wno-unused -Wno-parentheses -Wno-comment -Wno-unknown-pragmas -Wno-address -Wno-delete-non-virtual-dtor -Wno-char-subscripts -Wno-array-bounds -Wno-int-in-bool-context -Wno-ignored-qualifiers -Wno-missing-field-initializers -Wno-implicit-fallthrough -Wno-empty-body -Wno-strict-overflow -Wno-sequence-point -Wno-maybe-uninitialized -Wno-misleading-indentation -Wno-cast-function-type -Wno-shift-negative-value -std=c++14 -fdeprecated-macro -fdebug-compilation-dir /home/daniel/Projects/java/jdk/make/hotspot -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -stack-protector 1 -fno-rtti -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/daniel/Projects/java/scan/2021-12-21-193737-8510-1 -x c++ /home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp
1/*
2 * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25#include "precompiled.hpp"
26#include "asm/macroAssembler.hpp"
27#include "code/compiledIC.hpp"
28#include "memory/resourceArea.hpp"
29#include "nativeInst_x86.hpp"
30#include "oops/oop.inline.hpp"
31#include "runtime/handles.hpp"
32#include "runtime/safepoint.hpp"
33#include "runtime/sharedRuntime.hpp"
34#include "runtime/stubRoutines.hpp"
35#include "utilities/ostream.hpp"
36#ifdef COMPILER11
37#include "c1/c1_Runtime1.hpp"
38#endif
39
40void NativeInstruction::wrote(int offset) {
41 ICache::invalidate_word(addr_at(offset));
42}
43
44#ifdef ASSERT1
45void NativeLoadGot::report_and_fail() const {
46 tty->print_cr("Addr: " INTPTR_FORMAT"0x%016" "l" "x" " Code: %x %x %x", p2i(instruction_address()),
47 (has_rex ? ubyte_at(0) : 0), ubyte_at(rex_size), ubyte_at(rex_size + 1));
48 fatal("not a indirect rip mov to rbx")do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 48, "not a indirect rip mov to rbx"); ::breakpoint(); } while
(0)
;
49}
50
51void NativeLoadGot::verify() const {
52 if (has_rex) {
53 int rex = ubyte_at(0);
54 if (rex != rex_prefix && rex != rex_b_prefix) {
55 report_and_fail();
56 }
57 }
58
59 int inst = ubyte_at(rex_size);
60 if (inst != instruction_code) {
61 report_and_fail();
62 }
63 int modrm = ubyte_at(rex_size + 1);
64 if (modrm != modrm_rbx_code && modrm != modrm_rax_code) {
65 report_and_fail();
66 }
67}
68#endif
69
70intptr_t NativeLoadGot::data() const {
71 return *(intptr_t *) got_address();
72}
73
74address NativePltCall::destination() const {
75 NativeGotJump* jump = nativeGotJump_at(plt_jump());
76 return jump->destination();
77}
78
79address NativePltCall::plt_entry() const {
80 return return_address() + displacement();
81}
82
83address NativePltCall::plt_jump() const {
84 address entry = plt_entry();
85 // Virtual PLT code has move instruction first
86 if (((NativeGotJump*)entry)->is_GotJump()) {
87 return entry;
88 } else {
89 return nativeLoadGot_at(entry)->next_instruction_address();
90 }
91}
92
93address NativePltCall::plt_load_got() const {
94 address entry = plt_entry();
95 if (!((NativeGotJump*)entry)->is_GotJump()) {
96 // Virtual PLT code has move instruction first
97 return entry;
98 } else {
99 // Static PLT code has move instruction second (from c2i stub)
100 return nativeGotJump_at(entry)->next_instruction_address();
101 }
102}
103
104address NativePltCall::plt_c2i_stub() const {
105 address entry = plt_load_got();
106 // This method should be called only for static calls which has C2I stub.
107 NativeLoadGot* load = nativeLoadGot_at(entry);
108 return entry;
109}
110
111address NativePltCall::plt_resolve_call() const {
112 NativeGotJump* jump = nativeGotJump_at(plt_jump());
113 address entry = jump->next_instruction_address();
114 if (((NativeGotJump*)entry)->is_GotJump()) {
115 return entry;
116 } else {
117 // c2i stub 2 instructions
118 entry = nativeLoadGot_at(entry)->next_instruction_address();
119 return nativeGotJump_at(entry)->next_instruction_address();
120 }
121}
122
123void NativePltCall::reset_to_plt_resolve_call() {
124 set_destination_mt_safe(plt_resolve_call());
125}
126
127void NativePltCall::set_destination_mt_safe(address dest) {
128 // rewriting the value in the GOT, it should always be aligned
129 NativeGotJump* jump = nativeGotJump_at(plt_jump());
130 address* got = (address *) jump->got_address();
131 *got = dest;
132}
133
134void NativePltCall::set_stub_to_clean() {
135 NativeLoadGot* method_loader = nativeLoadGot_at(plt_c2i_stub());
136 NativeGotJump* jump = nativeGotJump_at(method_loader->next_instruction_address());
137 method_loader->set_data(0);
138 jump->set_jump_destination((address)-1);
139}
140
141void NativePltCall::verify() const {
142 // Make sure code pattern is actually a call rip+off32 instruction.
143 int inst = ubyte_at(0);
144 if (inst != instruction_code) {
145 tty->print_cr("Addr: " INTPTR_FORMAT"0x%016" "l" "x" " Code: 0x%x", p2i(instruction_address()),
146 inst);
147 fatal("not a call rip+off32")do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 147, "not a call rip+off32"); ::breakpoint(); } while (0)
;
148 }
149}
150
151address NativeGotJump::destination() const {
152 address *got_entry = (address *) got_address();
153 return *got_entry;
154}
155
156#ifdef ASSERT1
157void NativeGotJump::report_and_fail() const {
158 tty->print_cr("Addr: " INTPTR_FORMAT"0x%016" "l" "x" " Code: %x %x %x", p2i(instruction_address()),
159 (has_rex() ? ubyte_at(0) : 0), ubyte_at(rex_size()), ubyte_at(rex_size() + 1));
160 fatal("not a indirect rip jump")do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 160, "not a indirect rip jump"); ::breakpoint(); } while (0
)
;
161}
162
163void NativeGotJump::verify() const {
164 if (has_rex()) {
165 int rex = ubyte_at(0);
166 if (rex != rex_prefix) {
167 report_and_fail();
168 }
169 }
170 int inst = ubyte_at(rex_size());
171 if (inst != instruction_code) {
172 report_and_fail();
173 }
174 int modrm = ubyte_at(rex_size() + 1);
175 if (modrm != modrm_code) {
176 report_and_fail();
177 }
178}
179#endif
180
181void NativeCall::verify() {
182 // Make sure code pattern is actually a call imm32 instruction.
183 int inst = ubyte_at(0);
184 if (inst != instruction_code) {
185 tty->print_cr("Addr: " INTPTR_FORMAT"0x%016" "l" "x" " Code: 0x%x", p2i(instruction_address()),
186 inst);
187 fatal("not a call disp32")do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 187, "not a call disp32"); ::breakpoint(); } while (0)
;
188 }
189}
190
191address NativeCall::destination() const {
192 // Getting the destination of a call isn't safe because that call can
193 // be getting patched while you're calling this. There's only special
194 // places where this can be called but not automatically verifiable by
195 // checking which locks are held. The solution is true atomic patching
196 // on x86, nyi.
197 return return_address() + displacement();
198}
199
200void NativeCall::print() {
201 tty->print_cr(PTR_FORMAT"0x%016" "l" "x" ": call " PTR_FORMAT"0x%016" "l" "x",
202 p2i(instruction_address()), p2i(destination()));
203}
204
205// Inserts a native call instruction at a given pc
206void NativeCall::insert(address code_pos, address entry) {
207 intptr_t disp = (intptr_t)entry - ((intptr_t)code_pos + 1 + 4);
208#ifdef AMD641
209 guarantee(disp == (intptr_t)(jint)disp, "must be 32-bit offset")do { if (!(disp == (intptr_t)(jint)disp)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 209, "guarantee(" "disp == (intptr_t)(jint)disp" ") failed"
, "must be 32-bit offset"); ::breakpoint(); } } while (0)
;
210#endif // AMD64
211 *code_pos = instruction_code;
212 *((int32_t *)(code_pos+1)) = (int32_t) disp;
213 ICache::invalidate_range(code_pos, instruction_size);
214}
215
216// MT-safe patching of a call instruction.
217// First patches first word of instruction to two jmp's that jmps to them
218// selfs (spinlock). Then patches the last byte, and then atomicly replaces
219// the jmp's with the first 4 byte of the new instruction.
220void NativeCall::replace_mt_safe(address instr_addr, address code_buffer) {
221 assert(Patching_lock->is_locked() ||do { if (!(Patching_lock->is_locked() || SafepointSynchronize
::is_at_safepoint())) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 222, "assert(" "Patching_lock->is_locked() || SafepointSynchronize::is_at_safepoint()"
") failed", "concurrent code patching"); ::breakpoint(); } }
while (0)
222 SafepointSynchronize::is_at_safepoint(), "concurrent code patching")do { if (!(Patching_lock->is_locked() || SafepointSynchronize
::is_at_safepoint())) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 222, "assert(" "Patching_lock->is_locked() || SafepointSynchronize::is_at_safepoint()"
") failed", "concurrent code patching"); ::breakpoint(); } }
while (0)
;
223 assert (instr_addr != NULL, "illegal address for code patching")do { if (!(instr_addr != __null)) { (*g_assert_poison) = 'X';
; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 223, "assert(" "instr_addr != __null" ") failed", "illegal address for code patching"
); ::breakpoint(); } } while (0)
;
224
225 NativeCall* n_call = nativeCall_at (instr_addr); // checking that it is a call
226 guarantee((intptr_t)instr_addr % BytesPerWord == 0, "must be aligned")do { if (!((intptr_t)instr_addr % BytesPerWord == 0)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 226, "guarantee(" "(intptr_t)instr_addr % BytesPerWord == 0"
") failed", "must be aligned"); ::breakpoint(); } } while (0
)
;
227
228 // First patch dummy jmp in place
229 unsigned char patch[4];
230 assert(sizeof(patch)==sizeof(jint), "sanity check")do { if (!(sizeof(patch)==sizeof(jint))) { (*g_assert_poison)
= 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 230, "assert(" "sizeof(patch)==sizeof(jint)" ") failed", "sanity check"
); ::breakpoint(); } } while (0)
;
231 patch[0] = 0xEB; // jmp rel8
232 patch[1] = 0xFE; // jmp to self
233 patch[2] = 0xEB;
234 patch[3] = 0xFE;
235
236 // First patch dummy jmp in place
237 *(jint*)instr_addr = *(jint *)patch;
238
239 // Invalidate. Opteron requires a flush after every write.
240 n_call->wrote(0);
241
242 // Patch 4th byte
243 instr_addr[4] = code_buffer[4];
244
245 n_call->wrote(4);
246
247 // Patch bytes 0-3
248 *(jint*)instr_addr = *(jint *)code_buffer;
249
250 n_call->wrote(0);
251
252#ifdef ASSERT1
253 // verify patching
254 for ( int i = 0; i < instruction_size; i++) {
255 address ptr = (address)((intptr_t)code_buffer + i);
256 int a_byte = (*ptr) & 0xFF;
257 assert(*((address)((intptr_t)instr_addr + i)) == a_byte, "mt safe patching failed")do { if (!(*((address)((intptr_t)instr_addr + i)) == a_byte))
{ (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 257, "assert(" "*((address)((intptr_t)instr_addr + i)) == a_byte"
") failed", "mt safe patching failed"); ::breakpoint(); } } while
(0)
;
258 }
259#endif
260
261}
262
263bool NativeCall::is_displacement_aligned() {
264 return (uintptr_t) displacement_address() % 4 == 0;
265}
266
267// Similar to replace_mt_safe, but just changes the destination. The
268// important thing is that free-running threads are able to execute this
269// call instruction at all times. If the displacement field is aligned
270// we can simply rely on atomicity of 32-bit writes to make sure other threads
271// will see no intermediate states. Otherwise, the first two bytes of the
272// call are guaranteed to be aligned, and can be atomically patched to a
273// self-loop to guard the instruction while we change the other bytes.
274
275// We cannot rely on locks here, since the free-running threads must run at
276// full speed.
277//
278// Used in the runtime linkage of calls; see class CompiledIC.
279// (Cf. 4506997 and 4479829, where threads witnessed garbage displacements.)
280void NativeCall::set_destination_mt_safe(address dest) {
281 debug_only(verify())verify();
282 // Make sure patching code is locked. No two threads can patch at the same
283 // time but one may be executing this code.
284 assert(Patching_lock->is_locked() || SafepointSynchronize::is_at_safepoint() ||do { if (!(Patching_lock->is_locked() || SafepointSynchronize
::is_at_safepoint() || CompiledICLocker::is_safe(instruction_address
()))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 285, "assert(" "Patching_lock->is_locked() || SafepointSynchronize::is_at_safepoint() || CompiledICLocker::is_safe(instruction_address())"
") failed", "concurrent code patching"); ::breakpoint(); } }
while (0)
285 CompiledICLocker::is_safe(instruction_address()), "concurrent code patching")do { if (!(Patching_lock->is_locked() || SafepointSynchronize
::is_at_safepoint() || CompiledICLocker::is_safe(instruction_address
()))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 285, "assert(" "Patching_lock->is_locked() || SafepointSynchronize::is_at_safepoint() || CompiledICLocker::is_safe(instruction_address())"
") failed", "concurrent code patching"); ::breakpoint(); } }
while (0)
;
286 // Both C1 and C2 should now be generating code which aligns the patched address
287 // to be within a single cache line.
288 bool is_aligned = is_displacement_aligned();
289
290 guarantee(is_aligned, "destination must be aligned")do { if (!(is_aligned)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 290, "guarantee(" "is_aligned" ") failed", "destination must be aligned"
); ::breakpoint(); } } while (0)
;
291
292 // The destination lies within a single cache line.
293 set_destination(dest);
294}
295
296
297void NativeMovConstReg::verify() {
298#ifdef AMD641
299 // make sure code pattern is actually a mov reg64, imm64 instruction
300 if ((ubyte_at(0) != Assembler::REX_W && ubyte_at(0) != Assembler::REX_WB) ||
301 (ubyte_at(1) & (0xff ^ register_mask)) != 0xB8) {
302 print();
303 fatal("not a REX.W[B] mov reg64, imm64")do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 303, "not a REX.W[B] mov reg64, imm64"); ::breakpoint(); } while
(0)
;
304 }
305#else
306 // make sure code pattern is actually a mov reg, imm32 instruction
307 u_char test_byte = *(u_char*)instruction_address();
308 u_char test_byte_2 = test_byte & ( 0xff ^ register_mask);
309 if (test_byte_2 != instruction_code) fatal("not a mov reg, imm32")do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 309, "not a mov reg, imm32"); ::breakpoint(); } while (0)
;
310#endif // AMD64
311}
312
313
314void NativeMovConstReg::print() {
315 tty->print_cr(PTR_FORMAT"0x%016" "l" "x" ": mov reg, " INTPTR_FORMAT"0x%016" "l" "x",
316 p2i(instruction_address()), data());
317}
318
319//-------------------------------------------------------------------
320
321int NativeMovRegMem::instruction_start() const {
322 int off = 0;
323 u_char instr_0 = ubyte_at(off);
324
325 // See comment in Assembler::locate_operand() about VEX prefixes.
326 if (instr_0 == instruction_VEX_prefix_2bytes) {
327 assert((UseAVX > 0), "shouldn't have VEX prefix")do { if (!((UseAVX > 0))) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 327, "assert(" "(UseAVX > 0)" ") failed", "shouldn't have VEX prefix"
); ::breakpoint(); } } while (0)
;
328 NOT_LP64(assert((0xC0 & ubyte_at(1)) == 0xC0, "shouldn't have LDS and LES instructions"));
329 return 2;
330 }
331 if (instr_0 == instruction_VEX_prefix_3bytes) {
332 assert((UseAVX > 0), "shouldn't have VEX prefix")do { if (!((UseAVX > 0))) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 332, "assert(" "(UseAVX > 0)" ") failed", "shouldn't have VEX prefix"
); ::breakpoint(); } } while (0)
;
333 NOT_LP64(assert((0xC0 & ubyte_at(1)) == 0xC0, "shouldn't have LDS and LES instructions"));
334 return 3;
335 }
336 if (instr_0 == instruction_EVEX_prefix_4bytes) {
337 assert(VM_Version::supports_evex(), "shouldn't have EVEX prefix")do { if (!(VM_Version::supports_evex())) { (*g_assert_poison)
= 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 337, "assert(" "VM_Version::supports_evex()" ") failed", "shouldn't have EVEX prefix"
); ::breakpoint(); } } while (0)
;
338 return 4;
339 }
340
341 // First check to see if we have a (prefixed or not) xor
342 if (instr_0 >= instruction_prefix_wide_lo && // 0x40
343 instr_0 <= instruction_prefix_wide_hi) { // 0x4f
344 off++;
345 instr_0 = ubyte_at(off);
346 }
347
348 if (instr_0 == instruction_code_xor) {
349 off += 2;
350 instr_0 = ubyte_at(off);
351 }
352
353 // Now look for the real instruction and the many prefix/size specifiers.
354
355 if (instr_0 == instruction_operandsize_prefix ) { // 0x66
356 off++; // Not SSE instructions
357 instr_0 = ubyte_at(off);
358 }
359
360 if ( instr_0 == instruction_code_xmm_ss_prefix || // 0xf3
361 instr_0 == instruction_code_xmm_sd_prefix) { // 0xf2
362 off++;
363 instr_0 = ubyte_at(off);
364 }
365
366 if ( instr_0 >= instruction_prefix_wide_lo && // 0x40
367 instr_0 <= instruction_prefix_wide_hi) { // 0x4f
368 off++;
369 instr_0 = ubyte_at(off);
370 }
371
372
373 if (instr_0 == instruction_extended_prefix ) { // 0x0f
374 off++;
375 }
376
377 return off;
378}
379
380int NativeMovRegMem::patch_offset() const {
381 int off = data_offset + instruction_start();
382 u_char mod_rm = *(u_char*)(instruction_address() + 1);
383 // nnnn(r12|rsp) isn't coded as simple mod/rm since that is
384 // the encoding to use an SIB byte. Which will have the nnnn
385 // field off by one byte
386 if ((mod_rm & 7) == 0x4) {
387 off++;
388 }
389 return off;
390}
391
392void NativeMovRegMem::verify() {
393 // make sure code pattern is actually a mov [reg+offset], reg instruction
394 u_char test_byte = *(u_char*)instruction_address();
395 switch (test_byte) {
396 case instruction_code_reg2memb: // 0x88 movb a, r
397 case instruction_code_reg2mem: // 0x89 movl a, r (can be movq in 64bit)
398 case instruction_code_mem2regb: // 0x8a movb r, a
399 case instruction_code_mem2reg: // 0x8b movl r, a (can be movq in 64bit)
400 break;
401
402 case instruction_code_mem2reg_movslq: // 0x63 movsql r, a
403 case instruction_code_mem2reg_movzxb: // 0xb6 movzbl r, a (movzxb)
404 case instruction_code_mem2reg_movzxw: // 0xb7 movzwl r, a (movzxw)
405 case instruction_code_mem2reg_movsxb: // 0xbe movsbl r, a (movsxb)
406 case instruction_code_mem2reg_movsxw: // 0xbf movswl r, a (movsxw)
407 break;
408
409 case instruction_code_float_s: // 0xd9 fld_s a
410 case instruction_code_float_d: // 0xdd fld_d a
411 case instruction_code_xmm_load: // 0x10 movsd xmm, a
412 case instruction_code_xmm_store: // 0x11 movsd a, xmm
413 case instruction_code_xmm_lpd: // 0x12 movlpd xmm, a
414 break;
415
416 case instruction_code_lea: // 0x8d lea r, a
417 break;
418
419 default:
420 fatal ("not a mov [reg+offs], reg instruction")do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 420, "not a mov [reg+offs], reg instruction"); ::breakpoint
(); } while (0)
;
421 }
422}
423
424
425void NativeMovRegMem::print() {
426 tty->print_cr(PTR_FORMAT"0x%016" "l" "x" ": mov reg, [reg + %x]", p2i(instruction_address()), offset());
427}
428
429//-------------------------------------------------------------------
430
431void NativeLoadAddress::verify() {
432 // make sure code pattern is actually a mov [reg+offset], reg instruction
433 u_char test_byte = *(u_char*)instruction_address();
434#ifdef _LP641
435 if ( (test_byte == instruction_prefix_wide ||
436 test_byte == instruction_prefix_wide_extended) ) {
437 test_byte = *(u_char*)(instruction_address() + 1);
438 }
439#endif // _LP64
440 if ( ! ((test_byte == lea_instruction_code)
441 LP64_ONLY(|| (test_byte == mov64_instruction_code) )|| (test_byte == mov64_instruction_code))) {
442 fatal ("not a lea reg, [reg+offs] instruction")do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 442, "not a lea reg, [reg+offs] instruction"); ::breakpoint
(); } while (0)
;
443 }
444}
445
446
447void NativeLoadAddress::print() {
448 tty->print_cr(PTR_FORMAT"0x%016" "l" "x" ": lea [reg + %x], reg", p2i(instruction_address()), offset());
449}
450
451//--------------------------------------------------------------------------------
452
453void NativeJump::verify() {
454 if (*(u_char*)instruction_address() != instruction_code) {
455 // far jump
456 NativeMovConstReg* mov = nativeMovConstReg_at(instruction_address());
457 NativeInstruction* jmp = nativeInstruction_at(mov->next_instruction_address());
458 if (!jmp->is_jump_reg()) {
459 fatal("not a jump instruction")do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 459, "not a jump instruction"); ::breakpoint(); } while (0)
;
460 }
461 }
462}
463
464
465void NativeJump::insert(address code_pos, address entry) {
466 intptr_t disp = (intptr_t)entry - ((intptr_t)code_pos + 1 + 4);
467#ifdef AMD641
468 guarantee(disp == (intptr_t)(int32_t)disp, "must be 32-bit offset")do { if (!(disp == (intptr_t)(int32_t)disp)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 468, "guarantee(" "disp == (intptr_t)(int32_t)disp" ") failed"
, "must be 32-bit offset"); ::breakpoint(); } } while (0)
;
469#endif // AMD64
470
471 *code_pos = instruction_code;
472 *((int32_t*)(code_pos + 1)) = (int32_t)disp;
473
474 ICache::invalidate_range(code_pos, instruction_size);
475}
476
477void NativeJump::check_verified_entry_alignment(address entry, address verified_entry) {
478 // Patching to not_entrant can happen while activations of the method are
479 // in use. The patching in that instance must happen only when certain
480 // alignment restrictions are true. These guarantees check those
481 // conditions.
482#ifdef AMD641
483 const int linesize = 64;
484#else
485 const int linesize = 32;
486#endif // AMD64
487
488 // Must be wordSize aligned
489 guarantee(((uintptr_t) verified_entry & (wordSize -1)) == 0,do { if (!(((uintptr_t) verified_entry & (wordSize -1)) ==
0)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 490, "guarantee(" "((uintptr_t) verified_entry & (wordSize -1)) == 0"
") failed", "illegal address for code patching 2"); ::breakpoint
(); } } while (0)
490 "illegal address for code patching 2")do { if (!(((uintptr_t) verified_entry & (wordSize -1)) ==
0)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 490, "guarantee(" "((uintptr_t) verified_entry & (wordSize -1)) == 0"
") failed", "illegal address for code patching 2"); ::breakpoint
(); } } while (0)
;
491 // First 5 bytes must be within the same cache line - 4827828
492 guarantee((uintptr_t) verified_entry / linesize ==do { if (!((uintptr_t) verified_entry / linesize == ((uintptr_t
) verified_entry + 4) / linesize)) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 494, "guarantee(" "(uintptr_t) verified_entry / linesize == ((uintptr_t) verified_entry + 4) / linesize"
") failed", "illegal address for code patching 3"); ::breakpoint
(); } } while (0)
493 ((uintptr_t) verified_entry + 4) / linesize,do { if (!((uintptr_t) verified_entry / linesize == ((uintptr_t
) verified_entry + 4) / linesize)) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 494, "guarantee(" "(uintptr_t) verified_entry / linesize == ((uintptr_t) verified_entry + 4) / linesize"
") failed", "illegal address for code patching 3"); ::breakpoint
(); } } while (0)
494 "illegal address for code patching 3")do { if (!((uintptr_t) verified_entry / linesize == ((uintptr_t
) verified_entry + 4) / linesize)) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 494, "guarantee(" "(uintptr_t) verified_entry / linesize == ((uintptr_t) verified_entry + 4) / linesize"
") failed", "illegal address for code patching 3"); ::breakpoint
(); } } while (0)
;
495}
496
497
498// MT safe inserting of a jump over an unknown instruction sequence (used by nmethod::makeZombie)
499// The problem: jmp <dest> is a 5-byte instruction. Atomical write can be only with 4 bytes.
500// First patches the first word atomically to be a jump to itself.
501// Then patches the last byte and then atomically patches the first word (4-bytes),
502// thus inserting the desired jump
503// This code is mt-safe with the following conditions: entry point is 4 byte aligned,
504// entry point is in same cache line as unverified entry point, and the instruction being
505// patched is >= 5 byte (size of patch).
506//
507// In C2 the 5+ byte sized instruction is enforced by code in MachPrologNode::emit.
508// In C1 the restriction is enforced by CodeEmitter::method_entry
509// In JVMCI, the restriction is enforced by HotSpotFrameContext.enter(...)
510//
511void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) {
512 // complete jump instruction (to be inserted) is in code_buffer;
513 unsigned char code_buffer[5];
514 code_buffer[0] = instruction_code;
515 intptr_t disp = (intptr_t)dest - ((intptr_t)verified_entry + 1 + 4);
516#ifdef AMD641
517 guarantee(disp == (intptr_t)(int32_t)disp, "must be 32-bit offset")do { if (!(disp == (intptr_t)(int32_t)disp)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 517, "guarantee(" "disp == (intptr_t)(int32_t)disp" ") failed"
, "must be 32-bit offset"); ::breakpoint(); } } while (0)
;
1
Taking false branch
2
Loop condition is false. Exiting loop
518#endif // AMD64
519 *(int32_t*)(code_buffer + 1) = (int32_t)disp;
520
521 check_verified_entry_alignment(entry, verified_entry);
522
523 // Can't call nativeJump_at() because it's asserts jump exists
524 NativeJump* n_jump = (NativeJump*) verified_entry;
525
526 //First patch dummy jmp in place
527
528 unsigned char patch[4];
529 assert(sizeof(patch)==sizeof(int32_t), "sanity check")do { if (!(sizeof(patch)==sizeof(int32_t))) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 529, "assert(" "sizeof(patch)==sizeof(int32_t)" ") failed",
"sanity check"); ::breakpoint(); } } while (0)
;
3
Taking false branch
4
Loop condition is false. Exiting loop
530 patch[0] = 0xEB; // jmp rel8
531 patch[1] = 0xFE; // jmp to self
532 patch[2] = 0xEB;
533 patch[3] = 0xFE;
534
535 // First patch dummy jmp in place
536 *(int32_t*)verified_entry = *(int32_t *)patch;
537
538 n_jump->wrote(0);
539
540 // Patch 5th byte (from jump instruction)
541 verified_entry[4] = code_buffer[4];
5
Assigned value is garbage or undefined
542
543 n_jump->wrote(4);
544
545 // Patch bytes 0-3 (from jump instruction)
546 *(int32_t*)verified_entry = *(int32_t *)code_buffer;
547 // Invalidate. Opteron requires a flush after every write.
548 n_jump->wrote(0);
549
550}
551
552address NativeFarJump::jump_destination() const {
553 NativeMovConstReg* mov = nativeMovConstReg_at(addr_at(0));
554 return (address)mov->data();
555}
556
557void NativeFarJump::verify() {
558 if (is_far_jump()) {
559 NativeMovConstReg* mov = nativeMovConstReg_at(addr_at(0));
560 NativeInstruction* jmp = nativeInstruction_at(mov->next_instruction_address());
561 if (jmp->is_jump_reg()) return;
562 }
563 fatal("not a jump instruction")do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 563, "not a jump instruction"); ::breakpoint(); } while (0)
;
564}
565
566void NativePopReg::insert(address code_pos, Register reg) {
567 assert(reg->encoding() < 8, "no space for REX")do { if (!(reg->encoding() < 8)) { (*g_assert_poison) =
'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 567, "assert(" "reg->encoding() < 8" ") failed", "no space for REX"
); ::breakpoint(); } } while (0)
;
568 assert(NativePopReg::instruction_size == sizeof(char), "right address unit for update")do { if (!(NativePopReg::instruction_size == sizeof(char))) {
(*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 568, "assert(" "NativePopReg::instruction_size == sizeof(char)"
") failed", "right address unit for update"); ::breakpoint()
; } } while (0)
;
569 *code_pos = (u_char)(instruction_code | reg->encoding());
570 ICache::invalidate_range(code_pos, instruction_size);
571}
572
573
574void NativeIllegalInstruction::insert(address code_pos) {
575 assert(NativeIllegalInstruction::instruction_size == sizeof(short), "right address unit for update")do { if (!(NativeIllegalInstruction::instruction_size == sizeof
(short))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 575, "assert(" "NativeIllegalInstruction::instruction_size == sizeof(short)"
") failed", "right address unit for update"); ::breakpoint()
; } } while (0)
;
576 *(short *)code_pos = instruction_code;
577 ICache::invalidate_range(code_pos, instruction_size);
578}
579
580void NativeGeneralJump::verify() {
581 assert(((NativeInstruction *)this)->is_jump() ||do { if (!(((NativeInstruction *)this)->is_jump() || ((NativeInstruction
*)this)->is_cond_jump())) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 582, "assert(" "((NativeInstruction *)this)->is_jump() || ((NativeInstruction *)this)->is_cond_jump()"
") failed", "not a general jump instruction"); ::breakpoint(
); } } while (0)
582 ((NativeInstruction *)this)->is_cond_jump(), "not a general jump instruction")do { if (!(((NativeInstruction *)this)->is_jump() || ((NativeInstruction
*)this)->is_cond_jump())) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 582, "assert(" "((NativeInstruction *)this)->is_jump() || ((NativeInstruction *)this)->is_cond_jump()"
") failed", "not a general jump instruction"); ::breakpoint(
); } } while (0)
;
583}
584
585
586void NativeGeneralJump::insert_unconditional(address code_pos, address entry) {
587 intptr_t disp = (intptr_t)entry - ((intptr_t)code_pos + 1 + 4);
588#ifdef AMD641
589 guarantee(disp == (intptr_t)(int32_t)disp, "must be 32-bit offset")do { if (!(disp == (intptr_t)(int32_t)disp)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 589, "guarantee(" "disp == (intptr_t)(int32_t)disp" ") failed"
, "must be 32-bit offset"); ::breakpoint(); } } while (0)
;
590#endif // AMD64
591
592 *code_pos = unconditional_long_jump;
593 *((int32_t *)(code_pos+1)) = (int32_t) disp;
594 ICache::invalidate_range(code_pos, instruction_size);
595}
596
597
598// MT-safe patching of a long jump instruction.
599// First patches first word of instruction to two jmp's that jmps to them
600// selfs (spinlock). Then patches the last byte, and then atomicly replaces
601// the jmp's with the first 4 byte of the new instruction.
602void NativeGeneralJump::replace_mt_safe(address instr_addr, address code_buffer) {
603 assert (instr_addr != NULL, "illegal address for code patching (4)")do { if (!(instr_addr != __null)) { (*g_assert_poison) = 'X';
; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 603, "assert(" "instr_addr != __null" ") failed", "illegal address for code patching (4)"
); ::breakpoint(); } } while (0)
;
604 NativeGeneralJump* n_jump = nativeGeneralJump_at (instr_addr); // checking that it is a jump
605
606 // Temporary code
607 unsigned char patch[4];
608 assert(sizeof(patch)==sizeof(int32_t), "sanity check")do { if (!(sizeof(patch)==sizeof(int32_t))) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 608, "assert(" "sizeof(patch)==sizeof(int32_t)" ") failed",
"sanity check"); ::breakpoint(); } } while (0)
;
609 patch[0] = 0xEB; // jmp rel8
610 patch[1] = 0xFE; // jmp to self
611 patch[2] = 0xEB;
612 patch[3] = 0xFE;
613
614 // First patch dummy jmp in place
615 *(int32_t*)instr_addr = *(int32_t *)patch;
616 n_jump->wrote(0);
617
618 // Patch 4th byte
619 instr_addr[4] = code_buffer[4];
620
621 n_jump->wrote(4);
622
623 // Patch bytes 0-3
624 *(jint*)instr_addr = *(jint *)code_buffer;
625
626 n_jump->wrote(0);
627
628#ifdef ASSERT1
629 // verify patching
630 for ( int i = 0; i < instruction_size; i++) {
631 address ptr = (address)((intptr_t)code_buffer + i);
632 int a_byte = (*ptr) & 0xFF;
633 assert(*((address)((intptr_t)instr_addr + i)) == a_byte, "mt safe patching failed")do { if (!(*((address)((intptr_t)instr_addr + i)) == a_byte))
{ (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/cpu/x86/nativeInst_x86.cpp"
, 633, "assert(" "*((address)((intptr_t)instr_addr + i)) == a_byte"
") failed", "mt safe patching failed"); ::breakpoint(); } } while
(0)
;
634 }
635#endif
636
637}
638
639
640
641address NativeGeneralJump::jump_destination() const {
642 int op_code = ubyte_at(0);
643 bool is_rel32off = (op_code == 0xE9 || op_code == 0x0F);
644 int offset = (op_code == 0x0F) ? 2 : 1;
645 int length = offset + ((is_rel32off) ? 4 : 1);
646
647 if (is_rel32off)
648 return addr_at(0) + length + int_at(offset);
649 else
650 return addr_at(0) + length + sbyte_at(offset);
651}