sa-jdi

  
  private static String formatMessage(String message, int charsPerLine)
  {
    StringBuffer buf = new StringBuffer(message.length());
    StringTokenizer tokenizer = new StringTokenizer(message);
    int curLineLength = 0;
    while (tokenizer.hasMoreTokens())
    {
      String tok = tokenizer.nextToken();
      if (curLineLength + tok.length() > charsPerLine)
      {
        buf.append('\n');
        curLineLength = 0;
      }
      else if (curLineLength != 0)
      {
        buf.append(' ');
        curLineLength++;
      }
      buf.append(tok);
      curLineLength += tok.length();
    }
    return buf.toString();
  }
  
  private void setMenuItemsEnabled(List items, boolean enabled)
  {
    for (Iterator iter = items.iterator(); iter.hasNext();) {
      ((JMenuItem)iter.next()).setEnabled(enabled);
    }
  }
  
  private void showMessageDialog(final String message, final String title, final int jOptionPaneKind)
  {
    SwingUtilities.invokeLater(new Runnable()
    {
      public void run()
      {
        if (mdiMode) {
          JOptionPane.showInternalMessageDialog(desktop, message, title, jOptionPaneKind);
        } else {
          JOptionPane.showMessageDialog(null, message, title, jOptionPaneKind);
        }
      }
    });
  }
  
  private FrameWrapper newFrame(String title)
  {
    if (mdiMode) {
      return new JInternalFrameWrapper(new JInternalFrame(title));
    }
    return new JFrameWrapper(new JFrame(title));
  }
  
  private void addFrame(FrameWrapper frame)
  {
    if (mdiMode) {
      desktop.add(frame.getComponent());
    }
  }
  
  private void removeFrame(FrameWrapper frame)
  {
    if (mdiMode)
    {
      desktop.remove(frame.getComponent());
      desktop.invalidate();
      desktop.validate();
      desktop.repaint();
    }
  }
  
  private Dimension getParentDimension(Component c)
  {
    if (mdiMode) {
      return desktop.getSize();
    }
    return Toolkit.getDefaultToolkit().getScreenSize();
  }
  
  class DefaultEditor
    implements Editor
  {
    private BugSpot.DefaultEditorFactory factory;
    private FrameWrapper editorFrame;
    private String filename;
    private SourceCodePanel code;
    private boolean shown;
    private Object userData;
    
    public DefaultEditor(BugSpot.DefaultEditorFactory fact, String filename, final EditorCommands comm)
    {
      this.filename = filename;
      factory = fact;
      editorFrame = BugSpot.this.newFrame(filename);
      code = new SourceCodePanel();
      
      code.setFont(fixedWidthFont);
      editorFrame.getContentPane().add(code);
      editorFrame.setClosable(true);
      editorFrame.setResizable(true);
      editorFrame.setClosingActionListener(new ActionListener()
      {
        public void actionPerformed(ActionEvent e)
        {
          comm.windowClosed(BugSpot.DefaultEditor.this);
          BugSpot.this.removeFrame(editorFrame);
          editorFrame.dispose();
          factory.editorClosed(BugSpot.DefaultEditor.this);
        }
      });
      editorFrame.setActivatedActionListener(new ActionListener()
      {
        public void actionPerformed(ActionEvent e)
        {
          factory.makeEditorCurrent(BugSpot.DefaultEditor.this);
          code.requestFocus();
        }
      });
      code.setEditorCommands(comm, this);
    }
    
    public boolean openFile()
    {
      return code.openFile(filename);
    }
    
    public String getSourceFileName()
    {
      return filename;
    }
    
    public int getCurrentLineNumber()
    {
      return code.getCurrentLineNumber();
    }
    
    public void showLineNumber(int lineNo)
    {
      if (!shown)
      {
        BugSpot.this.addFrame(editorFrame);
        GraphicsUtilities.reshapeToAspectRatio(editorFrame.getComponent(), 1.0F, 0.85F, BugSpot.this.getParentDimension(editorFrame.getComponent()));
        
        editorFrame.setVisible(true);
        shown = true;
      }
      code.showLineNumber(lineNo);
      editorFrame.toFront();
    }
    
    public void highlightLineNumber(int lineNo)
    {
      code.highlightLineNumber(lineNo);
    }
    
    public void showBreakpointAtLine(int lineNo)
    {
      code.showBreakpointAtLine(lineNo);
    }
    
    public boolean hasBreakpointAtLine(int lineNo)
    {
      return code.hasBreakpointAtLine(lineNo);
    }
    
    public void clearBreakpointAtLine(int lineNo)
    {
      code.clearBreakpointAtLine(lineNo);
    }
    
    public void clearBreakpoints()
    {
      code.clearBreakpoints();
    }
    
    public void setUserData(Object o)
    {
      userData = o;
    }
    
    public Object getUserData()
    {
      return userData;
    }
    
    public void toFront()
    {
      editorFrame.toFront();
      factory.makeEditorCurrent(this);
    }
  }
  
  class DefaultEditorFactory
    implements EditorFactory
  {
    private LinkedList editors = new LinkedList();
    
    DefaultEditorFactory() {}
    
    public Editor openFile(String filename, EditorCommands commands)
    {
      BugSpot.DefaultEditor editor = new BugSpot.DefaultEditor(BugSpot.this, this, filename, editorComm);
      if (!editor.openFile()) {
        return null;
      }
      return editor;
    }
    
    public Editor getCurrentEditor()
    {
      if (editors.isEmpty()) {
        return null;
      }
      return (Editor)editors.getFirst();
    }
    
    void editorClosed(Editor editor)
    {
      editors.remove(editor);
    }
    
    void makeEditorCurrent(Editor editor)
    {
      editors.remove(editor);
      editors.addFirst(editor);
    }
  }
  
  static class JavaFileFilter
    extends FileFilter
  {
    private String packageName;
    private String fileName;
    
    JavaFileFilter(String packageName, String fileName)
    {
      this.packageName = packageName;
      this.fileName = fileName;
    }
    
    public boolean accept(File f)
    {
      if (f.isDirectory()) {
        return true;
      }
      if (!f.getName().equals(fileName)) {
        return false;
      }
      PackageScanner scanner = new PackageScanner();
      String pkg = scanner.scan(f);
      if (!pkg.equals(packageName)) {
        return false;
      }
      return true;
    }
    
    public String getDescription()
    {
      return "Java source files";
    }
  }
  
  static class JavaUserData
  {
    private String packageName;
    private String sourceFileName;
    
    JavaUserData(String packageName, String sourceFileName)
    {
      this.packageName = packageName;
      this.sourceFileName = sourceFileName;
    }
    
    String packageName()
    {
      return packageName;
    }
    
    String sourceFileName()
    {
      return sourceFileName;
    }
  }
  
  private void openSourceFile()
  {
    JFileChooser chooser = new JFileChooser();
    chooser.setDialogTitle("Open source code file");
    chooser.setMultiSelectionEnabled(false);
    if (chooser.showOpenDialog(null) != 0) {
      return;
    }
    File chosen = chooser.getSelectedFile();
    if (chosen == null) {
      return;
    }
    String path = chosen.getPath();
    String name = null;
    JavaUserData data = null;
    if (path.endsWith(".java"))
    {
      PackageScanner scanner = new PackageScanner();
      String pkg = scanner.scan(chosen);
      
      String fileName = chosen.getName();
      name = pkg + "." + fileName;
      data = new JavaUserData(pkg, fileName);
    }
    else
    {
      name = path;
    }
    Editor editor = (Editor)editors.get(name);
    if (editor == null)
    {
      editor = editorFact.openFile(path, editorComm);
      if (editor == null)
      {
        showMessageDialog("Unable to open file \"" + path + "\" -- unexpected error.", "Unable to open file", 2);
        
        return;
      }
      editors.put(name, editor);
      if (data != null) {
        editor.setUserData(data);
      }
    }
    else
    {
      editor.toFront();
    }
    editor.showLineNumber(1);
    
    Set set = (Set)fileToBreakpointMap.get(editor.getSourceFileName());
    Iterator iter;
    if (set != null) {
      for (iter = set.iterator(); iter.hasNext();) {
        editor.showBreakpointAtLine(((Integer)iter.next()).intValue());
      }
    }
  }
  
  private void showLineNumber(String packageName, String fileName, int lineNumber)
  {
    String name;
    String name;
    if (packageName == null) {
      name = fileName;
    } else {
      name = packageName + "." + fileName;
    }
    Editor editor = (Editor)editors.get(name);
    if (editor == null)
    {
      File file = new File(fileName);
      String realFileName = fileName;
      if (!file.exists())
      {
        JFileChooser chooser = new JFileChooser();
        chooser.setDialogTitle("Please locate " + fileName);
        chooser.setMultiSelectionEnabled(false);
        if (packageName != null) {
          chooser.setFileFilter(new JavaFileFilter(packageName, fileName));
        }
        int res = chooser.showOpenDialog(null);
        if (res != 0) {
          return;
        }
        File chosen = chooser.getSelectedFile();
        if (chosen == null) {
          return;
        }
        realFileName = chosen.getPath();
      }
      editor = editorFact.openFile(realFileName, editorComm);
      if (editor == null)
      {
        showMessageDialog("Unable to open file \"" + realFileName + "\" -- unexpected error.", "Unable to open file", 2);
        
        return;
      }
      editors.put(name, editor);
      if (packageName != null) {
        editor.setUserData(new JavaUserData(packageName, fileName));
      }
    }
    editor.showLineNumber(lineNumber);
    editor.highlightLineNumber(lineNumber);
    
    Set set = (Set)fileToBreakpointMap.get(editor.getSourceFileName());
    Iterator iter;
    if (set != null) {
      for (iter = set.iterator(); iter.hasNext();) {
        editor.showBreakpointAtLine(((Integer)iter.next()).intValue());
      }
    }
  }
  
  private boolean isSuspended()
  {
    return suspended;
  }
  
  private synchronized void suspend()
  {
    setMenuItemsEnabled(resumeDebugMenuItems, true);
    setMenuItemsEnabled(suspendDebugMenuItems, false);
    BugSpotAgent agent = getAgent();
    if ((agent.canInteractWithJava()) && (!agent.isJavaSuspended())) {
      agent.suspendJava();
    }
    agent.suspend();
    
    resetCurrentThread();
    debugEventTimer.stop();
    suspended = true;
  }
  
  private synchronized void resume()
  {
    threadToJavaThreadMap = null;
    setMenuItemsEnabled(resumeDebugMenuItems, false);
    setMenuItemsEnabled(suspendDebugMenuItems, true);
    registerPanel.clear();
    
    BugSpotAgent agent = getAgent();
    agent.resume();
    if (agent.canInteractWithJava())
    {
      if (agent.isJavaSuspended()) {
        agent.resumeJava();
      }
      if (javaEventPending)
      {
        javaEventPending = false;
        
        agent.javaEventContinue();
      }
    }
    agent.enableJavaInteraction();
    suspended = false;
    debugEventTimer.start();
  }
  
  private synchronized BreakpointResult handleBreakpointToggle(Editor editor, int lineNumber)
  {
    JavaUserData data = (JavaUserData)editor.getUserData();
    String filename = editor.getSourceFileName();
    BreakpointResult localBreakpointResult;
    if (data == null)
    {
      CDebugger dbg = getCDebugger();
      ProcessControl prctl = dbg.getProcessControl();
      if (prctl == null) {
        return new BreakpointResult(false, false, 0, "Process control not enabled");
      }
      boolean mustSuspendAndResume = !prctl.isSuspended();
      try
      {
        if (mustSuspendAndResume) {
          prctl.suspend();
        }
        LineNumberInfo info = getLineNumberInfo(filename, lineNumber);
        Set bpset;
        if (info != null)
        {
          bpset = (Set)fileToBreakpointMap.get(filename);
          if (bpset == null)
          {
            bpset = new HashSet();
            fileToBreakpointMap.put(filename, bpset);
          }
          Integer key = new Integer(info.getLineNumber());
          if (bpset.contains(key))
          {
            prctl.clearBreakpoint(info.getStartPC());
            bpset.remove(key);
            return new BreakpointResult(true, false, info.getLineNumber());
          }
          System.err.println("Setting breakpoint at PC " + info.getStartPC());
          prctl.setBreakpoint(info.getStartPC());
          bpset.add(key);
          return new BreakpointResult(true, true, info.getLineNumber());
        }
        return new BreakpointResult(false, false, 0, "No debug information for this source file and line");
      }
      finally
      {
        if (mustSuspendAndResume) {
          prctl.resume();
        }
      }
    }
    BugSpotAgent agent = getAgent();
    if (!agent.canInteractWithJava())
    {
      String why;
      String why;
      if (agent.isJavaInteractionDisabled()) {
        why = "Can not toggle Java breakpoints while stopped because\nof C/C++ debug events (breakpoints, single-stepping)";
      } else {
        why = "Could not talk to SA's JVMDI module to enable Java\nprogramming language breakpoints (run with -Xdebug -Xrunsa)";
      }
      return new BreakpointResult(false, false, 0, why);
    }
    Set bpset = (Set)fileToBreakpointMap.get(filename);
    if (bpset == null)
    {
      bpset = new HashSet();
      fileToBreakpointMap.put(filename, bpset);
    }
    boolean mustResumeAndSuspend = isSuspended();
    try
    {
      if (mustResumeAndSuspend) {
        agent.resume();
      }
      ServiceabilityAgentJVMDIModule.BreakpointToggleResult res = getAgent().toggleJavaBreakpoint(data.sourceFileName(), data.packageName(), lineNumber);
      Integer key;
      if (res.getSuccess())
      {
        key = new Integer(res.getLineNumber());
        boolean addRemRes = false;
        if (res.getWasSet())
        {
          addRemRes = bpset.add(key);
          System.err.println("Setting breakpoint at " + res.getMethodName() + res.getMethodSignature() + ", bci " + res.getBCI() + ", line " + res.getLineNumber());
        }
        else
        {
          addRemRes = bpset.remove(key);
          System.err.println("Clearing breakpoint at " + res.getMethodName() + res.getMethodSignature() + ", bci " + res.getBCI() + ", line " + res.getLineNumber());
        }
        if (Assert.ASSERTS_ENABLED) {
          Assert.that(addRemRes, "Inconsistent Java breakpoint state with respect to target process");
        }
        return new BreakpointResult(true, res.getWasSet(), res.getLineNumber());
      }
      return new BreakpointResult(false, false, 0, res.getErrMsg());
    }
    finally
    {
      if (mustResumeAndSuspend)
      {
        agent.suspend();
        resetCurrentThread();
      }
    }
  }
  
  private LineNumberInfo getLineNumberInfo(String filename, int lineNumber)
  {
    Map map = getSourceFileToLineNumberInfoMap();
    List infos = (List)map.get(filename);
    if (infos == null) {
      return null;
    }
    return searchLineNumbers(infos, lineNumber, 0, infos.size());
  }
  
  private Map getSourceFileToLineNumberInfoMap()
  {
    if (sourceFileToLineNumberInfoMap == null)
    {
      List loadObjects = getCDebugger().getLoadObjectList();
      final Map map = new HashMap();
      for (Iterator iter = loadObjects.iterator(); iter.hasNext();)
      {
        LoadObject lo = (LoadObject)iter.next();
        CDebugInfoDataBase db = lo.getDebugInfoDataBase();
        if (db != null) {
          db.iterate(new LineNumberVisitor()
          {
            public void doLineNumber(LineNumberInfo info)
            {
              String name = info.getSourceFileName();
              if (name != null)
              {
                List val = (List)map.get(name);
                if (val == null)
                {
                  val = new ArrayList();
                  map.put(name, val);
                }
                val.add(info);
              }
            }
          });
        }
      }
      for (Iterator iter = map.values().iterator(); iter.hasNext();)
      {
        List list = (List)iter.next();
        Collections.sort(list, new Comparator()
        {
          public int compare(Object o1, Object o2)
          {
            LineNumberInfo l1 = (LineNumberInfo)o1;
            LineNumberInfo l2 = (LineNumberInfo)o2;
            int n1 = l1.getLineNumber();
            int n2 = l2.getLineNumber();
            if (n1 < n2) {
              return -1;
            }
            if (n1 == n2) {
              return 0;
            }
            return 1;
          }
        });
      }
      sourceFileToLineNumberInfoMap = map;
    }
    return sourceFileToLineNumberInfoMap;
  }
  
  private LineNumberInfo searchLineNumbers(List infoList, int lineNo, int lowIdx, int highIdx)
  {
    if (highIdx < lowIdx) {
      return null;
    }
    if (lowIdx == highIdx)
    {
      if (checkLineNumber(infoList, lineNo, lowIdx)) {
        return (LineNumberInfo)infoList.get(lowIdx);
      }
      return null;
    }
    if (lowIdx == highIdx - 1)
    {
      if (checkLineNumber(infoList, lineNo, lowIdx)) {
        return (LineNumberInfo)infoList.get(lowIdx);
      }
      if (checkLineNumber(infoList, lineNo, highIdx)) {
        return (LineNumberInfo)infoList.get(highIdx);
      }
      return null;
    }
    int midIdx = lowIdx + highIdx >> 1;
    LineNumberInfo info = (LineNumberInfo)infoList.get(midIdx);
    if (lineNo < info.getLineNumber()) {
      return searchLineNumbers(infoList, lineNo, lowIdx, midIdx);
    }
    if (lineNo == info.getLineNumber()) {
      return info;
    }
    return searchLineNumbers(infoList, lineNo, midIdx, highIdx);
  }
  
  private boolean checkLineNumber(List infoList, int lineNo, int idx)
  {
    LineNumberInfo info = (LineNumberInfo)infoList.get(idx);
    return info.getLineNumber() >= lineNo;
  }
  
  private synchronized void pollForDebugEvent()
  {
    ProcessControl prctl = getCDebugger().getProcessControl();
    if (prctl == null) {
      return;
    }
    DebugEvent ev = prctl.debugEventPoll();
    if (ev != null)
    {
      DebugEvent.Type t = ev.getType();
      if ((t == DebugEvent.Type.LOADOBJECT_LOAD) || (t == DebugEvent.Type.LOADOBJECT_UNLOAD))
      {
        sourceFileToLineNumberInfoMap = null;
        
        prctl.debugEventContinue();
      }
      else if (t == DebugEvent.Type.BREAKPOINT)
      {
        showMessageDialog("Breakpoint reached at PC " + ev.getPC(), "Breakpoint reached", 1);
        
        agent.disableJavaInteraction();
        suspend();
        prctl.debugEventContinue();
      }
      else if (t == DebugEvent.Type.SINGLE_STEP)
      {
        agent.disableJavaInteraction();
        suspend();
        prctl.debugEventContinue();
      }
      else if (t == DebugEvent.Type.ACCESS_VIOLATION)
      {
        showMessageDialog("Access violation attempting to " + (ev.getWasWrite() ? "write" : "read") + " address " + ev.getAddress() + " at PC " + ev.getPC(), "Access Violation", 2);
        
        agent.disableJavaInteraction();
        suspend();
        prctl.debugEventContinue();
      }
      else
      {
        String info = "Unknown debug event encountered";
        if (ev.getUnknownEventDetail() != null) {
          info = info + ": " + ev.getUnknownEventDetail();
        }
        showMessageDialog(info, "Unknown debug event", 1);
        suspend();
        prctl.debugEventContinue();
      }
      return;
    }
    if ((getAgent().canInteractWithJava()) && 
      (!javaEventPending) && 
      (getAgent().javaEventPending()))
    {
      suspend();
      
      Event jev = getAgent().javaEventPoll();
      if (jev != null)
      {
        javaEventPending = true;
        if (jev.getType() == Event.Type.BREAKPOINT)
        {
          BreakpointEvent bpev = (BreakpointEvent)jev;
          showMessageDialog("Breakpoint reached in method\n" + bpev.methodID().method().externalNameAndSignature() + ",\nbci " + bpev.location(), "Breakpoint reached", 1);
        }
        else if (jev.getType() == Event.Type.EXCEPTION)
        {
          ExceptionEvent exev = (ExceptionEvent)jev;
          showMessageDialog(exev.exception().getKlass().getName().asString() + "\nthrown in method\n" + exev.methodID().method().externalNameAndSignature() + "\nat BCI " + exev.location(), "Exception thrown", 1);
        }
        else
        {
          Assert.that(false, "Should not reach here");
        }
      }
    }
  }
}

