1 /* 2 * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 package sun.jvm.hotspot.bugspot; 26 27 import java.io.PrintStream; 28 import java.net.*; 29 import java.rmi.*; 30 import sun.jvm.hotspot.*; 31 import sun.jvm.hotspot.debugger.*; 32 import sun.jvm.hotspot.debugger.bsd.*; 33 import sun.jvm.hotspot.debugger.proc.*; 34 import sun.jvm.hotspot.debugger.cdbg.*; 35 import sun.jvm.hotspot.debugger.windbg.*; 36 import sun.jvm.hotspot.debugger.linux.*; 37 import sun.jvm.hotspot.debugger.sparc.*; 38 import sun.jvm.hotspot.debugger.remote.*; 39 import sun.jvm.hotspot.livejvm.*; 40 import sun.jvm.hotspot.memory.*; 41 import sun.jvm.hotspot.oops.*; 42 import sun.jvm.hotspot.runtime.*; 43 import sun.jvm.hotspot.types.*; 44 import sun.jvm.hotspot.utilities.*; 45 46 /** <P> This class wraps the basic functionality for connecting to the 47 * target process or debug server. It makes it simple to start up the 48 * debugging system. </P> 49 * 50 * <P> This agent (as compared to the HotSpotAgent) can connect to 51 * and interact with arbitrary processes. If the target process 52 * happens to be a HotSpot JVM, the Java debugging features of the 53 * Serviceability Agent are enabled. Further, if the Serviceability 54 * Agent's JVMDI module is loaded into the target VM, interaction 55 * with the live Java program is possible, specifically the catching 56 * of exceptions and setting of breakpoints. </P> 57 * 58 * <P> The BugSpot debugger requires that the underlying Debugger 59 * support C/C++ debugging via the CDebugger interface. </P> 60 * 61 * <P> FIXME: need to add a way to configure the paths to dbx and the 62 * DSO from the outside. However, this should work for now for 63 * internal use. </P> 64 * 65 * <P> FIXME: especially with the addition of remote debugging, this 66 * has turned into a mess; needs rethinking. </P> */ 67 68 public class BugSpotAgent { 69 70 private JVMDebugger debugger; 71 private MachineDescription machDesc; 72 private TypeDataBase db; 73 74 private String os; 75 private String cpu; 76 private String fileSep; 77 78 // The system can work in several ways: 79 // - Attaching to local process 80 // - Attaching to local core file 81 // - Connecting to remote debug server 82 // - Starting debug server for process 83 // - Starting debug server for core file 84 85 // These are options for the "client" side of things 86 private static final int PROCESS_MODE = 0; 87 private static final int CORE_FILE_MODE = 1; 88 private static final int REMOTE_MODE = 2; 89 private int startupMode; 90 91 // This indicates whether we are really starting a server or not 92 private boolean isServer; 93 94 // All possible required information for connecting 95 private int pid; 96 private String executableName; 97 private String coreFileName; 98 private String debugServerID; 99 100 // All needed information for server side 101 private String serverID; 102 103 // Indicates whether we are attached to a HotSpot JVM or not 104 private boolean javaMode; 105 106 // Indicates whether we have process control over a live HotSpot JVM 107 // or not; non-null if so. 108 private ServiceabilityAgentJVMDIModule jvmdi; 109 // While handling C breakpoints interactivity with the Java program 110 // is forbidden. Too many invariants are broken while the target is 111 // stopped at a C breakpoint to risk making JVMDI calls. 112 private boolean javaInteractionDisabled; 113 114 private String[] jvmLibNames; 115 private String[] saLibNames; 116 117 // FIXME: make these configurable, i.e., via a dotfile; also 118 // consider searching within the JDK from which this Java executable 119 // comes to find them 120 private static final String defaultDbxPathPrefix = "/net/jano.eng/export/disk05/hotspot/sa"; 121 private static final String defaultDbxSvcAgentDSOPathPrefix = "/net/jano.eng/export/disk05/hotspot/sa"; 122 123 private static final boolean DEBUG; 124 static { 125 DEBUG = System.getProperty("sun.jvm.hotspot.bugspot.BugSpotAgent.DEBUG") 126 != null; 127 } 128 129 static void debugPrintln(String str) { 130 if (DEBUG) { 131 System.err.println(str); 132 } 133 } 134 135 static void showUsage() { 136 System.out.println(" You can also pass these -D options to java to specify where to find dbx and the \n" + 137 " Serviceability Agent plugin for dbx:"); 138 System.out.println(" -DdbxPathName=<path-to-dbx-executable>\n" + 139 " Default is derived from dbxPathPrefix"); 140 System.out.println(" or"); 141 System.out.println(" -DdbxPathPrefix=<xxx>\n" + 142 " where xxx is the path name of a dir structure that contains:\n" + 143 " <os>/<arch>/bin/dbx\n" + 144 " The default is " + defaultDbxPathPrefix); 145 System.out.println(" and"); 146 System.out.println(" -DdbxSvcAgentDSOPathName=<path-to-dbx-serviceability-agent-module>\n" + 147 " Default is determined from dbxSvcAgentDSOPathPrefix"); 148 System.out.println(" or"); 149 System.out.println(" -DdbxSvcAgentDSOPathPrefix=<xxx>\n" + 150 " where xxx is the pathname of a dir structure that contains:\n" + 151 " <os>/<arch>/bin/lib/libsvc_agent_dbx.so\n" + 152 " The default is " + defaultDbxSvcAgentDSOPathPrefix); 153 } 154 155 public BugSpotAgent() { 156 // for non-server add shutdown hook to clean-up debugger in case 157 // of forced exit. For remote server, shutdown hook is added by 158 // DebugServer. 159 Runtime.getRuntime().addShutdownHook(new java.lang.Thread( 160 new Runnable() { 161 public void run() { 162 synchronized (BugSpotAgent.this) { 163 if (!isServer) { 164 detach(); 165 } 166 } 167 } 168 })); 169 } 170 171 //-------------------------------------------------------------------------------- 172 // Accessors (once the system is set up) 173 // 174 175 public synchronized Debugger getDebugger() { 176 return debugger; 177 } 178 179 public synchronized CDebugger getCDebugger() { 180 return getDebugger().getCDebugger(); 181 } 182 183 public synchronized ProcessControl getProcessControl() { 184 return getCDebugger().getProcessControl(); 185 } 186 187 public synchronized TypeDataBase getTypeDataBase() { 188 return db; 189 } 190 191 /** Indicates whether the target process is suspended 192 completely. Equivalent to getProcessControl().isSuspended(). */ 193 public synchronized boolean isSuspended() throws DebuggerException { 194 return getProcessControl().isSuspended(); 195 } 196 197 /** Suspends the target process completely. Equivalent to 198 getProcessControl().suspend(). */ 199 public synchronized void suspend() throws DebuggerException { 200 getProcessControl().suspend(); 201 } 202 203 /** Resumes the target process completely. Equivalent to 204 getProcessControl().suspend(). */ 205 public synchronized void resume() throws DebuggerException { 206 getProcessControl().resume(); 207 } 208 209 /** Indicates whether we are attached to a Java HotSpot virtual 210 machine */ 211 public synchronized boolean isJavaMode() { 212 return javaMode; 213 } 214 215 /** Temporarily disables interaction with the target process via 216 JVMDI. This is done while the target process is stopped at a C 217 breakpoint. Can be called even if the JVMDI agent has not been 218 initialized. */ 219 public synchronized void disableJavaInteraction() { 220 javaInteractionDisabled = true; 221 } 222 223 /** Re-enables interaction with the target process via JVMDI. This 224 is done while the target process is continued past a C 225 braekpoint. Can be called even if the JVMDI agent has not been 226 initialized. */ 227 public synchronized void enableJavaInteraction() { 228 javaInteractionDisabled = false; 229 } 230 231 /** Indicates whether Java interaction has been disabled */ 232 public synchronized boolean isJavaInteractionDisabled() { 233 return javaInteractionDisabled; 234 } 235 236 /** Indicates whether we can talk to the Serviceability Agent's 237 JVMDI module to be able to set breakpoints */ 238 public synchronized boolean canInteractWithJava() { 239 return (jvmdi != null) && !javaInteractionDisabled; 240 } 241 242 /** Suspends all Java threads in the target process. Can only be 243 called if we are attached to a HotSpot JVM and can connect to 244 the SA's JVMDI module. Must not be called when the target 245 process has been suspended with suspend(). */ 246 public synchronized void suspendJava() throws DebuggerException { 247 if (!canInteractWithJava()) { 248 throw new DebuggerException("Could not connect to SA's JVMDI module"); 249 } 250 if (jvmdi.isSuspended()) { 251 throw new DebuggerException("Target process already suspended via JVMDI"); 252 } 253 jvmdi.suspend(); 254 } 255 256 /** Resumes all Java threads in the target process. Can only be 257 called if we are attached to a HotSpot JVM and can connect to 258 the SA's JVMDI module. Must not be called when the target 259 process has been suspended with suspend(). */ 260 public synchronized void resumeJava() throws DebuggerException { 261 if (!canInteractWithJava()) { 262 throw new DebuggerException("Could not connect to SA's JVMDI module"); 263 } 264 if (!jvmdi.isSuspended()) { 265 throw new DebuggerException("Target process already resumed via JVMDI"); 266 } 267 jvmdi.resume(); 268 } 269 270 /** Indicates whether the target process has been suspended at the 271 Java language level via the SA's JVMDI module */ 272 public synchronized boolean isJavaSuspended() throws DebuggerException { 273 return jvmdi.isSuspended(); 274 } 275 276 /** Toggle a Java breakpoint at the given location. */ 277 public synchronized ServiceabilityAgentJVMDIModule.BreakpointToggleResult 278 toggleJavaBreakpoint(String srcFileName, 279 String pkgName, 280 int lineNo) { 281 if (!canInteractWithJava()) { 282 throw new DebuggerException("Could not connect to SA's JVMDI module; can not toggle Java breakpoints"); 283 } 284 return jvmdi.toggleBreakpoint(srcFileName, pkgName, lineNo); 285 } 286 287 /** Access to JVMDI module's eventPending */ 288 public synchronized boolean javaEventPending() throws DebuggerException { 289 if (!canInteractWithJava()) { 290 throw new DebuggerException("Could not connect to SA's JVMDI module; can not poll for Java debug events"); 291 } 292 return jvmdi.eventPending(); 293 } 294 295 /** Access to JVMDI module's eventPoll */ 296 public synchronized Event javaEventPoll() throws DebuggerException { 297 if (!canInteractWithJava()) { 298 throw new DebuggerException("Could not connect to SA's JVMDI module; can not poll for Java debug events"); 299 } 300 return jvmdi.eventPoll(); 301 } 302 303 /** Access to JVMDI module's eventContinue */ 304 public synchronized void javaEventContinue() throws DebuggerException { 305 if (!canInteractWithJava()) { 306 throw new DebuggerException("Could not connect to SA's JVMDI module; can not continue past Java debug events"); 307 } 308 jvmdi.eventContinue(); 309 } 310 311 312 // FIXME: add other accessors. For example, suspension and 313 // resumption should be done through this interface, as well as 314 // interaction with the live Java process such as breakpoint setting. 315 // Probably should not expose the ServiceabilityAgentJVMDIModule 316 // from this interface. 317 318 //-------------------------------------------------------------------------------- 319 // Client-side operations 320 // 321 322 /** This attaches to a process running on the local machine. */ 323 public synchronized void attach(int processID) 324 throws DebuggerException { 325 if (debugger != null) { 326 throw new DebuggerException("Already attached"); 327 } 328 pid = processID; 329 startupMode = PROCESS_MODE; 330 isServer = false; 331 go(); 332 } 333 334 /** This opens a core file on the local machine */ 335 public synchronized void attach(String executableName, String coreFileName) 336 throws DebuggerException { 337 if (debugger != null) { 338 throw new DebuggerException("Already attached"); 339 } 340 if ((executableName == null) || (coreFileName == null)) { 341 throw new DebuggerException("Both the core file name and executable name must be specified"); 342 } 343 this.executableName = executableName; 344 this.coreFileName = coreFileName; 345 startupMode = CORE_FILE_MODE; 346 isServer = false; 347 go(); 348 } 349 350 /** This attaches to a "debug server" on a remote machine; this 351 remote server has already attached to a process or opened a 352 core file and is waiting for RMI calls on the Debugger object to 353 come in. */ 354 public synchronized void attach(String remoteServerID) 355 throws DebuggerException { 356 if (debugger != null) { 357 throw new DebuggerException("Already attached to a process"); 358 } 359 if (remoteServerID == null) { 360 throw new DebuggerException("Debug server id must be specified"); 361 } 362 363 debugServerID = remoteServerID; 364 startupMode = REMOTE_MODE; 365 isServer = false; 366 go(); 367 } 368 369 /** This should only be called by the user on the client machine, 370 not the server machine */ 371 public synchronized boolean detach() throws DebuggerException { 372 if (isServer) { 373 throw new DebuggerException("Should not call detach() for server configuration"); 374 } 375 return detachInternal(); 376 } 377 378 //-------------------------------------------------------------------------------- 379 // Server-side operations 380 // 381 382 /** This attaches to a process running on the local machine and 383 starts a debug server, allowing remote machines to connect and 384 examine this process. uniqueID is used to uniquely identify the 385 debuggee */ 386 public synchronized void startServer(int processID, String uniqueID) 387 throws DebuggerException { 388 if (debugger != null) { 389 throw new DebuggerException("Already attached"); 390 } 391 pid = processID; 392 startupMode = PROCESS_MODE; 393 isServer = true; 394 serverID = uniqueID; 395 go(); 396 } 397 398 /** This attaches to a process running on the local machine and 399 starts a debug server, allowing remote machines to connect and 400 examine this process. */ 401 public synchronized void startServer(int processID) 402 throws DebuggerException { 403 startServer(processID, null); 404 } 405 406 /** This opens a core file on the local machine and starts a debug 407 server, allowing remote machines to connect and examine this 408 core file. uniqueID is used to uniquely identify the 409 debuggee */ 410 public synchronized void startServer(String executableName, String coreFileName, 411 String uniqueID) 412 throws DebuggerException { 413 if (debugger != null) { 414 throw new DebuggerException("Already attached"); 415 } 416 if ((executableName == null) || (coreFileName == null)) { 417 throw new DebuggerException("Both the core file name and Java executable name must be specified"); 418 } 419 this.executableName = executableName; 420 this.coreFileName = coreFileName; 421 startupMode = CORE_FILE_MODE; 422 isServer = true; 423 serverID = uniqueID; 424 go(); 425 } 426 427 /** This opens a core file on the local machine and starts a debug 428 server, allowing remote machines to connect and examine this 429 core file.*/ 430 public synchronized void startServer(String executableName, String coreFileName) 431 throws DebuggerException { 432 startServer(executableName, coreFileName, null); 433 } 434 435 /** This may only be called on the server side after startServer() 436 has been called */ 437 public synchronized boolean shutdownServer() throws DebuggerException { 438 if (!isServer) { 439 throw new DebuggerException("Should not call shutdownServer() for client configuration"); 440 } 441 return detachInternal(); 442 } 443 444 445 //-------------------------------------------------------------------------------- 446 // Internals only below this point 447 // 448 449 private boolean detachInternal() { 450 if (debugger == null) { 451 return false; 452 } 453 if (canInteractWithJava()) { 454 jvmdi.detach(); 455 jvmdi = null; 456 } 457 boolean retval = true; 458 if (!isServer) { 459 VM.shutdown(); 460 } 461 // We must not call detach() if we are a client and are connected 462 // to a remote debugger 463 Debugger dbg = null; 464 DebuggerException ex = null; 465 if (isServer) { 466 try { 467 RMIHelper.unbind(serverID); 468 } 469 catch (DebuggerException de) { 470 ex = de; 471 } 472 dbg = debugger; 473 } else { 474 if (startupMode != REMOTE_MODE) { 475 dbg = debugger; 476 } 477 } 478 if (dbg != null) { 479 retval = dbg.detach(); 480 } 481 482 debugger = null; 483 machDesc = null; 484 db = null; 485 if (ex != null) { 486 throw(ex); 487 } 488 return retval; 489 } 490 491 private void go() { 492 setupDebugger(); 493 javaMode = setupVM(); 494 } 495 496 private void setupDebugger() { 497 if (startupMode != REMOTE_MODE) { 498 // 499 // Local mode (client attaching to local process or setting up 500 // server, but not client attaching to server) 501 // 502 503 try { 504 os = PlatformInfo.getOS(); 505 cpu = PlatformInfo.getCPU(); 506 } 507 catch (UnsupportedPlatformException e) { 508 throw new DebuggerException(e); 509 } 510 fileSep = System.getProperty("file.separator"); 511 512 if (os.equals("solaris")) { 513 setupDebuggerSolaris(); 514 } else if (os.equals("win32")) { 515 setupDebuggerWin32(); 516 } else if (os.equals("linux")) { 517 setupDebuggerLinux(); 518 } else if (os.equals("bsd")) { 519 setupDebuggerBsd(); 520 } else { 521 // Add support for more operating systems here 522 throw new DebuggerException("Operating system " + os + " not yet supported"); 523 } 524 if (isServer) { 525 RemoteDebuggerServer remote = null; 526 try { 527 remote = new RemoteDebuggerServer(debugger); 528 } 529 catch (RemoteException rem) { 530 throw new DebuggerException(rem); 531 } 532 RMIHelper.rebind(serverID, remote); 533 } 534 } else { 535 // 536 // Remote mode (client attaching to server) 537 // 538 539 // Create and install a security manager 540 541 // FIXME: currently commented out because we were having 542 // security problems since we're "in the sun.* hierarchy" here. 543 // Perhaps a permissive policy file would work around this. In 544 // the long run, will probably have to move into com.sun.*. 545 546 // if (System.getSecurityManager() == null) { 547 // System.setSecurityManager(new RMISecurityManager()); 548 // } 549 550 connectRemoteDebugger(); 551 } 552 } 553 554 private boolean setupVM() { 555 // We need to instantiate a HotSpotTypeDataBase on both the client 556 // and server machine. On the server it is only currently used to 557 // configure the Java primitive type sizes (which we should 558 // consider making constant). On the client it is used to 559 // configure the VM. 560 561 try { 562 if (os.equals("solaris")) { 563 db = new HotSpotTypeDataBase(machDesc, new HotSpotSolarisVtblAccess(debugger, jvmLibNames), 564 debugger, jvmLibNames); 565 } else if (os.equals("win32")) { 566 db = new HotSpotTypeDataBase(machDesc, new Win32VtblAccess(debugger, jvmLibNames), 567 debugger, jvmLibNames); 568 } else if (os.equals("linux")) { 569 db = new HotSpotTypeDataBase(machDesc, new LinuxVtblAccess(debugger, jvmLibNames), 570 debugger, jvmLibNames); 571 } else if (os.equals("bsd")) { 572 db = new HotSpotTypeDataBase(machDesc, new BsdVtblAccess(debugger, jvmLibNames), 573 debugger, jvmLibNames); 574 } else { 575 throw new DebuggerException("OS \"" + os + "\" not yet supported (no VtblAccess implemented yet)"); 576 } 577 } 578 catch (NoSuchSymbolException e) { 579 e.printStackTrace(); 580 return false; 581 } 582 583 if (startupMode != REMOTE_MODE) { 584 // Configure the debugger with the primitive type sizes just obtained from the VM 585 debugger.configureJavaPrimitiveTypeSizes(db.getJBooleanType().getSize(), 586 db.getJByteType().getSize(), 587 db.getJCharType().getSize(), 588 db.getJDoubleType().getSize(), 589 db.getJFloatType().getSize(), 590 db.getJIntType().getSize(), 591 db.getJLongType().getSize(), 592 db.getJShortType().getSize()); 593 } 594 595 if (!isServer) { 596 // Do not initialize the VM on the server (unnecessary, since it's 597 // instantiated on the client) 598 VM.initialize(db, debugger); 599 } 600 601 try { 602 jvmdi = new ServiceabilityAgentJVMDIModule(debugger, saLibNames); 603 if (jvmdi.canAttach()) { 604 jvmdi.attach(); 605 jvmdi.setCommandTimeout(6000); 606 debugPrintln("Attached to Serviceability Agent's JVMDI module."); 607 // Jog VM to suspended point with JVMDI module 608 resume(); 609 suspendJava(); 610 suspend(); 611 debugPrintln("Suspended all Java threads."); 612 } else { 613 debugPrintln("Could not locate SA's JVMDI module; skipping attachment"); 614 jvmdi = null; 615 } 616 } catch (Exception e) { 617 e.printStackTrace(); 618 jvmdi = null; 619 } 620 621 return true; 622 } 623 624 //-------------------------------------------------------------------------------- 625 // OS-specific debugger setup/connect routines 626 // 627 628 // 629 // Solaris 630 // 631 632 private void setupDebuggerSolaris() { 633 setupJVMLibNamesSolaris(); 634 ProcDebuggerLocal dbg = new ProcDebuggerLocal(null, true); 635 debugger = dbg; 636 attachDebugger(); 637 638 // Set up CPU-dependent stuff 639 if (cpu.equals("x86")) { 640 machDesc = new MachineDescriptionIntelX86(); 641 } else if (cpu.equals("sparc")) { 642 int addressSize = dbg.getRemoteProcessAddressSize(); 643 if (addressSize == -1) { 644 throw new DebuggerException("Error occurred while trying to determine the remote process's address size"); 645 } 646 647 if (addressSize == 32) { 648 machDesc = new MachineDescriptionSPARC32Bit(); 649 } else if (addressSize == 64) { 650 machDesc = new MachineDescriptionSPARC64Bit(); 651 } else { 652 throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC"); 653 } 654 } else if (cpu.equals("amd64")) { 655 machDesc = new MachineDescriptionAMD64(); 656 } else { 657 throw new DebuggerException("Solaris only supported on sparc/sparcv9/x86/amd64"); 658 } 659 660 dbg.setMachineDescription(machDesc); 661 } 662 663 private void connectRemoteDebugger() throws DebuggerException { 664 RemoteDebugger remote = 665 (RemoteDebugger) RMIHelper.lookup(debugServerID); 666 debugger = new RemoteDebuggerClient(remote); 667 machDesc = ((RemoteDebuggerClient) debugger).getMachineDescription(); 668 os = debugger.getOS(); 669 if (os.equals("solaris")) { 670 setupJVMLibNamesSolaris(); 671 } else if (os.equals("win32")) { 672 setupJVMLibNamesWin32(); 673 } else if (os.equals("linux")) { 674 setupJVMLibNamesLinux(); 675 } else if (os.equals("bsd")) { 676 setupJVMLibNamesBsd(); 677 } else { 678 throw new RuntimeException("Unknown OS type"); 679 } 680 681 cpu = debugger.getCPU(); 682 } 683 684 private void setupJVMLibNamesSolaris() { 685 jvmLibNames = new String[] { "libjvm.so", "libjvm_g.so", "gamma_g" }; 686 saLibNames = new String[] { "libsa.so", "libsa_g.so" }; 687 } 688 689 // 690 // Win32 691 // 692 693 private void setupDebuggerWin32() { 694 setupJVMLibNamesWin32(); 695 696 if (cpu.equals("x86")) { 697 machDesc = new MachineDescriptionIntelX86(); 698 } else if (cpu.equals("amd64")) { 699 machDesc = new MachineDescriptionAMD64(); 700 } else if (cpu.equals("ia64")) { 701 machDesc = new MachineDescriptionIA64(); 702 } else { 703 throw new DebuggerException("Win32 supported under x86, amd64 and ia64 only"); 704 } 705 706 // Note we do not use a cache for the local debugger in server 707 // mode; it will be taken care of on the client side (once remote 708 // debugging is implemented). 709 710 debugger = new WindbgDebuggerLocal(machDesc, !isServer); 711 712 attachDebugger(); 713 } 714 715 private void setupJVMLibNamesWin32() { 716 jvmLibNames = new String[] { "jvm.dll", "jvm_g.dll" }; 717 saLibNames = new String[] { "sa.dll", "sa_g.dll" }; 718 } 719 720 // 721 // Linux 722 // 723 724 private void setupDebuggerLinux() { 725 setupJVMLibNamesLinux(); 726 727 if (cpu.equals("x86")) { 728 machDesc = new MachineDescriptionIntelX86(); 729 } else if (cpu.equals("ia64")) { 730 machDesc = new MachineDescriptionIA64(); 731 } else if (cpu.equals("amd64")) { 732 machDesc = new MachineDescriptionAMD64(); 733 } else if (cpu.equals("sparc")) { 734 if (LinuxDebuggerLocal.getAddressSize()==8) { 735 machDesc = new MachineDescriptionSPARC64Bit(); 736 } else { 737 machDesc = new MachineDescriptionSPARC32Bit(); 738 } 739 } else { 740 throw new DebuggerException("Linux only supported on x86/ia64/amd64/sparc/sparc64"); 741 } 742 743 // Note we do not use a cache for the local debugger in server 744 // mode; it will be taken care of on the client side (once remote 745 // debugging is implemented). 746 747 debugger = new LinuxDebuggerLocal(machDesc, !isServer); 748 attachDebugger(); 749 } 750 751 private void setupJVMLibNamesLinux() { 752 // same as solaris 753 setupJVMLibNamesSolaris(); 754 } 755 756 // 757 // BSD 758 // 759 760 private void setupDebuggerBsd() { 761 setupJVMLibNamesBsd(); 762 763 if (cpu.equals("x86")) { 764 machDesc = new MachineDescriptionIntelX86(); 765 } else if (cpu.equals("amd64")) { 766 machDesc = new MachineDescriptionAMD64(); 767 } else { 768 throw new DebuggerException("Bsd only supported on x86/amd64"); 769 } 770 771 // Note we do not use a cache for the local debugger in server 772 // mode; it will be taken care of on the client side (once remote 773 // debugging is implemented). 774 775 debugger = new BsdDebuggerLocal(machDesc, !isServer); 776 attachDebugger(); 777 } 778 779 private void setupJVMLibNamesBsd() { 780 // same as solaris 781 setupJVMLibNamesSolaris(); 782 } 783 784 /** Convenience routine which should be called by per-platform 785 debugger setup. Should not be called when startupMode is 786 REMOTE_MODE. */ 787 private void attachDebugger() { 788 if (startupMode == PROCESS_MODE) { 789 debugger.attach(pid); 790 } else if (startupMode == CORE_FILE_MODE) { 791 debugger.attach(executableName, coreFileName); 792 } else { 793 throw new DebuggerException("Should not call attach() for startupMode == " + startupMode); 794 } 795 } 796 }