blob: b55c5ef5c77622795a29291e43563df17fb442d4 [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{
138 *(char *)data = line[strlen(prefix)];
139 return pcb_stop;
140}
141
142char
143process_status(pid_t pid)
144{
145 char ret = '?';
146 FILE * file = open_status_file(pid);
147 if (file != NULL) {
148 each_line_starting(file, "State:\t", &process_status_cb, &ret);
149 fclose(file);
150 }
151 return ret;
152}
153
154static int
155all_digits(const char *str)
156{
157 while (isdigit(*str))
158 str++;
159 return !*str;
160}
161
162int
163process_tasks(pid_t pid, pid_t **ret_tasks, size_t *ret_n)
164{
165 PROC_PID_FILE(fn, "/proc/%d/task", pid);
166 DIR * d = opendir(fn);
167 if (d == NULL)
168 return -1;
169
170 /* XXX This is racy. We need to stop the tasks that we
171 discover this way and re-scan the directory to eventually
172 reach a full set of tasks. */
173 pid_t *tasks = NULL;
174 size_t n = 0;
175 size_t alloc = 0;
176
177 while (1) {
178 struct dirent entry;
179 struct dirent *result;
180 if (readdir_r(d, &entry, &result) != 0) {
181 free(tasks);
182 return -1;
183 }
184 if (result == NULL)
185 break;
186 if (result->d_type == DT_DIR && all_digits(result->d_name)) {
187 pid_t npid = atoi(result->d_name);
188 if (n >= alloc) {
189 alloc = alloc > 0 ? (2 * alloc) : 8;
190 pid_t *ntasks = realloc(tasks,
191 sizeof(*tasks) * alloc);
192 if (ntasks == NULL) {
193 free(tasks);
194 return -1;
195 }
196 tasks = ntasks;
197 }
198 if (n >= alloc)
199 abort();
200 tasks[n++] = npid;
201 }
202 }
203
204 closedir(d);
205
206 *ret_tasks = tasks;
207 *ret_n = n;
208 return 0;
209}
210
Joe Damato47cae1e2010-11-08 15:47:39 -0800211static int
212find_dynamic_entry_addr(Process *proc, void *pvAddr, int d_tag, void **addr) {
213 int i = 0, done = 0;
214 ElfW(Dyn) entry;
215
216 debug(DEBUG_FUNCTION, "find_dynamic_entry()");
217
218 if (addr == NULL || pvAddr == NULL || d_tag < 0 || d_tag > DT_NUM) {
219 return -1;
220 }
221
222 while ((!done) && (i < ELF_MAX_SEGMENTS) &&
223 (sizeof(entry) == umovebytes(proc, pvAddr, &entry, sizeof(entry))) &&
224 (entry.d_tag != DT_NULL)) {
225 if (entry.d_tag == d_tag) {
226 done = 1;
227 *addr = (void *)entry.d_un.d_val;
228 }
229 pvAddr += sizeof(entry);
230 i++;
231 }
232
233 if (done) {
234 debug(2, "found address: 0x%p in dtag %d\n", *addr, d_tag);
235 return 0;
236 }
237 else {
238 debug(2, "Couldn't address for dtag!\n");
239 return -1;
240 }
241}
Joe Damatof0bd98b2010-11-08 15:47:42 -0800242
243struct cb_data {
244 const char *lib_name;
245 struct ltelf *lte;
246 ElfW(Addr) addr;
247 Process *proc;
248};
249
250static void
251crawl_linkmap(Process *proc, struct r_debug *dbg, void (*callback)(void *), struct cb_data *data) {
252 struct link_map rlm;
253 char lib_name[BUFSIZ];
254 struct link_map *lm = NULL;
255
256 debug (DEBUG_FUNCTION, "crawl_linkmap()");
257
258 if (!dbg || !dbg->r_map) {
259 debug(2, "Debug structure or it's linkmap are NULL!");
260 return;
261 }
262
263 lm = dbg->r_map;
264
265 while (lm) {
266 if (umovebytes(proc, lm, &rlm, sizeof(rlm)) != sizeof(rlm)) {
267 debug(2, "Unable to read link map\n");
268 return;
269 }
270
271 lm = rlm.l_next;
272 if (rlm.l_name == NULL) {
273 debug(2, "Invalid library name referenced in dynamic linker map\n");
274 return;
275 }
276
277 umovebytes(proc, rlm.l_name, lib_name, sizeof(lib_name));
278
279 if (lib_name[0] == '\0') {
280 debug(2, "Library name is an empty string");
281 continue;
282 }
283
284 if (callback) {
Zachary T Welch3ba522f2010-12-14 15:12:47 -0800285 debug(2, "Dispatching callback for: %s, "
286 "Loaded at 0x%" PRI_ELF_ADDR "\n",
287 lib_name, rlm.l_addr);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800288 data->addr = rlm.l_addr;
289 data->lib_name = lib_name;
290 callback(data);
291 }
292 }
293 return;
294}
295
296static struct r_debug *
297load_debug_struct(Process *proc) {
298 struct r_debug *rdbg = NULL;
299
300 debug(DEBUG_FUNCTION, "load_debug_struct");
301
302 rdbg = malloc(sizeof(*rdbg));
303 if (!rdbg) {
304 return NULL;
305 }
306
307 if (umovebytes(proc, proc->debug, rdbg, sizeof(*rdbg)) != sizeof(*rdbg)) {
308 debug(2, "This process does not have a debug structure!\n");
309 free(rdbg);
310 return NULL;
311 }
312
313 return rdbg;
314}
315
316static void
317linkmap_add_cb(void *data) { //const char *lib_name, ElfW(Addr) addr) {
Zachary T Welchba6aca22010-12-08 18:55:09 -0800318 size_t i = 0;
Joe Damatof0bd98b2010-11-08 15:47:42 -0800319 struct cb_data *lm_add = data;
320 struct ltelf lte;
321 struct opt_x_t *xptr;
322
323 debug(DEBUG_FUNCTION, "linkmap_add_cb");
324
325 /*
326 XXX
327 iterate through library[i]'s to see if this lib is in the list.
328 if not, add it
329 */
330 for(;i < library_num;i++) {
331 if (strcmp(library[i], lm_add->lib_name) == 0) {
332 /* found it, so its not new */
333 return;
334 }
335 }
336
337 /* new library linked! */
338 debug(2, "New libdl loaded library found: %s\n", lm_add->lib_name);
339
340 if (library_num < MAX_LIBRARIES) {
341 library[library_num++] = strdup(lm_add->lib_name);
342 memset(&lte, 0, sizeof(struct ltelf));
343 lte.base_addr = lm_add->addr;
344 do_init_elf(&lte, library[library_num-1]);
345 /* add bps */
346 for (xptr = opt_x; xptr; xptr = xptr->next) {
347 if (xptr->found)
348 continue;
349
350 GElf_Sym sym;
351 GElf_Addr addr;
352
353 if (in_load_libraries(xptr->name, &lte, 1, &sym)) {
Zachary T Welchbfb26c72010-12-06 23:21:00 -0800354 debug(2, "found symbol %s @ %#" PRIx64
355 ", adding it.",
356 xptr->name, sym.st_value);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800357 addr = sym.st_value;
358 add_library_symbol(addr, xptr->name, &library_symbols, LS_TOPLT_NONE, 0);
359 xptr->found = 1;
Petr Machata26627682011-07-08 18:15:32 +0200360 insert_breakpoint(lm_add->proc,
361 sym2addr(lm_add->proc,
362 library_symbols),
Petr Machatac7585b62011-07-08 22:58:12 +0200363 library_symbols, 1);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800364 }
365 }
366 do_close_elf(&lte);
367 }
368}
369
370void
371arch_check_dbg(Process *proc) {
372 struct r_debug *dbg = NULL;
373 struct cb_data data;
374
375 debug(DEBUG_FUNCTION, "arch_check_dbg");
376
377 if (!(dbg = load_debug_struct(proc))) {
378 debug(2, "Unable to load debug structure!");
379 return;
380 }
381
382 if (dbg->r_state == RT_CONSISTENT) {
383 debug(2, "Linkmap is now consistent");
384 if (proc->debug_state == RT_ADD) {
385 debug(2, "Adding DSO to linkmap");
386 data.proc = proc;
387 crawl_linkmap(proc, dbg, linkmap_add_cb, &data);
388 } else if (proc->debug_state == RT_DELETE) {
389 debug(2, "Removing DSO from linkmap");
390 } else {
391 debug(2, "Unexpected debug state!");
392 }
393 }
394
395 proc->debug_state = dbg->r_state;
396
397 return;
398}
399
400static void
401hook_libdl_cb(void *data) {
402 struct cb_data *hook_data = data;
403 const char *lib_name = NULL;
404 ElfW(Addr) addr;
405 struct ltelf *lte = NULL;
406
407 debug(DEBUG_FUNCTION, "add_library_cb");
408
409 if (!data) {
410 debug(2, "No callback data");
411 return;
412 }
413
414 lib_name = hook_data->lib_name;
415 addr = hook_data->addr;
416 lte = hook_data->lte;
417
418 if (library_num < MAX_LIBRARIES) {
Joe Damatof0bd98b2010-11-08 15:47:42 -0800419 lte[library_num].base_addr = addr;
Petr Machata08677d02011-05-19 16:09:17 +0200420 library[library_num++] = strdup(lib_name);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800421 }
422 else {
423 fprintf (stderr, "MAX LIBS REACHED\n");
424 exit(EXIT_FAILURE);
425 }
426}
427
428int
429linkmap_init(Process *proc, struct ltelf *lte) {
Zachary T Welch3ba522f2010-12-14 15:12:47 -0800430 void *dbg_addr = NULL, *dyn_addr = GELF_ADDR_CAST(lte->dyn_addr);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800431 struct r_debug *rdbg = NULL;
432 struct cb_data data;
433
434 debug(DEBUG_FUNCTION, "linkmap_init()");
435
Zachary T Welchba6aca22010-12-08 18:55:09 -0800436 if (find_dynamic_entry_addr(proc, dyn_addr, DT_DEBUG, &dbg_addr) == -1) {
Joe Damatof0bd98b2010-11-08 15:47:42 -0800437 debug(2, "Couldn't find debug structure!");
438 return -1;
439 }
440
441 proc->debug = dbg_addr;
442
443 if (!(rdbg = load_debug_struct(proc))) {
444 debug(2, "No debug structure or no memory to allocate one!");
445 return -1;
446 }
447
448 data.lte = lte;
449
450 add_library_symbol(rdbg->r_brk, "", &library_symbols, LS_TOPLT_NONE, 0);
Petr Machata26627682011-07-08 18:15:32 +0200451 insert_breakpoint(proc, sym2addr(proc, library_symbols),
Petr Machatac7585b62011-07-08 22:58:12 +0200452 library_symbols, 1);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800453
454 crawl_linkmap(proc, rdbg, hook_libdl_cb, &data);
455
456 free(rdbg);
457 return 0;
458}
Petr Machata9a5420c2011-07-09 11:21:23 +0200459
460int
461task_kill (pid_t pid, int sig)
462{
463 // Taken from GDB
464 int ret;
465
466 errno = 0;
467 ret = syscall (__NR_tkill, pid, sig);
468 return ret;
469}