1
0
mirror of https://github.com/golang/go synced 2024-11-21 19:14:44 -07:00
SVN=122505
This commit is contained in:
Rob Pike 2008-06-12 14:50:25 -07:00
parent ef61a4cb1e
commit ed5e39a66d
21 changed files with 7652 additions and 1 deletions

169
include/bootexec.h Normal file
View File

@ -0,0 +1,169 @@
// Inferno libmach/bootexec.h
// http://code.google.com/p/inferno-os/source/browse/utils/libmach/bootexec.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.
struct coffsect
{
char name[8];
ulong phys;
ulong virt;
ulong size;
ulong fptr;
ulong fptrreloc;
ulong fptrlineno;
ulong nrelocnlineno;
ulong flags;
};
/*
* proprietary exec headers, needed to bootstrap various machines
*/
struct mipsexec
{
short mmagic; /* (0x160) mips magic number */
short nscns; /* (unused) number of sections */
long timdat; /* (unused) time & date stamp */
long symptr; /* offset to symbol table */
long nsyms; /* size of symbol table */
short opthdr; /* (0x38) sizeof(optional hdr) */
short pcszs; /* flags */
short amagic; /* see above */
short vstamp; /* version stamp */
long tsize; /* text size in bytes */
long dsize; /* initialized data */
long bsize; /* uninitialized data */
long mentry; /* entry pt. */
long text_start; /* base of text used for this file */
long data_start; /* base of data used for this file */
long bss_start; /* base of bss used for this file */
long gprmask; /* general purpose register mask */
union{
long cprmask[4]; /* co-processor register masks */
long pcsize;
};
long gp_value; /* the gp value used for this object */
};
struct mips4kexec
{
struct mipsexec h;
struct coffsect itexts;
struct coffsect idatas;
struct coffsect ibsss;
};
struct sparcexec
{
short sjunk; /* dynamic bit and version number */
short smagic; /* 0407 */
ulong stext;
ulong sdata;
ulong sbss;
ulong ssyms;
ulong sentry;
ulong strsize;
ulong sdrsize;
};
struct nextexec
{
/* UNUSED
struct nexthdr{
ulong nmagic;
ulong ncputype;
ulong ncpusubtype;
ulong nfiletype;
ulong ncmds;
ulong nsizeofcmds;
ulong nflags;
};
struct nextcmd{
ulong cmd;
ulong cmdsize;
uchar segname[16];
ulong vmaddr;
ulong vmsize;
ulong fileoff;
ulong filesize;
ulong maxprot;
ulong initprot;
ulong nsects;
ulong flags;
}textc;
struct nextsect{
char sectname[16];
char segname[16];
ulong addr;
ulong size;
ulong offset;
ulong align;
ulong reloff;
ulong nreloc;
ulong flags;
ulong reserved1;
ulong reserved2;
}texts;
struct nextcmd datac;
struct nextsect datas;
struct nextsect bsss;
struct nextsym{
ulong cmd;
ulong cmdsize;
ulong symoff;
ulong nsyms;
ulong spoff;
ulong pcoff;
}symc;
*/
};
struct i386exec
{
/* UNUSED
struct i386coff{
ulong isectmagic;
ulong itime;
ulong isyms;
ulong insyms;
ulong iflags;
};
struct i386hdr{
ulong imagic;
ulong itextsize;
ulong idatasize;
ulong ibsssize;
ulong ientry;
ulong itextstart;
ulong idatastart;
};
struct coffsect itexts;
struct coffsect idatas;
struct coffsect ibsss;
struct coffsect icomments;
*/
};

403
include/mach_amd64.h Normal file
View File

