[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