/*
 * Copyright (c) 2002, 2013, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

package sun.jvm.hotspot.debugger.windbg;

import java.io.*;
import java.net.*;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.amd64.*;
import sun.jvm.hotspot.debugger.x86.*;
import sun.jvm.hotspot.debugger.ia64.*;
import sun.jvm.hotspot.debugger.windbg.amd64.*;
import sun.jvm.hotspot.debugger.windbg.x86.*;
import sun.jvm.hotspot.debugger.windbg.ia64.*;
import sun.jvm.hotspot.debugger.win32.coff.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.debugger.cdbg.basic.BasicDebugEvent;
import sun.jvm.hotspot.utilities.*;
import sun.jvm.hotspot.utilities.memo.*;
import sun.jvm.hotspot.runtime.*;

/** <P> An implementation of the JVMDebugger interface which talks to
    windbg and symbol table management is done in Java. </P>

    <P> <B>NOTE</B> that since we have the notion of fetching "Java
    primitive types" from the remote process (which might have
    different sizes than we expect) we have a bootstrapping
    problem. We need to know the sizes of these types before we can
    fetch them. The current implementation solves this problem by
    requiring that it be configured with these type sizes before they
    can be fetched. The readJ(Type) routines here will throw a
    RuntimeException if they are called before the debugger is
    configured with the Java primitive type sizes. </P> */

public class WindbgDebuggerLocal extends DebuggerBase implements WindbgDebugger {
  private PageCache cache;
  private boolean   attached;
  private boolean   isCore;

  // Symbol lookup support
  // This is a map of library names to DLLs
  private Map nameToDllMap;

  // C/C++ debugging support
  private List/*<LoadObject>*/ loadObjects;
  private CDebugger cdbg;

  // thread access
  private Map threadIntegerRegisterSet;
  private List threadList;

  // windbg native interface pointers

  private long ptrIDebugClient;
  private long ptrIDebugControl;
  private long ptrIDebugDataSpaces;
  private long ptrIDebugOutputCallbacks;
  private long ptrIDebugAdvanced;
  private long ptrIDebugSymbols;
  private long ptrIDebugSystemObjects;

  private WindbgThreadFactory threadFactory;

  //--------------------------------------------------------------------------------
  // Implementation of Debugger interface
  //

  /** <P> machDesc may not be null. </P>

      <P> useCache should be set to true if debugging is being done
      locally, and to false if the debugger is being created for the
      purpose of supporting remote debugging. </P> */
  public WindbgDebuggerLocal(MachineDescription machDesc,
                            boolean useCache) throws DebuggerException {
    this.machDesc = machDesc;
    utils = new DebuggerUtilities(machDesc.getAddressSize(), machDesc.isBigEndian()) {
           public void checkAlignment(long address, long alignment) {
             // Need to override default checkAlignment because we need to
             // relax alignment constraints on Windows/x86
             if ( (address % alignment != 0)
                &&(alignment != 8 || address % 4 != 0)) {
                throw new UnalignedAddressException(
                        "Trying to read at address: "
                      + addressValueToString(address)
                      + " with alignment: " + alignment,
                        address);
             }
           }
        };

    String cpu = PlatformInfo.getCPU();
    if (cpu.equals("x86")) {
       threadFactory = new WindbgX86ThreadFactory(this);
    } else if (cpu.equals("amd64")) {
       threadFactory = new WindbgAMD64ThreadFactory(this);
    } else if (cpu.equals("ia64")) {
       threadFactory = new WindbgIA64ThreadFactory(this);
    }

    if (useCache) {
      // Cache portion of the remote process's address space.
      // Fetching data over the socket connection to dbx is slow.
      // Might be faster if we were using a binary protocol to talk to
      // dbx, but would have to test. For now, this cache works best
      // if it covers the entire heap of the remote process. FIXME: at
      // least should make this tunable from the outside, i.e., via
      // the UI. This is a cache of 4096 4K pages, or 16 MB. The page
      // size must be adjusted to be the hardware's page size.
      // (FIXME: should pick this up from the debugger.)
      initCache(4096, 4096);
    }
    // FIXME: add instantiation of thread factory

  }

  /** From the Debugger interface via JVMDebugger */
  public boolean hasProcessList() throws DebuggerException {
    return false;
  }

  /** From the Debugger interface via JVMDebugger */
  public List getProcessList() throws DebuggerException {
    return null;
  }


