Tags: patch This patch should fix this issue. It depends on patch posted to Bug #450931.
It was based on work from Michael K. Edwards, whose original patch is at: http://lists.alioth.debian.org/pipermail/ltrace-devel/2007-February/000205.html Changelog: 2008-01-25 Anderson Lizardo <[EMAIL PROTECTED]> * Based on work of Michael K. Edwards <[EMAIL PROTECTED]> * ltrace.h, process_event.c, sysdeps/linux-gnu/arch_mksyscallent, sysdeps/linux-gnu/arm/trace.c, sysdeps/linux-gnu/Makefile, wait_for_something.c, sysdeps/linux-gnu/arm/arch.h, sysdeps/linux-gnu/arm/arch_syscallent.h, Makefile.in: fix support for ARM targets. -- Anderson Lizardo Instituto Nokia de Tecnologia Manaus - Brazil
Add support for ARM specific syscalls. Based on patch from: http://lists.alioth.debian.org/pipermail/ltrace-devel/2007-February/000205.html Fixes Debian bug #176413. Signed-off-by: Anderson Lizardo <[EMAIL PROTECTED]> Signed-off-by: Bruna Moreira <[EMAIL PROTECTED]> Index: ltrace-indt/ltrace.h =================================================================== --- ltrace-indt.orig/ltrace.h 2007-12-18 21:10:24.000000000 -0400 +++ ltrace-indt/ltrace.h 2007-12-18 21:10:24.000000000 -0400 @@ -187,12 +187,14 @@ struct event { LT_EV_EXIT_SIGNAL, LT_EV_SYSCALL, LT_EV_SYSRET, + LT_EV_ARCH_SYSCALL, + LT_EV_ARCH_SYSRET, LT_EV_BREAKPOINT } thing; union { int ret_val; /* _EV_EXIT */ int signum; /* _EV_SIGNAL, _EV_EXIT_SIGNAL */ - int sysnum; /* _EV_SYSCALL, _EV_SYSRET */ + int sysnum; /* _EV_SYSCALL, _EV_SYSRET, _EV_ARCH_SYSCALL, _EV_ARCH_SYSRET */ void *brk_addr; /* _EV_BREAKPOINT */ } e_un; }; Index: ltrace-indt/process_event.c =================================================================== --- ltrace-indt.orig/process_event.c 2007-12-18 21:10:24.000000000 -0400 +++ ltrace-indt/process_event.c 2007-12-18 21:10:24.000000000 -0400 @@ -24,7 +24,9 @@ static void process_signal(struct event static void process_exit(struct event *event); static void process_exit_signal(struct event *event); static void process_syscall(struct event *event); +static void process_arch_syscall(struct event *event); static void process_sysret(struct event *event); +static void process_arch_sysret(struct event *event); static void process_breakpoint(struct event *event); static void remove_proc(struct process *proc); @@ -81,6 +83,24 @@ static char *sysname(struct process *pro } } +static char *arch_sysname(struct process *proc, int sysnum) +{ + static char result[128]; + static char *arch_syscalent[] = { +#include "arch_syscallent.h" + }; + int nsyscals = sizeof arch_syscalent / sizeof arch_syscalent[0]; + + if (sysnum < 0 || sysnum >= nsyscals) { + sprintf(result, "ARCH_%d", sysnum); + return result; + } else { + sprintf(result, "ARCH_%s", + arch_syscalent[sysnum]); + return result; + } +} + void process_event(struct event *event) { switch (event->thing) { @@ -115,6 +135,18 @@ void process_event(struct event *event) event->e_un.sysnum); process_sysret(event); return; + case LT_EV_ARCH_SYSCALL: + debug(1, "event: arch_syscall (%s [%d])", + arch_sysname(event->proc, event->e_un.sysnum), + event->e_un.sysnum); + process_arch_syscall(event); + return; + case LT_EV_ARCH_SYSRET: + debug(1, "event: arch_sysret (%s [%d])", + arch_sysname(event->proc, event->e_un.sysnum), + event->e_un.sysnum); + process_arch_sysret(event); + return; case LT_EV_BREAKPOINT: debug(1, "event: breakpoint"); process_breakpoint(event); @@ -194,6 +226,19 @@ static void process_syscall(struct event continue_process(event->proc->pid); } +static void process_arch_syscall(struct event *event) +{ + if (opt_S) { + output_left(LT_TOF_SYSCALL, event->proc, + arch_sysname(event->proc, event->e_un.sysnum)); + } + if (event->proc->breakpoints_enabled == 0) { + enable_all_breakpoints(event->proc); + } + callstack_push_syscall(event->proc, 0xf0000 + event->e_un.sysnum); + continue_process(event->proc->pid); +} + struct timeval current_time_spent; static void calc_time_spent(struct process *proc) @@ -242,6 +287,19 @@ static void process_sysret(struct event continue_process(event->proc->pid); } +static void process_arch_sysret(struct event *event) +{ + if (opt_T || opt_c) { + calc_time_spent(event->proc); + } + callstack_pop(event->proc); + if (opt_S) { + output_right(LT_TOF_SYSCALLR, event->proc, + arch_sysname(event->proc, event->e_un.sysnum)); + } + continue_process(event->proc->pid); +} + static void process_breakpoint(struct event *event) { int i, j; Index: ltrace-indt/sysdeps/linux-gnu/arch_mksyscallent =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ltrace-indt/sysdeps/linux-gnu/arch_mksyscallent 2007-12-18 21:10:24.000000000 -0400 @@ -0,0 +1,43 @@ +#!/usr/bin/awk -f + +# hack expression to generate arch_syscallent.h from <asm/unistd.h> +# It reads from stdin and writes to stdout +# Currently (linux-2.6.16), it works OK on arm +# It is untested in other architectures + +BEGIN { + max=0; + FS="[ \t\n()+]+"; +} + +{ +# printf("/%s/%s/%s/%s/\n", $1, $2, $3, $4); + if (($1 ~ /^#define$/) && ($2 ~ /^__[A-Z]+_NR_/)) { + sub(/^__[A-Z]+_NR_/,"",$2); + if (($3>=0) && ($3<=1000)) { + SYSCALL[$3]=$2; + if ($3 > max) { + max=$3; + } + } else if (($3 ~ /^__[A-Z]+_NR_BASE$/) && ($4>=0) && ($4<=1000)) { + SYSCALL[$4]=$2; + if ($4 > max) { + max=$4; + } + } + } +} + +END { + for(i=0; i<=max; i++) { + if (!SYSCALL[i]) { + SYSCALL[i] = i; + } + pad = 32 - length(SYSCALL[i]); + if (pad<1) { + pad=1; + } + printf("\t\"%s\",%*s/* %d */\n", SYSCALL[i], pad, "", i); + } +} + Index: ltrace-indt/sysdeps/linux-gnu/Makefile =================================================================== --- ltrace-indt.orig/sysdeps/linux-gnu/Makefile 2007-12-18 21:10:24.000000000 -0400 +++ ltrace-indt/sysdeps/linux-gnu/Makefile 2007-12-18 21:10:24.000000000 -0400 @@ -5,7 +5,7 @@ CPPFLAGS += -I$(TOPDIR)/sysdeps/linux-gn OBJ = trace.o proc.o breakpoint.o -all: sysdep.h signalent.h syscallent.h signalent1.h syscallent1.h ../sysdep.o +all: sysdep.h signalent.h syscallent.h arch_syscallent.h signalent1.h syscallent1.h ../sysdep.o sysdep.h: $(ARCH)/arch.h cat $(ARCH)/arch.h > sysdep.h @@ -29,6 +29,13 @@ syscallent1.h: > syscallent1.h; \ fi +arch_syscallent.h: + if [ -f $(ARCH)/arch_syscallent.h ]; then \ + cp $(ARCH)/arch_syscallent.h arch_syscallent.h; \ + else \ + > arch_syscallent.h; \ + fi + ../sysdep.o: os.o $(ARCH)/arch.o $(CC) -nostdlib -r -o ../sysdep.o os.o $(ARCH)/arch.o @@ -40,7 +47,7 @@ $(ARCH)/arch.o: dummy clean: $(MAKE) -C $(ARCH) clean - rm -f $(OBJ) sysdep.h signalent.h signalent1.h syscallent.h + rm -f $(OBJ) sysdep.h signalent.h signalent1.h syscallent.h arch_syscallent.h rm -f syscallent1.h os.o sysdep.o ../sysdep.o dummy: Index: ltrace-indt/wait_for_something.c =================================================================== --- ltrace-indt.orig/wait_for_something.c 2007-12-18 21:10:24.000000000 -0400 +++ ltrace-indt/wait_for_something.c 2007-12-18 21:10:24.000000000 -0400 @@ -72,6 +72,14 @@ struct event *wait_for_something(void) event.thing = LT_EV_SYSRET; event.e_un.sysnum = tmp; return &event; + case 3: + event.thing = LT_EV_ARCH_SYSCALL; + event.e_un.sysnum = tmp; + return &event; + case 4: + event.thing = LT_EV_ARCH_SYSRET; + event.e_un.sysnum = tmp; + return &event; case -1: event.thing = LT_EV_NONE; continue_process(event.proc->pid); Index: ltrace-indt/sysdeps/linux-gnu/arm/arch_syscallent.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ltrace-indt/sysdeps/linux-gnu/arm/arch_syscallent.h 2007-12-18 21:10:24.000000000 -0400 @@ -0,0 +1,6 @@ + "0", /* 0 */ + "breakpoint", /* 1 */ + "cacheflush", /* 2 */ + "usr26", /* 3 */ + "usr32", /* 4 */ + "set_tls", /* 5 */ Index: ltrace-indt/sysdeps/linux-gnu/arm/trace.c =================================================================== --- ltrace-indt.orig/sysdeps/linux-gnu/arm/trace.c 2007-12-18 21:10:24.000000000 -0400 +++ ltrace-indt/sysdeps/linux-gnu/arm/trace.c 2007-12-18 21:10:24.000000000 -0400 @@ -28,7 +28,10 @@ void get_arch_dep(struct process *proc) { } -/* Returns 0 if not a syscall, 1 if syscall entry, 2 if syscall exit, -1 on error. +/* Returns 0 if not a syscall, + * 1 if syscall entry, 2 if syscall exit, + * 3 if arch-specific syscall entry, 4 if arch-specific syscall exit, + * -1 on error. */ int syscall_p(struct process *proc, int status, int *sysnum) { @@ -55,6 +58,11 @@ int syscall_p(struct process *proc, int output_line(proc, "unexpected instruction 0x%x at %p", insn, pc - 4); return -1; } + if ((*sysnum & 0xf0000) == 0xf0000) { + /* arch-specific syscall */ + *sysnum &= ~0xf0000; + return ip ? 4 : 3; + } /* ARM syscall convention: on syscall entry, ip is zero; * on syscall exit, ip is non-zero */ return ip ? 2 : 1;

