aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan Cespedes <cespedes@thehackers.org>1997-03-29 16:47:50 +0100
committerJuan Cespedes <cespedes@thehackers.org>1997-03-29 16:47:50 +0100
commite2ca89923bc7207583b8688f8f0c11e77c23f8c1 (patch)
tree67bef6b7f9710e220473ba364e689893987afc6e
parent1519dd0c0d81a2de425403593ffb0da8b245ef82 (diff)
downloadltrace-e2ca89923bc7207583b8688f8f0c11e77c23f8c1.tar.gz
Version 0.0.1997.03.29
-rw-r--r--include/hck/syscall.h7
-rwxr-xr-xlib/libtrace.so.1bin2518 -> 18624 bytes
-rw-r--r--src/libtrace/Makefile5
-rw-r--r--src/libtrace/__setfpucw.c2
-rw-r--r--src/libtrace/atoi.c13
-rw-r--r--src/libtrace/bcopy.c10
-rw-r--r--src/libtrace/getenv.c15
-rw-r--r--src/libtrace/init_libtrace.c196
-rw-r--r--src/libtrace/libtrace.c33
-rw-r--r--src/libtrace/print_results.c327
-rw-r--r--src/libtrace/sprintf.c25
-rw-r--r--src/libtrace/strcat.c12
-rw-r--r--src/libtrace/strcmp.c12
-rw-r--r--src/libtrace/strlen.c10
-rw-r--r--src/libtrace/strncmp.c14
-rw-r--r--src/libtrace/strnlen.c11
-rw-r--r--src/libtrace/vsprintf.c267
-rw-r--r--src/ltrace/ltrace.c116
18 files changed, 1024 insertions, 51 deletions
diff --git a/include/hck/syscall.h b/include/hck/syscall.h
index 41f09ef..c1c9f44 100644
--- a/include/hck/syscall.h
+++ b/include/hck/syscall.h
@@ -86,6 +86,7 @@
#define _INLINE static inline
#endif
+#if 0
#define __syscall_return(type, res) \
do { \
if ((unsigned long)(res) >= (unsigned long)(-125)) { \
@@ -94,6 +95,12 @@ do { \
} \
return (type) (res); \
} while (0)
+#else
+#define __syscall_return(type, res) \
+do { \
+ return (type) (res); \
+} while (0)
+#endif
#define _syscall0(type,name) \
_INLINE type _sys_##name(void) \
diff --git a/lib/libtrace.so.1 b/lib/libtrace.so.1
index e4b03b0..c70f4ef 100755
--- a/lib/libtrace.so.1
+++ b/lib/libtrace.so.1
Binary files differ
diff --git a/src/libtrace/Makefile b/src/libtrace/Makefile
index cee9a61..6ec31a7 100644
--- a/src/libtrace/Makefile
+++ b/src/libtrace/Makefile
@@ -3,10 +3,13 @@ CC = gcc
CFLAGS = -Wall -O2 -I$(TOPDIR)/include
LD = ld
-OBJS = __setfpucw.o init_libtrace.o
+#OBJS = __setfpucw.o init_libtrace.o
+OBJS = libtrace.o
all: libtrace.so.1
+libtrace.o: libtrace.c __setfpucw.c init_libtrace.c strlen.c strncmp.c getenv.c atoi.c bcopy.c print_results.c sprintf.c vsprintf.c strcmp.c strnlen.c strcat.c
+
libtrace.so.1: $(OBJS)
$(LD) -shared -m elf_i386 -soname $@ -o $@ $(OBJS)
cp libtrace.so.1 $(TOPDIR)/lib
diff --git a/src/libtrace/__setfpucw.c b/src/libtrace/__setfpucw.c
index 5b48c37..18689de 100644
--- a/src/libtrace/__setfpucw.c
+++ b/src/libtrace/__setfpucw.c
@@ -4,8 +4,6 @@ This file is part of the Linux C Library.
#include <fpu_control.h>
-extern void init_libtrace(void);
-
void
__setfpucw(unsigned short fpu_control)
{
diff --git a/src/libtrace/atoi.c b/src/libtrace/atoi.c
new file mode 100644
index 0000000..de6a173
--- /dev/null
+++ b/src/libtrace/atoi.c
@@ -0,0 +1,13 @@
+static unsigned long atoi(const char *cp)
+{
+ unsigned long result;
+
+ result = 0;
+
+ while(*cp >= '0' && *cp <= '9') {
+ result = 10*result + *cp-'0';
+ cp++;
+ }
+ return(result);
+}
+
diff --git a/src/libtrace/bcopy.c b/src/libtrace/bcopy.c
new file mode 100644
index 0000000..1fb8f1c
--- /dev/null
+++ b/src/libtrace/bcopy.c
@@ -0,0 +1,10 @@
+static char * bcopy(const char * src, char * dest, int count)
+{
+ char *tmp = dest;
+
+ while (count--)
+ *tmp++ = *src++;
+
+ return dest;
+}
+
diff --git a/src/libtrace/getenv.c b/src/libtrace/getenv.c
new file mode 100644
index 0000000..2ed15d6
--- /dev/null
+++ b/src/libtrace/getenv.c
@@ -0,0 +1,15 @@
+#include <sys/types.h>
+
+extern char **__environ;
+
+static char * getenv(const char *name)
+{
+ register const size_t len = strlen(name);
+ register char **ep;
+
+ for (ep = __environ; *ep != NULL; ++ep)
+ if (!strncmp(*ep, name, len) && (*ep)[len] == '=')
+ return(&(*ep)[len + 1]);
+
+ return(NULL);
+}
diff --git a/src/libtrace/init_libtrace.c b/src/libtrace/init_libtrace.c
index fb53721..9874f19 100644
--- a/src/libtrace/init_libtrace.c
+++ b/src/libtrace/init_libtrace.c
@@ -1,68 +1,172 @@
+#include <fcntl.h>
+#include <sys/types.h>
#include <linux/elf.h>
#include <hck/syscall.h>
+#include <sys/mman.h>
-static int errno;
+static int fd = 2;
-void init_libtrace(void)
+static char ax_jmp[] = {
+ 0xb8, 1, 2, 3, 4, /* movl $0x04030201, %eax */
+ 0xa3, 5, 6, 7, 8, /* movl %eax, 0x08070605 */
+ 0xff, 0x25, 1, 2, 3, 4, /* jmp *0x04030201 */
+ 0, 0, 0, 0, /* real_func */
+ 0, 0, 0, 0, /* name */
+ 0, 0, 0, 0 /* got */
+};
+
+struct ax_jmp_t {
+ char tmp1;
+ void * src __attribute__ ((packed));
+ char tmp2;
+ void * dst __attribute__ ((packed));
+ char tmp3,tmp4;
+ void * new_func __attribute__ ((packed));
+ void * real_func __attribute__ ((packed));
+ char * name __attribute__ ((packed));
+ u_long * got __attribute__ ((packed));
+};
+
+static struct ax_jmp_t * pointer;
+
+static void new_func(void);
+static void * new_func_ptr = NULL;
+
+static void init_libtrace(void)
{
- unsigned long tmp[0];
- unsigned long *stack = tmp;
- int phnum=0, phent=0;
- struct elf_phdr * phdr = NULL;
- int i;
- struct dynamic * dpnt;
+ int i,j;
+ void * k;
struct elf32_sym * symtab = NULL;
- void * strtab = NULL;
-
-/*
- * When loading the interpreter, in linux/fs/binfmt_elf.h, the stack
- * is filled with an auxiliary table defined in include/linux/elf.h;
- * it has some important things such as pointers to the program
- * headers. We are trying to find that table.
- *
- */
- for(; (stack < (unsigned long *)(0xc0000000-256)); stack++) {
- if ((stack[0]==3) && (stack[2]==4) && (stack[4]==5) && (stack[6]==6)) {
- phdr = (struct elf_phdr *)stack[1];
- phent = stack[3];
- phnum = stack[5];
- break;
+ size_t symtab_len = 0;
+ char * strtab = NULL;
+ char * tmp;
+ int nsymbols = 0;
+ long buffer[6];
+ struct ax_jmp_t * table;
+
+ if (new_func_ptr) {
+ return;
+ }
+ new_func_ptr = new_func;
+
+ tmp = getenv("LTRACE_FILENAME");
+ if (tmp) {
+ fd = _sys_open(tmp, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (fd<0) {
+ _sys_write(2, "Can't open LTRACE_FILENAME\n", 27);
+ return;
+ }
+ fd = _sys_dup2(fd, 234);
+ if (fd<0) {
+ _sys_write(2, "Not enough fd's?\n", 17);
+ return;
}
}
- if (!phdr) {
- _sys_write(2,"No auxiliary table in stack?\n",29);
+
+ tmp = getenv("LTRACE_SYMTAB");
+ if (!tmp) {
+ _sys_write(fd, "No LTRACE_SYMTAB...\n", 20);
return;
}
+ symtab = (struct elf32_sym *)atoi(tmp);
- for(i=0; i<phnum; i++) {
- if (phdr->p_type == PT_DYNAMIC) {
- break;
- }
- phdr = (struct elf_phdr *)((void*)phdr + phent);
+ tmp = getenv("LTRACE_SYMTAB_LEN");
+ if (!tmp) {
+ _sys_write(fd, "No LTRACE_SYMTAB_LEN...\n", 24);
+ return;
}
- if (!phdr || phdr->p_type != PT_DYNAMIC) {
- _sys_write(2,"No .dynamic in file?\n",21);
+ symtab_len = atoi(tmp);
+
+ tmp = getenv("LTRACE_STRTAB");
+ if (!tmp) {
+ _sys_write(fd, "No LTRACE_STRTAB...\n", 20);
return;
}
- dpnt = (struct dynamic *)phdr->p_vaddr;
+ strtab = (char *)atoi(tmp);
- while(dpnt->d_tag) {
- if (dpnt->d_tag == DT_SYMTAB) {
- symtab = (struct elf32_sym *) dpnt->d_un.d_ptr;
- }
- if (dpnt->d_tag == DT_STRTAB) {
- strtab = (void *) dpnt->d_un.d_ptr;
+ for(i=0; i<symtab_len/sizeof(struct elf32_sym); i++) {
+ if (!((symtab+i)->st_shndx) && (symtab+i)->st_value) {
+ nsymbols++;
+#if 0
+ _sys_write(fd, "New symbol: ", 12);
+ _sys_write(fd,strtab+(symtab+i)->st_name,strlen(strtab+(symtab+i)->st_name));
+ _sys_write(fd, "\n", 1);
+#endif
}
- dpnt++;
}
- if (!symtab) {
- _sys_write(2, "No .symtab?\n",12);
+
+ buffer[0] = 0;
+ buffer[1] = nsymbols * sizeof(struct ax_jmp_t);
+ buffer[2] = PROT_READ | PROT_WRITE | PROT_EXEC;
+ buffer[3] = MAP_PRIVATE | MAP_ANON;
+ buffer[4] = 0;
+ buffer[5] = 0;
+ table = (struct ax_jmp_t *)_sys_mmap(buffer);
+ if (!table) {
+ _sys_write(fd,"Cannot mmap?\n",13);
return;
}
- if (!strtab) {
- _sys_write(2, "No .strtab?\n",12);
- return;
+
+ j=0;
+ for(i=0; i<symtab_len/sizeof(struct elf32_sym); i++) {
+ if (!((symtab+i)->st_shndx) && (symtab+i)->st_value) {
+ bcopy(ax_jmp, (char *)&table[j], sizeof(struct ax_jmp_t));
+ table[j].src = (char *)&table[j];
+ table[j].dst = &pointer;
+ table[j].new_func = &new_func_ptr;
+ table[j].name = strtab+(symtab+i)->st_name;
+ table[j].got = (u_long *)*(long *)(((int)((symtab+i)->st_value))+2);
+ table[j].real_func = (void *)*(table[j].got);
+ k = &table[j];
+ bcopy((char*)&k, (char *)table[j].got, 4);
+ j++;
+ }
}
- _sys_write(2,"Hola\n",5);
+ _sys_write(fd,"ltrace starting...\n",19);
+}
+
+static u_long where_to_return;
+static u_long returned_value;
+static u_long where_to_jump;
+
+static int reentrant=0;
+
+static void print_results(u_long arg);
+
+static void new_func(void)
+{
+ if (reentrant) {
+#if 0
+_sys_write(fd,"reentrant\n",10);
+#endif
+ __asm__ __volatile__(
+ "movl %%ebp, %%esp\n\t"
+ "popl %%ebp\n\t"
+ "jmp *%%eax\n"
+ : : "a" (pointer->real_func)
+ );
+ }
+ reentrant=1;
+ where_to_jump = (u_long)pointer->real_func;
+
+ /* This is only to avoid a GCC warning; shouldn't be here:
+ */
+ where_to_return = returned_value = (u_long)print_results;
+
+ __asm__ __volatile__(
+ "movl %ebp, %esp\n\t"
+ "popl %ebp\n\t"
+ "popl %eax\n\t"
+ "movl %eax, where_to_return\n\t"
+ "movl where_to_jump, %eax\n\t"
+ "call *%eax\n\t"
+ "movl %eax, returned_value\n\t"
+ "call print_results\n\t"
+ "movl where_to_return, %eax\n\t"
+ "pushl %eax\n\t"
+ "movl returned_value, %eax\n\t"
+ "movl $0, reentrant\n\t"
+ "ret\n"
+ );
}
diff --git a/src/libtrace/libtrace.c b/src/libtrace/libtrace.c
new file mode 100644
index 0000000..8ddc973
--- /dev/null
+++ b/src/libtrace/libtrace.c
@@ -0,0 +1,33 @@
+/*
+ * Terrible hacks... I don't want *anything* to be exported, so
+ * everything has to be in the same file.
+ */
+
+#include <sys/types.h>
+#include <stdarg.h>
+
+static void init_libtrace(void);
+static size_t strlen(const char *);
+static int strncmp(const char *, const char *, size_t);
+static char * getenv(const char *);
+static unsigned long atoi(const char *);
+static char * bcopy(const char *, char *, int);
+static int sprintf(char * buf, const char *fmt, ...);
+static int strcmp(const char * cs,const char * ct);
+static size_t strnlen(const char * s, size_t count);
+static int vsprintf(char *buf, const char *fmt, va_list args);
+static char * strcat(char * dest, const char * src);
+
+#include "__setfpucw.c"
+#include "init_libtrace.c"
+#include "strlen.c"
+#include "strncmp.c"
+#include "getenv.c"
+#include "atoi.c"
+#include "bcopy.c"
+#include "print_results.c"
+#include "sprintf.c"
+#include "vsprintf.c"
+#include "strcmp.c"
+#include "strnlen.c"
+#include "strcat.c"
diff --git a/src/libtrace/print_results.c b/src/libtrace/print_results.c
new file mode 100644
index 0000000..418705d
--- /dev/null
+++ b/src/libtrace/print_results.c
@@ -0,0 +1,327 @@
+static u_long * function_args;
+
+struct debug_functions {
+ const char * function_name;
+ int return_type;
+ int no_params;
+ int params_type[10];
+};
+
+/*
+ * Lista de types:
+ */
+
+#define _TYPE_VOID 0
+#define _TYPE_INT 1
+#define _TYPE_UINT 2
+#define _TYPE_OCTAL 3
+#define _TYPE_CHAR 4
+#define _TYPE_STRING 5
+#define _TYPE_ADDR 6
+#define _TYPE_FILE 7
+
+#define MAX_STRING 30
+
+static struct debug_functions * function_actual;
+static int current_pid;
+
+static struct debug_functions functions_info[] = {
+ {"__setjmp", _TYPE_INT, 1, {_TYPE_ADDR}},
+ {"__overflow", _TYPE_CHAR, 2, {_TYPE_FILE, _TYPE_CHAR, 0, 0, 0}},
+ {"__random", _TYPE_INT, 0, {0, 0, 0, 0, 0}},
+ {"__setfpucw", _TYPE_VOID, 1, {_TYPE_UINT, 0, 0, 0, 0}},
+ {"__srandom", _TYPE_VOID, 1, {_TYPE_UINT, 0, 0, 0, 0}},
+ {"__uflow", _TYPE_INT, 1, {_TYPE_FILE, 0, 0, 0, 0}},
+ {"_fxstat", _TYPE_INT, 3, {_TYPE_INT, _TYPE_INT, _TYPE_ADDR, 0, 0}},
+ {"_lxstat", _TYPE_INT, 3, {_TYPE_INT, _TYPE_STRING, _TYPE_ADDR, 0, 0}},
+ {"_xmknod", _TYPE_INT, 4, {_TYPE_INT, _TYPE_STRING, _TYPE_OCTAL, _TYPE_ADDR, 0}},
+ {"_xstat", _TYPE_INT, 3, {_TYPE_INT, _TYPE_STRING, _TYPE_ADDR, 0, 0}},
+ {"access", _TYPE_INT, 2, {_TYPE_STRING, _TYPE_INT, 0, 0, 0}},
+ {"alarm", _TYPE_INT, 1, {_TYPE_INT, 0, 0, 0, 0}},
+ {"atexit", _TYPE_INT, 1, {_TYPE_ADDR, 0, 0, 0, 0}},
+ {"atoi", _TYPE_INT, 1, {_TYPE_STRING, 0, 0, 0, 0}},
+ {"basename", _TYPE_STRING,1, {_TYPE_STRING, 0, 0, 0, 0}},
+ {"bcmp", _TYPE_INT, 3, {_TYPE_ADDR, _TYPE_ADDR, _TYPE_UINT, 0, 0}},
+ {"bind", _TYPE_INT, 3, {_TYPE_INT, _TYPE_ADDR, _TYPE_INT, 0, 0}},
+ {"bindresvport",_TYPE_INT, 2, {_TYPE_INT, _TYPE_ADDR, 0, 0, 0}},
+ {"brk", _TYPE_INT, 1, {_TYPE_ADDR, 0, 0, 0, 0}},
+ {"bzero", _TYPE_VOID, 2, {_TYPE_ADDR, _TYPE_UINT, 0, 0, 0}},
+ {"calloc", _TYPE_ADDR, 2, {_TYPE_UINT, _TYPE_UINT, 0, 0, 0}},
+ {"cfgetospeed", _TYPE_UINT, 1, {_TYPE_ADDR, 0, 0, 0, 0}},
+ {"dup", _TYPE_INT, 1, {_TYPE_UINT, 0, 0, 0, 0}},
+ {"dup2", _TYPE_INT, 2, {_TYPE_UINT, _TYPE_UINT, 0, 0, 0}},
+ {"chdir", _TYPE_INT, 1, {_TYPE_STRING, 0, 0, 0, 0}},
+ {"chmod", _TYPE_INT, 2, {_TYPE_STRING, _TYPE_OCTAL, 0, 0, 0}},
+ {"chown", _TYPE_INT, 3, {_TYPE_STRING, _TYPE_UINT, _TYPE_UINT, 0, 0}},
+ {"close", _TYPE_INT, 1, {_TYPE_INT, 0, 0, 0, 0}},
+ {"closedir", _TYPE_INT, 1, {_TYPE_ADDR, 0, 0, 0, 0}},
+ {"ctime", _TYPE_STRING,1, {_TYPE_ADDR, 0, 0, 0, 0}},
+ {"endmntent", _TYPE_INT, 1, {_TYPE_ADDR, 0, 0, 0, 0}},
+ {"fchmod", _TYPE_INT, 2, {_TYPE_INT, _TYPE_OCTAL, 0, 0, 0}},
+ {"fchown", _TYPE_INT, 3, {_TYPE_INT, _TYPE_UINT, _TYPE_UINT, 0, 0}},
+ {"fclose", _TYPE_INT, 1, {_TYPE_FILE, 0, 0, 0, 0}},
+ {"fdopen", _TYPE_FILE, 2, {_TYPE_INT, _TYPE_STRING, 0, 0, 0}},
+ {"feof", _TYPE_INT, 1, {_TYPE_FILE, 0, 0, 0, 0}},
+ {"ferror", _TYPE_INT, 1, {_TYPE_FILE, 0, 0, 0, 0}},
+ {"fflush", _TYPE_INT, 1, {_TYPE_FILE, 0, 0, 0, 0}},
+ {"fgetc", _TYPE_CHAR, 1, {_TYPE_FILE, 0, 0, 0, 0}},
+ {"fgets", _TYPE_ADDR, 3, {_TYPE_ADDR, _TYPE_UINT, _TYPE_ADDR, 0, 0}},
+ {"fileno", _TYPE_INT, 1, {_TYPE_ADDR, 0, 0, 0, 0}},
+ {"fopen", _TYPE_ADDR, 2, {_TYPE_STRING, _TYPE_STRING, 0, 0, 0}},
+ {"fork", _TYPE_INT, 0, {0, 0, 0, 0, 0}},
+ {"fprintf", _TYPE_INT, 2, {_TYPE_FILE, _TYPE_STRING, 0, 0, 0}},
+ {"fputc", _TYPE_INT, 2, {_TYPE_CHAR, _TYPE_FILE, 0, 0, 0}},
+ {"fputs", _TYPE_INT, 2, {_TYPE_STRING, _TYPE_FILE, 0, 0, 0}},
+ {"fread", _TYPE_UINT, 4, {_TYPE_FILE, _TYPE_UINT, _TYPE_UINT, _TYPE_ADDR, 0}},
+ {"free", _TYPE_VOID, 1, {_TYPE_ADDR, 0, 0, 0, 0}},
+ {"freopen", _TYPE_ADDR, 3, {_TYPE_STRING, _TYPE_STRING, _TYPE_ADDR, 0, 0}},
+ {"fseek", _TYPE_INT, 3, {_TYPE_FILE, _TYPE_UINT, _TYPE_INT, 0, 0}},
+ {"ftell", _TYPE_UINT, 1, {_TYPE_FILE, 0, 0, 0, 0}},
+ {"fwrite", _TYPE_UINT, 4, {_TYPE_FILE, _TYPE_UINT, _TYPE_UINT, _TYPE_ADDR, 0}},
+ {"getdtablesize",_TYPE_INT, 0, {0, 0, 0, 0, 0}},
+ {"getenv", _TYPE_STRING,1, {_TYPE_STRING, 0, 0, 0, 0}},
+ {"getgid", _TYPE_INT, 0, {0, 0, 0, 0, 0}},
+ {"getgrgid", _TYPE_ADDR, 1, {_TYPE_UINT, 0, 0, 0, 0}},
+ {"getgrnam", _TYPE_ADDR, 1, {_TYPE_STRING, 0, 0, 0, 0}},
+ {"gethostbyname",_TYPE_ADDR, 1, {_TYPE_STRING, 0, 0, 0, 0}},
+ {"gethostname", _TYPE_INT, 2, {_TYPE_STRING, _TYPE_UINT, 0, 0, 0}},
+ {"getmntent", _TYPE_ADDR, 1, {_TYPE_ADDR, 0, 0, 0, 0}},
+ {"getopt", _TYPE_INT, 3, {_TYPE_INT, _TYPE_ADDR, _TYPE_STRING, 0, 0}},
+ {"getopt_long", _TYPE_INT, 5, {_TYPE_INT, _TYPE_ADDR,_TYPE_STRING,_TYPE_ADDR,_TYPE_ADDR}},
+ {"getpagesize", _TYPE_UINT, 0, {0, 0, 0, 0, 0}},
+ {"getpid", _TYPE_UINT, 0, {0, 0, 0, 0, 0}},
+ {"getpwnam", _TYPE_ADDR, 1, {_TYPE_STRING, 0, 0, 0, 0}},
+ {"getpwuid", _TYPE_ADDR, 1, {_TYPE_UINT, 0, 0, 0, 0}},
+ {"getservbyname",_TYPE_ADDR, 2, {_TYPE_STRING, _TYPE_STRING, 0, 0, 0}},
+ {"gettimeofday",_TYPE_INT, 2, {_TYPE_ADDR, _TYPE_ADDR, 0, 0, 0}},
+ {"htonl", _TYPE_UINT, 1, {_TYPE_UINT, 0, 0, 0, 0}},
+ {"inet_addr", _TYPE_ADDR, 1, {_TYPE_STRING, 0, 0, 0, 0}},
+ {"inet_ntoa", _TYPE_STRING,1, {_TYPE_ADDR, 0, 0, 0, 0}},
+ {"isalnum", _TYPE_INT, 1, {_TYPE_CHAR, 0, 0, 0, 0}},
+ {"isalpha", _TYPE_INT, 1, {_TYPE_CHAR, 0, 0, 0, 0}},
+ {"isascii", _TYPE_INT, 1, {_TYPE_CHAR, 0, 0, 0, 0}},
+ {"isatty", _TYPE_INT, 1, {_TYPE_INT, 0, 0, 0, 0}},
+ {"iscntrl", _TYPE_INT, 1, {_TYPE_CHAR, 0, 0, 0, 0}},
+ {"isdigit", _TYPE_INT, 1, {_TYPE_CHAR, 0, 0, 0, 0}},
+ {"isgraph", _TYPE_INT, 1, {_TYPE_CHAR, 0, 0, 0, 0}},
+ {"islower", _TYPE_INT, 1, {_TYPE_CHAR, 0, 0, 0, 0}},
+ {"isprint", _TYPE_INT, 1, {_TYPE_CHAR, 0, 0, 0, 0}},
+ {"ispunct", _TYPE_INT, 1, {_TYPE_CHAR, 0, 0, 0, 0}},
+ {"isspace", _TYPE_INT, 1, {_TYPE_CHAR, 0, 0, 0, 0}},
+ {"isupper", _TYPE_INT, 1, {_TYPE_CHAR, 0, 0, 0, 0}},
+ {"isxdigit", _TYPE_INT, 1, {_TYPE_CHAR, 0, 0, 0, 0}},
+ {"malloc", _TYPE_ADDR, 1, {_TYPE_UINT, 0, 0, 0, 0}},
+ {"memmove", _TYPE_ADDR, 3, {_TYPE_ADDR, _TYPE_ADDR, _TYPE_INT, 0, 0}},
+ {"mmap", _TYPE_ADDR, 5, {_TYPE_UINT, _TYPE_UINT, _TYPE_UINT, _TYPE_INT,_TYPE_UINT}},
+ {"ntohl", _TYPE_UINT, 1, {_TYPE_UINT, 0, 0, 0, 0}},
+ {"ntohs", _TYPE_UINT, 1, {_TYPE_UINT, 0, 0, 0, 0}},
+ {"open", _TYPE_INT, 3, {_TYPE_STRING, _TYPE_INT, _TYPE_OCTAL, 0, 0}},
+ {"opendir", _TYPE_ADDR, 1, {_TYPE_STRING, 0, 0, 0, 0}},
+ {"perror", _TYPE_VOID, 1, {_TYPE_STRING, 0, 0, 0, 0}},
+ {"printf", _TYPE_INT, 1, {_TYPE_STRING, 0, 0, 0, 0}},
+ {"putenv", _TYPE_INT, 1, {_TYPE_STRING, 0, 0, 0, 0}},
+ {"puts", _TYPE_INT, 1, {_TYPE_STRING, 0, 0, 0, 0}},
+ {"qsort", _TYPE_VOID, 4, {_TYPE_ADDR, _TYPE_UINT, _TYPE_UINT, _TYPE_ADDR, 0}},
+ {"read", _TYPE_INT, 3, {_TYPE_INT, _TYPE_ADDR, _TYPE_UINT, 0, 0}},
+ {"readdir", _TYPE_ADDR, 1, {_TYPE_ADDR, 0, 0, 0, 0}},
+ {"readline", _TYPE_STRING,0, {0, 0, 0, 0, 0}},
+ {"readlink", _TYPE_INT, 3, {_TYPE_STRING, _TYPE_ADDR, _TYPE_UINT, 0, 0}},
+ {"realloc", _TYPE_ADDR, 2, {_TYPE_ADDR, _TYPE_UINT, 0, 0, 0}},
+ {"rewind", _TYPE_VOID, 1, {_TYPE_FILE, 0, 0, 0, 0}},
+ {"rewinddir", _TYPE_VOID, 1, {_TYPE_FILE, 0, 0, 0, 0}},
+ {"rindex", _TYPE_STRING,2, {_TYPE_STRING, _TYPE_INT, 0, 0, 0}},
+ {"sbrk", _TYPE_ADDR, 1, {_TYPE_UINT, 0, 0, 0, 0}},
+ {"select", _TYPE_INT, 5, {_TYPE_INT, _TYPE_ADDR, _TYPE_ADDR, _TYPE_ADDR,_TYPE_ADDR}},
+ {"setbuf", _TYPE_VOID, 2, {_TYPE_ADDR, _TYPE_ADDR, 0, 0, 0}},
+ {"setlinebuf", _TYPE_VOID, 1, {_TYPE_FILE, 0, 0, 0, 0}},
+ {"setmntent", _TYPE_ADDR, 2, {_TYPE_STRING, _TYPE_STRING, 0, 0, 0}},
+ {"setuid", _TYPE_INT, 1, {_TYPE_INT, 0, 0, 0, 0}},
+ {"setvbuf", _TYPE_INT, 4, {_TYPE_ADDR, _TYPE_ADDR, _TYPE_INT, _TYPE_UINT, 0}},
+ {"sigaction", _TYPE_INT, 3, {_TYPE_INT, _TYPE_ADDR, _TYPE_ADDR, 0, 0}},
+ {"sleep", _TYPE_UINT, 1, {_TYPE_UINT, 0, 0, 0, 0}},
+ {"sprintf", _TYPE_INT, 2, {_TYPE_STRING, _TYPE_STRING, 0, 0, 0}},
+ {"strcasecmp", _TYPE_INT, 2, {_TYPE_STRING, _TYPE_STRING, 0, 0, 0}},
+ {"stpcpy", _TYPE_STRING,2, {_TYPE_STRING, _TYPE_STRING, 0, 0, 0}},
+ {"strcmp", _TYPE_INT, 2, {_TYPE_STRING, _TYPE_STRING, 0, 0, 0}},
+ {"strcspn", _TYPE_INT, 2, {_TYPE_STRING, _TYPE_STRING, 0, 0, 0}},
+ {"strdup", _TYPE_STRING,1, {_TYPE_STRING, 0, 0, 0, 0}},
+ {"strerror", _TYPE_STRING,1, {_TYPE_INT, 0, 0, 0, 0}},
+ {"strpbrk", _TYPE_STRING,2, {_TYPE_STRING, _TYPE_STRING, 0, 0, 0}},
+ {"strrchr", _TYPE_STRING,2, {_TYPE_STRING, _TYPE_CHAR, 0, 0, 0}},
+ {"strspn", _TYPE_UINT, 2, {_TYPE_STRING, _TYPE_STRING, 0, 0, 0}},
+ {"strtok", _TYPE_STRING,2, {_TYPE_STRING, _TYPE_STRING, 0, 0, 0}},
+ {"strtol", _TYPE_INT, 3, {_TYPE_STRING, _TYPE_ADDR, _TYPE_UINT, 0, 0}},
+ {"strtoul", _TYPE_INT, 3, {_TYPE_STRING, _TYPE_ADDR, _TYPE_UINT, 0, 0}},
+ {"tcgetattr", _TYPE_INT, 2, {_TYPE_INT, _TYPE_ADDR, 0, 0, 0}},
+ {"tcsetattr", _TYPE_INT, 2, {_TYPE_INT, _TYPE_ADDR, 0, 0, 0}},
+ {"toascii", _TYPE_CHAR, 1, {_TYPE_CHAR, 0, 0, 0, 0}},
+ {"tolower", _TYPE_CHAR, 1, {_TYPE_CHAR, 0, 0, 0, 0}},
+ {"toupper", _TYPE_CHAR, 1, {_TYPE_CHAR, 0, 0, 0, 0}},
+ {"unlink", _TYPE_INT, 1, {_TYPE_STRING, 0, 0, 0, 0}},
+ {"uname", _TYPE_INT, 1, {_TYPE_ADDR, 0, 0, 0, 0}},
+ {"ungetc", _TYPE_CHAR, 2, {_TYPE_INT, _TYPE_ADDR, 0, 0, 0}},
+ {"utime", _TYPE_INT, 2, {_TYPE_STRING, _TYPE_ADDR, 0, 0, 0}},
+ {"vfprintf", _TYPE_INT, 2, {_TYPE_ADDR, _TYPE_STRING, 0, 0, 0}},
+ {"wait", _TYPE_UINT, 1, {_TYPE_ADDR, 0, 0, 0, 0}},
+ {"wait3", _TYPE_UINT, 3, {_TYPE_ADDR, _TYPE_INT, _TYPE_ADDR, 0, 0}},
+ {"waitpid", _TYPE_UINT, 3, {_TYPE_UINT, _TYPE_ADDR, _TYPE_ADDR, 0, 0}},
+ {"write", _TYPE_INT, 3, {_TYPE_INT, _TYPE_ADDR, _TYPE_UINT, 0, 0}},
+ {NULL, 0, 0, {0, 0, 0, 0, 0}}
+};
+
+static char * print_char(unsigned long value)
+{
+ static char result[5];
+
+ result[0]='\\';
+ switch(value) {
+ case '\r': result[1]='r'; result[2]='\0'; break;
+ case '\n': result[1]='n'; result[2]='\0'; break;
+ case '\t': result[1]='t'; result[2]='\0'; break;
+ case '\\': result[1]='\\'; result[2]='\0'; break;
+ default:
+ if ((value<32) || ((value>126) && (value<256))) {
+ sprintf(result+1, "%lo", value);
+ } else {
+ result[0]=value; result[1]='\0'; break;
+ }
+ }
+ return result;
+}
+
+static char * print_param(int type, unsigned long value)
+{
+ static char result[1024];
+
+_sys_write(fd, "Toi en a\n", 9);
+ switch(type) {
+ case _TYPE_INT:
+_sys_write(fd, "Toi en b\n", 9);
+ sprintf(result, "%d", (int)value);
+ break;
+ case _TYPE_UINT:
+_sys_write(fd, "Toi en c\n", 9);
+ sprintf(result, "%u", (unsigned int)value);
+ break;
+ case _TYPE_ADDR:
+_sys_write(fd, "Toi en d\n", 9);
+ if (!value) {
+ sprintf(result, "NULL");
+ } else {
+ sprintf(result, "0x%08x", (unsigned int)value);
+ }
+ break;
+ case _TYPE_FILE:
+_sys_write(fd, "Toi en e\n", 9);
+#if 0
+ if (value==(unsigned long)stdin) {
+ sprintf(result, "stdin");
+ } else if (value==(unsigned long)stdout) {
+ sprintf(result, "stdout");
+ } else if (value==(unsigned long)stderr) {
+ sprintf(result, "stderr");
+ } else {
+#endif
+ return print_param(_TYPE_ADDR, value);
+#if 0
+ }
+#endif
+ break;
+ case _TYPE_OCTAL:
+_sys_write(fd, "Toi en f\n", 9);
+ sprintf(result, "0%o", (unsigned int)value);
+ break;
+ case _TYPE_CHAR:
+_sys_write(fd, "Toi en g\n", 9);
+ if (value==-1) {
+ sprintf(result, "EOF");
+ } else {
+ sprintf(result, "'%s'", print_char(value));
+ }
+ break;
+ case _TYPE_STRING:
+_sys_write(fd, "Toi en h\n", 9);
+ if (value==0) {
+_sys_write(fd, "Toi en h1\n", 10);
+ sprintf(result, "<NULL>");
+ } else {
+ int i;
+_sys_write(fd, "Toi en h2\n", 10);
+ sprintf(result, "\"");
+ for(i=0; *((char*)value+i) && i<MAX_STRING; i++) {
+ strcat(result, print_char(*((char*)value+i)));
+ }
+ strcat(result, "\"");
+ if (i==MAX_STRING) {
+ strcat(result, "...");
+ }
+ }
+ break;
+ case _TYPE_VOID:
+_sys_write(fd, "Toi en i\n", 9);
+ sprintf(result, "<void>");
+ break;
+ default:
+ sprintf(result, "???");
+ }
+ return result;
+}
+
+static void print_results(u_long arg)
+{
+ char message[1024];
+ int i;
+
+ if (pointer != (void *)*(pointer->got)) {
+ pointer->real_func = (void *)*(pointer->got);
+ bcopy((char *)&pointer, (char *)pointer->got, 4);
+ }
+
+_sys_write(fd, pointer->name, strlen(pointer->name));
+_sys_write(fd, ":\n", 2);
+
+ function_actual = functions_info;
+ while(function_actual->function_name) {
+ if (!strcmp(pointer->name, function_actual->function_name)) {
+ break;
+ }
+ function_actual++;
+ }
+ if (!function_actual->function_name) {
+ sprintf(message, "** WARN **: debug(%s) NOT FOUND\n", pointer->name);
+ _sys_write(fd, message, strlen(message));
+ }
+
+ function_args = &arg;
+
+sprintf(message,"return = 0x%08x\n"
+ "args[0] = 0x%08x\n"
+ "args[1] = 0x%08x\n"
+ "args[2] = 0x%08x\n"
+ "args[3] = 0x%08x\n"
+ "args[4] = 0x%08x\n"
+ "args[5] = 0x%08x\n", where_to_return,
+ function_args[0], function_args[1], function_args[2],
+ function_args[3], function_args[4], function_args[5]);
+_sys_write(fd, message, strlen(message));
+
+#if 0
+ message[0] = '\0';
+_sys_write(fd, "Toi en 3\n", 9);
+ sprintf(message, "%s%s(", message, pointer->name);
+_sys_write(fd, "Toi en 4\n", 9);
+ if (function_actual->no_params > 0) {
+_sys_write(fd, "Toi en 5\n", 9);
+ sprintf(message, "%s%s", message,
+ print_param(function_actual->params_type[0], function_args[0]));
+_sys_write(fd, "Toi en 6\n", 9);
+ }
+ for(i=1; i<function_actual->no_params; i++) {
+ sprintf(message, "%s,%s", message,
+ print_param(function_actual->params_type[i], function_args[i]));
+ }
+ sprintf(message, "%s) = %s\n", message,
+ print_param(function_actual->return_type, returned_value));
+ _sys_write(fd, message, strlen(message));
+#endif
+}
diff --git a/src/libtrace/sprintf.c b/src/libtrace/sprintf.c
new file mode 100644
index 0000000..d00e087
--- /dev/null
+++ b/src/libtrace/sprintf.c
@@ -0,0 +1,25 @@
+/*
+ * linux/lib/vsprintf.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
+/*
+ * Wirzenius wrote this portably, Torvalds fucked it up :-)
+ */
+
+#include <stdarg.h>
+
+static int sprintf(char * buf, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsprintf(buf,fmt,args);
+ va_end(args);
+
+ return i;
+}
+
diff --git a/src/libtrace/strcat.c b/src/libtrace/strcat.c
new file mode 100644
index 0000000..cb01564
--- /dev/null
+++ b/src/libtrace/strcat.c
@@ -0,0 +1,12 @@
+static char * strcat(char * dest, const char * src)
+{
+ char *tmp = dest;
+
+ while (*dest)
+ dest++;
+ while ((*dest++ = *src++) != '\0')
+ ;
+
+ return tmp;
+}
+
diff --git a/src/libtrace/strcmp.c b/src/libtrace/strcmp.c
new file mode 100644
index 0000000..8392ec3
--- /dev/null
+++ b/src/libtrace/strcmp.c
@@ -0,0 +1,12 @@
+int strcmp(const char * cs,const char * ct)
+{
+ register signed char __res;
+
+ while (1) {
+ if ((__res = *cs - *ct++) != 0 || !*cs++)
+ break;
+ }
+
+ return(__res);
+}
+
diff --git a/src/libtrace/strlen.c b/src/libtrace/strlen.c
new file mode 100644
index 0000000..f3f44e0
--- /dev/null
+++ b/src/libtrace/strlen.c
@@ -0,0 +1,10 @@
+#include <sys/types.h>
+
+static size_t strlen(const char * s)
+{
+ const char *sc;
+
+ for (sc = s; *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
diff --git a/src/libtrace/strncmp.c b/src/libtrace/strncmp.c
new file mode 100644
index 0000000..96512e6
--- /dev/null
+++ b/src/libtrace/strncmp.c
@@ -0,0 +1,14 @@
+#include <sys/types.h>
+
+int strncmp(const char * cs,const char * ct,size_t count)
+{
+ register signed char __res = 0;
+
+ while (count) {
+ if ((__res = *cs - *ct++) != 0 || !*cs++)
+ break;
+ count--;
+ }
+
+ return __res;
+}
diff --git a/src/libtrace/strnlen.c b/src/libtrace/strnlen.c
new file mode 100644
index 0000000..715dbce
--- /dev/null
+++ b/src/libtrace/strnlen.c
@@ -0,0 +1,11 @@
+#include <sys/types.h>
+
+size_t strnlen(const char * s, size_t count)
+{
+ const char *sc;
+
+ for (sc = s; count-- && *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
+
diff --git a/src/libtrace/vsprintf.c b/src/libtrace/vsprintf.c
new file mode 100644
index 0000000..e5603c9
--- /dev/null
+++ b/src/libtrace/vsprintf.c
@@ -0,0 +1,267 @@
+/*
+ * linux/lib/vsprintf.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
+/*
+ * Wirzenius wrote this portably, Torvalds fucked it up :-)
+ */
+
+#include <stdarg.h>
+#include <hck/ctype.h>
+
+/* we use this so that we can do without the ctype library */
+#define is_digit(c) ((c) >= '0' && (c) <= '9')
+
+static int skip_atoi(const char **s)
+{
+ int i=0;
+
+ while (is_digit(**s))
+ i = i*10 + *((*s)++) - '0';
+ return i;
+}
+
+#define ZEROPAD 1 /* pad with zero */
+#define SIGN 2 /* unsigned/signed long */
+#define PLUS 4 /* show plus */
+#define SPACE 8 /* space if plus */
+#define LEFT 16 /* left justified */
+#define SPECIAL 32 /* 0x */
+#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
+
+#define do_div(n,base) ({ \
+int __res; \
+__res = ((unsigned long) n) % (unsigned) base; \
+n = ((unsigned long) n) / (unsigned) base; \
+__res; })
+
+static char * number(char * str, long num, int base, int size, int precision
+ ,int type)
+{
+ char c,sign,tmp[66];
+ const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
+ int i;
+
+ if (type & LARGE)
+ digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ if (type & LEFT)
+ type &= ~ZEROPAD;
+ if (base < 2 || base > 36)
+ return 0;
+ c = (type & ZEROPAD) ? '0' : ' ';
+ sign = 0;
+ if (type & SIGN) {
+ if (num < 0) {
+ sign = '-';
+ num = -num;
+ size--;
+ } else if (type & PLUS) {
+ sign = '+';
+ size--;
+ } else if (type & SPACE) {
+ sign = ' ';
+ size--;
+ }
+ }
+ if (type & SPECIAL) {
+ if (base == 16)
+ size -= 2;
+ else if (base == 8)
+ size--;
+ }
+ i = 0;
+ if (num == 0)
+ tmp[i++]='0';
+ else while (num != 0)
+ tmp[i++] = digits[do_div(num,base)];
+ if (i > precision)
+ precision = i;
+ size -= precision;
+ if (!(type&(ZEROPAD+LEFT)))
+ while(size-->0)
+ *str++ = ' ';
+ if (sign)
+ *str++ = sign;
+ if (type & SPECIAL)
+ if (base==8)
+ *str++ = '0';
+ else if (base==16) {
+ *str++ = '0';
+ *str++ = digits[33];
+ }
+ if (!(type & LEFT))
+ while (size-- > 0)
+ *str++ = c;
+ while (i < precision--)
+ *str++ = '0';
+ while (i-- > 0)
+ *str++ = tmp[i];
+ while (size-- > 0)
+ *str++ = ' ';
+ return str;
+}
+
+static int vsprintf(char *buf, const char *fmt, va_list args)
+{
+ int len;
+ unsigned long num;
+ int i, base;
+ char * str;
+ const char *s;
+
+ int flags; /* flags to number() */
+
+ int field_width; /* width of output field */
+ int precision; /* min. # of digits for integers; max
+ number of chars for from string */
+ int qualifier; /* 'h', 'l', or 'L' for integer fields */
+
+ for (str=buf ; *fmt ; ++fmt) {
+ if (*fmt != '%') {
+ *str++ = *fmt;
+ continue;
+ }
+
+ /* process flags */
+ flags = 0;
+ repeat:
+ ++fmt; /* this also skips first '%' */
+ switch (*fmt) {
+ case '-': flags |= LEFT; goto repeat;
+ case '+': flags |= PLUS; goto repeat;
+ case ' ': flags |= SPACE; goto repeat;
+ case '#': flags |= SPECIAL; goto repeat;
+ case '0': flags |= ZEROPAD; goto repeat;
+ }
+
+ /* get field width */
+ field_width = -1;
+ if (is_digit(*fmt))
+ field_width = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ field_width = va_arg(args, int);
+ if (field_width < 0) {
+ field_width = -field_width;
+ flags |= LEFT;
+ }
+ }
+
+ /* get the precision */
+ precision = -1;
+ if (*fmt == '.') {
+ ++fmt;
+ if (is_digit(*fmt))
+ precision = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ precision = va_arg(args, int);
+ }
+ if (precision < 0)
+ precision = 0;
+ }
+
+ /* get the conversion qualifier */
+ qualifier = -1;
+ if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
+ qualifier = *fmt;
+ ++fmt;
+ }
+
+ /* default base */
+ base = 10;
+
+ switch (*fmt) {
+ case 'c':
+ if (!(flags & LEFT))
+ while (--field_width > 0)
+ *str++ = ' ';
+ *str++ = (unsigned char) va_arg(args, int);
+ while (--field_width > 0)
+ *str++ = ' ';
+ continue;
+
+ case 's':
+ s = va_arg(args, char *);
+ if (!s)
+ s = "<NULL>";
+
+ len = strnlen(s, precision);
+
+ if (!(flags & LEFT))
+ while (len < field_width--)
+ *str++ = ' ';
+ for (i = 0; i < len; ++i)
+ *str++ = *s++;
+ while (len < field_width--)
+ *str++ = ' ';
+ continue;
+
+ case 'p':
+ if (field_width == -1) {
+ field_width = 2*sizeof(void *);
+ flags |= ZEROPAD;
+ }
+ str = number(str,
+ (unsigned long) va_arg(args, void *), 16,
+ field_width, precision, flags);
+ continue;
+
+
+ case 'n':
+ if (qualifier == 'l') {
+ long * ip = va_arg(args, long *);
+ *ip = (str - buf);
+ } else {
+ int * ip = va_arg(args, int *);
+ *ip = (str - buf);
+ }
+ continue;
+
+ /* integer number formats - set up the flags and "break" */
+ case 'o':
+ base = 8;
+ break;
+
+ case 'X':
+ flags |= LARGE;
+ case 'x':
+ base = 16;
+ break;
+
+ case 'd':
+ case 'i':
+ flags |= SIGN;
+ case 'u':
+ break;
+
+ default:
+ if (*fmt != '%')
+ *str++ = '%';
+ if (*fmt)
+ *str++ = *fmt;
+ else
+ --fmt;
+ continue;
+ }
+ if (qualifier == 'l')
+ num = va_arg(args, unsigned long);
+ else if (qualifier == 'h')
+ if (flags & SIGN)
+ num = va_arg(args, short);
+ else
+ num = va_arg(args, unsigned short);
+ else if (flags & SIGN)
+ num = va_arg(args, int);
+ else
+ num = va_arg(args, unsigned int);
+ str = number(str, num, base, field_width, precision, flags);
+ }
+ *str = '\0';
+ return str-buf;
+}
diff --git a/src/ltrace/ltrace.c b/src/ltrace/ltrace.c
index d511ba9..7a105d0 100644
--- a/src/ltrace/ltrace.c
+++ b/src/ltrace/ltrace.c
@@ -1,15 +1,127 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <linux/elf.h>
+#include <string.h>
int main(int argc, char **argv)
{
+ int fd;
+ struct stat sbuf;
+ size_t filesize;
+ void * addr;
+ struct elf32_hdr * hdr;
+ Elf32_Shdr * shdr;
+ int i;
+ u_long strtab = 0;
+ u_long symtab = 0;
+ u_long symtab_len = 0;
+ char buf[1024];
+ char * debug_filename = NULL;
+
if (argc<2) {
- fprintf(stderr, "Usage: %s <program> [<arguments>]\n", argv[0]);
+ fprintf(stderr, "Usage: %s [options] <program> [<arguments>]\n", argv[0]);
+ exit(1);
+ }
+
+ while ((argv[1][0] == '-') && argv[1][1] && !argv[1][2]) {
+ switch(argv[1][1]) {
+ case 'o':
+ debug_filename = argv[2];
+ argc--; argv++;
+ break;
+ default:
+ fprintf(stderr, "Unknown option: '%c'\n", argv[1][1]);
+ }
+ argc--; argv++;
+ }
+
+ if (argc<2) {
+ fprintf(stderr, "Usage: %s [options] <program> [<arguments>]\n", argv[0]);
+ exit(1);
+ }
+
+ fd = open(argv[1], O_RDONLY);
+
+ if (fd<0) {
+ fprintf(stderr, "Can't open \"%s\" for reading: %s\n", argv[1], sys_errlist[errno]);
+ exit(1);
+ }
+
+ if (fstat(fd, &sbuf)<0) {
+ fprintf(stderr, "Can't stat \"%s\": %s\n", argv[1], sys_errlist[errno]);
+ exit(1);
+ }
+ filesize = sbuf.st_size;
+ if (filesize < sizeof(struct elf32_hdr)) {
+ fprintf(stderr, "\"%s\" is not an ELF object\n", argv[1]);
+ exit(1);
+ }
+
+ addr = mmap(NULL, filesize, PROT_READ, MAP_SHARED, fd, 0);
+ if (!addr) {
+ fprintf(stderr, "Can't mmap \"%s\": %s\n", argv[1], sys_errlist[errno]);
+ exit(1);
+ }
+
+ if (debug_filename) {
+ setenv("LTRACE_FILENAME", debug_filename, 1);
+ printf("LTRACE_FILENAME=%s\n", debug_filename);
+ }
+
+/*
+ * Tengo que decirle a libtrace:
+ * - Comienzo y tamanno de '.dynsym' LTRACE_SYMTAB_ADDR, LTRACE_SYMTAB_SIZE
+ * - Comienzo de '.dynstr' LTRACE_STRTAB_ADDR
+ *
+ * Todo ello especificado en decimal (por elegir algo)
+ */
+
+ hdr = addr;
+
+ if (strncmp(hdr->e_ident, ELFMAG, SELFMAG)) {
+ fprintf(stderr, "%s is not an ELF object\n", argv[1]);
exit(1);
}
+
+ for(i=0; i<hdr->e_shnum; i++) {
+ shdr = addr + hdr->e_shoff + i*hdr->e_shentsize;
+ if (shdr->sh_type == SHT_DYNSYM) {
+ if (!symtab) {
+ symtab = shdr->sh_addr;
+ symtab_len = shdr->sh_size;
+ }
+ }
+ if (shdr->sh_type == SHT_STRTAB) {
+ if (!strtab) {
+ strtab = shdr->sh_addr;
+ }
+ }
+ }
+ if (!symtab) {
+ fprintf(stderr, "No .dynsym in file. Not dynamically linked?\n");
+ exit(1);
+ }
+ if (!strtab) {
+ fprintf(stderr, "No .dynstr in file. Not dynamically linked?\n");
+ exit(1);
+ }
+
+ sprintf(buf,"%lu", symtab);
+ printf("LTRACE_SYMTAB=%lu\n", symtab);
+ setenv("LTRACE_SYMTAB", buf, 1);
+ sprintf(buf,"%lu", symtab_len);
+ printf("LTRACE_SYMTAB_LEN=%lu\n", symtab_len);
+ setenv("LTRACE_SYMTAB_LEN", buf, 1);
+ sprintf(buf,"%lu", strtab);
+ printf("LTRACE_STRTAB=%lu\n", strtab);
+ setenv("LTRACE_STRTAB", buf, 1);
+
setenv("LD_PRELOAD", TOPDIR "/lib/libtrace.so.1", 1);
execve(argv[1], &argv[1], environ);
- fprintf(stderr, "Couldn't execute %s\n", argv[1]);
+ fprintf(stderr, "Couldn't execute \"%s\": %s\n", argv[1], sys_errlist[errno]);
exit(1);
}