2009-09-30 18:33:39 -06:00
|
|
|
// 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.
|
|
|
|
|
|
|
|
// Mach-O file writing
|
|
|
|
// http://developer.apple.com/mac/library/DOCUMENTATION/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html
|
|
|
|
|
2009-10-07 01:11:59 -06:00
|
|
|
#include "l.h"
|
2010-09-01 13:54:28 -06:00
|
|
|
#include "../ld/dwarf.h"
|
2009-10-07 01:11:59 -06:00
|
|
|
#include "../ld/lib.h"
|
2009-09-30 18:33:39 -06:00
|
|
|
#include "../ld/macho.h"
|
|
|
|
|
|
|
|
static int macho64;
|
|
|
|
static MachoHdr hdr;
|
|
|
|
static MachoLoad load[16];
|
|
|
|
static MachoSeg seg[16];
|
|
|
|
static MachoDebug xdebug[16];
|
|
|
|
static int nload, nseg, ndebug, nsect;
|
|
|
|
|
|
|
|
void
|
|
|
|
machoinit(void)
|
|
|
|
{
|
|
|
|
switch(thechar) {
|
|
|
|
// 64-bit architectures
|
|
|
|
case '6':
|
|
|
|
macho64 = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// 32-bit architectures
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MachoHdr*
|
|
|
|
getMachoHdr(void)
|
|
|
|
{
|
|
|
|
return &hdr;
|
|
|
|
}
|
|
|
|
|
|
|
|
MachoLoad*
|
|
|
|
newMachoLoad(uint32 type, uint32 ndata)
|
|
|
|
{
|
|
|
|
MachoLoad *l;
|
|
|
|
|
|
|
|
if(nload >= nelem(load)) {
|
|
|
|
diag("too many loads");
|
|
|
|
errorexit();
|
|
|
|
}
|
2010-10-11 12:39:41 -06:00
|
|
|
|
|
|
|
if(macho64 && (ndata & 1))
|
|
|
|
ndata++;
|
|
|
|
|
2009-09-30 18:33:39 -06:00
|
|
|
l = &load[nload++];
|
|
|
|
l->type = type;
|
|
|
|
l->ndata = ndata;
|
|
|
|
l->data = mal(ndata*4);
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
MachoSeg*
|
|
|
|
newMachoSeg(char *name, int msect)
|
|
|
|
{
|
|
|
|
MachoSeg *s;
|
|
|
|
|
|
|
|
if(nseg >= nelem(seg)) {
|
|
|
|
diag("too many segs");
|
|
|
|
errorexit();
|
|
|
|
}
|
|
|
|
s = &seg[nseg++];
|
|
|
|
s->name = name;
|
|
|
|
s->msect = msect;
|
|
|
|
s->sect = mal(msect*sizeof s->sect[0]);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
MachoSect*
|
|
|
|
newMachoSect(MachoSeg *seg, char *name)
|
|
|
|
{
|
|
|
|
MachoSect *s;
|
|
|
|
|
|
|
|
if(seg->nsect >= seg->msect) {
|
|
|
|
diag("too many sects in segment %s", seg->name);
|
|
|
|
errorexit();
|
|
|
|
}
|
|
|
|
s = &seg->sect[seg->nsect++];
|
|
|
|
s->name = name;
|
|
|
|
nsect++;
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
MachoDebug*
|
|
|
|
newMachoDebug(void)
|
|
|
|
{
|
|
|
|
if(ndebug >= nelem(xdebug)) {
|
|
|
|
diag("too many debugs");
|
|
|
|
errorexit();
|
|
|
|
}
|
|
|
|
return &xdebug[ndebug++];
|
|
|
|
}
|
|
|
|
|
2009-10-03 11:37:12 -06:00
|
|
|
|
|
|
|
// Generic linking code.
|
|
|
|
|
|
|
|
static uchar *linkdata;
|
|
|
|
static uint32 nlinkdata;
|
|
|
|
static uint32 mlinkdata;
|
|
|
|
|
|
|
|
static uchar *strtab;
|
|
|
|
static uint32 nstrtab;
|
|
|
|
static uint32 mstrtab;
|
|
|
|
|
2010-03-25 12:45:18 -06:00
|
|
|
struct Expsym
|
|
|
|
{
|
|
|
|
int off;
|
|
|
|
Sym* s;
|
|
|
|
} *expsym;
|
|
|
|
static int nexpsym;
|
|
|
|
static int nimpsym;
|
|
|
|
|
2009-10-03 11:37:12 -06:00
|
|
|
static char **dylib;
|
|
|
|
static int ndylib;
|
|
|
|
|
|
|
|
static vlong linkoff;
|
|
|
|
|
2009-09-30 18:33:39 -06:00
|
|
|
int
|
|
|
|
machowrite(void)
|
|
|
|
{
|
|
|
|
vlong o1;
|
|
|
|
int loadsize;
|
|
|
|
int i, j;
|
|
|
|
MachoSeg *s;
|
|
|
|
MachoSect *t;
|
|
|
|
MachoDebug *d;
|
|
|
|
MachoLoad *l;
|
|
|
|
|
2010-09-01 13:54:28 -06:00
|
|
|
o1 = cpos();
|
2009-09-30 18:33:39 -06:00
|
|
|
|
|
|
|
loadsize = 4*4*ndebug;
|
|
|
|
for(i=0; i<nload; i++)
|
|
|
|
loadsize += 4*(load[i].ndata+2);
|
|
|
|
if(macho64) {
|
|
|
|
loadsize += 18*4*nseg;
|
|
|
|
loadsize += 20*4*nsect;
|
|
|
|
} else {
|
|
|
|
loadsize += 14*4*nseg;
|
|
|
|
loadsize += 17*4*nsect;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(macho64)
|
|
|
|
LPUT(0xfeedfacf);
|
|
|
|
else
|
|
|
|
LPUT(0xfeedface);
|
|
|
|
LPUT(hdr.cpu);
|
|
|
|
LPUT(hdr.subcpu);
|
|
|
|
LPUT(2); /* file type - mach executable */
|
|
|
|
LPUT(nload+nseg+ndebug);
|
|
|
|
LPUT(loadsize);
|
|
|
|
LPUT(1); /* flags - no undefines */
|
|
|
|
if(macho64)
|
|
|
|
LPUT(0); /* reserved */
|
|
|
|
|
|
|
|
for(i=0; i<nseg; i++) {
|
|
|
|
s = &seg[i];
|
|
|
|
if(macho64) {
|
|
|
|
LPUT(25); /* segment 64 */
|
|
|
|
LPUT(72+80*s->nsect);
|
|
|
|
strnput(s->name, 16);
|
|
|
|
VPUT(s->vaddr);
|
|
|
|
VPUT(s->vsize);
|
|
|
|
VPUT(s->fileoffset);
|
|
|
|
VPUT(s->filesize);
|
|
|
|
LPUT(s->prot1);
|
|
|
|
LPUT(s->prot2);
|
|
|
|
LPUT(s->nsect);
|
|
|
|
LPUT(s->flag);
|
|
|
|
} else {
|
|
|
|
LPUT(1); /* segment 32 */
|
|
|
|
LPUT(56+68*s->nsect);
|
|
|
|
strnput(s->name, 16);
|
|
|
|
LPUT(s->vaddr);
|
|
|
|
LPUT(s->vsize);
|
|
|
|
LPUT(s->fileoffset);
|
|
|
|
LPUT(s->filesize);
|
|
|
|
LPUT(s->prot1);
|
|
|
|
LPUT(s->prot2);
|
|
|
|
LPUT(s->nsect);
|
|
|
|
LPUT(s->flag);
|
|
|
|
}
|
|
|
|
for(j=0; j<s->nsect; j++) {
|
|
|
|
t = &s->sect[j];
|
|
|
|
if(macho64) {
|
|
|
|
strnput(t->name, 16);
|
|
|
|
strnput(s->name, 16);
|
|
|
|
VPUT(t->addr);
|
|
|
|
VPUT(t->size);
|
|
|
|
LPUT(t->off);
|
|
|
|
LPUT(t->align);
|
|
|
|
LPUT(t->reloc);
|
|
|
|
LPUT(t->nreloc);
|
|
|
|
LPUT(t->flag);
|
|
|
|
LPUT(0); /* reserved */
|
|
|
|
LPUT(0); /* reserved */
|
|
|
|
LPUT(0); /* reserved */
|
|
|
|
} else {
|
|
|
|
strnput(t->name, 16);
|
|
|
|
strnput(s->name, 16);
|
|
|
|
LPUT(t->addr);
|
|
|
|
LPUT(t->size);
|
|
|
|
LPUT(t->off);
|
|
|
|
LPUT(t->align);
|
|
|
|
LPUT(t->reloc);
|
|
|
|
LPUT(t->nreloc);
|
|
|
|
LPUT(t->flag);
|
|
|
|
LPUT(0); /* reserved */
|
|
|
|
LPUT(0); /* reserved */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i=0; i<nload; i++) {
|
|
|
|
l = &load[i];
|
|
|
|
LPUT(l->type);
|
|
|
|
LPUT(4*(l->ndata+2));
|
|
|
|
for(j=0; j<l->ndata; j++)
|
|
|
|
LPUT(l->data[j]);
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i=0; i<ndebug; i++) {
|
|
|
|
d = &xdebug[i];
|
|
|
|
LPUT(3); /* obsolete gdb debug info */
|
|
|
|
LPUT(16); /* size of symseg command */
|
|
|
|
LPUT(d->fileoffset);
|
|
|
|
LPUT(d->filesize);
|
|
|
|
}
|
|
|
|
|
2010-09-01 13:54:28 -06:00
|
|
|
return cpos() - o1;
|
2009-09-30 18:33:39 -06:00
|
|
|
}
|
2009-10-03 11:37:12 -06:00
|
|
|
|
|
|
|
static void*
|
|
|
|
grow(uchar **dat, uint32 *ndat, uint32 *mdat, uint32 n)
|
|
|
|
{
|
|
|
|
uchar *p;
|
|
|
|
uint32 old;
|
|
|
|
|
|
|
|
if(*ndat+n > *mdat) {
|
|
|
|
old = *mdat;
|
|
|
|
*mdat = (*ndat+n)*2 + 128;
|
|
|
|
*dat = realloc(*dat, *mdat);
|
|
|
|
if(*dat == 0) {
|
|
|
|
diag("out of memory");
|
|
|
|
errorexit();
|
|
|
|
}
|
|
|
|
memset(*dat+old, 0, *mdat-old);
|
|
|
|
}
|
|
|
|
p = *dat + *ndat;
|
|
|
|
*ndat += n;
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
needlib(char *name)
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
Sym *s;
|
|
|
|
|
|
|
|
/* reuse hash code in symbol table */
|
|
|
|
p = smprint(".machoload.%s", name);
|
|
|
|
s = lookup(p, 0);
|
|
|
|
if(s->type == 0) {
|
|
|
|
s->type = 100; // avoid SDATA, etc.
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
domacho(void)
|
|
|
|
{
|
2010-03-25 12:45:18 -06:00
|
|
|
int h, ptrsize, t;
|
2009-10-03 11:37:12 -06:00
|
|
|
char *p;
|
|
|
|
uchar *dat;
|
|
|
|
uint32 x;
|
2010-10-22 13:27:50 -06:00
|
|
|
Sym *s, *smacho;
|
2010-03-25 12:45:18 -06:00
|
|
|
Sym **impsym;
|
2009-10-03 11:37:12 -06:00
|
|
|
|
|
|
|
ptrsize = 4;
|
|
|
|
if(macho64)
|
|
|
|
ptrsize = 8;
|
|
|
|
|
|
|
|
// empirically, string table must begin with " \x00".
|
|
|
|
if(!debug['d'])
|
|
|
|
*(char*)grow(&strtab, &nstrtab, &mstrtab, 2) = ' ';
|
|
|
|
|
2010-03-25 12:45:18 -06:00
|
|
|
impsym = nil;
|
2009-10-03 11:37:12 -06:00
|
|
|
for(h=0; h<NHASH; h++) {
|
2010-10-13 13:51:21 -06:00
|
|
|
for(s=hash[h]; s!=S; s=s->hash) {
|
2010-03-25 12:45:18 -06:00
|
|
|
if(!s->reachable || (s->type != STEXT && s->type != SDATA && s->type != SBSS) || s->dynimpname == nil)
|
2009-10-03 11:37:12 -06:00
|
|
|
continue;
|
|
|
|
if(debug['d']) {
|
|
|
|
diag("cannot use dynamic loading and -d");
|
|
|
|
errorexit();
|
|
|
|
}
|
2010-03-25 12:45:18 -06:00
|
|
|
if(!s->dynexport) {
|
|
|
|
if(nimpsym%32 == 0) {
|
|
|
|
impsym = realloc(impsym, (nimpsym+32)*sizeof impsym[0]);
|
|
|
|
if(impsym == nil) {
|
|
|
|
diag("out of memory");
|
|
|
|
errorexit();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impsym[nimpsym++] = s;
|
|
|
|
continue;
|
|
|
|
}
|
2009-10-03 11:37:12 -06:00
|
|
|
|
|
|
|
/* symbol table entry - darwin still puts _ prefixes on all C symbols */
|
|
|
|
x = nstrtab;
|
2010-03-22 20:58:55 -06:00
|
|
|
p = grow(&strtab, &nstrtab, &mstrtab, 1+strlen(s->dynimpname)+1);
|
2009-10-03 11:37:12 -06:00
|
|
|
*p++ = '_';
|
2010-03-22 20:58:55 -06:00
|
|
|
strcpy(p, s->dynimpname);
|
2009-10-03 11:37:12 -06:00
|
|
|
|
|
|
|
dat = grow(&linkdata, &nlinkdata, &mlinkdata, 8+ptrsize);
|
|
|
|
dat[0] = x;
|
|
|
|
dat[1] = x>>8;
|
|
|
|
dat[2] = x>>16;
|
|
|
|
dat[3] = x>>24;
|
|
|
|
|
2010-03-25 12:45:18 -06:00
|
|
|
dat[4] = 0x0f; // type: N_SECT | N_EXT - external, defined in sect
|
|
|
|
switch(s->type) {
|
|
|
|
default:
|
|
|
|
case STEXT:
|
|
|
|
t = 1;
|
|
|
|
break;
|
|
|
|
case SDATA:
|
|
|
|
t = 2;
|
|
|
|
break;
|
|
|
|
case SBSS:
|
|
|
|
t = 4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
dat[5] = t; // sect: section number
|
|
|
|
|
|
|
|
if (nexpsym%32 == 0) {
|
|
|
|
expsym = realloc(expsym, (nexpsym+32)*sizeof expsym[0]);
|
|
|
|
if (expsym == nil) {
|
|
|
|
diag("out of memory");
|
|
|
|
errorexit();
|
2009-10-03 11:37:12 -06:00
|
|
|
}
|
|
|
|
}
|
2010-03-25 12:45:18 -06:00
|
|
|
expsym[nexpsym].off = nlinkdata - ptrsize;
|
|
|
|
expsym[nexpsym++].s = s;
|
2009-10-03 11:37:12 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-22 13:27:50 -06:00
|
|
|
smacho = lookup("__nl_symbol_ptr", 0);
|
|
|
|
smacho->type = SMACHO;
|
|
|
|
smacho->reachable = 1;
|
2010-03-25 12:45:18 -06:00
|
|
|
for(h=0; h<nimpsym; h++) {
|
|
|
|
s = impsym[h];
|
2010-10-22 13:27:50 -06:00
|
|
|
s->type = SMACHO | SSUB;
|
|
|
|
s->sub = smacho->sub;
|
|
|
|
smacho->sub = s;
|
2010-03-25 12:45:18 -06:00
|
|
|
s->value = (nexpsym+h) * ptrsize;
|
2010-10-22 13:27:50 -06:00
|
|
|
s->reachable = 1;
|
2010-03-25 12:45:18 -06:00
|
|
|
|
|
|
|
/* symbol table entry - darwin still puts _ prefixes on all C symbols */
|
|
|
|
x = nstrtab;
|
|
|
|
p = grow(&strtab, &nstrtab, &mstrtab, 1+strlen(s->dynimpname)+1);
|
|
|
|
*p++ = '_';
|
|
|
|
strcpy(p, s->dynimpname);
|
|
|
|
|
|
|
|
dat = grow(&linkdata, &nlinkdata, &mlinkdata, 8+ptrsize);
|
|
|
|
dat[0] = x;
|
|
|
|
dat[1] = x>>8;
|
|
|
|
dat[2] = x>>16;
|
|
|
|
dat[3] = x>>24;
|
|
|
|
|
|
|
|
dat[4] = 0x01; // type: N_EXT - external symbol
|
|
|
|
|
|
|
|
if(needlib(s->dynimplib)) {
|
|
|
|
if(ndylib%32 == 0) {
|
|
|
|
dylib = realloc(dylib, (ndylib+32)*sizeof dylib[0]);
|
|
|
|
if(dylib == nil) {
|
|
|
|
diag("out of memory");
|
|
|
|
errorexit();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dylib[ndylib++] = s->dynimplib;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(impsym);
|
|
|
|
|
2009-10-03 11:37:12 -06:00
|
|
|
/*
|
|
|
|
* list of symbol table indexes.
|
|
|
|
* we don't take advantage of the opportunity
|
|
|
|
* to order the symbol table differently from
|
|
|
|
* this list, so it is boring: 0 1 2 3 4 ...
|
|
|
|
*/
|
2010-03-25 12:45:18 -06:00
|
|
|
for(x=0; x<nexpsym+nimpsym; x++) {
|
2009-10-03 11:37:12 -06:00
|
|
|
dat = grow(&linkdata, &nlinkdata, &mlinkdata, 4);
|
|
|
|
dat[0] = x;
|
|
|
|
dat[1] = x>>8;
|
|
|
|
dat[2] = x>>16;
|
|
|
|
dat[3] = x>>24;
|
|
|
|
}
|
|
|
|
|
2010-10-22 13:27:50 -06:00
|
|
|
smacho->size = (nexpsym+nimpsym) * ptrsize;
|
|
|
|
if(smacho->size == 0)
|
|
|
|
smacho->reachable = 0;
|
2009-10-03 11:37:12 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
vlong
|
|
|
|
domacholink(void)
|
|
|
|
{
|
2010-03-25 12:45:18 -06:00
|
|
|
int i;
|
|
|
|
uchar *p;
|
|
|
|
Sym *s;
|
|
|
|
uint64 val;
|
2010-10-22 13:27:50 -06:00
|
|
|
Sym *smacho;
|
|
|
|
|
|
|
|
smacho = lookup("__nl_symbol_ptr", 0);
|
2010-03-25 12:45:18 -06:00
|
|
|
|
2009-10-03 11:37:12 -06:00
|
|
|
linkoff = 0;
|
2010-10-12 14:52:17 -06:00
|
|
|
if(nlinkdata > 0 || nstrtab > 0) {
|
2010-10-22 13:27:50 -06:00
|
|
|
linkoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen - smacho->size, INITRND);
|
2009-10-03 11:37:12 -06:00
|
|
|
seek(cout, linkoff, 0);
|
2010-03-25 12:45:18 -06:00
|
|
|
|
|
|
|
for(i = 0; i<nexpsym; ++i) {
|
|
|
|
s = expsym[i].s;
|
|
|
|
val = s->value;
|
2010-10-14 21:48:40 -06:00
|
|
|
if(s->type == SXREF)
|
2010-03-25 12:45:18 -06:00
|
|
|
diag("export of undefined symbol %s", s->name);
|
|
|
|
if (s->type != STEXT)
|
2010-10-19 11:08:17 -06:00
|
|
|
val += segdata.vaddr;
|
2010-03-25 12:45:18 -06:00
|
|
|
p = linkdata+expsym[i].off;
|
|
|
|
p[0] = val;
|
|
|
|
p[1] = val >> 8;
|
|
|
|
p[2] = val >> 16;
|
|
|
|
p[3] = val >> 24;
|
|
|
|
if (macho64) {
|
|
|
|
p[4] = val >> 32;
|
|
|
|
p[5] = val >> 40;
|
|
|
|
p[6] = val >> 48;
|
|
|
|
p[7] = val >> 56;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-28 11:00:13 -06:00
|
|
|
ewrite(cout, linkdata, nlinkdata);
|
|
|
|
ewrite(cout, strtab, nstrtab);
|
2009-10-03 11:37:12 -06:00
|
|
|
}
|
|
|
|
return rnd(nlinkdata+nstrtab, INITRND);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-10-19 16:07:19 -06:00
|
|
|
asmbmacho(void)
|
2009-10-03 11:37:12 -06:00
|
|
|
{
|
|
|
|
vlong v, w;
|
|
|
|
vlong va;
|
|
|
|
int a, i, ptrsize;
|
2010-07-01 00:31:27 -06:00
|
|
|
char *pkgroot;
|
2009-10-03 11:37:12 -06:00
|
|
|
MachoHdr *mh;
|
|
|
|
MachoSect *msect;
|
|
|
|
MachoSeg *ms;
|
|
|
|
MachoDebug *md;
|
|
|
|
MachoLoad *ml;
|
2010-10-22 13:27:50 -06:00
|
|
|
Sym *smacho;
|
2009-10-03 11:37:12 -06:00
|
|
|
|
|
|
|
/* apple MACH */
|
|
|
|
va = INITTEXT - HEADR;
|
|
|
|
mh = getMachoHdr();
|
|
|
|
switch(thechar){
|
|
|
|
default:
|
|
|
|
diag("unknown mach architecture");
|
|
|
|
errorexit();
|
|
|
|
case '6':
|
|
|
|
mh->cpu = MACHO_CPU_AMD64;
|
|
|
|
mh->subcpu = MACHO_SUBCPU_X86;
|
|
|
|
ptrsize = 8;
|
|
|
|
break;
|
|
|
|
case '8':
|
|
|
|
mh->cpu = MACHO_CPU_386;
|
|
|
|
mh->subcpu = MACHO_SUBCPU_X86;
|
|
|
|
ptrsize = 4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* segment for zero page */
|
|
|
|
ms = newMachoSeg("__PAGEZERO", 0);
|
|
|
|
ms->vsize = va;
|
|
|
|
|
|
|
|
/* text */
|
2010-10-19 11:08:17 -06:00
|
|
|
v = rnd(HEADR+segtext.len, INITRND);
|
2009-10-03 11:37:12 -06:00
|
|
|
ms = newMachoSeg("__TEXT", 1);
|
|
|
|
ms->vaddr = va;
|
|
|
|
ms->vsize = v;
|
|
|
|
ms->filesize = v;
|
|
|
|
ms->prot1 = 7;
|
|
|
|
ms->prot2 = 5;
|
|
|
|
|
|
|
|
msect = newMachoSect(ms, "__text");
|
|
|
|
msect->addr = INITTEXT;
|
2010-10-19 11:08:17 -06:00
|
|
|
msect->size = segtext.sect->len;
|
2009-10-03 11:37:12 -06:00
|
|
|
msect->off = INITTEXT - va;
|
|
|
|
msect->flag = 0x400; /* flag - some instructions */
|
|
|
|
|
|
|
|
/* data */
|
2010-10-22 13:27:50 -06:00
|
|
|
smacho = lookup("__nl_symbol_ptr", 0);
|
2010-10-14 21:48:40 -06:00
|
|
|
w = segdata.len;
|
2010-10-22 13:27:50 -06:00
|
|
|
ms = newMachoSeg("__DATA", 2+(smacho->size > 0));
|
2009-10-03 11:37:12 -06:00
|
|
|
ms->vaddr = va+v;
|
|
|
|
ms->vsize = w;
|
|
|
|
ms->fileoffset = v;
|
2010-10-14 21:48:40 -06:00
|
|
|
ms->filesize = segdata.filelen;
|
2009-10-03 11:37:12 -06:00
|
|
|
ms->prot1 = 7;
|
|
|
|
ms->prot2 = 3;
|
|
|
|
|
|
|
|
msect = newMachoSect(ms, "__data");
|
|
|
|
msect->addr = va+v;
|
2010-10-22 13:27:50 -06:00
|
|
|
msect->size = segdata.filelen - smacho->size;
|
2009-10-03 11:37:12 -06:00
|
|
|
msect->off = v;
|
|
|
|
|
2010-10-22 13:27:50 -06:00
|
|
|
if(smacho->size > 0) {
|
2009-10-03 11:37:12 -06:00
|
|
|
msect = newMachoSect(ms, "__nl_symbol_ptr");
|
2010-10-22 13:27:50 -06:00
|
|
|
msect->addr = smacho->value;
|
|
|
|
msect->size = smacho->size;
|
|
|
|
msect->off = datoff(msect->addr);
|
2009-10-03 11:37:12 -06:00
|
|
|
msect->align = 2;
|
|
|
|
msect->flag = 6; /* section with nonlazy symbol pointers */
|
|
|
|
/*
|
|
|
|
* The reserved1 field is supposed to be the index of
|
|
|
|
* the first entry in the list of symbol table indexes
|
|
|
|
* in isymtab for the symbols we need. We only use
|
|
|
|
* pointers, so we need the entire list, so the index
|
|
|
|
* here should be 0, which luckily is what the Mach-O
|
|
|
|
* writing code emits by default for this not really reserved field.
|
|
|
|
msect->reserved1 = 0; - first indirect symbol table entry we need
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
msect = newMachoSect(ms, "__bss");
|
2010-10-14 21:48:40 -06:00
|
|
|
msect->addr = va+v+segdata.filelen;
|
|
|
|
msect->size = segdata.len - segdata.filelen;
|
2009-10-03 11:37:12 -06:00
|
|
|
msect->flag = 1; /* flag - zero fill */
|
|
|
|
|
|
|
|
switch(thechar) {
|
|
|
|
default:
|
|
|
|
diag("unknown macho architecture");
|
|
|
|
errorexit();
|
|
|
|
case '6':
|
|
|
|
ml = newMachoLoad(5, 42+2); /* unix thread */
|
|
|
|
ml->data[0] = 4; /* thread type */
|
|
|
|
ml->data[1] = 42; /* word count */
|
|
|
|
ml->data[2+32] = entryvalue(); /* start pc */
|
2010-09-11 22:17:44 -06:00
|
|
|
ml->data[2+32+1] = entryvalue()>>16>>16; // hide >>32 for 8l
|
2009-10-03 11:37:12 -06:00
|
|
|
break;
|
|
|
|
case '8':
|
|
|
|
ml = newMachoLoad(5, 16+2); /* unix thread */
|
|
|
|
ml->data[0] = 1; /* thread type */
|
|
|
|
ml->data[1] = 16; /* word count */
|
|
|
|
ml->data[2+10] = entryvalue(); /* start pc */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!debug['d']) {
|
|
|
|
int nsym;
|
|
|
|
|
2010-10-22 13:27:50 -06:00
|
|
|
nsym = smacho->size/ptrsize;
|
2009-10-03 11:37:12 -06:00
|
|
|
|
|
|
|
ms = newMachoSeg("__LINKEDIT", 0);
|
2010-10-14 21:48:40 -06:00
|
|
|
ms->vaddr = va+v+rnd(segdata.len, INITRND);
|
2009-10-03 11:37:12 -06:00
|
|
|
ms->vsize = nlinkdata+nstrtab;
|
|
|
|
ms->fileoffset = linkoff;
|
|
|
|
ms->filesize = nlinkdata+nstrtab;
|
|
|
|
ms->prot1 = 7;
|
|
|
|
ms->prot2 = 3;
|
|
|
|
|
|
|
|
ml = newMachoLoad(2, 4); /* LC_SYMTAB */
|
|
|
|
ml->data[0] = linkoff; /* symoff */
|
|
|
|
ml->data[1] = nsym; /* nsyms */
|
|
|
|
ml->data[2] = linkoff + nlinkdata; /* stroff */
|
|
|
|
ml->data[3] = nstrtab; /* strsize */
|
|
|
|
|
|
|
|
ml = newMachoLoad(11, 18); /* LC_DYSYMTAB */
|
|
|
|
ml->data[0] = 0; /* ilocalsym */
|
|
|
|
ml->data[1] = 0; /* nlocalsym */
|
|
|
|
ml->data[2] = 0; /* iextdefsym */
|
2010-03-25 12:45:18 -06:00
|
|
|
ml->data[3] = nexpsym; /* nextdefsym */
|
|
|
|
ml->data[4] = nexpsym; /* iundefsym */
|
|
|
|
ml->data[5] = nimpsym; /* nundefsym */
|
2009-10-03 11:37:12 -06:00
|
|
|
ml->data[6] = 0; /* tocoffset */
|
|
|
|
ml->data[7] = 0; /* ntoc */
|
|
|
|
ml->data[8] = 0; /* modtaboff */
|
|
|
|
ml->data[9] = 0; /* nmodtab */
|
|
|
|
ml->data[10] = 0; /* extrefsymoff */
|
|
|
|
ml->data[11] = 0; /* nextrefsyms */
|
|
|
|
ml->data[12] = linkoff + nlinkdata - nsym*4; /* indirectsymoff */
|
|
|
|
ml->data[13] = nsym; /* nindirectsyms */
|
|
|
|
ml->data[14] = 0; /* extreloff */
|
|
|
|
ml->data[15] = 0; /* nextrel */
|
|
|
|
ml->data[16] = 0; /* locreloff */
|
|
|
|
ml->data[17] = 0; /* nlocrel */
|
|
|
|
|
|
|
|
ml = newMachoLoad(14, 6); /* LC_LOAD_DYLINKER */
|
|
|
|
ml->data[0] = 12; /* offset to string */
|
|
|
|
strcpy((char*)&ml->data[1], "/usr/lib/dyld");
|
|
|
|
|
2010-07-01 00:31:27 -06:00
|
|
|
if(ndylib > 0) { /* add reference to where .so files are installed */
|
|
|
|
pkgroot = smprint("%s/pkg/%s_%s", goroot, goos, goarch);
|
|
|
|
ml = newMachoLoad(0x80000000 | 0x1c, 1+(strlen(pkgroot)+1+7)/8*2); /* LC_RPATH */
|
|
|
|
ml->data[0] = 12; /* offset of string from beginning of load */
|
|
|
|
strcpy((char*)&ml->data[1], pkgroot);
|
|
|
|
}
|
2009-10-03 11:37:12 -06:00
|
|
|
for(i=0; i<ndylib; i++) {
|
|
|
|
ml = newMachoLoad(12, 4+(strlen(dylib[i])+1+7)/8*2); /* LC_LOAD_DYLIB */
|
|
|
|
ml->data[0] = 24; /* offset of string from beginning of load */
|
|
|
|
ml->data[1] = 0; /* time stamp */
|
|
|
|
ml->data[2] = 0; /* version */
|
|
|
|
ml->data[3] = 0; /* compatibility version */
|
|
|
|
strcpy((char*)&ml->data[4], dylib[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!debug['s']) {
|
2010-10-19 16:07:19 -06:00
|
|
|
Sym *s;
|
2009-10-03 11:37:12 -06:00
|
|
|
|
|
|
|
md = newMachoDebug();
|
2010-10-19 16:07:19 -06:00
|
|
|
s = lookup("symtab", 0);
|
|
|
|
md->fileoffset = datoff(s->value);
|
|
|
|
md->filesize = s->size;
|
2009-10-03 11:37:12 -06:00
|
|
|
|
|
|
|
md = newMachoDebug();
|
2010-10-19 16:07:19 -06:00
|
|
|
s = lookup("pclntab", 0);
|
|
|
|
md->fileoffset = datoff(s->value);
|
|
|
|
md->filesize = s->size;
|
2010-09-01 13:54:28 -06:00
|
|
|
|
2010-09-14 09:16:57 -06:00
|
|
|
dwarfaddmachoheaders();
|
2009-10-03 11:37:12 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
a = machowrite();
|
|
|
|
if(a > MACHORESERVE)
|
|
|
|
diag("MACHORESERVE too small: %d > %d", a, MACHORESERVE);
|
|
|
|
}
|