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;
|
2011-04-20 14:25:00 -06:00
|
|
|
static MachoLoad *load;
|
2009-09-30 18:33:39 -06:00
|
|
|
static MachoSeg seg[16];
|
|
|
|
static MachoDebug xdebug[16];
|
2011-04-20 14:25:00 -06:00
|
|
|
static int nload, mload, nseg, ndebug, nsect;
|
2009-09-30 18:33:39 -06:00
|
|
|
|
2011-05-24 17:50:13 -06:00
|
|
|
// Amount of space left for adding load commands
|
|
|
|
// that refer to dynamic libraries. Because these have
|
|
|
|
// to go in the Mach-O header, we can't just pick a
|
|
|
|
// "big enough" header size. The initial header is
|
|
|
|
// one page, the non-dynamic library stuff takes
|
|
|
|
// up about 1300 bytes; we overestimate that as 2k.
|
|
|
|
static int load_budget = INITIAL_MACHO_HEADR - 2*1024;
|
|
|
|
|
2009-09-30 18:33:39 -06:00
|
|
|
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;
|
|
|
|
|
2011-04-20 14:25:00 -06:00
|
|
|
if(nload >= mload) {
|
|
|
|
if(mload == 0)
|
|
|
|
mload = 1;
|
|
|
|
else
|
|
|
|
mload *= 2;
|
|
|
|
load = realloc(load, mload*sizeof load[0]);
|
|
|
|
if(load == nil) {
|
|
|
|
diag("out of memory");
|
|
|
|
errorexit();
|
|
|
|
}
|
2009-09-30 18:33:39 -06:00
|
|
|
}
|
2011-04-20 14:25:00 -06:00
|
|
|
|
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 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);
|
2010-12-08 11:56:43 -07:00
|
|
|
LPUT(t->res1); /* reserved */
|
|
|
|
LPUT(t->res2); /* reserved */
|
2009-09-30 18:33:39 -06:00
|
|
|
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);
|
2010-12-08 11:56:43 -07:00
|
|
|
LPUT(t->res1); /* reserved */
|
|
|
|
LPUT(t->res2); /* reserved */
|
2009-09-30 18:33:39 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
void
|
|
|
|
domacho(void)
|
|
|
|
{
|
2010-12-08 11:56:43 -07:00
|
|
|
Sym *s;
|
2009-10-03 11:37:12 -06:00
|
|
|
|
2010-12-08 11:56:43 -07:00
|
|
|
if(debug['d'])
|
|
|
|
return;
|
2009-10-03 11:37:12 -06:00
|
|
|
|
2010-12-08 11:56:43 -07:00
|
|
|
// empirically, string table must begin with " \x00".
|
|
|
|
s = lookup(".dynstr", 0);
|
|
|
|
s->type = SMACHODYNSTR;
|
|
|
|
s->reachable = 1;
|
|
|
|
adduint8(s, ' ');
|
|
|
|
adduint8(s, '\0');
|
|
|
|
|
|
|
|
s = lookup(".dynsym", 0);
|
|
|
|
s->type = SMACHODYNSYM;
|
|
|
|
s->reachable = 1;
|
|
|
|
|
|
|
|
s = lookup(".plt", 0); // will be __symbol_stub
|
|
|
|
s->type = SMACHOPLT;
|
|
|
|
s->reachable = 1;
|
|
|
|
|
|
|
|
s = lookup(".got", 0); // will be __nl_symbol_ptr
|
|
|
|
s->type = SMACHOGOT;
|
|
|
|
s->reachable = 1;
|
|
|
|
|
|
|
|
s = lookup(".linkedit.plt", 0); // indirect table for .plt
|
|
|
|
s->type = SMACHOINDIRECTPLT;
|
|
|
|
s->reachable = 1;
|
|
|
|
|
|
|
|
s = lookup(".linkedit.got", 0); // indirect table for .got
|
|
|
|
s->type = SMACHOINDIRECTGOT;
|
|
|
|
s->reachable = 1;
|
2009-10-03 11:37:12 -06:00
|
|
|
}
|
|
|
|
|
2010-12-08 11:56:43 -07:00
|
|
|
void
|
|
|
|
machoadddynlib(char *lib)
|
2009-10-03 11:37:12 -06:00
|
|
|
{
|
2011-05-24 17:50:13 -06:00
|
|
|
// Will need to store the library name rounded up
|
|
|
|
// and 24 bytes of header metadata. If not enough
|
|
|
|
// space, grab another page of initial space at the
|
|
|
|
// beginning of the output file.
|
|
|
|
load_budget -= (strlen(lib)+7)/8*8 + 24;
|
|
|
|
if(load_budget < 0) {
|
|
|
|
HEADR += 4096;
|
|
|
|
INITTEXT += 4096;
|
|
|
|
load_budget += 4096;
|
|
|
|
}
|
|
|
|
|
2010-12-08 11:56:43 -07:00
|
|
|
if(ndylib%32 == 0) {
|
|
|
|
dylib = realloc(dylib, (ndylib+32)*sizeof dylib[0]);
|
|
|
|
if(dylib == nil) {
|
|
|
|
diag("out of memory");
|
|
|
|
errorexit();
|
2010-03-25 12:45:18 -06:00
|
|
|
}
|
2009-10-03 11:37:12 -06:00
|
|
|
}
|
2010-12-08 11:56:43 -07:00
|
|
|
dylib[ndylib++] = lib;
|
2009-10-03 11:37:12 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-10-19 16:07:19 -06:00
|
|
|
asmbmacho(void)
|
2009-10-03 11:37:12 -06:00
|
|
|
{
|
|
|
|
vlong v, w;
|
|
|
|
vlong va;
|
2010-12-08 11:56:43 -07:00
|
|
|
int a, i;
|
2009-10-03 11:37:12 -06:00
|
|
|
MachoHdr *mh;
|
|
|
|
MachoSect *msect;
|
|
|
|
MachoSeg *ms;
|
|
|
|
MachoDebug *md;
|
|
|
|
MachoLoad *ml;
|
2010-12-08 11:56:43 -07:00
|
|
|
Sym *s;
|
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;
|
|
|
|
break;
|
|
|
|
case '8':
|
|
|
|
mh->cpu = MACHO_CPU_386;
|
|
|
|
mh->subcpu = MACHO_SUBCPU_X86;
|
|
|
|
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);
|
2010-12-08 11:56:43 -07:00
|
|
|
ms = newMachoSeg("__TEXT", 2);
|
2009-10-03 11:37:12 -06:00
|
|
|
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 */
|
2010-12-08 11:56:43 -07:00
|
|
|
|
|
|
|
s = lookup(".plt", 0);
|
|
|
|
if(s->size > 0) {
|
|
|
|
msect = newMachoSect(ms, "__symbol_stub1");
|
|
|
|
msect->addr = symaddr(s);
|
|
|
|
msect->size = s->size;
|
|
|
|
msect->off = ms->fileoffset + msect->addr - ms->vaddr;
|
|
|
|
msect->flag = 0x80000408; /* flag */
|
|
|
|
msect->res1 = 0; /* index into indirect symbol table */
|
|
|
|
msect->res2 = 6; /* size of stubs */
|
|
|
|
}
|
2009-10-03 11:37:12 -06:00
|
|
|
|
|
|
|
/* data */
|
2010-10-14 21:48:40 -06:00
|
|
|
w = segdata.len;
|
2010-12-08 11:56:43 -07:00
|
|
|
ms = newMachoSeg("__DATA", 3);
|
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;
|
|
|
|
msect->off = v;
|
2011-04-25 11:57:52 -06:00
|
|
|
msect->size = segdata.filelen;
|
2009-10-03 11:37:12 -06:00
|
|
|
|
2010-12-08 11:56:43 -07:00
|
|
|
s = lookup(".got", 0);
|
|
|
|
if(s->size > 0) {
|
2011-04-25 11:57:52 -06:00
|
|
|
msect->size = symaddr(s) - msect->addr;
|
|
|
|
|
2009-10-03 11:37:12 -06:00
|
|
|
msect = newMachoSect(ms, "__nl_symbol_ptr");
|
2010-12-08 11:56:43 -07:00
|
|
|
msect->addr = symaddr(s);
|
|
|
|
msect->size = s->size;
|
2010-10-22 13:27:50 -06:00
|
|
|
msect->off = datoff(msect->addr);
|
2009-10-03 11:37:12 -06:00
|
|
|
msect->align = 2;
|
|
|
|
msect->flag = 6; /* section with nonlazy symbol pointers */
|
2010-12-08 11:56:43 -07:00
|
|
|
msect->res1 = lookup(".linkedit.plt", 0)->size / 4; /* offset into indirect symbol table */
|
2009-10-03 11:37:12 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
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']) {
|
2010-12-08 11:56:43 -07:00
|
|
|
Sym *s1, *s2, *s3, *s4;
|
2009-10-03 11:37:12 -06:00
|
|
|
|
2010-12-08 11:56:43 -07:00
|
|
|
// must match domacholink below
|
|
|
|
s1 = lookup(".dynsym", 0);
|
2011-10-18 14:31:03 -06:00
|
|
|
s2 = lookup(".linkedit.plt", 0);
|
|
|
|
s3 = lookup(".linkedit.got", 0);
|
|
|
|
s4 = lookup(".dynstr", 0);
|
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);
|
2010-12-08 11:56:43 -07:00
|
|
|
ms->vsize = s1->size + s2->size + s3->size + s4->size;
|
2009-10-03 11:37:12 -06:00
|
|
|
ms->fileoffset = linkoff;
|
2010-12-08 11:56:43 -07:00
|
|
|
ms->filesize = ms->vsize;
|
2009-10-03 11:37:12 -06:00
|
|
|
ms->prot1 = 7;
|
|
|
|
ms->prot2 = 3;
|
|
|
|
|
|
|
|
ml = newMachoLoad(2, 4); /* LC_SYMTAB */
|
|
|
|
ml->data[0] = linkoff; /* symoff */
|
2010-12-08 11:56:43 -07:00
|
|
|
ml->data[1] = s1->size / (macho64 ? 16 : 12); /* nsyms */
|
2011-10-18 14:31:03 -06:00
|
|
|
ml->data[2] = linkoff + s1->size + s2->size + s3->size; /* stroff */
|
|
|
|
ml->data[3] = s4->size; /* strsize */
|
2009-10-03 11:37:12 -06:00
|
|
|
|
|
|
|
ml = newMachoLoad(11, 18); /* LC_DYSYMTAB */
|
|
|
|
ml->data[0] = 0; /* ilocalsym */
|
|
|
|
ml->data[1] = 0; /* nlocalsym */
|
|
|
|
ml->data[2] = 0; /* iextdefsym */
|
2011-01-11 14:56:47 -07:00
|
|
|
ml->data[3] = ndynexp; /* nextdefsym */
|
|
|
|
ml->data[4] = ndynexp; /* iundefsym */
|
|
|
|
ml->data[5] = (s1->size / (macho64 ? 16 : 12)) - ndynexp; /* 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 */
|
2011-10-18 14:31:03 -06:00
|
|
|
ml->data[12] = linkoff + s1->size; /* indirectsymoff */
|
|
|
|
ml->data[13] = (s2->size + s3->size) / 4; /* nindirectsyms */
|
2009-10-03 11:37:12 -06:00
|
|
|
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");
|
|
|
|
|
|
|
|
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();
|
2011-05-24 17:50:13 -06:00
|
|
|
if(a > HEADR)
|
|
|
|
diag("HEADR too small: %d > %d", a, HEADR);
|
2009-10-03 11:37:12 -06:00
|
|
|
}
|
2010-12-08 11:56:43 -07:00
|
|
|
|
|
|
|
vlong
|
|
|
|
domacholink(void)
|
|
|
|
{
|
|
|
|
int size;
|
|
|
|
Sym *s1, *s2, *s3, *s4;
|
|
|
|
|
|
|
|
// write data that will be linkedit section
|
|
|
|
s1 = lookup(".dynsym", 0);
|
2011-01-11 14:56:47 -07:00
|
|
|
relocsym(s1);
|
2011-10-18 14:31:03 -06:00
|
|
|
s2 = lookup(".linkedit.plt", 0);
|
|
|
|
s3 = lookup(".linkedit.got", 0);
|
|
|
|
s4 = lookup(".dynstr", 0);
|
2010-12-08 11:56:43 -07:00
|
|
|
|
2011-10-18 14:31:03 -06:00
|
|
|
while(s4->size%4)
|
|
|
|
adduint8(s4, 0);
|
2010-12-08 11:56:43 -07:00
|
|
|
|
|
|
|
size = s1->size + s2->size + s3->size + s4->size;
|
|
|
|
|
|
|
|
if(size > 0) {
|
2011-10-18 13:58:10 -06:00
|
|
|
linkoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen, INITRND) + rnd(segdwarf.filelen, INITRND);
|
2011-07-18 10:04:09 -06:00
|
|
|
cseek(linkoff);
|
2010-12-08 11:56:43 -07:00
|
|
|
|
2011-07-18 10:04:09 -06:00
|
|
|
cwrite(s1->p, s1->size);
|
|
|
|
cwrite(s2->p, s2->size);
|
|
|
|
cwrite(s3->p, s3->size);
|
|
|
|
cwrite(s4->p, s4->size);
|
2010-12-08 11:56:43 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return rnd(size, INITRND);
|
|
|
|
}
|