diff options
Diffstat (limited to 'src/libmach')
-rw-r--r-- | src/libmach/5obj.c | 3 | ||||
-rw-r--r-- | src/libmach/8db.c | 1 | ||||
-rw-r--r-- | src/libmach/darwin.c | 2 | ||||
-rw-r--r-- | src/libmach/executable.c | 42 | ||||
-rw-r--r-- | src/libmach/obj.c | 2 | ||||
-rw-r--r-- | src/libmach/sym.c | 169 | ||||
-rw-r--r-- | src/libmach/windows.c | 8 |
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 |