Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/debugtools/DDR_VM/src/com/ibm/j9ddr/DDRSymbolFinder.java
6004 views
1
/*******************************************************************************
2
* Copyright (c) 2012, 2019 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
23
package com.ibm.j9ddr;
24
25
import static java.util.logging.Level.FINE;
26
import static java.util.logging.Level.FINER;
27
28
import java.util.Collection;
29
import java.util.HashSet;
30
import java.util.LinkedList;
31
import java.util.List;
32
import java.util.Set;
33
import java.util.logging.Logger;
34
35
import com.ibm.j9ddr.StructureReader.FieldDescriptor;
36
import com.ibm.j9ddr.corereaders.memory.IMemoryRange;
37
import com.ibm.j9ddr.corereaders.memory.IModule;
38
import com.ibm.j9ddr.corereaders.memory.IProcess;
39
import com.ibm.j9ddr.corereaders.memory.ISymbol;
40
import com.ibm.j9ddr.corereaders.memory.MemoryFault;
41
import com.ibm.j9ddr.corereaders.memory.SymbolUtil;
42
import com.ibm.j9ddr.logging.LoggerNames;
43
44
public class DDRSymbolFinder {
45
46
private static boolean addSymbols = true;
47
48
private static List<String[][]> paths = new LinkedList<String[][]>();
49
50
/* Set of known fields to ignore as StructureName.fieldName */
51
private static Set<String> ignoredSymbols = new HashSet<String>();
52
53
static {
54
// Each table off function pointers to add has a path of pointers to follow to find it
55
// below. The path begins at J9JavaVM structure for the process so the first entry in
56
// the path is always a field within that.
57
// The path is an array of tuples of type and field names.
58
// (Except that java hasn't got tuples so it's a 2 element array instead.)
59
// All paths are from the J9JavaVM given in ctx.vmAddress.
60
// The types are necessary because a lot of the pointers are void * in their parent
61
// structure. By default we just add all the pointers from the last structure in the
62
// path.
63
64
/* Port Library */
65
paths.add( new String[][] { {"J9PortLibrary","portLibrary"} });
66
67
ignoredSymbols.add("J9PortLibrary.portVersion");
68
ignoredSymbols.add("J9PortLibrary.portGlobals");
69
70
/* Internal Functions. */
71
paths.add( new String[][] { {"J9InternalVMFunctions","internalVMFunctions"} });
72
73
ignoredSymbols.add("J9InternalVMFunctions.reserved0");
74
ignoredSymbols.add("J9InternalVMFunctions.reserved1");
75
ignoredSymbols.add("J9InternalVMFunctions.reserved2");
76
77
paths.add( new String[][] { {"J9InternalVMLabels","internalVMLabels"} });
78
79
/* GC Functions */
80
paths.add( new String[][] { {"J9MemoryManagerFunctions","memoryManagerFunctions"} });
81
82
/* Jni functions */
83
paths.add( new String[][] { {"jniNativeInterface", "jniFunctionTable"} });
84
85
ignoredSymbols.add("jniNativeInterface.reserved0");
86
ignoredSymbols.add("jniNativeInterface.reserved1");
87
ignoredSymbols.add("jniNativeInterface.reserved2");
88
ignoredSymbols.add("jniNativeInterface.reserved3");
89
90
/* Reflection functions */
91
paths.add( new String[][] { {"J9ReflectFunctionTable", "reflectFunctions"} });
92
93
/* RAS Trace functions */
94
paths.add( new String[][] { {"RasGlobalStorage","j9rasGlobalStorage"},
95
{"UtInterface","utIntf"},
96
{"UtServerInterface","server"}, });
97
98
ignoredSymbols.add("UtServerInterface.header");
99
100
paths.add( new String[][] { {"RasGlobalStorage","j9rasGlobalStorage"},
101
{"UtInterface","utIntf"},
102
{"UtClientInterface","client"}, });
103
104
ignoredSymbols.add("UtClientInterface.header");
105
106
paths.add( new String[][] { {"RasGlobalStorage","j9rasGlobalStorage"},
107
{"UtInterface","utIntf"},
108
{"UtModuleInterface","module"}, });
109
110
/* RAS Dump Functions */
111
paths.add( new String[][] { {"J9RASdumpFunctions","j9rasDumpFunctions"} });
112
113
ignoredSymbols.add("J9RASdumpFunctions.reserved");
114
}
115
116
public static void addSymbols(IProcess process, long j9RasAddress, StructureReader structureReader) {
117
118
long vmAddress = 0;
119
120
try {
121
122
vmAddress = followPointerFromStructure("J9RAS", j9RasAddress, "vm", structureReader, process);
123
124
} catch (MemoryFault e) {
125
Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);
126
logger.log(FINE, null, e);
127
} catch (com.ibm.j9ddr.NoSuchFieldException e){
128
Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);
129
logger.log(FINE, null, e);
130
} catch (Exception e) {
131
// This is optional information, we don't want to let an exception escape
132
// and block DDR startup!
133
Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);
134
logger.log(FINE, null, e);
135
}
136
137
if( vmAddress == 0 ) {
138
return;
139
}
140
141
for( String[][] path: paths) {
142
try {
143
long currentAddress = vmAddress;
144
String currentType = "J9JavaVM";
145
for( String[] pathEntry: path ) {
146
String structType = pathEntry[0];
147
String fieldName = pathEntry[1];
148
currentAddress = followPointerFromStructure(currentType, currentAddress, fieldName, structureReader, process);
149
currentType = structType;
150
}
151
addVoidPointersAsSymbols(currentType, currentAddress, structureReader, process );
152
} catch (MemoryFault e) {
153
Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);
154
logger.log(FINE, null, e);
155
} catch (com.ibm.j9ddr.NoSuchFieldException e){
156
Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);
157
logger.log(FINE, null, e);
158
} catch (CorruptDataException e) {
159
Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);
160
logger.log(FINE, null, e);
161
} catch (DataUnavailableException e) {
162
Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);
163
logger.log(FINE, null, e);
164
} catch (Exception e) {
165
// This is optional information, we don't want to let an exception escape
166
// and block DDR startup!
167
Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);
168
logger.log(FINE, null, e);
169
}
170
}
171
172
173
174
}
175
176
private static void addVoidPointersAsSymbols(String structureName,
177
long structureAddress, StructureReader structureReader, IProcess process) throws DataUnavailableException, CorruptDataException {
178
179
if( structureAddress == 0 ) {
180
return;
181
}
182
183
List<String> voidFields = getVoidPointerFieldsFromStructure(structureReader, structureName);
184
185
if( voidFields == null ) {
186
return;
187
}
188
189
// Format the hex and structure name the same as the rest of DDR.
190
int paddingSize = process.bytesPerPointer() * 2;
191
String formatString = "[!%s 0x%0"+ paddingSize + "X->%s]";
192
193
for( String field : voidFields ) {
194
195
if( ignoredSymbols.contains(structureName+"."+field)) {
196
// Ignore this field, it's not a function.
197
continue;
198
}
199
200
long functionAddress = followPointerFromStructure(structureName, structureAddress, field, structureReader, process);
201
if( functionAddress == 0 ) {
202
continue; // Skip null pointers.
203
}
204
// Lower case the structure name to match the rest of the DDR !<struct> commands.
205
String symName = String.format(formatString, structureName.toLowerCase(), structureAddress, field);
206
if( functionAddress == 0 ) {
207
// Null pointer, possibly unset or no longer used.
208
continue;
209
}
210
if( addSymbols ) {
211
IModule module = getModuleForInstructionAddress(process, functionAddress);
212
if( module == null ) {
213
continue;
214
}
215
boolean found = false;
216
// Don't override/duplicate symbols we've already seen.
217
for( ISymbol sym : module.getSymbols() ) {
218
if( sym.getAddress() == functionAddress ) {
219
Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);
220
logger.log(FINER, "DDRSymbolFinder: Found exact match with " + sym.toString() + " not adding.");
221
found = true;
222
break;
223
}
224
}
225
if( !found ) {
226
Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);
227
logger.log(FINER, "DDRSymbolFinder: Adding new DDR symbol " + symName);
228
SymbolUtil.addDDRSymbolToModule(module, "["+field+"]", symName, functionAddress);
229
}
230
}
231
}
232
}
233
234
private static long followPointerFromStructure(String structureName, long structureAddress, String fieldName, StructureReader reader, IProcess process) throws MemoryFault, NullPointerException {
235
236
if( structureAddress == 0 ) {
237
throw new NullPointerException("Null " + structureName + " found.");
238
}
239
240
for( FieldDescriptor f: reader.getFields(structureName)) {
241
if( f.getDeclaredName().equals(fieldName)) {
242
long offset = f.getOffset();
243
long pointerAddress = structureAddress + offset;
244
long pointer = process.getPointerAt(pointerAddress);
245
return pointer;
246
}
247
}
248
return 0;
249
}
250
251
private static List<String> getVoidPointerFieldsFromStructure(StructureReader reader, String structureName) throws MemoryFault {
252
253
List<String> functionPointers = new LinkedList<String>();
254
for( FieldDescriptor f: reader.getFields(structureName)) {
255
String name = f.getDeclaredName();
256
String type = f.getDeclaredType();
257
if( "void *".equals(type) ) {
258
functionPointers.add(name);
259
}
260
}
261
return functionPointers;
262
}
263
264
/* Logic stolen from SymbolUtil. */
265
private static IModule getModuleForInstructionAddress(IProcess process, long address) throws CorruptDataException {
266
Collection<? extends IModule> modules = process.getModules();
267
268
IModule matchingModule = null;
269
270
OUTER_LOOP: for (IModule thisModule : modules) {
271
for (IMemoryRange thisRange : thisModule.getMemoryRanges()) {
272
if (thisRange.contains(address)) {
273
matchingModule = thisModule;
274
break OUTER_LOOP;
275
}
276
}
277
}
278
return matchingModule;
279
}
280
}
281
282