[Ltrace-devel] r67 - in ltrace/trunk: . sysdeps sysdeps/linux-gnu/alpha sysdeps/linux-gnu/arm sysdeps/linux-gnu/i386 sysdeps/linux-gnu/ia64 sysdeps/linux-gnu/m68k sysdeps/linux-gnu/ppc sysdeps/linux-gnu/s390 sysdeps/linux-gnu/sparc sysdeps/linux-gnu/x86_64

Ian Wienand ianw-guest at costa.debian.org
Mon Sep 25 00:27:08 UTC 2006


Author: ianw-guest
Date: 2006-09-25 00:27:08 +0000 (Mon, 25 Sep 2006)
New Revision: 67

Modified:
   ltrace/trunk/ChangeLog
   ltrace/trunk/display_args.c
   ltrace/trunk/ltrace.h
   ltrace/trunk/output.c
   ltrace/trunk/process_event.c
   ltrace/trunk/read_config_file.c
   ltrace/trunk/sysdeps/README
   ltrace/trunk/sysdeps/linux-gnu/alpha/trace.c
   ltrace/trunk/sysdeps/linux-gnu/arm/trace.c
   ltrace/trunk/sysdeps/linux-gnu/i386/trace.c
   ltrace/trunk/sysdeps/linux-gnu/ia64/trace.c
   ltrace/trunk/sysdeps/linux-gnu/m68k/trace.c
   ltrace/trunk/sysdeps/linux-gnu/ppc/trace.c
   ltrace/trunk/sysdeps/linux-gnu/s390/trace.c
   ltrace/trunk/sysdeps/linux-gnu/sparc/trace.c
   ltrace/trunk/sysdeps/linux-gnu/x86_64/trace.c
Log:
Large IA64 fix, many thanks to Steve Fink



