mirror of
https://github.com/golang/go
synced 2024-11-22 22:00:02 -07:00
cmd/5l: generate FreeBSD compatible ELF
1. correctly initialize .plt.got entries (point to the 1st entry) 2. add section .rel.plt (FreeBSD insists PLT relocs to be there) 3. put relocs of .got.plt into .rel.plt 4. set ELFOSABI_FREEBSD in ELF header R=rsc CC=golang-dev https://golang.org/cl/6643050
This commit is contained in:
parent
fa563ae82e
commit
d901808869
@ -38,6 +38,7 @@
|
|||||||
static Prog *PP;
|
static Prog *PP;
|
||||||
|
|
||||||
char linuxdynld[] = "/lib/ld-linux.so.3"; // 2 for OABI, 3 for EABI
|
char linuxdynld[] = "/lib/ld-linux.so.3"; // 2 for OABI, 3 for EABI
|
||||||
|
char freebsddynld[] = "/usr/libexec/ld-elf.so.1";
|
||||||
|
|
||||||
int32
|
int32
|
||||||
entryvalue(void)
|
entryvalue(void)
|
||||||
@ -344,13 +345,16 @@ addpltsym(Sym *s)
|
|||||||
if(iself) {
|
if(iself) {
|
||||||
plt = lookup(".plt", 0);
|
plt = lookup(".plt", 0);
|
||||||
got = lookup(".got.plt", 0);
|
got = lookup(".got.plt", 0);
|
||||||
rel = lookup(".rel", 0);
|
rel = lookup(".rel.plt", 0);
|
||||||
if(plt->size == 0)
|
if(plt->size == 0)
|
||||||
elfsetupplt();
|
elfsetupplt();
|
||||||
|
|
||||||
// .got entry
|
// .got entry
|
||||||
s->got = got->size;
|
s->got = got->size;
|
||||||
adduint32(got, 0);
|
// In theory, all GOT should point to the first PLT entry,
|
||||||
|
// Linux/ARM's dynamic linker will do that for us, but FreeBSD/ARM's
|
||||||
|
// dynamic linker won't, so we'd better do it ourselves.
|
||||||
|
addaddrplus(got, plt, 0);
|
||||||
|
|
||||||
// .plt entry, this depends on the .got entry
|
// .plt entry, this depends on the .got entry
|
||||||
s->plt = plt->size;
|
s->plt = plt->size;
|
||||||
@ -696,7 +700,7 @@ asmb(void)
|
|||||||
/* !debug['d'] causes extra sections before the .text section */
|
/* !debug['d'] causes extra sections before the .text section */
|
||||||
elftextsh = 2;
|
elftextsh = 2;
|
||||||
if(!debug['d']) {
|
if(!debug['d']) {
|
||||||
elftextsh += 9;
|
elftextsh += 10;
|
||||||
if(elfverneed)
|
if(elfverneed)
|
||||||
elftextsh += 2;
|
elftextsh += 2;
|
||||||
}
|
}
|
||||||
@ -755,6 +759,9 @@ asmb(void)
|
|||||||
Bflush(&bso);
|
Bflush(&bso);
|
||||||
cseek(0L);
|
cseek(0L);
|
||||||
switch(HEADTYPE) {
|
switch(HEADTYPE) {
|
||||||
|
default:
|
||||||
|
if(iself)
|
||||||
|
goto Elfput;
|
||||||
case Hnoheader: /* no header */
|
case Hnoheader: /* no header */
|
||||||
break;
|
break;
|
||||||
case Hrisc: /* aif for risc os */
|
case Hrisc: /* aif for risc os */
|
||||||
@ -815,7 +822,7 @@ asmb(void)
|
|||||||
lputl(0xe3300000); /* nop */
|
lputl(0xe3300000); /* nop */
|
||||||
lputl(0xe3300000); /* nop */
|
lputl(0xe3300000); /* nop */
|
||||||
break;
|
break;
|
||||||
case Hlinux:
|
Elfput:
|
||||||
/* elf arm */
|
/* elf arm */
|
||||||
eh = getElfEhdr();
|
eh = getElfEhdr();
|
||||||
fo = HEADR;
|
fo = HEADR;
|
||||||
@ -851,8 +858,16 @@ asmb(void)
|
|||||||
sh->type = SHT_PROGBITS;
|
sh->type = SHT_PROGBITS;
|
||||||
sh->flags = SHF_ALLOC;
|
sh->flags = SHF_ALLOC;
|
||||||
sh->addralign = 1;
|
sh->addralign = 1;
|
||||||
if(interpreter == nil)
|
if(interpreter == nil) {
|
||||||
interpreter = linuxdynld;
|
switch(HEADTYPE) {
|
||||||
|
case Hlinux:
|
||||||
|
interpreter = linuxdynld;
|
||||||
|
break;
|
||||||
|
case Hfreebsd:
|
||||||
|
interpreter = freebsddynld;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
resoff -= elfinterp(sh, startva, resoff, interpreter);
|
resoff -= elfinterp(sh, startva, resoff, interpreter);
|
||||||
|
|
||||||
ph = newElfPhdr();
|
ph = newElfPhdr();
|
||||||
@ -886,6 +901,31 @@ asmb(void)
|
|||||||
/* Dynamic linking sections */
|
/* Dynamic linking sections */
|
||||||
if(!debug['d']) { /* -d suppresses dynamic loader format */
|
if(!debug['d']) { /* -d suppresses dynamic loader format */
|
||||||
/* S headers for dynamic linking */
|
/* S headers for dynamic linking */
|
||||||
|
dynsym = eh->shnum;
|
||||||
|
sh = newElfShdr(elfstr[ElfStrDynsym]);
|
||||||
|
sh->type = SHT_DYNSYM;
|
||||||
|
sh->flags = SHF_ALLOC;
|
||||||
|
sh->entsize = ELF32SYMSIZE;
|
||||||
|
sh->addralign = 4;
|
||||||
|
sh->link = dynsym+1; // dynstr
|
||||||
|
// sh->info = index of first non-local symbol (number of local symbols)
|
||||||
|
shsym(sh, lookup(".dynsym", 0));
|
||||||
|
|
||||||
|
sh = newElfShdr(elfstr[ElfStrDynstr]);
|
||||||
|
sh->type = SHT_STRTAB;
|
||||||
|
sh->flags = SHF_ALLOC;
|
||||||
|
sh->addralign = 1;
|
||||||
|
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));
|
||||||
|
|
||||||
// ARM ELF needs .plt to be placed before .got
|
// ARM ELF needs .plt to be placed before .got
|
||||||
sh = newElfShdr(elfstr[ElfStrPlt]);
|
sh = newElfShdr(elfstr[ElfStrPlt]);
|
||||||
sh->type = SHT_PROGBITS;
|
sh->type = SHT_PROGBITS;
|
||||||
@ -908,22 +948,6 @@ asmb(void)
|
|||||||
sh->addralign = 4;
|
sh->addralign = 4;
|
||||||
shsym(sh, lookup(".got", 0));
|
shsym(sh, lookup(".got", 0));
|
||||||
|
|
||||||
dynsym = eh->shnum;
|
|
||||||
sh = newElfShdr(elfstr[ElfStrDynsym]);
|
|
||||||
sh->type = SHT_DYNSYM;
|
|
||||||
sh->flags = SHF_ALLOC;
|
|
||||||
sh->entsize = ELF32SYMSIZE;
|
|
||||||
sh->addralign = 4;
|
|
||||||
sh->link = dynsym+1; // dynstr
|
|
||||||
// sh->info = index of first non-local symbol (number of local symbols)
|
|
||||||
shsym(sh, lookup(".dynsym", 0));
|
|
||||||
|
|
||||||
sh = newElfShdr(elfstr[ElfStrDynstr]);
|
|
||||||
sh->type = SHT_STRTAB;
|
|
||||||
sh->flags = SHF_ALLOC;
|
|
||||||
sh->addralign = 1;
|
|
||||||
shsym(sh, lookup(".dynstr", 0));
|
|
||||||
|
|
||||||
if(elfverneed) {
|
if(elfverneed) {
|
||||||
sh = newElfShdr(elfstr[ElfStrGnuVersion]);
|
sh = newElfShdr(elfstr[ElfStrGnuVersion]);
|
||||||
sh->type = SHT_GNU_VERSYM;
|
sh->type = SHT_GNU_VERSYM;
|
||||||
@ -1029,6 +1053,11 @@ asmb(void)
|
|||||||
eh->ident[EI_CLASS] = ELFCLASS32;
|
eh->ident[EI_CLASS] = ELFCLASS32;
|
||||||
eh->ident[EI_DATA] = ELFDATA2LSB;
|
eh->ident[EI_DATA] = ELFDATA2LSB;
|
||||||
eh->ident[EI_VERSION] = EV_CURRENT;
|
eh->ident[EI_VERSION] = EV_CURRENT;
|
||||||
|
switch(HEADTYPE) {
|
||||||
|
case Hfreebsd:
|
||||||
|
eh->ident[EI_OSABI] = ELFOSABI_FREEBSD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
eh->type = ET_EXEC;
|
eh->type = ET_EXEC;
|
||||||
eh->machine = EM_ARM;
|
eh->machine = EM_ARM;
|
||||||
|
@ -52,6 +52,7 @@ Header headers[] = {
|
|||||||
"ixp1200", Hixp1200,
|
"ixp1200", Hixp1200,
|
||||||
"ipaq", Hipaq,
|
"ipaq", Hipaq,
|
||||||
"linux", Hlinux,
|
"linux", Hlinux,
|
||||||
|
"freebsd", Hfreebsd,
|
||||||
0, 0
|
0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -152,7 +153,7 @@ main(int argc, char *argv[])
|
|||||||
libinit();
|
libinit();
|
||||||
|
|
||||||
if(HEADTYPE == -1)
|
if(HEADTYPE == -1)
|
||||||
HEADTYPE = Hlinux;
|
HEADTYPE = headtype(goos);
|
||||||
switch(HEADTYPE) {
|
switch(HEADTYPE) {
|
||||||
default:
|
default:
|
||||||
diag("unknown -H option");
|
diag("unknown -H option");
|
||||||
@ -212,6 +213,7 @@ main(int argc, char *argv[])
|
|||||||
INITRND = 1024;
|
INITRND = 1024;
|
||||||
break;
|
break;
|
||||||
case Hlinux: /* arm elf */
|
case Hlinux: /* arm elf */
|
||||||
|
case Hfreebsd:
|
||||||
debug['d'] = 0; // with dynamic linking
|
debug['d'] = 0; // with dynamic linking
|
||||||
tlsoffset = -8; // hardcoded number, first 4-byte word for g, and then 4-byte word for m
|
tlsoffset = -8; // hardcoded number, first 4-byte word for g, and then 4-byte word for m
|
||||||
// this number is known to ../../pkg/runtime/cgo/gcc_linux_arm.c
|
// this number is known to ../../pkg/runtime/cgo/gcc_linux_arm.c
|
||||||
|
Loading…
Reference in New Issue
Block a user