8181313: SA: Remove libthread_db dependency on Linux
authorysuenaga
Fri, 18 Jan 2019 14:43:25 +0900
changeset 53379 e47074d2d8cc
parent 53378 52abdb8a48b2
child 53380 c8208421a860
8181313: SA: Remove libthread_db dependency on Linux Reviewed-by: jgeorge, sballal
make/lib/Lib-jdk.hotspot.agent.gmk
src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c
src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h
src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c
src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.h
src/jdk.hotspot.agent/linux/native/libsaproc/proc_service.h
src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c
src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c
src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java
--- a/make/lib/Lib-jdk.hotspot.agent.gmk	Thu Jan 17 14:56:18 2019 -0800
+++ b/make/lib/Lib-jdk.hotspot.agent.gmk	Fri Jan 18 14:43:25 2019 +0900
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -66,7 +66,7 @@
     CXXFLAGS := $(CXXFLAGS_JDKLIB) $(SA_CFLAGS) $(SA_CXXFLAGS), \
     EXTRA_SRC := $(LIBSA_EXTRA_SRC), \
     LDFLAGS := $(LDFLAGS_JDKLIB) $(SA_LDFLAGS), \
-    LIBS_linux := -lthread_db $(LIBDL), \
+    LIBS_linux := $(LIBDL), \
     LIBS_solaris := -ldl -ldemangle -lthread -lproc, \
     LIBS_macosx := -framework Foundation -framework JavaNativeFoundation \
         -framework JavaRuntimeSupport -framework Security -framework CoreFoundation, \
--- a/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c	Thu Jan 17 14:56:18 2019 -0800
+++ b/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c	Fri Jan 18 14:43:25 2019 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 
 #include <jni.h>
 #include "libproc.h"
+#include "proc_service.h"
 
 #include <elf.h>
 #include <sys/types.h>
@@ -241,10 +242,10 @@
 /*
  * Class:     sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal
  * Method:    attach0
- * Signature: (IZ)V
+ * Signature: (I)V
  */
-JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_attach0__IZ
-  (JNIEnv *env, jobject this_obj, jint jpid, jboolean is_in_container) {
+JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_attach0__I
+  (JNIEnv *env, jobject this_obj, jint jpid) {
 
   // For bitness checking, locate binary at /proc/jpid/exe
   char buf[PATH_MAX];
@@ -254,7 +255,7 @@
 
   char err_buf[200];
   struct ps_prochandle* ph;
-  if ((ph = Pgrab(jpid, err_buf, sizeof(err_buf), is_in_container)) == NULL) {
+  if ((ph = Pgrab(jpid, err_buf, sizeof(err_buf))) == NULL) {
     char msg[230];
     snprintf(msg, sizeof(msg), "Can't attach to the process: %s", err_buf);
     THROW_NEW_DEBUGGER_EXCEPTION(msg);
--- a/src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h	Thu Jan 17 14:56:18 2019 -0800
+++ b/src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h	Fri Jan 18 14:43:25 2019 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,41 +28,10 @@
 #include <jni.h>
 #include <unistd.h>
 #include <stdint.h>
-#include "proc_service.h"
 
+#include <sys/procfs.h>
 #include <sys/ptrace.h>
 
-/************************************************************************************
-
-0. This is very minimal subset of Solaris libproc just enough for current application.
-Please note that the bulk of the functionality is from proc_service interface. This
-adds Pgrab__ and some missing stuff. We hide the difference b/w live process and core
-file by this interface.
-
-1. pthread_id unique in both NPTL & LinuxThreads. We store this in
-OSThread::_pthread_id in JVM code.
-
-2. All threads see the same pid when they call getpid() under NPTL.
-Threads receive different pid under LinuxThreads. We used to save the result of
-::getpid() call in OSThread::_thread_id. This way uniqueness of OSThread::_thread_id
-was lost under NPTL. Now, we store the result of ::gettid() call in
-OSThread::_thread_id. Because gettid returns actual pid of thread (lwp id), this is
-unique again. We therefore use OSThread::_thread_id as unique identifier.
-
-3. There is a unique LWP id under both thread libraries. libthread_db  maps pthread_id
-to its underlying lwp_id under both the thread libraries. thread_info.lwp_id stores
-lwp_id of the thread. The lwp id is nothing but the actual pid of clone'd processes. But
-unfortunately libthread_db does not work very well for core dumps. So, we get pthread_id
-only for processes. For core dumps, we don't use libthread_db at all (like gdb).
-
-4. ptrace operates on this LWP id under both the thread libraries. When we say 'pid' for
-ptrace call, we refer to lwp_id of the thread.
-
-5. for core file, we parse ELF files and read data from them. For processes we  use
-combination of ptrace and /proc calls.
-
-*************************************************************************************/
-
 
 #if defined(sparc) || defined(sparcv9) || defined(ppc64) || defined(ppc64le)
 #include <asm/ptrace.h>
@@ -87,7 +56,7 @@
 
 // attach to a process
 JNIEXPORT struct ps_prochandle* JNICALL
-Pgrab(pid_t pid, char* err_buf, size_t err_buf_len, bool is_in_container);
+Pgrab(pid_t pid, char* err_buf, size_t err_buf_len);
 
 // attach to a core dump
 JNIEXPORT struct ps_prochandle* JNICALL
--- a/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c	Thu Jan 17 14:56:18 2019 -0800
+++ b/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c	Fri Jan 18 14:43:25 2019 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,8 +26,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include <fcntl.h>
-#include <thread_db.h>
+#include <sys/procfs.h>
 #include "libproc_impl.h"
+#include "proc_service.h"
 
 #define SA_ALTROOT "SA_ALTROOT"
 
@@ -116,13 +117,6 @@
 init_libproc(bool debug) {
    // init debug mode
    _libsaproc_debug = debug;
-
-   // initialize the thread_db library
-   if (td_init() != TD_OK) {
-     print_debug("libthread_db's td_init failed\n");
-     return false;
-   }
-
    return true;
 }
 
@@ -256,7 +250,7 @@
 }
 
 // add a thread to ps_prochandle
-thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
+thread_info* add_thread_info(struct ps_prochandle* ph, lwpid_t lwp_id) {
    thread_info* newthr;
    if ( (newthr = (thread_info*) calloc(1, sizeof(thread_info))) == NULL) {
       print_debug("can't allocate memory for thread_info\n");
@@ -264,7 +258,6 @@
    }
 
    // initialize thread info
-   newthr->pthread_id = pthread_id;
    newthr->lwp_id = lwp_id;
 
    // add new thread to the list
@@ -295,64 +288,6 @@
     free(current_thr);
 }
 
-// struct used for client data from thread_db callback
-struct thread_db_client_data {
-   struct ps_prochandle* ph;
-   thread_info_callback callback;
-};
-
-// callback function for libthread_db
-static int thread_db_callback(const td_thrhandle_t *th_p, void *data) {
-  struct thread_db_client_data* ptr = (struct thread_db_client_data*) data;
-  td_thrinfo_t ti;
-  td_err_e err;
-
-  memset(&ti, 0, sizeof(ti));
-  err = td_thr_get_info(th_p, &ti);
-  if (err != TD_OK) {
-    print_debug("libthread_db : td_thr_get_info failed, can't get thread info\n");
-    return err;
-  }
-
-  print_debug("thread_db : pthread %d (lwp %d)\n", ti.ti_tid, ti.ti_lid);
-
-  if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE) {
-    print_debug("Skipping pthread %d (lwp %d)\n", ti.ti_tid, ti.ti_lid);
-    return TD_OK;
-  }
-
-  if (ptr->callback(ptr->ph, ti.ti_tid, ti.ti_lid) != true)
-    return TD_ERR;
-
-  return TD_OK;
-}
-
-// read thread_info using libthread_db
-bool read_thread_info(struct ps_prochandle* ph, thread_info_callback cb) {
-  struct thread_db_client_data mydata;
-  td_thragent_t* thread_agent = NULL;
-  if (td_ta_new(ph, &thread_agent) != TD_OK) {
-     print_debug("can't create libthread_db agent\n");
-     return false;
-  }
-
-  mydata.ph = ph;
-  mydata.callback = cb;
-
-  // we use libthread_db iterator to iterate thru list of threads.
-  if (td_ta_thr_iter(thread_agent, thread_db_callback, &mydata,
-                 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
-                 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS) != TD_OK) {
-     td_ta_delete(thread_agent);
-     return false;
-  }
-
-  // delete thread agent
-  td_ta_delete(thread_agent);
-  return true;
-}
-
-
 // get number of threads
 int get_num_threads(struct ps_prochandle* ph) {
    return ph->num_threads;
@@ -484,9 +419,3 @@
   return PS_OK;
 }
 
-// new libthread_db of NPTL seem to require this symbol
-JNIEXPORT ps_err_e JNICALL
-ps_get_thread_area() {
-  print_debug("ps_get_thread_area not implemented\n");
-  return PS_OK;
-}
--- a/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.h	Thu Jan 17 14:56:18 2019 -0800
+++ b/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.h	Fri Jan 18 14:43:25 2019 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,7 +46,6 @@
 // list of threads
 typedef struct thread_info {
    lwpid_t                  lwp_id;
-   pthread_t                pthread_id; // not used cores, always -1
    struct user_regs_struct  regs;       // not for process, core uses for caching regset
    struct thread_info*      next;
 } thread_info;
@@ -108,11 +107,6 @@
 void print_error(const char* format,...);
 bool is_debug();
 
-typedef bool (*thread_info_callback)(struct ps_prochandle* ph, pthread_t pid, lwpid_t lwpid);
-
-// reads thread info using libthread_db and calls above callback for each thread
-bool read_thread_info(struct ps_prochandle* ph, thread_info_callback cb);
-
 // deletes a thread from the thread list
 void delete_thread_info(struct ps_prochandle* ph, thread_info* thr);
 
@@ -124,7 +118,7 @@
                           uintptr_t base);
 
 // adds a new thread to threads list, returns NULL on failure
-thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id);
+thread_info* add_thread_info(struct ps_prochandle* ph, lwpid_t lwp_id);
 
 // a test for ELF signature without using libelf
 bool is_elf_file(int fd);
