Patch below enables DWARF line decoding in ddb; e.g.,

  ddb{0}> trace
  Debugger() at Debugger+0x9 [../../../../arch/amd64/amd64/db_interface.c:405]
  ddb_sysctl() at ddb_sysctl+0x1b4 [../../../../ddb/db_usrreq.c:104]
  sys___sysctl() at sys___sysctl+0x216 [../../../../kern/kern_sysctl.c:229]
  syscall() at syscall+0x297 [../../../../sys/syscall_mi.h:84]
  --- syscall (number 202) ---
  end of kernel
  end trace frame: 0x7f7ffffcf1d7, count: -4
  acpi_pdirpa+0x4117aa:

Full set of instructions to apply and test (assuming amd64 MP):

  # Apply patch
  cd /usr/src/sys
  patch < /path/to/diff

  # Enable DEBUG="-g"
  $EDITOR conf/GENERIC
  # uncomment ``makeoptions DEBUG="-g"'' line and save

  # Build new kernel
  cd arch/amd64/conf
  config GENERIC.MP
  cd ../compile/GENERIC.MP
  make clean
  make

  # Build new boot(8)
  cd ../../stand/boot
  make install

  # Install new boot(8)
  cp /usr/mdec/boot /boot
  installboot -v /boot /usr/mdec/biosboot sd0

Now reboot and boot the "nbsd" kernel.  Stack traces in ddb should
include file and line numbers.

For file/line numbers to appear, all of the following are necessary:

  1. New boot(8)
  2. New kernel
  3. Kernel built with DEBUG="-g"
  4. Boot bsd.gdb instead of bsd

Under any other conditions, ddb should gracefully fall back to bare
stack traces.  I've tested most combinations, but additional testing
is appreciated.


Implementation details:

  - boot(8) now loads the ELF header string table so it can identify
    section names. It also now loads the ".debug_line" section into
    memory, and marks loaded sections with SHF_ALLOC.

  - ddb when generating stack traces now checks if there's a section
    named ".debug_line" that's marked SHF_ALLOC; and if so, ddb parses
    the section contents to translate program counter values into
    file/line pairs.

  - New boot(8) should be backwards compatible with old kernels, because
    they won't care if ".debug_line" is loaded; new bsd.gdb should be
    compatible with old boot(8) because ".debug_line" isn't normally
    marked SHF_ALLOC.

Index: conf/files
===================================================================
RCS file: /home/matthew/anoncvs/cvs/src/sys/conf/files,v
retrieving revision 1.577
diff -u -p -r1.577 files
--- conf/files  8 Sep 2014 04:40:30 -0000       1.577
+++ conf/files  29 Sep 2014 02:46:16 -0000
@@ -611,6 +611,7 @@ file        net/if_pppoe.c                  pppoe   
needs-flag
 file ddb/db_access.c                   ddb | kgdb
 file ddb/db_break.c                    ddb
 file ddb/db_command.c                  ddb
+file ddb/db_dwarf.c                    ddb
 file ddb/db_elf.c                      ddb
 file ddb/db_examine.c                  ddb
 file ddb/db_expr.c                     ddb
Index: ddb/db_elf.c
===================================================================
RCS file: /home/matthew/anoncvs/cvs/src/sys/ddb/db_elf.c,v
retrieving revision 1.11
diff -u -p -r1.11 db_elf.c
--- ddb/db_elf.c        14 Sep 2014 14:17:24 -0000      1.11
+++ ddb/db_elf.c        29 Sep 2014 02:46:16 -0000
@@ -32,12 +32,14 @@
  */
 
 #include <sys/types.h>
+#include <sys/stdint.h>
 #include <sys/param.h>
 #include <sys/systm.h>  
 #include <sys/exec.h>
 
 #include <machine/db_machdep.h>
 
+#include <ddb/db_dwarf.h>
 #include <ddb/db_sym.h>
 #include <ddb/db_output.h>
 #include <ddb/db_extern.h>
@@ -45,6 +47,7 @@
 #include <sys/exec_elf.h>
 
 static char *db_elf_find_strtab(db_symtab_t *);
+static char *db_elf_find_linetab(db_symtab_t *, size_t *);
 
 #define        STAB_TO_SYMSTART(stab)  ((Elf_Sym *)((stab)->start))
 #define        STAB_TO_SYMEND(stab)    ((Elf_Sym *)((stab)->end))
