[PATCH] fix symbol completion

Jim Houston jim.houston at comcast.net
Wed Sep 29 11:53:08 PDT 2004


Hi Keith,

Attached is a patch which will fix the kdb symbol completion
problem I described yesterday.  It replaces most of the symbol
table handling with the version from the port I did last fall.

I have not looked at the code yet to check for the buffer
overflow you described.  As long as the buffers are larger
than the longest symbol in the kernel/module symbol tables
I would not expect a problem.

Jim Houston - Concurrent Computer Corp.

--

diff -urN -Xdontdiff linux-2.6.8.1.orig/include/linux/module.h linux-2.6.8.1/include/linux/module.h
--- linux-2.6.8.1.orig/include/linux/module.h	2004-08-23 16:38:06.000000000 -0400
+++ linux-2.6.8.1/include/linux/module.h	2004-09-29 13:33:11.249170728 -0400
@@ -437,6 +437,11 @@
 				  unsigned long *symbolsize,
 				  unsigned long *offset,
 				  char **modname);
+#ifdef CONFIG_KDB
+/* Kdb access to symbol table. */
+const char *module_symbol_index(unsigned int index,
+	unsigned long *value, const char **modname);
+#endif /* CONFIG_KDB */
 
 /* For extable.c to search modules' exception tables. */
 const struct exception_table_entry *search_module_extables(unsigned long addr);
@@ -518,6 +523,15 @@
 	return 0;
 }
 
