DDB's "show struct" on sparc64 does not work because the boot loader
does not load the kernel's ELF section ".SUNW_ctf".
Adapt ofwboot to do so just like libsa already does on other platforms
(such as amd64) and therefore enable DDB utilise CTF information.
I needed this back when the earlier wireguard patchsets would panic due
to memory alignment issues; those issues were fixed independently
before I even started this diff, but here's the proper fix nonetheless.
mpi mentioned the boot loader issue after I poked him regarding missing
CTF information in DDB, the rest I managed to figure out myself afer
reading through libsa's loadfile_elf.c:ELFNAME(), i.e. elf64_exec() on
amd64, and simply copying the missing bits into ofwboot.
To test, drop to DDB and simply do `show struct timespec' for example or
pick a real panic/issue (mine disappeared):
OpenBSD/sparc64 (xxx) (console)
login: Stopped at db_enter+0x8: nop
ddb{0}> show struct timespec
struct timespec at 0x1361588 (16 bytes) {tv_sec = 0x100000081c3e008,
tv_nsec = 0
x9c23bf3030680003}
Feedback? OK?
diff --git a/sys/arch/sparc64/stand/ofwboot/elf64_exec.c
b/sys/arch/sparc64/stand/ofwboot/elf64_exec.c
index 887aa5745..5ccdc6e0c 100644
--- a/sys/arch/sparc64/stand/ofwboot/elf64_exec.c
+++ b/sys/arch/sparc64/stand/ofwboot/elf64_exec.c
@@ -204,11 +204,24 @@ elf64_exec(int fd, Elf_Ehdr *elf, u_int64_t *entryp, void
**ssymp, void **esymp)
printf("read section headers: %s\n", strerror(errno));
return (1);
}
+
+ size_t shstrsz = shp[elf->e_shstrndx].sh_size;
+ char *shstr = alloc(shstrsz);
+ if (lseek(fd, (off_t)shp[elf->e_shstrndx].sh_offset, SEEK_SET) == -1) {
+ printf("lseek section header string table: %s\n",
strerror(errno));
+ return 1;
+ }
+ if (read(fd, shstr, shstrsz) != shstrsz) {
+ printf("read section header string table: %s\n",
strerror(errno));
+ return 1;
+ }
+
for (i = 0; i < elf->e_shnum; i++, shp++) {
if (shp->sh_type == SHT_NULL)
continue;
if (shp->sh_type != SHT_SYMTAB
- && shp->sh_type != SHT_STRTAB) {
+ && shp->sh_type != SHT_STRTAB
+ && strcmp(shstr + shp->sh_name, ELF_CTF)) {
shp->sh_offset = 0;
continue;
}
@@ -244,7 +257,8 @@ elf64_exec(int fd, Elf_Ehdr *elf, u_int64_t *entryp, void
**ssymp, void **esymp)
off = size;
for (first = 1, i = 0; i < elf->e_shnum; i++, shp++) {
if (shp->sh_type == SHT_SYMTAB
- || shp->sh_type == SHT_STRTAB) {
+ || shp->sh_type == SHT_STRTAB
+ || !strcmp(shstr + shp->sh_name, ELF_CTF)) {
if (first)
printf("symbols @ 0x%lx ", (u_long)addr);
printf("%s%d", first ? "" : "+", (int)shp->sh_size);
@@ -255,6 +269,7 @@ elf64_exec(int fd, Elf_Ehdr *elf, u_int64_t *entryp, void
**ssymp, void **esymp)
}
addr += ELF_ALIGN(shp->sh_size);
shp->sh_offset = off;
+ shp->sh_flags |= SHF_ALLOC;
off += ELF_ALIGN(shp->sh_size);
first = 0;
}
diff --git a/sys/arch/sparc64/stand/ofwboot/vers.c
b/sys/arch/sparc64/stand/ofwboot/vers.c
index cc2630e4e..2a743eee2 100644
--- a/sys/arch/sparc64/stand/ofwboot/vers.c
+++ b/sys/arch/sparc64/stand/ofwboot/vers.c
@@ -1 +1 @@
-const char version[] = "1.19";
+const char version[] = "1.20";