[Ltrace-devel] [PATCH 1/11] arg_type_info

Steve Fink sphink at gmail.com
Sat Aug 5 23:54:06 UTC 2006


I sent a new batch of patches a while back, but they got eaten by the
moderator (too big). Since the moderator doesn't seem in much danger
of getting indigestion and spitting them back up to this list anytime
soon, I guess I'll send each patch individually.

Lemme dig out that message...

On 7/26/06, Petr Machata <pmachata at redhat.com> wrote:
> I've looked at the patches today.  They are pretty generic code, so I've
> just gave it a shot on i686. Just nitpicking:
> * patches 1 and 4 lack ChangeLog entry.

Oh, right. I wasn't sure if the ChangeLog was only for user-visible
changes or not, and was inconsistent about updating it.

> * last hunk of patch 5 should be moved to patch 4, otherwise you are
> doing changes before you adjust what calls the changed code

Ouch. You're right.

> * patch 5 contains new files (parameters.c, parameters-lib.c) that fail
> to compile, and testsuite won't pass. The fix is trivial.

Odd. They compile for me, but it makes sense that your change would be
needed. Hopefully I didn't screw it up in my latest round of patches.

> I'm attaching modified patches 4 and 5, should they come in handy.
> Didn't add ChangeLog entries though.

Thanks. I added ChangeLog entries and your changes and regenerated the
whole batch of patches. I also tacked on the rest of the changes that
I've had backed up, which add pointers to arrays and structs. The
struct patch is pretty much guaranteed to be somewhat nonportable
because of alignment issues, but I wanted to get it out here for
discussion.

Oh, I also switched the way I added ChangeLog entries midway through
this series, because it was looking rather verbose with a separate
change section per patch. The latter half are all aggregated under one
change heading. I'm not sure what the preferred style is.

Finally, I tacked on a patch to change the man page to say that bugs
should be sent to this mailing list. It previously said to send them
to the author, and gives Juan Cespedes' email address. That clearly
seems wrong, but I don't know if the mailing list is what it should be
changed to or not.

I'm afraid I'm going to be lazy and attach the raw, git-generated
patch messages instead of editing them nicely.

[only now I'm going to send each as a separate message because the
mailing list choked on the size.]
-------------- next part --------------
From e3dcba8aa67ef060b4de9de644ce04ac01d0a1b7 Mon Sep 17 00:00:00 2001
From: Steve Fink sphink at gmail.com <sphink at gmail.com>
Date: Thu, 27 Jul 2006 07:58:50 -0700
Subject: [PATCH 1/11] expand parameter information from arg_type to arg_type_info

Switch to using arg_type_info so that we can record additional
information about types other than their names. This has no effect
right now, but is the necessary support for things like enumerations,
typedefs, strings that take their length from any argument, etc.
---
 ChangeLog          |    7 +++
 ltrace.h           |   31 +++++++++++----
 output.c           |   24 +++++++-----
 read_config_file.c |  105 ++++++++++++++++++++++++++++++++++++++++------------
 4 files changed, 125 insertions(+), 42 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b89fbe0..f23e7cd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2006-07-27    Steve Fink <sphink at gmail.com>
+
+	* 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.
+	* output.c: switch to using arg_type_info in output routines
+
 2006-07-18  Petr Machata <pmachata at redhat.com>
 
 	* elf.c: replace nonexistant elf_plt2addr with opd2addr, fix
diff --git a/ltrace.h b/ltrace.h
index 460167e..5561139 100644
--- a/ltrace.h
+++ b/ltrace.h
@@ -41,14 +41,26 @@ enum arg_type {
 	ARGTYPE_FILE,
 	ARGTYPE_FORMAT,		/* printf-like format */
 	ARGTYPE_STRING,
-	ARGTYPE_STRING0,	/* stringN: string up to (arg N) bytes */
-	ARGTYPE_STRING1,
-	ARGTYPE_STRING2,
-	ARGTYPE_STRING3,
-	ARGTYPE_STRING4,
-	ARGTYPE_STRING5
+	ARGTYPE_STRING_N,	/* stringN: string up to (arg N) bytes */
+        ARGTYPE_STRING0,
+        ARGTYPE_STRING1,
+        ARGTYPE_STRING2,
+        ARGTYPE_STRING3,
+        ARGTYPE_STRING4,
+        ARGTYPE_STRING5,
+        ARGTYPE_COUNT		/* number of ARGTYPE_* values */
 };
 
