mirror of
https://github.com/golang/go
synced 2024-11-22 06:34:40 -07:00
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
This commit is contained in:
parent
9042c2ce68
commit
f5690004c2
@ -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\
|
||||||
|
512
src/cmd/6l/asm.c
512
src/cmd/6l/asm.c
@ -138,6 +138,8 @@ enum {
|
|||||||
ElfStrShstrtab,
|
ElfStrShstrtab,
|
||||||
ElfStrSymtab,
|
ElfStrSymtab,
|
||||||
ElfStrStrtab,
|
ElfStrStrtab,
|
||||||
|
ElfStrRelaPlt,
|
||||||
|
ElfStrPlt,
|
||||||
NElfStr
|
NElfStr
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -159,11 +161,391 @@ needlib(char *name)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int nelfsym = 1;
|
||||||
|
|
||||||
|
static void adddynsym(Sym*);
|
||||||
|
static void addpltsym(Sym*);
|
||||||
|
static void addgotsym(Sym*);
|
||||||
|
|
||||||
|
void
|
||||||
|
adddynrel(Sym *s, Reloc *r)
|
||||||
|
{
|
||||||
|
Sym *targ, *rela, *got;
|
||||||
|
|
||||||
|
targ = r->sym;
|
||||||
|
cursym = s;
|
||||||
|
|
||||||
|
switch(r->type) {
|
||||||
|
default:
|
||||||
|
if(r->type >= 256) {
|
||||||
|
diag("unexpected relocation type %d", r->type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Handle relocations found in ELF object files.
|
||||||
|
case 256 + R_X86_64_PC32:
|
||||||
|
if(targ->dynimpname)
|
||||||
|
diag("unexpected R_X86_64_PC32 relocation for dynamic symbol %s", targ->name);
|
||||||
|
if(targ->type == 0 || targ->type == SXREF)
|
||||||
|
diag("unknown symbol %s in pcrel", targ->name);
|
||||||
|
r->type = D_PCREL;
|
||||||
|
r->add += 4;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 256 + R_X86_64_PLT32:
|
||||||
|
addpltsym(targ);
|
||||||
|
r->type = D_PCREL;
|
||||||
|
r->sym = lookup(".plt", 0);
|
||||||
|
r->add += 4;
|
||||||
|
r->add += targ->plt;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 256 + R_X86_64_GOTPCREL:
|
||||||
|
addgotsym(targ);
|
||||||
|
r->type = D_PCREL;
|
||||||
|
r->sym = lookup(".got", 0);
|
||||||
|
r->add += 4;
|
||||||
|
r->add += targ->got;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 256 + R_X86_64_64:
|
||||||
|
if(targ->dynimpname)
|
||||||
|
diag("unexpected R_X86_64_64 relocation for dynamic symbol %s", targ->name);
|
||||||
|
r->type = D_ADDR;
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Handle relocations found in Mach-O object files.
|
||||||
|
case 512 + MACHO_X86_64_RELOC_UNSIGNED*2 + 0:
|
||||||
|
case 512 + MACHO_X86_64_RELOC_SIGNED*2 + 0:
|
||||||
|
case 512 + MACHO_X86_64_RELOC_BRANCH*2 + 0:
|
||||||
|
// TODO: What is the difference between all these?
|
||||||
|
r->type = D_ADDR;
|
||||||
|
if(targ->dynimpname)
|
||||||
|
diag("unexpected reloc for dynamic symbol %s", targ->name);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 512 + MACHO_X86_64_RELOC_BRANCH*2 + 1:
|
||||||
|
if(targ->dynimpname) {
|
||||||
|
addpltsym(targ);
|
||||||
|
r->sym = lookup(".plt", 0);
|
||||||
|
r->add = targ->plt;
|
||||||
|
r->type = D_PCREL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// fall through
|
||||||
|
case 512 + MACHO_X86_64_RELOC_UNSIGNED*2 + 1:
|
||||||
|
case 512 + MACHO_X86_64_RELOC_SIGNED*2 + 1:
|
||||||
|
case 512 + MACHO_X86_64_RELOC_SIGNED_1*2 + 1:
|
||||||
|
case 512 + MACHO_X86_64_RELOC_SIGNED_2*2 + 1:
|
||||||
|
case 512 + MACHO_X86_64_RELOC_SIGNED_4*2 + 1:
|
||||||
|
r->type = D_PCREL;
|
||||||
|
if(targ->dynimpname)
|
||||||
|
diag("unexpected pc-relative reloc for dynamic symbol %s", targ->name);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 512 + MACHO_X86_64_RELOC_GOT_LOAD*2 + 1:
|
||||||
|
case 512 + MACHO_X86_64_RELOC_GOT*2 + 1:
|
||||||
|
// TODO: What is the difference between these two?
|
||||||
|
addgotsym(targ);
|
||||||
|
r->type = D_PCREL;
|
||||||
|
r->sym = lookup(".got", 0);
|
||||||
|
r->add += targ->got;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle references to ELF symbols from our own object files.
|
||||||
|
if(targ->dynimpname == nil)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch(r->type) {
|
||||||
|
case D_PCREL:
|
||||||
|
addpltsym(targ);
|
||||||
|
r->sym = lookup(".plt", 0);
|
||||||
|
r->add = targ->plt;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case D_ADDR:
|
||||||
|
if(s->type != SDATA)
|
||||||
|
break;
|
||||||
|
if(iself) {
|
||||||
|
adddynsym(targ);
|
||||||
|
rela = lookup(".rela", 0);
|
||||||
|
addaddrplus(rela, s, r->off);
|
||||||
|
if(r->siz == 8)
|
||||||
|
adduint64(rela, ELF64_R_INFO(targ->dynid, R_X86_64_64));
|
||||||
|
else
|
||||||
|
adduint64(rela, ELF64_R_INFO(targ->dynid, R_X86_64_32));
|
||||||
|
adduint64(rela, r->add);
|
||||||
|
r->type = 256; // ignore during relocsym
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(HEADTYPE == 6 && s->size == PtrSize && r->off == 0) {
|
||||||
|
// Mach-O relocations are a royal pain to lay out.
|
||||||
|
// They use a compact stateful bytecode representation
|
||||||
|
// that is too much bother to deal with.
|
||||||
|
// Instead, interpret the C declaration
|
||||||
|
// void *_Cvar_stderr = &stderr;
|
||||||
|
// as making _Cvar_stderr the name of a GOT entry
|
||||||
|
// for stderr. This is separate from the usual GOT entry,
|
||||||
|
// just in case the C code assigns to the variable,
|
||||||
|
// and of course it only works for single pointers,
|
||||||
|
// but we only need to support cgo and that's all it needs.
|
||||||
|
adddynsym(targ);
|
||||||
|
got = lookup(".got", 0);
|
||||||
|
s->type = got->type | SSUB;
|
||||||
|
s->outer = got;
|
||||||
|
s->sub = got->sub;
|
||||||
|
got->sub = s;
|
||||||
|
s->value = got->size;
|
||||||
|
adduint64(got, 0);
|
||||||
|
adduint32(lookup(".linkedit.got", 0), targ->dynid);
|
||||||
|
r->type = 256; // ignore during relocsym
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cursym = s;
|
||||||
|
diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ->name, r->type, targ->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
archreloc(Reloc *r, Sym *s, vlong *val)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
elfsetupplt(void)
|
||||||
|
{
|
||||||
|
Sym *plt, *got;
|
||||||
|
|
||||||
|
plt = lookup(".plt", 0);
|
||||||
|
got = lookup(".got.plt", 0);
|
||||||
|
if(plt->size == 0) {
|
||||||
|
// pushq got+8(IP)
|
||||||
|
adduint8(plt, 0xff);
|
||||||
|
adduint8(plt, 0x35);
|
||||||
|
addpcrelplus(plt, got, 8);
|
||||||
|
|
||||||
|
// jmpq got+16(IP)
|
||||||
|
adduint8(plt, 0xff);
|
||||||
|
adduint8(plt, 0x25);
|
||||||
|
addpcrelplus(plt, got, 16);
|
||||||
|
|
||||||
|
// nopl 0(AX)
|
||||||
|
adduint32(plt, 0x00401f0f);
|
||||||
|
|
||||||
|
// assume got->size == 0 too
|
||||||
|
addaddrplus(got, lookup(".dynamic", 0), 0);
|
||||||
|
adduint64(got, 0);
|
||||||
|
adduint64(got, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
addpltsym(Sym *s)
|
||||||
|
{
|
||||||
|
if(s->plt >= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
adddynsym(s);
|
||||||
|
|
||||||
|
if(iself) {
|
||||||
|
Sym *plt, *got, *rela;
|
||||||
|
|
||||||
|
plt = lookup(".plt", 0);
|
||||||
|
got = lookup(".got.plt", 0);
|
||||||
|
rela = lookup(".rela.plt", 0);
|
||||||
|
if(plt->size == 0)
|
||||||
|
elfsetupplt();
|
||||||
|
|
||||||
|
// jmpq *got+size(IP)
|
||||||
|
adduint8(plt, 0xff);
|
||||||
|
adduint8(plt, 0x25);
|
||||||
|
addpcrelplus(plt, got, got->size);
|
||||||
|
|
||||||
|
// add to got: pointer to current pos in plt
|
||||||
|
addaddrplus(got, plt, plt->size);
|
||||||
|
|
||||||
|
// pushq $x
|
||||||
|
adduint8(plt, 0x68);
|
||||||
|
adduint32(plt, (got->size-24-8)/8);
|
||||||
|
|
||||||
|
// jmpq .plt
|
||||||
|
adduint8(plt, 0xe9);
|
||||||
|
adduint32(plt, -(plt->size+4));
|
||||||
|
|
||||||
|
// rela
|
||||||
|
addaddrplus(rela, got, got->size-8);
|
||||||
|
adduint64(rela, ELF64_R_INFO(s->dynid, R_X86_64_JMP_SLOT));
|
||||||
|
adduint64(rela, 0);
|
||||||
|
|
||||||
|
s->plt = plt->size - 16;
|
||||||
|
} else if(HEADTYPE == 6) { // Mach-O
|
||||||
|
// To do lazy symbol lookup right, we're supposed
|
||||||
|
// to tell the dynamic loader which library each
|
||||||
|
// symbol comes from and format the link info
|
||||||
|
// section just so. I'm too lazy (ha!) to do that
|
||||||
|
// so for now we'll just use non-lazy pointers,
|
||||||
|
// which don't need to be told which library to use.
|
||||||
|
//
|
||||||
|
// http://networkpx.blogspot.com/2009/09/about-lcdyldinfoonly-command.html
|
||||||
|
// has details about what we're avoiding.
|
||||||
|
|
||||||
|
Sym *plt;
|
||||||
|
|
||||||
|
addgotsym(s);
|
||||||
|
plt = lookup(".plt", 0);
|
||||||
|
|
||||||
|
adduint32(lookup(".linkedit.plt", 0), s->dynid);
|
||||||
|
|
||||||
|
// jmpq *got+size(IP)
|
||||||
|
s->plt = plt->size;
|
||||||
|
|
||||||
|
adduint8(plt, 0xff);
|
||||||
|
adduint8(plt, 0x25);
|
||||||
|
addpcrelplus(plt, lookup(".got", 0), s->got);
|
||||||
|
} else {
|
||||||
|
diag("addpltsym: unsupported binary format");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
addgotsym(Sym *s)
|
||||||
|
{
|
||||||
|
Sym *got, *rela, *indir;
|
||||||
|
|
||||||
|
if(s->got >= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
adddynsym(s);
|
||||||
|
got = lookup(".got", 0);
|
||||||
|
s->got = got->size;
|
||||||
|
adduint64(got, 0);
|
||||||
|
|
||||||
|
if(iself) {
|
||||||
|
rela = lookup(".rela", 0);
|
||||||
|
addaddrplus(rela, got, s->got);
|
||||||
|
adduint64(rela, ELF64_R_INFO(s->dynid, R_X86_64_GLOB_DAT));
|
||||||
|
adduint64(rela, 0);
|
||||||
|
} else if(HEADTYPE == 6) { // Mach-O
|
||||||
|
adduint32(lookup(".linkedit.got", 0), s->dynid);
|
||||||
|
} else {
|
||||||
|
diag("addgotsym: unsupported binary format");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
adddynsym(Sym *s)
|
||||||
|
{
|
||||||
|
Sym *d, *str;
|
||||||
|
int t;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
if(s->dynid >= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(iself) {
|
||||||
|
s->dynid = nelfsym++;
|
||||||
|
|
||||||
|
d = lookup(".dynsym", 0);
|
||||||
|
name = s->dynimpname;
|
||||||
|
if(name == nil)
|
||||||
|
name = s->name;
|
||||||
|
adduint32(d, addstring(lookup(".dynstr", 0), name));
|
||||||
|
/* type */
|
||||||
|
t = STB_GLOBAL << 4;
|
||||||
|
if(s->dynexport && s->type == STEXT)
|
||||||
|
t |= STT_FUNC;
|
||||||
|
else
|
||||||
|
t |= STT_OBJECT;
|
||||||
|
adduint8(d, t);
|
||||||
|
|
||||||
|
/* reserved */
|
||||||
|
adduint8(d, 0);
|
||||||
|
|
||||||
|
/* section where symbol is defined */
|
||||||
|
if(!s->dynexport && s->dynimpname != nil)
|
||||||
|
adduint16(d, SHN_UNDEF);
|
||||||
|
else {
|
||||||
|
switch(s->type) {
|
||||||
|
default:
|
||||||
|
case STEXT:
|
||||||
|
t = 11;
|
||||||
|
break;
|
||||||
|
case SRODATA:
|
||||||
|
t = 12;
|
||||||
|
break;
|
||||||
|
case SDATA:
|
||||||
|
t = 13;
|
||||||
|
break;
|
||||||
|
case SBSS:
|
||||||
|
t = 14;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
adduint16(d, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* value */
|
||||||
|
if(s->type == SDYNIMPORT)
|
||||||
|
adduint64(d, 0);
|
||||||
|
else
|
||||||
|
addaddr(d, s);
|
||||||
|
|
||||||
|
/* size of object */
|
||||||
|
adduint64(d, 0);
|
||||||
|
|
||||||
|
if(!s->dynexport && s->dynimplib && needlib(s->dynimplib)) {
|
||||||
|
elfwritedynent(lookup(".dynamic", 0), DT_NEEDED,
|
||||||
|
addstring(lookup(".dynstr", 0), s->dynimplib));
|
||||||
|
}
|
||||||
|
} else if(HEADTYPE == 6) {
|
||||||
|
// Mach-o symbol nlist64
|
||||||
|
d = lookup(".dynsym", 0);
|
||||||
|
name = s->dynimpname;
|
||||||
|
if(name == nil)
|
||||||
|
name = s->name;
|
||||||
|
s->dynid = d->size/16;
|
||||||
|
// darwin still puts _ prefixes on all C symbols
|
||||||
|
str = lookup(".dynstr", 0);
|
||||||
|
adduint32(d, str->size);
|
||||||
|
adduint8(str, '_');
|
||||||
|
addstring(str, name);
|
||||||
|
adduint8(d, 0x01); // type - N_EXT - external symbol
|
||||||
|
adduint8(d, 0); // section
|
||||||
|
adduint16(d, 0); // desc
|
||||||
|
adduint64(d, 0); // value
|
||||||
|
} else {
|
||||||
|
diag("adddynsym: unsupported binary format");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
adddynlib(char *lib)
|
||||||
|
{
|
||||||
|
Sym *s;
|
||||||
|
|
||||||
|
if(!needlib(lib))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(iself) {
|
||||||
|
s = lookup(".dynstr", 0);
|
||||||
|
if(s->size == 0)
|
||||||
|
addstring(s, "");
|
||||||
|
elfwritedynent(lookup(".dynamic", 0), DT_NEEDED, addstring(s, lib));
|
||||||
|
} else if(HEADTYPE == 6) { // Mach-O
|
||||||
|
machoadddynlib(lib);
|
||||||
|
} else {
|
||||||
|
diag("adddynlib: unsupported binary format");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
doelf(void)
|
doelf(void)
|
||||||
{
|
{
|
||||||
Sym *s, *shstrtab, *dynamic, *dynstr, *d;
|
Sym *s, *shstrtab, *dynstr;
|
||||||
int h, nsym, t;
|
|
||||||
|
|
||||||
if(HEADTYPE != 7 && HEADTYPE != 9)
|
if(HEADTYPE != 7 && HEADTYPE != 9)
|
||||||
return;
|
return;
|
||||||
@ -198,6 +580,8 @@ doelf(void)
|
|||||||
elfstr[ElfStrDynsym] = addstring(shstrtab, ".dynsym");
|
elfstr[ElfStrDynsym] = addstring(shstrtab, ".dynsym");
|
||||||
elfstr[ElfStrDynstr] = addstring(shstrtab, ".dynstr");
|
elfstr[ElfStrDynstr] = addstring(shstrtab, ".dynstr");
|
||||||
elfstr[ElfStrRela] = addstring(shstrtab, ".rela");
|
elfstr[ElfStrRela] = addstring(shstrtab, ".rela");
|
||||||
|
elfstr[ElfStrRelaPlt] = addstring(shstrtab, ".rela.plt");
|
||||||
|
elfstr[ElfStrPlt] = addstring(shstrtab, ".plt");
|
||||||
|
|
||||||
/* dynamic symbol table - first entry all zeros */
|
/* dynamic symbol table - first entry all zeros */
|
||||||
s = lookup(".dynsym", 0);
|
s = lookup(".dynsym", 0);
|
||||||
@ -209,6 +593,7 @@ doelf(void)
|
|||||||
s = lookup(".dynstr", 0);
|
s = lookup(".dynstr", 0);
|
||||||
s->type = SELFDATA;
|
s->type = SELFDATA;
|
||||||
s->reachable = 1;
|
s->reachable = 1;
|
||||||
|
if(s->size == 0)
|
||||||
addstring(s, "");
|
addstring(s, "");
|
||||||
dynstr = s;
|
dynstr = s;
|
||||||
|
|
||||||
@ -220,94 +605,35 @@ doelf(void)
|
|||||||
/* global offset table */
|
/* global offset table */
|
||||||
s = lookup(".got", 0);
|
s = lookup(".got", 0);
|
||||||
s->reachable = 1;
|
s->reachable = 1;
|
||||||
s->type = SELFDATA;
|
s->type = SDATA; // writable, so not SELFDATA
|
||||||
|
|
||||||
/* got.plt - ??? */
|
|
||||||
s = lookup(".got.plt", 0);
|
|
||||||
s->reachable = 1;
|
|
||||||
s->type = SELFDATA;
|
|
||||||
|
|
||||||
/* hash */
|
/* hash */
|
||||||
s = lookup(".hash", 0);
|
s = lookup(".hash", 0);
|
||||||
s->reachable = 1;
|
s->reachable = 1;
|
||||||
s->type = SELFDATA;
|
s->type = SELFDATA;
|
||||||
|
|
||||||
|
s = lookup(".got.plt", 0);
|
||||||
|
s->reachable = 1;
|
||||||
|
s->type = SDATA; // writable, not SELFDATA
|
||||||
|
|
||||||
|
s = lookup(".plt", 0);
|
||||||
|
s->reachable = 1;
|
||||||
|
s->type = SELFDATA;
|
||||||
|
|
||||||
|
elfsetupplt();
|
||||||
|
|
||||||
|
s = lookup(".rela.plt", 0);
|
||||||
|
s->reachable = 1;
|
||||||
|
s->type = SELFDATA;
|
||||||
|
|
||||||
/* define dynamic elf table */
|
/* define dynamic elf table */
|
||||||
s = lookup(".dynamic", 0);
|
s = lookup(".dynamic", 0);
|
||||||
s->reachable = 1;
|
s->reachable = 1;
|
||||||
s->type = SELFDATA;
|
s->type = SELFDATA;
|
||||||
dynamic = s;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* relocation entries for dynimport symbols
|
|
||||||
*/
|
|
||||||
nsym = 1; // sym 0 is reserved
|
|
||||||
for(h=0; h<NHASH; h++) {
|
|
||||||
for(s=hash[h]; s!=S; s=s->hash) {
|
|
||||||
if(!s->reachable || (s->type != STEXT && s->type != SDATA && s->type != SBSS) || s->dynimpname == nil)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if(!s->dynexport) {
|
|
||||||
d = lookup(".rela", 0);
|
|
||||||
addaddr(d, s);
|
|
||||||
adduint64(d, ELF64_R_INFO(nsym, R_X86_64_64));
|
|
||||||
adduint64(d, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsym++;
|
|
||||||
|
|
||||||
d = lookup(".dynsym", 0);
|
|
||||||
adduint32(d, addstring(lookup(".dynstr", 0), s->dynimpname));
|
|
||||||
/* type */
|
|
||||||
t = STB_GLOBAL << 4;
|
|
||||||
if(s->dynexport && s->type == STEXT)
|
|
||||||
t |= STT_FUNC;
|
|
||||||
else
|
|
||||||
t |= STT_OBJECT;
|
|
||||||
adduint8(d, t);
|
|
||||||
|
|
||||||
/* reserved */
|
|
||||||
adduint8(d, 0);
|
|
||||||
|
|
||||||
/* section where symbol is defined */
|
|
||||||
if(!s->dynexport)
|
|
||||||
adduint16(d, SHN_UNDEF);
|
|
||||||
else {
|
|
||||||
switch(s->type) {
|
|
||||||
default:
|
|
||||||
case STEXT:
|
|
||||||
t = 9;
|
|
||||||
break;
|
|
||||||
case SDATA:
|
|
||||||
t = 10;
|
|
||||||
break;
|
|
||||||
case SBSS:
|
|
||||||
t = 11;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
adduint16(d, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* value */
|
|
||||||
if(!s->dynexport)
|
|
||||||
adduint64(d, 0);
|
|
||||||
else
|
|
||||||
addaddr(d, s);
|
|
||||||
|
|
||||||
/* size of object */
|
|
||||||
adduint64(d, 0);
|
|
||||||
|
|
||||||
if(!s->dynexport && needlib(s->dynimplib))
|
|
||||||
elfwritedynent(dynamic, DT_NEEDED, addstring(dynstr, s->dynimplib));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
elfdynhash(nsym);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* .dynamic table
|
* .dynamic table
|
||||||
*/
|
*/
|
||||||
s = dynamic;
|
|
||||||
elfwritedynentsym(s, DT_HASH, lookup(".hash", 0));
|
elfwritedynentsym(s, DT_HASH, lookup(".hash", 0));
|
||||||
elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0));
|
elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0));
|
||||||
elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE);
|
elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE);
|
||||||
@ -318,6 +644,11 @@ doelf(void)
|
|||||||
elfwritedynent(s, DT_RELAENT, ELF64RELASIZE);
|
elfwritedynent(s, DT_RELAENT, ELF64RELASIZE);
|
||||||
if(rpath)
|
if(rpath)
|
||||||
elfwritedynent(s, DT_RUNPATH, addstring(dynstr, rpath));
|
elfwritedynent(s, DT_RUNPATH, addstring(dynstr, rpath));
|
||||||
|
|
||||||
|
elfwritedynentsym(s, DT_PLTGOT, lookup(".got.plt", 0));
|
||||||
|
elfwritedynent(s, DT_PLTREL, DT_RELA);
|
||||||
|
elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rela.plt", 0));
|
||||||
|
elfwritedynentsym(s, DT_JMPREL, lookup(".rela.plt", 0));
|
||||||
elfwritedynent(s, DT_NULL, 0);
|
elfwritedynent(s, DT_NULL, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -398,10 +729,10 @@ asmb(void)
|
|||||||
case 9:
|
case 9:
|
||||||
debug['8'] = 1; /* 64-bit addresses */
|
debug['8'] = 1; /* 64-bit addresses */
|
||||||
/* index of elf text section; needed by asmelfsym, double-checked below */
|
/* index of elf text section; needed by asmelfsym, double-checked below */
|
||||||
/* !debug['d'] causes 8 extra sections before the .text section */
|
/* !debug['d'] causes extra sections before the .text section */
|
||||||
elftextsh = 1;
|
elftextsh = 1;
|
||||||
if(!debug['d'])
|
if(!debug['d'])
|
||||||
elftextsh += 8;
|
elftextsh += 10;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -579,6 +910,22 @@ asmb(void)
|
|||||||
sh->addralign = 1;
|
sh->addralign = 1;
|
||||||
shsym(sh, lookup(".dynstr", 0));
|
shsym(sh, lookup(".dynstr", 0));
|
||||||
|
|
||||||
|
sh = newElfShdr(elfstr[ElfStrRelaPlt]);
|
||||||
|
sh->type = SHT_RELA;
|
||||||
|
sh->flags = SHF_ALLOC;
|
||||||
|
sh->entsize = ELF64RELASIZE;
|
||||||
|
sh->addralign = 8;
|
||||||
|
sh->link = dynsym;
|
||||||
|
sh->info = eh->shnum; // .plt
|
||||||
|
shsym(sh, lookup(".rela.plt", 0));
|
||||||
|
|
||||||
|
sh = newElfShdr(elfstr[ElfStrPlt]);
|
||||||
|
sh->type = SHT_PROGBITS;
|
||||||
|
sh->flags = SHF_ALLOC+SHF_EXECINSTR;
|
||||||
|
sh->entsize = 16;
|
||||||
|
sh->addralign = 4;
|
||||||
|
shsym(sh, lookup(".plt", 0));
|
||||||
|
|
||||||
sh = newElfShdr(elfstr[ElfStrHash]);
|
sh = newElfShdr(elfstr[ElfStrHash]);
|
||||||
sh->type = SHT_HASH;
|
sh->type = SHT_HASH;
|
||||||
sh->flags = SHF_ALLOC;
|
sh->flags = SHF_ALLOC;
|
||||||
@ -744,12 +1091,12 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
|
|||||||
|
|
||||||
for(h=0; h<NHASH; h++) {
|
for(h=0; h<NHASH; h++) {
|
||||||
for(s=hash[h]; s!=S; s=s->hash) {
|
for(s=hash[h]; s!=S; s=s->hash) {
|
||||||
switch(s->type) {
|
switch(s->type&~SSUB) {
|
||||||
case SCONST:
|
case SCONST:
|
||||||
case SRODATA:
|
case SRODATA:
|
||||||
case SDATA:
|
case SDATA:
|
||||||
case SELFDATA:
|
case SELFDATA:
|
||||||
case SMACHO:
|
case SMACHOGOT:
|
||||||
if(!s->reachable)
|
if(!s->reachable)
|
||||||
continue;
|
continue;
|
||||||
put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
|
put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
|
||||||
@ -769,6 +1116,9 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(s = textp; s != nil; s = s->next) {
|
for(s = textp; s != nil; s = s->next) {
|
||||||
|
if(s->text == nil)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* filenames first */
|
/* filenames first */
|
||||||
for(a=s->autom; a; a=a->link)
|
for(a=s->autom; a; a=a->link)
|
||||||
if(a->type == D_FILE)
|
if(a->type == D_FILE)
|
||||||
@ -777,7 +1127,7 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
|
|||||||
if(a->type == D_FILE1)
|
if(a->type == D_FILE1)
|
||||||
put(nil, a->asym->name, 'Z', a->aoffset, 0, 0, 0);
|
put(nil, a->asym->name, 'Z', a->aoffset, 0, 0, 0);
|
||||||
|
|
||||||
put(s, s->name, 'T', 0, s->size, s->version, s->gotype);
|
put(s, s->name, 'T', s->value, s->size, s->version, s->gotype);
|
||||||
|
|
||||||
/* frame, auto and param after */
|
/* frame, auto and param after */
|
||||||
put(nil, ".frame", 'm', s->text->to.offset+8, 0, 0, 0);
|
put(nil, ".frame", 'm', s->text->to.offset+8, 0, 0, 0);
|
||||||
|
@ -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
|
|||||||
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
|
|||||||
/* 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
|
|||||||
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=\
|
|||||||
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\
|
||||||
|
504
src/cmd/8l/asm.c
504
src/cmd/8l/asm.c
@ -126,6 +126,10 @@ enum {
|
|||||||
ElfStrGosymtab,
|
ElfStrGosymtab,
|
||||||
ElfStrGopclntab,
|
ElfStrGopclntab,
|
||||||
ElfStrShstrtab,
|
ElfStrShstrtab,
|
||||||
|
ElfStrSymtab,
|
||||||
|
ElfStrStrtab,
|
||||||
|
ElfStrRelPlt,
|
||||||
|
ElfStrPlt,
|
||||||
NElfStr
|
NElfStr
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -147,11 +151,380 @@ needlib(char *name)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int nelfsym = 1;
|
||||||
|
|
||||||
|
static void adddynsym(Sym*);
|
||||||
|
static void addpltsym(Sym*);
|
||||||
|
static void addgotsym(Sym*);
|
||||||
|
|
||||||
|
void
|
||||||
|
adddynrel(Sym *s, Reloc *r)
|
||||||
|
{
|
||||||
|
Sym *targ, *rel, *got;
|
||||||
|
|
||||||
|
targ = r->sym;
|
||||||
|
cursym = s;
|
||||||
|
|
||||||
|
switch(r->type) {
|
||||||
|
default:
|
||||||
|
if(r->type >= 256) {
|
||||||
|
diag("unexpected relocation type %d", r->type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Handle relocations found in ELF object files.
|
||||||
|
case 256 + R_386_PC32:
|
||||||
|
if(targ->dynimpname)
|
||||||
|
diag("unexpected R_386_PC32 relocation for dynamic symbol %s", targ->name);
|
||||||
|
if(targ->type == 0 || targ->type == SXREF)
|
||||||
|
diag("unknown symbol %s in pcrel", targ->name);
|
||||||
|
r->type = D_PCREL;
|
||||||
|
r->add += 4;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 256 + R_386_PLT32:
|
||||||
|
addpltsym(targ);
|
||||||
|
r->type = D_PCREL;
|
||||||
|
r->sym = lookup(".plt", 0);
|
||||||
|
r->add += 4;
|
||||||
|
r->add += targ->plt;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 256 + R_386_GOT32:
|
||||||
|
addgotsym(targ);
|
||||||
|
r->type = D_CONST; // write r->add during relocsym
|
||||||
|
r->sym = S;
|
||||||
|
r->add += targ->got;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 256 + R_386_GOTOFF:
|
||||||
|
r->type = D_GOTOFF;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 256 + R_386_GOTPC:
|
||||||
|
r->type = D_PCREL;
|
||||||
|
r->sym = lookup(".got", 0);
|
||||||
|
r->add += 4;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 256 + R_386_32:
|
||||||
|
if(targ->dynimpname)
|
||||||
|
diag("unexpected R_386_32 relocation for dynamic symbol %s", targ->name);
|
||||||
|
r->type = D_ADDR;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 512 + MACHO_GENERIC_RELOC_VANILLA*2 + 0:
|
||||||
|
r->type = D_ADDR;
|
||||||
|
if(targ->dynimpname)
|
||||||
|
diag("unexpected reloc for dynamic symbol %s", targ->name);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 512 + MACHO_GENERIC_RELOC_VANILLA*2 + 1:
|
||||||
|
if(targ->dynimpname) {
|
||||||
|
addpltsym(targ);
|
||||||
|
r->sym = lookup(".plt", 0);
|
||||||
|
r->add = targ->plt;
|
||||||
|
r->type = D_PCREL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
r->type = D_PCREL;
|
||||||
|
if(targ->dynimpname)
|
||||||
|
diag("unexpected pc-relative reloc for dynamic symbol %s", targ->name);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 512 + MACHO_FAKE_GOTPCREL:
|
||||||
|
addgotsym(targ);
|
||||||
|
r->sym = lookup(".got", 0);
|
||||||
|
r->add += targ->got;
|
||||||
|
r->type = D_PCREL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle references to ELF symbols from our own object files.
|
||||||
|
if(targ->dynimpname == nil)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch(r->type) {
|
||||||
|
case D_PCREL:
|
||||||
|
addpltsym(targ);
|
||||||
|
r->sym = lookup(".plt", 0);
|
||||||
|
r->add = targ->plt;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case D_ADDR:
|
||||||
|
if(s->type != SDATA)
|
||||||
|
break;
|
||||||
|
if(iself) {
|
||||||
|
adddynsym(targ);
|
||||||
|
rel = lookup(".rel", 0);
|
||||||
|
addaddrplus(rel, s, r->off);
|
||||||
|
adduint32(rel, ELF32_R_INFO(targ->dynid, R_386_32));
|
||||||
|
r->type = D_CONST; // write r->add during relocsym
|
||||||
|
r->sym = S;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(HEADTYPE == 6 && s->size == PtrSize && r->off == 0) {
|
||||||
|
// Mach-O relocations are a royal pain to lay out.
|
||||||
|
// They use a compact stateful bytecode representation
|
||||||
|
// that is too much bother to deal with.
|
||||||
|
// Instead, interpret the C declaration
|
||||||
|
// void *_Cvar_stderr = &stderr;
|
||||||
|
// as making _Cvar_stderr the name of a GOT entry
|
||||||
|
// for stderr. This is separate from the usual GOT entry,
|
||||||
|
// just in case the C code assigns to the variable,
|
||||||
|
// and of course it only works for single pointers,
|
||||||
|
// but we only need to support cgo and that's all it needs.
|
||||||
|
adddynsym(targ);
|
||||||
|
got = lookup(".got", 0);
|
||||||
|
s->type = got->type | SSUB;
|
||||||
|
s->outer = got;
|
||||||
|
s->sub = got->sub;
|
||||||
|
got->sub = s;
|
||||||
|
s->value = got->size;
|
||||||
|
adduint32(got, 0);
|
||||||
|
adduint32(lookup(".linkedit.got", 0), targ->dynid);
|
||||||
|
r->type = 256; // ignore during relocsym
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cursym = s;
|
||||||
|
diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ->name, r->type, targ->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
elfsetupplt(void)
|
||||||
|
{
|
||||||
|
Sym *plt, *got;
|
||||||
|
|
||||||
|
plt = lookup(".plt", 0);
|
||||||
|
got = lookup(".got.plt", 0);
|
||||||
|
if(plt->size == 0) {
|
||||||
|
// pushl got+4
|
||||||
|
adduint8(plt, 0xff);
|
||||||
|
adduint8(plt, 0x35);
|
||||||
|
addaddrplus(plt, got, 4);
|
||||||
|
|
||||||
|
// jmp *got+8
|
||||||
|
adduint8(plt, 0xff);
|
||||||
|
adduint8(plt, 0x25);
|
||||||
|
addaddrplus(plt, got, 8);
|
||||||
|
|
||||||
|
// zero pad
|
||||||
|
adduint32(plt, 0);
|
||||||
|
|
||||||
|
// assume got->size == 0 too
|
||||||
|
addaddrplus(got, lookup(".dynamic", 0), 0);
|
||||||
|
adduint32(got, 0);
|
||||||
|
adduint32(got, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
archreloc(Reloc *r, Sym *s, vlong *val)
|
||||||
|
{
|
||||||
|
switch(r->type) {
|
||||||
|
case D_CONST:
|
||||||
|
*val = r->add;
|
||||||
|
return 0;
|
||||||
|
case D_GOTOFF:
|
||||||
|
*val = symaddr(r->sym) + r->add - symaddr(lookup(".got", 0));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
addpltsym(Sym *s)
|
||||||
|
{
|
||||||
|
Sym *plt, *got, *rel;
|
||||||
|
|
||||||
|
if(s->plt >= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
adddynsym(s);
|
||||||
|
|
||||||
|
if(iself) {
|
||||||
|
plt = lookup(".plt", 0);
|
||||||
|
got = lookup(".got.plt", 0);
|
||||||
|
rel = lookup(".rel.plt", 0);
|
||||||
|
if(plt->size == 0)
|
||||||
|
elfsetupplt();
|
||||||
|
|
||||||
|
// jmpq *got+size
|
||||||
|
adduint8(plt, 0xff);
|
||||||
|
adduint8(plt, 0x25);
|
||||||
|
addaddrplus(plt, got, got->size);
|
||||||
|
|
||||||
|
// add to got: pointer to current pos in plt
|
||||||
|
addaddrplus(got, plt, plt->size);
|
||||||
|
|
||||||
|
// pushl $x
|
||||||
|
adduint8(plt, 0x68);
|
||||||
|
adduint32(plt, rel->size);
|
||||||
|
|
||||||
|
// jmp .plt
|
||||||
|
adduint8(plt, 0xe9);
|
||||||
|
adduint32(plt, -(plt->size+4));
|
||||||
|
|
||||||
|
// rel
|
||||||
|
addaddrplus(rel, got, got->size-4);
|
||||||
|
adduint32(rel, ELF32_R_INFO(s->dynid, R_386_JMP_SLOT));
|
||||||
|
|
||||||
|
s->plt = plt->size - 16;
|
||||||
|
} else if(HEADTYPE == 6) { // Mach-O
|
||||||
|
// Same laziness as in 6l.
|
||||||
|
|
||||||
|
Sym *plt;
|
||||||
|
|
||||||
|
plt = lookup(".plt", 0);
|
||||||
|
|
||||||
|
addgotsym(s);
|
||||||
|
|
||||||
|
adduint32(lookup(".linkedit.plt", 0), s->dynid);
|
||||||
|
|
||||||
|
// jmpq *got+size(IP)
|
||||||
|
s->plt = plt->size;
|
||||||
|
|
||||||
|
adduint8(plt, 0xff);
|
||||||
|
adduint8(plt, 0x25);
|
||||||
|
addaddrplus(plt, lookup(".got", 0), s->got);
|
||||||
|
} else {
|
||||||
|
diag("addpltsym: unsupported binary format");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
addgotsym(Sym *s)
|
||||||
|
{
|
||||||
|
Sym *got, *rel;
|
||||||
|
|
||||||
|
if(s->got >= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
adddynsym(s);
|
||||||
|
got = lookup(".got", 0);
|
||||||
|
s->got = got->size;
|
||||||
|
adduint32(got, 0);
|
||||||
|
|
||||||
|
if(iself) {
|
||||||
|
rel = lookup(".rel", 0);
|
||||||
|
addaddrplus(rel, got, s->got);
|
||||||
|
adduint32(rel, ELF32_R_INFO(s->dynid, R_386_GLOB_DAT));
|
||||||
|
} else if(HEADTYPE == 6) { // Mach-O
|
||||||
|
adduint32(lookup(".linkedit.got", 0), s->dynid);
|
||||||
|
} else {
|
||||||
|
diag("addgotsym: unsupported binary format");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
adddynsym(Sym *s)
|
||||||
|
{
|
||||||
|
Sym *d, *str;
|
||||||
|
int t;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
if(s->dynid >= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(iself) {
|
||||||
|
s->dynid = nelfsym++;
|
||||||
|
|
||||||
|
d = lookup(".dynsym", 0);
|
||||||
|
|
||||||
|
/* name */
|
||||||
|
name = s->dynimpname;
|
||||||
|
if(name == nil)
|
||||||
|
name = s->name;
|
||||||
|
adduint32(d, addstring(lookup(".dynstr", 0), name));
|
||||||
|
|
||||||
|
/* value */
|
||||||
|
if(s->type == SDYNIMPORT)
|
||||||
|
adduint32(d, 0);
|
||||||
|
else
|
||||||
|
addaddr(d, s);
|
||||||
|
|
||||||
|
/* size */
|
||||||
|
adduint32(d, 0);
|
||||||
|
|
||||||
|
/* type */
|
||||||
|
t = STB_GLOBAL << 4;
|
||||||
|
if(s->dynexport && s->type == STEXT)
|
||||||
|
t |= STT_FUNC;
|
||||||
|
else
|
||||||
|
t |= STT_OBJECT;
|
||||||
|
adduint8(d, t);
|
||||||
|
adduint8(d, 0);
|
||||||
|
|
||||||
|
/* shndx */
|
||||||
|
if(!s->dynexport && s->dynimpname != nil)
|
||||||
|
adduint16(d, SHN_UNDEF);
|
||||||
|
else {
|
||||||
|
switch(s->type) {
|
||||||
|
default:
|
||||||
|
case STEXT:
|
||||||
|
t = 11;
|
||||||
|
break;
|
||||||
|
case SRODATA:
|
||||||
|
t = 12;
|
||||||
|
break;
|
||||||
|
case SDATA:
|
||||||
|
t = 13;
|
||||||
|
break;
|
||||||
|
case SBSS:
|
||||||
|
t = 14;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
adduint16(d, t);
|
||||||
|
}
|
||||||
|
} else if(HEADTYPE == 6) {
|
||||||
|
// Mach-O symbol nlist32
|
||||||
|
d = lookup(".dynsym", 0);
|
||||||
|
name = s->dynimpname;
|
||||||
|
if(name == nil)
|
||||||
|
name = s->name;
|
||||||
|
s->dynid = d->size/12;
|
||||||
|
// darwin still puts _ prefixes on all C symbols
|
||||||
|
str = lookup(".dynstr", 0);
|
||||||
|
adduint32(d, str->size);
|
||||||
|
adduint8(str, '_');
|
||||||
|
addstring(str, name);
|
||||||
|
adduint8(d, 0x01); // type - N_EXT - external symbol
|
||||||
|
adduint8(d, 0); // section
|
||||||
|
adduint16(d, 0); // desc
|
||||||
|
adduint32(d, 0); // value
|
||||||
|
} else {
|
||||||
|
diag("adddynsym: unsupported binary format");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
adddynlib(char *lib)
|
||||||
|
{
|
||||||
|
Sym *s;
|
||||||
|
|
||||||
|
if(!needlib(lib))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(iself) {
|
||||||
|
s = lookup(".dynstr", 0);
|
||||||
|
if(s->size == 0)
|
||||||
|
addstring(s, "");
|
||||||
|
elfwritedynent(lookup(".dynamic", 0), DT_NEEDED, addstring(s, lib));
|
||||||
|
} else if(HEADTYPE == 6) { // Mach-O
|
||||||
|
machoadddynlib(lib);
|
||||||
|
} else {
|
||||||
|
diag("adddynlib: unsupported binary format");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
doelf(void)
|
doelf(void)
|
||||||
{
|
{
|
||||||
Sym *s, *shstrtab, *dynamic, *dynstr, *d;
|
Sym *s, *shstrtab, *dynstr;
|
||||||
int h, nsym, t;
|
|
||||||
|
|
||||||
if(!iself)
|
if(!iself)
|
||||||
return;
|
return;
|
||||||
@ -186,6 +559,8 @@ doelf(void)
|
|||||||
elfstr[ElfStrDynsym] = addstring(shstrtab, ".dynsym");
|
elfstr[ElfStrDynsym] = addstring(shstrtab, ".dynsym");
|
||||||
elfstr[ElfStrDynstr] = addstring(shstrtab, ".dynstr");
|
elfstr[ElfStrDynstr] = addstring(shstrtab, ".dynstr");
|
||||||
elfstr[ElfStrRel] = addstring(shstrtab, ".rel");
|
elfstr[ElfStrRel] = addstring(shstrtab, ".rel");
|
||||||
|
elfstr[ElfStrRelPlt] = addstring(shstrtab, ".rel.plt");
|
||||||
|
elfstr[ElfStrPlt] = addstring(shstrtab, ".plt");
|
||||||
|
|
||||||
/* interpreter string */
|
/* interpreter string */
|
||||||
s = lookup(".interp", 0);
|
s = lookup(".interp", 0);
|
||||||
@ -202,6 +577,7 @@ doelf(void)
|
|||||||
s = lookup(".dynstr", 0);
|
s = lookup(".dynstr", 0);
|
||||||
s->reachable = 1;
|
s->reachable = 1;
|
||||||
s->type = SELFDATA;
|
s->type = SELFDATA;
|
||||||
|
if(s->size == 0)
|
||||||
addstring(s, "");
|
addstring(s, "");
|
||||||
dynstr = s;
|
dynstr = s;
|
||||||
|
|
||||||
@ -213,88 +589,36 @@ doelf(void)
|
|||||||
/* global offset table */
|
/* global offset table */
|
||||||
s = lookup(".got", 0);
|
s = lookup(".got", 0);
|
||||||
s->reachable = 1;
|
s->reachable = 1;
|
||||||
s->type = SELFDATA;
|
s->type = SDATA; // writable, so not SELFDATA
|
||||||
|
|
||||||
/* got.plt - ??? */
|
/* hash */
|
||||||
s = lookup(".got.plt", 0);
|
s = lookup(".hash", 0);
|
||||||
s->reachable = 1;
|
s->reachable = 1;
|
||||||
s->type = SELFDATA;
|
s->type = SELFDATA;
|
||||||
|
|
||||||
|
/* got.plt */
|
||||||
|
s = lookup(".got.plt", 0);
|
||||||
|
s->reachable = 1;
|
||||||
|
s->type = SDATA; // writable, so not SELFDATA
|
||||||
|
|
||||||
|
s = lookup(".plt", 0);
|
||||||
|
s->reachable = 1;
|
||||||
|
s->type = SELFDATA;
|
||||||
|
|
||||||
|
s = lookup(".rel.plt", 0);
|
||||||
|
s->reachable = 1;
|
||||||
|
s->type = SELFDATA;
|
||||||
|
|
||||||
|
elfsetupplt();
|
||||||
|
|
||||||
/* define dynamic elf table */
|
/* define dynamic elf table */
|
||||||
s = lookup(".dynamic", 0);
|
s = lookup(".dynamic", 0);
|
||||||
s->reachable = 1;
|
s->reachable = 1;
|
||||||
s->type = SELFDATA;
|
s->type = SELFDATA;
|
||||||
dynamic = s;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* relocation entries for dynimport symbols
|
|
||||||
*/
|
|
||||||
nsym = 1; // sym 0 is reserved
|
|
||||||
for(h=0; h<NHASH; h++) {
|
|
||||||
for(s=hash[h]; s!=S; s=s->hash) {
|
|
||||||
if(!s->reachable || (s->type != STEXT && s->type != SDATA && s->type != SBSS) || s->dynimpname == nil)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if(!s->dynexport) {
|
|
||||||
d = lookup(".rel", 0);
|
|
||||||
addaddr(d, s);
|
|
||||||
adduint32(d, ELF32_R_INFO(nsym, R_386_32));
|
|
||||||
}
|
|
||||||
|
|
||||||
nsym++;
|
|
||||||
|
|
||||||
d = lookup(".dynsym", 0);
|
|
||||||
adduint32(d, addstring(lookup(".dynstr", 0), s->dynimpname));
|
|
||||||
/* value */
|
|
||||||
if(!s->dynexport)
|
|
||||||
adduint32(d, 0);
|
|
||||||
else
|
|
||||||
addaddr(d, s);
|
|
||||||
|
|
||||||
/* size of object */
|
|
||||||
adduint32(d, 0);
|
|
||||||
|
|
||||||
/* type */
|
|
||||||
t = STB_GLOBAL << 4;
|
|
||||||
if(s->dynexport && s->type == STEXT)
|
|
||||||
t |= STT_FUNC;
|
|
||||||
else
|
|
||||||
t |= STT_OBJECT;
|
|
||||||
adduint8(d, t);
|
|
||||||
|
|
||||||
/* reserved */
|
|
||||||
adduint8(d, 0);
|
|
||||||
|
|
||||||
/* section where symbol is defined */
|
|
||||||
if(!s->dynexport)
|
|
||||||
adduint16(d, SHN_UNDEF);
|
|
||||||
else {
|
|
||||||
switch(s->type) {
|
|
||||||
default:
|
|
||||||
case STEXT:
|
|
||||||
t = 9;
|
|
||||||
break;
|
|
||||||
case SDATA:
|
|
||||||
t = 10;
|
|
||||||
break;
|
|
||||||
case SBSS:
|
|
||||||
t = 11;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
adduint16(d, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!s->dynexport && needlib(s->dynimplib))
|
|
||||||
elfwritedynent(dynamic, DT_NEEDED, addstring(dynstr, s->dynimplib));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
elfdynhash(nsym);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* .dynamic table
|
* .dynamic table
|
||||||
*/
|
*/
|
||||||
s = dynamic;
|
|
||||||
elfwritedynentsym(s, DT_HASH, lookup(".hash", 0));
|
elfwritedynentsym(s, DT_HASH, lookup(".hash", 0));
|
||||||
elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0));
|
elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0));
|
||||||
elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE);
|
elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE);
|
||||||
@ -305,6 +629,10 @@ doelf(void)
|
|||||||
elfwritedynent(s, DT_RELENT, ELF32RELSIZE);
|
elfwritedynent(s, DT_RELENT, ELF32RELSIZE);
|
||||||
if(rpath)
|
if(rpath)
|
||||||
elfwritedynent(s, DT_RUNPATH, addstring(dynstr, rpath));
|
elfwritedynent(s, DT_RUNPATH, addstring(dynstr, rpath));
|
||||||
|
elfwritedynentsym(s, DT_PLTGOT, lookup(".got.plt", 0));
|
||||||
|
elfwritedynent(s, DT_PLTREL, DT_REL);
|
||||||
|
elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rel.plt", 0));
|
||||||
|
elfwritedynentsym(s, DT_JMPREL, lookup(".rel.plt", 0));
|
||||||
elfwritedynent(s, DT_NULL, 0);
|
elfwritedynent(s, DT_NULL, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -365,6 +693,14 @@ asmb(void)
|
|||||||
if(HEADTYPE == 6)
|
if(HEADTYPE == 6)
|
||||||
machlink = domacholink();
|
machlink = domacholink();
|
||||||
|
|
||||||
|
if(iself) {
|
||||||
|
/* index of elf text section; needed by asmelfsym, double-checked below */
|
||||||
|
/* !debug['d'] causes extra sections before the .text section */
|
||||||
|
elftextsh = 1;
|
||||||
|
if(!debug['d'])
|
||||||
|
elftextsh += 10;
|
||||||
|
}
|
||||||
|
|
||||||
symsize = 0;
|
symsize = 0;
|
||||||
spsize = 0;
|
spsize = 0;
|
||||||
lcsize = 0;
|
lcsize = 0;
|
||||||
@ -636,6 +972,22 @@ asmb(void)
|
|||||||
sh->addralign = 1;
|
sh->addralign = 1;
|
||||||
shsym(sh, lookup(".dynstr", 0));
|
shsym(sh, lookup(".dynstr", 0));
|
||||||
|
|
||||||
|
sh = newElfShdr(elfstr[ElfStrRelPlt]);
|
||||||
|
sh->type = SHT_REL;
|
||||||
|
sh->flags = SHF_ALLOC;
|
||||||
|
sh->entsize = ELF32RELSIZE;
|
||||||
|
sh->addralign = 4;
|
||||||
|
sh->link = dynsym;
|
||||||
|
sh->info = eh->shnum; // .plt
|
||||||
|
shsym(sh, lookup(".rel.plt", 0));
|
||||||
|
|
||||||
|
sh = newElfShdr(elfstr[ElfStrPlt]);
|
||||||
|
sh->type = SHT_PROGBITS;
|
||||||
|
sh->flags = SHF_ALLOC+SHF_EXECINSTR;
|
||||||
|
sh->entsize = 4;
|
||||||
|
sh->addralign = 4;
|
||||||
|
shsym(sh, lookup(".plt", 0));
|
||||||
|
|
||||||
sh = newElfShdr(elfstr[ElfStrHash]);
|
sh = newElfShdr(elfstr[ElfStrHash]);
|
||||||
sh->type = SHT_HASH;
|
sh->type = SHT_HASH;
|
||||||
sh->flags = SHF_ALLOC;
|
sh->flags = SHF_ALLOC;
|
||||||
@ -682,6 +1034,8 @@ asmb(void)
|
|||||||
ph->flags = PF_W+PF_R;
|
ph->flags = PF_W+PF_R;
|
||||||
ph->align = 4;
|
ph->align = 4;
|
||||||
|
|
||||||
|
if(elftextsh != eh->shnum)
|
||||||
|
diag("elftextsh = %d, want %d", elftextsh, eh->shnum);
|
||||||
for(sect=segtext.sect; sect!=nil; sect=sect->next)
|
for(sect=segtext.sect; sect!=nil; sect=sect->next)
|
||||||
elfshbits(sect);
|
elfshbits(sect);
|
||||||
for(sect=segrodata.sect; sect!=nil; sect=sect->next)
|
for(sect=segrodata.sect; sect!=nil; sect=sect->next)
|
||||||
@ -814,12 +1168,13 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
|
|||||||
|
|
||||||
for(h=0; h<NHASH; h++) {
|
for(h=0; h<NHASH; h++) {
|
||||||
for(s=hash[h]; s!=S; s=s->hash) {
|
for(s=hash[h]; s!=S; s=s->hash) {
|
||||||
switch(s->type) {
|
switch(s->type&~SSUB) {
|
||||||
case SCONST:
|
case SCONST:
|
||||||
case SRODATA:
|
case SRODATA:
|
||||||
case SDATA:
|
case SDATA:
|
||||||
case SELFDATA:
|
case SELFDATA:
|
||||||
case SMACHO:
|
case SMACHO:
|
||||||
|
case SMACHOGOT:
|
||||||
case SWINDOWS:
|
case SWINDOWS:
|
||||||
if(!s->reachable)
|
if(!s->reachable)
|
||||||
continue;
|
continue;
|
||||||
@ -840,6 +1195,9 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(s = textp; s != nil; s = s->next) {
|
for(s = textp; s != nil; s = s->next) {
|
||||||
|
if(s->text == nil)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* filenames first */
|
/* filenames first */
|
||||||
for(a=s->autom; a; a=a->link)
|
for(a=s->autom; a; a=a->link)
|
||||||
if(a->type == D_FILE)
|
if(a->type == D_FILE)
|
||||||
|
@ -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
|
|||||||
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
|
|||||||
/* 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;
|
|||||||
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 @@
|
|||||||
#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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
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;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
// 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)
|
|||||||
*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)
|
|||||||
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:
|
|||||||
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.
|
|
||||||
// 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){
|
|
||||||
nfilen = malloc((files+16)*sizeof(char*));
|
|
||||||
memmove(nfilen, filen, files*sizeof(char*));
|
|
||||||
free(filen);
|
|
||||||
filen = nfilen;
|
|
||||||
}
|
|
||||||
pn = strdup(pn);
|
pn = strdup(pn);
|
||||||
filen[files++] = pn;
|
|
||||||
|
USED(c4);
|
||||||
|
USED(magic);
|
||||||
|
|
||||||
|
c1 = Bgetc(f);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/* check the header */
|
/* check the header */
|
||||||
line = Brdline(f, '\n');
|
line = Brdline(f, '\n');
|
||||||
@ -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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
|||||||
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*);
|
|||||||
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);
|
|||||||
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 {
|
||||||
|
@ -102,21 +102,12 @@ newMachoDebug(void)
|
|||||||
|
|
||||||
// Generic linking code.
|
// Generic linking code.
|
||||||
|
|
||||||
static uchar *linkdata;
|
|
||||||
static uint32 nlinkdata;
|
|
||||||
static uint32 mlinkdata;
|
|
||||||
|
|
||||||
static uchar *strtab;
|
|
||||||
static uint32 nstrtab;
|
|
||||||
static uint32 mstrtab;
|
|
||||||
|
|
||||||
struct Expsym
|
struct Expsym
|
||||||
{
|
{
|
||||||
int off;
|
int off;
|
||||||
Sym* s;
|
Sym* s;
|
||||||
} *expsym;
|
} *expsym;
|
||||||
static int nexpsym;
|
static int nexpsym;
|
||||||
static int nimpsym;
|
|
||||||
|
|
||||||
static char **dylib;
|
static char **dylib;
|
||||||
static int ndylib;
|
static int ndylib;
|
||||||
@ -199,8 +190,8 @@ machowrite(void)
|
|||||||
LPUT(t->reloc);
|
LPUT(t->reloc);
|
||||||
LPUT(t->nreloc);
|
LPUT(t->nreloc);
|
||||||
LPUT(t->flag);
|
LPUT(t->flag);
|
||||||
LPUT(0); /* reserved */
|
LPUT(t->res1); /* reserved */
|
||||||
LPUT(0); /* reserved */
|
LPUT(t->res2); /* reserved */
|
||||||
LPUT(0); /* reserved */
|
LPUT(0); /* reserved */
|
||||||
} else {
|
} else {
|
||||||
strnput(t->name, 16);
|
strnput(t->name, 16);
|
||||||
@ -212,8 +203,8 @@ machowrite(void)
|
|||||||
LPUT(t->reloc);
|
LPUT(t->reloc);
|
||||||
LPUT(t->nreloc);
|
LPUT(t->nreloc);
|
||||||
LPUT(t->flag);
|
LPUT(t->flag);
|
||||||
LPUT(0); /* reserved */
|
LPUT(t->res1); /* reserved */
|
||||||
LPUT(0); /* reserved */
|
LPUT(t->res2); /* reserved */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,147 +228,45 @@ machowrite(void)
|
|||||||
return cpos() - o1;
|
return cpos() - o1;
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
void
|
||||||
domacho(void)
|
domacho(void)
|
||||||
{
|
{
|
||||||
int h, ptrsize, t;
|
Sym *s;
|
||||||
char *p;
|
|
||||||
uchar *dat;
|
|
||||||
uint32 x;
|
|
||||||
Sym *s, *smacho;
|
|
||||||
Sym **impsym;
|
|
||||||
|
|
||||||
ptrsize = 4;
|
if(debug['d'])
|
||||||
if(macho64)
|
return;
|
||||||
ptrsize = 8;
|
|
||||||
|
|
||||||
// empirically, string table must begin with " \x00".
|
// empirically, string table must begin with " \x00".
|
||||||
if(!debug['d'])
|
s = lookup(".dynstr", 0);
|
||||||
*(char*)grow(&strtab, &nstrtab, &mstrtab, 2) = ' ';
|
s->type = SMACHODYNSTR;
|
||||||
|
s->reachable = 1;
|
||||||
|
adduint8(s, ' ');
|
||||||
|
adduint8(s, '\0');
|
||||||
|
|
||||||
impsym = nil;
|
s = lookup(".dynsym", 0);
|
||||||
for(h=0; h<NHASH; h++) {
|
s->type = SMACHODYNSYM;
|
||||||
for(s=hash[h]; s!=S; s=s->hash) {
|
|
||||||
if(!s->reachable || (s->type != STEXT && s->type != SDATA && s->type != SBSS) || s->dynimpname == nil)
|
|
||||||
continue;
|
|
||||||
if(debug['d']) {
|
|
||||||
diag("cannot use dynamic loading and -d");
|
|
||||||
errorexit();
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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] = 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expsym[nexpsym].off = nlinkdata - ptrsize;
|
|
||||||
expsym[nexpsym++].s = s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
smacho = lookup("__nl_symbol_ptr", 0);
|
|
||||||
smacho->type = SMACHO;
|
|
||||||
smacho->reachable = 1;
|
|
||||||
for(h=0; h<nimpsym; h++) {
|
|
||||||
s = impsym[h];
|
|
||||||
s->type = SMACHO | SSUB;
|
|
||||||
s->sub = smacho->sub;
|
|
||||||
smacho->sub = s;
|
|
||||||
s->value = (nexpsym+h) * ptrsize;
|
|
||||||
s->reachable = 1;
|
s->reachable = 1;
|
||||||
|
|
||||||
/* symbol table entry - darwin still puts _ prefixes on all C symbols */
|
s = lookup(".plt", 0); // will be __symbol_stub
|
||||||
x = nstrtab;
|
s->type = SMACHOPLT;
|
||||||
p = grow(&strtab, &nstrtab, &mstrtab, 1+strlen(s->dynimpname)+1);
|
s->reachable = 1;
|
||||||
*p++ = '_';
|
|
||||||
strcpy(p, s->dynimpname);
|
|
||||||
|
|
||||||
dat = grow(&linkdata, &nlinkdata, &mlinkdata, 8+ptrsize);
|
s = lookup(".got", 0); // will be __nl_symbol_ptr
|
||||||
dat[0] = x;
|
s->type = SMACHOGOT;
|
||||||
dat[1] = x>>8;
|
s->reachable = 1;
|
||||||
dat[2] = x>>16;
|
|
||||||
dat[3] = x>>24;
|
|
||||||
|
|
||||||
dat[4] = 0x01; // type: N_EXT - external symbol
|
s = lookup(".linkedit.plt", 0); // indirect table for .plt
|
||||||
|
s->type = SMACHOINDIRECTPLT;
|
||||||
|
s->reachable = 1;
|
||||||
|
|
||||||
if(needlib(s->dynimplib)) {
|
s = lookup(".linkedit.got", 0); // indirect table for .got
|
||||||
|
s->type = SMACHOINDIRECTGOT;
|
||||||
|
s->reachable = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
machoadddynlib(char *lib)
|
||||||
|
{
|
||||||
if(ndylib%32 == 0) {
|
if(ndylib%32 == 0) {
|
||||||
dylib = realloc(dylib, (ndylib+32)*sizeof dylib[0]);
|
dylib = realloc(dylib, (ndylib+32)*sizeof dylib[0]);
|
||||||
if(dylib == nil) {
|
if(dylib == nil) {
|
||||||
@ -385,70 +274,7 @@ domacho(void)
|
|||||||
errorexit();
|
errorexit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dylib[ndylib++] = s->dynimplib;
|
dylib[ndylib++] = lib;
|
||||||
}
|
|
||||||
}
|
|
||||||
free(impsym);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 ...
|
|
||||||
*/
|
|
||||||
for(x=0; x<nexpsym+nimpsym; x++) {
|
|
||||||
dat = grow(&linkdata, &nlinkdata, &mlinkdata, 4);
|
|
||||||
dat[0] = x;
|
|
||||||
dat[1] = x>>8;
|
|
||||||
dat[2] = x>>16;
|
|
||||||
dat[3] = x>>24;
|
|
||||||
}
|
|
||||||
|
|
||||||
smacho->size = (nexpsym+nimpsym) * ptrsize;
|
|
||||||
if(smacho->size == 0)
|
|
||||||
smacho->reachable = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
vlong
|
|
||||||
domacholink(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
uchar *p;
|
|
||||||
Sym *s;
|
|
||||||
uint64 val;
|
|
||||||
Sym *smacho;
|
|
||||||
|
|
||||||
smacho = lookup("__nl_symbol_ptr", 0);
|
|
||||||
|
|
||||||
linkoff = 0;
|
|
||||||
if(nlinkdata > 0 || nstrtab > 0) {
|
|
||||||
linkoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen - smacho->size, INITRND);
|
|
||||||
seek(cout, linkoff, 0);
|
|
||||||
|
|
||||||
for(i = 0; i<nexpsym; ++i) {
|
|
||||||
s = expsym[i].s;
|
|
||||||
val = s->value;
|
|
||||||
if(s->type == SXREF)
|
|
||||||
diag("export of undefined symbol %s", s->name);
|
|
||||||
if (s->type != STEXT)
|
|
||||||
val += segdata.vaddr;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ewrite(cout, linkdata, nlinkdata);
|
|
||||||
ewrite(cout, strtab, nstrtab);
|
|
||||||
}
|
|
||||||
return rnd(nlinkdata+nstrtab, INITRND);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -456,14 +282,14 @@ asmbmacho(void)
|
|||||||
{
|
{
|
||||||
vlong v, w;
|
vlong v, w;
|
||||||
vlong va;
|
vlong va;
|
||||||
int a, i, ptrsize;
|
int a, i;
|
||||||
char *pkgroot;
|
char *pkgroot;
|
||||||
MachoHdr *mh;
|
MachoHdr *mh;
|
||||||
MachoSect *msect;
|
MachoSect *msect;
|
||||||
MachoSeg *ms;
|
MachoSeg *ms;
|
||||||
MachoDebug *md;
|
MachoDebug *md;
|
||||||
MachoLoad *ml;
|
MachoLoad *ml;
|
||||||
Sym *smacho;
|
Sym *s;
|
||||||
|
|
||||||
/* apple MACH */
|
/* apple MACH */
|
||||||
va = INITTEXT - HEADR;
|
va = INITTEXT - HEADR;
|
||||||
@ -475,12 +301,10 @@ asmbmacho(void)
|
|||||||
case '6':
|
case '6':
|
||||||
mh->cpu = MACHO_CPU_AMD64;
|
mh->cpu = MACHO_CPU_AMD64;
|
||||||
mh->subcpu = MACHO_SUBCPU_X86;
|
mh->subcpu = MACHO_SUBCPU_X86;
|
||||||
ptrsize = 8;
|
|
||||||
break;
|
break;
|
||||||
case '8':
|
case '8':
|
||||||
mh->cpu = MACHO_CPU_386;
|
mh->cpu = MACHO_CPU_386;
|
||||||
mh->subcpu = MACHO_SUBCPU_X86;
|
mh->subcpu = MACHO_SUBCPU_X86;
|
||||||
ptrsize = 4;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,7 +314,7 @@ asmbmacho(void)
|
|||||||
|
|
||||||
/* text */
|
/* text */
|
||||||
v = rnd(HEADR+segtext.len, INITRND);
|
v = rnd(HEADR+segtext.len, INITRND);
|
||||||
ms = newMachoSeg("__TEXT", 1);
|
ms = newMachoSeg("__TEXT", 2);
|
||||||
ms->vaddr = va;
|
ms->vaddr = va;
|
||||||
ms->vsize = v;
|
ms->vsize = v;
|
||||||
ms->filesize = v;
|
ms->filesize = v;
|
||||||
@ -503,10 +327,20 @@ asmbmacho(void)
|
|||||||
msect->off = INITTEXT - va;
|
msect->off = INITTEXT - va;
|
||||||
msect->flag = 0x400; /* flag - some instructions */
|
msect->flag = 0x400; /* flag - some instructions */
|
||||||
|
|
||||||
|
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 */
|
||||||
|
}
|
||||||
|
|
||||||
/* data */
|
/* data */
|
||||||
smacho = lookup("__nl_symbol_ptr", 0);
|
|
||||||
w = segdata.len;
|
w = segdata.len;
|
||||||
ms = newMachoSeg("__DATA", 2+(smacho->size > 0));
|
ms = newMachoSeg("__DATA", 3);
|
||||||
ms->vaddr = va+v;
|
ms->vaddr = va+v;
|
||||||
ms->vsize = w;
|
ms->vsize = w;
|
||||||
ms->fileoffset = v;
|
ms->fileoffset = v;
|
||||||
@ -516,25 +350,18 @@ asmbmacho(void)
|
|||||||
|
|
||||||
msect = newMachoSect(ms, "__data");
|
msect = newMachoSect(ms, "__data");
|
||||||
msect->addr = va+v;
|
msect->addr = va+v;
|
||||||
msect->size = segdata.filelen - smacho->size;
|
msect->size = symaddr(lookup(".got", 0)) - msect->addr;
|
||||||
msect->off = v;
|
msect->off = v;
|
||||||
|
|
||||||
if(smacho->size > 0) {
|
s = lookup(".got", 0);
|
||||||
|
if(s->size > 0) {
|
||||||
msect = newMachoSect(ms, "__nl_symbol_ptr");
|
msect = newMachoSect(ms, "__nl_symbol_ptr");
|
||||||
msect->addr = smacho->value;
|
msect->addr = symaddr(s);
|
||||||
msect->size = smacho->size;
|
msect->size = s->size;
|
||||||
msect->off = datoff(msect->addr);
|
msect->off = datoff(msect->addr);
|
||||||
msect->align = 2;
|
msect->align = 2;
|
||||||
msect->flag = 6; /* section with nonlazy symbol pointers */
|
msect->flag = 6; /* section with nonlazy symbol pointers */
|
||||||
/*
|
msect->res1 = lookup(".linkedit.plt", 0)->size / 4; /* offset into indirect symbol table */
|
||||||
* 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");
|
msect = newMachoSect(ms, "__bss");
|
||||||
@ -562,39 +389,43 @@ asmbmacho(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!debug['d']) {
|
if(!debug['d']) {
|
||||||
int nsym;
|
Sym *s1, *s2, *s3, *s4;
|
||||||
|
|
||||||
nsym = smacho->size/ptrsize;
|
// must match domacholink below
|
||||||
|
s1 = lookup(".dynsym", 0);
|
||||||
|
s2 = lookup(".dynstr", 0);
|
||||||
|
s3 = lookup(".linkedit.plt", 0);
|
||||||
|
s4 = lookup(".linkedit.got", 0);
|
||||||
|
|
||||||
ms = newMachoSeg("__LINKEDIT", 0);
|
ms = newMachoSeg("__LINKEDIT", 0);
|
||||||
ms->vaddr = va+v+rnd(segdata.len, INITRND);
|
ms->vaddr = va+v+rnd(segdata.len, INITRND);
|
||||||
ms->vsize = nlinkdata+nstrtab;
|
ms->vsize = s1->size + s2->size + s3->size + s4->size;
|
||||||
ms->fileoffset = linkoff;
|
ms->fileoffset = linkoff;
|
||||||
ms->filesize = nlinkdata+nstrtab;
|
ms->filesize = ms->vsize;
|
||||||
ms->prot1 = 7;
|
ms->prot1 = 7;
|
||||||
ms->prot2 = 3;
|
ms->prot2 = 3;
|
||||||
|
|
||||||
ml = newMachoLoad(2, 4); /* LC_SYMTAB */
|
ml = newMachoLoad(2, 4); /* LC_SYMTAB */
|
||||||
ml->data[0] = linkoff; /* symoff */
|
ml->data[0] = linkoff; /* symoff */
|
||||||
ml->data[1] = nsym; /* nsyms */
|
ml->data[1] = s1->size / (macho64 ? 16 : 12); /* nsyms */
|
||||||
ml->data[2] = linkoff + nlinkdata; /* stroff */
|
ml->data[2] = linkoff + s1->size; /* stroff */
|
||||||
ml->data[3] = nstrtab; /* strsize */
|
ml->data[3] = s2->size; /* strsize */
|
||||||
|
|
||||||
ml = newMachoLoad(11, 18); /* LC_DYSYMTAB */
|
ml = newMachoLoad(11, 18); /* LC_DYSYMTAB */
|
||||||
ml->data[0] = 0; /* ilocalsym */
|
ml->data[0] = 0; /* ilocalsym */
|
||||||
ml->data[1] = 0; /* nlocalsym */
|
ml->data[1] = 0; /* nlocalsym */
|
||||||
ml->data[2] = 0; /* iextdefsym */
|
ml->data[2] = 0; /* iextdefsym */
|
||||||
ml->data[3] = nexpsym; /* nextdefsym */
|
ml->data[3] = 0; /* nextdefsym */ // TODO nexpsym
|
||||||
ml->data[4] = nexpsym; /* iundefsym */
|
ml->data[4] = 0; /* iundefsym */ // TODO nexpsym
|
||||||
ml->data[5] = nimpsym; /* nundefsym */
|
ml->data[5] = s1->size / (macho64 ? 16 : 12); /* nundefsym */
|
||||||
ml->data[6] = 0; /* tocoffset */
|
ml->data[6] = 0; /* tocoffset */
|
||||||
ml->data[7] = 0; /* ntoc */
|
ml->data[7] = 0; /* ntoc */
|
||||||
ml->data[8] = 0; /* modtaboff */
|
ml->data[8] = 0; /* modtaboff */
|
||||||
ml->data[9] = 0; /* nmodtab */
|
ml->data[9] = 0; /* nmodtab */
|
||||||
ml->data[10] = 0; /* extrefsymoff */
|
ml->data[10] = 0; /* extrefsymoff */
|
||||||
ml->data[11] = 0; /* nextrefsyms */
|
ml->data[11] = 0; /* nextrefsyms */
|
||||||
ml->data[12] = linkoff + nlinkdata - nsym*4; /* indirectsymoff */
|
ml->data[12] = linkoff + s1->size + s2->size; /* indirectsymoff */
|
||||||
ml->data[13] = nsym; /* nindirectsyms */
|
ml->data[13] = (s3->size + s4->size) / 4; /* nindirectsyms */
|
||||||
ml->data[14] = 0; /* extreloff */
|
ml->data[14] = 0; /* extreloff */
|
||||||
ml->data[15] = 0; /* nextrel */
|
ml->data[15] = 0; /* nextrel */
|
||||||
ml->data[16] = 0; /* locreloff */
|
ml->data[16] = 0; /* locreloff */
|
||||||
@ -640,3 +471,33 @@ asmbmacho(void)
|
|||||||
if(a > MACHORESERVE)
|
if(a > MACHORESERVE)
|
||||||
diag("MACHORESERVE too small: %d > %d", a, MACHORESERVE);
|
diag("MACHORESERVE too small: %d > %d", a, MACHORESERVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vlong
|
||||||
|
domacholink(void)
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
Sym *s1, *s2, *s3, *s4;
|
||||||
|
|
||||||
|
// write data that will be linkedit section
|
||||||
|
s1 = lookup(".dynsym", 0);
|
||||||
|
s2 = lookup(".dynstr", 0);
|
||||||
|
s3 = lookup(".linkedit.plt", 0);
|
||||||
|
s4 = lookup(".linkedit.got", 0);
|
||||||
|
|
||||||
|
while(s2->size%4)
|
||||||
|
adduint8(s2, 0);
|
||||||
|
|
||||||
|
size = s1->size + s2->size + s3->size + s4->size;
|
||||||
|
|
||||||
|
if(size > 0) {
|
||||||
|
linkoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen, INITRND);
|
||||||
|
seek(cout, linkoff, 0);
|
||||||
|
|
||||||
|
ewrite(cout, s1->p, s1->size);
|
||||||
|
ewrite(cout, s2->p, s2->size);
|
||||||
|
ewrite(cout, s3->p, s3->size);
|
||||||
|
ewrite(cout, s4->p, s4->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rnd(size, INITRND);
|
||||||
|
}
|
||||||
|
@ -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 {
|
|||||||
|
|
||||||
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user