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