aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--Makefile217
-rw-r--r--README4
-rwxr-xr-xltracebin0 -> 7212 bytes
-rw-r--r--ltrace.c151
5 files changed, 133 insertions, 44 deletions
diff --git a/Makefile b/Makefile
index ec4d8a5..1037283 100644
--- a/Makefile
+++ b/Makefile
@@ -1,11 +1,10 @@
CC = gcc
-CFLAGS = -Wall -Werror -O2
+CFLAGS = -Wall -O2
all: ltrace
clean:
rm -f ltrace ltrace.o
-dist:
- make clean
+dist: #clean
( cd .. ; tar zcvf ltrace2-`date +%y%m%d`.tgz ltrace2 )
diff --git a/Makefile2 b/Makefile2
deleted file mode 100644
index 0278488..0000000
--- a/Makefile2
+++ /dev/null
@@ -1,17 +0,0 @@
-CC = gcc
-CFLAGS = -Wall -O2 -Iinclude
-LD = ld
-
-all:
- @echo 'Type "make dist" to make a distribution .tgz'
- @echo
-
-clean:
- make -C src/libtrace clean
- make -C src/ltrace clean
- make -C src/test clean
- rm -f *.o
-
-dist:
- make clean
- ( cd .. ; tar zcvf ltrace-`date +%y%m%d`.tgz ltrace )
diff --git a/README b/README
index 23b6e80..27ac67c 100644
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
Funcionamiento:
---------------
-* Puts soft breakpoints (INT 3, CC) in process using ptrace, just like
- gdb/strace
+* 2nd approach: using soft breakpoints (INT 3, CC) in process using
+ ptrace, just like gdb/strace
diff --git a/ltrace b/ltrace
new file mode 100755
index 0000000..6aeb155
--- /dev/null
+++ b/ltrace
Binary files differ
diff --git a/ltrace.c b/ltrace.c
index 207913a..af5773f 100644
--- a/ltrace.c
+++ b/ltrace.c
@@ -1,5 +1,6 @@
#include <stdio.h>
#include <errno.h>
+#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ptrace.h>
@@ -11,9 +12,16 @@
#include <sys/mman.h>
#include <string.h>
-u_long strtab;
-u_long symtab;
-u_long symtab_len;
+static int debug = 0;
+
+struct library_symbol {
+ char * name;
+ unsigned long addr;
+ unsigned char value;
+ struct library_symbol * next;
+};
+
+struct library_symbol * library_symbols = NULL;
int read_elf(char *filename)
{
@@ -22,9 +30,10 @@ int read_elf(char *filename)
void * addr;
struct elf32_hdr * hdr;
Elf32_Shdr * shdr;
+ struct elf32_sym * symtab = NULL;
int i;
-
- strtab = symtab = symtab_len = 0;
+ char * strtab = NULL;
+ u_long symtab_len = 0;
fd = open(filename, O_RDONLY);
if (fd==-1) {
@@ -53,20 +62,52 @@ int read_elf(char *filename)
shdr = addr + hdr->e_shoff + i*hdr->e_shentsize;
if (shdr->sh_type == SHT_DYNSYM) {
if (!symtab) {
- symtab = shdr->sh_addr;
+#if 0
+ symtab = (struct elf32_sym *)shdr->sh_addr;
+#else
+ symtab = (struct elf32_sym *)(addr + shdr->sh_offset);
+#endif
symtab_len = shdr->sh_size;
}
}
if (shdr->sh_type == SHT_STRTAB) {
if (!strtab) {
- strtab = shdr->sh_addr;
+#if 0
+ strtab = (char *)(addr + shdr->sh_offset);
+#else
+ strtab = (char *)(addr + shdr->sh_offset);
+#endif
}
}
}
- fprintf(stderr, "symtab: 0x%08lx\n", symtab);
- fprintf(stderr, "symtab_len: %lu\n", symtab_len);
- fprintf(stderr, "strtab: 0x%08lx\n", strtab);
- return 0;
+ if (debug>0) {
+ fprintf(stderr, "symtab: 0x%08x\n", (unsigned)symtab);
+ fprintf(stderr, "symtab_len: %lu\n", symtab_len);
+ fprintf(stderr, "strtab: 0x%08x\n", (unsigned)strtab);
+ }
+ if (!symtab) {
+ return 0;
+ }
+ for(i=0; i<symtab_len/sizeof(struct elf32_sym); i++) {
+ if (!((symtab+i)->st_shndx) && (symtab+i)->st_value) {
+ struct library_symbol * tmp = library_symbols;
+
+ library_symbols = malloc(sizeof(struct library_symbol));
+ if (!library_symbols) {
+ perror("malloc");
+ exit(1);
+ }
+ library_symbols->addr = ((symtab+i)->st_value);
+ library_symbols->name = strtab+(symtab+i)->st_name;
+ library_symbols->next = tmp;
+ if (debug>0) {
+ fprintf(stderr, "addr: 0x%08x, symbol: \"%s\"\n",
+ (unsigned)((symtab+i)->st_value),
+ (strtab+(symtab+i)->st_name));
+ }
+ }
+ }
+ return 1;
}
int main(int argc, char **argv)
@@ -74,13 +115,23 @@ int main(int argc, char **argv)
int pid;
int status;
struct rusage ru;
+ struct library_symbol * tmp = NULL;
+
+ while ((argc>1) && (argv[1][0] == '-') && (argv[1][2] == '\0')) {
+ switch(argv[1][1]) {
+ case 'd': debug++;
+ break;
+ default: fprintf(stderr, "Unknown option '%c'\n", argv[1][1]);
+ exit(1);
+ }
+ argc--; argv++;
+ }
if (argc<2) {
- fprintf(stderr, "Usage: %s <program> [<arguments>]\n", argv[0]);
+ fprintf(stderr, "Usage: %s [<options>] <program> [<arguments>]\n", argv[0]);
exit(1);
}
- read_elf(argv[1]);
- if (!symtab) {
+ if (!read_elf(argv[1])) {
fprintf(stderr, "%s: Not dynamically linked\n", argv[0]);
exit(1);
}
@@ -98,7 +149,30 @@ int main(int argc, char **argv)
exit(1);
}
fprintf(stderr, "pid %u attached\n", pid);
+
+ /* Enable breakpoints: */
+ pid = wait4(-1, &status, 0, &ru);
+ if (pid==-1) {
+ perror("wait4");
+ exit(1);
+ }
+ fprintf(stderr, "Enabling breakpoints...\n");
+ tmp = library_symbols;
+ while(tmp) {
+ int a;
+ a = ptrace(PTRACE_PEEKTEXT, pid, tmp->addr, 0);
+ tmp->value = a & 0xFF;
+ a &= 0xFFFFFF00;
+ a |= 0xCC;
+ ptrace(PTRACE_POKETEXT, pid, tmp->addr, a);
+ tmp = tmp->next;
+ }
+ ptrace(PTRACE_CONT, pid, 1, 0);
+
while(1) {
+ int eip;
+ int function_seen;
+
pid = wait4(-1, &status, 0, &ru);
if (pid==-1) {
if (errno == ECHILD) {
@@ -112,17 +186,50 @@ int main(int argc, char **argv)
fprintf(stderr, "pid %u exited\n", pid);
continue;
}
- fprintf(stderr,"EIP = 0x%08x\n", ptrace(PTRACE_PEEKUSR, pid, 4*EIP, 0));
+ if (!WIFSTOPPED(status)) {
+ fprintf(stderr, "pid %u ???\n", pid);
+ continue;
+ }
+ /* pid is stopped... */
+ eip = ptrace(PTRACE_PEEKUSR, pid, 4*EIP, 0);
+/*
+ fprintf(stderr,"EIP = 0x%08x\n", eip);
fprintf(stderr,"EBP = 0x%08x\n", ptrace(PTRACE_PEEKUSR, pid, 4*EBP, 0));
-#if 0
- ptrace(PTRACE_SINGLESTEP, pid, 0, 0);
- continue;
-#endif
- if (WIFSTOPPED(status)) {
+*/
+ tmp = library_symbols;
+ function_seen = 0;
+ while(tmp) {
+ if (eip == tmp->addr+1) {
+ int a;
+ function_seen = 1;
+ fprintf(stderr, "Function: %s\n", tmp->name);
+ a = ptrace(PTRACE_PEEKTEXT, pid, tmp->addr, 0);
+ a &= 0xFFFFFF00;
+ a |= tmp->value;
+ ptrace(PTRACE_POKETEXT, pid, tmp->addr, a);
+ ptrace(PTRACE_POKEUSR, pid, 4*EIP, eip-1);
+ ptrace(PTRACE_SINGLESTEP, pid, 0, 0);
+ pid = wait4(-1, &status, 0, &ru);
+ if (pid==-1) {
+ if (errno == ECHILD) {
+ fprintf(stderr, "No more children\n");
+ exit(0);
+ }
+ perror("wait4");
+ exit(1);
+ }
+ a = ptrace(PTRACE_PEEKTEXT, pid, tmp->addr, 0);
+ a &= 0xFFFFFF00;
+ a |= 0xCC;
+ ptrace(PTRACE_POKETEXT, pid, tmp->addr, a);
+ ptrace(PTRACE_CONT, pid, 1, 0);
+ break;
+ }
+ tmp = tmp->next;
+ }
+ if (!function_seen) {
fprintf(stderr, "pid %u stopped; continuing it...\n", pid);
ptrace(PTRACE_CONT, pid, 1, 0);
- } else {
- fprintf(stderr, "pid %u ???\n", pid);
}
}
exit(0);