1 /*
2 * Copyright (c) 2002, 2008, 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.debugger.bsd;
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.x86.*;
32 import sun.jvm.hotspot.debugger.cdbg.*;
33 import sun.jvm.hotspot.utilities.*;
34 import java.lang.reflect.*;
35
36 /** <P> An implementation of the JVMDebugger interface. The basic debug
37 facilities are implemented through ptrace interface in the JNI code
38 (libsaproc.so). Library maps and symbol table management are done in
39 JNI. </P>
40
41 <P> <B>NOTE</B> that since we have the notion of fetching "Java
42 primitive types" from the remote process (which might have
43 different sizes than we expect) we have a bootstrapping
44 problem. We need to know the sizes of these types before we can
45 fetch them. The current implementation solves this problem by
46 requiring that it be configured with these type sizes before they
47 can be fetched. The readJ(Type) routines here will throw a
48 RuntimeException if they are called before the debugger is
49 configured with the Java primitive type sizes. </P> */
50
51 public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
52 private boolean useGCC32ABI;
53 private boolean attached;
54 private long p_ps_prochandle; // native debugger handle
55 private long symbolicator; // macosx symbolicator handle
56 private long task; // macosx task handle
57 private boolean isCore;
58
59 // CDebugger support
60 private BsdCDebugger cdbg;
61
62 // threadList and loadObjectList are filled by attach0 method
63 private List threadList;
64 private List loadObjectList;
65
66 // called by native method lookupByAddress0
67 private ClosestSymbol createClosestSymbol(String name, long offset) {
68 return new ClosestSymbol(name, offset);
69 }
70
71 // called by native method attach0
72 private LoadObject createLoadObject(String fileName, long textsize,
73 long base) {
74 File f = new File(fileName);
75 Address baseAddr = newAddress(base);
76 return new SharedObject(this, fileName, f.length(), baseAddr);
77 }
191
192 if (useCache) {
193 // FIXME: re-test necessity of cache on Bsd, where data
194 // fetching is faster
195 // Cache portion of the remote process's address space.
196 // Fetching data over the socket connection to dbx is slow.
197 // Might be faster if we were using a binary protocol to talk to
198 // dbx, but would have to test. For now, this cache works best
199 // if it covers the entire heap of the remote process. FIXME: at
200 // least should make this tunable from the outside, i.e., via
201 // the UI. This is a cache of 4096 4K pages, or 16 MB. The page
202 // size must be adjusted to be the hardware's page size.
203 // (FIXME: should pick this up from the debugger.)
204 if (getCPU().equals("ia64")) {
205 initCache(16384, parseCacheNumPagesProperty(1024));
206 } else {
207 initCache(4096, parseCacheNumPagesProperty(4096));
208 }
209 }
210
211 workerThread = new BsdDebuggerLocalWorkerThread(this);
212 workerThread.start();
213 }
214
215 /** From the Debugger interface via JVMDebugger */
216 public boolean hasProcessList() throws DebuggerException {
217 return false;
218 }
219
220 /** From the Debugger interface via JVMDebugger */
221 public List getProcessList() throws DebuggerException {
222 throw new DebuggerException("getProcessList not implemented yet");
223 }
224
225 private void checkAttached() throws DebuggerException {
226 if (attached) {
227 if (isCore) {
228 throw new DebuggerException("attached to a core dump already");
229 } else {
230 throw new DebuggerException("attached to a process already");
231 }
232 }
233 }
234
235 private void requireAttach() {
236 if (! attached) {
237 throw new RuntimeException("not attached to a process or a core!");
238 }
239 }
240
241 /* called from attach methods */
242 private void findABIVersion() throws DebuggerException {
243 if (lookupByName0("libjvm.so", "__vt_10JavaThread") != 0 ||
244 lookupByName0("libjvm_g.so", "__vt_10JavaThread") != 0) {
245 // old C++ ABI
246 useGCC32ABI = false;
247 } else {
248 // new C++ ABI
249 useGCC32ABI = true;
250 }
251 }
252
253 /** From the Debugger interface via JVMDebugger */
254 public synchronized void attach(int processID) throws DebuggerException {
255 checkAttached();
256 threadList = new ArrayList();
257 loadObjectList = new ArrayList();
258 class AttachTask implements WorkerThreadTask {
259 int pid;
260 public void doit(BsdDebuggerLocal debugger) {
261 debugger.attach0(pid);
262 debugger.attached = true;
263 debugger.isCore = false;
264 findABIVersion();
343 return null;
344 }
345
346 /* called from lookup */
347 private long handleGCC32ABI(long addr, String symbol) throws DebuggerException {
348 if (useGCC32ABI && symbol.startsWith("_ZTV")) {
349 return addr + (2 * machDesc.getAddressSize());
350 } else {
351 return addr;
352 }
353 }
354
355 /** From the SymbolLookup interface via Debugger and JVMDebugger */
356 public synchronized Address lookup(String objectName, String symbol) {
357 requireAttach();
358 if (!attached) {
359 return null;
360 }
361
362 if (isCore) {
363 long addr = lookupByName0(objectName, symbol);
364 return (addr == 0)? null : new BsdAddress(this, handleGCC32ABI(addr, symbol));
365 } else {
366 class LookupByNameTask implements WorkerThreadTask {
367 String objectName, symbol;
368 Address result;
369
370 public void doit(BsdDebuggerLocal debugger) {
371 long addr = debugger.lookupByName0(objectName, symbol);
372 result = (addr == 0 ? null : new BsdAddress(debugger, handleGCC32ABI(addr, symbol)));
373 }
374 }
375
376 LookupByNameTask task = new LookupByNameTask();
377 task.objectName = objectName;
378 task.symbol = symbol;
379 workerThread.execute(task);
380 return task.result;
381 }
382 }
383
386 Address addr = lookup(objectName, symbol);
387 if (addr == null) {
388 return null;
389 }
390 return addr.addOffsetToAsOopHandle(0);
391 }
392
393 /** From the Debugger interface */
394 public MachineDescription getMachineDescription() {
395 return machDesc;
396 }
397
398 //----------------------------------------------------------------------
399 // Implementation of ThreadAccess interface
400 //
401
402 /** From the ThreadAccess interface via Debugger and JVMDebugger */
403 public ThreadProxy getThreadForIdentifierAddress(Address threadIdAddr, Address uniqueThreadIdAddr) {
404 return new BsdThread(this, threadIdAddr, uniqueThreadIdAddr);
405 }
406 @Override
407 public ThreadProxy getThreadForIdentifierAddress(Address addr) {
408 throw new RuntimeException("unimplemented");
409 }
410
411
412 /** From the ThreadAccess interface via Debugger and JVMDebugger */
413 public ThreadProxy getThreadForThreadId(long id) {
414 return new BsdThread(this, id);
415 }
416
417 //----------------------------------------------------------------------
418 // Internal routines (for implementation of BsdAddress).
419 // These must not be called until the MachineDescription has been set up.
420 //
421
422 /** From the BsdDebugger interface */
423 public String addressValueToString(long address) {
424 return utils.addressValueToString(address);
425 }
426
427 /** From the BsdDebugger interface */
428 public BsdAddress readAddress(long address)
429 throws UnmappedAddressException, UnalignedAddressException {
430 long value = readAddressValue(address);
431 return (value == 0 ? null : new BsdAddress(this, value));
584 result = new ReadResult(res);
585 else
586 result = new ReadResult(address);
587 }
588 }
589
590 ReadBytesFromProcessTask task = new ReadBytesFromProcessTask();
591 task.address = address;
592 task.numBytes = numBytes;
593 workerThread.execute(task);
594 return task.result;
595 }
596 }
597
598 public void writeBytesToProcess(long address, long numBytes, byte[] data)
599 throws UnmappedAddressException, DebuggerException {
600 // FIXME
601 throw new DebuggerException("Unimplemented");
602 }
603
604 static {
605 System.loadLibrary("saproc");
606 init0();
607 }
608 }
|
1 /*
2 * Copyright (c) 2002, 2013, 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.debugger.bsd;
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.x86.*;
32 import sun.jvm.hotspot.debugger.cdbg.*;
33 import sun.jvm.hotspot.utilities.*;
34 import sun.jvm.hotspot.runtime.VM;
35 import sun.jvm.hotspot.runtime.Threads;
36 import sun.jvm.hotspot.runtime.JavaThread;
37 import java.lang.reflect.*;
38
39 /** <P> An implementation of the JVMDebugger interface. The basic debug
40 facilities are implemented through ptrace interface in the JNI code
41 (libsaproc.so). Library maps and symbol table management are done in
42 JNI. </P>
43
44 <P> <B>NOTE</B> that since we have the notion of fetching "Java
45 primitive types" from the remote process (which might have
46 different sizes than we expect) we have a bootstrapping
47 problem. We need to know the sizes of these types before we can
48 fetch them. The current implementation solves this problem by
49 requiring that it be configured with these type sizes before they
50 can be fetched. The readJ(Type) routines here will throw a
51 RuntimeException if they are called before the debugger is
52 configured with the Java primitive type sizes. </P> */
53
54 public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
55 private boolean useGCC32ABI;
56 private boolean attached;
57 private long p_ps_prochandle; // native debugger handle
58 private long symbolicator; // macosx symbolicator handle
59 private long task; // macosx task handle
60 private boolean isCore;
61 private boolean isDarwin; // variant for bsd
62
63 // CDebugger support
64 private BsdCDebugger cdbg;
65
66 // threadList and loadObjectList are filled by attach0 method
67 private List threadList;
68 private List loadObjectList;
69
70 // called by native method lookupByAddress0
71 private ClosestSymbol createClosestSymbol(String name, long offset) {
72 return new ClosestSymbol(name, offset);
73 }
74
75 // called by native method attach0
76 private LoadObject createLoadObject(String fileName, long textsize,
77 long base) {
78 File f = new File(fileName);
79 Address baseAddr = newAddress(base);
80 return new SharedObject(this, fileName, f.length(), baseAddr);
81 }
195
196 if (useCache) {
197 // FIXME: re-test necessity of cache on Bsd, where data
198 // fetching is faster
199 // Cache portion of the remote process's address space.
200 // Fetching data over the socket connection to dbx is slow.
201 // Might be faster if we were using a binary protocol to talk to
202 // dbx, but would have to test. For now, this cache works best
203 // if it covers the entire heap of the remote process. FIXME: at
204 // least should make this tunable from the outside, i.e., via
205 // the UI. This is a cache of 4096 4K pages, or 16 MB. The page
206 // size must be adjusted to be the hardware's page size.
207 // (FIXME: should pick this up from the debugger.)
208 if (getCPU().equals("ia64")) {
209 initCache(16384, parseCacheNumPagesProperty(1024));
210 } else {
211 initCache(4096, parseCacheNumPagesProperty(4096));
212 }
213 }
214
215 isDarwin = getOS().equals("darwin");
216 workerThread = new BsdDebuggerLocalWorkerThread(this);
217 workerThread.start();
218 }
219
220 /** From the Debugger interface via JVMDebugger */
221 public boolean hasProcessList() throws DebuggerException {
222 return false;
223 }
224
225 /** From the Debugger interface via JVMDebugger */
226 public List getProcessList() throws DebuggerException {
227 throw new DebuggerException("getProcessList not implemented yet");
228 }
229
230 private void checkAttached() throws DebuggerException {
231 if (attached) {
232 if (isCore) {
233 throw new DebuggerException("attached to a core dump already");
234 } else {
235 throw new DebuggerException("attached to a process already");
236 }
237 }
238 }
239
240 private void requireAttach() {
241 if (! attached) {
242 throw new RuntimeException("not attached to a process or a core!");
243 }
244 }
245
246 /* called from attach methods */
247 private void findABIVersion() throws DebuggerException {
248 String libjvmName = isDarwin ? "libjvm.dylib" : "libjvm.so";
249 String libjvm_gName = isDarwin? "libjvm_g.dylib" : "libjvm_g.so";
250 String javaThreadVt = isDarwin ? "_vt_10JavaThread" : "__vt_10JavaThread";
251 if (lookupByName0(libjvmName, javaThreadVt) != 0 ||
252 lookupByName0(libjvm_gName, javaThreadVt) != 0) {
253 // old C++ ABI
254 useGCC32ABI = false;
255 } else {
256 // new C++ ABI
257 useGCC32ABI = true;
258 }
259 }
260
261 /** From the Debugger interface via JVMDebugger */
262 public synchronized void attach(int processID) throws DebuggerException {
263 checkAttached();
264 threadList = new ArrayList();
265 loadObjectList = new ArrayList();
266 class AttachTask implements WorkerThreadTask {
267 int pid;
268 public void doit(BsdDebuggerLocal debugger) {
269 debugger.attach0(pid);
270 debugger.attached = true;
271 debugger.isCore = false;
272 findABIVersion();
351 return null;
352 }
353
354 /* called from lookup */
355 private long handleGCC32ABI(long addr, String symbol) throws DebuggerException {
356 if (useGCC32ABI && symbol.startsWith("_ZTV")) {
357 return addr + (2 * machDesc.getAddressSize());
358 } else {
359 return addr;
360 }
361 }
362
363 /** From the SymbolLookup interface via Debugger and JVMDebugger */
364 public synchronized Address lookup(String objectName, String symbol) {
365 requireAttach();
366 if (!attached) {
367 return null;
368 }
369
370 if (isCore) {
371 // MacOSX symbol with "_" as leading
372 long addr = lookupByName0(objectName, isDarwin ? "_" + symbol : symbol);
373 return (addr == 0)? null : new BsdAddress(this, handleGCC32ABI(addr, symbol));
374 } else {
375 class LookupByNameTask implements WorkerThreadTask {
376 String objectName, symbol;
377 Address result;
378
379 public void doit(BsdDebuggerLocal debugger) {
380 long addr = debugger.lookupByName0(objectName, symbol);
381 result = (addr == 0 ? null : new BsdAddress(debugger, handleGCC32ABI(addr, symbol)));
382 }
383 }
384
385 LookupByNameTask task = new LookupByNameTask();
386 task.objectName = objectName;
387 task.symbol = symbol;
388 workerThread.execute(task);
389 return task.result;
390 }
391 }
392
395 Address addr = lookup(objectName, symbol);
396 if (addr == null) {
397 return null;
398 }
399 return addr.addOffsetToAsOopHandle(0);
400 }
401
402 /** From the Debugger interface */
403 public MachineDescription getMachineDescription() {
404 return machDesc;
405 }
406
407 //----------------------------------------------------------------------
408 // Implementation of ThreadAccess interface
409 //
410
411 /** From the ThreadAccess interface via Debugger and JVMDebugger */
412 public ThreadProxy getThreadForIdentifierAddress(Address threadIdAddr, Address uniqueThreadIdAddr) {
413 return new BsdThread(this, threadIdAddr, uniqueThreadIdAddr);
414 }
415
416 @Override
417 public ThreadProxy getThreadForIdentifierAddress(Address addr) {
418 throw new RuntimeException("unimplemented");
419 }
420
421 /** From the ThreadAccess interface via Debugger and JVMDebugger */
422 public ThreadProxy getThreadForThreadId(long id) {
423 return new BsdThread(this, id);
424 }
425
426 //----------------------------------------------------------------------
427 // Internal routines (for implementation of BsdAddress).
428 // These must not be called until the MachineDescription has been set up.
429 //
430
431 /** From the BsdDebugger interface */
432 public String addressValueToString(long address) {
433 return utils.addressValueToString(address);
434 }
435
436 /** From the BsdDebugger interface */
437 public BsdAddress readAddress(long address)
438 throws UnmappedAddressException, UnalignedAddressException {
439 long value = readAddressValue(address);
440 return (value == 0 ? null : new BsdAddress(this, value));
593 result = new ReadResult(res);
594 else
595 result = new ReadResult(address);
596 }
597 }
598
599 ReadBytesFromProcessTask task = new ReadBytesFromProcessTask();
600 task.address = address;
601 task.numBytes = numBytes;
602 workerThread.execute(task);
603 return task.result;
604 }
605 }
606
607 public void writeBytesToProcess(long address, long numBytes, byte[] data)
608 throws UnmappedAddressException, DebuggerException {
609 // FIXME
610 throw new DebuggerException("Unimplemented");
611 }
612
613 /** this functions used for core file reading and called from native attach0,
614 it returns an array of long integers as
615 [thread_id, stack_start, stack_end, thread_id, stack_start, stack_end, ....] for
616 all java threads recorded in Threads. Also adds the ThreadProxy to threadList */
617 public long[] getJavaThreadsInfo() {
618 requireAttach();
619 Threads threads = VM.getVM().getThreads();
620 int len = threads.getNumberOfThreads();
621 long[] result = new long[len * 3]; // triple
622 JavaThread t = threads.first();
623 long beg, end;
624 int i = 0;
625 while (t != null) {
626 end = t.getStackBaseValue();
627 beg = end - t.getStackSize();
628 BsdThread bsdt = (BsdThread)t.getThreadProxy();
629 long uid = bsdt.getUniqueThreadId();
630 if (threadList != null) threadList.add(bsdt);
631 result[i] = uid;
632 result[i + 1] = beg;
633 result[i + 2] = end;
634 t = t.next();
635 i += 3;
636 }
637 return result;
638 }
639
640 static {
641 System.loadLibrary("saproc");
642 init0();
643 }
644 }
|