blob: 481f1bc2384edbc4bbfea56a1cdad15d8a315dd9 [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:
22 process_signal(event);
23 return;
24 case LT_EV_EXIT:
25 process_exit(event);
26 return;
27 case LT_EV_EXIT_SIGNAL:
28 process_exit_signal(event);
29 return;
30 case LT_EV_SYSCALL:
31 process_syscall(event);
32 return;
33 case LT_EV_SYSRET:
34 process_sysret(event);
35 return;
36 case LT_EV_BREAKPOINT:
37 process_breakpoint(event);
38 return;
39 default:
40 fprintf(stderr, "Error! unknown event?\n");
41 exit(1);
42 }
43}
44
45static char * shortsignal(int signum)
46{
47 static char * signalent0[] = {
48 #include "signalent.h"
49 };
50 int nsignals0 = sizeof signalent0 / sizeof signalent0[0];
51
52 if (signum<0 || signum>nsignals0) {
53 return "UNKNOWN_SIGNAL";
54 } else {
55 return signalent0[signum];
56 }
57}
58
59static char * sysname(int sysnum)
60{
61 static char result[128];
62 static char * syscalent0[] = {
63 #include "syscallent.h"
64 };
65 int nsyscals0 = sizeof syscalent0 / sizeof syscalent0[0];
66
67 if (sysnum<0 || sysnum>nsyscals0) {
68 sprintf(result, "SYS_%d", sysnum);
69 return result;
70 } else {
71 sprintf(result, "SYS_%s", syscalent0[sysnum]);
72 return result;
73 }
74}
75
76static void process_signal(struct event * event)
77{
78 output_line(event->proc, "--- %s (%s) ---",
79 shortsignal(event->e_un.signum), strsignal(event->e_un.signum));
80 continue_after_signal(event->proc->pid, event->e_un.signum);
81}
82
83static void process_exit(struct event * event)
84{
85 output_line(event->proc, "+++ exited (status %d) +++",
86 event->e_un.ret_val);
87}
88
89static void process_exit_signal(struct event * event)
90{
91 output_line(event->proc, "+++ killed by %s +++",
92 shortsignal(event->e_un.signum));
93}
94
95static void process_syscall(struct event * event)
96{
97 event->proc->current_syscall = event->e_un.sysnum;
98 if (opt_S) {
99 output_left(LT_TOF_SYSCALL, event->proc, sysname(event->e_un.sysnum));
100 }
101 if (child_p(event->e_un.sysnum)) {
102 disable_all_breakpoints(event->proc);
103 if (event->proc->current_symbol) {
104 delete_breakpoint(event->proc->pid, &event->proc->return_value);
105 }
106 }
107 continue_process(event->proc->pid);
108}
109
110static void process_sysret(struct event * event)
111{
112 if (opt_S) {
113 output_right(LT_TOF_SYSCALL, event->proc, sysname(event->e_un.sysnum));
114 }
115 if (child_p(event->e_un.sysnum)) {
116 enable_all_breakpoints(event->proc);
117 if (event->proc->current_symbol) {
118 insert_breakpoint(event->proc->pid, &event->proc->return_value);
119 }
120 if (opt_f) {
121 fprintf(stderr, "ERROR: Option `-f' doesn't work yet\n");
122 exit(1);
123 }
124 }
125 event->proc->current_syscall = -1;
126 continue_process(event->proc->pid);
127}
128
129static void process_breakpoint(struct event * event)
130{
131 struct library_symbol * tmp;
132
133 if (event->proc->breakpoint_being_enabled) {
134 continue_enabling_breakpoint(event->proc->pid, event->proc->breakpoint_being_enabled);
135 event->proc->breakpoint_being_enabled = NULL;
136 return;
137 }
138 if (event->proc->current_symbol && event->e_un.brk_addr == event->proc->return_value.addr) {
139 output_right(LT_TOF_FUNCTION, event->proc, event->proc->current_symbol->name);
140 continue_after_breakpoint(event->proc, &event->proc->return_value, 1);
141 event->proc->current_symbol = NULL;
142 return;
143 }
144
145 tmp = event->proc->list_of_symbols;
146 while(tmp) {
147 if (event->e_un.brk_addr == tmp->brk.addr) {
148 if (event->proc->current_symbol) {
149 delete_breakpoint(event->proc->pid, &event->proc->return_value);
150 }
151 event->proc->current_symbol = tmp;
152 event->proc->stack_pointer = get_stack_pointer(event->proc->pid);
153 event->proc->return_addr = get_return_addr(event->proc->pid, event->proc->stack_pointer);
154 output_left(LT_TOF_FUNCTION, event->proc, tmp->name);
155 event->proc->return_value.addr = event->proc->return_addr;
156 insert_breakpoint(event->proc->pid, &event->proc->return_value);
157 continue_after_breakpoint(event->proc, &tmp->brk, 0);
158 return;
159 }
160 tmp = tmp->next;
161 }
162 output_line(event->proc, "breakpointed at 0x%08x (?)",
163 (unsigned)event->e_un.brk_addr);
164 continue_process(event->proc->pid);
165}