Version 0.1.7
* Debian: New Standards-Version (2.3.0.1)
* Clean up structures a bit
* Trying to log return values...
diff --git a/THOUGHTS b/THOUGHTS
new file mode 100644
index 0000000..42ffb0f
--- /dev/null
+++ b/THOUGHTS
@@ -0,0 +1,25 @@
+process_options();
+open_program();
+enable_all_breakpoints();
+execute_program();
+forever {
+ wait_for_something();
+ switch(what happened) {
+ signal:
+ log_it();
+ exit:
+ log_it();
+ if (no_more_processes()) { exit(0); }
+ syscall:
+ log_it();
+ sysret:
+ log_it();
+ breakpoint:
+ libcall:
+ enable_brk_on_libret();
+ log_it();
+ libret:
+ log_it();
+ singlestep:
+ }
+}
diff --git a/all.h b/all.h
new file mode 100644
index 0000000..94d9617
--- /dev/null
+++ b/all.h
@@ -0,0 +1,135 @@
+/* elf.c: */
+extern int read_elf(const char *);
+
+
+/*
+ * Lista de types:
+ */
+
+#define _T_INT 1
+#define _T_ADDR 6
+
+#define _T_UNKNOWN -1
+#define _T_VOID 0
+#define _T_INT 1
+#define _T_UINT 2
+#define _T_OCTAL 3
+#define _T_CHAR 4
+#define _T_STRING 5
+#define _T_ADDR 6
+#define _T_FILE 7
+#define _T_HEX 8
+#define _T_FORMAT 9 /* printf-like format */
+
+#define _T_OUTPUT 0x80 /* OR'ed if arg is an OUTPUT value */
+
+struct function {
+ const char * function_name;
+ int return_type;
+ int num_params;
+ int params_type[10];
+ struct function * next;
+};
+
+extern struct function * list_of_functions;
+
+extern void print_function(const char *, int pid, int esp);
+#ifndef _LTRACE_I386_H
+#define _LTRACE_I386_H
+
+#define BREAKPOINT {0xcc}
+#define BREAKPOINT_LENGTH 1
+
+struct breakpoint {
+ unsigned long addr;
+ unsigned char value[BREAKPOINT_LENGTH];
+};
+
+void insert_breakpoint(int pid, struct breakpoint * sbp);
+void delete_breakpoint(int pid, struct breakpoint * sbp);
+unsigned long get_eip(int pid);
+unsigned long get_esp(int pid);
+unsigned long get_orig_eax(int pid);
+unsigned long get_return(int pid, unsigned long esp);
+unsigned long get_arg(int pid, unsigned long esp, int arg_num);
+int is_there_a_breakpoint(int pid, unsigned long eip);
+void continue_after_breakpoint(int pid, struct breakpoint * sbp, int delete_it);
+void continue_process(int pid, int signal);
+void trace_me(void);
+void untrace_pid(int pid);
+
+#include "process.h"
+#define PROC_BREAKPOINT 1
+#define PROC_SYSCALL 2
+#define PROC_SYSRET 3
+int type_of_stop(struct process * proc, int *what);
+
+#endif
+#include <stdio.h>
+
+extern FILE * output;
+extern int opt_d;
+extern int opt_i;
+extern int opt_S;
+void send_left(const char * fmt, ...);
+void send_right(const char * fmt, ...);
+void send_line(const char * fmt, ...);
+#ifndef _LTRACE_PROCESS_H
+#define _LTRACE_PROCESS_H
+
+#include "i386.h"
+
+/* not ready yet */
+#if 0
+struct symbols_from_filename {
+ char * filename;
+ struct library_symbol * list_of_symbols;
+}
+
+struct library_symbol {
+ char * name;
+ unsigned long addr;
+ unsigned long return_addr;
+ unsigned char old_value[BREAKPOINT_LENGTH];
+ struct library_symbol * next;
+};
+#endif
+
+struct process {
+ char * filename; /* from execve() (TODO) */
+ int pid;
+ int breakpoints_enabled;
+ struct breakpoint return_value; /* if within a function */
+ int syscall_number; /* outside syscall => -1 */
+ struct process * next;
+};
+
+extern struct process * list_of_processes;
+
+unsigned int instruction_pointer;
+
+int execute_process(const char * file, char * const argv[]);
+void wait_for_child(void);
+
+#endif
+extern char * signal_name[];
+#ifndef _LTRACE_SYMBOLS_H
+#define _LTRACE_SYMBOLS_H
+
+#include "i386.h"
+
+struct library_symbol {
+ char * name;
+ struct breakpoint sbp;
+ unsigned long return_addr;
+ struct library_symbol * next;
+};
+
+extern struct library_symbol * library_symbols;
+
+void enable_all_breakpoints(int pid);
+void disable_all_breakpoints(int pid);
+
+#endif
+
+extern char * syscall_list[];
diff --git a/debian/changelog b/debian/changelog
index 0c79334..c06caad 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+ltrace (0.1.7) experimental; urgency=low
+
+ * New Standards-Version (2.3.0.1)
+ * Clean up structures a bit
+ * Trying to log return values...
+
+ -- Juan Cespedes <cespedes@debian.org> Sun, 26 Oct 1997 19:53:20 +0100
+
ltrace (0.1.6) experimental; urgency=low
* New maintainer address
diff --git a/elf.c b/elf.c
index 03918aa..08e4b67 100644
--- a/elf.c
+++ b/elf.c
@@ -91,7 +91,7 @@
perror("malloc");
exit(1);
}
- library_symbols->addr = ((symtab+i)->st_value);
+ library_symbols->sbp.addr = ((symtab+i)->st_value);
library_symbols->name = strtab+(symtab+i)->st_name;
library_symbols->next = tmp;
if (opt_d>1) {
diff --git a/i386.c b/i386.c
index c2e9a98..4d62b43 100644
--- a/i386.c
+++ b/i386.c
@@ -8,25 +8,25 @@
#include "i386.h"
#include "ltrace.h"
-void insert_breakpoint(int pid, unsigned long addr, unsigned char * value)
+void insert_breakpoint(int pid, struct breakpoint * sbp)
{
int a;
- a = ptrace(PTRACE_PEEKTEXT, pid, addr, 0);
- value[0] = a & 0xFF;
+ a = ptrace(PTRACE_PEEKTEXT, pid, sbp->addr, 0);
+ sbp->value[0] = a & 0xFF;
a &= 0xFFFFFF00;
a |= 0xCC;
- ptrace(PTRACE_POKETEXT, pid, addr, a);
+ ptrace(PTRACE_POKETEXT, pid, sbp->addr, a);
}
-void delete_breakpoint(int pid, unsigned long addr, unsigned char * value)
+void delete_breakpoint(int pid, struct breakpoint * sbp)
{
int a;
- a = ptrace(PTRACE_PEEKTEXT, pid, addr, 0);
+ a = ptrace(PTRACE_PEEKTEXT, pid, sbp->addr, 0);
a &= 0xFFFFFF00;
- a |= value[0];
- ptrace(PTRACE_POKETEXT, pid, addr, a);
+ a |= sbp->value[0];
+ ptrace(PTRACE_POKETEXT, pid, sbp->addr, a);
}
unsigned long get_eip(int pid)
@@ -78,10 +78,10 @@
ptrace(PTRACE_SYSCALL, pid, 1, signal);
}
-void continue_after_breakpoint(int pid, unsigned long eip, unsigned char * value, int delete_it)
+void continue_after_breakpoint(int pid, struct breakpoint * sbp, int delete_it)
{
- delete_breakpoint(pid, eip, value);
- ptrace(PTRACE_POKEUSER, pid, 4*EIP, eip);
+ delete_breakpoint(pid, sbp);
+ ptrace(PTRACE_POKEUSER, pid, 4*EIP, sbp->addr);
if (delete_it) {
continue_process(pid, 0);
} else {
@@ -94,7 +94,7 @@
perror("wait4");
exit(1);
}
- insert_breakpoint(pid, eip, value);
+ insert_breakpoint(pid, sbp);
continue_process(pid, 0);
}
}
@@ -121,19 +121,24 @@
* PROC_SYSCALL - Syscall entry
* PROC_SYSRET - Syscall return
*/
-int type_of_stop(struct process * proc, int *what)
+int type_of_stop(int pid, struct proc_arch * proc_arch, int *what)
{
- *what = get_orig_eax(proc->pid);
+ *what = get_orig_eax(pid);
if (*what!=-1) {
- if (proc->syscall_number != *what) {
- proc->syscall_number = *what;
+ if (proc_arch->syscall_number != *what) {
+ proc_arch->syscall_number = *what;
return PROC_SYSCALL;
} else {
- proc->syscall_number = -1;
+ proc_arch->syscall_number = -1;
return PROC_SYSRET;
}
}
return PROC_BREAKPOINT;
}
+
+void proc_arch_init(struct proc_arch *proc_arch)
+{
+ proc_arch->syscall_number=-1;
+}
diff --git a/i386.h b/i386.h
index 54075ee..aecb891 100644
--- a/i386.h
+++ b/i386.h
@@ -4,23 +4,32 @@
#define BREAKPOINT {0xcc}
#define BREAKPOINT_LENGTH 1
-void insert_breakpoint(int pid, unsigned long addr, unsigned char * value);
-void delete_breakpoint(int pid, unsigned long addr, unsigned char * value);
+struct breakpoint {
+ unsigned long addr;
+ unsigned char value[BREAKPOINT_LENGTH];
+};
+
+void insert_breakpoint(int pid, struct breakpoint * sbp);
+void delete_breakpoint(int pid, struct breakpoint * sbp);
unsigned long get_eip(int pid);
unsigned long get_esp(int pid);
unsigned long get_orig_eax(int pid);
unsigned long get_return(int pid, unsigned long esp);
unsigned long get_arg(int pid, unsigned long esp, int arg_num);
int is_there_a_breakpoint(int pid, unsigned long eip);
-void continue_after_breakpoint(int pid, unsigned long eip, unsigned char * value, int delete_it);
+void continue_after_breakpoint(int pid, struct breakpoint * sbp, int delete_it);
void continue_process(int pid, int signal);
void trace_me(void);
void untrace_pid(int pid);
-#include "process.h"
+struct proc_arch {
+ int syscall_number; /* outside syscall => -1 */
+};
+
#define PROC_BREAKPOINT 1
#define PROC_SYSCALL 2
#define PROC_SYSRET 3
-int type_of_stop(struct process * proc, int *what);
+int type_of_stop(int pid, struct proc_arch *proc_arch, int *what);
+void proc_arch_init(struct proc_arch *proc_arch);
#endif
diff --git a/ltrace.h b/ltrace.h
index a1617bd..3dde957 100644
--- a/ltrace.h
+++ b/ltrace.h
@@ -1,6 +1,7 @@
#include <stdio.h>
extern FILE * output;
+
extern int opt_d;
extern int opt_i;
extern int opt_S;
diff --git a/output.c b/output.c
index f4173a3..142b725 100644
--- a/output.c
+++ b/output.c
@@ -45,3 +45,13 @@
va_end(args);
new_line=1;
}
+
+void print_libcall(const char name, int pid, int esp)
+{
+ fprintf(output, "libcall: %s\n", name);
+}
+
+void print_libret(const char name, int pid, int esp)
+{
+ fprintf(output, "libret: %s\n", name);
+}
diff --git a/process.c b/process.c
index 71f9791..2852310 100644
--- a/process.c
+++ b/process.c
@@ -3,6 +3,7 @@
#include <unistd.h>
#include <errno.h>
#include <signal.h>
+#include <string.h>
#include <sys/types.h>
#include <sys/resource.h>
#include <sys/wait.h>
@@ -44,7 +45,8 @@
tmp = (struct process *)malloc(sizeof(struct process));
tmp->pid = pid;
tmp->breakpoints_enabled = 0;
- tmp->syscall_number = -1;
+ proc_arch_init(&tmp->proc_arch);
+ tmp->within_function = 0;
tmp->next = list_of_processes;
list_of_processes = tmp;
@@ -155,7 +157,7 @@
eip = get_eip(pid);
instruction_pointer = eip;
- switch (type_of_stop(current_process, &status)) {
+ switch (type_of_stop(current_process->pid, ¤t_process->proc_arch, &status)) {
case PROC_SYSCALL:
if (status==__NR_fork) {
disable_all_breakpoints(pid);
@@ -178,16 +180,31 @@
default:
}
/* pid is breakpointed... */
- /* TODO: I may be here after a PTRACE_SINGLESTEP ... */
+ /* TODO: I could be here after a PTRACE_SINGLESTEP ... */
esp = get_esp(pid);
instruction_pointer = get_return(pid, esp);
tmp = library_symbols;
function_seen = 0;
- while(tmp) {
- if (eip == tmp->addr) {
+ if (eip == current_process->return_value.addr) {
+ function_seen = 1;
+#if 0
+ send_line("return");
+ print_libret(tmp->name, pid, esp);
+#endif
+ continue_after_breakpoint(pid, ¤t_process->return_value, 1);
+ } else while(tmp) {
+ if (eip == tmp->sbp.addr) {
function_seen = 1;
- print_function(tmp->name, pid, esp);
- continue_after_breakpoint(pid, eip, tmp->old_value, 0);
+ if (current_process->within_function) {
+ delete_breakpoint(pid, ¤t_process->return_value);
+ }
+ current_process->return_value.addr = instruction_pointer;
+ insert_breakpoint(pid, ¤t_process->return_value);
+ current_process->within_function=1;
+#if 0
+ print_libcall(tmp->name, pid, esp);
+#endif
+ continue_after_breakpoint(pid, &tmp->sbp, 0);
break;
}
tmp = tmp->next;
diff --git a/process.h b/process.h
index f14dc95..568f61d 100644
--- a/process.h
+++ b/process.h
@@ -1,6 +1,8 @@
#ifndef _LTRACE_PROCESS_H
#define _LTRACE_PROCESS_H
+#include "i386.h"
+
/* not ready yet */
#if 0
struct symbols_from_filename {
@@ -21,13 +23,15 @@
char * filename; /* from execve() (TODO) */
int pid;
int breakpoints_enabled;
- int syscall_number; /* outside syscall => -1 */
+ int within_function;
+ struct breakpoint return_value; /* if within a function */
+ struct proc_arch proc_arch;
struct process * next;
};
extern struct process * list_of_processes;
-unsigned int instruction_pointer;
+extern unsigned int instruction_pointer;
int execute_process(const char * file, char * const argv[]);
void wait_for_child(void);
diff --git a/symbols.c b/symbols.c
index b36c775..be109cb 100644
--- a/symbols.c
+++ b/symbols.c
@@ -15,7 +15,7 @@
tmp = library_symbols;
while(tmp) {
- insert_breakpoint(pid, tmp->addr, &tmp->old_value[0]);
+ insert_breakpoint(pid, &tmp->sbp);
tmp = tmp->next;
}
}
@@ -26,7 +26,7 @@
tmp = library_symbols;
while(tmp) {
- delete_breakpoint(pid, tmp->addr, &tmp->old_value[0]);
+ delete_breakpoint(pid, &tmp->sbp);
tmp = tmp->next;
}
}
diff --git a/symbols.h b/symbols.h
index cc410fe..55747fa 100644
--- a/symbols.h
+++ b/symbols.h
@@ -5,9 +5,8 @@
struct library_symbol {
char * name;
- unsigned long addr;
+ struct breakpoint sbp;
unsigned long return_addr;
- unsigned char old_value[BREAKPOINT_LENGTH];
struct library_symbol * next;
};