Modified: ltrace/trunk/ChangeLog
===================================================================
--- ltrace/trunk/ChangeLog	2006-09-14 23:57:49 UTC (rev 66)
+++ ltrace/trunk/ChangeLog	2006-09-25 00:27:08 UTC (rev 67)
@@ -1,3 +1,22 @@
+2006-09-18    Steve Fink <sphink at gmail.com>
+
+	* display_args.c: store arg_num in arg_type_info
+	* display_args.c: support 'double' parameters
+	* display_args.c: fix implementation of float,double params for ia64
+	* output.c, process_event.c: store arg_num in arg_type_info
+	* read_config_file.c: support 'double' parameters
+	* read_config_file.c: store arg_num in arg_type_info, and as a result,
+	stop using singleton objects for any of the arg_type_info's.
+	* read_config_file.c: improve support for struct field alignments
+	* read_config_file.c: count floating-point parameters to support ia64
+	float parameter passing
+	* sysdeps/README, sysdeps/linux-gnu/*/trace.c: pass in the full
+	arg_type_info to gimme_arg rather than just the arg_num (necessary
+	for float params on some architectures)
+	* sysdeps/linux-gnu/ia64/trace.c: accommodate register renaming when
+	fetching the parameters of a function after it has returned
+	* sysdeps/linux-gnu/ia64/trace.c: support floating point parameters
+
 2006-09-15  Olaf Hering <olh at suse.de>
 
 	* Makefile.in : allow installation as non-root user, print out

Modified: ltrace/trunk/display_args.c
===================================================================
--- ltrace/trunk/display_args.c	2006-09-14 23:57:49 UTC (rev 66)
+++ ltrace/trunk/display_args.c	2006-09-25 00:27:08 UTC (rev 67)
@@ -27,13 +27,18 @@
 		       void *st, arg_type_info* st_info)
 {
     long len;
+    arg_type_info info;
+
     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);
 	return len;
     }
-    return gimme_arg(type, proc, -len_spec - 1);
+
+    info.arg_num = -len_spec - 1;
+    info.type = ARGTYPE_INT;
+    return gimme_arg(type, proc, &info);
 }
 
 static int display_ptrto(enum tof type, struct process *proc, long item,
@@ -199,10 +204,15 @@
 	case ARGTYPE_USHORT:
 		return fprintf(output, "%hu", (unsigned short) value);
 	case ARGTYPE_FLOAT: {
-		union { long l; float f; } cvt;
+		union { long l; float f; double d; } cvt;
 		cvt.l = value;
 		return fprintf(output, "%f", cvt.f);
 	}
+	case ARGTYPE_DOUBLE: {
+		union { long l; float f; double d; } cvt;
+		cvt.l = value;
+		return fprintf(output, "%lf", cvt.d);
+	}
 	case ARGTYPE_ADDR:
 		if (!value)
 			return fprintf(output, "NULL");
@@ -233,17 +243,16 @@
 	}
 }
 
-int display_arg(enum tof type, struct process *proc, int arg_num,
-		arg_type_info * info)
+int display_arg(enum tof type, struct process *proc, arg_type_info * info)
 {
     long arg;
 
     if (info->type == ARGTYPE_VOID) {
 	return 0;
     } else if (info->type == ARGTYPE_FORMAT) {
-	return display_format(type, proc, arg_num);
+	return display_format(type, proc, info->arg_num);
     } else {
-	arg = gimme_arg(type, proc, arg_num);
+	arg = gimme_arg(type, proc, info);
 	return display_value(type, proc, arg, info, NULL, NULL);
     }
 }
@@ -326,8 +335,11 @@
 	unsigned char *str1;
 	int i;
 	int len = 0;
+	arg_type_info info;
 
-	addr = (void *)gimme_arg(type, proc, arg_num);
+	info.arg_num = arg_num;
+	info.type = ARGTYPE_POINTER;
+	addr = (void *)gimme_arg(type, proc, &info);
 	if (!addr) {
 		return fprintf(output, "NULL");
 	}
@@ -370,60 +382,68 @@
 						break;
 					}
 				} else if (c == 'd' || c == 'i') {
+					info.arg_num = ++arg_num;
+					info.type = ARGTYPE_LONG;
 					if (!is_long || proc->mask_32bit)
 						len +=
 						    fprintf(output, ", %d",
 							    (int)gimme_arg(type,
 									   proc,
-									   ++arg_num));
+									   &info));
 					else
 						len +=
 						    fprintf(output, ", %ld",
 							    gimme_arg(type,
 								      proc,
-								      ++arg_num));
+								      &info));
 					break;
 				} else if (c == 'u') {
+					info.arg_num = ++arg_num;
+					info.type = ARGTYPE_LONG;
 					if (!is_long || proc->mask_32bit)
 						len +=
 						    fprintf(output, ", %u",
 							    (int)gimme_arg(type,
 									   proc,
-									   ++arg_num));
+									   &info));
 					else
 						len +=
 						    fprintf(output, ", %lu",
 							    gimme_arg(type,
 								      proc,
-								      ++arg_num));
+								      &info));
 					break;
 				} else if (c == 'o') {
+					info.arg_num = ++arg_num;
+					info.type = ARGTYPE_LONG;
 					if (!is_long || proc->mask_32bit)
 						len +=
 						    fprintf(output, ", 0%o",
 							    (int)gimme_arg(type,
 									   proc,
-									   ++arg_num));
+									   &info));
 					else
 						len +=
 						    fprintf(output, ", 0%lo",
 							    gimme_arg(type,
 								      proc,
-								      ++arg_num));
+								      &info));
 					break;
 				} else if (c == 'x' || c == 'X') {
+					info.arg_num = ++arg_num;
+					info.type = ARGTYPE_LONG;
 					if (!is_long || proc->mask_32bit)
 						len +=
 						    fprintf(output, ", %#x",
 							    (int)gimme_arg(type,
 									   proc,
-									   ++arg_num));
+									   &info));
 					else
 						len +=
 						    fprintf(output, ", %#lx",
 							    gimme_arg(type,
 								      proc,
-								      ++arg_num));
+								      &info));
 					break;
 				} else if (strchr("eEfFgGaACS", c)
 					   || (is_long
@@ -432,34 +452,42 @@
 					str1[i + 1] = '\0';
 					break;
 				} else if (c == 'c') {
+					info.arg_num = ++arg_num;
+					info.type = ARGTYPE_LONG;
 					len += fprintf(output, ", '");
 					len +=
 					    display_char((int)
 							 gimme_arg(type, proc,
-								   ++arg_num));
+								   &info));
 					len += fprintf(output, "'");
 					break;
 				} else if (c == 's') {
+					info.arg_num = ++arg_num;
+					info.type = ARGTYPE_POINTER;
 					len += fprintf(output, ", ");
 					len +=
 					    display_string(type, proc,
 							   (void *)gimme_arg(type,
 									     proc,
-									     ++arg_num),
+									     &info),
 							   string_maxlength);
 					break;
 				} else if (c == 'p' || c == 'n') {
+					info.arg_num = ++arg_num;
+					info.type = ARGTYPE_POINTER;
 					len +=
 					    fprintf(output, ", %p",
 						    (void *)gimme_arg(type,
 								      proc,
-								      ++arg_num));
+								      &info));
 					break;
 				} else if (c == '*') {
+					info.arg_num = ++arg_num;
+					info.type = ARGTYPE_LONG;
 					len +=
 					    fprintf(output, ", %d",
 						    (int)gimme_arg(type, proc,
-								   ++arg_num));
+								   &info));
 				}
 			}
 		}

Modified: ltrace/trunk/ltrace.h
===================================================================
--- ltrace/trunk/ltrace.h	2006-09-14 23:57:49 UTC (rev 66)
+++ ltrace/trunk/ltrace.h	2006-09-25 00:27:08 UTC (rev 67)
@@ -39,7 +39,8 @@
 	ARGTYPE_CHAR,
 	ARGTYPE_SHORT,
 	ARGTYPE_USHORT,
-	ARGTYPE_FLOAT,
+	ARGTYPE_FLOAT,		/* float value, may require index */
+	ARGTYPE_DOUBLE,		/* double value, may require index */
 	ARGTYPE_ADDR,
 	ARGTYPE_FILE,
 	ARGTYPE_FORMAT,		/* printf-like format */
