BugSpotAgent.java 28.4 KB
Newer Older
D
duke 已提交
1
/*
N
never 已提交
2
 * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * 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.
 *
19 20 21
 * 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.
D
duke 已提交
22 23 24 25 26 27 28 29 30 31
 *
 */

package sun.jvm.hotspot.bugspot;

import java.io.PrintStream;
import java.net.*;
import java.rmi.*;
import sun.jvm.hotspot.*;
import sun.jvm.hotspot.debugger.*;
N
never 已提交
32
import sun.jvm.hotspot.debugger.bsd.*;
D
duke 已提交
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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517
import sun.jvm.hotspot.debugger.proc.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.debugger.windbg.*;
import sun.jvm.hotspot.debugger.linux.*;
import sun.jvm.hotspot.debugger.sparc.*;
import sun.jvm.hotspot.debugger.remote.*;
import sun.jvm.hotspot.livejvm.*;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.utilities.*;

/** <P> This class wraps the basic functionality for connecting to the
 * target process or debug server. It makes it simple to start up the
 * debugging system. </P>
 *
 * <P> This agent (as compared to the HotSpotAgent) can connect to
 * and interact with arbitrary processes. If the target process
 * happens to be a HotSpot JVM, the Java debugging features of the
 * Serviceability Agent are enabled. Further, if the Serviceability
 * Agent's JVMDI module is loaded into the target VM, interaction
 * with the live Java program is possible, specifically the catching
 * of exceptions and setting of breakpoints. </P>
 *
 * <P> The BugSpot debugger requires that the underlying Debugger
 * support C/C++ debugging via the CDebugger interface. </P>
 *
 * <P> FIXME: need to add a way to configure the paths to dbx and the
 * DSO from the outside. However, this should work for now for
 * internal use. </P>
 *
 * <P> FIXME: especially with the addition of remote debugging, this
 * has turned into a mess; needs rethinking. </P> */

public class BugSpotAgent {

    private JVMDebugger debugger;
    private MachineDescription machDesc;
    private TypeDataBase db;

    private String os;
    private String cpu;
    private String fileSep;

    // The system can work in several ways:
    //  - Attaching to local process
    //  - Attaching to local core file
    //  - Connecting to remote debug server
    //  - Starting debug server for process
    //  - Starting debug server for core file

    // These are options for the "client" side of things
    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;

    // This indicates whether we are really starting a server or not
    private boolean isServer;

    // All possible required information for connecting
    private int pid;
    private String executableName;
    private String coreFileName;
    private String debugServerID;

    // All needed information for server side
    private String serverID;

    // Indicates whether we are attached to a HotSpot JVM or not
    private boolean javaMode;

    // Indicates whether we have process control over a live HotSpot JVM
    // or not; non-null if so.
    private ServiceabilityAgentJVMDIModule jvmdi;
    // While handling C breakpoints interactivity with the Java program
    // is forbidden. Too many invariants are broken while the target is
    // stopped at a C breakpoint to risk making JVMDI calls.
    private boolean javaInteractionDisabled;

    private String[] jvmLibNames;
    private String[] saLibNames;

    // FIXME: make these configurable, i.e., via a dotfile; also
    // consider searching within the JDK from which this Java executable
    // comes to find them
    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;
    static {
        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 " + defaultDbxPathPrefix);
        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 " + defaultDbxSvcAgentDSOPathPrefix);
    }

    public BugSpotAgent() {
        // for non-server add shutdown hook to clean-up debugger in case
        // of forced exit. For remote server, shutdown hook is added by
        // DebugServer.
        Runtime.getRuntime().addShutdownHook(new java.lang.Thread(
        new Runnable() {
            public void run() {
                synchronized (BugSpotAgent.this) {
                    if (!isServer) {
                        detach();
                    }
                }
            }
        }));
    }

