1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 package sun.jvm.hotspot.debugger.proc;
  26 
  27 import java.io.*;
  28 import java.net.*;
  29 import java.util.*;
  30 import java.lang.reflect.*;
  31 import sun.jvm.hotspot.debugger.*;
  32 import sun.jvm.hotspot.debugger.cdbg.*;
  33 import sun.jvm.hotspot.debugger.proc.amd64.*;
  34 import sun.jvm.hotspot.debugger.proc.sparc.*;
  35 import sun.jvm.hotspot.debugger.proc.ppc64.*;
  36 import sun.jvm.hotspot.debugger.proc.x86.*;
  37 import sun.jvm.hotspot.debugger.ppc64.*;
  38 import sun.jvm.hotspot.debugger.amd64.*;
  39 import sun.jvm.hotspot.debugger.sparc.*;
  40 import sun.jvm.hotspot.debugger.x86.*;
  41 import sun.jvm.hotspot.utilities.*;
  42 
  43 /** <P> An implementation of the JVMDebugger interface which sits on
  44  * top of proc and relies on the SA's proc import module for
  45  * communication with the debugger. </P>
  46  *
  47  * <P> <B>NOTE</B> that since we have the notion of fetching "Java
  48  * primitive types" from the remote process (which might have
  49  * different sizes than we expect) we have a bootstrapping
  50  * problem. We need to know the sizes of these types before we can
  51  * fetch them. The current implementation solves this problem by
  52  * requiring that it be configured with these type sizes before they
  53  * can be fetched. The readJ(Type) routines here will throw a
  54  * RuntimeException if they are called before the debugger is
  55  * configured with the Java primitive type sizes. </P>
  56  */
  57 
  58 public class ProcDebuggerLocal extends DebuggerBase implements ProcDebugger {
  59     protected static final int cacheSize = 16 * 1024 * 1024; // 16 MB
  60 
  61     //------------------------------------------------------------------------
  62     // Implementation of Debugger interface
  63     //
  64 
  65     /** <P> machDesc may be null if it couldn't be determined yet; i.e.,
  66      * if we're on SPARC, we need to ask the remote process whether
  67      * we're in 32- or 64-bit mode. </P>
  68      *
  69      * <P> useCache should be set to true if debugging is being done
  70      * locally, and to false if the debugger is being created for the
  71      * purpose of supporting remote debugging. </P> */
  72     public ProcDebuggerLocal(MachineDescription machDesc, boolean useCache) {
  73         this.machDesc = machDesc;
  74         int cacheNumPages;
  75         int cachePageSize;
  76 
  77         final String cpu = PlatformInfo.getCPU();
  78         if (cpu.equals("sparc")) {
  79             threadFactory = new ProcSPARCThreadFactory(this);
  80             pcRegIndex = SPARCThreadContext.R_PC;
  81             fpRegIndex = SPARCThreadContext.R_I6;
  82         } else if (cpu.equals("x86")) {
  83             threadFactory = new ProcX86ThreadFactory(this);
  84             pcRegIndex = X86ThreadContext.EIP;
  85             fpRegIndex = X86ThreadContext.EBP;
  86             unalignedAccessesOkay = true;
  87         } else if (cpu.equals("amd64") || cpu.equals("x86_64")) {
  88             threadFactory = new ProcAMD64ThreadFactory(this);
  89             pcRegIndex = AMD64ThreadContext.RIP;
  90             fpRegIndex = AMD64ThreadContext.RBP;
  91         } else if (cpu.equals("ppc64")) {
  92             threadFactory = new ProcPPC64ThreadFactory(this);
  93             pcRegIndex = PPC64ThreadContext.PC;
  94             fpRegIndex = PPC64ThreadContext.SP;
  95         } else {
  96           try {
  97             Class tfc = Class.forName("sun.jvm.hotspot.debugger.proc." +
  98                cpu.toLowerCase() + ".Proc" + cpu.toUpperCase() +
  99                "ThreadFactory");
 100             Constructor[] ctfc = tfc.getConstructors();
 101             threadFactory = (ProcThreadFactory)ctfc[0].newInstance(this);
 102           } catch (Exception e) {
 103             throw new RuntimeException("Thread access for CPU architecture " + PlatformInfo.getCPU() + " not yet supported");
 104             // Note: pcRegIndex and fpRegIndex do not appear to be referenced
 105           }
 106         }
 107         if (useCache) {
 108             // Cache portion of the remote process's address space.
 109             // For now, this cache works best if it covers the entire
 110             // heap of the remote process. FIXME: at least should make this
 111             // tunable from the outside, i.e., via the UI. This is a 16 MB
 112             // cache divided on SPARC into 2048 8K pages and on x86 into
 113             // 4096 4K pages; the page size must be adjusted to be the OS's
 114             // page size.
 115 
 116             cachePageSize = getPageSize();
 117             cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize);
 118             initCache(cachePageSize, cacheNumPages);
 119         }
 120 
 121         resetNativePointers();
 122         clearCacheFields();
 123     }
 124 
 125     /** FIXME: implement this with a Runtime.exec() of ps followed by
 126      * parsing of its output */
 127     public boolean hasProcessList() throws DebuggerException {
 128         return false;
 129     }
 130 
 131     public List getProcessList() throws DebuggerException {
 132         throw new DebuggerException("Not yet supported");
 133     }
 134 
 135 
 136     /** From the Debugger interface via JVMDebugger */
 137     public synchronized void attach(int processID) throws DebuggerException {
 138         checkAttached();
 139         isCore = false;
 140         attach0(new Integer(processID).toString());
 141         attached = true;
 142         suspended = true;
 143     }
 144 
 145     /** From the Debugger interface via JVMDebugger */
 146     public synchronized void attach
 147     (String executableName, String coreFileName) throws DebuggerException {
 148         checkAttached();
 149         isCore = true;
 150         topFrameCache = new HashMap();
 151         attach0(executableName, coreFileName);
 152         attached = true;
 153         suspended = true;
 154     }
 155 
 156     /** From the Debugger interface via JVMDebugger */
 157     public synchronized boolean detach() {
 158         if (! attached) {
 159             return false;
 160         }
 161 
 162         try {
 163             if (p_ps_prochandle == 0L) {
 164                 return false;
 165             }
 166             detach0();
 167             clearCache();
 168             return true;
 169         } catch (Exception e) {
 170             e.printStackTrace();
 171             return false;
 172         } finally {
 173             resetNativePointers();
 174             clearCacheFields();
 175             suspended = false;
 176             attached = false;
 177         }
 178     }
 179 
 180     public synchronized void suspend() throws DebuggerException {
 181         requireAttach();
 182         if (suspended) {
 183             throw new DebuggerException("Process already suspended");
 184         }
 185         suspend0();
 186         suspended = true;
 187         enableCache();
 188         reresolveLoadObjects();
 189     }
 190 
 191     public synchronized void resume() throws DebuggerException {
 192         requireAttach();
 193         if (!suspended) {
 194             throw new DebuggerException("Process not suspended");
 195         }
 196         resume0();
 197         disableCache();
 198         suspended = false;
 199     }
 200 
 201     public synchronized boolean isSuspended() throws DebuggerException {
 202         requireAttach();
 203         return suspended;
 204     }
 205 
 206     /** From the Debugger interface via JVMDebugger */
 207     public Address parseAddress(String addressString) throws NumberFormatException {
 208         long addr = utils.scanAddress(addressString);
 209         if (addr == 0) {
 210             return null;
 211         }
 212         return new ProcAddress(this, addr);
 213     }
 214 
 215     /** From the Debugger interface via JVMDebugger */
 216     public String getOS() {
 217         return PlatformInfo.getOS();
 218     }
 219 
 220     /** From the Debugger interface via JVMDebugger */
 221     public String getCPU() {
 222         return PlatformInfo.getCPU();
 223     }
 224 
 225     public boolean hasConsole() throws DebuggerException {
 226         return false;
 227     }
 228 
 229     public String consoleExecuteCommand(String cmd) throws DebuggerException {
 230         throw new DebuggerException("Can't execute console commands");
 231     }
 232 
 233     public String getConsolePrompt() throws DebuggerException {
 234         return "";
 235     }
 236 
 237     public CDebugger getCDebugger() throws DebuggerException {
 238         if (cdbg == null) {
 239             cdbg = new ProcCDebugger(this);
 240         }
 241         return cdbg;
 242     }
 243 
 244     /** From the SymbolLookup interface via Debugger and JVMDebugger */
 245     public synchronized Address lookup(String objectName, String symbol) {
 246         requireAttach();
 247         long addr = lookupByName0(objectName, symbol);
 248         if (addr == 0) {
 249             return null;
 250         }
 251         return new ProcAddress(this, addr);
 252     }
 253 
 254     /** From the SymbolLookup interface via Debugger and JVMDebugger */
 255     public synchronized OopHandle lookupOop(String objectName, String symbol) {
 256         Address addr = lookup(objectName, symbol);
 257         if (addr == null) {
 258             return null;
 259         }
 260         return addr.addOffsetToAsOopHandle(0);
 261     }
 262 
 263     /** From the ProcDebugger interface */
 264     public MachineDescription getMachineDescription() {
 265         return machDesc;
 266     }
 267 
 268     /** Internal routine supporting lazy setting of MachineDescription,
 269      * since on SPARC we will need to query the remote process to ask
 270      * it what its data model is (32- or 64-bit).
 271      */
 272 
 273     public void setMachineDescription(MachineDescription machDesc) {
 274         this.machDesc = machDesc;
 275         setBigEndian(machDesc.isBigEndian());
 276         utils = new DebuggerUtilities(machDesc.getAddressSize(), machDesc.isBigEndian());
 277     }
 278 
 279     public synchronized int getRemoteProcessAddressSize()
 280     throws DebuggerException {
 281         requireAttach();
 282         return getRemoteProcessAddressSize0();
 283     }
 284 
 285     //--------------------------------------------------------------------------------
 286     // Implementation of ThreadAccess interface
 287     //
 288 
 289     /** From the ThreadAccess interface via Debugger and JVMDebugger */
 290     public ThreadProxy getThreadForIdentifierAddress(Address addr) {
 291         return threadFactory.createThreadWrapper(addr);
 292     }
 293 
 294     public ThreadProxy getThreadForThreadId(long id) {
 295         return threadFactory.createThreadWrapper(id);
 296     }
 297 
 298     //----------------------------------------------------------------------
 299     // Overridden from DebuggerBase because we need to relax alignment
 300     // constraints on x86
 301 
 302     public long readJLong(long address)
 303     throws UnmappedAddressException, UnalignedAddressException {
 304         checkJavaConfigured();
 305         // FIXME: allow this to be configurable. Undesirable to add a
 306         // dependency on the runtime package here, though, since this
 307         // package should be strictly underneath it.
 308         if (unalignedAccessesOkay) {
 309             utils.checkAlignment(address, jintSize);
 310         } else {
 311             utils.checkAlignment(address, jlongSize);
 312         }
 313         byte[] data = readBytes(address, jlongSize);
 314         return utils.dataToJLong(data, jlongSize);
 315     }
 316 
 317     //--------------------------------------------------------------------------------
 318     // Internal routines (for implementation of ProcAddress).
 319     // These must not be called until the MachineDescription has been set up.
 320     //
 321 
 322     /** From the ProcDebugger interface */
 323     public String addressValueToString(long address) {
 324         return utils.addressValueToString(address);
 325     }
 326 
 327     /** Need to override this to relax alignment checks on Solaris/x86. */
 328     public long readCInteger(long address, long numBytes, boolean isUnsigned)
 329     throws UnmappedAddressException, UnalignedAddressException {
 330         checkConfigured();
 331         if (!unalignedAccessesOkay) {
 332             utils.checkAlignment(address, numBytes);
 333         } else {
 334             // Only slightly relaxed semantics -- this is a hack, but is
 335             // necessary on Solaris/x86 where it seems the compiler is
 336             // putting some global 64-bit data on 32-bit boundaries
 337             if (numBytes == 8) {
 338                 utils.checkAlignment(address, 4);
 339             } else {
 340                 utils.checkAlignment(address, numBytes);
 341             }
 342         }
 343         byte[] data = readBytes(address, numBytes);
 344         return utils.dataToCInteger(data, isUnsigned);
 345     }
 346 
 347     /** From the ProcDebugger interface */
 348     public ProcAddress readAddress(long address)
 349     throws UnmappedAddressException, UnalignedAddressException {
 350         long value = readAddressValue(address);
 351         return (value == 0 ? null : new ProcAddress(this, value));
 352     }
 353 
 354     public ProcAddress readCompOopAddress(long address)
 355     throws UnmappedAddressException, UnalignedAddressException {
 356         long value = readCompOopAddressValue(address);
 357         return (value == 0 ? null : new ProcAddress(this, value));
 358     }
 359 
 360     public ProcAddress readCompKlassAddress(long address)
 361     throws UnmappedAddressException, UnalignedAddressException {
 362         long value = readCompKlassAddressValue(address);
 363         return (value == 0 ? null : new ProcAddress(this, value));
 364     }
 365 
 366     /** From the ProcDebugger interface */
 367     public ProcOopHandle readOopHandle(long address)
 368     throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
 369         long   value = readAddressValue(address);
 370         return (value == 0 ? null : new ProcOopHandle(this, value));
 371     }
 372 
 373     public ProcOopHandle readCompOopHandle(long address) {
 374         long value = readCompOopAddressValue(address);
 375         return (value == 0 ? null : new ProcOopHandle(this, value));
 376     }
 377 
 378     public void writeBytesToProcess(long address, long numBytes, byte[] data)
 379     throws UnmappedAddressException, DebuggerException {
 380         if (isCore) {
 381             throw new DebuggerException("Attached to a core file!");
 382         }
 383         writeBytesToProcess0(address, numBytes, data);
 384     }
 385 
 386     public synchronized ReadResult readBytesFromProcess(long address, long numBytes)
 387     throws DebuggerException {
 388         requireAttach();
 389         byte[] res = readBytesFromProcess0(address, numBytes);
 390         if(res != null)
 391             return new ReadResult(res);
 392         else
 393             return new ReadResult(address);
 394     }
 395 
 396     protected int getPageSize() {
 397         int pagesize = getPageSize0();
 398         if (pagesize == -1) {
 399             // return the hard coded default value.
 400             if (PlatformInfo.getCPU().equals("sparc") ||
 401                 PlatformInfo.getCPU().equals("amd64") )
 402                pagesize = 8196;
 403             else
 404                pagesize = 4096;
 405         }
 406         return pagesize;
 407     }
 408 
 409     //--------------------------------------------------------------------------------
 410     // Thread context access. Can not be package private, but should
 411     // only be accessed by the architecture-specific subpackages.
 412 
 413     /** From the ProcDebugger interface. May have to redefine this later. */
 414     public synchronized long[] getThreadIntegerRegisterSet(int tid) {
 415         requireAttach();
 416         return getThreadIntegerRegisterSet0(tid);
 417     }
 418 
 419     //--------------------------------------------------------------------------------
 420     // Address access. Can not be package private, but should only be
 421     // accessed by the architecture-specific subpackages.
 422 
 423     /** From the ProcDebugger interface */
 424     public long getAddressValue(Address addr) {
 425         if (addr == null) return 0;
 426         return ((ProcAddress) addr).getValue();
 427     }
 428 
 429     /** From the ProcDebugger interface */
 430     public Address newAddress(long value) {
 431         if (value == 0) return null;
 432         return new ProcAddress(this, value);
 433     }
 434 
 435     /** From the ProcDebugger interface */
 436     public synchronized List getThreadList() throws DebuggerException {
 437         requireAttach();
 438         List res = null;
 439         if (isCore && (threadListCache != null)) {
 440             res = threadListCache;
 441         } else {
 442             res = new ArrayList();
 443             fillThreadList0(res);
 444             if (isCore) {
 445                 threadListCache = res;
 446             }
 447         }
 448         return res;
 449     }
 450 
 451     /** From the ProcDebugger interface */
 452     public synchronized List getLoadObjectList() throws DebuggerException {
 453         requireAttach();
 454         if (!suspended) {
 455             throw new DebuggerException("Process not suspended");
 456         }
 457 
 458         if (loadObjectCache == null) {
 459             updateLoadObjectCache();
 460         }
 461         return loadObjectCache;
 462     }
 463 
 464     /** From the ProcDebugger interface */
 465     public synchronized CFrame topFrameForThread(ThreadProxy thread)
 466     throws DebuggerException {
 467         requireAttach();
 468         CFrame res = null;
 469         if (isCore && ((res = (CFrame) topFrameCache.get(thread)) != null)) {
 470             return res;
 471         } else {
 472             ThreadContext context = thread.getContext();
 473             int numRegs = context.getNumRegisters();
 474             long[] regs = new long[numRegs];
 475             for (int i = 0; i < numRegs; i++) {
 476                 regs[i] = context.getRegister(i);
 477             }
 478             res = fillCFrameList0(regs);
 479             if (isCore) {
 480                 topFrameCache.put(thread, res);
 481             }
 482             return res;
 483         }
 484     }
 485 
 486     /** From the ProcDebugger interface */
 487     public synchronized ClosestSymbol lookup(long address) {
 488         requireAttach();
 489         return lookupByAddress0(address);
 490     }
 491 
 492     /** From the ProcDebugger interface */
 493     public String demangle(String name) {
 494         return demangle0(name);
 495     }
 496 
 497     //------------- Internals only below this point --------------------
 498     //
 499     //
 500 
 501     private void updateLoadObjectCache() {
 502         List res = new ArrayList();
 503         nameToDsoMap = new HashMap();
 504         fillLoadObjectList0(res);
 505         loadObjectCache = sortLoadObjects(res);
 506     }
 507 
 508     // sort load objects by base address
 509     private static List sortLoadObjects(List in) {
 510         // sort the list by base address
 511         Object[] arr = in.toArray();
 512         Arrays.sort(arr, loadObjectComparator);
 513         return Arrays.asList(arr);
 514     }
 515 
 516     private long lookupByName(String objectName, String symbolName)
 517     throws DebuggerException {
 518         // NOTE: this assumes that process is suspended (which is probably
 519         // necessary assumption given that DSOs can be loaded/unloaded as
 520         // process runs). Should update documentation.
 521         if (nameToDsoMap == null) {
 522             getLoadObjectList();
 523         }
 524         SharedObject dso = (SharedObject) nameToDsoMap.get(objectName);
 525         // The DSO can be null because we use this to search through known
 526         // DSOs in HotSpotTypeDataBase (for example)
 527         if (dso != null) {
 528             ProcAddress addr = (ProcAddress) dso.lookupSymbol(symbolName);
 529             if (addr != null) {
 530                 return addr.getValue();
 531             }
 532         }
 533         return 0;
 534     }
 535 
 536     private SharedObject findDSOByName(String fullPathName) {
 537         if (loadObjectCache == null)
 538             return null;
 539         for (Iterator iter = loadObjectCache.iterator(); iter.hasNext(); ) {
 540             SharedObject dso = (SharedObject) iter.next();
 541             if (dso.getName().equals(fullPathName)) {
 542                 return dso;
 543             }
 544         }
 545         return null;
 546     }
 547 
 548     private void reresolveLoadObjects() throws DebuggerException {
 549         if (loadObjectCache == null) {
 550             return;
 551         }
 552         updateLoadObjectCache();
 553     }
 554 
 555 
 556     private void checkAttached() {
 557         if (attached) {
 558             if (isCore) {
 559                 throw new DebuggerException("already attached to a core file!");
 560             } else {
 561                 throw new DebuggerException("already attached to a process!");
 562             }
 563         }
 564     }
 565 
 566     private void requireAttach() {
 567         if (! attached) {
 568             throw new RuntimeException("not attached to a process or core file!");
 569         }
 570     }
 571 
 572     private void clearCacheFields() {
 573         loadObjectCache = null;
 574         nameToDsoMap    = null;
 575         threadListCache = null;
 576         topFrameCache   = null;
 577     }
 578 
 579     private void resetNativePointers() {
 580         p_ps_prochandle          = 0L;
 581 
 582         // reset thread_db pointers
 583         libthread_db_handle    = 0L;
 584         p_td_thragent_t        = 0L;
 585         p_td_init              = 0L;
 586         p_td_ta_new            = 0L;
 587         p_td_ta_delete         = 0L;
 588         p_td_ta_thr_iter       = 0L;
 589         p_td_thr_get_info      = 0L;
 590         p_td_ta_map_id2thr     = 0L;
 591         p_td_thr_getgregs      = 0L;
 592 
 593         // part of class sharing workaround
 594         classes_jsa_fd         = -1;
 595         p_file_map_header      = 0L;
 596     }
 597 
 598     // native methods and native helpers
 599 
 600     // attach, detach
 601     private native void attach0(String pid) throws DebuggerException;
 602     private native void attach0(String executableFile, String coreFileName) throws DebuggerException;
 603     private native void detach0() throws DebuggerException;
 604 
 605     // address size, page size
 606     private native int getRemoteProcessAddressSize0() throws DebuggerException;
 607     private native int getPageSize0() throws DebuggerException;
 608 
 609     // threads, stacks
 610     private native long[] getThreadIntegerRegisterSet0(long tid) throws DebuggerException;
 611     private native void   fillThreadList0(List l) throws DebuggerException;
 612 
 613     // fills stack frame list given reg set of the top frame and top frame
 614     private native ProcCFrame fillCFrameList0(long[] regs) throws DebuggerException;
 615 
 616     // helper called by fillCFrameList0
 617     private ProcCFrame createSenderFrame(ProcCFrame f, long pc, long fp) {
 618         ProcCFrame sender = new ProcCFrame(this, newAddress(pc), newAddress(fp));
 619         if (f != null) {
 620             f.setSender(sender);
 621         }
 622         return sender;
 623     }
 624 
 625     // shared objects
 626     private native void fillLoadObjectList0(List l) throws DebuggerException;
 627 
 628     // helper called by fillLoadObjectList0
 629     private LoadObject createLoadObject(String fileName, long textsize, long base) {
 630         File f = new File(fileName);
 631         Address baseAddr = newAddress(base);
 632         SharedObject res = findDSOByName(fileName);
 633         if (res != null) {
 634             // already in cache. just change the base, if needed
 635             Address oldBase = res.getBase();
 636             if (! baseAddr.equals(oldBase)) {
 637                 res.setBase(baseAddr);
 638             }
 639         } else {
 640             // new shared object.
 641             res = new SharedObject(this, fileName, f.length(), baseAddr);
 642         }
 643         nameToDsoMap.put(f.getName(), res);
 644         return res;
 645     }
 646 
 647     // symbol-to-pc
 648     private native long lookupByName0(String objectName, String symbolName) throws DebuggerException;
 649     private native ClosestSymbol lookupByAddress0(long address) throws DebuggerException;
 650 
 651     // helper called by lookupByAddress0
 652     private ClosestSymbol createClosestSymbol(String name, long offset) {
 653         return new ClosestSymbol(name, offset);
 654     }
 655 
 656     // process read/write
 657     private native byte[] readBytesFromProcess0(long address, long numBytes) throws DebuggerException;
 658     private native void writeBytesToProcess0(long address, long numBytes, byte[] data) throws DebuggerException;
 659 
 660     // process control
 661     private native void suspend0() throws DebuggerException;
 662     private native void resume0() throws DebuggerException;
 663 
 664     // demangle a C++ name
 665     private native String demangle0(String name);
 666 
 667     // init JNI ids to fields, methods
 668     private native static void initIDs() throws DebuggerException;
 669     private static LoadObjectComparator loadObjectComparator;
 670 
 671     static {
 672         System.loadLibrary("saproc");
 673         initIDs();
 674         loadObjectComparator = new LoadObjectComparator();
 675     }
 676 
 677     private boolean unalignedAccessesOkay;
 678     private ProcThreadFactory threadFactory;
 679 
 680     // indices of PC and FP registers in gregset
 681     private int pcRegIndex;
 682     private int fpRegIndex;
 683 
 684     // Symbol lookup support
 685     // This is a map of library names to DSOs
 686     private Map nameToDsoMap;  // Map<String, SharedObject>
 687 
 688     // C/C++ debugging support
 689     private List/*<LoadObject>*/ loadObjects;
 690     private CDebugger cdbg;
 691 
 692     // ProcessControl support
 693     private boolean suspended;
 694 
 695     // libproc handle
 696     private long p_ps_prochandle;
 697 
 698     // libthread.so's dlopen handle, thread agent
 699     // and function pointers
 700     private long libthread_db_handle;
 701     private long p_td_thragent_t;
 702     private long p_td_init;
 703     private long p_td_ta_new;
 704     private long p_td_ta_delete;
 705     private long p_td_ta_thr_iter;
 706     private long p_td_thr_get_info;
 707     private long p_td_ta_map_id2thr;
 708     private long p_td_thr_getgregs;
 709 
 710     // part of class sharing workaround
 711     private int classes_jsa_fd;
 712     private long p_file_map_header;
 713 
 714     private boolean attached = false;
 715     private boolean isCore;
 716 
 717     // for core files, we cache load object list, thread list, top frames etc.
 718     // for processes we cache load object list and sync. it during suspend.
 719     private List threadListCache;
 720     private List loadObjectCache;
 721     private Map  topFrameCache;      // Map<ThreadProxy, CFrame>
 722 }