diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/tools/ddrinteractive/BufferedMemory.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/tools/ddrinteractive/BufferedMemory.java new file mode 100644 index 0000000000..463804a113 --- /dev/null +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/tools/ddrinteractive/BufferedMemory.java @@ -0,0 +1,217 @@ +/******************************************************************************* + * Copyright (c) 2019, 2019 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * 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 + *******************************************************************************/ +package com.ibm.j9ddr.corereaders.memory; + +import java.util.Collection; +import java.util.Collections; +import java.nio.ByteOrder; +import java.util.Properties; +import java.util.List; + +import com.ibm.j9ddr.corereaders.memory.AbstractMemory; +import com.ibm.j9ddr.corereaders.memory.IAddressSpace; +import com.ibm.j9ddr.corereaders.Platform; +import com.ibm.j9ddr.corereaders.memory.IModule; +import com.ibm.j9ddr.corereaders.memory.IProcess; +import com.ibm.j9ddr.corereaders.memory.IMemorySource; +import com.ibm.j9ddr.corereaders.memory.MemoryFault; +import com.ibm.j9ddr.CorruptDataException; +import com.ibm.j9ddr.DataUnavailableException; +import com.ibm.j9ddr.corereaders.osthread.IOSThread; +import com.ibm.j9ddr.corereaders.ICore; +import com.ibm.j9ddr.corereaders.memory.SymbolUtil; + +/** + * Object representing a single live + * process model where a section of + * memory in a the process can be represented + * in a byte buffer as its source + * @see com.ibm.j9ddr.tools.ddrinteractive.BufferedMemorySource + * + * Can be used for inspection of the + * scc, without the need of a core file + * For example in the following, it is + * used to inspect romMethods: + * + * + * BufferedMemory memory = new BufferedMemory(ByteOrder.nativeOrder()); + * IVMData aVMData = VMDataFactory.getVMData((IProcess)memory); + * //this address denotes the beginning of range of interest, not shown here + * memory.addMemorySource(new BufferedMemorySource(sourceStartAddress, size)); + * aVMData.bootstrap("com.ibm.j9ddr.vm29.SomeDebugHandler"); + * + * public class SomeDebugHandler { + * //can fetch this address from a ROMClass Cookie + * J9ROMClassPointer pointer = J9ROMClassPointer.cast(romStartAddress); + * J9ROMMethodPointer romMethod = pointer.romMethods(); + * long dumpFlags = (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) ? 1 : 0; + * J9BCUtil.j9bcutil_dumpRomMethod(System.out, romMethod, pointer, dumpFlags, J9BCUtil.BCUtil_DumpAnnotations); + * } + * + * + * Behaviour of the model is not defined + * for the case where the underlying source's + * ByteBuffer is modified (address or capacity) + * during use. + * + * @author knewbury01 + * + */ + +public class BufferedMemory extends AbstractMemory implements IProcess, IAddressSpace +{ + private final int bytesPerPointer; + + public BufferedMemory(ByteOrder byteOrder) { + super(byteOrder); + bytesPerPointer = Integer.parseInt(System.getProperty("sun.arch.data.model")) / 8; + } + + @Override + public Platform getPlatform() { + String platform = System.getProperty("os.name").toLowerCase(); + if (platform.contains("aix")) { + return Platform.AIX; + } else if (platform.contains("windows")) { + return Platform.WINDOWS; + } else if (platform.contains("z/os")) { + return Platform.ZOS; + } else if (platform.contains("linux")) { + return Platform.LINUX; + } else if (platform.contains("mac")) { + return Platform.OSX; + } else { + //do not expect to reach here + throw new InternalError("Unsupported platform"); + } + } + + /** + * + * @return Address space this process uses. + */ + @Override + public IAddressSpace getAddressSpace() { + return this; + } + + @Override + public long getPointerAt(long address) throws MemoryFault { + if (bytesPerPointer == 8) { + return getLongAt(address); + } else { + return 0xFFFFFFFFL & getIntAt(address); + } + } + + /** + * + * @return Number of bytes in a pointer + */ + @Override + public int bytesPerPointer() { + return bytesPerPointer; + } + + /** + * @return Process command line or null if the data is unavailable + * @throws CorruptDataException + */ + @Override + public String getCommandLine() throws DataUnavailableException, CorruptDataException { + throw new DataUnavailableException("DDR not invoked via command line."); + } + + /** + * + * @return Properties containing environment variables name=value pairs + * @throws CorruptDataException + */ + @Override + public Properties getEnvironmentVariables() throws DataUnavailableException, CorruptDataException { + Properties env = new Properties(); + System.getenv().forEach((k, v) -> { + env.setProperty(k, v); + }); + return env; + } + + @Override + public Collection getModules() throws CorruptDataException { + return Collections.emptySet(); + } + + @Override + public IModule getExecutable() throws CorruptDataException { + return null; + } + + @Override + public long getProcessId() throws CorruptDataException { + return -1; + } + + /** + * Equivalent to getProcedureNameForAddress(address, false). + * Default behaviour is to return DDR format strings for symbols. + */ + @Override + public String getProcedureNameForAddress(long address) throws DataUnavailableException, CorruptDataException { + return getProcedureNameForAddress(address, false); + } + + @Override + public String getProcedureNameForAddress(long address, boolean dtfjFormat) throws DataUnavailableException, CorruptDataException { + return SymbolUtil.getProcedureNameForAddress(this, address, dtfjFormat); + } + + @Override + public Collection getThreads() throws CorruptDataException { + return Collections.emptySet(); + } + + @Override + public int getSignalNumber() throws DataUnavailableException { + return 0; + } + + @Override + public boolean isFailingProcess() throws DataUnavailableException { + return false; + } + + @Override + public ICore getCore() { + //not backed by underlying core file + return null; + } + + @Override + public List getProcesses() { + return Collections.singletonList(this); + } + + @Override + public int getAddressSpaceId() { + return 0; + } +} diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/tools/ddrinteractive/BufferedMemorySource.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/tools/ddrinteractive/BufferedMemorySource.java new file mode 100644 index 0000000000..61c6ad4e7f --- /dev/null +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/tools/ddrinteractive/BufferedMemorySource.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * Copyright (c) 2019, 2019 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * 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 + *******************************************************************************/ +package com.ibm.j9ddr.corereaders.memory; + +import java.nio.ByteOrder; +import java.nio.ByteBuffer; +import com.ibm.j9ddr.corereaders.memory.MemoryFault; +import com.ibm.j9ddr.corereaders.Platform; +import com.ibm.j9ddr.corereaders.memory.AbstractMemory; +import com.ibm.j9ddr.corereaders.memory.IMemorySource; +import com.ibm.j9ddr.corereaders.memory.ProtectedMemoryRange; +import java.nio.BufferUnderflowException; + +/** + * Serves as a ByteBuffer backed memory source. + * + * @see com.ibm.j9ddr.tools.ddrinteractive.BufferedMemory + * + * @author knewbury01 + * + */ + +public class BufferedMemorySource extends ProtectedMemoryRange implements IMemorySource +{ + private final ByteBuffer source; + + public BufferedMemorySource(long address, ByteBuffer source) { + super(address, source.capacity()); + this.source = source; + } + + // + // Since the src is byte buffer backed + // it makes most sense to expose the following accessor + // methods from the src implementation + // as opposed to a getBytes (rewrapped) result + // + public int getUnsignedShort(long address) throws MemoryFault { + return getShort(address) & 0xFFFF; + } + + public short getShort(long address) throws MemoryFault { + return source.getShort(checkIndex(address, Short.BYTES)); + } + + public int getInt(long address) throws MemoryFault { + return source.getInt(checkIndex(address, Integer.BYTES)); + } + + public double getDouble(long address) throws MemoryFault { + return source.getDouble(checkIndex(address, Double.BYTES)); + } + + public long getLong(long address) throws MemoryFault { + return source.getLong(checkIndex(address, Long.BYTES)); + } + + public byte getByte(long address) throws MemoryFault { + return source.get(checkIndex(address, 1)); + } + + @Override + public int getBytes(long address, byte[] buffer, int offset, int length) throws MemoryFault { + int index = checkIndex(address, length); + for (int i = 0; i < length; i++) { + buffer[offset + i] = source.get(index + i); + } + return length; + } + + private int checkIndex(long address, int byteCount) throws MemoryFault { + if (byteCount < 0) { + throw new IllegalArgumentException(); + } + + long maxAddress = baseAddress + Math.min(getSize(), Integer.MAX_VALUE) - byteCount; + + if ((address < baseAddress) || (address > maxAddress)) { + throw new MemoryFault(address); + } + return (int) (address - baseAddress); + } + + public ByteOrder getByteOrder() { + return source.order(); + } + + @Override + public String getName() { + return null; + } + + @Override + public int getAddressSpaceId() { + return 0; + } +}