blob: 8cea99cd9e81d6389261961dad8ba5a05c4871d5 [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"
Petr Machata366c2f42012-02-09 19:34:36 +010021#include "proc.h"
Petr Machata2b46cfc2012-02-18 11:17:29 +010022#include "library.h"
Juan Cespedes273ea6d1998-03-14 23:02:40 +010023
24/* /proc/pid doesn't exist just after the fork, and sometimes `ltrace'
25 * couldn't open it to find the executable. So it may be necessary to
26 * have a bit delay
27 */
28
Ian Wienand2d45b1a2006-02-20 22:48:07 +010029#define MAX_DELAY 100000 /* 100000 microseconds = 0.1 seconds */
Juan Cespedes1fe93d51998-03-13 00:29:21 +010030
Petr Machata9a5420c2011-07-09 11:21:23 +020031#define PROC_PID_FILE(VAR, FORMAT, PID) \
32 char VAR[strlen(FORMAT) + 6]; \
33 sprintf(VAR, FORMAT, PID)
34
Juan Cespedes1fe93d51998-03-13 00:29:21 +010035/*
Juan Cespedese0660df2009-05-21 18:14:39 +020036 * Returns a (malloc'd) file name corresponding to a running pid
Juan Cespedes1fe93d51998-03-13 00:29:21 +010037 */
Juan Cespedesf1350522008-12-16 18:19:58 +010038char *
39pid2name(pid_t pid) {
Juan Cespedes1fe93d51998-03-13 00:29:21 +010040 if (!kill(pid, 0)) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010041 int delay = 0;
Juan Cespedes273ea6d1998-03-14 23:02:40 +010042
Petr Machata9a5420c2011-07-09 11:21:23 +020043 PROC_PID_FILE(proc_exe, "/proc/%d/exe", pid);
Juan Cespedes273ea6d1998-03-14 23:02:40 +010044
Ian Wienand2d45b1a2006-02-20 22:48:07 +010045 while (delay < MAX_DELAY) {
Juan Cespedes273ea6d1998-03-14 23:02:40 +010046 if (!access(proc_exe, F_OK)) {
47 return strdup(proc_exe);
48 }
49 delay += 1000; /* 1 milisecond */
50 }
Juan Cespedes1fe93d51998-03-13 00:29:21 +010051 }
Juan Cespedes273ea6d1998-03-14 23:02:40 +010052 return NULL;
Juan Cespedes1fe93d51998-03-13 00:29:21 +010053}
Joe Damato47cae1e2010-11-08 15:47:39 -080054
Petr Machata9a5420c2011-07-09 11:21:23 +020055static FILE *
56open_status_file(pid_t pid)
57{
58 PROC_PID_FILE(fn, "/proc/%d/status", pid);
59 /* Don't complain if we fail. This would typically happen
60 when the process is about to terminate, and these files are
61 not available anymore. This function is called from the
62 event loop, and we don't want to clutter the output just
63 because the process terminates. */
64 return fopen(fn, "r");
65}
66
67static char *
68find_line_starting(FILE * file, const char * prefix, size_t len)
69{
70 char * line = NULL;
71 size_t line_len = 0;
72 while (!feof(file)) {
73 if (getline(&line, &line_len, file) < 0)
74 return NULL;
75 if (strncmp(line, prefix, len) == 0)
76 return line;
77 }
78 return NULL;
79}
80
81static void
Petr Machata2b46cfc2012-02-18 11:17:29 +010082each_line_starting(FILE *file, const char *prefix,
83 enum callback_status (*cb)(const char *line,
84 const char *prefix,
85 void *data),
86 void *data)
Petr Machata9a5420c2011-07-09 11:21:23 +020087{
88 size_t len = strlen(prefix);
89 char * line;
90 while ((line = find_line_starting(file, prefix, len)) != NULL) {
Petr Machata2b46cfc2012-02-18 11:17:29 +010091 enum callback_status st = (*cb)(line, prefix, data);
Petr Machata9a5420c2011-07-09 11:21:23 +020092 free (line);
Petr Machata2b46cfc2012-02-18 11:17:29 +010093 if (st == CBS_STOP)
Petr Machata9a5420c2011-07-09 11:21:23 +020094 return;
95 }
96}
97
Petr Machata2b46cfc2012-02-18 11:17:29 +010098static enum callback_status
99process_leader_cb(const char *line, const char *prefix, void *data)
Petr Machata9a5420c2011-07-09 11:21:23 +0200100{
101 pid_t * pidp = data;
102 *pidp = atoi(line + strlen(prefix));
Petr Machata2b46cfc2012-02-18 11:17:29 +0100103 return CBS_STOP;
Petr Machata9a5420c2011-07-09 11:21:23 +0200104}
105
106pid_t
107process_leader(pid_t pid)
108{
Petr Machata1974dbc2011-08-19 18:58:01 +0200109 pid_t tgid = 0;
Petr Machata9a5420c2011-07-09 11:21:23 +0200110 FILE * file = open_status_file(pid);
111 if (file != NULL) {
112 each_line_starting(file, "Tgid:\t", &process_leader_cb, &tgid);
113 fclose(file);
114 }
115
116 return tgid;
117}
118
Petr Machata2b46cfc2012-02-18 11:17:29 +0100119static enum callback_status
120process_stopped_cb(const char *line, const char *prefix, void *data)
Petr Machata9a5420c2011-07-09 11:21:23 +0200121{
122 char c = line[strlen(prefix)];
123 // t:tracing stop, T:job control stop
124 *(int *)data = (c == 't' || c == 'T');
Petr Machata2b46cfc2012-02-18 11:17:29 +0100125 return CBS_STOP;
Petr Machata9a5420c2011-07-09 11:21:23 +0200126}
127
128int
129process_stopped(pid_t pid)
130{
131 int is_stopped = -1;
132 FILE * file = open_status_file(pid);
133 if (file != NULL) {
134 each_line_starting(file, "State:\t", &process_stopped_cb,
135 &is_stopped);
136 fclose(file);
137 }
138 return is_stopped;
139}
140
Petr Machata2b46cfc2012-02-18 11:17:29 +0100141static enum callback_status
142process_status_cb(const char *line, const char *prefix, void *data)
Petr Machata9a5420c2011-07-09 11:21:23 +0200143{
Petr Machata617ff0b2011-10-06 14:23:24 +0200144 const char * status = line + strlen(prefix);
145 const char c = *status;
146
147#define RETURN(C) do { \
148 *(enum process_status *)data = C; \
Petr Machata2b46cfc2012-02-18 11:17:29 +0100149 return CBS_STOP; \
Petr Machata617ff0b2011-10-06 14:23:24 +0200150 } while (0)
151
152 switch (c) {
153 case 'Z': RETURN(ps_zombie);
154 case 't': RETURN(ps_tracing_stop);
Petr Machatacbe29c62011-09-27 02:27:58 +0200155 case 'T':
Petr Machata617ff0b2011-10-06 14:23:24 +0200156 /* This can be either "T (stopped)" or, for older
157 * kernels, "T (tracing stop)". */
158 if (!strcmp(status, "T (stopped)\n"))
159 RETURN(ps_stop);
160 else if (!strcmp(status, "T (tracing stop)\n"))
161 RETURN(ps_tracing_stop);
162 else {
163 fprintf(stderr, "Unknown process status: %s",
164 status);
165 RETURN(ps_stop); /* Some sort of stop
166 * anyway. */
167 }
Petr Machatacbe29c62011-09-27 02:27:58 +0200168 case 'D':
169 case 'S': RETURN(ps_sleeping);
Petr Machata617ff0b2011-10-06 14:23:24 +0200170 }
171
172 RETURN(ps_other);
173#undef RETURN
Petr Machata9a5420c2011-07-09 11:21:23 +0200174}
175
Petr Machata617ff0b2011-10-06 14:23:24 +0200176enum process_status
Petr Machata9a5420c2011-07-09 11:21:23 +0200177process_status(pid_t pid)
178{
Petr Machata617ff0b2011-10-06 14:23:24 +0200179 enum process_status ret = ps_invalid;
Petr Machata9a5420c2011-07-09 11:21:23 +0200180 FILE * file = open_status_file(pid);
181 if (file != NULL) {
182 each_line_starting(file, "State:\t", &process_status_cb, &ret);
183 fclose(file);
Petr Machata750ca8c2011-10-06 14:29:34 +0200184 if (ret == ps_invalid)
185 error(0, errno, "process_status %d", pid);
186 } else
187 /* If the file is not present, the process presumably
188 * exited already. */
189 ret = ps_zombie;
190
Petr Machata9a5420c2011-07-09 11:21:23 +0200191 return ret;
192}
193
194static int
195all_digits(const char *str)
196{
197 while (isdigit(*str))
198 str++;
199 return !*str;
200}
201
202int
203process_tasks(pid_t pid, pid_t **ret_tasks, size_t *ret_n)
204{
205 PROC_PID_FILE(fn, "/proc/%d/task", pid);
206 DIR * d = opendir(fn);
207 if (d == NULL)
208 return -1;
209
Petr Machata9a5420c2011-07-09 11:21:23 +0200210 pid_t *tasks = NULL;
211 size_t n = 0;
212 size_t alloc = 0;
213
214 while (1) {
215 struct dirent entry;
216 struct dirent *result;
217 if (readdir_r(d, &entry, &result) != 0) {
218 free(tasks);
219 return -1;
220 }
221 if (result == NULL)
222 break;
223 if (result->d_type == DT_DIR && all_digits(result->d_name)) {
224 pid_t npid = atoi(result->d_name);
225 if (n >= alloc) {
226 alloc = alloc > 0 ? (2 * alloc) : 8;
227 pid_t *ntasks = realloc(tasks,
228 sizeof(*tasks) * alloc);
229 if (ntasks == NULL) {
230 free(tasks);
231 return -1;
232 }
233 tasks = ntasks;
234 }
235 if (n >= alloc)
236 abort();
237 tasks[n++] = npid;
238 }
239 }
240
241 closedir(d);
242
243 *ret_tasks = tasks;
244 *ret_n = n;
245 return 0;
246}
247
Joe Damato47cae1e2010-11-08 15:47:39 -0800248static int
249find_dynamic_entry_addr(Process *proc, void *pvAddr, int d_tag, void **addr) {
Petr Machata2b46cfc2012-02-18 11:17:29 +0100250 fprintf(stderr, "find_dynamic_entry_addr %d %p %d\n",
251 proc->pid, pvAddr, d_tag);
Joe Damato47cae1e2010-11-08 15:47:39 -0800252 ElfW(Dyn) entry;
253
254 debug(DEBUG_FUNCTION, "find_dynamic_entry()");
255
Petr Machatace40b392012-02-23 18:50:49 +0100256 if (addr == NULL || pvAddr == NULL || d_tag < 0 || d_tag > DT_NUM) {
Joe Damato47cae1e2010-11-08 15:47:39 -0800257 return -1;
258 }
259
Petr Machata17476b72012-02-23 18:50:37 +0100260 while ((sizeof(entry) == umovebytes(proc, pvAddr, &entry, sizeof(entry))) &&
261 (entry.d_tag != DT_NULL)) {
Petr Machata2b46cfc2012-02-18 11:17:29 +0100262 fprintf(stderr, " entry %ld %#lx\n", entry.d_tag, entry.d_un.d_val);
Joe Damato47cae1e2010-11-08 15:47:39 -0800263 if (entry.d_tag == d_tag) {
Petr Machata2b46cfc2012-02-18 11:17:29 +0100264 fprintf(stderr, " hit\n");
Joe Damato47cae1e2010-11-08 15:47:39 -0800265 *addr = (void *)entry.d_un.d_val;
Petr Machata17476b72012-02-23 18:50:37 +0100266 debug(2, "found address: 0x%p in dtag %d\n", *addr, d_tag);
267 return 0;
Joe Damato47cae1e2010-11-08 15:47:39 -0800268 }
269 pvAddr += sizeof(entry);
Joe Damato47cae1e2010-11-08 15:47:39 -0800270 }
271
Petr Machata17476b72012-02-23 18:50:37 +0100272 debug(2, "Couldn't address for dtag!\n");
273 return -1;
Joe Damato47cae1e2010-11-08 15:47:39 -0800274}
Joe Damatof0bd98b2010-11-08 15:47:42 -0800275
Petr Machata2b46cfc2012-02-18 11:17:29 +0100276enum callback_status
277find_library_addr(struct Process *proc, struct library *lib, void *data)
278{
279 target_address_t addr = (target_address_t)*(GElf_Addr *)data;
280 return lib->base == addr ? CBS_STOP : CBS_CONT;
281}
Joe Damatof0bd98b2010-11-08 15:47:42 -0800282
283static void
Petr Machata2b46cfc2012-02-18 11:17:29 +0100284crawl_linkmap(Process *proc, struct r_debug *dbg)
285{
Joe Damatof0bd98b2010-11-08 15:47:42 -0800286 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
Petr Machata2b46cfc2012-02-18 11:17:29 +0100313 debug(2, "Dispatching callback for: %s, "
314 "Loaded at 0x%" PRI_ELF_ADDR "\n",
315 lib_name, rlm.l_addr);
316 fprintf(stderr, "DSO addr=%#lx, name='%s'\n", rlm.l_addr, lib_name);
317
318 /* Do we have that library already? */
319 struct library *lib
320 = proc_each_library(proc, NULL, find_library_addr,
321 &rlm.l_addr);
322 if (lib != NULL)
323 continue;
324
325 if (*lib_name == '\0') {
326 /* VDSO. No associated file, XXX but we might
327 * load it from the address space of the
328 * process. */
Joe Damatof0bd98b2010-11-08 15:47:42 -0800329 continue;
330 }
331
Petr Machatab120fdf2012-03-21 05:05:46 +0100332 lib = ltelf_read_library(proc, lib_name, rlm.l_addr);
Petr Machata2b46cfc2012-02-18 11:17:29 +0100333 if (lib == NULL) {
334 error(0, errno, "Couldn't load ELF object %s\n",
335 lib_name);
336 continue;
Joe Damatof0bd98b2010-11-08 15:47:42 -0800337 }
Petr Machata2b46cfc2012-02-18 11:17:29 +0100338
339 proc_add_library(proc, lib);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800340 }
341 return;
342}
343
344static struct r_debug *
345load_debug_struct(Process *proc) {
346 struct r_debug *rdbg = NULL;
347
348 debug(DEBUG_FUNCTION, "load_debug_struct");
349
350 rdbg = malloc(sizeof(*rdbg));
351 if (!rdbg) {
352 return NULL;
353 }
354
355 if (umovebytes(proc, proc->debug, rdbg, sizeof(*rdbg)) != sizeof(*rdbg)) {
356 debug(2, "This process does not have a debug structure!\n");
357 free(rdbg);
358 return NULL;
359 }
360
361 return rdbg;
362}
363
364static void
Petr Machata12affff2012-03-29 18:33:03 +0200365rdebug_bp_on_hit(struct breakpoint *bp, struct Process *proc)
Petr Machata2b46cfc2012-02-18 11:17:29 +0100366{
367 fprintf(stderr, "======= HIT\n");
Joe Damatof0bd98b2010-11-08 15:47:42 -0800368 struct r_debug *dbg = NULL;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100369 //struct cb_data data;
Joe Damatof0bd98b2010-11-08 15:47:42 -0800370
371 debug(DEBUG_FUNCTION, "arch_check_dbg");
372
373 if (!(dbg = load_debug_struct(proc))) {
374 debug(2, "Unable to load debug structure!");
375 return;
376 }
377
378 if (dbg->r_state == RT_CONSISTENT) {
379 debug(2, "Linkmap is now consistent");
380 if (proc->debug_state == RT_ADD) {
381 debug(2, "Adding DSO to linkmap");
Petr Machata2b46cfc2012-02-18 11:17:29 +0100382 //data.proc = proc;
383 crawl_linkmap(proc, dbg);
384 //&data);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800385 } else if (proc->debug_state == RT_DELETE) {
386 debug(2, "Removing DSO from linkmap");
387 } else {
388 debug(2, "Unexpected debug state!");
389 }
390 }
391
392 proc->debug_state = dbg->r_state;
Joe Damatof0bd98b2010-11-08 15:47:42 -0800393 return;
394}
395
Joe Damatof0bd98b2010-11-08 15:47:42 -0800396int
Petr Machata52dbfb12012-03-29 16:38:26 +0200397linkmap_init(struct Process *proc, target_address_t dyn_addr)
Petr Machata2b46cfc2012-02-18 11:17:29 +0100398{
399 void *dbg_addr = NULL;
Joe Damatof0bd98b2010-11-08 15:47:42 -0800400 struct r_debug *rdbg = NULL;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100401 //struct cb_data data;
Joe Damatof0bd98b2010-11-08 15:47:42 -0800402
403 debug(DEBUG_FUNCTION, "linkmap_init()");
Petr Machata2b46cfc2012-02-18 11:17:29 +0100404 fprintf(stderr, "linkmap_init dyn_addr=%p\n", dyn_addr);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800405
Zachary T Welchba6aca22010-12-08 18:55:09 -0800406 if (find_dynamic_entry_addr(proc, dyn_addr, DT_DEBUG, &dbg_addr) == -1) {
Joe Damatof0bd98b2010-11-08 15:47:42 -0800407 debug(2, "Couldn't find debug structure!");
408 return -1;
409 }
410
411 proc->debug = dbg_addr;
412
413 if (!(rdbg = load_debug_struct(proc))) {
414 debug(2, "No debug structure or no memory to allocate one!");
415 return -1;
416 }
417
Petr Machata2b46cfc2012-02-18 11:17:29 +0100418 //data.lte = lte;
Joe Damatof0bd98b2010-11-08 15:47:42 -0800419
Petr Machata2b46cfc2012-02-18 11:17:29 +0100420 void *addr;
421 {
422 struct library_symbol libsym;
Petr Machatae6523e62012-03-24 04:54:06 +0100423 library_symbol_init(&libsym, (target_address_t)rdbg->r_brk,
424 NULL, 0, LS_TOPLT_NONE);
Petr Machata2b46cfc2012-02-18 11:17:29 +0100425 addr = sym2addr(proc, &libsym);
426 library_symbol_destroy(&libsym);
427 }
Petr Machata9df15012012-02-20 12:49:46 +0100428 struct breakpoint *rdebug_bp = insert_breakpoint(proc, addr, NULL);
Petr Machata2b46cfc2012-02-18 11:17:29 +0100429 static struct bp_callbacks rdebug_callbacks = {
Petr Machata12affff2012-03-29 18:33:03 +0200430 .on_hit = rdebug_bp_on_hit,
Petr Machata2b46cfc2012-02-18 11:17:29 +0100431 };
432 rdebug_bp->cbs = &rdebug_callbacks;
Joe Damatof0bd98b2010-11-08 15:47:42 -0800433
Petr Machata2b46cfc2012-02-18 11:17:29 +0100434 crawl_linkmap(proc, rdbg);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800435
436 free(rdbg);
437 return 0;
438}
Petr Machata9a5420c2011-07-09 11:21:23 +0200439
440int
441task_kill (pid_t pid, int sig)
442{
443 // Taken from GDB
444 int ret;
445
446 errno = 0;
447 ret = syscall (__NR_tkill, pid, sig);
448 return ret;
449}