Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Evergreen:11.1
ltrace
ltrace.trunk-r67.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File ltrace.trunk-r67.patch of Package ltrace
------------------------------------------------------------------------ r67 | ianw-guest | 2006-09-25 00:27:08 +0000 (Mon, 25 Sep 2006) | 3 lines Changed paths: M /ltrace/trunk/ChangeLog M /ltrace/trunk/display_args.c M /ltrace/trunk/ltrace.h M /ltrace/trunk/output.c M /ltrace/trunk/process_event.c M /ltrace/trunk/read_config_file.c M /ltrace/trunk/sysdeps/README M /ltrace/trunk/sysdeps/linux-gnu/alpha/trace.c M /ltrace/trunk/sysdeps/linux-gnu/arm/trace.c M /ltrace/trunk/sysdeps/linux-gnu/i386/trace.c M /ltrace/trunk/sysdeps/linux-gnu/ia64/trace.c M /ltrace/trunk/sysdeps/linux-gnu/m68k/trace.c M /ltrace/trunk/sysdeps/linux-gnu/ppc/trace.c M /ltrace/trunk/sysdeps/linux-gnu/s390/trace.c M /ltrace/trunk/sysdeps/linux-gnu/sparc/trace.c M /ltrace/trunk/sysdeps/linux-gnu/x86_64/trace.c Large IA64 fix, many thanks to Steve Fink ------------------------------------------------------------------------ Index: read_config_file.c =================================================================== --- read_config_file.c (revision 66) +++ read_config_file.c (revision 67) @@ -36,6 +36,7 @@ static struct list_of_pt_t { "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 @@ static struct list_of_pt_t { 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 @@ static arg_type_info arg_type_singletons { ARGTYPE_SHORT }, { ARGTYPE_USHORT }, { ARGTYPE_FLOAT }, + { ARGTYPE_DOUBLE }, { ARGTYPE_ADDR }, { ARGTYPE_FILE }, { ARGTYPE_FORMAT }, @@ -74,12 +76,12 @@ static arg_type_info arg_type_singletons { 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 @@ static arg_type_info *str2type(char **st 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 @@ static char *start_of_arg_sig(char *str) 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 @@ static size_t arg_sizeof(arg_type_info * 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,58 +299,84 @@ static size_t arg_sizeof(arg_type_info * } } -/* 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; + + 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; - size_t int_alignment = alignof(i, ci); - size_t whole_struct_alignment = alignof(i, cis); + 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 @@ static arg_type_info *parse_nonpointer_t 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 @@ static arg_type_info *parse_nonpointer_t 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 @@ static arg_type_info *parse_nonpointer_t (*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 @@ static arg_type_info *parse_nonpointer_t (*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 @@ static arg_type_info *parse_nonpointer_t } 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 @@ static struct function *process_line(cha 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 @@ static struct function *process_line(cha 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 @@ static struct function *process_line(cha 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++; Index: output.c =================================================================== --- output.c (revision 66) +++ output.c (revision 67) @@ -166,7 +166,7 @@ void output_left(enum tof type, struct p 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 @@ void output_left(enum tof type, struct p 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 @@ void output_right(enum tof type, struct 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 @@ void output_right(enum tof type, struct } 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 @@ void output_right(enum tof type, struct 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) { Index: display_args.c =================================================================== --- display_args.c (revision 66) +++ display_args.c (revision 67) @@ -27,13 +27,18 @@ static long get_length(enum tof type, st 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 @@ int display_value(enum tof type, struct 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_value(enum tof type, struct } } -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 @@ static int display_format(enum tof type, 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 @@ static int display_format(enum tof type, 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 @@ static int display_format(enum tof type, 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)); } } } Index: ChangeLog =================================================================== --- ChangeLog (revision 66) +++ ChangeLog (revision 67) @@ -1,3 +1,22 @@ +2006-09-18 Steve Fink <sphink@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@suse.de> * Makefile.in : allow installation as non-root user, print out Index: sysdeps/linux-gnu/arm/trace.c =================================================================== --- sysdeps/linux-gnu/arm/trace.c (revision 66) +++ sysdeps/linux-gnu/arm/trace.c (revision 67) @@ -51,8 +51,10 @@ int syscall_p(struct process *proc, int 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); } Index: sysdeps/linux-gnu/ppc/trace.c =================================================================== --- sysdeps/linux-gnu/ppc/trace.c (revision 66) +++ sysdeps/linux-gnu/ppc/trace.c (revision 67) @@ -56,8 +56,10 @@ int syscall_p(struct process *proc, int 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); Index: sysdeps/linux-gnu/m68k/trace.c =================================================================== --- sysdeps/linux-gnu/m68k/trace.c (revision 66) +++ sysdeps/linux-gnu/m68k/trace.c (revision 67) @@ -48,8 +48,10 @@ int syscall_p(struct process *proc, int 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); } Index: sysdeps/linux-gnu/alpha/trace.c =================================================================== --- sysdeps/linux-gnu/alpha/trace.c (revision 66) +++ sysdeps/linux-gnu/alpha/trace.c (revision 67) @@ -47,8 +47,10 @@ int syscall_p(struct process *proc, int 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); } Index: sysdeps/linux-gnu/i386/trace.c =================================================================== --- sysdeps/linux-gnu/i386/trace.c (revision 66) +++ sysdeps/linux-gnu/i386/trace.c (revision 67) @@ -43,8 +43,10 @@ int syscall_p(struct process *proc, int 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); } Index: sysdeps/linux-gnu/s390/trace.c =================================================================== --- sysdeps/linux-gnu/s390/trace.c (revision 66) +++ sysdeps/linux-gnu/s390/trace.c (revision 67) @@ -161,8 +161,9 @@ int syscall_p(struct process *proc, int 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) { Index: sysdeps/linux-gnu/x86_64/trace.c =================================================================== --- sysdeps/linux-gnu/x86_64/trace.c (revision 66) +++ sysdeps/linux-gnu/x86_64/trace.c (revision 67) @@ -86,8 +86,10 @@ gimme_arg32(enum tof type, struct proces 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); Index: sysdeps/linux-gnu/ia64/trace.c =================================================================== --- sysdeps/linux-gnu/ia64/trace.c (revision 66) +++ sysdeps/linux-gnu/ia64/trace.c (revision 67) @@ -34,6 +34,18 @@ union bundle_t { 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 @@ int syscall_p(struct process *proc, int 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 @@ long gimme_arg(enum tof type, struct pro /* 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 @@ long gimme_arg(enum tof type, struct pro 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 @@ long gimme_arg(enum tof type, struct pro 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(®); + } + + 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(®); + } 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(®); + } + } + + /* 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) { } Index: sysdeps/linux-gnu/sparc/trace.c =================================================================== --- sysdeps/linux-gnu/sparc/trace.c (revision 66) +++ sysdeps/linux-gnu/sparc/trace.c (revision 67) @@ -48,8 +48,10 @@ int syscall_p(struct process *proc, int 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"); Index: sysdeps/README =================================================================== --- sysdeps/README (revision 66) +++ sysdeps/README (revision 67) @@ -22,7 +22,7 @@ int syscall_p(struct process * proc, int 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); Index: ltrace.h =================================================================== --- ltrace.h (revision 66) +++ ltrace.h (revision 67) @@ -39,7 +39,8 @@ enum arg_type { 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 @@ enum arg_type { typedef struct arg_type_info_t { enum arg_type type; + int arg_num; union { // ARGTYPE_ENUM struct { @@ -78,7 +80,6 @@ typedef struct arg_type_info_t { // 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 @@ typedef struct arg_type_info_t { 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 void *instruction_pointer; 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 void reinitialize_breakpoints(str 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_signal(pid_t 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); Index: process_event.c =================================================================== --- process_event.c (revision 66) +++ process_event.c (revision 67) @@ -225,8 +225,11 @@ static void process_sysret(struct event } 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 @@ static void process_sysret(struct event 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_sysret(struct event 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,
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor