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 | * |
23 | */ |
24 | |
25 | #include <stdio.h> |
26 | #include <stdlib.h> |
27 | #include <string.h> |
28 | #include <signal.h> |
29 | #include <errno.h> |
30 | #include <elf.h> |
31 | #include <dirent.h> |
32 | #include <ctype.h> |
33 | #include <sys/types.h> |
34 | #include <sys/wait.h> |
35 | #include <sys/ptrace.h> |
36 | #include <sys/uio.h> |
37 | #include "libproc_impl.h" |
38 | |
39 | #if defined(x86_64) && !defined(amd64) |
40 | #define amd64 1 |
41 | #endif |
42 | |
43 | #ifndef __WALL |
44 | #define __WALL 0x40000000 // Copied from /usr/include/linux/wait.h |
45 | #endif |
46 | |
47 | // This file has the libproc implementation specific to live process |
48 | // For core files, refer to ps_core.c |
49 | |
50 | typedef enum { |
51 | ATTACH_SUCCESS, |
52 | ATTACH_FAIL, |
53 | ATTACH_THREAD_DEAD |
54 | } attach_state_t; |
55 | |
56 | static inline uintptr_t align(uintptr_t ptr, size_t size) { |
57 | return (ptr & ~(size - 1)); |
58 | } |
59 | |
60 | // --------------------------------------------- |
61 | // ptrace functions |
62 | // --------------------------------------------- |
63 | |
64 | // read "size" bytes of data from "addr" within the target process. |
65 | // unlike the standard ptrace() function, process_read_data() can handle |
66 | // unaligned address - alignment check, if required, should be done |
67 | // before calling process_read_data. |
68 | |
69 | static bool process_read_data(struct ps_prochandle* ph, uintptr_t addr, char *buf, size_t size) { |
70 | long rslt; |
71 | size_t i, words; |
72 | uintptr_t end_addr = addr + size; |
73 | uintptr_t aligned_addr = align(addr, sizeof(long)); |
74 | |
75 | if (aligned_addr != addr) { |
76 | char *ptr = (char *)&rslt; |
77 | errno = 0; |
78 | rslt = ptrace(PTRACE_PEEKDATA, ph->pid, aligned_addr, 0); |
79 | if (errno) { |
80 | print_debug("ptrace(PTRACE_PEEKDATA, ..) failed for %d bytes @ %lx\n" , size, addr); |
81 | return false; |
82 | } |
83 | for (; aligned_addr != addr; aligned_addr++, ptr++); |
84 | for (; ((intptr_t)aligned_addr % sizeof(long)) && aligned_addr < end_addr; |
85 | aligned_addr++) |
86 | *(buf++) = *(ptr++); |
87 | } |
88 | |
89 | words = (end_addr - aligned_addr) / sizeof(long); |
90 | |
91 | // assert((intptr_t)aligned_addr % sizeof(long) == 0); |
92 | for (i = 0; i < words; i++) { |
93 | errno = 0; |
94 | rslt = ptrace(PTRACE_PEEKDATA, ph->pid, aligned_addr, 0); |
95 | if (errno) { |
96 | print_debug("ptrace(PTRACE_PEEKDATA, ..) failed for %d bytes @ %lx\n" , size, addr); |
97 | return false; |
98 | } |
99 | *(long *)buf = rslt; |
100 | buf += sizeof(long); |
101 | aligned_addr += sizeof(long); |
102 | } |
103 | |
104 | if (aligned_addr != end_addr) { |
105 | char *ptr = (char *)&rslt; |
106 | errno = 0; |
107 | rslt = ptrace(PTRACE_PEEKDATA, ph->pid, aligned_addr, 0); |
108 | if (errno) { |
109 | print_debug("ptrace(PTRACE_PEEKDATA, ..) failed for %d bytes @ %lx\n" , size, addr); |
110 | return false; |
111 | } |
112 | for (; aligned_addr != end_addr; aligned_addr++) |
113 | *(buf++) = *(ptr++); |
114 | } |
115 | return true; |
116 | } |
117 | |
118 | // null implementation for write |
119 | static bool process_write_data(struct ps_prochandle* ph, |
120 | uintptr_t addr, const char *buf , size_t size) { |
121 | return false; |
122 | } |
123 | |
124 | // "user" should be a pointer to a user_regs_struct |
125 | static bool process_get_lwp_regs(struct ps_prochandle* ph, pid_t pid, struct user_regs_struct *user) { |
126 | // we have already attached to all thread 'pid's, just use ptrace call |
127 | // to get regset now. Note that we don't cache regset upfront for processes. |
128 | // Linux on x86 and sparc are different. On x86 ptrace(PTRACE_GETREGS, ...) |
129 | // uses pointer from 4th argument and ignores 3rd argument. On sparc it uses |
130 | // pointer from 3rd argument and ignores 4th argument |
131 | #if defined(sparc) || defined(sparcv9) |
132 | #define ptrace_getregs(request, pid, addr, data) ptrace(request, pid, addr, data) |
133 | #else |
134 | #define ptrace_getregs(request, pid, addr, data) ptrace(request, pid, data, addr) |
135 | #endif |
136 | |
137 | #if defined(_LP64) && defined(PTRACE_GETREGS64) |
138 | #define PTRACE_GETREGS_REQ PTRACE_GETREGS64 |
139 | #elif defined(PTRACE_GETREGS) |
140 | #define PTRACE_GETREGS_REQ PTRACE_GETREGS |
141 | #elif defined(PT_GETREGS) |
142 | #define PTRACE_GETREGS_REQ PT_GETREGS |
143 | #endif |
144 | |
145 | #ifdef PTRACE_GETREGS_REQ |
146 | if (ptrace_getregs(PTRACE_GETREGS_REQ, pid, user, NULL) < 0) { |
147 | print_debug("ptrace(PTRACE_GETREGS, ...) failed for lwp %d\n" , pid); |
148 | return false; |
149 | } |
150 | return true; |
151 | #elif defined(PTRACE_GETREGSET) |
152 | struct iovec iov; |
153 | iov.iov_base = user; |
154 | iov.iov_len = sizeof(*user); |
155 | if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (void*) &iov) < 0) { |
156 | print_debug("ptrace(PTRACE_GETREGSET, ...) failed for lwp %d\n" , pid); |
157 | return false; |
158 | } |
159 | return true; |
160 | #else |
161 | print_debug("ptrace(PTRACE_GETREGS, ...) not supported\n" ); |
162 | return false; |
163 | #endif |
164 | |
165 | } |
166 | |
167 | static bool ptrace_continue(pid_t pid, int signal) { |
168 | // pass the signal to the process so we don't swallow it |
169 | if (ptrace(PTRACE_CONT, pid, NULL, signal) < 0) { |
170 | print_debug("ptrace(PTRACE_CONT, ..) failed for %d\n" , pid); |
171 | return false; |
172 | } |
173 | return true; |
174 | } |
175 | |
176 | // waits until the ATTACH has stopped the process |
177 | // by signal SIGSTOP |
178 | static attach_state_t ptrace_waitpid(pid_t pid) { |
179 | int ret; |
180 | int status; |
181 | errno = 0; |
182 | while (true) { |
183 | // Wait for debuggee to stop. |
184 | ret = waitpid(pid, &status, 0); |
185 | if (ret == -1 && errno == ECHILD) { |
186 | // try cloned process. |
187 | ret = waitpid(pid, &status, __WALL); |
188 | } |
189 | if (ret >= 0) { |
190 | if (WIFSTOPPED(status)) { |
191 | // Any signal will stop the thread, make sure it is SIGSTOP. Otherwise SIGSTOP |
192 | // will still be pending and delivered when the process is DETACHED and the process |
193 | // will go to sleep. |
194 | if (WSTOPSIG(status) == SIGSTOP) { |
195 | // Debuggee stopped by SIGSTOP. |
196 | return ATTACH_SUCCESS; |
197 | } |
198 | if (!ptrace_continue(pid, WSTOPSIG(status))) { |
199 | print_error("Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n" , WSTOPSIG(status)); |
200 | return ATTACH_FAIL; |
201 | } |
202 | } else { |
203 | print_debug("waitpid(): Child process %d exited/terminated (status = 0x%x)\n" , pid, status); |
204 | return ATTACH_THREAD_DEAD; |
205 | } |
206 | } else { |
207 | switch (errno) { |
208 | case EINTR: |
209 | continue; |
210 | break; |
211 | case ECHILD: |
212 | print_debug("waitpid() failed. Child process pid (%d) does not exist \n" , pid); |
213 | return ATTACH_THREAD_DEAD; |
214 | case EINVAL: |
215 | print_error("waitpid() failed. Invalid options argument.\n" ); |
216 | return ATTACH_FAIL; |
217 | default: |
218 | print_error("waitpid() failed. Unexpected error %d\n" , errno); |
219 | return ATTACH_FAIL; |
220 | } |
221 | } // else |
222 | } // while |
223 | } |
224 | |
225 | // checks the state of the thread/process specified by "pid", by reading |
226 | // in the 'State:' value from the /proc/<pid>/status file. From the proc |
227 | // man page, "Current state of the process. One of "R (running)", |
228 | // "S (sleeping)", "D (disk sleep)", "T (stopped)", "T (tracing stop)", |
229 | // "Z (zombie)", or "X (dead)"." Assumes that the thread is dead if we |
230 | // don't find the status file or if the status is 'X' or 'Z'. |
231 | static bool process_doesnt_exist(pid_t pid) { |
232 | char fname[32]; |
233 | char buf[30]; |
234 | FILE *fp = NULL; |
235 | const char state_string[] = "State:" ; |
236 | |
237 | sprintf(fname, "/proc/%d/status" , pid); |
238 | fp = fopen(fname, "r" ); |
239 | if (fp == NULL) { |
240 | print_debug("can't open /proc/%d/status file\n" , pid); |
241 | // Assume the thread does not exist anymore. |
242 | return true; |
243 | } |
244 | bool found_state = false; |
245 | size_t state_len = strlen(state_string); |
246 | while (fgets(buf, sizeof(buf), fp) != NULL) { |
247 | char *state = NULL; |
248 | if (strncmp (buf, state_string, state_len) == 0) { |
249 | found_state = true; |
250 | state = buf + state_len; |
251 | // Skip the spaces |
252 | while (isspace(*state)) { |
253 | state++; |
254 | } |
255 | // A state value of 'X' indicates that the thread is dead. 'Z' |
256 | // indicates that the thread is a zombie. |
257 | if (*state == 'X' || *state == 'Z') { |
258 | fclose (fp); |
259 | return true; |
260 | } |
261 | break; |
262 | } |
263 | } |
264 | // If the state value is not 'X' or 'Z', the thread exists. |
265 | if (!found_state) { |
266 | // We haven't found the line beginning with 'State:'. |
267 | // Assuming the thread exists. |
268 | print_error("Could not find the 'State:' string in the /proc/%d/status file\n" , pid); |
269 | } |
270 | fclose (fp); |
271 | return false; |
272 | } |
273 | |
274 | // attach to a process/thread specified by "pid" |
275 | static attach_state_t ptrace_attach(pid_t pid, char* err_buf, size_t err_buf_len) { |
276 | errno = 0; |
277 | if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) { |
278 | if (errno == EPERM || errno == ESRCH) { |
279 | // Check if the process/thread is exiting or is a zombie |
280 | if (process_doesnt_exist(pid)) { |
281 | print_debug("Thread with pid %d does not exist\n" , pid); |
282 | return ATTACH_THREAD_DEAD; |
283 | } |
284 | } |
285 | char buf[200]; |
286 | char* msg = strerror_r(errno, buf, sizeof(buf)); |
287 | snprintf(err_buf, err_buf_len, "ptrace(PTRACE_ATTACH, ..) failed for %d: %s" , pid, msg); |
288 | print_error("%s\n" , err_buf); |
289 | return ATTACH_FAIL; |
290 | } else { |
291 | attach_state_t wait_ret = ptrace_waitpid(pid); |
292 | if (wait_ret == ATTACH_THREAD_DEAD) { |
293 | print_debug("Thread with pid %d does not exist\n" , pid); |
294 | } |
295 | return wait_ret; |
296 | } |
297 | } |
298 | |
299 | // ------------------------------------------------------- |
300 | // functions for obtaining library information |
301 | // ------------------------------------------------------- |
302 | |
303 | /* |
304 | * splits a string _str_ into substrings with delimiter _delim_ by replacing old * delimiters with _new_delim_ (ideally, '\0'). the address of each substring |
305 | * is stored in array _ptrs_ as the return value. the maximum capacity of _ptrs_ * array is specified by parameter _n_. |
306 | * RETURN VALUE: total number of substrings (always <= _n_) |
307 | * NOTE: string _str_ is modified if _delim_!=_new_delim_ |
308 | */ |
309 | static int split_n_str(char * str, int n, char ** ptrs, char delim, char new_delim) |
310 | { |
311 | int i; |
312 | for(i = 0; i < n; i++) ptrs[i] = NULL; |
313 | if (str == NULL || n < 1 ) return 0; |
314 | |
315 | i = 0; |
316 | |
317 | // skipping leading blanks |
318 | while(*str&&*str==delim) str++; |
319 | |
320 | while(*str&&i<n){ |
321 | ptrs[i++] = str; |
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 | } |
362 | |
363 | // SA does not handle the lines with patterns: |
364 | // "[stack]", "[heap]", "[vdso]", "[vsyscall]", etc. |
365 | if (word[5][0] == '[') { |
366 | // not a shared library entry. ignore. |
367 | continue; |
368 | } |
369 | |
370 | if (nwords > 6) { |
371 | // prelink altered mapfile when the program is running. |
372 | // Entries like one below have to be skipped |
373 | // /lib64/libc-2.15.so (deleted) |
374 | // SO name in entries like one below have to be stripped. |
375 | // /lib64/libpthread-2.15.so.#prelink#.EECVts |
376 | char *s = strstr(word[5],".#prelink#" ); |
377 | if (s == NULL) { |
378 | // No prelink keyword. skip deleted library |
379 | print_debug("skip shared object %s deleted by prelink\n" , word[5]); |
380 | continue; |
381 | } |
382 | |
383 | // Fall through |
384 | print_debug("rectifying shared object name %s changed by prelink\n" , word[5]); |
385 | *s = 0; |
386 | } |
387 | |
388 | if (find_lib(ph, word[5]) == false) { |
389 | intptr_t base; |
390 | lib_info* lib; |
391 | #ifdef _LP64 |
392 | sscanf(word[0], "%lx" , &base); |
393 | #else |
394 | sscanf(word[0], "%x" , &base); |
395 | #endif |
396 | if ((lib = add_lib_info(ph, word[5], (uintptr_t)base)) == NULL) |
397 | continue; // ignore, add_lib_info prints error |
398 | |
399 | // we don't need to keep the library open, symtab is already |
400 | // built. Only for core dump we need to keep the fd open. |
401 | close(lib->fd); |
402 | lib->fd = -1; |
403 | } |
404 | } |
405 | fclose(fp); |
406 | return true; |
407 | } |
408 | |
409 | // detach a given pid |
410 | static bool ptrace_detach(pid_t pid) { |
411 | if (pid && ptrace(PTRACE_DETACH, pid, NULL, NULL) < 0) { |
412 | print_debug("ptrace(PTRACE_DETACH, ..) failed for %d\n" , pid); |
413 | return false; |
414 | } else { |
415 | return true; |
416 | } |
417 | } |
418 | |
419 | // detach all pids of a ps_prochandle |
420 | static void detach_all_pids(struct ps_prochandle* ph) { |
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 | } |
516 | } |
517 | return ph; |
518 | } |
519 | |