diff options
Diffstat (limited to 'src/libmach')
-rw-r--r-- | src/libmach/5obj.c | 3 | ||||
-rw-r--r-- | src/libmach/8db.c | 51 | ||||
-rw-r--r-- | src/libmach/Makefile | 22 | ||||
-rw-r--r-- | src/libmach/darwin.c | 11 | ||||
-rw-r--r-- | src/libmach/executable.c | 62 | ||||
-rw-r--r-- | src/libmach/linux.c | 58 | ||||
-rw-r--r-- | src/libmach/windows.c | 59 |
7 files changed, 178 insertions, 88 deletions
diff --git a/src/libmach/5obj.c b/src/libmach/5obj.c index 034deea2c..e539362b0 100644 --- a/src/libmach/5obj.c +++ b/src/libmach/5obj.c @@ -123,6 +123,9 @@ addr(Biobuf *bp) case D_PSR: case D_FPCR: break; + case D_REGREG: + Bgetc(bp); + break; case D_CONST2: Bgetc(bp); Bgetc(bp); diff --git a/src/libmach/8db.c b/src/libmach/8db.c index 92e4c7694..80aa4fe69 100644 --- a/src/libmach/8db.c +++ b/src/libmach/8db.c @@ -329,8 +329,8 @@ struct Instr uchar mod; /* bits 6-7 of mod r/m field */ uchar reg; /* bits 3-5 of mod r/m field */ char ss; /* bits 6-7 of SIB */ - char index; /* bits 3-5 of SIB */ - char base; /* bits 0-2 of SIB */ + schar index; /* bits 3-5 of SIB */ + schar base; /* bits 0-2 of SIB */ char rip; /* RIP-relative in amd64 mode */ uchar opre; /* f2/f3 could introduce media */ short seg; /* segment of far address */ @@ -355,14 +355,15 @@ enum{ DI, /* amd64 */ - R8, - R9, - R10, - R11, - R12, - R13, - R14, - R15 + /* be careful: some unix system headers #define R8, R9, etc */ + AMD64_R8, + AMD64_R9, + AMD64_R10, + AMD64_R11, + AMD64_R12, + AMD64_R13, + AMD64_R14, + AMD64_R15 }; /* amd64 rex extension byte */ @@ -416,8 +417,8 @@ enum { RMOPB, /* Byte R/M field with op code (/digit) */ RMR, /* R/M register only (mod = 11) */ RMM, /* R/M memory only (mod = 0/1/2) */ - R0, /* Base reg of Mod R/M is literal 0x00 */ - R1, /* Base reg of Mod R/M is literal 0x01 */ + Op_R0, /* Base reg of Mod R/M is literal 0x00 */ + Op_R1, /* Base reg of Mod R/M is literal 0x01 */ FRMOP, /* Floating point R/M field with opcode */ FRMEX, /* Extended floating point R/M field with opcode */ JUMP, /* Jump or Call flag - no operand */ @@ -1006,7 +1007,7 @@ static Optable optabDA[8+8] = [0x09] 0,0, "FCMOVEQ %f,F0", [0x0a] 0,0, "FCMOVLS %f,F0", [0x0b] 0,0, "FCMOVUN %f,F0", -[0x0d] R1,0, "FUCOMPP", +[0x0d] Op_R1,0, "FUCOMPP", }; static Optable optabDB[8+64] = @@ -1071,7 +1072,7 @@ static Optable optabDE[8+8] = [0x07] 0,0, "FDIVRW %e,F0", [0x08] 0,0, "FADDDP F0,%f", [0x09] 0,0, "FMULDP F0,%f", -[0x0b] R1,0, "FCOMPDP", +[0x0b] Op_R1,0, "FCOMPDP", [0x0c] 0,0, "FSUBRDP F0,%f", [0x0d] 0,0, "FSUBDP F0,%f", [0x0e] 0,0, "FDIVRDP F0,%f", @@ -1087,7 +1088,7 @@ static Optable optabDF[8+8] = [0x05] 0,0, "FMOVL %e,F0", [0x06] 0,0, "FBSTP %e", [0x07] 0,0, "FMOVLP F0,%e", -[0x0c] R0,0, "FSTSW %OAX", +[0x0c] Op_R0,0, "FSTSW %OAX", [0x0d] 0,0, "FUCOMIP F0,%f", [0x0e] 0,0, "FCOMIP F0,%f", }; @@ -1713,11 +1714,11 @@ badop: if (c != 0x0a) goto badop; break; - case R0: /* base register must be R0 */ + case Op_R0: /* base register must be R0 */ if (ip->base != 0) goto badop; break; - case R1: /* base register must be R1 */ + case Op_R1: /* base register must be R1 */ if (ip->base != 1) goto badop; break; @@ -1903,14 +1904,14 @@ static char *reg[] = { [DI] "DI", /* amd64 */ -[R8] "R8", -[R9] "R9", -[R10] "R10", -[R11] "R11", -[R12] "R12", -[R13] "R13", -[R14] "R14", -[R15] "R15", +[AMD64_R8] "R8", +[AMD64_R9] "R9", +[AMD64_R10] "R10", +[AMD64_R11] "R11", +[AMD64_R12] "R12", +[AMD64_R13] "R13", +[AMD64_R14] "R14", +[AMD64_R15] "R15", }; static char *breg[] = { "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH" }; diff --git a/src/libmach/Makefile b/src/libmach/Makefile index 900d27861..5d7e87d86 100644 --- a/src/libmach/Makefile +++ b/src/libmach/Makefile @@ -26,7 +26,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -include ../Make.conf +include ../Make.inc +O:=$(HOST_O) LIB=libmach.a OFILES=\ @@ -52,21 +53,12 @@ ifneq ($(GOOS),windows) OFILES+=\ $(shell uname | tr A-Z a-z).$O\ +else +OFILES+=\ + windows.$O\ + endif HFILES=../../include/mach.h elf.h macho.h obj.h -install: $(LIB) - cp $(LIB) ../../lib - -$(LIB): $(OFILES) - ar rsc $(LIB) $(OFILES) - -$(OFILES): $(HFILES) - -clean: - rm -f *.$O $(LIB) - -nuke: clean - rm -f "$(GOROOT)"/lib/$(LIB) - +include ../Make.clib diff --git a/src/libmach/darwin.c b/src/libmach/darwin.c index feb49c059..7ee6f7ace 100644 --- a/src/libmach/darwin.c +++ b/src/libmach/darwin.c @@ -807,8 +807,10 @@ ctlproc(int id, char *msg) // Find Mach thread for pid and suspend it. t = addpid(id, 1); - if(t == nil) + if(t == nil) { + fprint(2, "ctlproc attached: addpid: %r\n"); return -1; + } if(me(thread_suspend(t->thread)) < 0){ fprint(2, "ctlproc attached: thread_suspend: %r\n"); return -1; @@ -816,7 +818,12 @@ ctlproc(int id, char *msg) // Let ptrace tell the process to keep going: // then ptrace is out of the way and we're back in Mach land. - return ptrace(PT_CONTINUE, id, (caddr_t)1, 0); + if(ptrace(PT_CONTINUE, id, (caddr_t)1, 0) < 0) { + fprint(2, "ctlproc attached: ptrace continue: %r\n"); + return -1; + } + + return 0; } // All the other control messages require a Thread structure. diff --git a/src/libmach/executable.c b/src/libmach/executable.c index 34da72151..33000ed07 100644 --- a/src/libmach/executable.c +++ b/src/libmach/executable.c @@ -66,7 +66,7 @@ static int adotout(int, Fhdr*, ExecHdr*); static int elfdotout(int, Fhdr*, ExecHdr*); static int machdotout(int, Fhdr*, ExecHdr*); static int armdotout(int, Fhdr*, ExecHdr*); -static void setsym(Fhdr*, int32, int32, int32, vlong); +static void setsym(Fhdr*, vlong, int32, vlong, int32, vlong, int32); static void setdata(Fhdr*, uvlong, int32, vlong, int32); static void settext(Fhdr*, uvlong, uvlong, int32, vlong); static void hswal(void*, int, uint32(*)(uint32)); @@ -427,7 +427,7 @@ adotout(int fd, Fhdr *fp, ExecHdr *hp) 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); + setsym(fp, fp->datoff+fp->datsz, hp->e.exechdr.syms, 0, hp->e.exechdr.spsz, 0, hp->e.exechdr.pcsz); return 1; } @@ -525,7 +525,7 @@ commonllp64(int unused, Fhdr *fp, ExecHdr *hp) 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); + setsym(fp, fp->datoff+fp->datsz, hp->e.exechdr.syms, 0, hp->e.exechdr.spsz, 0, hp->e.exechdr.pcsz); if(hp->e.exechdr.magic & DYN_MAGIC) { fp->txtaddr = 0; @@ -758,13 +758,12 @@ elf64dotout(int fd, Fhdr *fp, ExecHdr *hp) 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); + setsym(fp, ph[1].offset, ph[1].filesz, 0, 0, 0, ph[1].memsz); free(ph); return 1; } werrstr("No TEXT or DATA sections"); -error: free(ph); free(sh); return 0; @@ -773,12 +772,13 @@ error: 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); + setsym(fp, ph[is].offset, ph[is].filesz, 0, 0, 0, ph[is].memsz); else if(sh != 0){ char *buf; uvlong symsize = 0; uvlong symoff = 0; uvlong pclnsz = 0; + uvlong pclnoff = 0; /* load shstrtab names */ buf = malloc(sh[ep->shstrndx].size); @@ -786,7 +786,8 @@ error: goto done; memset(buf, 0, sizeof buf); seek(fd, sh[ep->shstrndx].offset, 0); - read(fd, buf, sh[ep->shstrndx].size); + i = read(fd, buf, sh[ep->shstrndx].size); + USED(i); // shut up ubuntu gcc for(i = 0; i < ep->shnum; i++) { if (strcmp(&buf[sh[i].name], ".gosymtab") == 0) { @@ -794,15 +795,11 @@ error: symoff = sh[i].offset; } if (strcmp(&buf[sh[i].name], ".gopclntab") == 0) { - if (sh[i].offset != symoff+symsize) { - werrstr("pc line table not contiguous with symbol table"); - free(buf); - goto error; - } pclnsz = sh[i].size; + pclnoff = sh[i].offset; } } - setsym(fp, symsize, 0, pclnsz, symoff); + setsym(fp, symoff, symsize, 0, 0, pclnoff, pclnsz); free(buf); } done: @@ -939,13 +936,12 @@ elfdotout(int fd, Fhdr *fp, ExecHdr *hp) 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); + setsym(fp, ph[1].offset, ph[1].filesz, 0, 0, 0, ph[1].memsz); free(ph); return 1; } werrstr("No TEXT or DATA sections"); -error: free(sh); free(ph); return 0; @@ -954,12 +950,13 @@ error: 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); + setsym(fp, ph[is].offset, ph[is].filesz, 0, 0, 0, ph[is].memsz); else if(sh != 0){ char *buf; uvlong symsize = 0; uvlong symoff = 0; - uvlong pclnsz = 0; + uvlong pclnsize = 0; + uvlong pclnoff = 0; /* load shstrtab names */ buf = malloc(sh[ep->shstrndx].size); @@ -967,7 +964,8 @@ error: goto done; memset(buf, 0, sizeof buf); seek(fd, sh[ep->shstrndx].offset, 0); - read(fd, buf, sh[ep->shstrndx].size); + i = read(fd, buf, sh[ep->shstrndx].size); + USED(i); // shut up ubuntu gcc for(i = 0; i < ep->shnum; i++) { if (strcmp(&buf[sh[i].name], ".gosymtab") == 0) { @@ -975,15 +973,11 @@ error: symoff = sh[i].offset; } if (strcmp(&buf[sh[i].name], ".gopclntab") == 0) { - if (sh[i].offset != symoff+symsize) { - werrstr("pc line table not contiguous with symbol table"); - free(buf); - goto error; - } - pclnsz = sh[i].size; + pclnsize = sh[i].size; + pclnoff = sh[i].offset; } } - setsym(fp, symsize, 0, pclnsz, symoff); + setsym(fp, symoff, symsize, 0, 0, pclnoff, pclnsize); free(buf); } done: @@ -1207,7 +1201,7 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp) settext(fp, textva+sizeof(Machhdr) + mp->sizeofcmds, textva, textsize, textoff); setdata(fp, datava, datasize, dataoff, bsssize); if(symtab != 0) - setsym(fp, symtab->filesize, 0, pclntab? pclntab->filesize : 0, symtab->fileoff); + setsym(fp, symtab->fileoff, symtab->filesize, 0, 0, 0, pclntab? pclntab->filesize : 0); free(cmd); free(cmdbuf); return 1; @@ -1228,7 +1222,7 @@ armdotout(int fd, Fhdr *fp, ExecHdr *hp) 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); + setsym(fp, fp->datoff+fp->datsz, hp->e.exechdr.syms, 0, hp->e.exechdr.spsz, 0, hp->e.exechdr.pcsz); kbase = 0xF0000000; if ((fp->entry & kbase) == kbase) { /* Boot image */ @@ -1259,14 +1253,20 @@ setdata(Fhdr *fp, uvlong a, int32 s, vlong off, int32 bss) } static void -setsym(Fhdr *fp, int32 symsz, int32 sppcsz, int32 lnpcsz, vlong symoff) +setsym(Fhdr *fp, vlong symoff, int32 symsz, vlong sppcoff, int32 sppcsz, vlong lnpcoff, int32 lnpcsz) { - fp->symsz = symsz; fp->symoff = symoff; + fp->symsz = symsz; + + if(sppcoff == 0) + sppcoff = symoff+symsz; + fp->sppcoff = symoff; fp->sppcsz = sppcsz; - fp->sppcoff = fp->symoff+fp->symsz; + + if(lnpcoff == 0) + lnpcoff = sppcoff + sppcsz; + fp->lnpcoff = lnpcoff; fp->lnpcsz = lnpcsz; - fp->lnpcoff = fp->sppcoff+fp->sppcsz; } diff --git a/src/libmach/linux.c b/src/libmach/linux.c index 46724b87e..30b4da240 100644 --- a/src/libmach/linux.c +++ b/src/libmach/linux.c @@ -199,9 +199,11 @@ attachthread(int pid, int tid, int *new, int newstate) t = malloc(sizeof *t); if(t == nil) return nil; - memset(t, 0, sizeof *t); + memset(t, 0, sizeof *t); thr[nthr++] = t; + if(pid == 0 && nthr > 0) + pid = thr[0]->pid; t->pid = pid; t->tid = tid; t->state = newstate; @@ -296,7 +298,9 @@ wait1(int nohang) if(nohang != 0) nohang = WNOHANG; + status = 0; tid = waitpid(-1, &status, __WALL|WUNTRACED|WSTOPPED|WCONTINUED|nohang); + if(tid < 0) return -1; if(tid == 0) @@ -305,11 +309,15 @@ wait1(int nohang) if(trace > 0 && status != NormalStop) fprint(2, "TID %d: %#x\n", tid, status); - // If we've not heard of this tid, something is wrong. t = findthread(tid); if(t == nil) { - fprint(2, "ptrace waitpid: unexpected new tid %d status %#x\n", tid, status); - return -1; + // Sometimes the kernel tells us about new threads + // before we see the parent clone. + t = attachthread(0, tid, &new, Stopped); + if(t == nil) { + fprint(2, "failed to attach to new thread %d\n", tid); + return -1; + } } if(WIFSTOPPED(status)) { @@ -339,8 +347,6 @@ wait1(int nohang) } t->child = data; attachthread(t->pid, t->child, &new, Running); - if(!new) - fprint(2, "ptrace child: not new\n"); break; case PTRACE_EVENT_EXEC: @@ -759,9 +765,9 @@ ptracerw(int type, int xtype, int isr, int pid, uvlong addr, void *v, uint n) if(errno) goto ptraceerr; if(n-i >= sizeof(uintptr)) - *(uintptr*)((char*)v+i) = u; + memmove((char*)v+i, &u, sizeof(uintptr)); else{ - *(uintptr*)buf = u; + memmove(buf, &u, sizeof u); memmove((char*)v+i, buf, n-i); } }else{ @@ -772,9 +778,9 @@ ptracerw(int type, int xtype, int isr, int pid, uvlong addr, void *v, uint n) u = ptrace(xtype, pid, addr+i, 0); if(errno) return -1; - *(uintptr*)buf = u; + memmove(buf, &u, sizeof u); memmove(buf, (char*)v+i, n-i); - u = *(uintptr*)buf; + memmove(&u, buf, sizeof u); } if(ptrace(type, pid, addr+i, u) < 0) goto ptraceerr; @@ -810,9 +816,22 @@ ptracesegrw(Map *map, Seg *seg, uvlong addr, void *v, uint n, int isr) // Go 32-bit is // DI SI BP NSP BX DX CX AX GS FS ES DS TRAP ECODE PC CS EFLAGS SP SS -// uint go32tolinux32tab[] = { -// 4, 3, 5, 15, 0, 2, 1, 6, 10, 9, 8, 7, -1, -1, 12, 13, 14, 15, 16 -// }; +uint go32tolinux32tab[] = { + 4, 3, 5, 15, 0, 2, 1, 6, 10, 9, 8, 7, -1, -1, 12, 13, 14, 15, 16 +}; +static int +go32tolinux32(uvlong addr) +{ + int r; + + if(addr%4 || addr/4 >= nelem(go32tolinux32tab)) + return -1; + r = go32tolinux32tab[addr/4]; + if(r < 0) + return -1; + return r*4; +} + uint go32tolinux64tab[] = { 14, 13, 4, 19, 5, 12, 11, 10, 26, 25, 24, 23, -1, -1, 16, 17, 18, 19, 20 }; @@ -830,15 +849,24 @@ go32tolinux64(uvlong addr) } extern Mach mi386; +extern Mach mamd64; static int go2linux(uvlong addr) { - // TODO(rsc): If this file is being compiled in 32-bit mode, - // need to use the go32tolinux32 table instead. + if(sizeof(void*) == 4) { + if(mach == &mi386) + return go32tolinux32(addr); + werrstr("unsupported architecture"); + return -1; + } if(mach == &mi386) return go32tolinux64(addr); + if(mach != &mamd64) { + werrstr("unsupported architecture"); + return -1; + } switch(addr){ case offsetof(Ureg64, ax): diff --git a/src/libmach/windows.c b/src/libmach/windows.c new file mode 100644 index 000000000..391761c18 --- /dev/null +++ b/src/libmach/windows.c @@ -0,0 +1,59 @@ +// This is stubbed out for the moment. Will revisit when the time comes. +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> + +int +ctlproc(int pid, char *msg) +{ + sysfatal("ctlproc unimplemented in Windows"); +} + +char* +proctextfile(int pid) +{ + sysfatal("proctextfile unimplemented in Windows"); +} + +char* +procstatus(int pid) +{ + sysfatal("procstatus unimplemented in Windows"); +} + +Map* +attachproc(int pid, Fhdr *fp) +{ + sysfatal("attachproc unimplemented in Windows"); +} + +void +detachproc(Map *m) +{ + sysfatal("detachproc unimplemented in Windows"); +} + +int +procthreadpids(int pid, int *p, int np) +{ + sysfatal("procthreadpids unimplemented in Windows"); +} + +int +pread(int fd, void *buf, int count, int offset) +{ + sysfatal("pread unimplemented in Windows"); +} + +int +pwrite(int fd, void *buf, int count, int offset) +{ + sysfatal("pwrite unimplemented in Windows"); +} + +int +nanosleep(const struct timespec *rqtp, struct timespec *rmtp) +{ + sysfatal("nanosleep unimplemented in Windows"); +} |