blob: eca3548a7eeee7b5c5b58634224e5fdca067a0ea [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>
Zachary T Welchbfb26c72010-12-06 23:21:00 -08005#include <inttypes.h>
Joe Damato47cae1e2010-11-08 15:47:39 -08006#include <link.h>
Juan Cespedes1fe93d51998-03-13 00:29:21 +01007#include <stdio.h>
8#include <string.h>
9#include <signal.h>
Juan Cespedes273ea6d1998-03-14 23:02:40 +010010#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
Ian Wienand2d45b1a2006-02-20 22:48:07 +010017#define MAX_DELAY 100000 /* 100000 microseconds = 0.1 seconds */
Juan Cespedes1fe93d51998-03-13 00:29:21 +010018
19/*
Juan Cespedese0660df2009-05-21 18:14:39 +020020 * Returns a (malloc'd) file name corresponding to a running pid
Juan Cespedes1fe93d51998-03-13 00:29:21 +010021 */
Juan Cespedesf1350522008-12-16 18:19:58 +010022char *
23pid2name(pid_t pid) {
Juan Cespedes1fe93d51998-03-13 00:29:21 +010024 char proc_exe[1024];
25
26 if (!kill(pid, 0)) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010027 int delay = 0;
Juan Cespedes273ea6d1998-03-14 23:02:40 +010028
Juan Cespedes1fe93d51998-03-13 00:29:21 +010029 sprintf(proc_exe, "/proc/%d/exe", pid);
Juan Cespedes273ea6d1998-03-14 23:02:40 +010030
Ian Wienand2d45b1a2006-02-20 22:48:07 +010031 while (delay < MAX_DELAY) {
Juan Cespedes273ea6d1998-03-14 23:02:40 +010032 if (!access(proc_exe, F_OK)) {
33 return strdup(proc_exe);
34 }
35 delay += 1000; /* 1 milisecond */
36 }
Juan Cespedes1fe93d51998-03-13 00:29:21 +010037 }
Juan Cespedes273ea6d1998-03-14 23:02:40 +010038 return NULL;
Juan Cespedes1fe93d51998-03-13 00:29:21 +010039}
Joe Damato47cae1e2010-11-08 15:47:39 -080040
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}
Joe Damatof0bd98b2010-11-08 15:47:42 -080072
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) {
Zachary T Welch3ba522f2010-12-14 15:12:47 -0800115 debug(2, "Dispatching callback for: %s, "
116 "Loaded at 0x%" PRI_ELF_ADDR "\n",
117 lib_name, rlm.l_addr);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800118 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) {
Zachary T Welchba6aca22010-12-08 18:55:09 -0800148 size_t i = 0;
Joe Damatof0bd98b2010-11-08 15:47:42 -0800149 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)) {
Zachary T Welchbfb26c72010-12-06 23:21:00 -0800184 debug(2, "found symbol %s @ %#" PRIx64
185 ", adding it.",
186 xptr->name, sym.st_value);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800187 addr = sym.st_value;
188 add_library_symbol(addr, xptr->name, &library_symbols, LS_TOPLT_NONE, 0);
189 xptr->found = 1;
Petr Machata26627682011-07-08 18:15:32 +0200190 insert_breakpoint(lm_add->proc,
191 sym2addr(lm_add->proc,
192 library_symbols),
Petr Machatac7585b62011-07-08 22:58:12 +0200193 library_symbols, 1);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800194 }
195 }
196 do_close_elf(&lte);
197 }
198}
199
200void
201arch_check_dbg(Process *proc) {
202 struct r_debug *dbg = NULL;
203 struct cb_data data;
204
205 debug(DEBUG_FUNCTION, "arch_check_dbg");
206
207 if (!(dbg = load_debug_struct(proc))) {
208 debug(2, "Unable to load debug structure!");
209 return;
210 }
211
212 if (dbg->r_state == RT_CONSISTENT) {
213 debug(2, "Linkmap is now consistent");
214 if (proc->debug_state == RT_ADD) {
215 debug(2, "Adding DSO to linkmap");
216 data.proc = proc;
217 crawl_linkmap(proc, dbg, linkmap_add_cb, &data);
218 } else if (proc->debug_state == RT_DELETE) {
219 debug(2, "Removing DSO from linkmap");
220 } else {
221 debug(2, "Unexpected debug state!");
222 }
223 }
224
225 proc->debug_state = dbg->r_state;
226
227 return;
228}
229
230static void
231hook_libdl_cb(void *data) {
232 struct cb_data *hook_data = data;
233 const char *lib_name = NULL;
234 ElfW(Addr) addr;
235 struct ltelf *lte = NULL;
236
237 debug(DEBUG_FUNCTION, "add_library_cb");
238
239 if (!data) {
240 debug(2, "No callback data");
241 return;
242 }
243
244 lib_name = hook_data->lib_name;
245 addr = hook_data->addr;
246 lte = hook_data->lte;
247
248 if (library_num < MAX_LIBRARIES) {
Joe Damatof0bd98b2010-11-08 15:47:42 -0800249 lte[library_num].base_addr = addr;
Petr Machata08677d02011-05-19 16:09:17 +0200250 library[library_num++] = strdup(lib_name);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800251 }
252 else {
253 fprintf (stderr, "MAX LIBS REACHED\n");
254 exit(EXIT_FAILURE);
255 }
256}
257
258int
259linkmap_init(Process *proc, struct ltelf *lte) {
Zachary T Welch3ba522f2010-12-14 15:12:47 -0800260 void *dbg_addr = NULL, *dyn_addr = GELF_ADDR_CAST(lte->dyn_addr);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800261 struct r_debug *rdbg = NULL;
262 struct cb_data data;
263
264 debug(DEBUG_FUNCTION, "linkmap_init()");
265
Zachary T Welchba6aca22010-12-08 18:55:09 -0800266 if (find_dynamic_entry_addr(proc, dyn_addr, DT_DEBUG, &dbg_addr) == -1) {
Joe Damatof0bd98b2010-11-08 15:47:42 -0800267 debug(2, "Couldn't find debug structure!");
268 return -1;
269 }
270
271 proc->debug = dbg_addr;
272
273 if (!(rdbg = load_debug_struct(proc))) {
274 debug(2, "No debug structure or no memory to allocate one!");
275 return -1;
276 }
277
278 data.lte = lte;
279
280 add_library_symbol(rdbg->r_brk, "", &library_symbols, LS_TOPLT_NONE, 0);
Petr Machata26627682011-07-08 18:15:32 +0200281 insert_breakpoint(proc, sym2addr(proc, library_symbols),
Petr Machatac7585b62011-07-08 22:58:12 +0200282 library_symbols, 1);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800283
284 crawl_linkmap(proc, rdbg, hook_libdl_cb, &data);
285
286 free(rdbg);
287 return 0;
288}