+typedef struct arg_type_info_t {
+    enum arg_type type;
+    union {
+	// ARGTYPE_STRING_N
+	struct {
+	    int size_spec;
+	} string_n_info;
+    } u;
+} arg_type_info;
+
 enum tof {
 	LT_TOF_NONE = 0,
 	LT_TOF_FUNCTION,	/* A real library function */
@@ -59,9 +71,9 @@ enum tof {
 
 struct function {
 	const char *name;
-	enum arg_type return_type;
+	arg_type_info *return_info;
 	int num_params;
-	enum arg_type arg_types[MAX_ARGS];
+	arg_type_info *arg_info[MAX_ARGS];
 	int params_right;
 	struct function *next;
 };
@@ -160,7 +172,7 @@ extern struct event *wait_for_something(
 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,
-		       enum arg_type at);
+		       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,
@@ -173,6 +185,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);
 
 /* Arch-dependent stuff: */
 extern char *pid2name(pid_t pid);
diff --git a/output.c b/output.c
index 200126b..59c0807 100644
--- a/output.c
+++ b/output.c
@@ -164,6 +164,9 @@ static void tabto(int col)
 void output_left(enum tof type, struct process *proc, char *function_name)
 {
 	struct function *func;
+	static arg_type_info *arg_unknown = NULL;
+	if (arg_unknown == NULL)
+	    arg_unknown = lookup_singleton(ARGTYPE_UNKNOWN);
 
 	if (opt_c) {
 		return;
@@ -190,21 +193,21 @@ #endif
 		int i;
 		for (i = 0; i < 4; i++) {
 			current_column +=
-			    display_arg(type, proc, i, ARGTYPE_UNKNOWN);
+			    display_arg(type, proc, i, arg_unknown);
 			current_column += fprintf(output, ", ");
 		}
-		current_column += display_arg(type, proc, 4, ARGTYPE_UNKNOWN);
+		current_column += display_arg(type, proc, 4, arg_unknown);
 		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_types[i]);
+			    display_arg(type, proc, i, func->arg_info[i]);
 			current_column += fprintf(output, ", ");
 		}
 		if (func->num_params > func->params_right) {
 			current_column +=
-			    display_arg(type, proc, i, func->arg_types[i]);
+			    display_arg(type, proc, i, func->arg_info[i]);
 			if (func->params_right) {
 				current_column += fprintf(output, ", ");
 			}
@@ -218,6 +221,9 @@ #endif
 void output_right(enum tof type, struct process *proc, char *function_name)
 {
 	struct function *func = name2func(function_name);
+	static arg_type_info *arg_unknown = NULL;
+	if (arg_unknown == NULL)
+	    arg_unknown = lookup_singleton(ARGTYPE_UNKNOWN);
 
 	if (opt_c) {
 		struct opt_c_struct *st;
@@ -273,26 +279,26 @@ #endif
 		current_column += fprintf(output, ") ");
 		tabto(opt_a - 1);
 		fprintf(output, "= ");
-		display_arg(type, proc, -1, ARGTYPE_UNKNOWN);
+		display_arg(type, proc, -1, arg_unknown);
 	} 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_types[i]);
+			    display_arg(type, proc, i, func->arg_info[i]);
 			current_column += fprintf(output, ", ");
 		}
 		if (func->params_right) {
 			current_column +=
-			    display_arg(type, proc, i, func->arg_types[i]);
+			    display_arg(type, proc, i, func->arg_info[i]);
 		}
 		current_column += fprintf(output, ") ");
 		tabto(opt_a - 1);
 		fprintf(output, "= ");
-		if (func->return_type == ARGTYPE_VOID) {
+		if (func->return_info->type == ARGTYPE_VOID) {
 			fprintf(output, "<void>");
 		} else {
-			display_arg(type, proc, -1, func->return_type);
+			display_arg(type, proc, -1, func->return_info);
 		}
 	}
 	if (opt_T) {
diff --git a/read_config_file.c b/read_config_file.c
index 2c54f44..089d69a 100644
--- a/read_config_file.c
+++ b/read_config_file.c
@@ -11,19 +11,6 @@ #include "read_config_file.h"
 #include "output.h"
 #include "debug.h"
 
-/*
- *	"void"		ARGTYPE_VOID
- *	"int"		ARGTYPE_INT
- *	"uint"		ARGTYPE_UINT
- *	"long"		ARGTYPE_LONG
- *	"ulong"		ARGTYPE_ULONG
- *	"octal"		ARGTYPE_OCTAL
- *	"char"		ARGTYPE_CHAR
- *	"string"	ARGTYPE_STRING
- *	"format"	ARGTYPE_FORMAT
- *	"addr"		ARGTYPE_ADDR
- */
-
 struct function *list_of_functions = NULL;
 
 static struct list_of_pt_t {
@@ -51,7 +38,37 @@ static struct list_of_pt_t {
 	NULL, ARGTYPE_UNKNOWN}	/* Must finish with NULL */
 };
 
-static enum arg_type str2type(char **str)
+static arg_type_info arg_type_singletons[] = {
+	{ ARGTYPE_VOID },
+	{ ARGTYPE_INT },
+	{ ARGTYPE_UINT },
+	{ ARGTYPE_LONG },
+	{ ARGTYPE_ULONG },
+	{ ARGTYPE_OCTAL },
+	{ ARGTYPE_CHAR },
+	{ ARGTYPE_ADDR },
+	{ ARGTYPE_FILE },
+	{ ARGTYPE_FORMAT },
+	{ ARGTYPE_STRING },
+	{ ARGTYPE_STRING_N },
+	{ ARGTYPE_STRING0 },
+	{ ARGTYPE_STRING1 },
+	{ ARGTYPE_STRING2 },
+	{ ARGTYPE_STRING3 },
+	{ ARGTYPE_STRING4 },
+	{ ARGTYPE_STRING5 },
+	{ ARGTYPE_UNKNOWN }
+};
+
+arg_type_info *lookup_singleton(enum arg_type at)
+{
+	if (at >= 0 && at <= ARGTYPE_COUNT)
+		return &arg_type_singletons[at];
+	else
+		return &arg_type_singletons[ARGTYPE_COUNT]; /* UNKNOWN */
+}
+
+static arg_type_info *str2type(char **str)
 {
 	struct list_of_pt_t *tmp = &list_of_pt[0];
 
@@ -59,11 +76,11 @@ static enum arg_type str2type(char **str
 		if (!strncmp(*str, tmp->name, strlen(tmp->name))
 		    && index(" ,)#", *(*str + strlen(tmp->name)))) {
 			*str += strlen(tmp->name);
-			return tmp->pt;
+			return lookup_singleton(tmp->pt);
 		}
 		tmp++;
 	}
-	return ARGTYPE_UNKNOWN;
+	return lookup_singleton(ARGTYPE_UNKNOWN);
 }
 
 static void eat_spaces(char **str)
@@ -105,9 +122,46 @@ 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)
+{
+	return 1;
+}
+
 static int line_no;
 static char *filename;
 
+static arg_type_info *parse_type(char **str)
+{
+	arg_type_info *simple;
+	arg_type_info *info;
+
+	simple = str2type(str);
+	if (simple->type == ARGTYPE_UNKNOWN) {
+		return simple;		// UNKNOWN
+	}
+
+	if (simple_type(simple->type))
+		return simple;
+
+	info = malloc(sizeof(*info));
+	info->type = simple->type;
+
+	/* Code to parse parameterized types will go into the following
+	   switch statement. */
+
+	switch (info->type) {
+	default:
+		output_line(0, "Syntax error in `%s', line %d: Unknown type encountered",
+			    filename, line_no);
+		free(info);
+		return NULL;
+	}
+}
+
 static struct function *process_line(char *buf)
 {
 	struct function fun;
@@ -119,12 +173,12 @@ static struct function *process_line(cha
 	line_no++;
 	debug(3, "Reading line %d of `%s'", line_no, filename);
 	eat_spaces(&str);
-	fun.return_type = str2type(&str);
-	if (fun.return_type == ARGTYPE_UNKNOWN) {
+	fun.return_info = parse_type(&str);
+	if (fun.return_info == NULL) {
 		debug(3, " Skipping line %d", line_no);
 		return NULL;
 	}
-	debug(4, " return_type = %d", fun.return_type);
+	debug(4, " return_type = %d", fun.return_info->type);
 	eat_spaces(&str);
 	tmp = start_of_arg_sig(str);
 	if (!tmp) {
@@ -148,9 +202,10 @@ static struct function *process_line(cha
 		} else if (fun.params_right) {
 			fun.params_right++;
 		}
-		fun.arg_types[i] = str2type(&str);
-		if (fun.return_type == ARGTYPE_UNKNOWN) {
-			output_line(0, "Syntax error in `%s', line %d",
+		fun.arg_info[i] = parse_type(&str);
+		if (fun.arg_info[i] == NULL) {
+			output_line(0, "Syntax error in `%s', line %d"
+                                    ": unknown argument type",
 				    filename, line_no);
 			return NULL;
 		}
@@ -161,8 +216,10 @@ static struct function *process_line(cha
 		} else if (*str == ')') {
 			continue;
 		} else {
-			output_line(0, "Syntax error in `%s', line %d",
-				    filename, line_no);
+			if (str[strlen(str) - 1] == '\n')
+				str[strlen(str) - 1] = '\0';
+			output_line(0, "Syntax error in `%s', line %d at ...\"%s\"",
+				    filename, line_no, str);
 			return NULL;
 		}
 	}
-- 
1.4.1


More information about the Ltrace-devel mailing list