- handle floats
- fix arguments in function return. regs may have changed and stack
  handling may (imho) become a nightmare so backup integer and fp regs
  at function/syscall entry with save_register_args
- As we're now getting regs in get_arch_dep, remove other ptrace()
  calls used to get registers

Signed-off-by: Arnaud Patard <[email protected]>
---
 sysdeps/linux-gnu/x86_64/ptrace.h |   12 ++++
 sysdeps/linux-gnu/x86_64/trace.c  |  103 +++++++++++++++++++++++++++----------
 2 files changed, 88 insertions(+), 27 deletions(-)

diff --git a/sysdeps/linux-gnu/x86_64/ptrace.h b/sysdeps/linux-gnu/x86_64/ptrace.h
index c3cbcb6..b689637 100644
--- a/sysdeps/linux-gnu/x86_64/ptrace.h
+++ b/sysdeps/linux-gnu/x86_64/ptrace.h
@@ -1 +1,13 @@
+#include <stdint.h>
 #include <sys/ptrace.h>
+#include <sys/user.h>
+
+typedef struct {
+	int valid;
+	unsigned long func_args[6];
+	uint32_t func_fpr_args[64];
+	unsigned long sysc_args[6];
+	struct user_fpregs_struct fpregs;
+	struct user_regs_struct regs;
+} proc_archdep;
+
diff --git a/sysdeps/linux-gnu/x86_64/trace.c b/sysdeps/linux-gnu/x86_64/trace.c
index 189734d..bb93afd 100644
--- a/sysdeps/linux-gnu/x86_64/trace.c
+++ b/sysdeps/linux-gnu/x86_64/trace.c
@@ -6,8 +6,10 @@
 #include <stdlib.h>
 #include <sys/ptrace.h>
 #include <sys/reg.h>
+#include <string.h>
 
 #include "common.h"
+#include "ptrace.h"
 
 #if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
 # define PTRACE_PEEKUSER PTRACE_PEEKUSR
@@ -19,15 +21,20 @@
 
 void
 get_arch_dep(Process *proc) {
-	unsigned long cs;
-	if (proc->arch_ptr)
-		return;
-	cs = ptrace(PTRACE_PEEKUSER, proc->pid, 8 * CS, 0);
-	if (cs == 0x23) {
+        proc_archdep *a;
+
+	if (!proc->arch_ptr)
+		proc->arch_ptr = (void *)malloc(sizeof(proc_archdep));
+
+	a = (proc_archdep *) (proc->arch_ptr);
+	a->valid = (ptrace(PTRACE_GETREGS, proc->pid, 0, &a->regs) >= 0);
+	if (a->valid) {
+		a->valid = (ptrace(PTRACE_GETFPREGS, proc->pid, 0, &a->fpregs) >= 0);
+	}
+	if (a->regs.cs == 0x23) {
 		proc->mask_32bit = 1;
 		proc->personality = 1;
 	}
-	proc->arch_ptr = (void *)1;
 }
 
 /* Returns 1 if syscall, 2 if sysret, 0 otherwise.
@@ -53,8 +60,10 @@ syscall_p(Process *proc, int status, int *sysnum) {
 
 static unsigned int
 gimme_arg32(enum tof type, Process *proc, int arg_num) {
+	proc_archdep *a = (proc_archdep *) proc->arch_ptr;
+
 	if (arg_num == -1) {	/* return value */
-		return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RAX, 0);
+		return a->regs.rax;
 	}
 
 	if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) {
@@ -63,17 +72,17 @@ gimme_arg32(enum tof type, Process *proc, int arg_num) {
 	} else if (type == LT_TOF_SYSCALL || type == LT_TOF_SYSCALLR) {
 		switch (arg_num) {
 		case 0:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RBX, 0);
+			return a->regs.rbx;
 		case 1:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RCX, 0);
+			return a->regs.rcx;
 		case 2:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RDX, 0);
+			return a->regs.rdx;
 		case 3:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RSI, 0);
