libmach
diff --git a/src/libmach/dwarfpubnames.c b/src/libmach/dwarfpubnames.c
new file mode 100644
index 0000000..b09d286
--- /dev/null
+++ b/src/libmach/dwarfpubnames.c
@@ -0,0 +1,76 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "elf.h"
+#include "dwarf.h"
+
+static int
+_dwarfnametounit(Dwarf *d, char *name, DwarfBlock *bl, DwarfSym *s)
+{
+	int vers;
+	ulong len, unit, off;
+	uchar *next;
+	char *str;
+	DwarfBuf b;
+
+	b.d = d;
+	b.p = bl->data;
+	b.ep = b.p + bl->len;
+
+	while(b.p < b.ep){
+		len = dwarfget4(&b);
+		if(len > b.ep-b.p){
+			werrstr("bad length in dwarf name header");
+			return -1;
+		}
+		next = b.p + len;
+		vers = dwarfget2(&b);
+		if(vers != 1 && vers != 2){
+			werrstr("bad version %d in dwarf name header", vers);
+			return -1;
+		}
+		unit = dwarfget4(&b);
+		dwarfget4(&b);	/* unit length */
+		while(b.p < next){
+			off = dwarfget4(&b);
+			if(off == 0)
+				break;
+			str = dwarfgetstring(&b);
+			if(strcmp(str, name) == 0){
+				if(dwarfenumunit(d, unit, s) < 0)
+					return -1;
+				if(unit + off >= s->b.ep - d->info.data){
+					werrstr("bad offset in name entry");
+					return -1;
+				}
+				s->b.p = d->info.data + unit + off;
+				if(dwarfnextsym(d, s, 1) < 0)
+					return -1;
+				if(s->attrs.name==nil || strcmp(s->attrs.name, name)!=0){
+					werrstr("unexpected name %#q in lookup for %#q", s->attrs.name, name);
+					return -1;
+				}
+				return 0;
+			}
+		}
+		b.p = next;
+	}
+	werrstr("unknown name '%s'", name);
+	return -1;
+}
+
+int
+dwarflookupname(Dwarf *d, char *name, DwarfSym *sym)
+{
+	return _dwarfnametounit(d, name, &d->pubnames, sym);
+}
+
+/*
+
+int
+dwarflookuptype(Dwarf *d, char *name, DwarfSym *sym)
+{
+	return _dwarfnametounit(d, name, &d->pubtypes, sym);
+}
+
+ */