blob: 0689a74464801ab5961a51f1f33e858c7cf9b1cc [file] [log] [blame]
Juan Cespedes5e01f651998-03-08 22:31:44 +01001#define _GNU_SOURCE
2#include <stdio.h>
3#include <string.h>
4
5#include "ltrace.h"
6#include "output.h"
7#include "options.h"
8
9static void process_signal(struct event * event);
10static void process_exit(struct event * event);
11static void process_exit_signal(struct event * event);
12static void process_syscall(struct event * event);
13static void process_sysret(struct event * event);
14static void process_breakpoint(struct event * event);
15
16void process_event(struct event * event)
17{
18 switch (event->thing) {
19 case LT_EV_NONE:
20 return;
21 case LT_EV_SIGNAL:
Juan Cespedesf0fdae91998-03-11 00:03:00 +010022 if (opt_d>0) {
23 output_line(0, "event: signal (%d)", event->e_un.signum);
24 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010025 process_signal(event);
26 return;
27 case LT_EV_EXIT:
Juan Cespedesf0fdae91998-03-11 00:03:00 +010028 if (opt_d>0) {
29 output_line(0, "event: exit (%d)", event->e_un.ret_val);
30 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010031 process_exit(event);
32 return;
33 case LT_EV_EXIT_SIGNAL:
Juan Cespedesf0fdae91998-03-11 00:03:00 +010034 if (opt_d>0) {
35 output_line(0, "event: exit signal (%d)", event->e_un.signum);
36 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010037 process_exit_signal(event);
38 return;
39 case LT_EV_SYSCALL:
Juan Cespedesf0fdae91998-03-11 00:03:00 +010040 if (opt_d>0) {
41 output_line(0, "event: syscall (%d)", event->e_un.sysnum);
42 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010043 process_syscall(event);
44 return;
45 case LT_EV_SYSRET:
Juan Cespedesf0fdae91998-03-11 00:03:00 +010046 if (opt_d>0) {
47 output_line(0, "event: sysret (%d)", event->e_un.sysnum);
48 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010049 process_sysret(event);
50 return;
51 case LT_EV_BREAKPOINT:
52 process_breakpoint(event);
53 return;
54 default:
55 fprintf(stderr, "Error! unknown event?\n");
56 exit(1);
57 }
58}
59
60static char * shortsignal(int signum)
61{
62 static char * signalent0[] = {
63 #include "signalent.h"
64 };
65 int nsignals0 = sizeof signalent0 / sizeof signalent0[0];
66
67 if (signum<0 || signum>nsignals0) {
68 return "UNKNOWN_SIGNAL";
69 } else {
70 return signalent0[signum];
71 }
72}
73
74static char * sysname(int sysnum)
75{
76 static char result[128];
77 static char * syscalent0[] = {
78 #include "syscallent.h"
79 };
80 int nsyscals0 = sizeof syscalent0 / sizeof syscalent0[0];
81
82 if (sysnum<0 || sysnum>nsyscals0) {
83 sprintf(result, "SYS_%d", sysnum);
84 return result;
85 } else {
86 sprintf(result, "SYS_%s", syscalent0[sysnum]);
87 return result;
88 }
89}
90
91static void process_signal(struct event * event)
92{
93 output_line(event->proc, "--- %s (%s) ---",
94 shortsignal(event->e_un.signum), strsignal(event->e_un.signum));
95 continue_after_signal(event->proc->pid, event->e_un.signum);
96}
97
98static void process_exit(struct event * event)
99{
100 output_line(event->proc, "+++ exited (status %d) +++",
101 event->e_un.ret_val);
102}
103
104static void process_exit_signal(struct event * event)
105{
106 output_line(event->proc, "+++ killed by %s +++",
107 shortsignal(event->e_un.signum));
108}
109
110static void process_syscall(struct event * event)
111{
112 event->proc->current_syscall = event->e_un.sysnum;
113 if (opt_S) {
114 output_left(LT_TOF_SYSCALL, event->proc, sysname(event->e_un.sysnum));
115 }
116 if (child_p(event->e_un.sysnum)) {
117 disable_all_breakpoints(event->proc);
118 if (event->proc->current_symbol) {
119 delete_breakpoint(event->proc->pid, &event->proc->return_value);
120 }
121 }
122 continue_process(event->proc->pid);
123}
124
125static void process_sysret(struct event * event)
126{
127 if (opt_S) {
128 output_right(LT_TOF_SYSCALL, event->proc, sysname(event->e_un.sysnum));
129 }
130 if (child_p(event->e_un.sysnum)) {
131 enable_all_breakpoints(event->proc);
132 if (event->proc->current_symbol) {
133 insert_breakpoint(event->proc->pid, &event->proc->return_value);
134 }
135 if (opt_f) {
136 fprintf(stderr, "ERROR: Option `-f' doesn't work yet\n");
137 exit(1);
138 }
139 }
140 event->proc->current_syscall = -1;
141 continue_process(event->proc->pid);
142}
143
144static void process_breakpoint(struct event * event)
145{
146 struct library_symbol * tmp;
147
Juan Cespedesf0fdae91998-03-11 00:03:00 +0100148 if (opt_d>1) {
149 output_line(0,"event: breakpoint (0x%08x)", event->e_un.brk_addr);
150 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100151 if (event->proc->breakpoint_being_enabled) {
152 continue_enabling_breakpoint(event->proc->pid, event->proc->breakpoint_being_enabled);
153 event->proc->breakpoint_being_enabled = NULL;
154 return;
155 }
156 if (event->proc->current_symbol && event->e_un.brk_addr == event->proc->return_value.addr) {
157 output_right(LT_TOF_FUNCTION, event->proc, event->proc->current_symbol->name);
158 continue_after_breakpoint(event->proc, &event->proc->return_value, 1);
159 event->proc->current_symbol = NULL;
160 return;
161 }
162
163 tmp = event->proc->list_of_symbols;
164 while(tmp) {
165 if (event->e_un.brk_addr == tmp->brk.addr) {
166 if (event->proc->current_symbol) {
167 delete_breakpoint(event->proc->pid, &event->proc->return_value);
168 }
169 event->proc->current_symbol = tmp;
170 event->proc->stack_pointer = get_stack_pointer(event->proc->pid);
171 event->proc->return_addr = get_return_addr(event->proc->pid, event->proc->stack_pointer);
172 output_left(LT_TOF_FUNCTION, event->proc, tmp->name);
173 event->proc->return_value.addr = event->proc->return_addr;
174 insert_breakpoint(event->proc->pid, &event->proc->return_value);
175 continue_after_breakpoint(event->proc, &tmp->brk, 0);
176 return;
177 }
178 tmp = tmp->next;
179 }
180 output_line(event->proc, "breakpointed at 0x%08x (?)",
181 (unsigned)event->e_un.brk_addr);
182 continue_process(event->proc->pid);
183}