proc.c revision 9294d82f67e20f5f2b61f317ad04f5cb717c7d27
1#define _GNU_SOURCE /* For getline.  */
2#include "config.h"
3#include "common.h"
4
5#include <sys/types.h>
6#include <sys/stat.h>
7#include <fcntl.h>
8#include <inttypes.h>
9#include <link.h>
10#include <stdio.h>
11#include <string.h>
12#include <signal.h>
13#include <unistd.h>
14#include <dirent.h>
15#include <ctype.h>
16#include <errno.h>
17#include <sys/syscall.h>
18#include <error.h>
19
20#include "breakpoint.h"
21
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
27#define	MAX_DELAY	100000	/* 100000 microseconds = 0.1 seconds */
28
29#define PROC_PID_FILE(VAR, FORMAT, PID)		\
30	char VAR[strlen(FORMAT) + 6];		\
31	sprintf(VAR, FORMAT, PID)
32
33/*
34 * Returns a (malloc'd) file name corresponding to a running pid
35 */
36char *
37pid2name(pid_t pid) {
38	if (!kill(pid, 0)) {
39		int delay = 0;
40
41		PROC_PID_FILE(proc_exe, "/proc/%d/exe", pid);
42
43		while (delay < MAX_DELAY) {
44			if (!access(proc_exe, F_OK)) {
45				return strdup(proc_exe);
46			}
47			delay += 1000;	/* 1 milisecond */
48		}
49	}
50	return NULL;
51}
52
53static 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{
106	pid_t tgid = 0;
107	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{
141	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);
152	case 'T':
153		/* 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		}
165	case 'D':
166	case 'S': RETURN(ps_sleeping);
167	}
168
169	RETURN(ps_other);
170#undef RETURN
171}
172
173enum process_status
174process_status(pid_t pid)
175{
176	enum process_status ret = ps_invalid;
177	FILE * file = open_status_file(pid);
178	if (file != NULL) {
179		each_line_starting(file, "State:\t", &process_status_cb, &ret);
180		fclose(file);
181		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
188	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
207	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
245static 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}
276
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) {
319			debug(2, "Dispatching callback for: %s, "
320					"Loaded at 0x%" PRI_ELF_ADDR "\n",
321					lib_name, rlm.l_addr);
322			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) {
352	size_t i = 0;
353	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)) {
388				debug(2, "found symbol %s @ %#" PRIx64
389						", adding it.",
390						xptr->name, sym.st_value);
391				addr = sym.st_value;
392				add_library_symbol(addr, xptr->name, &library_symbols, LS_TOPLT_NONE, 0);
393				xptr->found = 1;
394				insert_breakpoint(lm_add->proc,
395						  sym2addr(lm_add->proc,
396							   library_symbols),
397						  library_symbols, 1);
398			}
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) {
453		lte[library_num].base_addr = addr;
454		library[library_num++] = strdup(lib_name);
455	}
456	else {
457		fprintf (stderr, "MAX LIBS REACHED\n");
458		exit(EXIT_FAILURE);
459	}
460}
461
462int
463linkmap_init(Process *proc, struct ltelf *lte) {
464	void *dbg_addr = NULL, *dyn_addr = GELF_ADDR_CAST(lte->dyn_addr);
465	struct r_debug *rdbg = NULL;
466	struct cb_data data;
467
468	debug(DEBUG_FUNCTION, "linkmap_init()");
469
470	if (find_dynamic_entry_addr(proc, dyn_addr, DT_DEBUG, &dbg_addr) == -1) {
471		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);
485	insert_breakpoint(proc, sym2addr(proc, library_symbols),
486			  library_symbols, 1);
487
488	crawl_linkmap(proc, rdbg, hook_libdl_cb, &data);
489
490	free(rdbg);
491	return 0;
492}
493
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}
504