Mercurial > hg > graal-compiler
comparison agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java @ 0:a61af66fc99e jdk7-b24
Initial load
author | duke |
---|---|
date | Sat, 01 Dec 2007 00:00:00 +0000 |
parents | |
children | ba764ed4b6f2 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a61af66fc99e |
---|---|
1 /* | |
2 * Copyright 2002-2005 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.debugger.windbg; | |
26 | |
27 import java.io.*; | |
28 import java.net.*; | |
29 import java.util.*; | |
30 import sun.jvm.hotspot.debugger.*; | |
31 import sun.jvm.hotspot.debugger.amd64.*; | |
32 import sun.jvm.hotspot.debugger.x86.*; | |
33 import sun.jvm.hotspot.debugger.ia64.*; | |
34 import sun.jvm.hotspot.debugger.windbg.amd64.*; | |
35 import sun.jvm.hotspot.debugger.windbg.x86.*; | |
36 import sun.jvm.hotspot.debugger.windbg.ia64.*; | |
37 import sun.jvm.hotspot.debugger.win32.coff.*; | |
38 import sun.jvm.hotspot.debugger.cdbg.*; | |
39 import sun.jvm.hotspot.debugger.cdbg.basic.BasicDebugEvent; | |
40 import sun.jvm.hotspot.utilities.*; | |
41 import sun.jvm.hotspot.utilities.memo.*; | |
42 | |
43 /** <P> An implementation of the JVMDebugger interface which talks to | |
44 windbg and symbol table management is done in Java. </P> | |
45 | |
46 <P> <B>NOTE</B> that since we have the notion of fetching "Java | |
47 primitive types" from the remote process (which might have | |
48 different sizes than we expect) we have a bootstrapping | |
49 problem. We need to know the sizes of these types before we can | |
50 fetch them. The current implementation solves this problem by | |
51 requiring that it be configured with these type sizes before they | |
52 can be fetched. The readJ(Type) routines here will throw a | |
53 RuntimeException if they are called before the debugger is | |
54 configured with the Java primitive type sizes. </P> */ | |
55 | |
56 public class WindbgDebuggerLocal extends DebuggerBase implements WindbgDebugger { | |
57 private PageCache cache; | |
58 private boolean attached; | |
59 private boolean isCore; | |
60 | |
61 // Symbol lookup support | |
62 // This is a map of library names to DLLs | |
63 private Map nameToDllMap; | |
64 | |
65 // C/C++ debugging support | |
66 private List/*<LoadObject>*/ loadObjects; | |
67 private CDebugger cdbg; | |
68 | |
69 // thread access | |
70 private Map threadIntegerRegisterSet; | |
71 private List threadList; | |
72 | |
73 // windbg native interface pointers | |
74 | |
75 private long ptrIDebugClient; | |
76 private long ptrIDebugControl; | |
77 private long ptrIDebugDataSpaces; | |
78 private long ptrIDebugOutputCallbacks; | |
79 private long ptrIDebugAdvanced; | |
80 private long ptrIDebugSymbols; | |
81 private long ptrIDebugSystemObjects; | |
82 | |
83 private WindbgThreadFactory threadFactory; | |
84 | |
85 //-------------------------------------------------------------------------------- | |
86 // Implementation of Debugger interface | |
87 // | |
88 | |
89 /** <P> machDesc may not be null. </P> | |
90 | |
91 <P> useCache should be set to true if debugging is being done | |
92 locally, and to false if the debugger is being created for the | |
93 purpose of supporting remote debugging. </P> */ | |
94 public WindbgDebuggerLocal(MachineDescription machDesc, | |
95 boolean useCache) throws DebuggerException { | |
96 this.machDesc = machDesc; | |
97 utils = new DebuggerUtilities(machDesc.getAddressSize(), machDesc.isBigEndian()) { | |
98 public void checkAlignment(long address, long alignment) { | |
99 // Need to override default checkAlignment because we need to | |
100 // relax alignment constraints on Windows/x86 | |
101 if ( (address % alignment != 0) | |
102 &&(alignment != 8 || address % 4 != 0)) { | |
103 throw new UnalignedAddressException( | |
104 "Trying to read at address: " | |
105 + addressValueToString(address) | |
106 + " with alignment: " + alignment, | |
107 address); | |
108 } | |
109 } | |
110 }; | |
111 | |
112 String cpu = PlatformInfo.getCPU(); | |
113 if (cpu.equals("x86")) { | |
114 threadFactory = new WindbgX86ThreadFactory(this); | |
115 } else if (cpu.equals("amd64")) { | |
116 threadFactory = new WindbgAMD64ThreadFactory(this); | |
117 } else if (cpu.equals("ia64")) { | |
118 threadFactory = new WindbgIA64ThreadFactory(this); | |
119 } | |
120 | |
121 if (useCache) { | |
122 // Cache portion of the remote process's address space. | |
123 // Fetching data over the socket connection to dbx is slow. | |
124 // Might be faster if we were using a binary protocol to talk to | |
125 // dbx, but would have to test. For now, this cache works best | |
126 // if it covers the entire heap of the remote process. FIXME: at | |
127 // least should make this tunable from the outside, i.e., via | |
128 // the UI. This is a cache of 4096 4K pages, or 16 MB. The page | |
129 // size must be adjusted to be the hardware's page size. | |
130 // (FIXME: should pick this up from the debugger.) | |
131 initCache(4096, 4096); | |
132 } | |
133 // FIXME: add instantiation of thread factory | |
134 | |
135 } | |
136 | |
137 /** From the Debugger interface via JVMDebugger */ | |
138 public boolean hasProcessList() throws DebuggerException { | |
139 return false; | |
140 } | |
141 | |
142 /** From the Debugger interface via JVMDebugger */ | |
143 public List getProcessList() throws DebuggerException { | |
144 return null; | |
145 } | |
146 | |
147 | |
148 /** From the Debugger interface via JVMDebugger */ | |
149 public synchronized void attach(int processID) throws DebuggerException { | |
150 attachInit(); | |
151 attach0(processID); | |
152 attached = true; | |
153 isCore = false; | |
154 } | |
155 | |
156 /** From the Debugger interface via JVMDebugger */ | |
157 public synchronized void attach(String executableName, String coreFileName) throws DebuggerException { | |
158 attachInit(); | |
159 attach0(executableName, coreFileName); | |
160 attached = true; | |
161 isCore = true; | |
162 } | |
163 | |
164 public List getLoadObjectList() { | |
165 requireAttach(); | |
166 return loadObjects; | |
167 } | |
168 | |
169 /** From the Debugger interface via JVMDebugger */ | |
170 public synchronized boolean detach() { | |
171 if ( ! attached) | |
172 return false; | |
173 | |
174 // Close all open DLLs | |
175 if (nameToDllMap != null) { | |
176 for (Iterator iter = nameToDllMap.values().iterator(); iter.hasNext(); ) { | |
177 DLL dll = (DLL) iter.next(); | |
178 dll.close(); | |
179 } | |
180 nameToDllMap = null; | |
181 loadObjects = null; | |
182 } | |
183 | |
184 cdbg = null; | |
185 clearCache(); | |
186 | |
187 threadIntegerRegisterSet = null; | |
188 threadList = null; | |
189 try { | |
190 detach0(); | |
191 } finally { | |
192 attached = false; | |
193 resetNativePointers(); | |
194 } | |
195 return true; | |
196 } | |
197 | |
198 | |
199 /** From the Debugger interface via JVMDebugger */ | |
200 public Address parseAddress(String addressString) throws NumberFormatException { | |
201 return newAddress(utils.scanAddress(addressString)); | |
202 } | |
203 | |
204 /** From the Debugger interface via JVMDebugger */ | |
205 public String getOS() { | |
206 return PlatformInfo.getOS(); | |
207 } | |
208 | |
209 /** From the Debugger interface via JVMDebugger */ | |
210 public String getCPU() { | |
211 return PlatformInfo.getCPU(); | |
212 } | |
213 | |
214 public boolean hasConsole() throws DebuggerException { | |
215 return true; | |
216 } | |
217 | |
218 public synchronized String consoleExecuteCommand(String cmd) throws DebuggerException { | |
219 requireAttach(); | |
220 if (! attached) { | |
221 throw new DebuggerException("debugger not yet attached to a Dr. Watson dump!"); | |
222 } | |
223 | |
224 return consoleExecuteCommand0(cmd); | |
225 } | |
226 | |
227 public String getConsolePrompt() throws DebuggerException { | |
228 return "(windbg)"; | |
229 } | |
230 | |
231 public CDebugger getCDebugger() throws DebuggerException { | |
232 if (cdbg == null) { | |
233 // FIXME: CDebugger is not yet supported for IA64 because | |
234 // of native stack walking issues. | |
235 if (! getCPU().equals("ia64")) { | |
236 cdbg = new WindbgCDebugger(this); | |
237 } | |
238 } | |
239 return cdbg; | |
240 } | |
241 | |
242 /** From the SymbolLookup interface via Debugger and JVMDebugger */ | |
243 public synchronized Address lookup(String objectName, String symbol) { | |
244 requireAttach(); | |
245 return newAddress(lookupByName(objectName, symbol)); | |
246 } | |
247 | |
248 /** From the SymbolLookup interface via Debugger and JVMDebugger */ | |
249 public synchronized OopHandle lookupOop(String objectName, String symbol) { | |
250 Address addr = lookup(objectName, symbol); | |
251 if (addr == null) { | |
252 return null; | |
253 } | |
254 return addr.addOffsetToAsOopHandle(0); | |
255 } | |
256 | |
257 public synchronized ClosestSymbol lookup(long address) { | |
258 return lookupByAddress0(address); | |
259 } | |
260 | |
261 /** From the Debugger interface */ | |
262 public MachineDescription getMachineDescription() { | |
263 return machDesc; | |
264 } | |
265 | |
266 //-------------------------------------------------------------------------------- | |
267 // Implementation of ThreadAccess interface | |
268 // | |
269 | |
270 | |
271 /** From the ThreadAccess interface via Debugger and JVMDebugger */ | |
272 public ThreadProxy getThreadForIdentifierAddress(Address addr) { | |
273 return threadFactory.createThreadWrapper(addr); | |
274 } | |
275 | |
276 public ThreadProxy getThreadForThreadId(long handle) { | |
277 // with windbg we can't make out using handle | |
278 throw new DebuggerException("Unimplemented!"); | |
279 } | |
280 | |
281 public long getThreadIdFromSysId(long sysId) throws DebuggerException { | |
282 requireAttach(); | |
283 return getThreadIdFromSysId0(sysId); | |
284 } | |
285 | |
286 //---------------------------------------------------------------------- | |
287 // Overridden from DebuggerBase because we need to relax alignment | |
288 // constraints on x86 | |
289 | |
290 public long readJLong(long address) | |
291 throws UnmappedAddressException, UnalignedAddressException { | |
292 checkJavaConfigured(); | |
293 // FIXME: allow this to be configurable. Undesirable to add a | |
294 // dependency on the runtime package here, though, since this | |
295 // package should be strictly underneath it. | |
296 // utils.checkAlignment(address, jlongSize); | |
297 utils.checkAlignment(address, jintSize); | |
298 byte[] data = readBytes(address, jlongSize); | |
299 return utils.dataToJLong(data, jlongSize); | |
300 } | |
301 | |
302 //-------------------------------------------------------------------------------- | |
303 // Internal routines (for implementation of WindbgAddress). | |
304 // These must not be called until the MachineDescription has been set up. | |
305 // | |
306 | |
307 /** From the WindbgDebugger interface */ | |
308 public String addressValueToString(long address) { | |
309 return utils.addressValueToString(address); | |
310 } | |
311 | |
312 /** From the WindbgDebugger interface */ | |
313 public WindbgAddress readAddress(long address) | |
314 throws UnmappedAddressException, UnalignedAddressException { | |
315 return (WindbgAddress) newAddress(readAddressValue(address)); | |
316 } | |
317 | |
318 /** From the WindbgDebugger interface */ | |
319 public WindbgOopHandle readOopHandle(long address) | |
320 throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { | |
321 long value = readAddressValue(address); | |
322 return (value == 0 ? null : new WindbgOopHandle(this, value)); | |
323 } | |
324 | |
325 /** From the WindbgDebugger interface */ | |
326 public int getAddressSize() { | |
327 return (int) machDesc.getAddressSize(); | |
328 } | |
329 | |
330 //-------------------------------------------------------------------------------- | |
331 // Thread context access | |
332 // | |
333 | |
334 private synchronized void setThreadIntegerRegisterSet(long threadId, | |
335 long[] regs) { | |
336 threadIntegerRegisterSet.put(new Long(threadId), regs); | |
337 } | |
338 | |
339 private synchronized void addThread(long sysId) { | |
340 threadList.add(threadFactory.createThreadWrapper(sysId)); | |
341 } | |
342 | |
343 public synchronized long[] getThreadIntegerRegisterSet(long threadId) | |
344 throws DebuggerException { | |
345 requireAttach(); | |
346 return (long[]) threadIntegerRegisterSet.get(new Long(threadId)); | |
347 } | |
348 | |
349 public synchronized List getThreadList() throws DebuggerException { | |
350 requireAttach(); | |
351 return threadList; | |
352 } | |
353 | |
354 private String findFullPath(String file) { | |
355 File f = new File(file); | |
356 if (f.exists()) { | |
357 return file; | |
358 } else { | |
359 // remove path part, if any. | |
360 file = f.getName(); | |
361 StringTokenizer st = new StringTokenizer(imagePath, File.pathSeparator); | |
362 while (st.hasMoreTokens()) { | |
363 f = new File(st.nextToken(), file); | |
364 if (f.exists()) { | |
365 return f.getPath(); | |
366 } | |
367 } | |
368 } | |
369 return null; | |
370 } | |
371 | |
372 private synchronized void addLoadObject(String file, long size, long base) { | |
373 String path = findFullPath(file); | |
374 if (path != null) { | |
375 DLL dll = null; | |
376 if (useNativeLookup) { | |
377 dll = new DLL(this, path, size,newAddress(base)) { | |
378 public ClosestSymbol closestSymbolToPC(Address pcAsAddr) { | |
379 long pc = getAddressValue(pcAsAddr); | |
380 ClosestSymbol sym = lookupByAddress0(pc); | |
381 if (sym == null) { | |
382 return super.closestSymbolToPC(pcAsAddr); | |
383 } else { | |
384 return sym; | |
385 } | |
386 } | |
387 }; | |
388 } else { | |
389 dll = new DLL(this, path, size, newAddress(base)); | |
390 } | |
391 loadObjects.add(dll); | |
392 nameToDllMap.put(new File(file).getName(), dll); | |
393 } | |
394 } | |
395 | |
396 //-------------------------------------------------------------------------------- | |
397 // Address access | |
398 // | |
399 | |
400 /** From the Debugger interface */ | |
401 public long getAddressValue(Address addr) { | |
402 if (addr == null) return 0; | |
403 return ((WindbgAddress) addr).getValue(); | |
404 } | |
405 | |
406 /** From the WindbgDebugger interface */ | |
407 public Address newAddress(long value) { | |
408 if (value == 0) return null; | |
409 return new WindbgAddress(this, value); | |
410 } | |
411 | |
412 //-------------------------------------------------------------------------------- | |
413 // Internals only below this point | |
414 // | |
415 | |
416 // attach/detach helpers | |
417 private void checkAttached() { | |
418 if (attached) { | |
419 String msg = (isCore)? "already attached to a Dr. Watson dump!" : | |
420 "already attached to a process!"; | |
421 throw new DebuggerException(msg); | |
422 } | |
423 } | |
424 | |
425 private void requireAttach() { | |
426 if (!attached) { | |
427 throw new RuntimeException("not attached to a process or Dr Watson dump"); | |
428 } | |
429 } | |
430 | |
431 private void attachInit() { | |
432 checkAttached(); | |
433 loadObjects = new ArrayList(); | |
434 nameToDllMap = new HashMap(); | |
435 threadIntegerRegisterSet = new HashMap(); | |
436 threadList = new ArrayList(); | |
437 } | |
438 | |
439 private void resetNativePointers() { | |
440 ptrIDebugClient = 0L; | |
441 ptrIDebugControl = 0L; | |
442 ptrIDebugDataSpaces = 0L; | |
443 ptrIDebugOutputCallbacks = 0L; | |
444 ptrIDebugAdvanced = 0L; | |
445 ptrIDebugSymbols = 0L; | |
446 ptrIDebugSystemObjects = 0L; | |
447 } | |
448 | |
449 synchronized long lookupByName(String objectName, String symbol) { | |
450 long res = 0L; | |
451 if (useNativeLookup) { | |
452 res = lookupByName0(objectName, symbol); | |
453 if (res != 0L) { | |
454 return res; | |
455 } // else fallthru... | |
456 } | |
457 | |
458 DLL dll = (DLL) nameToDllMap.get(objectName); | |
459 // The DLL can be null because we use this to search through known | |
460 // DLLs in HotSpotTypeDataBase (for example) | |
461 if (dll != null) { | |
462 WindbgAddress addr = (WindbgAddress) dll.lookupSymbol(symbol); | |
463 if (addr != null) { | |
464 return addr.getValue(); | |
465 } | |
466 } | |
467 return 0L; | |
468 } | |
469 | |
470 /** This reads bytes from the remote process. */ | |
471 public synchronized ReadResult readBytesFromProcess(long address, long numBytes) | |
472 throws UnmappedAddressException, DebuggerException { | |
473 requireAttach(); | |
474 byte[] res = readBytesFromProcess0(address, numBytes); | |
475 if(res != null) | |
476 return new ReadResult(res); | |
477 else | |
478 return new ReadResult(address); | |
479 } | |
480 | |
481 | |
482 private DLL findDLLByName(String fullPathName) { | |
483 for (Iterator iter = loadObjects.iterator(); iter.hasNext(); ) { | |
484 DLL dll = (DLL) iter.next(); | |
485 if (dll.getName().equals(fullPathName)) { | |
486 return dll; | |
487 } | |
488 } | |
489 return null; | |
490 } | |
491 | |
492 public void writeBytesToProcess(long address, long numBytes, byte[] data) | |
493 throws UnmappedAddressException, DebuggerException { | |
494 // FIXME | |
495 throw new DebuggerException("Unimplemented"); | |
496 } | |
497 | |
498 private static String DTFWHome; | |
499 private static String imagePath; | |
500 private static String symbolPath; | |
501 private static boolean useNativeLookup; | |
502 | |
503 static { | |
504 | |
505 /* | |
506 * sawindbg.dll depends on dbgeng.dll which | |
507 * itself depends on dbghelp.dll. dbgeng.dll and dbghelp.dll. | |
508 * On systems newer than Windows 2000, these two .dlls are | |
509 * in the standard system directory so we will find them there. | |
510 * On Windows 2000 and earlier, these files do not exist. | |
511 * The user must download Debugging Tools For Windows (DTFW) | |
512 * and install it in order to use SA. | |
513 * | |
514 * We have to make sure we use the two files from the same directory | |
515 * in case there are more than one copy on the system because | |
516 * one version of dbgeng.dll might not be compatible with a | |
517 * different version of dbghelp.dll. | |
518 * We first look for them in the directory pointed at by | |
519 * env. var. DEBUGGINGTOOLSFORWINDOWS, next in the default | |
520 * installation dir for DTFW, and lastly in the standard | |
521 * system directory. We expect that that we will find | |
522 * them in the standard system directory on all systems | |
523 * newer than Windows 2000. | |
524 */ | |
525 String dirName = null; | |
526 DTFWHome = System.getenv("DEBUGGINGTOOLSFORWINDOWS"); | |
527 | |
528 if (DTFWHome == null) { | |
529 // See if we have the files in the default location. | |
530 String sysRoot = System.getenv("SYSTEMROOT"); | |
531 DTFWHome = sysRoot + File.separator + | |
532 ".." + File.separator + "Program Files" + | |
533 File.separator + "Debugging Tools For Windows"; | |
534 } | |
535 | |
536 { | |
537 String dbghelp = DTFWHome + File.separator + "dbghelp.dll"; | |
538 String dbgeng = DTFWHome + File.separator + "dbgeng.dll"; | |
539 File fhelp = new File(dbghelp); | |
540 File feng = new File(dbgeng); | |
541 if (fhelp.exists() && feng.exists()) { | |
542 // found both, we are happy. | |
543 // NOTE: The order of loads is important! If we load dbgeng.dll | |
544 // first, then the dependency - dbghelp.dll - will be loaded | |
545 // from usual DLL search thereby defeating the purpose! | |
546 System.load(dbghelp); | |
547 System.load(dbgeng); | |
548 } else if (! fhelp.exists() && ! feng.exists()) { | |
549 // neither exist. We will ignore this dir and assume | |
550 // they are in the system dir. | |
551 DTFWHome = null; | |
552 } else { | |
553 // one exists but not the other | |
554 //System.err.println("Error: Both files dbghelp.dll and dbgeng.dll " | |
555 // "must exist in directory " + DTFWHome); | |
556 throw new UnsatisfiedLinkError("Both files dbghelp.dll and " + | |
557 "dbgeng.dll must exist in " + | |
558 "directory " + DTFWHome); | |
559 } | |
560 } | |
561 if (DTFWHome == null) { | |
562 // The files better be in the system dir. | |
563 String sysDir = System.getenv("SYSTEMROOT") + | |
564 File.separator + "system32"; | |
565 | |
566 File feng = new File(sysDir + File.separator + "dbgeng.dll"); | |
567 if (!feng.exists()) { | |
568 throw new UnsatisfiedLinkError("File dbgeng.dll does not exist in " + | |
569 sysDir + ". Please search microsoft.com " + | |
570 "for Debugging Tools For Windows, and " + | |
571 "either download it to the default " + | |
572 "location, or download it to a custom " + | |
573 "location and set environment variable " + | |
574 " DEBUGGINGTOOLSFORWINDOWS " + | |
575 "to the pathname of that location."); | |
576 } | |
577 } | |
578 | |
579 // Now, load sawindbg.dll | |
580 System.loadLibrary("sawindbg"); | |
581 // where do I find '.exe', '.dll' files? | |
582 imagePath = System.getProperty("sun.jvm.hotspot.debugger.windbg.imagePath"); | |
583 if (imagePath == null) { | |
584 imagePath = System.getenv("PATH"); | |
585 } | |
586 | |
587 // where do I find '.pdb', '.dbg' files? | |
588 symbolPath = System.getProperty("sun.jvm.hotspot.debugger.windbg.symbolPath"); | |
589 | |
590 // mostly, debug files would be find where .dll's, .exe's are found. | |
591 if (symbolPath == null) { | |
592 symbolPath = imagePath; | |
593 } | |
594 | |
595 // should we parse DLL symbol table in Java code or use | |
596 // Windbg's native lookup facility? By default, we use | |
597 // native lookup so that we can take advantage of '.pdb' | |
598 // files, if available. | |
599 useNativeLookup = true; | |
600 String str = System.getProperty("sun.jvm.hotspot.debugger.windbg.disableNativeLookup"); | |
601 if (str != null) { | |
602 useNativeLookup = false; | |
603 } | |
604 | |
605 initIDs(); | |
606 } | |
607 | |
608 // native methods | |
609 private static native void initIDs(); | |
610 private native void attach0(String executableName, String coreFileName); | |
611 private native void attach0(int processID); | |
612 private native void detach0(); | |
613 private native byte[] readBytesFromProcess0(long address, long numBytes) | |
614 throws UnmappedAddressException, DebuggerException; | |
615 private native long getThreadIdFromSysId0(long sysId); | |
616 private native String consoleExecuteCommand0(String cmd); | |
617 private native long lookupByName0(String objName, String symName); | |
618 private native ClosestSymbol lookupByAddress0(long address); | |
619 | |
620 // helper called lookupByAddress0 | |
621 private ClosestSymbol createClosestSymbol(String symbol, long diff) { | |
622 return new ClosestSymbol(symbol, diff); | |
623 } | |
624 } |