proc.c revision 9a5420c82a2fd81681572a2e3859ea1671c3bded
1#include "config.h" 2#include "common.h" 3 4#include <sys/types.h> 5#include <sys/stat.h> 6#include <fcntl.h> 7#include <inttypes.h> 8#include <link.h> 9#include <stdio.h> 10#include <string.h> 11#include <signal.h> 12#include <unistd.h> 13#include <dirent.h> 14#include <ctype.h> 15#include <errno.h> 16#include <sys/syscall.h> 17 18 19/* /proc/pid doesn't exist just after the fork, and sometimes `ltrace' 20 * couldn't open it to find the executable. So it may be necessary to 21 * have a bit delay 22 */ 23 24#define MAX_DELAY 100000 /* 100000 microseconds = 0.1 seconds */ 25 26#define PROC_PID_FILE(VAR, FORMAT, PID) \ 27 char VAR[strlen(FORMAT) + 6]; \ 28 sprintf(VAR, FORMAT, PID) 29 30/* 31 * Returns a (malloc'd) file name corresponding to a running pid 32 */ 33char * 34pid2name(pid_t pid) { 35 if (!kill(pid, 0)) { 36 int delay = 0; 37 38 PROC_PID_FILE(proc_exe, "/proc/%d/exe", pid); 39 40 while (delay < MAX_DELAY) { 41 if (!access(proc_exe, F_OK)) { 42 return strdup(proc_exe); 43 } 44 delay += 1000; /* 1 milisecond */ 45 } 46 } 47 return NULL; 48} 49 50static FILE * 51open_status_file(pid_t pid) 52{ 53 PROC_PID_FILE(fn, "/proc/%d/status", pid); 54 /* Don't complain if we fail. This would typically happen 55 when the process is about to terminate, and these files are 56 not available anymore. This function is called from the 57 event loop, and we don't want to clutter the output just 58 because the process terminates. */ 59 return fopen(fn, "r"); 60} 61 62static char * 63find_line_starting(FILE * file, const char * prefix, size_t len) 64{ 65 char * line = NULL; 66 size_t line_len = 0; 67 while (!feof(file)) { 68 if (getline(&line, &line_len, file) < 0) 69 return NULL; 70 if (strncmp(line, prefix, len) == 0) 71 return line; 72 } 73 return NULL; 74} 75 76static void 77each_line_starting(FILE * file, const char *prefix, 78 enum pcb_status (*cb)(const char * line, const char * prefix, 79 void * data), 80 void * data) 81{ 82 size_t len = strlen(prefix); 83 char * line; 84 while ((line = find_line_starting(file, prefix, len)) != NULL) { 85 enum pcb_status st = (*cb)(line, prefix, data); 86 free (line); 87 if (st == pcb_stop) 88 return; 89 } 90} 91 92static enum pcb_status 93process_leader_cb(const char * line, const char * prefix, void * data) 94{ 95 pid_t * pidp = data; 96 *pidp = atoi(line + strlen(prefix)); 97 return pcb_stop; 98} 99 100pid_t 101process_leader(pid_t pid) 102{ 103 pid_t tgid = pid; 104 FILE * file = open_status_file(pid); 105 if (file != NULL) { 106 each_line_starting(file, "Tgid:\t", &process_leader_cb, &tgid); 107 fclose(file); 108 } 109 110 return tgid; 111} 112 113static enum pcb_status 114process_stopped_cb(const char * line, const char * prefix, void * data) 115{ 116 char c = line[strlen(prefix)]; 117 // t:tracing stop, T:job control stop 118 *(int *)data = (c == 't' || c == 'T'); 119 return pcb_stop; 120} 121 122int 123process_stopped(pid_t pid) 124{ 125 int is_stopped = -1; 126 FILE * file = open_status_file(pid); 127 if (file != NULL) { 128 each_line_starting(file, "State:\t", &process_stopped_cb, 129 &is_stopped); 130 fclose(file); 131 } 132 return is_stopped; 133} 134 135static enum pcb_status 136process_status_cb(const char * line, const char * prefix, void * data) 137{ 138 *(char *)data = line[strlen(prefix)]; 139 return pcb_stop; 140} 141 142char 143process_status(pid_t pid) 144{ 145 char ret = '?'; 146 FILE * file = open_status_file(pid); 147 if (file != NULL) { 148 each_line_starting(file, "State:\t", &process_status_cb, &ret); 149 fclose(file); 150 } 151 return ret; 152} 153 154static int 155all_digits(const char *str) 156{ 157 while (isdigit(*str)) 158 str++; 159 return !*str; 160} 161 162int 163process_tasks(pid_t pid, pid_t **ret_tasks, size_t *ret_n) 164{ 165 PROC_PID_FILE(fn, "/proc/%d/task", pid); 166 DIR * d = opendir(fn); 167 if (d == NULL) 168 return -1; 169 170 /* XXX This is racy. We need to stop the tasks that we 171 discover this way and re-scan the directory to eventually 172 reach a full set of tasks. */ 173 pid_t *tasks = NULL; 174 size_t n = 0; 175 size_t alloc = 0; 176 177 while (1) { 178 struct dirent entry; 179 struct dirent *result; 180 if (readdir_r(d, &entry, &result) != 0) { 181 free(tasks); 182 return -1; 183 } 184 if (result == NULL) 185 break; 186 if (result->d_type == DT_DIR && all_digits(result->d_name)) { 187 pid_t npid = atoi(result->d_name); 188 if (n >= alloc) { 189 alloc = alloc > 0 ? (2 * alloc) : 8; 190 pid_t *ntasks = realloc(tasks, 191 sizeof(*tasks) * alloc); 192 if (ntasks == NULL) { 193 free(tasks); 194 return -1; 195 } 196 tasks = ntasks; 197 } 198 if (n >= alloc) 199 abort(); 200 tasks[n++] = npid; 201 } 202 } 203 204 closedir(d); 205 206 *ret_tasks = tasks; 207 *ret_n = n; 208 return 0; 209} 210 211static int 212find_dynamic_entry_addr(Process *proc, void *pvAddr, int d_tag, void **addr) { 213 int i = 0, done = 0; 214 ElfW(Dyn) entry; 215 216 debug(DEBUG_FUNCTION, "find_dynamic_entry()"); 217 218 if (addr == NULL || pvAddr == NULL || d_tag < 0 || d_tag > DT_NUM) { 219 return -1; 220 } 221 222 while ((!done) && (i < ELF_MAX_SEGMENTS) && 223 (sizeof(entry) == umovebytes(proc, pvAddr, &entry, sizeof(entry))) && 224 (entry.d_tag != DT_NULL)) { 225 if (entry.d_tag == d_tag) { 226 done = 1; 227 *addr = (void *)entry.d_un.d_val; 228 } 229 pvAddr += sizeof(entry); 230 i++; 231 } 232 233 if (done) { 234 debug(2, "found address: 0x%p in dtag %d\n", *addr, d_tag); 235 return 0; 236 } 237 else { 238 debug(2, "Couldn't address for dtag!\n"); 239 return -1; 240 } 241} 242 243struct cb_data { 244 const char *lib_name; 245 struct ltelf *lte; 246 ElfW(Addr) addr; 247 Process *proc; 248}; 249 250static void 251crawl_linkmap(Process *proc, struct r_debug *dbg, void (*callback)(void *), struct cb_data *data) { 252 struct link_map rlm; 253 char lib_name[BUFSIZ]; 254 struct link_map *lm = NULL; 255 256 debug (DEBUG_FUNCTION, "crawl_linkmap()"); 257 258 if (!dbg || !dbg->r_map) { 259 debug(2, "Debug structure or it's linkmap are NULL!"); 260 return; 261 } 262 263 lm = dbg->r_map; 264 265 while (lm) { 266 if (umovebytes(proc, lm, &rlm, sizeof(rlm)) != sizeof(rlm)) { 267 debug(2, "Unable to read link map\n"); 268 return; 269 } 270 271 lm = rlm.l_next; 272 if (rlm.l_name == NULL) { 273 debug(2, "Invalid library name referenced in dynamic linker map\n"); 274 return; 275 } 276 277 umovebytes(proc, rlm.l_name, lib_name, sizeof(lib_name)); 278 279 if (lib_name[0] == '\0') { 280 debug(2, "Library name is an empty string"); 281 continue; 282 } 283 284 if (callback) { 285 debug(2, "Dispatching callback for: %s, " 286 "Loaded at 0x%" PRI_ELF_ADDR "\n", 287 lib_name, rlm.l_addr); 288 data->addr = rlm.l_addr; 289 data->lib_name = lib_name; 290 callback(data); 291 } 292 } 293 return; 294} 295 296static struct r_debug * 297load_debug_struct(Process *proc) { 298 struct r_debug *rdbg = NULL; 299 300 debug(DEBUG_FUNCTION, "load_debug_struct"); 301 302 rdbg = malloc(sizeof(*rdbg)); 303 if (!rdbg) { 304 return NULL; 305 } 306 307 if (umovebytes(proc, proc->debug, rdbg, sizeof(*rdbg)) != sizeof(*rdbg)) { 308 debug(2, "This process does not have a debug structure!\n"); 309 free(rdbg); 310 return NULL; 311 } 312 313 return rdbg; 314} 315 316static void 317linkmap_add_cb(void *data) { //const char *lib_name, ElfW(Addr) addr) { 318 size_t i = 0; 319 struct cb_data *lm_add = data; 320 struct ltelf lte; 321 struct opt_x_t *xptr; 322 323 debug(DEBUG_FUNCTION, "linkmap_add_cb"); 324 325 /* 326 XXX 327 iterate through library[i]'s to see if this lib is in the list. 328 if not, add it 329 */ 330 for(;i < library_num;i++) { 331 if (strcmp(library[i], lm_add->lib_name) == 0) { 332 /* found it, so its not new */ 333 return; 334 } 335 } 336 337 /* new library linked! */ 338 debug(2, "New libdl loaded library found: %s\n", lm_add->lib_name); 339 340 if (library_num < MAX_LIBRARIES) { 341 library[library_num++] = strdup(lm_add->lib_name); 342 memset(<e, 0, sizeof(struct ltelf)); 343 lte.base_addr = lm_add->addr; 344 do_init_elf(<e, library[library_num-1]); 345 /* add bps */ 346 for (xptr = opt_x; xptr; xptr = xptr->next) { 347 if (xptr->found) 348 continue; 349 350 GElf_Sym sym; 351 GElf_Addr addr; 352 353 if (in_load_libraries(xptr->name, <e, 1, &sym)) { 354 debug(2, "found symbol %s @ %#" PRIx64 355 ", adding it.", 356 xptr->name, sym.st_value); 357 addr = sym.st_value; 358 add_library_symbol(addr, xptr->name, &library_symbols, LS_TOPLT_NONE, 0); 359 xptr->found = 1; 360 insert_breakpoint(lm_add->proc, 361 sym2addr(lm_add->proc, 362 library_symbols), 363 library_symbols, 1); 364 } 365 } 366 do_close_elf(<e); 367 } 368} 369 370void 371arch_check_dbg(Process *proc) { 372 struct r_debug *dbg = NULL; 373 struct cb_data data; 374 375 debug(DEBUG_FUNCTION, "arch_check_dbg"); 376 377 if (!(dbg = load_debug_struct(proc))) { 378 debug(2, "Unable to load debug structure!"); 379 return; 380 } 381 382 if (dbg->r_state == RT_CONSISTENT) { 383 debug(2, "Linkmap is now consistent"); 384 if (proc->debug_state == RT_ADD) { 385 debug(2, "Adding DSO to linkmap"); 386 data.proc = proc; 387 crawl_linkmap(proc, dbg, linkmap_add_cb, &data); 388 } else if (proc->debug_state == RT_DELETE) { 389 debug(2, "Removing DSO from linkmap"); 390 } else { 391 debug(2, "Unexpected debug state!"); 392 } 393 } 394 395 proc->debug_state = dbg->r_state; 396 397 return; 398} 399 400static void 401hook_libdl_cb(void *data) { 402 struct cb_data *hook_data = data; 403 const char *lib_name = NULL; 404 ElfW(Addr) addr; 405 struct ltelf *lte = NULL; 406 407 debug(DEBUG_FUNCTION, "add_library_cb"); 408 409 if (!data) { 410 debug(2, "No callback data"); 411 return; 412 } 413 414 lib_name = hook_data->lib_name; 415 addr = hook_data->addr; 416 lte = hook_data->lte; 417 418 if (library_num < MAX_LIBRARIES) { 419 lte[library_num].base_addr = addr; 420 library[library_num++] = strdup(lib_name); 421 } 422 else { 423 fprintf (stderr, "MAX LIBS REACHED\n"); 424 exit(EXIT_FAILURE); 425 } 426} 427 428int 429linkmap_init(Process *proc, struct ltelf *lte) { 430 void *dbg_addr = NULL, *dyn_addr = GELF_ADDR_CAST(lte->dyn_addr); 431 struct r_debug *rdbg = NULL; 432 struct cb_data data; 433 434 debug(DEBUG_FUNCTION, "linkmap_init()"); 435 436 if (find_dynamic_entry_addr(proc, dyn_addr, DT_DEBUG, &dbg_addr) == -1) { 437 debug(2, "Couldn't find debug structure!"); 438 return -1; 439 } 440 441 proc->debug = dbg_addr; 442 443 if (!(rdbg = load_debug_struct(proc))) { 444 debug(2, "No debug structure or no memory to allocate one!"); 445 return -1; 446 } 447 448 data.lte = lte; 449 450 add_library_symbol(rdbg->r_brk, "", &library_symbols, LS_TOPLT_NONE, 0); 451 insert_breakpoint(proc, sym2addr(proc, library_symbols), 452 library_symbols, 1); 453 454 crawl_linkmap(proc, rdbg, hook_libdl_cb, &data); 455 456 free(rdbg); 457 return 0; 458} 459 460int 461task_kill (pid_t pid, int sig) 462{ 463 // Taken from GDB 464 int ret; 465 466 errno = 0; 467 ret = syscall (__NR_tkill, pid, sig); 468 return ret; 469} 470