aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Fink <sphink@gmail.com>2006-08-07 04:29:06 +0200
committerIan Wienand <ianw@debian.org>2006-08-07 04:29:06 +0200
commit6a48a6d7f428cd7f0796477a3892603a83fcce99 (patch)
treeb223635601c7b849dc194b43d63078115dc6607f
parentb0315a0acbd219de2c7f02228d7fda5c14fb47ef (diff)
downloadltrace-6a48a6d7f428cd7f0796477a3892603a83fcce99.tar.gz
implement string[argN] and string[N] parameter descriptors
-rw-r--r--ChangeLog5
-rw-r--r--display_args.c68
-rw-r--r--etc/ltrace.conf11
-rw-r--r--ltrace.h10
-rw-r--r--read_config_file.c88
5 files changed, 120 insertions, 62 deletions
diff --git a/ChangeLog b/ChangeLog
index 580343f..86e5835 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
2006-08-07 Steve Fink <sphink@gmail.com>
+ * 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 <sphink@gmail.com>
+
* ltrace.h, output.c, read_config_file.c : use arg_type_info in
place of arg_type in order to eventually be able to record
properties along with types.
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;
}