private HeapRegion at(long index) { Address arrayAddr = regionsField.getValue(addr); // Offset of &_region[index] long offset = index * VM.getVM().getAddressSize(); Address regionAddr = arrayAddr.getAddressAt(offset); return (HeapRegion) VMObjectFactory.newObject(HeapRegion.class, regionAddr); }
public OopHandle getOopHandle(int x) { Address oopAddr = getOopHandleAddress(x); if (oopAddr != null) { return oopAddr.getOopHandleAt(0); } return null; }
/** * Debugging routine: returns the index (0..top() - 1) of the handle in this block, or -1 if the * handle was not contained in this block. Does not search successor blocks. */ public int indexOfHandle(Address jniHandle) { for (int i = 0; i < top(); i++) { Address addr = getOopHandleAddress(i); if (addr != null) { if (addr.equals(jniHandle)) { return i; } } } return -1; }
public ThreadProxy getThreadProxy(Address addr) { // Addr is the address of the JavaThread. // Fetch the OSThread (for now and for simplicity, not making a // separate "OSThread" class in this package) Address osThreadAddr = osThreadField.getValue(addr); // Get the address of the _thread_id from the OSThread Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset()); JVMDebugger debugger = VM.getVM().getDebugger(); return debugger.getThreadForIdentifierAddress(threadIdAddr); }
void setValue(String value) throws DebuggerException { try { byte[] data = value.getBytes("US-ASCII"); if (data.length >= bufLen) { throw new DebuggerException("String too long"); } for (int i = 0; i < data.length; i++) { addr.setCIntegerAt(i, 1, data[i]); } addr.setCIntegerAt(data.length, 1, 0); } catch (UnsupportedEncodingException e) { throw new DebuggerException("Unable to use US-ASCII encoding"); } }
String getValue() throws DebuggerException { int len = 0; while ((addr.getCIntegerAt(len, 1, true) != 0) && (len < bufLen)) { ++len; } byte[] res = new byte[len]; for (int i = 0; i < len; i++) { res[i] = (byte) addr.getCIntegerAt(i, 1, true); } try { return new String(res, "US-ASCII"); } catch (UnsupportedEncodingException e) { throw new DebuggerException("Unable to use US-ASCII encoding"); } }
public CFrame sender() { if (ebp == null) { return null; } Address nextEBP = ebp.getAddressAt(0 * ADDRESS_SIZE); if (nextEBP == null) { return null; } Address nextPC = ebp.getAddressAt(1 * ADDRESS_SIZE); if (nextPC == null) { return null; } return new X86CFrame(dbg(), nextEBP, nextPC); }
/** Only returns addresses of valid OopHandles */ private Address getOopHandleAddress(int x) { if (Assert.ASSERTS_ENABLED) { Assert.that(x < top(), "out of bounds"); } Address oopAddr = addr.addOffsetTo(handlesField.getOffset() + x * VM.getVM().getOopSize()); OopHandle handle = oopAddr.getOopHandleAt(0); if (VM.getVM().getUniverse().isInReserved(handle) && !VM.getVM().getJNIHandles().isDeletedHandle(handle)) { /* the oop handle is valid only if it is not freed (i.e. reserved in heap) and is not a deleted oop */ return oopAddr; } else { return null; } }
public LoadObject loadObjectContainingPC(Address pc) throws DebuggerException { if (pc == null) { return null; } List objs = getLoadObjectList(); Object[] arr = objs.toArray(); // load objects are sorted by base address, do binary search int mid = -1; int low = 0; int high = arr.length - 1; while (low <= high) { mid = (low + high) >> 1; LoadObject midVal = (LoadObject) arr[mid]; long cmp = pc.minus(midVal.getBase()); if (cmp < 0) { high = mid - 1; } else if (cmp > 0) { long size = midVal.getSize(); if (cmp >= size) { low = mid + 1; } else { return (LoadObject) arr[mid]; } } else { // match found return (LoadObject) arr[mid]; } } // no match found. return null; }
public void visitCompOopAddress(Address addr) { Oop next = heap.newOop(addr.getCompOopHandleAt(0)); LivenessPathElement lp = new LivenessPathElement( null, new NamedFieldIdentifier(baseRootDescription + " @ " + addr)); rp.put(lp, next); markAndTraverse(next); }
public DbxSPARCThread(DbxDebugger debugger, Address addr) { this.debugger = debugger; // FIXME: the size here should be configurable. However, making it // so would produce a dependency on the "types" package from the // debugger package, which is not desired. this.id = (int) addr.getCIntegerAt(0, 4, true); }
private String addressToString(Address a) { if (a == null) { if (is64Bit) { return "0x0000000000000000"; } else { return "0x00000000"; } } return a.toString(); }
// refer to Threads::owning_thread_from_monitor_owner public JavaThread owningThreadFromMonitor(Address o) { if (o == null) return null; for (JavaThread thread = first(); thread != null; thread = thread.next()) { if (o.equals(thread.threadObjectAddress())) { return thread; } } for (JavaThread thread = first(); thread != null; thread = thread.next()) { if (thread.isLockOwned(o)) return thread; } return null; }
/** Returns false if not able to find a frame within a reasonable range. */ public boolean run(long regionInBytesToSearch) { Address sp = context.getRegisterAsAddress(AMD64ThreadContext.RSP); Address pc = context.getRegisterAsAddress(AMD64ThreadContext.RIP); Address fp = context.getRegisterAsAddress(AMD64ThreadContext.RBP); if (sp == null) { // Bail out if no last java frame either if (thread.getLastJavaSP() != null) { setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null); return true; } return false; } Address end = sp.addOffsetTo(regionInBytesToSearch); VM vm = VM.getVM(); setValues(null, null, null); // Assume we're not going to find anything if (vm.isJavaPCDbg(pc)) { if (vm.isClientCompiler()) { // If the topmost frame is a Java frame, we are (pretty much) // guaranteed to have a viable EBP. We should be more robust // than this (we have the potential for losing entire threads' // stack traces) but need to see how much work we really have // to do here. Searching the stack for an (SP, FP) pair is // hard since it's easy to misinterpret inter-frame stack // pointers as base-of-frame pointers; we also don't know the // sizes of C1 frames (not registered in the nmethod) so can't // derive them from ESP. setValues(sp, fp, pc); return true; } else { if (vm.getInterpreter().contains(pc)) { if (DEBUG) { System.out.println( "CurrentFrameGuess: choosing interpreter frame: sp = " + sp + ", fp = " + fp + ", pc = " + pc); } setValues(sp, fp, pc); return true; } // For the server compiler, EBP is not guaranteed to be valid // for compiled code. In addition, an earlier attempt at a // non-searching algorithm (see below) failed because the // stack pointer from the thread context was pointing // (considerably) beyond the ostensible end of the stack, into // garbage; walking from the topmost frame back caused a crash. // // This algorithm takes the current PC as a given and tries to // find the correct corresponding SP by walking up the stack // and repeatedly performing stackwalks (very inefficient). // // FIXME: there is something wrong with stackwalking across // adapter frames...this is likely to be the root cause of the // failure with the simpler algorithm below. for (long offset = 0; offset < regionInBytesToSearch; offset += vm.getAddressSize()) { try { Address curSP = sp.addOffsetTo(offset); Frame frame = new X86Frame(curSP, null, pc); RegisterMap map = thread.newRegisterMap(false); while (frame != null) { if (frame.isEntryFrame() && frame.entryFrameIsFirst()) { // We were able to traverse all the way to the // bottommost Java frame. // This sp looks good. Keep it. if (DEBUG) { System.out.println("CurrentFrameGuess: Choosing sp = " + curSP + ", pc = " + pc); } setValues(curSP, null, pc); return true; } frame = frame.sender(map); } } catch (Exception e) { if (DEBUG) { System.out.println("CurrentFrameGuess: Exception " + e + " at offset " + offset); } // Bad SP. Try another. } } // Were not able to find a plausible SP to go with this PC. // Bail out. return false; /* // Original algorithm which does not work because SP was // pointing beyond where it should have: // For the server compiler, EBP is not guaranteed to be valid // for compiled code. We see whether the PC is in the // interpreter and take care of that, otherwise we run code // (unfortunately) duplicated from AMD64Frame.senderForCompiledFrame. CodeCache cc = vm.getCodeCache(); if (cc.contains(pc)) { CodeBlob cb = cc.findBlob(pc); // See if we can derive a frame pointer from SP and PC // NOTE: This is the code duplicated from AMD64Frame Address saved_fp = null; int llink_offset = cb.getLinkOffset(); if (llink_offset >= 0) { // Restore base-pointer, since next frame might be an interpreter frame. Address fp_addr = sp.addOffsetTo(VM.getVM().getAddressSize() * llink_offset); saved_fp = fp_addr.getAddressAt(0); } setValues(sp, saved_fp, pc); return true; } */ } } else { // If the current program counter was not known to us as a Java // PC, we currently assume that we are in the run-time system // and attempt to look to thread-local storage for saved ESP and // EBP. Note that if these are null (because we were, in fact, // in Java code, i.e., vtable stubs or similar, and the SA // didn't have enough insight into the target VM to understand // that) then we are going to lose the entire stack trace for // the thread, which is sub-optimal. FIXME. if (DEBUG) { System.out.println( "CurrentFrameGuess: choosing last Java frame: sp = " + thread.getLastJavaSP() + ", fp = " + thread.getLastJavaFP()); } if (thread.getLastJavaSP() == null) { return false; // No known Java frames on stack } setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null); return true; } }
public int regEncode() { if (matcherRegEncodeAddr != null) { return (int) matcherRegEncodeAddr.getCIntegerAt(value, 1, true); } return value; }
public void set_map(Address addr) { for (int i = 0; i < sizeInWords(); i++) { data[i] = (int) addr.getCIntegerAt(0, bytesPerWord, true); addr = addr.addOffsetTo(bytesPerWord); } }
public Address getLastJavaFP(Address addr) { return lastJavaFPField.getValue( addr.addOffsetTo(sun.jvm.hotspot.runtime.JavaThread.getAnchorField().getOffset())); }