summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormatthew <matthew@openbsd.org>2014-10-09 08:21:48 +0000
committermatthew <matthew@openbsd.org>2014-10-09 08:21:48 +0000
commit4d814044acb43c292030e1bc8453d620ed54beea (patch)
tree1caa633f941d32943dd664b4969d4debb7c244de
parenttweak previous; (diff)
downloadwireguard-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/files3
-rw-r--r--sys/ddb/db_elf.c55
-rw-r--r--sys/lib/libsa/loadfile_elf.c28
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);
}