@ -0,0 +1,403 @@
// Inferno libmach/a.out.h and libmach/mach.h
// http://code.google.com/p/inferno-os/source/browse/utils/libmach/a.out.h
// http://code.google.com/p/inferno-os/source/browse/utils/libmach/mach.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.
/*
* Architecture-dependent application data
* This is just Plan 9's mach.h, tweaked to support only amd64 for now.
*/
/*
* Start of Plan 9 a.out.h
* Don't use system a.out; instead just lay in the Plan 9 one for now.
*/
/*
#include "a.out.h"
*/
typedef struct Exec Exec;
struct Exec
{
long magic; /* magic number */
long text; /* size of text segment */
long data; /* size of initialized data */
long bss; /* size of uninitialized data */
long syms; /* size of symbol table */
long entry; /* entry point */
long spsz; /* size of pc/sp offset table */
long pcsz; /* size of pc/line number table */
};
#define HDR_MAGIC 0x00008000 /* header expansion */
#define _MAGIC(f, b) ((f)|((((4*(b))+0)*(b))+7))
#define A_MAGIC _MAGIC(0, 8) /* 68020 */
#define I_MAGIC _MAGIC(0, 11) /* intel 386 */
#define J_MAGIC _MAGIC(0, 12) /* intel 960 (retired) */
#define K_MAGIC _MAGIC(0, 13) /* sparc */
#define V_MAGIC _MAGIC(0, 16) /* mips 3000 BE */
#define X_MAGIC _MAGIC(0, 17) /* att dsp 3210 (retired) */
#define M_MAGIC _MAGIC(0, 18) /* mips 4000 BE */
#define D_MAGIC _MAGIC(0, 19) /* amd 29000 (retired) */
#define E_MAGIC _MAGIC(0, 20) /* arm */
#define Q_MAGIC _MAGIC(0, 21) /* powerpc */
#define N_MAGIC _MAGIC(0, 22) /* mips 4000 LE */
#define L_MAGIC _MAGIC(0, 23) /* dec alpha */
#define P_MAGIC _MAGIC(0, 24) /* mips 3000 LE */
#define U_MAGIC _MAGIC(0, 25) /* sparc64 */
#define S_MAGIC _MAGIC(HDR_MAGIC, 26) /* amd64 */
#define T_MAGIC _MAGIC(HDR_MAGIC, 27) /* powerpc64 */
#define MIN_MAGIC 8
#define MAX_MAGIC 27 /* <= 90 */
#define DYN_MAGIC 0x80000000 /* dlm */
typedef struct Sym Sym;
struct Sym
{
vlong value;
uint sig;
char type;
char *name;
};
/*
* End of Plan 9 a.out.h
* Don't use system a.out; instead just lay in the Plan 9 one for now.
*/
/*
* Supported architectures:
* mips,
* 68020,
* i386,
* amd64,
* sparc,
* sparc64,
* mips2 (R4000)
* arm
* powerpc,
* powerpc64
* alpha
*/
enum
{
MMIPS, /* machine types */
MSPARC,
M68020,
MI386,
MI960, /* retired */
M3210, /* retired */
MMIPS2,
NMIPS2,
M29000, /* retired */
MARM,
MPOWER,
MALPHA,
NMIPS,
MSPARC64,
MAMD64,
MPOWER64,
/* types of executables */
FNONE = 0, /* unidentified */
FMIPS, /* v.out */
FMIPSB, /* mips bootable */
FSPARC, /* k.out */
FSPARCB, /* Sparc bootable */
F68020, /* 2.out */
F68020B, /* 68020 bootable */
FNEXTB, /* Next bootable */
FI386, /* 8.out */
FI386B, /* I386 bootable */
FI960, /* retired */
FI960B, /* retired */
F3210, /* retired */
FMIPS2BE, /* 4.out */
F29000, /* retired */
FARM, /* 5.out */
FARMB, /* ARM bootable */
FPOWER, /* q.out */
FPOWERB, /* power pc bootable */
FMIPS2LE, /* 0.out */
FALPHA, /* 7.out */
FALPHAB, /* DEC Alpha bootable */
FMIPSLE, /* 3k little endian */
FSPARC64, /* u.out */
FAMD64, /* 6.out */
FAMD64B, /* 6.out bootable */
FPOWER64, /* 9.out */
FPOWER64B, /* 9.out bootable */
ANONE = 0, /* dissembler types */
AMIPS,
AMIPSCO, /* native mips */
ASPARC,
ASUNSPARC, /* native sun */
A68020,
AI386,
AI8086, /* oh god */
AI960, /* retired */
A29000, /* retired */
AARM,
APOWER,
AALPHA,
ASPARC64,
AAMD64,
APOWER64,
/* object file types */
Obj68020 = 0, /* .2 */
ObjSparc, /* .k */
ObjMips, /* .v */
Obj386, /* .8 */
Obj960, /* retired */
Obj3210, /* retired */
ObjMips2, /* .4 */
Obj29000, /* retired */
ObjArm, /* .5 */
ObjPower, /* .q */
ObjMips2le, /* .0 */
ObjAlpha, /* .7 */
ObjSparc64, /* .u */
ObjAmd64, /* .6 */
ObjSpim, /* .0 */
ObjPower64, /* .9 */
Maxobjtype,
CNONE = 0, /* symbol table classes */
CAUTO,
CPARAM,
CSTAB,
CTEXT,
CDATA,
CANY, /* to look for any class */
};
typedef struct Map Map;
typedef struct Symbol Symbol;
typedef struct Reglist Reglist;
typedef struct Mach Mach;
typedef struct Machdata Machdata;
/*
* Structure to map a segment to a position in a file
*/
struct Map {
int nsegs; /* number of segments */
struct segment { /* per-segment map */
char *name; /* the segment name */
int fd; /* file descriptor */
int inuse; /* in use - not in use */
int cache; /* should cache reads? */
uvlong b; /* base */
uvlong e; /* end */
vlong f; /* offset within file */
} seg[1]; /* actually n of these */
};
/*
* Internal structure describing a symbol table entry
*/
struct Symbol {
void *handle; /* used internally - owning func */
struct {
char *name;
vlong value; /* address or stack offset */
char type; /* as in a.out.h */
char class; /* as above */
int index; /* in findlocal, globalsym, textsym */
};
};
/*
* machine register description
*/
struct Reglist {
char *rname; /* register name */
short roffs; /* offset in u-block */
char rflags; /* INTEGER/FLOAT, WRITABLE */
char rformat; /* print format: 'x', 'X', 'f', '8', '3', 'Y', 'W' */
};
enum { /* bits in rflags field */
RINT = (0<<0),
RFLT = (1<<0),
RRDONLY = (1<<1),
};
/*
* Machine-dependent data is stored in two structures:
* Mach - miscellaneous general parameters
* Machdata - jump vector of service functions used by debuggers
*
* Mach is defined in ?.c and set in executable.c
*
* Machdata is defined in ?db.c
* and set in the debugger startup.
*/
struct Mach{
char *name;
int mtype; /* machine type code */
Reglist *reglist; /* register set */
long regsize; /* sizeof registers in bytes */
long fpregsize; /* sizeof fp registers in bytes */
char *pc; /* pc name */
char *sp; /* sp name */
char *link; /* link register name */
char *sbreg; /* static base register name */
uvlong sb; /* static base register value */
int pgsize; /* page size */
uvlong kbase; /* kernel base address */
uvlong ktmask; /* ktzero = kbase & ~ktmask */
uvlong utop; /* user stack top */
int pcquant; /* quantization of pc */
int szaddr; /* sizeof(void*) */
int szreg; /* sizeof(register) */
int szfloat; /* sizeof(float) */
int szdouble; /* sizeof(double) */
};
extern Mach *mach; /* Current machine */
typedef uvlong (*Rgetter)(Map*, char*);
typedef void (*Tracer)(Map*, uvlong, uvlong, Symbol*);
struct Machdata { /* Machine-dependent debugger support */
uchar bpinst[4]; /* break point instr. */
short bpsize; /* size of break point instr. */
ushort (*swab)(ushort); /* ushort to local byte order */
ulong (*swal)(ulong); /* ulong to local byte order */
uvlong (*swav)(uvlong); /* uvlong to local byte order */
int (*ctrace)(Map*, uvlong, uvlong, uvlong, Tracer); /* C traceback */
uvlong (*findframe)(Map*, uvlong, uvlong, uvlong, uvlong);/* frame finder */
char* (*excep)(Map*, Rgetter); /* last exception */
ulong (*bpfix)(uvlong); /* breakpoint fixup */
int (*sftos)(char*, int, void*); /* single precision float */
int (*dftos)(char*, int, void*); /* double precision float */
int (*foll)(Map*, uvlong, Rgetter, uvlong*);/* follow set */
int (*das)(Map*, uvlong, char, char*, int); /* symbolic disassembly */
int (*hexinst)(Map*, uvlong, char*, int); /* hex disassembly */
int (*instsize)(Map*, uvlong); /* instruction size */
};
/*
* Common a.out header describing all architectures
*/
typedef struct Fhdr
{
char *name; /* identifier of executable */
uchar type; /* file type - see codes above */
uchar hdrsz; /* header size */
uchar _magic; /* _MAGIC() magic */
uchar spare;
long magic; /* magic number */
uvlong txtaddr; /* text address */
vlong txtoff; /* start of text in file */
uvlong dataddr; /* start of data segment */
vlong datoff; /* offset to data seg in file */
vlong symoff; /* offset of symbol table in file */
uvlong entry; /* entry point */
vlong sppcoff; /* offset of sp-pc table in file */
vlong lnpcoff; /* offset of line number-pc table in file */
long txtsz; /* text size */
long datsz; /* size of data seg */
long bsssz; /* size of bss */
long symsz; /* size of symbol table */
long sppcsz; /* size of sp-pc table */
long lnpcsz; /* size of line number-pc table */
} Fhdr;
extern int asstype; /* dissembler type - machdata.c */
extern Machdata *machdata; /* jump vector - machdata.c */
Map* attachproc(int, int, int, Fhdr*);
int beieee80ftos(char*, int, void*);
int beieeesftos(char*, int, void*);
int beieeedftos(char*, int, void*);
ushort beswab(ushort);
ulong beswal(ulong);
uvlong beswav(uvlong);
uvlong ciscframe(Map*, uvlong, uvlong, uvlong, uvlong);
int cisctrace(Map*, uvlong, uvlong, uvlong, Tracer);
int crackhdr(int fd, Fhdr*);
uvlong file2pc(char*, long);
int fileelem(Sym**, uchar *, char*, int);
long fileline(char*, int, uvlong);
int filesym(int, char*, int);
int findlocal(Symbol*, char*, Symbol*);
int findseg(Map*, char*);
int findsym(uvlong, int, Symbol *);
int fnbound(uvlong, uvlong*);
int fpformat(Map*, Reglist*, char*, int, int);
int get1(Map*, uvlong, uchar*, int);
int get2(Map*, uvlong, ushort*);
int get4(Map*, uvlong, ulong*);
int get8(Map*, uvlong, uvlong*);
int geta(Map*, uvlong, uvlong*);
int getauto(Symbol*, int, int, Symbol*);
Sym* getsym(int);
int globalsym(Symbol *, int);
char* _hexify(char*, ulong, int);
int ieeesftos(char*, int, ulong);
int ieeedftos(char*, int, ulong, ulong);
int isar(Biobuf*);
int leieee80ftos(char*, int, void*);
int leieeesftos(char*, int, void*);
int leieeedftos(char*, int, void*);
ushort leswab(ushort);
ulong leswal(ulong);
uvlong leswav(uvlong);
uvlong line2addr(long, uvlong, uvlong);
Map* loadmap(Map*, int, Fhdr*);
int localaddr(Map*, char*, char*, uvlong*, Rgetter);
int localsym(Symbol*, int);
int lookup(char*, char*, Symbol*);
void machbytype(int);
int machbyname(char*);
int nextar(Biobuf*, int, char*);
Map* newmap(Map*, int);
void objtraverse(void(*)(Sym*, void*), void*);
int objtype(Biobuf*, char**);
uvlong pc2sp(uvlong);
long pc2line(uvlong);
int put1(Map*, uvlong, uchar*, int);
int put2(Map*, uvlong, ushort);
int put4(Map*, uvlong, ulong);
int put8(Map*, uvlong, uvlong);
int puta(Map*, uvlong, uvlong);
int readar(Biobuf*, int, vlong, int);
int readobj(Biobuf*, int);
uvlong riscframe(Map*, uvlong, uvlong, uvlong, uvlong);
int risctrace(Map*, uvlong, uvlong, uvlong, Tracer);
int setmap(Map*, int, uvlong, uvlong, vlong, char*);
Sym* symbase(long*);
int syminit(int, Fhdr*);
int symoff(char*, int, uvlong, int);
void textseg(uvlong, Fhdr*);
int textsym(Symbol*, int);
void unusemap(Map*, int);