/* Location:
 * Qualified Name:     sun.jvm.hotspot.bugspot.BugSpot
 * Java Class Version: 1.4 (48.0)
 * JD-Core Version:    0.7.1
 */
package sun.jvm.hotspot.bugspot;

final class BugSpotAgent$1
  implements Runnable
{
  private final BugSpotAgent this$0;
  
  BugSpotAgent$1(BugSpotAgent paramBugSpotAgent) {}
  
  public void run()
  {
    synchronized (this$0)
    {
      if (!BugSpotAgent.access$000(this$0)) {
        this$0.detach();
      }
    }
  }
}

/* Location:
 * Qualified Name:     sun.jvm.hotspot.bugspot.BugSpotAgent.1
 * Java Class Version: 1.4 (48.0)
 * JD-Core Version:    0.7.1
 */
package sun.jvm.hotspot.bugspot;

import java.io.PrintStream;
import java.rmi.RemoteException;
import sun.jvm.hotspot.HotSpotSolarisVtblAccess;
import sun.jvm.hotspot.HotSpotTypeDataBase;
import sun.jvm.hotspot.LinuxVtblAccess;
import sun.jvm.hotspot.RMIHelper;
import sun.jvm.hotspot.Win32VtblAccess;
import sun.jvm.hotspot.debugger.Debugger;
import sun.jvm.hotspot.debugger.DebuggerException;
import sun.jvm.hotspot.debugger.JVMDebugger;
import sun.jvm.hotspot.debugger.MachineDescription;
import sun.jvm.hotspot.debugger.MachineDescriptionAMD64;
import sun.jvm.hotspot.debugger.MachineDescriptionIA64;
import sun.jvm.hotspot.debugger.MachineDescriptionIntelX86;
import sun.jvm.hotspot.debugger.MachineDescriptionSPARC32Bit;
import sun.jvm.hotspot.debugger.MachineDescriptionSPARC64Bit;
import sun.jvm.hotspot.debugger.NoSuchSymbolException;
import sun.jvm.hotspot.debugger.cdbg.CDebugger;
import sun.jvm.hotspot.debugger.cdbg.ProcessControl;
import sun.jvm.hotspot.debugger.dbx.DbxDebuggerLocal;
import sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal;
import sun.jvm.hotspot.debugger.proc.ProcDebuggerLocal;
import sun.jvm.hotspot.debugger.remote.RemoteDebugger;
import sun.jvm.hotspot.debugger.remote.RemoteDebuggerClient;
import sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer;
import sun.jvm.hotspot.debugger.win32.Win32DebuggerLocal;
import sun.jvm.hotspot.debugger.windbg.WindbgDebuggerLocal;
import sun.jvm.hotspot.livejvm.Event;
import sun.jvm.hotspot.livejvm.ServiceabilityAgentJVMDIModule;
import sun.jvm.hotspot.livejvm.ServiceabilityAgentJVMDIModule.BreakpointToggleResult;
import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.types.Type;
import sun.jvm.hotspot.types.TypeDataBase;
import sun.jvm.hotspot.utilities.PlatformInfo;
import sun.jvm.hotspot.utilities.UnsupportedPlatformException;

