Index: kernel/generic/src/debug/symtab.c
===================================================================
--- kernel/generic/src/debug/symtab.c	(revision 40eab9fdcc5233a31ae07d23360a0b5fc2e5c701)
+++ kernel/generic/src/debug/symtab.c	(revision bab75df6bdac0b39185034277416374a06d4b37f)
@@ -36,86 +36,47 @@
  */
 
-#include <abi/elf.h>
+#include <symtab.h>
 #include <byteorder.h>
+#include <str.h>
+#include <stdio.h>
+#include <typedefs.h>
+#include <errno.h>
 #include <console/prompt.h>
-#include <debug/sections.h>
-#include <errno.h>
-#include <proc/task.h>
-#include <stdio.h>
-#include <str.h>
-#include <symtab.h>
-#include <typedefs.h>
-
-static inline const char *symtab_entry_name(debug_sections_t *scs, int entry)
-{
-	size_t index = scs->symtab[entry].st_name;
-
-	if (index >= scs->strtab_size)
-		return NULL;
-
-	return scs->strtab + index;
-}
-
-static inline size_t symtab_next(debug_sections_t *scs, size_t i)
-{
-	size_t symtab_len = scs->symtab_size / sizeof(elf_symbol_t);
-
-	for (; i < symtab_len; i++) {
-		const char *name = symtab_entry_name(scs, i);
-		int st_bind = elf_st_bind(scs->symtab[i].st_info);
-		int st_type = elf_st_type(scs->symtab[i].st_info);
-
-		if (st_bind == STB_LOCAL)
-			continue;
-
-		if (name == NULL || *name == '\0')
-			continue;
-
-		if (st_type == STT_FUNC || st_type == STT_OBJECT)
+
+/** Get name of a symbol that seems most likely to correspond to address.
+ *
+ * @param addr   Address.
+ * @param name   Place to store pointer to the symbol name.
+ * @param offset Place to store offset from the symbol address.
+ *
+ * @return Zero on success or an error code, ENOENT if not found,
+ *         ENOTSUP if symbol table not available.
+ *
+ */
+errno_t symtab_name_lookup(uintptr_t addr, const char **name, uintptr_t *offset)
+{
+#ifdef CONFIG_SYMTAB
+	size_t i;
+
+	for (i = 1; symbol_table[i].address_le; i++) {
+		if (addr < uint64_t_le2host(symbol_table[i].address_le))
 			break;
 	}
 
-	return i;
-}
-
-const char *symtab_name_lookup(uintptr_t addr, uintptr_t *symbol_addr, debug_sections_t *scs)
-{
-	const elf_symbol_t *symtab = scs->symtab;
-	size_t symtab_len = scs->symtab_size / sizeof(elf_symbol_t);
-	const char *strtab = scs->strtab;
-	size_t strtab_size = scs->strtab_size;
-
-	if (symtab == NULL || strtab == NULL)
-		return NULL;
-
-	uintptr_t closest_symbol_addr = 0;
-	uintptr_t closest_symbol_name = 0;
-
-	for (size_t i = symtab_next(scs, 0); i < symtab_len; i = symtab_next(scs, i + 1)) {
-		if (symtab[i].st_value > addr)
-			continue;
-
-		if (symtab[i].st_value + symtab[i].st_size > addr) {
-			closest_symbol_addr = symtab[i].st_value;
-			closest_symbol_name = symtab[i].st_name;
-			break;
-		}
-
-		if (symtab[i].st_value > closest_symbol_addr) {
-			closest_symbol_addr = symtab[i].st_value;
-			closest_symbol_name = symtab[i].st_name;
-		}
-	}
-
-	if (closest_symbol_addr == 0)
-		return NULL;
-
-	if (symbol_addr)
-		*symbol_addr = closest_symbol_addr;
-
-	if (closest_symbol_name >= strtab_size)
-		return NULL;
-
-	return strtab + closest_symbol_name;
+	if (addr >= uint64_t_le2host(symbol_table[i - 1].address_le)) {
+		*name = symbol_table[i - 1].symbol_name;
+		if (offset)
+			*offset = addr -
+			    uint64_t_le2host(symbol_table[i - 1].address_le);
+		return EOK;
+	}
+
+	*name = NULL;
+	return ENOENT;
+
+#else
+	*name = NULL;
+	return ENOTSUP;
+#endif
 }
 
@@ -134,9 +95,53 @@
 const char *symtab_fmt_name_lookup(uintptr_t addr)
 {
-	const char *name = symtab_name_lookup(addr, NULL, &kernel_sections);
-	if (name == NULL)
-		name = "<unknown>";
-	return name;
-}
+	const char *name;
+	errno_t rc = symtab_name_lookup(addr, &name, NULL);
+
+	switch (rc) {
+	case EOK:
+		return name;
+	case ENOENT:
+		return "unknown";
+	default:
+		return "N/A";
+	}
+}
+
+#ifdef CONFIG_SYMTAB
+
+/** Find symbols that match the parameter forward and print them.
+ *
+ * @param name     Search string
+ * @param startpos Starting position, changes to found position
+ *
+ * @return Pointer to the part of string that should be completed or NULL.
+ *
+ */
+static const char *symtab_search_one(const char *name, size_t *startpos)
+{
+	size_t namelen = str_length(name);
+
+	size_t pos;
+	for (pos = *startpos; symbol_table[pos].address_le; pos++) {
+		const char *curname = symbol_table[pos].symbol_name;
+
+		/* Find a ':' in curname */
+		const char *colon = str_chr(curname, ':');
+		if (colon == NULL)
+			continue;
+
+		if (str_length(curname) < namelen)
+			continue;
+
+		if (str_lcmp(name, curname, namelen) == 0) {
+			*startpos = pos;
+			return (curname + str_lsize(curname, namelen));
+		}
+	}
+
+	return NULL;
+}
+
+#endif
 
 /** Return address that corresponds to the entry.
@@ -147,20 +152,34 @@
  * @param addr Place to store symbol address
  *
- * @return Zero on success, ENOENT - not found
+ * @return Zero on success, ENOENT - not found, EOVERFLOW - duplicate
+ *         symbol, ENOTSUP - no symbol information available.
  *
  */
 errno_t symtab_addr_lookup(const char *name, uintptr_t *addr)
 {
-	debug_sections_t *scs = &kernel_sections;
-	size_t symtab_len = scs->symtab_size / sizeof(elf_symbol_t);
-
-	for (size_t i = symtab_next(scs, 0); i < symtab_len; i = symtab_next(scs, i + 1)) {
-		if (str_cmp(name, symtab_entry_name(scs, i)) == 0) {
-			*addr = scs->symtab[i].st_value;
-			return EOK;
+#ifdef CONFIG_SYMTAB
+	size_t found = 0;
+	size_t pos = 0;
+	const char *hint;
+
+	while ((hint = symtab_search_one(name, &pos))) {
+		if (str_length(hint) == 0) {
+			*addr = uint64_t_le2host(symbol_table[pos].address_le);
+			found++;
 		}
-	}
-
-	return ENOENT;
+		pos++;
+	}
+
+	if (found > 1)
+		return EOVERFLOW;
+
+	if (found < 1)
+		return ENOENT;
+
+	return EOK;
+
+#else
+	return ENOTSUP;
+#endif
 }
 
@@ -168,41 +187,44 @@
 void symtab_print_search(const char *name)
 {
-	debug_sections_t *scs = &kernel_sections;
-	size_t symtab_len = scs->symtab_size / sizeof(elf_symbol_t);
-
-	if (scs->symtab == NULL || scs->strtab == NULL) {
-		printf("No symbol information available.\n");
-		return;
-	}
-
-	size_t namelen = str_length(name);
-
-	for (size_t i = symtab_next(scs, 0); i < symtab_len; i = symtab_next(scs, i + 1)) {
-		const char *n = symtab_entry_name(scs, i);
-
-		if (str_lcmp(name, n, namelen) == 0) {
-			printf("%p: %s\n", (void *) scs->symtab[i].st_value, n);
-		}
-	}
+#ifdef CONFIG_SYMTAB
+	size_t pos = 0;
+	while (symtab_search_one(name, &pos)) {
+		uintptr_t addr = uint64_t_le2host(symbol_table[pos].address_le);
+		char *realname = symbol_table[pos].symbol_name;
+		printf("%p: %s\n", (void *) addr, realname);
+		pos++;
+	}
+
+#else
+	printf("No symbol information available.\n");
+#endif
 }
 
 /** Symtab completion enum, see kernel/generic/include/kconsole.h */
-const char *symtab_hints_enum(const char *input, const char **help, void **ctx)
-{
-	debug_sections_t *scs = &kernel_sections;
-	size_t symtab_len = scs->symtab_size / sizeof(elf_symbol_t);
-
-	if (scs->symtab == NULL || scs->strtab == NULL)
-		return NULL;
-
-	if (help)
-		*help = NULL;
-
+const char *symtab_hints_enum(const char *input, const char **help,
+    void **ctx)
+{
+#ifdef CONFIG_SYMTAB
 	size_t len = str_length(input);
-	for (size_t i = symtab_next(scs, (size_t) *ctx); i < symtab_len; i = symtab_next(scs, i + 1)) {
-		const char *curname = symtab_entry_name(scs, i);
+	struct symtab_entry **entry = (struct symtab_entry **)ctx;
+
+	if (*entry == NULL)
+		*entry = symbol_table;
+
+	for (; (*entry)->address_le; (*entry)++) {
+		const char *curname = (*entry)->symbol_name;
+
+		/* Find a ':' in curname */
+		const char *colon = str_chr(curname, ':');
+		if (colon == NULL)
+			continue;
+
+		if (str_length(curname) < len)
+			continue;
 
 		if (str_lcmp(input, curname, len) == 0) {
-			*ctx = (void *) (i + 1);
+			(*entry)++;
+			if (help)
+				*help = NULL;
 			return (curname + str_lsize(curname, len));
 		}
@@ -210,4 +232,8 @@
 
 	return NULL;
+
+#else
+	return NULL;
+#endif
 }
 
