blob: bdda4d1ffb4ac5a78333935548b2107432fc9808 [file] [log] [blame]
Petr Machatafed1e8d2012-02-07 02:06:29 +01001#define _GNU_SOURCE
Juan Cespedesd44c6b81998-09-25 14:48:42 +02002#include "config.h"
Juan Cespedesd44c6b81998-09-25 14:48:42 +02003
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +02004#include <assert.h>
Petr Machata534e00f2011-09-27 17:58:38 +02005#include <errno.h>
Petr Machata3d0c91c2012-04-14 02:37:38 +02006#include <error.h>
7#include <signal.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <sys/time.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +010012
Petr Machata9294d822012-02-07 12:35:58 +010013#include "breakpoint.h"
Petr Machata3d0c91c2012-04-14 02:37:38 +020014#include "common.h"
Petr Machata2b46cfc2012-02-18 11:17:29 +010015#include "library.h"
Petr Machata3d0c91c2012-04-14 02:37:38 +020016#include "proc.h"
Petr Machatafed1e8d2012-02-07 02:06:29 +010017
Juan Cespedes03192f82009-07-03 10:16:22 +020018static void handle_signal(Event *event);
19static void handle_exit(Event *event);
20static void handle_exit_signal(Event *event);
21static void handle_syscall(Event *event);
22static void handle_arch_syscall(Event *event);
23static void handle_sysret(Event *event);
24static void handle_arch_sysret(Event *event);
25static void handle_clone(Event *event);
26static void handle_exec(Event *event);
27static void handle_breakpoint(Event *event);
28static void handle_new(Event *event);
Juan Cespedes5e01f651998-03-08 22:31:44 +010029
Juan Cespedesa8909f72009-04-28 20:02:41 +020030static void callstack_push_syscall(Process *proc, int sysnum);
31static void callstack_push_symfunc(Process *proc,
Ian Wienand2d45b1a2006-02-20 22:48:07 +010032 struct library_symbol *sym);
Juan Cespedesa8909f72009-04-28 20:02:41 +020033static void callstack_pop(Process *proc);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020034
Juan Cespedes61da3372009-07-03 11:55:44 +020035static char * shortsignal(Process *proc, int signum);
36static char * sysname(Process *proc, int sysnum);
37static char * arch_sysname(Process *proc, int sysnum);
38
Petr Machatacbe29c62011-09-27 02:27:58 +020039static Event *
40call_handler(Process * proc, Event * event)
41{
42 assert(proc != NULL);
43
Petr Machata366c2f42012-02-09 19:34:36 +010044 struct event_handler *handler = proc->event_handler;
Petr Machatacbe29c62011-09-27 02:27:58 +020045 if (handler == NULL)
46 return event;
47
48 return (*handler->on_event) (handler, event);
49}
50
Juan Cespedes61da3372009-07-03 11:55:44 +020051void
Petr Machataffe4cd22012-04-11 18:01:44 +020052handle_event(Event *event)
53{
Petr Machata602330f2011-07-09 11:15:34 +020054 if (exiting == 1) {
Petr Machata602330f2011-07-09 11:15:34 +020055 debug(1, "ltrace about to exit");
Petr Machataffe4cd22012-04-11 18:01:44 +020056 os_ltrace_exiting();
57 exiting = 2;
Petr Machata602330f2011-07-09 11:15:34 +020058 }
Petr Machata26627682011-07-08 18:15:32 +020059 debug(DEBUG_FUNCTION, "handle_event(pid=%d, type=%d)",
60 event->proc ? event->proc->pid : -1, event->type);
Petr Machatacbe29c62011-09-27 02:27:58 +020061
62 /* If the thread group or an individual task define an
63 overriding event handler, give them a chance to kick in.
64 We will end up calling both handlers, if the first one
65 doesn't sink the event. */
66 if (event->proc != NULL) {
67 event = call_handler(event->proc, event);
68 if (event == NULL)
69 /* It was handled. */
70 return;
71
72 /* Note: the previous handler has a chance to alter
73 * the event. */
Petr Machata43d2fe52011-11-02 13:25:49 +010074 if (event->proc != NULL
75 && event->proc->leader != NULL
76 && event->proc != event->proc->leader) {
Petr Machatacbe29c62011-09-27 02:27:58 +020077 event = call_handler(event->proc->leader, event);
Petr Machata4007d742011-07-09 11:29:42 +020078 if (event == NULL)
Petr Machata4007d742011-07-09 11:29:42 +020079 return;
80 }
81 }
82
Juan Cespedes61da3372009-07-03 11:55:44 +020083 switch (event->type) {
84 case EVENT_NONE:
85 debug(1, "event: none");
86 return;
87 case EVENT_SIGNAL:
Petr Machataebfe7d62012-04-13 21:34:49 +020088 debug(1, "[%d] event: signal (%s [%d])",
89 event->proc->pid,
Juan Cespedes61da3372009-07-03 11:55:44 +020090 shortsignal(event->proc, event->e_un.signum),
91 event->e_un.signum);
92 handle_signal(event);
93 return;
94 case EVENT_EXIT:
Petr Machataebfe7d62012-04-13 21:34:49 +020095 debug(1, "[%d] event: exit (%d)",
96 event->proc->pid,
97 event->e_un.ret_val);
Juan Cespedes61da3372009-07-03 11:55:44 +020098 handle_exit(event);
99 return;
100 case EVENT_EXIT_SIGNAL:
Petr Machataebfe7d62012-04-13 21:34:49 +0200101 debug(1, "[%d] event: exit signal (%s [%d])",
102 event->proc->pid,
Juan Cespedes61da3372009-07-03 11:55:44 +0200103 shortsignal(event->proc, event->e_un.signum),
104 event->e_un.signum);
105 handle_exit_signal(event);
106 return;
107 case EVENT_SYSCALL:
Petr Machataebfe7d62012-04-13 21:34:49 +0200108 debug(1, "[%d] event: syscall (%s [%d])",
109 event->proc->pid,
Juan Cespedes61da3372009-07-03 11:55:44 +0200110 sysname(event->proc, event->e_un.sysnum),
111 event->e_un.sysnum);
112 handle_syscall(event);
113 return;
114 case EVENT_SYSRET:
Petr Machataebfe7d62012-04-13 21:34:49 +0200115 debug(1, "[%d] event: sysret (%s [%d])",
116 event->proc->pid,
Juan Cespedes61da3372009-07-03 11:55:44 +0200117 sysname(event->proc, event->e_un.sysnum),
118 event->e_un.sysnum);
119 handle_sysret(event);
120 return;
121 case EVENT_ARCH_SYSCALL:
Petr Machataebfe7d62012-04-13 21:34:49 +0200122 debug(1, "[%d] event: arch_syscall (%s [%d])",
123 event->proc->pid,
124 arch_sysname(event->proc, event->e_un.sysnum),
125 event->e_un.sysnum);
Juan Cespedes61da3372009-07-03 11:55:44 +0200126 handle_arch_syscall(event);
127 return;
128 case EVENT_ARCH_SYSRET:
Petr Machataebfe7d62012-04-13 21:34:49 +0200129 debug(1, "[%d] event: arch_sysret (%s [%d])",
130 event->proc->pid,
131 arch_sysname(event->proc, event->e_un.sysnum),
132 event->e_un.sysnum);
Juan Cespedes61da3372009-07-03 11:55:44 +0200133 handle_arch_sysret(event);
134 return;
135 case EVENT_CLONE:
Petr Machatacbe29c62011-09-27 02:27:58 +0200136 case EVENT_VFORK:
Petr Machataebfe7d62012-04-13 21:34:49 +0200137 debug(1, "[%d] event: clone (%u)",
138 event->proc->pid, event->e_un.newpid);
Juan Cespedes61da3372009-07-03 11:55:44 +0200139 handle_clone(event);
140 return;
141 case EVENT_EXEC:
Petr Machataebfe7d62012-04-13 21:34:49 +0200142 debug(1, "[%d] event: exec()",
143 event->proc->pid);
Juan Cespedes61da3372009-07-03 11:55:44 +0200144 handle_exec(event);
145 return;
146 case EVENT_BREAKPOINT:
Petr Machataebfe7d62012-04-13 21:34:49 +0200147 debug(1, "[%d] event: breakpoint %p",
148 event->proc->pid, event->e_un.brk_addr);
Juan Cespedes61da3372009-07-03 11:55:44 +0200149 handle_breakpoint(event);
150 return;
151 case EVENT_NEW:
Petr Machataebfe7d62012-04-13 21:34:49 +0200152 debug(1, "[%d] event: new process",
153 event->e_un.newpid);
Juan Cespedes61da3372009-07-03 11:55:44 +0200154 handle_new(event);
155 return;
156 default:
157 fprintf(stderr, "Error! unknown event?\n");
158 exit(1);
159 }
160}
161
Juan Cespedesbc8caf02009-05-07 19:38:38 +0200162typedef struct Pending_New Pending_New;
163struct Pending_New {
164 pid_t pid;
165 Pending_New * next;
166};
167static Pending_New * pending_news = NULL;
168
169static int
170pending_new(pid_t pid) {
Juan Cespedescd8976d2009-05-14 13:47:58 +0200171 Pending_New * p;
172
173 debug(DEBUG_FUNCTION, "pending_new(%d)", pid);
174
175 p = pending_news;
Juan Cespedesbc8caf02009-05-07 19:38:38 +0200176 while (p) {
177 if (p->pid == pid) {
178 return 1;
179 }
180 p = p->next;
181 }
182 return 0;
183}
184
185static void
186pending_new_insert(pid_t pid) {
Juan Cespedescd8976d2009-05-14 13:47:58 +0200187 Pending_New * p;
188
189 debug(DEBUG_FUNCTION, "pending_new_insert(%d)", pid);
190
191 p = malloc(sizeof(Pending_New));
Juan Cespedesbc8caf02009-05-07 19:38:38 +0200192 if (!p) {
193 perror("malloc()");
194 exit(1);
195 }
196 p->pid = pid;
197 p->next = pending_news;
198 pending_news = p;
199}
200
201static void
202pending_new_remove(pid_t pid) {
203 Pending_New *p, *pred;
204
Juan Cespedescd8976d2009-05-14 13:47:58 +0200205 debug(DEBUG_FUNCTION, "pending_new_remove(%d)", pid);
206
Juan Cespedesbc8caf02009-05-07 19:38:38 +0200207 p = pending_news;
208 if (p->pid == pid) {
209 pending_news = p->next;
210 free(p);
211 } else {
212 while (p) {
213 if (p->pid == pid) {
214 pred->next = p->next;
215 free(p);
216 }
217 pred = p;
218 p = p->next;
219 }
220 }
221}
222
223static void
Petr Machata2b46cfc2012-02-18 11:17:29 +0100224handle_clone(Event *event)
225{
Juan Cespedes03192f82009-07-03 10:16:22 +0200226 debug(DEBUG_FUNCTION, "handle_clone(pid=%d)", event->proc->pid);
Juan Cespedescd8976d2009-05-14 13:47:58 +0200227
Petr Machata2b46cfc2012-02-18 11:17:29 +0100228 struct Process *proc = malloc(sizeof(*proc));
229 if (proc == NULL) {
230 fail:
231 free(proc);
232 /* XXX proper error handling here, please. */
Juan Cespedesbc8caf02009-05-07 19:38:38 +0200233 perror("malloc()");
234 exit(1);
235 }
Petr Machata2b46cfc2012-02-18 11:17:29 +0100236
237 if (process_clone(proc, event->proc, event->e_un.newpid) < 0)
238 goto fail;
239 proc->parent = event->proc;
Juan Cespedesbc8caf02009-05-07 19:38:38 +0200240
Petr Machata75dcf7d2011-10-06 14:30:19 +0200241 /* We save register values to the arch pointer, and these need
242 to be per-thread. */
Petr Machata2b46cfc2012-02-18 11:17:29 +0100243 proc->arch_ptr = NULL;
Petr Machata75dcf7d2011-10-06 14:30:19 +0200244
Petr Machata2b46cfc2012-02-18 11:17:29 +0100245 if (pending_new(proc->pid)) {
246 pending_new_remove(proc->pid);
247 /* XXX this used to be destroy_event_handler call, but
248 * I don't think we want to call that on a shared
249 * state. */
250 proc->event_handler = NULL;
251 if (event->proc->state == STATE_ATTACHED && options.follow)
252 proc->state = STATE_ATTACHED;
253 else
254 proc->state = STATE_IGNORED;
255 continue_process(proc->pid);
Juan Cespedesbc8caf02009-05-07 19:38:38 +0200256 } else {
Petr Machata2b46cfc2012-02-18 11:17:29 +0100257 proc->state = STATE_BEING_CREATED;
Juan Cespedesbc8caf02009-05-07 19:38:38 +0200258 }
Petr Machata534e00f2011-09-27 17:58:38 +0200259
Petr Machatacbe29c62011-09-27 02:27:58 +0200260 if (event->type == EVENT_VFORK)
Petr Machata2b46cfc2012-02-18 11:17:29 +0100261 continue_after_vfork(proc);
Petr Machatacbe29c62011-09-27 02:27:58 +0200262 else
263 continue_process(event->proc->pid);
Juan Cespedesbc8caf02009-05-07 19:38:38 +0200264}
265
266static void
Juan Cespedes03192f82009-07-03 10:16:22 +0200267handle_new(Event * event) {
Juan Cespedescd8976d2009-05-14 13:47:58 +0200268 Process * proc;
269
Juan Cespedes03192f82009-07-03 10:16:22 +0200270 debug(DEBUG_FUNCTION, "handle_new(pid=%d)", event->e_un.newpid);
Juan Cespedescd8976d2009-05-14 13:47:58 +0200271
272 proc = pid2proc(event->e_un.newpid);
Juan Cespedesbc8caf02009-05-07 19:38:38 +0200273 if (!proc) {
274 pending_new_insert(event->e_un.newpid);
275 } else {
276 assert(proc->state == STATE_BEING_CREATED);
Juan Cespedes30439b42009-05-22 19:03:09 +0200277 if (options.follow) {
Juan Cespedes5c682042009-05-21 15:59:56 +0200278 proc->state = STATE_ATTACHED;
279 } else {
280 proc->state = STATE_IGNORED;
281 }
Juan Cespedesbc8caf02009-05-07 19:38:38 +0200282 continue_process(proc->pid);
283 }
284}
285
Juan Cespedesf1350522008-12-16 18:19:58 +0100286static char *
Juan Cespedesa8909f72009-04-28 20:02:41 +0200287shortsignal(Process *proc, int signum) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100288 static char *signalent0[] = {
289#include "signalent.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +0100290 };
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100291 static char *signalent1[] = {
292#include "signalent1.h"
Ian Wienand9a2ad352006-02-20 22:44:45 +0100293 };
294 static char **signalents[] = { signalent0, signalent1 };
295 int nsignals[] = { sizeof signalent0 / sizeof signalent0[0],
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100296 sizeof signalent1 / sizeof signalent1[0]
297 };
Juan Cespedes5e01f651998-03-08 22:31:44 +0100298
Juan Cespedescd8976d2009-05-14 13:47:58 +0200299 debug(DEBUG_FUNCTION, "shortsignal(pid=%d, signum=%d)", proc->pid, signum);
300
Ian Wienand9a2ad352006-02-20 22:44:45 +0100301 if (proc->personality > sizeof signalents / sizeof signalents[0])
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100302 abort();
Ian Wienand9a2ad352006-02-20 22:44:45 +0100303 if (signum < 0 || signum >= nsignals[proc->personality]) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100304 return "UNKNOWN_SIGNAL";
305 } else {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100306 return signalents[proc->personality][signum];
Juan Cespedes5e01f651998-03-08 22:31:44 +0100307 }
308}
309
Juan Cespedesf1350522008-12-16 18:19:58 +0100310static char *
Juan Cespedesa8909f72009-04-28 20:02:41 +0200311sysname(Process *proc, int sysnum) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100312 static char result[128];
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100313 static char *syscalent0[] = {
314#include "syscallent.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +0100315 };
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100316 static char *syscalent1[] = {
317#include "syscallent1.h"
Ian Wienand9a2ad352006-02-20 22:44:45 +0100318 };
319 static char **syscalents[] = { syscalent0, syscalent1 };
320 int nsyscals[] = { sizeof syscalent0 / sizeof syscalent0[0],
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100321 sizeof syscalent1 / sizeof syscalent1[0]
322 };
Juan Cespedes5e01f651998-03-08 22:31:44 +0100323
Juan Cespedescd8976d2009-05-14 13:47:58 +0200324 debug(DEBUG_FUNCTION, "sysname(pid=%d, sysnum=%d)", proc->pid, sysnum);
325
Ian Wienand9a2ad352006-02-20 22:44:45 +0100326 if (proc->personality > sizeof syscalents / sizeof syscalents[0])
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100327 abort();
Ian Wienand9a2ad352006-02-20 22:44:45 +0100328 if (sysnum < 0 || sysnum >= nsyscals[proc->personality]) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100329 sprintf(result, "SYS_%d", sysnum);
330 return result;
331 } else {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100332 sprintf(result, "SYS_%s",
333 syscalents[proc->personality][sysnum]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100334 return result;
335 }
336}
337
Juan Cespedesf1350522008-12-16 18:19:58 +0100338static char *
Juan Cespedesa8909f72009-04-28 20:02:41 +0200339arch_sysname(Process *proc, int sysnum) {
Juan Cespedes63184be2008-12-10 13:30:12 +0100340 static char result[128];
341 static char *arch_syscalent[] = {
342#include "arch_syscallent.h"
343 };
344 int nsyscals = sizeof arch_syscalent / sizeof arch_syscalent[0];
345
Juan Cespedescd8976d2009-05-14 13:47:58 +0200346 debug(DEBUG_FUNCTION, "arch_sysname(pid=%d, sysnum=%d)", proc->pid, sysnum);
347
Juan Cespedes63184be2008-12-10 13:30:12 +0100348 if (sysnum < 0 || sysnum >= nsyscals) {
349 sprintf(result, "ARCH_%d", sysnum);
350 return result;
351 } else {
352 sprintf(result, "ARCH_%s",
353 arch_syscalent[sysnum]);
354 return result;
355 }
356}
357
Juan Cespedesf1350522008-12-16 18:19:58 +0100358static void
Juan Cespedes03192f82009-07-03 10:16:22 +0200359handle_signal(Event *event) {
360 debug(DEBUG_FUNCTION, "handle_signal(pid=%d, signum=%d)", event->proc->pid, event->e_un.signum);
Joe Damato59e3fb12009-11-06 19:45:10 -0800361 if (event->proc->state != STATE_IGNORED && !options.no_signals) {
Juan Cespedes5c682042009-05-21 15:59:56 +0200362 output_line(event->proc, "--- %s (%s) ---",
363 shortsignal(event->proc, event->e_un.signum),
364 strsignal(event->e_un.signum));
365 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100366 continue_after_signal(event->proc->pid, event->e_un.signum);
367}
368
Juan Cespedesf1350522008-12-16 18:19:58 +0100369static void
Juan Cespedes03192f82009-07-03 10:16:22 +0200370handle_exit(Event *event) {
371 debug(DEBUG_FUNCTION, "handle_exit(pid=%d, status=%d)", event->proc->pid, event->e_un.ret_val);
Juan Cespedes5c682042009-05-21 15:59:56 +0200372 if (event->proc->state != STATE_IGNORED) {
373 output_line(event->proc, "+++ exited (status %d) +++",
374 event->e_un.ret_val);
375 }
Petr Machatacebb8842011-07-09 11:14:11 +0200376 remove_process(event->proc);
Petr Machata464026f2012-03-02 00:10:58 +0100377 free(event->proc);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100378}
379
Juan Cespedesf1350522008-12-16 18:19:58 +0100380static void
Juan Cespedes03192f82009-07-03 10:16:22 +0200381handle_exit_signal(Event *event) {
382 debug(DEBUG_FUNCTION, "handle_exit_signal(pid=%d, signum=%d)", event->proc->pid, event->e_un.signum);
Juan Cespedes5c682042009-05-21 15:59:56 +0200383 if (event->proc->state != STATE_IGNORED) {
384 output_line(event->proc, "+++ killed by %s +++",
385 shortsignal(event->proc, event->e_un.signum));
386 }
Petr Machatacebb8842011-07-09 11:14:11 +0200387 remove_process(event->proc);
Petr Machata464026f2012-03-02 00:10:58 +0100388 free(event->proc);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100389}
390
Petr Machata29add4f2012-02-18 16:38:05 +0100391static struct library_symbol *
392temporary_syscall_symbol(const char *name)
393{
394 struct library *syscalls = malloc(sizeof(*syscalls));
395 struct library_symbol *syscall = malloc(sizeof(*syscall));
396 if (syscalls == NULL || syscall == NULL) {
397 free(syscalls);
398 free(syscall);
399 return NULL;
400 }
Petr Machatab5f80ac2012-04-04 01:46:18 +0200401 library_init(syscalls, (enum library_type)-1);
Petr Machata0b55b582012-04-02 00:38:46 +0200402 library_set_soname(syscalls, "SYS", 0);
Petr Machatae6523e62012-03-24 04:54:06 +0100403 library_symbol_init(syscall, 0, name, 0, LS_TOPLT_NONE);
Petr Machata29add4f2012-02-18 16:38:05 +0100404 library_add_symbol(syscalls, syscall);
405 return syscall;
406}
407
408static void
409output_syscall_left(struct Process *proc, const char *name)
410{
411 struct library_symbol *syscall = temporary_syscall_symbol(name);
412 output_left(LT_TOF_SYSCALL, proc, syscall);
413 struct library *lib = syscall->lib;
414 library_destroy(lib);
415 free(lib);
416}
417
418static void
419output_syscall_right(struct Process *proc, const char *name)
420{
421 struct library_symbol *syscall = temporary_syscall_symbol(name);
422 output_right(LT_TOF_SYSCALLR, proc, syscall);
423 struct library *lib = syscall->lib;
424 library_destroy(lib);
425 free(lib);
426}
427
Juan Cespedesf1350522008-12-16 18:19:58 +0100428static void
Juan Cespedes03192f82009-07-03 10:16:22 +0200429handle_syscall(Event *event) {
430 debug(DEBUG_FUNCTION, "handle_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
Juan Cespedes5c682042009-05-21 15:59:56 +0200431 if (event->proc->state != STATE_IGNORED) {
Petr Machata211f0882010-11-03 18:42:18 +0100432 callstack_push_syscall(event->proc, event->e_un.sysnum);
Petr Machata29add4f2012-02-18 16:38:05 +0100433 if (options.syscalls)
434 output_syscall_left(event->proc,
435 sysname(event->proc,
436 event->e_un.sysnum));
Juan Cespedes5e01f651998-03-08 22:31:44 +0100437 }
Petr Machata43d2fe52011-11-02 13:25:49 +0100438 continue_after_syscall(event->proc, event->e_un.sysnum, 0);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100439}
440
Juan Cespedesf1350522008-12-16 18:19:58 +0100441static void
Juan Cespedes03192f82009-07-03 10:16:22 +0200442handle_exec(Event * event) {
Juan Cespedese0660df2009-05-21 18:14:39 +0200443 Process * proc = event->proc;
Juan Cespedese0660df2009-05-21 18:14:39 +0200444
Petr Machata3d0c91c2012-04-14 02:37:38 +0200445 /* Save the PID so that we can use it after unsuccessful
446 * process_exec. */
447 pid_t pid = proc->pid;
448
Juan Cespedes03192f82009-07-03 10:16:22 +0200449 debug(DEBUG_FUNCTION, "handle_exec(pid=%d)", proc->pid);
Juan Cespedese0660df2009-05-21 18:14:39 +0200450 if (proc->state == STATE_IGNORED) {
Petr Machata3d0c91c2012-04-14 02:37:38 +0200451 untrace:
452 untrace_pid(pid);
Petr Machatacebb8842011-07-09 11:14:11 +0200453 remove_process(proc);
Petr Machata464026f2012-03-02 00:10:58 +0100454 free(proc);
Juan Cespedese0660df2009-05-21 18:14:39 +0200455 return;
Juan Cespedes5c682042009-05-21 15:59:56 +0200456 }
Juan Cespedese0660df2009-05-21 18:14:39 +0200457 output_line(proc, "--- Called exec() ---");
Petr Machata3d0c91c2012-04-14 02:37:38 +0200458
459 if (process_exec(proc) < 0) {
460 error(0, errno,
461 "couldn't reinitialize process %d after exec", pid);
462 goto untrace;
463 }
464
Juan Cespedese0660df2009-05-21 18:14:39 +0200465 continue_process(proc->pid);
Petr Machatacb39a402012-04-13 22:19:02 +0200466
467 /* After the exec, we expect to hit the first executable
Petr Machata9847abe2012-04-14 00:36:03 +0200468 * instruction.
469 *
470 * XXX TODO It would be nice to have this removed, but then we
471 * need to do that also for initial call to wait_for_proc in
472 * execute_program. In that case we could generate a
473 * EVENT_FIRST event or something, or maybe this could somehow
474 * be rolled into EVENT_NEW. */
Petr Machatacb39a402012-04-13 22:19:02 +0200475 wait_for_proc(proc->pid);
476 continue_process(proc->pid);
Juan Cespedes1e583132009-04-07 18:17:11 +0200477}
478
479static void
Juan Cespedes03192f82009-07-03 10:16:22 +0200480handle_arch_syscall(Event *event) {
481 debug(DEBUG_FUNCTION, "handle_arch_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
Juan Cespedes5c682042009-05-21 15:59:56 +0200482 if (event->proc->state != STATE_IGNORED) {
Petr Machata211f0882010-11-03 18:42:18 +0100483 callstack_push_syscall(event->proc, 0xf0000 + event->e_un.sysnum);
Juan Cespedes5c682042009-05-21 15:59:56 +0200484 if (options.syscalls) {
Petr Machata29add4f2012-02-18 16:38:05 +0100485 output_syscall_left(event->proc,
486 arch_sysname(event->proc,
487 event->e_un.sysnum));
Juan Cespedes5c682042009-05-21 15:59:56 +0200488 }
Juan Cespedes63184be2008-12-10 13:30:12 +0100489 }
Juan Cespedes63184be2008-12-10 13:30:12 +0100490 continue_process(event->proc->pid);
491}
492
Juan Cespedesd65efa32003-02-03 00:22:30 +0100493struct timeval current_time_spent;
494
Juan Cespedesf1350522008-12-16 18:19:58 +0100495static void
Juan Cespedesa8909f72009-04-28 20:02:41 +0200496calc_time_spent(Process *proc) {
Juan Cespedesd65efa32003-02-03 00:22:30 +0100497 struct timeval tv;
498 struct timezone tz;
499 struct timeval diff;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100500 struct callstack_element *elem;
Juan Cespedesd65efa32003-02-03 00:22:30 +0100501
Juan Cespedescd8976d2009-05-14 13:47:58 +0200502 debug(DEBUG_FUNCTION, "calc_time_spent(pid=%d)", proc->pid);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100503 elem = &proc->callstack[proc->callstack_depth - 1];
Juan Cespedesd65efa32003-02-03 00:22:30 +0100504
505 gettimeofday(&tv, &tz);
506
507 diff.tv_sec = tv.tv_sec - elem->time_spent.tv_sec;
508 if (tv.tv_usec >= elem->time_spent.tv_usec) {
509 diff.tv_usec = tv.tv_usec - elem->time_spent.tv_usec;
510 } else {
511 diff.tv_sec++;
512 diff.tv_usec = 1000000 + tv.tv_usec - elem->time_spent.tv_usec;
513 }
514 current_time_spent = diff;
515}
516
Juan Cespedesf1350522008-12-16 18:19:58 +0100517static void
Juan Cespedes03192f82009-07-03 10:16:22 +0200518handle_sysret(Event *event) {
519 debug(DEBUG_FUNCTION, "handle_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
Juan Cespedes5c682042009-05-21 15:59:56 +0200520 if (event->proc->state != STATE_IGNORED) {
521 if (opt_T || options.summary) {
522 calc_time_spent(event->proc);
523 }
Petr Machata29add4f2012-02-18 16:38:05 +0100524 if (options.syscalls)
525 output_syscall_right(event->proc,
526 sysname(event->proc,
527 event->e_un.sysnum));
528
Petr Machata43d2fe52011-11-02 13:25:49 +0100529 assert(event->proc->callstack_depth > 0);
530 unsigned d = event->proc->callstack_depth - 1;
531 assert(event->proc->callstack[d].is_syscall);
Petr Machata211f0882010-11-03 18:42:18 +0100532 callstack_pop(event->proc);
Juan Cespedes21c63a12001-07-07 20:56:56 +0200533 }
Petr Machata43d2fe52011-11-02 13:25:49 +0100534 continue_after_syscall(event->proc, event->e_un.sysnum, 1);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100535}
536
Juan Cespedesf1350522008-12-16 18:19:58 +0100537static void
Juan Cespedes03192f82009-07-03 10:16:22 +0200538handle_arch_sysret(Event *event) {
539 debug(DEBUG_FUNCTION, "handle_arch_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
Juan Cespedes5c682042009-05-21 15:59:56 +0200540 if (event->proc->state != STATE_IGNORED) {
541 if (opt_T || options.summary) {
542 calc_time_spent(event->proc);
543 }
Petr Machata29add4f2012-02-18 16:38:05 +0100544 if (options.syscalls)
545 output_syscall_right(event->proc,
546 arch_sysname(event->proc,
547 event->e_un.sysnum));
Petr Machata211f0882010-11-03 18:42:18 +0100548 callstack_pop(event->proc);
Juan Cespedes63184be2008-12-10 13:30:12 +0100549 }
550 continue_process(event->proc->pid);
551}
552
Juan Cespedesf1350522008-12-16 18:19:58 +0100553static void
Petr Machata14298742012-04-12 23:09:21 +0200554output_right_tos(struct Process *proc)
555{
556 size_t d = proc->callstack_depth;
557 struct callstack_element *elem = &proc->callstack[d - 1];
558 if (proc->state != STATE_IGNORED)
559 output_right(LT_TOF_FUNCTIONR, proc, elem->c_un.libfunc->name);
560}
561
562static void
Petr Machatafed1e8d2012-02-07 02:06:29 +0100563handle_breakpoint(Event *event)
564{
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100565 int i, j;
Petr Machatabc373262012-02-07 23:31:15 +0100566 struct breakpoint *sbp;
Petr Machata9a5420c2011-07-09 11:21:23 +0200567 Process *leader = event->proc->leader;
Petr Machata31b2f9f2012-04-12 22:23:40 +0200568 void *brk_addr = event->e_un.brk_addr;
Petr Machata9a5420c2011-07-09 11:21:23 +0200569
570 /* The leader has terminated. */
571 if (leader == NULL) {
572 continue_process(event->proc->pid);
573 return;
574 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100575
Petr Machata31b2f9f2012-04-12 22:23:40 +0200576 debug(DEBUG_FUNCTION, "handle_breakpoint(pid=%d, addr=%p)",
577 event->proc->pid, brk_addr);
578 debug(2, "event: breakpoint (%p)", brk_addr);
Luis Machado55c5feb2008-03-12 15:56:01 +0100579
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100580 for (i = event->proc->callstack_depth - 1; i >= 0; i--) {
Petr Machata31b2f9f2012-04-12 22:23:40 +0200581 if (brk_addr == event->proc->callstack[i].return_addr) {
Petr Machatad09d9ce2012-04-06 13:25:37 +0200582#if defined(__mips__)
Arnaud Patard161193f2010-01-08 08:40:14 -0500583 void *addr = NULL;
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200584 struct library_symbol *sym= event->proc->callstack[i].c_un.libfunc;
Arnaud Patard161193f2010-01-08 08:40:14 -0500585 struct library_symbol *new_sym;
Juan Cespedesbc8caf02009-05-07 19:38:38 +0200586 assert(sym);
Petr Machatac185aff2011-11-09 16:18:06 +0100587 addr = sym2addr(event->proc, sym);
Petr Machata9a5420c2011-07-09 11:21:23 +0200588 sbp = dict_find_entry(leader->breakpoints, addr);
Arnaud Patard161193f2010-01-08 08:40:14 -0500589 if (sbp) {
590 if (addr != sbp->addr) {
Petr Machatadb30b102012-03-28 02:44:18 +0200591 insert_breakpoint(event->proc, addr, sym);
Arnaud Patard161193f2010-01-08 08:40:14 -0500592 }
593 } else {
594 new_sym=malloc(sizeof(*new_sym) + strlen(sym->name) + 1);
595 memcpy(new_sym,sym,sizeof(*new_sym) + strlen(sym->name) + 1);
Petr Machata26627682011-07-08 18:15:32 +0200596 new_sym->next = leader->list_of_symbols;
Petr Machata9a5420c2011-07-09 11:21:23 +0200597 leader->list_of_symbols = new_sym;
Petr Machatadb30b102012-03-28 02:44:18 +0200598 insert_breakpoint(event->proc, addr, new_sym);
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200599 }
Juan Cespedes5bfb0612002-03-31 20:01:28 +0200600#endif
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100601 for (j = event->proc->callstack_depth - 1; j > i; j--) {
Juan Cespedes5916fda2002-02-25 00:19:21 +0100602 callstack_pop(event->proc);
603 }
Juan Cespedes5c682042009-05-21 15:59:56 +0200604 if (event->proc->state != STATE_IGNORED) {
605 if (opt_T || options.summary) {
606 calc_time_spent(event->proc);
607 }
Juan Cespedesd65efa32003-02-03 00:22:30 +0100608 }
Petr Machata31b2f9f2012-04-12 22:23:40 +0200609 event->proc->return_addr = brk_addr;
610
Petr Machata14298742012-04-12 23:09:21 +0200611 output_right_tos(event->proc);
612 callstack_pop(event->proc);
613
Petr Machata31b2f9f2012-04-12 22:23:40 +0200614 /* Pop also any other entries that seem like
615 * they are linked to the current one: they
616 * have the same return address, but were made
617 * for different symbols. This should only
618 * happen for entry point tracing, i.e. for -x
619 * everywhere, or -x and -e on PPC64. */
Petr Machata31b2f9f2012-04-12 22:23:40 +0200620 while (event->proc->callstack_depth > 0) {
621 struct callstack_element *prev;
622 size_t d = event->proc->callstack_depth;
623 prev = &event->proc->callstack[d - 1];
624
Petr Machata14298742012-04-12 23:09:21 +0200625 if (prev->c_un.libfunc == libsym
626 || prev->return_addr != brk_addr)
Petr Machata31b2f9f2012-04-12 22:23:40 +0200627 break;
Petr Machata14298742012-04-12 23:09:21 +0200628
629 output_right_tos(event->proc);
630 callstack_pop(event->proc);
Juan Cespedes5c682042009-05-21 15:59:56 +0200631 }
Petr Machata31b2f9f2012-04-12 22:23:40 +0200632
633 sbp = address2bpstruct(leader, brk_addr);
Petr Machata9a5420c2011-07-09 11:21:23 +0200634 continue_after_breakpoint(event->proc, sbp);
Juan Cespedes5916fda2002-02-25 00:19:21 +0100635 return;
636 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100637 }
638
Petr Machata31b2f9f2012-04-12 22:23:40 +0200639 if ((sbp = address2bpstruct(leader, brk_addr))) {
Petr Machataa9fd8f42012-02-07 13:25:56 +0100640 breakpoint_on_hit(sbp, event->proc);
Petr Machatabc373262012-02-07 23:31:15 +0100641
Petr Machata2b46cfc2012-02-18 11:17:29 +0100642 if (event->proc->state != STATE_IGNORED
643 && sbp->libsym != NULL) {
Juan Cespedes5c682042009-05-21 15:59:56 +0200644 event->proc->stack_pointer = get_stack_pointer(event->proc);
645 event->proc->return_addr =
646 get_return_addr(event->proc, event->proc->stack_pointer);
Juan Cespedes5c682042009-05-21 15:59:56 +0200647 callstack_push_symfunc(event->proc, sbp->libsym);
Petr Machata29add4f2012-02-18 16:38:05 +0100648 output_left(LT_TOF_FUNCTION, event->proc, sbp->libsym);
Juan Cespedes5c682042009-05-21 15:59:56 +0200649 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100650
Petr Machata56a9ea62012-03-27 03:09:29 +0200651 breakpoint_on_continue(sbp, event->proc);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100652 return;
653 }
Ian Wienand9a2ad352006-02-20 22:44:45 +0100654
Petr Machata796267f2012-04-04 19:09:37 +0200655 if (event->proc->state != STATE_IGNORED)
Juan Cespedes5c682042009-05-21 15:59:56 +0200656 output_line(event->proc, "unexpected breakpoint at %p",
Petr Machata31b2f9f2012-04-12 22:23:40 +0200657 brk_addr);
Petr Machata796267f2012-04-04 19:09:37 +0200658
Juan Cespedes5e01f651998-03-08 22:31:44 +0100659 continue_process(event->proc->pid);
660}
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200661
Juan Cespedesf1350522008-12-16 18:19:58 +0100662static void
Juan Cespedesa8909f72009-04-28 20:02:41 +0200663callstack_push_syscall(Process *proc, int sysnum) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100664 struct callstack_element *elem;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200665
Juan Cespedescd8976d2009-05-14 13:47:58 +0200666 debug(DEBUG_FUNCTION, "callstack_push_syscall(pid=%d, sysnum=%d)", proc->pid, sysnum);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200667 /* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100668 if (proc->callstack_depth == MAX_CALLDEPTH - 1) {
Arnaud Patard91a1f322010-01-08 08:40:13 -0500669 fprintf(stderr, "%s: Error: call nesting too deep!\n", __func__);
670 abort();
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200671 return;
672 }
673
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100674 elem = &proc->callstack[proc->callstack_depth];
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200675 elem->is_syscall = 1;
676 elem->c_un.syscall = sysnum;
677 elem->return_addr = NULL;
678
679 proc->callstack_depth++;
Juan Cespedesda9b9532009-04-07 15:33:50 +0200680 if (opt_T || options.summary) {
Juan Cespedesd65efa32003-02-03 00:22:30 +0100681 struct timezone tz;
682 gettimeofday(&elem->time_spent, &tz);
683 }
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200684}
685
Juan Cespedes21c63a12001-07-07 20:56:56 +0200686static void
Juan Cespedesa8909f72009-04-28 20:02:41 +0200687callstack_push_symfunc(Process *proc, struct library_symbol *sym) {
Petr Machata14298742012-04-12 23:09:21 +0200688 struct callstack_element *elem;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200689
Juan Cespedescd8976d2009-05-14 13:47:58 +0200690 debug(DEBUG_FUNCTION, "callstack_push_symfunc(pid=%d, symbol=%s)", proc->pid, sym->name);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200691 /* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100692 if (proc->callstack_depth == MAX_CALLDEPTH - 1) {
Arnaud Patard91a1f322010-01-08 08:40:13 -0500693 fprintf(stderr, "%s: Error: call nesting too deep!\n", __func__);
694 abort();
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200695 return;
696 }
697
Petr Machata14298742012-04-12 23:09:21 +0200698 elem = &proc->callstack[proc->callstack_depth++];
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200699 elem->is_syscall = 0;
700 elem->c_un.libfunc = sym;
701
Juan Cespedes3f0b62e2001-07-09 01:02:52 +0200702 elem->return_addr = proc->return_addr;
Petr Machata9df15012012-02-20 12:49:46 +0100703 if (elem->return_addr)
704 insert_breakpoint(proc, elem->return_addr, NULL);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200705
Arnaud Patard26570082010-01-08 08:40:12 -0500706 /* handle functions like atexit() on mips which have no return */
Juan Cespedesda9b9532009-04-07 15:33:50 +0200707 if (opt_T || options.summary) {
Juan Cespedesd65efa32003-02-03 00:22:30 +0100708 struct timezone tz;
709 gettimeofday(&elem->time_spent, &tz);
710 }
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200711}
712
Juan Cespedesf1350522008-12-16 18:19:58 +0100713static void
Juan Cespedesa8909f72009-04-28 20:02:41 +0200714callstack_pop(Process *proc) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100715 struct callstack_element *elem;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200716 assert(proc->callstack_depth > 0);
717
Juan Cespedescd8976d2009-05-14 13:47:58 +0200718 debug(DEBUG_FUNCTION, "callstack_pop(pid=%d)", proc->pid);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100719 elem = &proc->callstack[proc->callstack_depth - 1];
Paul Gilliam76c61f12006-06-14 06:55:21 +0200720 if (!elem->is_syscall && elem->return_addr) {
Petr Machata9a5420c2011-07-09 11:21:23 +0200721 assert(proc->leader != NULL);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200722 delete_breakpoint(proc, elem->return_addr);
723 }
Petr Machata211f0882010-11-03 18:42:18 +0100724 if (elem->arch_ptr != NULL) {
725 free(elem->arch_ptr);
726 elem->arch_ptr = NULL;
727 }
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200728 proc->callstack_depth--;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200729}