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(<e, 0, sizeof(struct ltelf)); 173 lte.base_addr = lm_add->addr; 174 do_init_elf(<e, 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, <e, 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(<e); 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