Commit f5690004 authored by Russ Cox's avatar Russ Cox

6l, 8l: support for linking ELF and Mach-O .o files

More support for references to dynamic symbols,
including full GOT and PLT for ELF objects.

For Mach-O everything ends up in the GOT: dealing
with the real lazy PLT is too hard for now so we punt.

R=iant, iant2
CC=golang-dev
https://golang.org/cl/3491042
parent 9042c2ce
...@@ -14,6 +14,8 @@ OFILES=\ ...@@ -14,6 +14,8 @@ OFILES=\
elf.$O\ elf.$O\
enam.$O\ enam.$O\
go.$O\ go.$O\
ldelf.$O\
ldmacho.$O\
lib.$O\ lib.$O\
list.$O\ list.$O\
macho.$O\ macho.$O\
......
This diff is collapsed.
...@@ -84,7 +84,7 @@ struct Reloc ...@@ -84,7 +84,7 @@ struct Reloc
{ {
int32 off; int32 off;
uchar siz; uchar siz;
uchar type; int32 type;
int64 add; int64 add;
Sym* sym; Sym* sym;
}; };
...@@ -128,10 +128,14 @@ struct Sym ...@@ -128,10 +128,14 @@ struct Sym
uchar reachable; uchar reachable;
uchar dynexport; uchar dynexport;
uchar special; uchar special;
int32 dynid;
int32 sig; int32 sig;
int32 plt;
int32 got;
Sym* hash; // in hash table Sym* hash; // in hash table
Sym* next; // in text or data list Sym* next; // in text or data list
Sym* sub; // in SSUB list Sym* sub; // in SSUB list
Sym* outer; // container of sub
vlong value; vlong value;
vlong size; vlong size;
Sym* gotype; Sym* gotype;
...@@ -174,14 +178,20 @@ enum ...@@ -174,14 +178,20 @@ enum
/* order here is order in output file */ /* order here is order in output file */
STEXT = 1, STEXT = 1,
SELFDATA, SELFDATA,
SMACHOPLT,
SRODATA, SRODATA,
SDATA, SDATA,
SMACHO, SMACHOGOT,
SBSS, SBSS,
SXREF, SXREF,
SMACHODYNSTR,
SMACHODYNSYM,
SMACHOINDIRECTPLT,
SMACHOINDIRECTGOT,
SFILE, SFILE,
SCONST, SCONST,
SDYNIMPORT,
SSUB = 1<<8, SSUB = 1<<8,
NHASH = 10007, NHASH = 10007,
......
...@@ -500,6 +500,8 @@ enum ...@@ -500,6 +500,8 @@ enum
D_CONST2 = D_INDIR+D_INDIR, D_CONST2 = D_INDIR+D_INDIR,
D_SIZE, /* 8l internal */ D_SIZE, /* 8l internal */
D_PCREL, D_PCREL,
D_GOTOFF,
D_GOTPCREL,
T_TYPE = 1<<0, T_TYPE = 1<<0,
T_INDEX = 1<<1, T_INDEX = 1<<1,
......
...@@ -14,6 +14,8 @@ OFILES=\ ...@@ -14,6 +14,8 @@ OFILES=\
elf.$O\ elf.$O\
enam.$O\ enam.$O\
go.$O\ go.$O\
ldelf.$O\
ldmacho.$O\
lib.$O\ lib.$O\
list.$O\ list.$O\
macho.$O\ macho.$O\
......
This diff is collapsed.
...@@ -84,7 +84,7 @@ struct Reloc ...@@ -84,7 +84,7 @@ struct Reloc
{ {
int32 off; int32 off;
uchar siz; uchar siz;
uchar type; int32 type;
int32 add; int32 add;
Sym* sym; Sym* sym;
}; };
...@@ -130,9 +130,13 @@ struct Sym ...@@ -130,9 +130,13 @@ struct Sym
int32 value; int32 value;
int32 size; int32 size;
int32 sig; int32 sig;
int32 dynid;
int32 plt;
int32 got;
Sym* hash; // in hash table Sym* hash; // in hash table
Sym* next; // in text or data list Sym* next; // in text or data list
Sym* sub; // in sub list Sym* sub; // in sub list
Sym* outer; // container of sub
Sym* gotype; Sym* gotype;
char* file; char* file;
char* dynimpname; char* dynimpname;
...@@ -165,15 +169,22 @@ enum ...@@ -165,15 +169,22 @@ enum
/* order here is order in output file */ /* order here is order in output file */
STEXT, STEXT,
SELFDATA, SELFDATA,
SMACHOPLT,
SRODATA, SRODATA,
SDATA, SDATA,
SMACHO, /* Mach-O __nl_symbol_ptr */ SMACHO, /* Mach-O __nl_symbol_ptr */
SMACHOGOT,
SWINDOWS, SWINDOWS,
SBSS, SBSS,
SXREF, SXREF,
SMACHODYNSTR,
SMACHODYNSYM,
SMACHOINDIRECTPLT,
SMACHOINDIRECTGOT,
SFILE, SFILE,
SCONST, SCONST,
SDYNIMPORT,
SSUB = 1<<8, /* sub-symbol, linked from parent via ->sub list */ SSUB = 1<<8, /* sub-symbol, linked from parent via ->sub list */
...@@ -317,7 +328,7 @@ EXTERN int dtype; ...@@ -317,7 +328,7 @@ EXTERN int dtype;
EXTERN int tlsoffset; EXTERN int tlsoffset;
EXTERN Sym* adrgotype; // type symbol on last Adr read EXTERN Sym* adrgotype; // type symbol on last Adr read
EXTERN Sym* fromgotype; // type symbol on last p->from read EXTERN Sym* fromgotype; // type symbol on last p->from read
EXTERN int elftextsh;
extern Optab optab[]; extern Optab optab[];
extern char* anames[]; extern char* anames[];
......
...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,8 @@
#include "../ld/elf.h" #include "../ld/elf.h"
#include "../ld/pe.h" #include "../ld/pe.h"
void dynreloc(void);
/* /*
* divide-and-conquer list-link * divide-and-conquer list-link
* sort of Sym* structures. * sort of Sym* structures.
...@@ -147,27 +149,49 @@ relocsym(Sym *s) ...@@ -147,27 +149,49 @@ relocsym(Sym *s)
vlong o; vlong o;
uchar *cast; uchar *cast;
cursym = s;
memset(&p, 0, sizeof p); memset(&p, 0, sizeof p);
for(r=s->r; r<s->r+s->nr; r++) { for(r=s->r; r<s->r+s->nr; r++) {
off = r->off; off = r->off;
siz = r->siz; siz = r->siz;
if(off < 0 || off+(siz&~Rbig) > s->np) {
diag("%s: invalid relocation %d+%d not in [%d,%d)", s->name, off, siz&~Rbig, 0, s->np);
continue;
}
if(r->sym != S && (r->sym->type == 0 || r->sym->type == SXREF)) {
diag("%s: not defined", r->sym->name);
continue;
}
if(r->type >= 256)
continue;
if(r->sym != S && (r->sym->type == SDYNIMPORT || r->sym->dynimpname != nil))
diag("unhandled relocation for %s (rtype %d)", r->sym->name, r->type);
if(r->sym != S && !r->sym->reachable)
diag("unreachable sym in relocation: %s %s", s->name, r->sym->name);
switch(r->type) { switch(r->type) {
default: default:
o = 0;
if(archreloc(r, s, &o) < 0)
diag("unknown reloc %d", r->type); diag("unknown reloc %d", r->type);
break;
case D_ADDR: case D_ADDR:
o = symaddr(r->sym); o = symaddr(r->sym) + r->add;
break; break;
case D_PCREL: case D_PCREL:
o = symaddr(r->sym) - (s->value + r->off + r->siz); o = symaddr(r->sym) + r->add - (s->value + r->off + r->siz);
break; break;
case D_SIZE: case D_SIZE:
o = r->sym->size; o = r->sym->size + r->add;
break; break;
} }
o += r->add; //print("relocate %s %p %s => %p %p %p %p [%p]\n", s->name, s->value+off, r->sym ? r->sym->name : "<nil>", (void*)symaddr(r->sym), (void*)s->value, (void*)r->off, (void*)r->siz, (void*)o);
switch(siz) { switch(siz) {
default: default:
diag("bad reloc size %#ux", siz); cursym = s;
diag("bad reloc size %#ux for %s", siz, r->sym->name);
case 4 + Rbig: case 4 + Rbig:
fl = o; fl = o;
s->p[off] = fl>>24; s->p[off] = fl>>24;
...@@ -212,6 +236,33 @@ reloc(void) ...@@ -212,6 +236,33 @@ reloc(void)
relocsym(s); relocsym(s);
} }
void
dynrelocsym(Sym *s)
{
Reloc *r;
for(r=s->r; r<s->r+s->nr; r++)
if(r->sym->type == SDYNIMPORT || r->type >= 256)
adddynrel(s, r);
}
void
dynreloc(void)
{
Sym *s;
if(debug['v'])
Bprint(&bso, "%5.2f reloc\n", cputime());
Bflush(&bso);
for(s=textp; s!=S; s=s->next)
dynrelocsym(s);
for(s=datap; s!=S; s=s->next)
dynrelocsym(s);
if(iself)
elfdynhash();
}
void void
symgrow(Sym *s, int32 siz) symgrow(Sym *s, int32 siz)
{ {
...@@ -324,11 +375,13 @@ blk(Sym *allsym, int32 addr, int32 size) ...@@ -324,11 +375,13 @@ blk(Sym *allsym, int32 addr, int32 size)
uchar *p, *ep; uchar *p, *ep;
for(sym = allsym; sym != nil; sym = sym->next) for(sym = allsym; sym != nil; sym = sym->next)
if(sym->value >= addr) if(!(sym->type&SSUB) && sym->value >= addr)
break; break;
eaddr = addr+size; eaddr = addr+size;
for(; sym != nil; sym = sym->next) { for(; sym != nil; sym = sym->next) {
if(sym->type&SSUB)
continue;
if(sym->value >= eaddr) if(sym->value >= eaddr)
break; break;
if(sym->value < addr) { if(sym->value < addr) {
...@@ -411,7 +464,7 @@ codeblk(int32 addr, int32 size) ...@@ -411,7 +464,7 @@ codeblk(int32 addr, int32 size)
continue; continue;
} }
Bprint(&bso, "%.6llux\t%-20s | %P\n", (vlong)addr, sym->name, p); Bprint(&bso, "%.6llux\t%-20s | %P\n", sym->value, sym->name, p);
for(p = p->link; p != P; p = p->link) { for(p = p->link; p != P; p = p->link) {
if(p->link != P) if(p->link != P)
epc = p->link->pc; epc = p->link->pc;
...@@ -522,6 +575,7 @@ adduintxx(Sym *s, uint64 v, int wid) ...@@ -522,6 +575,7 @@ adduintxx(Sym *s, uint64 v, int wid)
r = s->size; r = s->size;
s->size += wid; s->size += wid;
symgrow(s, s->size); symgrow(s, s->size);
assert(r+wid <= s->size);
fl = v; fl = v;
cast = (uchar*)&fl; cast = (uchar*)&fl;
switch(wid) { switch(wid) {
...@@ -571,7 +625,7 @@ adduint64(Sym *s, uint64 v) ...@@ -571,7 +625,7 @@ adduint64(Sym *s, uint64 v)
} }
vlong vlong
addaddr(Sym *s, Sym *t) addaddrplus(Sym *s, Sym *t, int32 add)
{ {
vlong i; vlong i;
Reloc *r; Reloc *r;
...@@ -587,9 +641,37 @@ addaddr(Sym *s, Sym *t) ...@@ -587,9 +641,37 @@ addaddr(Sym *s, Sym *t)
r->off = i; r->off = i;
r->siz = PtrSize; r->siz = PtrSize;
r->type = D_ADDR; r->type = D_ADDR;
r->add = add;
return i;
}
vlong
addpcrelplus(Sym *s, Sym *t, int32 add)
{
vlong i;
Reloc *r;
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
i = s->size;
s->size += 4;
symgrow(s, s->size);
r = addrel(s);
r->sym = t;
r->off = i;
r->add = add;
r->type = D_PCREL;
r->siz = 4;
return i; return i;
} }
vlong
addaddr(Sym *s, Sym *t)
{
return addaddrplus(s, t, 0);
}
vlong vlong
addsize(Sym *s, Sym *t) addsize(Sym *s, Sym *t)
{ {
...@@ -615,7 +697,7 @@ dodata(void) ...@@ -615,7 +697,7 @@ dodata(void)
{ {
int32 h, t, datsize; int32 h, t, datsize;
Section *sect; Section *sect;
Sym *s, *last; Sym *s, *last, **l;
if(debug['v']) if(debug['v'])
Bprint(&bso, "%5.2f dodata\n", cputime()); Bprint(&bso, "%5.2f dodata\n", cputime());
...@@ -645,6 +727,24 @@ dodata(void) ...@@ -645,6 +727,24 @@ dodata(void)
diag("%s: initialize bounds (%lld < %d)", diag("%s: initialize bounds (%lld < %d)",
s->name, s->size, s->np); s->name, s->size, s->np);
} }
/*
* now that we have the datap list, but before we start
* to assign addresses, record all the necessary
* dynamic relocations. these will grow the relocation
* symbol, which is itself data.
*/
dynreloc();
/* some symbols may no longer belong in datap (Mach-O) */
for(l=&datap; (s=*l) != nil; ) {
if(s->type <= STEXT || SXREF <= s->type)
*l = s->next;
else
l = &s->next;
}
*l = nil;
datap = datsort(datap); datap = datsort(datap);
/* /*
...@@ -714,6 +814,40 @@ dodata(void) ...@@ -714,6 +814,40 @@ dodata(void)
sect->len = datsize - sect->vaddr; sect->len = datsize - sect->vaddr;
} }
// assign addresses to text
void
textaddress(void)
{
uvlong va;
Prog *p;
Section *sect;
Sym *sym, *sub;
addsection(&segtext, ".text", 05);
// Assign PCs in text segment.
// Could parallelize, by assigning to text
// and then letting threads copy down, but probably not worth it.
sect = segtext.sect;
va = INITTEXT;
sect->vaddr = va;
for(sym = textp; sym != nil; sym = sym->next) {
if(sym->type & SSUB)
continue;
sym->value = 0;
for(sub = sym; sub != S; sub = sub->sub) {
sub->value += va;
for(p = sub->text; p != P; p = p->link)
p->pc += sub->value;
}
if(sym->size == 0 && sym->sub != S) {
cursym = sym;
}
va += sym->size;
}
sect->len = va - sect->vaddr;
}
// assign addresses // assign addresses
void void
address(void) address(void)
...@@ -723,7 +857,7 @@ address(void) ...@@ -723,7 +857,7 @@ address(void)
uvlong va; uvlong va;
va = INITTEXT; va = INITTEXT;
segtext.rwx = 05; segtext.rwx = 07;
segtext.vaddr = va; segtext.vaddr = va;
segtext.fileoff = HEADR; segtext.fileoff = HEADR;
for(s=segtext.sect; s != nil; s=s->next) { for(s=segtext.sect; s != nil; s=s->next) {
......
...@@ -164,8 +164,7 @@ newElfPhdr(void) ...@@ -164,8 +164,7 @@ newElfPhdr(void)
{ {
ElfPhdr *e; ElfPhdr *e;
e = malloc(sizeof *e); e = mal(sizeof *e);
memset(e, 0, sizeof *e);
if (hdr.phnum >= NSECT) if (hdr.phnum >= NSECT)
diag("too many phdrs"); diag("too many phdrs");
else else
...@@ -189,8 +188,7 @@ newElfShdr(vlong name) ...@@ -189,8 +188,7 @@ newElfShdr(vlong name)
{ {
ElfShdr *e; ElfShdr *e;
e = malloc(sizeof *e); e = mal(sizeof *e);
memset(e, 0, sizeof *e);
e->name = name; e->name = name;
if (hdr.shnum >= NSECT) { if (hdr.shnum >= NSECT) {
diag("too many shdrs"); diag("too many shdrs");
...@@ -332,17 +330,25 @@ elfinterp(ElfShdr *sh, uint64 startva, char *p) ...@@ -332,17 +330,25 @@ elfinterp(ElfShdr *sh, uint64 startva, char *p)
sh->size = n; sh->size = n;
} }
extern int nelfsym;
void void
elfdynhash(int nsym) elfdynhash(void)
{ {
Sym *s, *sy; Sym *s, *sy;
int i, h, nbucket, b; int i, h, nbucket, b;
uchar *pc; uchar *pc;
uint32 hc, g; uint32 hc, g;
uint32 *chain, *buckets; uint32 *chain, *buckets;
int nsym;
char *name;
if(!iself)
return;
nsym = nelfsym;
s = lookup(".hash", 0); s = lookup(".hash", 0);
s->type = SELFDATA; // TODO: rodata s->type = SELFDATA;
s->reachable = 1; s->reachable = 1;
i = nsym; i = nsym;
...@@ -353,17 +359,24 @@ elfdynhash(int nsym) ...@@ -353,17 +359,24 @@ elfdynhash(int nsym)
} }
chain = malloc(nsym * sizeof(uint32)); chain = malloc(nsym * sizeof(uint32));
memset(chain, 0, nsym * sizeof(uint32));
buckets = malloc(nbucket * sizeof(uint32)); buckets = malloc(nbucket * sizeof(uint32));
if(chain == nil || buckets == nil) {
cursym = nil;
diag("out of memory");
errorexit();
}
memset(chain, 0, nsym * sizeof(uint32));
memset(buckets, 0, nbucket * sizeof(uint32)); memset(buckets, 0, nbucket * sizeof(uint32));
i = 1;
for(h = 0; h<NHASH; h++) { for(h = 0; h<NHASH; h++) {
for(sy=hash[h]; sy!=S; sy=sy->hash) { for(sy=hash[h]; sy!=S; sy=sy->hash) {
if (!sy->reachable || (sy->type != STEXT && sy->type != SDATA && sy->type != SBSS) || sy->dynimpname == nil) if (sy->dynid <= 0)
continue; continue;
hc = 0; hc = 0;
for(pc = (uchar*)sy->dynimpname; *pc; pc++) { name = sy->dynimpname;
if(name == nil)
name = sy->name;
for(pc = (uchar*)name; *pc; pc++) {
hc = (hc<<4) + *pc; hc = (hc<<4) + *pc;
g = hc & 0xf0000000; g = hc & 0xf0000000;
hc ^= g >> 24; hc ^= g >> 24;
...@@ -371,9 +384,8 @@ elfdynhash(int nsym) ...@@ -371,9 +384,8 @@ elfdynhash(int nsym)
} }
b = hc % nbucket; b = hc % nbucket;
chain[i] = buckets[b]; chain[sy->dynid] = buckets[b];
buckets[b] = i; buckets[b] = sy->dynid;
i++;
} }
} }
...@@ -386,6 +398,8 @@ elfdynhash(int nsym) ...@@ -386,6 +398,8 @@ elfdynhash(int nsym)
free(chain); free(chain);
free(buckets); free(buckets);
elfwritedynent(lookup(".dynamic", 0), DT_NULL, 0);
} }
ElfPhdr* ElfPhdr*
......
...@@ -266,6 +266,10 @@ expandpkg(char *t0, char *pkg) ...@@ -266,6 +266,10 @@ expandpkg(char *t0, char *pkg)
// use malloc, not mal, so that caller can free // use malloc, not mal, so that caller can free
w0 = malloc(strlen(t0) + strlen(pkg)*n); w0 = malloc(strlen(t0) + strlen(pkg)*n);
if(w0 == nil) {
diag("out of memory");
errorexit();
}
w = w0; w = w0;
for(p=t=t0; (p=strstr(p, "\"\".")) != nil; p=t) { for(p=t=t0; (p=strstr(p, "\"\".")) != nil; p=t) {
memmove(w, t, p - t); memmove(w, t, p - t);
...@@ -443,11 +447,20 @@ loaddynimport(char *file, char *pkg, char *p, int n) ...@@ -443,11 +447,20 @@ loaddynimport(char *file, char *pkg, char *p, int n)
*strchr(name, ' ') = 0; *strchr(name, ' ') = 0;
*strchr(def, ' ') = 0; *strchr(def, ' ') = 0;
name = expandpkg(name, pkg); if(strcmp(name, "_") == 0 && strcmp(def, "_") == 0) {
// allow #pragma dynimport _ _ "foo.so"
// to force a link of foo.so.
adddynlib(lib);
continue;
}
name = expandpkg(name, pkg);
s = lookup(name, 0); s = lookup(name, 0);
if(s->type == 0 || s->type == SXREF) {
s->dynimplib = lib; s->dynimplib = lib;
s->dynimpname = def; s->dynimpname = def;
s->type = SDYNIMPORT;
}
} }
return; return;
...@@ -547,6 +560,10 @@ mark(Sym *s) ...@@ -547,6 +560,10 @@ mark(Sym *s)
mark(s->r[i].sym); mark(s->r[i].sym);
if(s->gotype) if(s->gotype)
mark(s->gotype); mark(s->gotype);
if(s->sub)
mark(s->sub);
if(s->outer)
mark(s->outer);
} }
static char* static char*
......
...@@ -374,32 +374,38 @@ out: ...@@ -374,32 +374,38 @@ out:
void void
ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence) ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
{ {
static int files; char *line;
static char **filen; int n, c1, c2, c3, c4;
char **nfilen, *line; uint32 magic;
int i, n, c1, c2, c3;
vlong import0, import1, eof; vlong import0, import1, eof;
char src[1024]; char src[1024];
eof = Boffset(f) + len; eof = Boffset(f) + len;
src[0] = '\0'; src[0] = '\0';
// don't load individual object more than once. pn = strdup(pn);
// happens with import of .6 files because of loop in xresolv.
// doesn't happen with .a because SYMDEF is consulted
// first to decide whether each individual object file is needed.
for(i=0; i<files; i++)
if(strcmp(filen[i], pn) == 0)
return;
if((files&15) == 0){ USED(c4);
nfilen = malloc((files+16)*sizeof(char*)); USED(magic);
memmove(nfilen, filen, files*sizeof(char*));
free(filen); c1 = Bgetc(f);
filen = nfilen; c2 = Bgetc(f);
c3 = Bgetc(f);
c4 = Bgetc(f);
Bungetc(f);
Bungetc(f);
Bungetc(f);
Bungetc(f);
magic = c1<<24 | c2<<16 | c3<<8 | c4;
if(magic == 0x7f454c46) { // \x7F E L F
ldelf(f, pkg, len, pn);
return;
}
if((magic&~1) == 0xfeedface || (magic&~0x01000000) == 0xcefaedfe) {
ldmacho(f, pkg, len, pn);
return;
} }
pn = strdup(pn);
filen[files++] = pn;
/* check the header */ /* check the header */
line = Brdline(f, '\n'); line = Brdline(f, '\n');
...@@ -471,6 +477,9 @@ lookup(char *symb, int v) ...@@ -471,6 +477,9 @@ lookup(char *symb, int v)
if(debug['v'] > 1) if(debug['v'] > 1)
Bprint(&bso, "lookup %s\n", symb); Bprint(&bso, "lookup %s\n", symb);
s->dynid = -1;
s->plt = -1;
s->got = -1;
s->name = mal(l + 1); s->name = mal(l + 1);
memmove(s->name, symb, l); memmove(s->name, symb, l);
...@@ -766,11 +775,19 @@ mal(uint32 n) ...@@ -766,11 +775,19 @@ mal(uint32 n)
n = (n+7)&~7; n = (n+7)&~7;
if(n > NHUNK) { if(n > NHUNK) {
v = malloc(n); v = malloc(n);
if(v == nil) {
diag("out of memory");
errorexit();
}
memset(v, 0, n); memset(v, 0, n);
return v; return v;
} }
if(n > nhunk) { if(n > nhunk) {
hunk = malloc(NHUNK); hunk = malloc(NHUNK);
if(hunk == nil) {
diag("out of memory");
errorexit();
}
nhunk = NHUNK; nhunk = NHUNK;
} }
...@@ -1013,3 +1030,42 @@ mkfwd(void) ...@@ -1013,3 +1030,42 @@ mkfwd(void)
} }
} }
} }
uint16
le16(uchar *b)
{
return b[0] | b[1]<<8;
}
uint32
le32(uchar *b)
{
return b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24;
}
uint64
le64(uchar *b)
{
return le32(b) | (uint64)le32(b+4)<<32;
}
uint16
be16(uchar *b)
{
return b[0]<<8 | b[1];
}
uint32
be32(uchar *b)
{
return b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
}
uint64
be64(uchar *b)
{
return (uvlong)be32(b)<<32 | be32(b+4);
}
Endian be = { be16, be32, be64 };
Endian le = { le16, le32, le64 };
...@@ -125,8 +125,11 @@ void pclntab(void); ...@@ -125,8 +125,11 @@ void pclntab(void);
void symtab(void); void symtab(void);
void Lflag(char *arg); void Lflag(char *arg);
void usage(void); void usage(void);
void adddynrel(Sym*, Reloc*);
void ldobj1(Biobuf *f, char*, int64 len, char *pn); void ldobj1(Biobuf *f, char*, int64 len, char *pn);
void ldobj(Biobuf*, char*, int64, char*, int); void ldobj(Biobuf*, char*, int64, char*, int);
void ldelf(Biobuf*, char*, int64, char*);
void ldmacho(Biobuf*, char*, int64, char*);
void ldpkg(Biobuf*, char*, int64, char*, int); void ldpkg(Biobuf*, char*, int64, char*, int);
void mark(Sym *s); void mark(Sym *s);
void mkfwd(void); void mkfwd(void);
...@@ -144,6 +147,8 @@ vlong addstring(Sym*, char*); ...@@ -144,6 +147,8 @@ vlong addstring(Sym*, char*);
vlong adduint32(Sym*, uint32); vlong adduint32(Sym*, uint32);
vlong adduint64(Sym*, uint64); vlong adduint64(Sym*, uint64);
vlong addaddr(Sym*, Sym*); vlong addaddr(Sym*, Sym*);
vlong addaddrplus(Sym*, Sym*, int32);
vlong addpcrelplus(Sym*, Sym*, int32);
vlong addsize(Sym*, Sym*); vlong addsize(Sym*, Sym*);
vlong adduint8(Sym*, uint8); vlong adduint8(Sym*, uint8);
vlong adduint16(Sym*, uint16); vlong adduint16(Sym*, uint16);
...@@ -152,13 +157,34 @@ void asmelfsym64(void); ...@@ -152,13 +157,34 @@ void asmelfsym64(void);
void strnput(char*, int); void strnput(char*, int);
void dodata(void); void dodata(void);
void address(void); void address(void);
void textaddress(void);
void genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*)); void genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*));
vlong datoff(vlong); vlong datoff(vlong);
void adddynlib(char*);
int archreloc(Reloc*, Sym*, vlong*);
int pathchar(void); int pathchar(void);
void* mal(uint32); void* mal(uint32);
void unmal(void*, uint32); void unmal(void*, uint32);
void mywhatsys(void); void mywhatsys(void);
int rbyoff(const void*, const void*);
uint16 le16(uchar*);
uint32 le32(uchar*);
uint64 le64(uchar*);
uint16 be16(uchar*);
uint32 be32(uchar*);
uint64 be64(uchar*);
typedef struct Endian Endian;
struct Endian
{
uint16 (*e16)(uchar*);
uint32 (*e32)(uchar*);
uint64 (*e64)(uchar*);
};
extern Endian be, le;
// relocation size bits // relocation size bits
enum { enum {
......
This diff is collapsed.
...@@ -18,6 +18,8 @@ struct MachoSect { ...@@ -18,6 +18,8 @@ struct MachoSect {
uint32 reloc; uint32 reloc;
uint32 nreloc; uint32 nreloc;
uint32 flag; uint32 flag;
uint32 res1;
uint32 res2;
}; };
typedef struct MachoSeg MachoSeg; typedef struct MachoSeg MachoSeg;
...@@ -70,6 +72,20 @@ enum { ...@@ -70,6 +72,20 @@ enum {
MACHO32SYMSIZE = 12, MACHO32SYMSIZE = 12,
MACHO64SYMSIZE = 16, MACHO64SYMSIZE = 16,
MACHO_X86_64_RELOC_UNSIGNED = 0,
MACHO_X86_64_RELOC_SIGNED = 1,
MACHO_X86_64_RELOC_BRANCH = 2,
MACHO_X86_64_RELOC_GOT_LOAD = 3,
MACHO_X86_64_RELOC_GOT = 4,
MACHO_X86_64_RELOC_SUBTRACTOR = 5,
MACHO_X86_64_RELOC_SIGNED_1 = 6,
MACHO_X86_64_RELOC_SIGNED_2 = 7,
MACHO_X86_64_RELOC_SIGNED_4 = 8,
MACHO_GENERIC_RELOC_VANILLA = 0,
MACHO_FAKE_GOTPCREL = 100,
}; };
void domacho(void); void domacho(void);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment