[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
]
- Subject: [PATCH 5/6] Convert symbols from NetBSD kernel to format suitable for Hatari debugger
- From: Thorsten Otto <admin@xxxxxxxxxxx>
- Date: Mon, 25 Jul 2022 14:34:21 +0200
---
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--