blob: 1192c7863915fcc95e51edbed994266346132cfa [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;
28
Juan Cespedes28f60191998-04-12 00:04:39 +020029 if (!list_of_processes) {
Juan Cespedescac15c32003-01-31 18:58:58 +010030 debug(1, "No more children");
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 Cespedescac15c32003-01-31 18:58:58 +010036 debug(1, "No more children");
Juan Cespedes5e01f651998-03-08 22:31:44 +010037 exit(0);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010038 } else if (errno == EINTR) {
Juan Cespedescac15c32003-01-31 18:58:58 +010039 debug(1, "wait received EINTR ?");
Juan Cespedes28f60191998-04-12 00:04:39 +020040 event.thing = LT_EV_NONE;
41 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) {
48 fprintf(stderr, "signal from wrong pid %u ?!?\n", pid);
49 exit(1);
50 }
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 Cespedescac15c32003-01-31 18:58:58 +010053 debug(3, "signal 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);
56 event.thing = LT_EV_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)) {
66 case 1:
67 event.thing = LT_EV_SYSCALL;
68 event.e_un.sysnum = tmp;
69 return &event;
70 case 2:
71 event.thing = LT_EV_SYSRET;
72 event.e_un.sysnum = tmp;
73 return &event;
Juan Cespedes5e01f651998-03-08 22:31:44 +010074 }
75 if (WIFEXITED(status)) {
76 event.thing = LT_EV_EXIT;
77 event.e_un.ret_val = WEXITSTATUS(status);
78 return &event;
79 }
80 if (WIFSIGNALED(status)) {
81 event.thing = LT_EV_EXIT_SIGNAL;
82 event.e_un.signum = WTERMSIG(status);
83 return &event;
84 }
85 if (!WIFSTOPPED(status)) {
86 event.thing = LT_EV_UNKNOWN;
87 return &event;
88 }
Ian Wienand9a2ad352006-02-20 22:44:45 +010089 if ((WSTOPSIG(status) != (SIGTRAP | event.proc->tracesysgood)) &&
90 (WSTOPSIG(status) != SIGTRAP)) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010091 event.thing = LT_EV_SIGNAL;
92 event.e_un.signum = WSTOPSIG(status);
93 return &event;
94 }
95 event.thing = LT_EV_BREAKPOINT;
Juan Cespedes35d70631998-03-15 14:05:40 +010096 if (!event.proc->instruction_pointer) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010097 event.proc->instruction_pointer =
98 get_instruction_pointer(event.proc);
Juan Cespedes35d70631998-03-15 14:05:40 +010099 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100100 event.e_un.brk_addr =
101 event.proc->instruction_pointer - DECR_PC_AFTER_BREAK;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100102 return &event;
103}
104
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100105static struct process *pid2proc(pid_t pid)
106{
107 struct process *tmp;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100108
109 tmp = list_of_processes;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100110 while (tmp) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100111 if (pid == tmp->pid) {
112 return tmp;
113 }
114 tmp = tmp->next;
115 }
116 return NULL;
117}