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