summaryrefslogtreecommitdiff
path: root/src/libmach
diff options
context:
space:
mode:
Diffstat (limited to 'src/libmach')
-rw-r--r--src/libmach/5obj.c3
-rw-r--r--src/libmach/8db.c1
-rw-r--r--src/libmach/darwin.c2
-rw-r--r--src/libmach/executable.c42
-rw-r--r--src/libmach/obj.c2
-rw-r--r--src/libmach/sym.c169
-rw-r--r--src/libmach/windows.c8
7 files changed, 179 insertions, 48 deletions
diff --git a/src/libmach/5obj.c b/src/libmach/5obj.c
index e539362b0..57573b866 100644
--- a/src/libmach/5obj.c
+++ b/src/libmach/5obj.c
@@ -42,6 +42,7 @@ struct Addr
char type;
char sym;
char name;
+ char gotype;
};
static Addr addr(Biobuf*);
static char type2char(int);
@@ -115,6 +116,7 @@ addr(Biobuf *bp)
skip(bp,1); /* reg */
a.sym = Bgetc(bp); /* sym index */
a.name = Bgetc(bp); /* sym type */
+ a.gotype = Bgetc(bp); /* go type */
switch(a.type){
default:
case D_NONE:
@@ -124,6 +126,7 @@ addr(Biobuf *bp)
case D_FPCR:
break;
case D_REGREG:
+ case D_REGREG2:
Bgetc(bp);
break;
case D_CONST2:
diff --git a/src/libmach/8db.c b/src/libmach/8db.c
index ce1b4ddd7..9ef02c428 100644
--- a/src/libmach/8db.c
+++ b/src/libmach/8db.c
@@ -622,6 +622,7 @@ static Optable optab0F[256]=
[0x15] = { RM,0, "UNPCKH%s %x,%X" },
[0x16] = { RM,0, "MOV[L]H%s %x,%X" }, /* TO DO: L if source is XMM */
[0x17] = { RM,0, "MOVH%s %X,%x" },
+[0x1F] = { RM,0, "NOP%S %e" },
[0x20] = { RMR,0, "MOVL %C,%e" },
[0x21] = { RMR,0, "MOVL %D,%e" },
[0x22] = { RMR,0, "MOVL %e,%C" },
diff --git a/src/libmach/darwin.c b/src/libmach/darwin.c
index 63abde313..753d940fd 100644
--- a/src/libmach/darwin.c
+++ b/src/libmach/darwin.c
@@ -751,7 +751,7 @@ havet:
static void*
excthread(void *v)
{
- extern boolean_t exc_server();
+ extern boolean_t exc_server(mach_msg_header_t *, mach_msg_header_t *);
mach_msg_server(exc_server, 2048, excport, 0);
return 0;
}
diff --git a/src/libmach/executable.c b/src/libmach/executable.c
index 3db3e7da4..a93a8c268 100644
--- a/src/libmach/executable.c
+++ b/src/libmach/executable.c
@@ -1091,12 +1091,21 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp)
}
cmdbuf = malloc(mp->sizeofcmds);
+ if(!cmdbuf) {
+ werrstr("out of memory");
+ return 0;
+ }
seek(fd, hdrsize, 0);
if(read(fd, cmdbuf, mp->sizeofcmds) != mp->sizeofcmds) {
free(cmdbuf);
return 0;
}
cmd = malloc(mp->ncmds * sizeof(MachCmd*));
+ if(!cmd) {
+ free(cmdbuf);
+ werrstr("out of memory");
+ return 0;
+ }
cmdp = cmdbuf;
textva = 0;
textoff = 0;
@@ -1340,12 +1349,12 @@ static int
pedotout(int fd, Fhdr *fp, ExecHdr *hp)
{
uint32 start, magic;
- uint32 symtab, esymtab;
+ uint32 symtab, esymtab, pclntab, epclntab;
IMAGE_FILE_HEADER fh;
IMAGE_SECTION_HEADER sh;
IMAGE_OPTIONAL_HEADER oh;
uint8 sym[18];
- uint32 *valp;
+ uint32 *valp, ib;
int i;
USED(hp);
@@ -1380,6 +1389,19 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
return 0;
}
+ switch(oh.Magic) {
+ case 0x10b: // PE32
+ fp->type = FI386;
+ break;
+ case 0x20b: // PE32+
+ fp->type = FAMD64;
+ break;
+ default:
+ werrstr("invalid PE Optional magic number");
+ return 0;
+ }
+
+ ib=leswal(oh.ImageBase);
seek(fd, start+sizeof(magic)+sizeof(fh)+leswab(fh.SizeOfOptionalHeader), 0);
fp->txtaddr = 0;
fp->dataddr = 0;
@@ -1389,9 +1411,9 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
return 0;
}
if (match8(sh.Name, ".text"))
- settext(fp, leswal(sh.VirtualAddress), leswal(oh.AddressOfEntryPoint), leswal(sh.VirtualSize), leswal(sh.PointerToRawData));
+ settext(fp, ib+leswal(oh.AddressOfEntryPoint), ib+leswal(sh.VirtualAddress), leswal(sh.VirtualSize), leswal(sh.PointerToRawData));
if (match8(sh.Name, ".data"))
- setdata(fp, leswal(sh.VirtualAddress), leswal(sh.SizeOfRawData), leswal(sh.PointerToRawData), leswal(sh.VirtualSize)-leswal(sh.SizeOfRawData));
+ setdata(fp, ib+leswal(sh.VirtualAddress), leswal(sh.SizeOfRawData), leswal(sh.PointerToRawData), leswal(sh.VirtualSize)-leswal(sh.SizeOfRawData));
}
if (fp->txtaddr==0 || fp->dataddr==0) {
werrstr("no .text or .data");
@@ -1399,7 +1421,7 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
}
seek(fd, leswal(fh.PointerToSymbolTable), 0);
- symtab = esymtab = 0;
+ symtab = esymtab = pclntab = epclntab = 0;
for (i=0; i<leswal(fh.NumberOfSymbols); i++) {
if (readn(fd, sym, sizeof(sym)) != sizeof(sym)) {
werrstr("crippled COFF symbol %d", i);
@@ -1410,12 +1432,16 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
symtab = leswal(*valp);
if (match8(sym, "esymtab"))
esymtab = leswal(*valp);
+ if (match8(sym, "pclntab"))
+ pclntab = leswal(*valp);
+ if (match8(sym, "epclntab"))
+ epclntab = leswal(*valp);
}
- if (symtab==0 || esymtab==0) {
- werrstr("no symtab or esymtab in COFF symbol table");
+ if (symtab==0 || esymtab==0 || pclntab==0 || epclntab==0) {
+ werrstr("no symtab or esymtab or pclntab or epclntab in COFF symbol table");
return 0;
}
- setsym(fp, symtab, esymtab-symtab, 0, 0, 0, 0);
+ setsym(fp, symtab, esymtab-symtab, 0, 0, pclntab, epclntab-pclntab);
return 1;
}
diff --git a/src/libmach/obj.c b/src/libmach/obj.c
index 7999f24c6..2a5e04758 100644
--- a/src/libmach/obj.c
+++ b/src/libmach/obj.c
@@ -293,6 +293,8 @@ objlookup(int id, char *name, int type, uint sig)
}
}
sp = malloc(sizeof(Symtab));
+ if(sp == nil)
+ sysfatal("out of memory");
sp->s.name = name;
sp->s.type = type;
sp->s.sig = sig;
diff --git a/src/libmach/sym.c b/src/libmach/sym.c
index 1512d7a4f..120328d09 100644
--- a/src/libmach/sym.c
+++ b/src/libmach/sym.c
@@ -1,11 +1,11 @@
// Inferno libmach/sym.c
// http://code.google.com/p/inferno-os/source/browse/utils/libmach/sym.c
//
-// Copyright © 1994-1999 Lucent Technologies Inc.
-// Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
-// Portions Copyright © 1997-1999 Vita Nuova Limited.
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
-// Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
+// 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
@@ -112,13 +112,19 @@ syminit(int fd, Fhdr *fp)
int32 i, l, size;
vlong vl;
Biobuf b;
- int svalsz;
+ int svalsz, newformat, shift;
+ uvlong (*swav)(uvlong);
+ uint32 (*swal)(uint32);
+ uchar buf[8], c;
if(fp->symsz == 0)
return 0;
if(fp->type == FNONE)
return 0;
+ swav = beswav;
+ swal = beswal;
+
cleansyms();
textseg(fp->txtaddr, fp);
/* minimum symbol record size = 4+1+2 bytes */
@@ -129,40 +135,128 @@ syminit(int fd, Fhdr *fp)
}
Binit(&b, fd, OREAD);
Bseek(&b, fp->symoff, 0);
+ memset(buf, 0, sizeof buf);
+ Bread(&b, buf, sizeof buf);
+ newformat = 0;
+ if(memcmp(buf, "\xfd\xff\xff\xff\x00\x00\x00", 7) == 0) {
+ swav = leswav;
+ swal = leswal;
+ newformat = 1;
+ } else if(memcmp(buf, "\xff\xff\xff\xfd\x00\x00\x00", 7) == 0) {
+ newformat = 1;
+ } else if(memcmp(buf, "\xfe\xff\xff\xff\x00\x00", 6) == 0) {
+ // Table format used between Go 1.0 and Go 1.1:
+ // little-endian but otherwise same as the old Go 1.0 table.
+ // Not likely to be seen much in practice, but easy to handle.
+ swav = leswav;
+ swal = leswal;
+ Bseek(&b, fp->symoff+6, 0);
+ } else {
+ Bseek(&b, fp->symoff, 0);
+ }
+ svalsz = 0;
+ if(newformat) {
+ svalsz = buf[7];
+ if(svalsz != 4 && svalsz != 8) {
+ werrstr("invalid word size %d bytes", svalsz);
+ return -1;
+ }
+ }
+
nsym = 0;
size = 0;
for(p = symbols; size < fp->symsz; p++, nsym++) {
- if(fp->_magic && (fp->magic & HDR_MAGIC)){
- 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);
- }
- if(Bread(&b, &p->type, sizeof(p->type)) != sizeof(p->type))
- return symerrmsg(sizeof(p->value), "symbol");
-
- i = decodename(&b, p);
- if(i < 0)
- return -1;
- size += i+svalsz+sizeof(p->type);
-
- if(svalsz == 8){
- if(Bread(&b, &vl, 8) != 8)
- return symerrmsg(8, "symbol");
- p->gotype = beswav(vl);
- }
- else{
- if(Bread(&b, &l, 4) != 4)
- return symerrmsg(4, "symbol");
- p->gotype = (u32int)beswal(l);
+ if(newformat) {
+ // Go 1.1 format. See comment at top of ../pkg/runtime/symtab.c.
+ if(Bread(&b, &c, 1) != 1)
+ return symerrmsg(1, "symbol");
+ if((c&0x3F) < 26)
+ p->type = (c&0x3F)+ 'A';
+ else
+ p->type = (c&0x3F) - 26 + 'a';
+ size++;
+
+ if(c&0x40) {
+ // Fixed-width address.
+ if(svalsz == 8) {
+ if(Bread(&b, &vl, 8) != 8)
+ return symerrmsg(8, "symbol");
+ p->value = swav(vl);
+ } else {
+ if(Bread(&b, &l, 4) != 4)
+ return symerrmsg(4, "symbol");
+ p->value = (u32int)swal(l);
+ }
+ size += svalsz;
+ } else {
+ // Varint address.
+ shift = 0;
+ p->value = 0;
+ for(;;) {
+ if(Bread(&b, buf, 1) != 1)
+ return symerrmsg(1, "symbol");
+ p->value |= (uint64)(buf[0]&0x7F)<<shift;
+ shift += 7;
+ size++;
+ if((buf[0]&0x80) == 0)
+ break;
+ }
+ }
+ p->gotype = 0;
+ if(c&0x80) {
+ // Has Go type. Fixed-width address.
+ if(svalsz == 8) {
+ if(Bread(&b, &vl, 8) != 8)
+ return symerrmsg(8, "symbol");
+ p->gotype = swav(vl);
+ } else {
+ if(Bread(&b, &l, 4) != 4)
+ return symerrmsg(4, "symbol");
+ p->gotype = (u32int)swal(l);
+ }
+ size += svalsz;
+ }
+
+ // Name.
+ p->type |= 0x80; // for decodename
+ i = decodename(&b, p);
+ if(i < 0)
+ return -1;
+ size += i;
+ } else {
+ // Go 1.0 format: Plan 9 format + go type symbol.
+ if(fp->_magic && (fp->magic & HDR_MAGIC)){
+ svalsz = 8;
+ if(Bread(&b, &vl, 8) != 8)
+ return symerrmsg(8, "symbol");
+ p->value = swav(vl);
+ }
+ else{
+ svalsz = 4;
+ if(Bread(&b, &l, 4) != 4)
+ return symerrmsg(4, "symbol");
+ p->value = (u32int)swal(l);
+ }
+ if(Bread(&b, &p->type, sizeof(p->type)) != sizeof(p->type))
+ return symerrmsg(sizeof(p->value), "symbol");
+
+ i = decodename(&b, p);
+ if(i < 0)
+ return -1;
+ size += i+svalsz+sizeof(p->type);
+
+ if(svalsz == 8){
+ if(Bread(&b, &vl, 8) != 8)
+ return symerrmsg(8, "symbol");
+ p->gotype = swav(vl);
+ }
+ else{
+ if(Bread(&b, &l, 4) != 4)
+ return symerrmsg(4, "symbol");
+ p->gotype = (u32int)swal(l);
+ }
+ size += svalsz;
}
- size += svalsz;
/* count global & auto vars, text symbols, and file names */
switch (p->type) {
@@ -576,7 +670,8 @@ lookup(char *fn, char *var, Symbol *s)
* strcmp, but allow '_' to match center dot (rune 00b7 == bytes c2 b7)
*/
int
-cdotstrcmp(char *sym, char *user) {
+cdotstrcmp(char *sym, char *user)
+{
for (;;) {
while (*sym == *user) {
if (*sym++ == '\0')
diff --git a/src/libmach/windows.c b/src/libmach/windows.c
index 81fa6b6d2..aea7bace0 100644
--- a/src/libmach/windows.c
+++ b/src/libmach/windows.c
@@ -48,8 +48,12 @@ procthreadpids(int pid, int *p, int np)
int
pread(int fd, void *buf, int count, int offset)
{
- sysfatal("pread unimplemented in Windows");
- return -1;
+ int oldoffset, n;
+
+ oldoffset = seek(fd, offset, 0);
+ n = read(fd, buf, count);
+ seek(fd, oldoffset, 0);
+ return n;
}
int