fully decode the query_module syscall
diff --git a/bjm.c b/bjm.c
index cf7f4e8..76139b5 100644
--- a/bjm.c
+++ b/bjm.c
@@ -13,10 +13,6 @@
 #include <signal.h>
 #include <linux/module.h>
 
-/* WTA: #define these here: since Debian uses glibc2's includefiles
- * instead of the kernel includes we miss these otherwise.
- */
-
 #if !defined(QM_MODULES)
 #define QM_MODULES	1
 #define QM_DEPS		2
@@ -26,15 +22,47 @@
 #endif
 
 static struct xlat which[] = {
-	{ 0,			"0"				},
+	{ 0,		"0"		},
 	{ QM_MODULES,	"QM_MODULES"	},
-	{ QM_DEPS,		"QM_DEPS"		},
-	{ QM_REFS,		"QM_REFS"		},
+	{ QM_DEPS,	"QM_DEPS"	},
+	{ QM_REFS,	"QM_REFS"	},
 	{ QM_SYMBOLS,	"QM_SYMBOLS"	},
-	{ QM_INFO,		"QM_INFO"		},
+	{ QM_INFO,	"QM_INFO"	},
+	{ 0,		NULL		},
+};
+
+static struct xlat modflags[] = {
+	{ MOD_UNINITIALIZED,	"MOD_UNINITIALIZED"	},
+	{ MOD_RUNNING,		"MOD_RUNNING"		},
+	{ MOD_DELETED,		"MOD_DELETED"		},
+	{ MOD_AUTOCLEAN,	"MOD_AUTOCLEAN"		},
+	{ MOD_VISITED,		"MOD_VISITED"		},
+	{ MOD_USED_ONCE,	"MOD_USED_ONCE"		},
+	{ MOD_JUST_FREED,	"MOD_JUST_FREED"	},
 	{ 0,			NULL			},
 };
 
+void
+printstringlist(addr,num)
+char* addr;
+int num;
+{
+	int first;
+
+	first=1;
+	tprintf("{");
+	while (num--) {
+		if (first)
+			first=0;
+		else
+			tprintf(",");
+		tprintf(addr);
+		addr+=strlen(addr)+1;
+	}
+	tprintf("}");
+}
+
+
 int
 sys_query_module(tcp)
 struct tcb *tcp;
@@ -43,10 +71,58 @@
 	if (exiting(tcp)) {
 		printstr(tcp, tcp->u_arg[0], -1);
 		tprintf(", ");
-		printxval(which, tcp->u_arg[1], "L_???");
+		printxval(which, tcp->u_arg[1], "QM_???");
 		tprintf(", ");
-		printstr(tcp, tcp->u_arg[2], tcp->u_arg[3]);
-		tprintf(", %#lx", tcp->u_arg[4]);
+		if (tcp->u_rval!=0) {
+			size_t	ret;
+			umove(tcp, tcp->u_arg[4], &ret);
+			tprintf("%#lx, %lu, %d", tcp->u_arg[2], tcp->u_arg[3], ret);
+		} else if (tcp->u_arg[1]==QM_INFO) {
+			struct module_info	mi;
+			size_t			ret;
+			umove(tcp, tcp->u_arg[2], &mi);
+			tprintf("{address=%#lx, size=%lu, flags=", mi.addr, mi.size);
+			printflags(modflags, mi.flags);
+			tprintf(", usecount=%lu}", mi.usecount);
+			umove(tcp, tcp->u_arg[4], &ret);
+			tprintf(", %d", ret);
+		} else if ((tcp->u_arg[1]==QM_MODULES) ||
+			       	(tcp->u_arg[1]==QM_DEPS) ||
+			       	(tcp->u_arg[1]==QM_REFS)) {
+			char*	data	= (char*)malloc(tcp->u_arg[3]);
+			char*	mod	= data;
+			size_t	ret;
+			int	first	= 0;
+
+			umoven(tcp, tcp->u_arg[2], tcp->u_arg[3], data);
+			umove(tcp, tcp->u_arg[4], &ret);
+			tprintf("{");
+			while (ret--) {
+				if (first)
+					first=0;
+				else
+					tprintf(",");
+				tprintf(mod);
+				mod+=strlen(mod)+1;
+			}
+			tprintf("}, %d", ret);
+			free(data);
+		} else if (tcp->u_arg[1]==QM_SYMBOLS) {
+			char*			data	= (char *)malloc(tcp->u_arg[3]);
+			struct module_symbol*	sym	= (struct module_symbol*)data;
+			size_t			ret;
+			umoven(tcp, tcp->u_arg[2], tcp->u_arg[3], data);
+			tprintf("{");
+			while (ret--) {
+				tprintf("{name=%#lx, value=%lu} ", sym->name, sym->value);
+				sym++;
+			}
+			tprintf("}, %d", ret);
+			free(data);
+		} else {
+			printstr(tcp, tcp->u_arg[2], tcp->u_arg[3]);
+			tprintf(", %#lx", tcp->u_arg[4]);
+		}
 	}
 	return 0;
 }