blob: f3c966de1c6dbf129b720ccd7a310920ca121f06 [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
6#include <stdio.h>
7#include <string.h>
Juan Cespedes1fe93d51998-03-13 00:29:21 +01008#include <stdlib.h>
Juan Cespedes28f60191998-04-12 00:04:39 +02009#include <signal.h>
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020010#include <assert.h>
Juan Cespedesd65efa32003-02-03 00:22:30 +010011#include <sys/time.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +010012
13#include "ltrace.h"
14#include "output.h"
15#include "options.h"
Juan Cespedes81690ef1998-03-13 19:31:29 +010016#include "elf.h"
Juan Cespedescac15c32003-01-31 18:58:58 +010017#include "debug.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +010018
Juan Cespedesf1bfe202002-03-27 00:22:23 +010019#ifdef __powerpc__
20#include <sys/ptrace.h>
21#endif
22
Ian Wienand2d45b1a2006-02-20 22:48:07 +010023static void process_signal(struct event *event);
24static void process_exit(struct event *event);
25static void process_exit_signal(struct event *event);
26static void process_syscall(struct event *event);
Juan Cespedes63184be2008-12-10 13:30:12 +010027static void process_arch_syscall(struct event *event);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010028static void process_sysret(struct event *event);
Juan Cespedes63184be2008-12-10 13:30:12 +010029static void process_arch_sysret(struct event *event);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010030static void process_breakpoint(struct event *event);
31static void remove_proc(struct process *proc);
Juan Cespedes5e01f651998-03-08 22:31:44 +010032
Ian Wienand2d45b1a2006-02-20 22:48:07 +010033static void callstack_push_syscall(struct process *proc, int sysnum);
34static void callstack_push_symfunc(struct process *proc,
35 struct library_symbol *sym);
36static void callstack_pop(struct process *proc);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020037
Juan Cespedesf1350522008-12-16 18:19:58 +010038static char *
39shortsignal(struct process *proc, int signum) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010040 static char *signalent0[] = {
41#include "signalent.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +010042 };
Ian Wienand2d45b1a2006-02-20 22:48:07 +010043 static char *signalent1[] = {
44#include "signalent1.h"
Ian Wienand9a2ad352006-02-20 22:44:45 +010045 };
46 static char **signalents[] = { signalent0, signalent1 };
47 int nsignals[] = { sizeof signalent0 / sizeof signalent0[0],
Ian Wienand2d45b1a2006-02-20 22:48:07 +010048 sizeof signalent1 / sizeof signalent1[0]
49 };
Juan Cespedes5e01f651998-03-08 22:31:44 +010050
Ian Wienand9a2ad352006-02-20 22:44:45 +010051 if (proc->personality > sizeof signalents / sizeof signalents[0])
Ian Wienand2d45b1a2006-02-20 22:48:07 +010052 abort();
Ian Wienand9a2ad352006-02-20 22:44:45 +010053 if (signum < 0 || signum >= nsignals[proc->personality]) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010054 return "UNKNOWN_SIGNAL";
55 } else {
Ian Wienand9a2ad352006-02-20 22:44:45 +010056 return signalents[proc->personality][signum];
Juan Cespedes5e01f651998-03-08 22:31:44 +010057 }
58}
59
Juan Cespedesf1350522008-12-16 18:19:58 +010060static char *
61sysname(struct process *proc, int sysnum) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010062 static char result[128];
Ian Wienand2d45b1a2006-02-20 22:48:07 +010063 static char *syscalent0[] = {
64#include "syscallent.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +010065 };
Ian Wienand2d45b1a2006-02-20 22:48:07 +010066 static char *syscalent1[] = {
67#include "syscallent1.h"
Ian Wienand9a2ad352006-02-20 22:44:45 +010068 };
69 static char **syscalents[] = { syscalent0, syscalent1 };
70 int nsyscals[] = { sizeof syscalent0 / sizeof syscalent0[0],
Ian Wienand2d45b1a2006-02-20 22:48:07 +010071 sizeof syscalent1 / sizeof syscalent1[0]
72 };
Juan Cespedes5e01f651998-03-08 22:31:44 +010073
Ian Wienand9a2ad352006-02-20 22:44:45 +010074 if (proc->personality > sizeof syscalents / sizeof syscalents[0])
Ian Wienand2d45b1a2006-02-20 22:48:07 +010075 abort();
Ian Wienand9a2ad352006-02-20 22:44:45 +010076 if (sysnum < 0 || sysnum >= nsyscals[proc->personality]) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010077 sprintf(result, "SYS_%d", sysnum);
78 return result;
79 } else {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010080 sprintf(result, "SYS_%s",
81 syscalents[proc->personality][sysnum]);
Juan Cespedes5e01f651998-03-08 22:31:44 +010082 return result;
83 }
84}
85
Juan Cespedesf1350522008-12-16 18:19:58 +010086static char *
87arch_sysname(struct process *proc, int sysnum) {
Juan Cespedes63184be2008-12-10 13:30:12 +010088 static char result[128];
89 static char *arch_syscalent[] = {
90#include "arch_syscallent.h"
91 };
92 int nsyscals = sizeof arch_syscalent / sizeof arch_syscalent[0];
93
94 if (sysnum < 0 || sysnum >= nsyscals) {
95 sprintf(result, "ARCH_%d", sysnum);
96 return result;
97 } else {
98 sprintf(result, "ARCH_%s",
99 arch_syscalent[sysnum]);
100 return result;
101 }
102}
103
Juan Cespedesf1350522008-12-16 18:19:58 +0100104void
105process_event(struct event *event) {
Juan Cespedesefe85f02004-04-04 01:31:38 +0200106 switch (event->thing) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100107 case LT_EV_NONE:
108 debug(1, "event: none");
109 return;
110 case LT_EV_SIGNAL:
111 debug(1, "event: signal (%s [%d])",
112 shortsignal(event->proc, event->e_un.signum),
113 event->e_un.signum);
114 process_signal(event);
115 return;
116 case LT_EV_EXIT:
117 debug(1, "event: exit (%d)", event->e_un.ret_val);
118 process_exit(event);
119 return;
120 case LT_EV_EXIT_SIGNAL:
121 debug(1, "event: exit signal (%s [%d])",
122 shortsignal(event->proc, event->e_un.signum),
123 event->e_un.signum);
124 process_exit_signal(event);
125 return;
126 case LT_EV_SYSCALL:
127 debug(1, "event: syscall (%s [%d])",
128 sysname(event->proc, event->e_un.sysnum),
129 event->e_un.sysnum);
130 process_syscall(event);
131 return;
132 case LT_EV_SYSRET:
133 debug(1, "event: sysret (%s [%d])",
134 sysname(event->proc, event->e_un.sysnum),
135 event->e_un.sysnum);
136 process_sysret(event);
137 return;
Juan Cespedes63184be2008-12-10 13:30:12 +0100138 case LT_EV_ARCH_SYSCALL:
139 debug(1, "event: arch_syscall (%s [%d])",
140 arch_sysname(event->proc, event->e_un.sysnum),
141 event->e_un.sysnum);
142 process_arch_syscall(event);
143 return;
144 case LT_EV_ARCH_SYSRET:
145 debug(1, "event: arch_sysret (%s [%d])",
146 arch_sysname(event->proc, event->e_un.sysnum),
147 event->e_un.sysnum);
148 process_arch_sysret(event);
149 return;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100150 case LT_EV_BREAKPOINT:
151 debug(1, "event: breakpoint");
152 process_breakpoint(event);
153 return;
154 default:
155 fprintf(stderr, "Error! unknown event?\n");
156 exit(1);
Juan Cespedesefe85f02004-04-04 01:31:38 +0200157 }
158}
159
Juan Cespedesf1350522008-12-16 18:19:58 +0100160static void
161process_signal(struct event *event) {
Juan Cespedes28f60191998-04-12 00:04:39 +0200162 if (exiting && event->e_un.signum == SIGSTOP) {
163 pid_t pid = event->proc->pid;
164 disable_all_breakpoints(event->proc);
165 untrace_pid(pid);
166 remove_proc(event->proc);
167 continue_after_signal(pid, event->e_un.signum);
168 return;
169 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100170 output_line(event->proc, "--- %s (%s) ---",
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100171 shortsignal(event->proc, event->e_un.signum),
172 strsignal(event->e_un.signum));
Juan Cespedes5e01f651998-03-08 22:31:44 +0100173 continue_after_signal(event->proc->pid, event->e_un.signum);
174}
175
Juan Cespedesf1350522008-12-16 18:19:58 +0100176static void
177process_exit(struct event *event) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100178 output_line(event->proc, "+++ exited (status %d) +++",
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100179 event->e_un.ret_val);
Juan Cespedes1fe93d51998-03-13 00:29:21 +0100180 remove_proc(event->proc);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100181}
182
Juan Cespedesf1350522008-12-16 18:19:58 +0100183static void
184process_exit_signal(struct event *event) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100185 output_line(event->proc, "+++ killed by %s +++",
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100186 shortsignal(event->proc, event->e_un.signum));
Juan Cespedes1fe93d51998-03-13 00:29:21 +0100187 remove_proc(event->proc);
188}
189
Juan Cespedesf1350522008-12-16 18:19:58 +0100190static void
191remove_proc(struct process *proc) {
Juan Cespedes1fe93d51998-03-13 00:29:21 +0100192 struct process *tmp, *tmp2;
193
Juan Cespedescac15c32003-01-31 18:58:58 +0100194 debug(1, "Removing pid %u\n", proc->pid);
Juan Cespedes28f60191998-04-12 00:04:39 +0200195
Juan Cespedes1fe93d51998-03-13 00:29:21 +0100196 if (list_of_processes == proc) {
197 tmp = list_of_processes;
198 list_of_processes = list_of_processes->next;
199 free(tmp);
200 return;
201 }
202 tmp = list_of_processes;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100203 while (tmp->next) {
204 if (tmp->next == proc) {
Juan Cespedes1fe93d51998-03-13 00:29:21 +0100205 tmp2 = tmp->next;
206 tmp->next = tmp->next->next;
207 free(tmp2);
Juan Cespedes28f60191998-04-12 00:04:39 +0200208 continue;
Juan Cespedes1fe93d51998-03-13 00:29:21 +0100209 }
Juan Cespedes35d70631998-03-15 14:05:40 +0100210 tmp = tmp->next;
Juan Cespedes1fe93d51998-03-13 00:29:21 +0100211 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100212}
213
Juan Cespedesf1350522008-12-16 18:19:58 +0100214static void
215process_syscall(struct event *event) {
Juan Cespedesce377d52008-12-16 19:38:10 +0100216 if (options.syscalls) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100217 output_left(LT_TOF_SYSCALL, event->proc,
218 sysname(event->proc, event->e_un.sysnum));
Juan Cespedes5e01f651998-03-08 22:31:44 +0100219 }
Juan Cespedesaee09312007-08-31 18:49:48 +0200220 if (fork_p(event->proc, event->e_un.sysnum)) {
221 disable_all_breakpoints(event->proc);
222 } else if (event->proc->breakpoints_enabled == 0) {
Juan Cespedes81690ef1998-03-13 19:31:29 +0100223 enable_all_breakpoints(event->proc);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100224 }
Juan Cespedesd65efa32003-02-03 00:22:30 +0100225 callstack_push_syscall(event->proc, event->e_un.sysnum);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100226 continue_process(event->proc->pid);
227}
228
Juan Cespedesf1350522008-12-16 18:19:58 +0100229static void
230process_arch_syscall(struct event *event) {
Juan Cespedesce377d52008-12-16 19:38:10 +0100231 if (options.syscalls) {
Juan Cespedes63184be2008-12-10 13:30:12 +0100232 output_left(LT_TOF_SYSCALL, event->proc,
233 arch_sysname(event->proc, event->e_un.sysnum));
234 }
235 if (event->proc->breakpoints_enabled == 0) {
236 enable_all_breakpoints(event->proc);
237 }
238 callstack_push_syscall(event->proc, 0xf0000 + event->e_un.sysnum);
239 continue_process(event->proc->pid);
240}
241
Juan Cespedesd65efa32003-02-03 00:22:30 +0100242struct timeval current_time_spent;
243
Juan Cespedesf1350522008-12-16 18:19:58 +0100244static void
245calc_time_spent(struct process *proc) {
Juan Cespedesd65efa32003-02-03 00:22:30 +0100246 struct timeval tv;
247 struct timezone tz;
248 struct timeval diff;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100249 struct callstack_element *elem;
Juan Cespedesd65efa32003-02-03 00:22:30 +0100250
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100251 elem = &proc->callstack[proc->callstack_depth - 1];
Juan Cespedesd65efa32003-02-03 00:22:30 +0100252
253 gettimeofday(&tv, &tz);
254
255 diff.tv_sec = tv.tv_sec - elem->time_spent.tv_sec;
256 if (tv.tv_usec >= elem->time_spent.tv_usec) {
257 diff.tv_usec = tv.tv_usec - elem->time_spent.tv_usec;
258 } else {
259 diff.tv_sec++;
260 diff.tv_usec = 1000000 + tv.tv_usec - elem->time_spent.tv_usec;
261 }
262 current_time_spent = diff;
263}
264
Juan Cespedesf1350522008-12-16 18:19:58 +0100265static void
266process_sysret(struct event *event) {
Juan Cespedesd65efa32003-02-03 00:22:30 +0100267 if (opt_T || opt_c) {
268 calc_time_spent(event->proc);
269 }
Ian Wienand9a2ad352006-02-20 22:44:45 +0100270 if (fork_p(event->proc, event->e_un.sysnum)) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100271 if (opt_f) {
Steve Fink65b53df2006-09-25 02:27:08 +0200272 arg_type_info info;
Steve Fink65b53df2006-09-25 02:27:08 +0200273 info.type = ARGTYPE_LONG;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100274 pid_t child =
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200275 gimme_arg(LT_TOF_SYSCALLR, event->proc, -1, &info);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100276 if (child > 0) {
Juan Cespedes273ea6d1998-03-14 23:02:40 +0100277 open_pid(child, 0);
278 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100279 }
Juan Cespedes35d70631998-03-15 14:05:40 +0100280 enable_all_breakpoints(event->proc);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100281 }
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200282 callstack_pop(event->proc);
Juan Cespedesce377d52008-12-16 19:38:10 +0100283 if (options.syscalls) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100284 output_right(LT_TOF_SYSCALLR, event->proc,
285 sysname(event->proc, event->e_un.sysnum));
Juan Cespedes21c63a12001-07-07 20:56:56 +0200286 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100287 continue_process(event->proc->pid);
288}
289
Juan Cespedesf1350522008-12-16 18:19:58 +0100290static void
291process_arch_sysret(struct event *event) {
Juan Cespedes63184be2008-12-10 13:30:12 +0100292 if (opt_T || opt_c) {
293 calc_time_spent(event->proc);
294 }
295 callstack_pop(event->proc);
Juan Cespedesce377d52008-12-16 19:38:10 +0100296 if (options.syscalls) {
Juan Cespedes63184be2008-12-10 13:30:12 +0100297 output_right(LT_TOF_SYSCALLR, event->proc,
298 arch_sysname(event->proc, event->e_un.sysnum));
299 }
300 continue_process(event->proc->pid);
301}
302
Juan Cespedesf1350522008-12-16 18:19:58 +0100303static void
304process_breakpoint(struct event *event) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100305 int i, j;
Steve Fink65b53df2006-09-25 02:27:08 +0200306 struct breakpoint *sbp;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100307
Juan Cespedesefe85f02004-04-04 01:31:38 +0200308 debug(2, "event: breakpoint (%p)", event->e_un.brk_addr);
Luis Machado55c5feb2008-03-12 15:56:01 +0100309
Paul Gilliam76c61f12006-06-14 06:55:21 +0200310#ifdef __powerpc__
Luis Machado55c5feb2008-03-12 15:56:01 +0100311 /* Need to skip following NOP's to prevent a fake function from being stacked. */
312 long stub_addr = (long) get_count_register(event->proc);
313 struct breakpoint *stub_bp = NULL;
314 char nop_instruction[] = PPC_NOP;
315
316 stub_bp = address2bpstruct (event->proc, event->e_un.brk_addr);
317
318 if (stub_bp) {
319 unsigned char *bp_instruction = stub_bp->orig_value;
320
321 if (memcmp(bp_instruction, nop_instruction,
322 PPC_NOP_LENGTH) == 0) {
323 if (stub_addr != (long) event->e_un.brk_addr) {
324 set_instruction_pointer (event->proc, event->e_un.brk_addr + 4);
325 continue_process(event->proc->pid);
Paul Gilliam76c61f12006-06-14 06:55:21 +0200326 return;
327 }
328 }
Luis Machado55c5feb2008-03-12 15:56:01 +0100329 }
Paul Gilliam76c61f12006-06-14 06:55:21 +0200330#endif
Luis Machado55c5feb2008-03-12 15:56:01 +0100331 if ((sbp = event->proc->breakpoint_being_enabled) != 0) {
Juan Cespedesb1dd77d2002-03-03 00:22:06 +0100332 /* Reinsert breakpoint */
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100333 continue_enabling_breakpoint(event->proc->pid,
334 event->proc->
335 breakpoint_being_enabled);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100336 event->proc->breakpoint_being_enabled = NULL;
337 return;
338 }
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200339
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100340 for (i = event->proc->callstack_depth - 1; i >= 0; i--) {
341 if (event->e_un.brk_addr ==
342 event->proc->callstack[i].return_addr) {
Juan Cespedes5bfb0612002-03-31 20:01:28 +0200343#ifdef __powerpc__
Ian Wienand3219f322006-02-16 06:00:00 +0100344 /*
345 * PPC HACK! (XXX FIXME TODO)
346 * The PLT gets modified during the first call,
347 * so be sure to re-enable the breakpoint.
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100348 */
Ian Wienand9a2ad352006-02-20 22:44:45 +0100349 unsigned long a;
350 struct library_symbol *libsym =
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100351 event->proc->callstack[i].c_un.libfunc;
Paul Gilliam76c61f12006-06-14 06:55:21 +0200352 void *addr = sym2addr(event->proc, libsym);
Juan Cespedes5bfb0612002-03-31 20:01:28 +0200353
Paul Gilliam76c61f12006-06-14 06:55:21 +0200354 if (libsym->plt_type != LS_TOPLT_POINT) {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100355 unsigned char break_insn[] = BREAKPOINT_VALUE;
356
357 sbp = address2bpstruct(event->proc, addr);
358 assert(sbp);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100359 a = ptrace(PTRACE_PEEKTEXT, event->proc->pid,
360 addr);
Ian Wienand9a2ad352006-02-20 22:44:45 +0100361
Paul Gilliam76c61f12006-06-14 06:55:21 +0200362 if (memcmp(&a, break_insn, BREAKPOINT_LENGTH)) {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100363 sbp->enabled--;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100364 insert_breakpoint(event->proc, addr,
365 libsym);
Ian Wienand9a2ad352006-02-20 22:44:45 +0100366 }
367 } else {
368 sbp = libsym->brkpnt;
369 assert(sbp);
Paul Gilliam76c61f12006-06-14 06:55:21 +0200370 if (addr != sbp->addr) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100371 insert_breakpoint(event->proc, addr,
372 libsym);
Paul Gilliam76c61f12006-06-14 06:55:21 +0200373 }
Ian Wienand3219f322006-02-16 06:00:00 +0100374 }
Eric Vaitl1228a912006-12-28 16:16:56 +0100375#elif defined(__mips__)
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200376 void *addr;
377 void *old_addr;
378 struct library_symbol *sym= event->proc->callstack[i].c_un.libfunc;
379 assert(sym && sym->brkpnt);
380 old_addr=sym->brkpnt->addr;
381 addr=sym2addr(event->proc,sym);
382 assert(old_addr !=0 && addr !=0);
383 if(addr != old_addr){
384 struct library_symbol *new_sym;
385 new_sym=malloc(sizeof(*new_sym));
386 memcpy(new_sym,sym,sizeof(*new_sym));
387 new_sym->next=event->proc->list_of_symbols;
388 event->proc->list_of_symbols=new_sym;
389 new_sym->brkpnt=0;
390 insert_breakpoint(event->proc, addr, new_sym);
391 }
Juan Cespedes5bfb0612002-03-31 20:01:28 +0200392#endif
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100393 for (j = event->proc->callstack_depth - 1; j > i; j--) {
Juan Cespedes5916fda2002-02-25 00:19:21 +0100394 callstack_pop(event->proc);
395 }
Juan Cespedesd65efa32003-02-03 00:22:30 +0100396 if (opt_T || opt_c) {
397 calc_time_spent(event->proc);
398 }
399 callstack_pop(event->proc);
Juan Cespedes5916fda2002-02-25 00:19:21 +0100400 event->proc->return_addr = event->e_un.brk_addr;
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200401 output_right(LT_TOF_FUNCTIONR, event->proc,
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100402 event->proc->callstack[i].c_un.libfunc->
403 name);
Juan Cespedes5916fda2002-02-25 00:19:21 +0100404 continue_after_breakpoint(event->proc,
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100405 address2bpstruct(event->proc,
406 event->e_un.
407 brk_addr));
Juan Cespedes5916fda2002-02-25 00:19:21 +0100408 return;
409 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100410 }
411
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100412 if ((sbp = address2bpstruct(event->proc, event->e_un.brk_addr))) {
413 event->proc->stack_pointer = get_stack_pointer(event->proc);
414 event->proc->return_addr =
415 get_return_addr(event->proc, event->proc->stack_pointer);
416 output_left(LT_TOF_FUNCTION, event->proc, sbp->libsym->name);
417 callstack_push_symfunc(event->proc, sbp->libsym);
Paul Gilliambe320772006-04-24 22:06:23 +0200418#ifdef PLT_REINITALISATION_BP
419 if (event->proc->need_to_reinitialize_breakpoints
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100420 && (strcmp(sbp->libsym->name, PLTs_initialized_by_here) ==
421 0))
422 reinitialize_breakpoints(event->proc);
Paul Gilliambe320772006-04-24 22:06:23 +0200423#endif
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100424
425 continue_after_breakpoint(event->proc, sbp);
426 return;
427 }
Ian Wienand9a2ad352006-02-20 22:44:45 +0100428
429 output_line(event->proc, "unexpected breakpoint at %p",
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100430 (void *)event->e_un.brk_addr);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100431 continue_process(event->proc->pid);
432}
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200433
Juan Cespedesf1350522008-12-16 18:19:58 +0100434static void
435callstack_push_syscall(struct process *proc, int sysnum) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100436 struct callstack_element *elem;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200437
438 /* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100439 if (proc->callstack_depth == MAX_CALLDEPTH - 1) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200440 fprintf(stderr, "Error: call nesting too deep!\n");
441 return;
442 }
443
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100444 elem = &proc->callstack[proc->callstack_depth];
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200445 elem->is_syscall = 1;
446 elem->c_un.syscall = sysnum;
447 elem->return_addr = NULL;
448
449 proc->callstack_depth++;
Juan Cespedesd65efa32003-02-03 00:22:30 +0100450 if (opt_T || opt_c) {
451 struct timezone tz;
452 gettimeofday(&elem->time_spent, &tz);
453 }
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200454}
455
Juan Cespedes21c63a12001-07-07 20:56:56 +0200456static void
Juan Cespedesf1350522008-12-16 18:19:58 +0100457callstack_push_symfunc(struct process *proc, struct library_symbol *sym) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100458 struct callstack_element *elem;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200459
460 /* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100461 if (proc->callstack_depth == MAX_CALLDEPTH - 1) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200462 fprintf(stderr, "Error: call nesting too deep!\n");
463 return;
464 }
465
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100466 elem = &proc->callstack[proc->callstack_depth];
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200467 elem->is_syscall = 0;
468 elem->c_un.libfunc = sym;
469
Juan Cespedes3f0b62e2001-07-09 01:02:52 +0200470 elem->return_addr = proc->return_addr;
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200471 if (elem->return_addr) {
Paul Gilliam76c61f12006-06-14 06:55:21 +0200472 insert_breakpoint(proc, elem->return_addr, 0);
473 }
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200474
475 proc->callstack_depth++;
Juan Cespedesd65efa32003-02-03 00:22:30 +0100476 if (opt_T || opt_c) {
477 struct timezone tz;
478 gettimeofday(&elem->time_spent, &tz);
479 }
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200480}
481
Juan Cespedesf1350522008-12-16 18:19:58 +0100482static void
483callstack_pop(struct process *proc) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100484 struct callstack_element *elem;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200485 assert(proc->callstack_depth > 0);
486
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100487 elem = &proc->callstack[proc->callstack_depth - 1];
Paul Gilliam76c61f12006-06-14 06:55:21 +0200488 if (!elem->is_syscall && elem->return_addr) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200489 delete_breakpoint(proc, elem->return_addr);
490 }
491 proc->callstack_depth--;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200492}