[Ltrace-devel] r81 - in ltrace/trunk: . sysdeps/linux-gnu sysdeps/linux-gnu/ppc
pmachata-guest at alioth.debian.org
pmachata-guest at alioth.debian.org
Wed Mar 12 14:56:04 UTC 2008
Author: pmachata-guest
Date: 2008-03-12 14:56:01 +0000 (Wed, 12 Mar 2008)
New Revision: 81
Modified:
ltrace/trunk/ChangeLog
ltrace/trunk/display_args.c
ltrace/trunk/ltrace.h
ltrace/trunk/process_event.c
ltrace/trunk/sysdeps/linux-gnu/ppc/arch.h
ltrace/trunk/sysdeps/linux-gnu/ppc/regs.c
ltrace/trunk/sysdeps/linux-gnu/ppc/trace.c
ltrace/trunk/sysdeps/linux-gnu/trace.c
Log:
PPC argument handling improvements from Luis Machado
Modified: ltrace/trunk/ChangeLog
===================================================================
--- ltrace/trunk/ChangeLog 2007-09-04 15:34:53 UTC (rev 80)
+++ ltrace/trunk/ChangeLog 2008-03-12 14:56:01 UTC (rev 81)
@@ -1,3 +1,15 @@
+2008-02-27 Luis Machado <luisgpm at br.ibm.com>
+
+ * sysdeps/linux-gnu/ppc/trace.c (arch_umovelong): New function.
+ * sysdeps/linux-gnu/ppc/regs.c (get_instruction): New function.
+ (get_count_register): New function.
+ * sysdeps/linux-gnu/ppc/arch.h (ARCH_HAVE_UMOVELONG): New define.
+ * sysdeps/linux-gnu/trace.c (umovelong): Create arch-specific
+ variant.
+ * ltrace.h (umovelong): Change prototype.
+ * process_event.c (process_breakpoint): Handle specifics of ppc32 PLT.
+ * display_args.c: Call umovelong with info parameter.
+
2007-09-04 Juan Cespedes <cespedes at debian.org>
* ltrace.h: Take arg_num out of arg_type_info
Modified: ltrace/trunk/display_args.c
===================================================================
--- ltrace/trunk/display_args.c 2007-09-04 15:34:53 UTC (rev 80)
+++ ltrace/trunk/display_args.c 2008-03-12 14:56:01 UTC (rev 81)
@@ -32,7 +32,8 @@
if (len_spec > 0)
return len_spec;
if (type == LT_TOF_STRUCT) {
- umovelong(proc, st + st_info->u.struct_info.offset[-len_spec-1], &len);
+ umovelong (proc, st + st_info->u.struct_info.offset[-len_spec-1],
+ &len, st_info->u.struct_info.fields[-len_spec-1]);
return len;
}
@@ -135,7 +136,8 @@
} else {
if (value == 0)
return fprintf(output, "NULL");
- else if (umovelong(proc, (void *) value, &pointed_to) < 0)
+ else if (umovelong (proc, (void *) value, &pointed_to,
+ info->u.ptr_info.info) < 0)
return fprintf(output, "?");
else
return display_value(type, proc, pointed_to, inner,
Modified: ltrace/trunk/ltrace.h
===================================================================
--- ltrace/trunk/ltrace.h 2007-09-04 15:34:53 UTC (rev 80)
+++ ltrace/trunk/ltrace.h 2008-03-12 14:56:01 UTC (rev 81)
@@ -250,7 +250,7 @@
extern long gimme_arg(enum tof type, struct process *proc, int arg_num, arg_type_info *info);
extern void save_register_args(enum tof type, struct process *proc);
extern int umovestr(struct process *proc, void *addr, int len, void *laddr);
-extern int umovelong(struct process *proc, void *addr, long *result);
+extern int umovelong (struct process *proc, void *addr, long *result, arg_type_info *info);
extern int ffcheck(void *maddr);
extern void *sym2addr(struct process *, struct library_symbol *);
Modified: ltrace/trunk/process_event.c
===================================================================
--- ltrace/trunk/process_event.c 2007-09-04 15:34:53 UTC (rev 80)
+++ ltrace/trunk/process_event.c 2008-03-12 14:56:01 UTC (rev 81)
@@ -248,21 +248,29 @@
struct breakpoint *sbp;
debug(2, "event: breakpoint (%p)", event->e_un.brk_addr);
- if ((sbp = event->proc->breakpoint_being_enabled) != 0) {
+
#ifdef __powerpc__
- struct breakpoint *nxtbp;
- char nop_inst[] = PPC_NOP;
- if (memcmp(sbp->orig_value, nop_inst, PPC_NOP_LENGTH) == 0) {
- nxtbp = address2bpstruct(event->proc,
- event->e_un.brk_addr +
- PPC_NOP_LENGTH);
- if (nxtbp != 0) {
- enable_breakpoint(event->proc->pid, sbp);
- continue_after_breakpoint(event->proc, nxtbp);
+ /* Need to skip following NOP's to prevent a fake function from being stacked. */
+ long stub_addr = (long) get_count_register(event->proc);
+ struct breakpoint *stub_bp = NULL;
+ char nop_instruction[] = PPC_NOP;
+
+ stub_bp = address2bpstruct (event->proc, event->e_un.brk_addr);
+
+ if (stub_bp) {
+ unsigned char *bp_instruction = stub_bp->orig_value;
+
+ if (memcmp(bp_instruction, nop_instruction,
+ PPC_NOP_LENGTH) == 0) {
+ if (stub_addr != (long) event->e_un.brk_addr) {
+ set_instruction_pointer (event->proc, event->e_un.brk_addr + 4);
+ continue_process(event->proc->pid);
return;
}
}
+ }
#endif
+ if ((sbp = event->proc->breakpoint_being_enabled) != 0) {
/* Reinsert breakpoint */
continue_enabling_breakpoint(event->proc->pid,
event->proc->
Modified: ltrace/trunk/sysdeps/linux-gnu/ppc/arch.h
===================================================================
--- ltrace/trunk/sysdeps/linux-gnu/ppc/arch.h 2007-09-04 15:34:53 UTC (rev 80)
+++ ltrace/trunk/sysdeps/linux-gnu/ppc/arch.h 2008-03-12 14:56:01 UTC (rev 81)
@@ -13,6 +13,9 @@
#define PLT_REINITALISATION_BP "_start"
+/* Start of arch-specific functions. */
+#define ARCH_HAVE_UMOVELONG
+
#define PPC_NOP { 0x60, 0x00, 0x00, 0x00 }
#define PPC_NOP_LENGTH 4
Modified: ltrace/trunk/sysdeps/linux-gnu/ppc/regs.c
===================================================================
--- ltrace/trunk/sysdeps/linux-gnu/ppc/regs.c 2007-09-04 15:34:53 UTC (rev 80)
+++ ltrace/trunk/sysdeps/linux-gnu/ppc/regs.c 2008-03-12 14:56:01 UTC (rev 81)
@@ -38,3 +38,10 @@
return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, sizeof(long) * PT_LNK,
0);
}
+
+/* Grab the value of CTR registers. */
+void *get_count_register (struct process *proc)
+{
+ return (void *) ptrace (PTRACE_PEEKUSER, proc->pid,
+ sizeof (long) * PT_CTR, 0);
+}
Modified: ltrace/trunk/sysdeps/linux-gnu/ppc/trace.c
===================================================================
--- ltrace/trunk/sysdeps/linux-gnu/ppc/trace.c 2007-09-04 15:34:53 UTC (rev 80)
+++ ltrace/trunk/sysdeps/linux-gnu/ppc/trace.c 2008-03-12 14:56:01 UTC (rev 81)
@@ -8,6 +8,7 @@
#include <sys/ptrace.h>
#include <asm/ptrace.h>
#include <elf.h>
+#include <errno.h>
#include "ltrace.h"
@@ -29,9 +30,13 @@
#endif
}
-/* Returns 1 if syscall, 2 if sysret, 0 otherwise.
- */
+/* Returns 1 if syscall, 2 if sysret, 0 otherwise. */
#define SYSCALL_INSN 0x44000002
+
+unsigned int greg = 3;
+unsigned int freg = 1;
+unsigned int vreg = 2;
+
int syscall_p(struct process *proc, int status, int *sysnum)
{
if (WIFSTOPPED(status)
@@ -56,21 +61,97 @@
return 0;
}
+/* Grab functions arguments based on the PPC64 ABI. */
long gimme_arg(enum tof type, struct process *proc, int arg_num, arg_type_info *info)
{
- if (arg_num == -1) { /* return value */
- return ptrace(PTRACE_PEEKUSER, proc->pid, sizeof(long) * PT_R3,
- 0);
- } else if (arg_num < 8) {
- return ptrace(PTRACE_PEEKUSER, proc->pid,
- sizeof(long) * (arg_num + PT_R3), 0);
- } else {
- return ptrace(PTRACE_PEEKDATA, proc->pid,
- proc->stack_pointer + 8 * (arg_num - 8), 0);
+ long data;
+
+ if (type == LT_TOF_FUNCTIONR) {
+ if (info->type == ARGTYPE_FLOAT || info->type == ARGTYPE_DOUBLE)
+ return ptrace (PTRACE_PEEKUSER, proc->pid,
+ sizeof (long) * (PT_FPR0 + 1), 0);
+ else
+ return ptrace (PTRACE_PEEKUSER, proc->pid,
+ sizeof (long) * PT_R3, 0);
}
+
+ /* Check if we're entering a new function call to list parameters. If
+ so, initialize the register control variables to keep track of where
+ the parameters were stored. */
+ if (type == LT_TOF_FUNCTION && arg_num == 0) {
+ /* Initialize the set of registrers for parameter passing. */
+ greg = 3;
+ freg = 1;
+ vreg = 2;
+ }
+
+ if (info->type == ARGTYPE_FLOAT || info->type == ARGTYPE_DOUBLE) {
+ if (freg <= 13 || (proc->mask_32bit && freg <= 8)) {
+ data = ptrace (PTRACE_PEEKUSER, proc->pid,
+ sizeof (long) * (PT_FPR0 + freg), 0);
+
+ if (info->type == ARGTYPE_FLOAT) {
+ /* float values passed in FP registers are automatically
+ promoted to double. We need to convert it back to float
+ before printing. */
+ union { long val; float fval; double dval; } cvt;
+ cvt.val = data;
+ cvt.fval = (float) cvt.dval;
+ data = cvt.val;
+ }
+
+ freg++;
+ greg++;
+
+ return data;
+ }
+ }
+ else if (greg <= 10) {
+ data = ptrace (PTRACE_PEEKUSER, proc->pid,
+ sizeof (long) * greg, 0);
+ greg++;
+
+ return data;
+ }
+ else
+ return ptrace (PTRACE_PEEKDATA, proc->pid,
+ proc->stack_pointer + sizeof (long) *
+ (arg_num - 8), 0);
+
return 0;
}
void save_register_args(enum tof type, struct process *proc)
{
}
+
+/* Read a single long from the process's memory address 'addr'. */
+int arch_umovelong (struct process *proc, void *addr, long *result, arg_type_info *info)
+{
+ long pointed_to;
+
+ errno = 0;
+
+ pointed_to = ptrace (PTRACE_PEEKTEXT, proc->pid, addr, 0);
+
+ if (pointed_to == -1 && errno)
+ return -errno;
+
+ /* Since int's are 4-bytes (long is 8-bytes) in length for ppc64, we
+ need to shift the long values returned by ptrace to end up with
+ the correct value. */
+
+ if (info) {
+ if (info->type == ARGTYPE_INT || (proc->mask_32bit && (info->type == ARGTYPE_POINTER
+ || info->type == ARGTYPE_STRING))) {
+ pointed_to = pointed_to >> 32;
+
+ /* Make sure we have nothing in the upper word so we can
+ do a explicit cast from long to int later in the code. */
+ pointed_to &= 0x00000000ffffffff;
+ }
+ }
+
+ *result = pointed_to;
+ return 0;
+}
Modified: ltrace/trunk/sysdeps/linux-gnu/trace.c
===================================================================
--- ltrace/trunk/sysdeps/linux-gnu/trace.c 2007-09-04 15:34:53 UTC (rev 80)
+++ ltrace/trunk/sysdeps/linux-gnu/trace.c 2008-03-12 14:56:01 UTC (rev 81)
@@ -73,6 +73,29 @@
#endif
};
+#ifdef ARCH_HAVE_UMOVELONG
+extern int arch_umovelong (struct process *, void *, long *, arg_type_info *);
+int umovelong (struct process *proc, void *addr, long *result, arg_type_info *info)
+{
+ return arch_umovelong (proc, addr, result, info);
+}
+#else
+/* Read a single long from the process's memory address 'addr' */
+int umovelong (struct process *proc, void *addr, long *result, arg_type_info *info)
+{
+ long pointed_to;
+
+ errno = 0;
+ pointed_to = ptrace (PTRACE_PEEKTEXT, proc->pid, addr, 0);
+ if (pointed_to == -1 && errno)
+ return -errno;
+
+ *result = pointed_to;
+ return 0;
+}
+#endif
+
+
/* Returns 1 if the sysnum may make a new child to be created
* (ie, with fork() or clone())
* Returns 0 otherwise.
@@ -207,20 +230,6 @@
}
}
-/* Read a single long from the process's memory address 'addr' */
-int umovelong(struct process *proc, void *addr, long *result)
-{
- long pointed_to;
-
- errno = 0;
- pointed_to = ptrace(PTRACE_PEEKTEXT, proc->pid, addr, 0);
- if (pointed_to == -1 && errno)
- return -errno;
-
- *result = pointed_to;
- return 0;
-}
-
/* Read a series of bytes starting at the process's memory address
'addr' and continuing until a NUL ('\0') is seen or 'len' bytes
have been read.
More information about the Ltrace-devel
mailing list