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