    //--------------------------------------------------------------------------------
    // Accessors (once the system is set up)
    //

    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;
    }

    /** Indicates whether the target process is suspended
      completely. Equivalent to getProcessControl().isSuspended(). */
    public synchronized boolean isSuspended() throws DebuggerException {
        return getProcessControl().isSuspended();
    }

    /** Suspends the target process completely. Equivalent to
      getProcessControl().suspend(). */
    public synchronized void suspend() throws DebuggerException {
        getProcessControl().suspend();
    }

    /** Resumes the target process completely. Equivalent to
      getProcessControl().suspend(). */
    public synchronized void resume() throws DebuggerException {
        getProcessControl().resume();
    }

    /** Indicates whether we are attached to a Java HotSpot virtual
      machine */
    public synchronized boolean isJavaMode() {
        return javaMode;
    }

    /** Temporarily disables interaction with the target process via
      JVMDI. This is done while the target process is stopped at a C
      breakpoint. Can be called even if the JVMDI agent has not been
      initialized. */
    public synchronized void disableJavaInteraction() {
        javaInteractionDisabled = true;
    }

    /** Re-enables interaction with the target process via JVMDI. This
      is done while the target process is continued past a C
      braekpoint. Can be called even if the JVMDI agent has not been
      initialized. */
    public synchronized void enableJavaInteraction() {
        javaInteractionDisabled = false;
    }

    /** Indicates whether Java interaction has been disabled */
    public synchronized boolean isJavaInteractionDisabled() {
        return javaInteractionDisabled;
    }

    /** Indicates whether we can talk to the Serviceability Agent's
      JVMDI module to be able to set breakpoints */
    public synchronized boolean canInteractWithJava() {
        return (jvmdi != null) && !javaInteractionDisabled;
    }

    /** Suspends all Java threads in the target process. Can only be
      called if we are attached to a HotSpot JVM and can connect to
      the SA's JVMDI module. Must not be called when the target
      process has been suspended with suspend(). */
    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();
    }

    /** Resumes all Java threads in the target process. Can only be
      called if we are attached to a HotSpot JVM and can connect to
      the SA's JVMDI module. Must not be called when the target
      process has been suspended with 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();
    }

    /** Indicates whether the target process has been suspended at the
      Java language level via the SA's JVMDI module */
    public synchronized boolean isJavaSuspended() throws DebuggerException {
        return jvmdi.isSuspended();
    }

    /** Toggle a Java breakpoint at the given location. */
    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);
    }

    /** Access to JVMDI module's eventPending */
    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();
    }

    /** Access to JVMDI module's eventPoll */
    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();
    }

    /** Access to JVMDI module's eventContinue */
    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();
    }


    // FIXME: add other accessors. For example, suspension and
    // resumption should be done through this interface, as well as
    // interaction with the live Java process such as breakpoint setting.
    // Probably should not expose the ServiceabilityAgentJVMDIModule
    // from this interface.

    //--------------------------------------------------------------------------------
    // Client-side operations
    //

    /** This attaches to a process running on the local machine. */
    public synchronized void attach(int processID)
    throws DebuggerException {
        if (debugger != null) {
            throw new DebuggerException("Already attached");
        }
        pid = processID;
        startupMode = PROCESS_MODE;
        isServer = false;
        go();
    }

    /** This opens a core file on the local machine */
    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 = CORE_FILE_MODE;
        isServer = false;
        go();
    }

    /** This attaches to a "debug server" on a remote machine; this
      remote server has already attached to a process or opened a
      core file and is waiting for RMI calls on the Debugger object to
      come in. */
    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 = REMOTE_MODE;
        isServer = false;
        go();
    }

    /** This should only be called by the user on the client machine,
      not the server machine */
    public synchronized boolean detach() throws DebuggerException {
        if (isServer) {
            throw new DebuggerException("Should not call detach() for server configuration");
        }
        return detachInternal();
    }

    //--------------------------------------------------------------------------------
    // Server-side operations
    //

    /** This attaches to a process running on the local machine and
      starts a debug server, allowing remote machines to connect and
      examine this process. uniqueID is used to uniquely identify the
      debuggee */
    public synchronized void startServer(int processID, String uniqueID)
    throws DebuggerException {
        if (debugger != null) {
            throw new DebuggerException("Already attached");
        }
        pid = processID;
        startupMode = PROCESS_MODE;
        isServer = true;
        serverID = uniqueID;
        go();
    }

    /** This attaches to a process running on the local machine and
      starts a debug server, allowing remote machines to connect and
      examine this process. */
    public synchronized void startServer(int processID)
    throws DebuggerException {
        startServer(processID, null);
    }

    /** This opens a core file on the local machine and starts a debug
      server, allowing remote machines to connect and examine this
      core file. uniqueID is used to uniquely identify the
      debuggee */
    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 = CORE_FILE_MODE;
        isServer = true;
        serverID = uniqueID;
        go();
    }

    /** This opens a core file on the local machine and starts a debug
      server, allowing remote machines to connect and examine this
      core file.*/
    public synchronized void startServer(String executableName, String coreFileName)
    throws DebuggerException {
        startServer(executableName, coreFileName, null);
    }

    /** This may only be called on the server side after startServer()
      has been called */
    public synchronized boolean shutdownServer() throws DebuggerException {
        if (!isServer) {
            throw new DebuggerException("Should not call shutdownServer() for client configuration");
        }
        return detachInternal();
    }


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

    private boolean detachInternal() {
        if (debugger == null) {
            return false;
        }
        if (canInteractWithJava()) {
            jvmdi.detach();
            jvmdi = null;
        }
        boolean retval = true;
        if (!isServer) {
            VM.shutdown();
        }
        // We must not call detach() if we are a client and are connected
        // to a remote debugger
        Debugger dbg = null;
        DebuggerException ex = null;
        if (isServer) {
            try {
                RMIHelper.unbind(serverID);
            }
            catch (DebuggerException de) {
                ex = de;
            }
            dbg = debugger;
        } else {
            if (startupMode != REMOTE_MODE) {
                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 != REMOTE_MODE) {
            //
            // Local mode (client attaching to local process or setting up
            // server, but not client attaching to server)
            //

            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();
N
never 已提交
518 519
            } else if (os.equals("bsd")) {
                setupDebuggerBsd();
D
duke 已提交
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570
            } else {
                // Add support for more operating systems here
                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 {
            //
            // Remote mode (client attaching to server)
            //

            // Create and install a security manager

            // FIXME: currently commented out because we were having
            // security problems since we're "in the sun.* hierarchy" here.
            // Perhaps a permissive policy file would work around this. In
            // the long run, will probably have to move into com.sun.*.

            //    if (System.getSecurityManager() == null) {
            //      System.setSecurityManager(new RMISecurityManager());
            //    }

            connectRemoteDebugger();
        }
    }

    private boolean setupVM() {
        // We need to instantiate a HotSpotTypeDataBase on both the client
        // and server machine. On the server it is only currently used to
        // configure the Java primitive type sizes (which we should
        // consider making constant). On the client it is used to
        // configure the VM.

        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);
N
never 已提交
571 572 573
            } else if (os.equals("bsd")) {
                db = new HotSpotTypeDataBase(machDesc, new BsdVtblAccess(debugger, jvmLibNames),
                debugger, jvmLibNames);
D
duke 已提交
574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633
            } else {
                throw new DebuggerException("OS \"" + os + "\" not yet supported (no VtblAccess implemented yet)");
            }
        }
        catch (NoSuchSymbolException e) {
            e.printStackTrace();
            return false;
        }

        if (startupMode != REMOTE_MODE) {
            // Configure the debugger with the primitive type sizes just obtained from the VM
            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) {
            // Do not initialize the VM on the server (unnecessary, since it's
            // instantiated on the client)
            VM.initialize(db, debugger);
        }

        try {
            jvmdi = new ServiceabilityAgentJVMDIModule(debugger, saLibNames);
            if (jvmdi.canAttach()) {
                jvmdi.attach();
                jvmdi.setCommandTimeout(6000);
                debugPrintln("Attached to Serviceability Agent's JVMDI module.");
                // Jog VM to suspended point with 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;
    }

    //--------------------------------------------------------------------------------
    // OS-specific debugger setup/connect routines
    //

    //
    // Solaris
    //

    private void setupDebuggerSolaris() {
        setupJVMLibNamesSolaris();
N
never 已提交
634 635 636
        ProcDebuggerLocal dbg = new ProcDebuggerLocal(null, true);
        debugger = dbg;
        attachDebugger();
D
duke 已提交
637

N
never 已提交
638 639 640 641 642 643 644
        // Set up CPU-dependent stuff
        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");
D
duke 已提交
645 646
            }

N
never 已提交
647 648 649 650
            if (addressSize == 32) {
                machDesc = new MachineDescriptionSPARC32Bit();
            } else if (addressSize == 64) {
                machDesc = new MachineDescriptionSPARC64Bit();
D
duke 已提交
651
            } else {
N
never 已提交
652
                throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC");
D
duke 已提交
653
            }
N
never 已提交
654 655 656 657
        } else if (cpu.equals("amd64")) {
            machDesc = new MachineDescriptionAMD64();
        } else {
            throw new DebuggerException("Solaris only supported on sparc/sparcv9/x86/amd64");
D
duke 已提交
658
        }
