0N/A/*
1960N/A * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
1472N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1472N/A * or visit www.oracle.com if you need additional information or have any
1472N/A * questions.
0N/A *
0N/A */
0N/A
0N/Apackage sun.jvm.hotspot.debugger.windbg;
0N/A
0N/Aimport java.io.*;
0N/Aimport java.net.*;
0N/Aimport java.util.*;
0N/Aimport sun.jvm.hotspot.debugger.*;
0N/Aimport sun.jvm.hotspot.debugger.amd64.*;
0N/Aimport sun.jvm.hotspot.debugger.x86.*;
0N/Aimport sun.jvm.hotspot.debugger.ia64.*;
0N/Aimport sun.jvm.hotspot.debugger.windbg.amd64.*;
0N/Aimport sun.jvm.hotspot.debugger.windbg.x86.*;
0N/Aimport sun.jvm.hotspot.debugger.windbg.ia64.*;
0N/Aimport sun.jvm.hotspot.debugger.win32.coff.*;
0N/Aimport sun.jvm.hotspot.debugger.cdbg.*;
0N/Aimport sun.jvm.hotspot.debugger.cdbg.basic.BasicDebugEvent;
0N/Aimport sun.jvm.hotspot.utilities.*;
0N/Aimport sun.jvm.hotspot.utilities.memo.*;
113N/Aimport sun.jvm.hotspot.runtime.*;
0N/A
0N/A/** <P> An implementation of the JVMDebugger interface which talks to
0N/A windbg and symbol table management is done in Java. </P>
0N/A
0N/A <P> <B>NOTE</B> that since we have the notion of fetching "Java
0N/A primitive types" from the remote process (which might have
0N/A different sizes than we expect) we have a bootstrapping
0N/A problem. We need to know the sizes of these types before we can
0N/A fetch them. The current implementation solves this problem by
0N/A requiring that it be configured with these type sizes before they
0N/A can be fetched. The readJ(Type) routines here will throw a
0N/A RuntimeException if they are called before the debugger is
0N/A configured with the Java primitive type sizes. </P> */
0N/A
0N/Apublic class WindbgDebuggerLocal extends DebuggerBase implements WindbgDebugger {
0N/A private PageCache cache;
0N/A private boolean attached;
0N/A private boolean isCore;
0N/A
0N/A // Symbol lookup support
0N/A // This is a map of library names to DLLs
0N/A private Map nameToDllMap;
0N/A
0N/A // C/C++ debugging support
0N/A private List/*<LoadObject>*/ loadObjects;
0N/A private CDebugger cdbg;
0N/A
0N/A // thread access
0N/A private Map threadIntegerRegisterSet;
0N/A private List threadList;
0N/A
0N/A // windbg native interface pointers
0N/A
0N/A private long ptrIDebugClient;
0N/A private long ptrIDebugControl;
0N/A private long ptrIDebugDataSpaces;
0N/A private long ptrIDebugOutputCallbacks;
0N/A private long ptrIDebugAdvanced;
0N/A private long ptrIDebugSymbols;
0N/A private long ptrIDebugSystemObjects;
0N/A
0N/A private WindbgThreadFactory threadFactory;
0N/A
0N/A //--------------------------------------------------------------------------------
0N/A // Implementation of Debugger interface
0N/A //
0N/A
0N/A /** <P> machDesc may not be null. </P>
0N/A
0N/A <P> useCache should be set to true if debugging is being done
0N/A locally, and to false if the debugger is being created for the
0N/A purpose of supporting remote debugging. </P> */
0N/A public WindbgDebuggerLocal(MachineDescription machDesc,
0N/A boolean useCache) throws DebuggerException {
0N/A this.machDesc = machDesc;
0N/A utils = new DebuggerUtilities(machDesc.getAddressSize(), machDesc.isBigEndian()) {
0N/A public void checkAlignment(long address, long alignment) {
0N/A // Need to override default checkAlignment because we need to
0N/A // relax alignment constraints on Windows/x86
0N/A if ( (address % alignment != 0)
0N/A &&(alignment != 8 || address % 4 != 0)) {
0N/A throw new UnalignedAddressException(
0N/A "Trying to read at address: "
0N/A + addressValueToString(address)
0N/A + " with alignment: " + alignment,
0N/A address);
0N/A }
0N/A }
0N/A };
0N/A
0N/A String cpu = PlatformInfo.getCPU();
0N/A if (cpu.equals("x86")) {
0N/A threadFactory = new WindbgX86ThreadFactory(this);
0N/A } else if (cpu.equals("amd64")) {
0N/A threadFactory = new WindbgAMD64ThreadFactory(this);
0N/A } else if (cpu.equals("ia64")) {
0N/A threadFactory = new WindbgIA64ThreadFactory(this);
0N/A }
0N/A
0N/A if (useCache) {
0N/A // Cache portion of the remote process's address space.
0N/A // Fetching data over the socket connection to dbx is slow.
0N/A // Might be faster if we were using a binary protocol to talk to
0N/A // dbx, but would have to test. For now, this cache works best
0N/A // if it covers the entire heap of the remote process. FIXME: at
0N/A // least should make this tunable from the outside, i.e., via
0N/A // the UI. This is a cache of 4096 4K pages, or 16 MB. The page
0N/A // size must be adjusted to be the hardware's page size.
0N/A // (FIXME: should pick this up from the debugger.)
0N/A initCache(4096, 4096);
0N/A }
0N/A // FIXME: add instantiation of thread factory
0N/A
0N/A }
0N/A
0N/A /** From the Debugger interface via JVMDebugger */
0N/A public boolean hasProcessList() throws DebuggerException {
0N/A return false;
0N/A }
0N/A
0N/A /** From the Debugger interface via JVMDebugger */
0N/A public List getProcessList() throws DebuggerException {
0N/A return null;
0N/A }
0N/A
0N/A
0N/A /** From the Debugger interface via JVMDebugger */
0N/A public synchronized void attach(int processID) throws DebuggerException {
0N/A attachInit();
0N/A attach0(processID);
0N/A attached = true;
0N/A isCore = false;
0N/A }
0N/A
0N/A /** From the Debugger interface via JVMDebugger */
0N/A public synchronized void attach(String executableName, String coreFileName) throws DebuggerException {
0N/A attachInit();
0N/A attach0(executableName, coreFileName);
0N/A attached = true;
0N/A isCore = true;
0N/A }
0N/A
0N/A public List getLoadObjectList() {
0N/A requireAttach();
0N/A return loadObjects;
0N/A }
0N/A
0N/A /** From the Debugger interface via JVMDebugger */
0N/A public synchronized boolean detach() {
0N/A if ( ! attached)
0N/A return false;
0N/A
0N/A // Close all open DLLs
0N/A if (nameToDllMap != null) {
0N/A for (Iterator iter = nameToDllMap.values().iterator(); iter.hasNext(); ) {
0N/A DLL dll = (DLL) iter.next();
0N/A dll.close();
0N/A }
0N/A nameToDllMap = null;
0N/A loadObjects = null;
0N/A }
0N/A
0N/A cdbg = null;
0N/A clearCache();
0N/A
0N/A threadIntegerRegisterSet = null;
0N/A threadList = null;
0N/A try {
0N/A detach0();
0N/A } finally {
0N/A attached = false;
0N/A resetNativePointers();
0N/A }
0N/A return true;
0N/A }
0N/A
0N/A
0N/A /** From the Debugger interface via JVMDebugger */
0N/A public Address parseAddress(String addressString) throws NumberFormatException {
0N/A return newAddress(utils.scanAddress(addressString));
0N/A }
0N/A
0N/A /** From the Debugger interface via JVMDebugger */
0N/A public String getOS() {
0N/A return PlatformInfo.getOS();
0N/A }
0N/A
0N/A /** From the Debugger interface via JVMDebugger */
0N/A public String getCPU() {
0N/A return PlatformInfo.getCPU();
0N/A }
0N/A
0N/A public boolean hasConsole() throws DebuggerException {
0N/A return true;
0N/A }
0N/A
0N/A public synchronized String consoleExecuteCommand(String cmd) throws DebuggerException {
0N/A requireAttach();
0N/A if (! attached) {
0N/A throw new DebuggerException("debugger not yet attached to a Dr. Watson dump!");
0N/A }
0N/A
0N/A return consoleExecuteCommand0(cmd);
0N/A }
0N/A
0N/A public String getConsolePrompt() throws DebuggerException {
0N/A return "(windbg)";
0N/A }
0N/A
0N/A public CDebugger getCDebugger() throws DebuggerException {
0N/A if (cdbg == null) {
0N/A // FIXME: CDebugger is not yet supported for IA64 because
0N/A // of native stack walking issues.
0N/A if (! getCPU().equals("ia64")) {
0N/A cdbg = new WindbgCDebugger(this);
0N/A }
0N/A }
0N/A return cdbg;
0N/A }
0N/A
0N/A /** From the SymbolLookup interface via Debugger and JVMDebugger */
0N/A public synchronized Address lookup(String objectName, String symbol) {
0N/A requireAttach();
0N/A return newAddress(lookupByName(objectName, symbol));
0N/A }
0N/A
0N/A /** From the SymbolLookup interface via Debugger and JVMDebugger */
0N/A public synchronized OopHandle lookupOop(String objectName, String symbol) {
0N/A Address addr = lookup(objectName, symbol);
0N/A if (addr == null) {
0N/A return null;
0N/A }
0N/A return addr.addOffsetToAsOopHandle(0);
0N/A }
0N/A
0N/A public synchronized ClosestSymbol lookup(long address) {
0N/A return lookupByAddress0(address);
0N/A }
0N/A
0N/A /** From the Debugger interface */
0N/A public MachineDescription getMachineDescription() {
0N/A return machDesc;
0N/A }
0N/A
0N/A //--------------------------------------------------------------------------------
0N/A // Implementation of ThreadAccess interface
0N/A //
0N/A
0N/A
0N/A /** From the ThreadAccess interface via Debugger and JVMDebugger */
0N/A public ThreadProxy getThreadForIdentifierAddress(Address addr) {
0N/A return threadFactory.createThreadWrapper(addr);
0N/A }
0N/A
0N/A public ThreadProxy getThreadForThreadId(long handle) {
0N/A // with windbg we can't make out using handle
0N/A throw new DebuggerException("Unimplemented!");
0N/A }
0N/A
0N/A public long getThreadIdFromSysId(long sysId) throws DebuggerException {
0N/A requireAttach();
0N/A return getThreadIdFromSysId0(sysId);
0N/A }
0N/A
0N/A //----------------------------------------------------------------------
0N/A // Overridden from DebuggerBase because we need to relax alignment
0N/A // constraints on x86
0N/A
0N/A public long readJLong(long address)
0N/A throws UnmappedAddressException, UnalignedAddressException {
0N/A checkJavaConfigured();
0N/A // FIXME: allow this to be configurable. Undesirable to add a
0N/A // dependency on the runtime package here, though, since this
0N/A // package should be strictly underneath it.
0N/A // utils.checkAlignment(address, jlongSize);
0N/A utils.checkAlignment(address, jintSize);
0N/A byte[] data = readBytes(address, jlongSize);
0N/A return utils.dataToJLong(data, jlongSize);
0N/A }
0N/A
0N/A //--------------------------------------------------------------------------------
0N/A // Internal routines (for implementation of WindbgAddress).
0N/A // These must not be called until the MachineDescription has been set up.
0N/A //
0N/A
0N/A /** From the WindbgDebugger interface */
0N/A public String addressValueToString(long address) {
0N/A return utils.addressValueToString(address);
0N/A }
0N/A
0N/A /** From the WindbgDebugger interface */
0N/A public WindbgAddress readAddress(long address)
0N/A throws UnmappedAddressException, UnalignedAddressException {
0N/A return (WindbgAddress) newAddress(readAddressValue(address));
0N/A }
0N/A
113N/A public WindbgAddress readCompOopAddress(long address)
113N/A throws UnmappedAddressException, UnalignedAddressException {
113N/A return (WindbgAddress) newAddress(readCompOopAddressValue(address));
113N/A }
113N/A
0N/A /** From the WindbgDebugger interface */
0N/A public WindbgOopHandle readOopHandle(long address)
0N/A throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
0N/A long value = readAddressValue(address);
0N/A return (value == 0 ? null : new WindbgOopHandle(this, value));
0N/A }
113N/A public WindbgOopHandle readCompOopHandle(long address)
113N/A throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
113N/A long value = readCompOopAddressValue(address);
113N/A return (value == 0 ? null : new WindbgOopHandle(this, value));
113N/A }
0N/A
0N/A /** From the WindbgDebugger interface */
0N/A public int getAddressSize() {
0N/A return (int) machDesc.getAddressSize();
0N/A }
0N/A
0N/A //--------------------------------------------------------------------------------
0N/A // Thread context access
0N/A //
0N/A
0N/A private synchronized void setThreadIntegerRegisterSet(long threadId,
0N/A long[] regs) {
0N/A threadIntegerRegisterSet.put(new Long(threadId), regs);
0N/A }
0N/A
0N/A private synchronized void addThread(long sysId) {
0N/A threadList.add(threadFactory.createThreadWrapper(sysId));
0N/A }
0N/A
0N/A public synchronized long[] getThreadIntegerRegisterSet(long threadId)
0N/A throws DebuggerException {
0N/A requireAttach();
0N/A return (long[]) threadIntegerRegisterSet.get(new Long(threadId));
0N/A }
0N/A
0N/A public synchronized List getThreadList() throws DebuggerException {
0N/A requireAttach();
0N/A return threadList;
0N/A }
0N/A
0N/A private String findFullPath(String file) {
0N/A File f = new File(file);
0N/A if (f.exists()) {
0N/A return file;
0N/A } else {
0N/A // remove path part, if any.
0N/A file = f.getName();
0N/A StringTokenizer st = new StringTokenizer(imagePath, File.pathSeparator);
0N/A while (st.hasMoreTokens()) {
0N/A f = new File(st.nextToken(), file);
0N/A if (f.exists()) {
0N/A return f.getPath();
0N/A }
0N/A }
0N/A }
0N/A return null;
0N/A }
0N/A
0N/A private synchronized void addLoadObject(String file, long size, long base) {
0N/A String path = findFullPath(file);
0N/A if (path != null) {
0N/A DLL dll = null;
0N/A if (useNativeLookup) {
0N/A dll = new DLL(this, path, size,newAddress(base)) {
0N/A public ClosestSymbol closestSymbolToPC(Address pcAsAddr) {
0N/A long pc = getAddressValue(pcAsAddr);
0N/A ClosestSymbol sym = lookupByAddress0(pc);
0N/A if (sym == null) {
0N/A return super.closestSymbolToPC(pcAsAddr);
0N/A } else {
0N/A return sym;
0N/A }
0N/A }
0N/A };
0N/A } else {
0N/A dll = new DLL(this, path, size, newAddress(base));
0N/A }
0N/A loadObjects.add(dll);
0N/A nameToDllMap.put(new File(file).getName(), dll);
0N/A }
0N/A }
0N/A
0N/A //--------------------------------------------------------------------------------
0N/A // Address access
0N/A //
0N/A
0N/A /** From the Debugger interface */
0N/A public long getAddressValue(Address addr) {
0N/A if (addr == null) return 0;
0N/A return ((WindbgAddress) addr).getValue();
0N/A }
0N/A
0N/A /** From the WindbgDebugger interface */
0N/A public Address newAddress(long value) {
0N/A if (value == 0) return null;
0N/A return new WindbgAddress(this, value);
0N/A }
0N/A
0N/A //--------------------------------------------------------------------------------
0N/A // Internals only below this point
0N/A //
0N/A
0N/A // attach/detach helpers
0N/A private void checkAttached() {
0N/A if (attached) {
0N/A String msg = (isCore)? "already attached to a Dr. Watson dump!" :
0N/A "already attached to a process!";
0N/A throw new DebuggerException(msg);
0N/A }
0N/A }
0N/A
0N/A private void requireAttach() {
0N/A if (!attached) {
0N/A throw new RuntimeException("not attached to a process or Dr Watson dump");
0N/A }
0N/A }
0N/A
0N/A private void attachInit() {
0N/A checkAttached();
0N/A loadObjects = new ArrayList();
0N/A nameToDllMap = new HashMap();
0N/A threadIntegerRegisterSet = new HashMap();
0N/A threadList = new ArrayList();
0N/A }
0N/A
0N/A private void resetNativePointers() {
0N/A ptrIDebugClient = 0L;
0N/A ptrIDebugControl = 0L;
0N/A ptrIDebugDataSpaces = 0L;
0N/A ptrIDebugOutputCallbacks = 0L;
0N/A ptrIDebugAdvanced = 0L;
0N/A ptrIDebugSymbols = 0L;
0N/A ptrIDebugSystemObjects = 0L;
0N/A }
0N/A
0N/A synchronized long lookupByName(String objectName, String symbol) {
0N/A long res = 0L;
0N/A if (useNativeLookup) {
0N/A res = lookupByName0(objectName, symbol);
0N/A if (res != 0L) {
0N/A return res;
0N/A } // else fallthru...
0N/A }
0N/A
0N/A DLL dll = (DLL) nameToDllMap.get(objectName);
0N/A // The DLL can be null because we use this to search through known
0N/A // DLLs in HotSpotTypeDataBase (for example)
0N/A if (dll != null) {
0N/A WindbgAddress addr = (WindbgAddress) dll.lookupSymbol(symbol);
0N/A if (addr != null) {
0N/A return addr.getValue();
0N/A }
0N/A }
0N/A return 0L;
0N/A }
0N/A
0N/A /** This reads bytes from the remote process. */
0N/A public synchronized ReadResult readBytesFromProcess(long address, long numBytes)
0N/A throws UnmappedAddressException, DebuggerException {
0N/A requireAttach();
0N/A byte[] res = readBytesFromProcess0(address, numBytes);
0N/A if(res != null)
0N/A return new ReadResult(res);
0N/A else
0N/A return new ReadResult(address);
0N/A }
0N/A
0N/A
0N/A private DLL findDLLByName(String fullPathName) {
0N/A for (Iterator iter = loadObjects.iterator(); iter.hasNext(); ) {
0N/A DLL dll = (DLL) iter.next();
0N/A if (dll.getName().equals(fullPathName)) {
0N/A return dll;
0N/A }
0N/A }
0N/A return null;
0N/A }
0N/A
0N/A public void writeBytesToProcess(long address, long numBytes, byte[] data)
0N/A throws UnmappedAddressException, DebuggerException {
0N/A // FIXME
0N/A throw new DebuggerException("Unimplemented");
0N/A }
0N/A
0N/A private static String imagePath;
0N/A private static String symbolPath;
0N/A private static boolean useNativeLookup;
0N/A
0N/A static {
0N/A
0N/A /*
1960N/A * sawindbg.dll depends on dbgeng.dll which itself depends on
1960N/A * dbghelp.dll. We have to make sure that the dbgeng.dll and
1960N/A * dbghelp.dll that we load are compatible with each other. We
1960N/A * load both of those libraries from the same directory based
1960N/A * on the theory that co-located libraries are compatible.
1960N/A *
1960N/A * On Windows 2000 and earlier, dbgeng.dll and dbghelp.dll were
1960N/A * not included as part of the standard system directory. On
1960N/A * systems newer than Windows 2000, dbgeng.dll and dbghelp.dll
1960N/A * are included in the standard system directory. However, the
1960N/A * versions included in the standard system directory may not
1960N/A * be able to handle symbol information for the newer compilers.
1960N/A *
1960N/A * We search for and explicitly load the libraries using the
1960N/A * following directory search order:
0N/A *
1960N/A * - java.home/bin (same as $JAVA_HOME/jre/bin)
1960N/A * - dir named by DEBUGGINGTOOLSFORWINDOWS environment variable
1960N/A * - various "Debugging Tools For Windows" program directories
1960N/A * - the system directory ($SYSROOT/system32)
1960N/A *
1960N/A * If SA is invoked with -Dsun.jvm.hotspot.loadLibrary.DEBUG=1,
1960N/A * then debug messages about library loading are printed to
1960N/A * System.err.
0N/A */
0N/A
1960N/A String dbgengPath = null;
1960N/A String dbghelpPath = null;
1960N/A String sawindbgPath = null;
1960N/A List searchList = new ArrayList();
1960N/A
1960N/A boolean loadLibraryDEBUG =
1960N/A System.getProperty("sun.jvm.hotspot.loadLibrary.DEBUG") != null;
0N/A
0N/A {
1960N/A // First place to search is co-located with sawindbg.dll in
1960N/A // $JAVA_HOME/jre/bin (java.home property is set to $JAVA_HOME/jre):
1960N/A searchList.add(System.getProperty("java.home") + File.separator + "bin");
1960N/A sawindbgPath = (String) searchList.get(0) + File.separator +
1960N/A "sawindbg.dll";
1960N/A
1960N/A // second place to search is specified by an environment variable:
1960N/A String DTFWHome = System.getenv("DEBUGGINGTOOLSFORWINDOWS");
1960N/A if (DTFWHome != null) {
1960N/A searchList.add(DTFWHome);
0N/A }
0N/A
1960N/A // The third place to search is the install directory for the
1960N/A // "Debugging Tools For Windows" package; so far there are three
1960N/A // name variations that we know of:
1960N/A String sysRoot = System.getenv("SYSTEMROOT");
1960N/A DTFWHome = sysRoot + File.separator + ".." + File.separator +
1960N/A "Program Files" + File.separator + "Debugging Tools For Windows";
1960N/A searchList.add(DTFWHome);
1960N/A searchList.add(DTFWHome + " (x86)");
1960N/A searchList.add(DTFWHome + " (x64)");
1960N/A
1960N/A // The last place to search is the system directory:
1960N/A searchList.add(sysRoot + File.separator + "system32");
0N/A }
0N/A
1960N/A for (int i = 0; i < searchList.size(); i++) {
1960N/A File dir = new File((String) searchList.get(i));
1960N/A if (!dir.exists()) {
1960N/A if (loadLibraryDEBUG) {
1960N/A System.err.println("DEBUG: '" + searchList.get(i) +
1960N/A "': directory does not exist.");
1960N/A }
1960N/A // this search directory doesn't exist so skip it
1960N/A continue;
1960N/A }
1960N/A
1960N/A dbgengPath = (String) searchList.get(i) + File.separator + "dbgeng.dll";
1960N/A dbghelpPath = (String) searchList.get(i) + File.separator + "dbghelp.dll";
1960N/A
1960N/A File feng = new File(dbgengPath);
1960N/A File fhelp = new File(dbghelpPath);
1960N/A if (feng.exists() && fhelp.exists()) {
1960N/A // both files exist so we have a match
1960N/A break;
1960N/A }
1960N/A
1960N/A // At least one of the files does not exist; no warning if both
1960N/A // don't exist. If just one doesn't exist then we don't check
1960N/A // loadLibraryDEBUG because we have a mis-configured system.
1960N/A if (feng.exists()) {
1960N/A System.err.println("WARNING: found '" + dbgengPath +
1960N/A "' but did not find '" + dbghelpPath + "'; ignoring '" +
1960N/A dbgengPath + "'.");
1960N/A } else if (fhelp.exists()) {
1960N/A System.err.println("WARNING: found '" + dbghelpPath +
1960N/A "' but did not find '" + dbgengPath + "'; ignoring '" +
1960N/A dbghelpPath + "'.");
1960N/A } else if (loadLibraryDEBUG) {
1960N/A System.err.println("DEBUG: searched '" + searchList.get(i) +
1960N/A "': dbgeng.dll and dbghelp.dll were not found.");
1960N/A }
1960N/A dbgengPath = null;
1960N/A dbghelpPath = null;
1960N/A }
1960N/A
1960N/A if (dbgengPath == null || dbghelpPath == null) {
1960N/A // at least one of the files wasn't found anywhere we searched
1960N/A String mesg = null;
1960N/A
1960N/A if (dbgengPath == null && dbghelpPath == null) {
1960N/A mesg = "dbgeng.dll and dbghelp.dll cannot be found. ";
1960N/A } else if (dbgengPath == null) {
1960N/A mesg = "dbgeng.dll cannot be found (dbghelp.dll was found). ";
1960N/A } else {
1960N/A mesg = "dbghelp.dll cannot be found (dbgeng.dll was found). ";
1960N/A }
1960N/A throw new UnsatisfiedLinkError(mesg +
1960N/A "Please search microsoft.com for 'Debugging Tools For Windows', " +
1960N/A "and either download it to the default location, or download it " +
1960N/A "to a custom location and set environment variable " +
1960N/A "'DEBUGGINGTOOLSFORWINDOWS' to the pathname of that location.");
1960N/A }
1960N/A
1960N/A // NOTE: The order of loads is important! If we load dbgeng.dll
1960N/A // first, then the dependency - dbghelp.dll - will be loaded
1960N/A // from usual DLL search thereby defeating the purpose!
1960N/A if (loadLibraryDEBUG) {
1960N/A System.err.println("DEBUG: loading '" + dbghelpPath + "'.");
1960N/A }
1960N/A System.load(dbghelpPath);
1960N/A if (loadLibraryDEBUG) {
1960N/A System.err.println("DEBUG: loading '" + dbgengPath + "'.");
1960N/A }
1960N/A System.load(dbgengPath);
1960N/A
0N/A // Now, load sawindbg.dll
1960N/A if (loadLibraryDEBUG) {
1960N/A System.err.println("DEBUG: loading '" + sawindbgPath + "'.");
1960N/A }
1960N/A System.load(sawindbgPath);
1960N/A
0N/A // where do I find '.exe', '.dll' files?
0N/A imagePath = System.getProperty("sun.jvm.hotspot.debugger.windbg.imagePath");
0N/A if (imagePath == null) {
0N/A imagePath = System.getenv("PATH");
0N/A }
0N/A
0N/A // where do I find '.pdb', '.dbg' files?
0N/A symbolPath = System.getProperty("sun.jvm.hotspot.debugger.windbg.symbolPath");
0N/A
0N/A // mostly, debug files would be find where .dll's, .exe's are found.
0N/A if (symbolPath == null) {
0N/A symbolPath = imagePath;
0N/A }
0N/A
0N/A // should we parse DLL symbol table in Java code or use
0N/A // Windbg's native lookup facility? By default, we use
0N/A // native lookup so that we can take advantage of '.pdb'
0N/A // files, if available.
0N/A useNativeLookup = true;
0N/A String str = System.getProperty("sun.jvm.hotspot.debugger.windbg.disableNativeLookup");
0N/A if (str != null) {
0N/A useNativeLookup = false;
0N/A }
0N/A
0N/A initIDs();
0N/A }
0N/A
0N/A // native methods
0N/A private static native void initIDs();
0N/A private native void attach0(String executableName, String coreFileName);
0N/A private native void attach0(int processID);
0N/A private native void detach0();
0N/A private native byte[] readBytesFromProcess0(long address, long numBytes)
0N/A throws UnmappedAddressException, DebuggerException;
0N/A private native long getThreadIdFromSysId0(long sysId);
0N/A private native String consoleExecuteCommand0(String cmd);
0N/A private native long lookupByName0(String objName, String symName);
0N/A private native ClosestSymbol lookupByAddress0(long address);
0N/A
0N/A // helper called lookupByAddress0
0N/A private ClosestSymbol createClosestSymbol(String symbol, long diff) {
0N/A return new ClosestSymbol(symbol, diff);
0N/A }
0N/A}