blob: a99593c1fad2aaa7b61a1045eaf74a232000118a [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);
Petr Machatacbe29c62011-09-27 02:27:58 +0200151 case 'T':
Petr Machata617ff0b2011-10-06 14:23:24 +0200152 /* 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 }
Petr Machatacbe29c62011-09-27 02:27:58 +0200164 case 'D':
165 case 'S': RETURN(ps_sleeping);
Petr Machata617ff0b2011-10-06 14:23:24 +0200166 }
167
168 RETURN(ps_other);
169#undef RETURN
Petr Machata9a5420c2011-07-09 11:21:23 +0200170}
171
Petr Machata617ff0b2011-10-06 14:23:24 +0200172enum process_status
Petr Machata9a5420c2011-07-09 11:21:23 +0200173process_status(pid_t pid)
174{
Petr Machata617ff0b2011-10-06 14:23:24 +0200175 enum process_status ret = ps_invalid;
Petr Machata9a5420c2011-07-09 11:21:23 +0200176 FILE * file = open_status_file(pid);
177 if (file != NULL) {
178 each_line_starting(file, "State:\t", &process_status_cb, &ret);
179 fclose(file);
Petr Machata750ca8c2011-10-06 14:29:34 +0200180 if (ret == ps_invalid)
181 error(0, errno, "process_status %d", pid);
182 } else
183 /* If the file is not present, the process presumably
184 * exited already. */
185 ret = ps_zombie;
186
Petr Machata9a5420c2011-07-09 11:21:23 +0200187 return ret;
188}
189
190static int
191all_digits(const char *str)
192{
193 while (isdigit(*str))
194 str++;
195 return !*str;
196}
197
198int
199process_tasks(pid_t pid, pid_t **ret_tasks, size_t *ret_n)
200{
201 PROC_PID_FILE(fn, "/proc/%d/task", pid);
202 DIR * d = opendir(fn);
203 if (d == NULL)
204 return -1;
205
Petr Machata9a5420c2011-07-09 11:21:23 +0200206 pid_t *tasks = NULL;
207 size_t n = 0;
208 size_t alloc = 0;
209
210 while (1) {
211 struct dirent entry;
212 struct dirent *result;
213 if (readdir_r(d, &entry, &result) != 0) {
214 free(tasks);
215 return -1;
216 }
217 if (result == NULL)
218 break;
219 if (result->d_type == DT_DIR && all_digits(result->d_name)) {
220 pid_t npid = atoi(result->d_name);
221 if (n >= alloc) {
222 alloc = alloc > 0 ? (2 * alloc) : 8;
223 pid_t *ntasks = realloc(tasks,
224 sizeof(*tasks) * alloc);
225 if (ntasks == NULL) {
226 free(tasks);
227 return -1;
228 }
229 tasks = ntasks;
230 }
231 if (n >= alloc)
232 abort();
233 tasks[n++] = npid;
234 }
235 }
236
237 closedir(d);
238
239 *ret_tasks = tasks;
240 *ret_n = n;
241 return 0;
242}
243
Joe Damato47cae1e2010-11-08 15:47:39 -0800244static int
245find_dynamic_entry_addr(Process *proc, void *pvAddr, int d_tag, void **addr) {
246 int i = 0, done = 0;
247 ElfW(Dyn) entry;
248
249 debug(DEBUG_FUNCTION, "find_dynamic_entry()");
250
251 if (addr == NULL || pvAddr == NULL || d_tag < 0 || d_tag > DT_NUM) {
252 return -1;
253 }
254
255 while ((!done) && (i < ELF_MAX_SEGMENTS) &&
256 (sizeof(entry) == umovebytes(proc, pvAddr, &entry, sizeof(entry))) &&
257 (entry.d_tag != DT_NULL)) {
258 if (entry.d_tag == d_tag) {
259 done = 1;
260 *addr = (void *)entry.d_un.d_val;
261 }
262 pvAddr += sizeof(entry);
263 i++;
264 }
265
266 if (done) {
267 debug(2, "found address: 0x%p in dtag %d\n", *addr, d_tag);
268 return 0;
269 }
270 else {
271 debug(2, "Couldn't address for dtag!\n");
272 return -1;
273 }
274}
Joe Damatof0bd98b2010-11-08 15:47:42 -0800275
276struct cb_data {
277 const char *lib_name;
278 struct ltelf *lte;
279 ElfW(Addr) addr;
280 Process *proc;
281};
282
283static void
284crawl_linkmap(Process *proc, struct r_debug *dbg, void (*callback)(void *), struct cb_data *data) {
285 struct link_map rlm;
286 char lib_name[BUFSIZ];
287 struct link_map *lm = NULL;
288
289 debug (DEBUG_FUNCTION, "crawl_linkmap()");
290
291 if (!dbg || !dbg->r_map) {
292 debug(2, "Debug structure or it's linkmap are NULL!");
293 return;
294 }
295
296 lm = dbg->r_map;
297
298 while (lm) {
299 if (umovebytes(proc, lm, &rlm, sizeof(rlm)) != sizeof(rlm)) {
300 debug(2, "Unable to read link map\n");
301 return;
302 }
303
304 lm = rlm.l_next;
305 if (rlm.l_name == NULL) {
306 debug(2, "Invalid library name referenced in dynamic linker map\n");
307 return;
308 }
309
310 umovebytes(proc, rlm.l_name, lib_name, sizeof(lib_name));
311
312 if (lib_name[0] == '\0') {
313 debug(2, "Library name is an empty string");
314 continue;
315 }
316
317 if (callback) {
Zachary T Welch3ba522f2010-12-14 15:12:47 -0800318 debug(2, "Dispatching callback for: %s, "
319 "Loaded at 0x%" PRI_ELF_ADDR "\n",
320 lib_name, rlm.l_addr);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800321 data->addr = rlm.l_addr;
322 data->lib_name = lib_name;
323 callback(data);
324 }
325 }
326 return;
327}
328
329static struct r_debug *
330load_debug_struct(Process *proc) {
331 struct r_debug *rdbg = NULL;
332
333 debug(DEBUG_FUNCTION, "load_debug_struct");
334
335 rdbg = malloc(sizeof(*rdbg));
336 if (!rdbg) {
337 return NULL;
338 }
339
340 if (umovebytes(proc, proc->debug, rdbg, sizeof(*rdbg)) != sizeof(*rdbg)) {
341 debug(2, "This process does not have a debug structure!\n");
342 free(rdbg);
343 return NULL;
344 }
345
346 return rdbg;
347}
348
349static void
350linkmap_add_cb(void *data) { //const char *lib_name, ElfW(Addr) addr) {
Zachary T Welchba6aca22010-12-08 18:55:09 -0800351 size_t i = 0;
Joe Damatof0bd98b2010-11-08 15:47:42 -0800352 struct cb_data *lm_add = data;
353 struct ltelf lte;
354 struct opt_x_t *xptr;
355
356 debug(DEBUG_FUNCTION, "linkmap_add_cb");
357
358 /*
359 XXX
360 iterate through library[i]'s to see if this lib is in the list.
361 if not, add it
362 */
363 for(;i < library_num;i++) {
364 if (strcmp(library[i], lm_add->lib_name) == 0) {
365 /* found it, so its not new */
366 return;
367 }
368 }
369
370 /* new library linked! */
371 debug(2, "New libdl loaded library found: %s\n", lm_add->lib_name);
372
373 if (library_num < MAX_LIBRARIES) {
374 library[library_num++] = strdup(lm_add->lib_name);
375 memset(&lte, 0, sizeof(struct ltelf));
376 lte.base_addr = lm_add->addr;
377 do_init_elf(&lte, library[library_num-1]);
378 /* add bps */
379 for (xptr = opt_x; xptr; xptr = xptr->next) {
380 if (xptr->found)
381 continue;
382
383 GElf_Sym sym;
384 GElf_Addr addr;
385
386 if (in_load_libraries(xptr->name, &lte, 1, &sym)) {
Zachary T Welchbfb26c72010-12-06 23:21:00 -0800387 debug(2, "found symbol %s @ %#" PRIx64
388 ", adding it.",
389 xptr->name, sym.st_value);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800390 addr = sym.st_value;
391 add_library_symbol(addr, xptr->name, &library_symbols, LS_TOPLT_NONE, 0);
392 xptr->found = 1;
Petr Machata26627682011-07-08 18:15:32 +0200393 insert_breakpoint(lm_add->proc,
394 sym2addr(lm_add->proc,
395 library_symbols),
Petr Machatac7585b62011-07-08 22:58:12 +0200396 library_symbols, 1);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800397 }
398 }
399 do_close_elf(&lte);
400 }
401}
402
403void
404arch_check_dbg(Process *proc) {
405 struct r_debug *dbg = NULL;
406 struct cb_data data;
407
408 debug(DEBUG_FUNCTION, "arch_check_dbg");
409
410 if (!(dbg = load_debug_struct(proc))) {
411 debug(2, "Unable to load debug structure!");
412 return;
413 }
414
415 if (dbg->r_state == RT_CONSISTENT) {
416 debug(2, "Linkmap is now consistent");
417 if (proc->debug_state == RT_ADD) {
418 debug(2, "Adding DSO to linkmap");
419 data.proc = proc;
420 crawl_linkmap(proc, dbg, linkmap_add_cb, &data);
421 } else if (proc->debug_state == RT_DELETE) {
422 debug(2, "Removing DSO from linkmap");
423 } else {
424 debug(2, "Unexpected debug state!");
425 }
426 }
427
428 proc->debug_state = dbg->r_state;
429
430 return;
431}
432
433static void
434hook_libdl_cb(void *data) {
435 struct cb_data *hook_data = data;
436 const char *lib_name = NULL;
437 ElfW(Addr) addr;
438 struct ltelf *lte = NULL;
439
440 debug(DEBUG_FUNCTION, "add_library_cb");
441
442 if (!data) {
443 debug(2, "No callback data");
444 return;
445 }
446
447 lib_name = hook_data->lib_name;
448 addr = hook_data->addr;
449 lte = hook_data->lte;
450
451 if (library_num < MAX_LIBRARIES) {
Joe Damatof0bd98b2010-11-08 15:47:42 -0800452 lte[library_num].base_addr = addr;
Petr Machata08677d02011-05-19 16:09:17 +0200453 library[library_num++] = strdup(lib_name);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800454 }
455 else {
456 fprintf (stderr, "MAX LIBS REACHED\n");
457 exit(EXIT_FAILURE);
458 }
459}
460
461int
462linkmap_init(Process *proc, struct ltelf *lte) {
Zachary T Welch3ba522f2010-12-14 15:12:47 -0800463 void *dbg_addr = NULL, *dyn_addr = GELF_ADDR_CAST(lte->dyn_addr);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800464 struct r_debug *rdbg = NULL;
465 struct cb_data data;
466
467 debug(DEBUG_FUNCTION, "linkmap_init()");
468
Zachary T Welchba6aca22010-12-08 18:55:09 -0800469 if (find_dynamic_entry_addr(proc, dyn_addr, DT_DEBUG, &dbg_addr) == -1) {
Joe Damatof0bd98b2010-11-08 15:47:42 -0800470 debug(2, "Couldn't find debug structure!");
471 return -1;
472 }
473
474 proc->debug = dbg_addr;
475
476 if (!(rdbg = load_debug_struct(proc))) {
477 debug(2, "No debug structure or no memory to allocate one!");
478 return -1;
479 }
480
481 data.lte = lte;
482
483 add_library_symbol(rdbg->r_brk, "", &library_symbols, LS_TOPLT_NONE, 0);
Petr Machata26627682011-07-08 18:15:32 +0200484 insert_breakpoint(proc, sym2addr(proc, library_symbols),
Petr Machatac7585b62011-07-08 22:58:12 +0200485 library_symbols, 1);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800486
487 crawl_linkmap(proc, rdbg, hook_libdl_cb, &data);
488
489 free(rdbg);
490 return 0;
491}
Petr Machata9a5420c2011-07-09 11:21:23 +0200492
493int
494task_kill (pid_t pid, int sig)
495{
496 // Taken from GDB
497 int ret;
498
499 errno = 0;
500 ret = syscall (__NR_tkill, pid, sig);
501 return ret;
502}