blob: 170c37d7d8db0780fa0812826134d4a25045b188 [file] [log] [blame]
Juan Cespedes5e01f651998-03-08 22:31:44 +01001#define _GNU_SOURCE
2#include <stdio.h>
3#include <string.h>
Juan Cespedes1fe93d51998-03-13 00:29:21 +01004#include <stdlib.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +01005
6#include "ltrace.h"
7#include "output.h"
8#include "options.h"
9
10static void process_signal(struct event * event);
11static void process_exit(struct event * event);
12static void process_exit_signal(struct event * event);
13static void process_syscall(struct event * event);
14static void process_sysret(struct event * event);
15static void process_breakpoint(struct event * event);
16
17void process_event(struct event * event)
18{
19 switch (event->thing) {
20 case LT_EV_NONE:
21 return;
22 case LT_EV_SIGNAL:
Juan Cespedesf0fdae91998-03-11 00:03:00 +010023 if (opt_d>0) {
24 output_line(0, "event: signal (%d)", event->e_un.signum);
25 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010026 process_signal(event);
27 return;
28 case LT_EV_EXIT:
Juan Cespedesf0fdae91998-03-11 00:03:00 +010029 if (opt_d>0) {
30 output_line(0, "event: exit (%d)", event->e_un.ret_val);
31 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010032 process_exit(event);
33 return;
34 case LT_EV_EXIT_SIGNAL:
Juan Cespedesf0fdae91998-03-11 00:03:00 +010035 if (opt_d>0) {
36 output_line(0, "event: exit signal (%d)", event->e_un.signum);
37 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010038 process_exit_signal(event);
39 return;
40 case LT_EV_SYSCALL:
Juan Cespedesf0fdae91998-03-11 00:03:00 +010041 if (opt_d>0) {
42 output_line(0, "event: syscall (%d)", event->e_un.sysnum);
43 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010044 process_syscall(event);
45 return;
46 case LT_EV_SYSRET:
Juan Cespedesf0fdae91998-03-11 00:03:00 +010047 if (opt_d>0) {
48 output_line(0, "event: sysret (%d)", event->e_un.sysnum);
49 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010050 process_sysret(event);
51 return;
52 case LT_EV_BREAKPOINT:
53 process_breakpoint(event);
54 return;
55 default:
56 fprintf(stderr, "Error! unknown event?\n");
57 exit(1);
58 }
59}
60
61static char * shortsignal(int signum)
62{
63 static char * signalent0[] = {
64 #include "signalent.h"
65 };
66 int nsignals0 = sizeof signalent0 / sizeof signalent0[0];
67
68 if (signum<0 || signum>nsignals0) {
69 return "UNKNOWN_SIGNAL";
70 } else {
71 return signalent0[signum];
72 }
73}
74
75static char * sysname(int sysnum)
76{
77 static char result[128];
78 static char * syscalent0[] = {
79 #include "syscallent.h"
80 };
81 int nsyscals0 = sizeof syscalent0 / sizeof syscalent0[0];
82
83 if (sysnum<0 || sysnum>nsyscals0) {
84 sprintf(result, "SYS_%d", sysnum);
85 return result;
86 } else {
87 sprintf(result, "SYS_%s", syscalent0[sysnum]);
88 return result;
89 }
90}
91
92static void process_signal(struct event * event)
93{
94 output_line(event->proc, "--- %s (%s) ---",
95 shortsignal(event->e_un.signum), strsignal(event->e_un.signum));
96 continue_after_signal(event->proc->pid, event->e_un.signum);
97}
98
Juan Cespedes1fe93d51998-03-13 00:29:21 +010099static void remove_proc(struct process * proc);
100
Juan Cespedes5e01f651998-03-08 22:31:44 +0100101static void process_exit(struct event * event)
102{
103 output_line(event->proc, "+++ exited (status %d) +++",
104 event->e_un.ret_val);
Juan Cespedes1fe93d51998-03-13 00:29:21 +0100105 remove_proc(event->proc);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100106}
107
108static void process_exit_signal(struct event * event)
109{
110 output_line(event->proc, "+++ killed by %s +++",
111 shortsignal(event->e_un.signum));
Juan Cespedes1fe93d51998-03-13 00:29:21 +0100112 remove_proc(event->proc);
113}
114
115static void remove_proc(struct process * proc)
116{
117 struct process *tmp, *tmp2;
118
119 if (list_of_processes == proc) {
120 tmp = list_of_processes;
121 list_of_processes = list_of_processes->next;
122 free(tmp);
123 return;
124 }
125 tmp = list_of_processes;
126 while(tmp->next) {
127 if (tmp->next==proc) {
128 tmp2 = tmp->next;
129 tmp->next = tmp->next->next;
130 free(tmp2);
131 }
132 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100133}
134
135static void process_syscall(struct event * event)
136{
137 event->proc->current_syscall = event->e_un.sysnum;
138 if (opt_S) {
139 output_left(LT_TOF_SYSCALL, event->proc, sysname(event->e_un.sysnum));
140 }
141 if (child_p(event->e_un.sysnum)) {
142 disable_all_breakpoints(event->proc);
143 if (event->proc->current_symbol) {
144 delete_breakpoint(event->proc->pid, &event->proc->return_value);
145 }
146 }
147 continue_process(event->proc->pid);
148}
149
150static void process_sysret(struct event * event)
151{
152 if (opt_S) {
153 output_right(LT_TOF_SYSCALL, event->proc, sysname(event->e_un.sysnum));
154 }
155 if (child_p(event->e_un.sysnum)) {
156 enable_all_breakpoints(event->proc);
157 if (event->proc->current_symbol) {
158 insert_breakpoint(event->proc->pid, &event->proc->return_value);
159 }
160 if (opt_f) {
161 fprintf(stderr, "ERROR: Option `-f' doesn't work yet\n");
162 exit(1);
163 }
164 }
165 event->proc->current_syscall = -1;
166 continue_process(event->proc->pid);
167}
168
169static void process_breakpoint(struct event * event)
170{
171 struct library_symbol * tmp;
172
Juan Cespedesf0fdae91998-03-11 00:03:00 +0100173 if (opt_d>1) {
174 output_line(0,"event: breakpoint (0x%08x)", event->e_un.brk_addr);
175 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100176 if (event->proc->breakpoint_being_enabled) {
177 continue_enabling_breakpoint(event->proc->pid, event->proc->breakpoint_being_enabled);
178 event->proc->breakpoint_being_enabled = NULL;
179 return;
180 }
181 if (event->proc->current_symbol && event->e_un.brk_addr == event->proc->return_value.addr) {
182 output_right(LT_TOF_FUNCTION, event->proc, event->proc->current_symbol->name);
183 continue_after_breakpoint(event->proc, &event->proc->return_value, 1);
184 event->proc->current_symbol = NULL;
185 return;
186 }
187
188 tmp = event->proc->list_of_symbols;
189 while(tmp) {
190 if (event->e_un.brk_addr == tmp->brk.addr) {
191 if (event->proc->current_symbol) {
192 delete_breakpoint(event->proc->pid, &event->proc->return_value);
193 }
194 event->proc->current_symbol = tmp;
195 event->proc->stack_pointer = get_stack_pointer(event->proc->pid);
196 event->proc->return_addr = get_return_addr(event->proc->pid, event->proc->stack_pointer);
197 output_left(LT_TOF_FUNCTION, event->proc, tmp->name);
198 event->proc->return_value.addr = event->proc->return_addr;
199 insert_breakpoint(event->proc->pid, &event->proc->return_value);
200 continue_after_breakpoint(event->proc, &tmp->brk, 0);
201 return;
202 }
203 tmp = tmp->next;
204 }
205 output_line(event->proc, "breakpointed at 0x%08x (?)",
206 (unsigned)event->e_un.brk_addr);
207 continue_process(event->proc->pid);
208}