libmach
diff --git a/src/libmach/dwarf.h b/src/libmach/dwarf.h
new file mode 100644
index 0000000..0836523
--- /dev/null
+++ b/src/libmach/dwarf.h
@@ -0,0 +1,460 @@
+typedef struct Dwarf Dwarf;
+typedef struct DwarfAttrs DwarfAttrs;
+typedef struct DwarfBlock DwarfBlock;
+typedef struct DwarfBuf DwarfBuf;
+typedef struct DwarfExpr DwarfExpr;
+typedef struct DwarfSym DwarfSym;
+typedef union DwarfVal DwarfVal;
+
+enum
+{
+	TagArrayType = 0x01,
+	TagClassType = 0x02,
+	TagEntryPoint = 0x03,
+	TagEnumerationType = 0x04,
+	TagFormalParameter = 0x05,
+	TagImportedDeclaration = 0x08,
+	TagLabel = 0x0A,
+	TagLexDwarfBlock = 0x0B,
+	TagMember = 0x0D,
+	TagPointerType = 0x0F,
+	TagReferenceType = 0x10,
+	TagCompileUnit = 0x11,
+	TagStringType = 0x12,
+	TagStructType = 0x13,
+	TagSubroutineType = 0x15,
+	TagTypedef = 0x16,
+	TagUnionType = 0x17,
+	TagUnspecifiedParameters = 0x18,
+	TagVariant = 0x19,
+	TagCommonDwarfBlock = 0x1A,
+	TagCommonInclusion = 0x1B,
+	TagInheritance = 0x1C,
+	TagInlinedSubroutine = 0x1D,
+	TagModule = 0x1E,
+	TagPtrToMemberType = 0x1F,
+	TagSetType = 0x20,
+	TagSubrangeType = 0x21,
+	TagWithStmt = 0x22,
+	TagAccessDeclaration = 0x23,
+	TagBaseType = 0x24,
+	TagCatchDwarfBlock = 0x25,
+	TagConstType = 0x26,
+	TagConstant = 0x27,
+	TagEnumerator = 0x28,
+	TagFileType = 0x29,
+	TagFriend = 0x2A,
+	TagNamelist = 0x2B,
+	TagNamelistItem = 0x2C,
+	TagPackedType = 0x2D,
+	TagSubprogram = 0x2E,
+	TagTemplateTypeParameter = 0x2F,
+	TagTemplateValueParameter = 0x30,
+	TagThrownType = 0x31,
+	TagTryDwarfBlock = 0x32,
+	TagVariantPart = 0x33,
+	TagVariable = 0x34,
+	TagVolatileType = 0x35,
+	TagDwarfProcedure = 0x36,
+	TagRestrictType = 0x37,
+	TagInterfaceType = 0x38,
+	TagNamespace = 0x39,
+	TagImportedModule = 0x3A,
+	TagUnspecifiedType = 0x3B,
+	TagPartialUnit = 0x3C,
+	TagImportedUnit = 0x3D,
+	TagMutableType = 0x3E,
+
+	TypeAddress = 0x01,
+	TypeBoolean = 0x02,
+	TypeComplexFloat = 0x03,
+	TypeFloat = 0x04,
+	TypeSigned = 0x05,
+	TypeSignedChar = 0x06,
+	TypeUnsigned = 0x07,
+	TypeUnsignedChar = 0x08,
+	TypeImaginaryFloat = 0x09,
+
+	AccessPublic = 0x01,
+	AccessProtected = 0x02,
+	AccessPrivate = 0x03,
+
+	VisLocal = 0x01,
+	VisExported = 0x02,
+	VisQualified = 0x03,
+
+	VirtNone = 0x00,
+	VirtVirtual = 0x01,
+	VirtPureVirtual = 0x02,
+
+	LangC89 = 0x0001,
+	LangC = 0x0002,
+	LangAda83 = 0x0003,
+	LangCplusplus = 0x0004,
+	LangCobol74 = 0x0005,
+	LangCobol85 = 0x0006,
+	LangFortran77 = 0x0007,
+	LangFortran90 = 0x0008,
+	LangPascal83 = 0x0009,
+	LangModula2 = 0x000A,
+	LangJava = 0x000B,
+	LangC99 = 0x000C,
+	LangAda95 = 0x000D,
+	LangFortran95 = 0x000E,
+	LangPLI = 0x000F,
+	// 0x8000-0xFFFF reserved
+
+	IdCaseSensitive = 0x00,
+	IdCaseUpper = 0x01,
+	IdCaseLower = 0x02,
+	IdCaseInsensitive = 0x03,
+
+	CallingNormal = 0x01,
+	CallingProgram = 0x02,
+	CallingNocall = 0x03,
+	// 0x40-0xFF reserved
+
+	InNone = 0x00,
+	InInlined = 0x01,
+	InDeclaredNotInlined = 0x02,
+	InDeclaredInlined = 0x03,
+
+	OrderRowMajor = 0x00,
+	OrderColumnMajor = 0x01,
+
+	DiscLabel = 0x00,
+	DiscRange = 0x01,
+
+	TReference = 1<<0,
+	TBlock = 1<<1,
+	TConstant = 1<<2,
+	TString = 1<<3,
+	TFlag = 1<<4,
+	TAddress = 1<<5,
+
+	OpAddr = 0x03,	// 1 op, const addr
+	OpDeref = 0x06,
+	OpConst1u = 0x08,	// 1 op, 1 byte const
+	OpConst1s = 0x09,	//	" signed
+	OpConst2u = 0x0A,	// 1 op, 2 byte const 
+	OpConst2s = 0x0B,	//	" signed
+	OpConst4u = 0x0C,	// 1 op, 4 byte const
+	OpConst4s = 0x0D,	//	" signed
+	OpConst8u = 0x0E,	// 1 op, 8 byte const
+	OpConst8s = 0x0F,	//	" signed
+	OpConstu = 0x10,	// 1 op, LEB128 const
+	OpConsts = 0x11,	//	" signed
+	OpDup = 0x12,
+	OpDrop = 0x13,
+	OpOver = 0x14,
+	OpPick = 0x15,		// 1 op, 1 byte stack index
+	OpSwap = 0x16,
+	OpRot = 0x17,
+	OpXderef = 0x18,
+	OpAbs = 0x19,
+	OpAnd = 0x1A,
+	OpDiv = 0x1B,
+	OpMinus = 0x1C,
+	OpMod = 0x1D,
+	OpMul = 0x1E,
+	OpNeg = 0x1F,
+	OpNot = 0x20,
+	OpOr = 0x21,
+	OpPlus = 0x22,
+	OpPlusUconst = 0x23,	// 1 op, ULEB128 addend
+	OpShl = 0x24,
+	OpShr = 0x25,
+	OpShra = 0x26,
+	OpXor = 0x27,
+	OpSkip = 0x2F,		// 1 op, signed 2-byte constant
+	OpBra = 0x28,		// 1 op, signed 2-byte constant
+	OpEq = 0x29,
+	OpGe = 0x2A,
+	OpGt = 0x2B,
+	OpLe = 0x2C,
+	OpLt = 0x2D,
+	OpNe = 0x2E,
+	OpLit0 = 0x30,
+		// OpLitN = OpLit0 + N for N = 0..31
+	OpReg0 = 0x50,
+		// OpRegN = OpReg0 + N for N = 0..31
+	OpBreg0 = 0x70,	// 1 op, signed LEB128 constant
+		// OpBregN = OpBreg0 + N for N = 0..31
+	OpRegx = 0x90,	// 1 op, ULEB128 register
+	OpFbreg = 0x91,	// 1 op, SLEB128 offset
+	OpBregx = 0x92,	// 2 op, ULEB128 reg, SLEB128 off
+	OpPiece = 0x93,	// 1 op, ULEB128 size of piece
+	OpDerefSize = 0x94,	// 1-byte size of data retrieved
+	OpXderefSize = 0x95,	// 1-byte size of data retrieved
+	OpNop = 0x96,
+	// next four new in Dwarf v3
+	OpPushObjAddr = 0x97,
+	OpCall2 = 0x98,	// 2-byte offset of DIE
+	OpCall4 = 0x99,	// 4-byte offset of DIE
+	OpCallRef = 0x9A,	// 4- or 8- byte offset of DIE
+	// 0xE0-0xFF reserved for user-specific
+};
+
+struct DwarfBlock
+{
+	uchar *data;
+	ulong len;
+};
+
+/* not for consumer use */
+struct DwarfBuf
+{
+	Dwarf *d;
+	uchar *p;
+	uchar *ep;
+	uint addrsize;
+};
+
+union DwarfVal
+{
+	char *s;
+	ulong c;
+	ulong r;
+	DwarfBlock b;
+};
+
+struct DwarfAttrs
+{
+	ulong	tag;
+	uchar	haskids;
+
+	/* whether we have it, along with type */
+	struct {
+		uchar	abstractorigin;
+		uchar	accessibility;
+		uchar	addrclass;
+		uchar	basetypes;
+		uchar	bitoffset;
+		uchar	bitsize;
+		uchar	bytesize;
+		uchar	calling;
+		uchar	commonref;
+		uchar	compdir;
+		uchar	constvalue;
+		uchar	containingtype;
+		uchar	count;
+		uchar	datamemberloc;
+		uchar	declcolumn;
+		uchar	declfile;
+		uchar	declline;
+		uchar	defaultvalue;
+		uchar	discr;
+		uchar	discrlist;
+		uchar	discrvalue;
+		uchar	encoding;
+		uchar	framebase;
+		uchar	friend;
+		uchar	highpc;
+		uchar	identifiercase;
+		uchar	import;
+		uchar	inlined;
+		uchar	isartificial;
+		uchar	isdeclaration;
+		uchar	isexternal;
+		uchar	isoptional;
+		uchar	isprototyped;
+		uchar	isvarparam;
+		uchar	language;
+		uchar	location;
+		uchar	lowerbound;
+		uchar	lowpc;
+		uchar	macroinfo;
+		uchar	name;
+		uchar	namelistitem;
+		uchar	ordering;
+		uchar	priority;
+		uchar	producer;
+		uchar	ranges;
+		uchar	returnaddr;
+		uchar	segment;
+		uchar	sibling;
+		uchar	specification;
+		uchar	startscope;
+		uchar	staticlink;
+		uchar	stmtlist;
+		uchar	stridesize;
+		uchar	stringlength;
+		uchar	type;
+		uchar	upperbound;
+		uchar	uselocation;
+		uchar	virtuality;
+		uchar	visibility;
+		uchar	vtableelemloc;
+	} have;
+
+	ulong	abstractorigin;
+	ulong	accessibility;
+	ulong	addrclass;
+	ulong	basetypes;
+	ulong	bitoffset;
+	ulong	bitsize;
+	ulong	bytesize;
+	ulong	calling;
+	ulong	commonref;
+	char*	compdir;
+	DwarfVal	constvalue;
+	ulong	containingtype;
+	ulong	count;
+	DwarfVal	datamemberloc;
+	ulong	declcolumn;
+	ulong	declfile;
+	ulong	declline;
+	ulong	defaultvalue;
+	ulong	discr;
+	DwarfBlock	discrlist;
+	ulong	discrvalue;
+	ulong	encoding;
+	DwarfVal	framebase;
+	ulong	friend;
+	ulong	highpc;
+	ulong	identifiercase;
+	ulong	import;
+	ulong	inlined;
+	uchar	isartificial;
+	uchar	isdeclaration;
+	uchar	isexternal;
+	uchar	isoptional;
+	uchar	isprototyped;
+	uchar	isvarparam;
+	ulong	language;
+	DwarfVal	location;
+	ulong	lowerbound;
+	ulong	lowpc;
+	ulong	macroinfo;
+	char*	name;
+	DwarfBlock	namelistitem;
+	ulong	ordering;
+	ulong	priority;
+	char*	producer;
+	ulong	ranges;
+	DwarfVal	returnaddr;
+	DwarfVal	segment;
+	ulong	sibling;
+	ulong	specification;
+	ulong	startscope;
+	DwarfVal	staticlink;
+	ulong	stmtlist;
+	ulong	stridesize;
+	DwarfVal	stringlength;
+	ulong	type;
+	ulong	upperbound;
+	DwarfVal	uselocation;
+	ulong	virtuality;
+	ulong	visibility;
+	DwarfVal	vtableelemloc;
+};
+
+enum
+{
+	RuleUndef,
+	RuleSame,
+	RuleCfaOffset,
+	RuleRegister,
+	RuleRegOff,
+	RuleLocation,
+};
+struct DwarfExpr
+{
+	int type;
+	long offset;
+	ulong reg;
+	DwarfBlock loc;
+};
+
+struct DwarfSym
+{
+	DwarfAttrs attrs;
+
+/* not for consumer use... */
+	DwarfBuf b;
+	ulong unit;
+	uint uoff;
+	ulong aoff;
+	int depth;
+	int allunits;
+	ulong nextunit;
+};
+
+
+Dwarf *dwarfopen(Elf *elf);
+void dwarfclose(Dwarf*);
+int dwarfaddrtounit(Dwarf*, ulong, ulong*);
+int dwarflookupfn(Dwarf*, ulong, ulong, DwarfSym*);
+int dwarflookupname(Dwarf*, char*, DwarfSym*);
+int dwarflookupnameinunit(Dwarf*, ulong, char*, DwarfSym*);
+int dwarflookupsubname(Dwarf*, DwarfSym*, char*, DwarfSym*);
+int dwarflookuptag(Dwarf*, ulong, ulong, DwarfSym*);
+int dwarfenumunit(Dwarf*, ulong, DwarfSym*);
+int dwarfseeksym(Dwarf*, ulong, ulong, DwarfSym*);
+int dwarfenum(Dwarf*, DwarfSym*);
+int dwarfnextsym(Dwarf*, DwarfSym*, int);
+int dwarfpctoline(Dwarf*, ulong, char**, char**, char**, ulong*, ulong*, ulong*);
+int dwarfunwind(Dwarf*, ulong, DwarfExpr*, DwarfExpr*, DwarfExpr*, int);
+ulong dwarfget1(DwarfBuf*);
+ulong dwarfget2(DwarfBuf*);
+ulong dwarfget4(DwarfBuf*);
+uvlong dwarfget8(DwarfBuf*);
+ulong dwarfget128(DwarfBuf*);
+long dwarfget128s(DwarfBuf*);
+ulong dwarfgetaddr(DwarfBuf*);
+int dwarfgetn(DwarfBuf*, uchar*, int);
+uchar *dwarfgetnref(DwarfBuf*, ulong);
+char *dwarfgetstring(DwarfBuf*);
+
+
+typedef struct DwarfAbbrev DwarfAbbrev;
+typedef struct DwarfAttr DwarfAttr;
+
+struct DwarfAttr
+{
+	ulong name;
+	ulong form;
+};
+
+struct DwarfAbbrev
+{
+	ulong num;
+	ulong tag;
+	uchar haskids;
+	DwarfAttr *attr;
+	int nattr;
+};
+
+struct Dwarf
+{
+	Elf *elf;
+	int fd;
+	char **reg;
+	int nreg;
+	int addrsize;
+	DwarfBlock abbrev;
+	DwarfBlock aranges;
+	DwarfBlock frame;
+	DwarfBlock info;
+	DwarfBlock line;
+	DwarfBlock pubnames;
+	DwarfBlock pubtypes;
+	DwarfBlock ranges;
+	DwarfBlock str;
+
+	/* little cache */
+	struct {
+		DwarfAbbrev *a;
+		int na;
+		ulong off;
+	} acache;
+};
+
+DwarfAbbrev *dwarfgetabbrev(Dwarf*, ulong, ulong);
+
+int dwarfgetinfounit(Dwarf*, ulong, DwarfBlock*);
+
+extern int dwarf386nregs;
+extern char *dwarf386regs[];
+extern char *dwarf386fp;
+