Path: blob/master/debugtools/DDR_VM/src/com/ibm/j9ddr/VMDataFactory.java
6004 views
/*******************************************************************************1* Copyright (c) 1991, 2021 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* 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-exception20*******************************************************************************/21package com.ibm.j9ddr;2223import static java.util.logging.Level.FINE;2425import java.io.BufferedReader;26import java.io.ByteArrayInputStream;27import java.io.ByteArrayOutputStream;28import java.io.File;29import java.io.FileNotFoundException;30import java.io.IOException;31import java.io.InputStream;32import java.io.InputStreamReader;33import java.io.PrintWriter;34import java.io.StringWriter;35import java.lang.reflect.InvocationTargetException;36import java.lang.reflect.Method;37import java.nio.charset.StandardCharsets;38import java.security.AccessController;39import java.security.PrivilegedAction;40import java.util.ArrayList;41import java.util.HashSet;42import java.util.List;43import java.util.Properties;44import java.util.Set;45import java.util.logging.Logger;4647import javax.imageio.stream.FileImageInputStream;48import javax.imageio.stream.ImageInputStream;49import javax.imageio.stream.ImageInputStreamImpl;50import javax.imageio.stream.MemoryCacheImageInputStream;5152import com.ibm.j9ddr.StructureHeader.BlobID;53import com.ibm.j9ddr.StructureReader.PackageNameType;54import com.ibm.j9ddr.blobs.BlobFactory;55import com.ibm.j9ddr.blobs.IBlobFactory;56import com.ibm.j9ddr.blobs.IBlobFactory.Platforms;57import com.ibm.j9ddr.corereaders.ICore;58import com.ibm.j9ddr.corereaders.Platform;59import com.ibm.j9ddr.corereaders.memory.IMemoryImageInputStream;60import com.ibm.j9ddr.corereaders.memory.IModule;61import com.ibm.j9ddr.corereaders.memory.IProcess;62import com.ibm.j9ddr.corereaders.memory.ISymbol;63import com.ibm.j9ddr.corereaders.memory.MemoryFault;64import com.ibm.j9ddr.exceptions.CorruptStructuresException;65import com.ibm.j9ddr.exceptions.JVMNotDDREnabledException;66import com.ibm.j9ddr.exceptions.JVMNotFoundException;67import com.ibm.j9ddr.exceptions.MissingDDRStructuresException;68import com.ibm.j9ddr.exceptions.UnknownArchitectureException;69import com.ibm.j9ddr.logging.LoggerNames;70import com.ibm.j9ddr.util.WeakValueMap;7172/**73* Create IVMData instances for each VM found in a Process74*/75public abstract class VMDataFactory {76private final static String STRUCTUREFILE_PROPERTY = "com.ibm.j9ddr.structurefile";77private final static String SEARCHEYECATCHER_PROPERTY = "com.ibm.j9ddr.searcheyecatcher";78private final static String NOEXTRASEARCHFORNODE_PROPERTY = "com.ibm.j9ddr.noextrasearchfornode";7980/* Symbol used to find the J9RAS structure on z/OS */81public static final String J9RAS_SYMBOL = "_j9ras_";82private static final byte[] eyecatcher = "J9VMRAS".getBytes(StandardCharsets.US_ASCII);83private static final long integrityCheck = 0xaa55aa55aa55aa55L;84private static final int BIT_PATTERNS_OFFSET = 0x8;85private static final int J9RAS_VERSION_OFFSET = 0x10;86private static final int DDR_DATA_POINTER_OFFSET = 0x18;87private static final int MINIMUM_J9RAS_MAJOR_VERSION = 2;88private static long j9RASAddress;8990// a process can have more than one blob present, each blob is represented as a separate IVMData91private static WeakValueMap<IProcess, List<IVMData>> vmDataCache = new WeakValueMap<>();9293/**94* Returns a VMData for the first VM located in the process95* @param process96* @return97* @throws IOException98*/99public static IVMData getVMData(IProcess process) throws IOException {100List<IVMData> cachedVMData = vmDataCache.get(process);101102if ((cachedVMData != null) && (cachedVMData.size() > 0)) {103return cachedVMData.get(0); // return the first VM found104}105106cachedVMData = getAllVMData(process);107108if (cachedVMData.size() > 0) {109return cachedVMData.get(0); // return the first VM found110} else {111return null; // nothing was found in scan112}113}114// TODO - fix this for z/OS which will require noting which RAS symbols have already been found in the core115116/**117* Finds all of the blobs in a given process and wraps them in a IVMData structure.118*119* @param process process to scan120* @return all located blobs121* @throws IOException re-throws IOExceptions122*/123public synchronized static List<IVMData> getAllVMData(IProcess process) throws IOException {124List<IVMData> cachedVMData = vmDataCache.get(process);125126if (cachedVMData != null) {127return cachedVMData;128}129130// nothing in the cache for this process, so need to scan131// Get an ImageInputStream on the Structure Offset Data. This may or may not be in the core file itself.132List<IVMData> data = new ArrayList<>();133Set<Long> attemptedAddresses = new HashSet<>();134j9RASAddress = 0;135for (;;) {136long address = j9RASAddress + 1;137if (!attemptedAddresses.add(Long.valueOf(address))) {138// we already tried this address: give up now139break;140}141try {142ImageInputStream in = getStructureDataFile(process, address);143if (in == null) {144break;145}146IVMData vmdata = getVMData(process, in);147data.add(vmdata);148if (vmdata.getClassLoader().getHeader().getCoreVersion() == 1) {149// version 1 does not support multiple blobs150break;151}152if (!(in instanceof IMemoryImageInputStream)) {153break;154}155} catch (JVMNotFoundException e) {156// no more JVMs were found157break;158} catch (JVMNotDDREnabledException e) {159// an older JVM was found, so ignore that and carry on looking160if (process.getPlatform() == Platform.ZOS) {161// on z/OS a failure with the j9ras symbol resolution aborts the scan162break;163}164} catch (MissingDDRStructuresException e) {165// cannot process as the structures are missing166if (process.getPlatform() == Platform.ZOS) {167// on z/OS a failure with the j9ras symbol resolution aborts the scan168break;169}170} catch (CorruptStructuresException e) {171// cannot process as the structures are corrupt and cannot be read172if (process.getPlatform() == Platform.ZOS) {173// on z/OS a failure with the j9ras symbol resolution aborts the scan174break;175}176} catch (IOException e) {177// ignore, but unless j9RASAddress has changed we'll give up178}179}180181// For Node.JS only, if we have not found a BLOB at this point we do a more expensive scan. This extra182// scan is switched off for Java-only applications (specifically jdmpview) via a system property.183if (data.isEmpty() && (System.getProperty(NOEXTRASEARCHFORNODE_PROPERTY) == null)) {184StructureHeader header;185try {186header = findNodeVersion(process);187} catch (IOException e) {188throw e;189} catch (Exception e) {190throw new IOException(e);191}192if (header != null) {193ImageInputStream in = getBlobFromLibrary(process, header);194if (in != null) {195IVMData vmdata = getVMData(process, in);196data.add(vmdata);197}198}199}200201vmDataCache.put(process, data);202203return data;204}205206private static IVMData getVMData(IProcess process, ImageInputStream in) throws IOException {207// Create and initialize a StructureClassLoader for this VM instance208final StructureReader structureReader = new StructureReader(in);209210J9DDRClassLoader ddrClassLoader = AccessController.doPrivileged(new PrivilegedAction<J9DDRClassLoader>() {211@Override212public J9DDRClassLoader run() {213return new J9DDRClassLoader(structureReader, VMDataFactory.class.getClassLoader());214}215});216217try {218// Load and instantiate a VMData object. Load the VMData class for each core file219IVMData vmData = ddrClassLoader.getIVMData(process, j9RASAddress);220221// Load and initialize the statics on DataType for this core file.222Class<?> dataTypeClazz = ddrClassLoader.loadClassRelativeToStream("j9.DataType", false);223Method initMethod = dataTypeClazz.getDeclaredMethod("init", IProcess.class, StructureReader.class);224initMethod.invoke(null, process, structureReader);225226// Load an instantiate a VM specific J9RASPointer via a call to J9RASPointer.cast(long);227String basePackageName = structureReader.getPackageName(PackageNameType.POINTER_PACKAGE_DOT_NAME);228Class<?> rasClazz = ddrClassLoader.loadClass(basePackageName + ".J9RASPointer");229Method getStructureMethod = rasClazz.getDeclaredMethod("cast", new Class[] { Long.TYPE });230Object pointer = getStructureMethod.invoke(null, new Object[] { j9RASAddress });231232// Set the J9RASPointer on DataType.233Method setMethod = dataTypeClazz.getDeclaredMethod("setJ9RASPointer", pointer.getClass());234setMethod.invoke(vmData, new Object[] { pointer });235236// now add any blob fragments for this build237addFragments(rasClazz, pointer, structureReader, vmData);238239if (!Boolean.FALSE.toString().equals(System.getProperty("com.ibm.j9ddr.symbols.from.pointers"))) {240DDRSymbolFinder.addSymbols(process, j9RASAddress, structureReader);241}242243return vmData;244} catch (ClassNotFoundException e) {245Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);246logger.log(FINE, null, e);247throw new IOException(String.format("Invalid or unavailable structure offset data. %s", e.getMessage()));248} catch (NoSuchMethodException e) {249Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);250logger.log(FINE, null, e);251throw new IOException(String.format("Invalid or unavailable structure offset data. %s", e.getMessage()));252} catch (IllegalAccessException e) {253Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);254logger.log(FINE, null, e);255throw new IOException(String.format("Invalid or unavailable structure offset data. %s", e.getMessage()));256} catch (InvocationTargetException e) {257Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);258logger.log(FINE, null, e);259throw new IOException(String.format("Invalid or unavailable structure offset data. %s", e.getMessage()));260} catch (InstantiationException e) {261Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);262logger.log(FINE, null, e);263throw new IOException(String.format("Invalid or unavailable structure offset data. %s", e.getMessage()));264}265}266267/**268* Add any blob fragments which apply to this build269*270* @param rasptr pointer to the RAS structure so that we can get the buildID271*/272private static void addFragments(Class<?> rasClazz, Object rasptr, final StructureReader structureReader, IVMData vmdata) {273try {274InputStream in = rasClazz.getResourceAsStream("/fragments/fragments.properties");275if (in == null) {276Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);277logger.log(FINE, "Failed to find fragments property file");278return; // no property file found279}280Properties fragments = new Properties();281fragments.load(in);282in.close();283Method method = rasClazz.getDeclaredMethod("buildID", (Class<?>[]) null);284Object u64 = method.invoke(rasptr, (Object[]) null);285method = u64.getClass().getMethod("getHexValue", (Class<?>[]) null);286Object result = method.invoke(u64, (Object[]) null);287String buildID = result.toString();288// the buildID field consists of a 4 byte platform ID followed by a 4 byte Axxon build ID289if (buildID.length() < 8) {290return; // build ID hex string is not long enough so can't match any fragments291}292// 4 bytes = 8 hex chars293String shortID = buildID.substring(buildID.length() - 8);294String key = vmdata.getVersion() + "-" + buildID; // default is nothing to match295if (hasFragmentBeenLoaded(rasClazz, fragments, structureReader, key)) {296return; // loaded a fragment matched by it's full build ID297}298key = vmdata.getVersion() + "-" + shortID;299if (hasFragmentBeenLoaded(rasClazz, fragments, structureReader, key)) {300return; // loaded a fragment matched by it's short ID301}302} catch (Exception e) {303Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);304logger.log(FINE, "Failed to process blob fragments", e);305}306}307308private static boolean hasFragmentBeenLoaded(Class<?> rasClazz, Properties fragments, StructureReader reader, String key) throws IOException {309if (fragments.containsKey(key)) {310InputStream in = rasClazz.getResourceAsStream("/fragments/" + fragments.getProperty(key));311ImageInputStream iis = new MemoryCacheImageInputStream(in);312reader.addStructures(iis);313iis.close();314return true;315} else {316return false;317}318}319320private static ImageInputStream getStructureDataFile(IProcess process, long start) throws IOException {321try {322if (process.getPlatform() == Platform.ZOS) {323return getStructureDataFileFromSymbol(process);324} else {325return getStructureDataFileFromRASEyecatcher(process, start);326}327} catch (JVMNotFoundException e) {328String structureFileName = System.getProperty(STRUCTUREFILE_PROPERTY);329if (structureFileName != null) {330// first try to find value specified as a file, if that doesn't work look331// for it in the blob archive332try {333return getStructureDataFromFile(structureFileName, process);334} catch (Exception e1) {335throw new IOException(e);336}337}338if (process.getPlatform() == Platform.ZOS) {339// Check for system property to force searching for JVMs via the eyecatcher340if (System.getProperty(SEARCHEYECATCHER_PROPERTY) != null) {341return getStructureDataFileFromRASEyecatcher(process, start);342}343}344throw e;345}346}347348private static ImageInputStream getStructureDataFileFromRASEyecatcher(IProcess process, long start) throws IOException {349try {350long address = process.findPattern(eyecatcher, 1, start);351while (address != -1) {352353long bitPattern = process.getLongAt(address + BIT_PATTERNS_OFFSET);354if (bitPattern == integrityCheck) {355return foundRAS(process, address);356}357address = process.findPattern(eyecatcher, 1, address + eyecatcher.length);358}359360// Can't find RAS structure, bail out361throw new JVMNotFoundException(process, "Could not find J9RAS structure. No Java in process?");362} catch (MemoryFault e) {363// put the stack trace to the log364Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);365StringWriter sw = new StringWriter();366PrintWriter pw = new PrintWriter(sw);367e.printStackTrace(pw);368logger.logp(FINE, null, null, sw.toString());369throw new IOException(e.getMessage());370}371}372373// 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't374// tell which enclave (process) it belongs to.375// On z/OS we find the RAS structure by looking for the _j9ras_ symbol376private static ImageInputStream getStructureDataFileFromSymbol(IProcess process) throws IOException {377try {378for (IModule thisModule : process.getModules()) {379for (ISymbol thisSymbol : thisModule.getSymbols()) {380if (thisSymbol.getName().equals(J9RAS_SYMBOL)) {381return foundRAS(process, thisSymbol.getAddress());382}383}384}385} catch (CorruptDataException e) {386throw new IOException(e.getMessage());387} catch (DataUnavailableException e) {388throw new IOException(e.getMessage());389}390throw new JVMNotFoundException(process, "Could not find _j9ras_ symbol in process");391}392393private static ImageInputStream getStructureDataFromFile(String fileName, IProcess addressSpace) throws IOException {394File blobFile = new File(fileName);395ImageInputStream iis = new FileImageInputStream(blobFile);396397iis.setByteOrder(addressSpace.getByteOrder());398return iis;399}400401private static ImageInputStream foundRAS(IProcess addressSpace, long candidateAddress) throws IOException {402try {403j9RASAddress = candidateAddress;404405String structureFileName = System.getProperty(STRUCTUREFILE_PROPERTY);406if (structureFileName != null) {407// first try to find value specified as a file, if that doesn't work look408// for it in the blob archive409try {410return getStructureDataFromFile(structureFileName, addressSpace);411} catch (FileNotFoundException e) {412return getBlobFromArchive(structureFileName, addressSpace);413}414}415416int j9RASVersion = addressSpace.getIntAt(candidateAddress + J9RAS_VERSION_OFFSET);417short j9RASMajorVersion = (short) (j9RASVersion >> 16);418419if (j9RASMajorVersion < MINIMUM_J9RAS_MAJOR_VERSION) {420return locateInServiceVMStructure(addressSpace);421}422423long ddrDataStart = addressSpace.getPointerAt(candidateAddress + DDR_DATA_POINTER_OFFSET);424if (0 == ddrDataStart) {425// CMVC 172446 : no valid address to DDR blob, so see if we can locate it via the blob archive426try {427return locateInServiceVMStructure(addressSpace);428} catch (IOException e) {429// failed to locate a blob430MissingDDRStructuresException ioe = new MissingDDRStructuresException(addressSpace,431"System dump was generated by a DDR-enabled JVM, but did not contain embedded DDR structures. This dump cannot be analyzed by DDR. " +432"You can specify the location of a DDR structure file to use with the " + STRUCTUREFILE_PROPERTY + " system property");433ioe.initCause(e);434throw ioe;435}436}437// the address may be a marker to treat it in a special way, rather than as an actual address438// -1 = the blob is located directly after this structure439// -2 = there is only a blob descriptor loaded440long marker = (addressSpace.bytesPerPointer() == 4) ? 0xFFFFFFFF00000000L | ddrDataStart : ddrDataStart;441if (marker == -2) {442StructureHeader header = new StructureHeader((byte) 1);443ddrDataStart = candidateAddress + DDR_DATA_POINTER_OFFSET + (addressSpace.bytesPerPointer() * 2);444ImageInputStream stream = new IMemoryImageInputStream(addressSpace, ddrDataStart);445header.readBlobVersion(stream);446return getBlobFromLibrary(addressSpace, header);447}448if (marker == -1) {449if (j9RASVersion == 0x100000) {450ddrDataStart = candidateAddress + DDR_DATA_POINTER_OFFSET + (addressSpace.bytesPerPointer() * 2); // there is one pointer in the way that needs to be skipped over451} else {452MissingDDRStructuresException ioe = new MissingDDRStructuresException(addressSpace,453"System dump was generated by a DDR-enabled JVM, but did not contain embedded DDR structures. This dump cannot be analyzed by DDR. " +454"You can specify the location of a DDR structure file to use with the " + STRUCTUREFILE_PROPERTY + " system property");455throw ioe;456}457}458459return new IMemoryImageInputStream(addressSpace, ddrDataStart);460} catch (MemoryFault e) {461// put the stack trace to the log462Logger logger = Logger.getLogger(LoggerNames.LOGGER_STRUCTURE_READER);463StringWriter sw = new StringWriter();464PrintWriter pw = new PrintWriter(sw);465e.printStackTrace(pw);466logger.logp(FINE, null, null, sw.toString());467throw new IOException(e.getMessage());468}469}470471// Locate InServiceStructure data for core with old J9RAS472private static ImageInputStream locateInServiceVMStructure(IProcess process) throws IOException {473// we find the platform/architecture from the process, and look for J9VM build id474// in process. Appropriate IOException thrown if any problem here.475String path = getBlobBasedirInArchive(process);476String j9vmid = getJ9VMBuildInCore(process);477478try {479return getBlobFromArchive(path + j9vmid, process);480} catch (IOException e) {481// we can't find blob file for this build, try to give user enough info to make manual override482// using (colon separated) blob index.483InputStream indexIS = VMDataFactory.class.getResourceAsStream("/ddr.structurefiles.index");484if (indexIS == null) {485throw new JVMNotDDREnabledException(process,"DDR could not find VM structure data archive index. J9VM build ID: " + j9vmid486+ ". Platform: " + path + ". You can specify a structure file to use manually with the "487+ STRUCTUREFILE_PROPERTY + " system property.");488}489490BufferedReader reader = new BufferedReader(new InputStreamReader(indexIS));491String allBlobs = reader.readLine();492String[] blobs = allBlobs.split(":");493StringBuffer candidates = new StringBuffer();494for (int i = 0; i < blobs.length; i++) {495if (blobs[i].startsWith(path)) {496if (candidates.length() != 0) {497candidates.append(", ");498}499candidates.append(blobs[i]);500}501}502503throw new JVMNotDDREnabledException(process, "DDR could not find VM structure data file. J9VM build ID: " + j9vmid504+ ". Platform: " + path505+ ". You can specify a structure file to use manually with the " + STRUCTUREFILE_PROPERTY506+ " system property."507+ (candidates.length() > 0 ? " Possible structure file matches: " + candidates.toString() + "." : ""));508}509}510511private static ImageInputStream getBlobFromArchive(String path, IProcess process) throws IOException {512InputStream blobFile = VMDataFactory.class.getResourceAsStream('/' + path);513if (blobFile != null) {514ImageInputStream iis = new InputStreamImageWrapper(blobFile);515iis.setByteOrder(process.getByteOrder());516return iis;517} else {518throw new JVMNotDDREnabledException(process, "DDR could not find VM structure data file " + path);519}520}521522/**523* Wraps InputStream as data source for ImageInputStream524* Used to get blob as resource on class path525*/526private static class InputStreamImageWrapper extends ImageInputStreamImpl {527private ByteArrayInputStream is;528529public InputStreamImageWrapper(InputStream inputStream) throws IOException {530byte[] buffer = new byte[1024];531ByteArrayOutputStream out = new ByteArrayOutputStream();532int r = inputStream.read(buffer, 0, buffer.length);533while (r != -1) {534out.write(buffer, 0, r);535r = inputStream.read(buffer, 0, buffer.length);536}537is = new ByteArrayInputStream(out.toByteArray());538}539540@Override541public int read() throws IOException {542int read = is.read();543streamPos++;544return read;545}546547@Override548public int read(byte[] b, int off, int len) throws IOException {549int read = is.read(b, off, len);550if (read != -1) {551streamPos += read;552}553return read;554}555556@Override557public long getStreamPosition() throws IOException {558return streamPos;559}560561@Override562public void seek(long pos) throws IOException {563super.seek(pos);564is.reset();565is.skip(streamPos);566}567}568569private static String getJ9VMBuildInCore(IProcess process) throws IOException {570try {571// Find J9VM build ID572byte[] pattern = "J9VM - ".getBytes(StandardCharsets.US_ASCII); // "J9VM - YYYYMMDD_BUILD_FLAGS"573long addr = process.findPattern(pattern, 1, 0);574if (addr != -1) {575// get string between first and second underscores576// we can't hard-code offset as z/OS processes may contain extra bit577long startBuildIDAddr = -1;578for (long i = 0; i < 30; i++) { // search max of 30 bytes579if (process.getByteAt(addr + i) == (byte) '_') {580if (startBuildIDAddr == -1) {581startBuildIDAddr = addr + i + 1;582} else { // we've found second underscore583byte[] buildID = new byte[(int) (addr + i - startBuildIDAddr)];584for (int j = 0; j < addr + i - startBuildIDAddr; j++) {585buildID[j] = process.getByteAt(startBuildIDAddr + j);586}587return new String(buildID, StandardCharsets.UTF_8);588}589}590}591}592} catch (MemoryFault e) {593throw new IOException(e.getMessage());594}595throw new JVMNotDDREnabledException(process, "No J9VM build ID found in process");596}597598private static String getBlobBasedirInArchive(IProcess process) throws IOException {599ICore core = process.getAddressSpace().getCore();600601Platform platform = core.getPlatform();602int bytesPerPointer = process.bytesPerPointer();603604switch (platform) {605case AIX:606if (bytesPerPointer == 4) {607return "aix/ppc-32/";608} else {609return "aix/ppc-64/";610}611// break;612case LINUX:613String processorType = core.getProperties().getProperty(ICore.PROCESSOR_TYPE_PROPERTY);614// determine platform by processorType615if (bytesPerPointer == 4) {616if (processorType.equals("x86")) {617return "linux/ia32/";618} else if (processorType.equals("ppc")) {619return "linux/ppc-32/";620} else if (processorType.equals("s390")) {621return "linux/s390-31/";622}623} else {624if (processorType.equals("amd64")) {625return "linux/amd64/";626} else if (processorType.equals("ppc")) {627return "linux/ppc-64/";628} else if (processorType.equals("s390")) {629return "linux/s390-64/";630}631}632throw new UnknownArchitectureException(process, "Could not determine architecture for Linux core file.");633case WINDOWS:634if (bytesPerPointer == 4) {635return "win/ia32/";636} else {637return "win/amd64/";638}639// break;640case ZOS:641if (bytesPerPointer == 4) {642return "zos/s390-31/";643} else {644return "zos/s390-64/";645}646// break;647}648// shouldn't be here649throw new UnknownArchitectureException(process, "Could not determine platform of core file.");650}651652/**653* Clear the IVMData cache654*/655public static void clearCache() {656vmDataCache.clear();657}658659/**660* Try and determine a blob by scanning the process.661* This can be very expensive and should be the last option tried.662*663* @param process process to scan664* @return a blob if one can be identified, null if not665*/666private static ImageInputStream getBlobFromLibrary(IProcess process, StructureHeader header) throws JVMNotFoundException {667try {668if (header != null) {669IBlobFactory factory = BlobFactory.getInstance();670Platforms platform = null;671switch (process.getPlatform()) {672case LINUX:673platform = (process.bytesPerPointer() == 4) ? Platforms.xi32 : Platforms.xa64;674break;675default:676break;677678}679if (platform != null) {680int[] data = header.getBlobVersionArray();681return factory.getBlob(platform, header.getPackageID(), data[2], data[1], data[0]);682}683}684return null;685} catch (Exception e) {686throw new JVMNotFoundException(process, e);687}688}689690private static StructureHeader findNodeVersion(IProcess proc) throws Exception {691byte[] pattern = "v0.".getBytes();692long pos = 0;693do {694int[] data = new int[3];695data[0] = 0;696int count = 1;697pos = proc.findPattern(pattern, 0, pos);698if (pos != -1) {699pos += (pattern.length - 1); // jump over the start of the pattern700StringBuilder version = new StringBuilder();701while (count < 3) {702try {703char b = (char) proc.getByteAt(++pos);704if ((b >= '0') && (b <= '9')) {705version.append(b);706} else {707try {708Integer i = Integer.parseInt(version.toString());709data[count++] = i;710version = new StringBuilder();711} catch (NumberFormatException e) {712break; // invalid number so can abort713}714}715} catch (MemoryFault e) {716// ignore, but treat as end of input717break;718}719}720if (count == 3) {721int blobVersion = data[0] << 16 | data[1] << 8 | data[2];722StructureHeader header = new StructureHeader(BlobID.node, blobVersion, "node");723return header;724}725}726} while (pos != -1);727return null;728}729730}731732733