[PATCH 5/6] Convert symbols from NetBSD kernel to format suitable for Hatari debugger

[ Thread Index | Date Index | More lists.tuxfamily.org/hatari-devel Archives ]


---
 src/debug/symbols.c |  71 ++++++++++++++++++++++++++
 src/debug/symbols.h |   2 +
 src/includes/elf.h  |  55 ++++++++++++++++++++
 src/netbsd.c        | 119 ++++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 244 insertions(+), 3 deletions(-)

diff --git a/src/debug/symbols.c b/src/debug/symbols.c
index 7aa6e93d..071011d5 100644
--- a/src/debug/symbols.c
+++ b/src/debug/symbols.c
@@ -356,6 +356,77 @@ static void Symbols_Free(symbol_list_t* list)
 }
 
 
+/**
+ * set symbols from some other source
+ * (used eg. by the NetBSD loader)
+ */
+bool Symbols_Set(symbol_t *symbols, int count, char *strtable)
+{
+	symbol_list_t *list;
+	const char *filename = "kernel";
+
+	if (count == 0) {
+		fprintf(stderr, "ERROR: no valid symbols in %s, loading failed!\n", filename);
+		return false;
+	}
+
+	if ((list = symbol_list_alloc(1)) == NULL) {
+		return false;
+	}
+	free(list->names);
+	list->names = symbols; /* take ownership */
+	list->symbols = count;
+	list->namecount = count;
+	list->strtab = strtable; /* take ownership */
+
+	/* sort and trim names list */
+	qsort(list->names, list->namecount, sizeof(symbol_t), symbols_by_name);
+	symbols_trim_names(list);
+
+	/* copy name list to address list */
+	list->addresses = malloc(list->namecount * sizeof(symbol_t));
+	assert(list->addresses);
+	memcpy(list->addresses, list->names, list->namecount * sizeof(symbol_t));
+
+	/* sort address list and trim to contain just TEXT symbols */
+	qsort(list->addresses, list->namecount, sizeof(symbol_t), symbols_by_address);
+	symbols_trim_addresses(list);
+
+#if 0 /* not done here, because the kernel has lots of duplicate names */
+	/* check for duplicate names */
+	if (symbols_check_names(list->names, list->namecount)) {
+		fprintf(stderr, "-> Hatari symbol expansion can match only one of the addresses for name duplicates!\n");
+	}
+	/* check for duplicate TEXT & other addresses */
+	if (symbols_check_addresses(list->addresses, list->codecount)) {
+		fprintf(stderr, "-> Hatari profile/disassembly will show only one of the TEXT symbols for given address!\n");
+	}
+	if (symbols_check_addresses(list->addresses + list->codecount, list->datacount)) {
+		fprintf(stderr, "-> Hatari disassembly will show only one of the symbols for given address!\n");
+	}
+#endif
+
+	fprintf(stderr, "Loaded %d symbols (%d TEXT) from '%s'.\n",
+		list->namecount, list->codecount, filename);
+
+	SymbolsAreForProgram = false;
+	Symbols_Free(CpuSymbolsList);
+	CpuSymbolsList = list;
+
+#if 0
+	for (int i = 0; i < list->namecount; i++)
+	{
+		char c = list->addresses[i].type == SYMTYPE_ABS ? 'A' :
+			     list->addresses[i].type == SYMTYPE_TEXT ? 'T' :
+			     list->addresses[i].type == SYMTYPE_DATA ? 'D' :
+			     list->addresses[i].type == SYMTYPE_BSS ? 'B' : '?';
+		fprintf(stderr, "%08x %c %s\n", list->addresses[i].address, c, list->addresses[i].name);
+	}
+#endif
+
+	return true;
+}
+
 /* ---------------- symbol name completion support ------------------ */
 
 /**
diff --git a/src/debug/symbols.h b/src/debug/symbols.h
index 06b6f1ad..2e7a01da 100644
--- a/src/debug/symbols.h
+++ b/src/debug/symbols.h
@@ -55,5 +55,7 @@ extern void Symbols_LoadCurrentProgram(void);
 /* symbols/dspsymbols command parsing */
 extern char *Symbols_MatchCommand(const char *text, int state);
 extern int Symbols_Command(int nArgc, char *psArgs[]);
+/* set symbols from some other source */
+extern bool Symbols_Set(symbol_t *symbols, int count, char *strtable);
 
 #endif
diff --git a/src/includes/elf.h b/src/includes/elf.h
index 498b7f6d..b72638d9 100644
--- a/src/includes/elf.h
+++ b/src/includes/elf.h
@@ -83,6 +83,18 @@ typedef struct {
 	Elf32_Word	sh_entsize;	/* table entry size */
 } Elf32_Shdr;
 
