proc.c revision bfb26c745705a839f1ef5fc45e1b32135b9bc3e7
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, Loaded at 0x%x\n", lib_name, rlm.l_addr); 116 data->addr = rlm.l_addr; 117 data->lib_name = lib_name; 118 callback(data); 119 } 120 } 121 return; 122} 123 124static struct r_debug * 125load_debug_struct(Process *proc) { 126 struct r_debug *rdbg = NULL; 127 128 debug(DEBUG_FUNCTION, "load_debug_struct"); 129 130 rdbg = malloc(sizeof(*rdbg)); 131 if (!rdbg) { 132 return NULL; 133 } 134 135 if (umovebytes(proc, proc->debug, rdbg, sizeof(*rdbg)) != sizeof(*rdbg)) { 136 debug(2, "This process does not have a debug structure!\n"); 137 free(rdbg); 138 return NULL; 139 } 140 141 return rdbg; 142} 143 144static void 145linkmap_add_cb(void *data) { //const char *lib_name, ElfW(Addr) addr) { 146 int i = 0; 147 struct cb_data *lm_add = data; 148 struct ltelf lte; 149 struct opt_x_t *xptr; 150 151 debug(DEBUG_FUNCTION, "linkmap_add_cb"); 152 153 /* 154 XXX 155 iterate through library[i]'s to see if this lib is in the list. 156 if not, add it 157 */ 158 for(;i < library_num;i++) { 159 if (strcmp(library[i], lm_add->lib_name) == 0) { 160 /* found it, so its not new */ 161 return; 162 } 163 } 164 165 /* new library linked! */ 166 debug(2, "New libdl loaded library found: %s\n", lm_add->lib_name); 167 168 if (library_num < MAX_LIBRARIES) { 169 library[library_num++] = strdup(lm_add->lib_name); 170 memset(<e, 0, sizeof(struct ltelf)); 171 lte.base_addr = lm_add->addr; 172 do_init_elf(<e, library[library_num-1]); 173 /* add bps */ 174 for (xptr = opt_x; xptr; xptr = xptr->next) { 175 if (xptr->found) 176 continue; 177 178 GElf_Sym sym; 179 GElf_Addr addr; 180 181 if (in_load_libraries(xptr->name, <e, 1, &sym)) { 182 debug(2, "found symbol %s @ %#" PRIx64 183 ", adding it.", 184 xptr->name, sym.st_value); 185 addr = sym.st_value; 186 add_library_symbol(addr, xptr->name, &library_symbols, LS_TOPLT_NONE, 0); 187 xptr->found = 1; 188 insert_breakpoint(lm_add->proc, sym2addr(lm_add->proc, library_symbols), library_symbols); 189 } 190 } 191 do_close_elf(<e); 192 } 193} 194 195void 196arch_check_dbg(Process *proc) { 197 struct r_debug *dbg = NULL; 198 struct cb_data data; 199 200 debug(DEBUG_FUNCTION, "arch_check_dbg"); 201 202 if (!(dbg = load_debug_struct(proc))) { 203 debug(2, "Unable to load debug structure!"); 204 return; 205 } 206 207 if (dbg->r_state == RT_CONSISTENT) { 208 debug(2, "Linkmap is now consistent"); 209 if (proc->debug_state == RT_ADD) { 210 debug(2, "Adding DSO to linkmap"); 211 data.proc = proc; 212 crawl_linkmap(proc, dbg, linkmap_add_cb, &data); 213 } else if (proc->debug_state == RT_DELETE) { 214 debug(2, "Removing DSO from linkmap"); 215 } else { 216 debug(2, "Unexpected debug state!"); 217 } 218 } 219 220 proc->debug_state = dbg->r_state; 221 222 return; 223} 224 225static void 226hook_libdl_cb(void *data) { 227 struct cb_data *hook_data = data; 228 const char *lib_name = NULL; 229 ElfW(Addr) addr; 230 struct ltelf *lte = NULL; 231 232 debug(DEBUG_FUNCTION, "add_library_cb"); 233 234 if (!data) { 235 debug(2, "No callback data"); 236 return; 237 } 238 239 lib_name = hook_data->lib_name; 240 addr = hook_data->addr; 241 lte = hook_data->lte; 242 243 if (library_num < MAX_LIBRARIES) { 244 library[library_num++] = strdup(lib_name); 245 lte[library_num].base_addr = addr; 246 } 247 else { 248 fprintf (stderr, "MAX LIBS REACHED\n"); 249 exit(EXIT_FAILURE); 250 } 251} 252 253int 254linkmap_init(Process *proc, struct ltelf *lte) { 255 void *dbg_addr = NULL; 256 struct r_debug *rdbg = NULL; 257 struct cb_data data; 258 259 debug(DEBUG_FUNCTION, "linkmap_init()"); 260 261 if (find_dynamic_entry_addr(proc, (void *)lte->dyn_addr, DT_DEBUG, &dbg_addr) == -1) { 262 debug(2, "Couldn't find debug structure!"); 263 return -1; 264 } 265 266 proc->debug = dbg_addr; 267 268 if (!(rdbg = load_debug_struct(proc))) { 269 debug(2, "No debug structure or no memory to allocate one!"); 270 return -1; 271 } 272 273 data.lte = lte; 274 275 add_library_symbol(rdbg->r_brk, "", &library_symbols, LS_TOPLT_NONE, 0); 276 insert_breakpoint(proc, sym2addr(proc, library_symbols), library_symbols); 277 278 crawl_linkmap(proc, rdbg, hook_libdl_cb, &data); 279 280 free(rdbg); 281 return 0; 282} 283