N
never 已提交
659 660

        dbg.setMachineDescription(machDesc);
D
duke 已提交
661 662 663 664 665 666 667 668 669 670 671 672 673 674
    }

    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();
N
never 已提交
675 676
        } else if (os.equals("bsd")) {
            setupJVMLibNamesBsd();
D
duke 已提交
677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709
        } 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" };
    }

    //
    // Win32
    //

    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");
        }

        // Note we do not use a cache for the local debugger in server
        // mode; it will be taken care of on the client side (once remote
        // debugging is implemented).

N
never 已提交
710
        debugger = new WindbgDebuggerLocal(machDesc, !isServer);
D
duke 已提交
711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755

        attachDebugger();
    }

    private void setupJVMLibNamesWin32() {
        jvmLibNames = new String[] { "jvm.dll", "jvm_g.dll" };
        saLibNames = new String[] { "sa.dll", "sa_g.dll" };
    }

    //
    // Linux
    //

    private void setupDebuggerLinux() {
        setupJVMLibNamesLinux();

        if (cpu.equals("x86")) {
            machDesc = new MachineDescriptionIntelX86();
        } else if (cpu.equals("ia64")) {
            machDesc = new MachineDescriptionIA64();
        } else if (cpu.equals("amd64")) {
            machDesc = new MachineDescriptionAMD64();
        } else if (cpu.equals("sparc")) {
            if (LinuxDebuggerLocal.getAddressSize()==8) {
               machDesc = new MachineDescriptionSPARC64Bit();
            } else {
               machDesc = new MachineDescriptionSPARC32Bit();
            }
        } else {
            throw new DebuggerException("Linux only supported on x86/ia64/amd64/sparc/sparc64");
        }

        // Note we do not use a cache for the local debugger in server
        // mode; it will be taken care of on the client side (once remote
        // debugging is implemented).

        debugger = new LinuxDebuggerLocal(machDesc, !isServer);
        attachDebugger();
    }

    private void setupJVMLibNamesLinux() {
        // same as solaris
        setupJVMLibNamesSolaris();
    }

