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