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;

Reply via email to