1 /*
2 * Copyright (c) 2002, 2017, 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.linux;
26
27 import java.io.File;
28 import java.util.ArrayList;
29 import java.util.List;
30
31 import sun.jvm.hotspot.debugger.Address;
32 import sun.jvm.hotspot.debugger.DebuggerBase;
33 import sun.jvm.hotspot.debugger.DebuggerException;
34 import sun.jvm.hotspot.debugger.DebuggerUtilities;
35 import sun.jvm.hotspot.debugger.MachineDescription;
36 import sun.jvm.hotspot.debugger.NotInHeapException;
37 import sun.jvm.hotspot.debugger.OopHandle;
38 import sun.jvm.hotspot.debugger.ReadResult;
39 import sun.jvm.hotspot.debugger.ThreadProxy;
40 import sun.jvm.hotspot.debugger.UnalignedAddressException;
41 import sun.jvm.hotspot.debugger.UnmappedAddressException;
42 import sun.jvm.hotspot.debugger.cdbg.CDebugger;
43 import sun.jvm.hotspot.debugger.cdbg.ClosestSymbol;
44 import sun.jvm.hotspot.debugger.cdbg.LoadObject;
45 import sun.jvm.hotspot.utilities.PlatformInfo;
46
47 /** <P> An implementation of the JVMDebugger interface. The basic debug
48 facilities are implemented through ptrace interface in the JNI code
49 (libsaproc.so). Library maps and symbol table management are done in
55 problem. We need to know the sizes of these types before we can
56 fetch them. The current implementation solves this problem by
57 requiring that it be configured with these type sizes before they
58 can be fetched. The readJ(Type) routines here will throw a
59 RuntimeException if they are called before the debugger is
60 configured with the Java primitive type sizes. </P> */
61
62 public class LinuxDebuggerLocal extends DebuggerBase implements LinuxDebugger {
63 private boolean useGCC32ABI;
64 private boolean attached;
65 private long p_ps_prochandle; // native debugger handle
66 private boolean isCore;
67
68 // CDebugger support
69 private LinuxCDebugger cdbg;
70
71 // threadList and loadObjectList are filled by attach0 method
72 private List threadList;
73 private List loadObjectList;
74
75 // called by native method lookupByAddress0
76 private ClosestSymbol createClosestSymbol(String name, long offset) {
77 return new ClosestSymbol(name, offset);
78 }
79
80 // called by native method attach0
81 private LoadObject createLoadObject(String fileName, long textsize,
82 long base) {
83 File f = new File(fileName);
84 Address baseAddr = newAddress(base);
85 return new SharedObject(this, fileName, f.length(), baseAddr);
86 }
87
88 // native methods
89
90 private native static void init0()
91 throws DebuggerException;
92 private native void attach0(int pid)
93 throws DebuggerException;
94 private native void attach0(String execName, String coreName)
95 throws DebuggerException;
96 private native void detach0()
97 throws DebuggerException;
98 private native long lookupByName0(String objectName, String symbol)
99 throws DebuggerException;
100 private native ClosestSymbol lookupByAddress0(long address)
101 throws DebuggerException;
102 private native long[] getThreadIntegerRegisterSet0(int lwp_id)
103 throws DebuggerException;
104 private native byte[] readBytesFromProcess0(long address, long numBytes)
105 throws DebuggerException;
106 public native static int getAddressSize() ;
107
108 // Note on Linux threads are really processes. When target process is
109 // attached by a serviceability agent thread, only that thread can do
110 // ptrace operations on the target. This is because from kernel's point
111 // view, other threads are just separate processes and they are not
112 // attached to the target. When they attempt to make ptrace calls,
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 if (lookupByName0("libjvm.so", "__vt_10JavaThread") != 0) {
249 // old C++ ABI
250 useGCC32ABI = false;
251 } else {
252 // new C++ ABI
253 useGCC32ABI = true;
254 }
255 }
256
257 /** From the Debugger interface via JVMDebugger */
258 public synchronized void attach(int processID) throws DebuggerException {
259 checkAttached();
260 threadList = new ArrayList();
261 loadObjectList = new ArrayList();
262 class AttachTask implements WorkerThreadTask {
263 int pid;
264 public void doit(LinuxDebuggerLocal debugger) {
265 debugger.attach0(pid);
266 debugger.attached = true;
267 debugger.isCore = false;
268 findABIVersion();
269 }
270 }
271
272 AttachTask task = new AttachTask();
273 task.pid = processID;
274 workerThread.execute(task);
275 }
276
277 /** From the Debugger interface via JVMDebugger */
278 public synchronized void attach(String execName, String coreName) {
279 checkAttached();
280 threadList = new ArrayList();
281 loadObjectList = new ArrayList();
282 attach0(execName, coreName);
283 attached = true;
284 isCore = true;
285 findABIVersion();
286 }
287
288 /** From the Debugger interface via JVMDebugger */
289 public synchronized boolean detach() {
290 if (!attached) {
291 return false;
292 }
293
|
1 /*
2 * Copyright (c) 2002, 2018, 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.linux;
26
27 import java.io.File;
28 import java.io.IOException;
29 import java.io.UncheckedIOException;
30 import java.nio.file.Files;
31 import java.nio.file.Path;
32 import java.nio.file.Paths;
33 import java.util.ArrayList;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.NoSuchElementException;
37 import java.util.stream.Collectors;
38
39 import sun.jvm.hotspot.debugger.Address;
40 import sun.jvm.hotspot.debugger.DebuggerBase;
41 import sun.jvm.hotspot.debugger.DebuggerException;
42 import sun.jvm.hotspot.debugger.DebuggerUtilities;
43 import sun.jvm.hotspot.debugger.MachineDescription;
44 import sun.jvm.hotspot.debugger.NotInHeapException;
45 import sun.jvm.hotspot.debugger.OopHandle;
46 import sun.jvm.hotspot.debugger.ReadResult;
47 import sun.jvm.hotspot.debugger.ThreadProxy;
48 import sun.jvm.hotspot.debugger.UnalignedAddressException;
49 import sun.jvm.hotspot.debugger.UnmappedAddressException;
50 import sun.jvm.hotspot.debugger.cdbg.CDebugger;
51 import sun.jvm.hotspot.debugger.cdbg.ClosestSymbol;
52 import sun.jvm.hotspot.debugger.cdbg.LoadObject;
53 import sun.jvm.hotspot.utilities.PlatformInfo;
54
55 /** <P> An implementation of the JVMDebugger interface. The basic debug
56 facilities are implemented through ptrace interface in the JNI code
57 (libsaproc.so). Library maps and symbol table management are done in
63 problem. We need to know the sizes of these types before we can
64 fetch them. The current implementation solves this problem by
65 requiring that it be configured with these type sizes before they
66 can be fetched. The readJ(Type) routines here will throw a
67 RuntimeException if they are called before the debugger is
68 configured with the Java primitive type sizes. </P> */
69
70 public class LinuxDebuggerLocal extends DebuggerBase implements LinuxDebugger {
71 private boolean useGCC32ABI;
72 private boolean attached;
73 private long p_ps_prochandle; // native debugger handle
74 private boolean isCore;
75
76 // CDebugger support
77 private LinuxCDebugger cdbg;
78
79 // threadList and loadObjectList are filled by attach0 method
80 private List threadList;
81 private List loadObjectList;
82
83 // PID namespace support
84 // It maps the LWPID in the host to the LWPID in the container.
85 private Map<Integer, Integer> nspidMap;
86
87 // called by native method lookupByAddress0
88 private ClosestSymbol createClosestSymbol(String name, long offset) {
89 return new ClosestSymbol(name, offset);
90 }
91
92 // called by native method attach0
93 private LoadObject createLoadObject(String fileName, long textsize,
94 long base) {
95 File f = new File(fileName);
96 Address baseAddr = newAddress(base);
97 return new SharedObject(this, fileName, f.length(), baseAddr);
98 }
99
100 // native methods
101
102 private native static void init0()
103 throws DebuggerException;
104 private native void setSAAltRoot0(String altroot);
105 private native void attach0(int pid, boolean isInContainer)
106 throws DebuggerException;
107 private native void attach0(String execName, String coreName)
108 throws DebuggerException;
109 private native void detach0()
110 throws DebuggerException;
111 private native long lookupByName0(String objectName, String symbol)
112 throws DebuggerException;
113 private native ClosestSymbol lookupByAddress0(long address)
114 throws DebuggerException;
115 private native long[] getThreadIntegerRegisterSet0(int lwp_id)
116 throws DebuggerException;
117 private native byte[] readBytesFromProcess0(long address, long numBytes)
118 throws DebuggerException;
119 public native static int getAddressSize() ;
120
121 // Note on Linux threads are really processes. When target process is
122 // attached by a serviceability agent thread, only that thread can do
123 // ptrace operations on the target. This is because from kernel's point
124 // view, other threads are just separate processes and they are not
125 // attached to the target. When they attempt to make ptrace calls,
250 }
251 }
252
253 private void requireAttach() {
254 if (! attached) {
255 throw new RuntimeException("not attached to a process or a core!");
256 }
257 }
258
259 /* called from attach methods */
260 private void findABIVersion() throws DebuggerException {
261 if (lookupByName0("libjvm.so", "__vt_10JavaThread") != 0) {
262 // old C++ ABI
263 useGCC32ABI = false;
264 } else {
265 // new C++ ABI
266 useGCC32ABI = true;
267 }
268 }
269
270 // Get namespace PID from /proc/<PID>/status.
271 private int getNamespacePID(Path statusPath) {
272 try (var lines = Files.lines(statusPath)) {
273 return lines.map(s -> s.split("\\s+"))
274 .filter(a -> a.length == 3)
275 .filter(a -> a[0].equals("NSpid:"))
276 .mapToInt(a -> Integer.valueOf(a[2]))
277 .findFirst()
278 .getAsInt();
279 } catch (IOException | NoSuchElementException e) {
280 return Integer.valueOf(statusPath.getParent()
281 .toFile()
282 .getName());
283 }
284 }
285
286 // Get LWPID in the host from the container's LWPID.
287 // Returns -1 if the process is running in the host.
288 public int getHostPID(int id) {
289 return (nspidMap == null) ? -1 : nspidMap.get(id);
290 }
291
292 // Fill namespace PID map from procfs.
293 // This method scans all tasks (/proc/<PID>/task) in the process.
294 private void fillNSpidMap(Path proc) {
295 Path task = Paths.get(proc.toString(), "task");
296 try (var tasks = Files.list(task)) {
297 nspidMap = tasks.filter(p -> !p.toString().startsWith("."))
298 .collect(Collectors.toMap(p -> Integer.valueOf(getNamespacePID(Paths.get(p.toString(), "status"))),
299 p -> Integer.valueOf(p.toFile().getName())));
300 } catch (IOException e) {
301 throw new UncheckedIOException(e);
302 }
303 }
304
305 /** From the Debugger interface via JVMDebugger */
306 public synchronized void attach(int processID) throws DebuggerException {
307 checkAttached();
308 threadList = new ArrayList();
309 loadObjectList = new ArrayList();
310
311 Path proc = Paths.get("/proc", Integer.toString(processID));
312 int NSpid = getNamespacePID(Paths.get(proc.toString(), "status"));
313 if (NSpid != processID) {
314 // If PID different from namespace PID, we can assume the process
315 // is running in the container.
316 // So we need to set SA_ALTROOT environment variable that SA reads
317 // binaries in the container.
318 setSAAltRoot0(Paths.get(proc.toString(), "root").toString());
319 fillNSpidMap(proc);
320 }
321
322 class AttachTask implements WorkerThreadTask {
323 int pid;
324 boolean isInContainer;
325 public void doit(LinuxDebuggerLocal debugger) {
326 debugger.attach0(pid, isInContainer);
327 debugger.attached = true;
328 debugger.isCore = false;
329 findABIVersion();
330 }
331 }
332
333 AttachTask task = new AttachTask();
334 task.pid = processID;
335 task.isInContainer = (processID != NSpid);
336 workerThread.execute(task);
337 }
338
339 /** From the Debugger interface via JVMDebugger */
340 public synchronized void attach(String execName, String coreName) {
341 checkAttached();
342 threadList = new ArrayList();
343 loadObjectList = new ArrayList();
344 attach0(execName, coreName);
345 attached = true;
346 isCore = true;
347 findABIVersion();
348 }
349
350 /** From the Debugger interface via JVMDebugger */
351 public synchronized boolean detach() {
352 if (!attached) {
353 return false;
354 }
355
|