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