| // 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 |