public class BugSpotAgent
{
  private JVMDebugger debugger;
  private MachineDescription machDesc;
  private TypeDataBase db;
  private String os;
  private String cpu;
  private String fileSep;
  private static final int PROCESS_MODE = 0;
  private static final int CORE_FILE_MODE = 1;
  private static final int REMOTE_MODE = 2;
  private int startupMode;
  private boolean isServer;
  private int pid;
  private String executableName;
  private String coreFileName;
  private String debugServerID;
  private String serverID;
  private boolean javaMode;
  private ServiceabilityAgentJVMDIModule jvmdi;
  private boolean javaInteractionDisabled;
  private String[] jvmLibNames;
  private String[] saLibNames;
  private static final String defaultDbxPathPrefix = "/net/jano.eng/export/disk05/hotspot/sa";
  private static final String defaultDbxSvcAgentDSOPathPrefix = "/net/jano.eng/export/disk05/hotspot/sa";
  private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.bugspot.BugSpotAgent.DEBUG") != null;
  
  static void debugPrintln(String str)
  {
    if (DEBUG) {
      System.err.println(str);
    }
  }
  
  static void showUsage()
  {
    System.out.println("    You can also pass these -D options to java to specify where to find dbx and the \n    Serviceability Agent plugin for dbx:");
    
    System.out.println("       -DdbxPathName=<path-to-dbx-executable>\n             Default is derived from dbxPathPrefix");
    
    System.out.println("    or");
    System.out.println("       -DdbxPathPrefix=<xxx>\n             where xxx is the path name of a dir structure that contains:\n                   <os>/<arch>/bin/dbx\n             The default is /net/jano.eng/export/disk05/hotspot/sa");
    
    System.out.println("    and");
    System.out.println("       -DdbxSvcAgentDSOPathName=<path-to-dbx-serviceability-agent-module>\n             Default is determined from dbxSvcAgentDSOPathPrefix");
    
    System.out.println("    or");
    System.out.println("       -DdbxSvcAgentDSOPathPrefix=<xxx>\n             where xxx is the pathname of a dir structure that contains:\n                   <os>/<arch>/bin/lib/libsvc_agent_dbx.so\n             The default is /net/jano.eng/export/disk05/hotspot/sa");
  }
  
