proc.c revision f0bd98b3e6753d8609a3054a61f2df6f9cdac10a
1#include "config.h" 2#include "common.h" 3 4#include <sys/types.h> 5#include <link.h> 6#include <stdio.h> 7#include <string.h> 8#include <signal.h> 9#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 16#define MAX_DELAY 100000 /* 100000 microseconds = 0.1 seconds */ 17 18/* 19 * Returns a (malloc'd) file name corresponding to a running pid 20 */ 21char * 22pid2name(pid_t pid) { 23 char proc_exe[1024]; 24 25 if (!kill(pid, 0)) { 26 int delay = 0; 27 28 sprintf(proc_exe, "/proc/%d/exe", pid); 29 30 while (delay < MAX_DELAY) { 31 if (!access(proc_exe, F_OK)) { 32 return strdup(proc_exe); 33 } 34 delay += 1000; /* 1 milisecond */ 35 } 36 } 37 return NULL; 38} 39 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} 71 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(<e, 0, sizeof(struct ltelf)); 170 lte.base_addr = lm_add->addr; 171 do_init_elf(<e, 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, <e, 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(<e); 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} 280