proc.c revision 5bf471403f1145fb004005b99eb439969d672dcd
1/* 2 * This file is part of ltrace. 3 * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc. 4 * Copyright (C) 2010 Joe Damato 5 * Copyright (C) 1998,2009 Juan Cespedes 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 of the 10 * License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 * 02110-1301 USA 21 */ 22 23#include "config.h" 24 25#include <sys/types.h> 26#include <assert.h> 27#include <errno.h> 28#include <stdio.h> 29#include <stdlib.h> 30#include <string.h> 31 32#if defined(HAVE_LIBUNWIND) 33#include <libunwind.h> 34#include <libunwind-ptrace.h> 35#endif /* defined(HAVE_LIBUNWIND) */ 36 37#include "backend.h" 38#include "breakpoint.h" 39#include "debug.h" 40#include "fetch.h" 41#include "proc.h" 42#include "value_dict.h" 43 44#ifndef ARCH_HAVE_PROCESS_DATA 45int 46arch_process_init(struct Process *proc) 47{ 48 return 0; 49} 50 51void 52arch_process_destroy(struct Process *proc) 53{ 54} 55 56int 57arch_process_clone(struct Process *retp, struct Process *proc) 58{ 59 return 0; 60} 61 62int 63arch_process_exec(struct Process *proc) 64{ 65 return 0; 66} 67#endif 68 69#ifndef OS_HAVE_PROCESS_DATA 70int 71os_process_init(struct Process *proc) 72{ 73 return 0; 74} 75 76void 77os_process_destroy(struct Process *proc) 78{ 79} 80 81int 82os_process_clone(struct Process *retp, struct Process *proc) 83{ 84 return 0; 85} 86 87int 88os_process_exec(struct Process *proc) 89{ 90 return 0; 91} 92#endif 93 94#ifndef ARCH_HAVE_DYNLINK_DONE 95void 96arch_dynlink_done(struct Process *proc) 97{ 98} 99#endif 100 101static void add_process(struct Process *proc, int was_exec); 102static void unlist_process(struct Process *proc); 103 104static void 105destroy_unwind(struct Process *proc) 106{ 107#if defined(HAVE_LIBUNWIND) 108 _UPT_destroy(proc->unwind_priv); 109 unw_destroy_addr_space(proc->unwind_as); 110#endif /* defined(HAVE_LIBUNWIND) */ 111} 112 113static int 114process_bare_init(struct Process *proc, const char *filename, 115 pid_t pid, int was_exec) 116{ 117 if (!was_exec) { 118 memset(proc, 0, sizeof(*proc)); 119 120 proc->filename = strdup(filename); 121 if (proc->filename == NULL) { 122 fail: 123 free(proc->filename); 124 if (proc->breakpoints != NULL) 125 dict_clear(proc->breakpoints); 126 return -1; 127 } 128 } 129 130 /* Add process so that we know who the leader is. */ 131 proc->pid = pid; 132 add_process(proc, was_exec); 133 if (proc->leader == NULL) 134 goto fail; 135 136 if (proc->leader == proc) { 137 proc->breakpoints = dict_init(target_address_hash, 138 target_address_cmp); 139 if (proc->breakpoints == NULL) 140 goto fail; 141 } else { 142 proc->breakpoints = NULL; 143 } 144 145#if defined(HAVE_LIBUNWIND) 146 proc->unwind_priv = _UPT_create(pid); 147 proc->unwind_as = unw_create_addr_space(&_UPT_accessors, 0); 148#endif /* defined(HAVE_LIBUNWIND) */ 149 150 return 0; 151} 152 153static void 154process_bare_destroy(struct Process *proc, int was_exec) 155{ 156 dict_clear(proc->breakpoints); 157 if (!was_exec) { 158 free(proc->filename); 159 unlist_process(proc); 160 destroy_unwind(proc); 161 } 162} 163 164static int 165process_init_main(struct Process *proc) 166{ 167 if (breakpoints_init(proc) < 0) { 168 fprintf(stderr, "failed to init breakpoints %d\n", 169 proc->pid); 170 return -1; 171 } 172 173 return 0; 174} 175 176int 177process_init(struct Process *proc, const char *filename, pid_t pid) 178{ 179 if (process_bare_init(proc, filename, pid, 0) < 0) { 180 fail: 181 fprintf(stderr, "failed to initialize process %d: %s\n", 182 pid, strerror(errno)); 183 return -1; 184 } 185 186 if (os_process_init(proc) < 0) { 187 process_bare_destroy(proc, 0); 188 goto fail; 189 } 190 191 if (arch_process_init(proc) < 0) { 192 os_process_destroy(proc); 193 process_bare_destroy(proc, 0); 194 goto fail; 195 } 196 197 if (proc->leader != proc) 198 return 0; 199 if (process_init_main(proc) < 0) { 200 process_bare_destroy(proc, 0); 201 goto fail; 202 } 203 return 0; 204} 205 206static enum callback_status 207destroy_breakpoint_cb(struct Process *proc, struct breakpoint *bp, void *data) 208{ 209 breakpoint_destroy(bp); 210 free(bp); 211 return CBS_CONT; 212} 213 214// XXX see comment in handle_event.c 215void callstack_pop(struct Process *proc); 216 217static void 218private_process_destroy(struct Process *proc, int was_exec) 219{ 220 /* Pop remaining stack elements. */ 221 while (proc->callstack_depth > 0) { 222 /* When this is called just before a process is 223 * destroyed, the breakpoints should either have been 224 * retracted by now, or were killed by exec. In any 225 * case, it's safe to pretend that there are no 226 * breakpoints associated with the stack elements, so 227 * that stack_pop doesn't attempt to destroy them. */ 228 size_t i = proc->callstack_depth - 1; 229 if (!proc->callstack[i].is_syscall) 230 proc->callstack[i].return_addr = 0; 231 232 callstack_pop(proc); 233 } 234 235 if (!was_exec) 236 free(proc->filename); 237 238 /* Libraries and symbols. This is only relevant in 239 * leader. */ 240 struct library *lib; 241 for (lib = proc->libraries; lib != NULL; ) { 242 struct library *next = lib->next; 243 library_destroy(lib); 244 free(lib); 245 lib = next; 246 } 247 proc->libraries = NULL; 248 249 /* Breakpoints. */ 250 if (proc->breakpoints != NULL) { 251 proc_each_breakpoint(proc, NULL, destroy_breakpoint_cb, NULL); 252 dict_clear(proc->breakpoints); 253 proc->breakpoints = NULL; 254 } 255 256 destroy_unwind(proc); 257} 258 259void 260process_destroy(struct Process *proc) 261{ 262 arch_process_destroy(proc); 263 os_process_destroy(proc); 264 private_process_destroy(proc, 0); 265} 266 267int 268process_exec(struct Process *proc) 269{ 270 /* Call exec handlers first, before we destroy the main 271 * state. */ 272 if (arch_process_exec(proc) < 0 273 || os_process_exec(proc) < 0) 274 return -1; 275 276 private_process_destroy(proc, 1); 277 278 if (process_bare_init(proc, NULL, proc->pid, 1) < 0) 279 return -1; 280 if (process_init_main(proc) < 0) { 281 process_bare_destroy(proc, 1); 282 return -1; 283 } 284 return 0; 285} 286 287struct Process * 288open_program(const char *filename, pid_t pid) 289{ 290 assert(pid != 0); 291 struct Process *proc = malloc(sizeof(*proc)); 292 if (proc == NULL || process_init(proc, filename, pid) < 0) { 293 free(proc); 294 return NULL; 295 } 296 return proc; 297} 298 299struct clone_single_bp_data { 300 struct Process *old_proc; 301 struct Process *new_proc; 302 int error; 303}; 304 305static void 306clone_single_bp(void *key, void *value, void *u) 307{ 308 struct breakpoint *bp = value; 309 struct clone_single_bp_data *data = u; 310 311 /* Don't bother if there were errors anyway. */ 312 if (data->error != 0) 313 return; 314 315 struct breakpoint *clone = malloc(sizeof(*clone)); 316 if (clone == NULL 317 || breakpoint_clone(clone, data->new_proc, 318 bp, data->old_proc) < 0) { 319 fail: 320 free(clone); 321 data->error = -1; 322 } 323 if (proc_add_breakpoint(data->new_proc->leader, clone) < 0) { 324 breakpoint_destroy(clone); 325 goto fail; 326 } 327} 328 329int 330process_clone(struct Process *retp, struct Process *proc, pid_t pid) 331{ 332 if (process_bare_init(retp, proc->filename, pid, 0) < 0) { 333 fail1: 334 fprintf(stderr, "failed to clone process %d->%d : %s\n", 335 proc->pid, pid, strerror(errno)); 336 return -1; 337 } 338 339 retp->tracesysgood = proc->tracesysgood; 340 retp->e_machine = proc->e_machine; 341 retp->e_class = proc->e_class; 342 343 /* For non-leader processes, that's all we need to do. */ 344 if (retp->leader != retp) 345 return 0; 346 347 /* Clone symbols first so that we can clone and relink 348 * breakpoints. */ 349 struct library *lib; 350 struct library **nlibp = &retp->libraries; 351 for (lib = proc->libraries; lib != NULL; lib = lib->next) { 352 *nlibp = malloc(sizeof(**nlibp)); 353 if (*nlibp == NULL 354 || library_clone(*nlibp, lib) < 0) { 355 fail2: 356 process_bare_destroy(retp, 0); 357 358 /* Error when cloning. Unroll what was done. */ 359 for (lib = retp->libraries; lib != NULL; ) { 360 struct library *next = lib->next; 361 library_destroy(lib); 362 free(lib); 363 lib = next; 364 } 365 goto fail1; 366 } 367 368 nlibp = &(*nlibp)->next; 369 } 370 371 /* Now clone breakpoints. Symbol relinking is done in 372 * clone_single_bp. */ 373 struct clone_single_bp_data data = { 374 .old_proc = proc, 375 .new_proc = retp, 376 .error = 0, 377 }; 378 dict_apply_to_all(proc->breakpoints, &clone_single_bp, &data); 379 if (data.error < 0) 380 goto fail2; 381 382 /* And finally the call stack. */ 383 memcpy(retp->callstack, proc->callstack, sizeof(retp->callstack)); 384 retp->callstack_depth = proc->callstack_depth; 385 386 size_t i; 387 for (i = 0; i < retp->callstack_depth; ++i) { 388 struct fetch_context *ctx = retp->callstack[i].fetch_context; 389 if (ctx != NULL) { 390 struct fetch_context *nctx = fetch_arg_clone(retp, ctx); 391 if (nctx == NULL) { 392 size_t j; 393 fail3: 394 for (j = 0; j < i; ++j) { 395 nctx = retp->callstack[i].fetch_context; 396 fetch_arg_done(nctx); 397 retp->callstack[i].fetch_context = NULL; 398 } 399 goto fail2; 400 } 401 retp->callstack[i].fetch_context = nctx; 402 } 403 404 struct value_dict *args = retp->callstack[i].arguments; 405 if (args != NULL) { 406 struct value_dict *nargs = malloc(sizeof(*nargs)); 407 if (nargs == NULL 408 || val_dict_clone(nargs, args) < 0) { 409 size_t j; 410 for (j = 0; j < i; ++j) { 411 nargs = retp->callstack[i].arguments; 412 val_dict_destroy(nargs); 413 free(nargs); 414 retp->callstack[i].arguments = NULL; 415 } 416 417 /* Pretend that this round went well, 418 * so that fail3 frees I-th 419 * fetch_context. */ 420 ++i; 421 goto fail3; 422 } 423 retp->callstack[i].arguments = nargs; 424 } 425 426 /* If it's not a syscall, we need to find the 427 * corresponding library symbol in the cloned 428 * library. */ 429 if (!elem->is_syscall && elem->c_un.libfunc != NULL) { 430 struct library_symbol *libfunc = elem->c_un.libfunc; 431 int rc = proc_find_symbol(retp, libfunc, 432 NULL, &elem->c_un.libfunc); 433 assert(rc == 0); 434 } 435 } 436 437 /* At this point, retp is fully initialized, except for OS and 438 * arch parts, and we can call private_process_destroy. */ 439 if (os_process_clone(retp, proc) < 0) { 440 private_process_destroy(retp, 0); 441 return -1; 442 } 443 if (arch_process_clone(retp, proc) < 0) { 444 os_process_destroy(retp); 445 private_process_destroy(retp, 0); 446 return -1; 447 } 448 449 return 0; 450} 451 452static int 453open_one_pid(pid_t pid) 454{ 455 Process *proc; 456 char *filename; 457 debug(DEBUG_PROCESS, "open_one_pid(pid=%d)", pid); 458 459 /* Get the filename first. Should the trace_pid fail, we can 460 * easily free it, untracing is more work. */ 461 if ((filename = pid2name(pid)) == NULL 462 || trace_pid(pid) < 0) { 463 fail: 464 free(filename); 465 return -1; 466 } 467 468 proc = open_program(filename, pid); 469 if (proc == NULL) 470 goto fail; 471 free(filename); 472 trace_set_options(proc); 473 474 return 0; 475} 476 477static enum callback_status 478start_one_pid(Process * proc, void * data) 479{ 480 continue_process(proc->pid); 481 return CBS_CONT; 482} 483 484void 485open_pid(pid_t pid) 486{ 487 debug(DEBUG_PROCESS, "open_pid(pid=%d)", pid); 488 /* If we are already tracing this guy, we should be seeing all 489 * his children via normal tracing route. */ 490 if (pid2proc(pid) != NULL) 491 return; 492 493 /* First, see if we can attach the requested PID itself. */ 494 if (open_one_pid(pid)) { 495 fprintf(stderr, "Cannot attach to pid %u: %s\n", 496 pid, strerror(errno)); 497 trace_fail_warning(pid); 498 return; 499 } 500 501 /* Now attach to all tasks that belong to that PID. There's a 502 * race between process_tasks and open_one_pid. So when we 503 * fail in open_one_pid below, we just do another round. 504 * Chances are that by then that PID will have gone away, and 505 * that's why we have seen the failure. The processes that we 506 * manage to open_one_pid are stopped, so we should eventually 507 * reach a point where process_tasks doesn't give any new 508 * processes (because there's nobody left to produce 509 * them). */ 510 size_t old_ntasks = 0; 511 int have_all; 512 while (1) { 513 pid_t *tasks; 514 size_t ntasks; 515 size_t i; 516 517 if (process_tasks(pid, &tasks, &ntasks) < 0) { 518 fprintf(stderr, "Cannot obtain tasks of pid %u: %s\n", 519 pid, strerror(errno)); 520 break; 521 } 522 523 have_all = 1; 524 for (i = 0; i < ntasks; ++i) 525 if (pid2proc(tasks[i]) == NULL 526 && open_one_pid(tasks[i])) 527 have_all = 0; 528 529 free(tasks); 530 531 if (have_all && old_ntasks == ntasks) 532 break; 533 old_ntasks = ntasks; 534 } 535 536 struct Process *leader = pid2proc(pid)->leader; 537 538 /* XXX Is there a way to figure out whether _start has 539 * actually already been hit? */ 540 arch_dynlink_done(leader); 541 542 /* Done. Continue everyone. */ 543 each_task(leader, NULL, start_one_pid, NULL); 544} 545 546static enum callback_status 547find_proc(Process * proc, void * data) 548{ 549 pid_t pid = (pid_t)(uintptr_t)data; 550 return proc->pid == pid ? CBS_STOP : CBS_CONT; 551} 552 553Process * 554pid2proc(pid_t pid) { 555 return each_process(NULL, &find_proc, (void *)(uintptr_t)pid); 556} 557 558static Process * list_of_processes = NULL; 559 560static void 561unlist_process(Process * proc) 562{ 563 Process *tmp; 564 565 if (list_of_processes == proc) { 566 list_of_processes = list_of_processes->next; 567 return; 568 } 569 570 for (tmp = list_of_processes; ; tmp = tmp->next) { 571 /* If the following assert fails, the process wasn't 572 * in the list. */ 573 assert(tmp->next != NULL); 574 575 if (tmp->next == proc) { 576 tmp->next = tmp->next->next; 577 return; 578 } 579 } 580} 581 582struct Process * 583each_process(struct Process *start_after, 584 enum callback_status(*cb)(struct Process *proc, void *data), 585 void *data) 586{ 587 struct Process *it = start_after == NULL ? list_of_processes 588 : start_after->next; 589 590 while (it != NULL) { 591 /* Callback might call remove_process. */ 592 struct Process *next = it->next; 593 switch ((*cb)(it, data)) { 594 case CBS_FAIL: 595 /* XXX handle me */ 596 case CBS_STOP: 597 return it; 598 case CBS_CONT: 599 break; 600 } 601 it = next; 602 } 603 return NULL; 604} 605 606Process * 607each_task(struct Process *proc, struct Process *start_after, 608 enum callback_status(*cb)(struct Process *proc, void *data), 609 void *data) 610{ 611 assert(proc != NULL); 612 struct Process *it = start_after == NULL ? proc->leader 613 : start_after->next; 614 615 if (it != NULL) { 616 struct Process *leader = it->leader; 617 while (it != NULL && it->leader == leader) { 618 /* Callback might call remove_process. */ 619 struct Process *next = it->next; 620 switch ((*cb)(it, data)) { 621 case CBS_FAIL: 622 /* XXX handle me */ 623 case CBS_STOP: 624 return it; 625 case CBS_CONT: 626 break; 627 } 628 it = next; 629 } 630 } 631 return NULL; 632} 633 634static void 635add_process(struct Process *proc, int was_exec) 636{ 637 Process ** leaderp = &list_of_processes; 638 if (proc->pid) { 639 pid_t tgid = process_leader(proc->pid); 640 if (tgid == 0) 641 /* Must have been terminated before we managed 642 * to fully attach. */ 643 return; 644 if (tgid == proc->pid) 645 proc->leader = proc; 646 else { 647 Process * leader = pid2proc(tgid); 648 proc->leader = leader; 649 if (leader != NULL) 650 leaderp = &leader->next; 651 } 652 } 653 654 if (!was_exec) { 655 proc->next = *leaderp; 656 *leaderp = proc; 657 } 658} 659 660void 661change_process_leader(Process * proc, Process * leader) 662{ 663 Process ** leaderp = &list_of_processes; 664 if (proc->leader == leader) 665 return; 666 667 assert(leader != NULL); 668 unlist_process(proc); 669 if (proc != leader) 670 leaderp = &leader->next; 671 672 proc->leader = leader; 673 proc->next = *leaderp; 674 *leaderp = proc; 675} 676 677static enum callback_status 678clear_leader(struct Process *proc, void *data) 679{ 680 debug(DEBUG_FUNCTION, "detach_task %d from leader %d", 681 proc->pid, proc->leader->pid); 682 proc->leader = NULL; 683 return CBS_CONT; 684} 685 686void 687remove_process(Process *proc) 688{ 689 debug(DEBUG_FUNCTION, "remove_proc(pid=%d)", proc->pid); 690 691 if (proc->leader == proc) 692 each_task(proc, NULL, &clear_leader, NULL); 693 694 unlist_process(proc); 695 process_removed(proc); 696 process_destroy(proc); 697 free(proc); 698} 699 700void 701install_event_handler(Process *proc, struct event_handler *handler) 702{ 703 debug(DEBUG_FUNCTION, "install_event_handler(pid=%d, %p)", proc->pid, handler); 704 assert(proc->event_handler == NULL); 705 proc->event_handler = handler; 706} 707 708void 709destroy_event_handler(Process * proc) 710{ 711 struct event_handler *handler = proc->event_handler; 712 debug(DEBUG_FUNCTION, "destroy_event_handler(pid=%d, %p)", proc->pid, handler); 713 assert(handler != NULL); 714 if (handler->destroy != NULL) 715 handler->destroy(handler); 716 free(handler); 717 proc->event_handler = NULL; 718} 719 720static int 721breakpoint_for_symbol(struct library_symbol *libsym, struct Process *proc) 722{ 723 arch_addr_t bp_addr; 724 assert(proc->leader == proc); 725 726 /* Don't enable latent or delayed symbols. */ 727 if (libsym->latent || libsym->delayed) 728 return 0; 729 730 bp_addr = sym2addr(proc, libsym); 731 732 /* If there is an artificial breakpoint on the same address, 733 * its libsym will be NULL, and we can smuggle our libsym 734 * there. That artificial breakpoint is there presumably for 735 * the callbacks, which we don't touch. If there is a real 736 * breakpoint, then this is a bug. ltrace-elf.c should filter 737 * symbols and ignore extra symbol aliases. 738 * 739 * The other direction is more complicated and currently not 740 * supported. If a breakpoint has custom callbacks, it might 741 * be also custom-allocated, and we would really need to swap 742 * the two: delete the one now in the dictionary, swap values 743 * around, and put the new breakpoint back in. */ 744 struct breakpoint *bp = dict_find_entry(proc->breakpoints, 745 bp_addr); 746 if (bp != NULL) { 747 assert(bp->libsym == NULL); 748 bp->libsym = libsym; 749 return 0; 750 } 751 752 bp = malloc(sizeof(*bp)); 753 if (bp == NULL 754 || breakpoint_init(bp, proc, bp_addr, libsym) < 0) { 755 fail: 756 free(bp); 757 return -1; 758 } 759 if (proc_add_breakpoint(proc, bp) < 0) { 760 breakpoint_destroy(bp); 761 goto fail; 762 } 763 764 if (breakpoint_turn_on(bp, proc) < 0) { 765 proc_remove_breakpoint(proc, bp); 766 breakpoint_destroy(bp); 767 goto fail; 768 } 769 770 return 0; 771} 772 773static enum callback_status 774cb_breakpoint_for_symbol(struct library_symbol *libsym, void *data) 775{ 776 return breakpoint_for_symbol(libsym, data) < 0 ? CBS_FAIL : CBS_CONT; 777} 778 779static int 780proc_activate_latent_symbol(struct Process *proc, 781 struct library_symbol *libsym) 782{ 783 assert(libsym->latent); 784 libsym->latent = 0; 785 return breakpoint_for_symbol(libsym, proc); 786} 787 788int 789proc_activate_delayed_symbol(struct Process *proc, 790 struct library_symbol *libsym) 791{ 792 assert(libsym->delayed); 793 libsym->delayed = 0; 794 return breakpoint_for_symbol(libsym, proc); 795} 796 797static enum callback_status 798activate_latent_in(struct Process *proc, struct library *lib, void *data) 799{ 800 struct library_exported_name *exported; 801 for (exported = data; exported != NULL; exported = exported->next) { 802 struct library_symbol *libsym = NULL; 803 while ((libsym = library_each_symbol(lib, libsym, 804 library_symbol_named_cb, 805 (void *)exported->name)) 806 != NULL) 807 if (libsym->latent 808 && proc_activate_latent_symbol(proc, libsym) < 0) 809 return CBS_FAIL; 810 } 811 return CBS_CONT; 812} 813 814void 815proc_add_library(struct Process *proc, struct library *lib) 816{ 817 assert(lib->next == NULL); 818 lib->next = proc->libraries; 819 proc->libraries = lib; 820 debug(DEBUG_PROCESS, "added library %s@%p (%s) to %d", 821 lib->soname, lib->base, lib->pathname, proc->pid); 822 823 /* Insert breakpoints for all active (non-latent) symbols. */ 824 struct library_symbol *libsym = NULL; 825 while ((libsym = library_each_symbol(lib, libsym, 826 cb_breakpoint_for_symbol, 827 proc)) != NULL) 828 fprintf(stderr, "Couldn't insert breakpoint for %s to %d: %s.", 829 libsym->name, proc->pid, strerror(errno)); 830 831 /* Look through export list of the new library and compare it 832 * with latent symbols of all libraries (including this 833 * library itself). */ 834 struct library *lib2 = NULL; 835 while ((lib2 = proc_each_library(proc, lib2, activate_latent_in, 836 lib->exported_names)) != NULL) 837 fprintf(stderr, 838 "Couldn't activate latent symbols for %s in %d: %s.", 839 libsym->name, proc->pid, strerror(errno)); 840} 841 842int 843proc_remove_library(struct Process *proc, struct library *lib) 844{ 845 struct library **libp; 846 for (libp = &proc->libraries; *libp != NULL; libp = &(*libp)->next) 847 if (*libp == lib) { 848 *libp = lib->next; 849 return 0; 850 } 851 return -1; 852} 853 854struct library * 855proc_each_library(struct Process *proc, struct library *it, 856 enum callback_status (*cb)(struct Process *proc, 857 struct library *lib, void *data), 858 void *data) 859{ 860 if (it == NULL) 861 it = proc->libraries; 862 863 while (it != NULL) { 864 struct library *next = it->next; 865 866 switch (cb(proc, it, data)) { 867 case CBS_FAIL: 868 /* XXX handle me */ 869 case CBS_STOP: 870 return it; 871 case CBS_CONT: 872 break; 873 } 874 875 it = next; 876 } 877 878 return NULL; 879} 880 881static void 882check_leader(struct Process *proc) 883{ 884 /* Only the group leader should be getting the breakpoints and 885 * thus have ->breakpoint initialized. */ 886 assert(proc->leader != NULL); 887 assert(proc->leader == proc); 888 assert(proc->breakpoints != NULL); 889} 890 891int 892proc_add_breakpoint(struct Process *proc, struct breakpoint *bp) 893{ 894 debug(DEBUG_FUNCTION, "proc_add_breakpoint(pid=%d, %s@%p)", 895 proc->pid, breakpoint_name(bp), bp->addr); 896 check_leader(proc); 897 898 /* XXX We might merge bp->libsym instead of the following 899 * assert, but that's not necessary right now. Read the 900 * comment in breakpoint_for_symbol. */ 901 assert(dict_find_entry(proc->breakpoints, bp->addr) == NULL); 902 903 if (dict_enter(proc->breakpoints, bp->addr, bp) < 0) { 904 fprintf(stderr, 905 "couldn't enter breakpoint %s@%p to dictionary: %s\n", 906 breakpoint_name(bp), bp->addr, strerror(errno)); 907 return -1; 908 } 909 910 return 0; 911} 912 913void 914proc_remove_breakpoint(struct Process *proc, struct breakpoint *bp) 915{ 916 debug(DEBUG_FUNCTION, "proc_remove_breakpoint(pid=%d, %s@%p)", 917 proc->pid, breakpoint_name(bp), bp->addr); 918 check_leader(proc); 919 struct breakpoint *removed = dict_remove(proc->breakpoints, bp->addr); 920 assert(removed == bp); 921} 922 923/* Dict doesn't support iteration restarts, so here's this contraption 924 * for now. XXX add restarts to dict. */ 925struct each_breakpoint_data 926{ 927 void *start; 928 void *end; 929 struct Process *proc; 930 enum callback_status (*cb)(struct Process *proc, 931 struct breakpoint *bp, 932 void *data); 933 void *cb_data; 934}; 935 936static void 937each_breakpoint_cb(void *key, void *value, void *d) 938{ 939 struct each_breakpoint_data *data = d; 940 if (data->end != NULL) 941 return; 942 if (data->start == key) 943 data->start = NULL; 944 945 if (data->start == NULL) { 946 switch (data->cb(data->proc, value, data->cb_data)) { 947 case CBS_FAIL: 948 /* XXX handle me */ 949 case CBS_STOP: 950 data->end = key; 951 case CBS_CONT: 952 return; 953 } 954 } 955} 956 957void * 958proc_each_breakpoint(struct Process *proc, void *start, 959 enum callback_status (*cb)(struct Process *proc, 960 struct breakpoint *bp, 961 void *data), void *data) 962{ 963 struct each_breakpoint_data dd = { 964 .start = start, 965 .proc = proc, 966 .cb = cb, 967 .cb_data = data, 968 }; 969 dict_apply_to_all(proc->breakpoints, &each_breakpoint_cb, &dd); 970 return dd.end; 971} 972 973int 974proc_find_symbol(struct Process *proc, struct library_symbol *sym, 975 struct library **retlib, struct library_symbol **retsym) 976{ 977 struct library *lib = sym->lib; 978 assert(lib != NULL); 979 980 struct library *flib 981 = proc_each_library(proc, NULL, library_with_key_cb, &lib->key); 982 if (flib == NULL) 983 return -1; 984 985 struct library_symbol *fsym 986 = library_each_symbol(flib, NULL, library_symbol_named_cb, 987 (char *)sym->name); 988 if (fsym == NULL) 989 return -1; 990 991 if (retlib != NULL) 992 *retlib = flib; 993 if (retsym != NULL) 994 *retsym = fsym; 995 996 return 0; 997} 998