  public BugSpotAgent()
  {
    Runtime.getRuntime().addShutdownHook(new Thread(new Runnable()
    {
      public void run()
      {
        synchronized (BugSpotAgent.this)
        {
          if (!isServer) {
            detach();
          }
        }
      }
    }));
  }
  
  public synchronized Debugger getDebugger()
  {
    return debugger;
  }
  
  public synchronized CDebugger getCDebugger()
  {
    return getDebugger().getCDebugger();
  }
  
  public synchronized ProcessControl getProcessControl()
  {
    return getCDebugger().getProcessControl();
  }
  
  public synchronized TypeDataBase getTypeDataBase()
  {
    return db;
  }
  
  public synchronized boolean isSuspended()
    throws DebuggerException
  {
    return getProcessControl().isSuspended();
  }
  
  public synchronized void suspend()
    throws DebuggerException
  {
    getProcessControl().suspend();
  }
  
  public synchronized void resume()
    throws DebuggerException
  {
    getProcessControl().resume();
  }
  
  public synchronized boolean isJavaMode()
  {
    return javaMode;
  }
  
  public synchronized void disableJavaInteraction()
  {
    javaInteractionDisabled = true;
  }
  
  public synchronized void enableJavaInteraction()
  {
    javaInteractionDisabled = false;
  }
  