58
include/ureg_amd64.h Normal file
View File

@ -0,0 +1,58 @@
// Inferno utils/libmach/ureg6.h
// http://code.google.com/p/inferno-os/source/browse/utils/libmach/ureg6.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.
struct Ureg {
u64int ax;
u64int bx;
u64int cx;
u64int dx;
u64int si;
u64int di;
u64int bp;
u64int r8;
u64int r9;
u64int r10;
u64int r11;
u64int r12;
u64int r13;
u64int r14;
u64int r15;
u16int ds;
u16int es;
u16int fs;
u16int gs;
u64int type;
u64int error; /* error code (or zero) */
u64int ip; /* pc */
u64int cs; /* old context */
u64int flags; /* old flags */
u64int sp; /* sp */
u64int ss; /* old stack segment */
};

53
include/ureg_x86.h Normal file
View File

@ -0,0 +1,53 @@
// Inferno utils/libmach/ureg8.h
// http://code.google.com/p/inferno-os/source/browse/utils/libmach/ureg8.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.
struct Ureg
{
ulong di; /* general registers */
ulong si; /* ... */
ulong bp; /* ... */
ulong nsp;
ulong bx; /* ... */
ulong dx; /* ... */
ulong cx; /* ... */
ulong ax; /* ... */
ulong gs; /* data segments */
ulong fs; /* ... */
ulong es; /* ... */
ulong ds; /* ... */
ulong trap; /* trap type */
ulong ecode; /* error code (or zero) */
ulong pc; /* pc */
ulong cs; /* old context */
ulong flags; /* old flags */
union {
ulong usp;
ulong sp;
};
ulong ss; /* old stack segment */
};

