blob: e3b71e5c839681413de265db31829f40864cd075 [file] [log] [blame]
Petr Machata750ca8c2011-10-06 14:29:34 +02001#define _GNU_SOURCE /* For getline. */
Juan Cespedesd44c6b81998-09-25 14:48:42 +02002#include "config.h"
Joe Damato47cae1e2010-11-08 15:47:39 -08003#include "common.h"
Juan Cespedesd44c6b81998-09-25 14:48:42 +02004
Juan Cespedes1fe93d51998-03-13 00:29:21 +01005#include <sys/types.h>
Petr Machata9a5420c2011-07-09 11:21:23 +02006#include <sys/stat.h>
7#include <fcntl.h>
Zachary T Welchbfb26c72010-12-06 23:21:00 -08008#include <inttypes.h>
Joe Damato47cae1e2010-11-08 15:47:39 -08009#include <link.h>
Juan Cespedes1fe93d51998-03-13 00:29:21 +010010#include <stdio.h>
11#include <string.h>
12#include <signal.h>
Juan Cespedes273ea6d1998-03-14 23:02:40 +010013#include <unistd.h>
Petr Machata9a5420c2011-07-09 11:21:23 +020014#include <dirent.h>
15#include <ctype.h>
16#include <errno.h>
17#include <sys/syscall.h>
Petr Machata750ca8c2011-10-06 14:29:34 +020018#include <error.h>
Petr Machata9a5420c2011-07-09 11:21:23 +020019
Juan Cespedes273ea6d1998-03-14 23:02:40 +010020
21/* /proc/pid doesn't exist just after the fork, and sometimes `ltrace'
22 * couldn't open it to find the executable. So it may be necessary to
23 * have a bit delay
24 */
25
Ian Wienand2d45b1a2006-02-20 22:48:07 +010026#define MAX_DELAY 100000 /* 100000 microseconds = 0.1 seconds */
Juan Cespedes1fe93d51998-03-13 00:29:21 +010027
Petr Machata9a5420c2011-07-09 11:21:23 +020028#define PROC_PID_FILE(VAR, FORMAT, PID) \
29 char VAR[strlen(FORMAT) + 6]; \
30 sprintf(VAR, FORMAT, PID)
31
Juan Cespedes1fe93d51998-03-13 00:29:21 +010032/*
Juan Cespedese0660df2009-05-21 18:14:39 +020033 * Returns a (malloc'd) file name corresponding to a running pid
Juan Cespedes1fe93d51998-03-13 00:29:21 +010034 */
Juan Cespedesf1350522008-12-16 18:19:58 +010035char *
36pid2name(pid_t pid) {
Juan Cespedes1fe93d51998-03-13 00:29:21 +010037 if (!kill(pid, 0)) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010038 int delay = 0;
Juan Cespedes273ea6d1998-03-14 23:02:40 +010039
Petr Machata9a5420c2011-07-09 11:21:23 +020040 PROC_PID_FILE(proc_exe, "/proc/%d/exe", pid);
Juan Cespedes273ea6d1998-03-14 23:02:40 +010041
Ian Wienand2d45b1a2006-02-20 22:48:07 +010042 while (delay < MAX_DELAY) {
Juan Cespedes273ea6d1998-03-14 23:02:40 +010043 if (!access(proc_exe, F_OK)) {
44 return strdup(proc_exe);
45 }
46 delay += 1000; /* 1 milisecond */
47 }
Juan Cespedes1fe93d51998-03-13 00:29:21 +010048 }
Juan Cespedes273ea6d1998-03-14 23:02:40 +010049 return NULL;
Juan Cespedes1fe93d51998-03-13 00:29:21 +010050}
Joe Damato47cae1e2010-11-08 15:47:39 -080051
Petr Machata9a5420c2011-07-09 11:21:23 +020052static FILE *
53open_status_file(pid_t pid)
54{
55 PROC_PID_FILE(fn, "/proc/%d/status", pid);
56 /* Don't complain if we fail. This would typically happen
57 when the process is about to terminate, and these files are
58 not available anymore. This function is called from the
59 event loop, and we don't want to clutter the output just
60 because the process terminates. */
61 return fopen(fn, "r");
62}
63
64static char *
65find_line_starting(FILE * file, const char * prefix, size_t len)
66{
67 char * line = NULL;
68 size_t line_len = 0;
69 while (!feof(file)) {
70 if (getline(&line, &line_len, file) < 0)
71 return NULL;
72 if (strncmp(line, prefix, len) == 0)
73 return line;
74 }
75 return NULL;
76}
77
78static void
79each_line_starting(FILE * file, const char *prefix,
80 enum pcb_status (*cb)(const char * line, const char * prefix,
81 void * data),
82 void * data)
83{
84 size_t len = strlen(prefix);
85 char * line;
86 while ((line = find_line_starting(file, prefix, len)) != NULL) {
87 enum pcb_status st = (*cb)(line, prefix, data);
88 free (line);
89 if (st == pcb_stop)
90 return;
91 }
92}
93
94static enum pcb_status
95process_leader_cb(const char * line, const char * prefix, void * data)
96{
97 pid_t * pidp = data;
98 *pidp = atoi(line + strlen(prefix));
99 return pcb_stop;
100}
101
102pid_t
103process_leader(pid_t pid)
104{
Petr Machata1974dbc2011-08-19 18:58:01 +0200105 pid_t tgid = 0;
Petr Machata9a5420c2011-07-09 11:21:23 +0200106 FILE * file = open_status_file(pid);
107 if (file != NULL) {
108 each_line_starting(file, "Tgid:\t", &process_leader_cb, &tgid);
109 fclose(file);
110 }
111
112 return tgid;
113}
114
115static enum pcb_status
116process_stopped_cb(const char * line, const char * prefix, void * data)
117{
118 char c = line[strlen(prefix)];
119 // t:tracing stop, T:job control stop
120 *(int *)data = (c == 't' || c == 'T');
121 return pcb_stop;
122}
123
124int
125process_stopped(pid_t pid)
126{
127 int is_stopped = -1;
128 FILE * file = open_status_file(pid);
129 if (file != NULL) {
130 each_line_starting(file, "State:\t", &process_stopped_cb,
131 &is_stopped);
132 fclose(file);
133 }
134 return is_stopped;
135}
136
137static enum pcb_status
138process_status_cb(const char * line, const char * prefix, void * data)
139{
Petr Machata617ff0b2011-10-06 14:23:24 +0200140 const char * status = line + strlen(prefix);
141 const char c = *status;
142
143#define RETURN(C) do { \
144 *(enum process_status *)data = C; \
145 return pcb_stop; \
146 } while (0)
147
148 switch (c) {
149 case 'Z': RETURN(ps_zombie);
150 case 't': RETURN(ps_tracing_stop);
151 case 'T': {
152 /* This can be either "T (stopped)" or, for older
153 * kernels, "T (tracing stop)". */
154 if (!strcmp(status, "T (stopped)\n"))
155 RETURN(ps_stop);
156 else if (!strcmp(status, "T (tracing stop)\n"))
157 RETURN(ps_tracing_stop);
158 else {
159 fprintf(stderr, "Unknown process status: %s",
160 status);
161 RETURN(ps_stop); /* Some sort of stop
162 * anyway. */
163 }
164 }
165 }
166
167 RETURN(ps_other);
168#undef RETURN
Petr Machata9a5420c2011-07-09 11:21:23 +0200169}
170
Petr Machata617ff0b2011-10-06 14:23:24 +0200171enum process_status
Petr Machata9a5420c2011-07-09 11:21:23 +0200172process_status(pid_t pid)
173{
Petr Machata617ff0b2011-10-06 14:23:24 +0200174 enum process_status ret = ps_invalid;
Petr Machata9a5420c2011-07-09 11:21:23 +0200175 FILE * file = open_status_file(pid);
176 if (file != NULL) {
177 each_line_starting(file, "State:\t", &process_status_cb, &ret);
178 fclose(file);
Petr Machata750ca8c2011-10-06 14:29:34 +0200179 if (ret == ps_invalid)
180 error(0, errno, "process_status %d", pid);
181 } else
182 /* If the file is not present, the process presumably
183 * exited already. */
184 ret = ps_zombie;
185
Petr Machata9a5420c2011-07-09 11:21:23 +0200186 return ret;
187}
188
189static int
190all_digits(const char *str)
191{
192 while (isdigit(*str))
193 str++;
194 return !*str;
195}
196
197int
198process_tasks(pid_t pid, pid_t **ret_tasks, size_t *ret_n)
199{
200 PROC_PID_FILE(fn, "/proc/%d/task", pid);
201 DIR * d = opendir(fn);
202 if (d == NULL)
203 return -1;
204
Petr Machata9a5420c2011-07-09 11:21:23 +0200205 pid_t *tasks = NULL;
206 size_t n = 0;
207 size_t alloc = 0;
208
209 while (1) {
210 struct dirent entry;
211 struct dirent *result;
212 if (readdir_r(d, &entry, &result) != 0) {
213 free(tasks);
214 return -1;
215 }
216 if (result == NULL)
217 break;
218 if (result->d_type == DT_DIR && all_digits(result->d_name)) {
219 pid_t npid = atoi(result->d_name);
220 if (n >= alloc) {
221 alloc = alloc > 0 ? (2 * alloc) : 8;
222 pid_t *ntasks = realloc(tasks,
223 sizeof(*tasks) * alloc);
224 if (ntasks == NULL) {
225 free(tasks);
226 return -1;
227 }
228 tasks = ntasks;
229 }
230 if (n >= alloc)
231 abort();
232 tasks[n++] = npid;
233 }
234 }
235
236 closedir(d);
237
238 *ret_tasks = tasks;
239 *ret_n = n;
240 return 0;
241}
242
Joe Damato47cae1e2010-11-08 15:47:39 -0800243static int
244find_dynamic_entry_addr(Process *proc, void *pvAddr, int d_tag, void **addr) {
245 int i = 0, done = 0;
246 ElfW(Dyn) entry;
247
248 debug(DEBUG_FUNCTION, "find_dynamic_entry()");
249
250 if (addr == NULL || pvAddr == NULL || d_tag < 0 || d_tag > DT_NUM) {
251 return -1;
252 }
253
254 while ((!done) && (i < ELF_MAX_SEGMENTS) &&
255 (sizeof(entry) == umovebytes(proc, pvAddr, &entry, sizeof(entry))) &&
256 (entry.d_tag != DT_NULL)) {
257 if (entry.d_tag == d_tag) {
258 done = 1;
259 *addr = (void *)entry.d_un.d_val;
260 }
261 pvAddr += sizeof(entry);
262 i++;
263 }
264
265 if (done) {
266 debug(2, "found address: 0x%p in dtag %d\n", *addr, d_tag);
267 return 0;
268 }
269 else {
270 debug(2, "Couldn't address for dtag!\n");
271 return -1;
272 }
273}
Joe Damatof0bd98b2010-11-08 15:47:42 -0800274
275struct cb_data {
276 const char *lib_name;
277 struct ltelf *lte;
278 ElfW(Addr) addr;
279 Process *proc;
280};
281
282static void
283crawl_linkmap(Process *proc, struct r_debug *dbg, void (*callback)(void *), struct cb_data *data) {
284 struct link_map rlm;
285 char lib_name[BUFSIZ];
286 struct link_map *lm = NULL;
287
288 debug (DEBUG_FUNCTION, "crawl_linkmap()");
289
290 if (!dbg || !dbg->r_map) {
291 debug(2, "Debug structure or it's linkmap are NULL!");
292 return;
293 }
294
295 lm = dbg->r_map;
296
297 while (lm) {
298 if (umovebytes(proc, lm, &rlm, sizeof(rlm)) != sizeof(rlm)) {
299 debug(2, "Unable to read link map\n");
300 return;
301 }
302
303 lm = rlm.l_next;
304 if (rlm.l_name == NULL) {
305 debug(2, "Invalid library name referenced in dynamic linker map\n");
306 return;
307 }
308
309 umovebytes(proc, rlm.l_name, lib_name, sizeof(lib_name));
310
311 if (lib_name[0] == '\0') {
312 debug(2, "Library name is an empty string");
313 continue;
314 }
315
316 if (callback) {
Zachary T Welch3ba522f2010-12-14 15:12:47 -0800317 debug(2, "Dispatching callback for: %s, "
318 "Loaded at 0x%" PRI_ELF_ADDR "\n",
319 lib_name, rlm.l_addr);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800320 data->addr = rlm.l_addr;
321 data->lib_name = lib_name;
322 callback(data);
323 }
324 }
325 return;
326}
327
328static struct r_debug *
329load_debug_struct(Process *proc) {
330 struct r_debug *rdbg = NULL;
331
332 debug(DEBUG_FUNCTION, "load_debug_struct");
333
334 rdbg = malloc(sizeof(*rdbg));
335 if (!rdbg) {
336 return NULL;
337 }
338
339 if (umovebytes(proc, proc->debug, rdbg, sizeof(*rdbg)) != sizeof(*rdbg)) {
340 debug(2, "This process does not have a debug structure!\n");
341 free(rdbg);
342 return NULL;
343 }
344
345 return rdbg;
346}
347
348static void
349linkmap_add_cb(void *data) { //const char *lib_name, ElfW(Addr) addr) {
Zachary T Welchba6aca22010-12-08 18:55:09 -0800350 size_t i = 0;
Joe Damatof0bd98b2010-11-08 15:47:42 -0800351 struct cb_data *lm_add = data;
352 struct ltelf lte;
353 struct opt_x_t *xptr;
354
355 debug(DEBUG_FUNCTION, "linkmap_add_cb");
356
357 /*
358 XXX
359 iterate through library[i]'s to see if this lib is in the list.
360 if not, add it
361 */
362 for(;i < library_num;i++) {
363 if (strcmp(library[i], lm_add->lib_name) == 0) {
364 /* found it, so its not new */
365 return;
366 }
367 }
368
369 /* new library linked! */
370 debug(2, "New libdl loaded library found: %s\n", lm_add->lib_name);
371
372 if (library_num < MAX_LIBRARIES) {
373 library[library_num++] = strdup(lm_add->lib_name);
374 memset(&lte, 0, sizeof(struct ltelf));
375 lte.base_addr = lm_add->addr;
376 do_init_elf(&lte, library[library_num-1]);
377 /* add bps */
378 for (xptr = opt_x; xptr; xptr = xptr->next) {
379 if (xptr->found)
380 continue;
381
382 GElf_Sym sym;
383 GElf_Addr addr;
384
385 if (in_load_libraries(xptr->name, &lte, 1, &sym)) {
Zachary T Welchbfb26c72010-12-06 23:21:00 -0800386 debug(2, "found symbol %s @ %#" PRIx64
387 ", adding it.",
388 xptr->name, sym.st_value);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800389 addr = sym.st_value;
390 add_library_symbol(addr, xptr->name, &library_symbols, LS_TOPLT_NONE, 0);
391 xptr->found = 1;
Petr Machata26627682011-07-08 18:15:32 +0200392 insert_breakpoint(lm_add->proc,
393 sym2addr(lm_add->proc,
394 library_symbols),
Petr Machatac7585b62011-07-08 22:58:12 +0200395 library_symbols, 1);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800396 }
397 }
398 do_close_elf(&lte);
399 }
400}
401
402void
403arch_check_dbg(Process *proc) {
404 struct r_debug *dbg = NULL;
405 struct cb_data data;
406
407 debug(DEBUG_FUNCTION, "arch_check_dbg");
408
409 if (!(dbg = load_debug_struct(proc))) {
410 debug(2, "Unable to load debug structure!");
411 return;
412 }
413
414 if (dbg->r_state == RT_CONSISTENT) {
415 debug(2, "Linkmap is now consistent");
416 if (proc->debug_state == RT_ADD) {
417 debug(2, "Adding DSO to linkmap");
418 data.proc = proc;
419 crawl_linkmap(proc, dbg, linkmap_add_cb, &data);
420 } else if (proc->debug_state == RT_DELETE) {
421 debug(2, "Removing DSO from linkmap");
422 } else {
423 debug(2, "Unexpected debug state!");
424 }
425 }
426
427 proc->debug_state = dbg->r_state;
428
429 return;
430}
431
432static void
433hook_libdl_cb(void *data) {
434 struct cb_data *hook_data = data;
435 const char *lib_name = NULL;
436 ElfW(Addr) addr;
437 struct ltelf *lte = NULL;
438
439 debug(DEBUG_FUNCTION, "add_library_cb");
440
441 if (!data) {
442 debug(2, "No callback data");
443 return;
444 }
445
446 lib_name = hook_data->lib_name;
447 addr = hook_data->addr;
448 lte = hook_data->lte;
449
450 if (library_num < MAX_LIBRARIES) {
Joe Damatof0bd98b2010-11-08 15:47:42 -0800451 lte[library_num].base_addr = addr;
Petr Machata08677d02011-05-19 16:09:17 +0200452 library[library_num++] = strdup(lib_name);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800453 }
454 else {
455 fprintf (stderr, "MAX LIBS REACHED\n");
456 exit(EXIT_FAILURE);
457 }
458}
459
460int
461linkmap_init(Process *proc, struct ltelf *lte) {
Zachary T Welch3ba522f2010-12-14 15:12:47 -0800462 void *dbg_addr = NULL, *dyn_addr = GELF_ADDR_CAST(lte->dyn_addr);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800463 struct r_debug *rdbg = NULL;
464 struct cb_data data;
465
466 debug(DEBUG_FUNCTION, "linkmap_init()");
467
Zachary T Welchba6aca22010-12-08 18:55:09 -0800468 if (find_dynamic_entry_addr(proc, dyn_addr, DT_DEBUG, &dbg_addr) == -1) {
Joe Damatof0bd98b2010-11-08 15:47:42 -0800469 debug(2, "Couldn't find debug structure!");
470 return -1;
471 }
472
473 proc->debug = dbg_addr;
474
475 if (!(rdbg = load_debug_struct(proc))) {
476 debug(2, "No debug structure or no memory to allocate one!");
477 return -1;
478 }
479
480 data.lte = lte;
481
482 add_library_symbol(rdbg->r_brk, "", &library_symbols, LS_TOPLT_NONE, 0);
Petr Machata26627682011-07-08 18:15:32 +0200483 insert_breakpoint(proc, sym2addr(proc, library_symbols),
Petr Machatac7585b62011-07-08 22:58:12 +0200484 library_symbols, 1);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800485
486 crawl_linkmap(proc, rdbg, hook_libdl_cb, &data);
487
488 free(rdbg);
489 return 0;
490}
Petr Machata9a5420c2011-07-09 11:21:23 +0200491
492int
493task_kill (pid_t pid, int sig)
494{
495 // Taken from GDB
496 int ret;
497
498 errno = 0;
499 ret = syscall (__NR_tkill, pid, sig);
500 return ret;
501}