/*
 * Copyright (c) 2002, 2012, 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.proc;

import java.io.*;
import java.net.*;
import java.util.*;
import java.lang.reflect.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.debugger.proc.amd64.*;
import sun.jvm.hotspot.debugger.proc.sparc.*;
import sun.jvm.hotspot.debugger.proc.x86.*;
import sun.jvm.hotspot.debugger.amd64.*;
import sun.jvm.hotspot.debugger.sparc.*;
import sun.jvm.hotspot.debugger.x86.*;
import sun.jvm.hotspot.utilities.*;

/** <P> An implementation of the JVMDebugger interface which sits on
 * top of proc and relies on the SA's proc import module for
 * communication with the debugger. </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 ProcDebuggerLocal extends DebuggerBase implements ProcDebugger {
    protected static final int cacheSize = 16 * 1024 * 1024; // 16 MB

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

    /** <P> machDesc may be null if it couldn't be determined yet; i.e.,
     * if we're on SPARC, we need to ask the remote process whether
     * we're in 32- or 64-bit mode. </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 ProcDebuggerLocal(MachineDescription machDesc, boolean useCache) {
        this.machDesc = machDesc;
        int cacheNumPages;
        int cachePageSize;

        final String cpu = PlatformInfo.getCPU();
        if (cpu.equals("sparc")) {
            threadFactory = new ProcSPARCThreadFactory(this);
            pcRegIndex = SPARCThreadContext.R_PC;
            fpRegIndex = SPARCThreadContext.R_I6;
        } else if (cpu.equals("x86")) {
            threadFactory = new ProcX86ThreadFactory(this);
            pcRegIndex = X86ThreadContext.EIP;
            fpRegIndex = X86ThreadContext.EBP;
            unalignedAccessesOkay = true;
        } else if (cpu.equals("amd64") || cpu.equals("x86_64")) {
            threadFactory = new ProcAMD64ThreadFactory(this);
            pcRegIndex = AMD64ThreadContext.RIP;
            fpRegIndex = AMD64ThreadContext.RBP;
        } else {
          try {
            Class tfc = Class.forName("sun.jvm.hotspot.debugger.proc." +
               cpu.toLowerCase() + ".Proc" + cpu.toUpperCase() +
               "ThreadFactory");
            Constructor[] ctfc = tfc.getConstructors();
            threadFactory = (ProcThreadFactory)ctfc[0].newInstance(this);
          } catch (Exception e) {
            throw new RuntimeException("Thread access for CPU architecture " + PlatformInfo.getCPU() + " not yet supported");
            // Note: pcRegIndex and fpRegIndex do not appear to be referenced
          }
        }
        if (useCache) {
            // Cache portion of the remote process's address space.
            // 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 16 MB
            // cache divided on SPARC into 2048 8K pages and on x86 into
            // 4096 4K pages; the page size must be adjusted to be the OS's
            // page size.

            cachePageSize = getPageSize();
            cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize);
            initCache(cachePageSize, cacheNumPages);
        }

        resetNativePointers();
        clearCacheFields();
    }

    /** FIXME: implement this with a Runtime.exec() of ps followed by
     * parsing of its output */
    public boolean hasProcessList() throws DebuggerException {
        return false;
    }

    public List getProcessList() throws DebuggerException {
        throw new DebuggerException("Not yet supported");
    }


    /** From the Debugger interface via JVMDebugger */
    public synchronized void attach(int processID) throws DebuggerException {
        checkAttached();
        isCore = false;
        attach0(new Integer(processID).toString());
        attached = true;
        suspended = true;
    }

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

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

        try {
            if (p_ps_prochandle == 0L) {
                return false;
            }
            detach0();
            clearCache();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            resetNativePointers();
            clearCacheFields();
            suspended = false;
            attached = false;
        }
    }

    public synchronized void suspend() throws DebuggerException {
        requireAttach();
        if (suspended) {
            throw new DebuggerException("Process already suspended");
        }
        suspend0();
        suspended = true;
        enableCache();
        reresolveLoadObjects();
    }

    public synchronized void resume() throws DebuggerException {
        requireAttach();
        if (!suspended) {
            throw new DebuggerException("Process not suspended");
        }
        resume0();
        disableCache();
        suspended = false;
    }

    public synchronized boolean isSuspended() throws DebuggerException {
        requireAttach();
        return suspended;
    }

    /** From the Debugger interface via JVMDebugger */
    public Address parseAddress(String addressString) throws NumberFormatException {
        long addr = utils.scanAddress(addressString);
        if (addr == 0) {
            return null;
        }
        return new ProcAddress(this, addr);
    }

    /** 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 false;
    }

    public String consoleExecuteCommand(String cmd) throws DebuggerException {
        throw new DebuggerException("Can't execute console commands");
    }

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

    public CDebugger getCDebugger() throws DebuggerException {
        if (cdbg == null) {
            cdbg = new ProcCDebugger(this);
        }
        return cdbg;
    }

    /** From the SymbolLookup interface via Debugger and JVMDebugger */
    public synchronized Address lookup(String objectName, String symbol) {
        requireAttach();
        long addr = lookupByName0(objectName, symbol);
        if (addr == 0) {
            return null;
        }
        return new ProcAddress(this, addr);
    }

    /** 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);
    }

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

    /** Internal routine supporting lazy setting of MachineDescription,
     * since on SPARC we will need to query the remote process to ask
     * it what its data model is (32- or 64-bit).
     */

    public void setMachineDescription(MachineDescription machDesc) {
        this.machDesc = machDesc;
        setBigEndian(machDesc.isBigEndian());
        utils = new DebuggerUtilities(machDesc.getAddressSize(), machDesc.isBigEndian());
    }

    public synchronized int getRemoteProcessAddressSize()
    throws DebuggerException {
        requireAttach();
        return getRemoteProcessAddressSize0();
    }

    //--------------------------------------------------------------------------------
    // 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 id) {
        return threadFactory.createThreadWrapper(id);
    }

    //----------------------------------------------------------------------
    // 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.
        if (unalignedAccessesOkay) {
            utils.checkAlignment(address, jintSize);
        } else {
            utils.checkAlignment(address, jlongSize);
        }
        byte[] data = readBytes(address, jlongSize);
        return utils.dataToJLong(data, jlongSize);
    }

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

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

    /** Need to override this to relax alignment checks on Solaris/x86. */
    public long readCInteger(long address, long numBytes, boolean isUnsigned)
    throws UnmappedAddressException, UnalignedAddressException {
        checkConfigured();
        if (!unalignedAccessesOkay) {
            utils.checkAlignment(address, numBytes);
        } else {
            // Only slightly relaxed semantics -- this is a hack, but is
            // necessary on Solaris/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);
    }

    /** From the ProcDebugger interface */
    public ProcAddress readAddress(long address)
    throws UnmappedAddressException, UnalignedAddressException {
        long value = readAddressValue(address);
        return (value == 0 ? null : new ProcAddress(this, value));
    }

    public ProcAddress readCompOopAddress(long address)
    throws UnmappedAddressException, UnalignedAddressException {
        long value = readCompOopAddressValue(address);
        return (value == 0 ? null : new ProcAddress(this, value));
    }

    public ProcAddress readCompKlassAddress(long address)
    throws UnmappedAddressException, UnalignedAddressException {
        long value = readCompKlassAddressValue(address);
        return (value == 0 ? null : new ProcAddress(this, value));
    }

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

    public ProcOopHandle readCompOopHandle(long address) {
        long value = readCompOopAddressValue(address);
        return (value == 0 ? null : new ProcOopHandle(this, value));
    }

    public void writeBytesToProcess(long address, long numBytes, byte[] data)
    throws UnmappedAddressException, DebuggerException {
        if (isCore) {
            throw new DebuggerException("Attached to a core file!");
        }
        writeBytesToProcess0(address, numBytes, data);
    }

    public synchronized ReadResult readBytesFromProcess(long address, long numBytes)
    throws DebuggerException {
        requireAttach();
        byte[] res = readBytesFromProcess0(address, numBytes);
        if(res != null)
            return new ReadResult(res);
        else
            return new ReadResult(address);
    }

    protected int getPageSize() {
        int pagesize = getPageSize0();
        if (pagesize == -1) {
            // return the hard coded default value.
            if (PlatformInfo.getCPU().equals("sparc") ||
                PlatformInfo.getCPU().equals("amd64") )
               pagesize = 8196;
            else
               pagesize = 4096;
        }
        return pagesize;
    }

    //--------------------------------------------------------------------------------
    // Thread context access. Can not be package private, but should
    // only be accessed by the architecture-specific subpackages.

    /** From the ProcDebugger interface. May have to redefine this later. */
    public synchronized long[] getThreadIntegerRegisterSet(int tid) {
        requireAttach();
        return getThreadIntegerRegisterSet0(tid);
    }

    //--------------------------------------------------------------------------------
    // Address access. Can not be package private, but should only be
    // accessed by the architecture-specific subpackages.

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

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

    /** From the ProcDebugger interface */
    public synchronized List getThreadList() throws DebuggerException {
        requireAttach();
        List res = null;
        if (isCore && (threadListCache != null)) {
            res = threadListCache;
        } else {
            res = new ArrayList();
            fillThreadList0(res);
            if (isCore) {
                threadListCache = res;
            }
        }
        return res;
    }

    /** From the ProcDebugger interface */
    public synchronized List getLoadObjectList() throws DebuggerException {
        requireAttach();
        if (!suspended) {
            throw new DebuggerException("Process not suspended");
        }

        if (loadObjectCache == null) {
            updateLoadObjectCache();
        }
        return loadObjectCache;
    }

    /** From the ProcDebugger interface */
    public synchronized CFrame topFrameForThread(ThreadProxy thread)
    throws DebuggerException {
        requireAttach();
        CFrame res = null;
        if (isCore && ((res = (CFrame) topFrameCache.get(thread)) != null)) {
            return res;
        } else {
            ThreadContext context = thread.getContext();
            int numRegs = context.getNumRegisters();
            long[] regs = new long[numRegs];
            for (int i = 0; i < numRegs; i++) {
                regs[i] = context.getRegister(i);
            }
            res = fillCFrameList0(regs);
            if (isCore) {
                topFrameCache.put(thread, res);
            }
            return res;
        }
    }

    /** From the ProcDebugger interface */
    public synchronized ClosestSymbol lookup(long address) {
        requireAttach();
        return lookupByAddress0(address);
    }

    /** From the ProcDebugger interface */
    public String demangle(String name) {
        return demangle0(name);
    }

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

    private void updateLoadObjectCache() {
        List res = new ArrayList();
        nameToDsoMap = new HashMap();
        fillLoadObjectList0(res);
        loadObjectCache = sortLoadObjects(res);
    }

    // sort load objects by base address
    private static List sortLoadObjects(List in) {
        // sort the list by base address
        Object[] arr = in.toArray();
        Arrays.sort(arr, loadObjectComparator);
        return Arrays.asList(arr);
    }

    private long lookupByName(String objectName, String symbolName)
    throws DebuggerException {
        // NOTE: this assumes that process is suspended (which is probably
        // necessary assumption given that DSOs can be loaded/unloaded as
        // process runs). Should update documentation.
        if (nameToDsoMap == null) {
            getLoadObjectList();
        }
        SharedObject dso = (SharedObject) nameToDsoMap.get(objectName);
        // The DSO can be null because we use this to search through known
        // DSOs in HotSpotTypeDataBase (for example)
        if (dso != null) {
            ProcAddress addr = (ProcAddress) dso.lookupSymbol(symbolName);
            if (addr != null) {
                return addr.getValue();
            }
        }
        return 0;
    }

    private SharedObject findDSOByName(String fullPathName) {
        if (loadObjectCache == null)
            return null;
        for (Iterator iter = loadObjectCache.iterator(); iter.hasNext(); ) {
            SharedObject dso = (SharedObject) iter.next();
            if (dso.getName().equals(fullPathName)) {
                return dso;
            }
        }
        return null;
    }

    private void reresolveLoadObjects() throws DebuggerException {
        if (loadObjectCache == null) {
            return;
        }
        updateLoadObjectCache();
    }


    private void checkAttached() {
        if (attached) {
            if (isCore) {
                throw new DebuggerException("already attached to a core file!");
            } else {
                throw new DebuggerException("already attached to a process!");
            }
        }
    }

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

    private void clearCacheFields() {
        loadObjectCache = null;
        nameToDsoMap    = null;
        threadListCache = null;
        topFrameCache   = null;
    }

    private void resetNativePointers() {
        p_ps_prochandle          = 0L;

        // reset thread_db pointers
        libthread_db_handle    = 0L;
        p_td_thragent_t        = 0L;
        p_td_init              = 0L;
        p_td_ta_new            = 0L;
        p_td_ta_delete         = 0L;
        p_td_ta_thr_iter       = 0L;
        p_td_thr_get_info      = 0L;
        p_td_ta_map_id2thr     = 0L;
        p_td_thr_getgregs      = 0L;

        // part of class sharing workaround
        classes_jsa_fd         = -1;
        p_file_map_header      = 0L;
    }

    // native methods and native helpers

    // attach, detach
    private native void attach0(String pid) throws DebuggerException;
    private native void attach0(String executableFile, String coreFileName) throws DebuggerException;
    private native void detach0() throws DebuggerException;

    // address size, page size
    private native int getRemoteProcessAddressSize0() throws DebuggerException;
    private native int getPageSize0() throws DebuggerException;

    // threads, stacks
    private native long[] getThreadIntegerRegisterSet0(long tid) throws DebuggerException;
    private native void   fillThreadList0(List l) throws DebuggerException;

    // fills stack frame list given reg set of the top frame and top frame
    private native ProcCFrame fillCFrameList0(long[] regs) throws DebuggerException;

    // helper called by fillCFrameList0
    private ProcCFrame createSenderFrame(ProcCFrame f, long pc, long fp) {
        ProcCFrame sender = new ProcCFrame(this, newAddress(pc), newAddress(fp));
        if (f != null) {
            f.setSender(sender);
        }
        return sender;
    }

    // shared objects
    private native void fillLoadObjectList0(List l) throws DebuggerException;

    // helper called by fillLoadObjectList0
    private LoadObject createLoadObject(String fileName, long textsize, long base) {
        File f = new File(fileName);
        Address baseAddr = newAddress(base);
        SharedObject res = findDSOByName(fileName);
        if (res != null) {
            // already in cache. just change the base, if needed
            Address oldBase = res.getBase();
            if (! baseAddr.equals(oldBase)) {
                res.setBase(baseAddr);
            }
        } else {
            // new shared object.
            res = new SharedObject(this, fileName, f.length(), baseAddr);
        }
        nameToDsoMap.put(f.getName(), res);
        return res;
    }

    // symbol-to-pc
    private native long lookupByName0(String objectName, String symbolName) throws DebuggerException;
    private native ClosestSymbol lookupByAddress0(long address) throws DebuggerException;

    // helper called by lookupByAddress0
    private ClosestSymbol createClosestSymbol(String name, long offset) {
        return new ClosestSymbol(name, offset);
    }

    // process read/write
    private native byte[] readBytesFromProcess0(long address, long numBytes) throws DebuggerException;
    private native void writeBytesToProcess0(long address, long numBytes, byte[] data) throws DebuggerException;

    // process control
    private native void suspend0() throws DebuggerException;
    private native void resume0() throws DebuggerException;

    // demangle a C++ name
    private native String demangle0(String name);

    // init JNI ids to fields, methods
    private native static void initIDs() throws DebuggerException;
    private static LoadObjectComparator loadObjectComparator;

    static {
        System.loadLibrary("saproc");
        initIDs();
        loadObjectComparator = new LoadObjectComparator();
    }

    private boolean unalignedAccessesOkay;
    private ProcThreadFactory threadFactory;

    // indices of PC and FP registers in gregset
    private int pcRegIndex;
    private int fpRegIndex;

    // Symbol lookup support
    // This is a map of library names to DSOs
    private Map nameToDsoMap;  // Map<String, SharedObject>

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

    // ProcessControl support
    private boolean suspended;

    // libproc handle
    private long p_ps_prochandle;

    // libthread.so's dlopen handle, thread agent
    // and function pointers
    private long libthread_db_handle;
    private long p_td_thragent_t;
    private long p_td_init;
    private long p_td_ta_new;
    private long p_td_ta_delete;
    private long p_td_ta_thr_iter;
    private long p_td_thr_get_info;
    private long p_td_ta_map_id2thr;
    private long p_td_thr_getgregs;

    // part of class sharing workaround
    private int classes_jsa_fd;
    private long p_file_map_header;

    private boolean attached = false;
    private boolean isCore;

    // for core files, we cache load object list, thread list, top frames etc.
    // for processes we cache load object list and sync. it during suspend.
    private List threadListCache;
    private List loadObjectCache;
    private Map  topFrameCache;      // Map<ThreadProxy, CFrame>
}
