Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
DISCONTINUED:openSUSE:11.1:Update
ltrace
ltrace.trunk-r64.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File ltrace.trunk-r64.patch of Package ltrace
------------------------------------------------------------------------ r64 | ianw-guest | 2006-08-07 04:10:08 +0000 (Mon, 07 Aug 2006) | 2 lines Changed paths: M /ltrace/trunk/ChangeLog M /ltrace/trunk/display_args.c M /ltrace/trunk/etc/ltrace.conf M /ltrace/trunk/ltrace.h M /ltrace/trunk/read_config_file.c M /ltrace/trunk/testsuite/ltrace.main/parameters-lib.c M /ltrace/trunk/testsuite/ltrace.main/parameters.c M /ltrace/trunk/testsuite/ltrace.main/parameters.conf M /ltrace/trunk/testsuite/ltrace.main/parameters.exp add struct support ------------------------------------------------------------------------ --- ChangeLog | 12 +++ display_args.c | 83 +++++++++++++++++++----- etc/ltrace.conf | 40 +++++++++++ ltrace.h | 12 +++ read_config_file.c | 114 ++++++++++++++++++++++++++++++++- testsuite/ltrace.main/parameters-lib.c | 36 ++++++++++ testsuite/ltrace.main/parameters.c | 33 +++++++++ testsuite/ltrace.main/parameters.conf | 1 testsuite/ltrace.main/parameters.exp | 2 9 files changed, 315 insertions(+), 18 deletions(-) Index: read_config_file.c =================================================================== --- read_config_file.c.orig +++ read_config_file.c @@ -19,6 +19,8 @@ static arg_type_info *parse_type(char ** struct function *list_of_functions = NULL; +/* Map of strings to type names. These do not need to be in any + * particular order */ static struct list_of_pt_t { char *name; enum arg_type pt; @@ -39,11 +41,15 @@ static struct list_of_pt_t { "format", ARGTYPE_FORMAT}, { "string", ARGTYPE_STRING}, { "array", ARGTYPE_ARRAY}, { + "struct", ARGTYPE_STRUCT}, { "enum", ARGTYPE_ENUM}, { "ignore", ARGTYPE_IGNORE}, { NULL, ARGTYPE_UNKNOWN} /* Must finish with NULL */ }; +/* Array of singleton 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[] = { { ARGTYPE_VOID }, { ARGTYPE_INT }, @@ -62,6 +68,7 @@ static arg_type_info arg_type_singletons { ARGTYPE_STRING_N }, { ARGTYPE_ARRAY }, { ARGTYPE_ENUM }, + { ARGTYPE_STRUCT }, { ARGTYPE_IGNORE }, { ARGTYPE_POINTER }, { ARGTYPE_UNKNOWN } @@ -166,6 +173,7 @@ static int simple_type(enum arg_type at) case ARGTYPE_STRING_N: case ARGTYPE_ARRAY: case ARGTYPE_ENUM: + case ARGTYPE_STRUCT: return 0; default: @@ -178,8 +186,8 @@ static int parse_int(char **str) char *end; long n = strtol(*str, &end, 0); if (end == *str) { - output_line(0, "Syntax error in `%s', line %d: Bad number", - filename, line_no); + output_line(0, "Syntax error in `%s', line %d: Bad number (%s)", + filename, line_no, *str); error_count++; return 0; } @@ -209,6 +217,9 @@ static int parse_argnum(char **str) if (strncmp(*str, "arg", 3) == 0) { (*str) += 3; multiplier = -1; + } else if (strncmp(*str, "elt", 3) == 0) { + (*str) += 3; + multiplier = -1; } else if (strncmp(*str, "retval", 6) == 0) { (*str) += 6; return 0; @@ -289,6 +300,8 @@ static size_t arg_sizeof(arg_type_info * return sizeof(float); } 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_ARRAY) { if (arg->u.array_info.len_spec > 0) return arg->u.array_info.len_spec * arg->u.array_info.elt_size; @@ -299,6 +312,63 @@ 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) +{ + struct { + char c; + int i; + } ci; + struct { + struct { + char c; + } s; + int i; + } cis; + + size_t int_alignment = alignof(i, ci); + size_t whole_struct_alignment = alignof(i, cis); + + 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 + offset = 0; + for (i = 0; info->u.struct_info.fields[i] != NULL; i++) { + arg_type_info *field = info->u.struct_info.fields[i]; + 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; +} + static arg_type_info *parse_nonpointer_type(char **str) { arg_type_info *simple; @@ -432,6 +502,46 @@ static arg_type_info *parse_nonpointer_t (*str)++; // Skip past closing ] return info; + // Syntax: struct ( type,type,type,... ) + case ARGTYPE_STRUCT:{ + int field_num = 0; + (*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; + eat_spaces(str); // Empty arg list with whitespace inside + while (**str && **str != ')') { + if (field_num == MAX_ARGS) { + output_line(0, + "Error in `%s', line %d: Too many structure elements", + filename, line_no); + error_count++; + return NULL; + } + eat_spaces(str); + if (field_num != 0) { + (*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; + + // Must trim trailing spaces so the check for + // the closing paren is simple + eat_spaces(str); + } + (*str)++; // Get past closing paren + info->u.struct_info.fields[field_num] = NULL; + align_struct(info); + return info; + } + default: output_line(0, "Syntax error in `%s', line %d: Unknown type encountered", filename, line_no); Index: display_args.c =================================================================== --- display_args.c.orig +++ display_args.c @@ -15,27 +15,35 @@ static int display_char(int what); static int display_string(enum tof type, struct process *proc, void* addr, size_t maxlen); static int display_value(enum tof type, struct process *proc, - long value, arg_type_info *info); + long value, arg_type_info *info, + void *st, arg_type_info* st_info); static int display_unknown(enum tof type, struct process *proc, long value); static int display_format(enum tof type, struct process *proc, int arg_num); static int string_maxlength = INT_MAX; static int array_maxlength = INT_MAX; -static long get_length(enum tof type, struct process *proc, int len_spec) +static long get_length(enum tof type, struct process *proc, int len_spec, + void *st, arg_type_info* st_info) { + long len; 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); } static int display_ptrto(enum tof type, struct process *proc, long item, - arg_type_info * info) + arg_type_info * info, + void *st, arg_type_info* st_info) { arg_type_info temp; temp.type = ARGTYPE_POINTER; temp.u.ptr_info.info = info; - return display_value(type, proc, item, &temp); + return display_value(type, proc, item, &temp, st, st_info); } /* @@ -47,7 +55,8 @@ static int display_ptrto(enum tof type, * pointer to that region of memory. */ static int display_arrayptr(enum tof type, struct process *proc, - void *addr, arg_type_info * info) + void *addr, arg_type_info * info, + void *st, arg_type_info* st_info) { int len = 0; int i; @@ -56,7 +65,8 @@ static int display_arrayptr(enum tof typ if (addr == NULL) return fprintf(output, "NULL"); - array_len = get_length(type, proc, info->u.array_info.len_spec); + array_len = get_length(type, proc, info->u.array_info.len_spec, + st, st_info); len += fprintf(output, "[ "); for (i = 0; i < opt_A && i < array_maxlength && i < array_len; i++) { arg_type_info *elt_type = info->u.array_info.elt_type; @@ -66,7 +76,7 @@ static int display_arrayptr(enum tof typ if (opt_d) len += fprintf(output, "%p=", addr); len += - display_ptrto(type, proc, (long) addr, elt_type); + display_ptrto(type, proc, (long) addr, elt_type, st, st_info); addr += elt_size; } if (i < array_len) @@ -75,21 +85,57 @@ static int display_arrayptr(enum tof typ return len; } +/* addr - A pointer to the beginning of the memory region occupied by + * the struct (aka a pointer to the struct) + */ +static int display_structptr(enum tof type, struct process *proc, + void *addr, arg_type_info * info) +{ + int i; + arg_type_info *field; + int len = 0; + + if (addr == NULL) + return fprintf(output, "NULL"); + + len += fprintf(output, "{ "); + for (i = 0; (field = info->u.struct_info.fields[i]) != NULL; i++) { + if (i != 0) + len += fprintf(output, ", "); + if (opt_d) + len += + fprintf(output, "%p=", + addr + info->u.struct_info.offset[i]); + len += + display_ptrto(LT_TOF_STRUCT, proc, + (long) addr + info->u.struct_info.offset[i], + field, addr, info); + } + len += fprintf(output, " }"); + + return len; +} + static int display_pointer(enum tof type, struct process *proc, long value, - arg_type_info * info) + arg_type_info * info, + void *st, arg_type_info* st_info) { long pointed_to; arg_type_info *inner = info->u.ptr_info.info; if (inner->type == ARGTYPE_ARRAY) { - return display_arrayptr(type, proc, (void*) value, inner); + return display_arrayptr(type, proc, (void*) value, inner, + st, st_info); + } else if (inner->type == ARGTYPE_STRUCT) { + return display_structptr(type, proc, (void *) value, inner); } else { if (value == 0) return fprintf(output, "NULL"); else if (umovelong(proc, (void *) value, &pointed_to) < 0) return fprintf(output, "?"); else - return display_value(type, proc, pointed_to, inner); + return display_value(type, proc, pointed_to, inner, + st, st_info); } } @@ -110,9 +156,15 @@ static int display_enum(enum tof type, s proc - information about the traced process value - the value to display info - the description of the type to display + st - if the current value is a struct member, the address of the struct + st_info - type of the above struct + + Those last two parameters are used for structs containing arrays or + strings whose length is given by another structure element. */ int display_value(enum tof type, struct process *proc, - long value, arg_type_info *info) + long value, arg_type_info *info, + void *st, arg_type_info* st_info) { int tmp; @@ -165,13 +217,16 @@ int display_value(enum tof type, struct case ARGTYPE_STRING_N: return display_string(type, proc, (void*) value, get_length(type, proc, - info->u.string_n_info.size_spec)); + info->u.string_n_info.size_spec, st, st_info)); case ARGTYPE_ARRAY: return fprintf(output, "<array without address>"); case ARGTYPE_ENUM: return display_enum(type, proc, info, value); + case ARGTYPE_STRUCT: + return fprintf(output, "<struct without address>"); case ARGTYPE_POINTER: - return display_pointer(type, proc, value, info); + return display_pointer(type, proc, value, info, + st, st_info); case ARGTYPE_UNKNOWN: default: return display_unknown(type, proc, value); @@ -189,7 +244,7 @@ int display_arg(enum tof type, struct pr return display_format(type, proc, arg_num); } else { arg = gimme_arg(type, proc, arg_num); - return display_value(type, proc, arg, info); + return display_value(type, proc, arg, info, NULL, NULL); } } Index: ChangeLog =================================================================== --- ChangeLog.orig +++ ChangeLog @@ -1,5 +1,17 @@ 2006-08-07 Steve Fink <sphink@gmail.com> + * display_args.c, etc/ltrace.conf, ltrace.h, read_config_file.c, + testsuite/ltrace.main/parameters-lib.c, + testsuite/ltrace.main/parameters.c, + testsuite/ltrace.main/parameters.conf, + testsuite/ltrace.main/parameters.exp: Allow parameters to be + pointers to structs, which themselves can contain + (nearly) any other type, including other structs or pointers to + structs. + + +2006-08-07 Steve Fink <sphink@gmail.com> + * defs.h, display_args.c, etc/ltrace.conf, ltrace.1, ltrace.h, options.c, options.h, read_config_file.c, testsuite/ltrace.main/parameters-lib.c, Index: testsuite/ltrace.main/parameters.c =================================================================== --- testsuite/ltrace.main/parameters.c.orig +++ testsuite/ltrace.main/parameters.c @@ -24,6 +24,7 @@ void func_ushort(unsigned short, unsigne void func_float(float, float); void func_arrayi(int*, int); void func_arrayf(float*, int); +void func_struct(void*); typedef enum { RED, @@ -86,5 +87,37 @@ main () func_arrayf(af, 8); func_arrayf(af, 2); + { + struct { + int simple; + int alen; + int slen; + struct { int a; int b; }* array; + struct { int a; int b; } seq[3]; + char* str; + } x; + + x.simple = 89; + + x.alen = 2; + x.array = malloc(800); + x.array[0].a = 1; + x.array[0].b = 10; + x.array[1].a = 3; + x.array[1].b = 30; + + x.seq[0].a = 4; + x.seq[0].b = 40; + x.seq[1].a = 5; + x.seq[1].b = 50; + x.seq[2].a = 6; + x.seq[2].b = 60; + + x.slen = 3; + x.str = "123junk"; + + func_struct(&x); + } + return 0; } Index: testsuite/ltrace.main/parameters.conf =================================================================== --- testsuite/ltrace.main/parameters.conf.orig +++ testsuite/ltrace.main/parameters.conf @@ -13,3 +13,4 @@ typedef color = enum (RED=0,GREEN=1,BLUE void func_typedef(color) void func_arrayi(array(int,arg2)*,ignore) void func_arrayf(array(float,arg2)*,ignore) +void func_struct(struct(int,int,int,array(struct(int,int),elt2)*,array(struct(int,int),3),string[elt3])*) Index: testsuite/ltrace.main/parameters-lib.c =================================================================== --- testsuite/ltrace.main/parameters-lib.c.orig +++ testsuite/ltrace.main/parameters-lib.c @@ -79,3 +79,39 @@ void func_arrayf(float* a, int N) printf("%f ", a[i]); printf("\n"); } + +struct test_struct { + int simple; + int alen; + int slen; + struct { int a; int b; }* array; + struct { int a; int b; } seq[3]; + char* str; + char* outer_str; +}; + +void func_struct(struct test_struct* x) +{ + char buf[100]; + int i; + + printf("struct: "); + + printf("%d, [", x->simple); + for (i = 0; i < x->alen; i++) { + printf("%d/%d", x->array[i].a, x->array[i].b); + if (i < x->alen - 1) + printf(" "); + } + printf("] ["); + for (i = 0; i < 3; i++) { + printf("%d/%d", x->seq[i].a, x->seq[i].b); + if (i < 2) + printf(" "); + } + printf("] "); + + strncpy(buf, x->str, x->slen); + buf[x->slen] = '\0'; + printf("%s\n", buf); +} Index: testsuite/ltrace.main/parameters.exp =================================================================== --- testsuite/ltrace.main/parameters.exp.orig +++ testsuite/ltrace.main/parameters.exp @@ -70,3 +70,5 @@ set pattern "func_arrayf(. 10.10*, 11.10 ltrace_verify_output ${srcdir}/${subdir}/${testfile}.ltrace $pattern 1 set pattern "exited (status 0)" ltrace_verify_output ${srcdir}/${subdir}/${testfile}.ltrace $pattern 1 +set pattern "func_struct({ 89, 2, 3, . { 1, 10 }, { 3, 30 } ., . { 4, 40 }, { 5, 50 }, { 6, 60 } ., \\\"123\\\" })" +ltrace_verify_output ${srcdir}/${subdir}/${testfile}.ltrace $pattern 1 Index: ltrace.h =================================================================== --- ltrace.h.orig +++ ltrace.h @@ -47,6 +47,7 @@ enum arg_type { ARGTYPE_STRING_N, /* String of known maxlen */ ARGTYPE_ARRAY, /* Series of values in memory */ ARGTYPE_ENUM, /* Enumeration */ + ARGTYPE_STRUCT, /* Structure of values */ ARGTYPE_IGNORE, /* Leave parameter blank */ ARGTYPE_POINTER, /* Pointer to some other type */ ARGTYPE_COUNT /* number of ARGTYPE_* values */ @@ -74,6 +75,14 @@ typedef struct arg_type_info_t { int size_spec; } string_n_info; + // ARGTYPE_STRUCT + struct { + struct arg_type_info_t **fields; // NULL-terminated + size_t *gap; + size_t *offset; + size_t size; + } struct_info; + // ARGTYPE_POINTER struct { struct arg_type_info_t *info; @@ -86,7 +95,8 @@ enum tof { LT_TOF_FUNCTION, /* A real library function */ LT_TOF_FUNCTIONR, /* Return from a real library function */ LT_TOF_SYSCALL, /* A syscall */ - LT_TOF_SYSCALLR /* Return from a syscall */ + LT_TOF_SYSCALLR, /* Return from a syscall */ + LT_TOF_STRUCT /* Not a function; read args from struct */ }; struct function { Index: etc/ltrace.conf =================================================================== --- etc/ltrace.conf.orig +++ etc/ltrace.conf @@ -21,6 +21,7 @@ ; format == ((const char *), ...) [printf() like] [TODO] ; string == (char *) ; string[argN] == (char *) [N>0] [show only up to (arg N) bytes] +; string[eltN] == (char *) [N>0] [show only up to (elt N) bytes] ; string[retval] == (char *) [show only up to (return val) bytes] ; string[arg0] == (char *) [same as string[retval]] ; string[N] == (char *) [N>0] [show only up to N bytes] @@ -29,12 +30,18 @@ ; enum (key=value,key=value,...) [enumeration, see below] ; array(type,argN) ; == (type[SIZE]) [array of (arg N) elements] +; array(type,eltN) +; == (type[SIZE]) [array of (struct element N) elements] ; array(type,N) == (type[N]) [array of N elements] - +; struct(type,type,...) +; == (struct {...}) [struct of several types] +; ; Backwards-compatibility: ; string0 == (char *) [same as string[retval]] ; stringN == (char *) [N>0] [same as string[argN]] + + ; Typedefs ; ; To make it easier to specify argument lists, you can use 'typedef' @@ -56,6 +63,37 @@ ; NOTE: Uses of array(...) alone are very rare. You almost always ; want array(...)*. The exceptions are when you have a fixed-size ; array. +; +; Structs +; +; NOTE: Uses of struct(...) alone are very rare. You almost always +; want struct(...)* (a pointer to a struct) anyway. Most compilers +; pass structs as pointers anyway, and those that don't are not yet +; supported. The one time when you want to use a non-pointer +; struct(...) type are when you have an array of structs, or a struct +; containing another struct. +; +; For example, if you have +; struct s1 { +; int y_size; +; int * y; +; int z[3]; +; struct { char c; } a; +; struct { char c; } * b; +; } +; and a function +; void f(struct s1*) +; then the corresponding ltrace spec is +; void f(struct(int,array(int,elt0),array(int,3),struct(char),struct(char)*)*) +; which, formatted similarly to the C declaration, looks like +; void f(struct( +; int, +; array(int,elt0), +; array(int,3), +; struct(char), +; struct(char)* +; )* +; ) ; arpa/inet.h
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