blob: 94406527c2efcd2e0081ab7fd03cea9554d7b0ae [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
19/* This should also update `current_process' */
20
Ian Wienand2d45b1a2006-02-20 22:48:07 +010021static struct process *pid2proc(int pid);
Juan Cespedes5e01f651998-03-08 22:31:44 +010022
Ian Wienand2d45b1a2006-02-20 22:48:07 +010023struct event *wait_for_something(void)
24{
Juan Cespedes5e01f651998-03-08 22:31:44 +010025 pid_t pid;
26 int status;
27 int tmp;
Petr Machataef46b3e2007-05-09 19:21:42 +020028 int stop_signal;
Juan Cespedes5e01f651998-03-08 22:31:44 +010029
Juan Cespedes28f60191998-04-12 00:04:39 +020030 if (!list_of_processes) {
Juan Cespedescac15c32003-01-31 18:58:58 +010031 debug(1, "No more children");
Juan Cespedes28f60191998-04-12 00:04:39 +020032 exit(0);
33 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010034 pid = wait(&status);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010035 if (pid == -1) {
36 if (errno == ECHILD) {
Juan Cespedescac15c32003-01-31 18:58:58 +010037 debug(1, "No more children");
Juan Cespedes5e01f651998-03-08 22:31:44 +010038 exit(0);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010039 } else if (errno == EINTR) {
Juan Cespedescac15c32003-01-31 18:58:58 +010040 debug(1, "wait received EINTR ?");
Juan Cespedes28f60191998-04-12 00:04:39 +020041 event.thing = LT_EV_NONE;
42 return &event;
Juan Cespedes5e01f651998-03-08 22:31:44 +010043 }
44 perror("wait");
45 exit(1);
46 }
47 event.proc = pid2proc(pid);
48 if (!event.proc) {
49 fprintf(stderr, "signal from wrong pid %u ?!?\n", pid);
50 exit(1);
51 }
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 Cespedescac15c32003-01-31 18:58:58 +010054 debug(3, "signal 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);
57 event.thing = LT_EV_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);
60 return &event;
61 }
Juan Cespedes35d70631998-03-15 14:05:40 +010062 if (opt_i) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010063 event.proc->instruction_pointer =
64 get_instruction_pointer(event.proc);
Juan Cespedesf0fdae91998-03-11 00:03:00 +010065 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +010066 switch (syscall_p(event.proc, status, &tmp)) {
Juan Cespedes63184be2008-12-10 13:30:12 +010067 case 1:
68 event.thing = LT_EV_SYSCALL;
69 event.e_un.sysnum = tmp;
70 return &event;
71 case 2:
72 event.thing = LT_EV_SYSRET;
73 event.e_un.sysnum = tmp;
74 return &event;
75 case 3:
76 event.thing = LT_EV_ARCH_SYSCALL;
77 event.e_un.sysnum = tmp;
78 return &event;
79 case 4:
80 event.thing = LT_EV_ARCH_SYSRET;
81 event.e_un.sysnum = tmp;
82 return &event;
83 case -1:
84 event.thing = LT_EV_NONE;
85 continue_process(event.proc->pid);
86 return &event;
Juan Cespedes5e01f651998-03-08 22:31:44 +010087 }
88 if (WIFEXITED(status)) {
89 event.thing = LT_EV_EXIT;
90 event.e_un.ret_val = WEXITSTATUS(status);
91 return &event;
92 }
93 if (WIFSIGNALED(status)) {
94 event.thing = LT_EV_EXIT_SIGNAL;
95 event.e_un.signum = WTERMSIG(status);
96 return &event;
97 }
98 if (!WIFSTOPPED(status)) {
99 event.thing = LT_EV_UNKNOWN;
100 return &event;
101 }
Petr Machataef46b3e2007-05-09 19:21:42 +0200102
103 stop_signal = WSTOPSIG(status);
104
105 /* On some targets, breakpoints are signalled not using
106 SIGTRAP, but also with SIGILL, SIGSEGV or SIGEMT. Check
107 for these. */
108 if (stop_signal == SIGSEGV
109 || stop_signal == SIGILL
110#ifdef SIGEMT
111 || stop_signal == SIGEMT
112#endif
113 ) {
114 // If we didn't need to know IP so far, get it now.
115 void * addr = opt_i
116 ? event.proc->instruction_pointer
117 : (event.proc->instruction_pointer = get_instruction_pointer (event.proc));
118
119 if (address2bpstruct(event.proc, addr))
120 stop_signal = SIGTRAP;
121 }
122
123 if (stop_signal != (SIGTRAP | event.proc->tracesysgood)
124 && stop_signal != SIGTRAP) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100125 event.thing = LT_EV_SIGNAL;
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200126 event.e_un.signum = stop_signal;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100127 return &event;
128 }
Petr Machata55ed83b2007-05-17 16:24:15 +0200129
130 if (was_exec(event.proc, status)) {
131 pid_t saved_pid;
132
133 event.thing = LT_EV_NONE;
134 event.e_un.signum = WSTOPSIG(status);
135 debug(1, "Placing breakpoints for the new program");
136 event.proc->mask_32bit = 0;
137 event.proc->personality = 0;
138 event.proc->arch_ptr = NULL;
139 event.proc->filename = pid2name(event.proc->pid);
140 saved_pid = event.proc->pid;
141 event.proc->pid = 0;
142 breakpoints_init(event.proc);
143 event.proc->pid = saved_pid;
144 continue_process(event.proc->pid);
145 return &event;
146 }
147
Juan Cespedes5e01f651998-03-08 22:31:44 +0100148 event.thing = LT_EV_BREAKPOINT;
Juan Cespedes35d70631998-03-15 14:05:40 +0100149 if (!event.proc->instruction_pointer) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100150 event.proc->instruction_pointer =
151 get_instruction_pointer(event.proc);
Juan Cespedes35d70631998-03-15 14:05:40 +0100152 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100153 event.e_un.brk_addr =
154 event.proc->instruction_pointer - DECR_PC_AFTER_BREAK;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100155 return &event;
156}
157
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100158static struct process *pid2proc(pid_t pid)
159{
160 struct process *tmp;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100161
162 tmp = list_of_processes;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100163 while (tmp) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100164 if (pid == tmp->pid) {
165 return tmp;
166 }
167 tmp = tmp->next;
168 }
169 return NULL;
170}