@@ -55,6 +56,7 @@
 
 typedef struct arg_type_info_t {
     enum arg_type type;
+    int arg_num;
     union {
 	// ARGTYPE_ENUM
 	struct {
@@ -78,7 +80,6 @@
 	// ARGTYPE_STRUCT
 	struct {
 	    struct arg_type_info_t **fields;	// NULL-terminated
-	    size_t *gap;
 	    size_t *offset;
 	    size_t size;
 	} struct_info;
@@ -87,6 +88,16 @@
 	struct {
 	    struct arg_type_info_t *info;
 	} ptr_info;
+
+        // ARGTYPE_FLOAT
+	struct {
+	    size_t float_index;
+	} float_info;
+
+        // ARGTYPE_DOUBLE
+	struct {
+	    size_t float_index;
+	} double_info;
     } u;
 } arg_type_info;
 
@@ -201,8 +212,7 @@
 extern struct event *wait_for_something(void);
 extern void process_event(struct event *event);
 extern void execute_program(struct process *, char **);
-extern int display_arg(enum tof type, struct process *proc, int arg_num,
-		       arg_type_info *info);
+extern int display_arg(enum tof type, struct process *proc, arg_type_info *info);
 extern struct breakpoint *address2bpstruct(struct process *proc, void *addr);
 extern void breakpoints_init(struct process *proc);
 extern void insert_breakpoint(struct process *proc, void *addr,
@@ -215,7 +225,7 @@
 extern struct process *open_program(char *filename, pid_t pid);
 extern void open_pid(pid_t pid, int verbose);
 extern void show_summary(void);
-extern arg_type_info *lookup_singleton(enum arg_type at);
+extern arg_type_info *lookup_prototype(enum arg_type at);
 
 /* Arch-dependent stuff: */
 extern char *pid2name(pid_t pid);
@@ -238,7 +248,7 @@
 extern void continue_after_breakpoint(struct process *proc,
 				      struct breakpoint *sbp);
 extern void continue_enabling_breakpoint(pid_t pid, struct breakpoint *sbp);
-extern long gimme_arg(enum tof type, struct process *proc, int arg_num);
+extern long gimme_arg(enum tof type, struct process *proc, arg_type_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);

Modified: ltrace/trunk/output.c
===================================================================
--- ltrace/trunk/output.c	2006-09-14 23:57:49 UTC (rev 66)
+++ ltrace/trunk/output.c	2006-09-25 00:27:08 UTC (rev 67)
@@ -166,7 +166,7 @@
 	struct function *func;
 	static arg_type_info *arg_unknown = NULL;
 	if (arg_unknown == NULL)
-	    arg_unknown = lookup_singleton(ARGTYPE_UNKNOWN);
+	    arg_unknown = lookup_prototype(ARGTYPE_UNKNOWN);
 
 	if (opt_c) {
 		return;
@@ -191,23 +191,26 @@
 	func = name2func(function_name);
 	if (!func) {
 		int i;
+		arg_type_info info = *arg_unknown;
 		for (i = 0; i < 4; i++) {
+			info.arg_num = i;
 			current_column +=
-			    display_arg(type, proc, i, arg_unknown);
+			    display_arg(type, proc, &info);
 			current_column += fprintf(output, ", ");
 		}
-		current_column += display_arg(type, proc, 4, arg_unknown);
+		info.arg_num = 4;
+		current_column += display_arg(type, proc, &info);
 		return;
 	} else {
 		int i;
 		for (i = 0; i < func->num_params - func->params_right - 1; i++) {
 			current_column +=
-			    display_arg(type, proc, i, func->arg_info[i]);
+			    display_arg(type, proc, func->arg_info[i]);
 			current_column += fprintf(output, ", ");
 		}
 		if (func->num_params > func->params_right) {
 			current_column +=
-			    display_arg(type, proc, i, func->arg_info[i]);
+			    display_arg(type, proc, func->arg_info[i]);
 			if (func->params_right) {
 				current_column += fprintf(output, ", ");
 			}
@@ -223,7 +226,7 @@
 	struct function *func = name2func(function_name);
 	static arg_type_info *arg_unknown = NULL;
 	if (arg_unknown == NULL)
-	    arg_unknown = lookup_singleton(ARGTYPE_UNKNOWN);
+	    arg_unknown = lookup_prototype(ARGTYPE_UNKNOWN);
 
 	if (opt_c) {
 		struct opt_c_struct *st;
@@ -276,21 +279,23 @@
 	}
 
 	if (!func) {
+		arg_type_info info = *arg_unknown;
 		current_column += fprintf(output, ") ");
 		tabto(opt_a - 1);
 		fprintf(output, "= ");
-		display_arg(type, proc, -1, arg_unknown);
+		info.arg_num = -1;
+		display_arg(type, proc, &info);
 	} else {
 		int i;
 		for (i = func->num_params - func->params_right;
 		     i < func->num_params - 1; i++) {
 			current_column +=
-			    display_arg(type, proc, i, func->arg_info[i]);
+			    display_arg(type, proc, func->arg_info[i]);
 			current_column += fprintf(output, ", ");
 		}
 		if (func->params_right) {
 			current_column +=
-			    display_arg(type, proc, i, func->arg_info[i]);
+			    display_arg(type, proc, func->arg_info[i]);
 		}
 		current_column += fprintf(output, ") ");
 		tabto(opt_a - 1);
@@ -298,7 +303,7 @@
 		if (func->return_info->type == ARGTYPE_VOID) {
 			fprintf(output, "<void>");
 		} else {
-			display_arg(type, proc, -1, func->return_info);
+			display_arg(type, proc, func->return_info);
 		}
 	}
 	if (opt_T) {

Modified: ltrace/trunk/process_event.c
===================================================================
--- ltrace/trunk/process_event.c	2006-09-14 23:57:49 UTC (rev 66)
+++ ltrace/trunk/process_event.c	2006-09-25 00:27:08 UTC (rev 67)
@@ -225,8 +225,11 @@
 	}
 	if (fork_p(event->proc, event->e_un.sysnum)) {
 		if (opt_f) {
+			arg_type_info info;
+			info.arg_num = -1; /* Return value */
+			info.type = ARGTYPE_LONG;
 			pid_t child =
-			    gimme_arg(LT_TOF_SYSCALLR, event->proc, -1);
+			    gimme_arg(LT_TOF_SYSCALLR, event->proc, &info);
 			if (child > 0) {
 				open_pid(child, 0);
 			}
@@ -239,7 +242,10 @@
 			     sysname(event->proc, event->e_un.sysnum));
 	}
 	if (exec_p(event->proc, event->e_un.sysnum)) {
-		if (gimme_arg(LT_TOF_SYSCALLR, event->proc, -1) == 0) {
+		arg_type_info info;
+		info.arg_num = -1; /* Return value */
+		info.type = ARGTYPE_LONG;
+		if (gimme_arg(LT_TOF_SYSCALLR, event->proc, &info) == 0) {
 			pid_t saved_pid;
 			event->proc->mask_32bit = 0;
 			event->proc->personality = 0;
@@ -260,11 +266,12 @@
 static void process_breakpoint(struct event *event)
 {
 	int i, j;
-	struct breakpoint *sbp, *nxtbp;
+	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,

Modified: ltrace/trunk/read_config_file.c
===================================================================
--- ltrace/trunk/read_config_file.c	2006-09-14 23:57:49 UTC (rev 66)
+++ ltrace/trunk/read_config_file.c	2006-09-25 00:27:08 UTC (rev 67)
@@ -36,6 +36,7 @@
 	"short", ARGTYPE_SHORT}, {
 	"ushort", ARGTYPE_USHORT}, {
 	"float", ARGTYPE_FLOAT}, {
+	"double", ARGTYPE_DOUBLE}, {
 	"addr", ARGTYPE_ADDR}, {
 	"file", ARGTYPE_FILE}, {
 	"format", ARGTYPE_FORMAT}, {
@@ -47,10 +48,10 @@
 	NULL, ARGTYPE_UNKNOWN}	/* Must finish with NULL */
 };
 
-/* Array of singleton objects for each of the types. The order in this
+/* Array of prototype objects for each of the types. The order in this
  * array must exactly match the list of enumerated values in
  * ltrace.h */
-static arg_type_info arg_type_singletons[] = {
+static arg_type_info arg_type_prototypes[] = {
 	{ ARGTYPE_VOID },
 	{ ARGTYPE_INT },
 	{ ARGTYPE_UINT },
@@ -61,6 +62,7 @@
 	{ ARGTYPE_SHORT },
 	{ ARGTYPE_USHORT },
 	{ ARGTYPE_FLOAT },
+	{ ARGTYPE_DOUBLE },
 	{ ARGTYPE_ADDR },
 	{ ARGTYPE_FILE },
 	{ ARGTYPE_FORMAT },
@@ -74,12 +76,12 @@
 	{ ARGTYPE_UNKNOWN }
 };
 
-arg_type_info *lookup_singleton(enum arg_type at)
+arg_type_info *lookup_prototype(enum arg_type at)
 {
 	if (at >= 0 && at <= ARGTYPE_COUNT)
-		return &arg_type_singletons[at];
+		return &arg_type_prototypes[at];
 	else
-		return &arg_type_singletons[ARGTYPE_COUNT]; /* UNKNOWN */
+		return &arg_type_prototypes[ARGTYPE_COUNT]; /* UNKNOWN */
 }
 
 static arg_type_info *str2type(char **str)
@@ -90,11 +92,11 @@
 		if (!strncmp(*str, tmp->name, strlen(tmp->name))
 		    && index(" ,()#*;012345[", *(*str + strlen(tmp->name)))) {
 			*str += strlen(tmp->name);
-			return lookup_singleton(tmp->pt);
+			return lookup_prototype(tmp->pt);
 		}
 		tmp++;
 	}
-	return lookup_singleton(ARGTYPE_UNKNOWN);
+	return lookup_prototype(ARGTYPE_UNKNOWN);
 }
 
 static void eat_spaces(char **str)
@@ -162,25 +164,6 @@
 	return (stacked == 0) ? pos : NULL;
 }
 
-/*
-  Decide whether a type needs any additional parameters.
-  For now, we do not parse any nontrivial argument types.
-*/
-static int simple_type(enum arg_type at)
-{
-    switch (at) {
-    case ARGTYPE_STRING:
-    case ARGTYPE_STRING_N:
-    case ARGTYPE_ARRAY:
-    case ARGTYPE_ENUM:
-    case ARGTYPE_STRUCT:
-	return 0;
-
-    default:
-	return 1;
-    }
-}
-
 static int parse_int(char **str)
 {
     char *end;
@@ -298,10 +281,14 @@
 	return sizeof(short);
     } else if (arg->type == ARGTYPE_FLOAT) {
 	return sizeof(float);
+    } else if (arg->type == ARGTYPE_DOUBLE) {
+	return sizeof(double);
     } else if (arg->type == ARGTYPE_ENUM) {
 	return sizeof(int);
     } else if (arg->type == ARGTYPE_STRUCT) {
 	return arg->u.struct_info.size;
+    } else if (arg->type == ARGTYPE_POINTER) {
+	return sizeof(void*);
     } else if (arg->type == ARGTYPE_ARRAY) {
 	if (arg->u.array_info.len_spec > 0)
 	    return arg->u.array_info.len_spec * arg->u.array_info.elt_size;
@@ -312,60 +299,86 @@
     }
 }
 
-/* I'm sure this isn't completely correct, but just try to get most of
- * them right for now. */
 #undef alignof
 #define alignof(field,st) ((size_t) ((char*) &st.field - (char*) &st))
-static void align_struct(arg_type_info* info)
+static size_t arg_align(arg_type_info * arg)
 {
-    struct {
-	char c;
-	int i;
-    } ci;
-    struct {
-	struct {
-	    char c;
-	} s;
-	int i;
-    } cis;
+    struct { char c; char C; } cC;
+    struct { char c; short s; } cs;
+    struct { char c; int i; } ci;
+    struct { char c; long l; } cl;
+    struct { char c; void* p; } cp;
+    struct { char c; float f; } cf;
+    struct { char c; double d; } cd;
 
-    size_t int_alignment = alignof(i, ci);
-    size_t whole_struct_alignment = alignof(i, cis);
+    static size_t char_alignment = alignof(C, cC);
+    static size_t short_alignment = alignof(s, cs);
+    static size_t int_alignment = alignof(i, ci);
+    static size_t long_alignment = alignof(l, cl);
+    static size_t ptr_alignment = alignof(p, cp);
+    static size_t float_alignment = alignof(f, cf);
+    static size_t double_alignment = alignof(d, cd);
 
+    switch (arg->type) {
+    case ARGTYPE_LONG:
+    case ARGTYPE_ULONG:
+	return long_alignment;
+    case ARGTYPE_CHAR:
+	return char_alignment;
+    case ARGTYPE_SHORT:
+    case ARGTYPE_USHORT:
+	return short_alignment;
+    case ARGTYPE_FLOAT:
+	return float_alignment;
+    case ARGTYPE_DOUBLE:
+	return double_alignment;
+    case ARGTYPE_ADDR:
+    case ARGTYPE_FILE:
+    case ARGTYPE_FORMAT:
+    case ARGTYPE_STRING:
+    case ARGTYPE_STRING_N:
+    case ARGTYPE_POINTER:
+	return ptr_alignment;
+
+    case ARGTYPE_ARRAY:
+	return arg_align(&arg->u.array_info.elt_type[0]);
+
+    case ARGTYPE_STRUCT:
+	return arg_align(arg->u.struct_info.fields[0]);
+	
+    default:
+	return int_alignment;
+    }
+}
+
+static size_t align_skip(size_t alignment, size_t offset)
+{
+    if (offset % alignment)
+	return alignment - (offset % alignment);
+    else
+	return 0;
+}
+
+/* I'm sure this isn't completely correct, but just try to get most of
+ * them right for now. */
+static void align_struct(arg_type_info* info)
+{
     size_t offset;
-    size_t gap;
     int i;
 
     if (info->u.struct_info.size != 0)
 	return;			// Already done
 
-    // The gap array isn't actually needed anymore, because the
-    // offset can be used for everything.
-
-    // 1. Add internal padding
+    // Compute internal padding due to alignment constraints for
+    // various types.
     offset = 0;
     for (i = 0; info->u.struct_info.fields[i] != NULL; i++) {
 	arg_type_info *field = info->u.struct_info.fields[i];
+	offset += align_skip(arg_align(field), offset);
 	info->u.struct_info.offset[i] = offset;
 	offset += arg_sizeof(field);
-
-	if (offset % int_alignment != 0) {
-	    gap = int_alignment - offset % int_alignment;
-	    info->u.struct_info.gap[i] = gap;
-	    offset += gap;
-	}
     }
 
-    // 2. Add padding at end of entire struct
-    for (i = 0; info->u.struct_info.fields[i] != NULL; i++);
-    if (i == 0)
-	return;
-    if (offset % whole_struct_alignment != 0) {
-	gap = whole_struct_alignment - offset % whole_struct_alignment;
-	info->u.struct_info.gap[i - 1] = gap;
-	offset += gap;
-    }
-
     info->u.struct_info.size = offset;
 }
 
@@ -376,7 +389,7 @@
 
 	if (strncmp(*str, "typedef", 7) == 0) {
 	    parse_typedef(str);
-	    return lookup_singleton(ARGTYPE_UNKNOWN);
+	    return lookup_prototype(ARGTYPE_UNKNOWN);
 	}
 
 	simple = str2type(str);
@@ -388,9 +401,6 @@
 		return simple;		// UNKNOWN
 	}
 
-	if (simple_type(simple->type) && simple->type != ARGTYPE_STRING)
-		return simple;
-
 	info = malloc(sizeof(*info));
 	info->type = simple->type;
 
@@ -508,8 +518,6 @@
 	    (*str)++;		// Get past open paren
 	    info->u.struct_info.fields =
 		malloc((MAX_ARGS + 1) * sizeof(void *));
-	    info->u.struct_info.gap =
-		malloc((MAX_ARGS + 1) * sizeof(size_t));
 	    info->u.struct_info.offset =
 		malloc((MAX_ARGS + 1) * sizeof(size_t));
 	    info->u.struct_info.size = 0;
@@ -527,7 +535,6 @@
 		    (*str)++;	// Get past comma
 		    eat_spaces(str);
 		}
-		info->u.struct_info.gap[field_num] = 0;
 		if ((info->u.struct_info.fields[field_num++] =
 		     parse_type(str)) == NULL)
 		    return NULL;
@@ -543,11 +550,16 @@
 	}
 
 	default:
-		output_line(0, "Syntax error in `%s', line %d: Unknown type encountered",
-			    filename, line_no);
-		free(info);
-		error_count++;
-		return NULL;
+		if (info->type == ARGTYPE_UNKNOWN) {
+			output_line(0, "Syntax error in `%s', line %d: "
+				    "Unknown type encountered",
+				    filename, line_no);
+			free(info);
+			error_count++;
+			return NULL;
+		} else {
+			return info;
+		}
 	}
 }
 