@@ -110,10 +113,10 @@ db_elf_sym_init(int symsize, void *symta
         *      . . .
         *      . . .
         *      last section header
-        *      first symbol or string table section
+        *      first symbol, string, or line table section
         *      . . .
         *      . . .
-        *      last symbol or string table section
+        *      last symbol, string, or line table section
         */
 
        /*
@@ -232,6 +235,30 @@ db_elf_find_strtab(db_symtab_t *stab)
 }
 
 /*
+ * Internal helper function - return a pointer to the line table
+ * for the current symbol table.
+ */
+static char *
+db_elf_find_linetab(db_symtab_t *stab, size_t *size)
+{
+       Elf_Ehdr *elf = STAB_TO_EHDR(stab);
+       Elf_Shdr *shp = STAB_TO_SHDR(stab, elf);
+       char *shstrtab;
+       int i;
+
+       shstrtab = (char *)elf + shp[elf->e_shstrndx].sh_offset;
+       for (i = 0; i < elf->e_shnum; i++) {
+               if ((shp[i].sh_flags & SHF_ALLOC) != 0 &&
+                   strcmp(".debug_line", shstrtab+shp[i].sh_name) == 0) {
+                       *size = shp[i].sh_size;
+                       return ((char *)elf + shp[i].sh_offset);
+               }
+       }
+
+       return (NULL);
+}
+
+/*
  * Lookup the symbol with the given name.
  */
 db_sym_t
@@ -350,11 +377,25 @@ boolean_t
 db_elf_line_at_pc(db_symtab_t *symtab, db_sym_t cursym, char **filename,
     int *linenum, db_expr_t off)
 {
+       const char *linetab;
+       size_t linetab_size;
 
-       /*
-        * XXX We don't support this (yet).
-        */
-       return (FALSE);
+       linetab = db_elf_find_linetab(symtab, &linetab_size);
+       if (linetab == NULL)
+               return (FALSE);
+
+       const char *dirname, *basename;
+       if (!db_dwarf_line_at_pc(linetab, linetab_size, off,
+           &dirname, &basename, linenum))
+               return (FALSE);
+
+       static char path[PATH_MAX];
+       if (dirname == NULL)
+               strlcpy(path, basename, sizeof(path));
+       else
+               snprintf(path, sizeof(path), "%s/%s", dirname, basename);
+       *filename = path;
+       return (TRUE);
 }
 
 /*
Index: lib/libsa/loadfile_elf.c
===================================================================
RCS file: /home/matthew/anoncvs/cvs/src/sys/lib/libsa/loadfile_elf.c,v
retrieving revision 1.8
diff -u -p -r1.8 loadfile_elf.c
--- lib/libsa/loadfile_elf.c    25 Feb 2014 21:40:39 -0000      1.8
+++ lib/libsa/loadfile_elf.c    11 Jul 2014 08:38:41 -0000
@@ -76,7 +76,7 @@ ELFNAME(exec)(int fd, Elf_Ehdr *elf, u_l
        int i;
        size_t sz;
        int first;
-       int havesyms;
+       int havesyms, havelines;
        paddr_t minp = ~0, maxp = 0, pos = 0;
        paddr_t offset = marks[MARK_START], shpp, elfp;
 
@@ -199,6 +199,21 @@ ELFNAME(exec)(int fd, Elf_Ehdr *elf, u_l
                shpp = maxp;
                maxp += roundup(sz, sizeof(Elf_Addr));
 
+               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) {
+                       WARN(("lseek section header string table"));
+                       FREE(shstr, shstrsz);
+                       FREE(shp, sz);
+                       return 1;
+               }
+               if (READ(fd, shstr, shstrsz) != shstrsz) {
+                       WARN(("read section header string table"));
+                       FREE(shstr, shstrsz);
+                       FREE(shp, sz);
+                       return 1;
+               }
+
                /*
                 * Now load the symbol sections themselves. Make sure the
                 * sections are aligned. Don't bother with string tables if
@@ -206,25 +221,28 @@ ELFNAME(exec)(int fd, Elf_Ehdr *elf, u_l
                 */
                off = roundup((sizeof(Elf_Ehdr) + sz), sizeof(Elf_Addr));
 
-               for (havesyms = i = 0; i < elf->e_shnum; i++)
+               for (havesyms = havelines = i = 0; i < elf->e_shnum; i++)
                        if (shp[i].sh_type == SHT_SYMTAB)
                                havesyms = 1;
 
                for (first = 1, i = 0; i < elf->e_shnum; i++) {
                        if (shp[i].sh_type == SHT_SYMTAB ||
-                           shp[i].sh_type == SHT_STRTAB) {
+                           shp[i].sh_type == SHT_STRTAB ||
+                           !strcmp(shstr + shp[i].sh_name, ".debug_line")) {
                                if (havesyms && (flags & LOAD_SYM)) {
                                        PROGRESS(("%s%ld", first ? " [" : "+",
                                            (u_long)shp[i].sh_size));
                                        if (lseek(fd, (off_t)shp[i].sh_offset,
                                            SEEK_SET) == -1) {
                                                WARN(("lseek symbols"));
+                                               FREE(shstr, shstrsz);
                                                FREE(shp, sz);
                                                return 1;
                                        }
                                        if (READ(fd, maxp, shp[i].sh_size) !=
                                            shp[i].sh_size) {
                                                WARN(("read symbols"));
+                                               FREE(shstr, shstrsz);
                                                FREE(shp, sz);
                                                return 1;
                                        }
@@ -232,6 +250,7 @@ ELFNAME(exec)(int fd, Elf_Ehdr *elf, u_l
                                maxp += roundup(shp[i].sh_size,
                                    sizeof(Elf_Addr));
                                shp[i].sh_offset = off;
+                               shp[i].sh_flags |= SHF_ALLOC;
                                off += roundup(shp[i].sh_size, 
sizeof(Elf_Addr));
                                first = 0;
                        }
@@ -242,6 +261,7 @@ ELFNAME(exec)(int fd, Elf_Ehdr *elf, u_l
                        if (havesyms && first == 0)
                                PROGRESS(("]"));
                }
+               FREE(shstr, shstrsz);
                FREE(shp, sz);
        }
 

Reply via email to