proc.c revision 08677d0557284d36d3c898b1d876e65411069912
1#include "config.h"
2#include "common.h"
3
4#include <sys/types.h>
5#include <inttypes.h>
6#include <link.h>
7#include <stdio.h>
8#include <string.h>
9#include <signal.h>
10#include <unistd.h>
11
12/* /proc/pid doesn't exist just after the fork, and sometimes `ltrace'
13 * couldn't open it to find the executable.  So it may be necessary to
14 * have a bit delay
15 */
16
17#define	MAX_DELAY	100000	/* 100000 microseconds = 0.1 seconds */
18
19/*
20 * Returns a (malloc'd) file name corresponding to a running pid
21 */
22char *
23pid2name(pid_t pid) {
24	char proc_exe[1024];
25
26	if (!kill(pid, 0)) {
27		int delay = 0;
28
29		sprintf(proc_exe, "/proc/%d/exe", pid);
30
31		while (delay < MAX_DELAY) {
32			if (!access(proc_exe, F_OK)) {
33				return strdup(proc_exe);
34			}
35			delay += 1000;	/* 1 milisecond */
36		}
37	}
38	return NULL;
39}
40
41static int
42find_dynamic_entry_addr(Process *proc, void *pvAddr, int d_tag, void **addr) {
43	int i = 0, done = 0;
44	ElfW(Dyn) entry;
45
46	debug(DEBUG_FUNCTION, "find_dynamic_entry()");
47
48	if (addr ==	NULL || pvAddr == NULL || d_tag < 0 || d_tag > DT_NUM) {
49		return -1;
50	}
51
52	while ((!done) && (i < ELF_MAX_SEGMENTS) &&
53		(sizeof(entry) == umovebytes(proc, pvAddr, &entry, sizeof(entry))) &&
54		(entry.d_tag != DT_NULL)) {
55		if (entry.d_tag == d_tag) {
56			done = 1;
57			*addr = (void *)entry.d_un.d_val;
58		}
59		pvAddr += sizeof(entry);
60		i++;
61	}
62
63	if (done) {
64		debug(2, "found address: 0x%p in dtag %d\n", *addr, d_tag);
65		return 0;
66	}
67	else {
68		debug(2, "Couldn't address for dtag!\n");
69		return -1;
70	}
71}
72
73struct cb_data {
74	const char *lib_name;
75	struct ltelf *lte;
76	ElfW(Addr) addr;
77	Process *proc;
78};
79
80static void
81crawl_linkmap(Process *proc, struct r_debug *dbg, void (*callback)(void *), struct cb_data *data) {
82	struct link_map rlm;
83	char lib_name[BUFSIZ];
84	struct link_map *lm = NULL;
85
86	debug (DEBUG_FUNCTION, "crawl_linkmap()");
87
88	if (!dbg || !dbg->r_map) {
89		debug(2, "Debug structure or it's linkmap are NULL!");
90		return;
91	}
92
93	lm = dbg->r_map;
94
95	while (lm) {
96		if (umovebytes(proc, lm, &rlm, sizeof(rlm)) != sizeof(rlm)) {
97			debug(2, "Unable to read link map\n");
98			return;
99		}
100
101		lm = rlm.l_next;
102		if (rlm.l_name == NULL) {
103			debug(2, "Invalid library name referenced in dynamic linker map\n");
104			return;
105		}
106
107		umovebytes(proc, rlm.l_name, lib_name, sizeof(lib_name));
108
109		if (lib_name[0] == '\0') {
110			debug(2, "Library name is an empty string");
111			continue;
112		}
113
114		if (callback) {
115			debug(2, "Dispatching callback for: %s, "
116					"Loaded at 0x%" PRI_ELF_ADDR "\n",
117					lib_name, rlm.l_addr);
118			data->addr = rlm.l_addr;
119			data->lib_name = lib_name;
120			callback(data);
121		}
122	}
123	return;
124}
125
126static struct r_debug *
127load_debug_struct(Process *proc) {
128	struct r_debug *rdbg = NULL;
129
130	debug(DEBUG_FUNCTION, "load_debug_struct");
131
132	rdbg = malloc(sizeof(*rdbg));
133	if (!rdbg) {
134		return NULL;
135	}
136
137	if (umovebytes(proc, proc->debug, rdbg, sizeof(*rdbg)) != sizeof(*rdbg)) {
138		debug(2, "This process does not have a debug structure!\n");
139		free(rdbg);
140		return NULL;
141	}
142
143	return rdbg;
144}
145
146static void
147linkmap_add_cb(void *data) { //const char *lib_name, ElfW(Addr) addr) {
148	size_t i = 0;
149	struct cb_data *lm_add = data;
150	struct ltelf lte;
151	struct opt_x_t *xptr;
152
153	debug(DEBUG_FUNCTION, "linkmap_add_cb");
154
155	/*
156		XXX
157		iterate through library[i]'s to see if this lib is in the list.
158		if not, add it
159	 */
160	for(;i < library_num;i++) {
161		if (strcmp(library[i], lm_add->lib_name) == 0) {
162			/* found it, so its not new */
163			return;
164		}
165	}
166
167	/* new library linked! */
168	debug(2, "New libdl loaded library found: %s\n", lm_add->lib_name);
169
170	if (library_num < MAX_LIBRARIES) {
171		library[library_num++] = strdup(lm_add->lib_name);
172		memset(&lte, 0, sizeof(struct ltelf));
173		lte.base_addr = lm_add->addr;
174		do_init_elf(&lte, library[library_num-1]);
175		/* add bps */
176		for (xptr = opt_x; xptr; xptr = xptr->next) {
177			if (xptr->found)
178				continue;
179
180			GElf_Sym sym;
181			GElf_Addr addr;
182
183			if (in_load_libraries(xptr->name, &lte, 1, &sym)) {
184				debug(2, "found symbol %s @ %#" PRIx64
185						", adding it.",
186						xptr->name, sym.st_value);
187				addr = sym.st_value;
188				add_library_symbol(addr, xptr->name, &library_symbols, LS_TOPLT_NONE, 0);
189				xptr->found = 1;
190				insert_breakpoint(lm_add->proc, sym2addr(lm_add->proc, library_symbols), library_symbols);
191			}
192		}
193		do_close_elf(&lte);
194	}
195}
196
197void
198arch_check_dbg(Process *proc) {
199	struct r_debug *dbg = NULL;
200	struct cb_data data;
201
202	debug(DEBUG_FUNCTION, "arch_check_dbg");
203
204	if (!(dbg = load_debug_struct(proc))) {
205		debug(2, "Unable to load debug structure!");
206		return;
207	}
208
209	if (dbg->r_state == RT_CONSISTENT) {
210		debug(2, "Linkmap is now consistent");
211		if (proc->debug_state == RT_ADD) {
212			debug(2, "Adding DSO to linkmap");
213			data.proc = proc;
214			crawl_linkmap(proc, dbg, linkmap_add_cb, &data);
215		} else if (proc->debug_state == RT_DELETE) {
216			debug(2, "Removing DSO from linkmap");
217		} else {
218			debug(2, "Unexpected debug state!");
219		}
220	}
221
222	proc->debug_state = dbg->r_state;
223
224	return;
225}
226
227static void
228hook_libdl_cb(void *data) {
229	struct cb_data *hook_data = data;
230	const char *lib_name = NULL;
231	ElfW(Addr) addr;
232	struct ltelf *lte = NULL;
233
234	debug(DEBUG_FUNCTION, "add_library_cb");
235
236	if (!data) {
237		debug(2, "No callback data");
238		return;
239	}
240
241	lib_name = hook_data->lib_name;
242	addr = hook_data->addr;
243	lte = hook_data->lte;
244
245	if (library_num < MAX_LIBRARIES) {
246		lte[library_num].base_addr = addr;
247		library[library_num++] = strdup(lib_name);
248	}
249	else {
250		fprintf (stderr, "MAX LIBS REACHED\n");
251		exit(EXIT_FAILURE);
252	}
253}
254
255int
256linkmap_init(Process *proc, struct ltelf *lte) {
257	void *dbg_addr = NULL, *dyn_addr = GELF_ADDR_CAST(lte->dyn_addr);
258	struct r_debug *rdbg = NULL;
259	struct cb_data data;
260
261	debug(DEBUG_FUNCTION, "linkmap_init()");
262
263	if (find_dynamic_entry_addr(proc, dyn_addr, DT_DEBUG, &dbg_addr) == -1) {
264		debug(2, "Couldn't find debug structure!");
265		return -1;
266	}
267
268	proc->debug = dbg_addr;
269
270	if (!(rdbg = load_debug_struct(proc))) {
271		debug(2, "No debug structure or no memory to allocate one!");
272		return -1;
273	}
274
275	data.lte = lte;
276
277	add_library_symbol(rdbg->r_brk, "", &library_symbols, LS_TOPLT_NONE, 0);
278	insert_breakpoint(proc, sym2addr(proc, library_symbols), library_symbols);
279
280	crawl_linkmap(proc, rdbg, hook_libdl_cb, &data);
281
282	free(rdbg);
283	return 0;
284}
285