static Prog *PP;
char linuxdynld[] = "/lib/ld-linux.so.3"; // 2 for OABI, 3 for EABI
+char freebsddynld[] = "/usr/libexec/ld-elf.so.1";
int32
entryvalue(void)
if(iself) {
plt = lookup(".plt", 0);
got = lookup(".got.plt", 0);
- rel = lookup(".rel", 0);
+ rel = lookup(".rel.plt", 0);
if(plt->size == 0)
elfsetupplt();
// .got entry
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
s->plt = plt->size;
/* !debug['d'] causes extra sections before the .text section */
elftextsh = 2;
if(!debug['d']) {
- elftextsh += 9;
+ elftextsh += 10;
if(elfverneed)
elftextsh += 2;
}
Bflush(&bso);
cseek(0L);
switch(HEADTYPE) {
+ default:
+ if(iself)
+ goto Elfput;
case Hnoheader: /* no header */
break;
case Hrisc: /* aif for risc os */
lputl(0xe3300000); /* nop */
lputl(0xe3300000); /* nop */
break;
- case Hlinux:
+ Elfput:
/* elf arm */
eh = getElfEhdr();
fo = HEADR;
sh->type = SHT_PROGBITS;
sh->flags = SHF_ALLOC;
sh->addralign = 1;
- if(interpreter == nil)
- interpreter = linuxdynld;
+ if(interpreter == nil) {
+ switch(HEADTYPE) {
+ case Hlinux:
+ interpreter = linuxdynld;
+ break;
+ case Hfreebsd:
+ interpreter = freebsddynld;
+ break;
+ }
+ }
resoff -= elfinterp(sh, startva, resoff, interpreter);
ph = newElfPhdr();
/* Dynamic linking sections */
if(!debug['d']) { /* -d suppresses dynamic loader format */
/* 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
sh = newElfShdr(elfstr[ElfStrPlt]);
sh->type = SHT_PROGBITS;
sh->addralign = 4;
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) {
sh = newElfShdr(elfstr[ElfStrGnuVersion]);
sh->type = SHT_GNU_VERSYM;
eh->ident[EI_CLASS] = ELFCLASS32;
eh->ident[EI_DATA] = ELFDATA2LSB;
eh->ident[EI_VERSION] = EV_CURRENT;
+ switch(HEADTYPE) {
+ case Hfreebsd:
+ eh->ident[EI_OSABI] = ELFOSABI_FREEBSD;
+ break;
+ }
eh->type = ET_EXEC;
eh->machine = EM_ARM;