yann@1036: This patch was vampirised from the 0.5-3.1 Debian-packaged version of ltrace, yann@1036: and contains the following fixes (exerpt from the Debian changelog). Moreover, yann@1036: you will also find an exerpt of the Debian copyright file with proper yann@1036: attribution. yann@1036: yann@1036: ================ Debian changelog exerpt ================ yann@1036: ltrace (0.5-3.1) unstable; urgency=low yann@1036: yann@1036: * Non-maintainer upload. yann@1036: * Big thanks for Anderson Lizardo for providing patches! yann@1036: * Add generic support for arm targets, Closes: #176413 yann@1036: * Save funtion arguments on arm, Closes: #462530 yann@1036: * Add thumb instruction support, Closes: #462531 yann@1036: * Add basic arm/eabi support, Closes: #450931 yann@1036: * fix exec() testcase cleanup, Closes: #462532 yann@1036: * fix memory corruption in clone() test, Closes: #462533 yann@1036: * fix tracing child with "-p" option, Closes: #462535 yann@1036: * Update standard, no changes yann@1036: yann@1036: -- Riku Voipio Tue, 29 Jan 2008 00:26:50 +0200 yann@1036: yann@1036: ltrace (0.5-3) unstable; urgency=low yann@1036: yann@1036: * Really fix compilation problems in ppc (!) yann@1036: yann@1036: -- Juan Cespedes Fri, 31 Aug 2007 19:04:03 +0200 yann@1036: yann@1036: ltrace (0.5-2) unstable; urgency=low yann@1036: yann@1036: * Fixed compilation issue in ppc yann@1036: yann@1036: -- Juan Cespedes Fri, 31 Aug 2007 13:53:27 +0200 yann@1036: yann@1036: ltrace (0.5-1) unstable; urgency=low yann@1036: yann@1036: * New upstream version yann@1036: * Remove some unneeded files in /usr/share/doc (ChangeLog, COPYING...) yann@1036: * Fix several typos (closes: Bug#372928) yann@1036: * Added more system calls to ltrace.conf yann@1036: yann@1036: -- Juan Cespedes Thu, 30 Aug 2007 14:54:44 +0200 yann@1036: ============== End Debian changelog exerpt ============== yann@1036: yann@1036: ================ Debian copyright exerpt ================ yann@1036: Copyrights yann@1036: ---------- yann@1036: Copyright (C) 1997-2007 Juan Cespedes yann@1036: yann@1036: ARMLinux port: Copyright (C) 1998 Pat Beirne yann@1036: m68k port: Copyright (C) 1998 Roman Hodek yann@1036: Misc fixes: Copyright (C) 1999 Morten Eriksen yann@1036: s390 port: Copyright (C) 2001 IBM Poughkeepsie, IBM Cororation yann@1036: ELF hacking: Copyright (C) 1999 Silvio Cesare yann@1036: PowerPC port: Copyright (C) 2001-2002 Anton Blanchard yann@1036: SPARC port: Copyright (C) 1999 Jakub Jelinek yann@1036: yann@1036: Autoconf stuff: Copyright 1992-1996 Free Software Foundation, Inc. yann@1036: install-sh: Copyright 1991 by the Massachusetts Institute of Technology yann@1036: C++ demangle: Copyright 1989-1997 Free Software Foundation, Inc. yann@1036: ============== End Debian copyright exerpt ============== yann@1036: yann@1036: diff -durN ltrace-0.5.orig/breakpoints.c ltrace-0.5/breakpoints.c yann@1036: --- ltrace-0.5.orig/breakpoints.c 2006-06-14 06:55:21.000000000 +0200 yann@1036: +++ ltrace-0.5/breakpoints.c 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -53,6 +53,10 @@ yann@1036: if (libsym) yann@1036: libsym->brkpnt = sbp; yann@1036: } yann@1036: +#ifdef __arm__ yann@1036: + sbp->thumb_mode = proc->thumb_mode; yann@1036: + proc->thumb_mode = 0; yann@1036: +#endif yann@1036: sbp->enabled++; yann@1036: if (sbp->enabled == 1 && proc->pid) yann@1036: enable_breakpoint(proc->pid, sbp); yann@1036: diff -durN ltrace-0.5.orig/elf.c ltrace-0.5/elf.c yann@1036: --- ltrace-0.5.orig/elf.c 2006-06-14 06:55:21.000000000 +0200 yann@1036: +++ ltrace-0.5/elf.c 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -464,8 +464,7 @@ yann@1036: if (strcmp(xptr->name, PLTs_initialized_by_here) == 0) { yann@1036: if (lte->ehdr.e_entry) { yann@1036: add_library_symbol ( yann@1036: - elf_plt2addr (lte, (void*)(long) yann@1036: - lte->ehdr.e_entry), yann@1036: + opd2addr (lte, lte->ehdr.e_entry), yann@1036: PLTs_initialized_by_here, yann@1036: lib_tail, 1, 0); yann@1036: fprintf (stderr, "WARNING: Using e_ent" yann@1036: diff -durN ltrace-0.5.orig/etc/ltrace.conf ltrace-0.5/etc/ltrace.conf yann@1036: --- ltrace-0.5.orig/etc/ltrace.conf 2006-02-20 22:55:47.000000000 +0100 yann@1036: +++ ltrace-0.5/etc/ltrace.conf 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -444,3 +444,81 @@ yann@1036: int SYS_removexattr(string,string); yann@1036: int SYS_lremovexattr(string,string); yann@1036: int SYS_fremovexattr(int,string); yann@1036: +int SYS_chdir(string); yann@1036: +int SYS_fchdir(int); yann@1036: +int SYS_chmod(string,octal); yann@1036: +int SYS_fchmod(int,octal); yann@1036: +int SYS_chown(string,int,int); yann@1036: +int SYS_fchown(int,int,int); yann@1036: +int SYS_lchown(string,int,int); yann@1036: +int SYS_chroot(string); yann@1036: +int SYS_dup(int); yann@1036: +int SYS_dup2(int,int); yann@1036: +int SYS_fdatasync(int); yann@1036: +int SYS_fsync(int); yann@1036: +int SYS_getpriority(int,int); yann@1036: +int SYS_setpriority(int,int,int); yann@1036: +int SYS_getrlimit(int,addr); yann@1036: +int SYS_setrlimit(int,addr); yann@1036: +int SYS_gettimeofday(addr,addr); yann@1036: +int SYS_settimeofday(addr,addr); yann@1036: +int SYS_setfsgid(int); yann@1036: +int SYS_setfsuid(int); yann@1036: +int SYS_getuid(void); yann@1036: +int SYS_setuid(int); yann@1036: +int SYS_getgid(void); yann@1036: +int SYS_setgid(int); yann@1036: +int SYS_getsid(int); yann@1036: +int SYS_setsid(int); yann@1036: +int SYS_setreuid(int,int); yann@1036: +int SYS_setregid(int,int); yann@1036: +int SYS_geteuid(void); yann@1036: +int SYS_getegid(void); yann@1036: +int SYS_setpgid(int,int); yann@1036: +int SYS_getresuid(addr,addr,addr); yann@1036: +int SYS_setresuid(int,int,int); yann@1036: +int SYS_getresgid(addr,addr,addr); yann@1036: +int SYS_setresgid(int,int,int); yann@1036: +int SYS_kill(int,int); yann@1036: +int SYS_link(string,string); yann@1036: +int SYS_madvise(addr,ulong,int); yann@1036: +int SYS_mkdir(string,octal); yann@1036: +int SYS_mknod(string,octal,int); yann@1036: +int SYS_msync(addr,ulong,int); yann@1036: +int SYS_nice(int); yann@1036: +int SYS_poll(addr,uint,int); yann@1036: +int SYS_readdir(uint,addr,uint); yann@1036: +int SYS_readlink(string,string,ulong); yann@1036: +int SYS_reboot(int,int,int,addr); yann@1036: +int SYS_rename(string,string); yann@1036: +int SYS_rmdir(string); yann@1036: +int SYS_sigaltstack(addr,addr); yann@1036: +int SYS_statfs(string,addr); yann@1036: +int SYS_fstatfs(int,addr); yann@1036: +int SYS_fstat(int,addr); yann@1036: +int SYS_lstat(string,addr); yann@1036: +int SYS_stime(addr); yann@1036: +int SYS_symlink(string, string); yann@1036: +int SYS_sysinfo(addr); yann@1036: +int SYS_syslog(int,string,int); yann@1036: +int SYS_truncate(string,long); yann@1036: +int SYS_ftruncate(int,long); yann@1036: +int SYS_mount(string,string,string,ulong,addr); yann@1036: +int SYS_umount(string); yann@1036: +int SYS_umount2(string,int); yann@1036: +int SYS_unlink(string); yann@1036: +int SYS_utime(string,addr); yann@1036: +long SYS_lseek(int,long,int); yann@1036: +addr SYS_signal(int,addr); yann@1036: +int SYS_sigaction(int,addr,addr); yann@1036: +int SYS_pause(void); yann@1036: +int SYS_sigpending(addr); yann@1036: +int SYS_sigprocmask(int,addr,addr); yann@1036: +int SYS_sigqueue(int,int,addr); yann@1036: +int SYS_sigsuspend(addr); yann@1036: +int SYS_wait(addr); yann@1036: +int SYS_waitpid(int,addr,int); yann@1036: +ulong SYS_readv(int,addr,int); yann@1036: +ulong SYS_writev(int,addr,int); yann@1036: +int SYS_mprotect(addr,int,int); yann@1036: +int SYS_access(string,octal); yann@1036: diff -durN ltrace-0.5.orig/ltrace.1 ltrace-0.5/ltrace.1 yann@1036: --- ltrace-0.5.orig/ltrace.1 2006-06-16 03:15:18.000000000 +0200 yann@1036: +++ ltrace-0.5/ltrace.1 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -30,7 +30,7 @@ yann@1036: .TP yann@1036: .I \-C, \-\-demangle yann@1036: Decode (demangle) low-level symbol names into user-level names. yann@1036: -Besides removing any initial underscore prepended by the system, yann@1036: +Besides removing any initial underscore prefix used by the system, yann@1036: this makes C++ function names readable. yann@1036: .TP yann@1036: .I \-d, \-\-debug yann@1036: diff -durN ltrace-0.5.orig/ltrace.c ltrace-0.5/ltrace.c yann@1036: --- ltrace-0.5.orig/ltrace.c 2006-02-20 22:48:07.000000000 +0100 yann@1036: +++ ltrace-0.5/ltrace.c 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -54,6 +54,9 @@ yann@1036: { yann@1036: exiting = 1; yann@1036: debug(1, "Received interrupt signal; exiting..."); yann@1036: + if (opt_o) { yann@1036: + fclose(output); yann@1036: + } yann@1036: signal(SIGINT, SIG_IGN); yann@1036: signal(SIGTERM, SIG_IGN); yann@1036: signal(SIGALRM, signal_alarm); yann@1036: @@ -74,6 +77,9 @@ yann@1036: if (opt_c) { yann@1036: show_summary(); yann@1036: } yann@1036: + if (opt_o) { yann@1036: + fclose(output); yann@1036: + } yann@1036: } yann@1036: yann@1036: static void guess_cols(void) yann@1036: diff -durN ltrace-0.5.orig/ltrace.h ltrace-0.5/ltrace.h yann@1036: --- ltrace-0.5.orig/ltrace.h 2006-06-14 06:55:21.000000000 +0200 yann@1036: +++ ltrace-0.5/ltrace.h 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -26,6 +26,9 @@ yann@1036: unsigned char orig_value[BREAKPOINT_LENGTH]; yann@1036: int enabled; yann@1036: struct library_symbol *libsym; yann@1036: +#ifdef __arm__ yann@1036: + int thumb_mode; yann@1036: +#endif yann@1036: }; yann@1036: yann@1036: enum arg_type { yann@1036: @@ -119,6 +122,9 @@ yann@1036: void *arch_ptr; yann@1036: short e_machine; yann@1036: short need_to_reinitialize_breakpoints; yann@1036: +#ifdef __arm__ yann@1036: + int thumb_mode; /* ARM execution mode: 0: ARM mode, 1: Thumb mode */ yann@1036: +#endif yann@1036: yann@1036: /* output: */ yann@1036: enum tof type_being_displayed; yann@1036: @@ -136,12 +142,14 @@ yann@1036: LT_EV_EXIT_SIGNAL, yann@1036: LT_EV_SYSCALL, yann@1036: LT_EV_SYSRET, yann@1036: + LT_EV_ARCH_SYSCALL, yann@1036: + LT_EV_ARCH_SYSRET, yann@1036: LT_EV_BREAKPOINT yann@1036: } thing; yann@1036: union { yann@1036: int ret_val; /* _EV_EXIT */ yann@1036: int signum; /* _EV_SIGNAL, _EV_EXIT_SIGNAL */ yann@1036: - int sysnum; /* _EV_SYSCALL, _EV_SYSRET */ yann@1036: + int sysnum; /* _EV_SYSCALL, _EV_SYSRET, _EV_ARCH_SYSCALL, _EV_ARCH_SYSRET */ yann@1036: void *brk_addr; /* _EV_BREAKPOINT */ yann@1036: } e_un; yann@1036: }; yann@1036: diff -durN ltrace-0.5.orig/options.c ltrace-0.5/options.c yann@1036: --- ltrace-0.5.orig/options.c 2006-04-24 22:06:23.000000000 +0200 yann@1036: +++ ltrace-0.5/options.c 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -42,6 +42,7 @@ yann@1036: #endif yann@1036: int opt_n = 0; /* indent trace output according to program flow */ yann@1036: int opt_T = 0; /* show the time spent inside each call */ yann@1036: +int opt_o = 0; /* output to a specific file */ yann@1036: yann@1036: /* List of pids given to option -p: */ yann@1036: struct opt_p_t *opt_p = NULL; /* attach to process with a given pid */ yann@1036: @@ -274,6 +275,7 @@ yann@1036: opt_n = atoi(optarg); yann@1036: break; yann@1036: case 'o': yann@1036: + opt_o++; yann@1036: output = fopen(optarg, "w"); yann@1036: if (!output) { yann@1036: fprintf(stderr, yann@1036: diff -durN ltrace-0.5.orig/options.h ltrace-0.5/options.h yann@1036: --- ltrace-0.5.orig/options.h 2006-03-13 18:43:13.000000000 +0100 yann@1036: +++ ltrace-0.5/options.h 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -20,6 +20,7 @@ yann@1036: extern int opt_C; /* Demanglelow-level symbol names into user-level names */ yann@1036: extern int opt_n; /* indent trace output according to program flow */ yann@1036: extern int opt_T; /* show the time spent inside each call */ yann@1036: +extern int opt_o; /* output to a specific file */ yann@1036: yann@1036: struct opt_p_t { yann@1036: pid_t pid; yann@1036: diff -durN ltrace-0.5.orig/process_event.c ltrace-0.5/process_event.c yann@1036: --- ltrace-0.5.orig/process_event.c 2006-06-14 06:55:21.000000000 +0200 yann@1036: +++ ltrace-0.5/process_event.c 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -24,7 +24,9 @@ yann@1036: static void process_exit(struct event *event); yann@1036: static void process_exit_signal(struct event *event); yann@1036: static void process_syscall(struct event *event); yann@1036: +static void process_arch_syscall(struct event *event); yann@1036: static void process_sysret(struct event *event); yann@1036: +static void process_arch_sysret(struct event *event); yann@1036: static void process_breakpoint(struct event *event); yann@1036: static void remove_proc(struct process *proc); yann@1036: yann@1036: @@ -81,6 +83,24 @@ yann@1036: } yann@1036: } yann@1036: yann@1036: +static char *arch_sysname(struct process *proc, int sysnum) yann@1036: +{ yann@1036: + static char result[128]; yann@1036: + static char *arch_syscalent[] = { yann@1036: +#include "arch_syscallent.h" yann@1036: + }; yann@1036: + int nsyscals = sizeof arch_syscalent / sizeof arch_syscalent[0]; yann@1036: + yann@1036: + if (sysnum < 0 || sysnum >= nsyscals) { yann@1036: + sprintf(result, "ARCH_%d", sysnum); yann@1036: + return result; yann@1036: + } else { yann@1036: + sprintf(result, "ARCH_%s", yann@1036: + arch_syscalent[sysnum]); yann@1036: + return result; yann@1036: + } yann@1036: +} yann@1036: + yann@1036: void process_event(struct event *event) yann@1036: { yann@1036: switch (event->thing) { yann@1036: @@ -115,6 +135,18 @@ yann@1036: event->e_un.sysnum); yann@1036: process_sysret(event); yann@1036: return; yann@1036: + case LT_EV_ARCH_SYSCALL: yann@1036: + debug(1, "event: arch_syscall (%s [%d])", yann@1036: + arch_sysname(event->proc, event->e_un.sysnum), yann@1036: + event->e_un.sysnum); yann@1036: + process_arch_syscall(event); yann@1036: + return; yann@1036: + case LT_EV_ARCH_SYSRET: yann@1036: + debug(1, "event: arch_sysret (%s [%d])", yann@1036: + arch_sysname(event->proc, event->e_un.sysnum), yann@1036: + event->e_un.sysnum); yann@1036: + process_arch_sysret(event); yann@1036: + return; yann@1036: case LT_EV_BREAKPOINT: yann@1036: debug(1, "event: breakpoint"); yann@1036: process_breakpoint(event); yann@1036: @@ -195,6 +227,19 @@ yann@1036: continue_process(event->proc->pid); yann@1036: } yann@1036: yann@1036: +static void process_arch_syscall(struct event *event) yann@1036: +{ yann@1036: + if (opt_S) { yann@1036: + output_left(LT_TOF_SYSCALL, event->proc, yann@1036: + arch_sysname(event->proc, event->e_un.sysnum)); yann@1036: + } yann@1036: + if (event->proc->breakpoints_enabled == 0) { yann@1036: + enable_all_breakpoints(event->proc); yann@1036: + } yann@1036: + callstack_push_syscall(event->proc, 0xf0000 + event->e_un.sysnum); yann@1036: + continue_process(event->proc->pid); yann@1036: +} yann@1036: + yann@1036: struct timeval current_time_spent; yann@1036: yann@1036: static void calc_time_spent(struct process *proc) yann@1036: @@ -257,6 +302,19 @@ yann@1036: continue_process(event->proc->pid); yann@1036: } yann@1036: yann@1036: +static void process_arch_sysret(struct event *event) yann@1036: +{ yann@1036: + if (opt_T || opt_c) { yann@1036: + calc_time_spent(event->proc); yann@1036: + } yann@1036: + callstack_pop(event->proc); yann@1036: + if (opt_S) { yann@1036: + output_right(LT_TOF_SYSCALLR, event->proc, yann@1036: + arch_sysname(event->proc, event->e_un.sysnum)); yann@1036: + } yann@1036: + continue_process(event->proc->pid); yann@1036: +} yann@1036: + yann@1036: static void process_breakpoint(struct event *event) yann@1036: { yann@1036: int i, j; yann@1036: diff -durN ltrace-0.5.orig/sysdeps/linux-gnu/Makefile ltrace-0.5/sysdeps/linux-gnu/Makefile yann@1036: --- ltrace-0.5.orig/sysdeps/linux-gnu/Makefile 2008-11-04 19:25:11.000000000 +0100 yann@1036: +++ ltrace-0.5/sysdeps/linux-gnu/Makefile 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -2,7 +2,7 @@ yann@1036: yann@1036: OBJ = trace.o proc.o breakpoint.o yann@1036: yann@1036: -all: sysdep.h signalent.h syscallent.h signalent1.h syscallent1.h ../sysdep.o yann@1036: +all: sysdep.h signalent.h syscallent.h arch_syscallent.h signalent1.h syscallent1.h ../sysdep.o yann@1036: yann@1036: sysdep.h: $(ARCH)/arch.h yann@1036: cat $(ARCH)/arch.h > sysdep.h yann@1036: @@ -26,6 +26,13 @@ yann@1036: > syscallent1.h; \ yann@1036: fi yann@1036: yann@1036: +arch_syscallent.h: yann@1036: + if [ -f $(ARCH)/arch_syscallent.h ]; then \ yann@1036: + cp $(ARCH)/arch_syscallent.h arch_syscallent.h; \ yann@1036: + else \ yann@1036: + > arch_syscallent.h; \ yann@1036: + fi yann@1036: + yann@1036: ../sysdep.o: os.o $(ARCH)/arch.o yann@1036: $(CC) -nostdlib -r -o ../sysdep.o os.o $(ARCH)/arch.o yann@1036: yann@1036: @@ -37,7 +44,7 @@ yann@1036: yann@1036: clean: yann@1036: $(MAKE) -C $(ARCH) clean yann@1036: - rm -f $(OBJ) sysdep.h signalent.h signalent1.h syscallent.h yann@1036: + rm -f $(OBJ) sysdep.h signalent.h signalent1.h syscallent.h arch_syscallent.h yann@1036: rm -f syscallent1.h os.o sysdep.o ../sysdep.o yann@1036: yann@1036: dummy: yann@1036: diff -durN ltrace-0.5.orig/sysdeps/linux-gnu/arch_mksyscallent ltrace-0.5/sysdeps/linux-gnu/arch_mksyscallent yann@1036: --- ltrace-0.5.orig/sysdeps/linux-gnu/arch_mksyscallent 1970-01-01 01:00:00.000000000 +0100 yann@1036: +++ ltrace-0.5/sysdeps/linux-gnu/arch_mksyscallent 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -0,0 +1,43 @@ yann@1036: +#!/usr/bin/awk -f yann@1036: + yann@1036: +# hack expression to generate arch_syscallent.h from yann@1036: +# It reads from stdin and writes to stdout yann@1036: +# Currently (linux-2.6.16), it works OK on arm yann@1036: +# It is untested in other architectures yann@1036: + yann@1036: +BEGIN { yann@1036: + max=0; yann@1036: + FS="[ \t\n()+]+"; yann@1036: +} yann@1036: + yann@1036: +{ yann@1036: +# printf("/%s/%s/%s/%s/\n", $1, $2, $3, $4); yann@1036: + if (($1 ~ /^#define$/) && ($2 ~ /^__[A-Z]+_NR_/)) { yann@1036: + sub(/^__[A-Z]+_NR_/,"",$2); yann@1036: + if (($3>=0) && ($3<=1000)) { yann@1036: + SYSCALL[$3]=$2; yann@1036: + if ($3 > max) { yann@1036: + max=$3; yann@1036: + } yann@1036: + } else if (($3 ~ /^__[A-Z]+_NR_BASE$/) && ($4>=0) && ($4<=1000)) { yann@1036: + SYSCALL[$4]=$2; yann@1036: + if ($4 > max) { yann@1036: + max=$4; yann@1036: + } yann@1036: + } yann@1036: + } yann@1036: +} yann@1036: + yann@1036: +END { yann@1036: + for(i=0; i<=max; i++) { yann@1036: + if (!SYSCALL[i]) { yann@1036: + SYSCALL[i] = i; yann@1036: + } yann@1036: + pad = 32 - length(SYSCALL[i]); yann@1036: + if (pad<1) { yann@1036: + pad=1; yann@1036: + } yann@1036: + printf("\t\"%s\",%*s/* %d */\n", SYSCALL[i], pad, "", i); yann@1036: + } yann@1036: +} yann@1036: + yann@1036: diff -durN ltrace-0.5.orig/sysdeps/linux-gnu/arm/Makefile ltrace-0.5/sysdeps/linux-gnu/arm/Makefile yann@1036: --- ltrace-0.5.orig/sysdeps/linux-gnu/arm/Makefile 2006-02-20 22:44:45.000000000 +0100 yann@1036: +++ ltrace-0.5/sysdeps/linux-gnu/arm/Makefile 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -1,4 +1,4 @@ yann@1036: -OBJ = trace.o regs.o plt.o yann@1036: +OBJ = trace.o regs.o plt.o breakpoint.o yann@1036: yann@1036: all: arch.o yann@1036: yann@1036: diff -durN ltrace-0.5.orig/sysdeps/linux-gnu/arm/arch.h ltrace-0.5/sysdeps/linux-gnu/arm/arch.h yann@1036: --- ltrace-0.5.orig/sysdeps/linux-gnu/arm/arch.h 2006-04-24 22:06:23.000000000 +0200 yann@1036: +++ ltrace-0.5/sysdeps/linux-gnu/arm/arch.h 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -1,5 +1,10 @@ yann@1036: -#define BREAKPOINT_VALUE { 0x01, 0x00, 0x9f, 0xef } yann@1036: +#define ARCH_HAVE_ENABLE_BREAKPOINT 1 yann@1036: +#define ARCH_HAVE_DISABLE_BREAKPOINT 1 yann@1036: + yann@1036: +#define BREAKPOINT_VALUE { 0xf0, 0x01, 0xf0, 0xe7 } yann@1036: #define BREAKPOINT_LENGTH 4 yann@1036: +#define THUMB_BREAKPOINT_VALUE { 0x01, 0xde } yann@1036: +#define THUMB_BREAKPOINT_LENGTH 2 yann@1036: #define DECR_PC_AFTER_BREAK 0 yann@1036: yann@1036: #define LT_ELFCLASS ELFCLASS32 yann@1036: diff -durN ltrace-0.5.orig/sysdeps/linux-gnu/arm/arch_syscallent.h ltrace-0.5/sysdeps/linux-gnu/arm/arch_syscallent.h yann@1036: --- ltrace-0.5.orig/sysdeps/linux-gnu/arm/arch_syscallent.h 1970-01-01 01:00:00.000000000 +0100 yann@1036: +++ ltrace-0.5/sysdeps/linux-gnu/arm/arch_syscallent.h 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -0,0 +1,6 @@ yann@1036: + "0", /* 0 */ yann@1036: + "breakpoint", /* 1 */ yann@1036: + "cacheflush", /* 2 */ yann@1036: + "usr26", /* 3 */ yann@1036: + "usr32", /* 4 */ yann@1036: + "set_tls", /* 5 */ yann@1036: diff -durN ltrace-0.5.orig/sysdeps/linux-gnu/arm/breakpoint.c ltrace-0.5/sysdeps/linux-gnu/arm/breakpoint.c yann@1036: --- ltrace-0.5.orig/sysdeps/linux-gnu/arm/breakpoint.c 1970-01-01 01:00:00.000000000 +0100 yann@1036: +++ ltrace-0.5/sysdeps/linux-gnu/arm/breakpoint.c 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -0,0 +1,86 @@ yann@1036: +/* yann@1036: + * This file is part of ltrace. yann@1036: + * yann@1036: + * Copyright (C) 2007 by Instituto Nokia de Tecnologia (INdT) yann@1036: + * yann@1036: + * Author: Anderson Lizardo yann@1036: + * yann@1036: + * This program is free software; you can redistribute it and/or yann@1036: + * modify it under the terms of the GNU General Public License yann@1036: + * version 2 as published by the Free Software Foundation. yann@1036: + * yann@1036: + * This program is distributed in the hope that it will be useful, but yann@1036: + * WITHOUT ANY WARRANTY; without even the implied warranty of yann@1036: + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU yann@1036: + * General Public License for more details. yann@1036: + * yann@1036: + * You should have received a copy of the GNU General Public License yann@1036: + * along with this program; if not, write to the Free Software yann@1036: + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA yann@1036: + * 02110-1301 USA yann@1036: + * yann@1036: + * Modified from sysdeps/linux-gnu/breakpoint.c and added ARM Thumb support. yann@1036: +*/ yann@1036: + yann@1036: +#include yann@1036: +#include "config.h" yann@1036: +#include "arch.h" yann@1036: +#include "options.h" yann@1036: +#include "output.h" yann@1036: +#include "debug.h" yann@1036: + yann@1036: +void arch_enable_breakpoint(pid_t pid, struct breakpoint *sbp) yann@1036: +{ yann@1036: + unsigned int i, j; yann@1036: + const unsigned char break_insn[] = BREAKPOINT_VALUE; yann@1036: + const unsigned char thumb_break_insn[] = THUMB_BREAKPOINT_VALUE; yann@1036: + yann@1036: + debug(1, "arch_enable_breakpoint(%d,%p)", pid, sbp->addr); yann@1036: + yann@1036: + for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) { yann@1036: + long a = yann@1036: + ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i * sizeof(long), yann@1036: + 0); yann@1036: + unsigned char *bytes = (unsigned char *)&a; yann@1036: + yann@1036: + debug(2, "current = 0x%lx, orig_value = 0x%lx, thumb_mode = %d", a, *(long *)&sbp->orig_value, sbp->thumb_mode); yann@1036: + for (j = 0; yann@1036: + j < sizeof(long) yann@1036: + && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) { yann@1036: + yann@1036: + sbp->orig_value[i * sizeof(long) + j] = bytes[j]; yann@1036: + if (!sbp->thumb_mode) { yann@1036: + bytes[j] = break_insn[i * sizeof(long) + j]; yann@1036: + } yann@1036: + else if (j < THUMB_BREAKPOINT_LENGTH) { yann@1036: + bytes[j] = thumb_break_insn[i * sizeof(long) + j]; yann@1036: + } yann@1036: + } yann@1036: + ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a); yann@1036: + } yann@1036: +} yann@1036: + yann@1036: +void arch_disable_breakpoint(pid_t pid, const struct breakpoint *sbp) yann@1036: +{ yann@1036: + unsigned int i, j; yann@1036: + const unsigned char break_insn[] = BREAKPOINT_VALUE; yann@1036: + const unsigned char thumb_break_insn[] = THUMB_BREAKPOINT_VALUE; yann@1036: + yann@1036: + debug(1, "arch_disable_breakpoint(%d,%p)", pid, sbp->addr); yann@1036: + yann@1036: + for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) { yann@1036: + long a = yann@1036: + ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i * sizeof(long), yann@1036: + 0); yann@1036: + unsigned char *bytes = (unsigned char *)&a; yann@1036: + yann@1036: + debug(2, "current = 0x%lx, orig_value = 0x%lx, thumb_mode = %d", a, *(long *)&sbp->orig_value, sbp->thumb_mode); yann@1036: + for (j = 0; yann@1036: + j < sizeof(long) yann@1036: + && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) { yann@1036: + yann@1036: + bytes[j] = sbp->orig_value[i * sizeof(long) + j]; yann@1036: + } yann@1036: + ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a); yann@1036: + } yann@1036: +} yann@1036: diff -durN ltrace-0.5.orig/sysdeps/linux-gnu/arm/ptrace.h ltrace-0.5/sysdeps/linux-gnu/arm/ptrace.h yann@1036: --- ltrace-0.5.orig/sysdeps/linux-gnu/arm/ptrace.h 2006-02-20 22:44:45.000000000 +0100 yann@1036: +++ ltrace-0.5/sysdeps/linux-gnu/arm/ptrace.h 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -1 +1,9 @@ yann@1036: #include yann@1036: +#include yann@1036: + yann@1036: +typedef struct { yann@1036: + int valid; yann@1036: + struct pt_regs regs; yann@1036: + long func_arg[5]; yann@1036: + long sysc_arg[5]; yann@1036: +} proc_archdep; yann@1036: diff -durN ltrace-0.5.orig/sysdeps/linux-gnu/arm/regs.c ltrace-0.5/sysdeps/linux-gnu/arm/regs.c yann@1036: --- ltrace-0.5.orig/sysdeps/linux-gnu/arm/regs.c 2006-02-20 22:48:07.000000000 +0100 yann@1036: +++ ltrace-0.5/sysdeps/linux-gnu/arm/regs.c 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -39,5 +39,10 @@ yann@1036: * a CISC architecture; in our case, we don't need that */ yann@1036: void *get_return_addr(struct process *proc, void *stack_pointer) yann@1036: { yann@1036: - return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, off_lr, 0); yann@1036: + long addr = ptrace(PTRACE_PEEKUSER, proc->pid, off_lr, 0); yann@1036: + yann@1036: + proc->thumb_mode = addr & 1; yann@1036: + if (proc->thumb_mode) yann@1036: + addr &= ~1; yann@1036: + return (void *)addr; yann@1036: } yann@1036: diff -durN ltrace-0.5.orig/sysdeps/linux-gnu/arm/trace.c ltrace-0.5/sysdeps/linux-gnu/arm/trace.c yann@1036: --- ltrace-0.5.orig/sysdeps/linux-gnu/arm/trace.c 2006-02-20 22:48:07.000000000 +0100 yann@1036: +++ ltrace-0.5/sysdeps/linux-gnu/arm/trace.c 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -2,6 +2,7 @@ yann@1036: #include "config.h" yann@1036: #endif yann@1036: yann@1036: +#include yann@1036: #include yann@1036: #include yann@1036: #include yann@1036: @@ -9,6 +10,8 @@ yann@1036: #include yann@1036: yann@1036: #include "ltrace.h" yann@1036: +#include "output.h" yann@1036: +#include "ptrace.h" yann@1036: yann@1036: #if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) yann@1036: # define PTRACE_PEEKUSER PTRACE_PEEKUSR yann@1036: @@ -18,19 +21,25 @@ yann@1036: # define PTRACE_POKEUSER PTRACE_POKEUSR yann@1036: #endif yann@1036: yann@1036: -/* syscall tracing protocol: ArmLinux yann@1036: - on the way in, ip is 0 yann@1036: - on the way out, ip is non-zero yann@1036: -*/ yann@1036: #define off_r0 0 yann@1036: +#define off_r7 28 yann@1036: #define off_ip 48 yann@1036: #define off_pc 60 yann@1036: yann@1036: void get_arch_dep(struct process *proc) yann@1036: { yann@1036: + proc_archdep *a; yann@1036: + yann@1036: + if (!proc->arch_ptr) yann@1036: + proc->arch_ptr = (void *)malloc(sizeof(proc_archdep)); yann@1036: + a = (proc_archdep *) (proc->arch_ptr); yann@1036: + a->valid = (ptrace(PTRACE_GETREGS, proc->pid, 0, &a->regs) >= 0); yann@1036: } yann@1036: yann@1036: -/* Returns 1 if syscall, 2 if sysret, 0 otherwise. yann@1036: +/* Returns 0 if not a syscall, yann@1036: + * 1 if syscall entry, 2 if syscall exit, yann@1036: + * 3 if arch-specific syscall entry, 4 if arch-specific syscall exit, yann@1036: + * -1 on error. yann@1036: */ yann@1036: int syscall_p(struct process *proc, int status, int *sysnum) yann@1036: { yann@1036: @@ -40,19 +49,39 @@ yann@1036: int pc = ptrace(PTRACE_PEEKUSER, proc->pid, off_pc, 0); yann@1036: /* fetch the SWI instruction */ yann@1036: int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 4, 0); yann@1036: + int ip = ptrace(PTRACE_PEEKUSER, proc->pid, off_ip, 0); yann@1036: yann@1036: - *sysnum = insn & 0xFFFF; yann@1036: - /* if it is a syscall, return 1 or 2 */ yann@1036: - if ((insn & 0xFFFF0000) == 0xef900000) { yann@1036: - return ptrace(PTRACE_PEEKUSER, proc->pid, off_ip, yann@1036: - 0) ? 2 : 1; yann@1036: + if (insn == 0xef000000 || insn == 0x0f000000) { yann@1036: + /* EABI syscall */ yann@1036: + *sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, off_r7, 0); yann@1036: + } else if ((insn & 0xfff00000) == 0xef900000) { yann@1036: + /* old ABI syscall */ yann@1036: + *sysnum = insn & 0xfffff; yann@1036: + } else { yann@1036: + /* TODO: handle swi variations */ yann@1036: + /* one possible reason for getting in here is that we yann@1036: + * are coming from a signal handler, so the current yann@1036: + * PC does not point to the instruction just after the yann@1036: + * "swi" one. */ yann@1036: + output_line(proc, "unexpected instruction 0x%x at %p", insn, pc - 4); yann@1036: + return -1; yann@1036: + } yann@1036: + if ((*sysnum & 0xf0000) == 0xf0000) { yann@1036: + /* arch-specific syscall */ yann@1036: + *sysnum &= ~0xf0000; yann@1036: + return ip ? 4 : 3; yann@1036: } yann@1036: + /* ARM syscall convention: on syscall entry, ip is zero; yann@1036: + * on syscall exit, ip is non-zero */ yann@1036: + return ip ? 2 : 1; yann@1036: } yann@1036: return 0; yann@1036: } yann@1036: yann@1036: long gimme_arg(enum tof type, struct process *proc, int arg_num) yann@1036: { yann@1036: + proc_archdep *a = (proc_archdep *) proc->arch_ptr; yann@1036: + yann@1036: if (arg_num == -1) { /* return value */ yann@1036: return ptrace(PTRACE_PEEKUSER, proc->pid, off_r0, 0); yann@1036: } yann@1036: @@ -60,6 +89,10 @@ yann@1036: /* deal with the ARM calling conventions */ yann@1036: if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) { yann@1036: if (arg_num < 4) { yann@1036: + if (a->valid && type == LT_TOF_FUNCTION) yann@1036: + return a->regs.uregs[arg_num]; yann@1036: + if (a->valid && type == LT_TOF_FUNCTIONR) yann@1036: + return a->func_arg[arg_num]; yann@1036: return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * arg_num, yann@1036: 0); yann@1036: } else { yann@1036: @@ -69,6 +102,10 @@ yann@1036: } yann@1036: } else if (type == LT_TOF_SYSCALL || type == LT_TOF_SYSCALLR) { yann@1036: if (arg_num < 5) { yann@1036: + if (a->valid && type == LT_TOF_SYSCALL) yann@1036: + return a->regs.uregs[arg_num]; yann@1036: + if (a->valid && type == LT_TOF_SYSCALLR) yann@1036: + return a->sysc_arg[arg_num]; yann@1036: return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * arg_num, yann@1036: 0); yann@1036: } else { yann@1036: @@ -86,4 +123,11 @@ yann@1036: yann@1036: void save_register_args(enum tof type, struct process *proc) yann@1036: { yann@1036: + proc_archdep *a = (proc_archdep *) proc->arch_ptr; yann@1036: + if (a->valid) { yann@1036: + if (type == LT_TOF_FUNCTION) yann@1036: + memcpy(a->func_arg, a->regs.uregs, sizeof(a->func_arg)); yann@1036: + else yann@1036: + memcpy(a->sysc_arg, a->regs.uregs, sizeof(a->sysc_arg)); yann@1036: + } yann@1036: } yann@1036: diff -durN ltrace-0.5.orig/sysdeps/linux-gnu/ppc/arch.h ltrace-0.5/sysdeps/linux-gnu/ppc/arch.h yann@1036: --- ltrace-0.5.orig/sysdeps/linux-gnu/ppc/arch.h 2006-06-14 06:55:21.000000000 +0200 yann@1036: +++ ltrace-0.5/sysdeps/linux-gnu/ppc/arch.h 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -4,9 +4,12 @@ yann@1036: yann@1036: #define LT_ELFCLASS ELFCLASS32 yann@1036: #define LT_ELF_MACHINE EM_PPC yann@1036: + yann@1036: #ifdef __powerpc64__ // Says 'ltrace' is 64 bits, says nothing about target. yann@1036: #define LT_ELFCLASS2 ELFCLASS64 yann@1036: #define LT_ELF_MACHINE2 EM_PPC64 yann@1036: +#define ARCH_SUPPORTS_OPD yann@1036: +#endif yann@1036: yann@1036: #define PLT_REINITALISATION_BP "_start" yann@1036: yann@1036: @@ -16,6 +19,3 @@ yann@1036: #if (PPC_NOP_LENGTH != BREAKPOINT_LENGTH) yann@1036: #error "Length of the breakpoint value not equal to the length of a nop instruction" yann@1036: #endif yann@1036: - yann@1036: - yann@1036: -#endif yann@1036: diff -durN ltrace-0.5.orig/testsuite/ltrace.minor/Makefile.in ltrace-0.5/testsuite/ltrace.minor/Makefile.in yann@1036: --- ltrace-0.5.orig/testsuite/ltrace.minor/Makefile.in 2006-03-14 00:12:01.000000000 +0100 yann@1036: +++ ltrace-0.5/testsuite/ltrace.minor/Makefile.in 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -19,7 +19,7 @@ yann@1036: yann@1036: .SUFFIXES: yann@1036: clean: yann@1036: - -rm -f demangle trace-fork trace-clone yann@1036: + -rm -f demangle trace-fork trace-clone trace-exec trace-exec1 yann@1036: -rm -f time-record-tt time-record-ttt time-record-T yann@1036: -rm -f attach-process count-record yann@1036: -rm -f print-instruction-pointer yann@1036: diff -durN ltrace-0.5.orig/testsuite/ltrace.minor/trace-clone.c ltrace-0.5/testsuite/ltrace.minor/trace-clone.c yann@1036: --- ltrace-0.5.orig/testsuite/ltrace.minor/trace-clone.c 2006-03-16 01:38:47.000000000 +0100 yann@1036: +++ ltrace-0.5/testsuite/ltrace.minor/trace-clone.c 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -21,11 +21,11 @@ yann@1036: int main () yann@1036: { yann@1036: pid_t pid; yann@1036: - static char stack[STACK_SIZE]; yann@1036: + char stack[STACK_SIZE]; yann@1036: #ifdef __ia64__ yann@1036: pid = __clone2((myfunc)&child, stack, STACK_SIZE, CLONE_FS, NULL); yann@1036: #else yann@1036: - pid = clone((myfunc)&child, stack,CLONE_FS, NULL ); yann@1036: + pid = clone((myfunc)&child, stack + STACK_SIZE,CLONE_FS, NULL ); yann@1036: #endif yann@1036: if (pid < 0) yann@1036: { yann@1036: diff -durN ltrace-0.5.orig/wait_for_something.c ltrace-0.5/wait_for_something.c yann@1036: --- ltrace-0.5.orig/wait_for_something.c 2006-02-20 22:48:07.000000000 +0100 yann@1036: +++ ltrace-0.5/wait_for_something.c 2008-11-04 19:25:50.000000000 +0100 yann@1036: @@ -71,6 +71,18 @@ yann@1036: event.thing = LT_EV_SYSRET; yann@1036: event.e_un.sysnum = tmp; yann@1036: return &event; yann@1036: + case 3: yann@1036: + event.thing = LT_EV_ARCH_SYSCALL; yann@1036: + event.e_un.sysnum = tmp; yann@1036: + return &event; yann@1036: + case 4: yann@1036: + event.thing = LT_EV_ARCH_SYSRET; yann@1036: + event.e_un.sysnum = tmp; yann@1036: + return &event; yann@1036: + case -1: yann@1036: + event.thing = LT_EV_NONE; yann@1036: + continue_process(event.proc->pid); yann@1036: + return &event; yann@1036: } yann@1036: if (WIFEXITED(status)) { yann@1036: event.thing = LT_EV_EXIT;