trace.c revision 4b9f4d956e125360d4860d6a8d7574a271c799a0
1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4#include <errno.h> 5#include <unistd.h> 6#include <sys/types.h> 7#include <sys/wait.h> 8#include "ptrace.h" 9#include <asm/unistd.h> 10#include <assert.h> 11 12#include "common.h" 13 14/* If the system headers did not provide the constants, hard-code the normal 15 values. */ 16#ifndef PTRACE_EVENT_FORK 17 18#define PTRACE_OLDSETOPTIONS 21 19#define PTRACE_SETOPTIONS 0x4200 20#define PTRACE_GETEVENTMSG 0x4201 21 22/* options set using PTRACE_SETOPTIONS */ 23#define PTRACE_O_TRACESYSGOOD 0x00000001 24#define PTRACE_O_TRACEFORK 0x00000002 25#define PTRACE_O_TRACEVFORK 0x00000004 26#define PTRACE_O_TRACECLONE 0x00000008 27#define PTRACE_O_TRACEEXEC 0x00000010 28#define PTRACE_O_TRACEVFORKDONE 0x00000020 29#define PTRACE_O_TRACEEXIT 0x00000040 30 31/* Wait extended result codes for the above trace options. */ 32#define PTRACE_EVENT_FORK 1 33#define PTRACE_EVENT_VFORK 2 34#define PTRACE_EVENT_CLONE 3 35#define PTRACE_EVENT_EXEC 4 36#define PTRACE_EVENT_VFORK_DONE 5 37#define PTRACE_EVENT_EXIT 6 38 39#endif /* PTRACE_EVENT_FORK */ 40 41#ifdef ARCH_HAVE_UMOVELONG 42extern int arch_umovelong (Process *, void *, long *, arg_type_info *); 43int 44umovelong (Process *proc, void *addr, long *result, arg_type_info *info) { 45 return arch_umovelong (proc, addr, result, info); 46} 47#else 48/* Read a single long from the process's memory address 'addr' */ 49int 50umovelong (Process *proc, void *addr, long *result, arg_type_info *info) { 51 long pointed_to; 52 53 errno = 0; 54 pointed_to = ptrace (PTRACE_PEEKTEXT, proc->pid, addr, 0); 55 if (pointed_to == -1 && errno) 56 return -errno; 57 58 *result = pointed_to; 59 if (info) { 60 switch(info->type) { 61 case ARGTYPE_INT: 62 *result &= 0x00000000ffffffffUL; 63 default: 64 break; 65 }; 66 } 67 return 0; 68} 69#endif 70 71void 72trace_me(void) { 73 debug(DEBUG_PROCESS, "trace_me: pid=%d", getpid()); 74 if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) { 75 perror("PTRACE_TRACEME"); 76 exit(1); 77 } 78} 79 80int 81trace_pid(pid_t pid) { 82 debug(DEBUG_PROCESS, "trace_pid: pid=%d", pid); 83 if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) { 84 return -1; 85 } 86 87 /* man ptrace: PTRACE_ATTACH attaches to the process specified 88 in pid. The child is sent a SIGSTOP, but will not 89 necessarily have stopped by the completion of this call; 90 use wait() to wait for the child to stop. */ 91 if (waitpid (pid, NULL, __WALL) != pid) { 92 perror ("trace_pid: waitpid"); 93 return -1; 94 } 95 96 return 0; 97} 98 99void 100trace_set_options(Process *proc, pid_t pid) { 101 if (proc->tracesysgood & 0x80) 102 return; 103 104 debug(DEBUG_PROCESS, "trace_set_options: pid=%d", pid); 105 106 long options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK | 107 PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE | 108 PTRACE_O_TRACEEXEC; 109 if (ptrace(PTRACE_SETOPTIONS, pid, 0, options) < 0 && 110 ptrace(PTRACE_OLDSETOPTIONS, pid, 0, options) < 0) { 111 perror("PTRACE_SETOPTIONS"); 112 return; 113 } 114 proc->tracesysgood |= 0x80; 115} 116 117void 118untrace_pid(pid_t pid) { 119 debug(DEBUG_PROCESS, "untrace_pid: pid=%d", pid); 120 ptrace(PTRACE_DETACH, pid, 1, 0); 121} 122 123void 124continue_after_signal(pid_t pid, int signum) { 125 Process *proc; 126 127 debug(DEBUG_PROCESS, "continue_after_signal: pid=%d, signum=%d", pid, signum); 128 129 proc = pid2proc(pid); 130 ptrace(PTRACE_SYSCALL, pid, 0, signum); 131} 132 133static enum ecb_status 134event_for_pid(Event * event, void * data) 135{ 136 if (event->proc != NULL && event->proc->pid == (pid_t)(uintptr_t)data) 137 return ecb_yield; 138 return ecb_cont; 139} 140 141static int 142have_events_for(pid_t pid) 143{ 144 return each_qd_event(event_for_pid, (void *)(uintptr_t)pid) != NULL; 145} 146 147void 148continue_process(pid_t pid) 149{ 150 debug(DEBUG_PROCESS, "continue_process: pid=%d", pid); 151 152 /* Only really continue the process if there are no events in 153 the queue for this process. Otherwise just for the other 154 events to arrive. */ 155 if (!have_events_for(pid)) 156 /* We always trace syscalls to control fork(), 157 * clone(), execve()... */ 158 ptrace(PTRACE_SYSCALL, pid, 0, 0); 159 else 160 debug(DEBUG_PROCESS, 161 "putting off the continue, events in que."); 162} 163 164/** 165 * This is used for bookkeeping related to PIDs that the event 166 * handlers work with. 167 */ 168struct pid_task { 169 pid_t pid; /* This may be 0 for tasks that exited 170 * mid-handling. */ 171 int sigstopped; 172 int got_event; 173 int delivered; 174} * pids; 175 176struct pid_set { 177 struct pid_task * tasks; 178 size_t count; 179 size_t alloc; 180}; 181 182/** 183 * Breakpoint re-enablement. When we hit a breakpoint, we must 184 * disable it, single-step, and re-enable it. That single-step can be 185 * done only by one task in a task group, while others are stopped, 186 * otherwise the processes would race for who sees the breakpoint 187 * disabled and who doesn't. The following is to keep track of it 188 * all. 189 */ 190struct process_stopping_handler 191{ 192 Event_Handler super; 193 194 /* The task that is doing the re-enablement. */ 195 Process * task_enabling_breakpoint; 196 197 /* The pointer being re-enabled. */ 198 Breakpoint * breakpoint_being_enabled; 199 200 enum { 201 /* We are waiting for everyone to land in t/T. */ 202 psh_stopping = 0, 203 204 /* We are doing the PTRACE_SINGLESTEP. */ 205 psh_singlestep, 206 207 /* We are waiting for all the SIGSTOPs to arrive so 208 * that we can sink them. */ 209 psh_sinking, 210 } state; 211 212 struct pid_set pids; 213}; 214 215static enum pcb_status 216task_stopped(Process * task, void * data) 217{ 218 /* If the task is already stopped, don't worry about it. 219 * Likewise if it managed to become a zombie or terminate in 220 * the meantime. This can happen when the whole thread group 221 * is terminating. */ 222 switch (process_status(task->pid)) { 223 case ps_invalid: 224 case ps_tracing_stop: 225 case ps_zombie: 226 return pcb_cont; 227 default: 228 return pcb_stop; 229 } 230} 231 232static struct pid_task * 233get_task_info(struct pid_set * pids, pid_t pid) 234{ 235 assert(pid != 0); 236 size_t i; 237 for (i = 0; i < pids->count; ++i) 238 if (pids->tasks[i].pid == pid) 239 return &pids->tasks[i]; 240 241 return NULL; 242} 243 244static struct pid_task * 245add_task_info(struct pid_set * pids, pid_t pid) 246{ 247 if (pids->count == pids->alloc) { 248 size_t ns = (2 * pids->alloc) ?: 4; 249 struct pid_task * n = realloc(pids->tasks, 250 sizeof(*pids->tasks) * ns); 251 if (n == NULL) 252 return NULL; 253 pids->tasks = n; 254 pids->alloc = ns; 255 } 256 struct pid_task * task_info = &pids->tasks[pids->count++]; 257 memset(task_info, 0, sizeof(*task_info)); 258 task_info->pid = pid; 259 return task_info; 260} 261 262static enum pcb_status 263send_sigstop(Process * task, void * data) 264{ 265 Process * leader = task->leader; 266 struct pid_set * pids = data; 267 268 /* Look for pre-existing task record, or add new. */ 269 struct pid_task * task_info = get_task_info(pids, task->pid); 270 if (task_info == NULL) 271 task_info = add_task_info(pids, task->pid); 272 if (task_info == NULL) { 273 perror("send_sigstop: add_task_info"); 274 destroy_event_handler(leader); 275 /* Signal failure upwards. */ 276 return pcb_stop; 277 } 278 279 /* This task still has not been attached to. It should be 280 stopped by the kernel. */ 281 if (task->state == STATE_BEING_CREATED) 282 return pcb_cont; 283 284 /* Don't bother sending SIGSTOP if we are already stopped, or 285 * if we sent the SIGSTOP already, which happens when we 286 * inherit the handler from breakpoint re-enablement. */ 287 if (task_stopped(task, NULL) == pcb_cont) 288 return pcb_cont; 289 if (task_info->sigstopped) { 290 if (!task_info->delivered) 291 return pcb_cont; 292 task_info->delivered = 0; 293 } 294 295 if (task_kill(task->pid, SIGSTOP) >= 0) { 296 debug(DEBUG_PROCESS, "send SIGSTOP to %d", task->pid); 297 task_info->sigstopped = 1; 298 } else 299 fprintf(stderr, 300 "Warning: couldn't send SIGSTOP to %d\n", task->pid); 301 302 return pcb_cont; 303} 304 305static void 306process_stopping_done(struct process_stopping_handler * self, Process * leader) 307{ 308 debug(DEBUG_PROCESS, "process stopping done %d", 309 self->task_enabling_breakpoint->pid); 310 size_t i; 311 for (i = 0; i < self->pids.count; ++i) 312 if (self->pids.tasks[i].pid != 0 313 && self->pids.tasks[i].delivered) 314 continue_process(self->pids.tasks[i].pid); 315 continue_process(self->task_enabling_breakpoint->pid); 316 destroy_event_handler(leader); 317} 318 319static void 320handle_stopping_event(struct pid_task * task_info, Event ** eventp) 321{ 322 /* Mark all events, so that we know whom to SIGCONT later. */ 323 if (task_info != NULL && task_info->sigstopped) 324 task_info->got_event = 1; 325 326 Event * event = *eventp; 327 328 /* In every state, sink SIGSTOP events for tasks that it was 329 * sent to. */ 330 if (task_info != NULL 331 && event->type == EVENT_SIGNAL 332 && event->e_un.signum == SIGSTOP) { 333 debug(DEBUG_PROCESS, "SIGSTOP delivered to %d", task_info->pid); 334 if (task_info->sigstopped 335 && !task_info->delivered) { 336 task_info->delivered = 1; 337 *eventp = NULL; // sink the event 338 } else 339 fprintf(stderr, "suspicious: %d got SIGSTOP, but " 340 "sigstopped=%d and delivered=%d\n", 341 task_info->pid, task_info->sigstopped, 342 task_info->delivered); 343 } 344} 345 346/* Some SIGSTOPs may have not been delivered to their respective tasks 347 * yet. They are still in the queue. If we have seen an event for 348 * that process, continue it, so that the SIGSTOP can be delivered and 349 * caught by ltrace. */ 350static void 351continue_for_sigstop_delivery(struct pid_set * pids) 352{ 353 size_t i; 354 for (i = 0; i < pids->count; ++i) { 355 if (pids->tasks[i].pid != 0 356 && pids->tasks[i].sigstopped 357 && !pids->tasks[i].delivered 358 && pids->tasks[i].got_event) { 359 debug(DEBUG_PROCESS, "continue %d for SIGSTOP delivery", 360 pids->tasks[i].pid); 361 ptrace(PTRACE_SYSCALL, pids->tasks[i].pid, 0, 0); 362 } 363 } 364} 365 366static int 367event_exit_p(Event * event) 368{ 369 return event != NULL && (event->type == EVENT_EXIT 370 || event->type == EVENT_EXIT_SIGNAL); 371} 372 373static int 374event_exit_or_none_p(Event * event) 375{ 376 return event == NULL || event_exit_p(event) 377 || event->type == EVENT_NONE; 378} 379 380static int 381await_sigstop_delivery(struct pid_set * pids, struct pid_task * task_info, 382 Event * event) 383{ 384 /* If we still didn't get our SIGSTOP, continue the process 385 * and carry on. */ 386 if (event != NULL && !event_exit_or_none_p(event) 387 && task_info != NULL && task_info->sigstopped) { 388 debug(DEBUG_PROCESS, "continue %d for SIGSTOP delivery", 389 task_info->pid); 390 /* We should get the signal the first thing 391 * after this, so it should be OK to continue 392 * even if we are over a breakpoint. */ 393 ptrace(PTRACE_SYSCALL, task_info->pid, 0, 0); 394 395 } else { 396 /* If all SIGSTOPs were delivered, uninstall the 397 * handler and continue everyone. */ 398 /* XXX I suspect that we should check tasks that are 399 * still around. Is things are now, there should be a 400 * race between waiting for everyone to stop and one 401 * of the tasks exiting. */ 402 int all_clear = 1; 403 size_t i; 404 for (i = 0; i < pids->count; ++i) 405 if (pids->tasks[i].pid != 0 406 && pids->tasks[i].sigstopped 407 && !pids->tasks[i].delivered) { 408 all_clear = 0; 409 break; 410 } 411 return all_clear; 412 } 413 414 return 0; 415} 416 417/* This event handler is installed when we are in the process of 418 * stopping the whole thread group to do the pointer re-enablement for 419 * one of the threads. We pump all events to the queue for later 420 * processing while we wait for all the threads to stop. When this 421 * happens, we let the re-enablement thread to PTRACE_SINGLESTEP, 422 * re-enable, and continue everyone. */ 423static Event * 424process_stopping_on_event(Event_Handler * super, Event * event) 425{ 426 struct process_stopping_handler * self = (void *)super; 427 Process * task = event->proc; 428 Process * leader = task->leader; 429 Breakpoint * sbp = self->breakpoint_being_enabled; 430 Process * teb = self->task_enabling_breakpoint; 431 432 debug(DEBUG_PROCESS, 433 "pid %d; event type %d; state %d", 434 task->pid, event->type, self->state); 435 436 struct pid_task * task_info = get_task_info(&self->pids, task->pid); 437 if (task_info == NULL) 438 fprintf(stderr, "new task??? %d\n", task->pid); 439 handle_stopping_event(task_info, &event); 440 441 int state = self->state; 442 int event_to_queue = !event_exit_or_none_p(event); 443 444 /* Deactivate the entry if the task exits. */ 445 if (event_exit_p(event) && task_info != NULL) 446 task_info->pid = 0; 447 448 switch (state) { 449 case psh_stopping: 450 /* If everyone is stopped, singlestep. */ 451 if (each_task(leader, &task_stopped, NULL) == NULL) { 452 debug(DEBUG_PROCESS, "all stopped, now SINGLESTEP %d", 453 teb->pid); 454 if (sbp->enabled) 455 disable_breakpoint(teb, sbp); 456 if (ptrace(PTRACE_SINGLESTEP, teb->pid, 0, 0)) 457 perror("PTRACE_SINGLESTEP"); 458 self->state = state = psh_singlestep; 459 } 460 break; 461 462 case psh_singlestep: { 463 /* In singlestep state, breakpoint signifies that we 464 * have now stepped, and can re-enable the breakpoint. */ 465 if (event != NULL && task == teb) { 466 /* Essentially we don't care what event caused 467 * the thread to stop. We can do the 468 * re-enablement now. */ 469 enable_breakpoint(teb, sbp); 470 471 continue_for_sigstop_delivery(&self->pids); 472 473 self->breakpoint_being_enabled = NULL; 474 self->state = state = psh_sinking; 475 476 if (event->type == EVENT_BREAKPOINT) 477 event = NULL; // handled 478 } else 479 break; 480 } 481 482 /* fall-through */ 483 484 case psh_sinking: 485 if (await_sigstop_delivery(&self->pids, task_info, event)) 486 process_stopping_done(self, leader); 487 } 488 489 if (event != NULL && event_to_queue) { 490 enque_event(event); 491 event = NULL; // sink the event 492 } 493 494 return event; 495} 496 497static void 498process_stopping_destroy(Event_Handler * super) 499{ 500 struct process_stopping_handler * self = (void *)super; 501 if (self->breakpoint_being_enabled != NULL) 502 enable_breakpoint(self->task_enabling_breakpoint, 503 self->breakpoint_being_enabled); 504 free(self->pids.tasks); 505} 506 507void 508continue_after_breakpoint(Process *proc, Breakpoint *sbp) 509{ 510 set_instruction_pointer(proc, sbp->addr); 511 if (sbp->enabled == 0) { 512 if (sbp->enabled) 513 disable_breakpoint(proc, sbp); 514 continue_process(proc->pid); 515 } else { 516 debug(DEBUG_PROCESS, 517 "continue_after_breakpoint: pid=%d, addr=%p", 518 proc->pid, sbp->addr); 519#if defined __sparc__ || defined __ia64___ || defined __mips__ 520 /* we don't want to singlestep here */ 521 continue_process(proc->pid); 522#else 523 struct process_stopping_handler * handler 524 = calloc(sizeof(*handler), 1); 525 if (handler == NULL) { 526 perror("malloc breakpoint disable handler"); 527 fatal: 528 /* Carry on not bothering to re-enable. */ 529 continue_process(proc->pid); 530 return; 531 } 532 533 handler->super.on_event = process_stopping_on_event; 534 handler->super.destroy = process_stopping_destroy; 535 handler->task_enabling_breakpoint = proc; 536 handler->breakpoint_being_enabled = sbp; 537 install_event_handler(proc->leader, &handler->super); 538 539 if (each_task(proc->leader, &send_sigstop, 540 &handler->pids) != NULL) 541 goto fatal; 542 543 /* And deliver the first fake event, in case all the 544 * conditions are already fulfilled. */ 545 Event ev; 546 ev.type = EVENT_NONE; 547 ev.proc = proc; 548 process_stopping_on_event(&handler->super, &ev); 549#endif 550 } 551} 552 553/** 554 * Ltrace exit. When we are about to exit, we have to go through all 555 * the processes, stop them all, remove all the breakpoints, and then 556 * detach the processes that we attached to using -p. If we left the 557 * other tasks running, they might hit stray return breakpoints and 558 * produce artifacts, so we better stop everyone, even if it's a bit 559 * of extra work. 560 */ 561struct ltrace_exiting_handler 562{ 563 Event_Handler super; 564 struct pid_set pids; 565 int state; 566 Process * task_enabling_breakpoint; 567}; 568 569static enum pcb_status 570remove_task(Process * task, void * data) 571{ 572 /* Don't untrace leader just yet. */ 573 if (task != data) 574 remove_process(task); 575 return pcb_cont; 576} 577 578static enum pcb_status 579untrace_task(Process * task, void * data) 580{ 581 untrace_pid(task->pid); 582 return pcb_cont; 583} 584 585/* Before we detach, we need to make sure that task's IP is on the 586 * edge of an instruction. So for tasks that have a breakpoint event 587 * in the queue, we adjust the instruction pointer, just like 588 * continue_after_breakpoint does. */ 589static enum ecb_status 590undo_breakpoint(Event * event, void * data) 591{ 592 if (event != NULL 593 && event->proc->leader == data 594 && event->type == EVENT_BREAKPOINT) { 595 fprintf(stderr, " + %p ", get_instruction_pointer(event->proc)); 596 set_instruction_pointer(event->proc, event->e_un.brk_addr); 597 fprintf(stderr, "-> %p\n", get_instruction_pointer(event->proc)); 598 } 599 return ecb_cont; 600} 601 602static Event * 603ltrace_exiting_on_event(Event_Handler * super, Event * event) 604{ 605 struct ltrace_exiting_handler * self = (void *)super; 606 Process * task = event->proc; 607 Process * leader = task->leader; 608 609 debug(DEBUG_PROCESS, "pid %d; event type %d", task->pid, event->type); 610 611 struct pid_task * task_info = get_task_info(&self->pids, task->pid); 612 handle_stopping_event(task_info, &event); 613 614 if (event != NULL && event->type == EVENT_BREAKPOINT) { 615 if (self->state == psh_singlestep 616 && self->task_enabling_breakpoint == event->proc) { 617 self->task_enabling_breakpoint = NULL; 618 self->state = 0; 619 } else 620 undo_breakpoint(event, leader); 621 } 622 623 if (await_sigstop_delivery(&self->pids, task_info, event) 624 && (self->task_enabling_breakpoint == NULL 625 || self->state != psh_singlestep)) { 626 debug(DEBUG_PROCESS, "all SIGSTOPs delivered %d", leader->pid); 627 each_qd_event(&undo_breakpoint, leader); 628 disable_all_breakpoints(leader); 629 630 /* Now untrace the process, if it was attached to by -p. */ 631 struct opt_p_t * it; 632 for (it = opt_p; it != NULL; it = it->next) { 633 Process * proc = pid2proc(it->pid); 634 if (proc == NULL) 635 continue; 636 if (proc->leader == leader) { 637 each_task(leader, &untrace_task, NULL); 638 break; 639 } 640 } 641 642 each_task(leader, &remove_task, leader); 643 destroy_event_handler(leader); 644 remove_task(leader, NULL); 645 return NULL; 646 } 647 648 /* Sink all non-exit events. We are about to exit, so we 649 * don't bother with queuing them. */ 650 if (event_exit_or_none_p(event)) 651 return event; 652 653 return NULL; 654} 655 656static void 657ltrace_exiting_destroy(Event_Handler * super) 658{ 659 struct ltrace_exiting_handler * self = (void *)super; 660 free(self->pids.tasks); 661} 662 663static int 664ltrace_exiting_install_handler(Process * proc) 665{ 666 /* Only install to leader. */ 667 if (proc->leader != proc) 668 return 0; 669 670 /* Perhaps we are already installed, if the user passed 671 * several -p options that are tasks of one process. */ 672 if (proc->event_handler != NULL 673 && proc->event_handler->on_event == <race_exiting_on_event) 674 return 0; 675 676 struct ltrace_exiting_handler * handler 677 = calloc(sizeof(*handler), 1); 678 if (handler == NULL) { 679 perror("malloc exiting handler"); 680 fatal: 681 /* XXXXXXXXXXXXXXXXXXX fixme */ 682 return -1; 683 } 684 685 /* If we are in the middle of breakpoint, extract the 686 * pid-state information from that handler so that we can take 687 * over the SIGSTOP handling. */ 688 if (proc->event_handler != NULL) { 689 debug(DEBUG_PROCESS, "taking over breakpoint handling"); 690 assert(proc->event_handler->on_event 691 == &process_stopping_on_event); 692 struct process_stopping_handler * other 693 = (void *)proc->event_handler; 694 695 handler->state = other->state; 696 handler->task_enabling_breakpoint 697 = other->task_enabling_breakpoint; 698 699 size_t i; 700 for (i = 0; i < other->pids.count; ++i) { 701 struct pid_task * oti = &other->pids.tasks[i]; 702 if (oti->pid == 0) 703 continue; 704 705 struct pid_task * task_info 706 = add_task_info(&handler->pids, oti->pid); 707 if (task_info == NULL) { 708 perror("ltrace_exiting_install_handler" 709 ":add_task_info"); 710 goto fatal; 711 } 712 /* Copy over the state. */ 713 *task_info = *oti; 714 } 715 716 /* And destroy the original handler. */ 717 destroy_event_handler(proc); 718 } 719 720 handler->super.on_event = ltrace_exiting_on_event; 721 handler->super.destroy = ltrace_exiting_destroy; 722 install_event_handler(proc->leader, &handler->super); 723 724 if (each_task(proc->leader, &send_sigstop, 725 &handler->pids) != NULL) 726 goto fatal; 727 728 return 0; 729} 730 731/* If ltrace gets SIGINT, the processes directly or indirectly run by 732 * ltrace get it too. We just have to wait long enough for the signal 733 * to be delivered and the process terminated, which we notice and 734 * exit ltrace, too. So there's not much we need to do there. We 735 * want to keep tracing those processes as usual, in case they just 736 * SIG_IGN the SIGINT to do their shutdown etc. 737 * 738 * For processes ran on the background, we want to install an exit 739 * handler that stops all the threads, removes all breakpoints, and 740 * detaches. 741 */ 742void 743ltrace_exiting(void) 744{ 745 struct opt_p_t * it; 746 for (it = opt_p; it != NULL; it = it->next) { 747 Process * proc = pid2proc(it->pid); 748 if (proc == NULL || proc->leader == NULL) 749 continue; 750 if (ltrace_exiting_install_handler(proc->leader) < 0) 751 fprintf(stderr, 752 "Couldn't install exiting handler for %d.\n", 753 proc->pid); 754 } 755} 756 757size_t 758umovebytes(Process *proc, void *addr, void *laddr, size_t len) { 759 760 union { 761 long a; 762 char c[sizeof(long)]; 763 } a; 764 int started = 0; 765 size_t offset = 0, bytes_read = 0; 766 767 while (offset < len) { 768 a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr + offset, 0); 769 if (a.a == -1 && errno) { 770 if (started && errno == EIO) 771 return bytes_read; 772 else 773 return -1; 774 } 775 started = 1; 776 777 if (len - offset >= sizeof(long)) { 778 memcpy(laddr + offset, &a.c[0], sizeof(long)); 779 bytes_read += sizeof(long); 780 } 781 else { 782 memcpy(laddr + offset, &a.c[0], len - offset); 783 bytes_read += (len - offset); 784 } 785 offset += sizeof(long); 786 } 787 788 return bytes_read; 789} 790 791/* Read a series of bytes starting at the process's memory address 792 'addr' and continuing until a NUL ('\0') is seen or 'len' bytes 793 have been read. 794*/ 795int 796umovestr(Process *proc, void *addr, int len, void *laddr) { 797 union { 798 long a; 799 char c[sizeof(long)]; 800 } a; 801 unsigned i; 802 int offset = 0; 803 804 while (offset < len) { 805 a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr + offset, 0); 806 for (i = 0; i < sizeof(long); i++) { 807 if (a.c[i] && offset + (signed)i < len) { 808 *(char *)(laddr + offset + i) = a.c[i]; 809 } else { 810 *(char *)(laddr + offset + i) = '\0'; 811 return 0; 812 } 813 } 814 offset += sizeof(long); 815 } 816 *(char *)(laddr + offset) = '\0'; 817 return 0; 818} 819