Skip to content

Commit 0605504

Browse files
committed
8181313: SA: Remove libthread_db dependency on Linux
Reviewed-by: clanger Backport-of: ef3336e
1 parent 23719ae commit 0605504

File tree

9 files changed

+48
-170
lines changed

9 files changed

+48
-170
lines changed

make/lib/Lib-jdk.hotspot.agent.gmk

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
2+
# Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
33
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
#
55
# This code is free software; you can redistribute it and/or modify it
@@ -65,7 +65,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBSA, \
6565
CXXFLAGS := $(CXXFLAGS_JDKLIB) $(SA_CFLAGS) $(SA_CXXFLAGS), \
6666
EXTRA_SRC := $(LIBSA_EXTRA_SRC), \
6767
LDFLAGS := $(LDFLAGS_JDKLIB) $(SA_LDFLAGS), \
68-
LIBS_linux := -lthread_db $(LIBDL), \
68+
LIBS_linux := $(LIBDL), \
6969
LIBS_solaris := -ldl -ldemangle -lthread -lproc, \
7070
LIBS_macosx := -framework Foundation \
7171
-framework JavaRuntimeSupport -framework Security -framework CoreFoundation, \

src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
2424

2525
#include <jni.h>
2626
#include "libproc.h"
27+
#include "proc_service.h"
2728

