diff options
author | Juan Cespedes <cespedes@debian.org> | 1998-09-24 13:49:55 +0200 |
---|---|---|
committer | Juan Cespedes <cespedes@debian.org> | 1998-09-24 13:49:55 +0200 |
commit | 8e3e082c27716245619721207cd5067d8c6271f9 (patch) | |
tree | cacb2699a2558356ada79b9953fca7fed50ab4b3 | |
parent | f666d191986d3b342cfa8b2e96ed90a49edf4303 (diff) | |
download | ltrace-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-- | BUGS | 2 | ||||
-rw-r--r-- | README | 19 | ||||
-rw-r--r-- | debian/changelog | 7 | ||||
-rw-r--r-- | debian/control | 2 | ||||
-rw-r--r-- | debian/copyright | 3 | ||||
-rw-r--r-- | ltrace.1 | 4 | ||||
-rw-r--r-- | ltrace.spec | 2 | ||||
-rw-r--r-- | options.c | 4 | ||||
-rw-r--r-- | sysdeps/Linux/Makefile | 2 | ||||
-rw-r--r-- | sysdeps/Linux/arm/Makefile | 10 | ||||
-rw-r--r-- | sysdeps/Linux/arm/arch.h | 6 | ||||
-rw-r--r-- | sysdeps/Linux/arm/breakpoint.c | 23 | ||||
-rw-r--r-- | sysdeps/Linux/arm/regs.c | 33 | ||||
-rw-r--r-- | sysdeps/Linux/arm/signalent.h | 32 | ||||
-rw-r--r-- | sysdeps/Linux/arm/syscallent.h | 164 | ||||
-rw-r--r-- | sysdeps/Linux/arm/trace.c | 104 |
16 files changed, 404 insertions, 13 deletions
@@ -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 @@ -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. @@ -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 @@ -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; +} |