@@ -571,6 +583,7 @@
 	char *str = buf;
 	char *tmp;
 	int i;
+	int float_num = 0;
 
 	line_no++;
 	debug(3, "Reading line %d of `%s'", line_no, filename);
@@ -582,6 +595,7 @@
 		debug(3, " Skipping line %d", line_no);
 		return NULL;
 	}
+	fun.return_info->arg_num = -1;
 	debug(4, " return_type = %d", fun.return_info->type);
 	eat_spaces(&str);
 	tmp = start_of_arg_sig(str);
@@ -615,6 +629,11 @@
 			error_count++;
 			return NULL;
 		}
+		if (fun.arg_info[i]->type == ARGTYPE_FLOAT)
+			fun.arg_info[i]->u.float_info.float_index = float_num++;
+		else if (fun.arg_info[i]->type == ARGTYPE_DOUBLE)
+			fun.arg_info[i]->u.double_info.float_index = float_num++;
+		fun.arg_info[i]->arg_num = i;
 		eat_spaces(&str);
 		if (*str == ',') {
 			str++;

Modified: ltrace/trunk/sysdeps/README
===================================================================
--- ltrace/trunk/sysdeps/README	2006-09-14 23:57:49 UTC (rev 66)
+++ ltrace/trunk/sysdeps/README	2006-09-25 00:27:08 UTC (rev 67)
@@ -22,7 +22,7 @@
 void * get_instruction_pointer(pid_t pid);
 void * get_stack_pointer(pid_t pid);
 void * get_return_addr(pid_t pid, void * stack_pointer);
-long gimme_arg(enum tof type, struct process * proc, int arg_num);
+long gimme_arg(enum tof type, struct process * proc, arg_type_info*);
 int umovestr(struct process * proc, void * addr, int len, void * laddr);
 int umovelong(struct process * proc, void * addr, long * result);
 char * pid2name(pid_t pid);

Modified: ltrace/trunk/sysdeps/linux-gnu/alpha/trace.c
===================================================================
--- ltrace/trunk/sysdeps/linux-gnu/alpha/trace.c	2006-09-14 23:57:49 UTC (rev 66)
+++ ltrace/trunk/sysdeps/linux-gnu/alpha/trace.c	2006-09-25 00:27:08 UTC (rev 67)
@@ -47,8 +47,10 @@
 	return 0;
 }
 