--- a/src/jdk.hotspot.agent/linux/native/libsaproc/proc_service.h	Thu Jan 17 14:56:18 2019 -0800
+++ b/src/jdk.hotspot.agent/linux/native/libsaproc/proc_service.h	Fri Jan 18 14:43:25 2019 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,12 +26,10 @@
 #define _PROC_SERVICE_H_
 
 #include <stdio.h>
-#include <thread_db.h>
+#include <sys/procfs.h>
 #include "jni.h"
+#include "libproc.h"
 
-// Linux does not have the proc service library, though it does provide the
-// thread_db library which can be used to manipulate threads without having
-// to know the details of NPTL
 
 // copied from Solaris "proc_service.h"
 typedef enum {
@@ -79,8 +77,4 @@
 JNIEXPORT ps_err_e JNICALL
 ps_lgetregs(struct ps_prochandle *ph, lwpid_t lid, prgregset_t gregset);
 
-// new libthread_db of NPTL seem to require this symbol
-JNIEXPORT ps_err_e JNICALL
-ps_get_thread_area();
-
 #endif /* _PROC_SERVICE_H_ */
--- a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c	Thu Jan 17 14:56:18 2019 -0800
+++ b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c	Fri Jan 18 14:43:25 2019 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,7 @@
 #include <elf.h>
 #include <link.h>
 #include "libproc_impl.h"
+#include "proc_service.h"
 #include "salibelf.h"
 #include "cds.h"
 
@@ -510,8 +511,7 @@
    prstatus_t* prstat = (prstatus_t*) buf;
    thread_info* newthr;
    print_debug("got integer regset for lwp %d\n", prstat->pr_pid);
-   // we set pthread_t to -1 for core dump
-   if((newthr = add_thread_info(ph, (pthread_t) -1,  prstat->pr_pid)) == NULL)
+   if((newthr = add_thread_info(ph, prstat->pr_pid)) == NULL)
       return false;
 
    // copy regs
--- a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c	Thu Jan 17 14:56:18 2019 -0800
+++ b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c	Fri Jan 18 14:43:25 2019 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -339,11 +339,6 @@
    return rslt;
 }
 
-// callback for read_thread_info
-static bool add_new_thread(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
-  return add_thread_info(ph, pthread_id, lwp_id) != NULL;
-}
-
 static bool read_lib_info(struct ps_prochandle* ph) {
   char fname[32];
   char buf[PATH_MAX];
@@ -443,7 +438,7 @@
 
 // attach to the process. One and only one exposed stuff
 JNIEXPORT struct ps_prochandle* JNICALL
-Pgrab(pid_t pid, char* err_buf, size_t err_buf_len, bool is_in_container) {
+Pgrab(pid_t pid, char* err_buf, size_t err_buf_len) {
   struct ps_prochandle* ph = NULL;
   thread_info* thr = NULL;
   attach_state_t attach_status = ATTACH_SUCCESS;
@@ -464,6 +459,7 @@
 
   // initialize ps_prochandle
   ph->pid = pid;
+  add_thread_info(ph, ph->pid);
 
   // initialize vtable
   ph->ops = &process_ops;
@@ -473,33 +469,30 @@
   // the list of threads within the same process.
   read_lib_info(ph);
 
-  // read thread info
-  if (is_in_container) {
-    /*
-     * If the process is running in the container, SA scans all tasks in
-     * /proc/<PID>/task to read all threads info.
-     */
-    char taskpath[PATH_MAX];
-    DIR *dirp;
-    struct dirent *entry;
+  /*
+   * Read thread info.
+   * SA scans all tasks in /proc/<PID>/task to read all threads info.
+   */
+  char taskpath[PATH_MAX];
+  DIR *dirp;
+  struct dirent *entry;
 
-    snprintf(taskpath, PATH_MAX, "/proc/%d/task", ph->pid);
-    dirp = opendir(taskpath);
-    int lwp_id;
-    while ((entry = readdir(dirp)) != NULL) {
-      if (*entry->d_name == '.') {
-        continue;
-      }
-      lwp_id = atoi(entry->d_name);
-      if (lwp_id == ph->pid) {
-        continue;
-      }
-      add_new_thread(ph, -1, lwp_id);
+  snprintf(taskpath, PATH_MAX, "/proc/%d/task", ph->pid);
+  dirp = opendir(taskpath);
+  int lwp_id;
+  while ((entry = readdir(dirp)) != NULL) {
+    if (*entry->d_name == '.') {
+      continue;
     }
-    closedir(dirp);
-  } else {
-    read_thread_info(ph, add_new_thread);
+    lwp_id = atoi(entry->d_name);
+    if (lwp_id == ph->pid) {
+      continue;
+    }
+    if (!process_doesnt_exist(lwp_id)) {
+      add_thread_info(ph, lwp_id);
+    }
   }
+  closedir(dirp);
 
   // attach to the threads
   thr = ph->threads;
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java	Thu Jan 17 14:56:18 2019 -0800
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java	Fri Jan 18 14:43:25 2019 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -102,7 +102,7 @@
     private native static void init0()
                                 throws DebuggerException;
     private native void setSAAltRoot0(String altroot);
-    private native void attach0(int pid, boolean isInContainer)
+    private native void attach0(int pid)
                                 throws DebuggerException;
     private native void attach0(String execName, String coreName)
                                 throws DebuggerException;
@@ -321,9 +321,8 @@
 
         class AttachTask implements WorkerThreadTask {
            int pid;
-           boolean isInContainer;
            public void doit(LinuxDebuggerLocal debugger) {
-              debugger.attach0(pid, isInContainer);
+              debugger.attach0(pid);
               debugger.attached = true;
               debugger.isCore = false;
               findABIVersion();
@@ -332,7 +331,6 @@
 
         AttachTask task = new AttachTask();
         task.pid = processID;
-        task.isInContainer = (processID != NSpid);
         workerThread.execute(task);
     }