Bug Summary

File:jdk/src/hotspot/share/compiler/abstractDisassembler.cpp
Warning:line 246, column 27
Although the value stored to 'align' is used in the enclosing expression, the value is never actually read from 'align'

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 abstractDisassembler.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/share/compiler/abstractDisassembler.cpp
1/*
2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2019 SAP SE. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26// AbstractDisassembler is the base class for
27// platform-specific Disassembler classes.
28
29#include "precompiled.hpp"
30#include "asm/assembler.inline.hpp"
31#include "compiler/abstractDisassembler.hpp"
32#include "oops/oop.inline.hpp"
33#include "utilities/debug.hpp"
34#include "utilities/ostream.hpp"
35
36// Default values for what is being printed as line prefix when disassembling a single instruction.
37// Can be overridden by command line parameter PrintAssemblyOptions.
38bool AbstractDisassembler::_show_data_hex = true;
39bool AbstractDisassembler::_show_data_int = false;
40bool AbstractDisassembler::_show_data_float = false;
41bool AbstractDisassembler::_align_instr = true;
42bool AbstractDisassembler::_show_pc = true;
43bool AbstractDisassembler::_show_offset = false;
44bool AbstractDisassembler::_show_structs = true;
45bool AbstractDisassembler::_show_comment = true;
46bool AbstractDisassembler::_show_block_comment = true;
47
48// set "true" to see what's in memory bit by bit
49// might prove cumbersome on platforms where instr_len is hard to find out
50bool AbstractDisassembler::_show_bytes = false;
51
52// Return #bytes printed. Callers may use that for output alignment.
53// Print instruction address, and offset from blob begin.
54// Offset width (2, 4, 6, 8 bytes) is adapted to size of blob.
55// Working assumption: we are at st->bol() upon entry. If not, it's the
56// caller's responsibility to guarantee proper alignment.
57int AbstractDisassembler::print_location(address here, address begin, address end, outputStream* st, bool align, bool print_header) {
58 const int pos_0 = st->position();
59
60 if (show_pc() || show_offset()) {
61 st->print(" ");
62 }
63
64 if (show_pc()) {
65 if (print_header) {
66 st->print(" %*s", 18, "Address");
67 } else {
68 st->print(" " PTR_FORMAT"0x%016" "l" "x", p2i(here));
69 }
70 }
71
72 if (show_offset()) {
73#ifdef ASSERT1
74 if ((uintptr_t)begin > (uintptr_t)here) st->print(">>begin(" PTR_FORMAT"0x%016" "l" "x" ") > here(" PTR_FORMAT"0x%016" "l" "x" ")<<", p2i(begin), p2i(here));
75 if ((uintptr_t)end < (uintptr_t)here) st->print(">> end(" PTR_FORMAT"0x%016" "l" "x" ") < here(" PTR_FORMAT"0x%016" "l" "x" ")<<", p2i(end), p2i(here));
76 assert((uintptr_t)begin <= (uintptr_t)end, "inverted address range")do { if (!((uintptr_t)begin <= (uintptr_t)end)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/abstractDisassembler.cpp"
, 76, "assert(" "(uintptr_t)begin <= (uintptr_t)end" ") failed"
, "inverted address range"); ::breakpoint(); } } while (0)
;
77#endif
78 const int blob_len = end - begin;
79 const int offset = here - begin;
80 const int width = (blob_len < (1<< 8)) ? 2 : (blob_len < (1<<16)) ? 4 : (blob_len < (1<<24)) ? 6 : 8;
81 if (print_header) {
82 st->print(" %*s", width+5, "offset");
83 } else {
84 st->print(" (+0x%*.*x)", width, width, offset);
85 }
86 }
87
88 if ((show_pc() || show_offset()) && !print_header) {
89 st->print(": ");
90 }
91
92 if (align) {
93 const uint tabspacing = 8;
94 const uint pos = st->position();
95 const uint aligned_pos = ((pos+tabspacing-1)/tabspacing)*tabspacing /* - 1 */;
96 st->fill_to(aligned_pos);
97 }
98
99 return st->position() - pos_0;
100}
101
102
103// Return #bytes printed. Callers may use that for output alignment.
104// Print instruction in hexadecimal representation, using 2-byte blocks.
105// Used with real disassemblies. Not so useful with abstract disassemblies.
106int AbstractDisassembler::print_instruction(address here, int len, int max_len, outputStream* st, bool align, bool print_header) {
107 if (show_bytes()) {
108 const int block_bytes = 2;
109 const int pos_0 = st->position();
110 address pos = here;
111
112 //---< print instruction bytes in blocks >---
113 // must print byte by byte: address might be unaligned.
114 for (; pos <= here + len - block_bytes; pos += block_bytes) {
115 for (address byte = pos; byte < pos + block_bytes; byte++) {
116 st->print("%2.2x", *byte);
117 }
118 st->print(" ");
119 }
120
121 //---< Print the remaining bytes of the instruction >---
122 if ((len & (block_bytes - 1)) != 0) {
123 for (; pos < here + len; pos++) {
124 st->print("%2.2x", *pos);
125 }
126 }
127
128 //---< filler for shorter than max_len instructions >---
129 for (int i = len+1; i < max_len; i++) {
130 st->print(" ");
131 }
132
133 st->print(" "); // separator space.
134 print_delimiter(st);
135 return st->position() - pos_0;
136 }
137
138 if (align) {
139 const uint tabspacing = 8;
140 const uint pos = st->position();
141 const uint aligned_pos = ((pos+tabspacing-1)/tabspacing)*tabspacing /* - 1 */;
142 st->fill_to(aligned_pos);
143 }
144
145 return 0;
146}
147
148
149// Return #bytes printed. Callers may use that for output alignment.
150// Print data (e.g. constant pool entries) in hex format.
151// Depending on the alignment, short, int, and long entities are printed.
152// If selected, data is formatted as int/long and float/double values in addition.
153int AbstractDisassembler::print_hexdata(address here, int len, outputStream* st, bool print_header) {
154 const int tsize = 8;
155 const int pos_0 = st->position();
156 int pos = pos_0;
157 int align = ((pos+tsize-1)/tsize)*tsize;
158 st->fill_to(align);
159
160 //---< printing hex data >---
161 if (show_data_hex()) {
162 switch (len) {
163 case 1: if (print_header) {
164 st->print("hex1");
165 } else {
166 st->print("0x%02x", *here);
167 }
168 st->fill_to(align += tsize);
169 case 2: if (print_header) {
170 st->print(" hex2");
171 } else {
172 if (((uintptr_t)(here)&0x01) == 0) {
173 st->print("0x%04x", *((jushort*)here));
174 }
175 }
176 st->fill_to(align += tsize);
177 case 4: if (print_header) {
178 st->print(" hex4");
179 } else {
180 if (((uintptr_t)(here)&0x03) == 0) {
181 st->print("0x%08x", *((juint*)here));
182 }
183 }
184 st->fill_to(align += 2*tsize);
185 case 8: if (print_header) {
186 st->print(" hex8");
187 } else {
188 if (((uintptr_t)(here)&0x07) == 0) {
189 st->print(PTR_FORMAT"0x%016" "l" "x", *((uintptr_t*)here));
190 }
191 }
192 st->fill_to(align += 3*tsize);
193 break;
194 default: ;
195 }
196 pos = st->position();
197 align = ((pos+tsize-1)/tsize)*tsize;
198 st->fill_to(align);
199 }
200
201 //---< printing int/long data >---
202 if (show_data_int()) {
203 switch (len) {
204 case 4: if (print_header) {
205 st->print(" int");
206 } else {
207 if (((uintptr_t)(here)&0x03) == 0) {
208 st->print("%12.1d", *((jint*)here));
209 }
210 }
211 st->fill_to(align += 2*tsize);
212 case 8: if (print_header) {
213 st->print(" long");
214 } else {
215 if (((uintptr_t)(here)&0x07) == 0) {
216 st->print(JLONG_FORMAT_W(23)"%" "23" "l" "d", *((jlong*)here));
217 }
218 }
219 st->fill_to(align += 3*tsize);
220 break;
221 default: ;
222 }
223 pos = st->position();
224 align = ((pos+tsize-1)/tsize)*tsize;
225 st->fill_to(align);
226 }
227
228 //---< printing float/double data >---
229 if (show_data_float()) {
230 switch (len) {
231 case 4: if (print_header) {
232 st->print(" float");
233 } else {
234 if (((uintptr_t)(here)&0x03) == 0) {
235 st->print("%15.7e", (double)*((float*)here));
236 }
237 }
238 st->fill_to(align += 2*tsize);
239 case 8: if (print_header) {
240 st->print(" double");
241 } else {
242 if (((uintptr_t)(here)&0x07) == 0) {
243 st->print("%23.15e", *((double*)here));
244 }
245 }
246 st->fill_to(align += 3*tsize);
Although the value stored to 'align' is used in the enclosing expression, the value is never actually read from 'align'
247 break;
248 default: ;
249 }
250 }
251
252 return st->position() - pos_0;
253}
254
255
256// Return #bytes printed. Callers may use that for output alignment.
257// Print an instruction delimiter.
258int AbstractDisassembler::print_delimiter(outputStream* st) {
259 if (align_instr()) { st->print("| "); return 2; }
260 else return 0;
261}
262
263
264// Decodes the one instruction at address start in a platform-independent format.
265// Returns the start of the next instruction (which is 'start' plus 'instruction_size_in_bytes').
266// The parameter max_instr_size_in_bytes is used for output alignment purposes only.
267address AbstractDisassembler::decode_instruction_abstract(address start,
268 outputStream* st,
269 const int instruction_size_in_bytes,
270 const int max_instr_size_in_bytes) {
271 assert(instruction_size_in_bytes > 0, "no zero-size instructions!")do { if (!(instruction_size_in_bytes > 0)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/abstractDisassembler.cpp"
, 271, "assert(" "instruction_size_in_bytes > 0" ") failed"
, "no zero-size instructions!"); ::breakpoint(); } } while (0
)
;
272 assert(max_instr_size_in_bytes >= instruction_size_in_bytes, "inconsistent call parameters")do { if (!(max_instr_size_in_bytes >= instruction_size_in_bytes
)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/abstractDisassembler.cpp"
, 272, "assert(" "max_instr_size_in_bytes >= instruction_size_in_bytes"
") failed", "inconsistent call parameters"); ::breakpoint();
} } while (0)
;
273
274 //---< current instruction is at the start address >---
275 unsigned char* current = (unsigned char*) start;
276 int filler_limit = align_instr() ? max_instr_size_in_bytes : ((instruction_size_in_bytes+abstract_instruction_bytes_per_block-1)/abstract_instruction_bytes_per_block)
277 *abstract_instruction_bytes_per_block;
278
279 //---< print the instruction's bytes >---
280 for (int i = 1; i <= instruction_size_in_bytes; i++) {
281 st->print("%02x", *current);
282 ++current;
283 if (abstract_instruction_bytes_per_block <= max_instr_size_in_bytes) {
284 if (i%abstract_instruction_bytes_per_block == 0) st->print(" ");
285 } else {
286 if (i == instruction_size_in_bytes) st->print(" ");
287 }
288 }
289
290 //---< print some filler spaces to column-align instructions >---
291 for (int i = instruction_size_in_bytes+1; i <= filler_limit; i++) {
292 st->print(" ");
293 if (abstract_instruction_bytes_per_block <= max_instr_size_in_bytes) {
294 if (i%abstract_instruction_bytes_per_block == 0) st->print(" ");
295 } else {
296 if (i == instruction_size_in_bytes) st->print(" ");
297 }
298 }
299
300 //---< the address of the next instruction >---
301 return (address) current;
302}
303
304
305// Decodes all instructions in the given range [start..end)
306// calling decode_instruction_abstract for each instruction.
307// The format is platform dependent only to the extend that
308// it respects the actual instruction length where possible.
309// Does not print any markers or decorators.
310void AbstractDisassembler::decode_range_abstract(address range_start, address range_end,
311 address start, address end,
312 outputStream* st,
313 const int max_instr_size_in_bytes) {
314 assert(st != NULL, "need an output stream (no default)!")do { if (!(st != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/abstractDisassembler.cpp"
, 314, "assert(" "st != __null" ") failed", "need an output stream (no default)!"
); ::breakpoint(); } } while (0)
;
315 int idx = 0;
316 address pos = range_start;
317
318 while ((pos != NULL__null) && (pos < range_end)) {
319 int instr_size_in_bytes = Assembler::instr_len(pos);
320
321 if (idx == 0) print_location(pos, start, end, st, false, false);
322 else print_delimiter(st);
323
324 //---< print the instruction's bytes >---
325 // don't access storage beyond end of range
326 if (pos + instr_size_in_bytes <= range_end) {
327 pos = decode_instruction_abstract(pos, st, instr_size_in_bytes, max_instr_size_in_bytes);
328 } else {
329 // If the range to be decoded contains garbage at the end (e.g. 0xcc initializer bytes),
330 // instruction size calculation may run out of sync. Just terminate in that case.
331 pos = range_end;
332 }
333
334 idx += instr_size_in_bytes;
335 if (start_newline(idx)) {
336 st->cr();
337 idx = 0;
338 }
339 }
340}
341
342
343// Decodes all instructions in the given range [start..end).
344// The output is enclosed in [MachCode] and [/MachCode] tags for later recognition.
345// The format is platform dependent only to the extend that
346// it respects the actual instruction length where possible.
347void AbstractDisassembler::decode_abstract(address start, address end, outputStream* ost,
348 const int max_instr_size_in_bytes) {
349 int idx = 0;
350 address pos = start;
351
352 outputStream* st = (ost == NULL__null) ? tty : ost;
353
354 //---< Open the output (Marker for post-mortem disassembler) >---
355 st->bol();
356 st->print_cr("[MachCode]");
357
358 decode_range_abstract(start, end, start, end, st, max_instr_size_in_bytes);
359
360 //---< Close the output (Marker for post-mortem disassembler) >---
361 st->bol();
362 st->print_cr("[/MachCode]");
363}