  /** From the Debugger interface via JVMDebugger */
  public synchronized void attach(int processID) throws DebuggerException {
    attachInit();
    attach0(processID);
    attached = true;
    isCore = false;
  }

  /** From the Debugger interface via JVMDebugger */
  public synchronized void attach(String executableName, String coreFileName) throws DebuggerException {
    attachInit();
    attach0(executableName, coreFileName);
    attached = true;
    isCore = true;
  }

  public List getLoadObjectList() {
    requireAttach();
    return loadObjects;
  }

  /** From the Debugger interface via JVMDebugger */
  public synchronized boolean detach() {
    if ( ! attached)
       return false;

    // Close all open DLLs
    if (nameToDllMap != null) {
      for (Iterator iter = nameToDllMap.values().iterator(); iter.hasNext(); ) {
        DLL dll = (DLL) iter.next();
        dll.close();
      }
      nameToDllMap = null;
      loadObjects = null;
    }

    cdbg = null;
    clearCache();

    threadIntegerRegisterSet = null;
    threadList = null;
    try {
       detach0();
    } finally {
       attached = false;
       resetNativePointers();
    }
    return true;
  }


  /** From the Debugger interface via JVMDebugger */
  public Address parseAddress(String addressString) throws NumberFormatException {
    return newAddress(utils.scanAddress(addressString));
  }

  /** From the Debugger interface via JVMDebugger */
  public String getOS() {
    return PlatformInfo.getOS();
  }

  /** From the Debugger interface via JVMDebugger */
  public String getCPU() {
    return PlatformInfo.getCPU();
  }

  public boolean hasConsole() throws DebuggerException {
    return true;
  }

  public synchronized String consoleExecuteCommand(String cmd) throws DebuggerException {
    requireAttach();
    if (! attached) {
       throw new DebuggerException("debugger not yet attached to a Dr. Watson dump!");
    }

    return consoleExecuteCommand0(cmd);
  }

  public String getConsolePrompt() throws DebuggerException {
    return "(windbg)";
  }

  public CDebugger getCDebugger() throws DebuggerException {
    if (cdbg == null) {
      // FIXME: CDebugger is not yet supported for IA64 because
      // of native stack walking issues.
      if (! getCPU().equals("ia64")) {
         cdbg = new WindbgCDebugger(this);
      }
    }
    return cdbg;
  }

  /** From the SymbolLookup interface via Debugger and JVMDebugger */
  public synchronized Address lookup(String objectName, String symbol) {
    requireAttach();
    return newAddress(lookupByName(objectName, symbol));
  }

  /** From the SymbolLookup interface via Debugger and JVMDebugger */
  public synchronized OopHandle lookupOop(String objectName, String symbol) {
    Address addr = lookup(objectName, symbol);
    if (addr == null) {
      return null;
    }
    return addr.addOffsetToAsOopHandle(0);
  }

  public synchronized ClosestSymbol lookup(long address) {
    return lookupByAddress0(address);
  }

  /** From the Debugger interface */
  public MachineDescription getMachineDescription() {
    return machDesc;
  }

  //--------------------------------------------------------------------------------
  // Implementation of ThreadAccess interface
  //


  /** From the ThreadAccess interface via Debugger and JVMDebugger */
  public ThreadProxy getThreadForIdentifierAddress(Address addr) {
    return threadFactory.createThreadWrapper(addr);
  }

  public ThreadProxy getThreadForThreadId(long handle) {
    // with windbg we can't make out using handle
    throw new DebuggerException("Unimplemented!");
  }

  public long getThreadIdFromSysId(long sysId) throws DebuggerException {
    requireAttach();
    return getThreadIdFromSysId0(sysId);
  }

  //----------------------------------------------------------------------
  // Overridden from DebuggerBase because we need to relax alignment
  // constraints on x86

  public long readJLong(long address)
    throws UnmappedAddressException, UnalignedAddressException {
    checkJavaConfigured();
    // 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.
    //    utils.checkAlignment(address, jlongSize);
    utils.checkAlignment(address, jintSize);
    byte[] data = readBytes(address, jlongSize);
    return utils.dataToJLong(data, jlongSize);
  }

  //--------------------------------------------------------------------------------
  // Internal routines (for implementation of WindbgAddress).
  // These must not be called until the MachineDescription has been set up.
  //

  /** From the WindbgDebugger interface */
  public String addressValueToString(long address) {
    return utils.addressValueToString(address);
  }