-long gimme_arg(enum tof type, struct process *proc, int arg_num)
+long gimme_arg(enum tof type, struct process *proc, arg_type_info *info)
 {
+	int arg_num = info->arg_num;
+
 	if (arg_num == -1) {	/* return value */
 		return ptrace(PTRACE_PEEKUSER, proc->pid, 0 /* REG_R0 */ , 0);
 	}

Modified: ltrace/trunk/sysdeps/linux-gnu/arm/trace.c
===================================================================
--- ltrace/trunk/sysdeps/linux-gnu/arm/trace.c	2006-09-14 23:57:49 UTC (rev 66)
+++ ltrace/trunk/sysdeps/linux-gnu/arm/trace.c	2006-09-25 00:27:08 UTC (rev 67)
@@ -51,8 +51,10 @@
 	return 0;
 }
 
-long gimme_arg(enum tof type, struct process *proc, int arg_num)
+long gimme_arg(enum tof type, struct process *proc, arg_type_info *info)
 {
+	int arg_num = info->arg_num;
+
 	if (arg_num == -1) {	/* return value */
 		return ptrace(PTRACE_PEEKUSER, proc->pid, off_r0, 0);
 	}

Modified: ltrace/trunk/sysdeps/linux-gnu/i386/trace.c
===================================================================
--- ltrace/trunk/sysdeps/linux-gnu/i386/trace.c	2006-09-14 23:57:49 UTC (rev 66)
+++ ltrace/trunk/sysdeps/linux-gnu/i386/trace.c	2006-09-25 00:27:08 UTC (rev 67)
@@ -43,8 +43,10 @@
 	return 0;
 }
 
