diff options
author | 2014-10-09 08:21:48 +0000 | |
---|---|---|
committer | 2014-10-09 08:21:48 +0000 | |
commit | 4d814044acb43c292030e1bc8453d620ed54beea (patch) | |
tree | 1caa633f941d32943dd664b4969d4debb7c244de | |
parent | tweak previous; (diff) | |
download | wireguard-openbsd-4d814044acb43c292030e1bc8453d620ed54beea.tar.xz wireguard-openbsd-4d814044acb43c292030e1bc8453d620ed54beea.zip |
ddb: add support for DWARF line number decoding
This allows ddb's "trace" command to include file and line numbers:
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:
For this to work, it requires using a new version of boot(8), and
booting a kernel with the .debug_line section present (e.g., building
with ``makeoptions DEBUG="-g"'' and then booting the bsd.gdb kernel
instead of the stripped bsd kernel).
Still a WIP, but no failure reports yet. Committing so further
development and testing can happen in tree.
prodding deraadt, guenther, mlarkin
ok mpi
-rw-r--r-- | sys/conf/files | 3 | ||||
-rw-r--r-- | sys/ddb/db_elf.c | 55 | ||||
-rw-r--r-- | sys/lib/libsa/loadfile_elf.c | 28 |
3 files changed, 74 insertions, 12 deletions
diff --git a/sys/conf/files b/sys/conf/files index 680b077acea..7862ae70303 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $OpenBSD: files,v 1.580 2014/10/09 03:36:32 tedu Exp $ +# $OpenBSD: files,v 1.581 2014/10/09 08:21:48 matthew Exp $ # $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -609,6 +609,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 diff --git a/sys/ddb/db_elf.c b/sys/ddb/db_elf.c index 277488a80aa..9ccb5f3fb98 100644 --- a/sys/ddb/db_elf.c +++ b/sys/ddb/db_elf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: db_elf.c,v 1.11 2014/09/14 14:17:24 jsg Exp $ */ +/* $OpenBSD: db_elf.c,v 1.12 2014/10/09 08:21:48 matthew Exp $ */ /* $NetBSD: db_elf.c,v 1.13 2000/07/07 21:55:18 jhawk Exp $ */ /*- @@ -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 *symtab, void *esymtab, const char *name) * . . . * . . . * 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); } /* diff --git a/sys/lib/libsa/loadfile_elf.c b/sys/lib/libsa/loadfile_elf.c index e9ee42440de..42d3adcb216 100644 --- a/sys/lib/libsa/loadfile_elf.c +++ b/sys/lib/libsa/loadfile_elf.c @@ -1,5 +1,5 @@ /* $NetBSD: loadfile.c,v 1.10 2000/12/03 02:53:04 tsutsui Exp $ */ -/* $OpenBSD: loadfile_elf.c,v 1.8 2014/02/25 21:40:39 miod Exp $ */ +/* $OpenBSD: loadfile_elf.c,v 1.9 2014/10/09 08:21:48 matthew Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -76,7 +76,7 @@ ELFNAME(exec)(int fd, Elf_Ehdr *elf, u_long *marks, int flags) 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_long *marks, int flags) 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_long *marks, int flags) */ 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_long *marks, int flags) 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_long *marks, int flags) if (havesyms && first == 0) PROGRESS(("]")); } + FREE(shstr, shstrsz); FREE(shp, sz); } |