54960
|
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 |
#include "asm/assembler.inline.hpp"
|
|
27 |
#include "asm/macroAssembler.hpp"
|
|
28 |
#include "code/codeCache.hpp"
|
|
29 |
#include "compiler/disassembler.hpp"
|
|
30 |
#include "depChecker_s390.hpp"
|
|
31 |
#include "gc/shared/collectedHeap.hpp"
|
|
32 |
#include "gc/shared/cardTableBarrierSet.hpp"
|
|
33 |
#include "gc/shared/genOopClosures.inline.hpp"
|
|
34 |
#include "oops/oop.inline.hpp"
|
|
35 |
#include "runtime/handles.inline.hpp"
|
|
36 |
#include "runtime/stubCodeGenerator.hpp"
|
|
37 |
#include "runtime/stubRoutines.hpp"
|
|
38 |
#include "utilities/align.hpp"
|
|
39 |
|
|
40 |
// List of all major opcodes, as of
|
|
41 |
// Principles of Operation, Eleventh Edition, March 2015
|
|
42 |
bool Disassembler::valid_opcodes[] =
|
|
43 |
{ true, true, false, false, true, true, true, true, // 0x00..07
|
|
44 |
false, false, true, true, true, true, true, true, // 0x08..0f
|
|
45 |
true, true, true, true, true, true, true, true, // 0x10..17
|
|
46 |
true, true, true, true, true, true, true, true, // 0x18..1f
|
|
47 |
true, true, true, true, true, true, true, true, // 0x20..27
|
|
48 |
true, true, true, true, true, true, true, true, // 0x28..2f
|
|
49 |
true, true, true, true, true, true, true, true, // 0x30..37
|
|
50 |
true, true, true, true, true, true, true, true, // 0x38..3f
|
|
51 |
true, true, true, true, true, true, true, true, // 0x40..47
|
|
52 |
true, true, true, true, true, true, true, true, // 0x48..4f
|
|
53 |
true, true, false, false, true, true, true, true, // 0x50..57
|
|
54 |
true, true, true, true, true, true, true, true, // 0x58..5f
|
|
55 |
true, false, false, false, false, false, false, true, // 0x60..67
|
|
56 |
true, true, true, true, true, true, true, true, // 0x68..6f
|
|
57 |
true, true, false, false, false, false, false, false, // 0x70..77
|
|
58 |
true, true, true, true, true, true, true, true, // 0x78..7f
|
|
59 |
true, false, true, true, true, true, true, true, // 0x80..87
|
|
60 |
true, true, true, true, true, true, true, true, // 0x88..8f
|
|
61 |
true, true, true, true, true, true, true, true, // 0x90..97
|
|
62 |
true, true, true, true, false, false, false, false, // 0x98..9f
|
|
63 |
false, false, false, false, false, true, false, true, // 0xa0..a7
|
|
64 |
true, true, false, false, true, true, true, true, // 0xa8..af
|
|
65 |
false, true, true, true, false, false, true, true, // 0xb0..b7
|
|
66 |
false, true, true, true, false, true, true, true, // 0xb8..bf
|
|
67 |
true, false, true, false, true, false, true, false, // 0xc0..c7
|
|
68 |
true, false, false, false, true, false, false, false, // 0xc8..cf
|
|
69 |
true, true, true, true, true, true, true, true, // 0xd0..d7
|
|
70 |
false, true, true, true, true, true, true, true, // 0xd8..df
|
|
71 |
false, true, true, true, false, true, false, true, // 0xe0..e7
|
|
72 |
true, true, true, true, true, true, true, true, // 0xe8..ef
|
|
73 |
true, true, true, true, false, false, false, false, // 0xf0..f7
|
|
74 |
true, true, true, true, true, true, false, false, // 0xf8..ff
|
|
75 |
};
|
|
76 |
// Check for valid opcodes.
|
|
77 |
//
|
|
78 |
// The major opcode (one byte) at the passed location is inspected.
|
|
79 |
// If the opcode found is assigned, the function returns true, false otherwise.
|
|
80 |
// The true indication is not reliable. It may well be that the major opcode is
|
|
81 |
// assigned, but there exists a minor opcode field in the instruction which
|
|
82 |
// which has unassigned values.
|
|
83 |
bool Disassembler::is_valid_opcode_at(address here) {
|
|
84 |
return valid_opcodes[*here];
|
|
85 |
}
|
|
86 |
|
|
87 |
// This method does plain instruction decoding, no frills.
|
|
88 |
// It may be called before the binutils disassembler kicks in
|
|
89 |
// to handle special cases the binutils disassembler does not.
|
|
90 |
// Instruction address, comments, and the like have to be output by caller.
|
|
91 |
address Disassembler::decode_instruction0(address here, outputStream * st, address virtual_begin) {
|
|
92 |
if (is_abstract()) {
|
|
93 |
// The disassembler library was not loaded (yet),
|
|
94 |
// use AbstractDisassembler's decode-method.
|
|
95 |
return decode_instruction_abstract(here, st, Assembler::instr_len(here), Assembler::instr_maxlen());
|
|
96 |
}
|
|
97 |
|
|
98 |
// Currently, "special decoding" doesn't work when decoding error files.
|
|
99 |
// When decoding an instruction from a hs_err file, the given
|
|
100 |
// instruction address 'start' points to the instruction's virtual address
|
|
101 |
// which is not equal to the address where the instruction is located.
|
|
102 |
// Therefore, we will either crash or decode garbage.
|
|
103 |
if (is_decode_error_file()) {
|
|
104 |
return here;
|
|
105 |
}
|
|
106 |
|
|
107 |
//---< Decode some well-known "instructions" >---
|
|
108 |
|
|
109 |
address next;
|
|
110 |
uint16_t instruction_2bytes = *(uint16_t*)here;
|
|
111 |
|
|
112 |
if (Assembler::is_z_nop((long)instruction_2bytes)) {
|
|
113 |
#if 1
|
|
114 |
st->print("nop "); // fill up to operand column, leads to better code comment alignment
|
|
115 |
next = here + 2;
|
|
116 |
#else
|
|
117 |
// Compact disassembler output. Does not work the easy way.
|
|
118 |
// Currently unusable, search does not terminate, risk of crash.
|
|
119 |
// TODO: rework required.
|
|
120 |
// Terminate search loop when reaching CodeEntryAlignment-aligned offset
|
|
121 |
// or, at the latest, when reaching the next page boundary.
|
|
122 |
int n_nops = 0;
|
|
123 |
while(is_same_page(here, here+2*n_nops) && Assembler::is_z_nop((long)instruction_2bytes)) {
|
|
124 |
n_nops++;
|
|
125 |
instruction_2bytes = *(uint16_t*)(here+2*n_nops);
|
|
126 |
}
|
|
127 |
if (n_nops <= 4) { // do not group few subsequent nops
|
|
128 |
st->print("nop "); // fill up to operand column, leads to better code comment alignment
|
|
129 |
next = here + 2;
|
|
130 |
} else {
|
|
131 |
st->print("nop count=%d", n_nops);
|
|
132 |
next = here + 2*n_nops;
|
|
133 |
}
|
|
134 |
#endif
|
|
135 |
} else if (Assembler::is_z_sync((long)instruction_2bytes)) {
|
|
136 |
// Specific names. Make use of lightweight sync.
|
|
137 |
st->print("sync ");
|
|
138 |
if (Assembler::is_z_sync_full((long)instruction_2bytes) ) st->print("heavyweight");
|
|
139 |
if (Assembler::is_z_sync_light((long)instruction_2bytes)) st->print("lightweight");
|
|
140 |
next = here + 2;
|
|
141 |
} else if (instruction_2bytes == 0x0000) {
|
|
142 |
#if 1
|
|
143 |
st->print("illtrap .nodata");
|
|
144 |
next = here + 2;
|
|
145 |
#else
|
|
146 |
// Compact disassembler output. Does not work the easy way.
|
|
147 |
// Currently unusable, search does not terminate, risk of crash.
|
|
148 |
// TODO: rework required.
|
|
149 |
// Terminate search loop when reaching CodeEntryAlignment-aligned offset
|
|
150 |
// or, at the latest, when reaching the next page boundary.
|
|
151 |
int n_traps = 0;
|
|
152 |
while(is_same_page(here, here+2*n_nops) && (instruction_2bytes == 0x0000)) {
|
|
153 |
n_traps++;
|
|
154 |
instruction_2bytes = *(uint16_t*)(here+2*n_traps);
|
|
155 |
}
|
|
156 |
if (n_traps <= 4) { // do not group few subsequent illtraps
|
|
157 |
st->print("illtrap .nodata");
|
|
158 |
next = here + 2;
|
|
159 |
} else {
|
|
160 |
st->print("illtrap .nodata count=%d", n_traps);
|
|
161 |
next = here + 2*n_traps;
|
|
162 |
}
|
|
163 |
#endif
|
|
164 |
} else if ((instruction_2bytes & 0xff00) == 0x0000) {
|
|
165 |
st->print("illtrap .data 0x%2.2x", instruction_2bytes & 0x00ff);
|
|
166 |
next = here + 2;
|
|
167 |
} else {
|
|
168 |
next = here;
|
|
169 |
}
|
|
170 |
return next;
|
|
171 |
}
|
|
172 |
|
|
173 |
// Count the instructions contained in the range [begin..end).
|
|
174 |
// The range must exactly contain the instructions, i.e.
|
|
175 |
// - the first instruction starts @begin
|
|
176 |
// - the last instruction ends @(end-1)
|
|
177 |
// The caller has to make sure that the given range is readable.
|
|
178 |
// This function performs no safety checks!
|
|
179 |
// Return value:
|
|
180 |
// - The number of instructions, if there was exact containment.
|
|
181 |
// - If there is no exact containment, a negative value is returned.
|
|
182 |
// Its absolute value is the number of instructions from begin to end,
|
|
183 |
// where the last instruction counted runs over the range end.
|
|
184 |
// - 0 (zero) is returned if there was a parameter error
|
|
185 |
// (inverted range, bad starting point).
|
|
186 |
int Disassembler::count_instr(address begin, address end) {
|
|
187 |
if (end < begin+2) return 0; // no instructions in range
|
|
188 |
if (!Disassembler::is_valid_opcode_at(begin)) return 0; // bad starting point
|
|
189 |
|
|
190 |
address p = begin;
|
|
191 |
int n = 0;
|
|
192 |
while(p < end) {
|
|
193 |
p += Assembler::instr_len(p);
|
|
194 |
n++;
|
|
195 |
}
|
|
196 |
return (p == end) ? n : -n;
|
|
197 |
}
|
|
198 |
|
|
199 |
// Find preceding instruction.
|
|
200 |
//
|
|
201 |
// Starting at the passed location, the n-th preceding (towards lower addresses)
|
|
202 |
// instruction is searched. With variable length instructions, there may be
|
|
203 |
// more than one solution, or no solution at all (if the passed location
|
|
204 |
// does not point to the start of an instruction or if the storage area
|
|
205 |
// does not contain instructions at all).
|
|
206 |
// instructions - has the passed location as n-th successor.
|
|
207 |
// - If multiple such locations exist between (here-n*instr_maxlen()) and here,
|
|
208 |
// the most distant location is selected.
|
|
209 |
// - If no such location exists, NULL is returned. The caller should then
|
|
210 |
// terminate its search and react properly.
|
|
211 |
// Must be placed here in disassembler_s390.cpp. It does not compile
|
|
212 |
// in the header. There the class 'Assembler' is not available.
|
|
213 |
address Disassembler::find_prev_instr(address here, int n_instr) {
|
|
214 |
if (!os::is_readable_pointer(here)) return NULL; // obviously a bad location to decode
|
|
215 |
|
|
216 |
// Find most distant possible starting point.
|
|
217 |
// Narrow down because we don't want to SEGV while printing.
|
|
218 |
address start = here - n_instr*Assembler::instr_maxlen(); // starting point can't be further away.
|
|
219 |
while ((start < here) && !os::is_readable_range(start, here)) {
|
|
220 |
start = align_down(start, os::min_page_size()) + os::min_page_size();
|
|
221 |
}
|
|
222 |
if (start >= here) {
|
|
223 |
// Strange. Can only happen with here on page boundary.
|
|
224 |
return NULL;
|
|
225 |
}
|
|
226 |
|
|
227 |
//---< Find a starting point >---
|
|
228 |
int i_count = 0;
|
|
229 |
while ((start < here) && ((i_count = count_instr(start, here)) <= 0)) start += 2;
|
|
230 |
if (i_count == 0) return NULL; // There is something seriously wrong
|
|
231 |
|
|
232 |
//---< Narrow down distance (estimate was too large) >---
|
|
233 |
while(i_count-- > n_instr) {
|
|
234 |
start += Assembler::instr_len(start);
|
|
235 |
}
|
|
236 |
assert(n_instr >= count_instr(start, here), "just checking");
|
|
237 |
return start;
|
|
238 |
}
|
|
239 |
|
|
240 |
|
|
241 |
// Print annotations (value of loaded constant)
|
|
242 |
void Disassembler::annotate(address here, outputStream* st) {
|
|
243 |
// Currently, annotation doesn't work when decoding error files.
|
|
244 |
// When decoding an instruction from a hs_err file, the given
|
|
245 |
// instruction address 'start' points to the instruction's virtual address
|
|
246 |
// which is not equal to the address where the instruction is located.
|
|
247 |
// Therefore, we will either crash or decode garbage.
|
|
248 |
if (is_decode_error_file()) {
|
|
249 |
return;
|
|
250 |
}
|
|
251 |
|
|
252 |
if (MacroAssembler::is_load_const(here)) {
|
|
253 |
long value = MacroAssembler::get_const(here);
|
|
254 |
const int tsize = 8;
|
|
255 |
|
|
256 |
st->fill_to(60);
|
|
257 |
st->print(";const %p | %ld | %23.15e", (void *)value, value, (double)value);
|
|
258 |
}
|
|
259 |
}
|