blob: 6dedcc994d257e231780e9fe3ac9826a51c0fa6d [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 Cespedescde58262009-05-07 11:09:00 +020016#include "output.h"
Juan Cespedescac15c32003-01-31 18:58:58 +010017#include "debug.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +010018
Juan Cespedes393f1d02009-05-07 11:13:54 +020019static Event event;
Juan Cespedes5e01f651998-03-08 22:31:44 +010020
Juan Cespedes393f1d02009-05-07 11:13:54 +020021Event *
Juan Cespedese2023f72009-04-07 12:12:08 +020022next_event(void) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010023 pid_t pid;
24 int status;
25 int tmp;
Petr Machataef46b3e2007-05-09 19:21:42 +020026 int stop_signal;
Juan Cespedes5e01f651998-03-08 22:31:44 +010027
Juan Cespedescd8976d2009-05-14 13:47:58 +020028 debug(DEBUG_FUNCTION, "next_event()");
Juan Cespedes28f60191998-04-12 00:04:39 +020029 if (!list_of_processes) {
Juan Cespedescd8976d2009-05-14 13:47:58 +020030 debug(DEBUG_EVENT, "event: No more traced programs: exiting");
Juan Cespedes28f60191998-04-12 00:04:39 +020031 exit(0);
32 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010033 pid = wait(&status);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010034 if (pid == -1) {
35 if (errno == ECHILD) {
Juan Cespedescd8976d2009-05-14 13:47:58 +020036 debug(DEBUG_EVENT, "event: No more traced programs: exiting");
Juan Cespedes5e01f651998-03-08 22:31:44 +010037 exit(0);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010038 } else if (errno == EINTR) {
Juan Cespedescd8976d2009-05-14 13:47:58 +020039 debug(DEBUG_EVENT, "event: none (wait received EINTR?)");
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +020040 event.type = EVENT_NONE;
Juan Cespedes28f60191998-04-12 00:04:39 +020041 return &event;
Juan Cespedes5e01f651998-03-08 22:31:44 +010042 }
43 perror("wait");
44 exit(1);
45 }
46 event.proc = pid2proc(pid);
47 if (!event.proc) {
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +020048 event.type = EVENT_NEW;
Juan Cespedescd8976d2009-05-14 13:47:58 +020049 debug(DEBUG_EVENT, "event: NEW: pid=%d", pid);
Juan Cespedesa8909f72009-04-28 20:02:41 +020050 return &event;
Juan Cespedes5e01f651998-03-08 22:31:44 +010051 }
Juan Cespedes5c3fe062004-06-14 18:08:37 +020052 get_arch_dep(event.proc);
Juan Cespedes35d70631998-03-15 14:05:40 +010053 event.proc->instruction_pointer = NULL;
Juan Cespedes1e583132009-04-07 18:17:11 +020054 debug(3, "event from pid %u", pid);
Juan Cespedes5e01f651998-03-08 22:31:44 +010055 if (event.proc->breakpoints_enabled == -1) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010056 enable_all_breakpoints(event.proc);
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +020057 event.type = EVENT_NONE;
Ian Wienand9a2ad352006-02-20 22:44:45 +010058 trace_set_options(event.proc, event.proc->pid);
Juan Cespedes5e01f651998-03-08 22:31:44 +010059 continue_process(event.proc->pid);
Juan Cespedescd8976d2009-05-14 13:47:58 +020060 debug(DEBUG_EVENT, "event: NONE: pid=%d (enabling breakpoints)", pid);
Juan Cespedes5e01f651998-03-08 22:31:44 +010061 return &event;
62 }
Juan Cespedes35d70631998-03-15 14:05:40 +010063 if (opt_i) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010064 event.proc->instruction_pointer =
65 get_instruction_pointer(event.proc);
Juan Cespedesf0fdae91998-03-11 00:03:00 +010066 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +010067 switch (syscall_p(event.proc, status, &tmp)) {
Juan Cespedes63184be2008-12-10 13:30:12 +010068 case 1:
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +020069 event.type = EVENT_SYSCALL;
Juan Cespedes63184be2008-12-10 13:30:12 +010070 event.e_un.sysnum = tmp;
Juan Cespedescd8976d2009-05-14 13:47:58 +020071 debug(DEBUG_EVENT, "event: SYSCALL: pid=%d, sysnum=%d", pid, tmp);
Juan Cespedes63184be2008-12-10 13:30:12 +010072 return &event;
73 case 2:
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +020074 event.type = EVENT_SYSRET;
Juan Cespedes63184be2008-12-10 13:30:12 +010075 event.e_un.sysnum = tmp;
Juan Cespedescd8976d2009-05-14 13:47:58 +020076 debug(DEBUG_EVENT, "event: SYSRET: pid=%d, sysnum=%d", pid, tmp);
Juan Cespedes63184be2008-12-10 13:30:12 +010077 return &event;
78 case 3:
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +020079 event.type = EVENT_ARCH_SYSCALL;
Juan Cespedes63184be2008-12-10 13:30:12 +010080 event.e_un.sysnum = tmp;
Juan Cespedescd8976d2009-05-14 13:47:58 +020081 debug(DEBUG_EVENT, "event: ARCH_SYSCALL: pid=%d, sysnum=%d", pid, tmp);
Juan Cespedes63184be2008-12-10 13:30:12 +010082 return &event;
83 case 4:
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +020084 event.type = EVENT_ARCH_SYSRET;
Juan Cespedes63184be2008-12-10 13:30:12 +010085 event.e_un.sysnum = tmp;
Juan Cespedescd8976d2009-05-14 13:47:58 +020086 debug(DEBUG_EVENT, "event: ARCH_SYSRET: pid=%d, sysnum=%d", pid, tmp);
Juan Cespedes63184be2008-12-10 13:30:12 +010087 return &event;
88 case -1:
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +020089 event.type = EVENT_NONE;
Juan Cespedes63184be2008-12-10 13:30:12 +010090 continue_process(event.proc->pid);
Juan Cespedescd8976d2009-05-14 13:47:58 +020091 debug(DEBUG_EVENT, "event: NONE: pid=%d (syscall_p returned -1)", pid);
Juan Cespedes63184be2008-12-10 13:30:12 +010092 return &event;
Juan Cespedes5e01f651998-03-08 22:31:44 +010093 }
Juan Cespedes1e583132009-04-07 18:17:11 +020094 if (WIFSTOPPED(status) && ((status>>16 == PTRACE_EVENT_FORK) || (status>>16 == PTRACE_EVENT_VFORK) || (status>>16 == PTRACE_EVENT_CLONE))) {
95 unsigned long data;
96 ptrace(PTRACE_GETEVENTMSG, pid, NULL, &data);
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +020097 event.type = EVENT_CLONE;
Juan Cespedes1e583132009-04-07 18:17:11 +020098 event.e_un.newpid = data;
Juan Cespedescd8976d2009-05-14 13:47:58 +020099 debug(DEBUG_EVENT, "event: CLONE: pid=%d, newpid=%d", pid, (int)data);
Juan Cespedes1e583132009-04-07 18:17:11 +0200100 return &event;
101 }
Juan Cespedes1e583132009-04-07 18:17:11 +0200102 if (WIFSTOPPED(status) && (status>>16 == PTRACE_EVENT_EXEC)) {
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +0200103 event.type = EVENT_EXEC;
Juan Cespedescd8976d2009-05-14 13:47:58 +0200104 debug(DEBUG_EVENT, "event: EXEC: pid=%d", pid);
Juan Cespedes1e583132009-04-07 18:17:11 +0200105 return &event;
106 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100107 if (WIFEXITED(status)) {
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +0200108 event.type = EVENT_EXIT;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100109 event.e_un.ret_val = WEXITSTATUS(status);
Juan Cespedescd8976d2009-05-14 13:47:58 +0200110 debug(DEBUG_EVENT, "event: EXIT: pid=%d, status=%d", pid, event.e_un.ret_val);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100111 return &event;
112 }
113 if (WIFSIGNALED(status)) {
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +0200114 event.type = EVENT_EXIT_SIGNAL;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100115 event.e_un.signum = WTERMSIG(status);
Juan Cespedescd8976d2009-05-14 13:47:58 +0200116 debug(DEBUG_EVENT, "event: EXIT_SIGNAL: pid=%d, signum=%d", pid, event.e_un.signum);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100117 return &event;
118 }
119 if (!WIFSTOPPED(status)) {
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +0200120 event.type = EVENT_NONE;
Juan Cespedescd8976d2009-05-14 13:47:58 +0200121 debug(DEBUG_EVENT, "event: NONE: pid=%d (wait error?)", pid);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100122 return &event;
123 }
Petr Machataef46b3e2007-05-09 19:21:42 +0200124
125 stop_signal = WSTOPSIG(status);
126
127 /* On some targets, breakpoints are signalled not using
128 SIGTRAP, but also with SIGILL, SIGSEGV or SIGEMT. Check
129 for these. */
130 if (stop_signal == SIGSEGV
131 || stop_signal == SIGILL
132#ifdef SIGEMT
133 || stop_signal == SIGEMT
134#endif
135 ) {
136 // If we didn't need to know IP so far, get it now.
137 void * addr = opt_i
138 ? event.proc->instruction_pointer
139 : (event.proc->instruction_pointer = get_instruction_pointer (event.proc));
140
141 if (address2bpstruct(event.proc, addr))
142 stop_signal = SIGTRAP;
143 }
144
145 if (stop_signal != (SIGTRAP | event.proc->tracesysgood)
146 && stop_signal != SIGTRAP) {
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +0200147 event.type = EVENT_SIGNAL;
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200148 event.e_un.signum = stop_signal;
Juan Cespedescd8976d2009-05-14 13:47:58 +0200149 debug(DEBUG_EVENT, "event: SIGNAL: pid=%d, signum=%d", pid, stop_signal);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100150 return &event;
151 }
Petr Machata55ed83b2007-05-17 16:24:15 +0200152
153 if (was_exec(event.proc, status)) {
154 pid_t saved_pid;
155
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +0200156 event.type = EVENT_NONE;
Petr Machata55ed83b2007-05-17 16:24:15 +0200157 event.e_un.signum = WSTOPSIG(status);
158 debug(1, "Placing breakpoints for the new program");
159 event.proc->mask_32bit = 0;
160 event.proc->personality = 0;
161 event.proc->arch_ptr = NULL;
162 event.proc->filename = pid2name(event.proc->pid);
163 saved_pid = event.proc->pid;
164 event.proc->pid = 0;
165 breakpoints_init(event.proc);
166 event.proc->pid = saved_pid;
167 continue_process(event.proc->pid);
Juan Cespedescd8976d2009-05-14 13:47:58 +0200168 debug(DEBUG_EVENT, "event: NONE: pid=%d (was_exec; placed breakpoints)", pid);
Petr Machata55ed83b2007-05-17 16:24:15 +0200169 return &event;
170 }
171
Juan Cespedes8f6d1ec2009-05-07 17:50:34 +0200172 event.type = EVENT_BREAKPOINT;
Juan Cespedes35d70631998-03-15 14:05:40 +0100173 if (!event.proc->instruction_pointer) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100174 event.proc->instruction_pointer =
175 get_instruction_pointer(event.proc);
Juan Cespedes35d70631998-03-15 14:05:40 +0100176 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100177 event.e_un.brk_addr =
178 event.proc->instruction_pointer - DECR_PC_AFTER_BREAK;
Juan Cespedescd8976d2009-05-14 13:47:58 +0200179 debug(DEBUG_EVENT, "event: BREAKPOINT: pid=%d, addr=%p", pid, event.e_un.brk_addr);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100180 return &event;
181}