summaryrefslogtreecommitdiff
path: root/src/libmach
diff options
context:
space:
mode:
Diffstat (limited to 'src/libmach')
-rw-r--r--src/libmach/5.c92
-rw-r--r--src/libmach/5db.c1095
-rw-r--r--src/libmach/5obj.c171
-rw-r--r--src/libmach/6.c145
-rw-r--r--src/libmach/6obj.c173
-rw-r--r--src/libmach/8.c108
-rw-r--r--src/libmach/8db.c2447
-rw-r--r--src/libmach/8obj.c170
-rw-r--r--src/libmach/Makefile5
-rw-r--r--src/libmach/access.c241
-rw-r--r--src/libmach/darwin.c897
-rw-r--r--src/libmach/dragonfly.c62
-rw-r--r--src/libmach/elf.h182
-rw-r--r--src/libmach/executable.c1525
-rw-r--r--src/libmach/fakeobj.c29
-rw-r--r--src/libmach/freebsd.c62
-rw-r--r--src/libmach/linux.c1014
-rw-r--r--src/libmach/machdata.c477
-rw-r--r--src/libmach/macho.h100
-rw-r--r--src/libmach/map.c183
-rw-r--r--src/libmach/netbsd.c56
-rw-r--r--src/libmach/obj.c393
-rw-r--r--src/libmach/obj.h53
-rw-r--r--src/libmach/openbsd.c56
-rw-r--r--src/libmach/plan9.c72
-rw-r--r--src/libmach/setmach.c203
-rw-r--r--src/libmach/swap.c107
-rw-r--r--src/libmach/sym.c1883
-rw-r--r--src/libmach/windows.c87
29 files changed, 0 insertions, 12088 deletions
diff --git a/src/libmach/5.c b/src/libmach/5.c
deleted file mode 100644
index 9882c1acd..000000000
--- a/src/libmach/5.c
+++ /dev/null
@@ -1,92 +0,0 @@
-// Inferno libmach/5.c
-// http://code.google.com/p/inferno-os/source/browse/utils/libmach/5.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc.
-// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
-// Portions Copyright © 1997-1999 Vita Nuova Limited.
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-/*
- * arm definition
- */
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include "ureg_arm.h"
-#include <mach.h>
-
-#define REGOFF(x) (uintptr) (&((struct Ureg *) 0)->x)
-
-#define SP REGOFF(r13)
-#define PC REGOFF(pc)
-
-#define REGSIZE sizeof(struct Ureg)
-
-Reglist armreglist[] =
-{
- {"LINK", REGOFF(link), RINT|RRDONLY, 'X'},
- {"TYPE", REGOFF(type), RINT|RRDONLY, 'X'},
- {"PSR", REGOFF(psr), RINT|RRDONLY, 'X'},
- {"PC", PC, RINT, 'X'},
- {"SP", SP, RINT, 'X'},
- {"R15", PC, RINT, 'X'},
- {"R14", REGOFF(r14), RINT, 'X'},
- {"R13", REGOFF(r13), RINT, 'X'},
- {"R12", REGOFF(r12), RINT, 'X'},
- {"R11", REGOFF(r11), RINT, 'X'},
- {"R10", REGOFF(r10), RINT, 'X'},
- {"R9", REGOFF(r9), RINT, 'X'},
- {"R8", REGOFF(r8), RINT, 'X'},
- {"R7", REGOFF(r7), RINT, 'X'},
- {"R6", REGOFF(r6), RINT, 'X'},
- {"R5", REGOFF(r5), RINT, 'X'},
- {"R4", REGOFF(r4), RINT, 'X'},
- {"R3", REGOFF(r3), RINT, 'X'},
- {"R2", REGOFF(r2), RINT, 'X'},
- {"R1", REGOFF(r1), RINT, 'X'},
- {"R0", REGOFF(r0), RINT, 'X'},
- { 0 }
-};
-
- /* the machine description */
-Mach marm =
-{
- "arm",
- MARM, /* machine type */
- armreglist, /* register set */
- REGSIZE, /* register set size */
- 0, /* fp register set size */
- "PC", /* name of PC */
- "SP", /* name of SP */
- "R15", /* name of link register */
- "setR12", /* static base register name */
- 0, /* static base register value */
- 0x1000, /* page size */
- 0xC0000000, /* kernel base */
- 0, /* kernel text mask */
- 4, /* quantization of pc */
- 4, /* szaddr */
- 4, /* szreg */
- 4, /* szfloat */
- 8, /* szdouble */
-};
diff --git a/src/libmach/5db.c b/src/libmach/5db.c
deleted file mode 100644
index ae71dd90d..000000000
--- a/src/libmach/5db.c
+++ /dev/null
@@ -1,1095 +0,0 @@
-// Inferno libmach/5db.c
-// http://code.google.com/p/inferno-os/source/browse/utils/libmach/5db.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc.
-// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
-// Portions Copyright © 1997-1999 Vita Nuova Limited.
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include "ureg_arm.h"
-#include <mach.h>
-
-static int debug = 0;
-
-#define BITS(a, b) ((1<<(b+1))-(1<<a))
-
-#define LSR(v, s) ((ulong)(v) >> (s))
-#define ASR(v, s) ((long)(v) >> (s))
-#define ROR(v, s) (LSR((v), (s)) | (((v) & ((1 << (s))-1)) << (32 - (s))))
-
-
-
-typedef struct Instr Instr;
-struct Instr
-{
- Map *map;
- ulong w;
- ulong addr;
- uchar op; /* super opcode */
-
- uchar cond; /* bits 28-31 */
- uchar store; /* bit 20 */
-
- uchar rd; /* bits 12-15 */
- uchar rn; /* bits 16-19 */
- uchar rs; /* bits 0-11 (shifter operand) */
-
- long imm; /* rotated imm */
- char* curr; /* fill point in buffer */
- char* end; /* end of buffer */
- char* err; /* error message */
-};
-
-typedef struct Opcode Opcode;
-struct Opcode
-{
- char* o;
- void (*fmt)(Opcode*, Instr*);
- ulong (*foll)(Map*, Rgetter, Instr*, ulong);
- char* a;
-};
-
-static void format(char*, Instr*, char*);
-static char FRAMENAME[] = ".frame";
-
-/*
- * Arm-specific debugger interface
- */
-
-extern char *armexcep(Map*, Rgetter);
-static int armfoll(Map*, uvlong, Rgetter, uvlong*);
-static int arminst(Map*, uvlong, char, char*, int);
-static int armdas(Map*, uvlong, char*, int);
-static int arminstlen(Map*, uvlong);
-
-/*
- * Debugger interface
- */
-Machdata armmach =
-{
- {0, 0, 0, 0xD}, /* break point */
- 4, /* break point size */
-
- leswab, /* short to local byte order */
- leswal, /* long to local byte order */
- leswav, /* long to local byte order */
- risctrace, /* C traceback */
- riscframe, /* Frame finder */
- armexcep, /* print exception */
- 0, /* breakpoint fixup */
- 0, /* single precision float printer */
- 0, /* double precision float printer */
- armfoll, /* following addresses */
- arminst, /* print instruction */
- armdas, /* dissembler */
- arminstlen, /* instruction size */
-};
-
-char*
-armexcep(Map *map, Rgetter rget)
-{
- long c;
-
- c = (*rget)(map, "TYPE");
- switch (c&0x1f) {
- case 0x11:
- return "Fiq interrupt";
- case 0x12:
- return "Mirq interrupt";
- case 0x13:
- return "SVC/SWI Exception";
- case 0x17:
- return "Prefetch Abort/Data Abort";
- case 0x18:
- return "Data Abort";
- case 0x1b:
- return "Undefined instruction/Breakpoint";
- case 0x1f:
- return "Sys trap";
- default:
- return "Undefined trap";
- }
-}
-
-static
-char* cond[16] =
-{
- "EQ", "NE", "CS", "CC",
- "MI", "PL", "VS", "VC",
- "HI", "LS", "GE", "LT",
- "GT", "LE", 0, "NV"
-};
-
-static
-char* shtype[4] =
-{
- "<<", ">>", "->", "@>"
-};
-
-static
-char *hb[4] =
-{
- "???", "HU", "B", "H"
-};
-
-static
-char* addsub[2] =
-{
- "-", "+",
-};
-
-int
-armclass(long w)
-{
- int op;
-
- op = (w >> 25) & 0x7;
- switch(op) {
- case 0: /* data processing r,r,r */
- op = ((w >> 4) & 0xf);
- if(op == 0x9) {
- op = 48+16; /* mul */
- if(w & (1<<24)) {
- op += 2;
- if(w & (1<<22))
- op++; /* swap */
- break;
- }
- if(w & (1<<21))
- op++; /* mla */
- break;
- }
- if ((op & 0x9) == 0x9) /* ld/st byte/half s/u */
- {
- op = (48+16+4) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
- break;
- }
- op = (w >> 21) & 0xf;
- if(w & (1<<4))
- op += 32;
- else
- if(w & (31<<7))
- op += 16;
- break;
- case 1: /* data processing i,r,r */
- op = (48) + ((w >> 21) & 0xf);
- break;
- case 2: /* load/store byte/word i(r) */
- op = (48+24) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
- break;
- case 3: /* load/store byte/word (r)(r) */
- op = (48+24+4) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
- break;
- case 4: /* block data transfer (r)(r) */
- op = (48+24+4+4) + ((w >> 20) & 0x1);
- break;
- case 5: /* branch / branch link */
- op = (48+24+4+4+2) + ((w >> 24) & 0x1);
- break;
- case 7: /* coprocessor crap */
- op = (48+24+4+4+2+2) + ((w >> 3) & 0x2) + ((w >> 20) & 0x1);
- break;
- default:
- op = (48+24+4+4+2+2+4);
- break;
- }
- return op;
-}
-
-static int
-decode(Map *map, ulong pc, Instr *i)
-{
- uint32 w;
-
- if(get4(map, pc, &w) < 0) {
- werrstr("can't read instruction: %r");
- return -1;
- }
- i->w = w;
- i->addr = pc;
- i->cond = (w >> 28) & 0xF;
- i->op = armclass(w);
- i->map = map;
- return 1;
-}
-
-static void
-bprint(Instr *i, char *fmt, ...)
-{
- va_list arg;
-
- va_start(arg, fmt);
- i->curr = vseprint(i->curr, i->end, fmt, arg);
- va_end(arg);
-}
-
-static int
-plocal(Instr *i)
-{
- char *reg;
- Symbol s;
- char *fn;
- int class;
- int offset;
-
- if(!findsym(i->addr, CTEXT, &s)) {
- if(debug)fprint(2,"fn not found @%lux: %r\n", i->addr);
- return 0;
- }
- fn = s.name;
- if (!findlocal(&s, FRAMENAME, &s)) {
- if(debug)fprint(2,"%s.%s not found @%s: %r\n", fn, FRAMENAME, s.name);
- return 0;
- }
- if(s.value > i->imm) {
- class = CAUTO;
- offset = s.value-i->imm;
- reg = "(SP)";
- } else {
- class = CPARAM;
- offset = i->imm-s.value-4;
- reg = "(FP)";
- }
- if(!getauto(&s, offset, class, &s)) {
- if(debug)fprint(2,"%s %s not found @%ux: %r\n", fn,
- class == CAUTO ? " auto" : "param", offset);
- return 0;
- }
- bprint(i, "%s%c%d%s", s.name, class == CPARAM ? '+' : '-', s.value, reg);
- return 1;
-}
-
-/*
- * Print value v as name[+offset]
- */
-int
-gsymoff(char *buf, int n, long v, int space)
-{
- Symbol s;
- int r;
- long delta;
-
- r = delta = 0; /* to shut compiler up */
- if (v) {
- r = findsym(v, space, &s);
- if (r)
- delta = v-s.value;
- if (delta < 0)
- delta = -delta;
- }
- if (v == 0 || r == 0 || delta >= 4096)
- return snprint(buf, n, "#%lux", v);
- if (strcmp(s.name, ".string") == 0)
- return snprint(buf, n, "#%lux", v);
- if (!delta)
- return snprint(buf, n, "%s", s.name);
- if (s.type != 't' && s.type != 'T')
- return snprint(buf, n, "%s+%llux", s.name, v-s.value);
- else
- return snprint(buf, n, "#%lux", v);
-}
-
-static void
-armdps(Opcode *o, Instr *i)
-{
- i->store = (i->w >> 20) & 1;
- i->rn = (i->w >> 16) & 0xf;
- i->rd = (i->w >> 12) & 0xf;
- i->rs = (i->w >> 0) & 0xf;
- if(i->rn == 15 && i->rs == 0) {
- if(i->op == 8) {
- format("MOVW", i,"CPSR, R%d");
- return;
- } else
- if(i->op == 10) {
- format("MOVW", i,"SPSR, R%d");
- return;
- }
- } else
- if(i->rn == 9 && i->rd == 15) {
- if(i->op == 9) {
- format("MOVW", i, "R%s, CPSR");
- return;
- } else
- if(i->op == 11) {
- format("MOVW", i, "R%s, SPSR");
- return;
- }
- }
- format(o->o, i, o->a);
-}
-
-static void
-armdpi(Opcode *o, Instr *i)
-{
- ulong v;
- int c;
-
- v = (i->w >> 0) & 0xff;
- c = (i->w >> 8) & 0xf;
- while(c) {
- v = (v<<30) | (v>>2);
- c--;
- }
- i->imm = v;
- i->store = (i->w >> 20) & 1;
- i->rn = (i->w >> 16) & 0xf;
- i->rd = (i->w >> 12) & 0xf;
- i->rs = i->w&0x0f;
-
- /* RET is encoded as ADD #0,R14,R15 */
- if((i->w & 0x0fffffff) == 0x028ef000){
- format("RET%C", i, "");
- return;
- }
- if((i->w & 0x0ff0ffff) == 0x0280f000){
- format("B%C", i, "0(R%n)");
- return;
- }
- format(o->o, i, o->a);
-}
-
-static void
-armsdti(Opcode *o, Instr *i)
-{
- ulong v;
-
- v = i->w & 0xfff;
- if(!(i->w & (1<<23)))
- v = -v;
- i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
- i->imm = v;
- i->rn = (i->w >> 16) & 0xf;
- i->rd = (i->w >> 12) & 0xf;
- /* RET is encoded as LW.P x,R13,R15 */
- if ((i->w & 0x0ffff000) == 0x049df000)
- {
- format("RET%C%p", i, "%I");
- return;
- }
- format(o->o, i, o->a);
-}
-
-/* arm V4 ld/st halfword, signed byte */
-static void
-armhwby(Opcode *o, Instr *i)
-{
- i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
- i->imm = (i->w & 0xf) | ((i->w >> 8) & 0xf);
- if (!(i->w & (1 << 23)))
- i->imm = - i->imm;
- i->rn = (i->w >> 16) & 0xf;
- i->rd = (i->w >> 12) & 0xf;
- i->rs = (i->w >> 0) & 0xf;
- format(o->o, i, o->a);
-}
-
-static void
-armsdts(Opcode *o, Instr *i)
-{
- i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
- i->rs = (i->w >> 0) & 0xf;
- i->rn = (i->w >> 16) & 0xf;
- i->rd = (i->w >> 12) & 0xf;
- format(o->o, i, o->a);
-}
-
-static void
-armbdt(Opcode *o, Instr *i)
-{
- i->store = (i->w >> 21) & 0x3; /* S & W bits */
- i->rn = (i->w >> 16) & 0xf;
- i->imm = i->w & 0xffff;
- if(i->w == 0xe8fd8000)
- format("RFE", i, "");
- else
- format(o->o, i, o->a);
-}
-
-/*
-static void
-armund(Opcode *o, Instr *i)
-{
- format(o->o, i, o->a);
-}
-
-static void
-armcdt(Opcode *o, Instr *i)
-{
- format(o->o, i, o->a);
-}
-*/
-
-static void
-armunk(Opcode *o, Instr *i)
-{
- format(o->o, i, o->a);
-}
-
-static void
-armb(Opcode *o, Instr *i)
-{
- ulong v;
-
- v = i->w & 0xffffff;
- if(v & 0x800000)
- v |= ~0xffffff;
- i->imm = (v<<2) + i->addr + 8;
- format(o->o, i, o->a);
-}
-
-static void
-armco(Opcode *o, Instr *i) /* coprocessor instructions */
-{
- int op, p, cp;
-
- char buf[1024];
-
- i->rn = (i->w >> 16) & 0xf;
- i->rd = (i->w >> 12) & 0xf;
- i->rs = i->w&0xf;
- cp = (i->w >> 8) & 0xf;
- p = (i->w >> 5) & 0x7;
- if(i->w&(1<<4)) {
- op = (i->w >> 21) & 0x07;
- snprint(buf, sizeof(buf), "#%x, #%x, R%d, C(%d), C(%d), #%x\n", cp, op, i->rd, i->rn, i->rs, p);
- } else {
- op = (i->w >> 20) & 0x0f;
- snprint(buf, sizeof(buf), "#%x, #%x, C(%d), C(%d), C(%d), #%x\n", cp, op, i->rd, i->rn, i->rs, p);
- }
- format(o->o, i, buf);
-}
-
-static int
-armcondpass(Map *map, Rgetter rget, uchar cond)
-{
- ulong psr;
- uchar n;
- uchar z;
- uchar c;
- uchar v;
-
- psr = rget(map, "PSR");
- n = (psr >> 31) & 1;
- z = (psr >> 30) & 1;
- c = (psr >> 29) & 1;
- v = (psr >> 28) & 1;
-
- switch(cond) {
- case 0: return z;
- case 1: return !z;
- case 2: return c;
- case 3: return !c;
- case 4: return n;
- case 5: return !n;
- case 6: return v;
- case 7: return !v;
- case 8: return c && !z;
- case 9: return !c || z;
- case 10: return n == v;
- case 11: return n != v;
- case 12: return !z && (n == v);
- case 13: return z && (n != v);
- case 14: return 1;
- case 15: return 0;
- }
- return 0;
-}
-
-static ulong
-armshiftval(Map *map, Rgetter rget, Instr *i)
-{
- if(i->w & (1 << 25)) { /* immediate */
- ulong imm = i->w & BITS(0, 7);
- ulong s = (i->w & BITS(8, 11)) >> 7; /* this contains the *2 */
- return ROR(imm, s);
- } else {
- char buf[8];
- ulong v;
- ulong s = (i->w & BITS(7,11)) >> 7;
-
- sprint(buf, "R%ld", i->w & 0xf);
- v = rget(map, buf);
-
- switch((i->w & BITS(4, 6)) >> 4) {
- case 0: /* LSLIMM */
- return v << s;
- case 1: /* LSLREG */
- sprint(buf, "R%lud", s >> 1);
- s = rget(map, buf) & 0xFF;
- if(s >= 32) return 0;
- return v << s;
- case 2: /* LSRIMM */
- return LSR(v, s);
- case 3: /* LSRREG */
- sprint(buf, "R%ld", s >> 1);
- s = rget(map, buf) & 0xFF;
- if(s >= 32) return 0;
- return LSR(v, s);
- case 4: /* ASRIMM */
- if(s == 0) {
- if((v & (1U<<31)) == 0)
- return 0;
- return 0xFFFFFFFF;
- }
- return ASR(v, s);
- case 5: /* ASRREG */
- sprint(buf, "R%ld", s >> 1);
- s = rget(map, buf) & 0xFF;
- if(s >= 32) {
- if((v & (1U<<31)) == 0)
- return 0;
- return 0xFFFFFFFF;
- }
- return ASR(v, s);
- case 6: /* RORIMM */
- if(s == 0) {
- ulong c = (rget(map, "PSR") >> 29) & 1;
-
- return (c << 31) | LSR(v, 1);
- }
- return ROR(v, s);
- case 7: /* RORREG */
- sprint(buf, "R%ld", (s>>1)&0xF);
- s = rget(map, buf);
- if(s == 0 || (s & 0xF) == 0)
- return v;
- return ROR(v, s & 0xF);
- }
- }
- return 0;
-}
-
-static int
-nbits(ulong v)
-{
- int n = 0;
- int i;
-
- for(i=0; i < 32 ; i++) {
- if(v & 1) ++n;
- v >>= 1;
- }
-
- return n;
-}
-
-static ulong
-armmaddr(Map *map, Rgetter rget, Instr *i)
-{
- ulong v;
- ulong nb;
- char buf[8];
- ulong rn;
-
- rn = (i->w >> 16) & 0xf;
- sprint(buf,"R%ld", rn);
-
- v = rget(map, buf);
- nb = nbits(i->w & ((1 << 15) - 1));
-
- switch((i->w >> 23) & 3) {
- case 0: return (v - (nb*4)) + 4;
- case 1: return v;
- case 2: return v - (nb*4);
- case 3: return v + 4;
- }
- return 0;
-}
-
-static ulong
-armaddr(Map *map, Rgetter rget, Instr *i)
-{
- char buf[8];
- ulong rn;
-
- sprint(buf, "R%ld", (i->w >> 16) & 0xf);
- rn = rget(map, buf);
-
- if((i->w & (1<<24)) == 0) { /* POSTIDX */
- sprint(buf, "R%ld", rn);
- return rget(map, buf);
- }
-
- if((i->w & (1<<25)) == 0) { /* OFFSET */
- sprint(buf, "R%ld", rn);
- if(i->w & (1U<<23))
- return rget(map, buf) + (i->w & BITS(0,11));
- return rget(map, buf) - (i->w & BITS(0,11));
- } else { /* REGOFF */
- ulong index = 0;
- uchar c;
- uchar rm;
-
- sprint(buf, "R%ld", i->w & 0xf);
- rm = rget(map, buf);
-
- switch((i->w & BITS(5,6)) >> 5) {
- case 0: index = rm << ((i->w & BITS(7,11)) >> 7); break;
- case 1: index = LSR(rm, ((i->w & BITS(7,11)) >> 7)); break;
- case 2: index = ASR(rm, ((i->w & BITS(7,11)) >> 7)); break;
- case 3:
- if((i->w & BITS(7,11)) == 0) {
- c = (rget(map, "PSR") >> 29) & 1;
- index = c << 31 | LSR(rm, 1);
- } else {
- index = ROR(rm, ((i->w & BITS(7,11)) >> 7));
- }
- break;
- }
- if(i->w & (1<<23))
- return rn + index;
- return rn - index;
- }
-}
-
-static ulong
-armfadd(Map *map, Rgetter rget, Instr *i, ulong pc)
-{
- char buf[8];
- int r;
-
- r = (i->w >> 12) & 0xf;
- if(r != 15 || !armcondpass(map, rget, (i->w >> 28) & 0xf))
- return pc+4;
-
- r = (i->w >> 16) & 0xf;
- sprint(buf, "R%d", r);
-
- return rget(map, buf) + armshiftval(map, rget, i);
-}
-
-static ulong
-armfmovm(Map *map, Rgetter rget, Instr *i, ulong pc)
-{
- uint32 v;
- ulong addr;
-
- v = i->w & 1<<15;
- if(!v || !armcondpass(map, rget, (i->w>>28)&0xf))
- return pc+4;
-
- addr = armmaddr(map, rget, i) + nbits(i->w & BITS(0,15));
- if(get4(map, addr, &v) < 0) {
- werrstr("can't read addr: %r");
- return -1;
- }
- return v;
-}
-
-static ulong
-armfbranch(Map *map, Rgetter rget, Instr *i, ulong pc)
-{
- if(!armcondpass(map, rget, (i->w >> 28) & 0xf))
- return pc+4;
-
- return pc + (((signed long)i->w << 8) >> 6) + 8;
-}
-
-static ulong
-armfmov(Map *map, Rgetter rget, Instr *i, ulong pc)
-{
- ulong rd;
- uint32 v;
-
- rd = (i->w >> 12) & 0xf;
- if(rd != 15 || !armcondpass(map, rget, (i->w>>28)&0xf))
- return pc+4;
-
- /* LDR */
- /* BUG: Needs LDH/B, too */
- if(((i->w>>26)&0x3) == 1) {
- if(get4(map, armaddr(map, rget, i), &v) < 0) {
- werrstr("can't read instruction: %r");
- return pc+4;
- }
- return v;
- }
-
- /* MOV */
- return armshiftval(map, rget, i);
-}
-
-static Opcode opcodes[] =
-{
- "AND%C%S", armdps, 0, "R%s,R%n,R%d",
- "EOR%C%S", armdps, 0, "R%s,R%n,R%d",
- "SUB%C%S", armdps, 0, "R%s,R%n,R%d",
- "RSB%C%S", armdps, 0, "R%s,R%n,R%d",
- "ADD%C%S", armdps, armfadd, "R%s,R%n,R%d",
- "ADC%C%S", armdps, 0, "R%s,R%n,R%d",
- "SBC%C%S", armdps, 0, "R%s,R%n,R%d",
- "RSC%C%S", armdps, 0, "R%s,R%n,R%d",
- "TST%C%S", armdps, 0, "R%s,R%n",
- "TEQ%C%S", armdps, 0, "R%s,R%n",
- "CMP%C%S", armdps, 0, "R%s,R%n",
- "CMN%C%S", armdps, 0, "R%s,R%n",
- "ORR%C%S", armdps, 0, "R%s,R%n,R%d",
- "MOVW%C%S", armdps, armfmov, "R%s,R%d",
- "BIC%C%S", armdps, 0, "R%s,R%n,R%d",
- "MVN%C%S", armdps, 0, "R%s,R%d",
-
-/* 16 */
- "AND%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
- "EOR%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
- "SUB%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
- "RSB%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
- "ADD%C%S", armdps, armfadd, "(R%s%h%m),R%n,R%d",
- "ADC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
- "SBC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
- "RSC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
- "TST%C%S", armdps, 0, "(R%s%h%m),R%n",
- "TEQ%C%S", armdps, 0, "(R%s%h%m),R%n",
- "CMP%C%S", armdps, 0, "(R%s%h%m),R%n",
- "CMN%C%S", armdps, 0, "(R%s%h%m),R%n",
- "ORR%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
- "MOVW%C%S", armdps, armfmov, "(R%s%h%m),R%d",
- "BIC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
- "MVN%C%S", armdps, 0, "(R%s%h%m),R%d",
-
-/* 32 */
- "AND%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
- "EOR%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
- "SUB%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
- "RSB%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
- "ADD%C%S", armdps, armfadd, "(R%s%hR%M),R%n,R%d",
- "ADC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
- "SBC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
- "RSC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
- "TST%C%S", armdps, 0, "(R%s%hR%M),R%n",
- "TEQ%C%S", armdps, 0, "(R%s%hR%M),R%n",
- "CMP%C%S", armdps, 0, "(R%s%hR%M),R%n",
- "CMN%C%S", armdps, 0, "(R%s%hR%M),R%n",
- "ORR%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
- "MOVW%C%S", armdps, armfmov, "(R%s%hR%M),R%d",
- "BIC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
- "MVN%C%S", armdps, 0, "(R%s%hR%M),R%d",
-
-/* 48 */
- "AND%C%S", armdpi, 0, "$#%i,R%n,R%d",
- "EOR%C%S", armdpi, 0, "$#%i,R%n,R%d",
- "SUB%C%S", armdpi, 0, "$#%i,R%n,R%d",
- "RSB%C%S", armdpi, 0, "$#%i,R%n,R%d",
- "ADD%C%S", armdpi, armfadd, "$#%i,R%n,R%d",
- "ADC%C%S", armdpi, 0, "$#%i,R%n,R%d",
- "SBC%C%S", armdpi, 0, "$#%i,R%n,R%d",
- "RSC%C%S", armdpi, 0, "$#%i,R%n,R%d",
- "TST%C%S", armdpi, 0, "$#%i,R%n",
- "TEQ%C%S", armdpi, 0, "$#%i,R%n",
- "CMP%C%S", armdpi, 0, "$#%i,R%n",
- "CMN%C%S", armdpi, 0, "$#%i,R%n",
- "ORR%C%S", armdpi, 0, "$#%i,R%n,R%d",
- "MOVW%C%S", armdpi, armfmov, "$#%i,R%d",
- "BIC%C%S", armdpi, 0, "$#%i,R%n,R%d",
- "MVN%C%S", armdpi, 0, "$#%i,R%d",
-
-/* 48+16 */
- "MUL%C%S", armdpi, 0, "R%s,R%M,R%n",
- "MULA%C%S", armdpi, 0, "R%s,R%M,R%n,R%d",
- "SWPW", armdpi, 0, "R%s,(R%n),R%d",
- "SWPB", armdpi, 0, "R%s,(R%n),R%d",
-
-/* 48+16+4 */
- "MOV%u%C%p", armhwby, 0, "R%d,(R%n%UR%M)",
- "MOV%u%C%p", armhwby, 0, "R%d,%I",
- "MOV%u%C%p", armhwby, armfmov, "(R%n%UR%M),R%d",
- "MOV%u%C%p", armhwby, armfmov, "%I,R%d",
-
-/* 48+24 */
- "MOVW%C%p", armsdti, 0, "R%d,%I",
- "MOVB%C%p", armsdti, 0, "R%d,%I",
- "MOVW%C%p", armsdti, armfmov, "%I,R%d",
- "MOVBU%C%p", armsdti, armfmov, "%I,R%d",
-
- "MOVW%C%p", armsdts, 0, "R%d,(R%s%h%m)(R%n)",
- "MOVB%C%p", armsdts, 0, "R%d,(R%s%h%m)(R%n)",
- "MOVW%C%p", armsdts, armfmov, "(R%s%h%m)(R%n),R%d",
- "MOVBU%C%p", armsdts, armfmov, "(R%s%h%m)(R%n),R%d",
-
- "MOVM%C%P%a", armbdt, armfmovm, "[%r],(R%n)",
- "MOVM%C%P%a", armbdt, armfmovm, "(R%n),[%r]",
-
- "B%C", armb, armfbranch, "%b",
- "BL%C", armb, armfbranch, "%b",
-
- "CDP%C", armco, 0, "",
- "CDP%C", armco, 0, "",
- "MCR%C", armco, 0, "",
- "MRC%C", armco, 0, "",
-
- "UNK", armunk, 0, "",
-};
-
-static void
-gaddr(Instr *i)
-{
- *i->curr++ = '$';
- i->curr += gsymoff(i->curr, i->end-i->curr, i->imm, CANY);
-}
-
-static char *mode[] = { 0, "IA", "DB", "IB" };
-static char *pw[] = { "P", "PW", 0, "W" };
-static char *sw[] = { 0, "W", "S", "SW" };
-
-static void
-format(char *mnemonic, Instr *i, char *f)
-{
- int j, k, m, n;
- int g;
- char *fmt;
-
- if(mnemonic)
- format(0, i, mnemonic);
- if(f == 0)
- return;
- if(mnemonic)
- if(i->curr < i->end)
- *i->curr++ = '\t';
- for ( ; *f && i->curr < i->end; f++) {
- if(*f != '%') {
- *i->curr++ = *f;
- continue;
- }
- switch (*++f) {
-
- case 'C': /* .CONDITION */
- if(cond[i->cond])
- bprint(i, ".%s", cond[i->cond]);
- break;
-
- case 'S': /* .STORE */
- if(i->store)
- bprint(i, ".S");
- break;
-
- case 'P': /* P & U bits for block move */
- n = (i->w >>23) & 0x3;
- if (mode[n])
- bprint(i, ".%s", mode[n]);
- break;
-
- case 'p': /* P & W bits for single data xfer*/
- if (pw[i->store])
- bprint(i, ".%s", pw[i->store]);
- break;
-
- case 'a': /* S & W bits for single data xfer*/
- if (sw[i->store])
- bprint(i, ".%s", sw[i->store]);
- break;
-
- case 's':
- bprint(i, "%d", i->rs & 0xf);
- break;
-
- case 'M':
- bprint(i, "%d", (i->w>>8) & 0xf);
- break;
-
- case 'm':
- bprint(i, "%d", (i->w>>7) & 0x1f);
- break;
-
- case 'h':
- bprint(i, shtype[(i->w>>5) & 0x3]);
- break;
-
- case 'u': /* Signed/unsigned Byte/Halfword */
- bprint(i, hb[(i->w>>5) & 0x3]);
- break;
-
- case 'I':
- if (i->rn == 13) {
- if (plocal(i))
- break;
- }
- g = 0;
- fmt = "#%lx(R%d)";
- if (i->rn == 15) {
- /* convert load of offset(PC) to a load immediate */
- uint32 x;
- if (get4(i->map, i->addr+i->imm+8, &x) > 0)
- {
- i->imm = (int32)x;
- g = 1;
- fmt = "";
- }
- }
- if (mach->sb)
- {
- if (i->rd == 11) {
- uint32 nxti;
-
- if (get4(i->map, i->addr+4, &nxti) > 0) {
- if ((nxti & 0x0e0f0fff) == 0x060c000b) {
- i->imm += mach->sb;
- g = 1;
- fmt = "-SB";
- }
- }
- }
- if (i->rn == 12)
- {
- i->imm += mach->sb;
- g = 1;
- fmt = "-SB(SB)";
- }
- }
- if (g)
- {
- gaddr(i);
- bprint(i, fmt, i->rn);
- }
- else
- bprint(i, fmt, i->imm, i->rn);
- break;
- case 'U': /* Add/subtract from base */
- bprint(i, addsub[(i->w >> 23) & 1]);
- break;
-
- case 'n':
- bprint(i, "%d", i->rn);
- break;
-
- case 'd':
- bprint(i, "%d", i->rd);
- break;
-
- case 'i':
- bprint(i, "%lux", i->imm);
- break;
-
- case 'b':
- i->curr += symoff(i->curr, i->end-i->curr,
- i->imm, CTEXT);
- break;
-
- case 'g':
- i->curr += gsymoff(i->curr, i->end-i->curr,
- i->imm, CANY);
- break;
-
- case 'r':
- n = i->imm&0xffff;
- j = 0;
- k = 0;
- while(n) {
- m = j;
- while(n&0x1) {
- j++;
- n >>= 1;
- }
- if(j != m) {
- if(k)
- bprint(i, ",");
- if(j == m+1)
- bprint(i, "R%d", m);
- else
- bprint(i, "R%d-R%d", m, j-1);
- k = 1;
- }
- j++;
- n >>= 1;
- }
- break;
-
- case '\0':
- *i->curr++ = '%';
- return;
-
- default:
- bprint(i, "%%%c", *f);
- break;
- }
- }
- *i->curr = 0;
-}
-
-static int
-printins(Map *map, ulong pc, char *buf, int n)
-{
- Instr i;
-
- i.curr = buf;
- i.end = buf+n-1;
- if(decode(map, pc, &i) < 0)
- return -1;
-
- (*opcodes[i.op].fmt)(&opcodes[i.op], &i);
- return 4;
-}
-
-static int
-arminst(Map *map, uvlong pc, char modifier, char *buf, int n)
-{
- USED(modifier);
- return printins(map, pc, buf, n);
-}
-
-static int
-armdas(Map *map, uvlong pc, char *buf, int n)
-{
- Instr i;
-
- i.curr = buf;
- i.end = buf+n;
- if(decode(map, pc, &i) < 0)
- return -1;
- if(i.end-i.curr > 8)
- i.curr = _hexify(buf, i.w, 7);
- *i.curr = 0;
- return 4;
-}
-
-static int
-arminstlen(Map *map, uvlong pc)
-{
- Instr i;
-
- if(decode(map, pc, &i) < 0)
- return -1;
- return 4;
-}
-
-static int
-armfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
-{
- ulong d;
- Instr i;
-
- if(decode(map, pc, &i) < 0)
- return -1;
-
- if(opcodes[i.op].foll) {
- d = (*opcodes[i.op].foll)(map, rget, &i, pc);
- if(d == -1)
- return -1;
- } else
- d = pc+4;
-
- foll[0] = d;
- return 1;
-}
diff --git a/src/libmach/5obj.c b/src/libmach/5obj.c
deleted file mode 100644
index 7fd3459a8..000000000
--- a/src/libmach/5obj.c
+++ /dev/null
@@ -1,171 +0,0 @@
-// Inferno libmach/5obj.c
-// http://code.google.com/p/inferno-os/source/browse/utils/libmach/5obj.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc.
-// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
-// Portions Copyright © 1997-1999 Vita Nuova Limited.
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-/*
- * 5obj.c - identify and parse an arm object file
- */
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-#include "../cmd/5l/5.out.h"
-#include "obj.h"
-
-typedef struct Addr Addr;
-struct Addr
-{
- char type;
- char sym;
- char name;
- char gotype;
-};
-static Addr addr(Biobuf*);
-static char type2char(int);
-static void skip(Biobuf*, int);
-
-int
-_is5(char *s)
-{
- return s[0] == ANAME /* ANAME */
- && s[1] == D_FILE /* type */
- && s[2] == 1 /* sym */
- && s[3] == '<'; /* name of file */
-}
-
-int
-_read5(Biobuf *bp, Prog *p)
-{
- int as, n;
- Addr a;
-
- as = BGETC(bp); /* as */
- if(as < 0)
- return 0;
- p->kind = aNone;
- p->sig = 0;
- if(as == ANAME || as == ASIGNAME){
- if(as == ASIGNAME){
- Bread(bp, &p->sig, 4);
- p->sig = leswal(p->sig);
- }
- p->kind = aName;
- p->type = type2char(BGETC(bp)); /* type */
- p->sym = BGETC(bp); /* sym */
- n = 0;
- for(;;) {
- as = BGETC(bp);
- if(as < 0)
- return 0;
- n++;
- if(as == 0)
- break;
- }
- p->id = malloc(n);
- if(p->id == 0)
- return 0;
- Bseek(bp, -n, 1);
- if(Bread(bp, p->id, n) != n)
- return 0;
- return 1;
- }
- if(as == ATEXT)
- p->kind = aText;
- else if(as == AGLOBL)
- p->kind = aData;
- skip(bp, 6); /* scond(1), reg(1), lineno(4) */
- a = addr(bp);
- addr(bp);
- if(a.type != D_OREG || a.name != D_STATIC && a.name != D_EXTERN)
- p->kind = aNone;
- p->sym = a.sym;
- return 1;
-}
-
-static Addr
-addr(Biobuf *bp)
-{
- Addr a;
- long off;
-
- a.type = BGETC(bp); /* a.type */
- skip(bp,1); /* reg */
- a.sym = BGETC(bp); /* sym index */
- a.name = BGETC(bp); /* sym type */
- a.gotype = BGETC(bp); /* go type */
- switch(a.type){
- default:
- case D_NONE:
- case D_REG:
- case D_FREG:
- case D_PSR:
- case D_FPCR:
- break;
- case D_REGREG:
- case D_REGREG2:
- Bgetc(bp);
- break;
- case D_CONST2:
- Bgetle4(bp); // fall through
- case D_OREG:
- case D_CONST:
- case D_BRANCH:
- case D_SHIFT:
- off = BGETLE4(bp);
- if(off < 0)
- off = -off;
- if(a.sym && (a.name==D_PARAM || a.name==D_AUTO))
- _offset(a.sym, off);
- break;
- case D_SCONST:
- skip(bp, NSNAME);
- break;
- case D_FCONST:
- skip(bp, 8);
- break;
- }
- return a;
-}
-
-static char
-type2char(int t)
-{
- switch(t){
- case D_EXTERN: return 'U';
- case D_STATIC: return 'b';
- case D_AUTO: return 'a';
- case D_PARAM: return 'p';
- default: return UNKNOWN;
- }
-}
-
-static void
-skip(Biobuf *bp, int n)
-{
- while (n-- > 0)
- Bgetc(bp);
-}
diff --git a/src/libmach/6.c b/src/libmach/6.c
deleted file mode 100644
index 0f0636303..000000000
--- a/src/libmach/6.c
+++ /dev/null
@@ -1,145 +0,0 @@
-// Inferno libmach/6.c
-// http://code.google.com/p/inferno-os/source/browse/utils/libmach/6.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc.
-// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
-// Portions Copyright © 1997-1999 Vita Nuova Limited.
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-/*
- * amd64 definition
- */
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include "ureg_amd64.h"
-#include <mach.h>
-
-#define REGOFF(x) offsetof(struct Ureg, x)
-
-#define REGSIZE sizeof(struct Ureg)
-#define FP_CTLS(x) (REGSIZE+2*(x))
-#define FP_CTL(x) (REGSIZE+4*(x))
-#define FP_REG(x) (FP_CTL(8)+16*(x))
-#define XM_REG(x) (FP_CTL(8)+8*16+16*(x))
-
-#define FPREGSIZE 512 /* TO DO? currently only 0x1A0 used */
-
-Reglist amd64reglist[] = {
- {"AX", REGOFF(ax), RINT, 'Y'},
- {"BX", REGOFF(bx), RINT, 'Y'},
- {"CX", REGOFF(cx), RINT, 'Y'},
- {"DX", REGOFF(dx), RINT, 'Y'},
- {"SI", REGOFF(si), RINT, 'Y'},
- {"DI", REGOFF(di), RINT, 'Y'},
- {"BP", REGOFF(bp), RINT, 'Y'},
- {"R8", REGOFF(r8), RINT, 'Y'},
- {"R9", REGOFF(r9), RINT, 'Y'},
- {"R10", REGOFF(r10), RINT, 'Y'},
- {"R11", REGOFF(r11), RINT, 'Y'},
- {"R12", REGOFF(r12), RINT, 'Y'},
- {"R13", REGOFF(r13), RINT, 'Y'},
- {"R14", REGOFF(r14), RINT, 'Y'},
- {"R15", REGOFF(r15), RINT, 'Y'},
- {"DS", REGOFF(ds), RINT, 'x'},
- {"ES", REGOFF(es), RINT, 'x'},
- {"FS", REGOFF(fs), RINT, 'x'},
- {"GS", REGOFF(gs), RINT, 'x'},
- {"TYPE", REGOFF(type), RINT, 'Y'},
- {"TRAP", REGOFF(type), RINT, 'Y'}, /* alias for acid */
- {"ERROR", REGOFF(error), RINT, 'Y'},
- {"IP", REGOFF(ip), RINT, 'Y'},
- {"PC", REGOFF(ip), RINT, 'Y'}, /* alias for acid */
- {"CS", REGOFF(cs), RINT, 'Y'},
- {"FLAGS", REGOFF(flags), RINT, 'Y'},
- {"SP", REGOFF(sp), RINT, 'Y'},
- {"SS", REGOFF(ss), RINT, 'Y'},
-
- {"FCW", FP_CTLS(0), RFLT, 'x'},
- {"FSW", FP_CTLS(1), RFLT, 'x'},
- {"FTW", FP_CTLS(2), RFLT, 'b'},
- {"FOP", FP_CTLS(3), RFLT, 'x'},
- {"RIP", FP_CTL(2), RFLT, 'Y'},
- {"RDP", FP_CTL(4), RFLT, 'Y'},
- {"MXCSR", FP_CTL(6), RFLT, 'X'},
- {"MXCSRMASK", FP_CTL(7), RFLT, 'X'},
- {"M0", FP_REG(0), RFLT, 'F'}, /* assumes double */
- {"M1", FP_REG(1), RFLT, 'F'},
- {"M2", FP_REG(2), RFLT, 'F'},
- {"M3", FP_REG(3), RFLT, 'F'},
- {"M4", FP_REG(4), RFLT, 'F'},
- {"M5", FP_REG(5), RFLT, 'F'},
- {"M6", FP_REG(6), RFLT, 'F'},
- {"M7", FP_REG(7), RFLT, 'F'},
- {"X0", XM_REG(0), RFLT, 'F'}, /* assumes double */
- {"X1", XM_REG(1), RFLT, 'F'},
- {"X2", XM_REG(2), RFLT, 'F'},
- {"X3", XM_REG(3), RFLT, 'F'},
- {"X4", XM_REG(4), RFLT, 'F'},
- {"X5", XM_REG(5), RFLT, 'F'},
- {"X6", XM_REG(6), RFLT, 'F'},
- {"X7", XM_REG(7), RFLT, 'F'},
- {"X8", XM_REG(8), RFLT, 'F'},
- {"X9", XM_REG(9), RFLT, 'F'},
- {"X10", XM_REG(10), RFLT, 'F'},
- {"X11", XM_REG(11), RFLT, 'F'},
- {"X12", XM_REG(12), RFLT, 'F'},
- {"X13", XM_REG(13), RFLT, 'F'},
- {"X14", XM_REG(14), RFLT, 'F'},
- {"X15", XM_REG(15), RFLT, 'F'},
- {"X16", XM_REG(16), RFLT, 'F'},
-/*
- {"F0", FP_REG(7), RFLT, '3'},
- {"F1", FP_REG(6), RFLT, '3'},
- {"F2", FP_REG(5), RFLT, '3'},
- {"F3", FP_REG(4), RFLT, '3'},
- {"F4", FP_REG(3), RFLT, '3'},
- {"F5", FP_REG(2), RFLT, '3'},
- {"F6", FP_REG(1), RFLT, '3'},
- {"F7", FP_REG(0), RFLT, '3'},
-*/
- { 0 }
-};
-
-Mach mamd64=
-{
- "amd64",
- MAMD64, /* machine type */
- amd64reglist, /* register list */
- REGSIZE, /* size of registers in bytes */
- FPREGSIZE, /* size of fp registers in bytes */
- "PC", /* name of PC */
- "SP", /* name of SP */
- 0, /* link register */
- "setSB", /* static base register name (bogus anyways) */
- 0, /* static base register value */
- 0x1000, /* page size */
- 0xFFFFFFFF80110000ULL, /* kernel base */
- 0xFFFF800000000000ULL, /* kernel text mask */
- 0x00007FFFFFFFF000ULL, /* user stack top */
- 1, /* quantization of pc */
- 8, /* szaddr */
- 4, /* szreg */
- 4, /* szfloat */
- 8, /* szdouble */
-};
diff --git a/src/libmach/6obj.c b/src/libmach/6obj.c
deleted file mode 100644
index 1921c9e4c..000000000
--- a/src/libmach/6obj.c
+++ /dev/null
@@ -1,173 +0,0 @@
-// Inferno libmach/6obj.c
-// http://code.google.com/p/inferno-os/source/browse/utils/libmach/6obj.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc.
-// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
-// Portions Copyright © 1997-1999 Vita Nuova Limited.
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-/*
- * 6obj.c - identify and parse an amd64 object file
- */
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-#include "../cmd/6l/6.out.h"
-#include "obj.h"
-
-typedef struct Addr Addr;
-struct Addr
-{
- char sym;
- char flags;
- char gotype;
-};
-static Addr addr(Biobuf*);
-static char type2char(int);
-static void skip(Biobuf*, int);
-
-int
-_is6(char *t)
-{
- uchar *s = (uchar*)t;
-
- return s[0] == (ANAME&0xff) /* also = ANAME */
- && s[1] == ((ANAME>>8)&0xff)
- && s[2] == D_FILE /* type */
- && s[3] == 1 /* sym */
- && s[4] == '<'; /* name of file */
-}
-
-int
-_read6(Biobuf *bp, Prog* p)
-{
- int as, n, c;
- Addr a;
-
- as = BGETC(bp); /* as(low) */
- if(as < 0)
- return 0;
- c = BGETC(bp); /* as(high) */
- if(c < 0)
- return 0;
- as |= ((c & 0xff) << 8);
- p->kind = aNone;
- p->sig = 0;
- if(as == ANAME || as == ASIGNAME){
- if(as == ASIGNAME){
- Bread(bp, &p->sig, 4);
- p->sig = leswal(p->sig);
- }
- p->kind = aName;
- p->type = type2char(BGETC(bp)); /* type */
- p->sym = BGETC(bp); /* sym */
- n = 0;
- for(;;) {
- as = BGETC(bp);
- if(as < 0)
- return 0;
- n++;
- if(as == 0)
- break;
- }
- p->id = malloc(n);
- if(p->id == 0)
- return 0;
- Bseek(bp, -n, 1);
- if(Bread(bp, p->id, n) != n)
- return 0;
- return 1;
- }
- if(as == ATEXT)
- p->kind = aText;
- if(as == AGLOBL)
- p->kind = aData;
- skip(bp, 4); /* lineno(4) */
- a = addr(bp);
- addr(bp);
- if(!(a.flags & T_SYM))
- p->kind = aNone;
- p->sym = a.sym;
- return 1;
-}
-
-static Addr
-addr(Biobuf *bp)
-{
- Addr a;
- int t;
- int32 l;
- vlong off;
-
- off = 0;
- a.sym = -1;
- a.flags = BGETC(bp); /* flags */
- a.gotype = 0;
- if(a.flags & T_INDEX)
- skip(bp, 2);
- if(a.flags & T_OFFSET){
- l = BGETLE4(bp);
- off = l;
- if(a.flags & T_64){
- l = BGETLE4(bp);
- off = ((vlong)l << 32) | (off & 0xFFFFFFFF);
- }
- if(off < 0)
- off = -(uvlong)off;
- }
- if(a.flags & T_SYM)
- a.sym = BGETC(bp);
- if(a.flags & T_FCONST)
- skip(bp, 8);
- else
- if(a.flags & T_SCONST)
- skip(bp, NSNAME);
- if(a.flags & T_TYPE) {
- t = BGETC(bp);
- if(a.sym > 0 && (t==D_PARAM || t==D_AUTO))
- _offset(a.sym, off);
- }
- if(a.flags & T_GOTYPE)
- a.gotype = BGETC(bp);
- return a;
-}
-
-static char
-type2char(int t)
-{
- switch(t){
- case D_EXTERN: return 'U';
- case D_STATIC: return 'b';
- case D_AUTO: return 'a';
- case D_PARAM: return 'p';
- default: return UNKNOWN;
- }
-}
-
-static void
-skip(Biobuf *bp, int n)
-{
- while (n-- > 0)
- Bgetc(bp);
-}
diff --git a/src/libmach/8.c b/src/libmach/8.c
deleted file mode 100644
index 34248e6f3..000000000
--- a/src/libmach/8.c
+++ /dev/null
@@ -1,108 +0,0 @@
-// Inferno libmach/8.c
-// http://code.google.com/p/inferno-os/source/browse/utils/libmach/8.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc.
-// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
-// Portions Copyright © 1997-1999 Vita Nuova Limited.
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-/*
- * 386 definition
- */
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <ureg_x86.h>
-#include <mach.h>
-
-#define REGOFF(x) (uintptr)(&((struct Ureg *) 0)->x)
-
-#define PC REGOFF(pc)
-#define SP REGOFF(sp)
-#define AX REGOFF(ax)
-
-#define REGSIZE sizeof(struct Ureg)
-#define FP_CTL(x) (REGSIZE+4*(x))
-#define FP_REG(x) (FP_CTL(7)+10*(x))
-#define FPREGSIZE (7*4+8*10)
-
-Reglist i386reglist[] = {
- {"DI", REGOFF(di), RINT, 'X'},
- {"SI", REGOFF(si), RINT, 'X'},
- {"BP", REGOFF(bp), RINT, 'X'},
- {"BX", REGOFF(bx), RINT, 'X'},
- {"DX", REGOFF(dx), RINT, 'X'},
- {"CX", REGOFF(cx), RINT, 'X'},
- {"AX", REGOFF(ax), RINT, 'X'},
- {"GS", REGOFF(gs), RINT, 'X'},
- {"FS", REGOFF(fs), RINT, 'X'},
- {"ES", REGOFF(es), RINT, 'X'},
- {"DS", REGOFF(ds), RINT, 'X'},
- {"TRAP", REGOFF(trap), RINT, 'X'},
- {"ECODE", REGOFF(ecode), RINT, 'X'},
- {"PC", PC, RINT, 'X'},
- {"CS", REGOFF(cs), RINT, 'X'},
- {"EFLAGS", REGOFF(flags), RINT, 'X'},
- {"SP", SP, RINT, 'X'},
- {"SS", REGOFF(ss), RINT, 'X'},
-
- {"E0", FP_CTL(0), RFLT, 'X'},
- {"E1", FP_CTL(1), RFLT, 'X'},
- {"E2", FP_CTL(2), RFLT, 'X'},
- {"E3", FP_CTL(3), RFLT, 'X'},
- {"E4", FP_CTL(4), RFLT, 'X'},
- {"E5", FP_CTL(5), RFLT, 'X'},
- {"E6", FP_CTL(6), RFLT, 'X'},
- {"F0", FP_REG(0), RFLT, '3'},
- {"F1", FP_REG(1), RFLT, '3'},
- {"F2", FP_REG(2), RFLT, '3'},
- {"F3", FP_REG(3), RFLT, '3'},
- {"F4", FP_REG(4), RFLT, '3'},
- {"F5", FP_REG(5), RFLT, '3'},
- {"F6", FP_REG(6), RFLT, '3'},
- {"F7", FP_REG(7), RFLT, '3'},
- { 0 }
-};
-
-Mach mi386 =
-{
- "386",
- MI386, /* machine type */
- i386reglist, /* register list */
- REGSIZE, /* size of registers in bytes */
- FPREGSIZE, /* size of fp registers in bytes */
- "PC", /* name of PC */
- "SP", /* name of SP */
- 0, /* link register */
- "setSB", /* static base register name (bogus anyways) */
- 0, /* static base register value */
- 0x1000, /* page size */
- 0x80100000ULL, /* kernel base */
- 0xF0000000ULL, /* kernel text mask */
- 0xFFFFFFFFULL, /* user stack top */
- 1, /* quantization of pc */
- 4, /* szaddr */
- 4, /* szreg */
- 4, /* szfloat */
- 8, /* szdouble */
-};
diff --git a/src/libmach/8db.c b/src/libmach/8db.c
deleted file mode 100644
index cfc9cb99f..000000000
--- a/src/libmach/8db.c
+++ /dev/null
@@ -1,2447 +0,0 @@
-// Inferno libmach/8db.c
-// http://code.google.com/p/inferno-os/source/browse/utils/libmach/8db.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc.
-// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
-// Portions Copyright © 1997-1999 Vita Nuova Limited.
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-#define Ureg UregAmd64
-#include <ureg_amd64.h>
-#undef Ureg
-#define Ureg Ureg386
-#include <ureg_x86.h>
-#undef Ureg
-
-typedef struct UregAmd64 UregAmd64;
-typedef struct Ureg386 Ureg386;
-
-/*
- * i386-specific debugger interface
- * also amd64 extensions
- */
-
-static char *i386excep(Map*, Rgetter);
-
-static int i386trace(Map*, uvlong, uvlong, uvlong, Tracer);
-static uvlong i386frame(Map*, uvlong, uvlong, uvlong, uvlong);
-static int i386foll(Map*, uvlong, Rgetter, uvlong*);
-static int i386inst(Map*, uvlong, char, char*, int);
-static int i386das(Map*, uvlong, char*, int);
-static int i386instlen(Map*, uvlong);
-
-static char STARTSYM[] = "_main";
-static char GOSTARTSYM[] = "sys·goexit";
-static char PROFSYM[] = "_mainp";
-static char FRAMENAME[] = ".frame";
-static char LESSSTACK[] = "sys·lessstack";
-static char MORESTACK[] = "sys·morestack";
-static char *excname[] =
-{
-[0] = "divide error",
-[1] = "debug exception",
-[4] = "overflow",
-[5] = "bounds check",
-[6] = "invalid opcode",
-[7] = "math coprocessor emulation",
-[8] = "double fault",
-[9] = "math coprocessor overrun",
-[10] = "invalid TSS",
-[11] = "segment not present",
-[12] = "stack exception",
-[13] = "general protection violation",
-[14] = "page fault",
-[16] = "math coprocessor error",
-[17] = "alignment check",
-[18] = "machine check",
-[19] = "floating-point exception",
-[24] = "clock",
-[25] = "keyboard",
-[27] = "modem status",
-[28] = "serial line status",
-[30] = "floppy disk",
-[36] = "mouse",
-[37] = "math coprocessor",
-[38] = "hard disk",
-[64] = "system call",
-};
-
-Machdata i386mach =
-{
- {0xCC, 0, 0, 0}, /* break point: INT 3 */
- 1, /* break point size */
-
- leswab, /* convert short to local byte order */
- leswal, /* convert int32 to local byte order */
- leswav, /* convert vlong to local byte order */
- i386trace, /* C traceback */
- i386frame, /* frame finder */
- i386excep, /* print exception */
- 0, /* breakpoint fixup */
- leieeesftos, /* single precision float printer */
- leieeedftos, /* double precision float printer */
- i386foll, /* following addresses */
- i386inst, /* print instruction */
- i386das, /* dissembler */
- i386instlen, /* instruction size calculation */
-};
-
-static char*
-i386excep(Map *map, Rgetter rget)
-{
- uint32 c;
- uvlong pc;
- static char buf[16];
-
- c = (*rget)(map, "TRAP");
- if(c > 64 || excname[c] == 0) {
- if (c == 3) {
- pc = (*rget)(map, "PC");
- if (get1(map, pc, (uchar*)buf, machdata->bpsize) > 0)
- if (memcmp(buf, machdata->bpinst, machdata->bpsize) == 0)
- return "breakpoint";
- }
- snprint(buf, sizeof(buf), "exception %d", c);
- return buf;
- } else
- return excname[c];
-}
-
-static int
-i386trace(Map *map, uvlong pc, uvlong sp, uvlong link, Tracer trace)
-{
- int i;
- uvlong osp, pc1;
- Symbol s, f, s1;
- extern Mach mamd64;
- int isamd64;
- uvlong g, m, lessstack, morestack, stktop;
-
- isamd64 = (mach == &mamd64);
-
- // ../pkg/runtime/runtime.h
- // G is
- // byte* stackguard
- // byte* stackbase (= Stktop*)
- // TODO(rsc): Need some way to get at the g for other threads.
- // Probably need to pass it into the trace function.
- g = 0;
- if(isamd64)
- geta(map, offsetof(struct UregAmd64, r15), &g);
- else {
- // TODO(rsc): How to fetch g on 386?
- }
- stktop = 0;
- if(g != 0)
- geta(map, g+1*mach->szaddr, &stktop);
-
- lessstack = 0;
- if(lookup(0, LESSSTACK, &s))
- lessstack = s.value;
- morestack = 0;
- if(lookup(0, MORESTACK, &s))
- morestack = s.value;
-
- USED(link);
- osp = 0;
- i = 0;
-
- for(;;) {
- if(!findsym(pc, CTEXT, &s)) {
- // check for closure return sequence
- uchar buf[8], *p;
- if(get1(map, pc, buf, 8) < 0)
- break;
- // ADDQ $xxx, SP; RET
- p = buf;
- if(mach == &mamd64) {
- if(p[0] != 0x48)
- break;
- p++;
- }
- if(p[0] != 0x81 || p[1] != 0xc4 || p[6] != 0xc3)
- break;
- sp += p[2] | (p[3]<<8) | (p[4]<<16) | (p[5]<<24);
- if(geta(map, sp, &pc) < 0)
- break;
- sp += mach->szaddr;
- continue;
- }
-
- if (osp == sp)
- break;
- osp = sp;
-
- if(strcmp(STARTSYM, s.name) == 0 ||
- strcmp(GOSTARTSYM, s.name) == 0 ||
- strcmp(PROFSYM, s.name) == 0)
- break;
-
- if(s.value == morestack) {
- // This code is old and won't work anymore.
- // But no one uses it anyway.
- // Leave it obviously broken until someone needs it.
- werrstr("morestack not implemented correctly");
- return -1;
- // In the middle of morestack.
- // Caller is m->morepc.
- // Caller's caller is in m->morearg.
- // TODO(rsc): 386
- geta(map, offsetof(struct UregAmd64, r14), &m);
-
- pc = 0;
- sp = 0;
- pc1 = 0;
- s1 = s;
- memset(&s, 0, sizeof s);
- geta(map, m+1*mach->szaddr, &pc1); // m->morepc
- geta(map, m+2*mach->szaddr, &sp); // m->morebuf.sp
- geta(map, m+3*mach->szaddr, &pc); // m->morebuf.pc
- findsym(pc1, CTEXT, &s);
- (*trace)(map, pc1, sp-mach->szaddr, &s1); // morestack symbol; caller's PC/SP
-
- // caller's caller
- s1 = s;
- findsym(pc, CTEXT, &s);
- (*trace)(map, pc, sp, &s1); // morestack's caller; caller's caller's PC/SP
- continue;
- }
-
- if(pc == lessstack) {
- // ../pkg/runtime/runtime.h
- // Stktop is
- // byte* stackguard
- // byte* stackbase
- // Gobuf gobuf
- // byte* sp;
- // byte* pc;
- // G* g;
- if(!isamd64)
- fprint(2, "warning: cannot unwind stack split on 386\n");
- if(stktop == 0)
- break;
- pc = 0;
- sp = 0;
- geta(map, stktop+2*mach->szaddr, &sp);
- geta(map, stktop+3*mach->szaddr, &pc);
- geta(map, stktop+1*mach->szaddr, &stktop);
- (*trace)(map, pc, sp, &s1);
- continue;
- }
-
- s1 = s;
- pc1 = 0;
- if(pc != s.value) { /* not at first instruction */
- if(findlocal(&s, FRAMENAME, &f) == 0)
- break;
- geta(map, sp, &pc1);
- sp += f.value-mach->szaddr;
- }
- if(geta(map, sp, &pc) < 0)
- break;
-
- // If PC is not valid, assume we caught the function
- // before it moved the stack pointer down or perhaps
- // after it moved the stack pointer back up.
- // Try the PC we'd have gotten without the stack
- // pointer adjustment above (pc != s.value).
- // This only matters for the first frame, and it is only
- // a heuristic, but it does help.
- if(!findsym(pc, CTEXT, &s) || strcmp(s.name, "etext") == 0)
- pc = pc1;
-
- if(pc == 0)
- break;
-
- if(pc != lessstack)
- (*trace)(map, pc, sp, &s1);
- sp += mach->szaddr;
-
- if(++i > 1000)
- break;
- }
- return i;
-}
-
-static uvlong
-i386frame(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong link)
-{
- Symbol s, f;
-
- USED(link);
- while (findsym(pc, CTEXT, &s)) {
- if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
- break;
-
- if(pc != s.value) { /* not first instruction */
- if(findlocal(&s, FRAMENAME, &f) == 0)
- break;
- sp += f.value-mach->szaddr;
- }
-
- if (s.value == addr)
- return sp;
-
- if (geta(map, sp, &pc) < 0)
- break;
- sp += mach->szaddr;
- }
- return 0;
-}
-
- /* I386/486 - Disassembler and related functions */
-
-/*
- * an instruction
- */
-typedef struct Instr Instr;
-struct Instr
-{
- uchar mem[1+1+1+1+2+1+1+4+4]; /* raw instruction */
- uvlong addr; /* address of start of instruction */
- int n; /* number of bytes in instruction */
- char *prefix; /* instr prefix */
- char *segment; /* segment override */
- uchar jumptype; /* set to the operand type for jump/ret/call */
- uchar amd64;
- uchar rex; /* REX prefix (or zero) */
- char osize; /* 'W' or 'L' (or 'Q' on amd64) */
- char asize; /* address size 'W' or 'L' (or 'Q' or amd64) */
- uchar mod; /* bits 6-7 of mod r/m field */
- uchar reg; /* bits 3-5 of mod r/m field */
- char ss; /* bits 6-7 of SIB */
- schar index; /* bits 3-5 of SIB */
- schar base; /* bits 0-2 of SIB */
- char rip; /* RIP-relative in amd64 mode */
- uchar opre; /* f2/f3 could introduce media */
- short seg; /* segment of far address */
- uint32 disp; /* displacement */
- uint32 imm; /* immediate */
- uint32 imm2; /* second immediate operand */
- uvlong imm64; /* big immediate */
- char *curr; /* fill level in output buffer */
- char *end; /* end of output buffer */
- char *err; /* error message */
-};
-
- /* 386 register (ha!) set */
-enum{
- AX=0,
- CX,
- DX,
- BX,
- SP,
- BP,
- SI,
- DI,
-
- /* amd64 */
- /* be careful: some unix system headers #define R8, R9, etc */
- AMD64_R8,
- AMD64_R9,
- AMD64_R10,
- AMD64_R11,
- AMD64_R12,
- AMD64_R13,
- AMD64_R14,
- AMD64_R15
-};
-
- /* amd64 rex extension byte */
-enum{
- REXW = 1<<3, /* =1, 64-bit operand size */
- REXR = 1<<2, /* extend modrm reg */
- REXX = 1<<1, /* extend sib index */
- REXB = 1<<0 /* extend modrm r/m, sib base, or opcode reg */
-};
-
- /* Operand Format codes */
-/*
-%A - address size register modifier (!asize -> 'E')
-%C - Control register CR0/CR1/CR2
-%D - Debug register DR0/DR1/DR2/DR3/DR6/DR7
-%I - second immediate operand
-%O - Operand size register modifier (!osize -> 'E')
-%T - Test register TR6/TR7
-%S - size code ('W' or 'L')
-%W - Weird opcode: OSIZE == 'W' => "CBW"; else => "CWDE"
-%d - displacement 16-32 bits
-%e - effective address - Mod R/M value
-%f - floating point register F0-F7 - from Mod R/M register
-%g - segment register
-%i - immediate operand 8-32 bits
-%p - PC-relative - signed displacement in immediate field
-%r - Reg from Mod R/M
-%w - Weird opcode: OSIZE == 'W' => "CWD"; else => "CDQ"
-*/
-
-typedef struct Optable Optable;
-struct Optable
-{
- char operand[2];
- void *proto; /* actually either (char*) or (Optable*) */
-};
- /* Operand decoding codes */
-enum {
- Ib = 1, /* 8-bit immediate - (no sign extension)*/
- Ibs, /* 8-bit immediate (sign extended) */
- Jbs, /* 8-bit sign-extended immediate in jump or call */
- Iw, /* 16-bit immediate -> imm */
- Iw2, /* 16-bit immediate -> imm2 */
- Iwd, /* Operand-sized immediate (no sign extension)*/
- Iwdq, /* Operand-sized immediate, possibly 64 bits */
- Awd, /* Address offset */
- Iwds, /* Operand-sized immediate (sign extended) */
- RM, /* Word or int32 R/M field with register (/r) */
- RMB, /* Byte R/M field with register (/r) */
- RMOP, /* Word or int32 R/M field with op code (/digit) */
- RMOPB, /* Byte R/M field with op code (/digit) */
- RMR, /* R/M register only (mod = 11) */
- RMM, /* R/M memory only (mod = 0/1/2) */
- Op_R0, /* Base reg of Mod R/M is literal 0x00 */
- Op_R1, /* Base reg of Mod R/M is literal 0x01 */
- FRMOP, /* Floating point R/M field with opcode */
- FRMEX, /* Extended floating point R/M field with opcode */
- JUMP, /* Jump or Call flag - no operand */
- RET, /* Return flag - no operand */
- OA, /* literal 0x0a byte */
- PTR, /* Seg:Displacement addr (ptr16:16 or ptr16:32) */
- AUX, /* Multi-byte op code - Auxiliary table */
- AUXMM, /* multi-byte op code - auxiliary table chosen by prefix */
- PRE, /* Instr Prefix */
- OPRE, /* Instr Prefix or media op extension */
- SEG, /* Segment Prefix */
- OPOVER, /* Operand size override */
- ADDOVER, /* Address size override */
-};
-
-static Optable optab0F00[8]=
-{
-[0x00] = { 0,0, "MOVW LDT,%e" },
-[0x01] = { 0,0, "MOVW TR,%e" },
-[0x02] = { 0,0, "MOVW %e,LDT" },
-[0x03] = { 0,0, "MOVW %e,TR" },
-[0x04] = { 0,0, "VERR %e" },
-[0x05] = { 0,0, "VERW %e" },
-};
-
-static Optable optab0F01[8]=
-{
-[0x00] = { 0,0, "MOVL GDTR,%e" },
-[0x01] = { 0,0, "MOVL IDTR,%e" },
-[0x02] = { 0,0, "MOVL %e,GDTR" },
-[0x03] = { 0,0, "MOVL %e,IDTR" },
-[0x04] = { 0,0, "MOVW MSW,%e" }, /* word */
-[0x06] = { 0,0, "MOVW %e,MSW" }, /* word */
-[0x07] = { 0,0, "INVLPG %e" }, /* or SWAPGS */
-};
-
-static Optable optab0F01F8[1]=
-{
-[0x00] = { 0,0, "SWAPGS" },
-};
-
-/* 0F71 */
-/* 0F72 */
-/* 0F73 */
-
-static Optable optab0FAE[8]=
-{
-[0x00] = { 0,0, "FXSAVE %e" },
-[0x01] = { 0,0, "FXRSTOR %e" },
-[0x02] = { 0,0, "LDMXCSR %e" },
-[0x03] = { 0,0, "STMXCSR %e" },
-[0x05] = { 0,0, "LFENCE" },
-[0x06] = { 0,0, "MFENCE" },
-[0x07] = { 0,0, "SFENCE" },
-};
-
-static Optable optab0F18[4]=
-{
-[0x00] = { 0,0, "PREFETCHNTA %e" },
-[0x01] = { 0,0, "PREFECTCH0 %e" },
-[0x02] = { 0,0, "PREFECTCH1 %e" },
-[0x03] = { 0,0, "PREFECTCH2 %e" },
-};
-
-/* 0F0D */
-
-static Optable optab0FBA[8]=
-{
-[0x04] = { Ib,0, "BT%S %i,%e" },
-[0x05] = { Ib,0, "BTS%S %i,%e" },
-[0x06] = { Ib,0, "BTR%S %i,%e" },
-[0x07] = { Ib,0, "BTC%S %i,%e" },
-};
-
-static Optable optab0F0F[256]=
-{
-[0x0c] = { 0,0, "PI2FW %m,%M" },
-[0x0d] = { 0,0, "PI2L %m,%M" },
-[0x1c] = { 0,0, "PF2IW %m,%M" },
-[0x1d] = { 0,0, "PF2IL %m,%M" },
-[0x8a] = { 0,0, "PFNACC %m,%M" },
-[0x8e] = { 0,0, "PFPNACC %m,%M" },
-[0x90] = { 0,0, "PFCMPGE %m,%M" },
-[0x94] = { 0,0, "PFMIN %m,%M" },
-[0x96] = { 0,0, "PFRCP %m,%M" },
-[0x97] = { 0,0, "PFRSQRT %m,%M" },
-[0x9a] = { 0,0, "PFSUB %m,%M" },
-[0x9e] = { 0,0, "PFADD %m,%M" },
-[0xa0] = { 0,0, "PFCMPGT %m,%M" },
-[0xa4] = { 0,0, "PFMAX %m,%M" },
-[0xa6] = { 0,0, "PFRCPIT1 %m,%M" },
-[0xa7] = { 0,0, "PFRSQIT1 %m,%M" },
-[0xaa] = { 0,0, "PFSUBR %m,%M" },
-[0xae] = { 0,0, "PFACC %m,%M" },
-[0xb0] = { 0,0, "PFCMPEQ %m,%M" },
-[0xb4] = { 0,0, "PFMUL %m,%M" },
-[0xb6] = { 0,0, "PFRCPI2T %m,%M" },
-[0xb7] = { 0,0, "PMULHRW %m,%M" },
-[0xbb] = { 0,0, "PSWAPL %m,%M" },
-};
-
-static Optable optab0FC7[8]=
-{
-[0x01] = { 0,0, "CMPXCHG8B %e" },
-};
-
-static Optable optab660F38[256]=
-{
-[0x00] = { RM,0, "PSHUFB %x,%X" },
-[0xdc] = { RM,0, "AESENC %x,%X" },
-[0xdb] = { RM,0, "AESIMC %x,%X," },
-[0xdd] = { RM,0, "AESENCLAST %x,%X" },
-[0xde] = { RM,0, "AESDEC %x,%X" },
-[0xdf] = { RM,0, "AESDECLAST %x,%X" },
-};
-
-static Optable optab660F3A[256]=
-{
-[0x22] = { RM,Ib, "PINSR%S %i,%e,%X" },
-[0xdf] = { RM,Ib, "AESKEYGENASSIST %i,%x,%X" },
-};
-
-static Optable optab660F71[8]=
-{
-[0x02] = { Ib,0, "PSRLW %i,%X" },
-[0x04] = { Ib,0, "PSRAW %i,%X" },
-[0x06] = { Ib,0, "PSLLW %i,%X" },
-};
-
-static Optable optab660F72[8]=
-{
-[0x02] = { Ib,0, "PSRLL %i,%X" },
-[0x04] = { Ib,0, "PSRAL %i,%X" },
-[0x06] = { Ib,0, "PSLLL %i,%X" },
-};
-
-static Optable optab660F73[8]=
-{
-[0x02] = { Ib,0, "PSRLQ %i,%X" },
-[0x03] = { Ib,0, "PSRLO %i,%X" },
-[0x06] = { Ib,0, "PSLLQ %i,%X" },
-[0x07] = { Ib,0, "PSLLO %i,%X" },
-};
-
-static Optable optab660F[256]=
-{
-[0x2B] = { RM,0, "MOVNTPD %x,%e" },
-[0x2E] = { RM,0, "UCOMISD %x,%X" },
-[0x2F] = { RM,0, "COMISD %x,%X" },
-[0x38] = { AUX,0, optab660F38 },
-[0x3A] = { AUX,0, optab660F3A },
-[0x5A] = { RM,0, "CVTPD2PS %x,%X" },
-[0x5B] = { RM,0, "CVTPS2PL %x,%X" },
-[0x6A] = { RM,0, "PUNPCKHLQ %x,%X" },
-[0x6B] = { RM,0, "PACKSSLW %x,%X" },
-[0x6C] = { RM,0, "PUNPCKLQDQ %x,%X" },
-[0x6D] = { RM,0, "PUNPCKHQDQ %x,%X" },
-[0x6E] = { RM,0, "MOV%S %e,%X" },
-[0x6F] = { RM,0, "MOVO %x,%X" }, /* MOVDQA */
-[0x70] = { RM,Ib, "PSHUFL %i,%x,%X" },
-[0x71] = { RMOP,0, optab660F71 },
-[0x72] = { RMOP,0, optab660F72 },
-[0x73] = { RMOP,0, optab660F73 },
-[0x7E] = { RM,0, "MOV%S %X,%e" },
-[0x7F] = { RM,0, "MOVO %X,%x" },
-[0xC4] = { RM,Ib, "PINSRW %i,%e,%X" },
-[0xC5] = { RMR,Ib, "PEXTRW %i,%X,%e" },
-[0xD4] = { RM,0, "PADDQ %x,%X" },
-[0xD5] = { RM,0, "PMULLW %x,%X" },
-[0xD6] = { RM,0, "MOVQ %X,%x" },
-[0xE6] = { RM,0, "CVTTPD2PL %x,%X" },
-[0xE7] = { RM,0, "MOVNTO %X,%e" },
-[0xF7] = { RM,0, "MASKMOVOU %x,%X" },
-};
-
-static Optable optabF20F38[256]=
-{
-[0xf0] = { RM,0, "CRC32B %e, %r" },
-[0xf1] = { RM,0, "CRC32%S %e, %r" },
-};
-
-static Optable optabF20F[256]=
-{
-[0x10] = { RM,0, "MOVSD %x,%X" },
-[0x11] = { RM,0, "MOVSD %X,%x" },
-[0x2A] = { RM,0, "CVTS%S2SD %e,%X" },
-[0x2C] = { RM,0, "CVTTSD2S%S %x,%r" },
-[0x2D] = { RM,0, "CVTSD2S%S %x,%r" },
-[0x38] = { AUX,0, optabF20F38 },
-[0x5A] = { RM,0, "CVTSD2SS %x,%X" },
-[0x6F] = { RM,0, "MOVOU %x,%X" },
-[0x70] = { RM,Ib, "PSHUFLW %i,%x,%X" },
-[0x7F] = { RM,0, "MOVOU %X,%x" },
-[0xD6] = { RM,0, "MOVQOZX %M,%X" },
-[0xE6] = { RM,0, "CVTPD2PL %x,%X" },
-};
-
-static Optable optabF30F[256]=
-{
-[0x10] = { RM,0, "MOVSS %x,%X" },
-[0x11] = { RM,0, "MOVSS %X,%x" },
-[0x2A] = { RM,0, "CVTS%S2SS %e,%X" },
-[0x2C] = { RM,0, "CVTTSS2S%S %x,%r" },
-[0x2D] = { RM,0, "CVTSS2S%S %x,%r" },
-[0x5A] = { RM,0, "CVTSS2SD %x,%X" },
-[0x5B] = { RM,0, "CVTTPS2PL %x,%X" },
-[0x6F] = { RM,0, "MOVOU %x,%X" },
-[0x70] = { RM,Ib, "PSHUFHW %i,%x,%X" },
-[0x7E] = { RM,0, "MOVQOZX %x,%X" },
-[0x7F] = { RM,0, "MOVOU %X,%x" },
-[0xD6] = { RM,0, "MOVQOZX %m*,%X" },
-[0xE6] = { RM,0, "CVTPL2PD %x,%X" },
-};
-
-static Optable optab0F[256]=
-{
-[0x00] = { RMOP,0, optab0F00 },
-[0x01] = { RMOP,0, optab0F01 },
-[0x02] = { RM,0, "LAR %e,%r" },
-[0x03] = { RM,0, "LSL %e,%r" },
-[0x05] = { 0,0, "SYSCALL" },
-[0x06] = { 0,0, "CLTS" },
-[0x07] = { 0,0, "SYSRET" },
-[0x08] = { 0,0, "INVD" },
-[0x09] = { 0,0, "WBINVD" },
-[0x0B] = { 0,0, "UD2" },
-[0x0F] = { RM,AUX, optab0F0F }, /* 3DNow! */
-[0x10] = { RM,0, "MOVU%s %x,%X" },
-[0x11] = { RM,0, "MOVU%s %X,%x" },
-[0x12] = { RM,0, "MOV[H]L%s %x,%X" }, /* TO DO: H if source is XMM */
-[0x13] = { RM,0, "MOVL%s %X,%e" },
-[0x14] = { RM,0, "UNPCKL%s %x,%X" },
-[0x15] = { RM,0, "UNPCKH%s %x,%X" },
-[0x16] = { RM,0, "MOV[L]H%s %x,%X" }, /* TO DO: L if source is XMM */
-[0x17] = { RM,0, "MOVH%s %X,%x" },
-[0x18] = { RMOP,0, optab0F18 },
-[0x1F] = { RM,0, "NOP%S %e" },
-[0x20] = { RMR,0, "MOVL %C,%e" },
-[0x21] = { RMR,0, "MOVL %D,%e" },
-[0x22] = { RMR,0, "MOVL %e,%C" },
-[0x23] = { RMR,0, "MOVL %e,%D" },
-[0x24] = { RMR,0, "MOVL %T,%e" },
-[0x26] = { RMR,0, "MOVL %e,%T" },
-[0x28] = { RM,0, "MOVA%s %x,%X" },
-[0x29] = { RM,0, "MOVA%s %X,%x" },
-[0x2A] = { RM,0, "CVTPL2%s %m*,%X" },
-[0x2B] = { RM,0, "MOVNT%s %X,%e" },
-[0x2C] = { RM,0, "CVTT%s2PL %x,%M" },
-[0x2D] = { RM,0, "CVT%s2PL %x,%M" },
-[0x2E] = { RM,0, "UCOMISS %x,%X" },
-[0x2F] = { RM,0, "COMISS %x,%X" },
-[0x30] = { 0,0, "WRMSR" },
-[0x31] = { 0,0, "RDTSC" },
-[0x32] = { 0,0, "RDMSR" },
-[0x33] = { 0,0, "RDPMC" },
-[0x42] = { RM,0, "CMOVC %e,%r" }, /* CF */
-[0x43] = { RM,0, "CMOVNC %e,%r" }, /* ¬ CF */
-[0x44] = { RM,0, "CMOVZ %e,%r" }, /* ZF */
-[0x45] = { RM,0, "CMOVNZ %e,%r" }, /* ¬ ZF */
-[0x46] = { RM,0, "CMOVBE %e,%r" }, /* CF ∨ ZF */
-[0x47] = { RM,0, "CMOVA %e,%r" }, /* ¬CF ∧ ¬ZF */
-[0x48] = { RM,0, "CMOVS %e,%r" }, /* SF */
-[0x49] = { RM,0, "CMOVNS %e,%r" }, /* ¬ SF */
-[0x4A] = { RM,0, "CMOVP %e,%r" }, /* PF */
-[0x4B] = { RM,0, "CMOVNP %e,%r" }, /* ¬ PF */
-[0x4C] = { RM,0, "CMOVLT %e,%r" }, /* LT ≡ OF ≠ SF */
-[0x4D] = { RM,0, "CMOVGE %e,%r" }, /* GE ≡ ZF ∨ SF */
-[0x4E] = { RM,0, "CMOVLE %e,%r" }, /* LE ≡ ZF ∨ LT */
-[0x4F] = { RM,0, "CMOVGT %e,%r" }, /* GT ≡ ¬ZF ∧ GE */
-[0x50] = { RM,0, "MOVMSK%s %X,%r" }, /* TO DO: check */
-[0x51] = { RM,0, "SQRT%s %x,%X" },
-[0x52] = { RM,0, "RSQRT%s %x,%X" },
-[0x53] = { RM,0, "RCP%s %x,%X" },
-[0x54] = { RM,0, "AND%s %x,%X" },
-[0x55] = { RM,0, "ANDN%s %x,%X" },
-[0x56] = { RM,0, "OR%s %x,%X" }, /* TO DO: S/D */
-[0x57] = { RM,0, "XOR%s %x,%X" }, /* S/D */
-[0x58] = { RM,0, "ADD%s %x,%X" }, /* S/P S/D */
-[0x59] = { RM,0, "MUL%s %x,%X" },
-[0x5A] = { RM,0, "CVTPS2PD %x,%X" },
-[0x5B] = { RM,0, "CVTPL2PS %x,%X" },
-[0x5C] = { RM,0, "SUB%s %x,%X" },
-[0x5D] = { RM,0, "MIN%s %x,%X" },
-[0x5E] = { RM,0, "DIV%s %x,%X" }, /* TO DO: S/P S/D */
-[0x5F] = { RM,0, "MAX%s %x,%X" },
-[0x60] = { RM,0, "PUNPCKLBW %m,%M" },
-[0x61] = { RM,0, "PUNPCKLWL %m,%M" },
-[0x62] = { RM,0, "PUNPCKLLQ %m,%M" },
-[0x63] = { RM,0, "PACKSSWB %m,%M" },
-[0x64] = { RM,0, "PCMPGTB %m,%M" },
-[0x65] = { RM,0, "PCMPGTW %m,%M" },
-[0x66] = { RM,0, "PCMPGTL %m,%M" },
-[0x67] = { RM,0, "PACKUSWB %m,%M" },
-[0x68] = { RM,0, "PUNPCKHBW %m,%M" },
-[0x69] = { RM,0, "PUNPCKHWL %m,%M" },
-[0x6A] = { RM,0, "PUNPCKHLQ %m,%M" },
-[0x6B] = { RM,0, "PACKSSLW %m,%M" },
-[0x6E] = { RM,0, "MOV%S %e,%M" },
-[0x6F] = { RM,0, "MOVQ %m,%M" },
-[0x70] = { RM,Ib, "PSHUFW %i,%m,%M" },
-[0x74] = { RM,0, "PCMPEQB %m,%M" },
-[0x75] = { RM,0, "PCMPEQW %m,%M" },
-[0x76] = { RM,0, "PCMPEQL %m,%M" },
-[0x77] = { 0,0, "EMMS" },
-[0x7E] = { RM,0, "MOV%S %M,%e" },
-[0x7F] = { RM,0, "MOVQ %M,%m" },
-[0xAE] = { RMOP,0, optab0FAE },
-[0xAA] = { 0,0, "RSM" },
-[0xB0] = { RM,0, "CMPXCHGB %r,%e" },
-[0xB1] = { RM,0, "CMPXCHG%S %r,%e" },
-[0xC0] = { RMB,0, "XADDB %r,%e" },
-[0xC1] = { RM,0, "XADD%S %r,%e" },
-[0xC2] = { RM,Ib, "CMP%s %x,%X,%#i" },
-[0xC3] = { RM,0, "MOVNTI%S %r,%e" },
-[0xC6] = { RM,Ib, "SHUF%s %i,%x,%X" },
-[0xC8] = { 0,0, "BSWAP AX" },
-[0xC9] = { 0,0, "BSWAP CX" },
-[0xCA] = { 0,0, "BSWAP DX" },
-[0xCB] = { 0,0, "BSWAP BX" },
-[0xCC] = { 0,0, "BSWAP SP" },
-[0xCD] = { 0,0, "BSWAP BP" },
-[0xCE] = { 0,0, "BSWAP SI" },
-[0xCF] = { 0,0, "BSWAP DI" },
-[0xD1] = { RM,0, "PSRLW %m,%M" },
-[0xD2] = { RM,0, "PSRLL %m,%M" },
-[0xD3] = { RM,0, "PSRLQ %m,%M" },
-[0xD5] = { RM,0, "PMULLW %m,%M" },
-[0xD6] = { RM,0, "MOVQOZX %m*,%X" },
-[0xD7] = { RM,0, "PMOVMSKB %m,%r" },
-[0xD8] = { RM,0, "PSUBUSB %m,%M" },
-[0xD9] = { RM,0, "PSUBUSW %m,%M" },
-[0xDA] = { RM,0, "PMINUB %m,%M" },
-[0xDB] = { RM,0, "PAND %m,%M" },
-[0xDC] = { RM,0, "PADDUSB %m,%M" },
-[0xDD] = { RM,0, "PADDUSW %m,%M" },
-[0xDE] = { RM,0, "PMAXUB %m,%M" },
-[0xDF] = { RM,0, "PANDN %m,%M" },
-[0xE0] = { RM,0, "PAVGB %m,%M" },
-[0xE1] = { RM,0, "PSRAW %m,%M" },
-[0xE2] = { RM,0, "PSRAL %m,%M" },
-[0xE3] = { RM,0, "PAVGW %m,%M" },
-[0xE4] = { RM,0, "PMULHUW %m,%M" },
-[0xE5] = { RM,0, "PMULHW %m,%M" },
-[0xE7] = { RM,0, "MOVNTQ %M,%e" },
-[0xE8] = { RM,0, "PSUBSB %m,%M" },
-[0xE9] = { RM,0, "PSUBSW %m,%M" },
-[0xEA] = { RM,0, "PMINSW %m,%M" },
-[0xEB] = { RM,0, "POR %m,%M" },
-[0xEC] = { RM,0, "PADDSB %m,%M" },
-[0xED] = { RM,0, "PADDSW %m,%M" },
-[0xEE] = { RM,0, "PMAXSW %m,%M" },
-[0xEF] = { RM,0, "PXOR %m,%M" },
-[0xF1] = { RM,0, "PSLLW %m,%M" },
-[0xF2] = { RM,0, "PSLLL %m,%M" },
-[0xF3] = { RM,0, "PSLLQ %m,%M" },
-[0xF4] = { RM,0, "PMULULQ %m,%M" },
-[0xF5] = { RM,0, "PMADDWL %m,%M" },
-[0xF6] = { RM,0, "PSADBW %m,%M" },
-[0xF7] = { RMR,0, "MASKMOVQ %m,%M" },
-[0xF8] = { RM,0, "PSUBB %m,%M" },
-[0xF9] = { RM,0, "PSUBW %m,%M" },
-[0xFA] = { RM,0, "PSUBL %m,%M" },
-[0xFC] = { RM,0, "PADDB %m,%M" },
-[0xFD] = { RM,0, "PADDW %m,%M" },
-[0xFE] = { RM,0, "PADDL %m,%M" },
-
-[0x80] = { Iwds,0, "JOS %p" },
-[0x81] = { Iwds,0, "JOC %p" },
-[0x82] = { Iwds,0, "JCS %p" },
-[0x83] = { Iwds,0, "JCC %p" },
-[0x84] = { Iwds,0, "JEQ %p" },
-[0x85] = { Iwds,0, "JNE %p" },
-[0x86] = { Iwds,0, "JLS %p" },
-[0x87] = { Iwds,0, "JHI %p" },
-[0x88] = { Iwds,0, "JMI %p" },
-[0x89] = { Iwds,0, "JPL %p" },
-[0x8a] = { Iwds,0, "JPS %p" },
-[0x8b] = { Iwds,0, "JPC %p" },
-[0x8c] = { Iwds,0, "JLT %p" },
-[0x8d] = { Iwds,0, "JGE %p" },
-[0x8e] = { Iwds,0, "JLE %p" },
-[0x8f] = { Iwds,0, "JGT %p" },
-[0x90] = { RMB,0, "SETOS %e" },
-[0x91] = { RMB,0, "SETOC %e" },
-[0x92] = { RMB,0, "SETCS %e" },
-[0x93] = { RMB,0, "SETCC %e" },
-[0x94] = { RMB,0, "SETEQ %e" },
-[0x95] = { RMB,0, "SETNE %e" },
-[0x96] = { RMB,0, "SETLS %e" },
-[0x97] = { RMB,0, "SETHI %e" },
-[0x98] = { RMB,0, "SETMI %e" },
-[0x99] = { RMB,0, "SETPL %e" },
-[0x9a] = { RMB,0, "SETPS %e" },
-[0x9b] = { RMB,0, "SETPC %e" },
-[0x9c] = { RMB,0, "SETLT %e" },
-[0x9d] = { RMB,0, "SETGE %e" },
-[0x9e] = { RMB,0, "SETLE %e" },
-[0x9f] = { RMB,0, "SETGT %e" },
-[0xa0] = { 0,0, "PUSHL FS" },
-[0xa1] = { 0,0, "POPL FS" },
-[0xa2] = { 0,0, "CPUID" },
-[0xa3] = { RM,0, "BT%S %r,%e" },
-[0xa4] = { RM,Ib, "SHLD%S %r,%i,%e" },
-[0xa5] = { RM,0, "SHLD%S %r,CL,%e" },
-[0xa8] = { 0,0, "PUSHL GS" },
-[0xa9] = { 0,0, "POPL GS" },
-[0xab] = { RM,0, "BTS%S %r,%e" },
-[0xac] = { RM,Ib, "SHRD%S %r,%i,%e" },
-[0xad] = { RM,0, "SHRD%S %r,CL,%e" },
-[0xaf] = { RM,0, "IMUL%S %e,%r" },
-[0xb2] = { RMM,0, "LSS %e,%r" },
-[0xb3] = { RM,0, "BTR%S %r,%e" },
-[0xb4] = { RMM,0, "LFS %e,%r" },
-[0xb5] = { RMM,0, "LGS %e,%r" },
-[0xb6] = { RMB,0, "MOVBZX %e,%R" },
-[0xb7] = { RM,0, "MOVWZX %e,%R" },
-[0xba] = { RMOP,0, optab0FBA },
-[0xbb] = { RM,0, "BTC%S %e,%r" },
-[0xbc] = { RM,0, "BSF%S %e,%r" },
-[0xbd] = { RM,0, "BSR%S %e,%r" },
-[0xbe] = { RMB,0, "MOVBSX %e,%R" },
-[0xbf] = { RM,0, "MOVWSX %e,%R" },
-[0xc7] = { RMOP,0, optab0FC7 },
-};
-
-static Optable optab80[8]=
-{
-[0x00] = { Ib,0, "ADDB %i,%e" },
-[0x01] = { Ib,0, "ORB %i,%e" },
-[0x02] = { Ib,0, "ADCB %i,%e" },
-[0x03] = { Ib,0, "SBBB %i,%e" },
-[0x04] = { Ib,0, "ANDB %i,%e" },
-[0x05] = { Ib,0, "SUBB %i,%e" },
-[0x06] = { Ib,0, "XORB %i,%e" },
-[0x07] = { Ib,0, "CMPB %e,%i" },
-};
-
-static Optable optab81[8]=
-{
-[0x00] = { Iwd,0, "ADD%S %i,%e" },
-[0x01] = { Iwd,0, "OR%S %i,%e" },
-[0x02] = { Iwd,0, "ADC%S %i,%e" },
-[0x03] = { Iwd,0, "SBB%S %i,%e" },
-[0x04] = { Iwd,0, "AND%S %i,%e" },
-[0x05] = { Iwd,0, "SUB%S %i,%e" },
-[0x06] = { Iwd,0, "XOR%S %i,%e" },
-[0x07] = { Iwd,0, "CMP%S %e,%i" },
-};
-
-static Optable optab83[8]=
-{
-[0x00] = { Ibs,0, "ADD%S %i,%e" },
-[0x01] = { Ibs,0, "OR%S %i,%e" },
-[0x02] = { Ibs,0, "ADC%S %i,%e" },
-[0x03] = { Ibs,0, "SBB%S %i,%e" },
-[0x04] = { Ibs,0, "AND%S %i,%e" },
-[0x05] = { Ibs,0, "SUB%S %i,%e" },
-[0x06] = { Ibs,0, "XOR%S %i,%e" },
-[0x07] = { Ibs,0, "CMP%S %e,%i" },
-};
-
-static Optable optabC0[8] =
-{
-[0x00] = { Ib,0, "ROLB %i,%e" },
-[0x01] = { Ib,0, "RORB %i,%e" },
-[0x02] = { Ib,0, "RCLB %i,%e" },
-[0x03] = { Ib,0, "RCRB %i,%e" },
-[0x04] = { Ib,0, "SHLB %i,%e" },
-[0x05] = { Ib,0, "SHRB %i,%e" },
-[0x07] = { Ib,0, "SARB %i,%e" },
-};
-
-static Optable optabC1[8] =
-{
-[0x00] = { Ib,0, "ROL%S %i,%e" },
-[0x01] = { Ib,0, "ROR%S %i,%e" },
-[0x02] = { Ib,0, "RCL%S %i,%e" },
-[0x03] = { Ib,0, "RCR%S %i,%e" },
-[0x04] = { Ib,0, "SHL%S %i,%e" },
-[0x05] = { Ib,0, "SHR%S %i,%e" },
-[0x07] = { Ib,0, "SAR%S %i,%e" },
-};
-
-static Optable optabD0[8] =
-{
-[0x00] = { 0,0, "ROLB %e" },
-[0x01] = { 0,0, "RORB %e" },
-[0x02] = { 0,0, "RCLB %e" },
-[0x03] = { 0,0, "RCRB %e" },
-[0x04] = { 0,0, "SHLB %e" },
-[0x05] = { 0,0, "SHRB %e" },
-[0x07] = { 0,0, "SARB %e" },
-};
-
-static Optable optabD1[8] =
-{
-[0x00] = { 0,0, "ROL%S %e" },
-[0x01] = { 0,0, "ROR%S %e" },
-[0x02] = { 0,0, "RCL%S %e" },
-[0x03] = { 0,0, "RCR%S %e" },
-[0x04] = { 0,0, "SHL%S %e" },
-[0x05] = { 0,0, "SHR%S %e" },
-[0x07] = { 0,0, "SAR%S %e" },
-};
-
-static Optable optabD2[8] =
-{
-[0x00] = { 0,0, "ROLB CL,%e" },
-[0x01] = { 0,0, "RORB CL,%e" },
-[0x02] = { 0,0, "RCLB CL,%e" },
-[0x03] = { 0,0, "RCRB CL,%e" },
-[0x04] = { 0,0, "SHLB CL,%e" },
-[0x05] = { 0,0, "SHRB CL,%e" },
-[0x07] = { 0,0, "SARB CL,%e" },
-};
-
-static Optable optabD3[8] =
-{
-[0x00] = { 0,0, "ROL%S CL,%e" },
-[0x01] = { 0,0, "ROR%S CL,%e" },
-[0x02] = { 0,0, "RCL%S CL,%e" },
-[0x03] = { 0,0, "RCR%S CL,%e" },
-[0x04] = { 0,0, "SHL%S CL,%e" },
-[0x05] = { 0,0, "SHR%S CL,%e" },
-[0x07] = { 0,0, "SAR%S CL,%e" },
-};
-
-static Optable optabD8[8+8] =
-{
-[0x00] = { 0,0, "FADDF %e,F0" },
-[0x01] = { 0,0, "FMULF %e,F0" },
-[0x02] = { 0,0, "FCOMF %e,F0" },
-[0x03] = { 0,0, "FCOMFP %e,F0" },
-[0x04] = { 0,0, "FSUBF %e,F0" },
-[0x05] = { 0,0, "FSUBRF %e,F0" },
-[0x06] = { 0,0, "FDIVF %e,F0" },
-[0x07] = { 0,0, "FDIVRF %e,F0" },
-[0x08] = { 0,0, "FADDD %f,F0" },
-[0x09] = { 0,0, "FMULD %f,F0" },
-[0x0a] = { 0,0, "FCOMD %f,F0" },
-[0x0b] = { 0,0, "FCOMPD %f,F0" },
-[0x0c] = { 0,0, "FSUBD %f,F0" },
-[0x0d] = { 0,0, "FSUBRD %f,F0" },
-[0x0e] = { 0,0, "FDIVD %f,F0" },
-[0x0f] = { 0,0, "FDIVRD %f,F0" },
-};
-/*
- * optabD9 and optabDB use the following encoding:
- * if (0 <= modrm <= 2) instruction = optabDx[modrm&0x07];
- * else instruction = optabDx[(modrm&0x3f)+8];
- *
- * the instructions for MOD == 3, follow the 8 instructions
- * for the other MOD values stored at the front of the table.
- */
-static Optable optabD9[64+8] =
-{
-[0x00] = { 0,0, "FMOVF %e,F0" },
-[0x02] = { 0,0, "FMOVF F0,%e" },
-[0x03] = { 0,0, "FMOVFP F0,%e" },
-[0x04] = { 0,0, "FLDENV%S %e" },
-[0x05] = { 0,0, "FLDCW %e" },
-[0x06] = { 0,0, "FSTENV%S %e" },
-[0x07] = { 0,0, "FSTCW %e" },
-[0x08] = { 0,0, "FMOVD F0,F0" }, /* Mod R/M = 11xx xxxx*/
-[0x09] = { 0,0, "FMOVD F1,F0" },
-[0x0a] = { 0,0, "FMOVD F2,F0" },
-[0x0b] = { 0,0, "FMOVD F3,F0" },
-[0x0c] = { 0,0, "FMOVD F4,F0" },
-[0x0d] = { 0,0, "FMOVD F5,F0" },
-[0x0e] = { 0,0, "FMOVD F6,F0" },
-[0x0f] = { 0,0, "FMOVD F7,F0" },
-[0x10] = { 0,0, "FXCHD F0,F0" },
-[0x11] = { 0,0, "FXCHD F1,F0" },
-[0x12] = { 0,0, "FXCHD F2,F0" },
-[0x13] = { 0,0, "FXCHD F3,F0" },
-[0x14] = { 0,0, "FXCHD F4,F0" },
-[0x15] = { 0,0, "FXCHD F5,F0" },
-[0x16] = { 0,0, "FXCHD F6,F0" },
-[0x17] = { 0,0, "FXCHD F7,F0" },
-[0x18] = { 0,0, "FNOP" },
-[0x28] = { 0,0, "FCHS" },
-[0x29] = { 0,0, "FABS" },
-[0x2c] = { 0,0, "FTST" },
-[0x2d] = { 0,0, "FXAM" },
-[0x30] = { 0,0, "FLD1" },
-[0x31] = { 0,0, "FLDL2T" },
-[0x32] = { 0,0, "FLDL2E" },
-[0x33] = { 0,0, "FLDPI" },
-[0x34] = { 0,0, "FLDLG2" },
-[0x35] = { 0,0, "FLDLN2" },
-[0x36] = { 0,0, "FLDZ" },
-[0x38] = { 0,0, "F2XM1" },
-[0x39] = { 0,0, "FYL2X" },
-[0x3a] = { 0,0, "FPTAN" },
-[0x3b] = { 0,0, "FPATAN" },
-[0x3c] = { 0,0, "FXTRACT" },
-[0x3d] = { 0,0, "FPREM1" },
-[0x3e] = { 0,0, "FDECSTP" },
-[0x3f] = { 0,0, "FNCSTP" },
-[0x40] = { 0,0, "FPREM" },
-[0x41] = { 0,0, "FYL2XP1" },
-[0x42] = { 0,0, "FSQRT" },
-[0x43] = { 0,0, "FSINCOS" },
-[0x44] = { 0,0, "FRNDINT" },
-[0x45] = { 0,0, "FSCALE" },
-[0x46] = { 0,0, "FSIN" },
-[0x47] = { 0,0, "FCOS" },
-};
-
-static Optable optabDA[8+8] =
-{
-[0x00] = { 0,0, "FADDL %e,F0" },
-[0x01] = { 0,0, "FMULL %e,F0" },
-[0x02] = { 0,0, "FCOML %e,F0" },
-[0x03] = { 0,0, "FCOMLP %e,F0" },
-[0x04] = { 0,0, "FSUBL %e,F0" },
-[0x05] = { 0,0, "FSUBRL %e,F0" },
-[0x06] = { 0,0, "FDIVL %e,F0" },
-[0x07] = { 0,0, "FDIVRL %e,F0" },
-[0x08] = { 0,0, "FCMOVCS %f,F0" },
-[0x09] = { 0,0, "FCMOVEQ %f,F0" },
-[0x0a] = { 0,0, "FCMOVLS %f,F0" },
-[0x0b] = { 0,0, "FCMOVUN %f,F0" },
-[0x0d] = { Op_R1,0, "FUCOMPP" },
-};
-
-static Optable optabDB[8+64] =
-{
-[0x00] = { 0,0, "FMOVL %e,F0" },
-[0x02] = { 0,0, "FMOVL F0,%e" },
-[0x03] = { 0,0, "FMOVLP F0,%e" },
-[0x05] = { 0,0, "FMOVX %e,F0" },
-[0x07] = { 0,0, "FMOVXP F0,%e" },
-[0x08] = { 0,0, "FCMOVCC F0,F0" }, /* Mod R/M = 11xx xxxx*/
-[0x09] = { 0,0, "FCMOVCC F1,F0" },
-[0x0a] = { 0,0, "FCMOVCC F2,F0" },
-[0x0b] = { 0,0, "FCMOVCC F3,F0" },
-[0x0c] = { 0,0, "FCMOVCC F4,F0" },
-[0x0d] = { 0,0, "FCMOVCC F5,F0" },
-[0x0e] = { 0,0, "FCMOVCC F6,F0" },
-[0x0f] = { 0,0, "FCMOVCC F7,F0" },
-[0x10] = { 0,0, "FCMOVNE F0,F0" },
-[0x11] = { 0,0, "FCMOVNE F1,F0" },
-[0x12] = { 0,0, "FCMOVNE F2,F0" },
-[0x13] = { 0,0, "FCMOVNE F3,F0" },
-[0x14] = { 0,0, "FCMOVNE F4,F0" },
-[0x15] = { 0,0, "FCMOVNE F5,F0" },
-[0x16] = { 0,0, "FCMOVNE F6,F0" },
-[0x17] = { 0,0, "FCMOVNE F7,F0" },
-[0x18] = { 0,0, "FCMOVHI F0,F0" },
-[0x19] = { 0,0, "FCMOVHI F1,F0" },
-[0x1a] = { 0,0, "FCMOVHI F2,F0" },
-[0x1b] = { 0,0, "FCMOVHI F3,F0" },
-[0x1c] = { 0,0, "FCMOVHI F4,F0" },
-[0x1d] = { 0,0, "FCMOVHI F5,F0" },
-[0x1e] = { 0,0, "FCMOVHI F6,F0" },
-[0x1f] = { 0,0, "FCMOVHI F7,F0" },
-[0x20] = { 0,0, "FCMOVNU F0,F0" },
-[0x21] = { 0,0, "FCMOVNU F1,F0" },
-[0x22] = { 0,0, "FCMOVNU F2,F0" },
-[0x23] = { 0,0, "FCMOVNU F3,F0" },
-[0x24] = { 0,0, "FCMOVNU F4,F0" },
-[0x25] = { 0,0, "FCMOVNU F5,F0" },
-[0x26] = { 0,0, "FCMOVNU F6,F0" },
-[0x27] = { 0,0, "FCMOVNU F7,F0" },
-[0x2a] = { 0,0, "FCLEX" },
-[0x2b] = { 0,0, "FINIT" },
-[0x30] = { 0,0, "FUCOMI F0,F0" },
-[0x31] = { 0,0, "FUCOMI F1,F0" },
-[0x32] = { 0,0, "FUCOMI F2,F0" },
-[0x33] = { 0,0, "FUCOMI F3,F0" },
-[0x34] = { 0,0, "FUCOMI F4,F0" },
-[0x35] = { 0,0, "FUCOMI F5,F0" },
-[0x36] = { 0,0, "FUCOMI F6,F0" },
-[0x37] = { 0,0, "FUCOMI F7,F0" },
-[0x38] = { 0,0, "FCOMI F0,F0" },
-[0x39] = { 0,0, "FCOMI F1,F0" },
-[0x3a] = { 0,0, "FCOMI F2,F0" },
-[0x3b] = { 0,0, "FCOMI F3,F0" },
-[0x3c] = { 0,0, "FCOMI F4,F0" },
-[0x3d] = { 0,0, "FCOMI F5,F0" },
-[0x3e] = { 0,0, "FCOMI F6,F0" },
-[0x3f] = { 0,0, "FCOMI F7,F0" },
-};
-
-static Optable optabDC[8+8] =
-{
-[0x00] = { 0,0, "FADDD %e,F0" },
-[0x01] = { 0,0, "FMULD %e,F0" },
-[0x02] = { 0,0, "FCOMD %e,F0" },
-[0x03] = { 0,0, "FCOMDP %e,F0" },
-[0x04] = { 0,0, "FSUBD %e,F0" },
-[0x05] = { 0,0, "FSUBRD %e,F0" },
-[0x06] = { 0,0, "FDIVD %e,F0" },
-[0x07] = { 0,0, "FDIVRD %e,F0" },
-[0x08] = { 0,0, "FADDD F0,%f" },
-[0x09] = { 0,0, "FMULD F0,%f" },
-[0x0c] = { 0,0, "FSUBRD F0,%f" },
-[0x0d] = { 0,0, "FSUBD F0,%f" },
-[0x0e] = { 0,0, "FDIVRD F0,%f" },
-[0x0f] = { 0,0, "FDIVD F0,%f" },
-};
-
-static Optable optabDD[8+8] =
-{
-[0x00] = { 0,0, "FMOVD %e,F0" },
-[0x02] = { 0,0, "FMOVD F0,%e" },
-[0x03] = { 0,0, "FMOVDP F0,%e" },
-[0x04] = { 0,0, "FRSTOR%S %e" },
-[0x06] = { 0,0, "FSAVE%S %e" },
-[0x07] = { 0,0, "FSTSW %e" },
-[0x08] = { 0,0, "FFREED %f" },
-[0x0a] = { 0,0, "FMOVD %f,F0" },
-[0x0b] = { 0,0, "FMOVDP %f,F0" },
-[0x0c] = { 0,0, "FUCOMD %f,F0" },
-[0x0d] = { 0,0, "FUCOMDP %f,F0" },
-};
-
-static Optable optabDE[8+8] =
-{
-[0x00] = { 0,0, "FADDW %e,F0" },
-[0x01] = { 0,0, "FMULW %e,F0" },
-[0x02] = { 0,0, "FCOMW %e,F0" },
-[0x03] = { 0,0, "FCOMWP %e,F0" },
-[0x04] = { 0,0, "FSUBW %e,F0" },
-[0x05] = { 0,0, "FSUBRW %e,F0" },
-[0x06] = { 0,0, "FDIVW %e,F0" },
-[0x07] = { 0,0, "FDIVRW %e,F0" },
-[0x08] = { 0,0, "FADDDP F0,%f" },
-[0x09] = { 0,0, "FMULDP F0,%f" },
-[0x0b] = { Op_R1,0, "FCOMPDP" },
-[0x0c] = { 0,0, "FSUBRDP F0,%f" },
-[0x0d] = { 0,0, "FSUBDP F0,%f" },
-[0x0e] = { 0,0, "FDIVRDP F0,%f" },
-[0x0f] = { 0,0, "FDIVDP F0,%f" },
-};
-
-static Optable optabDF[8+8] =
-{
-[0x00] = { 0,0, "FMOVW %e,F0" },
-[0x02] = { 0,0, "FMOVW F0,%e" },
-[0x03] = { 0,0, "FMOVWP F0,%e" },
-[0x04] = { 0,0, "FBLD %e" },
-[0x05] = { 0,0, "FMOVL %e,F0" },
-[0x06] = { 0,0, "FBSTP %e" },
-[0x07] = { 0,0, "FMOVLP F0,%e" },
-[0x0c] = { Op_R0,0, "FSTSW %OAX" },
-[0x0d] = { 0,0, "FUCOMIP F0,%f" },
-[0x0e] = { 0,0, "FCOMIP F0,%f" },
-};
-
-static Optable optabF6[8] =
-{
-[0x00] = { Ib,0, "TESTB %i,%e" },
-[0x02] = { 0,0, "NOTB %e" },
-[0x03] = { 0,0, "NEGB %e" },
-[0x04] = { 0,0, "MULB AL,%e" },
-[0x05] = { 0,0, "IMULB AL,%e" },
-[0x06] = { 0,0, "DIVB AL,%e" },
-[0x07] = { 0,0, "IDIVB AL,%e" },
-};
-
-static Optable optabF7[8] =
-{
-[0x00] = { Iwd,0, "TEST%S %i,%e" },
-[0x02] = { 0,0, "NOT%S %e" },
-[0x03] = { 0,0, "NEG%S %e" },
-[0x04] = { 0,0, "MUL%S %OAX,%e" },
-[0x05] = { 0,0, "IMUL%S %OAX,%e" },
-[0x06] = { 0,0, "DIV%S %OAX,%e" },
-[0x07] = { 0,0, "IDIV%S %OAX,%e" },
-};
-
-static Optable optabFE[8] =
-{
-[0x00] = { 0,0, "INCB %e" },
-[0x01] = { 0,0, "DECB %e" },
-};
-
-static Optable optabFF[8] =
-{
-[0x00] = { 0,0, "INC%S %e" },
-[0x01] = { 0,0, "DEC%S %e" },
-[0x02] = { JUMP,0, "CALL* %e" },
-[0x03] = { JUMP,0, "CALLF* %e" },
-[0x04] = { JUMP,0, "JMP* %e" },
-[0x05] = { JUMP,0, "JMPF* %e" },
-[0x06] = { 0,0, "PUSHL %e" },
-};
-
-static Optable optable[256+2] =
-{
-[0x00] = { RMB,0, "ADDB %r,%e" },
-[0x01] = { RM,0, "ADD%S %r,%e" },
-[0x02] = { RMB,0, "ADDB %e,%r" },
-[0x03] = { RM,0, "ADD%S %e,%r" },
-[0x04] = { Ib,0, "ADDB %i,AL" },
-[0x05] = { Iwd,0, "ADD%S %i,%OAX" },
-[0x06] = { 0,0, "PUSHL ES" },
-[0x07] = { 0,0, "POPL ES" },
-[0x08] = { RMB,0, "ORB %r,%e" },
-[0x09] = { RM,0, "OR%S %r,%e" },
-[0x0a] = { RMB,0, "ORB %e,%r" },
-[0x0b] = { RM,0, "OR%S %e,%r" },
-[0x0c] = { Ib,0, "ORB %i,AL" },
-[0x0d] = { Iwd,0, "OR%S %i,%OAX" },
-[0x0e] = { 0,0, "PUSHL CS" },
-[0x0f] = { AUXMM,0, optab0F },
-[0x10] = { RMB,0, "ADCB %r,%e" },
-[0x11] = { RM,0, "ADC%S %r,%e" },
-[0x12] = { RMB,0, "ADCB %e,%r" },
-[0x13] = { RM,0, "ADC%S %e,%r" },
-[0x14] = { Ib,0, "ADCB %i,AL" },
-[0x15] = { Iwd,0, "ADC%S %i,%OAX" },
-[0x16] = { 0,0, "PUSHL SS" },
-[0x17] = { 0,0, "POPL SS" },
-[0x18] = { RMB,0, "SBBB %r,%e" },
-[0x19] = { RM,0, "SBB%S %r,%e" },
-[0x1a] = { RMB,0, "SBBB %e,%r" },
-[0x1b] = { RM,0, "SBB%S %e,%r" },
-[0x1c] = { Ib,0, "SBBB %i,AL" },
-[0x1d] = { Iwd,0, "SBB%S %i,%OAX" },
-[0x1e] = { 0,0, "PUSHL DS" },
-[0x1f] = { 0,0, "POPL DS" },
-[0x20] = { RMB,0, "ANDB %r,%e" },
-[0x21] = { RM,0, "AND%S %r,%e" },
-[0x22] = { RMB,0, "ANDB %e,%r" },
-[0x23] = { RM,0, "AND%S %e,%r" },
-[0x24] = { Ib,0, "ANDB %i,AL" },
-[0x25] = { Iwd,0, "AND%S %i,%OAX" },
-[0x26] = { SEG,0, "ES:" },
-[0x27] = { 0,0, "DAA" },
-[0x28] = { RMB,0, "SUBB %r,%e" },
-[0x29] = { RM,0, "SUB%S %r,%e" },
-[0x2a] = { RMB,0, "SUBB %e,%r" },
-[0x2b] = { RM,0, "SUB%S %e,%r" },
-[0x2c] = { Ib,0, "SUBB %i,AL" },
-[0x2d] = { Iwd,0, "SUB%S %i,%OAX" },
-[0x2e] = { SEG,0, "CS:" },
-[0x2f] = { 0,0, "DAS" },
-[0x30] = { RMB,0, "XORB %r,%e" },
-[0x31] = { RM,0, "XOR%S %r,%e" },
-[0x32] = { RMB,0, "XORB %e,%r" },
-[0x33] = { RM,0, "XOR%S %e,%r" },
-[0x34] = { Ib,0, "XORB %i,AL" },
-[0x35] = { Iwd,0, "XOR%S %i,%OAX" },
-[0x36] = { SEG,0, "SS:" },
-[0x37] = { 0,0, "AAA" },
-[0x38] = { RMB,0, "CMPB %r,%e" },
-[0x39] = { RM,0, "CMP%S %r,%e" },
-[0x3a] = { RMB,0, "CMPB %e,%r" },
-[0x3b] = { RM,0, "CMP%S %e,%r" },
-[0x3c] = { Ib,0, "CMPB %i,AL" },
-[0x3d] = { Iwd,0, "CMP%S %i,%OAX" },
-[0x3e] = { SEG,0, "DS:" },
-[0x3f] = { 0,0, "AAS" },
-[0x40] = { 0,0, "INC%S %OAX" },
-[0x41] = { 0,0, "INC%S %OCX" },
-[0x42] = { 0,0, "INC%S %ODX" },
-[0x43] = { 0,0, "INC%S %OBX" },
-[0x44] = { 0,0, "INC%S %OSP" },
-[0x45] = { 0,0, "INC%S %OBP" },
-[0x46] = { 0,0, "INC%S %OSI" },
-[0x47] = { 0,0, "INC%S %ODI" },
-[0x48] = { 0,0, "DEC%S %OAX" },
-[0x49] = { 0,0, "DEC%S %OCX" },
-[0x4a] = { 0,0, "DEC%S %ODX" },
-[0x4b] = { 0,0, "DEC%S %OBX" },
-[0x4c] = { 0,0, "DEC%S %OSP" },
-[0x4d] = { 0,0, "DEC%S %OBP" },
-[0x4e] = { 0,0, "DEC%S %OSI" },
-[0x4f] = { 0,0, "DEC%S %ODI" },
-[0x50] = { 0,0, "PUSH%S %OAX" },
-[0x51] = { 0,0, "PUSH%S %OCX" },
-[0x52] = { 0,0, "PUSH%S %ODX" },
-[0x53] = { 0,0, "PUSH%S %OBX" },
-[0x54] = { 0,0, "PUSH%S %OSP" },
-[0x55] = { 0,0, "PUSH%S %OBP" },
-[0x56] = { 0,0, "PUSH%S %OSI" },
-[0x57] = { 0,0, "PUSH%S %ODI" },
-[0x58] = { 0,0, "POP%S %OAX" },
-[0x59] = { 0,0, "POP%S %OCX" },
-[0x5a] = { 0,0, "POP%S %ODX" },
-[0x5b] = { 0,0, "POP%S %OBX" },
-[0x5c] = { 0,0, "POP%S %OSP" },
-[0x5d] = { 0,0, "POP%S %OBP" },
-[0x5e] = { 0,0, "POP%S %OSI" },
-[0x5f] = { 0,0, "POP%S %ODI" },
-[0x60] = { 0,0, "PUSHA%S" },
-[0x61] = { 0,0, "POPA%S" },
-[0x62] = { RMM,0, "BOUND %e,%r" },
-[0x63] = { RM,0, "ARPL %r,%e" },
-[0x64] = { SEG,0, "FS:" },
-[0x65] = { SEG,0, "GS:" },
-[0x66] = { OPOVER,0, "" },
-[0x67] = { ADDOVER,0, "" },
-[0x68] = { Iwd,0, "PUSH%S %i" },
-[0x69] = { RM,Iwd, "IMUL%S %e,%i,%r" },
-[0x6a] = { Ib,0, "PUSH%S %i" },
-[0x6b] = { RM,Ibs, "IMUL%S %e,%i,%r" },
-[0x6c] = { 0,0, "INSB DX,(%ODI)" },
-[0x6d] = { 0,0, "INS%S DX,(%ODI)" },
-[0x6e] = { 0,0, "OUTSB (%ASI),DX" },
-[0x6f] = { 0,0, "OUTS%S (%ASI),DX" },
-[0x70] = { Jbs,0, "JOS %p" },
-[0x71] = { Jbs,0, "JOC %p" },
-[0x72] = { Jbs,0, "JCS %p" },
-[0x73] = { Jbs,0, "JCC %p" },
-[0x74] = { Jbs,0, "JEQ %p" },
-[0x75] = { Jbs,0, "JNE %p" },
-[0x76] = { Jbs,0, "JLS %p" },
-[0x77] = { Jbs,0, "JHI %p" },
-[0x78] = { Jbs,0, "JMI %p" },
-[0x79] = { Jbs,0, "JPL %p" },
-[0x7a] = { Jbs,0, "JPS %p" },
-[0x7b] = { Jbs,0, "JPC %p" },
-[0x7c] = { Jbs,0, "JLT %p" },
-[0x7d] = { Jbs,0, "JGE %p" },
-[0x7e] = { Jbs,0, "JLE %p" },
-[0x7f] = { Jbs,0, "JGT %p" },
-[0x80] = { RMOPB,0, optab80 },
-[0x81] = { RMOP,0, optab81 },
-[0x83] = { RMOP,0, optab83 },
-[0x84] = { RMB,0, "TESTB %r,%e" },
-[0x85] = { RM,0, "TEST%S %r,%e" },
-[0x86] = { RMB,0, "XCHGB %r,%e" },
-[0x87] = { RM,0, "XCHG%S %r,%e" },
-[0x88] = { RMB,0, "MOVB %r,%e" },
-[0x89] = { RM,0, "MOV%S %r,%e" },
-[0x8a] = { RMB,0, "MOVB %e,%r" },
-[0x8b] = { RM,0, "MOV%S %e,%r" },
-[0x8c] = { RM,0, "MOVW %g,%e" },
-[0x8d] = { RM,0, "LEA%S %e,%r" },
-[0x8e] = { RM,0, "MOVW %e,%g" },
-[0x8f] = { RM,0, "POP%S %e" },
-[0x90] = { 0,0, "NOP" },
-[0x91] = { 0,0, "XCHG %OCX,%OAX" },
-[0x92] = { 0,0, "XCHG %ODX,%OAX" },
-[0x93] = { 0,0, "XCHG %OBX,%OAX" },
-[0x94] = { 0,0, "XCHG %OSP,%OAX" },
-[0x95] = { 0,0, "XCHG %OBP,%OAX" },
-[0x96] = { 0,0, "XCHG %OSI,%OAX" },
-[0x97] = { 0,0, "XCHG %ODI,%OAX" },
-[0x98] = { 0,0, "%W" }, /* miserable CBW or CWDE */
-[0x99] = { 0,0, "%w" }, /* idiotic CWD or CDQ */
-[0x9a] = { PTR,0, "CALL%S %d" },
-[0x9b] = { 0,0, "WAIT" },
-[0x9c] = { 0,0, "PUSHF" },
-[0x9d] = { 0,0, "POPF" },
-[0x9e] = { 0,0, "SAHF" },
-[0x9f] = { 0,0, "LAHF" },
-[0xa0] = { Awd,0, "MOVB %i,AL" },
-[0xa1] = { Awd,0, "MOV%S %i,%OAX" },
-[0xa2] = { Awd,0, "MOVB AL,%i" },
-[0xa3] = { Awd,0, "MOV%S %OAX,%i" },
-[0xa4] = { 0,0, "MOVSB (%ASI),(%ADI)" },
-[0xa5] = { 0,0, "MOVS%S (%ASI),(%ADI)" },
-[0xa6] = { 0,0, "CMPSB (%ASI),(%ADI)" },
-[0xa7] = { 0,0, "CMPS%S (%ASI),(%ADI)" },
-[0xa8] = { Ib,0, "TESTB %i,AL" },
-[0xa9] = { Iwd,0, "TEST%S %i,%OAX" },
-[0xaa] = { 0,0, "STOSB AL,(%ADI)" },
-[0xab] = { 0,0, "STOS%S %OAX,(%ADI)" },
-[0xac] = { 0,0, "LODSB (%ASI),AL" },
-[0xad] = { 0,0, "LODS%S (%ASI),%OAX" },
-[0xae] = { 0,0, "SCASB (%ADI),AL" },
-[0xaf] = { 0,0, "SCAS%S (%ADI),%OAX" },
-[0xb0] = { Ib,0, "MOVB %i,AL" },
-[0xb1] = { Ib,0, "MOVB %i,CL" },
-[0xb2] = { Ib,0, "MOVB %i,DL" },
-[0xb3] = { Ib,0, "MOVB %i,BL" },
-[0xb4] = { Ib,0, "MOVB %i,AH" },
-[0xb5] = { Ib,0, "MOVB %i,CH" },
-[0xb6] = { Ib,0, "MOVB %i,DH" },
-[0xb7] = { Ib,0, "MOVB %i,BH" },
-[0xb8] = { Iwdq,0, "MOV%S %i,%OAX" },
-[0xb9] = { Iwdq,0, "MOV%S %i,%OCX" },
-[0xba] = { Iwdq,0, "MOV%S %i,%ODX" },
-[0xbb] = { Iwdq,0, "MOV%S %i,%OBX" },
-[0xbc] = { Iwdq,0, "MOV%S %i,%OSP" },
-[0xbd] = { Iwdq,0, "MOV%S %i,%OBP" },
-[0xbe] = { Iwdq,0, "MOV%S %i,%OSI" },
-[0xbf] = { Iwdq,0, "MOV%S %i,%ODI" },
-[0xc0] = { RMOPB,0, optabC0 },
-[0xc1] = { RMOP,0, optabC1 },
-[0xc2] = { Iw,0, "RET %i" },
-[0xc3] = { RET,0, "RET" },
-[0xc4] = { RM,0, "LES %e,%r" },
-[0xc5] = { RM,0, "LDS %e,%r" },
-[0xc6] = { RMB,Ib, "MOVB %i,%e" },
-[0xc7] = { RM,Iwd, "MOV%S %i,%e" },
-[0xc8] = { Iw2,Ib, "ENTER %i,%I" }, /* loony ENTER */
-[0xc9] = { RET,0, "LEAVE" }, /* bizarre LEAVE */
-[0xca] = { Iw,0, "RETF %i" },
-[0xcb] = { RET,0, "RETF" },
-[0xcc] = { 0,0, "INT 3" },
-[0xcd] = { Ib,0, "INTB %i" },
-[0xce] = { 0,0, "INTO" },
-[0xcf] = { 0,0, "IRET" },
-[0xd0] = { RMOPB,0, optabD0 },
-[0xd1] = { RMOP,0, optabD1 },
-[0xd2] = { RMOPB,0, optabD2 },
-[0xd3] = { RMOP,0, optabD3 },
-[0xd4] = { OA,0, "AAM" },
-[0xd5] = { OA,0, "AAD" },
-[0xd7] = { 0,0, "XLAT" },
-[0xd8] = { FRMOP,0, optabD8 },
-[0xd9] = { FRMEX,0, optabD9 },
-[0xda] = { FRMOP,0, optabDA },
-[0xdb] = { FRMEX,0, optabDB },
-[0xdc] = { FRMOP,0, optabDC },
-[0xdd] = { FRMOP,0, optabDD },
-[0xde] = { FRMOP,0, optabDE },
-[0xdf] = { FRMOP,0, optabDF },
-[0xe0] = { Jbs,0, "LOOPNE %p" },
-[0xe1] = { Jbs,0, "LOOPE %p" },
-[0xe2] = { Jbs,0, "LOOP %p" },
-[0xe3] = { Jbs,0, "JCXZ %p" },
-[0xe4] = { Ib,0, "INB %i,AL" },
-[0xe5] = { Ib,0, "IN%S %i,%OAX" },
-[0xe6] = { Ib,0, "OUTB AL,%i" },
-[0xe7] = { Ib,0, "OUT%S %OAX,%i" },
-[0xe8] = { Iwds,0, "CALL %p" },
-[0xe9] = { Iwds,0, "JMP %p" },
-[0xea] = { PTR,0, "JMP %d" },
-[0xeb] = { Jbs,0, "JMP %p" },
-[0xec] = { 0,0, "INB DX,AL" },
-[0xed] = { 0,0, "IN%S DX,%OAX" },
-[0xee] = { 0,0, "OUTB AL,DX" },
-[0xef] = { 0,0, "OUT%S %OAX,DX" },
-[0xf0] = { PRE,0, "LOCK" },
-[0xf2] = { OPRE,0, "REPNE" },
-[0xf3] = { OPRE,0, "REP" },
-[0xf4] = { 0,0, "HLT" },
-[0xf5] = { 0,0, "CMC" },
-[0xf6] = { RMOPB,0, optabF6 },
-[0xf7] = { RMOP,0, optabF7 },
-[0xf8] = { 0,0, "CLC" },
-[0xf9] = { 0,0, "STC" },
-[0xfa] = { 0,0, "CLI" },
-[0xfb] = { 0,0, "STI" },
-[0xfc] = { 0,0, "CLD" },
-[0xfd] = { 0,0, "STD" },
-[0xfe] = { RMOPB,0, optabFE },
-[0xff] = { RMOP,0, optabFF },
-[0x100] = { RM,0, "MOVLQSX %e,%r" },
-[0x101] = { RM,0, "MOVLQZX %e,%r" },
-};
-
-/*
- * get a byte of the instruction
- */
-static int
-igetc(Map *map, Instr *ip, uchar *c)
-{
- if(ip->n+1 > sizeof(ip->mem)){
- werrstr("instruction too long");
- return -1;
- }
- if (get1(map, ip->addr+ip->n, c, 1) < 0) {
- werrstr("can't read instruction: %r");
- return -1;
- }
- ip->mem[ip->n++] = *c;
- return 1;
-}
-
-/*
- * get two bytes of the instruction
- */
-static int
-igets(Map *map, Instr *ip, ushort *sp)
-{
- uchar c;
- ushort s;
-
- if (igetc(map, ip, &c) < 0)
- return -1;
- s = c;
- if (igetc(map, ip, &c) < 0)
- return -1;
- s |= (c<<8);
- *sp = s;
- return 1;
-}
-
-/*
- * get 4 bytes of the instruction
- */
-static int
-igetl(Map *map, Instr *ip, uint32 *lp)
-{
- ushort s;
- int32 l;
-
- if (igets(map, ip, &s) < 0)
- return -1;
- l = s;
- if (igets(map, ip, &s) < 0)
- return -1;
- l |= (s<<16);
- *lp = l;
- return 1;
-}
-
-/*
- * get 8 bytes of the instruction
- *
-static int
-igetq(Map *map, Instr *ip, vlong *qp)
-{
- uint32 l;
- uvlong q;
-
- if (igetl(map, ip, &l) < 0)
- return -1;
- q = l;
- if (igetl(map, ip, &l) < 0)
- return -1;
- q |= ((uvlong)l<<32);
- *qp = q;
- return 1;
-}
- */
-
-static int
-getdisp(Map *map, Instr *ip, int mod, int rm, int code, int pcrel)
-{
- uchar c;
- ushort s;
-
- if (mod > 2)
- return 1;
- if (mod == 1) {
- if (igetc(map, ip, &c) < 0)
- return -1;
- if (c&0x80)
- ip->disp = c|0xffffff00;
- else
- ip->disp = c&0xff;
- } else if (mod == 2 || rm == code) {
- if (ip->asize == 'E') {
- if (igetl(map, ip, &ip->disp) < 0)
- return -1;
- if (mod == 0)
- ip->rip = pcrel;
- } else {
- if (igets(map, ip, &s) < 0)
- return -1;
- if (s&0x8000)
- ip->disp = s|0xffff0000;
- else
- ip->disp = s;
- }
- if (mod == 0)
- ip->base = -1;
- }
- return 1;
-}
-
-static int
-modrm(Map *map, Instr *ip, uchar c)
-{
- uchar rm, mod;
-
- mod = (c>>6)&3;
- rm = c&7;
- ip->mod = mod;
- ip->base = rm;
- ip->reg = (c>>3)&7;
- ip->rip = 0;
- if (mod == 3) /* register */
- return 1;
- if (ip->asize == 0) { /* 16-bit mode */
- switch(rm) {
- case 0:
- ip->base = BX; ip->index = SI;
- break;
- case 1:
- ip->base = BX; ip->index = DI;
- break;
- case 2:
- ip->base = BP; ip->index = SI;
- break;
- case 3:
- ip->base = BP; ip->index = DI;
- break;
- case 4:
- ip->base = SI;
- break;
- case 5:
- ip->base = DI;
- break;
- case 6:
- ip->base = BP;
- break;
- case 7:
- ip->base = BX;
- break;
- default:
- break;
- }
- return getdisp(map, ip, mod, rm, 6, 0);
- }
- if (rm == 4) { /* scummy sib byte */
- if (igetc(map, ip, &c) < 0)
- return -1;
- ip->ss = (c>>6)&0x03;
- ip->index = (c>>3)&0x07;
- if (ip->index == 4)
- ip->index = -1;
- ip->base = c&0x07;
- return getdisp(map, ip, mod, ip->base, 5, 0);
- }
- return getdisp(map, ip, mod, rm, 5, ip->amd64);
-}
-
-static Optable *
-mkinstr(Map *map, Instr *ip, uvlong pc)
-{
- int i, n, norex;
- uchar c;
- ushort s;
- Optable *op, *obase;
- char buf[128];
-
- memset(ip, 0, sizeof(*ip));
- norex = 1;
- ip->base = -1;
- ip->index = -1;
- if(asstype == AI8086)
- ip->osize = 'W';
- else {
- ip->osize = 'L';
- ip->asize = 'E';
- ip->amd64 = asstype != AI386;
- norex = 0;
- }
- ip->addr = pc;
- if (igetc(map, ip, &c) < 0)
- return 0;
- obase = optable;
-newop:
- if(ip->amd64 && !norex){
- if(c >= 0x40 && c <= 0x4f) {
- ip->rex = c;
- if(igetc(map, ip, &c) < 0)
- return 0;
- }
- if(c == 0x63){
- if(ip->rex&REXW)
- op = &obase[0x100]; /* MOVLQSX */
- else
- op = &obase[0x101]; /* MOVLQZX */
- goto hack;
- }
- }
- op = &obase[c];
-hack:
- if (op->proto == 0) {
-badop:
- n = snprint(buf, sizeof(buf), "opcode: ??");
- for (i = 0; i < ip->n && n < sizeof(buf)-3; i++, n+=2)
- _hexify(buf+n, ip->mem[i], 1);
- strcpy(buf+n, "??");
- werrstr(buf);
- return 0;
- }
- for(i = 0; i < 2 && op->operand[i]; i++) {
- switch(op->operand[i]) {
- case Ib: /* 8-bit immediate - (no sign extension)*/
- if (igetc(map, ip, &c) < 0)
- return 0;
- ip->imm = c&0xff;
- ip->imm64 = ip->imm;
- break;
- case Jbs: /* 8-bit jump immediate (sign extended) */
- if (igetc(map, ip, &c) < 0)
- return 0;
- if (c&0x80)
- ip->imm = c|0xffffff00;
- else
- ip->imm = c&0xff;
- ip->imm64 = (int32)ip->imm;
- ip->jumptype = Jbs;
- break;
- case Ibs: /* 8-bit immediate (sign extended) */
- if (igetc(map, ip, &c) < 0)
- return 0;
- if (c&0x80)
- if (ip->osize == 'L')
- ip->imm = c|0xffffff00;
- else
- ip->imm = c|0xff00;
- else
- ip->imm = c&0xff;
- ip->imm64 = (int32)ip->imm;
- break;
- case Iw: /* 16-bit immediate -> imm */
- if (igets(map, ip, &s) < 0)
- return 0;
- ip->imm = s&0xffff;
- ip->imm64 = ip->imm;
- ip->jumptype = Iw;
- break;
- case Iw2: /* 16-bit immediate -> in imm2*/
- if (igets(map, ip, &s) < 0)
- return 0;
- ip->imm2 = s&0xffff;
- break;
- case Iwd: /* Operand-sized immediate (no sign extension unless 64 bits)*/
- if (ip->osize == 'L') {
- if (igetl(map, ip, &ip->imm) < 0)
- return 0;
- ip->imm64 = ip->imm;
- if(ip->rex&REXW && (ip->imm & (1<<31)) != 0)
- ip->imm64 |= (vlong)~0 << 32;
- } else {
- if (igets(map, ip, &s)< 0)
- return 0;
- ip->imm = s&0xffff;
- ip->imm64 = ip->imm;
- }
- break;
- case Iwdq: /* Operand-sized immediate, possibly big */
- if (ip->osize == 'L') {
- if (igetl(map, ip, &ip->imm) < 0)
- return 0;
- ip->imm64 = ip->imm;
- if (ip->rex & REXW) {
- uint32 l;
- if (igetl(map, ip, &l) < 0)
- return 0;
- ip->imm64 |= (uvlong)l << 32;
- }
- } else {
- if (igets(map, ip, &s)< 0)
- return 0;
- ip->imm = s&0xffff;
- }
- break;
- case Awd: /* Address-sized immediate (no sign extension)*/
- if (ip->asize == 'E') {
- if (igetl(map, ip, &ip->imm) < 0)
- return 0;
- /* TO DO: REX */
- } else {
- if (igets(map, ip, &s)< 0)
- return 0;
- ip->imm = s&0xffff;
- }
- break;
- case Iwds: /* Operand-sized immediate (sign extended) */
- if (ip->osize == 'L') {
- if (igetl(map, ip, &ip->imm) < 0)
- return 0;
- } else {
- if (igets(map, ip, &s)< 0)
- return 0;
- if (s&0x8000)
- ip->imm = s|0xffff0000;
- else
- ip->imm = s&0xffff;
- }
- ip->jumptype = Iwds;
- break;
- case OA: /* literal 0x0a byte */
- if (igetc(map, ip, &c) < 0)
- return 0;
- if (c != 0x0a)
- goto badop;
- break;
- case Op_R0: /* base register must be R0 */
- if (ip->base != 0)
- goto badop;
- break;
- case Op_R1: /* base register must be R1 */
- if (ip->base != 1)
- goto badop;
- break;
- case RMB: /* R/M field with byte register (/r)*/
- if (igetc(map, ip, &c) < 0)
- return 0;
- if (modrm(map, ip, c) < 0)
- return 0;
- ip->osize = 'B';
- break;
- case RM: /* R/M field with register (/r) */
- if (igetc(map, ip, &c) < 0)
- return 0;
- if (modrm(map, ip, c) < 0)
- return 0;
- break;
- case RMOPB: /* R/M field with op code (/digit) */
- if (igetc(map, ip, &c) < 0)
- return 0;
- if (modrm(map, ip, c) < 0)
- return 0;
- c = ip->reg; /* secondary op code */
- obase = (Optable*)op->proto;
- ip->osize = 'B';
- goto newop;
- case RMOP: /* R/M field with op code (/digit) */
- if (igetc(map, ip, &c) < 0)
- return 0;
- if (modrm(map, ip, c) < 0)
- return 0;
- obase = (Optable*)op->proto;
- if(ip->amd64 && obase == optab0F01 && c == 0xF8)
- return optab0F01F8;
- c = ip->reg;
- goto newop;
- case FRMOP: /* FP R/M field with op code (/digit) */
- if (igetc(map, ip, &c) < 0)
- return 0;
- if (modrm(map, ip, c) < 0)
- return 0;
- if ((c&0xc0) == 0xc0)
- c = ip->reg+8; /* 16 entry table */
- else
- c = ip->reg;
- obase = (Optable*)op->proto;
- goto newop;
- case FRMEX: /* Extended FP R/M field with op code (/digit) */
- if (igetc(map, ip, &c) < 0)
- return 0;
- if (modrm(map, ip, c) < 0)
- return 0;
- if ((c&0xc0) == 0xc0)
- c = (c&0x3f)+8; /* 64-entry table */
- else
- c = ip->reg;
- obase = (Optable*)op->proto;
- goto newop;
- case RMR: /* R/M register only (mod = 11) */
- if (igetc(map, ip, &c) < 0)
- return 0;
- if ((c&0xc0) != 0xc0) {
- werrstr("invalid R/M register: %x", c);
- return 0;
- }
- if (modrm(map, ip, c) < 0)
- return 0;
- break;
- case RMM: /* R/M register only (mod = 11) */
- if (igetc(map, ip, &c) < 0)
- return 0;
- if ((c&0xc0) == 0xc0) {
- werrstr("invalid R/M memory mode: %x", c);
- return 0;
- }
- if (modrm(map, ip, c) < 0)
- return 0;
- break;
- case PTR: /* Seg:Displacement addr (ptr16:16 or ptr16:32) */
- if (ip->osize == 'L') {
- if (igetl(map, ip, &ip->disp) < 0)
- return 0;
- } else {
- if (igets(map, ip, &s)< 0)
- return 0;
- ip->disp = s&0xffff;
- }
- if (igets(map, ip, (ushort*)&ip->seg) < 0)
- return 0;
- ip->jumptype = PTR;
- break;
- case AUXMM: /* Multi-byte op code; prefix determines table selection */
- if (igetc(map, ip, &c) < 0)
- return 0;
- obase = (Optable*)op->proto;
- switch (ip->opre) {
- case 0x66:
- op = optab660F;
- break;
- case 0xF2:
- op = optabF20F;
- ip->prefix = 0; /* discard REPNE */
- break;
- case 0xF3:
- op = optabF30F;
- ip->prefix = 0; /* discard REP */
- break;
- default:
- op = nil;
- break;
- }
- if(op != nil && op[c].proto != nil)
- obase = op;
- /* otherwise the optab entry captures it */
- goto newop;
- case AUX: /* Multi-byte op code - Auxiliary table */
- obase = (Optable*)op->proto;
- if (igetc(map, ip, &c) < 0)
- return 0;
- goto newop;
- case OPRE: /* Instr Prefix or media op */
- ip->opre = c;
- /* fall through */
- case PRE: /* Instr Prefix */
- ip->prefix = (char*)op->proto;
- if (igetc(map, ip, &c) < 0)
- return 0;
- goto newop;
- case SEG: /* Segment Prefix */
- ip->segment = (char*)op->proto;
- if (igetc(map, ip, &c) < 0)
- return 0;
- goto newop;
- case OPOVER: /* Operand size override */
- ip->opre = c;
- ip->osize = 'W';
- if (igetc(map, ip, &c) < 0)
- return 0;
- if (c == 0x0F)
- ip->osize = 'L';
- else if (ip->amd64 && (c&0xF0) == 0x40)
- ip->osize = 'Q';
- goto newop;
- case ADDOVER: /* Address size override */
- ip->asize = 0;
- if (igetc(map, ip, &c) < 0)
- return 0;
- goto newop;
- case JUMP: /* mark instruction as JUMP or RET */
- case RET:
- ip->jumptype = op->operand[i];
- break;
- default:
- werrstr("bad operand type %d", op->operand[i]);
- return 0;
- }
- }
- return op;
-}
-
-#pragma varargck argpos bprint 2
-
-static void
-bprint(Instr *ip, char *fmt, ...)
-{
- va_list arg;
-
- va_start(arg, fmt);
- ip->curr = vseprint(ip->curr, ip->end, fmt, arg);
- va_end(arg);
-}
-
-/*
- * if we want to call 16 bit regs AX,BX,CX,...
- * and 32 bit regs EAX,EBX,ECX,... then
- * change the defs of ANAME and ONAME to:
- * #define ANAME(ip) ((ip->asize == 'E' ? "E" : "")
- * #define ONAME(ip) ((ip)->osize == 'L' ? "E" : "")
- */
-#define ANAME(ip) ""
-#define ONAME(ip) ""
-
-static char *reg[] = {
-[AX] = "AX",
-[CX] = "CX",
-[DX] = "DX",
-[BX] = "BX",
-[SP] = "SP",
-[BP] = "BP",
-[SI] = "SI",
-[DI] = "DI",
-
- /* amd64 */
-[AMD64_R8] = "R8",
-[AMD64_R9] = "R9",
-[AMD64_R10] = "R10",
-[AMD64_R11] = "R11",
-[AMD64_R12] = "R12",
-[AMD64_R13] = "R13",
-[AMD64_R14] = "R14",
-[AMD64_R15] = "R15",
-};
-
-static char *breg[] = { "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH" };
-static char *breg64[] = { "AL", "CL", "DL", "BL", "SPB", "BPB", "SIB", "DIB",
- "R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B" };
-static char *sreg[] = { "ES", "CS", "SS", "DS", "FS", "GS" };
-
-static void
-plocal(Instr *ip)
-{
- int ret;
- int32 offset;
- Symbol s;
- char *reg;
-
- offset = ip->disp;
- if (!findsym(ip->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s)) {
- bprint(ip, "%ux(SP)", offset);
- return;
- }
-
- if (s.value > ip->disp) {
- ret = getauto(&s, s.value-ip->disp-mach->szaddr, CAUTO, &s);
- reg = "(SP)";
- } else {
- offset -= s.value;
- ret = getauto(&s, offset, CPARAM, &s);
- reg = "(FP)";
- }
- if (ret)
- bprint(ip, "%s+", s.name);
- else
- offset = ip->disp;
- bprint(ip, "%ux%s", offset, reg);
-}
-
-static int
-isjmp(Instr *ip)
-{
- switch(ip->jumptype){
- case Iwds:
- case Jbs:
- case JUMP:
- return 1;
- default:
- return 0;
- }
-}
-
-/*
- * This is too smart for its own good, but it really is nice
- * to have accurate translations when debugging, and it
- * helps us identify which code is different in binaries that
- * are changed on sources.
- */
-static int
-issymref(Instr *ip, Symbol *s, int32 w, int32 val)
-{
- Symbol next, tmp;
- int32 isstring, size;
-
- if (isjmp(ip))
- return 1;
- if (s->class==CTEXT && w==0)
- return 1;
- if (s->class==CDATA) {
- /* use first bss symbol (or "end") rather than edata */
- if (s->name[0]=='e' && strcmp(s->name, "edata") == 0){
- if((s ->index >= 0 && globalsym(&tmp, s->index+1) && tmp.value==s->value)
- || (s->index > 0 && globalsym(&tmp, s->index-1) && tmp.value==s->value))
- *s = tmp;
- }
- if (w == 0)
- return 1;
- for (next=*s; next.value==s->value; next=tmp)
- if (!globalsym(&tmp, next.index+1))
- break;
- size = next.value - s->value;
- if (w >= size)
- return 0;
- if (w > size-w)
- w = size-w;
- /* huge distances are usually wrong except in .string */
- isstring = (s->name[0]=='.' && strcmp(s->name, ".string") == 0);
- if (w > 8192 && !isstring)
- return 0;
- /* medium distances are tricky - look for constants */
- /* near powers of two */
- if ((val&(val-1)) == 0 || (val&(val+1)) == 0)
- return 0;
- return 1;
- }
- return 0;
-}
-
-static void
-immediate(Instr *ip, vlong val)
-{
- Symbol s;
- int32 w;
-
- if (findsym(val, CANY, &s)) { /* TO DO */
- w = val - s.value;
- if (w < 0)
- w = -w;
- if (issymref(ip, &s, w, val)) {
- if (w)
- bprint(ip, "%s+%#ux(SB)", s.name, w);
- else
- bprint(ip, "%s(SB)", s.name);
- return;
- }
-/*
- if (s.class==CDATA && globalsym(&s, s.index+1)) {
- w = s.value - val;
- if (w < 0)
- w = -w;
- if (w < 4096) {
- bprint(ip, "%s-%#lux(SB)", s.name, w);
- return;
- }
- }
-*/
- }
- if((ip->rex & REXW) == 0)
- bprint(ip, "%lux", (long)val);
- else
- bprint(ip, "%llux", val);
-}
-
-static void
-pea(Instr *ip)
-{
- int base;
-
- base = ip->base;
- if(base >= 0 && (ip->rex & REXB))
- base += 8;
-
- if (ip->mod == 3) {
- if (ip->osize == 'B')
- bprint(ip, (ip->rex & REXB? breg64: breg)[(uchar)ip->base]);
- else
- bprint(ip, "%s%s", ANAME(ip), reg[base]);
- return;
- }
-
- if (ip->segment)
- bprint(ip, ip->segment);
- if (ip->asize == 'E' && base == SP)
- plocal(ip);
- else {
- if (ip->base < 0)
- immediate(ip, ip->disp);
- else {
- bprint(ip, "%ux", ip->disp);
- if(ip->rip)
- bprint(ip, "(RIP)");
- bprint(ip,"(%s%s)", ANAME(ip), reg[ip->rex&REXB? ip->base+8: ip->base]);
- }
- }
- if (ip->index >= 0)
- bprint(ip,"(%s%s*%d)", ANAME(ip), reg[ip->rex&REXX? ip->index+8: ip->index], 1<<ip->ss);
-}
-
-static void
-prinstr(Instr *ip, char *fmt)
-{
- int sharp;
- vlong v;
-
- if (ip->prefix)
- bprint(ip, "%s ", ip->prefix);
- for (; *fmt && ip->curr < ip->end; fmt++) {
- if (*fmt != '%'){
- *ip->curr++ = *fmt;
- continue;
- }
- sharp = 0;
- if(*++fmt == '#') {
- sharp = 1;
- ++fmt;
- }
- switch(*fmt){
- case '%':
- *ip->curr++ = '%';
- break;
- case 'A':
- bprint(ip, "%s", ANAME(ip));
- break;
- case 'C':
- bprint(ip, "CR%d", ip->reg);
- break;
- case 'D':
- if (ip->reg < 4 || ip->reg == 6 || ip->reg == 7)
- bprint(ip, "DR%d",ip->reg);
- else
- bprint(ip, "???");
- break;
- case 'I':
- bprint(ip, "$");
- immediate(ip, ip->imm2);
- break;
- case 'O':
- bprint(ip,"%s", ONAME(ip));
- break;
- case 'i':
- if(!sharp)
- bprint(ip, "$");
- v = ip->imm;
- if(ip->rex & REXW)
- v = ip->imm64;
- immediate(ip, v);
- break;
- case 'R':
- bprint(ip, "%s%s", ONAME(ip), reg[ip->rex&REXR? ip->reg+8: ip->reg]);
- break;
- case 'S':
- if(ip->osize == 'Q' || ip->osize == 'L' && ip->rex & REXW)
- bprint(ip, "Q");
- else
- bprint(ip, "%c", ip->osize);
- break;
- case 's':
- if(ip->opre == 0 || ip->opre == 0x66)
- bprint(ip, "P");
- else
- bprint(ip, "S");
- if(ip->opre == 0xf2 || ip->opre == 0x66)
- bprint(ip, "D");
- else
- bprint(ip, "S");
- break;
- case 'T':
- if (ip->reg == 6 || ip->reg == 7)
- bprint(ip, "TR%d",ip->reg);
- else
- bprint(ip, "???");
- break;
- case 'W':
- if (ip->osize == 'Q' || ip->osize == 'L' && ip->rex & REXW)
- bprint(ip, "CDQE");
- else if (ip->osize == 'L')
- bprint(ip,"CWDE");
- else
- bprint(ip, "CBW");
- break;
- case 'd':
- bprint(ip,"%ux:%ux", ip->seg, ip->disp);
- break;
- case 'm':
- if (ip->mod == 3 && ip->osize != 'B') {
- if(fmt[1] != '*'){
- if(ip->opre != 0) {
- bprint(ip, "X%d", ip->rex&REXB? ip->base+8: ip->base);
- break;
- }
- } else
- fmt++;
- bprint(ip, "M%d", ip->base);
- break;
- }
- pea(ip);
- break;
- case 'e':
- pea(ip);
- break;
- case 'f':
- bprint(ip, "F%d", ip->base);
- break;
- case 'g':
- if (ip->reg < 6)
- bprint(ip,"%s",sreg[ip->reg]);
- else
- bprint(ip,"???");
- break;
- case 'p':
- /*
- * signed immediate in the uint32 ip->imm.
- */
- v = (int32)ip->imm;
- immediate(ip, v+ip->addr+ip->n);
- break;
- case 'r':
- if (ip->osize == 'B')
- bprint(ip,"%s", (ip->rex? breg64: breg)[ip->rex&REXR? ip->reg+8: ip->reg]);
- else
- bprint(ip, reg[ip->rex&REXR? ip->reg+8: ip->reg]);
- break;
- case 'w':
- if (ip->osize == 'Q' || ip->rex & REXW)
- bprint(ip, "CQO");
- else if (ip->osize == 'L')
- bprint(ip,"CDQ");
- else
- bprint(ip, "CWD");
- break;
- case 'M':
- if(ip->opre != 0)
- bprint(ip, "X%d", ip->rex&REXR? ip->reg+8: ip->reg);
- else
- bprint(ip, "M%d", ip->reg);
- break;
- case 'x':
- if (ip->mod == 3 && ip->osize != 'B') {
- bprint(ip, "X%d", ip->rex&REXB? ip->base+8: ip->base);
- break;
- }
- pea(ip);
- break;
- case 'X':
- bprint(ip, "X%d", ip->rex&REXR? ip->reg+8: ip->reg);
- break;
- default:
- bprint(ip, "%%%c", *fmt);
- break;
- }
- }
- *ip->curr = 0; /* there's always room for 1 byte */
-}
-
-static int
-i386inst(Map *map, uvlong pc, char modifier, char *buf, int n)
-{
- Instr instr;
- Optable *op;
-
- USED(modifier);
- op = mkinstr(map, &instr, pc);
- if (op == 0) {
- errstr(buf, n);
- return -1;
- }
- instr.curr = buf;
- instr.end = buf+n-1;
- prinstr(&instr, op->proto);
- return instr.n;
-}
-
-static int
-i386das(Map *map, uvlong pc, char *buf, int n)
-{
- Instr instr;
- int i;
-
- if (mkinstr(map, &instr, pc) == 0) {
- errstr(buf, n);
- return -1;
- }
- for(i = 0; i < instr.n && n > 2; i++) {
- _hexify(buf, instr.mem[i], 1);
- buf += 2;
- n -= 2;
- }
- *buf = 0;
- return instr.n;
-}
-
-static int
-i386instlen(Map *map, uvlong pc)
-{
- Instr i;
-
- if (mkinstr(map, &i, pc))
- return i.n;
- return -1;
-}
-
-static int
-i386foll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
-{
- Instr i;
- Optable *op;
- ushort s;
- uvlong l, addr;
- vlong v;
- int n;
-
- op = mkinstr(map, &i, pc);
- if (!op)
- return -1;
-
- n = 0;
-
- switch(i.jumptype) {
- case RET: /* RETURN or LEAVE */
- case Iw: /* RETURN */
- if (strcmp(op->proto, "LEAVE") == 0) {
- if (geta(map, (*rget)(map, "BP"), &l) < 0)
- return -1;
- } else if (geta(map, (*rget)(map, mach->sp), &l) < 0)
- return -1;
- foll[0] = l;
- return 1;
- case Iwds: /* pc relative JUMP or CALL*/
- case Jbs: /* pc relative JUMP or CALL */
- v = (int32)i.imm;
- foll[0] = pc+v+i.n;
- n = 1;
- break;
- case PTR: /* seg:displacement JUMP or CALL */
- foll[0] = (i.seg<<4)+i.disp;
- return 1;
- case JUMP: /* JUMP or CALL EA */
-
- if(i.mod == 3) {
- foll[0] = (*rget)(map, reg[i.rex&REXB? i.base+8: i.base]);
- return 1;
- }
- /* calculate the effective address */
- addr = i.disp;
- if (i.base >= 0) {
- if (geta(map, (*rget)(map, reg[i.rex&REXB? i.base+8: i.base]), &l) < 0)
- return -1;
- addr += l;
- }
- if (i.index >= 0) {
- if (geta(map, (*rget)(map, reg[i.rex&REXX? i.index+8: i.index]), &l) < 0)
- return -1;
- addr += l*(1<<i.ss);
- }
- /* now retrieve a seg:disp value at that address */
- if (get2(map, addr, &s) < 0) /* seg */
- return -1;
- foll[0] = s<<4;
- addr += 2;
- if (i.asize == 'L') {
- if (geta(map, addr, &l) < 0) /* disp32 */
- return -1;
- foll[0] += l;
- } else { /* disp16 */
- if (get2(map, addr, &s) < 0)
- return -1;
- foll[0] += s;
- }
- return 1;
- default:
- break;
- }
- if (strncmp(op->proto,"JMP", 3) == 0 || strncmp(op->proto,"CALL", 4) == 0)
- return 1;
- foll[n++] = pc+i.n;
- return n;
-}
diff --git a/src/libmach/8obj.c b/src/libmach/8obj.c
deleted file mode 100644
index c44d92c55..000000000
--- a/src/libmach/8obj.c
+++ /dev/null
@@ -1,170 +0,0 @@
-// Inferno libmach/8obj.c
-// http://code.google.com/p/inferno-os/source/browse/utils/libmach/8obj.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc.
-// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
-// Portions Copyright © 1997-1999 Vita Nuova Limited.
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-/*
- * 8obj.c - identify and parse a 386 object file
- */
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-#include "../cmd/8l/8.out.h"
-#include "obj.h"
-
-typedef struct Addr Addr;
-struct Addr
-{
- char sym;
- char flags;
- char gotype;
-};
-static Addr addr(Biobuf*);
-static char type2char(int);
-static void skip(Biobuf*, int);
-
-int
-_is8(char *t)
-{
- uchar *s = (uchar*)t;
-
- return s[0] == (ANAME&0xff) /* also = ANAME */
- && s[1] == ((ANAME>>8)&0xff)
- && s[2] == D_FILE /* type */
- && s[3] == 1 /* sym */
- && s[4] == '<'; /* name of file */
-}
-
-int
-_read8(Biobuf *bp, Prog* p)
-{
- int as, n, c;
- Addr a;
-
- as = BGETC(bp); /* as(low) */
- if(as < 0)
- return 0;
- c = BGETC(bp); /* as(high) */
- if(c < 0)
- return 0;
- as |= ((c & 0xff) << 8);
- p->kind = aNone;
- p->sig = 0;
- if(as == ANAME || as == ASIGNAME){
- if(as == ASIGNAME){
- Bread(bp, &p->sig, 4);
- p->sig = leswal(p->sig);
- }
- p->kind = aName;
- p->type = type2char(BGETC(bp)); /* type */
- p->sym = BGETC(bp); /* sym */
- n = 0;
- for(;;) {
- as = BGETC(bp);
- if(as < 0)
- return 0;
- n++;
- if(as == 0)
- break;
- }
- p->id = malloc(n);
- if(p->id == 0)
- return 0;
- Bseek(bp, -n, 1);
- if(Bread(bp, p->id, n) != n)
- return 0;
- return 1;
- }
- if(as == ATEXT)
- p->kind = aText;
- if(as == AGLOBL)
- p->kind = aData;
- skip(bp, 4); /* lineno(4) */
- a = addr(bp);
- addr(bp);
- if(!(a.flags & T_SYM))
- p->kind = aNone;
- p->sym = a.sym;
- return 1;
-}
-
-static Addr
-addr(Biobuf *bp)
-{
- Addr a;
- int t;
- long off;
-
- off = 0;
- a.gotype = 0;
- a.sym = -1;
- a.flags = BGETC(bp); /* flags */
- if(a.flags & T_INDEX)
- skip(bp, 2);
- if(a.flags & T_OFFSET){
- off = BGETLE4(bp);
- if(off < 0)
- off = -off;
- }
- if(a.flags & T_OFFSET2){
- Bgetle4(bp);
- }
- if(a.flags & T_SYM)
- a.sym = BGETC(bp);
- if(a.flags & T_FCONST)
- skip(bp, 8);
- else
- if(a.flags & T_SCONST)
- skip(bp, NSNAME);
- if(a.flags & T_TYPE) {
- t = BGETC(bp);
- if(a.sym > 0 && (t==D_PARAM || t==D_AUTO))
- _offset(a.sym, off);
- }
- if(a.flags & T_GOTYPE)
- a.gotype = BGETC(bp);
- return a;
-}
-
-static char
-type2char(int t)
-{
- switch(t){
- case D_EXTERN: return 'U';
- case D_STATIC: return 'b';
- case D_AUTO: return 'a';
- case D_PARAM: return 'p';
- default: return UNKNOWN;
- }
-}
-
-static void
-skip(Biobuf *bp, int n)
-{
- while (n-- > 0)
- Bgetc(bp);
-}
diff --git a/src/libmach/Makefile b/src/libmach/Makefile
deleted file mode 100644
index 62aba5dca..000000000
--- a/src/libmach/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2012 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../Make.dist
diff --git a/src/libmach/access.c b/src/libmach/access.c
deleted file mode 100644
index 0ee75d148..000000000
--- a/src/libmach/access.c
+++ /dev/null
@@ -1,241 +0,0 @@
-// Inferno libmach/access.c
-// http://code.google.com/p/inferno-os/source/browse/utils/libmach/access.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc.
-// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
-// Portions Copyright © 1997-1999 Vita Nuova Limited.
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-/*
- * functions to read and write an executable or file image
- */
-
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-
-static int mget(Map*, uvlong, void*, int);
-static int mput(Map*, uvlong, void*, int);
-static Seg* reloc(Map*, uvlong, vlong*);
-
-/*
- * routines to get/put various types
- */
-int
-geta(Map *map, uvlong addr, uvlong *x)
-{
- uint32 l;
- uvlong vl;
-
- if (mach->szaddr == 8){
- if (get8(map, addr, &vl) < 0)
- return -1;
- *x = vl;
- return 1;
- }
-
- if (get4(map, addr, &l) < 0)
- return -1;
- *x = l;
-
- return 1;
-}
-
-int
-get8(Map *map, uvlong addr, uvlong *x)
-{
- if (!map) {
- werrstr("get8: invalid map");
- return -1;
- }
-
- if (map->nsegs == 1 && map->seg[0].fd < 0) {
- *x = addr;
- return 1;
- }
- if (mget(map, addr, x, 8) < 0)
- return -1;
- *x = machdata->swav(*x);
- return 1;
-}
-
-int
-get4(Map *map, uvlong addr, uint32 *x)
-{
- if (!map) {
- werrstr("get4: invalid map");
- return -1;
- }
-
- if (map->nsegs == 1 && map->seg[0].fd < 0) {
- *x = addr;
- return 1;
- }
- if (mget(map, addr, x, 4) < 0)
- return -1;
- *x = machdata->swal(*x);
- return 1;
-}
-
-int
-get2(Map *map, uvlong addr, ushort *x)
-{
- if (!map) {
- werrstr("get2: invalid map");
- return -1;
- }
-
- if (map->nsegs == 1 && map->seg[0].fd < 0) {
- *x = addr;
- return 1;
- }
- if (mget(map, addr, x, 2) < 0)
- return -1;
- *x = machdata->swab(*x);
- return 1;
-}
-
-int
-get1(Map *map, uvlong addr, uchar *x, int size)
-{
- uchar *cp;
-
- if (!map) {
- werrstr("get1: invalid map");
- return -1;
- }
-
- if (map->nsegs == 1 && map->seg[0].fd < 0) {
- cp = (uchar*)&addr;
- while (cp < (uchar*)(&addr+1) && size-- > 0)
- *x++ = *cp++;
- while (size-- > 0)
- *x++ = 0;
- } else
- return mget(map, addr, x, size);
- return 1;
-}
-
-int
-puta(Map *map, uvlong addr, uvlong v)
-{
- if (mach->szaddr == 8)
- return put8(map, addr, v);
-
- return put4(map, addr, v);
-}
-
-int
-put8(Map *map, uvlong addr, uvlong v)
-{
- if (!map) {
- werrstr("put8: invalid map");
- return -1;
- }
- v = machdata->swav(v);
- return mput(map, addr, &v, 8);
-}
-
-int
-put4(Map *map, uvlong addr, uint32 v)
-{
- if (!map) {
- werrstr("put4: invalid map");
- return -1;
- }
- v = machdata->swal(v);
- return mput(map, addr, &v, 4);
-}
-
-int
-put2(Map *map, uvlong addr, ushort v)
-{
- if (!map) {
- werrstr("put2: invalid map");
- return -1;
- }
- v = machdata->swab(v);
- return mput(map, addr, &v, 2);
-}
-
-int
-put1(Map *map, uvlong addr, uchar *v, int size)
-{
- if (!map) {
- werrstr("put1: invalid map");
- return -1;
- }
- return mput(map, addr, v, size);
-}
-
-static int
-mget(Map *map, uvlong addr, void *buf, int size)
-{
- uvlong off;
- Seg *s;
-
- s = reloc(map, addr, (vlong*)&off);
- if (!s)
- return -1;
- if (s->rw == nil) {
- werrstr("unreadable map");
- return -1;
- }
- return s->rw(map, s, off, buf, size, 1);
-}
-
-static int
-mput(Map *map, uvlong addr, void *buf, int size)
-{
- vlong off;
- Seg *s;
-
- s = reloc(map, addr, &off);
- if (!s)
- return -1;
- if (s->rw == nil) {
- werrstr("unwritable map");
- return -1;
- }
- return s->rw(map, s, off, buf, size, 0);
-}
-
-/*
- * convert address to file offset; returns nonzero if ok
- */
-static Seg*
-reloc(Map *map, uvlong addr, vlong *offp)
-{
- int i;
-
- for (i = 0; i < map->nsegs; i++) {
- if (map->seg[i].inuse)
- if (map->seg[i].b <= addr && addr < map->seg[i].e) {
- *offp = addr + map->seg[i].f - map->seg[i].b;
- return &map->seg[i];
- }
- }
- werrstr("can't translate address %llux", addr);
- return 0;
-}
diff --git a/src/libmach/darwin.c b/src/libmach/darwin.c
deleted file mode 100644
index 807dfa0d8..000000000
--- a/src/libmach/darwin.c
+++ /dev/null
@@ -1,897 +0,0 @@
-// Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#define __DARWIN_UNIX03 0
-
-#include <u.h>
-#include <sys/ptrace.h>
-#include <sys/signal.h>
-#include <mach/mach.h>
-#include <mach/mach_traps.h>
-#include <errno.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-#define Ureg Ureg32
-#include <ureg_x86.h>
-#undef Ureg
-#define Ureg Ureg64
-#include <ureg_amd64.h>
-#undef Ureg
-#undef waitpid /* want Unix waitpid, not Plan 9 */
-
-typedef struct Ureg32 Ureg32;
-typedef struct Ureg64 Ureg64;
-
-extern mach_port_t mach_reply_port(void); // should be in system headers, is not
-
-// Mach-error wrapper.
-// Takes a mach return code and converts it into 0 / -1,
-// setting errstr when it returns -1.
-
-static struct {
- int code;
- char *name;
-} macherr[] = {
- KERN_INVALID_ADDRESS, "invalid address",
- KERN_PROTECTION_FAILURE, "protection failure",
- KERN_NO_SPACE, "no space",
- KERN_INVALID_ARGUMENT, "invalid argument",
- KERN_FAILURE, "failure",
- KERN_RESOURCE_SHORTAGE, "resource shortage",
- KERN_NOT_RECEIVER, "not receiver",
- KERN_NO_ACCESS, "no access",
- KERN_MEMORY_FAILURE, "memory failure",
- KERN_MEMORY_ERROR, "memory error",
- KERN_ALREADY_IN_SET, "already in set",
- KERN_NOT_IN_SET, "not in set",
- KERN_NAME_EXISTS, "name exists",
- KERN_ABORTED, "aborted",
- KERN_INVALID_NAME, "invalid name",
- KERN_INVALID_TASK, "invalid task",
- KERN_INVALID_RIGHT, "invalid right",
- KERN_INVALID_VALUE, "invalid value",
- KERN_UREFS_OVERFLOW, "urefs overflow",
- KERN_INVALID_CAPABILITY, "invalid capability",
- KERN_RIGHT_EXISTS, "right exists",
- KERN_INVALID_HOST, "invalid host",
- KERN_MEMORY_PRESENT, "memory present",
- KERN_MEMORY_DATA_MOVED, "memory data moved",
- KERN_MEMORY_RESTART_COPY, "memory restart copy",
- KERN_INVALID_PROCESSOR_SET, "invalid processor set",
- KERN_POLICY_LIMIT, "policy limit",
- KERN_INVALID_POLICY, "invalid policy",
- KERN_INVALID_OBJECT, "invalid object",
- KERN_ALREADY_WAITING, "already waiting",
- KERN_DEFAULT_SET, "default set",
- KERN_EXCEPTION_PROTECTED, "exception protected",
- KERN_INVALID_LEDGER, "invalid ledger",
- KERN_INVALID_MEMORY_CONTROL, "invalid memory control",
- KERN_INVALID_SECURITY, "invalid security",
- KERN_NOT_DEPRESSED, "not depressed",
- KERN_TERMINATED, "terminated",
- KERN_LOCK_SET_DESTROYED, "lock set destroyed",
- KERN_LOCK_UNSTABLE, "lock unstable",
- KERN_LOCK_OWNED, "lock owned",
- KERN_LOCK_OWNED_SELF, "lock owned self",
- KERN_SEMAPHORE_DESTROYED, "semaphore destroyed",
- KERN_RPC_SERVER_TERMINATED, "rpc server terminated",
- KERN_RPC_TERMINATE_ORPHAN, "rpc terminate orphan",
- KERN_RPC_CONTINUE_ORPHAN, "rpc continue orphan",
- KERN_NOT_SUPPORTED, "not supported",
- KERN_NODE_DOWN, "node down",
- KERN_NOT_WAITING, "not waiting",
- KERN_OPERATION_TIMED_OUT, "operation timed out",
- KERN_RETURN_MAX, "return max",
-
- MACH_SEND_IN_PROGRESS, "send in progress",
- MACH_SEND_INVALID_DATA, "send invalid data",
- MACH_SEND_INVALID_DEST, "send invalid dest",
- MACH_SEND_TIMED_OUT, "send timed out",
- MACH_SEND_INTERRUPTED, "send interrupted",
- MACH_SEND_MSG_TOO_SMALL, "send msg too small",
- MACH_SEND_INVALID_REPLY, "send invalid reply",
- MACH_SEND_INVALID_RIGHT, "send invalid right",
- MACH_SEND_INVALID_NOTIFY, "send invalid notify",
- MACH_SEND_INVALID_MEMORY, "send invalid memory",
- MACH_SEND_NO_BUFFER, "send no buffer",
- MACH_SEND_TOO_LARGE, "send too large",
- MACH_SEND_INVALID_TYPE, "send invalid type",
- MACH_SEND_INVALID_HEADER, "send invalid header",
- MACH_SEND_INVALID_TRAILER, "send invalid trailer",
- MACH_SEND_INVALID_RT_OOL_SIZE, "send invalid rt ool size",
- MACH_RCV_IN_PROGRESS, "rcv in progress",
- MACH_RCV_INVALID_NAME, "rcv invalid name",
- MACH_RCV_TIMED_OUT, "rcv timed out",
- MACH_RCV_TOO_LARGE, "rcv too large",
- MACH_RCV_INTERRUPTED, "rcv interrupted",
- MACH_RCV_PORT_CHANGED, "rcv port changed",
- MACH_RCV_INVALID_NOTIFY, "rcv invalid notify",
- MACH_RCV_INVALID_DATA, "rcv invalid data",
- MACH_RCV_PORT_DIED, "rcv port died",
- MACH_RCV_IN_SET, "rcv in set",
- MACH_RCV_HEADER_ERROR, "rcv header error",
- MACH_RCV_BODY_ERROR, "rcv body error",
- MACH_RCV_INVALID_TYPE, "rcv invalid type",
- MACH_RCV_SCATTER_SMALL, "rcv scatter small",
- MACH_RCV_INVALID_TRAILER, "rcv invalid trailer",
- MACH_RCV_IN_PROGRESS_TIMED, "rcv in progress timed",
-
- MIG_TYPE_ERROR, "mig type error",
- MIG_REPLY_MISMATCH, "mig reply mismatch",
- MIG_REMOTE_ERROR, "mig remote error",
- MIG_BAD_ID, "mig bad id",
- MIG_BAD_ARGUMENTS, "mig bad arguments",
- MIG_NO_REPLY, "mig no reply",
- MIG_EXCEPTION, "mig exception",
- MIG_ARRAY_TOO_LARGE, "mig array too large",
- MIG_SERVER_DIED, "server died",
- MIG_TRAILER_ERROR, "trailer has an unknown format",
-};
-
-static int
-me(kern_return_t r)
-{
- int i;
-
- if(r == 0)
- return 0;
-
- for(i=0; i<nelem(macherr); i++){
- if(r == macherr[i].code){
- werrstr("mach: %s", macherr[i].name);
- return -1;
- }
- }
- werrstr("mach error %#x", r);
- return -1;
-}
-
-// Plan 9 and Linux do not distinguish between
-// process ids and thread ids, so the interface here doesn't either.
-// Unfortunately, Mach has three kinds of identifiers: process ids,
-// handles to tasks (processes), and handles to threads within a
-// process. All of them are small integers.
-//
-// To accommodate Mach, we employ a clumsy hack: in this interface,
-// if you pass in a positive number, that's a process id.
-// If you pass in a negative number, that identifies a thread that
-// has been previously returned by procthreadpids (it indexes
-// into the Thread table below).
-
-// Table of threads we have handles for.
-typedef struct Thread Thread;
-struct Thread
-{
- int pid;
- mach_port_t task;
- mach_port_t thread;
- int stopped;
- int exc;
- int code[10];
- Map *map;
-};
-static Thread thr[1000];
-static int nthr;
-static pthread_mutex_t mu;
-static pthread_cond_t cond;
-static void* excthread(void*);
-static void* waitthread(void*);
-static mach_port_t excport;
-
-enum {
- ExcMask = EXC_MASK_BAD_ACCESS |
- EXC_MASK_BAD_INSTRUCTION |
- EXC_MASK_ARITHMETIC |
- EXC_MASK_BREAKPOINT |
- EXC_MASK_SOFTWARE
-};
-
-// Add process pid to the thread table.
-// If it's already there, don't re-add it (unless force != 0).
-static Thread*
-addpid(int pid, int force)
-{
- int i, j;
- mach_port_t task;
- mach_port_t *thread;
- uint nthread;
- Thread *ret;
- static int first = 1;
-
- if(first){
- // Allocate a port for exception messages and
- // send all thread exceptions to that port.
- // The excthread reads that port and signals
- // us if we are waiting on that thread.
- pthread_t p;
- int err;
-
- excport = mach_reply_port();
- pthread_mutex_init(&mu, nil);
- pthread_cond_init(&cond, nil);
- err = pthread_create(&p, nil, excthread, nil);
- if (err != 0) {
- fprint(2, "pthread_create failed: %s\n", strerror(err));
- abort();
- }
- err = pthread_create(&p, nil, waitthread, (void*)(uintptr)pid);
- if (err != 0) {
- fprint(2, "pthread_create failed: %s\n", strerror(err));
- abort();
- }
- first = 0;
- }
-
- if(!force){
- for(i=0; i<nthr; i++)
- if(thr[i].pid == pid)
- return &thr[i];
- }
- if(me(task_for_pid(mach_task_self(), pid, &task)) < 0)
- return nil;
- if(me(task_threads(task, &thread, &nthread)) < 0)
- return nil;
- mach_port_insert_right(mach_task_self(), excport, excport, MACH_MSG_TYPE_MAKE_SEND);
- if(me(task_set_exception_ports(task, ExcMask,
- excport, EXCEPTION_DEFAULT, MACHINE_THREAD_STATE)) < 0){
- fprint(2, "warning: cannot set excport: %r\n");
- }
- ret = nil;
- for(j=0; j<nthread; j++){
- if(force){
- // If we're forcing a refresh, don't re-add existing threads.
- for(i=0; i<nthr; i++)
- if(thr[i].pid == pid && thr[i].thread == thread[j]){
- if(ret == nil)
- ret = &thr[i];
- goto skip;
- }
- }
- if(nthr >= nelem(thr))
- return nil;
- // TODO: We probably should save the old thread exception
- // ports for each bit and then put them back when we exit.
- // Probably the BSD signal handlers have put stuff there.
- mach_port_insert_right(mach_task_self(), excport, excport, MACH_MSG_TYPE_MAKE_SEND);
- if(me(thread_set_exception_ports(thread[j], ExcMask,
- excport, EXCEPTION_DEFAULT, MACHINE_THREAD_STATE)) < 0){
- fprint(2, "warning: cannot set excport: %r\n");
- }
- thr[nthr].pid = pid;
- thr[nthr].task = task;
- thr[nthr].thread = thread[j];
- if(ret == nil)
- ret = &thr[nthr];
- nthr++;
- skip:;
- }
- return ret;
-}
-
-static Thread*
-idtotable(int id)
-{
- if(id >= 0)
- return addpid(id, 1);
-
- id = -(id+1);
- if(id >= nthr)
- return nil;
- return &thr[id];
-}
-
-/*
-static int
-idtopid(int id)
-{
- Thread *t;
-
- if((t = idtotable(id)) == nil)
- return -1;
- return t->pid;
-}
-*/
-
-static mach_port_t
-idtotask(int id)
-{
- Thread *t;
-
- if((t = idtotable(id)) == nil)
- return -1;
- return t->task;
-}
-
-static mach_port_t
-idtothread(int id)
-{
- Thread *t;
-
- if((t = idtotable(id)) == nil)
- return -1;
- return t->thread;
-}
-
-static int machsegrw(Map *map, Seg *seg, uvlong addr, void *v, uint n, int isr);
-static int machregrw(Map *map, Seg *seg, uvlong addr, void *v, uint n, int isr);
-
-Map*
-attachproc(int id, Fhdr *fp)
-{
- Thread *t;
- Map *map;
-
- if((t = idtotable(id)) == nil)
- return nil;
- if(t->map)
- return t->map;
- map = newmap(0, 4);
- if(!map)
- return nil;
- map->pid = -((t-thr) + 1);
- if(mach->regsize)
- setmap(map, -1, 0, mach->regsize, 0, "regs", machregrw);
- setmap(map, -1, fp->txtaddr, fp->txtaddr+fp->txtsz, fp->txtaddr, "*text", machsegrw);
- setmap(map, -1, fp->dataddr, mach->utop, fp->dataddr, "*data", machsegrw);
- t->map = map;
- return map;
-}
-
-// Return list of ids for threads in id.
-int
-procthreadpids(int id, int *out, int nout)
-{
- Thread *t;
- int i, n, pid;
-
- t = idtotable(id);
- if(t == nil)
- return -1;
- pid = t->pid;
- addpid(pid, 1); // force refresh of thread list
- n = 0;
- for(i=0; i<nthr; i++) {
- if(thr[i].pid == pid) {
- if(n < nout)
- out[n] = -(i+1);
- n++;
- }
- }
- return n;
-}
-
-// Detach from proc.
-// TODO(rsc): Perhaps should unsuspend any threads and clean-up the table.
-void
-detachproc(Map *m)
-{
- free(m);
-}
-
-// Should return array of pending signals (notes)
-// but don't know how to do that on OS X.
-int
-procnotes(int pid, char ***pnotes)
-{
- USED(pid);
- *pnotes = 0;
- return 0;
-}
-
-// There must be a way to do this. Gdb can do it.
-// But I don't see, in the Apple gdb sources, how.
-char*
-proctextfile(int pid)
-{
- USED(pid);
- return nil;
-}
-
-// Read/write from a Mach data segment.
-static int
-machsegrw(Map *map, Seg *seg, uvlong addr, void *v, uint n, int isr)
-{
- mach_port_t task;
- int r;
-
- USED(seg);
-
- task = idtotask(map->pid);
- if(task == -1)
- return -1;
-
- if(isr){
- vm_size_t nn;
- nn = n;
- if(me(vm_read_overwrite(task, addr, n, (uintptr)v, &nn)) < 0) {
- fprint(2, "vm_read_overwrite %#llux %d to %p: %r\n", addr, n, v);
- return -1;
- }
- return nn;
- }else{
- r = vm_write(task, addr, (uintptr)v, n);
- if(r == KERN_INVALID_ADDRESS){
- // Happens when writing to text segment.
- // Change protections.
- if(me(vm_protect(task, addr, n, 0, VM_PROT_WRITE|VM_PROT_READ|VM_PROT_EXECUTE)) < 0){
- fprint(2, "vm_protect: %s\n", r);
- return -1;
- }
- r = vm_write(task, addr, (uintptr)v, n);
- }
- if(r != 0){
- me(r);
- return -1;
- }
- return n;
- }
-}
-
-// Convert Ureg offset to x86_thread_state32_t offset.
-static int
-go2darwin32(uvlong addr)
-{
- switch(addr){
- case offsetof(Ureg32, ax):
- return offsetof(x86_thread_state32_t, eax);
- case offsetof(Ureg32, bx):
- return offsetof(x86_thread_state32_t, ebx);
- case offsetof(Ureg32, cx):
- return offsetof(x86_thread_state32_t, ecx);
- case offsetof(Ureg32, dx):
- return offsetof(x86_thread_state32_t, edx);
- case offsetof(Ureg32, si):
- return offsetof(x86_thread_state32_t, esi);
- case offsetof(Ureg32, di):
- return offsetof(x86_thread_state32_t, edi);
- case offsetof(Ureg32, bp):
- return offsetof(x86_thread_state32_t, ebp);
- case offsetof(Ureg32, fs):
- return offsetof(x86_thread_state32_t, fs);
- case offsetof(Ureg32, gs):
- return offsetof(x86_thread_state32_t, gs);
- case offsetof(Ureg32, pc):
- return offsetof(x86_thread_state32_t, eip);
- case offsetof(Ureg32, cs):
- return offsetof(x86_thread_state32_t, cs);
- case offsetof(Ureg32, flags):
- return offsetof(x86_thread_state32_t, eflags);
- case offsetof(Ureg32, sp):
- return offsetof(x86_thread_state32_t, esp);
- }
- return -1;
-}
-
-// Convert Ureg offset to x86_thread_state64_t offset.
-static int
-go2darwin64(uvlong addr)
-{
- switch(addr){
- case offsetof(Ureg64, ax):
- return offsetof(x86_thread_state64_t, rax);
- case offsetof(Ureg64, bx):
- return offsetof(x86_thread_state64_t, rbx);
- case offsetof(Ureg64, cx):
- return offsetof(x86_thread_state64_t, rcx);
- case offsetof(Ureg64, dx):
- return offsetof(x86_thread_state64_t, rdx);
- case offsetof(Ureg64, si):
- return offsetof(x86_thread_state64_t, rsi);
- case offsetof(Ureg64, di):
- return offsetof(x86_thread_state64_t, rdi);
- case offsetof(Ureg64, bp):
- return offsetof(x86_thread_state64_t, rbp);
- case offsetof(Ureg64, r8):
- return offsetof(x86_thread_state64_t, r8);
- case offsetof(Ureg64, r9):
- return offsetof(x86_thread_state64_t, r9);
- case offsetof(Ureg64, r10):
- return offsetof(x86_thread_state64_t, r10);
- case offsetof(Ureg64, r11):
- return offsetof(x86_thread_state64_t, r11);
- case offsetof(Ureg64, r12):
- return offsetof(x86_thread_state64_t, r12);
- case offsetof(Ureg64, r13):
- return offsetof(x86_thread_state64_t, r13);
- case offsetof(Ureg64, r14):
- return offsetof(x86_thread_state64_t, r14);
- case offsetof(Ureg64, r15):
- return offsetof(x86_thread_state64_t, r15);
- case offsetof(Ureg64, fs):
- return offsetof(x86_thread_state64_t, fs);
- case offsetof(Ureg64, gs):
- return offsetof(x86_thread_state64_t, gs);
- case offsetof(Ureg64, ip):
- return offsetof(x86_thread_state64_t, rip);
- case offsetof(Ureg64, cs):
- return offsetof(x86_thread_state64_t, cs);
- case offsetof(Ureg64, flags):
- return offsetof(x86_thread_state64_t, rflags);
- case offsetof(Ureg64, sp):
- return offsetof(x86_thread_state64_t, rsp);
- }
- return -1;
-}
-
-extern Mach mi386;
-
-// Read/write from fake register segment.
-static int
-machregrw(Map *map, Seg *seg, uvlong addr, void *v, uint n, int isr)
-{
- uint nn, count, state;
- mach_port_t thread;
- int reg;
- char buf[100];
- union {
- x86_thread_state64_t reg64;
- x86_thread_state32_t reg32;
- uchar p[1];
- } u;
- uchar *p;
-
- USED(seg);
-
- if(n > 8){
- werrstr("asked for %d-byte register", n);
- return -1;
- }
-
- thread = idtothread(map->pid);
- if(thread == -1){
- werrstr("no such id");
- return -1;
- }
-
- if(mach == &mi386) {
- count = x86_THREAD_STATE32_COUNT;
- state = x86_THREAD_STATE32;
- if((reg = go2darwin32(addr)) < 0 || reg+n > sizeof u){
- if(isr){
- memset(v, 0, n);
- return 0;
- }
- werrstr("register %llud not available", addr);
- return -1;
- }
- } else {
- count = x86_THREAD_STATE64_COUNT;
- state = x86_THREAD_STATE64;
- if((reg = go2darwin64(addr)) < 0 || reg+n > sizeof u){
- if(isr){
- memset(v, 0, n);
- return 0;
- }
- werrstr("register %llud not available", addr);
- return -1;
- }
- }
-
- if(!isr && me(thread_suspend(thread)) < 0){
- werrstr("thread suspend %#x: %r", thread);
- return -1;
- }
- nn = count;
- if(me(thread_get_state(thread, state, (void*)u.p, &nn)) < 0){
- if(!isr)
- thread_resume(thread);
- rerrstr(buf, sizeof buf);
- if(strstr(buf, "send invalid dest") != nil)
- werrstr("process exited");
- else
- werrstr("thread_get_state: %r");
- return -1;
- }
-
- p = u.p+reg;
- if(isr)
- memmove(v, p, n);
- else{
- memmove(p, v, n);
- nn = count;
- if(me(thread_set_state(thread, state, (void*)u.p, nn)) < 0){
- thread_resume(thread);
- werrstr("thread_set_state: %r");
- return -1;
- }
-
- if(me(thread_resume(thread)) < 0){
- werrstr("thread_resume: %r");
- return -1;
- }
- }
- return 0;
-}
-
-enum
-{
- FLAGS_TF = 0x100 // x86 single-step processor flag
-};
-
-// Is thread t suspended?
-static int
-threadstopped(Thread *t)
-{
- struct thread_basic_info info;
- uint size;
-
- size = sizeof info;
- if(me(thread_info(t->thread, THREAD_BASIC_INFO, (thread_info_t)&info, &size)) < 0){
- fprint(2, "threadstopped thread_info %#x: %r\n");
- return 1;
- }
- return info.suspend_count > 0;
-}
-
-// If thread t is suspended, start it up again.
-// If singlestep is set, only let it execute one instruction.
-static int
-threadstart(Thread *t, int singlestep)
-{
- int i;
- uint n;
- struct thread_basic_info info;
-
- if(!threadstopped(t))
- return 0;
-
- // Set or clear the processor single-step flag, as appropriate.
- if(mach == &mi386) {
- x86_thread_state32_t regs;
- n = x86_THREAD_STATE32_COUNT;
- if(me(thread_get_state(t->thread, x86_THREAD_STATE32,
- (thread_state_t)&regs,
- &n)) < 0)
- return -1;
- if(singlestep)
- regs.eflags |= FLAGS_TF;
- else
- regs.eflags &= ~FLAGS_TF;
- if(me(thread_set_state(t->thread, x86_THREAD_STATE32,
- (thread_state_t)&regs,
- x86_THREAD_STATE32_COUNT)) < 0)
- return -1;
- } else {
- x86_thread_state64_t regs;
- n = x86_THREAD_STATE64_COUNT;
- if(me(thread_get_state(t->thread, x86_THREAD_STATE64,
- (thread_state_t)&regs,
- &n)) < 0)
- return -1;
- if(singlestep)
- regs.rflags |= FLAGS_TF;
- else
- regs.rflags &= ~FLAGS_TF;
- if(me(thread_set_state(t->thread, x86_THREAD_STATE64,
- (thread_state_t)&regs,
- x86_THREAD_STATE64_COUNT)) < 0)
- return -1;
- }
-
- // Run.
- n = sizeof info;
- if(me(thread_info(t->thread, THREAD_BASIC_INFO, (thread_info_t)&info, &n)) < 0)
- return -1;
- for(i=0; i<info.suspend_count; i++)
- if(me(thread_resume(t->thread)) < 0)
- return -1;
- return 0;
-}
-
-// Stop thread t.
-static int
-threadstop(Thread *t)
-{
- if(threadstopped(t))
- return 0;
- if(me(thread_suspend(t->thread)) < 0)
- return -1;
- return 0;
-}
-
-// Callback for exc_server below. Called when a thread we are
-// watching has an exception like hitting a breakpoint.
-kern_return_t
-catch_exception_raise(mach_port_t eport, mach_port_t thread,
- mach_port_t task, exception_type_t exception,
- exception_data_t code, mach_msg_type_number_t ncode)
-{
- Thread *t;
- int i;
-
- USED(eport);
- USED(task);
-
- t = nil;
- for(i=0; i<nthr; i++){
- if(thr[i].thread == thread){
- t = &thr[i];
- goto havet;
- }
- }
- if(nthr > 0)
- addpid(thr[0].pid, 1);
- for(i=0; i<nthr; i++){
- if(thr[i].thread == thread){
- t = &thr[i];
- goto havet;
- }
- }
- fprint(2, "did not find thread in catch_exception_raise\n");
- return KERN_SUCCESS; // let thread continue
-
-havet:
- t->exc = exception;
- if(ncode > nelem(t->code))
- ncode = nelem(t->code);
- memmove(t->code, code, ncode*sizeof t->code[0]);
-
- // Suspend thread, so that we can look at it & restart it later.
- if(me(thread_suspend(thread)) < 0)
- fprint(2, "catch_exception_raise thread_suspend: %r\n");
-
- // Synchronize with waitstop below.
- pthread_mutex_lock(&mu);
- pthread_cond_broadcast(&cond);
- pthread_mutex_unlock(&mu);
-
- return KERN_SUCCESS;
-}
-
-// Exception watching thread, started in addpid above.
-static void*
-excthread(void *v)
-{
- USED(v);
- extern boolean_t exc_server(mach_msg_header_t *, mach_msg_header_t *);
- mach_msg_server(exc_server, 2048, excport, 0);
- return 0;
-}
-
-// Wait for pid to exit.
-static int exited;
-static void*
-waitthread(void *v)
-{
- int pid, status;
-
- pid = (int)(uintptr)v;
- waitpid(pid, &status, 0);
- exited = 1;
- // Synchronize with waitstop below.
- pthread_mutex_lock(&mu);
- pthread_cond_broadcast(&cond);
- pthread_mutex_unlock(&mu);
- return nil;
-}
-
-// Wait for thread t to stop.
-static int
-waitstop(Thread *t)
-{
- pthread_mutex_lock(&mu);
- while(!exited && !threadstopped(t))
- pthread_cond_wait(&cond, &mu);
- pthread_mutex_unlock(&mu);
- return 0;
-}
-
-int
-ctlproc(int id, char *msg)
-{
- Thread *t;
- int status;
-
- // Hang/attached dance is for debugging newly exec'ed programs.
- // After fork, the child does ctlproc("hang") before exec,
- // and the parent does ctlproc("attached") and then waitstop.
- // Using these requires the BSD ptrace interface, unlike everything
- // else we do, which uses only the Mach interface. Our goal here
- // is to do as little as possible using ptrace and then flip over to Mach.
-
- if(strcmp(msg, "hang") == 0)
- return ptrace(PT_TRACE_ME, 0, 0, 0);
-
- if(strcmp(msg, "attached") == 0){
- // The pid "id" has done a ctlproc "hang" and then
- // exec, so we should find it stoppped just before exec
- // of the new program.
- #undef waitpid
- if(waitpid(id, &status, WUNTRACED) < 0){
- fprint(2, "ctlproc attached waitpid: %r\n");
- return -1;
- }
- if(WIFEXITED(status) || !WIFSTOPPED(status)){
- fprint(2, "ctlproc attached: bad process state\n");
- return -1;
- }
-
- // Find Mach thread for pid and suspend it.
- t = addpid(id, 1);
- if(t == nil) {
- fprint(2, "ctlproc attached: addpid: %r\n");
- return -1;
- }
- if(me(thread_suspend(t->thread)) < 0){
- fprint(2, "ctlproc attached: thread_suspend: %r\n");
- return -1;
- }
-
- // Let ptrace tell the process to keep going:
- // then ptrace is out of the way and we're back in Mach land.
- if(ptrace(PT_CONTINUE, id, (caddr_t)1, 0) < 0) {
- fprint(2, "ctlproc attached: ptrace continue: %r\n");
- return -1;
- }
-
- return 0;
- }
-
- // All the other control messages require a Thread structure.
- if((t = idtotable(id)) == nil){
- werrstr("no such thread");
- return -1;
- }
-
- if(strcmp(msg, "kill") == 0)
- return ptrace(PT_KILL, t->pid, 0, 0);
-
- if(strcmp(msg, "start") == 0)
- return threadstart(t, 0);
-
- if(strcmp(msg, "stop") == 0)
- return threadstop(t);
-
- if(strcmp(msg, "startstop") == 0){
- if(threadstart(t, 0) < 0)
- return -1;
- return waitstop(t);
- }
-
- if(strcmp(msg, "step") == 0){
- if(threadstart(t, 1) < 0)
- return -1;
- return waitstop(t);
- }
-
- if(strcmp(msg, "waitstop") == 0)
- return waitstop(t);
-
- // sysstop not available on OS X
-
- werrstr("unknown control message");
- return -1;
-}
-
-char*
-procstatus(int id)
-{
- Thread *t;
-
- if((t = idtotable(id)) == nil)
- return "gone!";
-
- if(threadstopped(t))
- return "Stopped";
-
- return "Running";
-}
-
diff --git a/src/libmach/dragonfly.c b/src/libmach/dragonfly.c
deleted file mode 100644
index 43dd005e9..000000000
--- a/src/libmach/dragonfly.c
+++ /dev/null
@@ -1,62 +0,0 @@
-// This is stubbed out for the moment. Will revisit when the time comes.
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-
-int
-ctlproc(int pid, char *msg)
-{
- USED(pid);
- USED(msg);
-
- sysfatal("ctlproc unimplemented in DragonFly");
- return -1;
-}
-
-char*
-proctextfile(int pid)
-{
- USED(pid);
-
- sysfatal("proctextfile unimplemented in DragonFly");
- return nil;
-}
-
-char*
-procstatus(int pid)
-{
- USED(pid);
-
- sysfatal("procstatus unimplemented in DragonFly");
- return nil;
-}
-
-Map*
-attachproc(int pid, Fhdr *fp)
-{
- USED(pid);
- USED(fp);
-
- sysfatal("attachproc unimplemented in DragonFly");
- return nil;
-}
-
-void
-detachproc(Map *m)
-{
- USED(m);
-
- sysfatal("detachproc unimplemented in DragonFly");
-}
-
-int
-procthreadpids(int pid, int *p, int np)
-{
- USED(pid);
- USED(p);
- USED(np);
-
- sysfatal("procthreadpids unimplemented in DragonFly");
- return -1;
-}
diff --git a/src/libmach/elf.h b/src/libmach/elf.h
deleted file mode 100644
index 8dbc983f0..000000000
--- a/src/libmach/elf.h
+++ /dev/null
@@ -1,182 +0,0 @@
-// Inferno libmach/elf.h
-// http://code.google.com/p/inferno-os/source/browse/utils/libmach/elf.h
-//
-// Copyright © 1994-1999 Lucent Technologies Inc.
-// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
-// Portions Copyright © 1997-1999 Vita Nuova Limited.
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-/*
- * Definitions needed for accessing ELF headers.
- * 32-bit and 64-bit structs differ.
- */
-typedef struct {
- uchar ident[16]; /* ident bytes */
- ushort type; /* file type */
- ushort machine; /* target machine */
- int version; /* file version */
- uint32 elfentry; /* start address */
- uint32 phoff; /* phdr file offset */
- uint32 shoff; /* shdr file offset */
- int flags; /* file flags */
- ushort ehsize; /* sizeof ehdr */
- ushort phentsize; /* sizeof phdr */
- ushort phnum; /* number phdrs */
- ushort shentsize; /* sizeof shdr */
- ushort shnum; /* number shdrs */
- ushort shstrndx; /* shdr string index */
-} Ehdr32;
-
-typedef struct {
- uchar ident[16]; /* ident bytes */
- ushort type; /* file type */
- ushort machine; /* target machine */
- int version; /* file version */
- uvlong elfentry; /* start address */
- uvlong phoff; /* phdr file offset */
- uvlong shoff; /* shdr file offset */
- int flags; /* file flags */
- ushort ehsize; /* sizeof ehdr */
- ushort phentsize; /* sizeof phdr */
- ushort phnum; /* number phdrs */
- ushort shentsize; /* sizeof shdr */
- ushort shnum; /* number shdrs */
- ushort shstrndx; /* shdr string index */
-} Ehdr64;
-
-typedef struct {
- int type; /* entry type */
- uint32 offset; /* file offset */
- uint32 vaddr; /* virtual address */
- uint32 paddr; /* physical address */
- int filesz; /* file size */
- uint32 memsz; /* memory size */
- int flags; /* entry flags */
- int align; /* memory/file alignment */
-} Phdr32;
-
-typedef struct {
- int type; /* entry type */
- int flags; /* entry flags */
- uvlong offset; /* file offset */
- uvlong vaddr; /* virtual address */
- uvlong paddr; /* physical address */
- uvlong filesz; /* file size */
- uvlong memsz; /* memory size */
- uvlong align; /* memory/file alignment */
-} Phdr64;
-
-typedef struct {
- uint32 name; /* section name */
- uint32 type; /* SHT_... */
- uint32 flags; /* SHF_... */
- uint32 addr; /* virtual address */
- uint32 offset; /* file offset */
- uint32 size; /* section size */
- uint32 link; /* misc info */
- uint32 info; /* misc info */
- uint32 addralign; /* memory alignment */
- uint32 entsize; /* entry size if table */
-} Shdr32;
-
-typedef struct {
- uint32 name; /* section name */
- uint32 type; /* SHT_... */
- uvlong flags; /* SHF_... */
- uvlong addr; /* virtual address */
- uvlong offset; /* file offset */
- uvlong size; /* section size */
- uint32 link; /* misc info */
- uint32 info; /* misc info */
- uvlong addralign; /* memory alignment */
- uvlong entsize; /* entry size if table */
-} Shdr64;
-
-enum {
- /* Ehdr codes */
- MAG0 = 0, /* ident[] indexes */
- MAG1 = 1,
- MAG2 = 2,
- MAG3 = 3,
- CLASS = 4,
- DATA = 5,
- VERSION = 6,
-
- ELFCLASSNONE = 0, /* ident[CLASS] */
- ELFCLASS32 = 1,
- ELFCLASS64 = 2,
- ELFCLASSNUM = 3,
-
- ELFDATANONE = 0, /* ident[DATA] */
- ELFDATA2LSB = 1,
- ELFDATA2MSB = 2,
- ELFDATANUM = 3,
-
- NOETYPE = 0, /* type */
- REL = 1,
- EXEC = 2,
- DYN = 3,
- CORE = 4,
-
- NONE = 0, /* machine */
- M32 = 1, /* AT&T WE 32100 */
- SPARC = 2, /* Sun SPARC */
- I386 = 3, /* Intel 80386 */
- M68K = 4, /* Motorola 68000 */
- M88K = 5, /* Motorola 88000 */
- I486 = 6, /* Intel 80486 */
- I860 = 7, /* Intel i860 */
- MIPS = 8, /* Mips R2000 */
- S370 = 9, /* Amdhal */
- SPARC64 = 18, /* Sun SPARC v9 */
- POWER = 20, /* PowerPC */
- ARM = 40, /* ARM */
- AMD64 = 62, /* Amd64 */
-
- NO_VERSION = 0, /* version, ident[VERSION] */
- CURRENT = 1,
-
- /* Phdr Codes */
- NOPTYPE = 0, /* type */
- LOAD = 1,
- DYNAMIC = 2,
- INTERP = 3,
- NOTE = 4,
- SHLIB = 5,
- PHDR = 6,
-
- R = 0x4, /* flags */
- W = 0x2,
- X = 0x1,
-
- /* Shdr Codes */
- Progbits = 1, /* section types */
- Strtab = 3,
- Nobits = 8,
-
- Swrite = 1, /* section attributes */
- Salloc = 2,
- Sexec = 4,
-};
-
-#define ELF_MAG ((0x7f<<24) | ('E'<<16) | ('L'<<8) | 'F')
diff --git a/src/libmach/executable.c b/src/libmach/executable.c
deleted file mode 100644
index eae14441a..000000000
--- a/src/libmach/executable.c
+++ /dev/null
@@ -1,1525 +0,0 @@
-// Inferno libmach/executable.c
-// http://code.google.com/p/inferno-os/source/browse/utils/libmach/executable.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc.
-// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
-// Portions Copyright © 1997-1999 Vita Nuova Limited.
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <bootexec.h>
-#include <mach.h>
-#include "elf.h"
-#include "macho.h"
-
-/*
- * All a.out header types. The dummy entry allows canonical
- * processing of the union as a sequence of int32s
- */
-
-typedef struct {
- union{
- /*struct { */
- Exec exechdr; /* a.out.h */
- /* uvlong hdr[1];*/
- /*};*/
- Ehdr32 elfhdr32; /* elf.h */
- Ehdr64 elfhdr64; /* elf.h */
- struct mipsexec mips; /* bootexec.h */
- struct mips4kexec mipsk4; /* bootexec.h */
- struct sparcexec sparc; /* bootexec.h */
- struct nextexec next; /* bootexec.h */
- Machhdr machhdr; /* macho.h */
- } e;
- int32 dummy; /* padding to ensure extra int32 */
-} ExecHdr;
-
-static int nextboot(int, Fhdr*, ExecHdr*);
-static int sparcboot(int, Fhdr*, ExecHdr*);
-static int mipsboot(int, Fhdr*, ExecHdr*);
-static int mips4kboot(int, Fhdr*, ExecHdr*);
-static int common(int, Fhdr*, ExecHdr*);
-static int commonllp64(int, Fhdr*, ExecHdr*);
-static int adotout(int, Fhdr*, ExecHdr*);
-static int elfdotout(int, Fhdr*, ExecHdr*);
-static int machdotout(int, Fhdr*, ExecHdr*);
-static int armdotout(int, Fhdr*, ExecHdr*);
-static int pedotout(int, Fhdr*, ExecHdr*);
-static void setsym(Fhdr*, vlong, int32, vlong, int32, vlong, int32);
-static void setdata(Fhdr*, uvlong, int32, vlong, int32);
-static void settext(Fhdr*, uvlong, uvlong, int32, vlong);
-static void hswal(void*, int, uint32(*)(uint32));
-static uvlong _round(uvlong, uint32);
-
-/*
- * definition of per-executable file type structures
- */
-
-typedef struct Exectable{
- int32 magic; /* big-endian magic number of file */
- char *name; /* executable identifier */
- char *dlmname; /* dynamically loadable module identifier */
- uchar type; /* Internal code */
- uchar _magic; /* _MAGIC() magic */
- Mach *mach; /* Per-machine data */
- int32 hsize; /* header size */
- uint32 (*swal)(uint32); /* beswal or leswal */
- int (*hparse)(int, Fhdr*, ExecHdr*);
-} ExecTable;
-
-extern Mach mmips;
-extern Mach mmips2le;
-extern Mach mmips2be;
-extern Mach msparc;
-extern Mach msparc64;
-extern Mach m68020;
-extern Mach mi386;
-extern Mach mamd64;
-extern Mach marm;
-extern Mach mpower;
-extern Mach mpower64;
-extern Mach malpha;
-
-/* BUG: FIX THESE WHEN NEEDED */
-Mach mmips;
-Mach mmips2le;
-Mach mmips2be;
-Mach msparc;
-Mach msparc64;
-Mach m68020;
-Mach mpower;
-Mach mpower64;
-Mach malpha;
-
-ExecTable exectab[] =
-{
- { V_MAGIC, /* Mips v.out */
- "mips plan 9 executable BE",
- "mips plan 9 dlm BE",
- FMIPS,
- 1,
- &mmips,
- sizeof(Exec),
- beswal,
- adotout },
- { P_MAGIC, /* Mips 0.out (r3k le) */
- "mips plan 9 executable LE",
- "mips plan 9 dlm LE",
- FMIPSLE,
- 1,
- &mmips,
- sizeof(Exec),
- beswal,
- adotout },
- { M_MAGIC, /* Mips 4.out */
- "mips 4k plan 9 executable BE",
- "mips 4k plan 9 dlm BE",
- FMIPS2BE,
- 1,
- &mmips2be,
- sizeof(Exec),
- beswal,
- adotout },
- { N_MAGIC, /* Mips 0.out */
- "mips 4k plan 9 executable LE",
- "mips 4k plan 9 dlm LE",
- FMIPS2LE,
- 1,
- &mmips2le,
- sizeof(Exec),
- beswal,
- adotout },
- { 0x160<<16, /* Mips boot image */
- "mips plan 9 boot image",
- nil,
- FMIPSB,
- 0,
- &mmips,
- sizeof(struct mipsexec),
- beswal,
- mipsboot },
- { (0x160<<16)|3, /* Mips boot image */
- "mips 4k plan 9 boot image",
- nil,
- FMIPSB,
- 0,
- &mmips2be,
- sizeof(struct mips4kexec),
- beswal,
- mips4kboot },
- { K_MAGIC, /* Sparc k.out */
- "sparc plan 9 executable",
- "sparc plan 9 dlm",
- FSPARC,
- 1,
- &msparc,
- sizeof(Exec),
- beswal,
- adotout },
- { 0x01030107, /* Sparc boot image */
- "sparc plan 9 boot image",
- nil,
- FSPARCB,
- 0,
- &msparc,
- sizeof(struct sparcexec),
- beswal,
- sparcboot },
- { U_MAGIC, /* Sparc64 u.out */
- "sparc64 plan 9 executable",
- "sparc64 plan 9 dlm",
- FSPARC64,
- 1,
- &msparc64,
- sizeof(Exec),
- beswal,
- adotout },
- { A_MAGIC, /* 68020 2.out & boot image */
- "68020 plan 9 executable",
- "68020 plan 9 dlm",
- F68020,
- 1,
- &m68020,
- sizeof(Exec),
- beswal,
- common },
- { 0xFEEDFACE, /* Next boot image */
- "next plan 9 boot image",
- nil,
- FNEXTB,
- 0,
- &m68020,
- sizeof(struct nextexec),
- beswal,
- nextboot },
- { I_MAGIC, /* I386 8.out & boot image */
- "386 plan 9 executable",
- "386 plan 9 dlm",
- FI386,
- 1,
- &mi386,
- sizeof(Exec),
- beswal,
- common },
- { S_MAGIC, /* amd64 6.out & boot image */
- "amd64 plan 9 executable",
- "amd64 plan 9 dlm",
- FAMD64,
- 1,
- &mamd64,
- sizeof(Exec)+8,
- nil,
- commonllp64 },
- { Q_MAGIC, /* PowerPC q.out & boot image */
- "power plan 9 executable",
- "power plan 9 dlm",
- FPOWER,
- 1,
- &mpower,
- sizeof(Exec),
- beswal,
- common },
- { T_MAGIC, /* power64 9.out & boot image */
- "power64 plan 9 executable",
- "power64 plan 9 dlm",
- FPOWER64,
- 1,
- &mpower64,
- sizeof(Exec)+8,
- nil,
- commonllp64 },
- { ELF_MAG, /* any elf32 or elf64 */
- "elf executable",
- nil,
- FNONE,
- 0,
- &mi386,
- sizeof(Ehdr64),
- nil,
- elfdotout },
- { MACH64_MAG, /* 64-bit MACH (apple mac) */
- "mach executable",
- nil,
- FAMD64,
- 0,
- &mamd64,
- sizeof(Machhdr),
- nil,
- machdotout },
- { MACH32_MAG, /* 32-bit MACH (apple mac) */
- "mach executable",
- nil,
- FI386,
- 0,
- &mi386,
- sizeof(Machhdr),
- nil,
- machdotout },
- { E_MAGIC, /* Arm 5.out and boot image */
- "arm plan 9 executable",
- "arm plan 9 dlm",
- FARM,
- 1,
- &marm,
- sizeof(Exec),
- beswal,
- common },
- { (143<<16)|0413, /* (Free|Net)BSD Arm */
- "arm *bsd executable",
- nil,
- FARM,
- 0,
- &marm,
- sizeof(Exec),
- leswal,
- armdotout },
- { L_MAGIC, /* alpha 7.out */
- "alpha plan 9 executable",
- "alpha plan 9 dlm",
- FALPHA,
- 1,
- &malpha,
- sizeof(Exec),
- beswal,
- common },
- { 0x0700e0c3, /* alpha boot image */
- "alpha plan 9 boot image",
- nil,
- FALPHA,
- 0,
- &malpha,
- sizeof(Exec),
- beswal,
- common },
- { 0x4d5a9000, /* see dosstub[] in pe.c */
- "windows PE executable",
- nil,
- FWINPE,
- 0,
- &mi386,
- sizeof(Exec), /* TODO */
- nil,
- pedotout },
- { 0 },
-};
-
-Mach *mach = &mi386; /* Global current machine table */
-
-static ExecTable*
-couldbe4k(ExecTable *mp)
-{
- Dir *d;
- ExecTable *f;
-
- if((d=dirstat("/proc/1/regs")) == nil)
- return mp;
- if(d->length < 32*8){ /* R3000 */
- free(d);
- return mp;
- }
- free(d);
- for (f = exectab; f->magic; f++)
- if(f->magic == M_MAGIC) {
- f->name = "mips plan 9 executable on mips2 kernel";
- return f;
- }
- return mp;
-}
-
-int
-crackhdr(int fd, Fhdr *fp)
-{
- ExecTable *mp;
- ExecHdr d;
- int nb, ret;
- uint32 magic;
-
- fp->type = FNONE;
- nb = read(fd, (char *)&d.e, sizeof(d.e));
- if (nb <= 0)
- return 0;
-
- ret = 0;
- magic = beswal(d.e.exechdr.magic); /* big-endian */
- for (mp = exectab; mp->magic; mp++) {
- if (nb < mp->hsize)
- continue;
-
- /*
- * The magic number has morphed into something
- * with fields (the straw was DYN_MAGIC) so now
- * a flag is needed in Fhdr to distinguish _MAGIC()
- * magic numbers from foreign magic numbers.
- *
- * This code is creaking a bit and if it has to
- * be modified/extended much more it's probably
- * time to step back and redo it all.
- */
- if(mp->_magic){
- if(mp->magic != (magic & ~DYN_MAGIC))
- continue;
-
- if(mp->magic == V_MAGIC)
- mp = couldbe4k(mp);
-
- if ((magic & DYN_MAGIC) && mp->dlmname != nil)
- fp->name = mp->dlmname;
- else
- fp->name = mp->name;
- }
- else{
- if(mp->magic != magic)
- continue;
- fp->name = mp->name;
- }
- fp->type = mp->type;
- fp->hdrsz = mp->hsize; /* will be zero on bootables */
- fp->_magic = mp->_magic;
- fp->magic = magic;
-
- mach = mp->mach;
- if(mp->swal != nil)
- hswal(&d, sizeof(d.e)/sizeof(uint32), mp->swal);
- ret = mp->hparse(fd, fp, &d);
- seek(fd, mp->hsize, 0); /* seek to end of header */
- break;
- }
- if(mp->magic == 0)
- werrstr("unknown header type");
- return ret;
-}
-
-/*
- * Convert header to canonical form
- */
-static void
-hswal(void *v, int n, uint32 (*swap)(uint32))
-{
- uint32 *ulp;
-
- for(ulp = v; n--; ulp++)
- *ulp = (*swap)(*ulp);
-}
-
-/*
- * Crack a normal a.out-type header
- */
-static int
-adotout(int fd, Fhdr *fp, ExecHdr *hp)
-{
- int32 pgsize;
-
- USED(fd);
- pgsize = mach->pgsize;
- settext(fp, hp->e.exechdr.entry, pgsize+sizeof(Exec),
- hp->e.exechdr.text, sizeof(Exec));
- setdata(fp, _round(pgsize+fp->txtsz+sizeof(Exec), pgsize),
- hp->e.exechdr.data, fp->txtsz+sizeof(Exec), hp->e.exechdr.bss);
- setsym(fp, fp->datoff+fp->datsz, hp->e.exechdr.syms, 0, hp->e.exechdr.spsz, 0, hp->e.exechdr.pcsz);
- return 1;
-}
-
-static void
-commonboot(Fhdr *fp)
-{
- if (!(fp->entry & mach->ktmask))
- return;
-
- switch(fp->type) { /* boot image */
- case F68020:
- fp->type = F68020B;
- fp->name = "68020 plan 9 boot image";
- break;
- case FI386:
- fp->type = FI386B;
- fp->txtaddr = (u32int)fp->entry;
- fp->name = "386 plan 9 boot image";
- fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize);
- break;
- case FARM:
- fp->type = FARMB;
- fp->txtaddr = (u32int)fp->entry;
- fp->name = "ARM plan 9 boot image";
- fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize);
- return;
- case FALPHA:
- fp->type = FALPHAB;
- fp->txtaddr = (u32int)fp->entry;
- fp->name = "alpha plan 9 boot image";
- fp->dataddr = fp->txtaddr+fp->txtsz;
- break;
- case FPOWER:
- fp->type = FPOWERB;
- fp->txtaddr = (u32int)fp->entry;
- fp->name = "power plan 9 boot image";
- fp->dataddr = fp->txtaddr+fp->txtsz;
- break;
- case FAMD64:
- fp->type = FAMD64B;
- fp->txtaddr = fp->entry;
- fp->name = "amd64 plan 9 boot image";
- fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize);
- break;
- default:
- return;
- }
- fp->hdrsz = 0; /* header stripped */
-}
-
-/*
- * _MAGIC() style headers and
- * alpha plan9-style bootable images for axp "headerless" boot
- *
- */
-static int
-common(int fd, Fhdr *fp, ExecHdr *hp)
-{
- adotout(fd, fp, hp);
- if(hp->e.exechdr.magic & DYN_MAGIC) {
- fp->txtaddr = 0;
- fp->dataddr = fp->txtsz;
- return 1;
- }
- commonboot(fp);
- return 1;
-}
-
-static int
-commonllp64(int unused, Fhdr *fp, ExecHdr *hp)
-{
- int32 pgsize;
- uvlong entry;
-
- USED(unused);
-
- hswal(&hp->e, sizeof(Exec)/sizeof(int32), beswal);
- if(!(hp->e.exechdr.magic & HDR_MAGIC))
- return 0;
-
- /*
- * There can be more magic here if the
- * header ever needs more expansion.
- * For now just catch use of any of the
- * unused bits.
- */
- if((hp->e.exechdr.magic & ~DYN_MAGIC)>>16)
- return 0;
- union {
- char *p;
- uvlong *v;
- } u;
- u.p = (char*)&hp->e.exechdr;
- entry = beswav(*u.v);
-
- pgsize = mach->pgsize;
- settext(fp, entry, pgsize+fp->hdrsz, hp->e.exechdr.text, fp->hdrsz);
- setdata(fp, _round(pgsize+fp->txtsz+fp->hdrsz, pgsize),
- hp->e.exechdr.data, fp->txtsz+fp->hdrsz, hp->e.exechdr.bss);
- setsym(fp, fp->datoff+fp->datsz, hp->e.exechdr.syms, 0, hp->e.exechdr.spsz, 0, hp->e.exechdr.pcsz);
-
- if(hp->e.exechdr.magic & DYN_MAGIC) {
- fp->txtaddr = 0;
- fp->dataddr = fp->txtsz;
- return 1;
- }
- commonboot(fp);
- return 1;
-}
-
-/*
- * mips bootable image.
- */
-static int
-mipsboot(int fd, Fhdr *fp, ExecHdr *hp)
-{
- USED(fd);
- USED(fp);
- USED(hp);
-
-abort();
-#ifdef unused
- USED(fd);
- fp->type = FMIPSB;
- switch(hp->e.exechdr.amagic) {
- default:
- case 0407: /* some kind of mips */
- settext(fp, (u32int)hp->e.mentry, (u32int)hp->e.text_start,
- hp->e.tsize, sizeof(struct mipsexec)+4);
- setdata(fp, (u32int)hp->e.data_start, hp->e.dsize,
- fp->txtoff+hp->e.tsize, hp->e.bsize);
- break;
- case 0413: /* some kind of mips */
- settext(fp, (u32int)hp->e.mentry, (u32int)hp->e.text_start,
- hp->e.tsize, 0);
- setdata(fp, (u32int)hp->e.data_start, hp->e.dsize,
- hp->e.tsize, hp->e.bsize);
- break;
- }
- setsym(fp, hp->e.nsyms, 0, hp->e.pcsize, hp->e.symptr);
- fp->hdrsz = 0; /* header stripped */
-#endif
- return 1;
-}
-
-/*
- * mips4k bootable image.
- */
-static int
-mips4kboot(int fd, Fhdr *fp, ExecHdr *hp)
-{
- USED(fd);
- USED(fp);
- USED(hp);
-
-abort();
-#ifdef unused
- USED(fd);
- fp->type = FMIPSB;
- switch(hp->e.h.amagic) {
- default:
- case 0407: /* some kind of mips */
- settext(fp, (u32int)hp->e.h.mentry, (u32int)hp->e.h.text_start,
- hp->e.h.tsize, sizeof(struct mips4kexec));
- setdata(fp, (u32int)hp->e.h.data_start, hp->e.h.dsize,
- fp->txtoff+hp->e.h.tsize, hp->e.h.bsize);
- break;
- case 0413: /* some kind of mips */
- settext(fp, (u32int)hp->e.h.mentry, (u32int)hp->e.h.text_start,
- hp->e.h.tsize, 0);
- setdata(fp, (u32int)hp->e.h.data_start, hp->e.h.dsize,
- hp->e.h.tsize, hp->e.h.bsize);
- break;
- }
- setsym(fp, hp->e.h.nsyms, 0, hp->e.h.pcsize, hp->e.h.symptr);
- fp->hdrsz = 0; /* header stripped */
-#endif
- return 1;
-}
-
-/*
- * sparc bootable image
- */
-static int
-sparcboot(int fd, Fhdr *fp, ExecHdr *hp)
-{
- USED(fd);
- USED(fp);
- USED(hp);
-
-abort();
-#ifdef unused
- USED(fd);
- fp->type = FSPARCB;
- settext(fp, hp->e.sentry, hp->e.sentry, hp->e.stext,
- sizeof(struct sparcexec));
- setdata(fp, hp->e.sentry+hp->e.stext, hp->e.sdata,
- fp->txtoff+hp->e.stext, hp->e.sbss);
- setsym(fp, hp->e.ssyms, 0, hp->e.sdrsize, fp->datoff+hp->e.sdata);
- fp->hdrsz = 0; /* header stripped */
-#endif
- return 1;
-}
-
-/*
- * next bootable image
- */
-static int
-nextboot(int fd, Fhdr *fp, ExecHdr *hp)
-{
- USED(fd);
- USED(fp);
- USED(hp);
-
-abort();
-#ifdef unused
- USED(fd);
- fp->type = FNEXTB;
- settext(fp, hp->e.textc.vmaddr, hp->e.textc.vmaddr,
- hp->e.texts.size, hp->e.texts.offset);
- setdata(fp, hp->e.datac.vmaddr, hp->e.datas.size,
- hp->e.datas.offset, hp->e.bsss.size);
- setsym(fp, hp->e.symc.nsyms, hp->e.symc.spoff, hp->e.symc.pcoff,
- hp->e.symc.symoff);
- fp->hdrsz = 0; /* header stripped */
-#endif
- return 1;
-}
-
-/*
- * Elf32 and Elf64 binaries.
- */
-static int
-elf64dotout(int fd, Fhdr *fp, ExecHdr *hp)
-{
- uvlong (*swav)(uvlong);
- uint32 (*swal)(uint32);
- ushort (*swab)(ushort);
- Ehdr64 *ep;
- Phdr64 *ph, *pph;
- Shdr64 *sh;
- int i, it, id, is, phsz, shsz;
-
- /* bitswap the header according to the DATA format */
- ep = &hp->e.elfhdr64;
- if(ep->ident[CLASS] != ELFCLASS64) {
- werrstr("bad ELF class - not 32 bit or 64 bit");
- return 0;
- }
- if(ep->ident[DATA] == ELFDATA2LSB) {
- swab = leswab;
- swal = leswal;
- swav = leswav;
- } else if(ep->ident[DATA] == ELFDATA2MSB) {
- swab = beswab;
- swal = beswal;
- swav = beswav;
- } else {
- werrstr("bad ELF encoding - not big or little endian");
- return 0;
- }
-
- ep->type = swab(ep->type);
- ep->machine = swab(ep->machine);
- ep->version = swal(ep->version);
- ep->elfentry = swal(ep->elfentry);
- ep->phoff = swav(ep->phoff);
- ep->shoff = swav(ep->shoff);
- ep->flags = swav(ep->flags);
- ep->ehsize = swab(ep->ehsize);
- ep->phentsize = swab(ep->phentsize);
- ep->phnum = swab(ep->phnum);
- ep->shentsize = swab(ep->shentsize);
- ep->shnum = swab(ep->shnum);
- ep->shstrndx = swab(ep->shstrndx);
- if(ep->type != EXEC || ep->version != CURRENT)
- return 0;
-
- /* we could definitely support a lot more machines here */
- fp->magic = ELF_MAG;
- fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15;
- switch(ep->machine) {
- case AMD64:
- mach = &mamd64;
- fp->type = FAMD64;
- break;
- default:
- return 0;
- }
-
- if(ep->phentsize != sizeof(Phdr64)) {
- werrstr("bad ELF header size");
- return 0;
- }
- phsz = sizeof(Phdr64)*ep->phnum;
- ph = malloc(phsz);
- if(!ph)
- return 0;
- seek(fd, ep->phoff, 0);
- if(read(fd, ph, phsz) < 0) {
- free(ph);
- return 0;
- }
- hswal(ph, phsz/sizeof(uint32), swal);
-
- shsz = sizeof(Shdr64)*ep->shnum;
- sh = malloc(shsz);
- if(sh) {
- seek(fd, ep->shoff, 0);
- if(read(fd, sh, shsz) < 0) {
- free(sh);
- sh = 0;
- } else
- hswal(sh, shsz/sizeof(uint32), swal);
- }
-
- /* find text, data and symbols and install them */
- it = id = is = -1;
- for(i = 0; i < ep->phnum; i++) {
- if(ph[i].type == LOAD
- && (ph[i].flags & (R|X)) == (R|X) && it == -1)
- it = i;
- else if(ph[i].type == LOAD
- && (ph[i].flags & (R|W)) == (R|W) && id == -1)
- id = i;
- else if(ph[i].type == NOPTYPE && is == -1)
- is = i;
- }
- if(it == -1 || id == -1) {
- /*
- * The SPARC64 boot image is something of an ELF hack.
- * Text+Data+BSS are represented by ph[0]. Symbols
- * are represented by ph[1]:
- *
- * filesz, memsz, vaddr, paddr, off
- * ph[0] : txtsz+datsz, txtsz+datsz+bsssz, txtaddr-KZERO, datasize, txtoff
- * ph[1] : symsz, lcsz, 0, 0, symoff
- */
- if(ep->machine == SPARC64 && ep->phnum == 2) {
- uint32 txtaddr, txtsz, dataddr, bsssz;
-
- txtaddr = ph[0].vaddr | 0x80000000;
- txtsz = ph[0].filesz - ph[0].paddr;
- dataddr = txtaddr + txtsz;
- bsssz = ph[0].memsz - ph[0].filesz;
- settext(fp, ep->elfentry | 0x80000000, txtaddr, txtsz, ph[0].offset);
- setdata(fp, dataddr, ph[0].paddr, ph[0].offset + txtsz, bsssz);
- setsym(fp, ph[1].offset, ph[1].filesz, 0, 0, 0, ph[1].memsz);
- free(ph);
- return 1;
- }
-
- werrstr("No TEXT or DATA sections");
- free(ph);
- free(sh);
- return 0;
- }
-
- settext(fp, ep->elfentry, ph[it].vaddr, ph[it].memsz, ph[it].offset);
- pph = ph + id;
- setdata(fp, pph->vaddr, pph->filesz, pph->offset, pph->memsz - pph->filesz);
- if(is != -1)
- setsym(fp, ph[is].offset, ph[is].filesz, 0, 0, 0, ph[is].memsz);
- else if(sh != 0){
- char *buf;
- uvlong symsize = 0;
- uvlong symoff = 0;
- uvlong pclnsz = 0;
- uvlong pclnoff = 0;
-
- /* load shstrtab names */
- buf = malloc(sh[ep->shstrndx].size);
- if (buf == 0)
- goto done;
- memset(buf, 0, sh[ep->shstrndx].size);
- seek(fd, sh[ep->shstrndx].offset, 0);
- i = read(fd, buf, sh[ep->shstrndx].size);
- USED(i); // shut up ubuntu gcc
-
- for(i = 0; i < ep->shnum; i++) {
- if (strcmp(&buf[sh[i].name], ".gosymtab") == 0) {
- symsize = sh[i].size;
- symoff = sh[i].offset;
- }
- if (strcmp(&buf[sh[i].name], ".gopclntab") == 0) {
- pclnsz = sh[i].size;
- pclnoff = sh[i].offset;
- }
- }
- setsym(fp, symoff, symsize, 0, 0, pclnoff, pclnsz);
- free(buf);
- }
-done:
- free(ph);
- free(sh);
- return 1;
-}
-
-static int
-elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
-{
-
- uint32 (*swal)(uint32);
- ushort (*swab)(ushort);
- Ehdr32 *ep;
- Phdr32 *ph;
- int i, it, id, is, phsz, shsz;
- Shdr32 *sh;
-
- /* bitswap the header according to the DATA format */
- ep = &hp->e.elfhdr32;
- if(ep->ident[CLASS] != ELFCLASS32) {
- return elf64dotout(fd, fp, hp);
- }
- if(ep->ident[DATA] == ELFDATA2LSB) {
- swab = leswab;
- swal = leswal;
- } else if(ep->ident[DATA] == ELFDATA2MSB) {
- swab = beswab;
- swal = beswal;
- } else {
- werrstr("bad ELF encoding - not big or little endian");
- return 0;
- }
-
- ep->type = swab(ep->type);
- ep->machine = swab(ep->machine);
- ep->version = swal(ep->version);
- ep->elfentry = swal(ep->elfentry);
- ep->phoff = swal(ep->phoff);
- ep->shoff = swal(ep->shoff);
- ep->flags = swal(ep->flags);
- ep->ehsize = swab(ep->ehsize);
- ep->phentsize = swab(ep->phentsize);
- ep->phnum = swab(ep->phnum);
- ep->shentsize = swab(ep->shentsize);
- ep->shnum = swab(ep->shnum);
- ep->shstrndx = swab(ep->shstrndx);
- if(ep->type != EXEC || ep->version != CURRENT)
- return 0;
-
- /* we could definitely support a lot more machines here */
- fp->magic = ELF_MAG;
- fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15;
- switch(ep->machine) {
- case I386:
- mach = &mi386;
- fp->type = FI386;
- break;
- case MIPS:
- mach = &mmips;
- fp->type = FMIPS;
- break;
- case SPARC64:
- mach = &msparc64;
- fp->type = FSPARC64;
- break;
- case POWER:
- mach = &mpower;
- fp->type = FPOWER;
- break;
- case ARM:
- mach = &marm;
- fp->type = FARM;
- break;
- default:
- return 0;
- }
-
- if(ep->phentsize != sizeof(Phdr32)) {
- werrstr("bad ELF header size");
- return 0;
- }
- phsz = sizeof(Phdr32)*ep->phnum;
- ph = malloc(phsz);
- if(!ph)
- return 0;
- seek(fd, ep->phoff, 0);
- if(read(fd, ph, phsz) < 0) {
- free(ph);
- return 0;
- }
- hswal(ph, phsz/sizeof(uint32), swal);
-
- shsz = sizeof(Shdr32)*ep->shnum;
- sh = malloc(shsz);
- if(sh) {
- seek(fd, ep->shoff, 0);
- if(read(fd, sh, shsz) < 0) {
- free(sh);
- sh = 0;
- } else
- hswal(sh, shsz/sizeof(uint32), swal);
- }
-
- /* find text, data and symbols and install them */
- it = id = is = -1;
- for(i = 0; i < ep->phnum; i++) {
- if(ph[i].type == LOAD
- && (ph[i].flags & (R|X)) == (R|X) && it == -1)
- it = i;
- else if(ph[i].type == LOAD
- && (ph[i].flags & (R|W)) == (R|W) && id == -1)
- id = i;
- else if(ph[i].type == NOPTYPE && is == -1)
- is = i;
- }
- if(it == -1 || id == -1) {
- /*
- * The SPARC64 boot image is something of an ELF hack.
- * Text+Data+BSS are represented by ph[0]. Symbols
- * are represented by ph[1]:
- *
- * filesz, memsz, vaddr, paddr, off
- * ph[0] : txtsz+datsz, txtsz+datsz+bsssz, txtaddr-KZERO, datasize, txtoff
- * ph[1] : symsz, lcsz, 0, 0, symoff
- */
- if(ep->machine == SPARC64 && ep->phnum == 2) {
- uint32 txtaddr, txtsz, dataddr, bsssz;
-
- txtaddr = ph[0].vaddr | 0x80000000;
- txtsz = ph[0].filesz - ph[0].paddr;
- dataddr = txtaddr + txtsz;
- bsssz = ph[0].memsz - ph[0].filesz;
- settext(fp, ep->elfentry | 0x80000000, txtaddr, txtsz, ph[0].offset);
- setdata(fp, dataddr, ph[0].paddr, ph[0].offset + txtsz, bsssz);
- setsym(fp, ph[1].offset, ph[1].filesz, 0, 0, 0, ph[1].memsz);
- free(ph);
- return 1;
- }
-
- werrstr("No TEXT or DATA sections");
- free(sh);
- free(ph);
- return 0;
- }
-
- settext(fp, ep->elfentry, ph[it].vaddr, ph[it].memsz, ph[it].offset);
- setdata(fp, ph[id].vaddr, ph[id].filesz, ph[id].offset, ph[id].memsz - ph[id].filesz);
- if(is != -1)
- setsym(fp, ph[is].offset, ph[is].filesz, 0, 0, 0, ph[is].memsz);
- else if(sh != 0){
- char *buf;
- uvlong symsize = 0;
- uvlong symoff = 0;
- uvlong pclnsize = 0;
- uvlong pclnoff = 0;
-
- /* load shstrtab names */
- buf = malloc(sh[ep->shstrndx].size);
- if (buf == 0)
- goto done;
- memset(buf, 0, sh[ep->shstrndx].size);
- seek(fd, sh[ep->shstrndx].offset, 0);
- i = read(fd, buf, sh[ep->shstrndx].size);
- USED(i); // shut up ubuntu gcc
-
- for(i = 0; i < ep->shnum; i++) {
- if (strcmp(&buf[sh[i].name], ".gosymtab") == 0) {
- symsize = sh[i].size;
- symoff = sh[i].offset;
- }
- if (strcmp(&buf[sh[i].name], ".gopclntab") == 0) {
- pclnsize = sh[i].size;
- pclnoff = sh[i].offset;
- }
- }
- setsym(fp, symoff, symsize, 0, 0, pclnoff, pclnsize);
- free(buf);
- }
-done:
- free(sh);
- free(ph);
- return 1;
-}
-
-static int
-machdotout(int fd, Fhdr *fp, ExecHdr *hp)
-{
- uvlong (*swav)(uvlong);
- uint32 (*swal)(uint32);
- Machhdr *mp;
- MachCmd **cmd;
- MachSymSeg *symtab;
- MachSymSeg *pclntab;
- MachSeg64 *seg;
- MachSect64 *sect;
- MachSeg32 *seg32;
- MachSect32 *sect32;
- uvlong textsize, datasize, bsssize;
- uchar *cmdbuf;
- uchar *cmdp;
- int i, j, hdrsize;
- uint32 textva, textoff, datava, dataoff, symoff, symsize, pclnoff, pclnsize;
-
- mp = &hp->e.machhdr;
- if (leswal(mp->filetype) != MACH_EXECUTABLE_TYPE) {
- werrstr("bad MACH executable type %#ux", leswal(mp->filetype));
- return 0;
- }
-
- swal = leswal;
- swav = leswav;
-
- mp->magic = swal(mp->magic);
- mp->cputype = swal(mp->cputype);
- mp->cpusubtype = swal(mp->cpusubtype);
- mp->filetype = swal(mp->filetype);
- mp->ncmds = swal(mp->ncmds);
- mp->sizeofcmds = swal(mp->sizeofcmds);
- mp->flags = swal(mp->flags);
- mp->reserved = swal(mp->reserved);
-
- switch(mp->magic) {
- case 0xFEEDFACE: // 32-bit mach
- if (mp->cputype != MACH_CPU_TYPE_X86) {
- werrstr("bad MACH cpu type - not 386");
- return 0;
- }
- if (mp->cpusubtype != MACH_CPU_SUBTYPE_X86) {
- werrstr("bad MACH cpu subtype - not 386");
- return 0;
- }
- if (mp->filetype != MACH_EXECUTABLE_TYPE) {
- werrstr("bad MACH executable type");
- return 0;
- }
- mach = &mi386;
- fp->type = FI386;
- hdrsize = 28;
- break;
-
- case 0xFEEDFACF: // 64-bit mach
- if (mp->cputype != MACH_CPU_TYPE_X86_64) {
- werrstr("bad MACH cpu type - not amd64");
- return 0;
- }
-
- if (mp->cpusubtype != MACH_CPU_SUBTYPE_X86 && mp->cpusubtype != MACH_CPU_SUBTYPE_X86_64) {
- werrstr("bad MACH cpu subtype - not amd64");
- return 0;
- }
- mach = &mamd64;
- fp->type = FAMD64;
- hdrsize = 32;
- break;
-
- default:
- werrstr("not mach %#ux", mp->magic);
- return 0;
- }
-
- cmdbuf = malloc(mp->sizeofcmds);
- if(!cmdbuf) {
- werrstr("out of memory");
- return 0;
- }
- seek(fd, hdrsize, 0);
- if(read(fd, cmdbuf, mp->sizeofcmds) != mp->sizeofcmds) {
- free(cmdbuf);
- return 0;
- }
- cmd = malloc(mp->ncmds * sizeof(MachCmd*));
- if(!cmd) {
- free(cmdbuf);
- werrstr("out of memory");
- return 0;
- }
- cmdp = cmdbuf;
- textva = 0;
- textoff = 0;
- dataoff = 0;
- datava = 0;
- symtab = 0;
- pclntab = 0;
- textsize = 0;
- datasize = 0;
- bsssize = 0;
- symoff = 0;
- symsize = 0;
- pclnoff = 0;
- pclnsize = 0;
- for (i = 0; i < mp->ncmds; i++) {
- MachCmd *c;
-
- cmd[i] = (MachCmd*)cmdp;
- c = cmd[i];
- c->type = swal(c->type);
- c->size = swal(c->size);
- switch(c->type) {
- case MACH_SEGMENT_32:
- if(mp->magic != 0xFEEDFACE) {
- werrstr("segment 32 in mach 64");
- goto bad;
- }
- seg32 = (MachSeg32*)c;
- seg32->vmaddr = swav(seg32->vmaddr);
- seg32->vmsize = swav(seg32->vmsize);
- seg32->fileoff = swav(seg32->fileoff);
- seg32->filesize = swav(seg32->filesize);
- seg32->maxprot = swal(seg32->maxprot);
- seg32->initprot = swal(seg32->initprot);
- seg32->nsects = swal(seg32->nsects);
- seg32->flags = swal(seg32->flags);
- if (strcmp(seg32->segname, "__TEXT") == 0) {
- textva = seg32->vmaddr;
- textoff = seg32->fileoff;
- textsize = seg32->vmsize;
- sect32 = (MachSect32*)(cmdp + sizeof(MachSeg32));
- for(j = 0; j < seg32->nsects; j++, sect32++) {
- if (strcmp(sect32->sectname, "__gosymtab") == 0) {
- symoff = swal(sect32->offset);
- symsize = swal(sect32->size);
- }
- if (strcmp(sect32->sectname, "__gopclntab") == 0) {
- pclnoff = swal(sect32->offset);
- pclnsize = swal(sect32->size);
- }
- }
- }
- if (strcmp(seg32->segname, "__DATA") == 0) {
- datava = seg32->vmaddr;
- dataoff = seg32->fileoff;
- datasize = seg32->filesize;
- bsssize = seg32->vmsize - seg32->filesize;
- }
- break;
-
- case MACH_SEGMENT_64:
- if(mp->magic != 0xFEEDFACF) {
- werrstr("segment 32 in mach 64");
- goto bad;
- }
- seg = (MachSeg64*)c;
- seg->vmaddr = swav(seg->vmaddr);
- seg->vmsize = swav(seg->vmsize);
- seg->fileoff = swav(seg->fileoff);
- seg->filesize = swav(seg->filesize);
- seg->maxprot = swal(seg->maxprot);
- seg->initprot = swal(seg->initprot);
- seg->nsects = swal(seg->nsects);
- seg->flags = swal(seg->flags);
- if (strcmp(seg->segname, "__TEXT") == 0) {
- textva = seg->vmaddr;
- textoff = seg->fileoff;
- textsize = seg->vmsize;
- sect = (MachSect64*)(cmdp + sizeof(MachSeg64));
- for(j = 0; j < seg->nsects; j++, sect++) {
- if (strcmp(sect->sectname, "__gosymtab") == 0) {
- symoff = swal(sect->offset);
- symsize = swal(sect->size);
- }
- if (strcmp(sect->sectname, "__gopclntab") == 0) {
- pclnoff = swal(sect->offset);
- pclnsize = swal(sect->size);
- }
- }
- }
- if (strcmp(seg->segname, "__DATA") == 0) {
- datava = seg->vmaddr;
- dataoff = seg->fileoff;
- datasize = seg->filesize;
- bsssize = seg->vmsize - seg->filesize;
- }
- break;
- case MACH_UNIXTHREAD:
- break;
- case MACH_SYMSEG:
- if (symtab == 0) {
- symtab = (MachSymSeg*)c;
- symoff = swal(symtab->fileoff);
- symsize = swal(symtab->filesize);
- } else if (pclntab == 0) {
- pclntab = (MachSymSeg*)c;
- pclnoff = swal(pclntab->fileoff);
- pclnsize = swal(pclntab->filesize);
- }
- break;
- }
- cmdp += c->size;
- }
- if (textva == 0 || datava == 0) {
- free(cmd);
- free(cmdbuf);
- return 0;
- }
- /* compute entry by taking address after header - weird - BUG? */
- settext(fp, textva+sizeof(Machhdr) + mp->sizeofcmds, textva, textsize, textoff);
- setdata(fp, datava, datasize, dataoff, bsssize);
- if(symoff > 0)
- setsym(fp, symoff, symsize, 0, 0, pclnoff, pclnsize);
- free(cmd);
- free(cmdbuf);
- return 1;
-bad:
- free(cmd);
- free(cmdbuf);
- return 0;
-}
-
-/*
- * (Free|Net)BSD ARM header.
- */
-static int
-armdotout(int fd, Fhdr *fp, ExecHdr *hp)
-{
- uvlong kbase;
-
- USED(fd);
- settext(fp, hp->e.exechdr.entry, sizeof(Exec), hp->e.exechdr.text, sizeof(Exec));
- setdata(fp, fp->txtsz, hp->e.exechdr.data, fp->txtsz, hp->e.exechdr.bss);
- setsym(fp, fp->datoff+fp->datsz, hp->e.exechdr.syms, 0, hp->e.exechdr.spsz, 0, hp->e.exechdr.pcsz);
-
- kbase = 0xF0000000;
- if ((fp->entry & kbase) == kbase) { /* Boot image */
- fp->txtaddr = kbase+sizeof(Exec);
- fp->name = "ARM *BSD boot image";
- fp->hdrsz = 0; /* header stripped */
- fp->dataddr = kbase+fp->txtsz;
- }
- return 1;
-}
-
-/*
- * Structures needed to parse PE image.
- */
-typedef struct {
- uint16 Machine;
- uint16 NumberOfSections;
- uint32 TimeDateStamp;
- uint32 PointerToSymbolTable;
- uint32 NumberOfSymbols;
- uint16 SizeOfOptionalHeader;
- uint16 Characteristics;
-} IMAGE_FILE_HEADER;
-
-typedef struct {
- uint8 Name[8];
- uint32 VirtualSize;
- uint32 VirtualAddress;
- uint32 SizeOfRawData;
- uint32 PointerToRawData;
- uint32 PointerToRelocations;
- uint32 PointerToLineNumbers;
- uint16 NumberOfRelocations;
- uint16 NumberOfLineNumbers;
- uint32 Characteristics;
-} IMAGE_SECTION_HEADER;
-
-typedef struct {
- uint32 VirtualAddress;
- uint32 Size;
-} IMAGE_DATA_DIRECTORY;
-
-typedef struct {
- uint16 Magic;
- uint8 MajorLinkerVersion;
- uint8 MinorLinkerVersion;
- uint32 SizeOfCode;
- uint32 SizeOfInitializedData;
- uint32 SizeOfUninitializedData;
- uint32 AddressOfEntryPoint;
- uint32 BaseOfCode;
- uint32 BaseOfData;
- uint32 ImageBase;
- uint32 SectionAlignment;
- uint32 FileAlignment;
- uint16 MajorOperatingSystemVersion;
- uint16 MinorOperatingSystemVersion;
- uint16 MajorImageVersion;
- uint16 MinorImageVersion;
- uint16 MajorSubsystemVersion;
- uint16 MinorSubsystemVersion;
- uint32 Win32VersionValue;
- uint32 SizeOfImage;
- uint32 SizeOfHeaders;
- uint32 CheckSum;
- uint16 Subsystem;
- uint16 DllCharacteristics;
- uint32 SizeOfStackReserve;
- uint32 SizeOfStackCommit;
- uint32 SizeOfHeapReserve;
- uint32 SizeOfHeapCommit;
- uint32 LoaderFlags;
- uint32 NumberOfRvaAndSizes;
- IMAGE_DATA_DIRECTORY DataDirectory[16];
-} IMAGE_OPTIONAL_HEADER;
-
-typedef struct {
- uint16 Magic;
- uint8 MajorLinkerVersion;
- uint8 MinorLinkerVersion;
- uint32 SizeOfCode;
- uint32 SizeOfInitializedData;
- uint32 SizeOfUninitializedData;
- uint32 AddressOfEntryPoint;
- uint32 BaseOfCode;
- uint64 ImageBase;
- uint32 SectionAlignment;
- uint32 FileAlignment;
- uint16 MajorOperatingSystemVersion;
- uint16 MinorOperatingSystemVersion;
- uint16 MajorImageVersion;
- uint16 MinorImageVersion;
- uint16 MajorSubsystemVersion;
- uint16 MinorSubsystemVersion;
- uint32 Win32VersionValue;
- uint32 SizeOfImage;
- uint32 SizeOfHeaders;
- uint32 CheckSum;
- uint16 Subsystem;
- uint16 DllCharacteristics;
- uint64 SizeOfStackReserve;
- uint64 SizeOfStackCommit;
- uint64 SizeOfHeapReserve;
- uint64 SizeOfHeapCommit;
- uint32 LoaderFlags;
- uint32 NumberOfRvaAndSizes;
- IMAGE_DATA_DIRECTORY DataDirectory[16];
-} PE64_IMAGE_OPTIONAL_HEADER;
-
-static int
-match8(void *buf, char *cmp)
-{
- return strncmp((char*)buf, cmp, 8) == 0;
-}
-
-/*
- * Read from Windows PE/COFF .exe file image.
- */
-static int
-pedotout(int fd, Fhdr *fp, ExecHdr *hp)
-{
- uint32 start, magic;
- uint32 symtab, esymtab, pclntab, epclntab;
- IMAGE_FILE_HEADER fh;
- IMAGE_SECTION_HEADER sh;
- IMAGE_OPTIONAL_HEADER oh;
- PE64_IMAGE_OPTIONAL_HEADER oh64;
- uint8 sym[18];
- uint32 *valp, ib, entry;
- int i, ohoffset;
-
- USED(hp);
- seek(fd, 0x3c, 0);
- if (readn(fd, &start, sizeof(start)) != sizeof(start)) {
- werrstr("crippled PE MSDOS header");
- return 0;
- }
- start = leswal(start);
-
- seek(fd, start, 0);
- if (readn(fd, &magic, sizeof(magic)) != sizeof(magic)) {
- werrstr("no PE magic number found");
- return 0;
- }
- if (beswal(magic) != 0x50450000) { /* "PE\0\0" */
- werrstr("incorrect PE magic number");
- return 0;
- }
-
- if (readn(fd, &fh, sizeof(fh)) != sizeof(fh)) {
- werrstr("crippled PE File Header");
- return 0;
- }
- if (fh.PointerToSymbolTable == 0) {
- werrstr("zero pointer to COFF symbol table");
- return 0;
- }
-
- ohoffset = seek(fd, 0, 1);
- if (readn(fd, &oh, sizeof(oh)) != sizeof(oh)) {
- werrstr("crippled PE Optional Header");
- return 0;
- }
-
- switch(oh.Magic) {
- case 0x10b: // PE32
- fp->type = FI386;
- ib = leswal(oh.ImageBase);
- entry = leswal(oh.AddressOfEntryPoint);
- break;
- case 0x20b: // PE32+
- fp->type = FAMD64;
- seek(fd, ohoffset, 0);
- if (readn(fd, &oh64, sizeof(oh64)) != sizeof(oh64)) {
- werrstr("crippled PE32+ Optional Header");
- return 0;
- }
- ib = leswal(oh64.ImageBase);
- entry = leswal(oh64.AddressOfEntryPoint);
- break;
- default:
- werrstr("invalid PE Optional Header magic number");
- return 0;
- }
-
- fp->txtaddr = 0;
- fp->dataddr = 0;
- for (i=0; i<leswab(fh.NumberOfSections); i++) {
- if (readn(fd, &sh, sizeof(sh)) != sizeof(sh)) {
- werrstr("could not read Section Header %d", i+1);
- return 0;
- }
- if (match8(sh.Name, ".text"))
- settext(fp, ib+entry, ib+leswal(sh.VirtualAddress), leswal(sh.VirtualSize), leswal(sh.PointerToRawData));
- if (match8(sh.Name, ".data"))
- setdata(fp, ib+leswal(sh.VirtualAddress), leswal(sh.SizeOfRawData), leswal(sh.PointerToRawData), leswal(sh.VirtualSize)-leswal(sh.SizeOfRawData));
- }
- if (fp->txtaddr==0 || fp->dataddr==0) {
- werrstr("no .text or .data");
- return 0;
- }
-
- seek(fd, leswal(fh.PointerToSymbolTable), 0);
- symtab = esymtab = pclntab = epclntab = 0;
- for (i=0; i<leswal(fh.NumberOfSymbols); i++) {
- if (readn(fd, sym, sizeof(sym)) != sizeof(sym)) {
- werrstr("crippled COFF symbol %d", i);
- return 0;
- }
- valp = (uint32 *)&sym[8];
- if (match8(sym, "symtab"))
- symtab = leswal(*valp);
- if (match8(sym, "esymtab"))
- esymtab = leswal(*valp);
- if (match8(sym, "pclntab"))
- pclntab = leswal(*valp);
- if (match8(sym, "epclntab"))
- epclntab = leswal(*valp);
- }
- if (symtab==0 || esymtab==0 || pclntab==0 || epclntab==0) {
- werrstr("no symtab or esymtab or pclntab or epclntab in COFF symbol table");
- return 0;
- }
- setsym(fp, symtab, esymtab-symtab, 0, 0, pclntab, epclntab-pclntab);
-
- return 1;
-}
-
-static void
-settext(Fhdr *fp, uvlong e, uvlong a, int32 s, vlong off)
-{
- fp->txtaddr = a;
- fp->entry = e;
- fp->txtsz = s;
- fp->txtoff = off;
-}
-
-static void
-setdata(Fhdr *fp, uvlong a, int32 s, vlong off, int32 bss)
-{
- fp->dataddr = a;
- fp->datsz = s;
- fp->datoff = off;
- fp->bsssz = bss;
-}
-
-static void
-setsym(Fhdr *fp, vlong symoff, int32 symsz, vlong sppcoff, int32 sppcsz, vlong lnpcoff, int32 lnpcsz)
-{
- fp->symoff = symoff;
- fp->symsz = symsz;
-
- if(sppcoff == 0)
- sppcoff = symoff+symsz;
- fp->sppcoff = symoff;
- fp->sppcsz = sppcsz;
-
- if(lnpcoff == 0)
- lnpcoff = sppcoff + sppcsz;
- fp->lnpcoff = lnpcoff;
- fp->lnpcsz = lnpcsz;
-}
-
-static uvlong
-_round(uvlong a, uint32 b)
-{
- uvlong w;
-
- w = (a/b)*b;
- if (a!=w)
- w += b;
- return(w);
-}
diff --git a/src/libmach/fakeobj.c b/src/libmach/fakeobj.c
deleted file mode 100644
index a4a897cfe..000000000
--- a/src/libmach/fakeobj.c
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- * obj.c
- * routines universal to all object files
- */
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <ar.h>
-#include <mach.h>
-#include "obj.h"
-
-int _is2(char* x) { USED(x); return 0; }
-int _is7(char* x) { USED(x); return 0; }
-int _is9(char* x) { USED(x); return 0; }
-int _isk(char* x) { USED(x); return 0; }
-int _isq(char* x) { USED(x); return 0; }
-int _isv(char* x) { USED(x); return 0; }
-int _isu(char* x) { USED(x); return 0; }
-int _read2(Biobuf* b, Prog* p) { USED(b); USED(p); return 0; }
-int _read7(Biobuf* b, Prog* p) { USED(b); USED(p); return 0; }
-int _read9(Biobuf* b, Prog* p) { USED(b); USED(p); return 0; }
-int _readk(Biobuf* b, Prog* p) { USED(b); USED(p); return 0; }
-int _readq(Biobuf* b, Prog* p) { USED(b); USED(p); return 0; }
-int _readv(Biobuf* b, Prog* p) { USED(b); USED(p); return 0; }
-int _readu(Biobuf* b, Prog* p) { USED(b); USED(p); return 0; }
diff --git a/src/libmach/freebsd.c b/src/libmach/freebsd.c
deleted file mode 100644
index c4e5efddf..000000000
--- a/src/libmach/freebsd.c
+++ /dev/null
@@ -1,62 +0,0 @@
-// This is stubbed out for the moment. Will revisit when the time comes.
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-
-int
-ctlproc(int pid, char *msg)
-{
- USED(pid);
- USED(msg);
-
- sysfatal("ctlproc unimplemented in FreeBSD");
- return -1;
-}
-
-char*
-proctextfile(int pid)
-{
- USED(pid);
-
- sysfatal("proctextfile unimplemented in FreeBSD");
- return nil;
-}
-
-char*
-procstatus(int pid)
-{
- USED(pid);
-
- sysfatal("procstatus unimplemented in FreeBSD");
- return nil;
-}
-
-Map*
-attachproc(int pid, Fhdr *fp)
-{
- USED(pid);
- USED(fp);
-
- sysfatal("attachproc unimplemented in FreeBSD");
- return nil;
-}
-
-void
-detachproc(Map *m)
-{
- USED(m);
-
- sysfatal("detachproc unimplemented in FreeBSD");
-}
-
-int
-procthreadpids(int pid, int *p, int np)
-{
- USED(pid);
- USED(p);
- USED(np);
-
- sysfatal("procthreadpids unimplemented in FreeBSD");
- return -1;
-}
diff --git a/src/libmach/linux.c b/src/libmach/linux.c
deleted file mode 100644
index 2c143266a..000000000
--- a/src/libmach/linux.c
+++ /dev/null
@@ -1,1014 +0,0 @@
-// Derived from Plan 9 from User Space src/libmach/Linux.c
-// http://code.swtch.com/plan9port/src/tip/src/libmach/Linux.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc.
-// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
-// Portions Copyright © 1997-1999 Vita Nuova Limited.
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
-// Portions Copyright © 2001-2007 Russ Cox.
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include <sys/syscall.h> /* for tkill */
-#include <unistd.h>
-#include <dirent.h>
-#include <sys/ptrace.h>
-#include <sys/signal.h>
-#include <sys/wait.h>
-#include <errno.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-#define Ureg Ureg32
-#include <ureg_x86.h>
-#undef Ureg
-#define Ureg Ureg64
-#include <ureg_amd64.h>
-#undef Ureg
-#undef waitpid
-
-// The old glibc used with crosstool compilers on thresher
-// doesn't know these numbers, but the Linux kernel
-// had them as far back as 2.6.0.
-#ifndef WSTOPPED
-#define WSTOPPED 2
-#define WCONTINUED 8
-#define WIFCONTINUED(x) ((x) == 0xffff)
-#endif
-#ifndef PTRACE_SETOPTIONS
-#define PTRACE_SETOPTIONS 0x4200
-#define PTRACE_GETEVENTMSG 0x4201
-#define PTRACE_O_TRACEFORK 0x2
-#define PTRACE_O_TRACEVFORK 0x4
-#define PTRACE_O_TRACECLONE 0x8
-#define PTRACE_O_TRACEEXEC 0x10
-#define PTRACE_O_TRACEVFORKDONE 0x20
-#define PTRACE_O_TRACEEXIT 0x40
-#define PTRACE_EVENT_FORK 0x1
-#define PTRACE_EVENT_VFORK 0x2
-#define PTRACE_EVENT_CLONE 0x3
-#define PTRACE_EVENT_EXEC 0x4
-#define PTRACE_EVENT_VFORK_DONE 0x5
-#define PTRACE_EVENT_EXIT 0x6
-#endif
-
-typedef struct Ureg64 Ureg64;
-
-static Maprw ptracesegrw;
-static Maprw ptraceregrw;
-
-// /usr/include/asm-x86_64/user.h
-struct user_regs_struct {
- unsigned long r15,r14,r13,r12,rbp,rbx,r11,r10;
- unsigned long r9,r8,rax,rcx,rdx,rsi,rdi,orig_rax;
- unsigned long rip,cs,eflags;
- unsigned long rsp,ss;
- unsigned long fs_base, gs_base;
- unsigned long ds,es,fs,gs;
-};
-
-// Linux gets very upset if a debugger forgets the reported state
-// of a debugged process, so we keep everything we know about
-// a debugged process in the LinuxThread structure.
-//
-// We can poll for state changes by calling waitpid and interpreting
-// the integer status code that comes back. Wait1 does this.
-//
-// If the process is already running, it is an error to PTRACE_CONT it.
-//
-// If the process is already stopped, it is an error to stop it again.
-//
-// If the process is stopped because of a signal, the debugger must
-// relay the signal to the PTRACE_CONT call, or else the signal is
-// dropped.
-//
-// If the process exits, the debugger should detach so that the real
-// parent can reap the zombie.
-//
-// On first attach, the debugger should set a handful of flags in order
-// to catch future events like fork, clone, exec, etc.
-
-// One for every attached thread.
-typedef struct LinuxThread LinuxThread;
-struct LinuxThread
-{
- int pid;
- int tid;
- int state;
- int signal;
- int child;
- int exitcode;
-};
-
-static int trace = 0;
-
-static LinuxThread **thr;
-static int nthr;
-static int mthr;
-
-static int realpid(int pid);
-
-enum
-{
- Unknown,
- Detached,
- Attached,
- AttachStop,
- Stopped,
- Running,
- Forking,
- Vforking,
- VforkDone,
- Cloning,
- Execing,
- Exiting,
- Exited,
- Killed,
-
- NSTATE,
-};
-
-static char* statestr[NSTATE] = {
- "Unknown",
- "Detached",
- "Attached",
- "AttachStop",
- "Stopped",
- "Running",
- "Forking",
- "Vforking",
- "VforkDone",
- "Cloning",
- "Execing",
- "Exiting",
- "Exited",
- "Killed"
-};
-
-static LinuxThread*
-attachthread(int pid, int tid, int *new, int newstate)
-{
- int i, n, status;
- LinuxThread **p, *t;
- uintptr flags;
-
- if(new)
- *new = 0;
-
- for(i=0; i<nthr; i++)
- if((pid == 0 || thr[i]->pid == pid) && thr[i]->tid == tid) {
- t = thr[i];
- goto fixup;
- }
-
- if(!new)
- return nil;
-
- if(nthr >= mthr) {
- n = mthr;
- if(n == 0)
- n = 64;
- else
- n *= 2;
- p = realloc(thr, n*sizeof thr[0]);
- if(p == nil)
- return nil;
- thr = p;
- mthr = n;
- }
-
- t = malloc(sizeof *t);
- if(t == nil)
- return nil;
- memset(t, 0, sizeof *t);
-
- thr[nthr++] = t;
- if(pid == 0 && nthr > 0)
- pid = thr[0]->pid;
- t->pid = pid;
- t->tid = tid;
- t->state = newstate;
- if(trace)
- fprint(2, "new thread %d %d\n", t->pid, t->tid);
- if(new)
- *new = 1;
-
-fixup:
- if(t->state == Detached) {
- if(ptrace(PTRACE_ATTACH, tid, 0, 0) < 0) {
- fprint(2, "ptrace ATTACH %d: %r\n", tid);
- return nil;
- }
- t->state = Attached;
- }
-
- if(t->state == Attached) {
- // wait for stop, so we can set options
- if(waitpid(tid, &status, __WALL|WUNTRACED|WSTOPPED) < 0)
- return nil;
- if(!WIFSTOPPED(status)) {
- fprint(2, "waitpid %d: status=%#x not stopped\n", tid);
- return nil;
- }
- t->state = AttachStop;
- }
-
- if(t->state == AttachStop) {
- // set options so we'll find out about new threads
- flags = PTRACE_O_TRACEFORK |
- PTRACE_O_TRACEVFORK |
- PTRACE_O_TRACECLONE |
- PTRACE_O_TRACEEXEC |
- PTRACE_O_TRACEVFORKDONE;
- if(ptrace(PTRACE_SETOPTIONS, tid, 0, (void*)flags) < 0) {
- fprint(2, "ptrace PTRACE_SETOPTIONS %d: %r\n", tid);
- return nil;
- }
- t->state = Stopped;
- }
-
- return t;
-}
-
-static LinuxThread*
-findthread(int tid)
-{
- return attachthread(0, tid, nil, 0);
-}
-
-int
-procthreadpids(int pid, int *p, int np)
-{
- int i, n;
- LinuxThread *t;
-
- n = 0;
- for(i=0; i<nthr; i++) {
- t = thr[i];
- if(t->pid == pid) {
- switch(t->state) {
- case Exited:
- case Detached:
- case Killed:
- break;
-
- default:
- if(n < np)
- p[n] = t->tid;
- n++;
- break;
- }
- }
- }
- return n;
-}
-
-// Execute a single wait and update the corresponding thread.
-static int
-wait1(int nohang)
-{
- int tid, new, status, event;
- ulong data;
- LinuxThread *t;
- enum
- {
- NormalStop = 0x137f
- };
-
- if(nohang != 0)
- nohang = WNOHANG;
-
- status = 0;
- tid = waitpid(-1, &status, __WALL|WUNTRACED|WSTOPPED|WCONTINUED|nohang);
-
- if(tid < 0)
- return -1;
- if(tid == 0)
- return 0;
-
- if(trace > 0 && status != NormalStop)
- fprint(2, "TID %d: %#x\n", tid, status);
-
- t = findthread(tid);
- if(t == nil) {
- // Sometimes the kernel tells us about new threads
- // before we see the parent clone.
- t = attachthread(0, tid, &new, Stopped);
- if(t == nil) {
- fprint(2, "failed to attach to new thread %d\n", tid);
- return -1;
- }
- }
-
- if(WIFSTOPPED(status)) {
- t->state = Stopped;
- t->signal = WSTOPSIG(status);
- if(trace)
- fprint(2, "tid %d: stopped %#x%s\n", tid, status,
- status != NormalStop ? " ***" : "");
- if(t->signal == SIGTRAP && (event = status>>16) != 0) { // ptrace event
- switch(event) {
- case PTRACE_EVENT_FORK:
- t->state = Forking;
- goto child;
-
- case PTRACE_EVENT_VFORK:
- t->state = Vforking;
- goto child;
-
- case PTRACE_EVENT_CLONE:
- t->state = Cloning;
- goto child;
-
- child:
- if(ptrace(PTRACE_GETEVENTMSG, t->tid, 0, &data) < 0) {
- fprint(2, "ptrace GETEVENTMSG tid %d: %r\n", tid);
- break;
- }
- t->child = data;
- attachthread(t->pid, t->child, &new, Running);
- break;
-
- case PTRACE_EVENT_EXEC:
- t->state = Execing;
- break;
-
- case PTRACE_EVENT_VFORK_DONE:
- t->state = VforkDone;
- break;
-
- case PTRACE_EVENT_EXIT:
- // We won't see this unless we set PTRACE_O_TRACEEXIT.
- // The debuggers assume that a read or write on a Map
- // will fail for a thread that has exited. This event
- // breaks that assumption. It's not a big deal: we
- // only lose the ability to see the register state at
- // the time of exit.
- if(trace)
- fprint(2, "tid %d: exiting %#x\n", tid, status);
- t->state = Exiting;
- if(ptrace(PTRACE_GETEVENTMSG, t->tid, 0, &data) < 0) {
- fprint(2, "ptrace GETEVENTMSG tid %d: %r\n", tid);
- break;
- }
- t->exitcode = data;
- break;
- }
- }
- }
- if(WIFCONTINUED(status)) {
- if(trace)
- fprint(2, "tid %d: continued %#x\n", tid, status);
- t->state = Running;
- }
- if(WIFEXITED(status)) {
- if(trace)
- fprint(2, "tid %d: exited %#x\n", tid, status);
- t->state = Exited;
- t->exitcode = WEXITSTATUS(status);
- t->signal = -1;
- ptrace(PTRACE_DETACH, t->tid, 0, 0);
- if(trace)
- fprint(2, "tid %d: detach exited\n", tid);
- }
- if(WIFSIGNALED(status)) {
- if(trace)
- fprint(2, "tid %d: signaled %#x\n", tid, status);
- t->state = Exited;
- t->signal = WTERMSIG(status);
- t->exitcode = -1;
- ptrace(PTRACE_DETACH, t->tid, 0, 0);
- if(trace)
- fprint(2, "tid %d: detach signaled\n", tid);
- }
- return 1;
-}
-
-static int
-waitstop(LinuxThread *t)
-{
- while(t->state == Running)
- if(wait1(0) < 0)
- return -1;
- return 0;
-}
-
-// Attach to and stop all threads in process pid.
-// Must stop everyone in order to make sure we set
-// the "tell me about new threads" option in every
-// task.
-int
-attachallthreads(int pid)
-{
- int tid, foundnew, new;
- char buf[100];
- DIR *d;
- struct dirent *de;
- LinuxThread *t;
-
- if(pid == 0) {
- fprint(2, "attachallthreads(0)\n");
- return -1;
- }
-
- pid = realpid(pid);
-
- snprint(buf, sizeof buf, "/proc/%d/task", pid);
- if((d = opendir(buf)) == nil) {
- fprint(2, "opendir %s: %r\n", buf);
- return -1;
- }
-
- // Loop in case new threads are being created right now.
- // We stop every thread as we find it, so eventually
- // this has to stop (or the system runs out of procs).
- do {
- foundnew = 0;
- while((de = readdir(d)) != nil) {
- tid = atoi(de->d_name);
- if(tid == 0)
- continue;
- t = attachthread(pid, tid, &new, Detached);
- foundnew |= new;
- if(t)
- waitstop(t);
- }
- rewinddir(d);
- } while(foundnew);
- closedir(d);
-
- return 0;
-}
-
-Map*
-attachproc(int pid, Fhdr *fp)
-{
- Map *map;
-
- if(pid == 0) {
- fprint(2, "attachproc(0)\n");
- return nil;
- }
-
- if(findthread(pid) == nil && attachallthreads(pid) < 0)
- return nil;
-
- map = newmap(0, 4);
- if (!map)
- return 0;
- map->pid = pid;
- if(mach->regsize)
- setmap(map, -1, 0, mach->regsize, 0, "regs", ptraceregrw);
-// if(mach->fpregsize)
-// setmap(map, -1, mach->regsize, mach->regsize+mach->fpregsize, 0, "fpregs", ptraceregrw);
- setmap(map, -1, fp->txtaddr, fp->txtaddr+fp->txtsz, fp->txtaddr, "*text", ptracesegrw);
- setmap(map, -1, fp->dataddr, mach->utop, fp->dataddr, "*data", ptracesegrw);
- return map;
-}
-
-void
-detachproc(Map *m)
-{
- LinuxThread *t;
-
- t = findthread(m->pid);
- if(t != nil) {
- ptrace(PTRACE_DETACH, t->tid, 0, 0);
- t->state = Detached;
- if(trace)
- fprint(2, "tid %d: detachproc\n", t->tid);
- // TODO(rsc): Reclaim thread structs somehow?
- }
- free(m);
-}
-
-/* /proc/pid/stat contains
- pid
- command in parens
- 0. state
- 1. ppid
- 2. pgrp
- 3. session
- 4. tty_nr
- 5. tpgid
- 6. flags (math=4, traced=10)
- 7. minflt
- 8. cminflt
- 9. majflt
- 10. cmajflt
- 11. utime
- 12. stime
- 13. cutime
- 14. cstime
- 15. priority
- 16. nice
- 17. 0
- 18. itrealvalue
- 19. starttime
- 20. vsize
- 21. rss
- 22. rlim
- 23. startcode
- 24. endcode
- 25. startstack
- 26. kstkesp
- 27. kstkeip
- 28. pending signal bitmap
- 29. blocked signal bitmap
- 30. ignored signal bitmap
- 31. caught signal bitmap
- 32. wchan
- 33. nswap
- 34. cnswap
- 35. exit_signal
- 36. processor
-*/
-
-static int
-readstat(int pid, char *buf, int nbuf, char **f, int nf)
-{
- int fd, n;
- char *p;
-
- snprint(buf, nbuf, "/proc/%d/stat", pid);
- if((fd = open(buf, OREAD)) < 0){
- fprint(2, "open %s: %r\n", buf);
- return -1;
- }
- n = read(fd, buf, nbuf-1);
- close(fd);
- if(n <= 0){
- fprint(2, "read %s: %r\n", buf);
- return -1;
- }
- buf[n] = 0;
-
- /* command name is in parens, no parens afterward */
- p = strrchr(buf, ')');
- if(p == nil || *++p != ' '){
- fprint(2, "bad format in /proc/%d/stat\n", pid);
- return -1;
- }
- ++p;
-
- nf = tokenize(p, f, nf);
- if(0) print("code 0x%lux-0x%lux stack 0x%lux kstk 0x%lux keip 0x%lux pending 0x%lux\n",
- strtoul(f[23], 0, 0), strtoul(f[24], 0, 0), strtoul(f[25], 0, 0),
- strtoul(f[26], 0, 0), strtoul(f[27], 0, 0), strtoul(f[28], 0, 0));
-
- return nf;
-}
-
-static char*
-readstatus(int pid, char *buf, int nbuf, char *key)
-{
- int fd, n;
- char *p;
-
- snprint(buf, nbuf, "/proc/%d/status", pid);
- if((fd = open(buf, OREAD)) < 0){
- fprint(2, "open %s: %r\n", buf);
- return nil;
- }
- n = read(fd, buf, nbuf-1);
- close(fd);
- if(n <= 0){
- fprint(2, "read %s: %r\n", buf);
- return nil;
- }
- buf[n] = 0;
- p = strstr(buf, key);
- if(p)
- return p+strlen(key);
- return nil;
-}
-
-int
-procnotes(int pid, char ***pnotes)
-{
- char buf[1024], *f[40];
- int i, n, nf;
- char *s, **notes;
- ulong sigs;
- extern char *_p9sigstr(int, char*);
-
- *pnotes = nil;
- nf = readstat(pid, buf, sizeof buf, f, nelem(f));
- if(nf <= 28)
- return -1;
-
- sigs = strtoul(f[28], 0, 0) & ~(1<<SIGCONT);
- if(sigs == 0){
- *pnotes = nil;
- return 0;
- }
-
- notes = malloc(32*sizeof(char*));
- if(notes == nil)
- return -1;
- memset(notes, 0, 32*sizeof(char*));
- n = 0;
- for(i=0; i<32; i++){
- if((sigs&(1<<i)) == 0)
- continue;
- if((s = _p9sigstr(i, nil)) == nil)
- continue;
- notes[n++] = s;
- }
- *pnotes = notes;
- return n;
-}
-
-static int
-realpid(int pid)
-{
- char buf[1024], *p;
-
- p = readstatus(pid, buf, sizeof buf, "\nTgid:");
- if(p == nil)
- return pid;
- return atoi(p);
-}
-
-int
-ctlproc(int pid, char *msg)
-{
- int new;
- LinuxThread *t;
- uintptr data;
-
- while(wait1(1) > 0)
- ;
-
- if(strcmp(msg, "attached") == 0){
- t = attachthread(pid, pid, &new, Attached);
- if(t == nil)
- return -1;
- return 0;
- }
-
- if(strcmp(msg, "hang") == 0){
- if(pid == getpid())
- return ptrace(PTRACE_TRACEME, 0, 0, 0);
- werrstr("can only hang self");
- return -1;
- }
-
- t = findthread(pid);
- if(t == nil) {
- werrstr("not attached to pid %d", pid);
- return -1;
- }
- if(t->state == Exited) {
- werrstr("pid %d has exited", pid);
- return -1;
- }
- if(t->state == Killed) {
- werrstr("pid %d has been killed", pid);
- return -1;
- }
-
- if(strcmp(msg, "kill") == 0) {
- if(ptrace(PTRACE_KILL, pid, 0, 0) < 0)
- return -1;
- t->state = Killed;
- return 0;
- }
- if(strcmp(msg, "startstop") == 0){
- if(ctlproc(pid, "start") < 0)
- return -1;
- return waitstop(t);
- }
- if(strcmp(msg, "sysstop") == 0){
- if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
- return -1;
- t->state = Running;
- return waitstop(t);
- }
- if(strcmp(msg, "stop") == 0){
- if(trace > 1)
- fprint(2, "tid %d: tkill stop\n", pid);
- if(t->state == Stopped)
- return 0;
- if(syscall(__NR_tkill, pid, SIGSTOP) < 0)
- return -1;
- return waitstop(t);
- }
- if(strcmp(msg, "step") == 0){
- if(t->state == Running) {
- werrstr("cannot single-step unstopped %d", pid);
- return -1;
- }
- if(ptrace(PTRACE_SINGLESTEP, pid, 0, 0) < 0)
- return -1;
- return waitstop(t);
- }
- if(strcmp(msg, "start") == 0) {
- if(t->state == Running)
- return 0;
- data = 0;
- if(t->state == Stopped && t->signal != SIGSTOP && t->signal != SIGTRAP)
- data = t->signal;
- if(trace && data)
- fprint(2, "tid %d: continue %lud\n", pid, (ulong)data);
- if(ptrace(PTRACE_CONT, pid, 0, (void*)data) < 0)
- return -1;
- t->state = Running;
- return 0;
- }
- if(strcmp(msg, "waitstop") == 0) {
- return waitstop(t);
- }
- werrstr("unknown control message '%s'", msg);
- return -1;
-}
-
-char*
-proctextfile(int pid)
-{
- static char buf[1024], pbuf[128];
-
- snprint(pbuf, sizeof pbuf, "/proc/%d/exe", pid);
- if(readlink(pbuf, buf, sizeof buf) >= 0)
- return strdup(buf);
- if(access(pbuf, AEXIST) >= 0)
- return strdup(pbuf);
- return nil;
-}
-
-
-static int
-ptracerw(int type, int xtype, int isr, int pid, uvlong addr, void *v, uint n)
-{
- int i;
- uintptr u, a;
- uchar buf[sizeof(uintptr)];
-
- for(i=0; i<n; i+=sizeof(uintptr)){
- // Tread carefully here. On recent versions of glibc,
- // ptrace is a variadic function which means the third
- // argument will be pushed onto the stack as a uvlong.
- // This is fine on amd64 but will not work for 386.
- // We must convert addr to a uintptr.
- a = addr+i;
- if(isr){
- errno = 0;
- u = ptrace(type, pid, a, 0);
- if(errno)
- goto ptraceerr;
- if(n-i >= sizeof(uintptr))
- memmove((char*)v+i, &u, sizeof(uintptr));
- else{
- memmove(buf, &u, sizeof u);
- memmove((char*)v+i, buf, n-i);
- }
- }else{
- if(n-i >= sizeof(uintptr))
- u = *(uintptr*)((char*)v+i);
- else{
- errno = 0;
- u = ptrace(xtype, pid, a, 0);
- if(errno)
- return -1;
- memmove(buf, &u, sizeof u);
- memmove(buf, (char*)v+i, n-i);
- memmove(&u, buf, sizeof u);
- }
- if(ptrace(type, pid, a, u) < 0)
- goto ptraceerr;
- }
- }
- return 0;
-
-ptraceerr:
- werrstr("ptrace %s addr=%#llux pid=%d: %r", isr ? "read" : "write", addr, pid);
- return -1;
-}
-
-static int
-ptracesegrw(Map *map, Seg *seg, uvlong addr, void *v, uint n, int isr)
-{
- USED(seg);
-
- return ptracerw(isr ? PTRACE_PEEKDATA : PTRACE_POKEDATA, PTRACE_PEEKDATA,
- isr, map->pid, addr, v, n);
-}
-
-// If the debugger is compiled as an x86-64 program,
-// then all the ptrace register read/writes are done on
-// a 64-bit register set. If the target program
-// is a 32-bit program, the debugger is expected to
-// read the bottom half of the relevant registers
-// out of the 64-bit set.
-
-// Linux 32-bit is
-// BX CX DX SI DI BP AX DS ES FS GS OrigAX IP CS EFLAGS SP SS
-
-// Linux 64-bit is
-// R15 R14 R13 R12 BP BX R11 R10 R9 R8 AX CX DX SI DI OrigAX IP CS EFLAGS SP SS FSBase GSBase DS ES FS GS
-
-// Go 32-bit is
-// DI SI BP NSP BX DX CX AX GS FS ES DS TRAP ECODE PC CS EFLAGS SP SS
-
-uint go32tolinux32tab[] = {
- 4, 3, 5, 15, 0, 2, 1, 6, 10, 9, 8, 7, -1, -1, 12, 13, 14, 15, 16
-};
-static int
-go32tolinux32(uvlong addr)
-{
- int r;
-
- if(addr%4 || addr/4 >= nelem(go32tolinux32tab))
- return -1;
- r = go32tolinux32tab[addr/4];
- if(r < 0)
- return -1;
- return r*4;
-}
-
-uint go32tolinux64tab[] = {
- 14, 13, 4, 19, 5, 12, 11, 10, 26, 25, 24, 23, -1, -1, 16, 17, 18, 19, 20
-};
-static int
-go32tolinux64(uvlong addr)
-{
- int r;
-
- if(addr%4 || addr/4 >= nelem(go32tolinux64tab))
- return -1;
- r = go32tolinux64tab[addr/4];
- if(r < 0)
- return -1;
- return r*8;
-}
-
-extern Mach mi386;
-extern Mach mamd64;
-
-static int
-go2linux(uvlong addr)
-{
- if(sizeof(void*) == 4) {
- if(mach == &mi386)
- return go32tolinux32(addr);
- werrstr("unsupported architecture");
- return -1;
- }
-
- if(mach == &mi386)
- return go32tolinux64(addr);
- if(mach != &mamd64) {
- werrstr("unsupported architecture");
- return -1;
- }
-
- switch(addr){
- case offsetof(Ureg64, ax):
- return offsetof(struct user_regs_struct, rax);
- case offsetof(Ureg64, bx):
- return offsetof(struct user_regs_struct, rbx);
- case offsetof(Ureg64, cx):
- return offsetof(struct user_regs_struct, rcx);
- case offsetof(Ureg64, dx):
- return offsetof(struct user_regs_struct, rdx);
- case offsetof(Ureg64, si):
- return offsetof(struct user_regs_struct, rsi);
- case offsetof(Ureg64, di):
- return offsetof(struct user_regs_struct, rdi);
- case offsetof(Ureg64, bp):
- return offsetof(struct user_regs_struct, rbp);
- case offsetof(Ureg64, r8):
- return offsetof(struct user_regs_struct, r8);
- case offsetof(Ureg64, r9):
- return offsetof(struct user_regs_struct, r9);
- case offsetof(Ureg64, r10):
- return offsetof(struct user_regs_struct, r10);
- case offsetof(Ureg64, r11):
- return offsetof(struct user_regs_struct, r11);
- case offsetof(Ureg64, r12):
- return offsetof(struct user_regs_struct, r12);
- case offsetof(Ureg64, r13):
- return offsetof(struct user_regs_struct, r13);
- case offsetof(Ureg64, r14):
- return offsetof(struct user_regs_struct, r14);
- case offsetof(Ureg64, r15):
- return offsetof(struct user_regs_struct, r15);
- case offsetof(Ureg64, ds):
- return offsetof(struct user_regs_struct, ds);
- case offsetof(Ureg64, es):
- return offsetof(struct user_regs_struct, es);
- case offsetof(Ureg64, fs):
- return offsetof(struct user_regs_struct, fs);
- case offsetof(Ureg64, gs):
- return offsetof(struct user_regs_struct, gs);
- case offsetof(Ureg64, ip):
- return offsetof(struct user_regs_struct, rip);
- case offsetof(Ureg64, cs):
- return offsetof(struct user_regs_struct, cs);
- case offsetof(Ureg64, flags):
- return offsetof(struct user_regs_struct, eflags);
- case offsetof(Ureg64, sp):
- return offsetof(struct user_regs_struct, rsp);
- case offsetof(Ureg64, ss):
- return offsetof(struct user_regs_struct, ss);
- }
- return -1;
-}
-
-static int
-ptraceregrw(Map *map, Seg *seg, uvlong addr, void *v, uint n, int isr)
-{
- int laddr;
- uvlong u;
-
- USED(seg);
-
- if((laddr = go2linux(addr)) < 0){
- if(isr){
- memset(v, 0, n);
- return 0;
- }
- werrstr("register %llud not available", addr);
- return -1;
- }
-
- if(isr){
- errno = 0;
- u = ptrace(PTRACE_PEEKUSER, map->pid, laddr, 0);
- if(errno)
- goto ptraceerr;
- switch(n){
- case 1:
- *(uint8*)v = u;
- break;
- case 2:
- *(uint16*)v = u;
- break;
- case 4:
- *(uint32*)v = u;
- break;
- case 8:
- *(uint64*)v = u;
- break;
- default:
- werrstr("bad register size");
- return -1;
- }
- }else{
- switch(n){
- case 1:
- u = *(uint8*)v;
- break;
- case 2:
- u = *(uint16*)v;
- break;
- case 4:
- u = *(uint32*)v;
- break;
- case 8:
- u = *(uint64*)v;
- break;
- default:
- werrstr("bad register size");
- return -1;
- }
- if(ptrace(PTRACE_POKEUSER, map->pid, laddr, (void*)(uintptr)u) < 0)
- goto ptraceerr;
- }
- return 0;
-
-ptraceerr:
- werrstr("ptrace %s register laddr=%d pid=%d n=%d: %r", isr ? "read" : "write", laddr, map->pid, n);
- return -1;
-}
-
-char*
-procstatus(int pid)
-{
- LinuxThread *t;
-
- t = findthread(pid);
- if(t == nil)
- return "???";
-
- return statestr[t->state];
-}
diff --git a/src/libmach/machdata.c b/src/libmach/machdata.c
deleted file mode 100644
index 66c19f953..000000000
--- a/src/libmach/machdata.c
+++ /dev/null
@@ -1,477 +0,0 @@
-// Inferno libmach/machdata.c
-// http://code.google.com/p/inferno-os/source/browse/utils/libmach/machdata.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc.
-// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
-// Portions Copyright © 1997-1999 Vita Nuova Limited.
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-/*
- * Debugger utilities shared by at least two architectures
- */
-
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-
-#define STARTSYM "_main"
-#define PROFSYM "_mainp"
-#define FRAMENAME ".frame"
-
-extern Machdata mipsmach;
-
-int asstype = AMIPS; /* disassembler type */
-Machdata *machdata; /* machine-dependent functions */
-
-int
-localaddr(Map *map, char *fn, char *var, uvlong *r, Rgetter rget)
-{
- Symbol s;
- uvlong fp, pc, sp, link;
-
- if (!lookup(fn, 0, &s)) {
- werrstr("function not found");
- return -1;
- }
- pc = rget(map, mach->pc);
- sp = rget(map, mach->sp);
- if(mach->link)
- link = rget(map, mach->link);
- else
- link = 0;
- fp = machdata->findframe(map, s.value, pc, sp, link);
- if (fp == 0) {
- werrstr("stack frame not found");
- return -1;
- }
-
- if (!var || !var[0]) {
- *r = fp;
- return 1;
- }
-
- if (findlocal(&s, var, &s) == 0) {
- werrstr("local variable not found");
- return -1;
- }
-
- switch (s.class) {
- case CAUTO:
- *r = fp - s.value;
- break;
- case CPARAM: /* assume address size is stack width */
- *r = fp + s.value + mach->szaddr;
- break;
- default:
- werrstr("local variable not found: %d", s.class);
- return -1;
- }
- return 1;
-}
-
-/*
- * Print value v as s.name[+offset] if possible, or just v.
- */
-int
-symoff(char *buf, int n, uvlong v, int space)
-{
- Symbol s;
- int r;
- int32 delta;
-
- r = delta = 0; /* to shut compiler up */
- if (v) {
- r = findsym(v, space, &s);
- if (r)
- delta = v-s.value;
- if (delta < 0)
- delta = -delta;
- }
- if (v == 0 || r == 0)
- return snprint(buf, n, "%llux", v);
- if (s.type != 't' && s.type != 'T' && delta >= 4096)
- return snprint(buf, n, "%llux", v);
- else if (delta)
- return snprint(buf, n, "%s+%#ux", s.name, delta);
- else
- return snprint(buf, n, "%s", s.name);
-}
-
-/*
- * Format floating point registers
- *
- * Register codes in format field:
- * 'X' - print as 32-bit hexadecimal value
- * 'F' - 64-bit double register when modif == 'F'; else 32-bit single reg
- * 'f' - 32-bit ieee float
- * '8' - big endian 80-bit ieee extended float
- * '3' - little endian 80-bit ieee extended float with hole in bytes 8&9
- */
-int
-fpformat(Map *map, Reglist *rp, char *buf, int n, int modif)
-{
- char reg[12];
- uint32 r;
-
- switch(rp->rformat)
- {
- case 'X':
- if (get4(map, rp->roffs, &r) < 0)
- return -1;
- snprint(buf, n, "%ux", r);
- break;
- case 'F': /* first reg of double reg pair */
- if (modif == 'F')
- if ((rp->rformat=='F') || (((rp+1)->rflags&RFLT) && (rp+1)->rformat == 'f')) {
- if (get1(map, rp->roffs, (uchar *)reg, 8) < 0)
- return -1;
- machdata->dftos(buf, n, reg);
- if (rp->rformat == 'F')
- return 1;
- return 2;
- }
- /* treat it like 'f' */
- if (get1(map, rp->roffs, (uchar *)reg, 4) < 0)
- return -1;
- machdata->sftos(buf, n, reg);
- break;
- case 'f': /* 32 bit float */
- if (get1(map, rp->roffs, (uchar *)reg, 4) < 0)
- return -1;
- machdata->sftos(buf, n, reg);
- break;
- case '3': /* little endian ieee 80 with hole in bytes 8&9 */
- if (get1(map, rp->roffs, (uchar *)reg, 10) < 0)
- return -1;
- memmove(reg+10, reg+8, 2); /* open hole */
- memset(reg+8, 0, 2); /* fill it */
- leieee80ftos(buf, n, reg);
- break;
- case '8': /* big-endian ieee 80 */
- if (get1(map, rp->roffs, (uchar *)reg, 10) < 0)
- return -1;
- beieee80ftos(buf, n, reg);
- break;
- default: /* unknown */
- break;
- }
- return 1;
-}
-
-char *
-_hexify(char *buf, uint32 p, int zeros)
-{
- uint32 d;
-
- d = p/16;
- if(d)
- buf = _hexify(buf, d, zeros-1);
- else
- while(zeros--)
- *buf++ = '0';
- *buf++ = "0123456789abcdef"[p&0x0f];
- return buf;
-}
-
-/*
- * These routines assume that if the number is representable
- * in IEEE floating point, it will be representable in the native
- * double format. Naive but workable, probably.
- */
-int
-ieeedftos(char *buf, int n, uint32 h, uint32 l)
-{
- double fr;
- int exp;
-
- if (n <= 0)
- return 0;
-
-
- if(h & (1L<<31)){
- *buf++ = '-';
- h &= ~(1L<<31);
- }else
- *buf++ = ' ';
- n--;
- if(l == 0 && h == 0)
- return snprint(buf, n, "0.");
- exp = (h>>20) & ((1L<<11)-1L);
- if(exp == 0)
- return snprint(buf, n, "DeN(%.8ux%.8ux)", h, l);
- if(exp == ((1L<<11)-1L)){
- if(l==0 && (h&((1L<<20)-1L)) == 0)
- return snprint(buf, n, "Inf");
- else
- return snprint(buf, n, "NaN(%.8ux%.8ux)", h&((1<<20)-1), l);
- }
- exp -= (1L<<10) - 2L;
- fr = l & ((1L<<16)-1L);
- fr /= 1L<<16;
- fr += (l>>16) & ((1L<<16)-1L);
- fr /= 1L<<16;
- fr += (h & (1L<<20)-1L) | (1L<<20);
- fr /= 1L<<21;
- fr = ldexp(fr, exp);
- return snprint(buf, n, "%.18g", fr);
-}
-
-int
-ieeesftos(char *buf, int n, uint32 h)
-{
- double fr;
- int exp;
-
- if (n <= 0)
- return 0;
-
- if(h & (1L<<31)){
- *buf++ = '-';
- h &= ~(1L<<31);
- }else
- *buf++ = ' ';
- n--;
- if(h == 0)
- return snprint(buf, n, "0.");
- exp = (h>>23) & ((1L<<8)-1L);
- if(exp == 0)
- return snprint(buf, n, "DeN(%.8ux)", h);
- if(exp == ((1L<<8)-1L)){
- if((h&((1L<<23)-1L)) == 0)
- return snprint(buf, n, "Inf");
- else
- return snprint(buf, n, "NaN(%.8lux)", h&((1L<<23)-1L));
- }
- exp -= (1L<<7) - 2L;
- fr = (h & ((1L<<23)-1L)) | (1L<<23);
- fr /= 1L<<24;
- fr = ldexp(fr, exp);
- return snprint(buf, n, "%.9g", fr);
-}
-
-int
-beieeesftos(char *buf, int n, void *s)
-{
- return ieeesftos(buf, n, beswal(*(uint32*)s));
-}
-
-int
-beieeedftos(char *buf, int n, void *s)
-{
- return ieeedftos(buf, n, beswal(*(uint32*)s), beswal(((uint32*)(s))[1]));
-}
-
-int
-leieeesftos(char *buf, int n, void *s)
-{
- return ieeesftos(buf, n, leswal(*(uint32*)s));
-}
-
-int
-leieeedftos(char *buf, int n, void *s)
-{
- return ieeedftos(buf, n, leswal(((uint32*)(s))[1]), leswal(*(uint32*)s));
-}
-
-/* packed in 12 bytes, with s[2]==s[3]==0; mantissa starts at s[4]*/
-int
-beieee80ftos(char *buf, int n, void *s)
-{
- uchar *reg = (uchar*)s;
- int i;
- uint32 x;
- uchar ieee[8+8]; /* room for slop */
- uchar *p, *q;
-
- memset(ieee, 0, sizeof(ieee));
- /* sign */
- if(reg[0] & 0x80)
- ieee[0] |= 0x80;
-
- /* exponent */
- x = ((reg[0]&0x7F)<<8) | reg[1];
- if(x == 0) /* number is ±0 */
- goto done;
- if(x == 0x7FFF){
- if(memcmp(reg+4, ieee+1, 8) == 0){ /* infinity */
- x = 2047;
- }else{ /* NaN */
- x = 2047;
- ieee[7] = 0x1; /* make sure */
- }
- ieee[0] |= x>>4;
- ieee[1] |= (x&0xF)<<4;
- goto done;
- }
- x -= 0x3FFF; /* exponent bias */
- x += 1023;
- if(x >= (1<<11) || ((reg[4]&0x80)==0 && x!=0))
- return snprint(buf, n, "not in range");
- ieee[0] |= x>>4;
- ieee[1] |= (x&0xF)<<4;
-
- /* mantissa */
- p = reg+4;
- q = ieee+1;
- for(i=0; i<56; i+=8, p++, q++){ /* move one byte */
- x = (p[0]&0x7F) << 1;
- if(p[1] & 0x80)
- x |= 1;
- q[0] |= x>>4;
- q[1] |= (x&0xF)<<4;
- }
- done:
- return beieeedftos(buf, n, (void*)ieee);
-}
-
-int
-leieee80ftos(char *buf, int n, void *s)
-{
- int i;
- char *cp;
- char b[12];
-
- cp = (char*) s;
- for(i=0; i<12; i++)
- b[11-i] = *cp++;
- return beieee80ftos(buf, n, b);
-}
-
-int
-cisctrace(Map *map, uvlong pc, uvlong sp, uvlong link, Tracer trace)
-{
- Symbol s;
- int found, i;
- uvlong opc, moved;
-
- USED(link);
- i = 0;
- opc = 0;
- while(pc && opc != pc) {
- moved = pc2sp(pc);
- if (moved == ~0)
- break;
- found = findsym(pc, CTEXT, &s);
- if (!found)
- break;
- if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
- break;
-
- sp += moved;
- opc = pc;
- if (geta(map, sp, &pc) < 0)
- break;
- (*trace)(map, pc, sp, &s);
- sp += mach->szaddr; /*assumes address size = stack width*/
- if(++i > 40)
- break;
- }
- return i;
-}
-
-int
-risctrace(Map *map, uvlong pc, uvlong sp, uvlong link, Tracer trace)
-{
- int i;
- Symbol s, f;
- uvlong oldpc;
-
- i = 0;
- while(findsym(pc, CTEXT, &s)) {
- if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
- break;
-
- if(pc == s.value) /* at first instruction */
- f.value = 0;
- else if(findlocal(&s, FRAMENAME, &f) == 0)
- break;
-
- oldpc = pc;
- if(s.type == 'L' || s.type == 'l' || pc <= s.value+mach->pcquant)
- pc = link;
- else
- if (geta(map, sp, &pc) < 0)
- break;
-
- if(pc == 0 || (pc == oldpc && f.value == 0))
- break;
-
- sp += f.value;
- (*trace)(map, pc-8, sp, &s);
-
- if(++i > 40)
- break;
- }
- return i;
-}
-
-uvlong
-ciscframe(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong link)
-{
- Symbol s;
- uvlong moved;
-
- USED(link);
- for(;;) {
- moved = pc2sp(pc);
- if (moved == ~0)
- break;
- sp += moved;
- findsym(pc, CTEXT, &s);
- if (addr == s.value)
- return sp;
- if (geta(map, sp, &pc) < 0)
- break;
- sp += mach->szaddr; /*assumes sizeof(addr) = stack width*/
- }
- return 0;
-}
-
-uvlong
-riscframe(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong link)
-{
- Symbol s, f;
-
- while (findsym(pc, CTEXT, &s)) {
- if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
- break;
-
- if(pc == s.value) /* at first instruction */
- f.value = 0;
- else
- if(findlocal(&s, FRAMENAME, &f) == 0)
- break;
-
- sp += f.value;
- if (s.value == addr)
- return sp;
-
- if (s.type == 'L' || s.type == 'l' || pc-s.value <= mach->szaddr*2)
- pc = link;
- else
- if (geta(map, sp-f.value, &pc) < 0)
- break;
- }
- return 0;
-}
diff --git a/src/libmach/macho.h b/src/libmach/macho.h
deleted file mode 100644
index 9dfea5a85..000000000
--- a/src/libmach/macho.h
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- * Definitions needed for accessing MACH object headers.
- */
-
-typedef struct {
- uint32 magic; /* mach magic number identifier */
- uint32 cputype; /* cpu specifier */
- uint32 cpusubtype; /* machine specifier */
- uint32 filetype; /* type of file */
- uint32 ncmds; /* number of load commands */
- uint32 sizeofcmds; /* the size of all the load commands */
- uint32 flags; /* flags */
- uint32 reserved; /* reserved */
-} Machhdr;
-
-typedef struct {
- uint32 type; /* type of load command */
- uint32 size; /* total size in bytes */
-} MachCmd;
-
-typedef struct {
- MachCmd cmd;
- char segname[16]; /* segment name */
- uint32 vmaddr; /* memory address of this segment */
- uint32 vmsize; /* memory size of this segment */
- uint32 fileoff; /* file offset of this segment */
- uint32 filesize; /* amount to map from the file */
- uint32 maxprot; /* maximum VM protection */
- uint32 initprot; /* initial VM protection */
- uint32 nsects; /* number of sections in segment */
- uint32 flags; /* flags */
-} MachSeg32; /* for 32-bit architectures */
-
-typedef struct {
- MachCmd cmd;
- char segname[16]; /* segment name */
- uvlong vmaddr; /* memory address of this segment */
- uvlong vmsize; /* memory size of this segment */
- uvlong fileoff; /* file offset of this segment */
- uvlong filesize; /* amount to map from the file */
- uint32 maxprot; /* maximum VM protection */
- uint32 initprot; /* initial VM protection */
- uint32 nsects; /* number of sections in segment */
- uint32 flags; /* flags */
-} MachSeg64; /* for 64-bit architectures */
-
-typedef struct {
- MachCmd cmd;
- uint32 fileoff; /* file offset of this segment */
- uint32 filesize; /* amount to map from the file */
-} MachSymSeg;
-
-typedef struct {
- char sectname[16]; /* name of this section */
- char segname[16]; /* segment this section goes in */
- uint32 addr; /* memory address of this section */
- uint32 size; /* size in bytes of this section */
- uint32 offset; /* file offset of this section */
- uint32 align; /* section alignment (power of 2) */
- uint32 reloff; /* file offset of relocation entries */
- uint32 nreloc; /* number of relocation entries */
- uint32 flags; /* flags (section type and attributes)*/
- uint32 reserved1; /* reserved (for offset or index) */
- uint32 reserved2; /* reserved (for count or sizeof) */
-} MachSect32; /* for 32-bit architectures */
-
-typedef struct {
- char sectname[16]; /* name of this section */
- char segname[16]; /* segment this section goes in */
- uvlong addr; /* memory address of this section */
- uvlong size; /* size in bytes of this section */
- uint32 offset; /* file offset of this section */
- uint32 align; /* section alignment (power of 2) */
- uint32 reloff; /* file offset of relocation entries */
- uint32 nreloc; /* number of relocation entries */
- uint32 flags; /* flags (section type and attributes)*/
- uint32 reserved1; /* reserved (for offset or index) */
- uint32 reserved2; /* reserved (for count or sizeof) */
- uint32 reserved3; /* reserved */
-} MachSect64; /* for 64-bit architectures */
-
-enum {
- MACH_CPU_TYPE_X86_64 = (1<<24)|7,
- MACH_CPU_TYPE_X86 = 7,
- MACH_CPU_SUBTYPE_X86 = 3,
- MACH_CPU_SUBTYPE_X86_64 = (1<<31)|3,
- MACH_EXECUTABLE_TYPE = 2,
- MACH_SEGMENT_32 = 1, /* 32-bit mapped segment */
- MACH_SEGMENT_64 = 0x19, /* 64-bit mapped segment */
- MACH_SYMSEG = 3, /* obsolete gdb symtab, reused by go */
- MACH_UNIXTHREAD = 0x5, /* thread (for stack) */
-};
-
-
-#define MACH64_MAG ((0xcf<<24) | (0xfa<<16) | (0xed<<8) | 0xfe)
-#define MACH32_MAG ((0xce<<24) | (0xfa<<16) | (0xed<<8) | 0xfe)
diff --git a/src/libmach/map.c b/src/libmach/map.c
deleted file mode 100644
index cd5ef0985..000000000
--- a/src/libmach/map.c
+++ /dev/null
@@ -1,183 +0,0 @@
-// Derived from Inferno libmach/map.c and
-// Plan 9 from User Space src/libmach/map.c
-//
-// http://code.swtch.com/plan9port/src/tip/src/libmach/map.c
-// http://code.google.com/p/inferno-os/source/browse/utils/libmach/map.c
-//
-//
-// Copyright © 1994-1999 Lucent Technologies Inc.
-// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
-// Portions Copyright © 1997-1999 Vita Nuova Limited.
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
-// Portions Copyright © 2001-2007 Russ Cox.
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-/*
- * file map routines
- */
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-
-Map *
-newmap(Map *map, int n)
-{
- int size;
-
- size = sizeof(Map)+(n-1)*sizeof(Seg);
- if (map == 0)
- map = malloc(size);
- else
- map = realloc(map, size);
- if (map == 0) {
- werrstr("out of memory: %r");
- return 0;
- }
- memset(map, 0, size);
- map->nsegs = n;
- return map;
-}
-
-int
-setmap(Map *map, int fd, uvlong b, uvlong e, vlong f, char *name, Maprw *rw)
-{
- int i;
-
- if (map == 0)
- return 0;
- for (i = 0; i < map->nsegs; i++)
- if (!map->seg[i].inuse)
- break;
- if (i >= map->nsegs)
- return 0;
- map->seg[i].b = b;
- map->seg[i].e = e;
- map->seg[i].f = f;
- map->seg[i].inuse = 1;
- map->seg[i].name = name;
- map->seg[i].fd = fd;
- map->seg[i].rw = rw;
- return 1;
-}
-
-/*
-static uvlong
-stacktop(int pid)
-{
- char buf[64];
- int fd;
- int n;
- char *cp;
-
- snprint(buf, sizeof(buf), "/proc/%d/segment", pid);
- fd = open(buf, 0);
- if (fd < 0)
- return 0;
- n = read(fd, buf, sizeof(buf)-1);
- close(fd);
- buf[n] = 0;
- if (strncmp(buf, "Stack", 5))
- return 0;
- for (cp = buf+5; *cp && *cp == ' '; cp++)
- ;
- if (!*cp)
- return 0;
- cp = strchr(cp, ' ');
- if (!cp)
- return 0;
- while (*cp && *cp == ' ')
- cp++;
- if (!*cp)
- return 0;
- return strtoull(cp, 0, 16);
-}
-*/
-
-int
-findseg(Map *map, char *name)
-{
- int i;
-
- if (!map)
- return -1;
- for (i = 0; i < map->nsegs; i++)
- if (map->seg[i].inuse && !strcmp(map->seg[i].name, name))
- return i;
- return -1;
-}
-
-void
-unusemap(Map *map, int i)
-{
- if (map != 0 && 0 <= i && i < map->nsegs)
- map->seg[i].inuse = 0;
-}
-
-int
-fdrw(Map *map, Seg *s, uvlong addr, void *v, uint n, int isread)
-{
- int tot, m;
-
- USED(map);
-
- for(tot=0; tot<n; tot+=m){
- if(isread)
- m = pread(s->fd, (uchar*)v+tot, n-tot, addr+tot);
- else
- m = pwrite(s->fd, (uchar*)v+tot, n-tot, addr+tot);
- if(m == 0){
- werrstr("short %s", isread ? "read" : "write");
- return -1;
- }
- if(m < 0){
- werrstr("%s %d at %#llux (+%#llux): %r", isread ? "read" : "write", n, addr, s->f);
- return -1;
- }
- }
- return 0;
-}
-
-
-Map*
-loadmap(Map *map, int fd, Fhdr *fp)
-{
- map = newmap(map, 2);
- if (map == 0)
- return 0;
-
- map->seg[0].b = fp->txtaddr;
- map->seg[0].e = fp->txtaddr+fp->txtsz;
- map->seg[0].f = fp->txtoff;
- map->seg[0].fd = fd;
- map->seg[0].inuse = 1;
- map->seg[0].name = "text";
- map->seg[0].rw = fdrw;
- map->seg[1].b = fp->dataddr;
- map->seg[1].e = fp->dataddr+fp->datsz;
- map->seg[1].f = fp->datoff;
- map->seg[1].fd = fd;
- map->seg[1].inuse = 1;
- map->seg[1].name = "data";
- map->seg[0].rw = fdrw;
- return map;
-}
diff --git a/src/libmach/netbsd.c b/src/libmach/netbsd.c
deleted file mode 100644
index adeeff333..000000000
--- a/src/libmach/netbsd.c
+++ /dev/null
@@ -1,56 +0,0 @@
-// This is stubbed out for the moment. Will revisit when the time comes.
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-
-int
-ctlproc(int pid, char *msg)
-{
- USED(pid);
- USED(msg);
- sysfatal("ctlproc unimplemented in NetBSD");
- return -1;
-}
-
-char*
-proctextfile(int pid)
-{
- USED(pid);
- sysfatal("proctextfile unimplemented in NetBSD");
- return nil;
-}
-
-char*
-procstatus(int pid)
-{
- USED(pid);
- sysfatal("procstatus unimplemented in NetBSD");
- return nil;
-}
-
-Map*
-attachproc(int pid, Fhdr *fp)
-{
- USED(pid);
- USED(fp);
- sysfatal("attachproc unimplemented in NetBSD");
- return nil;
-}
-
-void
-detachproc(Map *m)
-{
- USED(m);
- sysfatal("detachproc unimplemented in NetBSD");
-}
-
-int
-procthreadpids(int pid, int *p, int np)
-{
- USED(pid);
- USED(p);
- USED(np);
- sysfatal("procthreadpids unimplemented in NetBSD");
- return -1;
-}
diff --git a/src/libmach/obj.c b/src/libmach/obj.c
deleted file mode 100644
index 729a3eab8..000000000
--- a/src/libmach/obj.c
+++ /dev/null
@@ -1,393 +0,0 @@
-// Inferno libmach/obj.c
-// http://code.google.com/p/inferno-os/source/browse/utils/libmach/obj.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc.
-// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
-// Portions Copyright © 1997-1999 Vita Nuova Limited.
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-/*
- * obj.c
- * routines universal to all object files
- */
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <ar.h>
-#include <mach.h>
-#include "obj.h"
-
-#define islocal(t) ((t)=='a' || (t)=='p')
-
-enum
-{
- NNAMES = 50,
- MAXIS = 8, /* max length to determine if a file is a .? file */
- MAXOFF = 0x7fffffff, /* larger than any possible local offset */
- NHASH = 1024, /* must be power of two */
- HASHMUL = 79L,
-};
-
-int _is2(char*), /* in [$OS].c */
- _is5(char*),
- _is6(char*),
- _is7(char*),
- _is8(char*),
- _is9(char*),
- _isk(char*),
- _isq(char*),
- _isv(char*),
- _isu(char*),
- _read2(Biobuf*, Prog*),
- _read5(Biobuf*, Prog*),
- _read6(Biobuf*, Prog*),
- _read7(Biobuf*, Prog*),
- _read8(Biobuf*, Prog*),
- _read9(Biobuf*, Prog*),
- _readk(Biobuf*, Prog*),
- _readq(Biobuf*, Prog*),
- _readv(Biobuf*, Prog*),
- _readu(Biobuf*, Prog*);
-
-typedef struct Obj Obj;
-typedef struct Symtab Symtab;
-
-struct Obj /* functions to handle each intermediate (.$O) file */
-{
- char *name; /* name of each $O file */
- int (*is)(char*); /* test for each type of $O file */
- int (*read)(Biobuf*, Prog*); /* read for each type of $O file*/
-};
-
-static Obj obj[] =
-{ /* functions to identify and parse each type of obj */
- [Obj68020] = { "68020 .2", _is2, _read2 },
- [ObjAmd64] = { "amd64 .6", _is6 , _read6 },
- [ObjArm] = { "arm .5", _is5, _read5 },
- [ObjAlpha] = { "alpha .7", _is7, _read7 },
- [Obj386] = { "386 .8", _is8, _read8 },
- [ObjSparc] = { "sparc .k", _isk, _readk },
- [ObjPower] = { "power .q", _isq, _readq },
- [ObjMips] = { "mips .v", _isv, _readv },
- [ObjSparc64] = { "sparc64 .u", _isu, _readu },
- [ObjPower64] = { "power64 .9", _is9, _read9 },
- [Maxobjtype] = { 0, 0, 0 }
-};
-
-struct Symtab
-{
- struct Sym s;
- struct Symtab *next;
-};
-
-static Symtab *hash[NHASH];
-static Sym *names[NNAMES]; /* working set of active names */
-
-static int processprog(Prog*,int); /* decode each symbol reference */
-static void objreset(void);
-static void objlookup(int, char *, int, uint);
-static void objupdate(int, int);
-
-static int sequence;
-
-int
-objtype(Biobuf *bp, char **name)
-{
- int i;
- char buf[MAXIS];
- int c;
- char *p;
-
- /*
- * Look for import block.
- */
- p = Brdline(bp, '\n');
- if(p == nil)
- return -1;
- if(Blinelen(bp) < 10 || strncmp(p, "go object ", 10) != 0)
- return -1;
- Bseek(bp, -1, 1);
-
- /*
- * Found one. Skip until "\n!\n"
- */
- for(;;) {
- if((c = BGETC(bp)) == Beof)
- return -1;
- if(c != '\n')
- continue;
- c = BGETC(bp);
- if(c != '!'){
- Bungetc(bp);
- continue;
- }
- c = BGETC(bp);
- if(c != '\n'){
- Bungetc(bp);
- continue;
- }
- break;
- }
-
- if(Bread(bp, buf, MAXIS) < MAXIS)
- return -1;
- Bseek(bp, -MAXIS, 1);
- for (i = 0; i < Maxobjtype; i++) {
- if (obj[i].is && (*obj[i].is)(buf)) {
- if (name)
- *name = obj[i].name;
- return i;
- }
- }
-
- return -1;
-}
-
-int
-isar(Biobuf *bp)
-{
- int n;
- char magbuf[SARMAG];
-
- n = Bread(bp, magbuf, SARMAG);
- if(n == SARMAG && strncmp(magbuf, ARMAG, SARMAG) == 0)
- return 1;
- return 0;
-}
-
-/*
- * determine what kind of object file this is and process it.
- * return whether or not this was a recognized intermediate file.
- */
-int
-readobj(Biobuf *bp, int objtype)
-{
- Prog p;
-
- if (objtype < 0 || objtype >= Maxobjtype || obj[objtype].is == 0)
- return 1;
- objreset();
- while ((*obj[objtype].read)(bp, &p))
- if (!processprog(&p, 1))
- return 0;
- return 1;
-}
-
-int
-readar(Biobuf *bp, int objtype, vlong end, int doautos)
-{
- Prog p;
-
- if (objtype < 0 || objtype >= Maxobjtype || obj[objtype].is == 0)
- return 1;
- objreset();
- while ((*obj[objtype].read)(bp, &p) && Boffset(bp) < end)
- if (!processprog(&p, doautos))
- return 0;
- return 1;
-}
-
-/*
- * decode a symbol reference or definition
- */
-static int
-processprog(Prog *p, int doautos)
-{
- if(p->kind == aNone)
- return 1;
- if((schar)p->sym < 0 || p->sym >= NNAMES)
- return 0;
- switch(p->kind)
- {
- case aName:
- if (!doautos)
- if(p->type != 'U' && p->type != 'b')
- break;
- objlookup(p->sym, p->id, p->type, p->sig);
- break;
- case aText:
- objupdate(p->sym, 'T');
- break;
- case aData:
- objupdate(p->sym, 'D');
- break;
- default:
- break;
- }
- return 1;
-}
-
-/*
- * find the entry for s in the symbol array.
- * make a new entry if it is not already there.
- */
-static void
-objlookup(int id, char *name, int type, uint sig)
-{
- uint32 h;
- char *cp;
- Sym *s;
- Symtab *sp;
-
- s = names[id];
- if(s && strcmp(s->name, name) == 0) {
- s->type = type;
- s->sig = sig;
- return;
- }
-
- h = *name;
- for(cp = name+1; *cp; h += *cp++)
- h *= HASHMUL;
- h &= NHASH-1;
- if (type == 'U' || type == 'b' || islocal(type)) {
- for(sp = hash[h]; sp; sp = sp->next)
- if(strcmp(sp->s.name, name) == 0) {
- switch(sp->s.type) {
- case 'T':
- case 'D':
- case 'U':
- if (type == 'U') {
- names[id] = &sp->s;
- return;
- }
- break;
- case 't':
- case 'd':
- case 'b':
- if (type == 'b') {
- names[id] = &sp->s;
- return;
- }
- break;
- case 'a':
- case 'p':
- if (islocal(type)) {
- names[id] = &sp->s;
- return;
- }
- break;
- default:
- break;
- }
- }
- }
- sp = malloc(sizeof(Symtab));
- if(sp == nil)
- sysfatal("out of memory");
- sp->s.name = name;
- sp->s.type = type;
- sp->s.sig = sig;
- sp->s.value = islocal(type) ? MAXOFF : 0;
- sp->s.sequence = sequence++;
- names[id] = &sp->s;
- sp->next = hash[h];
- hash[h] = sp;
- return;
-}
-/*
- * traverse the symbol lists
- */
-void
-objtraverse(void (*fn)(Sym*, void*), void *pointer)
-{
- int i;
- Symtab *s;
-
- for(i = 0; i < NHASH; i++)
- for(s = hash[i]; s; s = s->next)
- (*fn)(&s->s, pointer);
-}
-
-/*
- * update the offset information for a 'a' or 'p' symbol in an intermediate file
- */
-void
-_offset(int id, vlong off)
-{
- Sym *s;
-
- s = names[id];
- if (s && s->name[0] && islocal(s->type) && s->value > off)
- s->value = off;
-}
-
-/*
- * update the type of a global text or data symbol
- */
-static void
-objupdate(int id, int type)
-{
- Sym *s;
-
- s = names[id];
- if (s && s->name[0])
- if (s->type == 'U')
- s->type = type;
- else if (s->type == 'b')
- s->type = tolower(type);
-}
-
-/*
- * look for the next file in an archive
- */
-int
-nextar(Biobuf *bp, int offset, char *buf)
-{
- struct ar_hdr a;
- int i, r;
- int32 arsize;
-
- if (offset&01)
- offset++;
- Bseek(bp, offset, 0);
- r = Bread(bp, &a, SAR_HDR);
- if(r != SAR_HDR)
- return 0;
- if(strncmp(a.fmag, ARFMAG, sizeof(a.fmag)))
- return -1;
- for(i=0; i<sizeof(a.name) && i<SARNAME && a.name[i] != ' '; i++)
- buf[i] = a.name[i];
- buf[i] = 0;
- arsize = strtol(a.size, 0, 0);
- if (arsize&1)
- arsize++;
- return arsize + SAR_HDR;
-}
-
-static void
-objreset(void)
-{
- int i;
- Symtab *s, *n;
-
- for(i = 0; i < NHASH; i++) {
- for(s = hash[i]; s; s = n) {
- n = s->next;
- free(s->s.name);
- free(s);
- }
- hash[i] = 0;
- }
- memset(names, 0, sizeof names);
-}
diff --git a/src/libmach/obj.h b/src/libmach/obj.h
deleted file mode 100644
index 35ec413a6..000000000
--- a/src/libmach/obj.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Inferno libmach/obj.h
-// http://code.google.com/p/inferno-os/source/browse/utils/libmach/obj.h
-//
-// Copyright © 1994-1999 Lucent Technologies Inc.
-// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
-// Portions Copyright © 1997-1999 Vita Nuova Limited.
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-/*
- * obj.h -- defs for dealing with object files
- */
-
-typedef enum Kind /* variable defs and references in obj */
-{
- aNone, /* we don't care about this prog */
- aName, /* introduces a name */
- aText, /* starts a function */
- aData, /* references to a global object */
-} Kind;
-
-typedef struct Prog Prog;
-
-struct Prog /* info from .$O files */
-{
- Kind kind; /* what kind of symbol */
- char type; /* type of the symbol: ie, 'T', 'a', etc. */
- char sym; /* index of symbol's name */
- char *id; /* name for the symbol, if it introduces one */
- uint sig; /* type signature for symbol */
-};
-
-#define UNKNOWN '?'
-void _offset(int, vlong);
diff --git a/src/libmach/openbsd.c b/src/libmach/openbsd.c
deleted file mode 100644
index ace8a22a5..000000000
--- a/src/libmach/openbsd.c
+++ /dev/null
@@ -1,56 +0,0 @@
-// This is stubbed out for the moment. Will revisit when the time comes.
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-
-int
-ctlproc(int pid, char *msg)
-{
- USED(pid);
- USED(msg);
- sysfatal("ctlproc unimplemented in OpenBSD");
- return -1;
-}
-
-char*
-proctextfile(int pid)
-{
- USED(pid);
- sysfatal("proctextfile unimplemented in OpenBSD");
- return nil;
-}
-
-char*
-procstatus(int pid)
-{
- USED(pid);
- sysfatal("procstatus unimplemented in OpenBSD");
- return nil;
-}
-
-Map*
-attachproc(int pid, Fhdr *fp)
-{
- USED(pid);
- USED(fp);
- sysfatal("attachproc unimplemented in OpenBSD");
- return nil;
-}
-
-void
-detachproc(Map *m)
-{
- USED(m);
- sysfatal("detachproc unimplemented in OpenBSD");
-}
-
-int
-procthreadpids(int pid, int *p, int np)
-{
- USED(pid);
- USED(p);
- USED(np);
- sysfatal("procthreadpids unimplemented in OpenBSD");
- return -1;
-}
diff --git a/src/libmach/plan9.c b/src/libmach/plan9.c
deleted file mode 100644
index 59e2649d0..000000000
--- a/src/libmach/plan9.c
+++ /dev/null
@@ -1,72 +0,0 @@
-// This is stubbed out for the moment. Will revisit when the time comes.
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-
-int
-ctlproc(int pid, char *msg)
-{
- USED(pid);
- USED(msg);
-
- sysfatal("ctlproc unimplemented on Plan 9");
- return -1;
-}
-
-char*
-proctextfile(int pid)
-{
- USED(pid);
-
- sysfatal("proctextfile unimplemented on Plan 9");
- return nil;
-}
-
-char*
-procstatus(int pid)
-{
- USED(pid);
-
- sysfatal("procstatus unimplemented on Plan 9");
- return nil;
-}
-
-Map*
-attachproc(int pid, Fhdr *fp)
-{
- USED(pid);
- USED(fp);
-
- sysfatal("attachproc unimplemented on Plan 9");
- return nil;
-}
-
-void
-detachproc(Map *m)
-{
- USED(m);
-
- sysfatal("detachproc unimplemented on Plan 9");
-}
-
-int
-procthreadpids(int pid, int *p, int np)
-{
- USED(pid);
- USED(p);
- USED(np);
-
- sysfatal("procthreadpids unimplemented on Plan 9");
- return -1;
-}
-
-int
-nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
-{
- USED(rqtp);
- USED(rmtp);
-
- sysfatal("nanosleep unimplemented on Plan 9");
- return -1;
-}
diff --git a/src/libmach/setmach.c b/src/libmach/setmach.c
deleted file mode 100644
index 0fa4d3192..000000000
--- a/src/libmach/setmach.c
+++ /dev/null
@@ -1,203 +0,0 @@
-// Inferno libmach/setmach.c
-// http://code.google.com/p/inferno-os/source/browse/utils/libmach/setmach.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc.
-// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
-// Portions Copyright © 1997-1999 Vita Nuova Limited.
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
- /* table for selecting machine-dependent parameters */
-
-typedef struct machtab Machtab;
-
-struct machtab
-{
- char *name; /* machine name */
- short type; /* executable type */
- short boottype; /* bootable type */
- int asstype; /* disassembler code */
- Mach *mach; /* machine description */
- Machdata *machdata; /* machine functions */
-};
-
-/*
-extern Mach mmips, msparc, m68020, mi386, mamd64,
- marm, mmips2be, mmips2le, mpower, mpower64, malpha, msparc64;
-extern Machdata mipsmach, sparcmach, m68020mach, i386mach,
- armmach, mipsmach2le, powermach, alphamach, sparc64mach;
-*/
-extern Mach mi386, mamd64, marm;
-extern Machdata i386mach, armmach;
-
-/*
- * machine selection table. machines with native disassemblers should
- * follow the plan 9 variant in the table; native modes are selectable
- * only by name.
- */
-Machtab machines[] =
-{
- { "386", /*plan 9 386*/
- FI386,
- FI386B,
- AI386,
- &mi386,
- &i386mach, },
- { "amd64", /*amd64*/
- FAMD64,
- FAMD64B,
- AAMD64,
- &mamd64,
- &i386mach, },
- { "arm", /*ARM*/
- FARM,
- FARMB,
- AARM,
- &marm,
- &armmach, },
-#ifdef unused
- { "68020", /*68020*/
- F68020,
- F68020B,
- A68020,
- &m68020,
- &m68020mach, },
- { "68020", /*Next 68040 bootable*/
- F68020,
- FNEXTB,
- A68020,
- &m68020,
- &m68020mach, },
- { "mips2LE", /*plan 9 mips2 little endian*/
- FMIPS2LE,
- 0,
- AMIPS,
- &mmips2le,
- &mipsmach2le, },
- { "mips", /*plan 9 mips*/
- FMIPS,
- FMIPSB,
- AMIPS,
- &mmips,
- &mipsmach, },
- { "mips2", /*plan 9 mips2*/
- FMIPS2BE,
- FMIPSB,
- AMIPS,
- &mmips2be,
- &mipsmach, }, /* shares debuggers with native mips */
- { "mipsco", /*native mips - must follow plan 9*/
- FMIPS,
- FMIPSB,
- AMIPSCO,
- &mmips,
- &mipsmach, },
- { "sparc", /*plan 9 sparc */
- FSPARC,
- FSPARCB,
- ASPARC,
- &msparc,
- &sparcmach, },
- { "sunsparc", /*native sparc - must follow plan 9*/
- FSPARC,
- FSPARCB,
- ASUNSPARC,
- &msparc,
- &sparcmach, },
- { "86", /*8086 - a peach of a machine*/
- FI386,
- FI386B,
- AI8086,
- &mi386,
- &i386mach, },
- { "power", /*PowerPC*/
- FPOWER,
- FPOWERB,
- APOWER,
- &mpower,
- &powermach, },
- { "power64", /*PowerPC*/
- FPOWER64,
- FPOWER64B,
- APOWER64,
- &mpower64,
- &powermach, },
- { "alpha", /*Alpha*/
- FALPHA,
- FALPHAB,
- AALPHA,
- &malpha,
- &alphamach, },
- { "sparc64", /*plan 9 sparc64 */
- FSPARC64,
- FSPARCB, /* XXX? */
- ASPARC64,
- &msparc64,
- &sparc64mach, },
-#endif
- { 0 }, /*the terminator*/
-};
-
-/*
- * select a machine by executable file type
- */
-void
-machbytype(int type)
-{
- Machtab *mp;
-
- for (mp = machines; mp->name; mp++){
- if (mp->type == type || mp->boottype == type) {
- asstype = mp->asstype;
- machdata = mp->machdata;
- break;
- }
- }
-}
-/*
- * select a machine by name
- */
-int
-machbyname(char *name)
-{
- Machtab *mp;
-
- if (!name) {
- asstype = AAMD64;
- machdata = &i386mach;
- mach = &mamd64;
- return 1;
- }
- for (mp = machines; mp->name; mp++){
- if (strcmp(mp->name, name) == 0) {
- asstype = mp->asstype;
- machdata = mp->machdata;
- mach = mp->mach;
- return 1;
- }
- }
- return 0;
-}
diff --git a/src/libmach/swap.c b/src/libmach/swap.c
deleted file mode 100644
index bc296a3d7..000000000
--- a/src/libmach/swap.c
+++ /dev/null
@@ -1,107 +0,0 @@
-// Inferno libmach/swap.c
-// http://code.google.com/p/inferno-os/source/browse/utils/libmach/swap.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc.
-// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
-// Portions Copyright © 1997-1999 Vita Nuova Limited.
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-
-/*
- * big-endian short
- */
-ushort
-beswab(ushort s)
-{
- uchar *p;
-
- p = (uchar*)&s;
- return (p[0]<<8) | p[1];
-}
-
-/*
- * big-endian int32
- */
-uint32
-beswal(uint32 l)
-{
- uchar *p;
-
- p = (uchar*)&l;
- return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
-}
-
-/*
- * big-endian vlong
- */
-uvlong
-beswav(uvlong v)
-{
- uchar *p;
-
- p = (uchar*)&v;
- return ((uvlong)p[0]<<56) | ((uvlong)p[1]<<48) | ((uvlong)p[2]<<40)
- | ((uvlong)p[3]<<32) | ((uvlong)p[4]<<24)
- | ((uvlong)p[5]<<16) | ((uvlong)p[6]<<8)
- | (uvlong)p[7];
-}
-
-/*
- * little-endian short
- */
-ushort
-leswab(ushort s)
-{
- uchar *p;
-
- p = (uchar*)&s;
- return (p[1]<<8) | p[0];
-}
-
-/*
- * little-endian int32
- */
-uint32
-leswal(uint32 l)
-{
- uchar *p;
-
- p = (uchar*)&l;
- return (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0];
-}
-
-/*
- * little-endian vlong
- */
-uvlong
-leswav(uvlong v)
-{
- uchar *p;
-
- p = (uchar*)&v;
- return ((uvlong)p[7]<<56) | ((uvlong)p[6]<<48) | ((uvlong)p[5]<<40)
- | ((uvlong)p[4]<<32) | ((uvlong)p[3]<<24)
- | ((uvlong)p[2]<<16) | ((uvlong)p[1]<<8)
- | (uvlong)p[0];
-}
diff --git a/src/libmach/sym.c b/src/libmach/sym.c
deleted file mode 100644
index 474cc0c62..000000000
--- a/src/libmach/sym.c
+++ /dev/null
@@ -1,1883 +0,0 @@
-// Inferno libmach/sym.c
-// http://code.google.com/p/inferno-os/source/browse/utils/libmach/sym.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc.
-// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
-// Portions Copyright © 1997-1999 Vita Nuova Limited.
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-
-#define HUGEINT 0x7fffffff
-#define NNAME 20 /* a relic of the past */
-
-typedef struct txtsym Txtsym;
-typedef struct file File;
-typedef struct hist Hist;
-
-struct txtsym { /* Text Symbol table */
- int n; /* number of local vars */
- Sym **locals; /* array of ptrs to autos */
- Sym *sym; /* function symbol entry */
-};
-
-struct hist { /* Stack of include files & #line directives */
- char *name; /* Assumes names Null terminated in file */
- int32 line; /* line # where it was included */
- int32 offset; /* line # of #line directive */
-};
-
-struct file { /* Per input file header to history stack */
- uvlong addr; /* address of first text sym */
- union {
- Txtsym *txt; /* first text symbol */
- Sym *sym; /* only during initilization */
- };
- int n; /* size of history stack */
- Hist *hist; /* history stack */
-};
-
-static int debug = 0;
-
-static Sym **autos; /* Base of auto variables */
-static File *files; /* Base of file arena */
-static int fmaxi; /* largest file path index */
-static Sym **fnames; /* file names path component table */
-static Sym **globals; /* globals by addr table */
-static Hist *hist; /* base of history stack */
-static int isbuilt; /* internal table init flag */
-static int32 nauto; /* number of automatics */
-static int32 nfiles; /* number of files */
-static int32 nglob; /* number of globals */
-static int32 nhist; /* number of history stack entries */
-static int32 nsym; /* number of symbols */
-static int ntxt; /* number of text symbols */
-static uchar *pcline; /* start of pc-line state table */
-static uchar *pclineend; /* end of pc-line table */
-static uchar *spoff; /* start of pc-sp state table */
-static uchar *spoffend; /* end of pc-sp offset table */
-static Sym *symbols; /* symbol table */
-static Txtsym *txt; /* Base of text symbol table */
-static uvlong txtstart; /* start of text segment */
-static uvlong txtend; /* end of text segment */
-static uvlong firstinstr; /* as found from symtab; needed for amd64 */
-
-static void cleansyms(void);
-static int32 decodename(Biobuf*, Sym*);
-static short *encfname(char*);
-static int fline(char*, int, int32, Hist*, Hist**);
-static void fillsym(Sym*, Symbol*);
-static int findglobal(char*, Symbol*);
-static int findlocvar(Symbol*, char *, Symbol*);
-static int findtext(char*, Symbol*);
-static int hcomp(Hist*, short*);
-static int hline(File*, short*, int32*);
-static void printhist(char*, Hist*, int);
-static int buildtbls(void);
-static int symcomp(const void*, const void*);
-static int symerrmsg(int, char*);
-static int txtcomp(const void*, const void*);
-static int filecomp(const void*, const void*);
-
-/*
- * Go 1.2 pcln table (also contains pcsp).
- */
-#define Go12PclnMagic 0xfffffffb
-#define Go12PclnMagicRev 0xfbffffff
-static int isgo12pcline(void);
-static uvlong go12pc2sp(uvlong);
-static int32 go12fileline(char*, int, uvlong);
-static void go12clean(void);
-static uvlong go12file2pc(char*, int);
-
-/*
- * initialize the symbol tables
- */
-int
-syminit(int fd, Fhdr *fp)
-{
- Sym *p;
- int32 i, l, size, symsz;
- vlong vl;
- Biobuf b;
- int svalsz, newformat, shift;
- uvlong (*swav)(uvlong);
- uint32 (*swal)(uint32);
- uchar buf[8], c;
-
- if(fp->symsz == 0)
- return 0;
- if(fp->type == FNONE)
- return 0;
-
- swav = beswav;
- swal = beswal;
-
- cleansyms();
- textseg(fp->txtaddr, fp);
- /* minimum symbol record size = 4+1+2 bytes */
- symbols = malloc((fp->symsz/(4+1+2)+1)*sizeof(Sym));
- if(symbols == 0) {
- werrstr("can't malloc %d bytes", fp->symsz);
- return -1;
- }
- Binit(&b, fd, OREAD);
- Bseek(&b, fp->symoff, 0);
- memset(buf, 0, sizeof buf);
- Bread(&b, buf, sizeof buf);
- newformat = 0;
- symsz = fp->symsz;
- if(memcmp(buf, "\xfd\xff\xff\xff\x00\x00\x00", 7) == 0) {
- swav = leswav;
- swal = leswal;
- newformat = 1;
- } else if(memcmp(buf, "\xff\xff\xff\xfd\x00\x00\x00", 7) == 0) {
- newformat = 1;
- } else if(memcmp(buf, "\xfe\xff\xff\xff\x00\x00", 6) == 0) {
- // Table format used between Go 1.0 and Go 1.1:
- // little-endian but otherwise same as the old Go 1.0 table.
- // Not likely to be seen much in practice, but easy to handle.
- swav = leswav;
- swal = leswal;
- Bseek(&b, fp->symoff+6, 0);
- symsz -= 6;
- } else {
- Bseek(&b, fp->symoff, 0);
- }
- svalsz = 0;
- if(newformat) {
- svalsz = buf[7];
- if(svalsz != 4 && svalsz != 8) {
- werrstr("invalid word size %d bytes", svalsz);
- return -1;
- }
- symsz -= 8;
- }
-
- nsym = 0;
- size = 0;
- for(p = symbols; size < symsz; p++, nsym++) {
- if(newformat) {
- // Go 1.1 format. See comment at top of ../pkg/runtime/symtab.c.
- if(Bread(&b, &c, 1) != 1)
- return symerrmsg(1, "symbol");
- if((c&0x3F) < 26)
- p->type = (c&0x3F)+ 'A';
- else
- p->type = (c&0x3F) - 26 + 'a';
- size++;
-
- if(c&0x40) {
- // Fixed-width address.
- if(svalsz == 8) {
- if(Bread(&b, &vl, 8) != 8)
- return symerrmsg(8, "symbol");
- p->value = swav(vl);
- } else {
- if(Bread(&b, &l, 4) != 4)
- return symerrmsg(4, "symbol");
- p->value = (u32int)swal(l);
- }
- size += svalsz;
- } else {
- // Varint address.
- shift = 0;
- p->value = 0;
- for(;;) {
- if(Bread(&b, buf, 1) != 1)
- return symerrmsg(1, "symbol");
- p->value |= (uint64)(buf[0]&0x7F)<<shift;
- shift += 7;
- size++;
- if((buf[0]&0x80) == 0)
- break;
- }
- }
- p->gotype = 0;
- if(c&0x80) {
- // Has Go type. Fixed-width address.
- if(svalsz == 8) {
- if(Bread(&b, &vl, 8) != 8)
- return symerrmsg(8, "symbol");
- p->gotype = swav(vl);
- } else {
- if(Bread(&b, &l, 4) != 4)
- return symerrmsg(4, "symbol");
- p->gotype = (u32int)swal(l);
- }
- size += svalsz;
- }
-
- // Name.
- p->type |= 0x80; // for decodename
- i = decodename(&b, p);
- if(i < 0)
- return -1;
- size += i;
- } else {
- // Go 1.0 format: Plan 9 format + go type symbol.
- if(fp->_magic && (fp->magic & HDR_MAGIC)){
- svalsz = 8;
- if(Bread(&b, &vl, 8) != 8)
- return symerrmsg(8, "symbol");
- p->value = swav(vl);
- }
- else{
- svalsz = 4;
- if(Bread(&b, &l, 4) != 4)
- return symerrmsg(4, "symbol");
- p->value = (u32int)swal(l);
- }
- if(Bread(&b, &p->type, sizeof(p->type)) != sizeof(p->type))
- return symerrmsg(sizeof(p->value), "symbol");
-
- i = decodename(&b, p);
- if(i < 0)
- return -1;
- size += i+svalsz+sizeof(p->type);
-
- if(svalsz == 8){
- if(Bread(&b, &vl, 8) != 8)
- return symerrmsg(8, "symbol");
- p->gotype = swav(vl);
- }
- else{
- if(Bread(&b, &l, 4) != 4)
- return symerrmsg(4, "symbol");
- p->gotype = (u32int)swal(l);
- }
- size += svalsz;
- }
-
- /* count global & auto vars, text symbols, and file names */
- switch (p->type) {
- case 'l':
- case 'L':
- case 't':
- case 'T':
- ntxt++;
- break;
- case 'd':
- case 'D':
- case 'b':
- case 'B':
- nglob++;
- break;
- case 'f':
- if(strcmp(p->name, ".frame") == 0) {
- p->type = 'm';
- nauto++;
- }
- else if(p->value > fmaxi)
- fmaxi = p->value; /* highest path index */
- break;
- case 'a':
- case 'p':
- case 'm':
- nauto++;
- break;
- case 'z':
- if(p->value == 1) { /* one extra per file */
- nhist++;
- nfiles++;
- }
- nhist++;
- break;
- default:
- break;
- }
- }
- if (debug)
- print("NG: %d NT: %d NF: %d\n", nglob, ntxt, fmaxi);
- if (fp->sppcsz) { /* pc-sp offset table */
- spoff = (uchar *)malloc(fp->sppcsz);
- if(spoff == 0) {
- werrstr("can't malloc %d bytes", fp->sppcsz);
- return -1;
- }
- Bseek(&b, fp->sppcoff, 0);
- if(Bread(&b, spoff, fp->sppcsz) != fp->sppcsz){
- spoff = 0;
- return symerrmsg(fp->sppcsz, "sp-pc");
- }
- spoffend = spoff+fp->sppcsz;
- }
- if (fp->lnpcsz) { /* pc-line number table */
- pcline = (uchar *)malloc(fp->lnpcsz);
- if(pcline == 0) {
- werrstr("can't malloc %d bytes", fp->lnpcsz);
- return -1;
- }
- Bseek(&b, fp->lnpcoff, 0);
- if(Bread(&b, pcline, fp->lnpcsz) != fp->lnpcsz){
- pcline = 0;
- return symerrmsg(fp->lnpcsz, "pc-line");
- }
- pclineend = pcline+fp->lnpcsz;
- }
- return nsym;
-}
-
-static int
-symerrmsg(int n, char *table)
-{
- werrstr("can't read %d bytes of %s table", n, table);
- return -1;
-}
-
-static int32
-decodename(Biobuf *bp, Sym *p)
-{
- char *cp;
- int c1, c2;
- int32 n;
- vlong o;
-
- if((p->type & 0x80) == 0) { /* old-style, fixed length names */
- p->name = malloc(NNAME);
- if(p->name == 0) {
- werrstr("can't malloc %d bytes", NNAME);
- return -1;
- }
- if(Bread(bp, p->name, NNAME) != NNAME)
- return symerrmsg(NNAME, "symbol");
- Bseek(bp, 3, 1);
- return NNAME+3;
- }
-
- p->type &= ~0x80;
- if(p->type == 'z' || p->type == 'Z') {
- o = Bseek(bp, 0, 1);
- if(BGETC(bp) < 0) {
- werrstr("can't read symbol name");
- return -1;
- }
- for(;;) {
- c1 = BGETC(bp);
- c2 = BGETC(bp);
- if(c1 < 0 || c2 < 0) {
- werrstr("can't read symbol name");
- return -1;
- }
- if(c1 == 0 && c2 == 0)
- break;
- }
- n = Bseek(bp, 0, 1)-o;
- p->name = malloc(n);
- if(p->name == 0) {
- werrstr("can't malloc %d bytes", n);
- return -1;
- }
- Bseek(bp, -n, 1);
- if(Bread(bp, p->name, n) != n) {
- werrstr("can't read %d bytes of symbol name", n);
- return -1;
- }
- } else {
- cp = Brdline(bp, '\0');
- if(cp == 0) {
- werrstr("can't read symbol name");
- return -1;
- }
- n = Blinelen(bp);
- p->name = malloc(n);
- if(p->name == 0) {
- werrstr("can't malloc %d bytes", n);
- return -1;
- }
- strcpy(p->name, cp);
- }
- return n;
-}
-
-/*
- * free any previously loaded symbol tables
- */
-static void
-cleansyms(void)
-{
- if(globals)
- free(globals);
- globals = 0;
- nglob = 0;
- if(txt)
- free(txt);
- txt = 0;
- ntxt = 0;
- if(fnames)
- free(fnames);
- fnames = 0;
- fmaxi = 0;
-
- if(files)
- free(files);
- files = 0;
- nfiles = 0;
- if(hist)
- free(hist);
- hist = 0;
- nhist = 0;
- if(autos)
- free(autos);
- autos = 0;
- nauto = 0;
- isbuilt = 0;
- if(symbols)
- free(symbols);
- symbols = 0;
- nsym = 0;
- if(spoff)
- free(spoff);
- spoff = 0;
- if(pcline)
- free(pcline);
- pcline = 0;
- go12clean();
-}
-
-/*
- * delimit the text segment
- */
-void
-textseg(uvlong base, Fhdr *fp)
-{
- txtstart = base;
- txtend = base+fp->txtsz;
-}
-
-/*
- * symbase: return base and size of raw symbol table
- * (special hack for high access rate operations)
- */
-Sym *
-symbase(int32 *n)
-{
- *n = nsym;
- return symbols;
-}
-
-/*
- * Get the ith symbol table entry
- */
-Sym *
-getsym(int index)
-{
- if(index >= 0 && index < nsym)
- return &symbols[index];
- return 0;
-}
-
-/*
- * initialize internal symbol tables
- */
-static int
-buildtbls(void)
-{
- int32 i;
- int j, nh, ng, nt;
- File *f;
- Txtsym *tp;
- Hist *hp;
- Sym *p, **ap;
-
- if(isbuilt)
- return 1;
- isbuilt = 1;
- /* allocate the tables */
- firstinstr = 0;
- if(nglob) {
- globals = malloc(nglob*sizeof(*globals));
- if(!globals) {
- werrstr("can't malloc global symbol table");
- return 0;
- }
- }
- if(ntxt) {
- txt = malloc(ntxt*sizeof(*txt));
- if (!txt) {
- werrstr("can't malloc text symbol table");
- return 0;
- }
- }
- fnames = malloc((fmaxi+1)*sizeof(*fnames));
- if (!fnames) {
- werrstr("can't malloc file name table");
- return 0;
- }
- memset(fnames, 0, (fmaxi+1)*sizeof(*fnames));
- files = malloc(nfiles*sizeof(*files));
- if(!files) {
- werrstr("can't malloc file table");
- return 0;
- }
- hist = malloc(nhist*sizeof(Hist));
- if(hist == 0) {
- werrstr("can't malloc history stack");
- return 0;
- }
- autos = malloc(nauto*sizeof(Sym*));
- if(autos == 0) {
- werrstr("can't malloc auto symbol table");
- return 0;
- }
- /* load the tables */
- ng = nt = nh = 0;
- f = 0;
- tp = 0;
- i = nsym;
- hp = hist;
- ap = autos;
- for(p = symbols; i-- > 0; p++) {
-//print("sym %d type %c name %s value %llux\n", p-symbols, p->type, p->name, p->value);
- switch(p->type) {
- case 'D':
- case 'd':
- case 'B':
- case 'b':
- if(debug)
- print("Global: %s %llux\n", p->name, p->value);
- globals[ng++] = p;
- break;
- case 'z':
- if(p->value == 1) { /* New file */
- if(f) {
- f->n = nh;
- f->hist[nh].name = 0; /* one extra */
- hp += nh+1;
- f++;
- }
- else
- f = files;
- f->hist = hp;
- f->sym = 0;
- f->addr = 0;
- nh = 0;
- }
- /* alloc one slot extra as terminator */
- f->hist[nh].name = p->name;
- f->hist[nh].line = p->value;
- f->hist[nh].offset = 0;
- if(debug)
- printhist("-> ", &f->hist[nh], 1);
- nh++;
- break;
- case 'Z':
- if(f && nh > 0)
- f->hist[nh-1].offset = p->value;
- break;
- case 'T':
- case 't': /* Text: terminate history if first in file */
- case 'L':
- case 'l':
- tp = &txt[nt++];
- tp->n = 0;
- tp->sym = p;
- tp->locals = ap;
- if(debug)
- print("TEXT: %s at %llux\n", p->name, p->value);
- if (firstinstr == 0 || p->value < firstinstr)
- firstinstr = p->value;
- if(f && !f->sym) { /* first */
- f->sym = p;
- f->addr = p->value;
- }
- break;
- case 'a':
- case 'p':
- case 'm': /* Local Vars */
- if(!tp)
- print("Warning: Free floating local var: %s\n",
- p->name);
- else {
- if(debug)
- print("Local: %s %llux\n", p->name, p->value);
- tp->locals[tp->n] = p;
- tp->n++;
- ap++;
- }
- break;
- case 'f': /* File names */
- if(debug)
- print("Fname: %s\n", p->name);
- fnames[p->value] = p;
- break;
- default:
- break;
- }
- }
- /* sort global and text tables into ascending address order */
- qsort(globals, nglob, sizeof(Sym*), symcomp);
- qsort(txt, ntxt, sizeof(Txtsym), txtcomp);
- qsort(files, nfiles, sizeof(File), filecomp);
- tp = txt;
- for(i = 0, f = files; i < nfiles; i++, f++) {
- for(j = 0; j < ntxt; j++) {
- if(f->sym == tp->sym) {
- if(debug) {
- print("LINK: %s to at %llux", f->sym->name, f->addr);
- printhist("... ", f->hist, 1);
- }
- f->txt = tp++;
- break;
- }
- if(++tp >= txt+ntxt) /* wrap around */
- tp = txt;
- }
- }
- return 1;
-}
-
-/*
- * find symbol function.var by name.
- * fn != 0 && var != 0 => look for fn in text, var in data
- * fn != 0 && var == 0 => look for fn in text
- * fn == 0 && var != 0 => look for var first in text then in data space.
- */
-int
-lookup(char *fn, char *var, Symbol *s)
-{
- int found;
-
- if(buildtbls() == 0)
- return 0;
- if(fn) {
- found = findtext(fn, s);
- if(var == 0) /* case 2: fn not in text */
- return found;
- else if(!found) /* case 1: fn not found */
- return 0;
- } else if(var) {
- found = findtext(var, s);
- if(found)
- return 1; /* case 3: var found in text */
- } else return 0; /* case 4: fn & var == zero */
-
- if(found)
- return findlocal(s, var, s); /* case 1: fn found */
- return findglobal(var, s); /* case 3: var not found */
-
-}
-
-/*
- * strcmp, but allow '_' to match center dot (rune 00b7 == bytes c2 b7)
- */
-int
-cdotstrcmp(char *sym, char *user)
-{
- for (;;) {
- while (*sym == *user) {
- if (*sym++ == '\0')
- return 0;
- user++;
- }
- /* unequal - but maybe '_' matches center dot */
- if (user[0] == '_' && (sym[0]&0xFF) == 0xc2 && (sym[1]&0xFF) == 0xb7) {
- /* '_' matches center dot - advance and continue */
- user++;
- sym += 2;
- continue;
- }
- break;
- }
- return *user - *sym;
-}
-
-/*
- * find a function by name
- */
-static int
-findtext(char *name, Symbol *s)
-{
- int i;
-
- for(i = 0; i < ntxt; i++) {
- if(cdotstrcmp(txt[i].sym->name, name) == 0) {
- fillsym(txt[i].sym, s);
- s->handle = (void *) &txt[i];
- s->index = i;
- return 1;
- }
- }
- return 0;
-}
-/*
- * find global variable by name
- */
-static int
-findglobal(char *name, Symbol *s)
-{
- int32 i;
-
- for(i = 0; i < nglob; i++) {
- if(cdotstrcmp(globals[i]->name, name) == 0) {
- fillsym(globals[i], s);
- s->index = i;
- return 1;
- }
- }
- return 0;
-}
-
-/*
- * find the local variable by name within a given function
- */
-int
-findlocal(Symbol *s1, char *name, Symbol *s2)
-{
- if(s1 == 0)
- return 0;
- if(buildtbls() == 0)
- return 0;
- return findlocvar(s1, name, s2);
-}
-
-/*
- * find the local variable by name within a given function
- * (internal function - does no parameter validation)
- */
-static int
-findlocvar(Symbol *s1, char *name, Symbol *s2)
-{
- Txtsym *tp;
- int i;
-
- tp = (Txtsym *)s1->handle;
- if(tp && tp->locals) {
- for(i = 0; i < tp->n; i++)
- if (cdotstrcmp(tp->locals[i]->name, name) == 0) {
- fillsym(tp->locals[i], s2);
- s2->handle = (void *)tp;
- s2->index = tp->n-1 - i;
- return 1;
- }
- }
- return 0;
-}
-
-/*
- * Get ith text symbol
- */
-int
-textsym(Symbol *s, int index)
-{
-
- if(buildtbls() == 0)
- return 0;
- if(index < 0 || index >= ntxt)
- return 0;
- fillsym(txt[index].sym, s);
- s->handle = (void *)&txt[index];
- s->index = index;
- return 1;
-}
-
-/*
- * Get ith file name
- */
-int
-filesym(int index, char *buf, int n)
-{
- Hist *hp;
-
- if(buildtbls() == 0)
- return 0;
- if(index < 0 || index >= nfiles)
- return 0;
- hp = files[index].hist;
- if(!hp || !hp->name)
- return 0;
- return fileelem(fnames, (uchar*)hp->name, buf, n);
-}
-
-/*
- * Lookup name of local variable located at an offset into the frame.
- * The type selects either a parameter or automatic.
- */
-int
-getauto(Symbol *s1, int off, int type, Symbol *s2)
-{
- Txtsym *tp;
- Sym *p;
- int i, t;
-
- if(s1 == 0)
- return 0;
- if(type == CPARAM)
- t = 'p';
- else if(type == CAUTO)
- t = 'a';
- else
- return 0;
- if(buildtbls() == 0)
- return 0;
- tp = (Txtsym *)s1->handle;
- if(tp == 0)
- return 0;
- for(i = 0; i < tp->n; i++) {
- p = tp->locals[i];
- if(p->type == t && p->value == off) {
- fillsym(p, s2);
- s2->handle = s1->handle;
- s2->index = tp->n-1 - i;
- return 1;
- }
- }
- return 0;
-}
-
-/*
- * Find text symbol containing addr; binary search assumes text array is sorted by addr
- */
-static int
-srchtext(uvlong addr)
-{
- uvlong val;
- int top, bot, mid;
- Sym *sp;
-
- val = addr;
- bot = 0;
- top = ntxt;
- for (mid = (bot+top)/2; mid < top; mid = (bot+top)/2) {
- sp = txt[mid].sym;
- if(val < sp->value)
- top = mid;
- else if(mid != ntxt-1 && val >= txt[mid+1].sym->value)
- bot = mid;
- else
- return mid;
- }
- return -1;
-}
-
-/*
- * Find data symbol containing addr; binary search assumes data array is sorted by addr
- */
-static int
-srchdata(uvlong addr)
-{
- uvlong val;
- int top, bot, mid;
- Sym *sp;
-
- bot = 0;
- top = nglob;
- val = addr;
- for(mid = (bot+top)/2; mid < top; mid = (bot+top)/2) {
- sp = globals[mid];
- if(val < sp->value)
- top = mid;
- else if(mid < nglob-1 && val >= globals[mid+1]->value)
- bot = mid;
- else
- return mid;
- }
- return -1;
-}
-
-/*
- * Find symbol containing val in specified search space
- * There is a special case when a value falls beyond the end
- * of the text segment; if the search space is CTEXT, that value
- * (usually etext) is returned. If the search space is CANY, symbols in the
- * data space are searched for a match.
- */
-int
-findsym(uvlong val, int type, Symbol *s)
-{
- int i;
-
- if(buildtbls() == 0)
- return 0;
-
- if(type == CTEXT || type == CANY) {
- i = srchtext(val);
- if(i >= 0) {
- if(type == CTEXT || i != ntxt-1) {
- fillsym(txt[i].sym, s);
- s->handle = (void *) &txt[i];
- s->index = i;
- return 1;
- }
- }
- }
- if(type == CDATA || type == CANY) {
- i = srchdata(val);
- if(i >= 0) {
- fillsym(globals[i], s);
- s->index = i;
- return 1;
- }
- }
- return 0;
-}
-
-/*
- * Find the start and end address of the function containing addr
- */
-int
-fnbound(uvlong addr, uvlong *bounds)
-{
- int i;
-
- if(buildtbls() == 0)
- return 0;
-
- i = srchtext(addr);
- if(0 <= i && i < ntxt-1) {
- bounds[0] = txt[i].sym->value;
- bounds[1] = txt[i+1].sym->value;
- return 1;
- }
- return 0;
-}
-
-/*
- * get the ith local symbol for a function
- * the input symbol table is reverse ordered, so we reverse
- * accesses here to maintain approx. parameter ordering in a stack trace.
- */
-int
-localsym(Symbol *s, int index)
-{
- Txtsym *tp;
-
- if(s == 0 || index < 0)
- return 0;
- if(buildtbls() == 0)
- return 0;
-
- tp = (Txtsym *)s->handle;
- if(tp && tp->locals && index < tp->n) {
- fillsym(tp->locals[tp->n-index-1], s); /* reverse */
- s->handle = (void *)tp;
- s->index = index;
- return 1;
- }
- return 0;
-}
-
-/*
- * get the ith global symbol
- */
-int
-globalsym(Symbol *s, int index)
-{
- if(s == 0)
- return 0;
- if(buildtbls() == 0)
- return 0;
-
- if(index >=0 && index < nglob) {
- fillsym(globals[index], s);
- s->index = index;
- return 1;
- }
- return 0;
-}
-
-/*
- * find the pc given a file name and line offset into it.
- */
-uvlong
-file2pc(char *file, int32 line)
-{
- File *fp;
- int32 i;
- uvlong pc, start, end;
- short *name;
-
- if(isgo12pcline())
- return go12file2pc(file, line);
- if(buildtbls() == 0 || files == 0)
- return ~(uvlong)0;
- name = encfname(file);
- if(name == 0) { /* encode the file name */
- werrstr("file %s not found", file);
- return ~(uvlong)0;
- }
- /* find this history stack */
- for(i = 0, fp = files; i < nfiles; i++, fp++)
- if (hline(fp, name, &line))
- break;
- free(name);
- if(i >= nfiles) {
- werrstr("line %d in file %s not found", line, file);
- return ~(uvlong)0;
- }
- start = fp->addr; /* first text addr this file */
- if(i < nfiles-1)
- end = (fp+1)->addr; /* first text addr next file */
- else
- end = 0; /* last file in load module */
- /*
- * At this point, line contains the offset into the file.
- * run the state machine to locate the pc closest to that value.
- */
- if(debug)
- print("find pc for %d - between: %llux and %llux\n", line, start, end);
- pc = line2addr(line, start, end);
- if(pc == ~(uvlong)0) {
- werrstr("line %d not in file %s", line, file);
- return ~(uvlong)0;
- }
- return pc;
-}
-
-/*
- * search for a path component index
- */
-static int
-pathcomp(char *s, int n)
-{
- int i;
-
- for(i = 0; i <= fmaxi; i++)
- if(fnames[i] && strncmp(s, fnames[i]->name, n) == 0)
- return i;
- return -1;
-}
-
-/*
- * Encode a char file name as a sequence of short indices
- * into the file name dictionary.
- */
-static short*
-encfname(char *file)
-{
- int i, j;
- char *cp, *cp2;
- short *dest;
-
- if(*file == '/') /* always check first '/' */
- cp2 = file+1;
- else {
- cp2 = strchr(file, '/');
- if(!cp2)
- cp2 = strchr(file, 0);
- }
- cp = file;
- dest = 0;
- for(i = 0; *cp; i++) {
- j = pathcomp(cp, cp2-cp);
- if(j < 0)
- return 0; /* not found */
- dest = realloc(dest, (i+1)*sizeof(short));
- dest[i] = j;
- cp = cp2;
- while(*cp == '/') /* skip embedded '/'s */
- cp++;
- cp2 = strchr(cp, '/');
- if(!cp2)
- cp2 = strchr(cp, 0);
- }
- dest = realloc(dest, (i+1)*sizeof(short));
- dest[i] = 0;
- return dest;
-}
-
-/*
- * Search a history stack for a matching file name accumulating
- * the size of intervening files in the stack.
- */
-static int
-hline(File *fp, short *name, int32 *line)
-{
- Hist *hp;
- int offset, depth;
- int32 ln;
-
- for(hp = fp->hist; hp->name; hp++) /* find name in stack */
- if(hp->name[1] || hp->name[2]) {
- if(hcomp(hp, name))
- break;
- }
- if(!hp->name) /* match not found */
- return 0;
- if(debug)
- printhist("hline found ... ", hp, 1);
- /*
- * unwind the stack until empty or we hit an entry beyond our line
- */
- ln = *line;
- offset = hp->line-1;
- depth = 1;
- for(hp++; depth && hp->name; hp++) {
- if(debug)
- printhist("hline inspect ... ", hp, 1);
- if(hp->name[1] || hp->name[2]) {
- if(hp->offset){ /* Z record */
- offset = 0;
- if(hcomp(hp, name)) {
- if(*line <= hp->offset)
- break;
- ln = *line+hp->line-hp->offset;
- depth = 1; /* implicit pop */
- } else
- depth = 2; /* implicit push */
- } else if(depth == 1 && ln < hp->line-offset)
- break; /* Beyond our line */
- else if(depth++ == 1) /* push */
- offset -= hp->line;
- } else if(--depth == 1) /* pop */
- offset += hp->line;
- }
- *line = ln+offset;
- return 1;
-}
-
-/*
- * compare two encoded file names
- */
-static int
-hcomp(Hist *hp, short *sp)
-{
- uchar *cp;
- int i, j;
- short *s;
-
- cp = (uchar *)hp->name;
- s = sp;
- if (*s == 0)
- return 0;
- for (i = 1; j = (cp[i]<<8)|cp[i+1]; i += 2) {
- if(j == 0)
- break;
- if(*s == j)
- s++;
- else
- s = sp;
- }
- return *s == 0;
-}
-
-/*
- * Convert a pc to a "file:line {file:line}" string.
- */
-int32
-fileline(char *str, int n, uvlong dot)
-{
- int32 line, top, bot, mid;
- File *f;
-
- if(isgo12pcline())
- return go12fileline(str, n, dot);
-
- *str = 0;
- if(buildtbls() == 0)
- return 0;
- /* binary search assumes file list is sorted by addr */
- bot = 0;
- top = nfiles;
- for (mid = (bot+top)/2; mid < top; mid = (bot+top)/2) {
- f = &files[mid];
- if(dot < f->addr)
- top = mid;
- else if(mid < nfiles-1 && dot >= (f+1)->addr)
- bot = mid;
- else {
- line = pc2line(dot);
- if(line > 0 && fline(str, n, line, f->hist, 0) >= 0)
- return 1;
- break;
- }
- }
- return 0;
-}
-
-/*
- * Convert a line number within a composite file to relative line
- * number in a source file. A composite file is the source
- * file with included files inserted in line.
- */
-static int
-fline(char *str, int n, int32 line, Hist *base, Hist **ret)
-{
- Hist *start; /* start of current level */
- Hist *h; /* current entry */
- int32 delta; /* sum of size of files this level */
- int k;
-
- start = base;
- h = base;
- delta = h->line;
- while(h && h->name && line > h->line) {
- if(h->name[1] || h->name[2]) {
- if(h->offset != 0) { /* #line Directive */
- delta = h->line-h->offset+1;
- start = h;
- base = h++;
- } else { /* beginning of File */
- if(start == base)
- start = h++;
- else {
- k = fline(str, n, line, start, &h);
- if(k <= 0)
- return k;
- }
- }
- } else {
- if(start == base && ret) { /* end of recursion level */
- *ret = h;
- return 1;
- } else { /* end of included file */
- delta += h->line-start->line;
- h++;
- start = base;
- }
- }
- }
- if(!h)
- return -1;
- if(start != base)
- line = line-start->line+1;
- else
- line = line-delta+1;
- if(!h->name)
- strncpy(str, "<eof>", n);
- else {
- k = fileelem(fnames, (uchar*)start->name, str, n);
- if(k+8 < n)
- sprint(str+k, ":%d", line);
- }
-/**********Remove comments for complete back-trace of include sequence
- * if(start != base) {
- * k = strlen(str);
- * if(k+2 < n) {
- * str[k++] = ' ';
- * str[k++] = '{';
- * }
- * k += fileelem(fnames, (uchar*) base->name, str+k, n-k);
- * if(k+10 < n)
- * sprint(str+k, ":%ld}", start->line-delta);
- * }
- ********************/
- return 0;
-}
-
-/*
- * convert an encoded file name to a string.
- */
-int
-fileelem(Sym **fp, uchar *cp, char *buf, int n)
-{
- int i, j;
- char *c, *bp, *end;
-
- bp = buf;
- end = buf+n-1;
- for(i = 1; j = (cp[i]<<8)|cp[i+1]; i+=2){
- c = fp[j]->name;
- if(bp != buf && bp[-1] != '/' && bp < end)
- *bp++ = '/';
- while(bp < end && *c)
- *bp++ = *c++;
- }
- *bp = 0;
- i = bp-buf;
- if(i > 1) {
- cleanname(buf);
- i = strlen(buf);
- }
- return i;
-}
-
-/*
- * compare the values of two symbol table entries.
- */
-static int
-symcomp(const void *a, const void *b)
-{
- int i;
-
- i = (*(Sym**)a)->value - (*(Sym**)b)->value;
- if (i)
- return i;
- return strcmp((*(Sym**)a)->name, (*(Sym**)b)->name);
-}
-
-/*
- * compare the values of the symbols referenced by two text table entries
- */
-static int
-txtcomp(const void *a, const void *b)
-{
- return ((Txtsym*)a)->sym->value - ((Txtsym*)b)->sym->value;
-}
-
-/*
- * compare the values of the symbols referenced by two file table entries
- */
-static int
-filecomp(const void *a, const void *b)
-{
- return ((File*)a)->addr - ((File*)b)->addr;
-}
-
-/*
- * fill an interface Symbol structure from a symbol table entry
- */
-static void
-fillsym(Sym *sp, Symbol *s)
-{
- s->type = sp->type;
- s->value = sp->value;
- s->name = sp->name;
- s->index = 0;
- switch(sp->type) {
- case 'b':
- case 'B':
- case 'D':
- case 'd':
- s->class = CDATA;
- break;
- case 't':
- case 'T':
- case 'l':
- case 'L':
- s->class = CTEXT;
- break;
- case 'a':
- s->class = CAUTO;
- break;
- case 'p':
- s->class = CPARAM;
- break;
- case 'm':
- s->class = CSTAB;
- break;
- default:
- s->class = CNONE;
- break;
- }
- s->handle = 0;
-}
-
-/*
- * find the stack frame, given the pc
- */
-uvlong
-pc2sp(uvlong pc)
-{
- uchar *c, u;
- uvlong currpc, currsp;
-
- if(isgo12pcline())
- return go12pc2sp(pc);
-
- if(spoff == 0)
- return ~(uvlong)0;
- currsp = 0;
- currpc = txtstart - mach->pcquant;
-
- if(pc<currpc || pc>txtend)
- return ~(uvlong)0;
- for(c = spoff; c < spoffend; c++) {
- if (currpc >= pc)
- return currsp;
- u = *c;
- if (u == 0) {
- currsp += (c[1]<<24)|(c[2]<<16)|(c[3]<<8)|c[4];
- c += 4;
- }
- else if (u < 65)
- currsp += 4*u;
- else if (u < 129)
- currsp -= 4*(u-64);
- else
- currpc += mach->pcquant*(u-129);
- currpc += mach->pcquant;
- }
- return ~(uvlong)0;
-}
-
-/*
- * find the source file line number for a given value of the pc
- */
-int32
-pc2line(uvlong pc)
-{
- uchar *c, u;
- uvlong currpc;
- int32 currline;
-
- if(pcline == 0)
- return -1;
- currline = 0;
- if (firstinstr != 0)
- currpc = firstinstr-mach->pcquant;
- else
- currpc = txtstart-mach->pcquant;
- if(pc<currpc || pc>txtend)
- return -1;
-
- for(c = pcline; c < pclineend && currpc < pc; c++) {
- u = *c;
- if(u == 0) {
- currline += (c[1]<<24)|(c[2]<<16)|(c[3]<<8)|c[4];
- c += 4;
- }
- else if(u < 65)
- currline += u;
- else if(u < 129)
- currline -= (u-64);
- else
- currpc += mach->pcquant*(u-129);
- currpc += mach->pcquant;
- }
- return currline;
-}
-
-/*
- * find the pc associated with a line number
- * basepc and endpc are text addresses bounding the search.
- * if endpc == 0, the end of the table is used (i.e., no upper bound).
- * usually, basepc and endpc contain the first text address in
- * a file and the first text address in the following file, respectively.
- */
-uvlong
-line2addr(int32 line, uvlong basepc, uvlong endpc)
-{
- uchar *c, u;
- uvlong currpc, pc;
- int32 currline;
- int32 delta, d;
- int found;
-
- if(pcline == 0 || line == 0)
- return ~(uvlong)0;
-
- currline = 0;
- currpc = txtstart-mach->pcquant;
- pc = ~(uvlong)0;
- found = 0;
- delta = HUGEINT;
-
- for(c = pcline; c < pclineend; c++) {
- if(endpc && currpc >= endpc) /* end of file of interest */
- break;
- if(currpc >= basepc) { /* proper file */
- if(currline >= line) {
- d = currline-line;
- found = 1;
- } else
- d = line-currline;
- if(d < delta) {
- delta = d;
- pc = currpc;
- }
- }
- u = *c;
- if(u == 0) {
- currline += (c[1]<<24)|(c[2]<<16)|(c[3]<<8)|c[4];
- c += 4;
- }
- else if(u < 65)
- currline += u;
- else if(u < 129)
- currline -= (u-64);
- else
- currpc += mach->pcquant*(u-129);
- currpc += mach->pcquant;
- }
- if(found)
- return pc;
- return ~(uvlong)0;
-}
-
-/*
- * Print a history stack (debug). if count is 0, prints the whole stack
- */
-static void
-printhist(char *msg, Hist *hp, int count)
-{
- int i;
- uchar *cp;
- char buf[128];
-
- i = 0;
- while(hp->name) {
- if(count && ++i > count)
- break;
- print("%s Line: %x (%d) Offset: %x (%d) Name: ", msg,
- hp->line, hp->line, hp->offset, hp->offset);
- for(cp = (uchar *)hp->name+1; (*cp<<8)|cp[1]; cp += 2) {
- if (cp != (uchar *)hp->name+1)
- print("/");
- print("%x", (*cp<<8)|cp[1]);
- }
- fileelem(fnames, (uchar *) hp->name, buf, sizeof(buf));
- print(" (%s)\n", buf);
- hp++;
- }
-}
-
-#ifdef DEBUG
-/*
- * print the history stack for a file. (debug only)
- * if (name == 0) => print all history stacks.
- */
-void
-dumphist(char *name)
-{
- int i;
- File *f;
- short *fname;
-
- if(buildtbls() == 0)
- return;
- if(name)
- fname = encfname(name);
- for(i = 0, f = files; i < nfiles; i++, f++)
- if(fname == 0 || hcomp(f->hist, fname))
- printhist("> ", f->hist, f->n);
-
- if(fname)
- free(fname);
-}
-#endif
-
-// Go 1.2 pcln table
-// See golang.org/s/go12symtab.
-
-// Func layout
-#define FuncEntry (0)
-#define FuncName (pcptrsize)
-#define FuncArgs (pcptrsize+4)
-#define FuncFrame (pcptrsize+2*4)
-#define FuncPCSP (pcptrsize+3*4)
-#define FuncPCFile (pcptrsize+4*4)
-#define FuncPCLine (pcptrsize+5*4)
-
-static int32 pcquantum;
-static int32 pcptrsize;
-static uvlong (*pcswav)(uvlong);
-static uint32 (*pcswal)(uint32);
-static uvlong (*pcuintptr)(uchar*);
-static uchar *functab;
-static uint32 nfunctab;
-static uint32 *filetab;
-static uint32 nfiletab;
-
-static uint32
-xswal(uint32 v)
-{
- return (v>>24) | ((v>>8)&0xFF00) | ((v<<8)&0xFF0000) | v<<24;
-}
-
-static uvlong
-xswav(uvlong v)
-{
- return (uvlong)xswal(v)<<32 | xswal(v>>32);
-}
-
-static uvlong
-noswav(uvlong v)
-{
- return v;
-}
-
-static uint32
-noswal(uint32 v)
-{
- return v;
-}
-
-static uvlong
-readuintptr64(uchar *p)
-{
- return pcswav(*(uvlong*)p);
-}
-
-static uvlong
-readuintptr32(uchar *p)
-{
- return pcswal(*(uint32*)p);
-}
-
-static void
-go12clean(void)
-{
- pcquantum = 0;
- pcswav = nil;
- pcswal = nil;
- functab = nil;
- nfunctab = 0;
- filetab = nil;
- nfiletab = 0;
-}
-
-static void
-go12init(void)
-{
- uint32 m;
- uchar *p;
-
- if(pcquantum != 0)
- return;
- pcquantum = -1; // not go 1.2
- if(pcline == nil || pclineend - pcline < 16 ||
- pcline[4] != 0 || pcline[5] != 0 ||
- (pcline[6] != 1 && pcline[6] != 4) ||
- (pcline[7] != 4 && pcline[7] != 8))
- return;
-
- // header is magic, 00 00 pcquantum ptrsize
- m = *(uint32*)pcline;
- if(m == Go12PclnMagic) {
- pcswav = noswav;
- pcswal = noswal;
- } else {
- pcswav = xswav;
- pcswal = xswal;
- }
- pcptrsize = pcline[7];
-
- if(pcptrsize == 4)
- pcuintptr = readuintptr32;
- else
- pcuintptr = readuintptr64;
-
- nfunctab = pcuintptr(pcline+8);
- functab = pcline + 8 + pcptrsize;
-
- // functab is 2*nfunctab pointer-sized values.
- // The offset to the file table follows.
- p = functab + nfunctab*2*pcptrsize + pcptrsize;
- if(p+4 > pclineend)
- return;
- filetab = (uint32*)(pcline + pcswal(*(uint32*)p));
- if((uchar*)filetab+4 > pclineend)
- return;
-
- // File table begins with count.
- nfiletab = pcswal(filetab[0]);
- if((uchar*)(filetab + nfiletab) > pclineend)
- return;
-
- // Committed.
- pcquantum = pcline[6];
-}
-
-static int
-isgo12pcline(void)
-{
- go12init();
- return pcquantum > 0;
-}
-
-static uchar*
-go12findfunc(uvlong pc)
-{
- uchar *f, *fm;
- int32 nf, m;
-
- if(pc < pcuintptr(functab) || pc >= pcuintptr(functab+2*nfunctab*pcptrsize))
- return nil;
-
- // binary search to find func with entry <= addr.
- f = functab;
- nf = nfunctab;
- while(nf > 0) {
- m = nf/2;
- fm = f + 2*pcptrsize*m;
- if(pcuintptr(fm) <= pc && pc < pcuintptr(fm+2*pcptrsize)) {
- f = pcline + pcuintptr(fm+pcptrsize);
- if(f >= pclineend)
- return nil;
- return f;
- } else if(pc < pcuintptr(fm))
- nf = m;
- else {
- f += (m+1)*2*pcptrsize;
- nf -= m+1;
- }
- }
- return nil;
-}
-
-static uint32
-readvarint(uchar **pp)
-{
- uchar *p;
- uint32 v;
- int32 shift;
-
- v = 0;
- p = *pp;
- for(shift = 0;; shift += 7) {
- v |= (*p & 0x7F) << shift;
- if(!(*p++ & 0x80))
- break;
- }
- *pp = p;
- return v;
-}
-
-static char*
-pcstring(uint32 off)
-{
- if(off == 0 || off >= pclineend - pcline ||
- memchr(pcline + off, '\0', pclineend - (pcline + off)) == nil)
- return "?";
- return (char*)pcline+off;
-}
-
-
-static int
-step(uchar **pp, uvlong *pc, int32 *value, int first)
-{
- uint32 uvdelta, pcdelta;
- int32 vdelta;
-
- uvdelta = readvarint(pp);
- if(uvdelta == 0 && !first)
- return 0;
- if(uvdelta&1)
- uvdelta = ~(uvdelta>>1);
- else
- uvdelta >>= 1;
- vdelta = (int32)uvdelta;
- pcdelta = readvarint(pp) * pcquantum;
- *value += vdelta;
- *pc += pcdelta;
- return 1;
-}
-
-static int32
-pcvalue(uint32 off, uvlong entry, uvlong targetpc)
-{
- uvlong pc;
- int32 val;
- uchar *p;
-
- val = -1;
- pc = entry;
- if(off == 0 || off >= pclineend - pcline)
- return -1;
- p = pcline + off;
- while(step(&p, &pc, &val, pc == entry)) {
- if(targetpc < pc)
- return val;
- }
- return -1;
-}
-
-static uvlong
-go12pc2sp(uvlong pc)
-{
- uchar *f;
- uint32 off;
- uvlong entry;
- int32 sp;
-
- f = go12findfunc(pc);
- if(f == nil)
- return ~(uvlong)0;
- entry = pcuintptr(f+FuncEntry);
- off = pcswal(*(uint32*)(f+FuncPCSP));
- sp = pcvalue(off, entry, pc);
- if(sp < 0)
- return ~(uvlong)0;
- return sp;
-}
-
-static int32
-go12fileline(char *str, int n, uvlong pc)
-{
- uchar *f;
- uint32 fileoff, lineoff;
- uvlong entry;
- int lno, fno;
-
- f = go12findfunc(pc);
- if(f == nil)
- return 0;
- entry = pcuintptr(f+FuncEntry);
- fileoff = pcswal(*(uint32*)(f+FuncPCFile));
- lineoff = pcswal(*(uint32*)(f+FuncPCLine));
- lno = pcvalue(lineoff, entry, pc);
- fno = pcvalue(fileoff, entry, pc);
- if(lno < 0 || fno <= 0 || fno >= nfiletab) {
- return 0;
- }
- snprint(str, n, "%s:%d", pcstring(pcswal(filetab[fno])), lno);
- return 1;
-}
-
-static uvlong
-go12file2pc(char *file, int line)
-{
- int fno;
- int32 i, fval, lval;
- uchar *func, *fp, *lp;
- uvlong fpc, lpc, fstartpc, lstartpc, entry;
-
- // Map file to file number.
- // NOTE(rsc): Could introduce a hash table for repeated
- // lookups if anyone ever calls this.
- for(fno=1; fno<nfiletab; fno++)
- if(strcmp(pcstring(pcswal(filetab[fno])), file) == 0)
- goto havefile;
- werrstr("cannot find file");
- return ~(uvlong)0;
-
-havefile:
- // Consider each func.
- // Run file number program to find file match,
- // then run line number program to find line match.
- // Most file number programs are tiny, and most will
- // not mention the file number, so this should be fairly
- // quick.
- for(i=0; i<nfunctab; i++) {
- func = pcline + pcuintptr(functab+i*2*pcptrsize+pcptrsize);
- entry = pcuintptr(func+FuncEntry);
- fp = pcline + pcswal(*(uint32*)(func+FuncPCFile));
- lp = pcline + pcswal(*(uint32*)(func+FuncPCLine));
- fval = lval = -1;
- fpc = lpc = entry;
- fstartpc = fpc;
- while(step(&fp, &fpc, &fval, fpc==entry)) {
- if(fval == fno && fstartpc < fpc) {
- lstartpc = lpc;
- while(lpc < fpc && step(&lp, &lpc, &lval, lpc==entry)) {
- if(lval == line) {
- if(fstartpc <= lstartpc) {
- return lstartpc;
- }
- if(fstartpc < lpc) {
- return fstartpc;
- }
- }
- lstartpc = lpc;
- }
- }
- fstartpc = fpc;
- }
- }
- werrstr("cannot find line in file");
- return ~(uvlong)0;
-}
diff --git a/src/libmach/windows.c b/src/libmach/windows.c
deleted file mode 100644
index 9ffc3af01..000000000
--- a/src/libmach/windows.c
+++ /dev/null
@@ -1,87 +0,0 @@
-// This is stubbed out for the moment. Will revisit when the time comes.
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-
-int
-ctlproc(int pid, char *msg)
-{
- USED(pid);
- USED(msg);
- sysfatal("ctlproc unimplemented in Windows");
- return -1;
-}
-
-char*
-proctextfile(int pid)
-{
- USED(pid);
- sysfatal("proctextfile unimplemented in Windows");
- return nil;
-}
-
-char*
-procstatus(int pid)
-{
- USED(pid);
- sysfatal("procstatus unimplemented in Windows");
- return nil;
-}
-
-Map*
-attachproc(int pid, Fhdr *fp)
-{
- USED(pid);
- USED(fp);
- sysfatal("attachproc unimplemented in Windows");
- return nil;
-}
-
-void
-detachproc(Map *m)
-{
- USED(m);
- sysfatal("detachproc unimplemented in Windows");
-}
-
-int
-procthreadpids(int pid, int *p, int np)
-{
- USED(pid);
- USED(p);
- USED(np);
- sysfatal("procthreadpids unimplemented in Windows");
- return -1;
-}
-
-int
-pread(int fd, void *buf, int count, int offset)
-{
- int oldoffset, n;
-
- oldoffset = seek(fd, offset, 0);
- n = read(fd, buf, count);
- seek(fd, oldoffset, 0);
- return n;
-}
-
-int
-pwrite(int fd, void *buf, int count, int offset)
-{
- USED(fd);
- USED(buf);
- USED(count);
- USED(offset);
- sysfatal("pwrite unimplemented in Windows");
- return -1;
-}
-
-int
-nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
-{
- USED(rqtp);
- USED(rmtp);
- sysfatal("nanosleep unimplemented in Windows");
- return -1;
-}