示例#1
0
 public Object[] getIds() {
   Object[] superIds = super.getIds();
   Object[] tmp = fields.keySet().toArray();
   Object[] res = new Object[superIds.length + tmp.length];
   System.arraycopy(tmp, 0, res, 0, tmp.length);
   System.arraycopy(superIds, 0, res, tmp.length, superIds.length);
   return res;
 }
示例#2
0
 private void usage() {
   System.out.println("usage: java " + getClass().getName() + " <pid> [server id]");
   System.out.println("   or: java " + getClass().getName() + " <executable> <core> [server id]");
   System.out.println("\"pid\" must be the process ID of a HotSpot process.");
   System.out.println("If reading a core file, \"executable\" must (currently) be the");
   System.out.println("full path name to the precise java executable which generated");
   System.out.println("the core file (not, on Solaris, the \"java\" wrapper script in");
   System.out.println("the \"bin\" subdirectory of the JDK.)");
   System.out.println("The \"server id\" is a unique name for a specific remote debuggee.");
   System.exit(1);
 }
示例#3
0
  private void run(String[] args) {
    if ((args.length < 1) || (args.length > 3)) {
      usage();
    }

    // Attempt to handle "-h" or "-help"
    if (args[0].startsWith("-")) {
      usage();
    }

    int pid = 0;
    boolean usePid = false;
    String coreFileName = null;
    // FIXME: would be nice to pick this up from the core file
    // somehow, but that doesn't look possible. Should at least figure
    // it out from a path to the JDK.
    String javaExecutableName = null;
    String serverID = null;

    switch (args.length) {
      case 1:
        try {
          pid = Integer.parseInt(args[0]);
          usePid = true;
        } catch (NumberFormatException e) {
          usage();
        }
        break;

      case 2:
        // either we have pid and server id or exec file and core file
        try {
          pid = Integer.parseInt(args[0]);
          usePid = true;
          serverID = args[1];
        } catch (NumberFormatException e) {
          pid = -1;
          usePid = false;
          javaExecutableName = args[0];
          coreFileName = args[1];
        }
        break;

      case 3:
        javaExecutableName = args[0];
        coreFileName = args[1];
        serverID = args[2];
        break;

      default:
        // should not happend, taken care already.
        break;
    }

    final HotSpotAgent agent = new HotSpotAgent();
    try {
      if (usePid) {
        System.err.println(
            "Attaching to process ID " + pid + " and starting RMI services, please wait...");
        agent.startServer(pid, serverID);
      } else {
        System.err.println(
            "Attaching to core "
                + coreFileName
                + " from executable "
                + javaExecutableName
                + " and starting RMI services, please wait...");
        agent.startServer(javaExecutableName, coreFileName, serverID);
      }
    } catch (DebuggerException e) {
      if (usePid) {
        System.err.print("Error attaching to process or starting server: ");
      } else {
        System.err.print("Error attaching to core file or starting server: ");
      }
      e.printStackTrace();
      System.exit(1);
    }

    // shutdown hook to clean-up the server in case of forced exit.
    Runtime.getRuntime()
        .addShutdownHook(
            new java.lang.Thread(
                new Runnable() {
                  public void run() {
                    agent.shutdownServer();
                  }
                }));
    System.err.println("Debugger attached and RMI services started.");
  }
/**
 * Should be able to be used on all amd64 platforms we support (Linux/amd64) to implement
 * JavaThread's "currentFrameGuess()" functionality. Input is an AMD64ThreadContext; output is SP,
 * FP, and PC for an AMD64Frame. Instantiation of the AMD64Frame is left to the caller, since we may
 * need to subclass AMD64Frame to support signal handler frames on Unix platforms.
 *
 * <p>Algorithm is to walk up the stack within a given range (say, 512K at most) looking for a
 * plausible PC and SP for a Java frame, also considering those coming in from the context. If we
 * find a PC that belongs to the VM (i.e., in generated code like the interpreter or CodeCache) then
 * we try to find an associated EBP. We repeat this until we either find a complete frame or run out
 * of stack to look at.
 */
public class AMD64CurrentFrameGuess {
  private AMD64ThreadContext context;
  private JavaThread thread;
  private Address spFound;
  private Address fpFound;
  private Address pcFound;

  private static final boolean DEBUG =
      System.getProperty("sun.jvm.hotspot.runtime.amd64.AMD64Frame.DEBUG") != null;

  public AMD64CurrentFrameGuess(AMD64ThreadContext context, JavaThread thread) {
    this.context = context;
    this.thread = thread;
  }

  /** 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 Address getSP() {
    return spFound;
  }

  public Address getFP() {
    return fpFound;
  }
  /**
   * May be null if getting values from thread-local storage; take care to call the correct
   * AMD64Frame constructor to recover this if necessary
   */
  public Address getPC() {
    return pcFound;
  }

  private void setValues(Address sp, Address fp, Address pc) {
    spFound = sp;
    fpFound = fp;
    pcFound = pc;
  }
}