+#ifdef CONFIG_KDB
+/* Kdb access to symbol table. */
+static inline const char *module_symbol_index(unsigned int index,
+	unsigned long *value, const char **modname)
+{
+	return NULL;
+}
+#endif /* CONFIG_KDB */
+
 static inline int register_module_notifier(struct notifier_block * nb)
 {
 	/* no events will happen anyway, so this can always succeed */
diff -urN -Xdontdiff linux-2.6.8.1.orig/kdb/kdbsupport.c linux-2.6.8.1/kdb/kdbsupport.c
--- linux-2.6.8.1.orig/kdb/kdbsupport.c	2004-09-02 15:18:00.000000000 -0400
+++ linux-2.6.8.1/kdb/kdbsupport.c	2004-09-29 13:22:21.707916008 -0400
@@ -27,14 +27,6 @@
 #include <linux/kdb.h>
 #include <linux/kdbprivate.h>
 
-#ifdef CONFIG_MODULES
-extern struct list_head *kdb_modules;
-#endif
-
-/* These will be re-linked against their real values during the second link stage */
-extern unsigned long kallsyms_addresses[] __attribute__((weak));;
-extern unsigned long kallsyms_num_syms __attribute__((weak));
-extern char kallsyms_names[] __attribute__((weak));
 
 /*
  * Symbol table functions.
@@ -46,7 +38,7 @@
  *	Return the address of the given symbol.
  *
  * Parameters:
- *	symname	Character string containing symbol name
+ * 	symname	Character string containing symbol name
  *      symtab  Structure to receive results
  * Outputs:
  * Returns:
@@ -57,55 +49,12 @@
  * Remarks:
  */
 
-int
-kdbgetsymval(const char *symname, kdb_symtab_t *symtab)
-{
-	int i;
-	char *name = kallsyms_names;
-	char namebuf[128];
 
-	if (KDB_DEBUG(AR))
-		kdb_printf("kdbgetsymval: symname=%s, symtab=%p\n", symname, symtab);
-	memset(symtab, 0, sizeof(*symtab));
-
-	namebuf[127] = 0;
-	namebuf[0] = 0;
-	for (i = 0; i < kallsyms_num_syms; i++) {
-		unsigned prefix = *name++;
-		strncpy(namebuf + prefix, name, 127 - prefix);
-		if (strcmp(namebuf, symname) == 0) {
-			/* found */
-			symtab->sym_start = kallsyms_addresses[i];
-			if (KDB_DEBUG(AR))
-				kdb_printf("kdbgetsymval: returns 1, symtab->sym_start=0x%lx\n", symtab->sym_start);
-			return(1);
-		}
-		name += strlen(name) + 1;
-	}
-#ifdef CONFIG_MODULES
- {
-	struct module *mod;
-	/* look into modules */
-	list_for_each_entry(mod, kdb_modules, list) {
-		for (i = 1; i < mod->num_symtab; i++) {
-			if (mod->symtab[i].st_shndx == SHN_UNDEF)
-				continue;
-			name =  mod->strtab + mod->symtab[i].st_name;
-			if (strcmp(name, symname) == 0) {
-				/* found */
-				symtab->sym_start = mod->symtab[i].st_value;
-				if (KDB_DEBUG(AR))
-					kdb_printf("kdbgetsymval: returns 1, symtab->sym_start=0x%lx\n", symtab->sym_start);
-				return(1);
-			}
-		}
-	}
- }
-#endif /* CONFIG_MODULES */
-	if (KDB_DEBUG(AR))
-		kdb_printf("kdbgetsymval: returns 0\n");
-	return(0);
-}
+/* These will be re-linked against their real values during the second link stage */
+extern unsigned long kallsyms_addresses[] __attribute__((weak));
+extern unsigned long kallsyms_num_syms __attribute__((weak));
+extern char kallsyms_names[] __attribute__((weak));
+extern char _end;
 
 /*
  * kdbnearsym
@@ -114,8 +63,8 @@
  *	less than 'addr'.
  *
  * Parameters:
- *	addr	Address to check for symbol near
- *	symtab  Structure to receive results
+ * 	addr	Address to check for symbol near
+ *      symtab  Structure to receive results
  * Outputs:
  * Returns:
  *	0	No sections contain this address, symtab zero filled
@@ -123,189 +72,164 @@
  * Locking:
  *	None.
  * Remarks:
- *	2.6 kallsyms has a "feature" where it unpacks the name into a string.
- *	If that string is reused before the caller expects it then the caller
- *	sees its string change without warning.  To avoid cluttering up the
- *	main kdb code with lots of kdb_strdup, tests and kfree calls, kdbnearsym
- *	maintains an LRU list of the last few unique strings.  The list is sized
- *	large enough to hold active strings, no kdb caller of kdbnearsym makes
- *	more than ~20 later calls before using a saved value.
  */
 
 int
 kdbnearsym(unsigned long addr, kdb_symtab_t *symtab)
 {
-	int ret;
-	unsigned long symbolsize;
-	unsigned long offset;
-	static char *knt[100];	/* kdb name table, arbitrary size */
-#define knt1_size 128		/* must be >= kallsyms table size */
-	char *knt1 = kmalloc(knt1_size, GFP_ATOMIC);
+	const char *name;
+	char *modname;
+	long size, offset;
+	int h, l , m;
 
-	if (!knt1) {
-		kdb_printf("kdbnearsym: addr=0x%lx cannot kmalloc knt1\n", addr);
+	if (!kallsyms_addresses) {
+		kdb_printf("kdbnearsym: no symbol table\n");
 		return 0;
 	}
-
-	if (KDB_DEBUG(AR))
-		kdb_printf("kdbnearsym: addr=0x%lx, symtab=%p\n", addr, symtab);
-
+	name = NULL;
+	if (addr > (unsigned long)&_end) {
+		name = module_address_lookup(addr,  &size, &offset, &modname);
+	} else if (addr > PAGE_OFFSET) {
+		l = 0;
+		h = kallsyms_num_syms-1;
+		m = (h+l)/2;
+		while (h > l+1) {
+			if (kallsyms_addresses[m] > addr)
+				h = m;
+			else
+				l = m;
+			m = (h+l)/2;
+		}
+		if (kallsyms_addresses[h] <= addr)
+			l = h;
+		h = l+1;
+		name = kallsyms_names;
+		for (m = 0; m < l ; m++)
+			name += strlen(name)+1;
+		size = kallsyms_addresses[h] - kallsyms_addresses[l];
+		offset = addr - kallsyms_addresses[l];
+		modname = NULL;
+	}
 	memset(symtab, 0, sizeof(*symtab));
-	symtab->sym_name = kallsyms_lookup(addr, &symbolsize , &offset, (char **)(&symtab->mod_name), knt1);
+	if (!name) 
+		return 0;
+	symtab->sym_name = name;
 	symtab->sym_start = addr - offset;
-	symtab->sym_end = symtab->sym_start + symbolsize;
-	ret = symtab->sym_name != NULL && *(symtab->sym_name) != '\0';
+	symtab->sym_end = addr - offset + size;
+	symtab->mod_name = modname ? modname : "kernel";
+	return 1;
+}
 
-	if (ret) {
-		int i;
-		/* Another 2.6 kallsyms "feature".  Sometimes the sym_name is
-		 * set but the buffer passed into kallsyms_lookup is not used,
-		 * so it contains garbage.  The caller has to work out which
-		 * buffer needs to be saved.
-		 *
-		 * What was Rusty smoking when he wrote that code?
-		 */
-		if (symtab->sym_name != knt1) {
-			strncpy(knt1, symtab->sym_name, knt1_size);
-			knt1[knt1_size-1] = '\0';
-		}
-		for (i = 0; i < ARRAY_SIZE(knt); ++i) {
-			if (knt[i] && strcmp(knt[i], knt1) == 0)
-				break;
-		}
-		if (i >= ARRAY_SIZE(knt)) {
-			memcpy(knt, knt+1, sizeof(knt[0])*(ARRAY_SIZE(knt)-1));
-			i = ARRAY_SIZE(knt)-1;
-		} else {
-			kfree(knt1);
-			knt1 = knt[i];
-			memcpy(knt+i, knt+i+1, sizeof(knt[0])*(ARRAY_SIZE(knt)-i-1));
-			i = ARRAY_SIZE(knt) - 1;
-		}
-		knt[i] = knt1;
-		symtab->sym_name = knt[i];
-	}
+#define first_symbol(index, string, value, module) \
+	index = 0; \
+	string = kallsyms_names; \
+	module = NULL; \
+	value = kallsyms_addresses[0];
 
-	if (symtab->mod_name == NULL)
-		symtab->mod_name = "kernel";
-	if (KDB_DEBUG(AR))
-		kdb_printf("kdbnearsym: returns %d symtab->sym_start=0x%lx, symtab->mod_name=%p, symtab->sym_name=%p (%s)\n", ret, symtab->sym_start, symtab->mod_name, symtab->sym_name, symtab->sym_name);
 
-	return ret;
-}
+#define next_symbol(index, string, value, module) \
+	if (++index < kallsyms_num_syms) { \
+		string += strlen(string)+1; \
+		value = kallsyms_addresses[index]; \
+	} else { \
+		string = module_symbol_index(index-kallsyms_num_syms, &value, &module); \
+	}
 
-/*
- * kallsyms_symbol_complete
- *
- * Parameters:
- *	prefix_name	prefix of a symbol name to lookup
- * Returns:
- *	Number of symbols which match the given prefix.
- */
 
+/* paramter prefix_name is a buffer provided by the caller, it must ends with '\0'. */
+/* return the extra string together with the given prefix of a symbol name. */
+/* return 0 means no prefix string is found. */
+/* return >0 means prefix string is found. */
+/* Prefix of a symbol name to lookup */
 int kallsyms_symbol_complete(char *prefix_name)
 {
-	char *name = kallsyms_names;
-	int i;
-	char namebuf[128];
-	int prefix_len = strlen(prefix_name);
-	int number = 0;
-
-	/* look into kernel symbols */
-
-	for (i=0; i < kallsyms_num_syms; i++) {
-		unsigned prefix = *name++;
-		strncpy(namebuf + prefix, name, 127 - prefix);
-		if (strncmp(namebuf, prefix_name, prefix_len) == 0) {
-			/* found */
-			++number;
-		}
-		name += strlen(name) + 1;
-	}
-#ifdef CONFIG_MODULES
- {
-	struct module *mod;
-	/* look into modules symbols */
-	list_for_each_entry(mod, kdb_modules, list) {
-		for (i = 1; i < mod->num_symtab; i++) {
-			if (mod->symtab[i].st_shndx == SHN_UNDEF)
-				continue;
-			name =  mod->strtab + mod->symtab[i].st_name;
-			if (strncmp(name, prefix_name, prefix_len) == 0) {
-				/* found */
-				++number;
+	int prefix_len=strlen(prefix_name);
+	int last_pos=0;
+	int number=0;
+	const char *p, *mod;
+	unsigned long value;
+	int i, j;
+
+	first_symbol(i, p, value, mod);
+	while (p) {
+		if (strncmp(p, prefix_name,prefix_len) == 0) {
+			if (number++ == 0) {
+				last_pos = strlen(p);
+				strncpy(prefix_name, p, last_pos+1);
+			} else {
+				for (j = prefix_len ; j < last_pos; j++) {
+					if (!p[j] || p[j] != prefix_name[j]) {
+						last_pos = j;
+						prefix_name[j] = '\0';
+						break;
+					}
+				}
 			}
 		}
+		next_symbol(i, p, value, mod);
 	}
- }
-#endif /* CONFIG_MODULES */
+
 	return number;
 }
 
-/*
- * kallsyms_symbol_next
- *
- * Parameters:
- *	prefix_name	prefix of a symbol name to lookup
- *	flag	0 means search from the head, 1 means continue search.
- * Returns:
- *	1 if a symbol matches the given prefix.
- *	0 if no string found
- */
+/* paramter prefix_name is a buffer provided by the caller, it must ends with '\0'. */
+/* parameter flag = 0 means search from the head, flag = 1 means continue search. */
+/* return a symbol string which matches the given prefix. */
+/* return 0 means no prefix string is found. */
+/* return >0 means prefix string is found. */
+
+static unsigned int current_index;
+static const char *current_string;
 
-int kallsyms_symbol_next(char *prefix_name, int flag)
+/* Prefix of a symbol name to lookup */
+/* Indicate if search from the head */
+int kallsyms_symbol_next( char *prefix_name, int flag)
 {
-	int prefix_len = strlen(prefix_name);
-	char namebuf[128];
-	static int i;
-	static char *name;
-	static struct module *mod;
-
-	if (flag) {
-		/* continue searching */
-		i++;
-		name += strlen(name) + 1;
-	} else {
-		/* new search */
-		i = 0;
-		name = kallsyms_names;
-		mod = (struct module *)NULL;
+	int prefix_len=strlen(prefix_name);
+	unsigned long value;
+	const char *p, *mod;
+
+
+	if(!flag) {
+		first_symbol(current_index, current_string, value, mod);
 	}
 
-	if (mod == (struct module *)NULL) {
-		/* look into kernel symbols */
-		for (; i < kallsyms_num_syms; i++) {
-			unsigned prefix = *name++;
-			strncpy(namebuf + prefix, name, 127 - prefix);
-			if (strncmp(namebuf, prefix_name, prefix_len) == 0) {
-				/* found */
-				strncpy(prefix_name, namebuf, strlen(namebuf)+1);
-				return(1);
-			}
-			name += strlen(name) + 1;
+	while ((p = current_string)) {
+		next_symbol(current_index, current_string, value, mod);
+		if (strncmp(p, prefix_name,prefix_len) == 0) {
+			strncpy(prefix_name, p, strlen(p)+1);
+			return 1;
 		}
-#ifdef CONFIG_MODULES
-		/* not found */
-		i = 1;
-		mod = list_entry(kdb_modules->next, struct module, list);
-	}
-	/* look into modules */
-	for (; &mod->list != kdb_modules; mod =
-		     list_entry(mod->list.next, struct module, list))
-		for (; i < mod->num_symtab; i++) {
-			if (mod->symtab[i].st_shndx == SHN_UNDEF)
-				continue;
-			name =  mod->strtab + mod->symtab[i].st_name;
-			if (strncmp(name, prefix_name, prefix_len) == 0) {
-				/* found */
-				strncpy(prefix_name, name, strlen(name)+1);
-				return(1);
-			}
-		}
-#else /* CONFIG_MODULES */
 	}
-#endif /* CONFIG_MODULES */
-	return(0);
+	return 0;
+}
+
+int
+kdbgetsymval(const char *symname, kdb_symtab_t *symtab)
+{
+	unsigned long value;
+	const char *p, *mod;
+	int i;
+
+	if (!kallsyms_addresses) {
+		kdb_printf("kdbgetsymval: no symbol table\n");
+		return 0;
+	}
+	first_symbol(i, p, value, mod);
+	while (p) {
+		if (strcmp(p, symname) == 0)
+			break;
+		next_symbol (i, p, value, mod);
+	}
+	if (!p)
+		return 0;
+	/*
+	 * Use the value based lookup to find the symbol's size.
+	 */
+	i = kdbnearsym(value, symtab);
+	/* return the name we matched. */
+	symtab->sym_name = p;
+	return(i);
 }
 
 #if defined(CONFIG_SMP)
Binary files linux-2.6.8.1.orig/kernel/config_data.gz and linux-2.6.8.1/kernel/config_data.gz differ
diff -urN -Xdontdiff linux-2.6.8.1.orig/kernel/kallsyms.c linux-2.6.8.1/kernel/kallsyms.c
--- linux-2.6.8.1.orig/kernel/kallsyms.c	2004-09-02 15:18:00.000000000 -0400
+++ linux-2.6.8.1/kernel/kallsyms.c	2004-09-29 12:20:44.000000000 -0400
@@ -14,11 +14,7 @@
 #include <linux/err.h>
 #include <linux/proc_fs.h>
 
-#ifdef CONFIG_KDB
-#define kdb 1
-#else
-#define kdb 0
-#endif
+static int stem_compression = 1;
 
 /* These will be re-linked against their real values during the second link stage */
 extern unsigned long kallsyms_addresses[] __attribute__((weak));
@@ -27,7 +23,6 @@
 
 /* Defined by the linker script. */
 extern char _stext[], _etext[], _sinittext[], _einittext[];
-extern char _end[];	/* for CONFIG_KDB */
 
 static inline int is_kernel_inittext(unsigned long addr)
 {
@@ -44,12 +39,6 @@
 	return 0;
 }
 
-/* kdb treats all kernel addresses as valid, including data */
-static inline int is_kernel(unsigned long addr)
-{
-	return (addr >= (unsigned long)_stext && addr <= (unsigned long)_end);
-}
-
 /* Lookup the address for this symbol. Returns 0 if not found. */
 unsigned long kallsyms_lookup_name(const char *name)
 {
@@ -82,30 +71,26 @@
 
 	namebuf[KSYM_NAME_LEN] = 0;
 	namebuf[0] = 0;
-	if ((kdb && is_kernel(addr)) ||
-	    (!kdb && (is_kernel_text(addr) || is_kernel_inittext(addr)))) {
+
+	if (is_kernel_text(addr) || is_kernel_inittext(addr)) {
 		unsigned long symbol_end;
 		char *name = kallsyms_names;
 
 		/* They're sorted, we could be clever here, but who cares? */
 		for (i = 0; i < kallsyms_num_syms; i++) {
-			if (kallsyms_addresses[i] > kallsyms_addresses[best] &&
+			if (kallsyms_addresses[i] >= kallsyms_addresses[best] &&
 			    kallsyms_addresses[i] <= addr)
 				best = i;
 		}
 
+
 		/* Grab name */
-		for (i = 0; i <= best; i++) { 
-			unsigned prefix = *name++;
-			strncpy(namebuf + prefix, name, KSYM_NAME_LEN - prefix);
-			name += strlen(name) + 1;
-		}
 
 		/* At worst, symbol ends at end of section. */
 		if (is_kernel_inittext(addr))
 			symbol_end = (unsigned long)_einittext;
 		else
-			symbol_end = kdb ? (unsigned long)_end : (unsigned long)_etext;
+			symbol_end = (unsigned long)_etext;
 
 		/* Search for next non-aliased symbol */
 		for (i = best+1; i < kallsyms_num_syms; i++) {
@@ -118,7 +103,18 @@
 		*symbolsize = symbol_end - kallsyms_addresses[best];
 		*modname = NULL;
 		*offset = addr - kallsyms_addresses[best];
-		return namebuf;
+		if (stem_compression) {
+			for (i = 0; i <= best; i++) { 
+				unsigned prefix = *name++;
+				strncpy(namebuf + prefix, name, KSYM_NAME_LEN - prefix);
+				name += strlen(name) + 1;
+			}
+			return namebuf;
+		}
+		for (i = 0; i < best; i++)
+			name += strlen(name)+1;
+		strncpy(namebuf, name, KSYM_NAME_LEN);
+		return name;
 	}
 
 	return module_address_lookup(addr, symbolsize, offset, modname);
@@ -185,7 +181,11 @@
 
 	/* First char of each symbol name indicates prefix length
 	   shared with previous name (stem compression). */
-	stemlen = kallsyms_names[off++];
+	if (stem_compression) {
+		stemlen = kallsyms_names[off++];
+	} else {
+		stemlen = 0;
+	}
 
 	strlcpy(iter->name+stemlen, kallsyms_names + off,
 		KSYM_NAME_LEN+1-stemlen);
@@ -318,6 +318,8 @@
 	entry = create_proc_entry("kallsyms", 0444, NULL);
 	if (entry)
 		entry->proc_fops = &kallsyms_operations;
+
+	stem_compression = kallsyms_names ? (*kallsyms_names == 0) : 0;
 	return 0;
 }
 __initcall(kallsyms_init);
diff -urN -Xdontdiff linux-2.6.8.1.orig/kernel/module.c linux-2.6.8.1/kernel/module.c
--- linux-2.6.8.1.orig/kernel/module.c	2004-09-02 15:18:00.000000000 -0400
+++ linux-2.6.8.1/kernel/module.c	2004-09-29 12:20:44.000000000 -0400
@@ -38,6 +38,10 @@
 #include <asm/semaphore.h>
 #include <asm/cacheflush.h>
 
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#endif
+
 #if 0
 #define DEBUGP printk
 #else
@@ -2038,6 +2042,30 @@
 }
 #endif /* CONFIG_KALLSYMS */
 
+#ifdef CONFIG_KDB
+/*
+ * Allow the debugger to iterate over the symbols for all of
+ * the currently loaded modules.  The  enumeration of the
+ * symbols will change when ever a module loaded or unloaded.
+ */
+const char *module_symbol_index(unsigned int index,
+	unsigned long *value, const char **modname)
+{
+	struct module *mod;
+
+	list_for_each_entry(mod, &modules, list) {
+		if (index < mod->num_symtab) { 
+			*value = mod->symtab[index].st_value;
+			*modname = mod->name;
+			return mod->strtab + mod->symtab[index].st_name;
+		}
+		index -= mod->num_symtab;
+	}
+	return NULL;
+
+}
+#endif
+
 /* Called by the /proc file system to return a list of modules. */
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
diff -urN -Xdontdiff linux-2.6.8.1.orig/Makefile linux-2.6.8.1/Makefile
--- linux-2.6.8.1.orig/Makefile	2004-09-02 15:18:00.000000000 -0400
+++ linux-2.6.8.1/Makefile	2004-09-29 12:24:14.000000000 -0400
@@ -577,7 +577,12 @@
 endef
 
 quiet_cmd_kallsyms = KSYM    $@
+# Disable stem compression and add data symbols for kdb
+ifdef CONFIG_KDB
+cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) --no-stem-compression --all-symbols > $@
+else
 cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) $(foreach x,$(CONFIG_KALLSYMS_ALL),--all-symbols) > $@
+endif
 
 .tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE
 	$(call if_changed_dep,as_o_S)
diff -urN -Xdontdiff linux-2.6.8.1.orig/scripts/kallsyms.c linux-2.6.8.1/scripts/kallsyms.c
--- linux-2.6.8.1.orig/scripts/kallsyms.c	2004-08-23 16:38:09.000000000 -0400
+++ linux-2.6.8.1/scripts/kallsyms.c	2004-09-29 12:20:44.000000000 -0400
@@ -12,6 +12,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
+#include <unistd.h>
 
 struct sym_entry {
 	unsigned long long addr;
@@ -24,11 +25,12 @@
 static int size, cnt;
 static unsigned long long _stext, _etext, _sinittext, _einittext;
 static int all_symbols = 0;
+static int stem_compression = 1;
 
 static void
 usage(void)
 {
-	fprintf(stderr, "Usage: kallsyms [--all-symbols] < in.map > out.S\n");
+	fprintf(stderr, "Usage: kallsyms [--no-stem-compression][--all-symbols] < in.map > out.S\n");
 	exit(1);
 }
 
@@ -131,7 +133,7 @@
 	for (i = 0; i < cnt; i++) {
 		if (!symbol_valid(&table[i]))
 			continue;
-
+		
 		printf("\tPTR\t%#llx\n", table[i].addr);
 		valid++;
 	}
@@ -153,10 +155,16 @@
 		if (!symbol_valid(&table[i]))
 			continue;
 
-		for (k = 0; table[i].sym[k] && table[i].sym[k] == prev[k]; ++k)
-			; 
+		if (stem_compression) {
+			for (k = 0; table[i].sym[k] && table[i].sym[k] == prev[k]; ++k)
+				; 
+
+			printf("\t.byte 0x%02x\n\t.asciz\t\"%s\"\n",
+				 k, table[i].sym + k);
+		} else {
+			printf("\t.asciz\t\"%s\"\n", table[i].sym);
+		}
 
-		printf("\t.byte 0x%02x\n\t.asciz\t\"%s\"\n", k, table[i].sym + k);
 		prev = table[i].sym;
 	}
 	printf("\n");
@@ -165,10 +173,13 @@
 int
 main(int argc, char **argv)
 {
-	if (argc == 2 && strcmp(argv[1], "--all-symbols") == 0)
-		all_symbols = 1;
-	else if (argc != 1)
-		usage();
+	while(++argv,--argc) {
+		if (strcmp(*argv, "--all-symbols") == 0)
+			all_symbols = 1;
+		else if (strcmp(*argv, "--no-stem-compression") == 0)
+			stem_compression = 0;
+		else usage();
+	}
 
 	read_map(stdin);
 	write_src();
---------------------------
Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe.


More information about the kdb mailing list