View File

@ -40,3 +40,8 @@ echo; echo; echo %%%% making 6g %%%%; echo
cd 6g
make install
cd ..
echo; echo; echo %%%% making db %%%%; echo
cd db
make install
cd ..

145
src/libmachamd64/6.c Normal file
View File

@ -0,0 +1,145 @@
// 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_amd64.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 */
};

175
src/libmachamd64/6obj.c Normal file
View File

@ -0,0 +1,175 @@
// 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_amd64.h>
#include "../cmd/6l/6.out.h"
#include "obj.h"
typedef struct Addr Addr;
struct Addr
{
char sym;
char flags;
};
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) /* aslo = 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;
long l;
vlong off;
off = 0;
a.sym = -1;
a.flags = Bgetc(bp); /* flags */
if(a.flags & T_INDEX)
skip(bp, 2);
if(a.flags & T_OFFSET){
l = Bgetc(bp);
l |= Bgetc(bp) << 8;
l |= Bgetc(bp) << 16;
l |= Bgetc(bp) << 24;
off = l;
if(a.flags & T_64){
l = Bgetc(bp);
l |= Bgetc(bp) << 8;
l |= Bgetc(bp) << 16;
l |= Bgetc(bp) << 24;
off = ((vlong)l << 32) | (off & 0xFFFFFFFF);
}
if(off < 0)
off = -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);
}
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);
}

