aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--Makefile.in4
-rw-r--r--breakpoints.c4
-rw-r--r--debian/changelog21
-rw-r--r--ltrace.c1
-rw-r--r--ltrace.h10
-rw-r--r--process_event.c58
-rw-r--r--sysdeps/linux-gnu/Makefile11
-rw-r--r--sysdeps/linux-gnu/arch_mksyscallent42
-rw-r--r--sysdeps/linux-gnu/arm/Makefile2
-rw-r--r--sysdeps/linux-gnu/arm/arch.h7
-rw-r--r--sysdeps/linux-gnu/arm/arch_syscallent.h6
-rw-r--r--sysdeps/linux-gnu/arm/breakpoint.c77
-rw-r--r--sysdeps/linux-gnu/arm/ptrace.h8
-rw-r--r--sysdeps/linux-gnu/arm/regs.c7
-rw-r--r--sysdeps/linux-gnu/arm/trace.c64
-rw-r--r--testsuite/ltrace.minor/Makefile.in2
-rw-r--r--testsuite/ltrace.minor/trace-clone.c2
-rw-r--r--wait_for_something.c28
19 files changed, 339 insertions, 26 deletions
diff --git a/ChangeLog b/ChangeLog
index e495253..937d198 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2008-12-10 Juan Cespedes <cespedes@debian.org>
+
+ * Patches from Anderson Lizardo and Riku Voipio:
+ + Add generic support for arm targets
+ + Save funtion arguments on arm
+ + Add thumb instruction support
+ + Add basic arm/eabi support
+ + fix exec() testcase cleanup
+ + fix memory corruption in clone() test
+ + fix tracing child with "-p" option
+
2008-02-27 Luis Machado <luisgpm@br.ibm.com>
* sysdeps/linux-gnu/ppc/trace.c (arch_umovelong): New function.
diff --git a/Makefile.in b/Makefile.in
index e43f057..b29b066 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -5,6 +5,10 @@
#OS := $(shell uname -s)
OS := @HOST_OS@
+ifeq ($(OS),linux-gnueabi)
+OS = linux-gnu
+endif
+
TOPDIR = $(shell pwd)
prefix = @prefix@
diff --git a/breakpoints.c b/breakpoints.c
index 18de1e2..b77ad60 100644
--- a/breakpoints.c
+++ b/breakpoints.c
@@ -48,6 +48,10 @@ insert_breakpoint(struct process *proc, void *addr,
if (libsym)
libsym->brkpnt = sbp;
}
+#ifdef __arm__
+ sbp->thumb_mode = proc->thumb_mode;
+ proc->thumb_mode = 0;
+#endif
sbp->enabled++;
if (sbp->enabled == 1 && proc->pid)
enable_breakpoint(proc->pid, sbp);
diff --git a/debian/changelog b/debian/changelog
index 18a6b63..8441019 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,24 @@
+ltrace (0.5-3.1) unstable; urgency=low
+
+ * Non-maintainer upload.
+ * Big thanks for Anderson Lizardo for providing patches!
+ * Add generic support for arm targets, Closes: #176413
+ * Save funtion arguments on arm, Closes: #462530
+ * Add thumb instruction support, Closes: #462531
+ * Add basic arm/eabi support, Closes: #450931
+ * fix exec() testcase cleanup, Closes: #462532
+ * fix memory corruption in clone() test, Closes: #462533
+ * fix tracing child with "-p" option, Closes: #462535
+ * Update standard, no changes
+
+ -- Riku Voipio <riku.voipio@iki.fi> Tue, 29 Jan 2008 00:26:50 +0200
+
+ltrace (0.5-3) unstable; urgency=low
+
+ * Really fix compilation problems in ppc (!)
+
+ -- Juan Cespedes <cespedes@debian.org> Fri, 31 Aug 2007 19:04:03 +0200
+
ltrace (0.5-2) unstable; urgency=low
* Fixed compilation issue in ppc
diff --git a/ltrace.c b/ltrace.c
index 3a5f9aa..8ba1347 100644
--- a/ltrace.c
+++ b/ltrace.c
@@ -77,6 +77,7 @@ static void normal_exit(void)
}
if (opt_o) {
fclose(output);
+ opt_o = 0;
}
}
diff --git a/ltrace.h b/ltrace.h
index 3733ad8..f029664 100644
--- a/ltrace.h
+++ b/ltrace.h
@@ -26,6 +26,9 @@ struct breakpoint {
unsigned char orig_value[BREAKPOINT_LENGTH];
int enabled;
struct library_symbol *libsym;
+#ifdef __arm__
+ int thumb_mode;
+#endif
};
enum arg_type {
@@ -170,6 +173,9 @@ struct process {
void *arch_ptr;
short e_machine;
short need_to_reinitialize_breakpoints;
+#ifdef __arm__
+ int thumb_mode; /* ARM execution mode: 0: ARM mode, 1: Thumb mode */
+#endif
/* output: */
enum tof type_being_displayed;
@@ -187,12 +193,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;
};
diff --git a/process_event.c b/process_event.c
index 9e6ef81..177fc6a 100644
--- a/process_event.c
+++ b/process_event.c
@@ -24,7 +24,9 @@ static void process_signal(struct event *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 *proc, int sysnum)
}
}
+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 *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 *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;
diff --git a/sysdeps/linux-gnu/Makefile b/sysdeps/linux-gnu/Makefile
index 6cbff83..6e0eb32 100644
--- a/sysdeps/linux-gnu/Makefile
+++ b/sysdeps/linux-gnu/Makefile
@@ -5,7 +5,7 @@ CPPFLAGS += -I$(TOPDIR)/sysdeps/linux-gnu/$(ARCH)
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:
diff --git a/sysdeps/linux-gnu/arch_mksyscallent b/sysdeps/linux-gnu/arch_mksyscallent
new file mode 100644
index 0000000..853d62d
--- /dev/null
+++ b/sysdeps/linux-gnu/arch_mksyscallent
@@ -0,0 +1,42 @@
+#!/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);
+ }
+}
diff --git a/sysdeps/linux-gnu/arm/Makefile b/sysdeps/linux-gnu/arm/Makefile
index 00e77bc..f55ba48 100644
--- a/sysdeps/linux-gnu/arm/Makefile
+++ b/sysdeps/linux-gnu/arm/Makefile
@@ -1,4 +1,4 @@
-OBJ = trace.o regs.o plt.o
+OBJ = trace.o regs.o plt.o breakpoint.o
all: arch.o
diff --git a/sysdeps/linux-gnu/arm/arch.h b/sysdeps/linux-gnu/arm/arch.h
index e8a8b66..8f2dfb3 100644
--- a/sysdeps/linux-gnu/arm/arch.h
+++ b/sysdeps/linux-gnu/arm/arch.h
@@ -1,5 +1,10 @@
-#define BREAKPOINT_VALUE { 0x01, 0x00, 0x9f, 0xef }
+#define ARCH_HAVE_ENABLE_BREAKPOINT 1
+#define ARCH_HAVE_DISABLE_BREAKPOINT 1
+
+#define BREAKPOINT_VALUE { 0xf0, 0x01, 0xf0, 0xe7 }
#define BREAKPOINT_LENGTH 4
+#define THUMB_BREAKPOINT_VALUE { 0x01, 0xde }
+#define THUMB_BREAKPOINT_LENGTH 2
#define DECR_PC_AFTER_BREAK 0
#define LT_ELFCLASS ELFCLASS32
diff --git a/sysdeps/linux-gnu/arm/arch_syscallent.h b/sysdeps/linux-gnu/arm/arch_syscallent.h
new file mode 100644
index 0000000..ce1e844
--- /dev/null
+++ b/sysdeps/linux-gnu/arm/arch_syscallent.h
@@ -0,0 +1,6 @@
+ "0", /* 0 */
+ "breakpoint", /* 1 */
+ "cacheflush", /* 2 */
+ "usr26", /* 3 */
+ "usr32", /* 4 */
+ "set_tls", /* 5 */
diff --git a/sysdeps/linux-gnu/arm/breakpoint.c b/sysdeps/linux-gnu/arm/breakpoint.c
new file mode 100644
index 0000000..2130dcb
--- /dev/null
+++ b/sysdeps/linux-gnu/arm/breakpoint.c
@@ -0,0 +1,77 @@
+/*
+ * This file is part of ltrace.
+ *
+ * Copyright (C) 2007 by Instituto Nokia de Tecnologia (INdT)
+ *
+ * Author: Anderson Lizardo <anderson.lizardo@indt.org.br>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * Modified from sysdeps/linux-gnu/breakpoint.c and added ARM Thumb support.
+ */
+
+#include <sys/ptrace.h>
+#include "config.h"
+#include "arch.h"
+#include "options.h"
+#include "output.h"
+#include "debug.h"
+
+void arch_enable_breakpoint(pid_t pid, struct breakpoint *sbp)
+{
+ unsigned int i, j;
+ const unsigned char break_insn[] = BREAKPOINT_VALUE;
+ const unsigned char thumb_break_insn[] = THUMB_BREAKPOINT_VALUE;
+
+ debug(1, "arch_enable_breakpoint(%d,%p)", pid, sbp->addr);
+
+ for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) {
+ long a = ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i * sizeof(long), 0);
+ unsigned char *bytes = (unsigned char *)&a;
+
+ debug(2, "current = 0x%lx, orig_value = 0x%lx, thumb_mode = %d", a, *(long *)&sbp->orig_value, sbp->thumb_mode);
+ for (j = 0; j < sizeof(long) && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) {
+
+ sbp->orig_value[i * sizeof(long) + j] = bytes[j];
+ if (!sbp->thumb_mode) {
+ bytes[j] = break_insn[i * sizeof(long) + j];
+ }
+ else if (j < THUMB_BREAKPOINT_LENGTH) {
+ bytes[j] = thumb_break_insn[i * sizeof(long) + j];
+ }
+ }
+ ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a);
+ }
+}
+
+void arch_disable_breakpoint(pid_t pid, const struct breakpoint *sbp)
+{
+ unsigned int i, j;
+ const unsigned char break_insn[] = BREAKPOINT_VALUE;
+ const unsigned char thumb_break_insn[] = THUMB_BREAKPOINT_VALUE;
+
+ debug(1, "arch_disable_breakpoint(%d,%p)", pid, sbp->addr);
+
+ for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) {
+ long a = ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i * sizeof(long), 0);
+ unsigned char *bytes = (unsigned char *)&a;
+
+ debug(2, "current = 0x%lx, orig_value = 0x%lx, thumb_mode = %d", a, *(long *)&sbp->orig_value, sbp->thumb_mode);
+ for (j = 0; j < sizeof(long) && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) {
+ bytes[j] = sbp->orig_value[i * sizeof(long) + j];
+ }
+ ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a);
+ }
+}
diff --git a/sysdeps/linux-gnu/arm/ptrace.h b/sysdeps/linux-gnu/arm/ptrace.h
index c3cbcb6..52215bc 100644
--- a/sysdeps/linux-gnu/arm/ptrace.h
+++ b/sysdeps/linux-gnu/arm/ptrace.h
@@ -1 +1,9 @@
#include <sys/ptrace.h>
+#include <asm/ptrace.h>
+
+typedef struct {
+ int valid;
+ struct pt_regs regs;
+ long func_arg[5];
+ long sysc_arg[5];
+} proc_archdep;
diff --git a/sysdeps/linux-gnu/arm/regs.c b/sysdeps/linux-gnu/arm/regs.c
index 819754f..b1c4ae6 100644
--- a/sysdeps/linux-gnu/arm/regs.c
+++ b/sysdeps/linux-gnu/arm/regs.c
@@ -39,5 +39,10 @@ void *get_stack_pointer(struct process *proc)
* a CISC architecture; in our case, we don't need that */
void *get_return_addr(struct process *proc, void *stack_pointer)
{
- return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, off_lr, 0);
+ long addr = ptrace(PTRACE_PEEKUSER, proc->pid, off_lr, 0);
+
+ proc->thumb_mode = addr & 1;
+ if (proc->thumb_mode)
+ addr &= ~1;
+ return (void *)addr;
}
diff --git a/sysdeps/linux-gnu/arm/trace.c b/sysdeps/linux-gnu/arm/trace.c
index b5c2122..b9be605 100644
--- a/sysdeps/linux-gnu/arm/trace.c
+++ b/sysdeps/linux-gnu/arm/trace.c
@@ -2,6 +2,7 @@
#include "config.h"
#endif
+#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
@@ -9,6 +10,8 @@
#include <asm/ptrace.h>
#include "ltrace.h"
+#include "output.h"
+#include "ptrace.h"
#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
# define PTRACE_PEEKUSER PTRACE_PEEKUSR
@@ -18,19 +21,25 @@
# define PTRACE_POKEUSER PTRACE_POKEUSR
#endif
-/* syscall tracing protocol: ArmLinux
- on the way in, ip is 0
- on the way out, ip is non-zero
-*/
#define off_r0 0
+#define off_r7 28
#define off_ip 48
#define off_pc 60
void get_arch_dep(struct process *proc)
{
+ proc_archdep *a;
+
+ if (!proc->arch_ptr)
+ proc->arch_ptr = (void *)malloc(sizeof(proc_archdep));
+ a = (proc_archdep *) (proc->arch_ptr);
+ a->valid = (ptrace(PTRACE_GETREGS, proc->pid, 0, &a->regs) >= 0);
}
-/* Returns 1 if syscall, 2 if sysret, 0 otherwise.
+/* 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)
{
@@ -40,19 +49,39 @@ int syscall_p(struct process *proc, int status, int *sysnum)
int pc = ptrace(PTRACE_PEEKUSER, proc->pid, off_pc, 0);
/* fetch the SWI instruction */
int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 4, 0);
+ int ip = ptrace(PTRACE_PEEKUSER, proc->pid, off_ip, 0);
- *sysnum = insn & 0xFFFF;
- /* if it is a syscall, return 1 or 2 */
- if ((insn & 0xFFFF0000) == 0xef900000) {
- return ptrace(PTRACE_PEEKUSER, proc->pid, off_ip,
- 0) ? 2 : 1;
+ if (insn == 0xef000000 || insn == 0x0f000000) {
+ /* EABI syscall */
+ *sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, off_r7, 0);
+ } else if ((insn & 0xfff00000) == 0xef900000) {
+ /* old ABI syscall */
+ *sysnum = insn & 0xfffff;
+ } else {
+ /* TODO: handle swi<cond> variations */
+ /* one possible reason for getting in here is that we
+ * are coming from a signal handler, so the current
+ * PC does not point to the instruction just after the
+ * "swi" one. */
+ 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;
}
return 0;
}
long gimme_arg(enum tof type, struct process *proc, int arg_num, arg_type_info *info)
{
+ proc_archdep *a = (proc_archdep *) proc->arch_ptr;
+
if (arg_num == -1) { /* return value */
return ptrace(PTRACE_PEEKUSER, proc->pid, off_r0, 0);
}
@@ -60,6 +89,10 @@ long gimme_arg(enum tof type, struct process *proc, int arg_num, arg_type_info *
/* deal with the ARM calling conventions */
if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) {
if (arg_num < 4) {
+ if (a->valid && type == LT_TOF_FUNCTION)
+ return a->regs.uregs[arg_num];
+ if (a->valid && type == LT_TOF_FUNCTIONR)
+ return a->func_arg[arg_num];
return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * arg_num,
0);
} else {
@@ -69,6 +102,10 @@ long gimme_arg(enum tof type, struct process *proc, int arg_num, arg_type_info *
}
} else if (type == LT_TOF_SYSCALL || type == LT_TOF_SYSCALLR) {
if (arg_num < 5) {
+ if (a->valid && type == LT_TOF_SYSCALL)
+ return a->regs.uregs[arg_num];
+ if (a->valid && type == LT_TOF_SYSCALLR)
+ return a->sysc_arg[arg_num];
return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * arg_num,
0);
} else {
@@ -86,4 +123,11 @@ long gimme_arg(enum tof type, struct process *proc, int arg_num, arg_type_info *
void save_register_args(enum tof type, struct process *proc)
{
+ proc_archdep *a = (proc_archdep *) proc->arch_ptr;
+ if (a->valid) {
+ if (type == LT_TOF_FUNCTION)
+ memcpy(a->func_arg, a->regs.uregs, sizeof(a->func_arg));
+ else
+ memcpy(a->sysc_arg, a->regs.uregs, sizeof(a->sysc_arg));
+ }
}
diff --git a/testsuite/ltrace.minor/Makefile.in b/testsuite/ltrace.minor/Makefile.in
index c4a1687..40fff97 100644
--- a/testsuite/ltrace.minor/Makefile.in
+++ b/testsuite/ltrace.minor/Makefile.in
@@ -19,7 +19,7 @@ CLEANFILES = *.log *.sum site.bak setval.tmp site.exp
.SUFFIXES:
clean:
- -rm -f demangle trace-fork trace-clone
+ -rm -f demangle trace-fork trace-clone trace-exec trace-exec1
-rm -f time-record-tt time-record-ttt time-record-T
-rm -f attach-process count-record
-rm -f print-instruction-pointer
diff --git a/testsuite/ltrace.minor/trace-clone.c b/testsuite/ltrace.minor/trace-clone.c
index e3c5f39..a1ccb22 100644
--- a/testsuite/ltrace.minor/trace-clone.c
+++ b/testsuite/ltrace.minor/trace-clone.c
@@ -26,7 +26,7 @@ int main ()
#ifdef __ia64__
pid = __clone2((myfunc)&child, stack, STACK_SIZE, CLONE_FS, NULL);
#else
- pid = clone((myfunc)&child, stack,CLONE_FS, NULL );
+ pid = clone((myfunc)&child, stack + STACK_SIZE, CLONE_FS, NULL);
#endif
if (pid < 0)
{
diff --git a/wait_for_something.c b/wait_for_something.c
index c65de41..9440652 100644
--- a/wait_for_something.c
+++ b/wait_for_something.c
@@ -64,14 +64,26 @@ struct event *wait_for_something(void)
get_instruction_pointer(event.proc);
}
switch (syscall_p(event.proc, status, &tmp)) {
- case 1:
- event.thing = LT_EV_SYSCALL;
- event.e_un.sysnum = tmp;
- return &event;
- case 2:
- event.thing = LT_EV_SYSRET;
- event.e_un.sysnum = tmp;
- return &event;
+ case 1:
+ event.thing = LT_EV_SYSCALL;
+ event.e_un.sysnum = tmp;
+ return &event;
+ case 2:
+ 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);
+ return &event;
}
if (WIFEXITED(status)) {
event.thing = LT_EV_EXIT;