- 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