blob: 4592924303406685d904a90e3e84b39ce4fa4482 [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 int i = 0, done = 0;
253 ElfW(Dyn) entry;
254
255 debug(DEBUG_FUNCTION, "find_dynamic_entry()");
256
257 if (addr == NULL || pvAddr == NULL || d_tag < 0 || d_tag > DT_NUM) {
258 return -1;
259 }
260
261 while ((!done) && (i < ELF_MAX_SEGMENTS) &&
262 (sizeof(entry) == umovebytes(proc, pvAddr, &entry, sizeof(entry))) &&
263 (entry.d_tag != DT_NULL)) {
Petr Machata2b46cfc2012-02-18 11:17:29 +0100264 fprintf(stderr, " entry %ld %#lx\n", entry.d_tag, entry.d_un.d_val);
Joe Damato47cae1e2010-11-08 15:47:39 -0800265 if (entry.d_tag == d_tag) {
Petr Machata2b46cfc2012-02-18 11:17:29 +0100266 fprintf(stderr, " hit\n");
Joe Damato47cae1e2010-11-08 15:47:39 -0800267 done = 1;
268 *addr = (void *)entry.d_un.d_val;
269 }
270 pvAddr += sizeof(entry);
271 i++;
272 }
273
274 if (done) {
275 debug(2, "found address: 0x%p in dtag %d\n", *addr, d_tag);
276 return 0;
277 }
278 else {
279 debug(2, "Couldn't address for dtag!\n");
280 return -1;
281 }
282}
Joe Damatof0bd98b2010-11-08 15:47:42 -0800283
Petr Machata2b46cfc2012-02-18 11:17:29 +0100284enum callback_status
285find_library_addr(struct Process *proc, struct library *lib, void *data)
286{
287 target_address_t addr = (target_address_t)*(GElf_Addr *)data;
288 return lib->base == addr ? CBS_STOP : CBS_CONT;
289}
Joe Damatof0bd98b2010-11-08 15:47:42 -0800290
291static void
Petr Machata2b46cfc2012-02-18 11:17:29 +0100292crawl_linkmap(Process *proc, struct r_debug *dbg)
293{
Joe Damatof0bd98b2010-11-08 15:47:42 -0800294 struct link_map rlm;
295 char lib_name[BUFSIZ];
296 struct link_map *lm = NULL;
297
298 debug (DEBUG_FUNCTION, "crawl_linkmap()");
299
300 if (!dbg || !dbg->r_map) {
301 debug(2, "Debug structure or it's linkmap are NULL!");
302 return;
303 }
304
305 lm = dbg->r_map;
306
307 while (lm) {
308 if (umovebytes(proc, lm, &rlm, sizeof(rlm)) != sizeof(rlm)) {
309 debug(2, "Unable to read link map\n");
310 return;
311 }
312
313 lm = rlm.l_next;
314 if (rlm.l_name == NULL) {
315 debug(2, "Invalid library name referenced in dynamic linker map\n");
316 return;
317 }
318
319 umovebytes(proc, rlm.l_name, lib_name, sizeof(lib_name));
320
Petr Machata2b46cfc2012-02-18 11:17:29 +0100321 debug(2, "Dispatching callback for: %s, "
322 "Loaded at 0x%" PRI_ELF_ADDR "\n",
323 lib_name, rlm.l_addr);
324 fprintf(stderr, "DSO addr=%#lx, name='%s'\n", rlm.l_addr, lib_name);
325
326 /* Do we have that library already? */
327 struct library *lib
328 = proc_each_library(proc, NULL, find_library_addr,
329 &rlm.l_addr);
330 if (lib != NULL)
331 continue;
332
333 if (*lib_name == '\0') {
334 /* VDSO. No associated file, XXX but we might
335 * load it from the address space of the
336 * process. */
Joe Damatof0bd98b2010-11-08 15:47:42 -0800337 continue;
338 }
339
Petr Machata2b46cfc2012-02-18 11:17:29 +0100340 lib = ltelf_read_library(lib_name, rlm.l_addr);
341 if (lib == NULL) {
342 error(0, errno, "Couldn't load ELF object %s\n",
343 lib_name);
344 continue;
Joe Damatof0bd98b2010-11-08 15:47:42 -0800345 }
Petr Machata2b46cfc2012-02-18 11:17:29 +0100346
347 proc_add_library(proc, lib);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800348 }
349 return;
350}
351
352static struct r_debug *
353load_debug_struct(Process *proc) {
354 struct r_debug *rdbg = NULL;
355
356 debug(DEBUG_FUNCTION, "load_debug_struct");
357
358 rdbg = malloc(sizeof(*rdbg));
359 if (!rdbg) {
360 return NULL;
361 }
362
363 if (umovebytes(proc, proc->debug, rdbg, sizeof(*rdbg)) != sizeof(*rdbg)) {
364 debug(2, "This process does not have a debug structure!\n");
365 free(rdbg);
366 return NULL;
367 }
368
369 return rdbg;
370}
371
372static void
Petr Machata2b46cfc2012-02-18 11:17:29 +0100373rdebug_callback_hit(struct breakpoint *bp, struct Process *proc)
374{
375 fprintf(stderr, "======= HIT\n");
Joe Damatof0bd98b2010-11-08 15:47:42 -0800376 struct r_debug *dbg = NULL;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100377 //struct cb_data data;
Joe Damatof0bd98b2010-11-08 15:47:42 -0800378
379 debug(DEBUG_FUNCTION, "arch_check_dbg");
380
381 if (!(dbg = load_debug_struct(proc))) {
382 debug(2, "Unable to load debug structure!");
383 return;
384 }
385
386 if (dbg->r_state == RT_CONSISTENT) {
387 debug(2, "Linkmap is now consistent");
388 if (proc->debug_state == RT_ADD) {
389 debug(2, "Adding DSO to linkmap");
Petr Machata2b46cfc2012-02-18 11:17:29 +0100390 //data.proc = proc;
391 crawl_linkmap(proc, dbg);
392 //&data);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800393 } else if (proc->debug_state == RT_DELETE) {
394 debug(2, "Removing DSO from linkmap");
395 } else {
396 debug(2, "Unexpected debug state!");
397 }
398 }
399
400 proc->debug_state = dbg->r_state;
Joe Damatof0bd98b2010-11-08 15:47:42 -0800401 return;
402}
403
Petr Machata2b46cfc2012-02-18 11:17:29 +0100404void *dyn_addr;
Joe Damatof0bd98b2010-11-08 15:47:42 -0800405int
Petr Machata2b46cfc2012-02-18 11:17:29 +0100406linkmap_init(struct Process *proc)
407{
408 void *dbg_addr = NULL;
Joe Damatof0bd98b2010-11-08 15:47:42 -0800409 struct r_debug *rdbg = NULL;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100410 //struct cb_data data;
Joe Damatof0bd98b2010-11-08 15:47:42 -0800411
412 debug(DEBUG_FUNCTION, "linkmap_init()");
Petr Machata2b46cfc2012-02-18 11:17:29 +0100413 fprintf(stderr, "linkmap_init dyn_addr=%p\n", dyn_addr);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800414
Zachary T Welchba6aca22010-12-08 18:55:09 -0800415 if (find_dynamic_entry_addr(proc, dyn_addr, DT_DEBUG, &dbg_addr) == -1) {
Joe Damatof0bd98b2010-11-08 15:47:42 -0800416 debug(2, "Couldn't find debug structure!");
417 return -1;
418 }
419
420 proc->debug = dbg_addr;
421
422 if (!(rdbg = load_debug_struct(proc))) {
423 debug(2, "No debug structure or no memory to allocate one!");
424 return -1;
425 }
426
Petr Machata2b46cfc2012-02-18 11:17:29 +0100427 //data.lte = lte;
Joe Damatof0bd98b2010-11-08 15:47:42 -0800428
Petr Machata2b46cfc2012-02-18 11:17:29 +0100429 void *addr;
430 {
431 struct library_symbol libsym;
432 library_symbol_init(&libsym, rdbg->r_brk, NULL, 0,
433 LS_TOPLT_NONE, 0);
434 addr = sym2addr(proc, &libsym);
435 library_symbol_destroy(&libsym);
436 }
437 struct breakpoint *rdebug_bp = insert_breakpoint(proc, addr, NULL, 1);
438 static struct bp_callbacks rdebug_callbacks = {
439 .on_hit = rdebug_callback_hit,
440 };
441 rdebug_bp->cbs = &rdebug_callbacks;
Joe Damatof0bd98b2010-11-08 15:47:42 -0800442
Petr Machata2b46cfc2012-02-18 11:17:29 +0100443 crawl_linkmap(proc, rdbg);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800444
445 free(rdbg);
446 return 0;
447}
Petr Machata9a5420c2011-07-09 11:21:23 +0200448
449int
450task_kill (pid_t pid, int sig)
451{
452 // Taken from GDB
453 int ret;
454
455 errno = 0;
456 ret = syscall (__NR_tkill, pid, sig);
457 return ret;
458}