proc.c revision 9a5420c82a2fd81681572a2e3859ea1671c3bded
1#include "config.h"
2#include "common.h"
3
4#include <sys/types.h>
5#include <sys/stat.h>
6#include <fcntl.h>
7#include <inttypes.h>
8#include <link.h>
9#include <stdio.h>
10#include <string.h>
11#include <signal.h>
12#include <unistd.h>
13#include <dirent.h>
14#include <ctype.h>
15#include <errno.h>
16#include <sys/syscall.h>
17
18
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
24#define	MAX_DELAY	100000	/* 100000 microseconds = 0.1 seconds */
25
26#define PROC_PID_FILE(VAR, FORMAT, PID)		\
27	char VAR[strlen(FORMAT) + 6];		\
28	sprintf(VAR, FORMAT, PID)
29
30/*
31 * Returns a (malloc'd) file name corresponding to a running pid
32 */
33char *
34pid2name(pid_t pid) {
35	if (!kill(pid, 0)) {
36		int delay = 0;
37
38		PROC_PID_FILE(proc_exe, "/proc/%d/exe", pid);
39
40		while (delay < MAX_DELAY) {
41			if (!access(proc_exe, F_OK)) {
42				return strdup(proc_exe);
43			}
44			delay += 1000;	/* 1 milisecond */
45		}
46	}
47	return NULL;
48}
49
50static 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
211static 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}
242
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) {
285			debug(2, "Dispatching callback for: %s, "
286					"Loaded at 0x%" PRI_ELF_ADDR "\n",
287					lib_name, rlm.l_addr);
288			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) {
318	size_t i = 0;
319	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)) {
354				debug(2, "found symbol %s @ %#" PRIx64
355						", adding it.",
356						xptr->name, sym.st_value);
357				addr = sym.st_value;
358				add_library_symbol(addr, xptr->name, &library_symbols, LS_TOPLT_NONE, 0);
359				xptr->found = 1;
360				insert_breakpoint(lm_add->proc,
361						  sym2addr(lm_add->proc,
362							   library_symbols),
363						  library_symbols, 1);
364			}
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) {
419		lte[library_num].base_addr = addr;
420		library[library_num++] = strdup(lib_name);
421	}
422	else {
423		fprintf (stderr, "MAX LIBS REACHED\n");
424		exit(EXIT_FAILURE);
425	}
426}
427
428int
429linkmap_init(Process *proc, struct ltelf *lte) {
430	void *dbg_addr = NULL, *dyn_addr = GELF_ADDR_CAST(lte->dyn_addr);
431	struct r_debug *rdbg = NULL;
432	struct cb_data data;
433
434	debug(DEBUG_FUNCTION, "linkmap_init()");
435
436	if (find_dynamic_entry_addr(proc, dyn_addr, DT_DEBUG, &dbg_addr) == -1) {
437		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);
451	insert_breakpoint(proc, sym2addr(proc, library_symbols),
452			  library_symbols, 1);
453
454	crawl_linkmap(proc, rdbg, hook_libdl_cb, &data);
455
456	free(rdbg);
457	return 0;
458}
459
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}
470