diff agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children ba764ed4b6f2
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,381 @@
+/*
+ * Copyright 2002-2004 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+package sun.jvm.hotspot.debugger.remote;
+
+import java.rmi.*;
+import java.util.*;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.cdbg.*;
+import sun.jvm.hotspot.debugger.remote.sparc.*;
+import sun.jvm.hotspot.debugger.remote.x86.*;
+import sun.jvm.hotspot.debugger.remote.amd64.*;
+
+/** An implementation of Debugger which wraps a
+    RemoteDebugger, providing remote debugging via RMI.
+    This implementation provides caching of the remote process's
+    address space on the local machine where the user interface is
+    running. */
+
+public class RemoteDebuggerClient extends DebuggerBase implements JVMDebugger {
+  private RemoteDebugger remoteDebugger;
+  private RemoteThreadFactory threadFactory;
+  private boolean unalignedAccessesOkay = false;
+  private static final int cacheSize = 16 * 1024 * 1024; // 16 MB
+
+  public RemoteDebuggerClient(RemoteDebugger remoteDebugger) throws DebuggerException {
+    super();
+    try {
+      this.remoteDebugger = remoteDebugger;
+      machDesc = remoteDebugger.getMachineDescription();
+      utils = new DebuggerUtilities(machDesc.getAddressSize(), machDesc.isBigEndian());
+      int cacheNumPages;
+      int cachePageSize;
+      String cpu = remoteDebugger.getCPU();
+      // page size. (FIXME: should pick this up from the remoteDebugger.)
+      if (cpu.equals("sparc")) {
+        threadFactory = new RemoteSPARCThreadFactory(this);
+        cachePageSize = 8192;
+        cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize);
+      } else if (cpu.equals("x86")) {
+        threadFactory = new RemoteX86ThreadFactory(this);
+        cachePageSize = 4096;
+        cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize);
+        unalignedAccessesOkay = true;
+      } else if (cpu.equals("amd64")) {
+        threadFactory = new RemoteAMD64ThreadFactory(this);
+        cachePageSize = 4096;
+        cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize);
+        unalignedAccessesOkay = true;
+      } else {
+        throw new DebuggerException("Thread access for CPU architecture " + cpu + " not yet supported");
+      }
+
+      // Cache portion of the remote process's address space.
+      initCache(cachePageSize, cacheNumPages);
+
+      jbooleanSize = remoteDebugger.getJBooleanSize();
+      jbyteSize    = remoteDebugger.getJByteSize();
+      jcharSize    = remoteDebugger.getJCharSize();
+      jdoubleSize  = remoteDebugger.getJDoubleSize();
+      jfloatSize   = remoteDebugger.getJFloatSize();
+      jintSize     = remoteDebugger.getJIntSize();
+      jlongSize    = remoteDebugger.getJLongSize();
+      jshortSize   = remoteDebugger.getJShortSize();
+      javaPrimitiveTypesConfigured = true;
+    }
+    catch (RemoteException e) {
+      throw new DebuggerException(e);
+    }
+  }
+
+  public long[] getThreadIntegerRegisterSet(Address addr) {
+    try {
+      return remoteDebugger.getThreadIntegerRegisterSet(getAddressValue(addr), true);
+    }
+    catch (RemoteException e) {
+      throw new DebuggerException(e);
+    }
+  }
+
+  public long[] getThreadIntegerRegisterSet(long id) {
+    try {
+      return remoteDebugger.getThreadIntegerRegisterSet(id, false);
+    }
+    catch (RemoteException e) {
+      throw new DebuggerException(e);
+    }
+  }
+
+  /** Unimplemented in this class (remote remoteDebugger should already be attached) */
+  public boolean hasProcessList() throws DebuggerException {
+    throw new DebuggerException("Should not be called on RemoteDebuggerClient");
+  }
+
+  /** Unimplemented in this class (remote remoteDebugger should already be attached) */
+  public List getProcessList() throws DebuggerException {
+    throw new DebuggerException("Should not be called on RemoteDebuggerClient");
+  }
+
+  /** Unimplemented in this class (remote remoteDebugger should already be attached) */
+  public void attach(int processID) throws DebuggerException {
+    throw new DebuggerException("Should not be called on RemoteDebuggerClient");
+  }
+
+  /** Unimplemented in this class (remote remoteDebugger should already be attached) */
+  public void attach(String executableName, String coreFileName) throws DebuggerException {
+    throw new DebuggerException("Should not be called on RemoteDebuggerClient");
+  }
+
+  /** Unimplemented in this class (remote remoteDebugger can not be detached) */
+  public boolean detach() {
+    throw new DebuggerException("Should not be called on RemoteDebuggerClient");
+  }
+
+  public Address parseAddress(String addressString) throws NumberFormatException {
+    long addr = utils.scanAddress(addressString);
+    if (addr == 0) {
+      return null;
+    }
+    return new RemoteAddress(this, addr);
+  }
+
+  public String getOS() throws DebuggerException {
+    try {
+      return remoteDebugger.getOS();
+    }
+    catch (RemoteException e) {
+      throw new DebuggerException(e);
+    }
+  }
+
+  public String getCPU() {
+    try {
+      return remoteDebugger.getCPU();
+    }
+    catch (RemoteException e) {
+      throw new DebuggerException(e);
+    }
+  }
+
+  public boolean hasConsole() throws DebuggerException {
+    try {
+       return remoteDebugger.hasConsole();
+    } catch (RemoteException e) {
+       throw new DebuggerException(e);
+    }
+  }
+
+  public String consoleExecuteCommand(String cmd) throws DebuggerException {
+    try {
+      return remoteDebugger.consoleExecuteCommand(cmd);
+    }
+    catch (RemoteException e) {
+      throw new DebuggerException(e);
+    }
+  }
+
+  public String getConsolePrompt() throws DebuggerException {
+    try {
+      return remoteDebugger.getConsolePrompt();
+    } catch (RemoteException e) {
+      throw new DebuggerException(e);
+    }
+  }
+
+  public CDebugger getCDebugger() throws DebuggerException {
+    return null;
+  }
+
+  //--------------------------------------------------------------------------------
+  // Implementation of SymbolLookup interface
+
+  public Address lookup(String objectName, String symbol) {
+    try {
+      long addr = remoteDebugger.lookupInProcess(objectName, symbol);
+      if (addr == 0) {
+        return null;
+      }
+      return new RemoteAddress(this, addr);
+    }
+    catch (RemoteException e) {
+      throw new DebuggerException(e);
+    }
+  }
+
+  public OopHandle lookupOop(String objectName, String symbol) {
+    try {
+      long addr = remoteDebugger.lookupInProcess(objectName, symbol);
+      if (addr == 0) {
+        return null;
+      }
+      return new RemoteOopHandle(this, addr);
+    }
+    catch (RemoteException e) {
+      throw new DebuggerException(e);
+    }
+  }
+
+  /** Need to override this to relax alignment checks on x86. */
+  public long readCInteger(long address, long numBytes, boolean isUnsigned)
+    throws UnmappedAddressException, UnalignedAddressException {
+    if (!unalignedAccessesOkay) {
+      utils.checkAlignment(address, numBytes);
+    } else {
+      // Only slightly relaxed semantics -- this is a hack, but is
+      // necessary on x86 where it seems the compiler is
+      // putting some global 64-bit data on 32-bit boundaries
+      if (numBytes == 8) {
+        utils.checkAlignment(address, 4);
+      } else {
+        utils.checkAlignment(address, numBytes);
+      }
+    }
+    byte[] data = readBytes(address, numBytes);
+    return utils.dataToCInteger(data, isUnsigned);
+  }
+
+  // Overridden from DebuggerBase because we need to relax alignment
+  // constraints on x86
+  public long readJLong(long address)
+    throws UnmappedAddressException, UnalignedAddressException {
+    // FIXME: allow this to be configurable. Undesirable to add a
+    // dependency on the runtime package here, though, since this
+    // package should be strictly underneath it.
+    if (unalignedAccessesOkay) {
+      utils.checkAlignment(address, jintSize);
+    } else {
+      utils.checkAlignment(address, jlongSize);
+    }
+    byte[] data = readBytes(address, jlongSize);
+    return utils.dataToJLong(data, jlongSize);
+  }
+
+
+  //--------------------------------------------------------------------------------
+  // Implementation of JVMDebugger interface
+  //
+
+  /** Unimplemented in this class (remote remoteDebugger should already be configured) */
+  public void configureJavaPrimitiveTypeSizes(long jbooleanSize,
+                                              long jbyteSize,
+                                              long jcharSize,
+                                              long jdoubleSize,
+                                              long jfloatSize,
+                                              long jintSize,
+                                              long jlongSize,
+                                              long jshortSize) {
+    throw new DebuggerException("Should not be called on RemoteDebuggerClient");
+  }
+
+  public void setMachineDescription(MachineDescription machDesc) {
+    throw new DebuggerException("Should not be called on RemoteDebuggerClient");
+  }
+
+  public int getRemoteProcessAddressSize() {
+    throw new DebuggerException("Should not be called on RemoteDebuggerClient");
+  }
+
+  public String addressValueToString(long addr) {
+    return utils.addressValueToString(addr);
+  }
+
+  public long getAddressValue(Address addr) throws DebuggerException {
+    if (addr == null) return 0;
+    return ((RemoteAddress) addr).getValue();
+  }
+
+  public Address newAddress(long value) {
+    if (value == 0) return null;
+    return new RemoteAddress(this, value);
+  }
+
+  RemoteAddress readAddress(long address)
+    throws UnmappedAddressException, UnalignedAddressException {
+    long value = readAddressValue(address);
+    return (value == 0 ? null : new RemoteAddress(this, value));
+  }
+
+  RemoteOopHandle readOopHandle(long address)
+    throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
+    long value = readAddressValue(address);
+    return (value == 0 ? null : new RemoteOopHandle(this, value));
+  }
+
+  boolean areThreadsEqual(Address addr1, Address addr2) {
+    try {
+       return remoteDebugger.areThreadsEqual(getAddressValue(addr1), true,
+                                             getAddressValue(addr2), true);
+    } catch (RemoteException e) {
+    }
+    return false;
+  }
+
+  boolean areThreadsEqual(long id1, long id2) {
+    try {
+       return remoteDebugger.areThreadsEqual(id1, false, id2, false);
+    } catch (RemoteException e) {
+    }
+    return false;
+  }
+
+  boolean areThreadsEqual(Address addr1, long id2) {
+    try {
+       return remoteDebugger.areThreadsEqual(getAddressValue(addr1), true, id2, false);
+    } catch (RemoteException e) {
+    }
+    return false;
+  }
+
+  boolean areThreadsEqual(long id1, Address addr2) {
+    try {
+       return remoteDebugger.areThreadsEqual(id1, false, getAddressValue(addr2), true);
+    } catch (RemoteException e) {
+    }
+    return false;
+  }
+
+  int getThreadHashCode(Address a) {
+    try {
+       return remoteDebugger.getThreadHashCode(getAddressValue(a), true);
+    } catch (RemoteException e) {
+    }
+    return a.hashCode();
+  }
+
+  int getThreadHashCode(long id) {
+    try {
+       return remoteDebugger.getThreadHashCode(id, false);
+    } catch (RemoteException e) {
+    }
+    return (int) id;
+  }
+
+  public ThreadProxy getThreadForIdentifierAddress(Address addr) {
+     return threadFactory.createThreadWrapper(addr);
+  }
+
+  public ThreadProxy getThreadForThreadId(long id) {
+     return threadFactory.createThreadWrapper(id);
+  }
+
+  public MachineDescription getMachineDescription() throws DebuggerException {
+     return machDesc;
+  }
+
+  /** This reads bytes from the remote process. */
+  public ReadResult readBytesFromProcess(long address, long numBytes) {
+    try {
+      return remoteDebugger.readBytesFromProcess(address, numBytes);
+    }
+    catch (RemoteException e) {
+      throw new DebuggerException(e);
+    }
+  }
+
+  public void writeBytesToProcess(long a, long b, byte[] c) {
+     throw new DebuggerException("Unimplemented!");
+  }
+}