1 /*
2 * Copyright (c) 2003, 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 *
322 while(*str&&*str!=delim) str++;
323 while(*str&&*str==delim) *(str++) = new_delim;
324 }
325
326 return i;
327 }
328
329 /*
330 * fgets without storing '\n' at the end of the string
331 */
332 static char * fgets_no_cr(char * buf, int n, FILE *fp)
333 {
334 char * rslt = fgets(buf, n, fp);
335 if (rslt && buf && *buf){
336 char *p = strchr(buf, '\0');
337 if (*--p=='\n') *p='\0';
338 }
339 return rslt;
340 }
341
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
347 static bool read_lib_info(struct ps_prochandle* ph) {
348 char fname[32];
349 char buf[PATH_MAX];
350 FILE *fp = NULL;
351
352 sprintf(fname, "/proc/%d/maps", ph->pid);
353 fp = fopen(fname, "r");
354 if (fp == NULL) {
355 print_debug("can't open /proc/%d/maps file\n", ph->pid);
356 return false;
357 }
358
359 while(fgets_no_cr(buf, PATH_MAX, fp)){
360 char * word[7];
361 int nwords = split_n_str(buf, 7, word, ' ', '\0');
362
363 if (nwords < 6) {
364 // not a shared library entry. ignore.
365 continue;
366 }
426 thread_info* thr = ph->threads;
427 while (thr) {
428 ptrace_detach(thr->lwp_id);
429 thr = thr->next;
430 }
431 }
432
433 static void process_cleanup(struct ps_prochandle* ph) {
434 detach_all_pids(ph);
435 }
436
437 static ps_prochandle_ops process_ops = {
438 .release= process_cleanup,
439 .p_pread= process_read_data,
440 .p_pwrite= process_write_data,
441 .get_lwp_regs= process_get_lwp_regs
442 };
443
444 // attach to the process. One and only one exposed stuff
445 JNIEXPORT struct ps_prochandle* JNICALL
446 Pgrab(pid_t pid, char* err_buf, size_t err_buf_len, bool is_in_container) {
447 struct ps_prochandle* ph = NULL;
448 thread_info* thr = NULL;
449 attach_state_t attach_status = ATTACH_SUCCESS;
450
451 if ( (ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle))) == NULL) {
452 snprintf(err_buf, err_buf_len, "can't allocate memory for ps_prochandle");
453 print_debug("%s\n", err_buf);
454 return NULL;
455 }
456
457 if ((attach_status = ptrace_attach(pid, err_buf, err_buf_len)) != ATTACH_SUCCESS) {
458 if (attach_status == ATTACH_THREAD_DEAD) {
459 print_error("The process with pid %d does not exist.\n", pid);
460 }
461 free(ph);
462 return NULL;
463 }
464
465 // initialize ps_prochandle
466 ph->pid = pid;
467
468 // initialize vtable
469 ph->ops = &process_ops;
470
471 // read library info and symbol tables, must do this before attaching threads,
472 // as the symbols in the pthread library will be used to figure out
473 // the list of threads within the same process.
474 read_lib_info(ph);
475
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);
498 }
499 closedir(dirp);
500 } else {
501 read_thread_info(ph, add_new_thread);
502 }
503
504 // attach to the threads
505 thr = ph->threads;
506
507 while (thr) {
508 thread_info* current_thr = thr;
509 thr = thr->next;
510 // don't attach to the main thread again
511 if (ph->pid != current_thr->lwp_id) {
512 if ((attach_status = ptrace_attach(current_thr->lwp_id, err_buf, err_buf_len)) != ATTACH_SUCCESS) {
513 if (attach_status == ATTACH_THREAD_DEAD) {
514 // Remove this thread from the threads list
515 delete_thread_info(ph, current_thr);
516 }
517 else {
518 Prelease(ph);
519 return NULL;
520 } // ATTACH_THREAD_DEAD
521 } // !ATTACH_SUCCESS
522 }
|
1 /*
2 * Copyright (c) 2003, 2019, 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 *
322 while(*str&&*str!=delim) str++;
323 while(*str&&*str==delim) *(str++) = new_delim;
324 }
325
326 return i;
327 }
328
329 /*
330 * fgets without storing '\n' at the end of the string
331 */
332 static char * fgets_no_cr(char * buf, int n, FILE *fp)
333 {
334 char * rslt = fgets(buf, n, fp);
335 if (rslt && buf && *buf){
336 char *p = strchr(buf, '\0');
337 if (*--p=='\n') *p='\0';
338 }
339 return rslt;
340 }
341
342 static bool read_lib_info(struct ps_prochandle* ph) {
343 char fname[32];
344 char buf[PATH_MAX];
345 FILE *fp = NULL;
346
347 sprintf(fname, "/proc/%d/maps", ph->pid);
348 fp = fopen(fname, "r");
349 if (fp == NULL) {
350 print_debug("can't open /proc/%d/maps file\n", ph->pid);
351 return false;
352 }
353
354 while(fgets_no_cr(buf, PATH_MAX, fp)){
355 char * word[7];
356 int nwords = split_n_str(buf, 7, word, ' ', '\0');
357
358 if (nwords < 6) {
359 // not a shared library entry. ignore.
360 continue;
361 }
421 thread_info* thr = ph->threads;
422 while (thr) {
423 ptrace_detach(thr->lwp_id);
424 thr = thr->next;
425 }
426 }
427
428 static void process_cleanup(struct ps_prochandle* ph) {
429 detach_all_pids(ph);
430 }
431
432 static ps_prochandle_ops process_ops = {
433 .release= process_cleanup,
434 .p_pread= process_read_data,
435 .p_pwrite= process_write_data,
436 .get_lwp_regs= process_get_lwp_regs
437 };
438
439 // attach to the process. One and only one exposed stuff
440 JNIEXPORT struct ps_prochandle* JNICALL
441 Pgrab(pid_t pid, char* err_buf, size_t err_buf_len) {
442 struct ps_prochandle* ph = NULL;
443 thread_info* thr = NULL;
444 attach_state_t attach_status = ATTACH_SUCCESS;
445
446 if ( (ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle))) == NULL) {
447 snprintf(err_buf, err_buf_len, "can't allocate memory for ps_prochandle");
448 print_debug("%s\n", err_buf);
449 return NULL;
450 }
451
452 if ((attach_status = ptrace_attach(pid, err_buf, err_buf_len)) != ATTACH_SUCCESS) {
453 if (attach_status == ATTACH_THREAD_DEAD) {
454 print_error("The process with pid %d does not exist.\n", pid);
455 }
456 free(ph);
457 return NULL;
458 }
459
460 // initialize ps_prochandle
461 ph->pid = pid;
462 add_thread_info(ph, ph->pid);
463
464 // initialize vtable
465 ph->ops = &process_ops;
466
467 // read library info and symbol tables, must do this before attaching threads,
468 // as the symbols in the pthread library will be used to figure out
469 // the list of threads within the same process.
470 read_lib_info(ph);
471
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);
493 }
494 }
495 closedir(dirp);
496
497 // attach to the threads
498 thr = ph->threads;
499
500 while (thr) {
501 thread_info* current_thr = thr;
502 thr = thr->next;
503 // don't attach to the main thread again
504 if (ph->pid != current_thr->lwp_id) {
505 if ((attach_status = ptrace_attach(current_thr->lwp_id, err_buf, err_buf_len)) != ATTACH_SUCCESS) {
506 if (attach_status == ATTACH_THREAD_DEAD) {
507 // Remove this thread from the threads list
508 delete_thread_info(ph, current_thr);
509 }
510 else {
511 Prelease(ph);
512 return NULL;
513 } // ATTACH_THREAD_DEAD
514 } // !ATTACH_SUCCESS
515 }
|