events.c revision e2023f721b66db48cc8a0f4ab6519460093c2cf1
1#if HAVE_CONFIG_H 2#include "config.h" 3#endif 4 5#define _GNU_SOURCE 1 6#include <stdlib.h> 7#include <sys/types.h> 8#include <sys/wait.h> 9#include <errno.h> 10#include <signal.h> 11#include <string.h> 12 13#include "ltrace.h" 14#include "options.h" 15#include "debug.h" 16 17static struct event event; 18 19struct event * 20next_event(void) { 21 pid_t pid; 22 int status; 23 int tmp; 24 int stop_signal; 25 26 if (!list_of_processes) { 27 debug(1, "No more children"); 28 exit(0); 29 } 30 pid = wait(&status); 31 if (pid == -1) { 32 if (errno == ECHILD) { 33 debug(1, "No more children"); 34 exit(0); 35 } else if (errno == EINTR) { 36 debug(1, "wait received EINTR ?"); 37 event.thing = EVENT_NONE; 38 return &event; 39 } 40 perror("wait"); 41 exit(1); 42 } 43 event.proc = pid2proc(pid); 44 if (!event.proc) { 45 fprintf(stderr, "signal from wrong pid %u ?!?\n", pid); 46 exit(1); 47 } 48 get_arch_dep(event.proc); 49 event.proc->instruction_pointer = NULL; 50 debug(3, "signal from pid %u", pid); 51 if (event.proc->breakpoints_enabled == -1) { 52 enable_all_breakpoints(event.proc); 53 event.thing = EVENT_NONE; 54 trace_set_options(event.proc, event.proc->pid); 55 continue_process(event.proc->pid); 56 return &event; 57 } 58 if (opt_i) { 59 event.proc->instruction_pointer = 60 get_instruction_pointer(event.proc); 61 } 62 switch (syscall_p(event.proc, status, &tmp)) { 63 case 1: 64 event.thing = EVENT_SYSCALL; 65 event.e_un.sysnum = tmp; 66 return &event; 67 case 2: 68 event.thing = EVENT_SYSRET; 69 event.e_un.sysnum = tmp; 70 return &event; 71 case 3: 72 event.thing = EVENT_ARCH_SYSCALL; 73 event.e_un.sysnum = tmp; 74 return &event; 75 case 4: 76 event.thing = EVENT_ARCH_SYSRET; 77 event.e_un.sysnum = tmp; 78 return &event; 79 case -1: 80 event.thing = EVENT_NONE; 81 continue_process(event.proc->pid); 82 return &event; 83 } 84 if (WIFEXITED(status)) { 85 event.thing = EVENT_EXIT; 86 event.e_un.ret_val = WEXITSTATUS(status); 87 return &event; 88 } 89 if (WIFSIGNALED(status)) { 90 event.thing = EVENT_EXIT_SIGNAL; 91 event.e_un.signum = WTERMSIG(status); 92 return &event; 93 } 94 if (!WIFSTOPPED(status)) { 95 event.thing = EVENT_NONE; 96 return &event; 97 } 98 99 stop_signal = WSTOPSIG(status); 100 101 /* On some targets, breakpoints are signalled not using 102 SIGTRAP, but also with SIGILL, SIGSEGV or SIGEMT. Check 103 for these. */ 104 if (stop_signal == SIGSEGV 105 || stop_signal == SIGILL 106#ifdef SIGEMT 107 || stop_signal == SIGEMT 108#endif 109 ) { 110 // If we didn't need to know IP so far, get it now. 111 void * addr = opt_i 112 ? event.proc->instruction_pointer 113 : (event.proc->instruction_pointer = get_instruction_pointer (event.proc)); 114 115 if (address2bpstruct(event.proc, addr)) 116 stop_signal = SIGTRAP; 117 } 118 119 if (stop_signal != (SIGTRAP | event.proc->tracesysgood) 120 && stop_signal != SIGTRAP) { 121 event.thing = EVENT_SIGNAL; 122 event.e_un.signum = stop_signal; 123 return &event; 124 } 125 126 if (was_exec(event.proc, status)) { 127 pid_t saved_pid; 128 129 event.thing = EVENT_NONE; 130 event.e_un.signum = WSTOPSIG(status); 131 debug(1, "Placing breakpoints for the new program"); 132 event.proc->mask_32bit = 0; 133 event.proc->personality = 0; 134 event.proc->arch_ptr = NULL; 135 event.proc->filename = pid2name(event.proc->pid); 136 saved_pid = event.proc->pid; 137 event.proc->pid = 0; 138 breakpoints_init(event.proc); 139 event.proc->pid = saved_pid; 140 continue_process(event.proc->pid); 141 return &event; 142 } 143 144 event.thing = EVENT_BREAKPOINT; 145 if (!event.proc->instruction_pointer) { 146 event.proc->instruction_pointer = 147 get_instruction_pointer(event.proc); 148 } 149 event.e_un.brk_addr = 150 event.proc->instruction_pointer - DECR_PC_AFTER_BREAK; 151 return &event; 152} 153