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.c51
-rw-r--r--src/libmach/Makefile22
-rw-r--r--src/libmach/darwin.c11
-rw-r--r--src/libmach/executable.c62
-rw-r--r--src/libmach/linux.c58
-rw-r--r--src/libmach/windows.c59
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");
+}