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 #include <stdarg.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <fcntl.h>
29 #include <thread_db.h>
30 #include "libproc_impl.h"
31
32 #define SA_ALTROOT "SA_ALTROOT"
33
34 int pathmap_open(const char* name) {
35 static const char *alt_root = NULL;
36 static int alt_root_initialized = 0;
37
38 int fd;
39 char alt_path[PATH_MAX + 1], *alt_path_end;
40 const char *s;
41 int free_space;
42
43 if (!alt_root_initialized) {
44 alt_root_initialized = -1;
45 alt_root = getenv(SA_ALTROOT);
46 }
47
48 if (alt_root == NULL) {
49 return open(name, O_RDONLY);
99 }
100 }
101
102 void print_error(const char* format,...) {
103 va_list alist;
104 va_start(alist, format);
105 fputs("ERROR: ", stderr);
106 vfprintf(stderr, format, alist);
107 va_end(alist);
108 }
109
110 bool is_debug() {
111 return _libsaproc_debug;
112 }
113
114 // initialize libproc
115 bool init_libproc(bool debug) {
116 // init debug mode
117 _libsaproc_debug = debug;
118
119 // initialize the thread_db library
120 if (td_init() != TD_OK) {
121 print_debug("libthread_db's td_init failed\n");
122 return false;
123 }
124
125 return true;
126 }
127
128 static void destroy_lib_info(struct ps_prochandle* ph) {
129 lib_info* lib = ph->libs;
130 while (lib) {
131 lib_info *next = lib->next;
132 if (lib->symtab) {
133 destroy_symtab(lib->symtab);
134 }
135 free(lib);
136 lib = next;
137 }
138 }
139
140 static void destroy_thread_info(struct ps_prochandle* ph) {
141 thread_info* thr = ph->threads;
142 while (thr) {
143 thread_info *next = thr->next;
256 // add a thread to ps_prochandle
257 thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
258 thread_info* newthr;
259 if ( (newthr = (thread_info*) calloc(1, sizeof(thread_info))) == NULL) {
260 print_debug("can't allocate memory for thread_info\n");
261 return NULL;
262 }
263
264 // initialize thread info
265 newthr->pthread_id = pthread_id;
266 newthr->lwp_id = lwp_id;
267
268 // add new thread to the list
269 newthr->next = ph->threads;
270 ph->threads = newthr;
271 ph->num_threads++;
272 return newthr;
273 }
274
275
276 // struct used for client data from thread_db callback
277 struct thread_db_client_data {
278 struct ps_prochandle* ph;
279 thread_info_callback callback;
280 };
281
282 // callback function for libthread_db
283 static int thread_db_callback(const td_thrhandle_t *th_p, void *data) {
284 struct thread_db_client_data* ptr = (struct thread_db_client_data*) data;
285 td_thrinfo_t ti;
286 td_err_e err;
287
288 memset(&ti, 0, sizeof(ti));
289 err = td_thr_get_info(th_p, &ti);
290 if (err != TD_OK) {
291 print_debug("libthread_db : td_thr_get_info failed, can't get thread info\n");
292 return err;
293 }
294
295 print_debug("thread_db : pthread %d (lwp %d)\n", ti.ti_tid, ti.ti_lid);
307 if (td_ta_new(ph, &thread_agent) != TD_OK) {
308 print_debug("can't create libthread_db agent\n");
309 return false;
310 }
311
312 mydata.ph = ph;
313 mydata.callback = cb;
314
315 // we use libthread_db iterator to iterate thru list of threads.
316 if (td_ta_thr_iter(thread_agent, thread_db_callback, &mydata,
317 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
318 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS) != TD_OK) {
319 td_ta_delete(thread_agent);
320 return false;
321 }
322
323 // delete thread agent
324 td_ta_delete(thread_agent);
325 return true;
326 }
327
328
329 // get number of threads
330 int get_num_threads(struct ps_prochandle* ph) {
331 return ph->num_threads;
332 }
333
334 // get lwp_id of n'th thread
335 lwpid_t get_lwp_id(struct ps_prochandle* ph, int index) {
336 int count = 0;
337 thread_info* thr = ph->threads;
338 while (thr) {
339 if (count == index) {
340 return thr->lwp_id;
341 }
342 count++;
343 thr = thr->next;
344 }
345 return -1;
346 }
347
|
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 #include <stdarg.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <fcntl.h>
29 #ifdef INCLUDE_SA_ATTACH
30 #include <thread_db.h>
31 #endif
32 #include "libproc_impl.h"
33
34 #define SA_ALTROOT "SA_ALTROOT"
35
36 int pathmap_open(const char* name) {
37 static const char *alt_root = NULL;
38 static int alt_root_initialized = 0;
39
40 int fd;
41 char alt_path[PATH_MAX + 1], *alt_path_end;
42 const char *s;
43 int free_space;
44
45 if (!alt_root_initialized) {
46 alt_root_initialized = -1;
47 alt_root = getenv(SA_ALTROOT);
48 }
49
50 if (alt_root == NULL) {
51 return open(name, O_RDONLY);
101 }
102 }
103
104 void print_error(const char* format,...) {
105 va_list alist;
106 va_start(alist, format);
107 fputs("ERROR: ", stderr);
108 vfprintf(stderr, format, alist);
109 va_end(alist);
110 }
111
112 bool is_debug() {
113 return _libsaproc_debug;
114 }
115
116 // initialize libproc
117 bool init_libproc(bool debug) {
118 // init debug mode
119 _libsaproc_debug = debug;
120
121 #ifdef INCLUDE_SA_ATTACH
122 // initialize the thread_db library
123 if (td_init() != TD_OK) {
124 print_debug("libthread_db's td_init failed\n");
125 return false;
126 }
127 #endif
128
129 return true;
130 }
131
132 static void destroy_lib_info(struct ps_prochandle* ph) {
133 lib_info* lib = ph->libs;
134 while (lib) {
135 lib_info *next = lib->next;
136 if (lib->symtab) {
137 destroy_symtab(lib->symtab);
138 }
139 free(lib);
140 lib = next;
141 }
142 }
143
144 static void destroy_thread_info(struct ps_prochandle* ph) {
145 thread_info* thr = ph->threads;
146 while (thr) {
147 thread_info *next = thr->next;
260 // add a thread to ps_prochandle
261 thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
262 thread_info* newthr;
263 if ( (newthr = (thread_info*) calloc(1, sizeof(thread_info))) == NULL) {
264 print_debug("can't allocate memory for thread_info\n");
265 return NULL;
266 }
267
268 // initialize thread info
269 newthr->pthread_id = pthread_id;
270 newthr->lwp_id = lwp_id;
271
272 // add new thread to the list
273 newthr->next = ph->threads;
274 ph->threads = newthr;
275 ph->num_threads++;
276 return newthr;
277 }
278
279
280 #ifdef INCLUDE_SA_ATTACH
281 // struct used for client data from thread_db callback
282 struct thread_db_client_data {
283 struct ps_prochandle* ph;
284 thread_info_callback callback;
285 };
286
287 // callback function for libthread_db
288 static int thread_db_callback(const td_thrhandle_t *th_p, void *data) {
289 struct thread_db_client_data* ptr = (struct thread_db_client_data*) data;
290 td_thrinfo_t ti;
291 td_err_e err;
292
293 memset(&ti, 0, sizeof(ti));
294 err = td_thr_get_info(th_p, &ti);
295 if (err != TD_OK) {
296 print_debug("libthread_db : td_thr_get_info failed, can't get thread info\n");
297 return err;
298 }
299
300 print_debug("thread_db : pthread %d (lwp %d)\n", ti.ti_tid, ti.ti_lid);
312 if (td_ta_new(ph, &thread_agent) != TD_OK) {
313 print_debug("can't create libthread_db agent\n");
314 return false;
315 }
316
317 mydata.ph = ph;
318 mydata.callback = cb;
319
320 // we use libthread_db iterator to iterate thru list of threads.
321 if (td_ta_thr_iter(thread_agent, thread_db_callback, &mydata,
322 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
323 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS) != TD_OK) {
324 td_ta_delete(thread_agent);
325 return false;
326 }
327
328 // delete thread agent
329 td_ta_delete(thread_agent);
330 return true;
331 }
332 #endif // INCLUDE_SA_ATTACH
333
334 // get number of threads
335 int get_num_threads(struct ps_prochandle* ph) {
336 return ph->num_threads;
337 }
338
339 // get lwp_id of n'th thread
340 lwpid_t get_lwp_id(struct ps_prochandle* ph, int index) {
341 int count = 0;
342 thread_info* thr = ph->threads;
343 while (thr) {
344 if (count == index) {
345 return thr->lwp_id;
346 }
347 count++;
348 thr = thr->next;
349 }
350 return -1;
351 }
352
|