aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan Cespedes <cespedes@debian.org>1998-09-24 13:49:55 +0200
committerJuan Cespedes <cespedes@debian.org>1998-09-24 13:49:55 +0200
commit8e3e082c27716245619721207cd5067d8c6271f9 (patch)
treecacb2699a2558356ada79b9953fca7fed50ab4b3
parentf666d191986d3b342cfa8b2e96ed90a49edf4303 (diff)
downloadltrace-8e3e082c27716245619721207cd5067d8c6271f9.tar.gz
Version: 0.3.5
* Added ARMLinux port (Pat Beirne <pbeirne@home.com>) (Bug#27040) * Fixed minor things in options.c
-rw-r--r--BUGS2
-rw-r--r--README19
-rw-r--r--debian/changelog7
-rw-r--r--debian/control2
-rw-r--r--debian/copyright3
-rw-r--r--ltrace.14
-rw-r--r--ltrace.spec2
-rw-r--r--options.c4
-rw-r--r--sysdeps/Linux/Makefile2
-rw-r--r--sysdeps/Linux/arm/Makefile10
-rw-r--r--sysdeps/Linux/arm/arch.h6
-rw-r--r--sysdeps/Linux/arm/breakpoint.c23
-rw-r--r--sysdeps/Linux/arm/regs.c33
-rw-r--r--sysdeps/Linux/arm/signalent.h32
-rw-r--r--sysdeps/Linux/arm/syscallent.h164
-rw-r--r--sysdeps/Linux/arm/trace.c104
16 files changed, 404 insertions, 13 deletions
diff --git a/BUGS b/BUGS
index c481fbb..2edbd39 100644
--- a/BUGS
+++ b/BUGS
@@ -2,4 +2,4 @@
* Manual page is not accurate (config files...)
* elf.c only supports elf32 binaries
* netscape sometimes dies with SIGSEGV (is this still true?)
-* Only Linux/i386 is supported
+* It only works on Linux/i386 and Linux/arm
diff --git a/README b/README
index 81eca6c..8d5c186 100644
--- a/README
+++ b/README
@@ -7,6 +7,7 @@
Contents
--------
+ 0. Authors
1. Introduction
2. Where can I find it
3. How does it work
@@ -15,6 +16,14 @@ Contents
6. Licence
+0. Authors
+----------
+ltrace has been developed mainly by Juan Cespedes <cespedes@debian.org>,
+but he has received many contributions from other people. The following
+people have contributed significantly to this project:
+
+* Pat Beirne <pbeirne@home.com> (ARM port)
+
1. Introduction
---------------
ltrace is a debugging tool, similar to strace, but it traces library
@@ -33,14 +42,12 @@ see ftp://ftp.debian.org/debian/README.mirrors
3. How does it work
-------------------
-Using i386 software breakpoints, just like gdb.
+Using software breakpoints, just like gdb.
4. Where does it work
---------------------
-At the time of writting, it works only with Intel ELF executables. It
-has been used only in Debian/GNU Linux, but it should work without any
-problem in any other i386 Linux, such as SuSe or RedHat, and maybe in
-other i386 based POSIX system, such as Hurd or *BSD.
+At the time of writting, it works only with ELF32 executables. It only
+works in Linux, and it only works on i386 and ARM processors.
5. Bugs
-------
@@ -50,7 +57,7 @@ or mail ``Juan Cespedes <cespedes@debian.org>''.
6. Licence
----------
- Copyright (C) 1997 Juan Cespedes <cespedes@debian.org>
+ Copyright (C) 1997,1998 Juan Cespedes <cespedes@debian.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/debian/changelog b/debian/changelog
index e6fceac..882d3db 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+ltrace (0.3.5) unstable; urgency=low
+
+ * Added ARMLinux port (Pat Beirne <pbeirne@home.com>) (Bug#27040)
+ * Fixed minor things in options.c
+
+ -- Juan Cespedes <cespedes@debian.org> Thu, 24 Sep 1998 13:18:01 +0200
+
ltrace (0.3.4) unstable; urgency=low
* Added "ltrace.spec" to build a .rpm binary file.
diff --git a/debian/control b/debian/control
index 8769897..7421947 100644
--- a/debian/control
+++ b/debian/control
@@ -5,7 +5,7 @@ Maintainer: Juan Cespedes <cespedes@debian.org>
Standards-Version: 2.4.1
Package: ltrace
-Architecture: i386
+Architecture: i386 arm
Depends: ${shlibs:Depends}
Description: A library call tracer
ltrace is a library call tracer, i.e. a debugging tool which prints out
diff --git a/debian/copyright b/debian/copyright
index dc71675..3cf4b0a 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -5,6 +5,9 @@ Dynamic Library Tracer ``ltrace''.
Copyrights
----------
Copyright (C) 1997,1998 Juan Cespedes <cespedes@debian.org>
+
+ARMLinux port: Copyright (C) 1998 Pat Beirne <pbeirne@home.com>
+
Autoconf stuff: Copyright 1992-1996 Free Software Foundation, Inc.
install-sh: Copyright 1991 by the Massachusetts Institute of Technology
C++ demangle: Copyright 1989-1997 Free Software Foundation, Inc.
diff --git a/ltrace.1 b/ltrace.1
index 3264929..dad0980 100644
--- a/ltrace.1
+++ b/ltrace.1
@@ -1,4 +1,4 @@
-.\" Copyright (c) 1997 Juan Cespedes <cespedes@debian.org>
+.\" Copyright (c) 1997,1998 Juan Cespedes <cespedes@debian.org>
.\" This file is covered by the GNU GPL
.TH ltrace 1
.SH NAME
@@ -116,7 +116,7 @@ Manual page and documentation are not very up-to-date.
.LP
Option -f sometimes fails to trace some children.
.LP
-Only Linux/i386 is supported
+It only works on Linux/i386 and Linux/arm
.LP
Only ELF32 binaries are supported
.PP
diff --git a/ltrace.spec b/ltrace.spec
index edef6dd..e207ae0 100644
--- a/ltrace.spec
+++ b/ltrace.spec
@@ -1,6 +1,6 @@
Summary: A library call tracer
Name: ltrace
-%define version 0.3.4
+%define version 0.3.5
Version: %{version}
Release: 1
Copyright: GPL
diff --git a/options.c b/options.c
index 025e909..a8c1354 100644
--- a/options.c
+++ b/options.c
@@ -136,7 +136,9 @@ char ** process_options(int argc, char **argv)
static struct option long_options[] = {
{ "align", 1, 0, 'a'},
{ "debug", 0, 0, 'd'},
+# if HAVE_LIBIBERTY
{ "demangle", 0, 0, 'C'},
+#endif
{ "help", 0, 0, 'h'},
{ "output", 1, 0, 'o'},
{ "version", 0, 0, 'V'},
@@ -148,7 +150,7 @@ char ** process_options(int argc, char **argv)
# endif
"a:s:o:u:p:e:", long_options, &option_index);
#else
- c = getopt(argc, argv, "+dfiLSth"
+ c = getopt(argc, argv, "+dfiLSrthV"
# if HAVE_LIBIBERTY
"C"
# endif
diff --git a/sysdeps/Linux/Makefile b/sysdeps/Linux/Makefile
index 279e274..b9baa28 100644
--- a/sysdeps/Linux/Makefile
+++ b/sysdeps/Linux/Makefile
@@ -1,4 +1,4 @@
-ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
+ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
CFLAGS += -I$(TOPDIR)/sysdeps/Linux/$(ARCH)
diff --git a/sysdeps/Linux/arm/Makefile b/sysdeps/Linux/arm/Makefile
new file mode 100644
index 0000000..f630626
--- /dev/null
+++ b/sysdeps/Linux/arm/Makefile
@@ -0,0 +1,10 @@
+OBJ = breakpoint.o trace.o regs.o
+
+all: arch.o
+
+arch.o: $(OBJ) arch.h
+ $(LD) -r -o arch.o $(OBJ)
+
+clean:
+ $(RM) $(OBJ) arch.o
+
diff --git a/sysdeps/Linux/arm/arch.h b/sysdeps/Linux/arm/arch.h
new file mode 100644
index 0000000..7a5af84
--- /dev/null
+++ b/sysdeps/Linux/arm/arch.h
@@ -0,0 +1,6 @@
+#include <sys/types.h>
+
+#define BREAKPOINT_VALUE 0xef9f0001
+#define BREAKPOINT_LENGTH 4
+/* we don't need to decr the pc; the kernel does it for us! */
+#define DECR_PC_AFTER_BREAK 0
diff --git a/sysdeps/Linux/arm/breakpoint.c b/sysdeps/Linux/arm/breakpoint.c
new file mode 100644
index 0000000..1fe7994
--- /dev/null
+++ b/sysdeps/Linux/arm/breakpoint.c
@@ -0,0 +1,23 @@
+#include <sys/ptrace.h>
+#include "ltrace.h"
+
+void insert_breakpoint(int pid, struct breakpoint * sbp)
+{
+ int a;
+
+ a = ptrace(PTRACE_PEEKTEXT, pid, sbp->addr, 0);
+ sbp->orig_value[0] = a;
+ sbp->orig_value[1] = a>>8;
+ sbp->orig_value[2] = a>>16;
+ sbp->orig_value[3] = a>>24;
+ a = BREAKPOINT_VALUE;
+ ptrace(PTRACE_POKETEXT, pid, sbp->addr, a);
+}
+
+void delete_breakpoint(int pid, struct breakpoint * sbp)
+{
+ int a;
+
+ a = sbp->orig_value[0] + (sbp->orig_value[1]<<8) + (sbp->orig_value[2]<<16) + (sbp->orig_value[3]<<24);
+ ptrace(PTRACE_POKETEXT, pid, sbp->addr, a);
+}
diff --git a/sysdeps/Linux/arm/regs.c b/sysdeps/Linux/arm/regs.c
new file mode 100644
index 0000000..92d1ca9
--- /dev/null
+++ b/sysdeps/Linux/arm/regs.c
@@ -0,0 +1,33 @@
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <asm/ptrace.h>
+
+#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
+# define PTRACE_PEEKUSER PTRACE_PEEKUSR
+#endif
+
+#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
+# define PTRACE_POKEUSER PTRACE_POKEUSR
+#endif
+
+#define off_pc 60
+#define off_lr 56
+#define off_sp 52
+
+int get_instruction_pointer(pid_t pid)
+{
+ return ptrace(PTRACE_PEEKUSER, pid, off_pc, 0);
+}
+
+int get_stack_pointer(pid_t pid)
+{
+ return ptrace(PTRACE_PEEKUSER, pid, off_sp, 0);
+}
+
+/* really, this is given the *stack_pointer expecting
+ * a CISC architecture; in our case, we don't need that */
+int get_return_addr(pid_t pid, void * stack_pointer)
+{
+ return ptrace(PTRACE_PEEKUSER, pid, off_lr, 0);
+}
+
diff --git a/sysdeps/Linux/arm/signalent.h b/sysdeps/Linux/arm/signalent.h
new file mode 100644
index 0000000..e2c1337
--- /dev/null
+++ b/sysdeps/Linux/arm/signalent.h
@@ -0,0 +1,32 @@
+ "SIG_0", /* 0 */
+ "SIGHUP", /* 1 */
+ "SIGINT", /* 2 */
+ "SIGQUIT", /* 3 */
+ "SIGILL", /* 4 */
+ "SIGTRAP", /* 5 */
+ "SIGABRT", /* 6 */
+ "SIGBUS", /* 7 */
+ "SIGFPE", /* 8 */
+ "SIGKILL", /* 9 */
+ "SIGUSR1", /* 10 */
+ "SIGSEGV", /* 11 */
+ "SIGUSR2", /* 12 */
+ "SIGPIPE", /* 13 */
+ "SIGALRM", /* 14 */
+ "SIGTERM", /* 15 */
+ "SIGSTKFLT", /* 16 */
+ "SIGCHLD", /* 17 */
+ "SIGCONT", /* 18 */
+ "SIGSTOP", /* 19 */
+ "SIGTSTP", /* 20 */
+ "SIGTTIN", /* 21 */
+ "SIGTTOU", /* 22 */
+ "SIGURG", /* 23 */
+ "SIGXCPU", /* 24 */
+ "SIGXFSZ", /* 25 */
+ "SIGVTALRM", /* 26 */
+ "SIGPROF", /* 27 */
+ "SIGWINCH", /* 28 */
+ "SIGIO", /* 29 */
+ "SIGPWR", /* 30 */
+ "SIGUNUSED", /* 31 */
diff --git a/sysdeps/Linux/arm/syscallent.h b/sysdeps/Linux/arm/syscallent.h
new file mode 100644
index 0000000..36b9021
--- /dev/null
+++ b/sysdeps/Linux/arm/syscallent.h
@@ -0,0 +1,164 @@
+ "setup", /* 0 */
+ "exit", /* 1 */
+ "fork", /* 2 */
+ "read", /* 3 */
+ "write", /* 4 */
+ "open", /* 5 */
+ "close", /* 6 */
+ "waitpid", /* 7 */
+ "creat", /* 8 */
+ "link", /* 9 */
+ "unlink", /* 10 */
+ "execve", /* 11 */
+ "chdir", /* 12 */
+ "time", /* 13 */
+ "mknod", /* 14 */
+ "chmod", /* 15 */
+ "chown", /* 16 */
+ "break", /* 17 */
+ "oldstat", /* 18 */
+ "lseek", /* 19 */
+ "getpid", /* 20 */
+ "mount", /* 21 */
+ "umount", /* 22 */
+ "setuid", /* 23 */
+ "getuid", /* 24 */
+ "stime", /* 25 */
+ "ptrace", /* 26 */
+ "alarm", /* 27 */
+ "oldfstat", /* 28 */
+ "pause", /* 29 */
+ "utime", /* 30 */
+ "stty", /* 31 */
+ "gtty", /* 32 */
+ "access", /* 33 */
+ "nice", /* 34 */
+ "ftime", /* 35 */
+ "sync", /* 36 */
+ "kill", /* 37 */
+ "rename", /* 38 */
+ "mkdir", /* 39 */
+ "rmdir", /* 40 */
+ "dup", /* 41 */
+ "pipe", /* 42 */
+ "times", /* 43 */
+ "prof", /* 44 */
+ "brk", /* 45 */
+ "setgid", /* 46 */
+ "getgid", /* 47 */
+ "signal", /* 48 */
+ "geteuid", /* 49 */
+ "getegid", /* 50 */
+ "acct", /* 51 */
+ "phys", /* 52 */
+ "lock", /* 53 */
+ "ioctl", /* 54 */
+ "fcntl", /* 55 */
+ "mpx", /* 56 */
+ "setpgid", /* 57 */
+ "ulimit", /* 58 */
+ "oldolduname", /* 59 */
+ "umask", /* 60 */
+ "chroot", /* 61 */
+ "ustat", /* 62 */
+ "dup2", /* 63 */
+ "getppid", /* 64 */
+ "getpgrp", /* 65 */
+ "setsid", /* 66 */
+ "sigaction", /* 67 */
+ "sgetmask", /* 68 */
+ "ssetmask", /* 69 */
+ "setreuid", /* 70 */
+ "setregid", /* 71 */
+ "sigsuspend", /* 72 */
+ "sigpending", /* 73 */
+ "sethostname", /* 74 */
+ "setrlimit", /* 75 */
+ "getrlimit", /* 76 */
+ "getrusage", /* 77 */
+ "gettimeofday", /* 78 */
+ "settimeofday", /* 79 */
+ "getgroups", /* 80 */
+ "setgroups", /* 81 */
+ "select", /* 82 */
+ "symlink", /* 83 */
+ "oldlstat", /* 84 */
+ "readlink", /* 85 */
+ "uselib", /* 86 */
+ "swapon", /* 87 */
+ "reboot", /* 88 */
+ "readdir", /* 89 */
+ "mmap", /* 90 */
+ "munmap", /* 91 */
+ "truncate", /* 92 */
+ "ftruncate", /* 93 */
+ "fchmod", /* 94 */
+ "fchown", /* 95 */
+ "getpriority", /* 96 */
+ "setpriority", /* 97 */
+ "profil", /* 98 */
+ "statfs", /* 99 */
+ "fstatfs", /* 100 */
+ "ioperm", /* 101 */
+ "socketcall", /* 102 */
+ "syslog", /* 103 */
+ "setitimer", /* 104 */
+ "getitimer", /* 105 */
+ "stat", /* 106 */
+ "lstat", /* 107 */
+ "fstat", /* 108 */
+ "olduname", /* 109 */
+ "iopl", /* 110 */
+ "vhangup", /* 111 */
+ "idle", /* 112 */
+ "vm86", /* 113 */
+ "wait4", /* 114 */
+ "swapoff", /* 115 */
+ "sysinfo", /* 116 */
+ "ipc", /* 117 */
+ "fsync", /* 118 */
+ "sigreturn", /* 119 */
+ "clone", /* 120 */
+ "setdomainname", /* 121 */
+ "uname", /* 122 */
+ "modify_ldt", /* 123 */
+ "adjtimex", /* 124 */
+ "mprotect", /* 125 */
+ "sigprocmask", /* 126 */
+ "create_module", /* 127 */
+ "init_module", /* 128 */
+ "delete_module", /* 129 */
+ "get_kernel_syms", /* 130 */
+ "quotactl", /* 131 */
+ "getpgid", /* 132 */
+ "fchdir", /* 133 */
+ "bdflush", /* 134 */
+ "sysfs", /* 135 */
+ "personality", /* 136 */
+ "afs_syscall", /* 137 */
+ "setfsuid", /* 138 */
+ "setfsgid", /* 139 */
+ "_llseek", /* 140 */
+ "getdents", /* 141 */
+ "_newselect", /* 142 */
+ "flock", /* 143 */
+ "msync", /* 144 */
+ "readv", /* 145 */
+ "writev", /* 146 */
+ "getsid", /* 147 */
+ "fdatasync", /* 148 */
+ "_sysctl", /* 149 */
+ "mlock", /* 150 */
+ "munlock", /* 151 */
+ "mlockall", /* 152 */
+ "munlockall", /* 153 */
+ "sched_setparam", /* 154 */
+ "sched_getparam", /* 155 */
+ "sched_setscheduler", /* 156 */
+ "sched_getscheduler", /* 157 */
+ "sched_yield", /* 158 */
+ "sched_get_priority_max",/* 159 */
+ "sched_get_priority_min",/* 160 */
+ "sched_rr_get_interval",/* 161 */
+ "nanosleep", /* 162 */
+ "mremap", /* 163 */
diff --git a/sysdeps/Linux/arm/trace.c b/sysdeps/Linux/arm/trace.c
new file mode 100644
index 0000000..95d2c47
--- /dev/null
+++ b/sysdeps/Linux/arm/trace.c
@@ -0,0 +1,104 @@
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <sys/ptrace.h>
+#include <asm/ptrace.h>
+
+#include "ltrace.h"
+
+#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
+# define PTRACE_PEEKUSER PTRACE_PEEKUSR
+#endif
+
+#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
+# 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_ip 48
+#define off_pc 60
+
+/* Returns 1 if syscall, 2 if sysret, 0 otherwise.
+ */
+int syscall_p(struct process * proc, int status, int * sysnum)
+{
+ if (WIFSTOPPED(status) && WSTOPSIG(status)==SIGTRAP) {
+ /* get the user's pc (plus 8) */
+ int pc = ptrace(PTRACE_PEEKUSER, proc->pid, off_pc, 0);
+ /* fetch the SWI instruction */
+ int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, pc-4, 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;
+ }
+ }
+ return 0;
+}
+
+
+void continue_after_breakpoint(struct process *proc, struct breakpoint * sbp, int delete_it)
+{
+ delete_breakpoint(proc->pid, sbp);
+ ptrace(PTRACE_POKEUSER, proc->pid, off_pc, sbp->addr);
+ if (delete_it) {
+ continue_process(proc->pid);
+ } else {
+ proc->breakpoint_being_enabled = sbp;
+ ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0);
+ }
+}
+
+long gimme_arg(enum tof type, struct process * proc, int arg_num)
+{
+ if (arg_num==-1) { /* return value */
+ return ptrace(PTRACE_PEEKUSER, proc->pid, off_r0, 0);
+ }
+
+ /* deal with the ARM calling conventions */
+ if (type==LT_TOF_FUNCTION) {
+ if (arg_num<4) {
+ return ptrace(PTRACE_PEEKUSER, proc->pid, 4*arg_num, 0);
+ } else {
+ return ptrace(PTRACE_PEEKDATA, proc->pid, proc->stack_pointer+4*(arg_num-4), 0);
+ }
+ } else if (type==LT_TOF_SYSCALL) {
+ if (arg_num<5) {
+ return ptrace(PTRACE_PEEKUSER, proc->pid, 4*arg_num, 0);
+ } else {
+ return ptrace(PTRACE_PEEKDATA, proc->pid, proc->stack_pointer+4*(arg_num-5), 0);
+ }
+ } else {
+ fprintf(stderr, "gimme_arg called with wrong arguments\n");
+ exit(1);
+ }
+
+ return 0;
+}
+
+int umovestr(struct process * proc, void * addr, int len, void * laddr)
+{
+ long a;
+ int i;
+ int offset=0;
+
+ while(offset<len) {
+ a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr+offset, 0);
+ for(i=0; i<sizeof(long); i++) {
+ if (((char*)&a)[i] && offset+i < len) {
+ *(char *)(laddr+offset+i) = ((char*)&a)[i];
+ } else {
+ *(char *)(laddr+offset+i) = '\0';
+ return 0;
+ }
+ }
+ offset += sizeof(long);
+ }
+ *(char *)(laddr+offset) = '\0';
+ return 0;
+}