+/* special sections indexes */
+#define SHN_UNDEF 0
+#define SHN_LORESERVE    0xFF00         /* Begin range of reserved indices */
+#define SHN_LOPROC       0xFF00         /* Begin range of appl-specific */
+#define SHN_HIPROC       0xFF1F         /* End range of appl-specific */
+#define SHN_LOOS         0xFF20         /* OS specific semantics, lo */
+#define SHN_HIOS         0xFF3F         /* OS specific semantics, hi */
+#define SHN_ABS          0xfff1         /* Associated symbol is absolute */
+#define SHN_COMMON       0xfff2         /* Associated symbol is in common */
+#define SHN_XINDEX		 0xFFFF			/* Section index is held elsewhere */
+#define SHN_HIRESERVE    0xFFFF         /* End range of reserved indices */
+
 /* sh_type */
 #define	SHT_NULL	0		/* Section header table entry unused */
 #define	SHT_PROGBITS	1		/* Program information */
@@ -113,4 +125,47 @@ typedef struct {
 #define	SHF_MASKOS	0x0f000000	/* Operating system specific values */
 #define	SHF_MASKPROC	0xf0000000	/* Processor-specific values */
 
+typedef struct
+{
+  Elf32_Word	st_name;		/* Symbol name (string tbl index) */
+  Elf32_Addr	st_value;		/* Symbol value */
+  Elf32_Word	st_size;		/* Symbol size */
+  unsigned char	st_info;		/* Symbol type and binding */
+  unsigned char	st_other;		/* Symbol visibility */
+  Elf32_Section	st_shndx;		/* Section index */
+} Elf32_Sym;
+
+/* These three macros disassemble and assemble a symbol table st_info field,
+   which contains the symbol binding and symbol type.  The STB_ and STT_
+   defines identify the binding and type. */
+
+#define ELF_ST_BIND(val)		(((unsigned int)(val)) >> 4)
+#define ELF_ST_TYPE(val)		((val) & 0xF)
+#define ELF_ST_INFO(bind,type)		(((bind) << 4) + ((type) & 0xF))
+
+/* ST_BIND */
+#define STB_LOCAL  0				/* Symbol not visible outside obj */
+#define STB_GLOBAL 1				/* Symbol visible outside obj */
+#define STB_WEAK   2				/* Like globals, lower precedence */
+#define STB_LOOS   10				/* Start of OS-specific */
+#define STB_GNU_UNIQUE	10			/* Symbol is unique in namespace */
+#define STB_HIOS   12				/* End of OS-specific */
+#define STB_LOPROC 13				/* Application-specific semantics */
+#define STB_HIPROC 15				/* Application-specific semantics */
+
+/* ST_TYPE */
+#define STT_NOTYPE	0				/* Symbol type is unspecified */
+#define STT_OBJECT	1				/* Symbol is a data object */
+#define STT_FUNC	2				/* Symbol is a code object */
+#define STT_SECTION 3				/* Symbol associated with a section */
+#define STT_FILE	4				/* Symbol gives a file name */
+#define STT_COMMON	5				/* Symbol is a common data object */
+#define STT_TLS 	6				/* Symbol is thread-local data object*/
+#define STT_LOOS	10				/* Start of OS-specific */
+#define STT_GNU_IFUNC	10			/* Symbol is an indirect code object */
+#define STT_HIOS	12				/* End of OS-specific */
+#define STT_LOPROC	13				/* Application-specific semantics */
+#define STT_HIPROC	15				/* Application-specific semantics */
+
+
 /* end of rip from elf.h */
diff --git a/src/netbsd.c b/src/netbsd.c
index 771845b7..0c67706f 100644
--- a/src/netbsd.c
+++ b/src/netbsd.c
@@ -19,6 +19,7 @@
 #include <SDL_endian.h>
 #include "newcpu.h"
 #include "elf.h"
+#include "symbols.h"
 
 bool bUseNetbsd;
 
@@ -230,7 +231,7 @@ static bool check_kernel(void *kernel, Elf32_Addr *kernel_offset)
 	Elf32_Addr mem_ptr;
 	Elf32_Addr symsize, symstart;
 	uint32_t *tmp;
-	int i;
+	Elf32_Word i;
 	int debug_flag;
 	int no_symbols;
 	int stmem_only;
@@ -363,7 +364,7 @@ static bool check_kernel(void *kernel, Elf32_Addr *kernel_offset)
 
 	*kernel_offset = 0;
 	mem_ptr = KERNEL_START;
-	int segments = SDL_SwapBE16(kexec_elf->e_phnum);
+	Elf32_Word segments = SDL_SwapBE16(kexec_elf->e_phnum);
 	Dprintf(("NetBSD: copying %d segments to %s...\n", segments,
 		 "ST-RAM"));
 	for (i = 0; i < segments; i++) {
@@ -393,9 +394,11 @@ static bool check_kernel(void *kernel, Elf32_Addr *kernel_offset)
 	if (symsize != 0)
 	{
 		unsigned char *p, *symtab;
-		int nhdrs;
+		Elf32_Word nhdrs;
 		Elf32_Shdr *shp;
 		Elf32_Addr size;
+		Elf32_Word symtab_index;
+		Elf32_Word strtab_index;
 
 		symtab = RAMBaseHost + KERNEL_START + symstart;
 
@@ -427,6 +430,116 @@ static bool check_kernel(void *kernel, Elf32_Addr *kernel_offset)
 		}
 		kexec_elf->e_shoff = SDL_SwapBE32(sizeof(*kexec_elf));
 		memcpy(symtab, kexec_elf, sizeof(*kexec_elf));
+
+		/*
+		 * build a symbol table for Hatari's debugger
+		 */
+		symtab_index = 0;
+		strtab_index = 0;
+		for (i = 0; i < nhdrs; i++)
+		{
+			if (SDL_SwapBE32(shp[i].sh_type) == SHT_SYMTAB)
+			{
+				symtab_index = i;
+				strtab_index = SDL_SwapBE32(shp[i].sh_link);
+				break;
+			}
+		}
+		if (strtab_index != 0 && strtab_index < nhdrs)
+		{
+			char *strings = (char *)symtab + SDL_SwapBE32(shp[strtab_index].sh_offset);
+			Elf32_Word count, symbolcount, strtab_size;
+			symbol_t *symbols;
+			Elf32_Sym *esym;
+			Elf32_Word strx;
+			Elf32_Word idx;
+			static char null_string[] = "";
+
+			count = SDL_SwapBE32(shp[symtab_index].sh_size) / SDL_SwapBE32(shp[symtab_index].sh_entsize);
+			symbols = malloc(count * sizeof(*symbols));
+			strtab_size = SDL_SwapBE32(shp[strtab_index].sh_size);
+			strings = malloc(strtab_size);
+			if (symbols != NULL && strings != NULL)
+			{
+				/*
+				 * struct symbol_t needs a pointer, so we need to make a copy also of
+				 * the string table, since the kernel may move it around
+				 */
+				memcpy(strings, (char *)symtab + SDL_SwapBE32(shp[strtab_index].sh_offset), strtab_size);
+				esym = (Elf32_Sym *)(symtab + SDL_SwapBE32(shp[symtab_index].sh_offset));
+				symbolcount = 0;
+				for (i = 0; i < count; i++, esym++)
+				{
+					strx = SDL_SwapBE32(esym->st_name);
+					idx = SDL_Swap16(esym->st_shndx);
+					if (strx > 0 && strx < strtab_size)
+						symbols[symbolcount].name = strings + strx;
+					else
+						symbols[symbolcount].name = null_string;
+					symbols[symbolcount].name_allocated = false;
+					symbols[symbolcount].address = SDL_SwapBE32(esym->st_value);
+					switch (esym->st_info)
+					{
+					case ELF_ST_INFO(STB_LOCAL, STT_OBJECT):
+					case ELF_ST_INFO(STB_GLOBAL, STT_OBJECT):
+					case ELF_ST_INFO(STB_WEAK, STT_OBJECT):
+					case ELF_ST_INFO(STB_LOCAL, STT_FUNC):
+					case ELF_ST_INFO(STB_GLOBAL, STT_FUNC):
+					case ELF_ST_INFO(STB_WEAK, STT_FUNC):
+					case ELF_ST_INFO(STB_LOCAL, STT_COMMON):
+					case ELF_ST_INFO(STB_GLOBAL, STT_COMMON):
+					case ELF_ST_INFO(STB_WEAK, STT_COMMON):
+					case ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE):
+					case ELF_ST_INFO(STB_LOCAL, STT_NOTYPE):
+					case ELF_ST_INFO(STB_WEAK, STT_NOTYPE):
+						switch (idx)
+						{
+						case SHN_ABS:
+							symbols[symbolcount].type = SYMTYPE_ABS;
+							symbolcount++;
+							break;
+						case SHN_UNDEF:
+							/* should not happen here, and isn't used by hatari debugger */
+							break;
+						case SHN_COMMON:
+							/* should not happen here, and isn't used by hatari debugger */
+							break;
+						default:
+							if (idx < nhdrs)
+							{
+								if (SDL_SwapBE32(shp[idx].sh_type) == SHT_NOBITS)
+								{
+									symbols[symbolcount].type = SYMTYPE_BSS;
+								} else if (SDL_SwapBE32(shp[idx].sh_flags) & SHF_EXECINSTR)
+								{
+									symbols[symbolcount].type = SYMTYPE_TEXT;
+								} else
+								{
+									symbols[symbolcount].type = SYMTYPE_DATA;
+								}
+								/* symbols[symbolcount].address += SDL_SwapBE32(shp[idx].sh_addr); */
+								symbolcount++;
+							}
+							break;
+						}
+						break;
+					case ELF_ST_INFO(STB_LOCAL, STT_FILE):
+						/* file name; unused here */
+						break;
+					case ELF_ST_INFO(STB_LOCAL, STT_SECTION):
+						/* section name; unused here */
+						break;
+					default:
+						break;
+					}
+				}
+				if (!Symbols_Set(symbols, symbolcount, strings))
+				{
+					free(symbols);
+					free(strings);
+				}
+			}
+		}
 	}
 
 	/*--- Create the bootinfo structure ---*/
-- 
2.24.0


--nextPart47411014.jKvtMvv4xN--






Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/