blob: afe6a9665997a13e7b96cd7c27f82c59f86ec070 [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>
12
13#include "ltrace.h"
14#include "options.h"
Juan Cespedescac15c32003-01-31 18:58:58 +010015#include "debug.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +010016
17static struct event event;
18
Juan Cespedesf1350522008-12-16 18:19:58 +010019struct event *
Juan Cespedese2023f72009-04-07 12:12:08 +020020next_event(void) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010021 pid_t pid;
22 int status;
23 int tmp;
Petr Machataef46b3e2007-05-09 19:21:42 +020024 int stop_signal;
Juan Cespedes5e01f651998-03-08 22:31:44 +010025
Juan Cespedes28f60191998-04-12 00:04:39 +020026 if (!list_of_processes) {
Juan Cespedescac15c32003-01-31 18:58:58 +010027 debug(1, "No more children");
Juan Cespedes28f60191998-04-12 00:04:39 +020028 exit(0);
29 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010030 pid = wait(&status);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010031 if (pid == -1) {
32 if (errno == ECHILD) {
Juan Cespedescac15c32003-01-31 18:58:58 +010033 debug(1, "No more children");
Juan Cespedes5e01f651998-03-08 22:31:44 +010034 exit(0);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010035 } else if (errno == EINTR) {
Juan Cespedescac15c32003-01-31 18:58:58 +010036 debug(1, "wait received EINTR ?");
Juan Cespedes138d41c2009-04-07 00:49:12 +020037 event.thing = EVENT_NONE;
Juan Cespedes28f60191998-04-12 00:04:39 +020038 return &event;
Juan Cespedes5e01f651998-03-08 22:31:44 +010039 }
40 perror("wait");
41 exit(1);
42 }
43 event.proc = pid2proc(pid);
44 if (!event.proc) {
45 fprintf(stderr, "signal from wrong pid %u ?!?\n", pid);
46 exit(1);
47 }
Juan Cespedes5c3fe062004-06-14 18:08:37 +020048 get_arch_dep(event.proc);
Juan Cespedes35d70631998-03-15 14:05:40 +010049 event.proc->instruction_pointer = NULL;
Juan Cespedescac15c32003-01-31 18:58:58 +010050 debug(3, "signal from pid %u", pid);
Juan Cespedes5e01f651998-03-08 22:31:44 +010051 if (event.proc->breakpoints_enabled == -1) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010052 enable_all_breakpoints(event.proc);
Juan Cespedes138d41c2009-04-07 00:49:12 +020053 event.thing = EVENT_NONE;
Ian Wienand9a2ad352006-02-20 22:44:45 +010054 trace_set_options(event.proc, event.proc->pid);
Juan Cespedes5e01f651998-03-08 22:31:44 +010055 continue_process(event.proc->pid);
56 return &event;
57 }
Juan Cespedes35d70631998-03-15 14:05:40 +010058 if (opt_i) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010059 event.proc->instruction_pointer =
60 get_instruction_pointer(event.proc);
Juan Cespedesf0fdae91998-03-11 00:03:00 +010061 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +010062 switch (syscall_p(event.proc, status, &tmp)) {
Juan Cespedes63184be2008-12-10 13:30:12 +010063 case 1:
Juan Cespedes138d41c2009-04-07 00:49:12 +020064 event.thing = EVENT_SYSCALL;
Juan Cespedes63184be2008-12-10 13:30:12 +010065 event.e_un.sysnum = tmp;
66 return &event;
67 case 2:
Juan Cespedes138d41c2009-04-07 00:49:12 +020068 event.thing = EVENT_SYSRET;
Juan Cespedes63184be2008-12-10 13:30:12 +010069 event.e_un.sysnum = tmp;
70 return &event;
71 case 3:
Juan Cespedes138d41c2009-04-07 00:49:12 +020072 event.thing = EVENT_ARCH_SYSCALL;
Juan Cespedes63184be2008-12-10 13:30:12 +010073 event.e_un.sysnum = tmp;
74 return &event;
75 case 4:
Juan Cespedes138d41c2009-04-07 00:49:12 +020076 event.thing = EVENT_ARCH_SYSRET;
Juan Cespedes63184be2008-12-10 13:30:12 +010077 event.e_un.sysnum = tmp;
78 return &event;
79 case -1:
Juan Cespedes138d41c2009-04-07 00:49:12 +020080 event.thing = EVENT_NONE;
Juan Cespedes63184be2008-12-10 13:30:12 +010081 continue_process(event.proc->pid);
82 return &event;
Juan Cespedes5e01f651998-03-08 22:31:44 +010083 }
84 if (WIFEXITED(status)) {
Juan Cespedes138d41c2009-04-07 00:49:12 +020085 event.thing = EVENT_EXIT;
Juan Cespedes5e01f651998-03-08 22:31:44 +010086 event.e_un.ret_val = WEXITSTATUS(status);
87 return &event;
88 }
89 if (WIFSIGNALED(status)) {
Juan Cespedes138d41c2009-04-07 00:49:12 +020090 event.thing = EVENT_EXIT_SIGNAL;
Juan Cespedes5e01f651998-03-08 22:31:44 +010091 event.e_un.signum = WTERMSIG(status);
92 return &event;
93 }
94 if (!WIFSTOPPED(status)) {
Juan Cespedes138d41c2009-04-07 00:49:12 +020095 event.thing = EVENT_NONE;
Juan Cespedes5e01f651998-03-08 22:31:44 +010096 return &event;
97 }
Petr Machataef46b3e2007-05-09 19:21:42 +020098
99 stop_signal = WSTOPSIG(status);
100
101 /* On some targets, breakpoints are signalled not using
102 SIGTRAP, but also with SIGILL, SIGSEGV or SIGEMT. Check
103 for these. */
104 if (stop_signal == SIGSEGV
105 || stop_signal == SIGILL
106#ifdef SIGEMT
107 || stop_signal == SIGEMT
108#endif
109 ) {
110 // If we didn't need to know IP so far, get it now.
111 void * addr = opt_i
112 ? event.proc->instruction_pointer
113 : (event.proc->instruction_pointer = get_instruction_pointer (event.proc));
114
115 if (address2bpstruct(event.proc, addr))
116 stop_signal = SIGTRAP;
117 }
118
119 if (stop_signal != (SIGTRAP | event.proc->tracesysgood)
120 && stop_signal != SIGTRAP) {
Juan Cespedes138d41c2009-04-07 00:49:12 +0200121 event.thing = EVENT_SIGNAL;
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200122 event.e_un.signum = stop_signal;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100123 return &event;
124 }
Petr Machata55ed83b2007-05-17 16:24:15 +0200125
126 if (was_exec(event.proc, status)) {
127 pid_t saved_pid;
128
Juan Cespedes138d41c2009-04-07 00:49:12 +0200129 event.thing = EVENT_NONE;
Petr Machata55ed83b2007-05-17 16:24:15 +0200130 event.e_un.signum = WSTOPSIG(status);
131 debug(1, "Placing breakpoints for the new program");
132 event.proc->mask_32bit = 0;
133 event.proc->personality = 0;
134 event.proc->arch_ptr = NULL;
135 event.proc->filename = pid2name(event.proc->pid);
136 saved_pid = event.proc->pid;
137 event.proc->pid = 0;
138 breakpoints_init(event.proc);
139 event.proc->pid = saved_pid;
140 continue_process(event.proc->pid);
141 return &event;
142 }
143
Juan Cespedes138d41c2009-04-07 00:49:12 +0200144 event.thing = EVENT_BREAKPOINT;
Juan Cespedes35d70631998-03-15 14:05:40 +0100145 if (!event.proc->instruction_pointer) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100146 event.proc->instruction_pointer =
147 get_instruction_pointer(event.proc);
Juan Cespedes35d70631998-03-15 14:05:40 +0100148 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100149 event.e_un.brk_addr =
150 event.proc->instruction_pointer - DECR_PC_AFTER_BREAK;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100151 return &event;
152}