libmach
diff --git a/src/libmach/dwarfopen.c b/src/libmach/dwarfopen.c
new file mode 100644
index 0000000..6122ae6
--- /dev/null
+++ b/src/libmach/dwarfopen.c
@@ -0,0 +1,107 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "elf.h"
+#include "dwarf.h"
+
+static int
+readblock(int fd, DwarfBlock *b, ulong off, ulong len)
+{
+	b->data = malloc(len);
+	if(b->data == nil)
+		return -1;
+	if(seek(fd, off, 0) < 0 || readn(fd, b->data, len) != len){
+		free(b->data);
+		b->data = nil;
+		return -1;
+	}
+	b->len = len;
+	return 0;
+}
+
+static int
+findsection(Elf *elf, char *name, ulong *off, ulong *len)
+{
+	ElfSect *s;
+
+	if((s = elfsection(elf, name)) == nil)
+		return -1;
+	*off = s->offset;
+	*len = s->size;
+	return s - elf->sect;
+}
+	
+static int
+loadsection(Elf *elf, char *name, DwarfBlock *b)
+{
+	ulong off, len;
+
+	if(findsection(elf, name, &off, &len) < 0)
+		return -1;
+	return readblock(elf->fd, b, off, len);
+}
+
+Dwarf*
+dwarfopen(Elf *elf)
+{
+	Dwarf *d;
+
+	if(elf == nil){
+		werrstr("nil elf passed to dwarfopen");
+		return nil;
+	}
+
+	d = mallocz(sizeof(Dwarf), 1);
+	if(d == nil)
+		return nil;
+
+	d->elf = elf;
+	if(loadsection(elf, ".debug_abbrev", &d->abbrev) < 0
+	|| loadsection(elf, ".debug_aranges", &d->aranges) < 0
+	|| loadsection(elf, ".debug_frame", &d->frame) < 0
+	|| loadsection(elf, ".debug_line", &d->line) < 0
+	|| loadsection(elf, ".debug_pubnames", &d->pubnames) < 0
+	|| loadsection(elf, ".debug_ranges", &d->ranges) < 0
+	|| loadsection(elf, ".debug_str", &d->str) < 0
+	|| loadsection(elf, ".debug_info", &d->info) < 0)
+		goto err;
+
+	/* make this a table once there are more */
+	switch(d->elf->hdr.machine){
+	case ElfMach386:
+		d->reg = dwarf386regs;
+		d->nreg = dwarf386nregs;
+		break;
+	default:
+		werrstr("unsupported machine");
+		goto err;
+	}
+
+	return d;
+
+err:
+	free(d->abbrev.data);
+	free(d->aranges.data);
+	free(d->frame.data);
+	free(d->line.data);
+	free(d->pubnames.data);
+	free(d->ranges.data);
+	free(d->str.data);
+	free(d->info.data);
+	free(d);
+	return nil;
+}
+
+void
+dwarfclose(Dwarf *d)
+{
+	free(d->abbrev.data);
+	free(d->aranges.data);
+	free(d->frame.data);
+	free(d->line.data);
+	free(d->pubnames.data);
+	free(d->ranges.data);
+	free(d->str.data);
+	free(d->info.data);
+	free(d);
+}