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";

Reply via email to