+			return a->regs.rsi;
 		case 4:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RDI, 0);
+			return a->regs.rdi;
 		case 5:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RBP, 0);
+			return a->regs.rbp;
 		default:
 			fprintf(stderr,
 				"gimme_arg32 called with wrong arguments\n");
@@ -86,46 +95,65 @@ gimme_arg32(enum tof type, Process *proc, int arg_num) {
 
 long
 gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) {
+	proc_archdep *a = (proc_archdep *) proc->arch_ptr;
+
+	if (!a || !a->valid)
+		return -1;
+
 	if (proc->mask_32bit)
 		return (unsigned int)gimme_arg32(type, proc, arg_num);
 
 	if (arg_num == -1) {	/* return value */
-		return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RAX, 0);
+		return a->regs.rax;
 	}
 
-	if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) {
+	if (type == LT_TOF_FUNCTION) {
+		if (info->type == ARGTYPE_FLOAT)
+			return a->fpregs.xmm_space[4*arg_num];
+
 		switch (arg_num) {
 		case 0:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RDI, 0);
+			return a->regs.rdi;
 		case 1:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RSI, 0);
+			return a->regs.rsi;
 		case 2:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RDX, 0);
+			return a->regs.rdx;
 		case 3:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RCX, 0);
+			return a->regs.rcx;
 		case 4:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * R8, 0);
+			return a->regs.r8;
 		case 5:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * R9, 0);
+			return a->regs.r9;
 		default:
 			return ptrace(PTRACE_PEEKTEXT, proc->pid,
 				      proc->stack_pointer + 8 * (arg_num - 6 +
 								 1), 0);
 		}
+	} else if (type == LT_TOF_FUNCTIONR) {
+		if (info->type == ARGTYPE_FLOAT)
+			return a->func_fpr_args[4*arg_num];
+		switch (arg_num) {
+			case 0 ... 5:
+				return a->func_args[arg_num];
+			default:
+				return ptrace(PTRACE_PEEKTEXT, proc->pid,
+				      proc->stack_pointer + 8 * (arg_num - 6 +
+								 1), 0);
+		}
 	} else if (type == LT_TOF_SYSCALL || LT_TOF_SYSCALLR) {
 		switch (arg_num) {
 		case 0:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RDI, 0);
+			return a->regs.rdi;
 		case 1:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RSI, 0);
+			return a->regs.rsi;
 		case 2:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RDX, 0);
+			return a->regs.rdx;
 		case 3:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * R10, 0);
+			return a->regs.rcx;
 		case 4:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * R8, 0);
+			return a->regs.r8;
 		case 5:
-			return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * R9, 0);
+			return a->regs.r9;
 		default:
 			fprintf(stderr,
 				"gimme_arg called with wrong arguments\n");
@@ -141,4 +169,25 @@ gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) {
 
 void
 save_register_args(enum tof type, Process *proc) {
+	proc_archdep *a = (proc_archdep *) proc->arch_ptr;
+
+	if (a && a->valid) {
+		if(type == LT_TOF_FUNCTION) {
+			a->func_args[0] = a->regs.rdi;
+			a->func_args[1] = a->regs.rsi;
+			a->func_args[2] = a->regs.rdx;
+			a->func_args[3] = a->regs.rcx;
+			a->func_args[4] = a->regs.r8;
+			a->func_args[5] = a->regs.r9;
+			memcpy(a->func_fpr_args, &a->fpregs.xmm_space, sizeof(a->func_fpr_args));
+
+		} else {
+			a->sysc_args[0] = a->regs.rdi;
+			a->sysc_args[1] = a->regs.rsi;
+			a->sysc_args[2] = a->regs.rdx;
+			a->sysc_args[3] = a->regs.rcx;
+			a->sysc_args[4] = a->regs.r8;
+			a->sysc_args[5] = a->regs.r9;
+		}
+	}
 }
_______________________________________________
Ltrace-devel mailing list
[email protected]
http://lists.alioth.debian.org/mailman/listinfo/ltrace-devel

Reply via email to