107
src/libmachamd64/8.c Normal file
View File

@ -0,0 +1,107 @@
// 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 <bio.h>
#include <ureg_x86.h>
#include <mach_amd64.h>
#define REGOFF(x) (ulong)(&((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 */
0x7FFFFFFFULL, /* user stack top */
1, /* quantization of pc */
4, /* szaddr */
4, /* szreg */
4, /* szfloat */
8, /* szdouble */
};

2204
src/libmachamd64/8db.c Normal file

File diff suppressed because it is too large Load Diff

84
src/libmachamd64/Makefile Normal file
View File

@ -0,0 +1,84 @@
# Derived from Inferno libmach/mkfile
# http://code.google.com/p/inferno-os/source/browse/utils/libmach/mkfile
#
# 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.
CFLAGS=-I$(GOROOT)/include
O=o
LIB=libmach_amd64.a
OFILES=\
executable.$O\
map.$O\
obj.$O\
swap.$O\
sym.$O\
access.$O\
machdata.$O\
setmach.$O\
6.$O\
8.$O\
8db.$O\
6obj.$O\
# v.$O\
# k.$O\
# u.$O\
# q.$O\
# 0.$O\
# 2.$O\
# 5.$O\
# 7.$O\
# 9.$O\
# vdb.$O\
# kdb.$O\
# udb.$O\
# qdb.$O\
# 2db.$O\
# 5db.$O\
# 7db.$O\
# vobj.$O\
# kobj.$O\
# uobj.$O\
# 2obj.$O\
# 5obj.$O\
# 7obj.$O\
# 8obj.$O\
# 9obj.$O\
# qobj.$O\
# vcodas.$O\
HFILES=$(GOROOT)/include/mach_amd64.h elf.h obj.h
install: $(LIB)
cp $(LIB) $(GOROOT)/lib
$(LIB): $(OFILES)
ar rsc $(LIB) $(OFILES)
$(OFILES): $(HFILES)
clean:
rm -f $(OFILES) $(LIB)

