mirror of
https://github.com/golang/go
synced 2024-11-25 13:07:57 -07:00
add .8 support to libmach_amd64 [sic].
add code to handle 32-bit Mach-O and ELF binaries. R=r DELTA=452 (365 added, 29 deleted, 58 changed) OCL=26696 CL=26712
This commit is contained in:
parent
58f7fc331f
commit
fcd536d801
@ -98,7 +98,7 @@ Mach mi386 =
|
||||
0x1000, /* page size */
|
||||
0x80100000ULL, /* kernel base */
|
||||
0xF0000000ULL, /* kernel text mask */
|
||||
0x7FFFFFFFULL, /* user stack top */
|
||||
0xFFFFFFFFULL, /* user stack top */
|
||||
1, /* quantization of pc */
|
||||
4, /* szaddr */
|
||||
4, /* szreg */
|
||||
|
172
src/libmach_amd64/8obj.c
Normal file
172
src/libmach_amd64/8obj.c
Normal file
@ -0,0 +1,172 @@
|
||||
// Inferno libmach/8obj.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/libmach/8obj.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.
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
/*
|
||||
* 8obj.c - identify and parse a 386 object file
|
||||
*/
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include <mach_amd64.h>
|
||||
#include "../cmd/8l/8.out.h"
|
||||
#include "obj.h"
|
||||
|
||||
typedef struct Addr Addr;
|
||||
struct Addr
|
||||
{
|
||||
char sym;
|
||||
char flags;
|
||||
};
|
||||
static Addr addr(Biobuf*);
|
||||
static char type2char(int);
|
||||
static void skip(Biobuf*, int);
|
||||
|
||||
int
|
||||
_is8(char *t)
|
||||
{
|
||||
uchar *s = (uchar*)t;
|
||||
|
||||
return s[0] == (ANAME&0xff) /* aslo = ANAME */
|
||||
&& s[1] == ((ANAME>>8)&0xff)
|
||||
&& s[2] == D_FILE /* type */
|
||||
&& s[3] == 1 /* sym */
|
||||
&& s[4] == '<'; /* name of file */
|
||||
}
|
||||
|
||||
int
|
||||
_read8(Biobuf *bp, Prog* p)
|
||||
{
|
||||
int as, n, c;
|
||||
Addr a;
|
||||
|
||||
as = Bgetc(bp); /* as(low) */
|
||||
if(as < 0)
|
||||
return 0;
|
||||
c = Bgetc(bp); /* as(high) */
|
||||
if(c < 0)
|
||||
return 0;
|
||||
as |= ((c & 0xff) << 8);
|
||||
p->kind = aNone;
|
||||
p->sig = 0;
|
||||
if(as == ANAME || as == ASIGNAME){
|
||||
if(as == ASIGNAME){
|
||||
Bread(bp, &p->sig, 4);
|
||||
p->sig = leswal(p->sig);
|
||||
}
|
||||
p->kind = aName;
|
||||
p->type = type2char(Bgetc(bp)); /* type */
|
||||
p->sym = Bgetc(bp); /* sym */
|
||||
n = 0;
|
||||
for(;;) {
|
||||
as = Bgetc(bp);
|
||||
if(as < 0)
|
||||
return 0;
|
||||
n++;
|
||||
if(as == 0)
|
||||
break;
|
||||
}
|
||||
p->id = malloc(n);
|
||||
if(p->id == 0)
|
||||
return 0;
|
||||
Bseek(bp, -n, 1);
|
||||
if(Bread(bp, p->id, n) != n)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
if(as == ATEXT)
|
||||
p->kind = aText;
|
||||
if(as == AGLOBL)
|
||||
p->kind = aData;
|
||||
skip(bp, 4); /* lineno(4) */
|
||||
a = addr(bp);
|
||||
addr(bp);
|
||||
if(!(a.flags & T_SYM))
|
||||
p->kind = aNone;
|
||||
p->sym = a.sym;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static Addr
|
||||
addr(Biobuf *bp)
|
||||
{
|
||||
Addr a;
|
||||
int t;
|
||||
long off;
|
||||
|
||||
off = 0;
|
||||
a.sym = -1;
|
||||
a.flags = Bgetc(bp); /* flags */
|
||||
if(a.flags & T_INDEX)
|
||||
skip(bp, 2);
|
||||
if(a.flags & T_OFFSET){
|
||||
off = Bgetc(bp);
|
||||
off |= Bgetc(bp) << 8;
|
||||
off |= Bgetc(bp) << 16;
|
||||
off |= Bgetc(bp) << 24;
|
||||
if(off < 0)
|
||||
off = -off;
|
||||
}
|
||||
if(a.flags & T_OFFSET2){
|
||||
Bgetc(bp);
|
||||
Bgetc(bp);
|
||||
Bgetc(bp);
|
||||
Bgetc(bp);
|
||||
}
|
||||
if(a.flags & T_SYM)
|
||||
a.sym = Bgetc(bp);
|
||||
if(a.flags & T_FCONST)
|
||||
skip(bp, 8);
|
||||
else
|
||||
if(a.flags & T_SCONST)
|
||||
skip(bp, NSNAME);
|
||||
if(a.flags & T_TYPE) {
|
||||
t = Bgetc(bp);
|
||||
if(a.sym > 0 && (t==D_PARAM || t==D_AUTO))
|
||||
_offset(a.sym, off);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
static char
|
||||
type2char(int t)
|
||||
{
|
||||
switch(t){
|
||||
case D_EXTERN: return 'U';
|
||||
case D_STATIC: return 'b';
|
||||
case D_AUTO: return 'a';
|
||||
case D_PARAM: return 'p';
|
||||
default: return UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
skip(Biobuf *bp, int n)
|
||||
{
|
||||
while (n-- > 0)
|
||||
Bgetc(bp);
|
||||
}
|
@ -43,6 +43,7 @@ OFILES=\
|
||||
8.$O\
|
||||
8db.$O\
|
||||
6obj.$O\
|
||||
8obj.$O\
|
||||
$(GOOS).$O\
|
||||
# v.$O\
|
||||
# k.$O\
|
||||
@ -66,7 +67,6 @@ OFILES=\
|
||||
# 2obj.$O\
|
||||
# 5obj.$O\
|
||||
# 7obj.$O\
|
||||
# 8obj.$O\
|
||||
# 9obj.$O\
|
||||
# qobj.$O\
|
||||
# vcodas.$O\
|
||||
|
@ -259,13 +259,22 @@ ExecTable exectab[] =
|
||||
sizeof(Ehdr64),
|
||||
nil,
|
||||
elfdotout },
|
||||
{ MACH_MAG, /* 64-bit MACH (apple mac) */
|
||||
{ MACH64_MAG, /* 64-bit MACH (apple mac) */
|
||||
"mach executable",
|
||||
nil,
|
||||
FAMD64,
|
||||
0,
|
||||
&mamd64,
|
||||
sizeof(Machhdr),
|
||||
nil,
|
||||
machdotout },
|
||||
{ MACH32_MAG, /* 64-bit MACH (apple mac) */
|
||||
"mach executable",
|
||||
nil,
|
||||
FI386,
|
||||
0,
|
||||
&mi386,
|
||||
sizeof(Ehdr64),
|
||||
sizeof(Machhdr),
|
||||
nil,
|
||||
machdotout },
|
||||
{ E_MAGIC, /* Arm 5.out and boot image */
|
||||
@ -680,30 +689,10 @@ elf64dotout(int fd, Fhdr *fp, ExecHdr *hp)
|
||||
fp->magic = ELF_MAG;
|
||||
fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15;
|
||||
switch(ep->machine) {
|
||||
case I386:
|
||||
mach = &mi386;
|
||||
fp->type = FI386;
|
||||
break;
|
||||
case MIPS:
|
||||
mach = &mmips;
|
||||
fp->type = FMIPS;
|
||||
break;
|
||||
case SPARC64:
|
||||
mach = &msparc64;
|
||||
fp->type = FSPARC64;
|
||||
break;
|
||||
case POWER:
|
||||
mach = &mpower;
|
||||
fp->type = FPOWER;
|
||||
break;
|
||||
case AMD64:
|
||||
mach = &mamd64;
|
||||
fp->type = FAMD64;
|
||||
break;
|
||||
case ARM:
|
||||
mach = &marm;
|
||||
fp->type = FARM;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@ -731,7 +720,7 @@ elf64dotout(int fd, Fhdr *fp, ExecHdr *hp)
|
||||
free(sh);
|
||||
sh = 0;
|
||||
} else
|
||||
hswal(ph, phsz/sizeof(uint32), swal);
|
||||
hswal(sh, shsz/sizeof(uint32), swal);
|
||||
}
|
||||
|
||||
/* find text, data and symbols and install them */
|
||||
@ -781,7 +770,7 @@ error:
|
||||
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);
|
||||
else if(ep->machine == AMD64 && sh != 0){
|
||||
else if(sh != 0){
|
||||
char *buf;
|
||||
uvlong symsize = 0;
|
||||
uvlong symoff = 0;
|
||||
@ -826,7 +815,8 @@ elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
|
||||
ushort (*swab)(ushort);
|
||||
Ehdr32 *ep;
|
||||
Phdr32 *ph;
|
||||
int i, it, id, is, phsz;
|
||||
int i, it, id, is, phsz, shsz;
|
||||
Shdr32 *sh;
|
||||
|
||||
/* bitswap the header according to the DATA format */
|
||||
ep = &hp->e.elfhdr32;
|
||||
@ -880,10 +870,6 @@ elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
|
||||
mach = &mpower;
|
||||
fp->type = FPOWER;
|
||||
break;
|
||||
case AMD64:
|
||||
mach = &mamd64;
|
||||
fp->type = FAMD64;
|
||||
break;
|
||||
case ARM:
|
||||
mach = &marm;
|
||||
fp->type = FARM;
|
||||
@ -907,6 +893,17 @@ elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
|
||||
}
|
||||
hswal(ph, phsz/sizeof(uint32), swal);
|
||||
|
||||
shsz = sizeof(Shdr32)*ep->shnum;
|
||||
sh = malloc(shsz);
|
||||
if(sh) {
|
||||
seek(fd, ep->shoff, 0);
|
||||
if(read(fd, sh, shsz) < 0) {
|
||||
free(sh);
|
||||
sh = 0;
|
||||
} else
|
||||
hswal(sh, shsz/sizeof(uint32), swal);
|
||||
}
|
||||
|
||||
/* find text, data and symbols and install them */
|
||||
it = id = is = -1;
|
||||
for(i = 0; i < ep->phnum; i++) {
|
||||
@ -944,6 +941,8 @@ elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
|
||||
}
|
||||
|
||||
werrstr("No TEXT or DATA sections");
|
||||
error:
|
||||
free(sh);
|
||||
free(ph);
|
||||
return 0;
|
||||
}
|
||||
@ -952,6 +951,39 @@ elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
|
||||
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);
|
||||
else if(sh != 0){
|
||||
char *buf;
|
||||
uvlong symsize = 0;
|
||||
uvlong symoff = 0;
|
||||
uvlong pclnsz = 0;
|
||||
|
||||
/* load shstrtab names */
|
||||
buf = malloc(sh[ep->shstrndx].size);
|
||||
if (buf == 0)
|
||||
goto done;
|
||||
memset(buf, 0, sizeof buf);
|
||||
seek(fd, sh[ep->shstrndx].offset, 0);
|
||||
read(fd, buf, sh[ep->shstrndx].size);
|
||||
|
||||
for(i = 0; i < ep->shnum; i++) {
|
||||
if (strcmp(&buf[sh[i].name], ".gosymtab") == 0) {
|
||||
symsize = sh[i].size;
|
||||
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;
|
||||
}
|
||||
}
|
||||
setsym(fp, symsize, 0, pclnsz, symoff);
|
||||
free(buf);
|
||||
}
|
||||
done:
|
||||
free(sh);
|
||||
free(ph);
|
||||
return 1;
|
||||
}
|
||||
@ -964,23 +996,24 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp)
|
||||
ushort (*swab)(ushort);
|
||||
Machhdr *mp;
|
||||
MachCmd **cmd;
|
||||
MachSeg64 *text;
|
||||
MachSeg64 *data;
|
||||
MachSymSeg *symtab;
|
||||
MachSymSeg *pclntab;
|
||||
MachSeg64 *seg;
|
||||
MachSect64 *sect;
|
||||
MachSeg32 *seg32;
|
||||
MachSect32 *sect32;
|
||||
uvlong textsize, datasize, bsssize;
|
||||
uchar *cmdbuf;
|
||||
uchar *cmdp;
|
||||
int i;
|
||||
int i, hdrsize;
|
||||
uint32 textva, textoff, datava, dataoff;
|
||||
|
||||
/* bitswap the header according to the DATA format */
|
||||
mp = &hp->e.machhdr;
|
||||
if (mp->cputype != leswal(MACH_CPU_TYPE_X86_64)) {
|
||||
werrstr("bad MACH cpu type - not amd64");
|
||||
if (leswal(mp->filetype) != MACH_EXECUTABLE_TYPE) {
|
||||
werrstr("bad MACH executable type %#ux", leswal(mp->filetype));
|
||||
return 0;
|
||||
}
|
||||
|
||||
swab = leswab;
|
||||
swal = leswal;
|
||||
swav = leswav;
|
||||
@ -993,27 +1026,59 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp)
|
||||
mp->sizeofcmds = swal(mp->sizeofcmds);
|
||||
mp->flags = swal(mp->flags);
|
||||
mp->reserved = swal(mp->reserved);
|
||||
if (mp->cpusubtype != MACH_CPU_SUBTYPE_X86) {
|
||||
werrstr("bad MACH cpu subtype - not amd64");
|
||||
hdrsize = 0;
|
||||
|
||||
switch(mp->magic) {
|
||||
case 0xFEEDFACE: // 32-bit mach
|
||||
if (mp->cputype != MACH_CPU_TYPE_X86) {
|
||||
werrstr("bad MACH cpu type - not 386");
|
||||
return 0;
|
||||
}
|
||||
if (mp->cpusubtype != MACH_CPU_SUBTYPE_X86) {
|
||||
werrstr("bad MACH cpu subtype - not 386");
|
||||
return 0;
|
||||
}
|
||||
if (mp->filetype != MACH_EXECUTABLE_TYPE) {
|
||||
werrstr("bad MACH executable type");
|
||||
return 0;
|
||||
}
|
||||
mach = &mi386;
|
||||
fp->type = FI386;
|
||||
hdrsize = 28;
|
||||
break;
|
||||
|
||||
case 0xFEEDFACF: // 64-bit mach
|
||||
if (mp->cputype != MACH_CPU_TYPE_X86_64) {
|
||||
werrstr("bad MACH cpu type - not amd64");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mp->cpusubtype != MACH_CPU_SUBTYPE_X86) {
|
||||
werrstr("bad MACH cpu subtype - not amd64");
|
||||
return 0;
|
||||
}
|
||||
mach = &mamd64;
|
||||
fp->type = FAMD64;
|
||||
hdrsize = 32;
|
||||
break;
|
||||
|
||||
default:
|
||||
werrstr("not mach %#ux", mp->magic);
|
||||
return 0;
|
||||
}
|
||||
if (mp->filetype != MACH_EXECUTABLE_TYPE) {
|
||||
werrstr("bad MACH cpu subtype - not amd64");
|
||||
return 0;
|
||||
}
|
||||
mach = &mamd64;
|
||||
fp->type = FAMD64;
|
||||
|
||||
cmdbuf = malloc(mp->sizeofcmds);
|
||||
seek(fd, sizeof(Machhdr), 0);
|
||||
seek(fd, hdrsize, 0);
|
||||
if(read(fd, cmdbuf, mp->sizeofcmds) != mp->sizeofcmds) {
|
||||
free(cmdbuf);
|
||||
return 0;
|
||||
}
|
||||
cmd = malloc(mp->ncmds * sizeof(MachCmd*));
|
||||
cmdp = cmdbuf;
|
||||
text = 0;
|
||||
data = 0;
|
||||
textva = 0;
|
||||
textoff = 0;
|
||||
dataoff = 0;
|
||||
datava = 0;
|
||||
symtab = 0;
|
||||
pclntab = 0;
|
||||
textsize = datasize = bsssize = 0;
|
||||
@ -1025,7 +1090,56 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp)
|
||||
c->type = swal(c->type);
|
||||
c->size = swal(c->size);
|
||||
switch(c->type) {
|
||||
case MACH_SEGMENT_32:
|
||||
if(mp->magic != 0xFEEDFACE) {
|
||||
werrstr("segment 32 in mach 64");
|
||||
goto bad;
|
||||
}
|
||||
seg32 = (MachSeg32*)c;
|
||||
seg32->vmaddr = swav(seg32->vmaddr);
|
||||
seg32->vmsize = swav(seg32->vmsize);
|
||||
seg32->fileoff = swav(seg32->fileoff);
|
||||
seg32->filesize = swav(seg32->filesize);
|
||||
seg32->maxprot = swal(seg32->maxprot);
|
||||
seg32->initprot = swal(seg32->initprot);
|
||||
seg32->nsects = swal(seg32->nsects);
|
||||
seg32->flags = swal(seg32->flags);
|
||||
if (strcmp(seg32->segname, "__TEXT") == 0) {
|
||||
textva = seg32->vmaddr;
|
||||
textoff = seg32->fileoff;
|
||||
sect32 = (MachSect32*)(cmdp + sizeof(MachSeg32));
|
||||
if (strcmp(sect32->sectname, "__text") == 0) {
|
||||
textsize = swal(sect32->size);
|
||||
} else {
|
||||
werrstr("no text section");
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
if (strcmp(seg32->segname, "__DATA") == 0) {
|
||||
datava = seg32->vmaddr;
|
||||
dataoff = seg32->fileoff;
|
||||
sect32 = (MachSect32*)(cmdp + sizeof(MachSeg32));
|
||||
if (strcmp(sect32->sectname, "__data") == 0) {
|
||||
datasize = swal(sect32->size);
|
||||
} else {
|
||||
werrstr("no data section");
|
||||
goto bad;
|
||||
}
|
||||
sect32++;
|
||||
if (strcmp(sect32->sectname, "__bss") == 0) {
|
||||
bsssize = swal(sect32->size);
|
||||
} else {
|
||||
werrstr("no bss section");
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MACH_SEGMENT_64:
|
||||
if(mp->magic != 0xFEEDFACF) {
|
||||
werrstr("segment 32 in mach 64");
|
||||
goto bad;
|
||||
}
|
||||
seg = (MachSeg64*)c;
|
||||
seg->vmaddr = swav(seg->vmaddr);
|
||||
seg->vmsize = swav(seg->vmsize);
|
||||
@ -1036,7 +1150,8 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp)
|
||||
seg->nsects = swal(seg->nsects);
|
||||
seg->flags = swal(seg->flags);
|
||||
if (strcmp(seg->segname, "__TEXT") == 0) {
|
||||
text = seg;
|
||||
textva = seg->vmaddr;
|
||||
textoff = seg->fileoff;
|
||||
sect = (MachSect64*)(cmdp + sizeof(MachSeg64));
|
||||
if (strcmp(sect->sectname, "__text") == 0) {
|
||||
textsize = swav(sect->size);
|
||||
@ -1046,7 +1161,8 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp)
|
||||
}
|
||||
}
|
||||
if (strcmp(seg->segname, "__DATA") == 0) {
|
||||
data = seg;
|
||||
datava = seg->vmaddr;
|
||||
dataoff = seg->fileoff;
|
||||
sect = (MachSect64*)(cmdp + sizeof(MachSeg64));
|
||||
if (strcmp(sect->sectname, "__data") == 0) {
|
||||
datasize = swav(sect->size);
|
||||
@ -1074,14 +1190,14 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp)
|
||||
}
|
||||
cmdp += c->size;
|
||||
}
|
||||
if (text == 0 || data == 0) {
|
||||
if (textva == 0 || datava == 0) {
|
||||
free(cmd);
|
||||
free(cmdbuf);
|
||||
return 0;
|
||||
}
|
||||
/* compute entry by taking address after header - weird - BUG? */
|
||||
settext(fp, text->vmaddr+sizeof(Machhdr) + mp->sizeofcmds, text->vmaddr, textsize, text->fileoff);
|
||||
setdata(fp, data->vmaddr, datasize, data->fileoff, bsssize);
|
||||
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);
|
||||
free(cmd);
|
||||
|
@ -16,7 +16,6 @@
|
||||
int _is2(char* x) { return 0; }
|
||||
int _is5(char* x) { return 0; }
|
||||
int _is7(char* x) { return 0; }
|
||||
int _is8(char* x) { return 0; }
|
||||
int _is9(char* x) { return 0; }
|
||||
int _isk(char* x) { return 0; }
|
||||
int _isq(char* x) { return 0; }
|
||||
@ -25,7 +24,6 @@ int _isu(char* x) { return 0; }
|
||||
int _read2(Biobuf* b, Prog* p) { return 0; }
|
||||
int _read5(Biobuf* b, Prog* p) { return 0; }
|
||||
int _read7(Biobuf* b, Prog* p) { return 0; }
|
||||
int _read8(Biobuf* b, Prog* p) { return 0; }
|
||||
int _read9(Biobuf* b, Prog* p) { return 0; }
|
||||
int _readk(Biobuf* b, Prog* p) { return 0; }
|
||||
int _readq(Biobuf* b, Prog* p) { return 0; }
|
||||
|
@ -38,7 +38,12 @@
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include <mach_amd64.h>
|
||||
#define Ureg Ureg32
|
||||
#include <ureg_x86.h>
|
||||
#undef Ureg
|
||||
#define Ureg Ureg64
|
||||
#include <ureg_amd64.h>
|
||||
#undef Ureg
|
||||
#undef waitpid
|
||||
|
||||
// The old glibc used with crosstool compilers on thresher
|
||||
@ -66,7 +71,7 @@
|
||||
#define PTRACE_EVENT_EXIT 0x6
|
||||
#endif
|
||||
|
||||
typedef struct Ureg Ureg;
|
||||
typedef struct Ureg64 Ureg64;
|
||||
|
||||
static Maprw ptracesegrw;
|
||||
static Maprw ptraceregrw;
|
||||
@ -787,57 +792,100 @@ ptracesegrw(Map *map, Seg *seg, uvlong addr, void *v, uint n, int isr)
|
||||
isr, map->pid, addr, v, n);
|
||||
}
|
||||
|
||||
// If the debugger is compiled as an x86-64 program,
|
||||
// then all the ptrace register read/writes are done on
|
||||
// a 64-bit register set. If the target program
|
||||
// is a 32-bit program, the debugger is expected to
|
||||
// read the bottom half of the relevant registers
|
||||
// out of the 64-bit set.
|
||||
|
||||
// Linux 32-bit is
|
||||
// BX CX DX SI DI BP AX DS ES FS GS OrigAX IP CS EFLAGS SP SS
|
||||
|
||||
// Linux 64-bit is
|
||||
// R15 R14 R13 R12 BP BX R11 R10 R9 R8 AX CX DX SI DI OrigAX IP CS EFLAGS SP SS FSBase GSBase DS ES FS GS
|
||||
|
||||
// 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 go32tolinux64tab[] = {
|
||||
14, 13, 4, 19, 5, 12, 11, 10, 26, 25, 24, 23, -1, -1, 16, 17, 18, 19, 20
|
||||
};
|
||||
static int
|
||||
go32tolinux64(uvlong addr)
|
||||
{
|
||||
int r;
|
||||
|
||||
if(addr%4 || addr/4 >= nelem(go32tolinux64tab))
|
||||
return -1;
|
||||
r = go32tolinux64tab[addr/4];
|
||||
if(r < 0)
|
||||
return -1;
|
||||
return r*8;
|
||||
}
|
||||
|
||||
extern Mach mi386;
|
||||
|
||||
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(mach == &mi386)
|
||||
return go32tolinux64(addr);
|
||||
|
||||
switch(addr){
|
||||
case offsetof(Ureg, ax):
|
||||
case offsetof(Ureg64, ax):
|
||||
return offsetof(struct user_regs_struct, rax);
|
||||
case offsetof(Ureg, bx):
|
||||
case offsetof(Ureg64, bx):
|
||||
return offsetof(struct user_regs_struct, rbx);
|
||||
case offsetof(Ureg, cx):
|
||||
case offsetof(Ureg64, cx):
|
||||
return offsetof(struct user_regs_struct, rcx);
|
||||
case offsetof(Ureg, dx):
|
||||
case offsetof(Ureg64, dx):
|
||||
return offsetof(struct user_regs_struct, rdx);
|
||||
case offsetof(Ureg, si):
|
||||
case offsetof(Ureg64, si):
|
||||
return offsetof(struct user_regs_struct, rsi);
|
||||
case offsetof(Ureg, di):
|
||||
case offsetof(Ureg64, di):
|
||||
return offsetof(struct user_regs_struct, rdi);
|
||||
case offsetof(Ureg, bp):
|
||||
case offsetof(Ureg64, bp):
|
||||
return offsetof(struct user_regs_struct, rbp);
|
||||
case offsetof(Ureg, r8):
|
||||
case offsetof(Ureg64, r8):
|
||||
return offsetof(struct user_regs_struct, r8);
|
||||
case offsetof(Ureg, r9):
|
||||
case offsetof(Ureg64, r9):
|
||||
return offsetof(struct user_regs_struct, r9);
|
||||
case offsetof(Ureg, r10):
|
||||
case offsetof(Ureg64, r10):
|
||||
return offsetof(struct user_regs_struct, r10);
|
||||
case offsetof(Ureg, r11):
|
||||
case offsetof(Ureg64, r11):
|
||||
return offsetof(struct user_regs_struct, r11);
|
||||
case offsetof(Ureg, r12):
|
||||
case offsetof(Ureg64, r12):
|
||||
return offsetof(struct user_regs_struct, r12);
|
||||
case offsetof(Ureg, r13):
|
||||
case offsetof(Ureg64, r13):
|
||||
return offsetof(struct user_regs_struct, r13);
|
||||
case offsetof(Ureg, r14):
|
||||
case offsetof(Ureg64, r14):
|
||||
return offsetof(struct user_regs_struct, r14);
|
||||
case offsetof(Ureg, r15):
|
||||
case offsetof(Ureg64, r15):
|
||||
return offsetof(struct user_regs_struct, r15);
|
||||
case offsetof(Ureg, ds):
|
||||
case offsetof(Ureg64, ds):
|
||||
return offsetof(struct user_regs_struct, ds);
|
||||
case offsetof(Ureg, es):
|
||||
case offsetof(Ureg64, es):
|
||||
return offsetof(struct user_regs_struct, es);
|
||||
case offsetof(Ureg, fs):
|
||||
case offsetof(Ureg64, fs):
|
||||
return offsetof(struct user_regs_struct, fs);
|
||||
case offsetof(Ureg, gs):
|
||||
case offsetof(Ureg64, gs):
|
||||
return offsetof(struct user_regs_struct, gs);
|
||||
case offsetof(Ureg, ip):
|
||||
case offsetof(Ureg64, ip):
|
||||
return offsetof(struct user_regs_struct, rip);
|
||||
case offsetof(Ureg, cs):
|
||||
case offsetof(Ureg64, cs):
|
||||
return offsetof(struct user_regs_struct, cs);
|
||||
case offsetof(Ureg, flags):
|
||||
case offsetof(Ureg64, flags):
|
||||
return offsetof(struct user_regs_struct, eflags);
|
||||
case offsetof(Ureg, sp):
|
||||
case offsetof(Ureg64, sp):
|
||||
return offsetof(struct user_regs_struct, rsp);
|
||||
case offsetof(Ureg, ss):
|
||||
case offsetof(Ureg64, ss):
|
||||
return offsetof(struct user_regs_struct, ss);
|
||||
}
|
||||
return -1;
|
||||
@ -904,7 +952,7 @@ ptraceregrw(Map *map, Seg *seg, uvlong addr, void *v, uint n, int isr)
|
||||
return 0;
|
||||
|
||||
ptraceerr:
|
||||
werrstr("ptrace %s register laddr=%d pid=%d: %r", isr ? "read" : "write", laddr, map->pid);
|
||||
werrstr("ptrace %s register laddr=%d pid=%d n=%d: %r", isr ? "read" : "write", laddr, map->pid, n);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,19 @@ typedef struct {
|
||||
uint32 size; /* total size in bytes */
|
||||
} MachCmd;
|
||||
|
||||
typedef struct {
|
||||
MachCmd cmd;
|
||||
char segname[16]; /* segment name */
|
||||
uint32 vmaddr; /* memory address of this segment */
|
||||
uint32 vmsize; /* memory size of this segment */
|
||||
uint32 fileoff; /* file offset of this segment */
|
||||
uint32 filesize; /* amount to map from the file */
|
||||
uint32 maxprot; /* maximum VM protection */
|
||||
uint32 initprot; /* initial VM protection */
|
||||
uint32 nsects; /* number of sections in segment */
|
||||
uint32 flags; /* flags */
|
||||
} MachSeg32; /* for 32-bit architectures */
|
||||
|
||||
typedef struct {
|
||||
MachCmd cmd;
|
||||
char segname[16]; /* segment name */
|
||||
@ -41,6 +54,20 @@ typedef struct {
|
||||
uint32 filesize; /* amount to map from the file */
|
||||
} MachSymSeg;
|
||||
|
||||
typedef struct {
|
||||
char sectname[16]; /* name of this section */
|
||||
char segname[16]; /* segment this section goes in */
|
||||
uint32 addr; /* memory address of this section */
|
||||
uint32 size; /* size in bytes of this section */
|
||||
uint32 offset; /* file offset of this section */
|
||||
uint32 align; /* section alignment (power of 2) */
|
||||
uint32 reloff; /* file offset of relocation entries */
|
||||
uint32 nreloc; /* number of relocation entries */
|
||||
uint32 flags; /* flags (section type and attributes)*/
|
||||
uint32 reserved1; /* reserved (for offset or index) */
|
||||
uint32 reserved2; /* reserved (for count or sizeof) */
|
||||
} MachSect32; /* for 32-bit architectures */
|
||||
|
||||
typedef struct {
|
||||
char sectname[16]; /* name of this section */
|
||||
char segname[16]; /* segment this section goes in */
|
||||
@ -58,12 +85,15 @@ typedef struct {
|
||||
|
||||
enum {
|
||||
MACH_CPU_TYPE_X86_64 = (1<<24)|7,
|
||||
MACH_CPU_TYPE_X86 = 7,
|
||||
MACH_CPU_SUBTYPE_X86 = 3,
|
||||
MACH_EXECUTABLE_TYPE = 2,
|
||||
MACH_SEGMENT_32 = 1, /* 32-bit mapped segment */
|
||||
MACH_SEGMENT_64 = 0x19, /* 64-bit mapped segment */
|
||||
MACH_SYMSEG = 3, /* obsolete gdb symtab, reused by go */
|
||||
MACH_UNIXTHREAD = 0x5, /* thread (for stack) */
|
||||
};
|
||||
|
||||
|
||||
#define MACH_MAG ((0xcf<<24) | (0xfa<<16) | (0xed<<8) | 0xfe)
|
||||
#define MACH64_MAG ((0xcf<<24) | (0xfa<<16) | (0xed<<8) | 0xfe)
|
||||
#define MACH32_MAG ((0xce<<24) | (0xfa<<16) | (0xed<<8) | 0xfe)
|
||||
|
Loading…
Reference in New Issue
Block a user