  /** From the WindbgDebugger interface */
  public WindbgAddress readAddress(long address)
    throws UnmappedAddressException, UnalignedAddressException {
    return (WindbgAddress) newAddress(readAddressValue(address));
  }

  public WindbgAddress readCompOopAddress(long address)
    throws UnmappedAddressException, UnalignedAddressException {
    return (WindbgAddress) newAddress(readCompOopAddressValue(address));
  }

  public WindbgAddress readCompKlassAddress(long address)
    throws UnmappedAddressException, UnalignedAddressException {
    return (WindbgAddress) newAddress(readCompKlassAddressValue(address));
  }

  /** From the WindbgDebugger interface */
  public WindbgOopHandle readOopHandle(long address)
    throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
    long value = readAddressValue(address);
    return (value == 0 ? null : new WindbgOopHandle(this, value));
  }
  public WindbgOopHandle readCompOopHandle(long address)
    throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
    long value = readCompOopAddressValue(address);
    return (value == 0 ? null : new WindbgOopHandle(this, value));
  }

  /** From the WindbgDebugger interface */
  public int getAddressSize() {
    return (int) machDesc.getAddressSize();
  }

  //--------------------------------------------------------------------------------
  // Thread context access
  //

  private synchronized void setThreadIntegerRegisterSet(long threadId,
                                               long[] regs) {
    threadIntegerRegisterSet.put(new Long(threadId), regs);
  }

  private synchronized void addThread(long sysId) {
    threadList.add(threadFactory.createThreadWrapper(sysId));
  }

  public synchronized long[] getThreadIntegerRegisterSet(long threadId)
    throws DebuggerException {
    requireAttach();
    return (long[]) threadIntegerRegisterSet.get(new Long(threadId));
  }

  public synchronized List getThreadList() throws DebuggerException {
    requireAttach();
    return threadList;
  }

  private String findFullPath(String file) {
    File f = new File(file);
    if (f.exists()) {
       return file;
    } else {
       // remove path part, if any.
       file = f.getName();
       StringTokenizer st = new StringTokenizer(imagePath, File.pathSeparator);
       while (st.hasMoreTokens()) {
          f = new File(st.nextToken(), file);
          if (f.exists()) {
             return f.getPath();
          }
       }
    }
    return null;
  }

  private synchronized void addLoadObject(String file, long size, long base) {
    String path = findFullPath(file);
    if (path != null) {
       DLL dll = null;
       if (useNativeLookup) {
          dll = new DLL(this, path, size,newAddress(base)) {
                 public ClosestSymbol  closestSymbolToPC(Address pcAsAddr) {
                   long pc = getAddressValue(pcAsAddr);
                   ClosestSymbol sym = lookupByAddress0(pc);
                   if (sym == null) {
                     return super.closestSymbolToPC(pcAsAddr);
                   } else {
                     return sym;
                   }
                 }
              };
       } else {
         dll = new DLL(this, path, size, newAddress(base));
       }
       loadObjects.add(dll);
       nameToDllMap.put(new File(file).getName(), dll);
    }
  }

  //--------------------------------------------------------------------------------
  // Address access
  //

  /** From the Debugger interface */
  public long getAddressValue(Address addr) {
    if (addr == null) return 0;
    return ((WindbgAddress) addr).getValue();
  }

  /** From the WindbgDebugger interface */
  public Address newAddress(long value) {
    if (value == 0) return null;
    return new WindbgAddress(this, value);
  }

  //--------------------------------------------------------------------------------
  // Internals only below this point
  //

  // attach/detach helpers
  private void checkAttached() {
    if (attached) {
       String msg = (isCore)? "already attached to a Dr. Watson dump!" :
                              "already attached to a process!";
       throw new DebuggerException(msg);
    }
  }

  private void requireAttach() {
    if (!attached) {
       throw new RuntimeException("not attached to a process or Dr Watson dump");
    }
  }

  private void attachInit() {
    checkAttached();
    loadObjects = new ArrayList();
    nameToDllMap = new HashMap();
    threadIntegerRegisterSet = new HashMap();
    threadList = new ArrayList();
  }

  private void resetNativePointers() {
    ptrIDebugClient          = 0L;
    ptrIDebugControl         = 0L;
    ptrIDebugDataSpaces      = 0L;
    ptrIDebugOutputCallbacks = 0L;
    ptrIDebugAdvanced        = 0L;
    ptrIDebugSymbols         = 0L;
    ptrIDebugSystemObjects   = 0L;
  }

  synchronized long lookupByName(String objectName, String symbol) {
    long res = 0L;
    if (useNativeLookup) {
      res = lookupByName0(objectName, symbol);
      if (res != 0L) {
        return res;
      } // else fallthru...
    }

    DLL dll = (DLL) nameToDllMap.get(objectName);
    // The DLL can be null because we use this to search through known
    // DLLs in HotSpotTypeDataBase (for example)
    if (dll != null) {
      WindbgAddress addr = (WindbgAddress) dll.lookupSymbol(symbol);
      if (addr != null) {
        return addr.getValue();
      }
    }
    return 0L;
  }

  /** This reads bytes from the remote process. */
  public synchronized ReadResult readBytesFromProcess(long address, long numBytes)
    throws UnmappedAddressException, DebuggerException {
    requireAttach();
    byte[] res = readBytesFromProcess0(address, numBytes);
    if(res != null)
       return new ReadResult(res);
    else
       return new ReadResult(address);
  }


  private DLL findDLLByName(String fullPathName) {
    for (Iterator iter = loadObjects.iterator(); iter.hasNext(); ) {
      DLL dll = (DLL) iter.next();
      if (dll.getName().equals(fullPathName)) {
        return dll;
      }
    }
    return null;
  }

  public void writeBytesToProcess(long address, long numBytes, byte[] data)
    throws UnmappedAddressException, DebuggerException {
    // FIXME
    throw new DebuggerException("Unimplemented");
  }

  private static String  imagePath;
  private static String  symbolPath;
  private static boolean useNativeLookup;

    static {

     /*
      * sawindbg.dll depends on dbgeng.dll which itself depends on
      * dbghelp.dll. We have to make sure that the dbgeng.dll and
      * dbghelp.dll that we load are compatible with each other. We
      * load both of those libraries from the same directory based
      * on the theory that co-located libraries are compatible.
      *
      * On Windows 2000 and earlier, dbgeng.dll and dbghelp.dll were
      * not included as part of the standard system directory. On
      * systems newer than Windows 2000, dbgeng.dll and dbghelp.dll
      * are included in the standard system directory. However, the
      * versions included in the standard system directory may not
      * be able to handle symbol information for the newer compilers.
      *
      * We search for and explicitly load the libraries using the
      * following directory search order:
      *
      * - java.home/bin (same as $JAVA_HOME/jre/bin)
      * - dir named by DEBUGGINGTOOLSFORWINDOWS environment variable
      * - various "Debugging Tools For Windows" program directories
      * - the system directory ($SYSROOT/system32)
      *
      * If SA is invoked with -Dsun.jvm.hotspot.loadLibrary.DEBUG=1,
      * then debug messages about library loading are printed to
      * System.err.
      */

    String dbgengPath   = null;
    String dbghelpPath  = null;
    String sawindbgPath = null;
    List   searchList   = new ArrayList();

    boolean loadLibraryDEBUG =
        System.getProperty("sun.jvm.hotspot.loadLibrary.DEBUG") != null;

    {
      // First place to search is co-located with sawindbg.dll in
      // $JAVA_HOME/jre/bin (java.home property is set to $JAVA_HOME/jre):
      searchList.add(System.getProperty("java.home") + File.separator + "bin");
      sawindbgPath = (String) searchList.get(0) + File.separator +
          "sawindbg.dll";

      // second place to search is specified by an environment variable:
      String DTFWHome = System.getenv("DEBUGGINGTOOLSFORWINDOWS");
      if (DTFWHome != null) {
        searchList.add(DTFWHome);
      }

      // The third place to search is the install directory for the
      // "Debugging Tools For Windows" package; so far there are three
      // name variations that we know of:
      String sysRoot = System.getenv("SYSTEMROOT");
      DTFWHome = sysRoot + File.separator + ".." + File.separator +
          "Program Files" + File.separator + "Debugging Tools For Windows";
      searchList.add(DTFWHome);

      // Only add the search path for the current CPU architecture:
      String cpu = PlatformInfo.getCPU();
      if (cpu.equals("x86")) {
          searchList.add(DTFWHome + " (x86)");
      } else if (cpu.equals("amd64")) {
          searchList.add(DTFWHome + " (x64)");
      }
      // The last place to search is the system directory:
      searchList.add(sysRoot + File.separator + "system32");
    }

    for (int i = 0; i < searchList.size(); i++) {
      File dir = new File((String) searchList.get(i));
      if (!dir.exists()) {
        if (loadLibraryDEBUG) {
          System.err.println("DEBUG: '" + searchList.get(i) +
              "': directory does not exist.");
        }
        // this search directory doesn't exist so skip it
        continue;
      }

      dbgengPath = (String) searchList.get(i) + File.separator + "dbgeng.dll";
      dbghelpPath = (String) searchList.get(i) + File.separator + "dbghelp.dll";

      File feng = new File(dbgengPath);
      File fhelp = new File(dbghelpPath);
      if (feng.exists() && fhelp.exists()) {
        // both files exist so we have a match
        break;
      }

      // At least one of the files does not exist; no warning if both
      // don't exist. If just one doesn't exist then we don't check
      // loadLibraryDEBUG because we have a mis-configured system.
      if (feng.exists()) {
        System.err.println("WARNING: found '" + dbgengPath +
            "' but did not find '" + dbghelpPath + "'; ignoring '" +
            dbgengPath + "'.");
      } else if (fhelp.exists()) {
        System.err.println("WARNING: found '" + dbghelpPath +
            "' but did not find '" + dbgengPath + "'; ignoring '" +
            dbghelpPath + "'.");
      } else if (loadLibraryDEBUG) {
        System.err.println("DEBUG: searched '" + searchList.get(i) +
          "': dbgeng.dll and dbghelp.dll were not found.");
      }
      dbgengPath = null;
      dbghelpPath = null;
    }

    if (dbgengPath == null || dbghelpPath == null) {
      // at least one of the files wasn't found anywhere we searched
      String mesg = null;

      if (dbgengPath == null && dbghelpPath == null) {
        mesg = "dbgeng.dll and dbghelp.dll cannot be found. ";
      } else if (dbgengPath == null) {
        mesg = "dbgeng.dll cannot be found (dbghelp.dll was found). ";
      } else {
        mesg = "dbghelp.dll cannot be found (dbgeng.dll was found). ";
      }
      throw new UnsatisfiedLinkError(mesg +
          "Please search microsoft.com for 'Debugging Tools For Windows', " +
          "and either download it to the default location, or download it " +
          "to a custom location and set environment variable " +
          "'DEBUGGINGTOOLSFORWINDOWS' to the pathname of that location.");
    }

    // NOTE: The order of loads is important! If we load dbgeng.dll
    // first, then the dependency - dbghelp.dll - will be loaded
    // from usual DLL search thereby defeating the purpose!
    if (loadLibraryDEBUG) {
      System.err.println("DEBUG: loading '" + dbghelpPath + "'.");
    }
    System.load(dbghelpPath);
    if (loadLibraryDEBUG) {
      System.err.println("DEBUG: loading '" + dbgengPath + "'.");
    }
    System.load(dbgengPath);

    // Now, load sawindbg.dll
    if (loadLibraryDEBUG) {
      System.err.println("DEBUG: loading '" + sawindbgPath + "'.");
    }
    System.load(sawindbgPath);

    // where do I find '.exe', '.dll' files?
    imagePath = System.getProperty("sun.jvm.hotspot.debugger.windbg.imagePath");
    if (imagePath == null) {
      imagePath = System.getenv("PATH");
    }

    // where do I find '.pdb', '.dbg' files?
    symbolPath = System.getProperty("sun.jvm.hotspot.debugger.windbg.symbolPath");

    // mostly, debug files would be find where .dll's, .exe's are found.
    if (symbolPath == null) {
      symbolPath = imagePath;
    }

    // should we parse DLL symbol table in Java code or use
    // Windbg's native lookup facility? By default, we use
    // native lookup so that we can take advantage of '.pdb'
    // files, if available.
    useNativeLookup = true;
    String str = System.getProperty("sun.jvm.hotspot.debugger.windbg.disableNativeLookup");
    if (str != null) {
      useNativeLookup = false;
    }

    initIDs();
  }

  // native methods
  private static native void initIDs();
  private native void attach0(String executableName, String coreFileName);
  private native void attach0(int processID);
  private native void detach0();
  private native byte[] readBytesFromProcess0(long address, long numBytes)
    throws UnmappedAddressException, DebuggerException;
  private native long getThreadIdFromSysId0(long sysId);
  private native String consoleExecuteCommand0(String cmd);
  private native long lookupByName0(String objName, String symName);
  private native ClosestSymbol lookupByAddress0(long address);

  // helper called lookupByAddress0
  private ClosestSymbol createClosestSymbol(String symbol, long diff) {
    return new ClosestSymbol(symbol, diff);
  }
}