300
src/libmachamd64/access.c Normal file
View File

@ -0,0 +1,300 @@
// 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_amd64.h>
static int mget(Map*, uvlong, void*, int);
static int mput(Map*, uvlong, void*, int);
static struct segment* reloc(Map*, uvlong, vlong*);
/*
* routines to get/put various types
*/
int
geta(Map *map, uvlong addr, uvlong *x)
{
ulong 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, ulong *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, ulong 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
spread(struct segment *s, void *buf, int n, uvlong off)
{
uvlong base;
static struct {
struct segment *s;
char a[8192];
uvlong off;
} cache;
if(s->cache){
base = off&~(sizeof cache.a-1);
if(cache.s != s || cache.off != base){
cache.off = ~0;
if(seek(s->fd, base, 0) >= 0
&& readn(s->fd, cache.a, sizeof cache.a) == sizeof cache.a){
cache.s = s;
cache.off = base;
}
}
if(cache.s == s && cache.off == base){
off &= sizeof cache.a-1;
if(off+n > sizeof cache.a)
n = sizeof cache.a - off;
memmove(buf, cache.a+off, n);
return n;
}
}
return pread(s->fd, buf, n, off);
}
static int
mget(Map *map, uvlong addr, void *buf, int size)
{
uvlong off;
int i, j, k;
struct segment *s;
s = reloc(map, addr, (vlong*)&off);
if (!s)
return -1;
if (s->fd < 0) {
werrstr("unreadable map");
return -1;
}
for (i = j = 0; i < 2; i++) { /* in case read crosses page */
k = spread(s, buf, size-j, off+j);
if (k < 0) {
werrstr("can't read address %llux: %r", addr);
return -1;
}
j += k;
if (j == size)
return j;
}
werrstr("partial read at address %llux (size %d j %d)", addr, size, j);
return -1;
}
static int
mput(Map *map, uvlong addr, void *buf, int size)
{
vlong off;
int i, j, k;
struct segment *s;
s = reloc(map, addr, &off);
if (!s)
return -1;
if (s->fd < 0) {
werrstr("unwritable map");
return -1;
}
seek(s->fd, off, 0);
for (i = j = 0; i < 2; i++) { /* in case read crosses page */
k = write(s->fd, buf, size-j);
if (k < 0) {
werrstr("can't write address %llux: %r", addr);
return -1;
}
j += k;
if (j == size)
return j;
}
werrstr("partial write at address %llux", addr);
return -1;
}
/*
* convert address to file offset; returns nonzero if ok
*/
static struct segment*
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;
}

182
src/libmachamd64/elf.h Normal file
View File

