Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/DebuggerBase.java
41161 views
/*1* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324package sun.jvm.hotspot.debugger;2526/** <P> DebuggerBase is a recommended base class for debugger27implementations. It can use a PageCache to cache data from the28target process. Note that this class would not be suitable if the29system were used to reflect upon itself; it would never be safe to30store the value in an OopHandle in anything but an OopHandle.31However, it provides a fair amount of code sharing to the current32dbx and win32 implementations. </P>3334<P> NOTE that much of the code sharing is achieved by having this35class implement many of the methods in the Win32Debugger and36DbxDebugger interfaces. </P> */3738public abstract class DebuggerBase implements Debugger {3940// May be set lazily, but must be set before calling any of the read41// routines below42protected MachineDescription machDesc;43protected DebuggerUtilities utils;44// Java primitive type sizes, set during bootstrapping. Do not call45// any of the Java read routines until these are set up.46protected long jbooleanSize;47protected long jbyteSize;48protected long jcharSize;49protected long jdoubleSize;50protected long jfloatSize;51protected long jintSize;52protected long jlongSize;53protected long jshortSize;54protected boolean javaPrimitiveTypesConfigured;55// heap data.56protected long oopSize;57protected long heapOopSize;58protected long narrowOopBase; // heap base for compressed oops.59protected int narrowOopShift; // shift to decode compressed oops.60// class metadata space61protected long klassPtrSize;62protected long narrowKlassBase; // heap base for compressed klass ptrs.63protected int narrowKlassShift; // shift to decode compressed klass ptrs.64// Should be initialized if desired by calling initCache()65private PageCache cache;6667// State for faster accessors that don't allocate memory on each read68private boolean useFastAccessors;69private boolean bigEndian;7071// Page-fetching functionality for LRU cache72class Fetcher implements PageFetcher {73public Page fetchPage(long pageBaseAddress, long numBytes) {74// This assumes that if any byte is unmapped, that the entire75// page is. The common case, however, is that the page is76// mapped, so we always fetch the entire thing all at once to77// avoid two round-trip communications per page fetch, even78// though fetching of unmapped pages will be slow.79ReadResult res = readBytesFromProcess(pageBaseAddress, numBytes);80if (res.getData() == null) {81return new Page(pageBaseAddress, numBytes);82}83return new Page(pageBaseAddress, res.getData());84}85}8687protected DebuggerBase() {88}8990/** From the JVMDebugger interface. This is the only public method91of this class. */92public void configureJavaPrimitiveTypeSizes(long jbooleanSize,93long jbyteSize,94long jcharSize,95long jdoubleSize,96long jfloatSize,97long jintSize,98long jlongSize,99long jshortSize) {100this.jbooleanSize = jbooleanSize;101this.jbyteSize = jbyteSize;102this.jcharSize = jcharSize;103this.jdoubleSize = jdoubleSize;104this.jfloatSize = jfloatSize;105this.jintSize = jintSize;106this.jlongSize = jlongSize;107this.jshortSize = jshortSize;108109if (jbooleanSize < 1) {110throw new RuntimeException("jboolean size is too small");111}112113if (jbyteSize < 1) {114throw new RuntimeException("jbyte size is too small");115}116117if (jcharSize < 2) {118throw new RuntimeException("jchar size is too small");119}120121if (jdoubleSize < 8) {122throw new RuntimeException("jdouble size is too small");123}124125if (jfloatSize < 4) {126throw new RuntimeException("jfloat size is too small");127}128129if (jintSize < 4) {130throw new RuntimeException("jint size is too small");131}132133if (jlongSize < 8) {134throw new RuntimeException("jlong size is too small");135}136137if (jshortSize < 2) {138throw new RuntimeException("jshort size is too small");139}140141if (jintSize != jfloatSize) {142// If dataToJFloat were rewritten, this wouldn't be necessary143throw new RuntimeException("jint size and jfloat size must be equal");144}145146if (jlongSize != jdoubleSize) {147// If dataToJDouble were rewritten, this wouldn't be necessary148throw new RuntimeException("jlong size and jdouble size must be equal");149}150151useFastAccessors =152((cache != null) &&153(jbooleanSize == 1) &&154(jbyteSize == 1) &&155(jcharSize == 2) &&156(jdoubleSize == 8) &&157(jfloatSize == 4) &&158(jintSize == 4) &&159(jlongSize == 8) &&160(jshortSize == 2));161162javaPrimitiveTypesConfigured = true;163}164165public void putHeapConst(long heapOopSize, long klassPtrSize, long narrowOopBase, int narrowOopShift,166long narrowKlassBase, int narrowKlassShift) {167this.heapOopSize = heapOopSize;168this.klassPtrSize = klassPtrSize;169this.narrowOopBase = narrowOopBase;170this.narrowOopShift = narrowOopShift;171this.narrowKlassBase = narrowKlassBase;172this.narrowKlassShift = narrowKlassShift;173}174175/** May be called by subclasses if desired to initialize the page176cache but may not be overridden */177protected final void initCache(long pageSize, long maxNumPages) {178cache = new PageCache(pageSize, maxNumPages, new Fetcher());179if (machDesc != null) {180bigEndian = machDesc.isBigEndian();181}182}183184/** May be called by subclasses if needed (if the machine185description is not available at the time of cache186initialization, as on Solaris) but may not be overridden */187protected final void setBigEndian(boolean bigEndian) {188this.bigEndian = bigEndian;189}190191/** May be called by subclasses to clear out the cache but may not192be overridden. For convenience, this can be called even if the193cache has not been initialized. */194protected final void clearCache() {195if (cache != null) {196cache.clear();197}198}199200/** May be called by subclasses to disable the cache (for example,201when the target process has been resumed) but may not be202overridden. For convenience, this can be called even if the203cache has not been initialized. */204protected final void disableCache() {205if (cache != null) {206cache.disable();207}208}209210/** May be called by subclasses to re-enable the cache (for example,211when the target process has been suspended) but may not be212overridden. For convenience, this can be called even if the213cache has not been initialized. */214protected final void enableCache() {215if (cache != null) {216cache.enable();217}218}219220/** May be called by subclasses directly but may not be overridden */221protected final byte[] readBytes(long address, long numBytes)222throws UnmappedAddressException, DebuggerException {223if (cache != null) {224return cache.getData(address, numBytes);225} else {226ReadResult res = readBytesFromProcess(address, numBytes);227if (res.getData() != null) {228return res.getData();229}230throw new UnmappedAddressException(res.getFailureAddress());231}232}233234/** May be called by subclasses directly but may not be overridden */235protected final void writeBytes(long address, long numBytes, byte[] data)236throws UnmappedAddressException, DebuggerException {237if (cache != null) {238cache.clear(address, numBytes);239}240writeBytesToProcess(address, numBytes, data);241}242243public boolean readJBoolean(long address)244throws UnmappedAddressException, UnalignedAddressException {245checkJavaConfigured();246utils.checkAlignment(address, jbooleanSize);247if (useFastAccessors) {248return (cache.getByte(address) != 0);249} else {250byte[] data = readBytes(address, jbooleanSize);251return utils.dataToJBoolean(data, jbooleanSize);252}253}254255public byte readJByte(long address)256throws UnmappedAddressException, UnalignedAddressException {257checkJavaConfigured();258utils.checkAlignment(address, jbyteSize);259if (useFastAccessors) {260return cache.getByte(address);261} else {262byte[] data = readBytes(address, jbyteSize);263return utils.dataToJByte(data, jbyteSize);264}265}266267// NOTE: assumes value does not span pages (may be bad assumption on268// Solaris/x86; see unalignedAccessesOkay in DbxDebugger hierarchy)269public char readJChar(long address)270throws UnmappedAddressException, UnalignedAddressException {271checkJavaConfigured();272utils.checkAlignment(address, jcharSize);273if (useFastAccessors) {274return cache.getChar(address, bigEndian);275} else {276byte[] data = readBytes(address, jcharSize);277return (char) utils.dataToJChar(data, jcharSize);278}279}280281// NOTE: assumes value does not span pages (may be bad assumption on282// Solaris/x86; see unalignedAccessesOkay in DbxDebugger hierarchy)283public double readJDouble(long address)284throws UnmappedAddressException, UnalignedAddressException {285checkJavaConfigured();286utils.checkAlignment(address, jdoubleSize);287if (useFastAccessors) {288return cache.getDouble(address, bigEndian);289} else {290byte[] data = readBytes(address, jdoubleSize);291return utils.dataToJDouble(data, jdoubleSize);292}293}294295// NOTE: assumes value does not span pages (may be bad assumption on296// Solaris/x86; see unalignedAccessesOkay in DbxDebugger hierarchy)297public float readJFloat(long address)298throws UnmappedAddressException, UnalignedAddressException {299checkJavaConfigured();300utils.checkAlignment(address, jfloatSize);301if (useFastAccessors) {302return cache.getFloat(address, bigEndian);303} else {304byte[] data = readBytes(address, jfloatSize);305return utils.dataToJFloat(data, jfloatSize);306}307}308309// NOTE: assumes value does not span pages (may be bad assumption on310// Solaris/x86; see unalignedAccessesOkay in DbxDebugger hierarchy)311public int readJInt(long address)312throws UnmappedAddressException, UnalignedAddressException {313checkJavaConfigured();314utils.checkAlignment(address, jintSize);315if (useFastAccessors) {316return cache.getInt(address, bigEndian);317} else {318byte[] data = readBytes(address, jintSize);319return utils.dataToJInt(data, jintSize);320}321}322323// NOTE: assumes value does not span pages (may be bad assumption on324// Solaris/x86; see unalignedAccessesOkay in DbxDebugger hierarchy)325public long readJLong(long address)326throws UnmappedAddressException, UnalignedAddressException {327checkJavaConfigured();328utils.checkAlignment(address, jlongSize);329if (useFastAccessors) {330return cache.getLong(address, bigEndian);331} else {332byte[] data = readBytes(address, jlongSize);333return utils.dataToJLong(data, jlongSize);334}335}336337// NOTE: assumes value does not span pages (may be bad assumption on338// Solaris/x86; see unalignedAccessesOkay in DbxDebugger hierarchy)339public short readJShort(long address)340throws UnmappedAddressException, UnalignedAddressException {341checkJavaConfigured();342utils.checkAlignment(address, jshortSize);343if (useFastAccessors) {344return cache.getShort(address, bigEndian);345} else {346byte[] data = readBytes(address, jshortSize);347return utils.dataToJShort(data, jshortSize);348}349}350351// NOTE: assumes value does not span pages (may be bad assumption on352// Solaris/x86; see unalignedAccessesOkay in DbxDebugger hierarchy)353public long readCInteger(long address, long numBytes, boolean isUnsigned)354throws UnmappedAddressException, UnalignedAddressException {355checkConfigured();356utils.checkAlignment(address, numBytes);357if (useFastAccessors) {358if (isUnsigned) {359switch((int) numBytes) {360case 1: return cache.getByte(address) & 0xFF;361case 2: return cache.getShort(address, bigEndian) & 0xFFFF;362case 4: return cache.getInt(address, bigEndian) & 0xFFFFFFFFL;363case 8: return cache.getLong(address, bigEndian);364default: {365byte[] data = readBytes(address, numBytes);366return utils.dataToCInteger(data, isUnsigned);367}368}369} else {370switch((int) numBytes) {371case 1: return cache.getByte(address);372case 2: return cache.getShort(address, bigEndian);373case 4: return cache.getInt(address, bigEndian);374case 8: return cache.getLong(address, bigEndian);375default: {376byte[] data = readBytes(address, numBytes);377return utils.dataToCInteger(data, isUnsigned);378}379}380}381} else {382byte[] data = readBytes(address, numBytes);383return utils.dataToCInteger(data, isUnsigned);384}385}386387public void writeJBoolean(long address, boolean value)388throws UnmappedAddressException, UnalignedAddressException {389checkJavaConfigured();390utils.checkAlignment(address, jbooleanSize);391byte[] data = utils.jbooleanToData(value);392writeBytes(address, jbooleanSize, data);393}394395public void writeJByte(long address, byte value)396throws UnmappedAddressException, UnalignedAddressException {397checkJavaConfigured();398utils.checkAlignment(address, jbyteSize);399byte[] data = utils.jbyteToData(value);400writeBytes(address, jbyteSize, data);401}402403public void writeJChar(long address, char value)404throws UnmappedAddressException, UnalignedAddressException {405checkJavaConfigured();406utils.checkAlignment(address, jcharSize);407byte[] data = utils.jcharToData(value);408writeBytes(address, jcharSize, data);409}410411public void writeJDouble(long address, double value)412throws UnmappedAddressException, UnalignedAddressException {413checkJavaConfigured();414utils.checkAlignment(address, jdoubleSize);415byte[] data = utils.jdoubleToData(value);416writeBytes(address, jdoubleSize, data);417}418419public void writeJFloat(long address, float value)420throws UnmappedAddressException, UnalignedAddressException {421checkJavaConfigured();422utils.checkAlignment(address, jfloatSize);423byte[] data = utils.jfloatToData(value);424writeBytes(address, jfloatSize, data);425}426427public void writeJInt(long address, int value)428throws UnmappedAddressException, UnalignedAddressException {429checkJavaConfigured();430utils.checkAlignment(address, jintSize);431byte[] data = utils.jintToData(value);432writeBytes(address, jintSize, data);433}434435public void writeJLong(long address, long value)436throws UnmappedAddressException, UnalignedAddressException {437checkJavaConfigured();438utils.checkAlignment(address, jlongSize);439byte[] data = utils.jlongToData(value);440writeBytes(address, jlongSize, data);441}442443public void writeJShort(long address, short value)444throws UnmappedAddressException, UnalignedAddressException {445checkJavaConfigured();446utils.checkAlignment(address, jshortSize);447byte[] data = utils.jshortToData(value);448writeBytes(address, jshortSize, data);449}450451public void writeCInteger(long address, long numBytes, long value)452throws UnmappedAddressException, UnalignedAddressException {453checkConfigured();454utils.checkAlignment(address, numBytes);455byte[] data = utils.cIntegerToData(numBytes, value);456writeBytes(address, numBytes, data);457}458459protected long readAddressValue(long address)460throws UnmappedAddressException, UnalignedAddressException {461return readCInteger(address, machDesc.getAddressSize(), true);462}463464protected long readCompOopAddressValue(long address)465throws UnmappedAddressException, UnalignedAddressException {466long value = readCInteger(address, getHeapOopSize(), true);467if (value != 0) {468// See oop.inline.hpp decode_heap_oop469value = (long)(narrowOopBase + (long)(value << narrowOopShift));470}471return value;472}473474protected long readCompKlassAddressValue(long address)475throws UnmappedAddressException, UnalignedAddressException {476long value = readCInteger(address, getKlassPtrSize(), true);477if (value != 0) {478value = (long)(narrowKlassBase + (long)(value << narrowKlassShift));479}480return value;481}482483protected void writeAddressValue(long address, long value)484throws UnmappedAddressException, UnalignedAddressException {485writeCInteger(address, machDesc.getAddressSize(), value);486}487488/** Can be called by subclasses but can not be overridden */489protected final void checkConfigured() {490if (machDesc == null) {491throw new RuntimeException("MachineDescription must have been set by this point");492}493if (utils == null) {494throw new RuntimeException("DebuggerUtilities must have been set by this point");495}496}497498/** Can be called by subclasses but can not be overridden */499protected final void checkJavaConfigured() {500checkConfigured();501502if (!javaPrimitiveTypesConfigured) {503throw new RuntimeException("Java primitive type sizes have not yet been configured");504}505}506507/** Possibly override page cache size with user-specified property */508protected int parseCacheNumPagesProperty(int defaultNum) {509String cacheNumPagesString = System.getProperty("cacheNumPages");510if (cacheNumPagesString != null) {511try {512return Integer.parseInt(cacheNumPagesString);513} catch (Exception e) {514System.err.println("Error parsing cacheNumPages property:");515e.printStackTrace();516}517}518return defaultNum;519}520521/** Interim solution for allowing subclasses to write bytes to522process until we make that functionality available in the basic523Address interface */524protected void invalidatePageCache(long startAddress, long numBytes) {525cache.clear(startAddress, numBytes);526}527528@Override529public String findSymbol(String symbol) {530Address addr = lookup(null, symbol);531if (addr == null && getOS().equals("win32")) {532// On win32 symbols are prefixed with the dll name. Do the user533// a favor and see if this is a symbol in jvm.dll or java.dll.534addr = lookup(null, "jvm!" + symbol);535if (addr == null) {536addr = lookup(null, "java!" + symbol);537}538}539if (addr == null) {540return null;541}542var builder = new StringBuilder(addr.toString());543var cdbg = getCDebugger();544var loadObject = cdbg.loadObjectContainingPC(addr);545// Print the shared library path and the offset of the symbol546if (loadObject != null) {547builder.append(": ").append(loadObject.getName());548long diff = addr.minus(loadObject.getBase());549if (diff != 0L) {550builder.append(" + 0x").append(Long.toHexString(diff));551}552}553return builder.toString();554}555556public long getJBooleanSize() {557return jbooleanSize;558}559560public long getJByteSize() {561return jbyteSize;562}563564public long getJCharSize() {565return jcharSize;566}567568public long getJDoubleSize() {569return jdoubleSize;570}571572public long getJFloatSize() {573return jfloatSize;574}575576public long getJIntSize() {577return jintSize;578}579580public long getJLongSize() {581return jlongSize;582}583584public long getJShortSize() {585return jshortSize;586}587588public long getHeapOopSize() {589return heapOopSize;590}591592public long getNarrowOopBase() {593return narrowOopBase;594}595public int getNarrowOopShift() {596return narrowOopShift;597}598599public long getKlassPtrSize() {600return klassPtrSize;601}602603public long getNarrowKlassBase() {604return narrowKlassBase;605}606public int getNarrowKlassShift() {607return narrowKlassShift;608}609}610611612