  public synchronized boolean isJavaInteractionDisabled()
  {
    return javaInteractionDisabled;
  }
  
  public synchronized boolean canInteractWithJava()
  {
    return (jvmdi != null) && (!javaInteractionDisabled);
  }
  
  public synchronized void suspendJava()
    throws DebuggerException
  {
    if (!canInteractWithJava()) {
      throw new DebuggerException("Could not connect to SA's JVMDI module");
    }
    if (jvmdi.isSuspended()) {
      throw new DebuggerException("Target process already suspended via JVMDI");
    }
    jvmdi.suspend();
  }
  
  public synchronized void resumeJava()
    throws DebuggerException
  {
    if (!canInteractWithJava()) {
      throw new DebuggerException("Could not connect to SA's JVMDI module");
    }
    if (!jvmdi.isSuspended()) {
      throw new DebuggerException("Target process already resumed via JVMDI");
    }
    jvmdi.resume();
  }
  
  public synchronized boolean isJavaSuspended()
    throws DebuggerException
  {
    return jvmdi.isSuspended();
  }
  
  public synchronized ServiceabilityAgentJVMDIModule.BreakpointToggleResult toggleJavaBreakpoint(String srcFileName, String pkgName, int lineNo)
  {
    if (!canInteractWithJava()) {
      throw new DebuggerException("Could not connect to SA's JVMDI module; can not toggle Java breakpoints");
    }
    return jvmdi.toggleBreakpoint(srcFileName, pkgName, lineNo);
  }
  
