mirror of
https://github.com/golang/go
synced 2024-11-25 23:58:02 -07:00
add support for debugging in MACH binaries
fix up libmach_amd64 to handle MACH binaries and symbols db now works on mac and linux SVN=122807
This commit is contained in:
parent
30706a7ee7
commit
073486c3ed
@ -179,6 +179,7 @@ asmb(void)
|
|||||||
seek(cout, HEADR+textsize, 0);
|
seek(cout, HEADR+textsize, 0);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
|
debug['8'] = 1; /* 64-bit addresses */
|
||||||
v = HEADR+textsize;
|
v = HEADR+textsize;
|
||||||
myseek(cout, v);
|
myseek(cout, v);
|
||||||
v = rnd(v, 4096) - v;
|
v = rnd(v, 4096) - v;
|
||||||
@ -232,7 +233,7 @@ asmb(void)
|
|||||||
seek(cout, HEADR+textsize+datsize, 0);
|
seek(cout, HEADR+textsize+datsize, 0);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
debug['s'] = 1;
|
seek(cout, rnd(HEADR+textsize, INITRND)+rnd(datsize, INITRND), 0);
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
seek(cout, rnd(HEADR+textsize, INITRND)+datsize+strtabsize, 0);
|
seek(cout, rnd(HEADR+textsize, INITRND)+datsize+strtabsize, 0);
|
||||||
@ -348,7 +349,10 @@ asmb(void)
|
|||||||
lputl((1<<24)|7); /* cputype - x86/ABI64 */
|
lputl((1<<24)|7); /* cputype - x86/ABI64 */
|
||||||
lputl(3); /* subtype - x86 */
|
lputl(3); /* subtype - x86 */
|
||||||
lputl(2); /* file type - mach executable */
|
lputl(2); /* file type - mach executable */
|
||||||
|
if (debug['s'])
|
||||||
lputl(4); /* number of loads */
|
lputl(4); /* number of loads */
|
||||||
|
else
|
||||||
|
lputl(6); /* number of loads */
|
||||||
lputl(machheadr()-32); /* size of loads */
|
lputl(machheadr()-32); /* size of loads */
|
||||||
lputl(1); /* flags - no undefines */
|
lputl(1); /* flags - no undefines */
|
||||||
lputl(0); /* reserved */
|
lputl(0); /* reserved */
|
||||||
@ -386,7 +390,15 @@ asmb(void)
|
|||||||
va+v+datsize,bsssize, /* addr size */
|
va+v+datsize,bsssize, /* addr size */
|
||||||
0,0,0,0, /* offset align reloc nreloc */
|
0,0,0,0, /* offset align reloc nreloc */
|
||||||
1); /* flag - zero fill */
|
1); /* flag - zero fill */
|
||||||
|
|
||||||
machstack(va+HEADR);
|
machstack(va+HEADR);
|
||||||
|
|
||||||
|
if (!debug['s']) {
|
||||||
|
v += rnd(datsize, INITRND);
|
||||||
|
machsymseg(v,symsize); /* fileoffset,filesize */
|
||||||
|
v += symsize;
|
||||||
|
machsymseg(v,lcsize); /* fileoffset,filesize */
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
/* elf amd-64 */
|
/* elf amd-64 */
|
||||||
@ -737,7 +749,7 @@ void
|
|||||||
machseg(char *name, vlong vaddr, vlong vsize, vlong foff, vlong fsize,
|
machseg(char *name, vlong vaddr, vlong vsize, vlong foff, vlong fsize,
|
||||||
ulong prot1, ulong prot2, ulong nsect, ulong flag)
|
ulong prot1, ulong prot2, ulong nsect, ulong flag)
|
||||||
{
|
{
|
||||||
lputl(25); // section
|
lputl(25); /* segment 64 */
|
||||||
lputl(72 + 80*nsect);
|
lputl(72 + 80*nsect);
|
||||||
strnput(name, 16);
|
strnput(name, 16);
|
||||||
vputl(vaddr);
|
vputl(vaddr);
|
||||||
@ -750,6 +762,15 @@ machseg(char *name, vlong vaddr, vlong vsize, vlong foff, vlong fsize,
|
|||||||
lputl(flag);
|
lputl(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
machsymseg(ulong foffset, ulong fsize)
|
||||||
|
{
|
||||||
|
lputl(3); /* obsolete gdb debug info */
|
||||||
|
lputl(16); /* size of symseg command */
|
||||||
|
lputl(foffset);
|
||||||
|
lputl(fsize);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
machsect(char *name, char *seg, vlong addr, vlong size, ulong off,
|
machsect(char *name, char *seg, vlong addr, vlong size, ulong off,
|
||||||
ulong align, ulong reloc, ulong nreloc, ulong flag)
|
ulong align, ulong reloc, ulong nreloc, ulong flag)
|
||||||
@ -799,6 +820,10 @@ machheadr(void)
|
|||||||
a += 20; /* data sect */
|
a += 20; /* data sect */
|
||||||
a += 20; /* bss sect */
|
a += 20; /* bss sect */
|
||||||
a += 46; /* stack sect */
|
a += 46; /* stack sect */
|
||||||
|
if (!debug['s']) {
|
||||||
|
a += 4; /* symtab seg */
|
||||||
|
a += 4; /* lctab seg */
|
||||||
|
}
|
||||||
|
|
||||||
return a*4;
|
return a*4;
|
||||||
}
|
}
|
||||||
|
@ -421,6 +421,7 @@ int zaddr(uchar*, Adr*, Sym*[]);
|
|||||||
void zerosig(char*);
|
void zerosig(char*);
|
||||||
|
|
||||||
void machseg(char*, vlong, vlong, vlong, vlong, ulong, ulong, ulong, ulong);
|
void machseg(char*, vlong, vlong, vlong, vlong, ulong, ulong, ulong, ulong);
|
||||||
|
void machsymseg(ulong, ulong);
|
||||||
void machsect(char*, char*, vlong, vlong, ulong, ulong, ulong, ulong, ulong);
|
void machsect(char*, char*, vlong, vlong, ulong, ulong, ulong, ulong, ulong);
|
||||||
void machstack(vlong);
|
void machstack(vlong);
|
||||||
ulong machheadr(void);
|
ulong machheadr(void);
|
||||||
|
@ -43,6 +43,7 @@ char* paramspace = "FP";
|
|||||||
* -H3 -T4128 -R4096 is plan9 32-bit format
|
* -H3 -T4128 -R4096 is plan9 32-bit format
|
||||||
* -H5 -T0x80110000 -R4096 is ELF32
|
* -H5 -T0x80110000 -R4096 is ELF32
|
||||||
* -H6 -Tx -Rx is apple MH-exec
|
* -H6 -Tx -Rx is apple MH-exec
|
||||||
|
* -H7 -Tx -Rx is linux elf-exec
|
||||||
*
|
*
|
||||||
* options used: 189BLQSWabcjlnpsvz
|
* options used: 189BLQSWabcjlnpsvz
|
||||||
*/
|
*/
|
||||||
|
@ -70,7 +70,7 @@ OFILES=\
|
|||||||
# qobj.$O\
|
# qobj.$O\
|
||||||
# vcodas.$O\
|
# vcodas.$O\
|
||||||
|
|
||||||
HFILES=$(GOROOT)/include/mach_amd64.h elf.h obj.h
|
HFILES=$(GOROOT)/include/mach_amd64.h elf.h macho.h obj.h
|
||||||
|
|
||||||
install: $(LIB)
|
install: $(LIB)
|
||||||
cp $(LIB) $(GOROOT)/lib
|
cp $(LIB) $(GOROOT)/lib
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <bootexec.h>
|
#include <bootexec.h>
|
||||||
#include <mach_amd64.h>
|
#include <mach_amd64.h>
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
|
#include "macho.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All a.out header types. The dummy entry allows canonical
|
* All a.out header types. The dummy entry allows canonical
|
||||||
@ -50,6 +51,7 @@ typedef struct {
|
|||||||
struct mips4kexec mipsk4; /* bootexec.h */
|
struct mips4kexec mipsk4; /* bootexec.h */
|
||||||
struct sparcexec sparc; /* bootexec.h */
|
struct sparcexec sparc; /* bootexec.h */
|
||||||
struct nextexec next; /* bootexec.h */
|
struct nextexec next; /* bootexec.h */
|
||||||
|
Machhdr machhdr; /* macho.h */
|
||||||
} e;
|
} e;
|
||||||
long dummy; /* padding to ensure extra long */
|
long dummy; /* padding to ensure extra long */
|
||||||
} ExecHdr;
|
} ExecHdr;
|
||||||
@ -62,6 +64,7 @@ static int common(int, Fhdr*, ExecHdr*);
|
|||||||
static int commonllp64(int, Fhdr*, ExecHdr*);
|
static int commonllp64(int, Fhdr*, ExecHdr*);
|
||||||
static int adotout(int, Fhdr*, ExecHdr*);
|
static int adotout(int, Fhdr*, ExecHdr*);
|
||||||
static int elfdotout(int, Fhdr*, ExecHdr*);
|
static int elfdotout(int, Fhdr*, ExecHdr*);
|
||||||
|
static int machdotout(int, Fhdr*, ExecHdr*);
|
||||||
static int armdotout(int, Fhdr*, ExecHdr*);
|
static int armdotout(int, Fhdr*, ExecHdr*);
|
||||||
static void setsym(Fhdr*, long, long, long, vlong);
|
static void setsym(Fhdr*, long, long, long, vlong);
|
||||||
static void setdata(Fhdr*, uvlong, long, vlong, long);
|
static void setdata(Fhdr*, uvlong, long, vlong, long);
|
||||||
@ -256,6 +259,15 @@ ExecTable exectab[] =
|
|||||||
sizeof(Ehdr64),
|
sizeof(Ehdr64),
|
||||||
nil,
|
nil,
|
||||||
elfdotout },
|
elfdotout },
|
||||||
|
{ MACH_MAG, /* 64-bit MACH (apple mac) */
|
||||||
|
"mach executable",
|
||||||
|
nil,
|
||||||
|
FAMD64,
|
||||||
|
0,
|
||||||
|
&mi386,
|
||||||
|
sizeof(Ehdr64),
|
||||||
|
nil,
|
||||||
|
machdotout },
|
||||||
{ E_MAGIC, /* Arm 5.out and boot image */
|
{ E_MAGIC, /* Arm 5.out and boot image */
|
||||||
"arm plan 9 executable",
|
"arm plan 9 executable",
|
||||||
"arm plan 9 dlm",
|
"arm plan 9 dlm",
|
||||||
@ -652,7 +664,6 @@ elf64dotout(int fd, Fhdr *fp, ExecHdr *hp)
|
|||||||
ep->machine = swab(ep->machine);
|
ep->machine = swab(ep->machine);
|
||||||
ep->version = swal(ep->version);
|
ep->version = swal(ep->version);
|
||||||
ep->elfentry = swal(ep->elfentry);
|
ep->elfentry = swal(ep->elfentry);
|
||||||
print("entry: 0x%x\n", ep->elfentry);
|
|
||||||
ep->phoff = swav(ep->phoff);
|
ep->phoff = swav(ep->phoff);
|
||||||
ep->shoff = swav(ep->shoff);
|
ep->shoff = swav(ep->shoff);
|
||||||
ep->flags = swav(ep->flags);
|
ep->flags = swav(ep->flags);
|
||||||
@ -945,6 +956,143 @@ elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
machdotout(int fd, Fhdr *fp, ExecHdr *hp)
|
||||||
|
{
|
||||||
|
uvlong (*swav)(uvlong);
|
||||||
|
ulong (*swal)(ulong);
|
||||||
|
ushort (*swab)(ushort);
|
||||||
|
Machhdr *mp;
|
||||||
|
MachCmd **cmd;
|
||||||
|
MachSeg64 *text;
|
||||||
|
MachSeg64 *data;
|
||||||
|
MachSymSeg *symtab;
|
||||||
|
MachSymSeg *pclntab;
|
||||||
|
MachSeg64 *seg;
|
||||||
|
MachSect64 *sect;
|
||||||
|
uvlong textsize, datasize, bsssize;
|
||||||
|
uchar *cmdbuf;
|
||||||
|
uchar *cmdp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* 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");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
swab = leswab;
|
||||||
|
swal = leswal;
|
||||||
|
swav = leswav;
|
||||||
|
|
||||||
|
mp->magic = swal(mp->magic);
|
||||||
|
mp->cputype = swal(mp->cputype);
|
||||||
|
mp->cpusubtype = swal(mp->cpusubtype);
|
||||||
|
mp->filetype = swal(mp->filetype);
|
||||||
|
mp->ncmds = swal(mp->ncmds);
|
||||||
|
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");
|
||||||
|
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);
|
||||||
|
if(read(fd, cmdbuf, mp->sizeofcmds) != mp->sizeofcmds) {
|
||||||
|
free(cmdbuf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
cmd = malloc(mp->ncmds * sizeof(MachCmd*));
|
||||||
|
cmdp = cmdbuf;
|
||||||
|
text = 0;
|
||||||
|
data = 0;
|
||||||
|
symtab = 0;
|
||||||
|
pclntab = 0;
|
||||||
|
textsize = datasize = bsssize = 0;
|
||||||
|
for (i = 0; i < mp->ncmds; i++) {
|
||||||
|
MachCmd *c;
|
||||||
|
|
||||||
|
cmd[i] = (MachCmd*)cmdp;
|
||||||
|
c = cmd[i];
|
||||||
|
c->type = swal(c->type);
|
||||||
|
c->size = swal(c->size);
|
||||||
|
switch(c->type) {
|
||||||
|
case MACH_SEGMENT_64:
|
||||||
|
seg = (MachSeg64*)c;
|
||||||
|
seg->vmaddr = swav(seg->vmaddr);
|
||||||
|
seg->vmsize = swav(seg->vmsize);
|
||||||
|
seg->fileoff = swav(seg->fileoff);
|
||||||
|
seg->filesize = swav(seg->filesize);
|
||||||
|
seg->maxprot = swal(seg->maxprot);
|
||||||
|
seg->initprot = swal(seg->initprot);
|
||||||
|
seg->nsects = swal(seg->nsects);
|
||||||
|
seg->flags = swal(seg->flags);
|
||||||
|
if (strcmp(seg->segname, "__TEXT") == 0) {
|
||||||
|
text = seg;
|
||||||
|
sect = (MachSect64*)(cmdp + sizeof(MachSeg64));
|
||||||
|
if (strcmp(sect->sectname, "__text") == 0) {
|
||||||
|
textsize = swav(sect->size);
|
||||||
|
} else {
|
||||||
|
werrstr("no text section");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (strcmp(seg->segname, "__DATA") == 0) {
|
||||||
|
data = seg;
|
||||||
|
sect = (MachSect64*)(cmdp + sizeof(MachSeg64));
|
||||||
|
if (strcmp(sect->sectname, "__data") == 0) {
|
||||||
|
datasize = swav(sect->size);
|
||||||
|
} else {
|
||||||
|
werrstr("no data section");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
sect++;
|
||||||
|
if (strcmp(sect->sectname, "__bss") == 0) {
|
||||||
|
bsssize = swav(sect->size);
|
||||||
|
} else {
|
||||||
|
werrstr("no bss section");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MACH_UNIXTHREAD:
|
||||||
|
break;
|
||||||
|
case MACH_SYMSEG:
|
||||||
|
if (symtab == 0)
|
||||||
|
symtab = (MachSymSeg*)c;
|
||||||
|
else if (pclntab == 0)
|
||||||
|
pclntab = (MachSymSeg*)c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cmdp += c->size;
|
||||||
|
}
|
||||||
|
if (text == 0 || data == 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);
|
||||||
|
if(symtab != 0)
|
||||||
|
setsym(fp, symtab->filesize, 0, pclntab? pclntab->filesize : 0, symtab->fileoff);
|
||||||
|
free(cmd);
|
||||||
|
free(cmdbuf);
|
||||||
|
return 1;
|
||||||
|
bad:
|
||||||
|
free(cmd);
|
||||||
|
free(cmdbuf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (Free|Net)BSD ARM header.
|
* (Free|Net)BSD ARM header.
|
||||||
*/
|
*/
|
||||||
|
69
src/libmach_amd64/macho.h
Normal file
69
src/libmach_amd64/macho.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definitions needed for accessing MACH object headers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ulong magic; /* mach magic number identifier */
|
||||||
|
ulong cputype; /* cpu specifier */
|
||||||
|
ulong cpusubtype; /* machine specifier */
|
||||||
|
ulong filetype; /* type of file */
|
||||||
|
ulong ncmds; /* number of load commands */
|
||||||
|
ulong sizeofcmds; /* the size of all the load commands */
|
||||||
|
ulong flags; /* flags */
|
||||||
|
ulong reserved; /* reserved */
|
||||||
|
} Machhdr;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ulong type; /* type of load command */
|
||||||
|
ulong size; /* total size in bytes */
|
||||||
|
} MachCmd;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
MachCmd cmd;
|
||||||
|
char segname[16]; /* segment name */
|
||||||
|
uvlong vmaddr; /* memory address of this segment */
|
||||||
|
uvlong vmsize; /* memory size of this segment */
|
||||||
|
uvlong fileoff; /* file offset of this segment */
|
||||||
|
uvlong filesize; /* amount to map from the file */
|
||||||
|
ulong maxprot; /* maximum VM protection */
|
||||||
|
ulong initprot; /* initial VM protection */
|
||||||
|
ulong nsects; /* number of sections in segment */
|
||||||
|
ulong flags; /* flags */
|
||||||
|
} MachSeg64; /* for 64-bit architectures */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
MachCmd cmd;
|
||||||
|
ulong fileoff; /* file offset of this segment */
|
||||||
|
ulong 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 */
|
||||||
|
uvlong addr; /* memory address of this section */
|
||||||
|
uvlong size; /* size in bytes of this section */
|
||||||
|
ulong offset; /* file offset of this section */
|
||||||
|
ulong align; /* section alignment (power of 2) */
|
||||||
|
ulong reloff; /* file offset of relocation entries */
|
||||||
|
ulong nreloc; /* number of relocation entries */
|
||||||
|
ulong flags; /* flags (section type and attributes)*/
|
||||||
|
ulong reserved1; /* reserved (for offset or index) */
|
||||||
|
ulong reserved2; /* reserved (for count or sizeof) */
|
||||||
|
ulong reserved3; /* reserved */
|
||||||
|
} MachSect64; /* for 64-bit architectures */
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MACH_CPU_TYPE_X86_64 = (1<<24)|7,
|
||||||
|
MACH_CPU_SUBTYPE_X86 = 3,
|
||||||
|
MACH_EXECUTABLE_TYPE = 2,
|
||||||
|
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)
|
@ -1050,7 +1050,6 @@ fileline(char *str, int n, uvlong dot)
|
|||||||
bot = mid;
|
bot = mid;
|
||||||
else {
|
else {
|
||||||
line = pc2line(dot);
|
line = pc2line(dot);
|
||||||
print("line %d\n", line);
|
|
||||||
if(line > 0 && fline(str, n, line, f->hist, 0) >= 0)
|
if(line > 0 && fline(str, n, line, f->hist, 0) >= 0)
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user