summaryrefslogtreecommitdiff
path: root/sys/src/libmach
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2012-07-30 19:11:16 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2012-07-30 19:11:16 +0200
commit4f33c88a51587681b7be1ae57cfbc43b627c6bc4 (patch)
tree25560404dc80007e5dc268811242c9071f6a1017 /sys/src/libmach
parentfcc5e75d07e5bc6cb3ddac6d9a437e7ec62d0d95 (diff)
import updated compilers from sources
Diffstat (limited to 'sys/src/libmach')
-rw-r--r--sys/src/libmach/5db.c73
-rw-r--r--sys/src/libmach/6.c8
-rw-r--r--sys/src/libmach/9.c34
-rw-r--r--sys/src/libmach/elf.h47
-rw-r--r--sys/src/libmach/executable.c174
-rw-r--r--sys/src/libmach/map.c8
-rw-r--r--sys/src/libmach/mkfile12
-rw-r--r--sys/src/libmach/sym.c8
8 files changed, 305 insertions, 59 deletions
diff --git a/sys/src/libmach/5db.c b/sys/src/libmach/5db.c
index 848281f59..e490d11a6 100644
--- a/sys/src/libmach/5db.c
+++ b/sys/src/libmach/5db.c
@@ -61,7 +61,7 @@ static int arminstlen(Map*, uvlong);
*/
Machdata armmach =
{
- {0, 0, 0, 0xD}, /* break point */
+ {0x70, 0x00, 0x20, 0xD1}, /* break point */ /* D1200070 */
4, /* break point size */
leswab, /* short to local byte order */
@@ -135,18 +135,26 @@ char* addsub[2] =
int
armclass(long w)
{
- int op;
+ int op, done;
op = (w >> 25) & 0x7;
switch(op) {
case 0: /* data processing r,r,r */
op = ((w >> 4) & 0xf);
if(op == 0x9) {
- op = 48+16; /* mul */
+ op = 48+16; /* mul, swp or *rex */
+ if((w & 0x0ff00fff) == 0x01900f9f) {
+ op = 93; /* ldrex */
+ break;
+ }
+ if((w & 0x0ff00ff0) == 0x01800f90) {
+ op = 94; /* strex */
+ break;
+ }
if(w & (1<<24)) {
op += 2;
if(w & (1<<22))
- op++; /* swap */
+ op++; /* swpb */
break;
}
if(w & (1<<23)) { /* mullu */
@@ -174,12 +182,38 @@ armclass(long w)
op = (48) + ((w >> 21) & 0xf);
break;
case 2: /* load/store byte/word i(r) */
+ if ((w & 0xffffff8f) == 0xf57ff00f) { /* barriers, clrex */
+ done = 1;
+ switch ((w >> 4) & 7) {
+ case 1:
+ op = 95; /* clrex */
+ break;
+ case 4:
+ op = 96; /* dsb */
+ break;
+ case 5:
+ op = 97; /* dmb */
+ break;
+ case 6:
+ op = 98; /* isb */
+ break;
+ default:
+ done = 0;
+ break;
+ }
+ if (done)
+ break;
+ }
op = (48+24) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
break;
case 3: /* load/store byte/word (r)(r) */
op = (48+24+4) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
break;
case 4: /* block data transfer (r)(r) */
+ if ((w & 0xfe50ffff) == 0xf8100a00) { /* v7 RFE */
+ op = 99;
+ break;
+ }
op = (48+24+4+4) + ((w >> 20) & 0x1);
break;
case 5: /* branch / branch link */
@@ -188,7 +222,7 @@ armclass(long w)
case 7: /* coprocessor crap */
op = (48+24+4+4+2+2) + ((w >> 3) & 0x2) + ((w >> 20) & 0x1);
break;
- default:
+ default:
op = (48+24+4+4+2+2+4+4);
break;
}
@@ -602,19 +636,16 @@ armaddr(Map *map, Rgetter rget, Instr *i)
char buf[8];
ulong rn;
- sprint(buf, "R%ld", (i->w >> 16) & 0xf);
+ snprint(buf, sizeof(buf), "R%ld", (i->w >> 16) & 0xf);
rn = rget(map, buf);
- if((i->w & (1<<24)) == 0) { /* POSTIDX */
- sprint(buf, "R%ld", rn);
- return rget(map, buf);
- }
+ if((i->w & (1<<24)) == 0) /* POSTIDX */
+ return rn;
if((i->w & (1<<25)) == 0) { /* OFFSET */
- sprint(buf, "R%ld", rn);
if(i->w & (1U<<23))
- return rget(map, buf) + (i->w & BITS(0,11));
- return rget(map, buf) - (i->w & BITS(0,11));
+ return rn + (i->w & BITS(0,11));
+ return rn - (i->w & BITS(0,11));
} else { /* REGOFF */
ulong index = 0;
uchar c;
@@ -823,8 +854,22 @@ static Opcode opcodes[] =
"MULL%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)",
"MULAL%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)",
-/* 48+24+4+4+2+2+4+4 */
+/* 48+24+4+4+2+2+4+4 = 92 */
"UNK", armunk, 0, "",
+
+ /* new v7 arch instructions */
+/* 93 */
+ "LDREX", armdpi, 0, "(R%n),R%d",
+ "STREX", armdpi, 0, "R%s,(R%n),R%d",
+ "CLREX", armunk, 0, "",
+
+/* 96 */
+ "DSB", armunk, 0, "",
+ "DMB", armunk, 0, "",
+ "ISB", armunk, 0, "",
+
+/* 99 */
+ "RFEV7%P%a", armbdt, 0, "(R%n)",
};
static void
diff --git a/sys/src/libmach/6.c b/sys/src/libmach/6.c
index 6aca0006f..a3566f60b 100644
--- a/sys/src/libmach/6.c
+++ b/sys/src/libmach/6.c
@@ -105,10 +105,10 @@ Mach mamd64=
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 */
+ 0x200000, /* page size */
+ 0xfffffffff0110000ull, /* kernel base */
+ 0xffff800000000000ull, /* kernel text mask */
+ 0x00007ffffffff000ull, /* user stack top */
1, /* quantization of pc */
8, /* szaddr */
4, /* szreg */
diff --git a/sys/src/libmach/9.c b/sys/src/libmach/9.c
index 6eb98be96..824c0aba4 100644
--- a/sys/src/libmach/9.c
+++ b/sys/src/libmach/9.c
@@ -101,21 +101,21 @@ Mach mpower64 =
{
"power64",
MPOWER64, /* machine type */
- power64reglist, /* register set */
- REGSIZE, /* number of bytes in register set */
- FPREGSIZE, /* number of bytes in FP register set */
- "PC", /* name of PC */
- "SP", /* name of SP */
- "LR", /* name of link register */
- "setSB", /* static base register name */
- 0, /* value */
- 0x1000, /* page size */
- 0x80000000ULL, /* kernel base */
- 0, /* kernel text mask */
- 0x7FFFFFFFULL, /* user stack top */
- 4, /* quantization of pc */
- 8, /* szaddr */
- 8, /* szreg */
- 4, /* szfloat */
- 8, /* szdouble */
+ power64reglist, /* register set */
+ REGSIZE, /* number of bytes in register set */
+ FPREGSIZE, /* number of bytes in FP register set */
+ "PC", /* name of PC */
+ "SP", /* name of SP */
+ "LR", /* name of link register */
+ "setSB", /* static base register name */
+ 0, /* value */
+ 0x100000, /* page size (TODO, too many choices) */
+ 0xffffffff80000000ull, /* kernel base (TODO, likely incorrect) */
+ 0xf000000000000000ull, /* kernel text mask (TODO, likely incorrect) */
+ 0x00007ffffff00000ull, /* user stack top (TODO, likely incorrect) */
+ 4, /* quantization of pc */
+ 8, /* szaddr */
+ 8, /* szreg */
+ 4, /* szfloat */
+ 8, /* szdouble */
};
diff --git a/sys/src/libmach/elf.h b/sys/src/libmach/elf.h
index 5d755b7a6..94fa7331c 100644
--- a/sys/src/libmach/elf.h
+++ b/sys/src/libmach/elf.h
@@ -1,5 +1,5 @@
/*
- * Definitions needed for accessing Irix ELF headers
+ * Definitions needed for accessing ELF headers
*/
typedef struct {
uchar ident[16]; /* ident bytes */
@@ -19,6 +19,23 @@ typedef struct {
} Ehdr;
typedef struct {
+ u8int ident[16]; /* ident bytes */
+ u16int type; /* file type */
+ u16int machine; /* target machine */
+ u32int version; /* file version */
+ u64int elfentry; /* start address */
+ u64int phoff; /* phdr file offset */
+ u64int shoff; /* shdr file offset */
+ u32int flags; /* file flags */
+ u16int ehsize; /* sizeof ehdr */
+ u16int phentsize; /* sizeof phdr */
+ u16int phnum; /* number phdrs */
+ u16int shentsize; /* sizeof shdr */
+ u16int shnum; /* number shdrs */
+ u16int shstrndx; /* shdr string index */
+} E64hdr;
+
+typedef struct {
int type; /* entry type */
ulong offset; /* file offset */
ulong vaddr; /* virtual address */
@@ -30,6 +47,17 @@ typedef struct {
} Phdr;
typedef struct {
+ u32int type; /* entry type */
+ u32int flags; /* entry flags */
+ u64int offset; /* file offset */
+ u64int vaddr; /* virtual address */
+ u64int paddr; /* physical address */
+ u64int filesz; /* file size */
+ u64int memsz; /* memory size */
+ u64int align; /* memory/file alignment */
+} P64hdr;
+
+typedef struct {
ulong name; /* section name */
ulong type; /* SHT_... */
ulong flags; /* SHF_... */
@@ -42,6 +70,19 @@ typedef struct {
ulong entsize; /* entry size if table */
} Shdr;
+typedef struct {
+ u32int name; /* section name */
+ u32int type; /* SHT_... */
+ u64int flags; /* SHF_... */
+ u64int addr; /* virtual address */
+ u64int offset; /* file offset */
+ u64int size; /* section size */
+ u32int link; /* misc info */
+ u32int info; /* misc info */
+ u64int addralign; /* memory alignment */
+ u64int entsize; /* entry size if table */
+} S64hdr;
+
enum {
/* Ehdr codes */
MAG0 = 0, /* ident[] indexes */
@@ -80,8 +121,10 @@ enum {
S370 = 9, /* Amdhal */
SPARC64 = 18, /* Sun SPARC v9 */
POWER = 20, /* PowerPC */
- ARM = 40, /* ARM */
+ POWER64 = 21, /* PowerPC64 */
+ ARM = 40, /* ARM */
AMD64 = 62, /* Amd64 */
+ ARM64 = 183, /* ARM64 */
NO_VERSION = 0, /* version, ident[VERSION] */
CURRENT = 1,
diff --git a/sys/src/libmach/executable.c b/sys/src/libmach/executable.c
index 614285651..4dbe94d92 100644
--- a/sys/src/libmach/executable.c
+++ b/sys/src/libmach/executable.c
@@ -17,6 +17,7 @@ typedef struct {
uvlong hdr[1];
};
Ehdr; /* elf.h */
+ E64hdr;
struct mipsexec; /* bootexec.h */
struct mips4kexec; /* bootexec.h */
struct sparcexec; /* bootexec.h */
@@ -52,7 +53,7 @@ typedef struct Exectable{
uchar _magic; /* _MAGIC() magic */
Mach *mach; /* Per-machine data */
long hsize; /* header size */
- ulong (*swal)(ulong); /* header swap, beswal or leswal */
+ ulong (*swal)(ulong); /* beswal or leswal */
int (*hparse)(int, Fhdr*, ExecHdr*);
} ExecTable;
@@ -186,7 +187,7 @@ ExecTable exectab[] =
1,
&mamd64,
sizeof(Exec)+8,
- beswal,
+ nil,
commonllp64 },
{ Q_MAGIC, /* PowerPC q.out & boot image */
"power plan 9 executable",
@@ -204,9 +205,9 @@ ExecTable exectab[] =
1,
&mpower64,
sizeof(Exec)+8,
- beswal,
+ nil,
commonllp64 },
- { ELF_MAG, /* any elf32 */
+ { ELF_MAG, /* any ELF */
"elf executable",
nil,
FNONE,
@@ -409,7 +410,13 @@ commonboot(Fhdr *fp)
fp->type = FAMD64B;
fp->txtaddr = fp->entry;
fp->name = "amd64 plan 9 boot image";
- fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize);
+ fp->dataddr = _round(fp->txtaddr+fp->txtsz, 4096);
+ break;
+ case FPOWER64:
+ fp->type = FPOWER64B;
+ fp->txtaddr = fp->entry;
+ fp->name = "power64 plan 9 boot image";
+ fp->dataddr = fp->txtaddr+fp->txtsz;
break;
default:
return;
@@ -441,6 +448,7 @@ commonllp64(int, Fhdr *fp, ExecHdr *hp)
long pgsize;
uvlong entry;
+ hswal(&hp->e, sizeof(Exec)/sizeof(long), beswal);
if(!(hp->e.magic & HDR_MAGIC))
return 0;
@@ -561,12 +569,124 @@ nextboot(int fd, Fhdr *fp, ExecHdr *hp)
}
/*
- * Elf32 binaries.
+ * ELF64 binaries.
*/
static int
-elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
+elf64dotout(int fd, Fhdr *fp, ExecHdr *hp)
{
+ E64hdr *ep;
+ P64hdr *ph;
+ ushort (*swab)(ushort);
+ ulong (*swal)(ulong);
+ uvlong (*swav)(uvlong);
+ int i, it, id, is, phsz;
+ uvlong uvl;
+
+ ep = &hp->e;
+ 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 ELF64 encoding - not big or little endian");
+ return 0;
+ }
+
+ ep->type = swab(ep->type);
+ ep->machine = swab(ep->machine);
+ ep->version = swal(ep->version);
+ if(ep->type != EXEC || ep->version != CURRENT)
+ return 0;
+ ep->elfentry = swav(ep->elfentry);
+ ep->phoff = swav(ep->phoff);
+ ep->shoff = swav(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);
+
+ fp->magic = ELF_MAG;
+ fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15;
+ switch(ep->machine) {
+ default:
+ return 0;
+ case AMD64:
+ mach = &mamd64;
+ fp->type = FAMD64;
+ fp->name = "amd64 ELF64 executable";
+ break;
+ case POWER64:
+ mach = &mpower64;
+ fp->type = FPOWER64;
+ fp->name = "power64 ELF64 executable";
+ break;
+ }
+
+ if(ep->phentsize != sizeof(P64hdr)) {
+ werrstr("bad ELF64 header size");
+ return 0;
+ }
+ phsz = sizeof(P64hdr)*ep->phnum;
+ ph = malloc(phsz);
+ if(!ph)
+ return 0;
+ seek(fd, ep->phoff, 0);
+ if(read(fd, ph, phsz) < 0) {
+ free(ph);
+ return 0;
+ }
+ for(i = 0; i < ep->phnum; i++) {
+ ph[i].type = swal(ph[i].type);
+ ph[i].flags = swal(ph[i].flags);
+ ph[i].offset = swav(ph[i].offset);
+ ph[i].vaddr = swav(ph[i].vaddr);
+ ph[i].paddr = swav(ph[i].paddr);
+ ph[i].filesz = swav(ph[i].filesz);
+ ph[i].memsz = swav(ph[i].memsz);
+ ph[i].align = swav(ph[i].align);
+ }
+
+ /* 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) {
+ werrstr("No ELF64 TEXT or DATA sections");
+ free(ph);
+ return 0;
+ }
+ settext(fp, ep->elfentry, ph[it].vaddr, ph[it].memsz, ph[it].offset);
+ /* 8c: out of fixed registers */
+ uvl = ph[id].memsz - ph[id].filesz;
+ setdata(fp, ph[id].vaddr, ph[id].filesz, ph[id].offset, uvl);
+ if(is != -1)
+ setsym(fp, ph[is].filesz, 0, ph[is].memsz, ph[is].offset);
+ free(ph);
+ return 1;
+}
+
+/*
+ * ELF32 binaries.
+ */
+static int
+elf32dotout(int fd, Fhdr *fp, ExecHdr *hp)
+{
ulong (*swal)(ulong);
ushort (*swab)(ushort);
Ehdr *ep;
@@ -575,10 +695,6 @@ elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
/* bitswap the header according to the DATA format */
ep = &hp->e;
- if(ep->ident[CLASS] != ELFCLASS32) {
- werrstr("bad ELF class - not 32 bit");
- return 0;
- }
if(ep->ident[DATA] == ELFDATA2LSB) {
swab = leswab;
swal = leswal;
@@ -586,7 +702,7 @@ elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
swab = beswab;
swal = beswal;
} else {
- werrstr("bad ELF encoding - not big or little endian");
+ werrstr("bad ELF32 encoding - not big or little endian");
return 0;
}
@@ -613,33 +729,44 @@ elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
case I386:
mach = &mi386;
fp->type = FI386;
+ fp->name = "386 ELF32 executable";
break;
case MIPS:
mach = &mmips;
fp->type = FMIPS;
+ fp->name = "mips ELF32 executable";
break;
case SPARC64:
mach = &msparc64;
fp->type = FSPARC64;
+ fp->name = "sparc64 ELF32 executable";
break;
case POWER:
mach = &mpower;
fp->type = FPOWER;
+ fp->name = "power ELF32 executable";
+ break;
+ case POWER64:
+ mach = &mpower64;
+ fp->type = FPOWER64;
+ fp->name = "power64 ELF32 executable";
break;
case AMD64:
mach = &mamd64;
fp->type = FAMD64;
+ fp->name = "amd64 ELF32 executable";
break;
case ARM:
mach = &marm;
fp->type = FARM;
+ fp->name = "arm ELF32 executable";
break;
default:
return 0;
}
if(ep->phentsize != sizeof(Phdr)) {
- werrstr("bad ELF header size");
+ werrstr("bad ELF32 header size");
return 0;
}
phsz = sizeof(Phdr)*ep->phnum;
@@ -689,7 +816,7 @@ elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
return 1;
}
- werrstr("No TEXT or DATA sections");
+ werrstr("No ELF32 TEXT or DATA sections");
free(ph);
return 0;
}
@@ -703,6 +830,25 @@ elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
}
/*
+ * Elf binaries.
+ */
+static int
+elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
+{
+ Ehdr *ep;
+
+ /* bitswap the header according to the DATA format */
+ ep = &hp->e;
+ if(ep->ident[CLASS] == ELFCLASS32)
+ return elf32dotout(fd, fp, hp);
+ else if(ep->ident[CLASS] == ELFCLASS64)
+ return elf64dotout(fd, fp, hp);
+
+ werrstr("bad ELF class - not 32 bit");
+ return 0;
+}
+
+/*
* (Free|Net)BSD ARM header.
*/
static int
diff --git a/sys/src/libmach/map.c b/sys/src/libmach/map.c
index c668defd1..c745d82a6 100644
--- a/sys/src/libmach/map.c
+++ b/sys/src/libmach/map.c
@@ -89,13 +89,11 @@ attachproc(int pid, int kflag, int corefd, Fhdr *fp)
map = newmap(0, 4);
if (!map)
return 0;
- if(kflag) {
+ if(kflag)
regs = "kregs";
- mode = OREAD;
- } else {
+ else
regs = "regs";
- mode = ORDWR;
- }
+ mode = ORDWR;
if (mach->regsize) {
sprint(buf, "/proc/%d/%s", pid, regs);
fd = open(buf, mode);
diff --git a/sys/src/libmach/mkfile b/sys/src/libmach/mkfile
index a71bcfd88..27ab477ae 100644
--- a/sys/src/libmach/mkfile
+++ b/sys/src/libmach/mkfile
@@ -55,3 +55,15 @@ UPDATE=mkfile\
</sys/src/cmd/mksyslib
CFLAGS=$CFLAGS -I/sys/src/cmd
+
+2obj.$O: /sys/src/cmd/2c/2.out.h
+5obj.$O: /sys/src/cmd/5c/5.out.h
+6obj.$O: /sys/src/cmd/6c/6.out.h
+7obj.$O: /sys/src/cmd/7c/7.out.h
+8obj.$O: /sys/src/cmd/8c/8.out.h
+kobj.$O: /sys/src/cmd/kc/k.out.h
+qobj.$O: /sys/src/cmd/qc/q.out.h
+vobj.$O: /sys/src/cmd/vc/v.out.h
+
+# 9obj.$O: /sys/src/cmd/9c/9.out.h
+# uobj.$O: uc/u.out.h
diff --git a/sys/src/libmach/sym.c b/sys/src/libmach/sym.c
index c80793d94..ab647e621 100644
--- a/sys/src/libmach/sym.c
+++ b/sys/src/libmach/sym.c
@@ -102,15 +102,17 @@ syminit(int fd, Fhdr *fp)
Bseek(&b, fp->symoff, 0);
nsym = 0;
size = 0;
+ if((fp->_magic && (fp->magic & HDR_MAGIC)) || mach->szaddr == 8)
+ svalsz = 8;
+ else
+ svalsz = 4;
for(p = symbols; size < fp->symsz; p++, nsym++) {
- if(fp->_magic && (fp->magic & HDR_MAGIC)){
- svalsz = 8;
+ if(svalsz == 8){
if(Bread(&b, &vl, 8) != 8)
return symerrmsg(8, "symbol");
p->value = beswav(vl);
}
else{
- svalsz = 4;
if(Bread(&b, &l, 4) != 4)
return symerrmsg(4, "symbol");
p->value = (u32int)beswal(l);