N
never 已提交
756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783
    //
    // BSD
    //

    private void setupDebuggerBsd() {
        setupJVMLibNamesBsd();

        if (cpu.equals("x86")) {
            machDesc = new MachineDescriptionIntelX86();
        } else if (cpu.equals("amd64")) {
            machDesc = new MachineDescriptionAMD64();
        } else {
            throw new DebuggerException("Bsd only supported on x86/amd64");
        }

        // Note we do not use a cache for the local debugger in server
        // mode; it will be taken care of on the client side (once remote
        // debugging is implemented).

        debugger = new BsdDebuggerLocal(machDesc, !isServer);
        attachDebugger();
    }

    private void setupJVMLibNamesBsd() {
        // same as solaris
        setupJVMLibNamesSolaris();
    }

D
duke 已提交
784 785 786 787 788 789 790 791 792 793 794 795 796
    /** Convenience routine which should be called by per-platform
      debugger setup. Should not be called when startupMode is
      REMOTE_MODE. */
    private void attachDebugger() {
        if (startupMode == PROCESS_MODE) {
            debugger.attach(pid);
        } else if (startupMode == CORE_FILE_MODE) {
            debugger.attach(executableName, coreFileName);
        } else {
            throw new DebuggerException("Should not call attach() for startupMode == " + startupMode);
        }
    }
}