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