rsc | 0e3cc9f | 2004-04-19 19:26:19 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Architecture-dependent application data. |
| 3 | * |
| 4 | * The code assumes that ulong is big enough to hold |
| 5 | * an address on any system of interest as well as any |
| 6 | * register. Debugging 64-bit code on 32-bit machines |
| 7 | * will be interesting. |
| 8 | * |
| 9 | * Supported architectures: |
| 10 | * |
| 11 | * MIPS R3000 |
| 12 | * Motorola 68020 |
| 13 | * Intel 386 |
| 14 | * SPARC |
| 15 | * PowerPC (limited) |
| 16 | * ARM (limited) |
| 17 | * Intel 960 (limited) |
| 18 | * AT&T 3210 DSP (limited) |
| 19 | * MIPS2 (R4000) |
| 20 | */ |
| 21 | |
| 22 | typedef struct Fhdr Fhdr; |
| 23 | typedef struct Loc Loc; |
| 24 | typedef struct Mach Mach; |
| 25 | typedef struct Map Map; |
| 26 | typedef struct Regdesc Regdesc; |
| 27 | typedef struct Regs Regs; |
| 28 | typedef struct Seg Seg; |
| 29 | typedef struct Symbol Symbol; |
| 30 | typedef struct Symtype Symtype; |
| 31 | |
| 32 | typedef int (*Tracer)(Map*, Regs*, ulong, ulong, Symbol*, int); |
| 33 | |
| 34 | extern Mach *mach; |
| 35 | extern Mach *machcpu; |
| 36 | |
| 37 | /* |
| 38 | * Byte-order data layout manipulation. |
| 39 | * swap.c ieee.c |
| 40 | */ |
| 41 | u16int beswap2(u16int u); |
| 42 | u32int beswap4(u32int u); |
| 43 | u64int beswap8(u64int u); |
| 44 | int beieeeftoa32(char*, uint, void*); |
| 45 | int beieeeftoa64(char*, uint, void*); |
| 46 | int beieeeftoa80(char*, uint, void*); |
| 47 | |
| 48 | u16int leswap2(u16int u); |
| 49 | u32int leswap4(u32int u); |
| 50 | u64int leswap8(u64int u); |
| 51 | int leieeeftoa32(char *a, uint n, void *v); |
| 52 | int leieeeftoa64(char *a, uint n, void *v); |
| 53 | int leieeeftoa80(char *a, uint n, void *v); |
| 54 | |
| 55 | u16int beload2(uchar*); |
| 56 | u32int beload4(uchar*); |
| 57 | u64int beload8(uchar*); |
| 58 | |
| 59 | u16int leload2(uchar*); |
| 60 | u32int leload4(uchar*); |
| 61 | u64int leload8(uchar*); |
| 62 | |
| 63 | int ieeeftoa32(char *a, uint n, u32int u); |
| 64 | int ieeeftoa64(char *a, uint n, u32int h, u32int u); |
| 65 | |
| 66 | /* |
| 67 | * Machine-independent access to an executable image. |
| 68 | * map.c |
| 69 | */ |
| 70 | struct Seg |
| 71 | { |
| 72 | char *name; |
| 73 | char *file; |
| 74 | uchar *p; |
| 75 | int fd; |
| 76 | int pid; |
| 77 | ulong base; |
| 78 | ulong size; |
| 79 | ulong offset; |
| 80 | int (*rw)(Map*, Seg*, ulong, void*, uint, int); |
| 81 | }; |
| 82 | |
| 83 | struct Map |
| 84 | { |
| 85 | int nseg; |
| 86 | Seg *seg; |
| 87 | }; |
| 88 | |
| 89 | struct Regs |
| 90 | { |
| 91 | int (*rw)(Regs*, char*, ulong*, int); |
| 92 | }; |
| 93 | |
| 94 | typedef struct UregRegs UregRegs; |
| 95 | struct UregRegs |
| 96 | { |
| 97 | Regs r; |
| 98 | uchar *ureg; |
| 99 | }; |
| 100 | int _uregrw(Regs*, char*, ulong*, int); |
| 101 | |
| 102 | typedef struct PidRegs PidRegs; |
| 103 | struct PidRegs |
| 104 | { |
| 105 | Regs r; |
| 106 | int pid; |
| 107 | }; |
| 108 | |
| 109 | Map* allocmap(void); |
| 110 | int addseg(Map *map, Seg seg); |
| 111 | int findseg(Map *map, char *name, char *file); |
| 112 | int addrtoseg(Map *map, ulong addr, Seg *seg); |
| 113 | int addrtosegafter(Map *map, ulong addr, Seg *seg); |
| 114 | void removeseg(Map *map, int i); |
| 115 | void freemap(Map*); |
| 116 | |
| 117 | int get1(Map *map, ulong addr, uchar *a, uint n); |
| 118 | int get2(Map *map, ulong addr, u16int *u); |
| 119 | int get4(Map *map, ulong addr, u32int *u); |
| 120 | int get8(Map *map, ulong addr, u64int *u); |
| 121 | |
| 122 | int put1(Map *map, ulong addr, uchar *a, uint n); |
| 123 | int put2(Map *map, ulong addr, u16int u); |
| 124 | int put4(Map *map, ulong addr, u32int u); |
| 125 | int put8(Map *map, ulong addr, u64int u); |
| 126 | |
| 127 | int rget(Regs*, char*, ulong*); |
| 128 | int rput(Regs*, char*, ulong); |
| 129 | |
| 130 | /* |
| 131 | * A location is either a memory address or a register. |
| 132 | * It is useful to be able to specify constant values that |
| 133 | * originate from outside the register set and memory, |
| 134 | * hence LCONST. If the register values are known, then |
| 135 | * we can dispense with LOFFSET, but it's useful to be able |
| 136 | * to look up local symbols (via findlsym) with locations |
| 137 | * like 8(BP). |
| 138 | * |
| 139 | * loc.c |
| 140 | */ |
| 141 | |
| 142 | enum |
| 143 | { |
| 144 | /* location type */ |
| 145 | LNONE, |
| 146 | LREG, /* register */ |
| 147 | LADDR, /* absolute address */ |
| 148 | LCONST, /* constant (an anonymous readonly location) */ |
| 149 | LOFFSET, /* dereference offset + register ptr */ |
| 150 | }; |
| 151 | |
| 152 | struct Loc |
| 153 | { |
| 154 | uint type; /* LNONE, ... */ |
| 155 | char *reg; /* LREG */ |
| 156 | ulong addr; /* LADDR, CONST */ |
| 157 | long offset; /* LOFFSET */ |
| 158 | }; |
| 159 | |
| 160 | int lget1(Map *map, Regs *regs, Loc loc, uchar *a, uint n); |
| 161 | int lget2(Map *map, Regs *regs, Loc loc, u16int *v); |
| 162 | int lget4(Map *map, Regs *regs, Loc loc, u32int *v); |
| 163 | int lget8(Map *map, Regs *regs, Loc loc, u64int *v); |
| 164 | |
| 165 | int lput1(Map *map, Regs *regs, Loc loc, uchar *a, uint n); |
| 166 | int lput2(Map *map, Regs *regs, Loc loc, u16int v); |
| 167 | int lput4(Map *map, Regs *regs, Loc loc, u32int v); |
| 168 | int lput8(Map *map, Regs *regs, Loc loc, u64int v); |
| 169 | |
| 170 | Loc locnone(void); |
| 171 | Loc locaddr(ulong addr); |
| 172 | Loc locconst(ulong con); |
| 173 | Loc locreg(char*); |
| 174 | Loc locindir(char*, long); |
| 175 | |
| 176 | /* |
| 177 | * Executable file parsing. |
| 178 | * |
| 179 | * An Fhdr represents an open file image. |
| 180 | * The contents are a grab bag of constants used for the |
| 181 | * various file types. Not all elements are used by all |
| 182 | * file types. |
| 183 | * |
| 184 | * crackadotplan9.c crackadotunix.c |
| 185 | * crackelf.c crackdwarf.c |
| 186 | */ |
| 187 | enum |
| 188 | { |
| 189 | /* file types */ |
| 190 | FNONE, |
| 191 | FEXEC, /* executable image */ |
| 192 | FLIB, /* library */ |
| 193 | FOBJ, /* object file */ |
| 194 | FRELOC, /* relocatable executable */ |
| 195 | FSHLIB, /* shared library */ |
| 196 | FSHOBJ, /* shared object */ |
| 197 | FCORE, /* core dump */ |
| 198 | FBOOT, /* bootable image */ |
| 199 | FKERNEL, /* kernel image */ |
| 200 | NFTYPE, |
| 201 | |
| 202 | /* abi types */ |
| 203 | ANONE = 0, |
| 204 | APLAN9, |
| 205 | ALINUX, |
| 206 | AFREEBSD, |
| 207 | AMACH, |
| 208 | NATYPE |
| 209 | }; |
| 210 | |
| 211 | /* I wish this could be kept in stabs.h */ |
| 212 | struct Stab |
| 213 | { |
| 214 | uchar *stabbase; |
| 215 | uint stabsize; |
| 216 | char *strbase; |
| 217 | uint strsize; |
| 218 | u16int (*e2)(uchar*); |
| 219 | u32int (*e4)(uchar*); |
| 220 | }; |
| 221 | |
| 222 | struct Fhdr |
| 223 | { |
| 224 | int fd; /* file descriptor */ |
| 225 | char *filename; /* file name */ |
| 226 | Mach *mach; /* machine */ |
| 227 | char *mname; /* 386, power, ... */ |
| 228 | uint mtype; /* machine type M386, ... */ |
| 229 | char *fname; /* core, executable, boot image, ... */ |
| 230 | uint ftype; /* file type FCORE, ... */ |
| 231 | char *aname; /* abi name */ |
| 232 | uint atype; /* abi type ALINUX, ... */ |
| 233 | |
| 234 | ulong magic; /* magic number */ |
| 235 | ulong txtaddr; /* text address */ |
| 236 | ulong entry; /* entry point */ |
| 237 | ulong txtsz; /* text size */ |
| 238 | ulong txtoff; /* text offset in file */ |
| 239 | ulong dataddr; /* data address */ |
| 240 | ulong datsz; /* data size */ |
| 241 | ulong datoff; /* data offset in file */ |
| 242 | ulong bsssz; /* bss size */ |
| 243 | ulong symsz; /* symbol table size */ |
| 244 | ulong symoff; /* symbol table offset in file */ |
| 245 | ulong sppcsz; /* size of sp-pc table */ |
| 246 | ulong sppcoff; /* offset of sp-pc table in file */ |
| 247 | ulong lnpcsz; /* size of line number-pc table */ |
| 248 | ulong lnpcoff; /* size of line number-pc table */ |
rsc | cdf1805 | 2004-12-25 22:01:28 +0000 | [diff] [blame] | 249 | char *txtfil; /* text name, for core files */ |
rsc | 0e3cc9f | 2004-04-19 19:26:19 +0000 | [diff] [blame] | 250 | void *elf; /* handle to elf image */ |
| 251 | void *dwarf; /* handle to dwarf image */ |
| 252 | void *macho; /* handle to mach-o image */ |
| 253 | struct Stab stabs; |
| 254 | |
| 255 | /* private */ |
| 256 | Symbol *sym; /* cached list of symbols */ |
| 257 | Symbol **byname; |
| 258 | uint nsym; |
| 259 | Symbol *esym; /* elf symbols */ |
| 260 | Symbol **ebyname; |
| 261 | uint nesym; |
| 262 | ulong base; /* base address for relocatables */ |
| 263 | Fhdr *next; /* link to next fhdr (internal) */ |
| 264 | |
| 265 | /* file mapping */ |
| 266 | int (*map)(Fhdr*, ulong, Map*, Regs**); |
| 267 | |
| 268 | /* debugging symbol access; see below */ |
| 269 | int (*syminit)(Fhdr*); |
| 270 | void (*symclose)(Fhdr*); |
| 271 | |
| 272 | int (*pc2file)(Fhdr*, ulong, char*, uint, ulong*); |
| 273 | int (*file2pc)(Fhdr*, char*, ulong, ulong*); |
| 274 | int (*line2pc)(Fhdr*, ulong, ulong, ulong*); |
| 275 | |
| 276 | int (*lookuplsym)(Fhdr*, Symbol*, char*, Symbol*); |
| 277 | int (*indexlsym)(Fhdr*, Symbol*, uint, Symbol*); |
| 278 | int (*findlsym)(Fhdr*, Symbol*, Loc, Symbol*); |
| 279 | |
rsc | cdf1805 | 2004-12-25 22:01:28 +0000 | [diff] [blame] | 280 | int (*unwind)(Fhdr*, Map*, Regs*, ulong*, Symbol*); |
rsc | 0e3cc9f | 2004-04-19 19:26:19 +0000 | [diff] [blame] | 281 | }; |
| 282 | |
| 283 | Fhdr* crackhdr(char *file, int mode); |
| 284 | void uncrackhdr(Fhdr *hdr); |
| 285 | int crackelf(int fd, Fhdr *hdr); |
| 286 | int crackmacho(int fd, Fhdr *hdr); |
| 287 | |
| 288 | int syminit(Fhdr*); |
| 289 | int symdwarf(Fhdr*); |
| 290 | int symelf(Fhdr*); |
| 291 | int symstabs(Fhdr*); |
| 292 | int symmacho(Fhdr*); |
| 293 | |
| 294 | int mapfile(Fhdr *fp, ulong base, Map *map, Regs **regs); |
| 295 | void unmapfile(Fhdr *fp, Map *map); |
| 296 | |
| 297 | /* |
| 298 | * Process manipulation. |
| 299 | */ |
| 300 | int mapproc(int pid, Map *map, Regs **regs); |
| 301 | void unmapproc(Map *map); |
| 302 | int detachproc(int pid); |
| 303 | int ctlproc(int pid, char *msg); |
| 304 | int procnotes(int pid, char ***notes); |
| 305 | char* proctextfile(int pid); |
| 306 | |
| 307 | /* |
rsc | cdf1805 | 2004-12-25 22:01:28 +0000 | [diff] [blame] | 308 | * Command-line debugger help |
| 309 | */ |
| 310 | extern Fhdr *symhdr; |
| 311 | extern Fhdr *corhdr; |
| 312 | extern char *symfil; |
| 313 | extern char *corfil; |
| 314 | extern int corpid; |
| 315 | extern Regs *correg; |
| 316 | extern Map *symmap; |
| 317 | extern Map *cormap; |
| 318 | |
| 319 | int attachproc(int pid); |
| 320 | int attachcore(Fhdr *hdr); |
| 321 | int attachargs(int argc, char **argv, int omode); |
| 322 | |
| 323 | /* |
rsc | 0e3cc9f | 2004-04-19 19:26:19 +0000 | [diff] [blame] | 324 | * Machine descriptions. |
| 325 | * |
| 326 | * mach.c |
| 327 | * mach386.c dis386.c |
| 328 | * machsparc.c dissparc.c |
| 329 | * ... |
| 330 | */ |
| 331 | |
| 332 | /* |
| 333 | * Register sets. The Regs are opaque, accessed by using |
| 334 | * the reglist (and really the accessor functions). |
| 335 | */ |
| 336 | enum |
| 337 | { |
| 338 | /* must be big enough for all machine register sets */ |
| 339 | REGSIZE = 256, |
| 340 | |
| 341 | RINT = 0<<0, |
| 342 | RFLT = 1<<0, |
| 343 | RRDONLY = 1<<1, |
| 344 | }; |
| 345 | |
| 346 | struct Regdesc |
| 347 | { |
| 348 | char *name; /* register name */ |
| 349 | uint offset; /* offset in b */ |
| 350 | uint flags; /* RINT/RFLT/RRDONLY */ |
| 351 | uint format; /* print format: 'x', 'X', 'f', 'z', 'Z' */ |
| 352 | }; |
| 353 | |
| 354 | Regdesc* regdesc(char*); |
| 355 | |
| 356 | enum |
| 357 | { |
| 358 | /* machine types */ |
| 359 | MNONE, |
| 360 | MMIPS, /* MIPS R3000 */ |
| 361 | MSPARC, /* SUN SPARC */ |
| 362 | M68000, /* Motorola 68000 */ |
| 363 | M386, /* Intel 32-bit x86*/ |
| 364 | M960, /* Intel 960 */ |
| 365 | M3210, /* AT&T 3210 DSP */ |
| 366 | MMIPS2, /* MIPS R4000 */ |
| 367 | M29000, /* AMD 29000 */ |
| 368 | MARM, /* ARM */ |
| 369 | MPOWER, /* PowerPC */ |
| 370 | MALPHA, /* DEC/Compaq Alpha */ |
| 371 | NMTYPE |
| 372 | }; |
| 373 | |
| 374 | struct Mach |
| 375 | { |
| 376 | char *name; /* "386", ... */ |
| 377 | uint type; /* M386, ... */ |
| 378 | Regdesc *reglist; /* register set */ |
| 379 | uint regsize; /* size of register set in bytes */ |
| 380 | uint fpregsize; /* size of fp register set in bytes */ |
| 381 | char *pc; /* name of program counter */ |
| 382 | char *sp; /* name of stack pointer */ |
| 383 | char *fp; /* name of frame pointer */ |
| 384 | char *link; /* name of link register */ |
| 385 | char *sbreg; /* name of static base */ |
| 386 | ulong sb; /* value of static base */ |
| 387 | uint pgsize; /* page size */ |
| 388 | ulong kbase; /* kernel base address for Plan 9 */ |
| 389 | ulong ktmask; /* ktzero = kbase & ~ktmask */ |
| 390 | uint pcquant; /* pc quantum */ |
| 391 | uint szaddr; /* size of pointer in bytes */ |
| 392 | uint szreg; /* size of integer register */ |
| 393 | uint szfloat; /* size of float */ |
| 394 | uint szdouble; /* size of double */ |
| 395 | char** windreg; /* unwinding registers */ |
| 396 | uint nwindreg; |
| 397 | |
| 398 | uchar bpinst[4]; /* break point instruction */ |
| 399 | uint bpsize; /* size of bp instruction */ |
| 400 | |
| 401 | int (*foll)(Map*, Regs*, ulong, ulong*); /* follow set */ |
| 402 | char* (*exc)(Map*, Regs*); /* last exception */ |
rsc | cdf1805 | 2004-12-25 22:01:28 +0000 | [diff] [blame] | 403 | int (*unwind)(Map*, Regs*, ulong*, Symbol*); |
rsc | 0e3cc9f | 2004-04-19 19:26:19 +0000 | [diff] [blame] | 404 | |
| 405 | /* cvt to local byte order */ |
| 406 | u16int (*swap2)(u16int); |
| 407 | u32int (*swap4)(u32int); |
| 408 | u64int (*swap8)(u64int); |
| 409 | int (*ftoa32)(char*, uint, void*); |
| 410 | int (*ftoa64)(char*, uint, void*); |
| 411 | int (*ftoa80)(char*, uint, void*); |
| 412 | |
| 413 | /* disassembly */ |
| 414 | int (*das)(Map*, ulong, char, char*, int); /* symbolic */ |
| 415 | int (*kendas)(Map*, ulong, char, char*, int); /* symbolic */ |
| 416 | int (*codas)(Map*, ulong, char, char*, int); |
| 417 | int (*hexinst)(Map*, ulong, char*, int); /* hex */ |
| 418 | int (*instsize)(Map*, ulong); /* instruction size */ |
| 419 | }; |
| 420 | |
| 421 | Mach *machbyname(char*); |
| 422 | Mach *machbytype(uint); |
| 423 | |
| 424 | extern Mach mach386; |
| 425 | extern Mach machsparc; |
| 426 | extern Mach machmips; |
| 427 | extern Mach machpower; |
| 428 | |
| 429 | /* |
| 430 | * Debugging symbols and type information. |
| 431 | * (Not all objects include type information.) |
| 432 | * |
| 433 | * sym.c |
| 434 | */ |
| 435 | |
| 436 | enum |
| 437 | { |
| 438 | /* symbol table classes */ |
| 439 | CNONE, |
| 440 | CAUTO, /* stack variable */ |
| 441 | CPARAM, /* function parameter */ |
| 442 | CTEXT, /* text segment */ |
| 443 | CDATA, /* data segment */ |
| 444 | CANY, |
| 445 | }; |
| 446 | |
| 447 | struct Symbol |
| 448 | { |
| 449 | char *name; /* name of symbol */ |
| 450 | /* Symtype *typedesc; /* type info, if any */ |
| 451 | Loc loc; /* location of symbol */ |
| 452 | Loc hiloc; /* location of end of symbol */ |
| 453 | char class; /* CAUTO, ... */ |
| 454 | char type; /* type letter from a.out.h */ |
| 455 | Fhdr *fhdr; /* where did this come from? */ |
| 456 | uint index; /* in by-address list */ |
| 457 | |
| 458 | /* private use by various symbol implementations */ |
| 459 | union { |
| 460 | struct { |
| 461 | uint unit; |
| 462 | uint uoff; |
| 463 | } dwarf; |
| 464 | struct { |
| 465 | uint i; |
| 466 | uint locals; |
| 467 | char *dir; |
| 468 | char *file; |
| 469 | char frameptr; |
| 470 | uint framesize; |
| 471 | } stabs; |
| 472 | } u; |
| 473 | }; |
| 474 | |
| 475 | /* look through all currently cracked Fhdrs calling their fns */ |
| 476 | int pc2file(ulong pc, char *file, uint nfile, ulong *line); |
| 477 | int file2pc(char *file, ulong line, ulong *addr); |
| 478 | int line2pc(ulong basepc, ulong line, ulong *pc); |
| 479 | int fnbound(ulong pc, ulong *bounds); |
| 480 | int fileline(ulong pc, char *a, uint n); |
| 481 | int pc2line(ulong pc, ulong *line); |
| 482 | |
| 483 | int lookupsym(char *fn, char *var, Symbol *s); |
| 484 | int indexsym(uint ndx, Symbol *s); |
| 485 | int findsym(Loc loc, uint class, Symbol *s); |
| 486 | int findexsym(Fhdr*, uint, Symbol*); |
| 487 | |
| 488 | int lookuplsym(Symbol *s1, char *name, Symbol *s2); |
| 489 | int indexlsym(Symbol *s1, uint ndx, Symbol *s2); |
| 490 | int findlsym(Symbol *s1, Loc loc, Symbol *s); |
| 491 | int symoff(char *a, uint n, ulong addr, uint class); |
rsc | cdf1805 | 2004-12-25 22:01:28 +0000 | [diff] [blame] | 492 | int unwindframe(Map *map, Regs *regs, ulong *next, Symbol*); |
rsc | 0e3cc9f | 2004-04-19 19:26:19 +0000 | [diff] [blame] | 493 | |
| 494 | void _addhdr(Fhdr*); |
| 495 | void _delhdr(Fhdr*); |
rsc | 67e4fce | 2004-04-19 23:58:57 +0000 | [diff] [blame] | 496 | extern Fhdr* fhdrlist; |
rsc | cdf1805 | 2004-12-25 22:01:28 +0000 | [diff] [blame] | 497 | Fhdr* findhdr(char*); |
rsc | 0e3cc9f | 2004-04-19 19:26:19 +0000 | [diff] [blame] | 498 | |
| 499 | Symbol* flookupsym(Fhdr*, char*); |
| 500 | Symbol* ffindsym(Fhdr*, Loc, uint); |
| 501 | Symbol* addsym(Fhdr*, Symbol*); |
| 502 | |
| 503 | /* |
| 504 | * Stack frame walking. |
| 505 | * |
| 506 | * frame.c |
| 507 | */ |
| 508 | int stacktrace(Map*, Regs*, Tracer); |
| 509 | int windindex(char*); |
| 510 | Loc* windreglocs(void); |
| 511 | |
| 512 | /* |
| 513 | * Debugger help. |
| 514 | */ |
| 515 | int localaddr(Map *map, Regs *regs, char *fn, char *var, ulong *val); |
| 516 | int fpformat(Map *map, Regdesc *reg, char *a, uint n, uint code); |
| 517 | char* _hexify(char*, ulong, int); |
| 518 | int locfmt(Fmt*); |
| 519 | int loccmp(Loc*, Loc*); |
| 520 | int locsimplify(Map *map, Regs *regs, Loc loc, Loc *newloc); |
| 521 | |
rsc | cdf1805 | 2004-12-25 22:01:28 +0000 | [diff] [blame] | 522 | struct ps_prochandle |
| 523 | { |
| 524 | int pid; |
| 525 | }; |
| 526 | |
rsc | 0e3cc9f | 2004-04-19 19:26:19 +0000 | [diff] [blame] | 527 | extern int machdebug; |