blob: 574122d9c29d20b53a27467613de74e25a1fb850 [file] [log] [blame]
// 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