  public synchronized boolean javaEventPending()
    throws DebuggerException
  {
    if (!canInteractWithJava()) {
      throw new DebuggerException("Could not connect to SA's JVMDI module; can not poll for Java debug events");
    }
    return jvmdi.eventPending();
  }
  
  public synchronized Event javaEventPoll()
    throws DebuggerException
  {
    if (!canInteractWithJava()) {
      throw new DebuggerException("Could not connect to SA's JVMDI module; can not poll for Java debug events");
    }
    return jvmdi.eventPoll();
  }
  
  public synchronized void javaEventContinue()
    throws DebuggerException
  {
    if (!canInteractWithJava()) {
      throw new DebuggerException("Could not connect to SA's JVMDI module; can not continue past Java debug events");
    }
    jvmdi.eventContinue();
  }
  
  public synchronized void attach(int processID)
    throws DebuggerException
  {
    if (debugger != null) {
      throw new DebuggerException("Already attached");
    }
    pid = processID;
    startupMode = 0;
    isServer = false;
    go();
  }
  
  public synchronized void attach(String executableName, String coreFileName)
    throws DebuggerException
  {
    if (debugger != null) {
      throw new DebuggerException("Already attached");
    }
    if ((executableName == null) || (coreFileName == null)) {
      throw new DebuggerException("Both the core file name and executable name must be specified");
    }
    this.executableName = executableName;
    this.coreFileName = coreFileName;
    startupMode = 1;
    isServer = false;
    go();
  }
  
  public synchronized void attach(String remoteServerID)
    throws DebuggerException
  {
    if (debugger != null) {
      throw new DebuggerException("Already attached to a process");
    }
    if (remoteServerID == null) {
      throw new DebuggerException("Debug server id must be specified");
    }
    debugServerID = remoteServerID;
    startupMode = 2;
    isServer = false;
    go();
  }
  
  public synchronized boolean detach()
    throws DebuggerException
  {
    if (isServer) {
      throw new DebuggerException("Should not call detach() for server configuration");
    }
    return detachInternal();
  }
  
  public synchronized void startServer(int processID, String uniqueID)
    throws DebuggerException
  {
    if (debugger != null) {
      throw new DebuggerException("Already attached");
    }
    pid = processID;
    startupMode = 0;
    isServer = true;
    serverID = uniqueID;
    go();
  }
  
  public synchronized void startServer(int processID)
    throws DebuggerException
  {
    startServer(processID, null);
  }
  