-long gimme_arg(enum tof type, struct process *proc, int arg_num)
+long gimme_arg(enum tof type, struct process *proc, arg_type_info *info)
 {
+	int arg_num = info->arg_num;
+
 	if (arg_num == -1) {	/* return value */
 		return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * EAX, 0);
 	}

Modified: ltrace/trunk/sysdeps/linux-gnu/ia64/trace.c
===================================================================
--- ltrace/trunk/sysdeps/linux-gnu/ia64/trace.c	2006-09-14 23:57:49 UTC (rev 66)
+++ ltrace/trunk/sysdeps/linux-gnu/ia64/trace.c	2006-09-25 00:27:08 UTC (rev 67)
@@ -34,6 +34,18 @@
 	unsigned long code[2];
 };
 
+union cfm_t {
+	struct {
+		unsigned long sof:7;
+		unsigned long sol:7;
+		unsigned long sor:4;
+		unsigned long rrb_gr:7;
+		unsigned long rrb_fr:7;
+		unsigned long rrb_pr:6;
+	} cfm;
+	unsigned long value;
+};
+
 int syscall_p(struct process *proc, int status, int *sysnum)
 {
 
@@ -105,13 +117,25 @@
 	return 0;
 }
 
-long gimme_arg(enum tof type, struct process *proc, int arg_num)
+/* Stolen from David Mosberger's utrace tool, which he released under
+   the GPL
+   (http://www.gelato.unsw.edu.au/archives/linux-ia64/0104/1405.html) */
+static inline double
+fpreg_to_double (struct ia64_fpreg *fp)
 {
+  double result;
 
-	unsigned long bsp, cfm;
+  asm ("ldf.fill %0=%1" : "=f"(result) : "m"(*fp));
+  return result;
+}
 
