diff options
Diffstat (limited to 'src/cmd/6l/asm.c')
-rw-r--r-- | src/cmd/6l/asm.c | 75 |
1 files changed, 63 insertions, 12 deletions
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c index 3a8223e65..ee31a05cd 100644 --- a/src/cmd/6l/asm.c +++ b/src/cmd/6l/asm.c @@ -37,13 +37,12 @@ #include "../ld/macho.h" #include "../ld/pe.h" -#define Dbufslop 100 - #define PADDR(a) ((uint32)(a) & ~0x80000000) char linuxdynld[] = "/lib64/ld-linux-x86-64.so.2"; char freebsddynld[] = "/libexec/ld-elf.so.1"; char openbsddynld[] = "/usr/libexec/ld.so"; +char netbsddynld[] = "/libexec/ld.elf_so"; char zeroes[32]; @@ -95,6 +94,9 @@ enum { ElfStrPlt, ElfStrGnuVersion, ElfStrGnuVersionR, + ElfStrNoteNetbsdIdent, + ElfStrNoPtrData, + ElfStrNoPtrBss, NElfStr }; @@ -112,6 +114,7 @@ needlib(char *name) /* reuse hash code in symbol table */ p = smprint(".elfload.%s", name); s = lookup(p, 0); + free(p); if(s->type == 0) { s->type = 100; // avoid SDATA, etc. return 1; @@ -558,7 +561,7 @@ doelf(void) { Sym *s, *shstrtab, *dynstr; - if(HEADTYPE != Hlinux && HEADTYPE != Hfreebsd && HEADTYPE != Hopenbsd) + if(HEADTYPE != Hlinux && HEADTYPE != Hfreebsd && HEADTYPE != Hopenbsd && HEADTYPE != Hnetbsd) return; /* predefine strings we need for section headers */ @@ -568,8 +571,12 @@ doelf(void) elfstr[ElfStrEmpty] = addstring(shstrtab, ""); elfstr[ElfStrText] = addstring(shstrtab, ".text"); + elfstr[ElfStrNoPtrData] = addstring(shstrtab, ".noptrdata"); elfstr[ElfStrData] = addstring(shstrtab, ".data"); elfstr[ElfStrBss] = addstring(shstrtab, ".bss"); + elfstr[ElfStrNoPtrBss] = addstring(shstrtab, ".noptrbss"); + if(HEADTYPE == Hnetbsd) + elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident"); addstring(shstrtab, ".elfdata"); addstring(shstrtab, ".rodata"); addstring(shstrtab, ".gosymtab"); @@ -649,7 +656,7 @@ doelf(void) /* define dynamic elf table */ s = lookup(".dynamic", 0); s->reachable = 1; - s->type = SELFROSECT; + s->type = SELFSECT; // writable /* * .dynamic table @@ -670,6 +677,8 @@ doelf(void) elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rela.plt", 0)); elfwritedynentsym(s, DT_JMPREL, lookup(".rela.plt", 0)); + elfwritedynent(s, DT_DEBUG, 0); + // Do not write DT_NULL. elfdynhash will finish it. } } @@ -701,7 +710,7 @@ asmb(void) { int32 magic; int a, dynsym; - vlong vl, startva, symo, machlink; + vlong vl, startva, symo, dwarfoff, machlink, resoff; ElfEhdr *eh; ElfPhdr *ph, *pph; ElfShdr *sh; @@ -736,8 +745,19 @@ asmb(void) datblk(segdata.vaddr, segdata.filelen); machlink = 0; - if(HEADTYPE == Hdarwin) + if(HEADTYPE == Hdarwin) { + if(debug['v']) + Bprint(&bso, "%5.2f dwarf\n", cputime()); + + dwarfoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen, INITRND); + cseek(dwarfoff); + + segdwarf.fileoff = cpos(); + dwarfemitdebugsections(); + segdwarf.filelen = cpos() - segdwarf.fileoff; + machlink = domacholink(); + } switch(HEADTYPE) { default: @@ -750,6 +770,7 @@ asmb(void) break; case Hlinux: case Hfreebsd: + case Hnetbsd: case Hopenbsd: debug['8'] = 1; /* 64-bit addresses */ /* index of elf text section; needed by asmelfsym, double-checked below */ @@ -760,6 +781,8 @@ asmb(void) if(elfverneed) elftextsh += 2; } + if(HEADTYPE == Hnetbsd) + elftextsh += 1; break; case Hwindows: break; @@ -785,6 +808,7 @@ asmb(void) break; case Hlinux: case Hfreebsd: + case Hnetbsd: case Hopenbsd: symo = rnd(HEADR+segtext.len, INITRND)+segdata.filelen; symo = rnd(symo, INITRND); @@ -809,7 +833,6 @@ asmb(void) dwarfemitdebugsections(); } break; - case Hdarwin: case Hwindows: if(debug['v']) Bprint(&bso, "%5.2f dwarf\n", cputime()); @@ -855,11 +878,13 @@ asmb(void) break; case Hlinux: case Hfreebsd: + case Hnetbsd: case Hopenbsd: /* elf amd-64 */ eh = getElfEhdr(); startva = INITTEXT - HEADR; + resoff = ELFRESERVE; /* This null SHdr must appear before all others */ newElfShdr(elfstr[ElfStrEmpty]); @@ -898,12 +923,15 @@ asmb(void) case Hfreebsd: interpreter = freebsddynld; break; + case Hnetbsd: + interpreter = netbsddynld; + break; case Hopenbsd: interpreter = openbsddynld; break; } } - elfinterp(sh, startva, interpreter); + resoff -= elfinterp(sh, startva, resoff, interpreter); ph = newElfPhdr(); ph->type = PT_INTERP; @@ -911,11 +939,24 @@ asmb(void) phsh(ph, sh); } + if(HEADTYPE == Hnetbsd) { + sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]); + sh->type = SHT_NOTE; + sh->flags = SHF_ALLOC; + sh->addralign = 4; + resoff -= elfnetbsdsig(sh, startva, resoff); + + ph = newElfPhdr(); + ph->type = PT_NOTE; + ph->flags = PF_R; + phsh(ph, sh); + } + elfphload(&segtext); elfphload(&segdata); /* Dynamic linking sections */ - if (!debug['d']) { /* -d suppresses dynamic loader format */ + if(!debug['d']) { /* -d suppresses dynamic loader format */ /* S headers for dynamic linking */ sh = newElfShdr(elfstr[ElfStrGot]); sh->type = SHT_PROGBITS; @@ -1039,7 +1080,7 @@ asmb(void) for(sect=segdata.sect; sect!=nil; sect=sect->next) elfshbits(sect); - if (!debug['s']) { + if(!debug['s']) { sh = newElfShdr(elfstr[ElfStrSymtab]); sh->type = SHT_SYMTAB; sh->off = symo; @@ -1064,6 +1105,8 @@ asmb(void) eh->ident[EI_MAG3] = 'F'; if(HEADTYPE == Hfreebsd) eh->ident[EI_OSABI] = ELFOSABI_FREEBSD; + else if(HEADTYPE == Hnetbsd) + eh->ident[EI_OSABI] = ELFOSABI_NETBSD; else if(HEADTYPE == Hopenbsd) eh->ident[EI_OSABI] = ELFOSABI_OPENBSD; eh->ident[EI_CLASS] = ELFCLASS64; @@ -1083,8 +1126,10 @@ asmb(void) a += elfwritehdr(); a += elfwritephdrs(); a += elfwriteshdrs(); - cflush(); - if(a+elfwriteinterp() > ELFRESERVE) + a += elfwriteinterp(elfstr[ElfStrInterp]); + if(HEADTYPE == Hnetbsd) + a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]); + if(a > ELFRESERVE) diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE); break; case Hwindows: @@ -1125,7 +1170,10 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*)) switch(s->type&~SSUB) { case SCONST: case SRODATA: + case SSYMTAB: + case SPCLNTAB: case SDATA: + case SNOPTRDATA: case SELFROSECT: case SMACHOGOT: case STYPE: @@ -1138,8 +1186,11 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*)) continue; case SBSS: + case SNOPTRBSS: if(!s->reachable) continue; + if(s->np > 0) + diag("%s should not be bss (size=%d type=%d special=%d)", s->name, (int)s->np, s->type, s->special); put(s, s->name, 'B', symaddr(s), s->size, s->version, s->gotype); continue; |