src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java
changeset 51203 220c9188db4f
parent 48166 2659c4fe8ea7
child 53379 e47074d2d8cc
equal deleted inserted replaced
51202:59b0d8afc831 51203:220c9188db4f
     1 /*
     1 /*
     2  * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
     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.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    23  */
    23  */
    24 
    24 
    25 package sun.jvm.hotspot.debugger.linux;
    25 package sun.jvm.hotspot.debugger.linux;
    26 
    26 
    27 import java.io.File;
    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;
    28 import java.util.ArrayList;
    33 import java.util.ArrayList;
    29 import java.util.List;
    34 import java.util.List;
       
    35 import java.util.Map;
       
    36 import java.util.NoSuchElementException;
       
    37 import java.util.stream.Collectors;
    30 
    38 
    31 import sun.jvm.hotspot.debugger.Address;
    39 import sun.jvm.hotspot.debugger.Address;
    32 import sun.jvm.hotspot.debugger.DebuggerBase;
    40 import sun.jvm.hotspot.debugger.DebuggerBase;
    33 import sun.jvm.hotspot.debugger.DebuggerException;
    41 import sun.jvm.hotspot.debugger.DebuggerException;
    34 import sun.jvm.hotspot.debugger.DebuggerUtilities;
    42 import sun.jvm.hotspot.debugger.DebuggerUtilities;
    70 
    78 
    71     // threadList and loadObjectList are filled by attach0 method
    79     // threadList and loadObjectList are filled by attach0 method
    72     private List threadList;
    80     private List threadList;
    73     private List loadObjectList;
    81     private List loadObjectList;
    74 
    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 
    75     // called by native method lookupByAddress0
    87     // called by native method lookupByAddress0
    76     private ClosestSymbol createClosestSymbol(String name, long offset) {
    88     private ClosestSymbol createClosestSymbol(String name, long offset) {
    77        return new ClosestSymbol(name, offset);
    89        return new ClosestSymbol(name, offset);
    78     }
    90     }
    79 
    91 
    87 
    99 
    88     // native methods
   100     // native methods
    89 
   101 
    90     private native static void init0()
   102     private native static void init0()
    91                                 throws DebuggerException;
   103                                 throws DebuggerException;
    92     private native void attach0(int pid)
   104     private native void setSAAltRoot0(String altroot);
       
   105     private native void attach0(int pid, boolean isInContainer)
    93                                 throws DebuggerException;
   106                                 throws DebuggerException;
    94     private native void attach0(String execName, String coreName)
   107     private native void attach0(String execName, String coreName)
    95                                 throws DebuggerException;
   108                                 throws DebuggerException;
    96     private native void detach0()
   109     private native void detach0()
    97                                 throws DebuggerException;
   110                                 throws DebuggerException;
   252             // new C++ ABI
   265             // new C++ ABI
   253             useGCC32ABI = true;
   266             useGCC32ABI = true;
   254         }
   267         }
   255     }
   268     }
   256 
   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 
   257     /** From the Debugger interface via JVMDebugger */
   305     /** From the Debugger interface via JVMDebugger */
   258     public synchronized void attach(int processID) throws DebuggerException {
   306     public synchronized void attach(int processID) throws DebuggerException {
   259         checkAttached();
   307         checkAttached();
   260         threadList = new ArrayList();
   308         threadList = new ArrayList();
   261         loadObjectList = 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 
   262         class AttachTask implements WorkerThreadTask {
   322         class AttachTask implements WorkerThreadTask {
   263            int pid;
   323            int pid;
       
   324            boolean isInContainer;
   264            public void doit(LinuxDebuggerLocal debugger) {
   325            public void doit(LinuxDebuggerLocal debugger) {
   265               debugger.attach0(pid);
   326               debugger.attach0(pid, isInContainer);
   266               debugger.attached = true;
   327               debugger.attached = true;
   267               debugger.isCore = false;
   328               debugger.isCore = false;
   268               findABIVersion();
   329               findABIVersion();
   269            }
   330            }
   270         }
   331         }
   271 
   332 
   272         AttachTask task = new AttachTask();
   333         AttachTask task = new AttachTask();
   273         task.pid = processID;
   334         task.pid = processID;
       
   335         task.isInContainer = (processID != NSpid);
   274         workerThread.execute(task);
   336         workerThread.execute(task);
   275     }
   337     }
   276 
   338 
   277     /** From the Debugger interface via JVMDebugger */
   339     /** From the Debugger interface via JVMDebugger */
   278     public synchronized void attach(String execName, String coreName) {
   340     public synchronized void attach(String execName, String coreName) {