+static long gimme_long_arg(enum tof type, struct process *proc, int arg_num)
+{
+	union cfm_t cfm;
+	unsigned long bsp;
+
 	bsp = ptrace(PTRACE_PEEKUSER, proc->pid, PT_AR_BSP, 0);
-	cfm = ptrace(PTRACE_PEEKUSER, proc->pid, PT_CFM, 0);
+	cfm.value = ptrace(PTRACE_PEEKUSER, proc->pid, PT_CFM, 0);
 
 	if (arg_num == -1)	/* return value */
 		return ptrace(PTRACE_PEEKUSER, proc->pid, PT_R8, 0);
@@ -119,14 +143,25 @@
 	/* First 8 arguments are passed in registers on the register
 	 * stack, the following arguments are passed on the stack
 	 * after a 16 byte scratch area
-	 */
-	if (type == LT_TOF_FUNCTION || LT_TOF_FUNCTIONR) {
-		if (arg_num < 8)
+	 *
+	 * If the function has returned, the ia64 register window has
+	 * been reverted to the caller's configuration. So although in
+	 * the callee, the first parameter is in R32, in the caller
+	 * the first parameter comes in the registers after the local
+	 * registers (really, input parameters plus locals, but the
+	 * hardware doesn't track the distinction.) So we have to add
+	 * in the size of the local area (sol) to find the first
+	 * parameter passed to the callee. */
+	if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) {
+		if (arg_num < 8) {
+                        if (type == LT_TOF_FUNCTIONR)
+				arg_num += cfm.cfm.sol;
+
 			return ptrace(PTRACE_PEEKDATA, proc->pid,
-				      (long)ia64_rse_skip_regs((long *)bsp,
-							       -cfm + arg_num),
+				      (long)ia64_rse_skip_regs((unsigned long *)bsp,
+							       -cfm.cfm.sof + arg_num),
 				      0);
-		else {
+		} else {
 			unsigned long sp =
 			    ptrace(PTRACE_PEEKUSER, proc->pid, PT_R12, 0) + 16;
 			return ptrace(PTRACE_PEEKDATA, proc->pid,
@@ -136,7 +171,7 @@
 
 	if (type == LT_TOF_SYSCALL || LT_TOF_SYSCALLR)
 		return ptrace(PTRACE_PEEKDATA, proc->pid,
-			      (long)ia64_rse_skip_regs((long *)bsp, arg_num),
+			      (long)ia64_rse_skip_regs((unsigned long *)bsp, arg_num),
 			      0);
 
 	/* error if we get here */
@@ -144,6 +179,91 @@
 	exit(1);
 }
 
+static long float_regs[8] = { PT_F8, PT_F9, PT_F10, PT_F11,
+			      PT_F12, PT_F13, PT_F14, PT_F15 };
+static double gimme_float_arg(enum tof type, struct process *proc, int arg_num)
+{
+	union cfm_t cfm;
+	unsigned long bsp;
+	struct ia64_fpreg reg;
+
+	if (arg_num == -1) {	/* return value */
+		reg.u.bits[0] = ptrace(PTRACE_PEEKUSER, proc->pid,
+				       PT_F8, 0);
+		reg.u.bits[1] = ptrace(PTRACE_PEEKUSER, proc->pid,
+				       PT_F8 + 0x8, 0);
+		return fpreg_to_double(&reg);
+	}
+
+	bsp = ptrace(PTRACE_PEEKUSER, proc->pid, PT_AR_BSP, 0);
+	cfm.value = ptrace(PTRACE_PEEKUSER, proc->pid, PT_CFM, 0);
+
+	/* The first 8 arguments are passed in regular registers
+	 * (counting from R32), unless they are floating point values
+	 * (the case in question here). In that case, up to the first
+	 * 8 regular registers are still "allocated" for each of the
+	 * first 8 parameters, but if a parameter is floating point,
+	 * then the register is left unset and the parameter is passed
+	 * in the first available floating-point register, counting
+	 * from F8.
+	 *
+	 * Take func(int a, float f, int b, double d), for example.
+	 *    a - passed in R32
+	 *    f - R33 left unset, value passed in F8
+	 *    b - passed in R34
+	 *    d - R35 left unset, value passed in F9
+	 *
+	 * ltrace handles this by counting floating point arguments
+	 * while parsing declarations. The "arg_num" in this routine
+	 * (which is only called for floating point values) really
+	 * means which floating point parameter we're looking for,
+	 * ignoring everything else.
+	 *
+	 * Following the first 8 arguments, the remaining arguments
+	 * are passed on the stack after a 16 byte scratch area
+	 */
+	if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) {
+		if (arg_num < 8) {
+			reg.u.bits[0] = ptrace(PTRACE_PEEKUSER, proc->pid,
+					       float_regs[arg_num], 0);
+			reg.u.bits[1] = ptrace(PTRACE_PEEKUSER, proc->pid,
+					       float_regs[arg_num] + 0x8, 0);
+			return fpreg_to_double(&reg);
+		} else {
+			unsigned long sp =
+			    ptrace(PTRACE_PEEKUSER, proc->pid, PT_R12, 0) + 16;
+			reg.u.bits[0] = ptrace(PTRACE_PEEKDATA, proc->pid,
+					       sp + (8 * (arg_num - 8)));
+			reg.u.bits[0] = ptrace(PTRACE_PEEKDATA, proc->pid,
+					       sp + (8 * (arg_num - 8)) + 0x8);
+			return fpreg_to_double(&reg);
+		}
+	}
+
+	/* error if we get here */
+	fprintf(stderr, "gimme_arg called with wrong arguments\n");
+	exit(1);
+}
+
+long gimme_arg(enum tof type, struct process *proc, arg_type_info *info)
+{
+	int arg_num = info->arg_num;
+	union {
+		long l;
+		float f;
+		double d;
+	} cvt;
+
+	if (info->type == ARGTYPE_FLOAT)
+		cvt.f = gimme_float_arg(type, proc, info->u.float_info.float_index);
+	else if (info->type == ARGTYPE_DOUBLE)
+		cvt.d = gimme_float_arg(type, proc, info->u.double_info.float_index);
+	else
+		cvt.l = gimme_long_arg(type, proc, arg_num);
+
+	return cvt.l;
+}
+
 void save_register_args(enum tof type, struct process *proc)
 {
 }

Modified: ltrace/trunk/sysdeps/linux-gnu/m68k/trace.c
===================================================================
--- ltrace/trunk/sysdeps/linux-gnu/m68k/trace.c	2006-09-14 23:57:49 UTC (rev 66)
+++ ltrace/trunk/sysdeps/linux-gnu/m68k/trace.c	2006-09-25 00:27:08 UTC (rev 67)
@@ -48,8 +48,10 @@
 	return 0;
 }
 
-long gimme_arg(enum tof type, struct process *proc, int arg_num)
+long gimme_arg(enum tof type, struct process *proc, arg_type_info *info)
 {
+	int arg_num = info->arg_num;
+
 	if (arg_num == -1) {	/* return value */
 		return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_D0, 0);
 	}

Modified: ltrace/trunk/sysdeps/linux-gnu/ppc/trace.c
===================================================================
--- ltrace/trunk/sysdeps/linux-gnu/ppc/trace.c	2006-09-14 23:57:49 UTC (rev 66)
+++ ltrace/trunk/sysdeps/linux-gnu/ppc/trace.c	2006-09-25 00:27:08 UTC (rev 67)
@@ -56,8 +56,10 @@
 	return 0;
 }
 
-long gimme_arg(enum tof type, struct process *proc, int arg_num)
+long gimme_arg(enum tof type, struct process *proc, arg_type_info *info)
 {
+	int arg_num = info->arg_num;
+
 	if (arg_num == -1) {	/* return value */
 		return ptrace(PTRACE_PEEKUSER, proc->pid, sizeof(long) * PT_R3,
 			      0);

Modified: ltrace/trunk/sysdeps/linux-gnu/s390/trace.c
===================================================================
--- ltrace/trunk/sysdeps/linux-gnu/s390/trace.c	2006-09-14 23:57:49 UTC (rev 66)
+++ ltrace/trunk/sysdeps/linux-gnu/s390/trace.c	2006-09-25 00:27:08 UTC (rev 67)
@@ -161,8 +161,9 @@
 	return 0;
 }
 
-long gimme_arg(enum tof type, struct process *proc, int arg_num)
+long gimme_arg(enum tof type, struct process *proc, arg_type_info *info)
 {
+	int arg_num = info->arg_num;
 	long ret;
 
 	switch (arg_num) {

Modified: ltrace/trunk/sysdeps/linux-gnu/sparc/trace.c
===================================================================
--- ltrace/trunk/sysdeps/linux-gnu/sparc/trace.c	2006-09-14 23:57:49 UTC (rev 66)
+++ ltrace/trunk/sysdeps/linux-gnu/sparc/trace.c	2006-09-25 00:27:08 UTC (rev 67)
@@ -48,8 +48,10 @@
 	return 0;
 }
 
-long gimme_arg(enum tof type, struct process *proc, int arg_num)
+long gimme_arg(enum tof type, struct process *proc, arg_type_info *info)
 {
+	int arg_num = info->arg_num;
+
 	proc_archdep *a = (proc_archdep *) proc->arch_ptr;
 	if (!a->valid) {
 		fprintf(stderr, "Could not get child registers\n");

Modified: ltrace/trunk/sysdeps/linux-gnu/x86_64/trace.c
===================================================================
--- ltrace/trunk/sysdeps/linux-gnu/x86_64/trace.c	2006-09-14 23:57:49 UTC (rev 66)
+++ ltrace/trunk/sysdeps/linux-gnu/x86_64/trace.c	2006-09-25 00:27:08 UTC (rev 67)
@@ -86,8 +86,10 @@
 	exit(1);
 }
 
-long gimme_arg(enum tof type, struct process *proc, int arg_num)
+long gimme_arg(enum tof type, struct process *proc, arg_type_info *info)
 {
+	int arg_num = info->arg_num;
+
 	if (proc->mask_32bit)
 		return (unsigned int)gimme_arg32(type, proc, arg_num);
 




More information about the Ltrace-devel mailing list