  public synchronized void startServer(String executableName, String coreFileName, String uniqueID)
    throws DebuggerException
  {
    if (debugger != null) {
      throw new DebuggerException("Already attached");
    }
    if ((executableName == null) || (coreFileName == null)) {
      throw new DebuggerException("Both the core file name and Java executable name must be specified");
    }
    this.executableName = executableName;
    this.coreFileName = coreFileName;
    startupMode = 1;
    isServer = true;
    serverID = uniqueID;
    go();
  }
  
  public synchronized void startServer(String executableName, String coreFileName)
    throws DebuggerException
  {
    startServer(executableName, coreFileName, null);
  }
  
  public synchronized boolean shutdownServer()
    throws DebuggerException
  {
    if (!isServer) {
      throw new DebuggerException("Should not call shutdownServer() for client configuration");
    }
    return detachInternal();
  }
  
  private boolean detachInternal()
  {
    if (debugger == null) {
      return false;
    }
    if (canInteractWithJava())
    {
      jvmdi.detach();
      jvmdi = null;
    }
    boolean retval = true;
    if (!isServer) {
      VM.shutdown();
    }
    Debugger dbg = null;
    DebuggerException ex = null;
    if (isServer)
    {
      try
      {
        RMIHelper.unbind(serverID);
      }
      catch (DebuggerException de)
      {
        ex = de;
      }
      dbg = debugger;
    }
    else if (startupMode != 2)
    {
      dbg = debugger;
    }
    if (dbg != null) {
      retval = dbg.detach();
    }
    debugger = null;
    machDesc = null;
    db = null;
    if (ex != null) {
      throw ex;
    }
    return retval;
  }
  
  private void go()
  {
    setupDebugger();
    javaMode = setupVM();
  }
  
  private void setupDebugger()
  {
    if (startupMode != 2)
    {
      try
      {
        os = PlatformInfo.getOS();
        cpu = PlatformInfo.getCPU();
      }
      catch (UnsupportedPlatformException e)
      {
        throw new DebuggerException(e);
      }
      fileSep = System.getProperty("file.separator");
      if (os.equals("solaris")) {
        setupDebuggerSolaris();
      } else if (os.equals("win32")) {
        setupDebuggerWin32();
      } else if (os.equals("linux")) {
        setupDebuggerLinux();
      } else {
        throw new DebuggerException("Operating system " + os + " not yet supported");
      }
      if (isServer)
      {
        RemoteDebuggerServer remote = null;
        try
        {
          remote = new RemoteDebuggerServer(debugger);
        }
        catch (RemoteException rem)
        {
          throw new DebuggerException(rem);
        }
        RMIHelper.rebind(serverID, remote);
      }
    }
    else
    {
      connectRemoteDebugger();
    }
  }
  
  private boolean setupVM()
  {
    try
    {
      if (os.equals("solaris")) {
        db = new HotSpotTypeDataBase(machDesc, new HotSpotSolarisVtblAccess(debugger, jvmLibNames), debugger, jvmLibNames);
      } else if (os.equals("win32")) {
        db = new HotSpotTypeDataBase(machDesc, new Win32VtblAccess(debugger, jvmLibNames), debugger, jvmLibNames);
      } else if (os.equals("linux")) {
        db = new HotSpotTypeDataBase(machDesc, new LinuxVtblAccess(debugger, jvmLibNames), debugger, jvmLibNames);
      } else {
        throw new DebuggerException("OS \"" + os + "\" not yet supported (no VtblAccess implemented yet)");
      }
    }
    catch (NoSuchSymbolException e)
    {
      e.printStackTrace();
      return false;
    }
    if (startupMode != 2) {
      debugger.configureJavaPrimitiveTypeSizes(db.getJBooleanType().getSize(), db.getJByteType().getSize(), db.getJCharType().getSize(), db.getJDoubleType().getSize(), db.getJFloatType().getSize(), db.getJIntType().getSize(), db.getJLongType().getSize(), db.getJShortType().getSize());
    }
    if (!isServer) {
      VM.initialize(db, debugger);
    }
    try
    {
      jvmdi = new ServiceabilityAgentJVMDIModule(debugger, saLibNames);
      if (jvmdi.canAttach())
      {
        jvmdi.attach();
        jvmdi.setCommandTimeout(6000L);
        debugPrintln("Attached to Serviceability Agent's JVMDI module.");
        
        resume();
        suspendJava();
        suspend();
        debugPrintln("Suspended all Java threads.");
      }
      else
      {
        debugPrintln("Could not locate SA's JVMDI module; skipping attachment");
        jvmdi = null;
      }
    }
    catch (Exception e)
    {
      e.printStackTrace();
      jvmdi = null;
    }
    return true;
  }
  
