diff options
author | Juan Cespedes <cespedes@thehackers.org> | 1997-03-29 16:47:50 +0100 |
---|---|---|
committer | Juan Cespedes <cespedes@thehackers.org> | 1997-03-29 16:47:50 +0100 |
commit | e2ca89923bc7207583b8688f8f0c11e77c23f8c1 (patch) | |
tree | 67bef6b7f9710e220473ba364e689893987afc6e | |
parent | 1519dd0c0d81a2de425403593ffb0da8b245ef82 (diff) | |
download | ltrace-e2ca89923bc7207583b8688f8f0c11e77c23f8c1.tar.gz |
Version 0.0.1997.03.29
-rw-r--r-- | include/hck/syscall.h | 7 | ||||
-rwxr-xr-x | lib/libtrace.so.1 | bin | 2518 -> 18624 bytes | |||
-rw-r--r-- | src/libtrace/Makefile | 5 | ||||
-rw-r--r-- | src/libtrace/__setfpucw.c | 2 | ||||
-rw-r--r-- | src/libtrace/atoi.c | 13 | ||||
-rw-r--r-- | src/libtrace/bcopy.c | 10 | ||||
-rw-r--r-- | src/libtrace/getenv.c | 15 | ||||
-rw-r--r-- | src/libtrace/init_libtrace.c | 196 | ||||
-rw-r--r-- | src/libtrace/libtrace.c | 33 | ||||
-rw-r--r-- | src/libtrace/print_results.c | 327 | ||||
-rw-r--r-- | src/libtrace/sprintf.c | 25 | ||||
-rw-r--r-- | src/libtrace/strcat.c | 12 | ||||
-rw-r--r-- | src/libtrace/strcmp.c | 12 | ||||
-rw-r--r-- | src/libtrace/strlen.c | 10 | ||||
-rw-r--r-- | src/libtrace/strncmp.c | 14 | ||||
-rw-r--r-- | src/libtrace/strnlen.c | 11 | ||||
-rw-r--r-- | src/libtrace/vsprintf.c | 267 | ||||
-rw-r--r-- | src/ltrace/ltrace.c | 116 |
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 Binary files differindex e4b03b0..c70f4ef 100755 --- a/lib/libtrace.so.1 +++ b/lib/libtrace.so.1 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); } |