// See ../src/libmach/LICENSE #ifndef _MACH_H_ #define _MACH_H_ 1 #if defined(__cplusplus) extern "C" { #endif AUTOLIB(mach) /* * Architecture-dependent application data. * * The code assumes that u64int is big enough to hold * an address on any system of interest as well as any * register. * * Supported architectures: * * MIPS R3000 * Motorola 68020 * Intel 386 * SPARC * PowerPC (limited) * ARM (limited) * Intel 960 (limited) * AT&T 3210 DSP (limited) * MIPS2 (R4000) */ typedef struct Fhdr Fhdr; typedef struct Loc Loc; typedef struct Mach Mach; typedef struct Map Map; typedef struct Regdesc Regdesc; typedef struct Regs Regs; typedef struct Seg Seg; typedef struct Symbol Symbol; typedef struct Symtype Symtype; typedef int (*Tracer)(Map*, Regs*, u64int, u64int, Symbol*, int); extern Mach *mach; extern Mach *machcpu; /* * Byte-order data layout manipulation. * swap.c ieee.c */ u16int beswap2(u16int u); u32int beswap4(u32int u); u64int beswap8(u64int u); int beieeeftoa32(char*, uint, void*); int beieeeftoa64(char*, uint, void*); int beieeeftoa80(char*, uint, void*); u16int leswap2(u16int u); u32int leswap4(u32int u); u64int leswap8(u64int u); int leieeeftoa32(char *a, uint n, void *v); int leieeeftoa64(char *a, uint n, void *v); int leieeeftoa80(char *a, uint n, void *v); u16int beload2(uchar*); u32int beload4(uchar*); u64int beload8(uchar*); u16int leload2(uchar*); u32int leload4(uchar*); u64int leload8(uchar*); int ieeeftoa32(char *a, uint n, u32int u); int ieeeftoa64(char *a, uint n, u32int h, u32int u); /* * Machine-independent access to an executable image. * map.c */ struct Seg { char *name; char *file; uchar *p; int fd; int pid; u64int base; u64int size; u64int offset; int (*rw)(Map*, Seg*, u64int, void*, uint, int); }; struct Map { int nseg; Seg *seg; }; struct Regs { int (*rw)(Regs*, char*, u64int*, int); }; typedef struct UregRegs UregRegs; struct UregRegs { Regs r; uchar *ureg; }; int _uregrw(Regs*, char*, u64int*, int); typedef struct PidRegs PidRegs; struct PidRegs { Regs r; int pid; }; Map* allocmap(void); int addseg(Map *map, Seg seg); int findseg(Map *map, char *name, char *file); int addrtoseg(Map *map, u64int addr, Seg *seg); int addrtosegafter(Map *map, u64int addr, Seg *seg); void removeseg(Map *map, int i); void freemap(Map*); int get1(Map *map, u64int addr, uchar *a, uint n); int get2(Map *map, u64int addr, u16int *u); int get4(Map *map, u64int addr, u32int *u); int get8(Map *map, u64int addr, u64int *u); int geta(Map *map, u64int addr, u64int *u); int put1(Map *map, u64int addr, uchar *a, uint n); int put2(Map *map, u64int addr, u16int u); int put4(Map *map, u64int addr, u32int u); int put8(Map *map, u64int addr, u64int u); int rget(Regs*, char*, u64int*); int rput(Regs*, char*, u64int); /* * A location is either a memory address or a register. * It is useful to be able to specify constant values that * originate from outside the register set and memory, * hence LCONST. If the register values are known, then * we can dispense with LOFFSET, but it's useful to be able * to look up local symbols (via findlsym) with locations * like 8(BP). * * loc.c */ enum { /* location type */ LNONE, LREG, /* register */ LADDR, /* absolute address */ LCONST, /* constant (an anonymous readonly location) */ LOFFSET /* dereference offset + register ptr */ }; struct Loc { uint type; /* LNONE, ... */ char *reg; /* LREG */ u64int addr; /* LADDR, CONST */ long offset; /* LOFFSET */ }; int lget1(Map *map, Regs *regs, Loc loc, uchar *a, uint n); int lget2(Map *map, Regs *regs, Loc loc, u16int *v); int lget4(Map *map, Regs *regs, Loc loc, u32int *v); int lget8(Map *map, Regs *regs, Loc loc, u64int *v); int lgeta(Map *map, Regs *regs, Loc loc, u64int *v); int lput1(Map *map, Regs *regs, Loc loc, uchar *a, uint n); int lput2(Map *map, Regs *regs, Loc loc, u16int v); int lput4(Map *map, Regs *regs, Loc loc, u32int v); int lput8(Map *map, Regs *regs, Loc loc, u64int v); Loc locnone(void); Loc locaddr(u64int addr); Loc locconst(u64int con); Loc locreg(char*); Loc locindir(char*, long); /* * Executable file parsing. * * An Fhdr represents an open file image. * The contents are a grab bag of constants used for the * various file types. Not all elements are used by all * file types. * * crackadotplan9.c crackadotunix.c * crackelf.c crackdwarf.c */ enum { /* file types */ FNONE, FEXEC, /* executable image */ FLIB, /* library */ FOBJ, /* object file */ FRELOC, /* relocatable executable */ FSHLIB, /* shared library */ FSHOBJ, /* shared object */ FCORE, /* core dump */ FBOOT, /* bootable image */ FKERNEL, /* kernel image */ NFTYPE, /* abi types */ ANONE = 0, APLAN9, ALINUX, AFREEBSD, AMACH, NATYPE }; /* I wish this could be kept in stabs.h */ struct Stab { uchar *stabbase; uint stabsize; char *strbase; uint strsize; u16int (*e2)(uchar*); u32int (*e4)(uchar*); }; struct Fhdr { int fd; /* file descriptor */ char *filename; /* file name */ Mach *mach; /* machine */ char *mname; /* 386, power, ... */ uint mtype; /* machine type M386, ... */ char *fname; /* core, executable, boot image, ... */ uint ftype; /* file type FCORE, ... */ char *aname; /* abi name */ uint atype; /* abi type ALINUX, ... */ ulong magic; /* magic number */ u64int txtaddr; /* text address */ u64int entry; /* entry point */ u64int txtsz; /* text size */ u64int txtoff; /* text offset in file */ u64int dataddr; /* data address */ u64int datsz; /* data size */ u64int datoff; /* data offset in file */ u64int bsssz; /* bss size */ u64int symsz; /* symbol table size */ u64int symoff; /* symbol table offset in file */ u64int sppcsz; /* size of sp-pc table */ u64int sppcoff; /* offset of sp-pc table in file */ u64int lnpcsz; /* size of line number-pc table */ u64int lnpcoff; /* size of line number-pc table */ void *elf; /* handle to elf image */ void *dwarf; /* handle to dwarf image */ void *macho; /* handle to mach-o image */ struct Stab stabs; uint pid; /* for core files */ char *prog; /* program name, for core files */ char *cmdline; /* command-line that produced core */ struct { /* thread state for core files */ uint id; void *ureg; } *thread; uint nthread; /* private */ Symbol *sym; /* cached list of symbols */ Symbol **byname; Symbol **byxname; uint nsym; Symbol *esym; /* elf symbols */ uint nesym; ulong base; /* base address for relocatables */ Fhdr *next; /* link to next fhdr (internal) */ /* file mapping */ int (*map)(Fhdr*, u64int, Map*, Regs**); /* debugging symbol access; see below */ int (*syminit)(Fhdr*); void (*symclose)(Fhdr*); int (*pc2file)(Fhdr*, u64int, char*, uint, ulong*); int (*file2pc)(Fhdr*, char*, u64int, u64int*); int (*line2pc)(Fhdr*, u64int, ulong, u64int*); int (*lookuplsym)(Fhdr*, Symbol*, char*, Symbol*); int (*indexlsym)(Fhdr*, Symbol*, uint, Symbol*); int (*findlsym)(Fhdr*, Symbol*, Loc, Symbol*); int (*unwind)(Fhdr*, Map*, Regs*, u64int*, Symbol*); }; Fhdr* crackhdr(char *file, int mode); void uncrackhdr(Fhdr *hdr); int crackelf(int fd, Fhdr *hdr); int crackmacho(int fd, Fhdr *hdr); Regs* coreregs(Fhdr*, uint); int symopen(Fhdr*); int symdwarf(Fhdr*); int symelf(Fhdr*); int symstabs(Fhdr*); int symmacho(Fhdr*); void symclose(Fhdr*); int mapfile(Fhdr *fp, u64int base, Map *map, Regs **regs); void unmapfile(Fhdr *fp, Map *map); /* * Process manipulation. */ int mapproc(int pid, Map *map, Regs **regs); void unmapproc(Map *map); int detachproc(int pid); int ctlproc(int pid, char *msg); int procnotes(int pid, char ***notes); char* proctextfile(int pid); /* * Command-line debugger help */ extern Fhdr *symhdr; extern Fhdr *corhdr; extern char *symfil; extern char *corfil; extern int corpid; extern Regs *correg; extern Map *symmap; extern Map *cormap; int attachproc(int pid); int attachcore(Fhdr *hdr); int attachargs(int argc, char **argv, int omode, int); int attachdynamic(int); /* * Machine descriptions. * * mach.c * mach386.c dis386.c * machsparc.c dissparc.c * ... */ /* * Register sets. The Regs are opaque, accessed by using * the reglist (and really the accessor functions). */ enum { /* must be big enough for all machine register sets */ REGSIZE = 256, RINT = 0<<0, RFLT = 1<<0, RRDONLY = 1<<1 }; struct Regdesc { char *name; /* register name */ uint offset; /* offset in b */ uint flags; /* RINT/RFLT/RRDONLY */ uint format; /* print format: 'x', 'X', 'f', 'z', 'Z' */ }; enum { /* machine types */ MNONE, MMIPS, /* MIPS R3000 */ MSPARC, /* SUN SPARC */ M68000, /* Motorola 68000 */ M386, /* Intel 32-bit x86*/ M960, /* Intel 960 */ M3210, /* AT&T 3210 DSP */ MMIPS2, /* MIPS R4000 */ M29000, /* AMD 29000 */ MARM, /* ARM */ MPOWER, /* PowerPC */ MALPHA, /* DEC/Compaq Alpha */ MAMD64, /* AMD64 */ NMTYPE }; struct Mach { char *name; /* "386", ... */ uint type; /* M386, ... */ Regdesc *reglist; /* register set */ uint regsize; /* size of register set in bytes */ uint fpregsize; /* size of fp register set in bytes */ char *pc; /* name of program counter */ char *sp; /* name of stack pointer */ char *fp; /* name of frame pointer */ char *link; /* name of link register */ char *sbreg; /* name of static base */ ulong sb; /* value of static base */ uint pgsize; /* page size */ u64int kbase; /* kernel base address for Plan 9 */ u64int ktmask; /* ktzero = kbase & ~ktmask */ uint pcquant; /* pc quantum */ uint szaddr; /* size of pointer in bytes */ uint szreg; /* size of integer register */ uint szfloat; /* size of float */ uint szdouble; /* size of double */ char** windreg; /* unwinding registers */ uint nwindreg; uchar bpinst[4]; /* break point instruction */ uint bpsize; /* size of bp instruction */ int (*foll)(Map*, Regs*, u64int, u64int*); /* follow set */ char* (*exc)(Map*, Regs*); /* last exception */ int (*unwind)(Map*, Regs*, u64int*, Symbol*); /* cvt to local byte order */ u16int (*swap2)(u16int); u32int (*swap4)(u32int); u64int (*swap8)(u64int); int (*ftoa32)(char*, uint, void*); int (*ftoa64)(char*, uint, void*); int (*ftoa80)(char*, uint, void*); /* disassembly */ int (*das)(Map*, u64int, char, char*, int); /* symbolic */ int (*kendas)(Map*, u64int, char, char*, int); /* symbolic */ int (*codas)(Map*, u64int, char, char*, int); int (*hexinst)(Map*, u64int, char*, int); /* hex */ int (*instsize)(Map*, u64int); /* instruction size */ }; Mach *machbyname(char*); Mach *machbytype(uint); extern Mach mach386; extern Mach machsparc; extern Mach machmips; extern Mach machpower; extern Mach machamd64; /* * Debugging symbols and type information. * (Not all objects include type information.) * * sym.c */ enum { /* symbol table classes */ CNONE, CAUTO, /* stack variable */ CPARAM, /* function parameter */ CTEXT, /* text segment */ CDATA, /* data segment */ CANY }; struct Symbol { char *name; /* name of symbol */ char *xname; /* demangled name */ /* Symtype *typedesc; /* type info, if any */ Loc loc; /* location of symbol */ Loc hiloc; /* location of end of symbol */ char class; /* CAUTO, ... */ char type; /* type letter from a.out.h */ Fhdr *fhdr; /* where did this come from? */ uint index; /* in by-address list */ /* private use by various symbol implementations */ union { struct { uint unit; uint uoff; } dwarf; struct { uint i; uint locals; char *dir; char *file; schar frameptr; uint framesize; } stabs; } u; void *aux; /* for use by client */ }; /* look through all currently cracked Fhdrs calling their fns */ int pc2file(u64int pc, char *file, uint nfile, ulong *line); int file2pc(char *file, ulong line, u64int *addr); int line2pc(u64int basepc, ulong line, u64int *pc); int fnbound(u64int pc, u64int *bounds); int fileline(u64int pc, char *a, uint n); int pc2line(u64int pc, ulong *line); int lookupsym(char *fn, char *var, Symbol *s); int indexsym(uint ndx, Symbol *s); int findsym(Loc loc, uint class, Symbol *s); int findexsym(Fhdr*, uint, Symbol*); int lookuplsym(Symbol *s1, char *name, Symbol *s2); int indexlsym(Symbol *s1, uint ndx, Symbol *s2); int findlsym(Symbol *s1, Loc loc, Symbol *s); int symoff(char *a, uint n, u64int addr, uint class); int unwindframe(Map *map, Regs *regs, u64int *next, Symbol*); void _addhdr(Fhdr*); void _delhdr(Fhdr*); extern Fhdr* fhdrlist; Fhdr* findhdr(char*); Symbol* flookupsym(Fhdr*, char*); Symbol* ffindsym(Fhdr*, Loc, uint); Symbol* _addsym(Fhdr*, Symbol*); char* demangle(char*, char*, int); char* demanglegcc3(char*, char*); char* demanglegcc2(char*, char*); /* * Stack frame walking. * * frame.c */ int stacktrace(Map*, Regs*, Tracer); int windindex(char*); Loc* windreglocs(void); /* * Debugger help. */ int localaddr(Map *map, Regs *regs, char *fn, char *var, u64int *val); int fpformat(Map *map, Regdesc *reg, char *a, uint n, uint code); char* _hexify(char*, u64int, int); int locfmt(Fmt*); int loccmp(Loc*, Loc*); int locsimplify(Map *map, Regs *regs, Loc loc, Loc *newloc); Regdesc* regdesc(char*); extern int machdebug; #if defined(__cplusplus) } #endif #endif