< prev index next >

src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java

Print this page


   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 


< prev index next >