blob: 8d63d7d97f6a8b4516fffc5069ae681ac13b5ee5 [file] [log] [blame]
Juan Cespedesd44c6b81998-09-25 14:48:42 +02001#if HAVE_CONFIG_H
2#include "config.h"
3#endif
4
Juan Cespedes5e01f651998-03-08 22:31:44 +01005#define _GNU_SOURCE 1
Juan Cespedes1cd999a2001-07-03 00:46:04 +02006#include <stdlib.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +01007#include <sys/types.h>
8#include <sys/wait.h>
9#include <errno.h>
10#include <signal.h>
11#include <string.h>
Juan Cespedes1e583132009-04-07 18:17:11 +020012#include <sys/ptrace.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +010013
14#include "ltrace.h"
15#include "options.h"
Juan Cespedescac15c32003-01-31 18:58:58 +010016#include "debug.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +010017
18static struct event event;
19
Juan Cespedesf1350522008-12-16 18:19:58 +010020struct event *
Juan Cespedese2023f72009-04-07 12:12:08 +020021next_event(void) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010022 pid_t pid;
23 int status;
24 int tmp;
Petr Machataef46b3e2007-05-09 19:21:42 +020025 int stop_signal;
Juan Cespedes5e01f651998-03-08 22:31:44 +010026
Juan Cespedes28f60191998-04-12 00:04:39 +020027 if (!list_of_processes) {
Juan Cespedescac15c32003-01-31 18:58:58 +010028 debug(1, "No more children");
Juan Cespedes28f60191998-04-12 00:04:39 +020029 exit(0);
30 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010031 pid = wait(&status);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010032 if (pid == -1) {
33 if (errno == ECHILD) {
Juan Cespedescac15c32003-01-31 18:58:58 +010034 debug(1, "No more children");
Juan Cespedes5e01f651998-03-08 22:31:44 +010035 exit(0);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010036 } else if (errno == EINTR) {
Juan Cespedescac15c32003-01-31 18:58:58 +010037 debug(1, "wait received EINTR ?");
Juan Cespedes138d41c2009-04-07 00:49:12 +020038 event.thing = EVENT_NONE;
Juan Cespedes28f60191998-04-12 00:04:39 +020039 return &event;
Juan Cespedes5e01f651998-03-08 22:31:44 +010040 }
41 perror("wait");
42 exit(1);
43 }
44 event.proc = pid2proc(pid);
45 if (!event.proc) {
Juan Cespedesa8909f72009-04-28 20:02:41 +020046 output_line(NULL, "event from wrong pid %u ?!?\n", pid);
47// exit(1);
48 event.thing = EVENT_NONE;
49 return &event;
Juan Cespedes5e01f651998-03-08 22:31:44 +010050 }
Juan Cespedes5c3fe062004-06-14 18:08:37 +020051 get_arch_dep(event.proc);
Juan Cespedes35d70631998-03-15 14:05:40 +010052 event.proc->instruction_pointer = NULL;
Juan Cespedes1e583132009-04-07 18:17:11 +020053 debug(3, "event from pid %u", pid);
Juan Cespedes5e01f651998-03-08 22:31:44 +010054 if (event.proc->breakpoints_enabled == -1) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010055 enable_all_breakpoints(event.proc);
Juan Cespedes138d41c2009-04-07 00:49:12 +020056 event.thing = EVENT_NONE;
Ian Wienand9a2ad352006-02-20 22:44:45 +010057 trace_set_options(event.proc, event.proc->pid);
Juan Cespedes5e01f651998-03-08 22:31:44 +010058 continue_process(event.proc->pid);
59 return &event;
60 }
Juan Cespedes35d70631998-03-15 14:05:40 +010061 if (opt_i) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010062 event.proc->instruction_pointer =
63 get_instruction_pointer(event.proc);
Juan Cespedesf0fdae91998-03-11 00:03:00 +010064 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +010065 switch (syscall_p(event.proc, status, &tmp)) {
Juan Cespedes63184be2008-12-10 13:30:12 +010066 case 1:
Juan Cespedes138d41c2009-04-07 00:49:12 +020067 event.thing = EVENT_SYSCALL;
Juan Cespedes63184be2008-12-10 13:30:12 +010068 event.e_un.sysnum = tmp;
69 return &event;
70 case 2:
Juan Cespedes138d41c2009-04-07 00:49:12 +020071 event.thing = EVENT_SYSRET;
Juan Cespedes63184be2008-12-10 13:30:12 +010072 event.e_un.sysnum = tmp;
73 return &event;
74 case 3:
Juan Cespedes138d41c2009-04-07 00:49:12 +020075 event.thing = EVENT_ARCH_SYSCALL;
Juan Cespedes63184be2008-12-10 13:30:12 +010076 event.e_un.sysnum = tmp;
77 return &event;
78 case 4:
Juan Cespedes138d41c2009-04-07 00:49:12 +020079 event.thing = EVENT_ARCH_SYSRET;
Juan Cespedes63184be2008-12-10 13:30:12 +010080 event.e_un.sysnum = tmp;
81 return &event;
82 case -1:
Juan Cespedes138d41c2009-04-07 00:49:12 +020083 event.thing = EVENT_NONE;
Juan Cespedes63184be2008-12-10 13:30:12 +010084 continue_process(event.proc->pid);
85 return &event;
Juan Cespedes5e01f651998-03-08 22:31:44 +010086 }
Juan Cespedes1e583132009-04-07 18:17:11 +020087 if (WIFSTOPPED(status) && ((status>>16 == PTRACE_EVENT_FORK) || (status>>16 == PTRACE_EVENT_VFORK) || (status>>16 == PTRACE_EVENT_CLONE))) {
88 unsigned long data;
89 ptrace(PTRACE_GETEVENTMSG, pid, NULL, &data);
90 event.thing = EVENT_FORK;
91 event.e_un.newpid = data;
92 return &event;
93 }
94 /* TODO: check for EVENT_CLONE */
95 if (WIFSTOPPED(status) && (status>>16 == PTRACE_EVENT_EXEC)) {
96 event.thing = EVENT_EXEC;
97 return &event;
98 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010099 if (WIFEXITED(status)) {
Juan Cespedes138d41c2009-04-07 00:49:12 +0200100 event.thing = EVENT_EXIT;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100101 event.e_un.ret_val = WEXITSTATUS(status);
102 return &event;
103 }
104 if (WIFSIGNALED(status)) {
Juan Cespedes138d41c2009-04-07 00:49:12 +0200105 event.thing = EVENT_EXIT_SIGNAL;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100106 event.e_un.signum = WTERMSIG(status);
107 return &event;
108 }
109 if (!WIFSTOPPED(status)) {
Juan Cespedes138d41c2009-04-07 00:49:12 +0200110 event.thing = EVENT_NONE;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100111 return &event;
112 }
Petr Machataef46b3e2007-05-09 19:21:42 +0200113
114 stop_signal = WSTOPSIG(status);
115
116 /* On some targets, breakpoints are signalled not using
117 SIGTRAP, but also with SIGILL, SIGSEGV or SIGEMT. Check
118 for these. */
119 if (stop_signal == SIGSEGV
120 || stop_signal == SIGILL
121#ifdef SIGEMT
122 || stop_signal == SIGEMT
123#endif
124 ) {
125 // If we didn't need to know IP so far, get it now.
126 void * addr = opt_i
127 ? event.proc->instruction_pointer
128 : (event.proc->instruction_pointer = get_instruction_pointer (event.proc));
129
130 if (address2bpstruct(event.proc, addr))
131 stop_signal = SIGTRAP;
132 }
133
134 if (stop_signal != (SIGTRAP | event.proc->tracesysgood)
135 && stop_signal != SIGTRAP) {
Juan Cespedes138d41c2009-04-07 00:49:12 +0200136 event.thing = EVENT_SIGNAL;
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200137 event.e_un.signum = stop_signal;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100138 return &event;
139 }
Petr Machata55ed83b2007-05-17 16:24:15 +0200140
141 if (was_exec(event.proc, status)) {
142 pid_t saved_pid;
143
Juan Cespedes138d41c2009-04-07 00:49:12 +0200144 event.thing = EVENT_NONE;
Petr Machata55ed83b2007-05-17 16:24:15 +0200145 event.e_un.signum = WSTOPSIG(status);
146 debug(1, "Placing breakpoints for the new program");
147 event.proc->mask_32bit = 0;
148 event.proc->personality = 0;
149 event.proc->arch_ptr = NULL;
150 event.proc->filename = pid2name(event.proc->pid);
151 saved_pid = event.proc->pid;
152 event.proc->pid = 0;
153 breakpoints_init(event.proc);
154 event.proc->pid = saved_pid;
155 continue_process(event.proc->pid);
156 return &event;
157 }
158
Juan Cespedes138d41c2009-04-07 00:49:12 +0200159 event.thing = EVENT_BREAKPOINT;
Juan Cespedes35d70631998-03-15 14:05:40 +0100160 if (!event.proc->instruction_pointer) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100161 event.proc->instruction_pointer =
162 get_instruction_pointer(event.proc);
Juan Cespedes35d70631998-03-15 14:05:40 +0100163 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100164 event.e_un.brk_addr =
165 event.proc->instruction_pointer - DECR_PC_AFTER_BREAK;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100166 return &event;
167}