Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/debugtools/DDR_VM/src/com/ibm/j9ddr/VMDataFactory.java
6004 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2021 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
package com.ibm.j9ddr;
23
24
import static java.util.logging.Level.FINE;
25
26
import java.io.BufferedReader;
27
import java.io.ByteArrayInputStream;
28
import java.io.ByteArrayOutputStream;
29
import java.io.File;
30
import java.io.FileNotFoundException;
31
import java.io.IOException;
32
import java.io.InputStream;
33
import java.io.InputStreamReader;
34
import java.io.PrintWriter;
35
import java.io.StringWriter;
36
import java.lang.reflect.InvocationTargetException;
37
import java.lang.reflect.Method;
38
import java.nio.charset.StandardCharsets;
39
import java.security.AccessController;
40
import java.security.PrivilegedAction;
41
import java.util.ArrayList;
42
import java.util.HashSet;
43
import java.util.List;
44
import java.util.Properties;
45
import java.util.Set;
46
import java.util.logging.Logger;
47
48
import javax.imageio.stream.FileImageInputStream;
49
import javax.imageio.stream.ImageInputStream;
50
import javax.imageio.stream.ImageInputStreamImpl;
51
import javax.imageio.stream.MemoryCacheImageInputStream;
52
53
import com.ibm.j9ddr.StructureHeader.BlobID;
54
import com.ibm.j9ddr.StructureReader.PackageNameType;
55
import com.ibm.j9ddr.blobs.BlobFactory;
56
import com.ibm.j9ddr.blobs.IBlobFactory;
57
import com.ibm.j9ddr.blobs.IBlobFactory.Platforms;
58
import com.ibm.j9ddr.corereaders.ICore;
59
import com.ibm.j9ddr.corereaders.Platform;
60
import com.ibm.j9ddr.corereaders.memory.IMemoryImageInputStream;
61
import com.ibm.j9ddr.corereaders.memory.IModule;
62
import com.ibm.j9ddr.corereaders.memory.IProcess;
63
import com.ibm.j9ddr.corereaders.memory.ISymbol;
64
import com.ibm.j9ddr.corereaders.memory.MemoryFault;
65
import com.ibm.j9ddr.exceptions.CorruptStructuresException;
66
import com.ibm.j9ddr.exceptions.JVMNotDDREnabledException;
67
import com.ibm.j9ddr.exceptions.JVMNotFoundException;
68
import com.ibm.j9ddr.exceptions.MissingDDRStructuresException;
69
import com.ibm.j9ddr.exceptions.UnknownArchitectureException;
70
import com.ibm.j9ddr.logging.LoggerNames;
71
import com.ibm.j9ddr.util.WeakValueMap;
72
73
/**
74
* Create IVMData instances for each VM found in a Process
75
*/
76
public abstract class VMDataFactory {
77
private final static String STRUCTUREFILE_PROPERTY = "com.ibm.j9ddr.structurefile";
78
private final static String SEARCHEYECATCHER_PROPERTY = "com.ibm.j9ddr.searcheyecatcher";
79
private final static String NOEXTRASEARCHFORNODE_PROPERTY = "com.ibm.j9ddr.noextrasearchfornode";
80
81
/* Symbol used to find the J9RAS structure on z/OS */
82
public static final String J9RAS_SYMBOL = "_j9ras_";
83
private static final byte[] eyecatcher = "J9VMRAS".getBytes(StandardCharsets.US_ASCII);
84
private static final long integrityCheck = 0xaa55aa55aa55aa55L;
85
private static final int BIT_PATTERNS_OFFSET = 0x8;
86
private static final int J9RAS_VERSION_OFFSET = 0x10;
87
private static final int DDR_DATA_POINTER_OFFSET = 0x18;
88
private static final int MINIMUM_J9RAS_MAJOR_VERSION = 2;
89
private static long j9RASAddress;
90
91
// a process can have more than one blob present, each blob is represented as a separate IVMData
92
private static WeakValueMap<IProcess, List<IVMData>> vmDataCache = new WeakValueMap<>();
93
94
/**
95
* Returns a VMData for the first VM located in the process
96
* @param process
97
* @return
98
* @throws IOException
99
*/
100
public static IVMData getVMData(IProcess process) throws IOException {
101
List<IVMData> cachedVMData = vmDataCache.get(process);
102
103
if ((cachedVMData != null) && (cachedVMData.size() > 0)) {
104
return cachedVMData.get(0); // return the first VM found
105
}
106
107
cachedVMData = getAllVMData(process);
108
109
if (cachedVMData.size() > 0) {
110
return cachedVMData.get(0); // return the first VM found
111
} else {
112
return null; // nothing was found in scan
113
}
114
}
115
// TODO - fix this for z/OS which will require noting which RAS symbols have already been found in the core
116
117
/**
118
* Finds all of the blobs in a given process and wraps them in a IVMData structure.
119
*
120
* @param process process to scan
121
* @return all located blobs
122
* @throws IOException re-throws IOExceptions
123
*/
124
public synchronized static List<IVMData> getAllVMData(IProcess process) throws IOException {
125
List<IVMData> cachedVMData = vmDataCache.get(process);
126
127
if (cachedVMData != null) {
128
return cachedVMData;
129
}
130
131
// nothing in the cache for this process, so need to scan
132
// Get an ImageInputStream on the Structure Offset Data. This may or may not be in the core file itself.
133
List<IVMData> data = new ArrayList<>();
134
Set<Long> attemptedAddresses = new HashSet<>();
135
j9RASAddress = 0;
136
for (;;) {
137
long address = j9RASAddress + 1;
138
if (!attemptedAddresses.add(Long.valueOf(address))) {
139
// we already tried this address: give up now
140
break;
141
}
142
try {
143
ImageInputStream in = getStructureDataFile(process, address);
144
if (in == null) {
145
break;
146
}
147
IVMData vmdata = getVMData(process, in);
148
data.add(vmdata);
149
if (vmdata.getClassLoader().getHeader().getCoreVersion() == 1) {
150
// version 1 does not support multiple blobs
151
break;
152
}
153
if (!(in instanceof IMemoryImageInputStream)) {
154
break;
155
}
156
} catch (JVMNotFoundException e) {
157
// no more JVMs were found
158
break;
159
} catch (JVMNotDDREnabledException e) {
160
// an older JVM was found, so ignore that and carry on looking
161
if (process.getPlatform() == Platform.ZOS) {
162
// on z/OS a failure with the j9ras symbol resolution aborts the scan
163
break;
164
}
165
} catch (MissingDDRStructuresException e) {
166
// cannot process as the structures are missing
167
if (process.getPlatform() == Platform.ZOS) {
168
// on z/OS a failure with the j9ras symbol resolution aborts the scan
169
break;
170
}
171
} catch (CorruptStructuresException e) {
172
// cannot process as the structures are corrupt and cannot be read
173
if (process.getPlatform() == Platform.ZOS) {
174
// on z/OS a failure with the j9ras symbol resolution aborts the scan
175
break;
176
}
177
} catch (IOException e) {
178
// ignore, but unless j9RASAddress has changed we'll give up
179
}
180
}
181
182
// For Node.JS only, if we have not found a BLOB at this point we do a more expensive scan. This extra
183
// scan is switched off for Java-only applications (specifically jdmpview) via a system property.
184
if (data.isEmpty() && (System.getProperty(NOEXTRASEARCHFORNODE_PROPERTY) == null)) {
185
StructureHeader header;
186
try {
187
header = findNodeVersion(process);
188
} catch (IOException e) {
189
throw e;
190
} catch (Exception e) {
191
throw new IOException(e);
192
}
193
if (header != null) {
194
ImageInputStream in = getBlobFromLibrary(process, header);
195
if (in != null) {
196
IVMData vmdata = getVMData(process, in);
197
data.add(vmdata);
198
}
199
}
200
}
201
202
vmDataCache.put(process, data);
203
204
return data;
205
}
206
207
private static IVMData getVMData(IProcess process, ImageInputStream in) throws IOException {
208
// Create and initialize a StructureClassLoader for this VM instance
209
final StructureReader structureReader = new StructureReader(in);
210
211
J9DDRClassLoader ddrClassLoader = AccessController.doPrivileged(new PrivilegedAction<J9DDRClassLoader>() {
212
@Override
213
public J9DDRClassLoader run() {
214
return new J9DDRClassLoader(structureReader, VMDataFactory.class.getClassLoader());
215
}
216
});
217
218
try {
219
// Load and instantiate a VMData object. Load the VMData class for each core file
220
IVMData vmData = ddrClassLoader.getIVMData(process, j9RASAddress);
221
222
// Load and initialize the statics on DataType for this core file.
223
Class<?> dataTypeClazz = ddrClassLoader.loadClassRelativeToStream("j9.DataType", false);
224
Method initMethod = dataTypeClazz.getDeclaredMethod("init", IProcess.class, StructureReader.class);
225
initMethod.invoke(null, process, structureReader);
226
227
// Load an instantiate a VM specific J9RASPointer via a call to J9RASPointer.cast(long);
228
String basePackageName = structureReader.getPackageName(PackageNameType.POINTER_PACKAGE_DOT_NAME);
229
Class<?> rasClazz = ddrClassLoader.loadClass(basePackageName + ".J9RASPointer");
230
Method getStructureMethod = rasClazz.getDeclaredMethod("cast", new Class[] { Long.TYPE });
231
Object pointer = getStructureMethod.invoke(null, new Object[] { j9RASAddress });
232
233
// Set the J9RASPointer on DataType.
234
Method setMethod = dataTypeClazz.getDeclaredMethod("setJ9RASPointer", pointer.getClass());
235
setMethod.invoke(vmData, new Object[] { pointer });
236
237
// now add any blob fragments for this build
238
addFragments(rasClazz, pointer, structureReader, vmData);
239
240
if (!Boolean.FALSE.toString().equals(System.getProperty("com.ibm.j9ddr.symbols.from.pointers"))) {
241
DDRSymbolFinder.addSymbols(process, j9RASAddress, structureReader);
242
}
243
244
return vmData;
245
} catch (ClassNotFoundException e) {
246
Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);
247
logger.log(FINE, null, e);
248
throw new IOException(String.format("Invalid or unavailable structure offset data. %s", e.getMessage()));
249
} catch (NoSuchMethodException e) {
250
Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);
251
logger.log(FINE, null, e);
252
throw new IOException(String.format("Invalid or unavailable structure offset data. %s", e.getMessage()));
253
} catch (IllegalAccessException e) {
254
Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);
255
logger.log(FINE, null, e);
256
throw new IOException(String.format("Invalid or unavailable structure offset data. %s", e.getMessage()));
257
} catch (InvocationTargetException e) {
258
Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);
259
logger.log(FINE, null, e);
260
throw new IOException(String.format("Invalid or unavailable structure offset data. %s", e.getMessage()));
261
} catch (InstantiationException e) {
262
Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);
263
logger.log(FINE, null, e);
264
throw new IOException(String.format("Invalid or unavailable structure offset data. %s", e.getMessage()));
265
}
266
}
267
268
/**
269
* Add any blob fragments which apply to this build
270
*
271
* @param rasptr pointer to the RAS structure so that we can get the buildID
272
*/
273
private static void addFragments(Class<?> rasClazz, Object rasptr, final StructureReader structureReader, IVMData vmdata) {
274
try {
275
InputStream in = rasClazz.getResourceAsStream("/fragments/fragments.properties");
276
if (in == null) {
277
Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);
278
logger.log(FINE, "Failed to find fragments property file");
279
return; // no property file found
280
}
281
Properties fragments = new Properties();
282
fragments.load(in);
283
in.close();
284
Method method = rasClazz.getDeclaredMethod("buildID", (Class<?>[]) null);
285
Object u64 = method.invoke(rasptr, (Object[]) null);
286
method = u64.getClass().getMethod("getHexValue", (Class<?>[]) null);
287
Object result = method.invoke(u64, (Object[]) null);
288
String buildID = result.toString();
289
// the buildID field consists of a 4 byte platform ID followed by a 4 byte Axxon build ID
290
if (buildID.length() < 8) {
291
return; // build ID hex string is not long enough so can't match any fragments
292
}
293
// 4 bytes = 8 hex chars
294
String shortID = buildID.substring(buildID.length() - 8);
295
String key = vmdata.getVersion() + "-" + buildID; // default is nothing to match
296
if (hasFragmentBeenLoaded(rasClazz, fragments, structureReader, key)) {
297
return; // loaded a fragment matched by it's full build ID
298
}
299
key = vmdata.getVersion() + "-" + shortID;
300
if (hasFragmentBeenLoaded(rasClazz, fragments, structureReader, key)) {
301
return; // loaded a fragment matched by it's short ID
302
}
303
} catch (Exception e) {
304
Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);
305
logger.log(FINE, "Failed to process blob fragments", e);
306
}
307
}
308
309
private static boolean hasFragmentBeenLoaded(Class<?> rasClazz, Properties fragments, StructureReader reader, String key) throws IOException {
310
if (fragments.containsKey(key)) {
311
InputStream in = rasClazz.getResourceAsStream("/fragments/" + fragments.getProperty(key));
312
ImageInputStream iis = new MemoryCacheImageInputStream(in);
313
reader.addStructures(iis);
314
iis.close();
315
return true;
316
} else {
317
return false;
318
}
319
}
320
321
private static ImageInputStream getStructureDataFile(IProcess process, long start) throws IOException {
322
try {
323
if (process.getPlatform() == Platform.ZOS) {
324
return getStructureDataFileFromSymbol(process);
325
} else {
326
return getStructureDataFileFromRASEyecatcher(process, start);
327
}
328
} catch (JVMNotFoundException e) {
329
String structureFileName = System.getProperty(STRUCTUREFILE_PROPERTY);
330
if (structureFileName != null) {
331
// first try to find value specified as a file, if that doesn't work look
332
// for it in the blob archive
333
try {
334
return getStructureDataFromFile(structureFileName, process);
335
} catch (Exception e1) {
336
throw new IOException(e);
337
}
338
}
339
if (process.getPlatform() == Platform.ZOS) {
340
// Check for system property to force searching for JVMs via the eyecatcher
341
if (System.getProperty(SEARCHEYECATCHER_PROPERTY) != null) {
342
return getStructureDataFileFromRASEyecatcher(process, start);
343
}
344
}
345
throw e;
346
}
347
}
348
349
private static ImageInputStream getStructureDataFileFromRASEyecatcher(IProcess process, long start) throws IOException {
350
try {
351
long address = process.findPattern(eyecatcher, 1, start);
352
while (address != -1) {
353
354
long bitPattern = process.getLongAt(address + BIT_PATTERNS_OFFSET);
355
if (bitPattern == integrityCheck) {
356
return foundRAS(process, address);
357
}
358
address = process.findPattern(eyecatcher, 1, address + eyecatcher.length);
359
}
360
361
// Can't find RAS structure, bail out
362
throw new JVMNotFoundException(process, "Could not find J9RAS structure. No Java in process?");
363
} catch (MemoryFault e) {
364
// put the stack trace to the log
365
Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);
366
StringWriter sw = new StringWriter();
367
PrintWriter pw = new PrintWriter(sw);
368
e.printStackTrace(pw);
369
logger.logp(FINE, null, null, sw.toString());
370
throw new IOException(e.getMessage());
371
}
372
}
373
374
// On z/OS multiple VMs could inhabit the same address space - so we can't just search the A/S for a pattern (we can't
375
// tell which enclave (process) it belongs to.
376
// On z/OS we find the RAS structure by looking for the _j9ras_ symbol
377
private static ImageInputStream getStructureDataFileFromSymbol(IProcess process) throws IOException {
378
try {
379
for (IModule thisModule : process.getModules()) {
380
for (ISymbol thisSymbol : thisModule.getSymbols()) {
381
if (thisSymbol.getName().equals(J9RAS_SYMBOL)) {
382
return foundRAS(process, thisSymbol.getAddress());
383
}
384
}
385
}
386
} catch (CorruptDataException e) {
387
throw new IOException(e.getMessage());
388
} catch (DataUnavailableException e) {
389
throw new IOException(e.getMessage());
390
}
391
throw new JVMNotFoundException(process, "Could not find _j9ras_ symbol in process");
392
}
393
394
private static ImageInputStream getStructureDataFromFile(String fileName, IProcess addressSpace) throws IOException {
395
File blobFile = new File(fileName);
396
ImageInputStream iis = new FileImageInputStream(blobFile);
397
398
iis.setByteOrder(addressSpace.getByteOrder());
399
return iis;
400
}
401
402
private static ImageInputStream foundRAS(IProcess addressSpace, long candidateAddress) throws IOException {
403
try {
404
j9RASAddress = candidateAddress;
405
406
String structureFileName = System.getProperty(STRUCTUREFILE_PROPERTY);
407
if (structureFileName != null) {
408
// first try to find value specified as a file, if that doesn't work look
409
// for it in the blob archive
410
try {
411
return getStructureDataFromFile(structureFileName, addressSpace);
412
} catch (FileNotFoundException e) {
413
return getBlobFromArchive(structureFileName, addressSpace);
414
}
415
}
416
417
int j9RASVersion = addressSpace.getIntAt(candidateAddress + J9RAS_VERSION_OFFSET);
418
short j9RASMajorVersion = (short) (j9RASVersion >> 16);
419
420
if (j9RASMajorVersion < MINIMUM_J9RAS_MAJOR_VERSION) {
421
return locateInServiceVMStructure(addressSpace);
422
}
423
424
long ddrDataStart = addressSpace.getPointerAt(candidateAddress + DDR_DATA_POINTER_OFFSET);
425
if (0 == ddrDataStart) {
426
// CMVC 172446 : no valid address to DDR blob, so see if we can locate it via the blob archive
427
try {
428
return locateInServiceVMStructure(addressSpace);
429
} catch (IOException e) {
430
// failed to locate a blob
431
MissingDDRStructuresException ioe = new MissingDDRStructuresException(addressSpace,
432
"System dump was generated by a DDR-enabled JVM, but did not contain embedded DDR structures. This dump cannot be analyzed by DDR. " +
433
"You can specify the location of a DDR structure file to use with the " + STRUCTUREFILE_PROPERTY + " system property");
434
ioe.initCause(e);
435
throw ioe;
436
}
437
}
438
// the address may be a marker to treat it in a special way, rather than as an actual address
439
// -1 = the blob is located directly after this structure
440
// -2 = there is only a blob descriptor loaded
441
long marker = (addressSpace.bytesPerPointer() == 4) ? 0xFFFFFFFF00000000L | ddrDataStart : ddrDataStart;
442
if (marker == -2) {
443
StructureHeader header = new StructureHeader((byte) 1);
444
ddrDataStart = candidateAddress + DDR_DATA_POINTER_OFFSET + (addressSpace.bytesPerPointer() * 2);
445
ImageInputStream stream = new IMemoryImageInputStream(addressSpace, ddrDataStart);
446
header.readBlobVersion(stream);
447
return getBlobFromLibrary(addressSpace, header);
448
}
449
if (marker == -1) {
450
if (j9RASVersion == 0x100000) {
451
ddrDataStart = candidateAddress + DDR_DATA_POINTER_OFFSET + (addressSpace.bytesPerPointer() * 2); // there is one pointer in the way that needs to be skipped over
452
} else {
453
MissingDDRStructuresException ioe = new MissingDDRStructuresException(addressSpace,
454
"System dump was generated by a DDR-enabled JVM, but did not contain embedded DDR structures. This dump cannot be analyzed by DDR. " +
455
"You can specify the location of a DDR structure file to use with the " + STRUCTUREFILE_PROPERTY + " system property");
456
throw ioe;
457
}
458
}
459
460
return new IMemoryImageInputStream(addressSpace, ddrDataStart);
461
} catch (MemoryFault e) {
462
// put the stack trace to the log
463
Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);
464
StringWriter sw = new StringWriter();
465
PrintWriter pw = new PrintWriter(sw);
466
e.printStackTrace(pw);
467
logger.logp(FINE, null, null, sw.toString());
468
throw new IOException(e.getMessage());
469
}
470
}
471
472
// Locate InServiceStructure data for core with old J9RAS
473
private static ImageInputStream locateInServiceVMStructure(IProcess process) throws IOException {
474
// we find the platform/architecture from the process, and look for J9VM build id
475
// in process. Appropriate IOException thrown if any problem here.
476
String path = getBlobBasedirInArchive(process);
477
String j9vmid = getJ9VMBuildInCore(process);
478
479
try {
480
return getBlobFromArchive(path + j9vmid, process);
481
} catch (IOException e) {
482
// we can't find blob file for this build, try to give user enough info to make manual override
483
// using (colon separated) blob index.
484
InputStream indexIS = VMDataFactory.class.getResourceAsStream("/ddr.structurefiles.index");
485
if (indexIS == null) {
486
throw new JVMNotDDREnabledException(process,"DDR could not find VM structure data archive index. J9VM build ID: " + j9vmid
487
+ ". Platform: " + path + ". You can specify a structure file to use manually with the "
488
+ STRUCTUREFILE_PROPERTY + " system property.");
489
}
490
491
BufferedReader reader = new BufferedReader(new InputStreamReader(indexIS));
492
String allBlobs = reader.readLine();
493
String[] blobs = allBlobs.split(":");
494
StringBuffer candidates = new StringBuffer();
495
for (int i = 0; i < blobs.length; i++) {
496
if (blobs[i].startsWith(path)) {
497
if (candidates.length() != 0) {
498
candidates.append(", ");
499
}
500
candidates.append(blobs[i]);
501
}
502
}
503
504
throw new JVMNotDDREnabledException(process, "DDR could not find VM structure data file. J9VM build ID: " + j9vmid
505
+ ". Platform: " + path
506
+ ". You can specify a structure file to use manually with the " + STRUCTUREFILE_PROPERTY
507
+ " system property."
508
+ (candidates.length() > 0 ? " Possible structure file matches: " + candidates.toString() + "." : ""));
509
}
510
}
511
512
private static ImageInputStream getBlobFromArchive(String path, IProcess process) throws IOException {
513
InputStream blobFile = VMDataFactory.class.getResourceAsStream('/' + path);
514
if (blobFile != null) {
515
ImageInputStream iis = new InputStreamImageWrapper(blobFile);
516
iis.setByteOrder(process.getByteOrder());
517
return iis;
518
} else {
519
throw new JVMNotDDREnabledException(process, "DDR could not find VM structure data file " + path);
520
}
521
}
522
523
/**
524
* Wraps InputStream as data source for ImageInputStream
525
* Used to get blob as resource on class path
526
*/
527
private static class InputStreamImageWrapper extends ImageInputStreamImpl {
528
private ByteArrayInputStream is;
529
530
public InputStreamImageWrapper(InputStream inputStream) throws IOException {
531
byte[] buffer = new byte[1024];
532
ByteArrayOutputStream out = new ByteArrayOutputStream();
533
int r = inputStream.read(buffer, 0, buffer.length);
534
while (r != -1) {
535
out.write(buffer, 0, r);
536
r = inputStream.read(buffer, 0, buffer.length);
537
}
538
is = new ByteArrayInputStream(out.toByteArray());
539
}
540
541
@Override
542
public int read() throws IOException {
543
int read = is.read();
544
streamPos++;
545
return read;
546
}
547
548
@Override
549
public int read(byte[] b, int off, int len) throws IOException {
550
int read = is.read(b, off, len);
551
if (read != -1) {
552
streamPos += read;
553
}
554
return read;
555
}
556
557
@Override
558
public long getStreamPosition() throws IOException {
559
return streamPos;
560
}
561
562
@Override
563
public void seek(long pos) throws IOException {
564
super.seek(pos);
565
is.reset();
566
is.skip(streamPos);
567
}
568
}
569
570
private static String getJ9VMBuildInCore(IProcess process) throws IOException {
571
try {
572
// Find J9VM build ID
573
byte[] pattern = "J9VM - ".getBytes(StandardCharsets.US_ASCII); // "J9VM - YYYYMMDD_BUILD_FLAGS"
574
long addr = process.findPattern(pattern, 1, 0);
575
if (addr != -1) {
576
// get string between first and second underscores
577
// we can't hard-code offset as z/OS processes may contain extra bit
578
long startBuildIDAddr = -1;
579
for (long i = 0; i < 30; i++) { // search max of 30 bytes
580
if (process.getByteAt(addr + i) == (byte) '_') {
581
if (startBuildIDAddr == -1) {
582
startBuildIDAddr = addr + i + 1;
583
} else { // we've found second underscore
584
byte[] buildID = new byte[(int) (addr + i - startBuildIDAddr)];
585
for (int j = 0; j < addr + i - startBuildIDAddr; j++) {
586
buildID[j] = process.getByteAt(startBuildIDAddr + j);
587
}
588
return new String(buildID, StandardCharsets.UTF_8);
589
}
590
}
591
}
592
}
593
} catch (MemoryFault e) {
594
throw new IOException(e.getMessage());
595
}
596
throw new JVMNotDDREnabledException(process, "No J9VM build ID found in process");
597
}
598
599
private static String getBlobBasedirInArchive(IProcess process) throws IOException {
600
ICore core = process.getAddressSpace().getCore();
601
602
Platform platform = core.getPlatform();
603
int bytesPerPointer = process.bytesPerPointer();
604
605
switch (platform) {
606
case AIX:
607
if (bytesPerPointer == 4) {
608
return "aix/ppc-32/";
609
} else {
610
return "aix/ppc-64/";
611
}
612
// break;
613
case LINUX:
614
String processorType = core.getProperties().getProperty(ICore.PROCESSOR_TYPE_PROPERTY);
615
// determine platform by processorType
616
if (bytesPerPointer == 4) {
617
if (processorType.equals("x86")) {
618
return "linux/ia32/";
619
} else if (processorType.equals("ppc")) {
620
return "linux/ppc-32/";
621
} else if (processorType.equals("s390")) {
622
return "linux/s390-31/";
623
}
624
} else {
625
if (processorType.equals("amd64")) {
626
return "linux/amd64/";
627
} else if (processorType.equals("ppc")) {
628
return "linux/ppc-64/";
629
} else if (processorType.equals("s390")) {
630
return "linux/s390-64/";
631
}
632
}
633
throw new UnknownArchitectureException(process, "Could not determine architecture for Linux core file.");
634
case WINDOWS:
635
if (bytesPerPointer == 4) {
636
return "win/ia32/";
637
} else {
638
return "win/amd64/";
639
}
640
// break;
641
case ZOS:
642
if (bytesPerPointer == 4) {
643
return "zos/s390-31/";
644
} else {
645
return "zos/s390-64/";
646
}
647
// break;
648
}
649
// shouldn't be here
650
throw new UnknownArchitectureException(process, "Could not determine platform of core file.");
651
}
652
653
/**
654
* Clear the IVMData cache
655
*/
656
public static void clearCache() {
657
vmDataCache.clear();
658
}
659
660
/**
661
* Try and determine a blob by scanning the process.
662
* This can be very expensive and should be the last option tried.
663
*
664
* @param process process to scan
665
* @return a blob if one can be identified, null if not
666
*/
667
private static ImageInputStream getBlobFromLibrary(IProcess process, StructureHeader header) throws JVMNotFoundException {
668
try {
669
if (header != null) {
670
IBlobFactory factory = BlobFactory.getInstance();
671
Platforms platform = null;
672
switch (process.getPlatform()) {
673
case LINUX:
674
platform = (process.bytesPerPointer() == 4) ? Platforms.xi32 : Platforms.xa64;
675
break;
676
default:
677
break;
678
679
}
680
if (platform != null) {
681
int[] data = header.getBlobVersionArray();
682
return factory.getBlob(platform, header.getPackageID(), data[2], data[1], data[0]);
683
}
684
}
685
return null;
686
} catch (Exception e) {
687
throw new JVMNotFoundException(process, e);
688
}
689
}
690
691
private static StructureHeader findNodeVersion(IProcess proc) throws Exception {
692
byte[] pattern = "v0.".getBytes();
693
long pos = 0;
694
do {
695
int[] data = new int[3];
696
data[0] = 0;
697
int count = 1;
698
pos = proc.findPattern(pattern, 0, pos);
699
if (pos != -1) {
700
pos += (pattern.length - 1); // jump over the start of the pattern
701
StringBuilder version = new StringBuilder();
702
while (count < 3) {
703
try {
704
char b = (char) proc.getByteAt(++pos);
705
if ((b >= '0') && (b <= '9')) {
706
version.append(b);
707
} else {
708
try {
709
Integer i = Integer.parseInt(version.toString());
710
data[count++] = i;
711
version = new StringBuilder();
712
} catch (NumberFormatException e) {
713
break; // invalid number so can abort
714
}
715
}
716
} catch (MemoryFault e) {
717
// ignore, but treat as end of input
718
break;
719
}
720
}
721
if (count == 3) {
722
int blobVersion = data[0] << 16 | data[1] << 8 | data[2];
723
StructureHeader header = new StructureHeader(BlobID.node, blobVersion, "node");
724
return header;
725
}
726
}
727
} while (pos != -1);
728
return null;
729
}
730
731
}
732
733