mirror of
https://github.com/golang/go
synced 2024-11-22 01:14:40 -07:00
Add 6db
SVN=122505
This commit is contained in:
parent
ef61a4cb1e
commit
ed5e39a66d
169
include/bootexec.h
Normal file
169
include/bootexec.h
Normal 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
403
include/mach_amd64.h
Normal 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
58
include/ureg_amd64.h
Normal 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
53
include/ureg_x86.h
Normal 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 */
|
||||||
|
};
|
@ -40,3 +40,8 @@ echo; echo; echo %%%% making 6g %%%%; echo
|
|||||||
cd 6g
|
cd 6g
|
||||||
make install
|
make install
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
|
echo; echo; echo %%%% making db %%%%; echo
|
||||||
|
cd db
|
||||||
|
make install
|
||||||
|
cd ..
|
||||||
|
145
src/libmachamd64/6.c
Normal file
145
src/libmachamd64/6.c
Normal 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
175
src/libmachamd64/6obj.c
Normal 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
107
src/libmachamd64/8.c
Normal 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
2204
src/libmachamd64/8db.c
Normal file
File diff suppressed because it is too large
Load Diff
84
src/libmachamd64/Makefile
Normal file
84
src/libmachamd64/Makefile
Normal 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
300
src/libmachamd64/access.c
Normal 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
182
src/libmachamd64/elf.h
Normal 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')
|
963
src/libmachamd64/executable.c
Normal file
963
src/libmachamd64/executable.c
Normal 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
477
src/libmachamd64/machdata.c
Normal 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
205
src/libmachamd64/map.c
Normal 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
356
src/libmachamd64/obj.c
Normal 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
53
src/libmachamd64/obj.h
Normal 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
203
src/libmachamd64/setmach.c
Normal 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
107
src/libmachamd64/swap.c
Normal 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
1402
src/libmachamd64/sym.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,7 @@
|
|||||||
# Use of this source code is governed by a BSD-style
|
# Use of this source code is governed by a BSD-style
|
||||||
# license that can be found in the LICENSE file.
|
# license that can be found in the LICENSE file.
|
||||||
|
|
||||||
for i in lib9 libbio
|
for i in lib9 libbio libmach_amd64
|
||||||
do
|
do
|
||||||
cd $i
|
cd $i
|
||||||
make install
|
make install
|
||||||
|
Loading…
Reference in New Issue
Block a user