@ -0,0 +1,182 @@
// 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 */
ulong elfentry; /* start address */
ulong phoff; /* phdr file offset */
ulong 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 */
ulong offset; /* file offset */
ulong vaddr; /* virtual address */
ulong paddr; /* physical address */
int filesz; /* file size */
ulong 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 {
ulong name; /* section name */
ulong type; /* SHT_... */
ulong flags; /* SHF_... */
ulong addr; /* virtual address */
ulong offset; /* file offset */
ulong size; /* section size */
ulong link; /* misc info */
ulong info; /* misc info */
ulong addralign; /* memory alignment */
ulong entsize; /* entry size if table */
} Shdr32;
typedef struct {
ulong name; /* section name */
ulong type; /* SHT_... */
uvlong flags; /* SHF_... */
uvlong addr; /* virtual address */
uvlong offset; /* file offset */
uvlong size; /* section size */
ulong link; /* misc info */
ulong 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')

View File

@ -0,0 +1,963 @@
// 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_amd64.h>
#include "elf.h"
/*
* All a.out header types. The dummy entry allows canonical
* processing of the union as a sequence of longs
*/
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 */
} e;
long dummy; /* padding to ensure extra long */
} 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 armdotout(int, Fhdr*, ExecHdr*);
static void setsym(Fhdr*, long, long, long, vlong);
static void setdata(Fhdr*, uvlong, long, vlong, long);
static void settext(Fhdr*, uvlong, uvlong, long, vlong);
static void hswal(void*, int, ulong(*)(ulong));
static uvlong _round(uvlong, ulong);
/*
* definition of per-executable file type structures
*/
typedef struct Exectable{
long 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 */
long hsize; /* header size */
ulong (*swal)(ulong); /* 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 marm;
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 },
{ 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 },
{ 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;
ulong 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(ulong), 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, ulong (*swap)(ulong))
{
ulong *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)
{
long 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, hp->e.exechdr.syms, hp->e.exechdr.spsz, hp->e.exechdr.pcsz, fp->datoff+fp->datsz);
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)
{
long pgsize;
uvlong entry;
hswal(&hp->e, sizeof(Exec)/sizeof(long), 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;
entry = beswav(*(uvlong*)&hp->e.exechdr);
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, hp->e.exechdr.syms, hp->e.exechdr.spsz, hp->e.exechdr.pcsz, fp->datoff+fp->datsz);
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)
{
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)
{
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)
{
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)
{
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);
ulong (*swal)(ulong);
ushort (*swab)(ushort);
Ehdr64 *ep;
Phdr64 *ph;
int i, it, id, is, phsz;
/* 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);
print("entry: 0x%x\n", 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 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 AMD64:
mach = &mamd64;
fp->type = FAMD64;
break;
case ARM:
mach = &marm;
fp->type = FARM;
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(ulong), 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) {
ulong 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].filesz, 0, ph[1].memsz, ph[1].offset);
free(ph);
return 1;
}
werrstr("No TEXT or DATA sections");
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].filesz, 0, ph[is].memsz, ph[is].offset);
free(ph);
return 1;
}
static int
elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
{
ulong (*swal)(ulong);
ushort (*swab)(ushort);
Ehdr32 *ep;
Phdr32 *ph;
int i, it, id, is, phsz;
/* 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 AMD64:
mach = &mamd64;
fp->type = FAMD64;
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(ulong), 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) {
ulong 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].filesz, 0, ph[1].memsz, ph[1].offset);
free(ph);
return 1;
}
werrstr("No TEXT or DATA sections");
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].filesz, 0, ph[is].memsz, ph[is].offset);
free(ph);
return 1;
}
/*
* (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, hp->e.exechdr.syms, hp->e.exechdr.spsz, hp->e.exechdr.pcsz, fp->datoff+fp->datsz);
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;
}
static void
settext(Fhdr *fp, uvlong e, uvlong a, long s, vlong off)
{
fp->txtaddr = a;
fp->entry = e;
fp->txtsz = s;
fp->txtoff = off;
}
static void
setdata(Fhdr *fp, uvlong a, long s, vlong off, long bss)
{
fp->dataddr = a;
fp->datsz = s;
fp->datoff = off;
fp->bsssz = bss;
}
static void
setsym(Fhdr *fp, long symsz, long sppcsz, long lnpcsz, vlong symoff)
{
fp->symsz = symsz;
fp->symoff = symoff;
fp->sppcsz = sppcsz;
fp->sppcoff = fp->symoff+fp->symsz;
fp->lnpcsz = lnpcsz;
fp->lnpcoff = fp->sppcoff+fp->sppcsz;
}
static uvlong
_round(uvlong a, ulong b)
{
uvlong w;
w = (a/b)*b;
if (a!=w)
w += b;
return(w);
}

477
src/libmachamd64/machdata.c Normal file
View File

@ -0,0 +1,477 @@
// 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_amd64.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;
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)
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+%lux", 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];
ulong r;
switch(rp->rformat)
{
case 'X':
if (get4(map, rp->roffs, &r) < 0)
return -1;
snprint(buf, n, "%lux", 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, ulong p, int zeros)
{
ulong 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, ulong h, ulong 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(%.8lux%.8lux)", 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(%.8lux%.8lux)", h&((1L<<20)-1L), 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, ulong 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(%.8lux)", 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(*(ulong*)s));
}
int
beieeedftos(char *buf, int n, void *s)
{
return ieeedftos(buf, n, beswal(*(ulong*)s), beswal(((ulong*)(s))[1]));
}
int
leieeesftos(char *buf, int n, void *s)
{
return ieeesftos(buf, n, leswal(*(ulong*)s));
}
int
leieeedftos(char *buf, int n, void *s)
{
return ieeedftos(buf, n, leswal(((ulong*)(s))[1]), leswal(*(ulong*)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;
ulong 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;
}

205
src/libmachamd64/map.c Normal file
View File

@ -0,0 +1,205 @@
// 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_amd64.h>
Map *
newmap(Map *map, int n)
{
int size;
size = sizeof(Map)+(n-1)*sizeof(struct segment);
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)
{
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;
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);
}
Map*
attachproc(int pid, int kflag, int corefd, Fhdr *fp)
{
char buf[64], *regs;
int fd;
Map *map;
uvlong n;
int mode;
map = newmap(0, 4);
if (!map)
return 0;
if(kflag) {
regs = "kregs";
mode = OREAD;
} else {
regs = "regs";
mode = ORDWR;
}
if (mach->regsize) {
sprint(buf, "/proc/%d/%s", pid, regs);
fd = open(buf, mode);
if(fd < 0) {
free(map);
return 0;
}
setmap(map, fd, 0, mach->regsize, 0, "regs");
}
if (mach->fpregsize) {
sprint(buf, "/proc/%d/fpregs", pid);
fd = open(buf, mode);
if(fd < 0) {
close(map->seg[0].fd);
free(map);
return 0;
}
setmap(map, fd, mach->regsize, mach->regsize+mach->fpregsize, 0, "fpregs");
}
setmap(map, corefd, fp->txtaddr, fp->txtaddr+fp->txtsz, fp->txtaddr, "text");
if(kflag || fp->dataddr >= mach->utop) {
setmap(map, corefd, fp->dataddr, ~0, fp->dataddr, "data");
return map;
}
n = stacktop(pid);
if (n == 0) {
setmap(map, corefd, fp->dataddr, mach->utop, fp->dataddr, "data");
return map;
}
setmap(map, corefd, fp->dataddr, n, fp->dataddr, "data");
return map;
}
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;
}
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[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";
return map;
}

356
src/libmachamd64/obj.c Normal file
View File

@ -0,0 +1,356 @@
// 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_amd64.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
};
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);
int
objtype(Biobuf *bp, char **name)
{
int i;
char buf[MAXIS];
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(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)
{
long 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;
if(h < 0)
h = ~h;
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));
sp->s.name = name;
sp->s.type = type;
sp->s.sig = sig;
sp->s.value = islocal(type) ? MAXOFF : 0;
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;
long 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);
}

53
src/libmachamd64/obj.h Normal file
View File

@ -0,0 +1,53 @@
// 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);

203
src/libmachamd64/setmach.c Normal file
View File

@ -0,0 +1,203 @@
// 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_amd64.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;
extern Machdata i386mach;
/*
* 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, },
#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, },
{ "arm", /*ARM*/
FARM,
FARMB,
AARM,
&marm,
&armmach, },
{ "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;
}

107
src/libmachamd64/swap.c Normal file
View File

@ -0,0 +1,107 @@
// 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 long
*/
ulong
beswal(ulong 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 long
*/
ulong
leswal(ulong 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];
}

1402
src/libmachamd64/sym.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
for i in lib9 libbio
for i in lib9 libbio libmach_amd64
do
cd $i
make install