From 6a48a6d7f428cd7f0796477a3892603a83fcce99 Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Mon, 7 Aug 2006 04:29:06 +0200 Subject: implement string[argN] and string[N] parameter descriptors --- ChangeLog | 5 ++++ display_args.c | 68 +++++++++++++++++++---------------------- etc/ltrace.conf | 11 +++++-- ltrace.h | 10 ++----- read_config_file.c | 88 ++++++++++++++++++++++++++++++++++++++++++++---------- 5 files changed, 120 insertions(+), 62 deletions(-) diff --git a/ChangeLog b/ChangeLog index 580343f..86e5835 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2006-08-07 Steve Fink + + * display_args.c, etc/ltrace.conf, ltrace.h, read_config_file.c: + implement string[argN] and string[N] parameter descriptors + 2006-08-07 Steve Fink * ltrace.h, output.c, read_config_file.c : use arg_type_info in diff --git a/display_args.c b/display_args.c index 083c9dc..1c15f22 100644 --- a/display_args.c +++ b/display_args.c @@ -11,19 +11,29 @@ #include "options.h" static int display_char(int what); -static int display_string(enum tof type, struct process *proc, int arg_num); -static int display_stringN(int arg2, enum tof type, struct process *proc, - int arg_num); +static int display_string(enum tof type, struct process *proc, + int arg_num, arg_type_info *info, + size_t maxlen); static int display_unknown(enum tof type, struct process *proc, int arg_num); static int display_format(enum tof type, struct process *proc, int arg_num); +static int string_maxlength = INT_MAX; + +static long get_length(enum tof type, struct process *proc, int len_spec) +{ + if (len_spec > 0) + return len_spec; + return gimme_arg(type, proc, -len_spec - 1); +} + int -display_arg(enum tof type, struct process *proc, int arg_num, enum arg_type at) +display_arg(enum tof type, struct process *proc, + int arg_num, arg_type_info *info) { int tmp; long arg; - switch (at) { + switch (info->type) { case ARGTYPE_VOID: return 0; case ARGTYPE_INT: @@ -62,19 +72,12 @@ display_arg(enum tof type, struct process *proc, int arg_num, enum arg_type at) case ARGTYPE_FORMAT: return display_format(type, proc, arg_num); case ARGTYPE_STRING: - return display_string(type, proc, arg_num); - case ARGTYPE_STRING0: - return display_stringN(0, type, proc, arg_num); - case ARGTYPE_STRING1: - return display_stringN(1, type, proc, arg_num); - case ARGTYPE_STRING2: - return display_stringN(2, type, proc, arg_num); - case ARGTYPE_STRING3: - return display_stringN(3, type, proc, arg_num); - case ARGTYPE_STRING4: - return display_stringN(4, type, proc, arg_num); - case ARGTYPE_STRING5: - return display_stringN(5, type, proc, arg_num); + return display_string(type, proc, arg_num, info, + string_maxlength); + case ARGTYPE_STRING_N: + return display_string(type, proc, arg_num, info, + get_length(type, proc, + info->u.string_n_info.size_spec)); case ARGTYPE_UNKNOWN: default: return display_unknown(type, proc, arg_num); @@ -106,11 +109,10 @@ static int display_char(int what) } } -static int string_maxlength = INT_MAX; - #define MIN(a,b) (((a)<(b)) ? (a) : (b)) -static int display_string(enum tof type, struct process *proc, int arg_num) +static int display_string(enum tof type, struct process *proc, + int arg_num, arg_type_info *info, size_t maxlength) { void *addr; unsigned char *str1; @@ -122,13 +124,13 @@ static int display_string(enum tof type, struct process *proc, int arg_num) return fprintf(output, "NULL"); } - str1 = malloc(MIN(opt_s, string_maxlength) + 3); + str1 = malloc(MIN(opt_s, maxlength) + 3); if (!str1) { return fprintf(output, "???"); } - umovestr(proc, addr, MIN(opt_s, string_maxlength) + 1, str1); + umovestr(proc, addr, MIN(opt_s, maxlength) + 1, str1); len = fprintf(output, "\""); - for (i = 0; i < MIN(opt_s, string_maxlength); i++) { + for (i = 0; i < MIN(opt_s, maxlength); i++) { if (str1[i]) { len += display_char(str1[i]); } else { @@ -136,24 +138,13 @@ static int display_string(enum tof type, struct process *proc, int arg_num) } } len += fprintf(output, "\""); - if (str1[i] && (opt_s <= string_maxlength)) { + if (str1[i] && (opt_s <= maxlength)) { len += fprintf(output, "..."); } free(str1); return len; } -static int -display_stringN(int arg2, enum tof type, struct process *proc, int arg_num) -{ - int a; - - string_maxlength = gimme_arg(type, proc, arg2 - 1); - a = display_string(type, proc, arg_num); - string_maxlength = INT_MAX; - return a; -} - static int display_unknown(enum tof type, struct process *proc, int arg_num) { long tmp; @@ -292,10 +283,13 @@ static int display_format(enum tof type, struct process *proc, int arg_num) len += fprintf(output, "'"); break; } else if (c == 's') { + arg_type_info *info = + lookup_singleton(ARGTYPE_STRING); len += fprintf(output, ", "); len += display_string(type, proc, - ++arg_num); + ++arg_num, info, + string_maxlength); break; } else if (c == 'p' || c == 'n') { len += diff --git a/etc/ltrace.conf b/etc/ltrace.conf index 5c85e19..29c50ec 100644 --- a/etc/ltrace.conf +++ b/etc/ltrace.conf @@ -18,7 +18,14 @@ ; file == (FILE *) [TODO] ; format == ((const char *), ...) [printf() like] [TODO] ; string == (char *) -; stringN == (char *) [N>=0] [show only up to (arg N) bytes] +; string[argN] == (char *) [N>0] [show only up to (arg 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] + +; Backwards-compatibility: +; string0 == (char *) [same as string[retval]] +; stringN == (char *) [N>0] [same as string[argN]] ; arpa/inet.h int inet_aton(string,addr); @@ -338,7 +345,7 @@ int getpgid(int); int isatty(int); int link(string,string); int mkdir(string,octal); -long read(int, +string0, ulong); +long read(int, +string[retval], ulong); int rmdir(string); int seteuid(uint); int setgid(int); diff --git a/ltrace.h b/ltrace.h index 5561139..dec2e0b 100644 --- a/ltrace.h +++ b/ltrace.h @@ -40,14 +40,8 @@ enum arg_type { ARGTYPE_ADDR, ARGTYPE_FILE, ARGTYPE_FORMAT, /* printf-like format */ - ARGTYPE_STRING, - ARGTYPE_STRING_N, /* stringN: string up to (arg N) bytes */ - ARGTYPE_STRING0, - ARGTYPE_STRING1, - ARGTYPE_STRING2, - ARGTYPE_STRING3, - ARGTYPE_STRING4, - ARGTYPE_STRING5, + ARGTYPE_STRING, /* NUL-terminated string */ + ARGTYPE_STRING_N, /* String of known maxlen */ ARGTYPE_COUNT /* number of ARGTYPE_* values */ }; diff --git a/read_config_file.c b/read_config_file.c index 089d69a..6c9eb5d 100644 --- a/read_config_file.c +++ b/read_config_file.c @@ -29,12 +29,6 @@ static struct list_of_pt_t { "file", ARGTYPE_FILE}, { "format", ARGTYPE_FORMAT}, { "string", ARGTYPE_STRING}, { - "string0", ARGTYPE_STRING0}, { - "string1", ARGTYPE_STRING1}, { - "string2", ARGTYPE_STRING2}, { - "string3", ARGTYPE_STRING3}, { - "string4", ARGTYPE_STRING4}, { - "string5", ARGTYPE_STRING5}, { NULL, ARGTYPE_UNKNOWN} /* Must finish with NULL */ }; @@ -51,12 +45,6 @@ static arg_type_info arg_type_singletons[] = { { ARGTYPE_FORMAT }, { ARGTYPE_STRING }, { ARGTYPE_STRING_N }, - { ARGTYPE_STRING0 }, - { ARGTYPE_STRING1 }, - { ARGTYPE_STRING2 }, - { ARGTYPE_STRING3 }, - { ARGTYPE_STRING4 }, - { ARGTYPE_STRING5 }, { ARGTYPE_UNKNOWN } }; @@ -74,7 +62,7 @@ static arg_type_info *str2type(char **str) while (tmp->name) { if (!strncmp(*str, tmp->name, strlen(tmp->name)) - && index(" ,)#", *(*str + strlen(tmp->name)))) { + && index(" ,()#;012345[", *(*str + strlen(tmp->name)))) { *str += strlen(tmp->name); return lookup_singleton(tmp->pt); } @@ -134,6 +122,51 @@ static int simple_type(enum arg_type at) static int line_no; static char *filename; +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); + return 0; + } + + *str = end; + return n; +} + +/* + * Input: + * argN : The value of argument #N, counting from 1 (arg0 = retval) + * eltN : The value of element #N of the containing structure + * retval : The return value + * 0 : Error + * N : The numeric value N, if N > 0 + * + * Output: + * > 0 actual numeric value + * = 0 return value + * < 0 (arg -n), counting from one + */ +static int parse_argnum(char **str) +{ + int multiplier = 1; + int n = 0; + + if (strncmp(*str, "arg", 3) == 0) { + (*str) += 3; + multiplier = -1; + } else if (strncmp(*str, "retval", 6) == 0) { + (*str) += 6; + return 0; + } + + n = parse_int(str); + + return n * multiplier; +} + static arg_type_info *parse_type(char **str) { arg_type_info *simple; @@ -144,7 +177,7 @@ static arg_type_info *parse_type(char **str) return simple; // UNKNOWN } - if (simple_type(simple->type)) + if (simple_type(simple->type) && simple->type != ARGTYPE_STRING) return simple; info = malloc(sizeof(*info)); @@ -154,6 +187,29 @@ static arg_type_info *parse_type(char **str) switch statement. */ switch (info->type) { + + case ARGTYPE_STRING: + if (!isdigit(**str) && **str != '[') { + /* Oops, was just a simple string after all */ + free(info); + return simple; + } + + info->type = ARGTYPE_STRING_N; + + /* Backwards compatibility for string0, string1, ... */ + if (isdigit(**str)) { + info->u.string_n_info.size_spec = -parse_int(str); + return info; + } + + (*str)++; // Skip past opening [ + eat_spaces(str); + info->u.string_n_info.size_spec = parse_argnum(str); + eat_spaces(str); + (*str)++; // Skip past closing ] + return info; + default: output_line(0, "Syntax error in `%s', line %d: Unknown type encountered", filename, line_no); @@ -174,7 +230,9 @@ static struct function *process_line(char *buf) debug(3, "Reading line %d of `%s'", line_no, filename); eat_spaces(&str); fun.return_info = parse_type(&str); - if (fun.return_info == NULL) { + if (fun.return_info == NULL) + return NULL; + if (fun.return_info->type == ARGTYPE_UNKNOWN) { debug(3, " Skipping line %d", line_no); return NULL; } -- cgit v1.2.3