2829
#include <elf.h>
2930
#include <sys/types.h>
@@ -241,10 +242,10 @@ JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_se
241242
/*
242243
* Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal
243244
* Method: attach0
244-
* Signature: (IZ)V
245+
* Signature: (I)V
245246
*/
246-
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_attach0__IZ
247-
(JNIEnv *env, jobject this_obj, jint jpid, jboolean is_in_container) {
247+
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_attach0__I
248+
(JNIEnv *env, jobject this_obj, jint jpid) {
248249

249250
// For bitness checking, locate binary at /proc/jpid/exe
250251
char buf[PATH_MAX];
@@ -254,7 +255,7 @@ JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_at
254255

255256
char err_buf[200];
256257
struct ps_prochandle* ph;
257-
if ((ph = Pgrab(jpid, err_buf, sizeof(err_buf), is_in_container)) == NULL) {
258+
if ((ph = Pgrab(jpid, err_buf, sizeof(err_buf))) == NULL) {
258259
char msg[230];
259260
snprintf(msg, sizeof(msg), "Can't attach to the process: %s", err_buf);
260261
THROW_NEW_DEBUGGER_EXCEPTION(msg);

src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h

Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -28,41 +28,10 @@
2828
#include <jni.h>
2929
#include <unistd.h>
3030
#include <stdint.h>
31-
#include "proc_service.h"
3231

32+
#include <sys/procfs.h>
3333
#include <sys/ptrace.h>
3434

35-
/************************************************************************************
36-
37-
0. This is very minimal subset of Solaris libproc just enough for current application.
38-
Please note that the bulk of the functionality is from proc_service interface. This
39-
adds Pgrab__ and some missing stuff. We hide the difference b/w live process and core
40-
file by this interface.
41-
42-
1. pthread_id unique in both NPTL & LinuxThreads. We store this in
43-
OSThread::_pthread_id in JVM code.
44-
45-
2. All threads see the same pid when they call getpid() under NPTL.
46-
Threads receive different pid under LinuxThreads. We used to save the result of
47-
::getpid() call in OSThread::_thread_id. This way uniqueness of OSThread::_thread_id
48-
was lost under NPTL. Now, we store the result of ::gettid() call in
49-
OSThread::_thread_id. Because gettid returns actual pid of thread (lwp id), this is
50-
unique again. We therefore use OSThread::_thread_id as unique identifier.
51-
52-
3. There is a unique LWP id under both thread libraries. libthread_db maps pthread_id
53-
to its underlying lwp_id under both the thread libraries. thread_info.lwp_id stores
54-
lwp_id of the thread. The lwp id is nothing but the actual pid of clone'd processes. But
55-
unfortunately libthread_db does not work very well for core dumps. So, we get pthread_id
56-
only for processes. For core dumps, we don't use libthread_db at all (like gdb).
57-
58-
4. ptrace operates on this LWP id under both the thread libraries. When we say 'pid' for
59-
ptrace call, we refer to lwp_id of the thread.
60-
61-
5. for core file, we parse ELF files and read data from them. For processes we use
62-
combination of ptrace and /proc calls.
63-
64-
*************************************************************************************/
65-
6635

6736
#if defined(sparc) || defined(sparcv9) || defined(ppc64) || defined(ppc64le)
6837
#include <asm/ptrace.h>
@@ -87,7 +56,7 @@ struct ps_prochandle;
8756

8857
// attach to a process
8958
JNIEXPORT struct ps_prochandle* JNICALL
90-
Pgrab(pid_t pid, char* err_buf, size_t err_buf_len, bool is_in_container);
59+
Pgrab(pid_t pid, char* err_buf, size_t err_buf_len);
9160

9261
// attach to a core dump
9362
JNIEXPORT struct ps_prochandle* JNICALL

src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c

Lines changed: 3 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@
2626
#include <stdlib.h>
2727
#include <string.h>
2828
#include <fcntl.h>
29-
#include <thread_db.h>
29+
#include <sys/procfs.h>
3030
#include "libproc_impl.h"
31+
#include "proc_service.h"
3132

3233
#define SA_ALTROOT "SA_ALTROOT"
3334

@@ -116,13 +117,6 @@ JNIEXPORT bool JNICALL
116117
init_libproc(bool debug) {
117118
// init debug mode
118119
_libsaproc_debug = debug;
119-
120-
// initialize the thread_db library
121-
if (td_init() != TD_OK) {
122-
print_debug("libthread_db's td_init failed\n");
123-
return false;
124-
}
125-
126120
return true;
127121
}
128122

@@ -256,15 +250,14 @@ const char* symbol_for_pc(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* p
256250
}
257251

258252
// add a thread to ps_prochandle
259-
thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
253+
thread_info* add_thread_info(struct ps_prochandle* ph, lwpid_t lwp_id) {
260254
thread_info* newthr;
261255
if ( (newthr = (thread_info*) calloc(1, sizeof(thread_info))) == NULL) {
262256
print_debug("can't allocate memory for thread_info\n");
263257
return NULL;
264258
}
265259

266260
// initialize thread info
267-
newthr->pthread_id = pthread_id;
268261
newthr->lwp_id = lwp_id;
269262

270263
// add new thread to the list
@@ -295,64 +288,6 @@ void delete_thread_info(struct ps_prochandle* ph, thread_info* thr_to_be_removed
295288
free(current_thr);
296289
}
297290

298-
// struct used for client data from thread_db callback
299-
struct thread_db_client_data {
300-
struct ps_prochandle* ph;
301-
thread_info_callback callback;
302-
};
303-
304-
// callback function for libthread_db
305-
static int thread_db_callback(const td_thrhandle_t *th_p, void *data) {
306-
struct thread_db_client_data* ptr = (struct thread_db_client_data*) data;
307-
td_thrinfo_t ti;
308-
td_err_e err;
309-
310-
memset(&ti, 0, sizeof(ti));
311-
err = td_thr_get_info(th_p, &ti);
312-
if (err != TD_OK) {
313-
print_debug("libthread_db : td_thr_get_info failed, can't get thread info\n");
314-
return err;
315-
}
316-
317-
print_debug("thread_db : pthread %d (lwp %d)\n", ti.ti_tid, ti.ti_lid);
318-
319-
if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE) {
320-
print_debug("Skipping pthread %d (lwp %d)\n", ti.ti_tid, ti.ti_lid);
321-
return TD_OK;
322-
}
323-
324-
if (ptr->callback(ptr->ph, ti.ti_tid, ti.ti_lid) != true)
325-
return TD_ERR;
326-
327-
return TD_OK;
328-
}
329-
330-
// read thread_info using libthread_db
331-
bool read_thread_info(struct ps_prochandle* ph, thread_info_callback cb) {
332-
struct thread_db_client_data mydata;
333-
td_thragent_t* thread_agent = NULL;
334-
if (td_ta_new(ph, &thread_agent) != TD_OK) {
335-
print_debug("can't create libthread_db agent\n");
336-
return false;
337-
}
338-
339-
mydata.ph = ph;
340-
mydata.callback = cb;
341-
342-
// we use libthread_db iterator to iterate thru list of threads.
343-
if (td_ta_thr_iter(thread_agent, thread_db_callback, &mydata,
344-
TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
345-
TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS) != TD_OK) {
346-
td_ta_delete(thread_agent);
347-
return false;
348-
}
349-
350-
// delete thread agent
351-
td_ta_delete(thread_agent);
352-
return true;
353-
}
354-
355-
356291
// get number of threads
357292
int get_num_threads(struct ps_prochandle* ph) {
358293
return ph->num_threads;
@@ -484,9 +419,3 @@ ps_lgetregs(struct ps_prochandle *ph, lwpid_t lid, prgregset_t gregset) {
484419
return PS_OK;
485420
}
486421

487-
// new libthread_db of NPTL seem to require this symbol
488-
JNIEXPORT ps_err_e JNICALL
489-
ps_get_thread_area() {
490-
print_debug("ps_get_thread_area not implemented\n");
491-
return PS_OK;
492-
}

src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ typedef struct lib_info {
4646
// list of threads
4747
typedef struct thread_info {
4848
lwpid_t lwp_id;
49-
pthread_t pthread_id; // not used cores, always -1
5049
struct user_regs_struct regs; // not for process, core uses for caching regset
5150
struct thread_info* next;
5251
} thread_info;
@@ -109,11 +108,6 @@ void print_debug(const char* format,...);
109108
void print_error(const char* format,...);
110109
bool is_debug();
111110

112-
typedef bool (*thread_info_callback)(struct ps_prochandle* ph, pthread_t pid, lwpid_t lwpid);
113-
114-
// reads thread info using libthread_db and calls above callback for each thread
115-
bool read_thread_info(struct ps_prochandle* ph, thread_info_callback cb);
116-
117111
// deletes a thread from the thread list
118112
void delete_thread_info(struct ps_prochandle* ph, thread_info* thr);
119113

@@ -125,7 +119,7 @@ lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd,
125119
uintptr_t base);
126120

127121
// adds a new thread to threads list, returns NULL on failure
128-
thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id);
122+
thread_info* add_thread_info(struct ps_prochandle* ph, lwpid_t lwp_id);
129123

130124
// a test for ELF signature without using libelf
131125
bool is_elf_file(int fd);

src/jdk.hotspot.agent/linux/native/libsaproc/proc_service.h

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -26,12 +26,10 @@
2626
#define _PROC_SERVICE_H_
2727

2828
#include <stdio.h>
29-
#include <thread_db.h>
29+
#include <sys/procfs.h>
3030
#include "jni.h"
31+
#include "libproc.h"
3132

32-
// Linux does not have the proc service library, though it does provide the
33-
// thread_db library which can be used to manipulate threads without having
34-
// to know the details of NPTL
3533

3634
// copied from Solaris "proc_service.h"
3735
typedef enum {
@@ -79,8 +77,4 @@ ps_lgetfpregs(struct ps_prochandle *ph, lwpid_t lid, prfpregset_t *fpregs);
7977
JNIEXPORT ps_err_e JNICALL
8078
ps_lgetregs(struct ps_prochandle *ph, lwpid_t lid, prgregset_t gregset);
8179

82-
// new libthread_db of NPTL seem to require this symbol
83-
JNIEXPORT ps_err_e JNICALL
84-
ps_get_thread_area();
85-
8680
#endif /* _PROC_SERVICE_H_ */

src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <elf.h>
3232
#include <link.h>
3333
#include "libproc_impl.h"
34+
#include "proc_service.h"
3435
#include "salibelf.h"
3536
#include "cds.h"
3637

@@ -511,8 +512,7 @@ static bool core_handle_prstatus(struct ps_prochandle* ph, const char* buf, size
511512
prstatus_t* prstat = (prstatus_t*) buf;
512513
thread_info* newthr;
513514
print_debug("got integer regset for lwp %d\n", prstat->pr_pid);
514-
// we set pthread_t to -1 for core dump
515-
if((newthr = add_thread_info(ph, (pthread_t) -1, prstat->pr_pid)) == NULL)
515+
if((newthr = add_thread_info(ph, prstat->pr_pid)) == NULL)
516516
return false;
517517

518518
// copy regs

src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -339,11 +339,6 @@ static char * fgets_no_cr(char * buf, int n, FILE *fp)
339339
return rslt;
340340
}
341341

342-
// callback for read_thread_info
343-
static bool add_new_thread(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
344-
return add_thread_info(ph, pthread_id, lwp_id) != NULL;
345-
}
346-
347342
static bool read_lib_info(struct ps_prochandle* ph) {
348343
char fname[32];
349344
char buf[PATH_MAX];
@@ -443,7 +438,7 @@ static ps_prochandle_ops process_ops = {
443438

444439
// attach to the process. One and only one exposed stuff
445440
JNIEXPORT struct ps_prochandle* JNICALL
446-
Pgrab(pid_t pid, char* err_buf, size_t err_buf_len, bool is_in_container) {
441+
Pgrab(pid_t pid, char* err_buf, size_t err_buf_len) {
447442
struct ps_prochandle* ph = NULL;
448443
thread_info* thr = NULL;
449444
attach_state_t attach_status = ATTACH_SUCCESS;
@@ -464,6 +459,7 @@ Pgrab(pid_t pid, char* err_buf, size_t err_buf_len, bool is_in_container) {
464459

465460
// initialize ps_prochandle
466461
ph->pid = pid;
462+
add_thread_info(ph, ph->pid);
467463

468464
// initialize vtable
469465
ph->ops = &process_ops;
@@ -473,33 +469,30 @@ Pgrab(pid_t pid, char* err_buf, size_t err_buf_len, bool is_in_container) {
473469
// the list of threads within the same process.
474470
read_lib_info(ph);
475471

476-
// read thread info
477-
if (is_in_container) {
478-
/*
479-
* If the process is running in the container, SA scans all tasks in
480-
* /proc/<PID>/task to read all threads info.
481-
*/
482-
char taskpath[PATH_MAX];
483-
DIR *dirp;
484-
struct dirent *entry;
485-
486-
snprintf(taskpath, PATH_MAX, "/proc/%d/task", ph->pid);
487-
dirp = opendir(taskpath);
488-
int lwp_id;
489-
while ((entry = readdir(dirp)) != NULL) {
490-
if (*entry->d_name == '.') {
491-
continue;
492-
}
493-
lwp_id = atoi(entry->d_name);
494-
if (lwp_id == ph->pid) {
495-
continue;
496-
}
497-
add_new_thread(ph, -1, lwp_id);
472+
/*
473+
* Read thread info.
474+
* SA scans all tasks in /proc/<PID>/task to read all threads info.
475+
*/
476+
char taskpath[PATH_MAX];
477+
DIR *dirp;
478+
struct dirent *entry;
479+
480+
snprintf(taskpath, PATH_MAX, "/proc/%d/task", ph->pid);
481+
dirp = opendir(taskpath);
482+
int lwp_id;
483+
while ((entry = readdir(dirp)) != NULL) {
484+
if (*entry->d_name == '.') {
485+
continue;
486+
}
487+
lwp_id = atoi(entry->d_name);
488+
if (lwp_id == ph->pid) {
489+
continue;
490+
}
491+
if (!process_doesnt_exist(lwp_id)) {
492+
add_thread_info(ph, lwp_id);
498493
}
499-
closedir(dirp);
500-
} else {
501-
read_thread_info(ph, add_new_thread);
502494
}
495+
closedir(dirp);
503496

504497
// attach to the threads
505498
thr = ph->threads;

0 commit comments

Comments
 (0)