proc.c revision 3fd099b71ae9e0c4fe9f48a239523e7037e4baf4
1#include "config.h" 2 3#if defined(HAVE_LIBUNWIND) 4#include <libunwind.h> 5#include <libunwind-ptrace.h> 6#endif /* defined(HAVE_LIBUNWIND) */ 7 8#include <sys/types.h> 9#include <string.h> 10#include <stdio.h> 11#include <errno.h> 12#include <stdlib.h> 13#include <assert.h> 14#include <error.h> 15 16#include "common.h" 17#include "breakpoint.h" 18#include "proc.h" 19#include "filter.h" 20 21static int 22process_bare_init(struct Process *proc, const char *filename, pid_t pid) 23{ 24 fprintf(stderr, "process_bare_init %s %d\n", filename, pid); 25 memset(proc, 0, sizeof(*proc)); 26 27 proc->filename = strdup(filename); 28 if (proc->filename == NULL) { 29 fail: 30 free(proc->filename); 31 if (proc->breakpoints != NULL) 32 dict_clear(proc->breakpoints); 33 return -1; 34 } 35 36 /* Add process so that we know who the leader is. */ 37 proc->pid = pid; 38 add_process(proc); 39 if (proc->leader == NULL) 40 goto fail; 41 42 if (proc->leader == proc) { 43 proc->breakpoints = dict_init(dict_key2hash_int, 44 dict_key_cmp_int); 45 if (proc->breakpoints == NULL) 46 goto fail; 47 } else { 48 proc->breakpoints = NULL; 49 } 50 51#if defined(HAVE_LIBUNWIND) 52 proc->unwind_priv = _UPT_create(pid); 53 proc->unwind_as = unw_create_addr_space(&_UPT_accessors, 0); 54#endif /* defined(HAVE_LIBUNWIND) */ 55 56 return 0; 57} 58 59static void 60process_bare_destroy(struct Process *proc) 61{ 62 free(proc->filename); 63 dict_clear(proc->breakpoints); 64 remove_process(proc); 65} 66 67int 68process_init(struct Process *proc, const char *filename, pid_t pid, int enable) 69{ 70 fprintf(stderr, "process_init %s %d enable=%d\n", filename, pid, enable); 71 if (process_bare_init(proc, filename, pid) < 0) { 72 error(0, errno, "init process %d", pid); 73 return -1; 74 } 75 76 if (proc->leader == proc && breakpoints_init(proc, enable) < 0) { 77 fprintf(stderr, "failed to init breakpoints %d\n", 78 proc->pid); 79 process_bare_destroy(proc); 80 return -1; 81 } 82 83 return 0; 84} 85 86struct Process * 87open_program(const char *filename, pid_t pid, int enable) 88{ 89 fprintf(stderr, "open_program %s %d enable=%d\n", 90 filename, pid, enable); 91 assert(pid != 0); 92 struct Process *proc = malloc(sizeof(*proc)); 93 if (proc == NULL 94 || process_init(proc, filename, pid, enable) < 0) { 95 free(proc); 96 return NULL; 97 } 98 return proc; 99} 100 101struct clone_single_bp_data { 102 struct Process *old_proc; 103 struct Process *new_proc; 104 int error; 105}; 106 107struct find_symbol_data { 108 struct library_symbol *old_libsym; 109 struct library_symbol *found_libsym; 110}; 111 112static enum callback_status 113find_sym_in_lib(struct Process *proc, struct library *lib, void *u) 114{ 115 struct find_symbol_data *fs = u; 116 fs->found_libsym 117 = library_each_symbol(lib, NULL, library_symbol_equal_cb, 118 fs->old_libsym); 119 return fs->found_libsym != NULL ? CBS_STOP : CBS_CONT; 120} 121 122static void 123clone_single_bp(void *key, void *value, void *u) 124{ 125 target_address_t addr = (target_address_t)key; 126 struct breakpoint *bp = value; 127 struct clone_single_bp_data *data = u; 128 129 /* Find library and symbol that this symbol was linked to. */ 130 struct library_symbol *libsym = bp->libsym; 131 struct library *lib = NULL; 132 if (libsym != NULL) { 133 struct find_symbol_data f_data = { 134 .old_libsym = libsym, 135 }; 136 lib = proc_each_library(data->old_proc, NULL, 137 find_sym_in_lib, &f_data); 138 assert(lib != NULL); 139 libsym = f_data.found_libsym; 140 } 141 142 /* LIB and LIBSYM now hold the new library and symbol that 143 * correspond to the original breakpoint. Now we can do the 144 * clone itself. */ 145 struct breakpoint *clone = malloc(sizeof(*clone)); 146 if (clone == NULL 147 || breakpoint_init(clone, data->new_proc, addr, libsym) < 0) { 148 data->error = -1; 149 return; 150 } 151 breakpoint_set_callbacks(clone, bp->cbs); 152} 153 154int 155process_clone(struct Process *retp, struct Process *proc, pid_t pid) 156{ 157 if (process_bare_init(retp, proc->filename, pid) < 0) { 158 fail: 159 error(0, errno, "clone process %d->%d", proc->pid, pid); 160 return -1; 161 } 162 163 /* For non-leader processes, that's all we need to do. */ 164 if (proc->leader != proc) 165 return 0; 166 167 /* Clone symbols first so that we can clone and relink 168 * breakpoints. */ 169 struct library *lib; 170 struct library **nlibp = &retp->libraries; 171 for (lib = proc->libraries; lib != NULL; lib = lib->next) { 172 *nlibp = malloc(sizeof(**nlibp)); 173 if (*nlibp == NULL 174 || library_clone(*nlibp, lib) < 0) { 175 fail2: 176 process_bare_destroy(retp); 177 178 /* Error when cloning. Unroll what was done. */ 179 for (lib = retp->libraries; lib != NULL; ) { 180 struct library *next = lib->next; 181 library_destroy(lib); 182 free(lib); 183 lib = next; 184 } 185 goto fail; 186 } 187 188 nlibp = &(*nlibp)->next; 189 } 190 191 /* Now clone breakpoints. Symbol relinking is done in 192 * clone_single_bp. */ 193 struct clone_single_bp_data data = { 194 .old_proc = proc, 195 .new_proc = retp, 196 .error = 0, 197 }; 198 dict_apply_to_all(proc->breakpoints, &clone_single_bp, &data); 199 200 if (data.error < 0) 201 goto fail2; 202 203 return 0; 204} 205 206static int 207open_one_pid(pid_t pid) 208{ 209 Process *proc; 210 char *filename; 211 debug(DEBUG_PROCESS, "open_one_pid(pid=%d)", pid); 212 213 /* Get the filename first. Should the trace_pid fail, we can 214 * easily free it, untracing is more work. */ 215 if ((filename = pid2name(pid)) == NULL 216 || trace_pid(pid) < 0) { 217 free(filename); 218 return -1; 219 } 220 221 proc = open_program(filename, pid, 0); 222 if (proc == NULL) 223 return -1; 224 trace_set_options(proc, pid); 225 226 return 0; 227} 228 229static enum callback_status 230start_one_pid(Process * proc, void * data) 231{ 232 continue_process(proc->pid); 233 return CBS_CONT; 234} 235 236void 237open_pid(pid_t pid) 238{ 239 debug(DEBUG_PROCESS, "open_pid(pid=%d)", pid); 240 /* If we are already tracing this guy, we should be seeing all 241 * his children via normal tracing route. */ 242 if (pid2proc(pid) != NULL) 243 return; 244 245 /* First, see if we can attach the requested PID itself. */ 246 if (open_one_pid(pid)) { 247 fprintf(stderr, "Cannot attach to pid %u: %s\n", 248 pid, strerror(errno)); 249 trace_fail_warning(pid); 250 return; 251 } 252 253 /* Now attach to all tasks that belong to that PID. There's a 254 * race between process_tasks and open_one_pid. So when we 255 * fail in open_one_pid below, we just do another round. 256 * Chances are that by then that PID will have gone away, and 257 * that's why we have seen the failure. The processes that we 258 * manage to open_one_pid are stopped, so we should eventually 259 * reach a point where process_tasks doesn't give any new 260 * processes (because there's nobody left to produce 261 * them). */ 262 size_t old_ntasks = 0; 263 int have_all; 264 while (1) { 265 pid_t *tasks; 266 size_t ntasks; 267 size_t i; 268 269 if (process_tasks(pid, &tasks, &ntasks) < 0) { 270 fprintf(stderr, "Cannot obtain tasks of pid %u: %s\n", 271 pid, strerror(errno)); 272 break; 273 } 274 275 have_all = 1; 276 for (i = 0; i < ntasks; ++i) 277 if (pid2proc(tasks[i]) == NULL 278 && open_one_pid(tasks[i])) 279 have_all = 0; 280 281 free(tasks); 282 283 if (have_all && old_ntasks == ntasks) 284 break; 285 old_ntasks = ntasks; 286 } 287 288 /* Done. Now initialize breakpoints and then continue 289 * everyone. */ 290 Process * leader; 291 leader = pid2proc(pid)->leader; 292 enable_all_breakpoints(leader); 293 294 each_task(pid2proc(pid)->leader, NULL, start_one_pid, NULL); 295} 296 297static enum callback_status 298find_proc(Process * proc, void * data) 299{ 300 pid_t pid = (pid_t)(uintptr_t)data; 301 return proc->pid == pid ? CBS_STOP : CBS_CONT; 302} 303 304Process * 305pid2proc(pid_t pid) { 306 return each_process(NULL, &find_proc, (void *)(uintptr_t)pid); 307} 308 309static Process * list_of_processes = NULL; 310 311static void 312unlist_process(Process * proc) 313{ 314 Process *tmp; 315 316 if (list_of_processes == proc) { 317 list_of_processes = list_of_processes->next; 318 return; 319 } 320 321 for (tmp = list_of_processes; ; tmp = tmp->next) { 322 /* If the following assert fails, the process wasn't 323 * in the list. */ 324 assert(tmp->next != NULL); 325 326 if (tmp->next == proc) { 327 tmp->next = tmp->next->next; 328 return; 329 } 330 } 331} 332 333struct Process * 334each_process(struct Process *start_after, 335 enum callback_status(*cb)(struct Process *proc, void *data), 336 void *data) 337{ 338 struct Process *it = start_after == NULL ? list_of_processes 339 : start_after->next; 340 341 while (it != NULL) { 342 /* Callback might call remove_process. */ 343 struct Process *next = it->next; 344 switch ((*cb)(it, data)) { 345 case CBS_FAIL: 346 /* XXX handle me */ 347 case CBS_STOP: 348 return it; 349 case CBS_CONT: 350 break; 351 } 352 it = next; 353 } 354 return NULL; 355} 356 357Process * 358each_task(struct Process *proc, struct Process *start_after, 359 enum callback_status(*cb)(struct Process *proc, void *data), 360 void *data) 361{ 362 assert(proc != NULL); 363 struct Process *it = start_after == NULL ? proc->leader 364 : start_after->next; 365 366 if (it != NULL) { 367 struct Process *leader = it->leader; 368 while (it != NULL && it->leader == leader) { 369 /* Callback might call remove_process. */ 370 struct Process *next = it->next; 371 switch ((*cb)(it, data)) { 372 case CBS_FAIL: 373 /* XXX handle me */ 374 case CBS_STOP: 375 return it; 376 case CBS_CONT: 377 break; 378 } 379 it = next; 380 } 381 } 382 return NULL; 383} 384 385void 386add_process(Process * proc) 387{ 388 fprintf(stderr, "add_process %d\n", proc->pid); 389 Process ** leaderp = &list_of_processes; 390 if (proc->pid) { 391 pid_t tgid = process_leader(proc->pid); 392 fprintf(stderr, " + leader is %d\n", tgid); 393 if (tgid == 0) 394 /* Must have been terminated before we managed 395 * to fully attach. */ 396 return; 397 if (tgid == proc->pid) 398 proc->leader = proc; 399 else { 400 Process * leader = pid2proc(tgid); 401 proc->leader = leader; 402 if (leader != NULL) 403 leaderp = &leader->next; 404 } 405 } 406 proc->next = *leaderp; 407 *leaderp = proc; 408} 409 410void 411change_process_leader(Process * proc, Process * leader) 412{ 413 Process ** leaderp = &list_of_processes; 414 if (proc->leader == leader) 415 return; 416 417 assert(leader != NULL); 418 unlist_process(proc); 419 if (proc != leader) 420 leaderp = &leader->next; 421 422 proc->leader = leader; 423 proc->next = *leaderp; 424 *leaderp = proc; 425} 426 427static enum callback_status 428clear_leader(struct Process *proc, void *data) 429{ 430 debug(DEBUG_FUNCTION, "detach_task %d from leader %d", 431 proc->pid, proc->leader->pid); 432 proc->leader = NULL; 433 return CBS_CONT; 434} 435 436static enum ecb_status 437event_for_proc(Event * event, void * data) 438{ 439 if (event->proc == data) 440 return ecb_deque; 441 else 442 return ecb_cont; 443} 444 445static void 446delete_events_for(Process * proc) 447{ 448 Event * event; 449 while ((event = each_qd_event(&event_for_proc, proc)) != NULL) 450 free(event); 451} 452 453void 454remove_process(Process *proc) 455{ 456 debug(DEBUG_FUNCTION, "remove_proc(pid=%d)", proc->pid); 457 458 if (proc->leader == proc) 459 each_task(proc, NULL, &clear_leader, NULL); 460 461 unlist_process(proc); 462 delete_events_for(proc); 463} 464 465void 466install_event_handler(Process *proc, struct event_handler *handler) 467{ 468 debug(DEBUG_FUNCTION, "install_event_handler(pid=%d, %p)", proc->pid, handler); 469 assert(proc->event_handler == NULL); 470 proc->event_handler = handler; 471} 472 473void 474destroy_event_handler(Process * proc) 475{ 476 struct event_handler *handler = proc->event_handler; 477 debug(DEBUG_FUNCTION, "destroy_event_handler(pid=%d, %p)", proc->pid, handler); 478 assert(handler != NULL); 479 if (handler->destroy != NULL) 480 handler->destroy(handler); 481 free(handler); 482 proc->event_handler = NULL; 483} 484 485static enum callback_status 486breakpoint_for_symbol(struct library_symbol *libsym, void *data) 487{ 488 struct Process *proc = data; 489 490 if (!filter_matches_symbol(options.filter, libsym)) 491 return CBS_CONT; 492 493 struct breakpoint *bp = malloc(sizeof(*bp)); 494 if (bp == NULL 495 || breakpoint_init(bp, proc, libsym->enter_addr, libsym) < 0) { 496 fail: 497 free(bp); 498 return CBS_FAIL; 499 } 500 if (proc_add_breakpoint(proc, bp) < 0) { 501 breakpoint_destroy(bp); 502 goto fail; 503 } 504 505 return CBS_CONT; 506} 507 508void 509proc_add_library(struct Process *proc, struct library *lib) 510{ 511 assert(lib->next == NULL); 512 lib->next = proc->libraries; 513 proc->libraries = lib; 514 fprintf(stderr, "=== Added library %s@%p (%s) to %d:\n", 515 lib->soname, lib->base, lib->pathname, proc->pid); 516 517 if (!filter_matches_library(options.filter, lib)) 518 return; 519 520 struct library_symbol *libsym = NULL; 521 while ((libsym = library_each_symbol(lib, libsym, breakpoint_for_symbol, 522 proc)) != NULL) 523 error(0, errno, "insert breakpoint for %s", libsym->name); 524} 525 526int 527proc_remove_library(struct Process *proc, struct library *lib) 528{ 529 struct library **libp; 530 for (libp = &proc->libraries; *libp != NULL; libp = &(*libp)->next) 531 if (*libp == lib) { 532 *libp = lib->next; 533 return 0; 534 } 535 return -1; 536} 537 538struct library * 539proc_each_library(struct Process *proc, struct library *it, 540 enum callback_status (*cb)(struct Process *proc, 541 struct library *lib, void *data), 542 void *data) 543{ 544 if (it == NULL) 545 it = proc->libraries; 546 547 while (it != NULL) { 548 struct library *next = it->next; 549 550 switch (cb(proc, it, data)) { 551 case CBS_FAIL: 552 /* XXX handle me */ 553 case CBS_STOP: 554 return it; 555 case CBS_CONT: 556 break; 557 } 558 559 it = next; 560 } 561 562 return NULL; 563} 564 565int 566proc_add_breakpoint(struct Process *proc, struct breakpoint *bp) 567{ 568 struct Process *leader = proc->leader; 569 570 /* Only the group leader should be getting the breakpoints and 571 * thus have ->breakpoint initialized. */ 572 assert(leader != NULL); 573 assert(leader->breakpoints != NULL); 574 575 /* Make sure it wasn't inserted yet. */ 576 assert(bp->proc == NULL); 577 578 debug(DEBUG_FUNCTION, "proc_insert_breakpoint(pid=%d, %s@%p)", 579 proc->pid, breakpoint_name(bp), bp->addr); 580 581 assert(dict_find_entry(leader->breakpoints, bp->addr) == NULL); 582 if (dict_enter(leader->breakpoints, bp->addr, bp) < 0) { 583 error(0, errno, "couldn't enter breakpoint %s@%p to dictionary", 584 breakpoint_name(bp), bp->addr); 585 return -1; 586 } 587 588 bp->proc = proc; 589 return 0; 590} 591 592int 593proc_remove_breakpoint(struct Process *proc, struct breakpoint *bp) 594{ 595 /* XXX We can't, really. We are missing dict_remove. */ 596 assert(!"Not yet implemented!"); 597 abort(); 598} 599