  private void setupDebuggerSolaris()
  {
    setupJVMLibNamesSolaris();
    String prop = System.getProperty("sun.jvm.hotspot.debugger.useProcDebugger");
    if ((prop != null) && (!prop.equals("false")))
    {
      ProcDebuggerLocal dbg = new ProcDebuggerLocal(null, true);
      debugger = dbg;
      attachDebugger();
      if (cpu.equals("x86"))
      {
        machDesc = new MachineDescriptionIntelX86();
      }
      else if (cpu.equals("sparc"))
      {
        int addressSize = dbg.getRemoteProcessAddressSize();
        if (addressSize == -1) {
          throw new DebuggerException("Error occurred while trying to determine the remote process's address size");
        }
        if (addressSize == 32) {
          machDesc = new MachineDescriptionSPARC32Bit();
        } else if (addressSize == 64) {
          machDesc = new MachineDescriptionSPARC64Bit();
        } else {
          throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC");
        }
      }
      else if (cpu.equals("amd64"))
      {
        machDesc = new MachineDescriptionAMD64();
      }
      else
      {
        throw new DebuggerException("Solaris only supported on sparc/sparcv9/x86/amd64");
      }
      dbg.setMachineDescription(machDesc);
      return;
    }
    String[] dbxSvcAgentDSOPathNames = null;
    
    String dbxPathName = System.getProperty("dbxPathName");
    if (dbxPathName == null)
    {
      String dbxPathPrefix = System.getProperty("dbxPathPrefix");
      if (dbxPathPrefix == null) {
        dbxPathPrefix = "/net/jano.eng/export/disk05/hotspot/sa";
      }
      dbxPathName = dbxPathPrefix + fileSep + os + fileSep + cpu + fileSep + "bin" + fileSep + "dbx";
    }
    String dbxSvcAgentDSOPathName = System.getProperty("dbxSvcAgentDSOPathName");
    if (dbxSvcAgentDSOPathName != null)
    {
      dbxSvcAgentDSOPathNames = new String[] { dbxSvcAgentDSOPathName };
    }
    else
    {
      String dbxSvcAgentDSOPathPrefix = System.getProperty("dbxSvcAgentDSOPathPrefix");
      if (dbxSvcAgentDSOPathPrefix == null) {
        dbxSvcAgentDSOPathPrefix = "/net/jano.eng/export/disk05/hotspot/sa";
      }
      if (cpu.equals("sparc")) {
        dbxSvcAgentDSOPathNames = new String[] { dbxSvcAgentDSOPathPrefix + fileSep + os + fileSep + cpu + "v9" + fileSep + "lib" + fileSep + "libsvc_agent_dbx.so", dbxSvcAgentDSOPathPrefix + fileSep + os + fileSep + cpu + fileSep + "lib" + fileSep + "libsvc_agent_dbx.so" };
      } else {
        dbxSvcAgentDSOPathNames = new String[] { dbxSvcAgentDSOPathPrefix + fileSep + os + fileSep + cpu + fileSep + "lib" + fileSep + "libsvc_agent_dbx.so" };
      }
    }
    DbxDebuggerLocal dbg = new DbxDebuggerLocal(null, dbxPathName, dbxSvcAgentDSOPathNames, !isServer);
    debugger = dbg;
    
    attachDebugger();
    if (cpu.equals("x86"))
    {
      machDesc = new MachineDescriptionIntelX86();
    }
    else if (cpu.equals("sparc"))
    {
      int addressSize = dbg.getRemoteProcessAddressSize();
      if (addressSize == -1) {
        throw new DebuggerException("Error occurred while trying to determine the remote process's address size. It's possible that the Serviceability Agent's dbx module failed to initialize. Examine the standard output and standard error streams from the dbx process for more information.");
      }
      if (addressSize == 32) {
        machDesc = new MachineDescriptionSPARC32Bit();
      } else if (addressSize == 64) {
        machDesc = new MachineDescriptionSPARC64Bit();
      } else {
        throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC");
      }
    }
    dbg.setMachineDescription(machDesc);
  }
  
  private void connectRemoteDebugger()
    throws DebuggerException
  {
    RemoteDebugger remote = (RemoteDebugger)RMIHelper.lookup(debugServerID);
    
    debugger = new RemoteDebuggerClient(remote);
    machDesc = ((RemoteDebuggerClient)debugger).getMachineDescription();
    os = debugger.getOS();
    if (os.equals("solaris")) {
      setupJVMLibNamesSolaris();
    } else if (os.equals("win32")) {
      setupJVMLibNamesWin32();
    } else if (os.equals("linux")) {
      setupJVMLibNamesLinux();
    } else {
      throw new RuntimeException("Unknown OS type");
    }
    cpu = debugger.getCPU();
  }
  
  private void setupJVMLibNamesSolaris()
  {
    jvmLibNames = new String[] { "libjvm.so", "libjvm_g.so", "gamma_g" };
    saLibNames = new String[] { "libsa.so", "libsa_g.so" };
  }
  
  private void setupDebuggerWin32()
  {
    setupJVMLibNamesWin32();
    if (cpu.equals("x86")) {
      machDesc = new MachineDescriptionIntelX86();
    } else if (cpu.equals("amd64")) {
      machDesc = new MachineDescriptionAMD64();
    } else if (cpu.equals("ia64")) {
      machDesc = new MachineDescriptionIA64();
    } else {
      throw new DebuggerException("Win32 supported under x86, amd64 and ia64 only");
    }
    if (System.getProperty("sun.jvm.hotspot.debugger.useWindbgDebugger") != null) {
      debugger = new WindbgDebuggerLocal(machDesc, !isServer);
    } else {
      debugger = new Win32De
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114

Further reading...

For more information on Java 1.5 Tiger, you may find Java 1.5 Tiger, A developer's Notebook by D. Flanagan and B. McLaughlin from O'Reilly of interest.

New!JAR listings


Copyright 2006-2019. Infinite Loop Ltd