summaryrefslogtreecommitdiff
path: root/src/cmd/8l/asm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/8l/asm.c')
-rw-r--r--src/cmd/8l/asm.c1262
1 files changed, 0 insertions, 1262 deletions
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
deleted file mode 100644
index e1ccfb8a3..000000000
--- a/src/cmd/8l/asm.c
+++ /dev/null
@@ -1,1262 +0,0 @@
-// Inferno utils/8l/asm.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8l/asm.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-// Writing object files.
-
-#include "l.h"
-#include "../ld/lib.h"
-#include "../ld/elf.h"
-#include "../ld/dwarf.h"
-#include "../ld/macho.h"
-#include "../ld/pe.h"
-
-#define Dbufslop 100
-
-char linuxdynld[] = "/lib/ld-linux.so.2";
-char freebsddynld[] = "/usr/libexec/ld-elf.so.1";
-
-int32
-entryvalue(void)
-{
- char *a;
- Sym *s;
-
- a = INITENTRY;
- if(*a >= '0' && *a <= '9')
- return atolwhex(a);
- s = lookup(a, 0);
- if(s->type == 0)
- return INITTEXT;
- if(s->type != STEXT)
- diag("entry not text: %s", s->name);
- return s->value;
-}
-
-vlong
-datoff(vlong addr)
-{
- if(addr >= segdata.vaddr)
- return addr - segdata.vaddr + segdata.fileoff;
- if(addr >= segtext.vaddr)
- return addr - segtext.vaddr + segtext.fileoff;
- diag("datoff %#llx", addr);
- return 0;
-}
-
-enum {
- ElfStrEmpty,
- ElfStrInterp,
- ElfStrHash,
- ElfStrGot,
- ElfStrGotPlt,
- ElfStrDynamic,
- ElfStrDynsym,
- ElfStrDynstr,
- ElfStrRel,
- ElfStrText,
- ElfStrData,
- ElfStrBss,
- ElfStrShstrtab,
- ElfStrSymtab,
- ElfStrStrtab,
- ElfStrRelPlt,
- ElfStrPlt,
- ElfStrGnuVersion,
- ElfStrGnuVersionR,
- NElfStr
-};
-
-vlong elfstr[NElfStr];
-
-static int
-needlib(char *name)
-{
- char *p;
- Sym *s;
-
- if(*name == '\0')
- return 0;
-
- /* reuse hash code in symbol table */
- p = smprint(".dynlib.%s", name);
- s = lookup(p, 0);
- if(s->type == 0) {
- s->type = 100; // avoid SDATA, etc.
- return 1;
- }
- return 0;
-}
-
-int nelfsym = 1;
-
-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 != nil && !targ->dynexport)
- 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:
- r->type = D_PCREL;
- r->add += 4;
- if(targ->dynimpname != nil && !targ->dynexport) {
- addpltsym(targ);
- r->sym = lookup(".plt", 0);
- r->add += targ->plt;
- }
- return;
-
- case 256 + R_386_GOT32:
- if(targ->dynimpname == nil || targ->dynexport) {
- // have symbol
- // turn MOVL of GOT entry into LEAL of symbol itself
- if(r->off < 2 || s->p[r->off-2] != 0x8b) {
- diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name);
- return;
- }
- s->p[r->off-2] = 0x8d;
- r->type = D_GOTOFF;
- return;
- }
- 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 != nil && !targ->dynexport)
- 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 != nil && !targ->dynexport)
- diag("unexpected reloc for dynamic symbol %s", targ->name);
- return;
-
- case 512 + MACHO_GENERIC_RELOC_VANILLA*2 + 1:
- if(targ->dynimpname != nil && !targ->dynexport) {
- addpltsym(targ);
- r->sym = lookup(".plt", 0);
- r->add = targ->plt;
- r->type = D_PCREL;
- return;
- }
- r->type = D_PCREL;
- return;
-
- case 512 + MACHO_FAKE_GOTPCREL:
- if(targ->dynimpname == nil || targ->dynexport) {
- // have symbol
- // turn MOVL of GOT entry into LEAL of symbol itself
- if(r->off < 2 || s->p[r->off-2] != 0x8b) {
- diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name);
- return;
- }
- s->p[r->off-2] = 0x8d;
- r->type = D_PCREL;
- return;
- }
- 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 || targ->dynexport)
- 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 == Hdarwin && 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)
-{
- USED(s);
- 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 == Hdarwin) {
- // 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 == Hdarwin) {
- adduint32(lookup(".linkedit.got", 0), s->dynid);
- } else {
- diag("addgotsym: unsupported binary format");
- }
-}
-
-void
-adddynsym(Sym *s)
-{
- Sym *d, *str;
- int t;
- char *name;
-
- if(s->dynid >= 0)
- return;
-
- if(s->dynimpname == nil)
- diag("adddynsym: no dynamic name for %s", s->name, *(int32*)0);
-
- 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 == Hdarwin) {
- // 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 if(HEADTYPE != Hwindows) {
- 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 == Hdarwin) {
- machoadddynlib(lib);
- } else if(HEADTYPE != Hwindows) {
- diag("adddynlib: unsupported binary format");
- }
-}
-
-void
-doelf(void)
-{
- Sym *s, *shstrtab, *dynstr;
-
- if(!iself)
- return;
-
- /* predefine strings we need for section headers */
- shstrtab = lookup(".shstrtab", 0);
- shstrtab->type = SELFDATA;
- shstrtab->reachable = 1;
-
- elfstr[ElfStrEmpty] = addstring(shstrtab, "");
- elfstr[ElfStrText] = addstring(shstrtab, ".text");
- elfstr[ElfStrData] = addstring(shstrtab, ".data");
- elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
- addstring(shstrtab, ".elfdata");
- addstring(shstrtab, ".rodata");
- addstring(shstrtab, ".gosymtab");
- addstring(shstrtab, ".gopclntab");
- if(!debug['s']) {
- elfstr[ElfStrSymtab] = addstring(shstrtab, ".symtab");
- elfstr[ElfStrStrtab] = addstring(shstrtab, ".strtab");
- dwarfaddshstrings(shstrtab);
- }
- elfstr[ElfStrShstrtab] = addstring(shstrtab, ".shstrtab");
-
- if(!debug['d']) { /* -d suppresses dynamic loader format */
- elfstr[ElfStrInterp] = addstring(shstrtab, ".interp");
- elfstr[ElfStrHash] = addstring(shstrtab, ".hash");
- elfstr[ElfStrGot] = addstring(shstrtab, ".got");
- elfstr[ElfStrGotPlt] = addstring(shstrtab, ".got.plt");
- elfstr[ElfStrDynamic] = addstring(shstrtab, ".dynamic");
- elfstr[ElfStrDynsym] = addstring(shstrtab, ".dynsym");
- elfstr[ElfStrDynstr] = addstring(shstrtab, ".dynstr");
- elfstr[ElfStrRel] = addstring(shstrtab, ".rel");
- elfstr[ElfStrRelPlt] = addstring(shstrtab, ".rel.plt");
- elfstr[ElfStrPlt] = addstring(shstrtab, ".plt");
- elfstr[ElfStrGnuVersion] = addstring(shstrtab, ".gnu.version");
- elfstr[ElfStrGnuVersionR] = addstring(shstrtab, ".gnu.version_r");
-
- /* interpreter string */
- s = lookup(".interp", 0);
- s->reachable = 1;
- s->type = SELFDATA;
-
- /* dynamic symbol table - first entry all zeros */
- s = lookup(".dynsym", 0);
- s->type = SELFDATA;
- s->reachable = 1;
- s->size += ELF32SYMSIZE;
-
- /* dynamic string table */
- s = lookup(".dynstr", 0);
- s->reachable = 1;
- s->type = SELFDATA;
- if(s->size == 0)
- addstring(s, "");
- dynstr = s;
-
- /* relocation table */
- s = lookup(".rel", 0);
- s->reachable = 1;
- s->type = SELFDATA;
-
- /* global offset table */
- s = lookup(".got", 0);
- s->reachable = 1;
- s->type = SDATA; // writable, so not SELFDATA
-
- /* hash */
- s = lookup(".hash", 0);
- s->reachable = 1;
- 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;
-
- s = lookup(".gnu.version", 0);
- s->reachable = 1;
- s->type = SELFDATA;
-
- s = lookup(".gnu.version_r", 0);
- s->reachable = 1;
- s->type = SELFDATA;
-
- elfsetupplt();
-
- /* define dynamic elf table */
- s = lookup(".dynamic", 0);
- s->reachable = 1;
- s->type = SELFDATA;
-
- /*
- * .dynamic table
- */
- elfwritedynentsym(s, DT_HASH, lookup(".hash", 0));
- elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0));
- elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE);
- elfwritedynentsym(s, DT_STRTAB, lookup(".dynstr", 0));
- elfwritedynentsymsize(s, DT_STRSZ, lookup(".dynstr", 0));
- elfwritedynentsym(s, DT_REL, lookup(".rel", 0));
- elfwritedynentsymsize(s, DT_RELSZ, lookup(".rel", 0));
- elfwritedynent(s, DT_RELENT, ELF32RELSIZE);
- if(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));
-
- // Do not write DT_NULL. elfdynhash will finish it.
- }
-}
-
-void
-shsym(Elf64_Shdr *sh, Sym *s)
-{
- sh->addr = symaddr(s);
- sh->off = datoff(sh->addr);
- sh->size = s->size;
-}
-
-void
-phsh(Elf64_Phdr *ph, Elf64_Shdr *sh)
-{
- ph->vaddr = sh->addr;
- ph->paddr = ph->vaddr;
- ph->off = sh->off;
- ph->filesz = sh->size;
- ph->memsz = sh->size;
- ph->align = sh->addralign;
-}
-
-void
-asmb(void)
-{
- int32 v, magic;
- int a, dynsym;
- uint32 symo, startva, machlink;
- ElfEhdr *eh;
- ElfPhdr *ph, *pph;
- ElfShdr *sh;
- Section *sect;
- Sym *sym;
- int i;
-
- if(debug['v'])
- Bprint(&bso, "%5.2f asmb\n", cputime());
- Bflush(&bso);
-
- sect = segtext.sect;
- seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
- codeblk(sect->vaddr, sect->len);
-
- /* output read-only data in text segment (rodata, gosymtab and pclntab) */
- for(sect = sect->next; sect != nil; sect = sect->next) {
- seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
- datblk(sect->vaddr, sect->len);
- }
-
- if(debug['v'])
- Bprint(&bso, "%5.2f datblk\n", cputime());
- Bflush(&bso);
-
- seek(cout, segdata.fileoff, 0);
- datblk(segdata.vaddr, segdata.filelen);
-
- machlink = 0;
- if(HEADTYPE == Hdarwin)
- 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;
- if(elfverneed)
- elftextsh += 2;
- }
- }
-
- symsize = 0;
- spsize = 0;
- lcsize = 0;
- symo = 0;
- if(!debug['s']) {
- // TODO: rationalize
- if(debug['v'])
- Bprint(&bso, "%5.2f sym\n", cputime());
- Bflush(&bso);
- switch(HEADTYPE) {
- default:
- if(iself)
- goto Elfsym;
- case Hgarbunix:
- symo = rnd(HEADR+segtext.filelen, 8192)+segdata.filelen;
- break;
- case Hunixcoff:
- symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen;
- break;
- case Hplan9x32:
- symo = HEADR+segtext.filelen+segdata.filelen;
- break;
- case Hmsdoscom:
- case Hmsdosexe:
- debug['s'] = 1;
- symo = HEADR+segtext.filelen+segdata.filelen;
- break;
- case Hdarwin:
- symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(segdata.filelen, INITRND)+machlink;
- break;
- Elfsym:
- symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen;
- symo = rnd(symo, INITRND);
- break;
- case Hwindows:
- symo = rnd(HEADR+segtext.filelen, PEFILEALIGN)+segdata.filelen;
- symo = rnd(symo, PEFILEALIGN);
- break;
- }
- seek(cout, symo, 0);
- switch(HEADTYPE) {
- default:
- if(iself) {
- if(debug['v'])
- Bprint(&bso, "%5.2f elfsym\n", cputime());
- asmelfsym();
- cflush();
- ewrite(cout, elfstrdat, elfstrsize);
-
- if(debug['v'])
- Bprint(&bso, "%5.2f dwarf\n", cputime());
- dwarfemitdebugsections();
- }
- break;
- case Hplan9x32:
- asmplan9sym();
- cflush();
-
- sym = lookup("pclntab", 0);
- if(sym != nil) {
- lcsize = sym->np;
- for(i=0; i < lcsize; i++)
- cput(sym->p[i]);
-
- cflush();
- }
- break;
- case Hdarwin:
- case Hwindows:
- if(debug['v'])
- Bprint(&bso, "%5.2f dwarf\n", cputime());
- dwarfemitdebugsections();
- break;
- }
- }
- if(debug['v'])
- Bprint(&bso, "%5.2f headr\n", cputime());
- Bflush(&bso);
- seek(cout, 0L, 0);
- switch(HEADTYPE) {
- default:
- if(iself)
- goto Elfput;
- case Hgarbunix: /* garbage */
- lputb(0x160L<<16); /* magic and sections */
- lputb(0L); /* time and date */
- lputb(rnd(HEADR+segtext.filelen, 4096)+segdata.filelen);
- lputb(symsize); /* nsyms */
- lputb((0x38L<<16)|7L); /* size of optional hdr and flags */
- lputb((0413<<16)|0437L); /* magic and version */
- lputb(rnd(HEADR+segtext.filelen, 4096)); /* sizes */
- lputb(segdata.filelen);
- lputb(segdata.len - segdata.filelen);
- lputb(entryvalue()); /* va of entry */
- lputb(INITTEXT-HEADR); /* va of base of text */
- lputb(segdata.vaddr); /* va of base of data */
- lputb(segdata.vaddr+segdata.filelen); /* va of base of bss */
- lputb(~0L); /* gp reg mask */
- lputb(0L);
- lputb(0L);
- lputb(0L);
- lputb(0L);
- lputb(~0L); /* gp value ?? */
- break;
- case Hunixcoff: /* unix coff */
- /*
- * file header
- */
- lputl(0x0004014c); /* 4 sections, magic */
- lputl(0); /* unix time stamp */
- lputl(0); /* symbol table */
- lputl(0); /* nsyms */
- lputl(0x0003001c); /* flags, sizeof a.out header */
- /*
- * a.out header
- */
- lputl(0x10b); /* magic, version stamp */
- lputl(rnd(segtext.filelen, INITRND)); /* text sizes */
- lputl(segdata.filelen); /* data sizes */
- lputl(segdata.len - segdata.filelen); /* bss sizes */
- lputb(entryvalue()); /* va of entry */
- lputl(INITTEXT); /* text start */
- lputl(segdata.vaddr); /* data start */
- /*
- * text section header
- */
- s8put(".text");
- lputl(HEADR); /* pa */
- lputl(HEADR); /* va */
- lputl(segtext.filelen); /* text size */
- lputl(HEADR); /* file offset */
- lputl(0); /* relocation */
- lputl(0); /* line numbers */
- lputl(0); /* relocation, line numbers */
- lputl(0x20); /* flags text only */
- /*
- * data section header
- */
- s8put(".data");
- lputl(segdata.vaddr); /* pa */
- lputl(segdata.vaddr); /* va */
- lputl(segdata.filelen); /* data size */
- lputl(HEADR+segtext.filelen); /* file offset */
- lputl(0); /* relocation */
- lputl(0); /* line numbers */
- lputl(0); /* relocation, line numbers */
- lputl(0x40); /* flags data only */
- /*
- * bss section header
- */
- s8put(".bss");
- lputl(segdata.vaddr+segdata.filelen); /* pa */
- lputl(segdata.vaddr+segdata.filelen); /* va */
- lputl(segdata.len - segdata.filelen); /* bss size */
- lputl(0); /* file offset */
- lputl(0); /* relocation */
- lputl(0); /* line numbers */
- lputl(0); /* relocation, line numbers */
- lputl(0x80); /* flags bss only */
- /*
- * comment section header
- */
- s8put(".comment");
- lputl(0); /* pa */
- lputl(0); /* va */
- lputl(symsize+lcsize); /* comment size */
- lputl(HEADR+segtext.filelen+segdata.filelen); /* file offset */
- lputl(HEADR+segtext.filelen+segdata.filelen); /* offset of syms */
- lputl(HEADR+segtext.filelen+segdata.filelen+symsize);/* offset of line numbers */
- lputl(0); /* relocation, line numbers */
- lputl(0x200); /* flags comment only */
- break;
- case Hplan9x32: /* plan9 */
- magic = 4*11*11+7;
- lputb(magic); /* magic */
- lputb(segtext.filelen); /* sizes */
- lputb(segdata.filelen);
- lputb(segdata.len - segdata.filelen);
- lputb(symsize); /* nsyms */
- lputb(entryvalue()); /* va of entry */
- lputb(spsize); /* sp offsets */
- lputb(lcsize); /* line offsets */
- break;
- case Hmsdoscom:
- /* MS-DOS .COM */
- break;
- case Hmsdosexe:
- /* fake MS-DOS .EXE */
- v = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen;
- wputl(0x5A4D); /* 'MZ' */
- wputl(v % 512); /* bytes in last page */
- wputl(rnd(v, 512)/512); /* total number of pages */
- wputl(0x0000); /* number of reloc items */
- v = rnd(HEADR-(INITTEXT & 0xFFFF), 16);
- wputl(v/16); /* size of header */
- wputl(0x0000); /* minimum allocation */
- wputl(0xFFFF); /* maximum allocation */
- wputl(0x0000); /* initial ss value */
- wputl(0x0100); /* initial sp value */
- wputl(0x0000); /* complemented checksum */
- v = entryvalue();
- wputl(v); /* initial ip value (!) */
- wputl(0x0000); /* initial cs value */
- wputl(0x0000);
- wputl(0x0000);
- wputl(0x003E); /* reloc table offset */
- wputl(0x0000); /* overlay number */
- break;
-
- case Hdarwin:
- asmbmacho();
- break;
-
- Elfput:
- eh = getElfEhdr();
- startva = INITTEXT - HEADR;
-
- /* This null SHdr must appear before all others */
- newElfShdr(elfstr[ElfStrEmpty]);
-
- /* program header info */
- pph = newElfPhdr();
- pph->type = PT_PHDR;
- pph->flags = PF_R + PF_X;
- pph->off = eh->ehsize;
- pph->vaddr = INITTEXT - HEADR + pph->off;
- pph->paddr = INITTEXT - HEADR + pph->off;
- pph->align = INITRND;
-
- if(!debug['d']) {
- /* interpreter */
- sh = newElfShdr(elfstr[ElfStrInterp]);
- sh->type = SHT_PROGBITS;
- sh->flags = SHF_ALLOC;
- sh->addralign = 1;
- if(interpreter == nil) {
- switch(HEADTYPE) {
- case Hlinux:
- interpreter = linuxdynld;
- break;
- case Hfreebsd:
- interpreter = freebsddynld;
- break;
- }
- }
- elfinterp(sh, startva, interpreter);
-
- ph = newElfPhdr();
- ph->type = PT_INTERP;
- ph->flags = PF_R;
- phsh(ph, sh);
- }
-
- elfphload(&segtext);
- elfphload(&segdata);
-
- /* Dynamic linking sections */
- if (!debug['d']) { /* -d suppresses dynamic loader format */
- /* S headers for dynamic linking */
- sh = newElfShdr(elfstr[ElfStrGot]);
- sh->type = SHT_PROGBITS;
- sh->flags = SHF_ALLOC+SHF_WRITE;
- sh->entsize = 4;
- sh->addralign = 4;
- shsym(sh, lookup(".got", 0));
-
- sh = newElfShdr(elfstr[ElfStrGotPlt]);
- sh->type = SHT_PROGBITS;
- sh->flags = SHF_ALLOC+SHF_WRITE;
- sh->entsize = 4;
- sh->addralign = 4;
- shsym(sh, lookup(".got.plt", 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;
- sh->flags = SHF_ALLOC;
- sh->addralign = 2;
- sh->link = dynsym;
- sh->entsize = 2;
- shsym(sh, lookup(".gnu.version", 0));
-
- sh = newElfShdr(elfstr[ElfStrGnuVersionR]);
- sh->type = SHT_GNU_VERNEED;
- sh->flags = SHF_ALLOC;
- sh->addralign = 4;
- sh->info = elfverneed;
- sh->link = dynsym+1; // dynstr
- shsym(sh, lookup(".gnu.version_r", 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->type = SHT_HASH;
- sh->flags = SHF_ALLOC;
- sh->entsize = 4;
- sh->addralign = 4;
- sh->link = dynsym;
- shsym(sh, lookup(".hash", 0));
-
- sh = newElfShdr(elfstr[ElfStrRel]);
- sh->type = SHT_REL;
- sh->flags = SHF_ALLOC;
- sh->entsize = ELF32RELSIZE;
- sh->addralign = 4;
- sh->link = dynsym;
- shsym(sh, lookup(".rel", 0));
-
- /* sh and PT_DYNAMIC for .dynamic section */
- sh = newElfShdr(elfstr[ElfStrDynamic]);
- sh->type = SHT_DYNAMIC;
- sh->flags = SHF_ALLOC+SHF_WRITE;
- sh->entsize = 8;
- sh->addralign = 4;
- sh->link = dynsym+1; // dynstr
- shsym(sh, lookup(".dynamic", 0));
- ph = newElfPhdr();
- ph->type = PT_DYNAMIC;
- ph->flags = PF_R + PF_W;
- phsh(ph, sh);
-
- /*
- * Thread-local storage segment (really just size).
- */
- if(tlsoffset != 0) {
- ph = newElfPhdr();
- ph->type = PT_TLS;
- ph->flags = PF_R;
- ph->memsz = -tlsoffset;
- ph->align = 4;
- }
- }
-
- ph = newElfPhdr();
- ph->type = PT_GNU_STACK;
- ph->flags = PF_W+PF_R;
- ph->align = 4;
-
- if(elftextsh != eh->shnum)
- diag("elftextsh = %d, want %d", elftextsh, eh->shnum);
- for(sect=segtext.sect; sect!=nil; sect=sect->next)
- elfshbits(sect);
- for(sect=segdata.sect; sect!=nil; sect=sect->next)
- elfshbits(sect);
-
- if (!debug['s']) {
- sh = newElfShdr(elfstr[ElfStrSymtab]);
- sh->type = SHT_SYMTAB;
- sh->off = symo;
- sh->size = symsize;
- sh->addralign = 4;
- sh->entsize = 16;
- sh->link = eh->shnum; // link to strtab
-
- sh = newElfShdr(elfstr[ElfStrStrtab]);
- sh->type = SHT_STRTAB;
- sh->off = symo+symsize;
- sh->size = elfstrsize;
- sh->addralign = 1;
-
- dwarfaddelfheaders();
- }
-
- sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
- sh->type = SHT_STRTAB;
- sh->addralign = 1;
- shsym(sh, lookup(".shstrtab", 0));
-
- /* Main header */
- eh->ident[EI_MAG0] = '\177';
- eh->ident[EI_MAG1] = 'E';
- eh->ident[EI_MAG2] = 'L';
- eh->ident[EI_MAG3] = 'F';
- eh->ident[EI_CLASS] = ELFCLASS32;
- eh->ident[EI_DATA] = ELFDATA2LSB;
- eh->ident[EI_VERSION] = EV_CURRENT;
- switch(HEADTYPE) {
- case Hfreebsd:
- eh->ident[EI_OSABI] = 9;
- break;
- }
-
- eh->type = ET_EXEC;
- eh->machine = EM_386;
- eh->version = EV_CURRENT;
- eh->entry = entryvalue();
-
- if(pph != nil) {
- pph->filesz = eh->phnum * eh->phentsize;
- pph->memsz = pph->filesz;
- }
-
- seek(cout, 0, 0);
- a = 0;
- a += elfwritehdr();
- a += elfwritephdrs();
- a += elfwriteshdrs();
- cflush();
- if(a+elfwriteinterp() > ELFRESERVE)
- diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
- break;
-
- case Hwindows:
- asmbpe();
- break;
- }
- cflush();
-}
-
-void
-s8put(char *n)
-{
- char name[8];
- int i;
-
- strncpy(name, n, sizeof(name));
- for(i=0; i<sizeof(name); i++)
- cput(name[i]);
-}
-
-void
-cflush(void)
-{
- int n;
-
- n = sizeof(buf.cbuf) - cbc;
- if(n)
- ewrite(cout, buf.cbuf, n);
- cbp = buf.cbuf;
- cbc = sizeof(buf.cbuf);
-}
-
-/* Current position in file */
-vlong
-cpos(void)
-{
- return seek(cout, 0, 1) + sizeof(buf.cbuf) - cbc;
-}
-
-int32
-rnd(int32 v, int32 r)
-{
- int32 c;
-
- if(r <= 0)
- return v;
- v += r - 1;
- c = v % r;
- if(c < 0)
- c += r;
- v -= c;
- return v;
-}
-
-void
-genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
-{
- Auto *a;
- Sym *s;
- int h;
-
- s = lookup("etext", 0);
- if(s->type == STEXT)
- put(s, s->name, 'T', s->value, s->size, s->version, 0);
-
- for(h=0; h<NHASH; h++) {
- for(s=hash[h]; s!=S; s=s->hash) {
- if(s->hide)
- continue;
- switch(s->type&~SSUB) {
- case SCONST:
- case SRODATA:
- case SDATA:
- case SELFDATA:
- case SMACHO:
- case SMACHOGOT:
- case STYPE:
- case SSTRING:
- case SGOSTRING:
- case SWINDOWS:
- if(!s->reachable)
- continue;
- put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
- continue;
-
- case SBSS:
- if(!s->reachable)
- continue;
- put(s, s->name, 'B', symaddr(s), s->size, s->version, s->gotype);
- continue;
-
- case SFILE:
- put(nil, s->name, 'f', s->value, 0, s->version, 0);
- continue;
- }
- }
- }
-
- for(s = textp; s != nil; s = s->next) {
- if(s->text == nil)
- continue;
-
- /* filenames first */
- for(a=s->autom; a; a=a->link)
- if(a->type == D_FILE)
- put(nil, a->asym->name, 'z', a->aoffset, 0, 0, 0);
- else
- if(a->type == D_FILE1)
- put(nil, a->asym->name, 'Z', a->aoffset, 0, 0, 0);
-
- put(s, s->name, 'T', s->value, s->size, s->version, s->gotype);
-
- /* frame, auto and param after */
- put(nil, ".frame", 'm', s->text->to.offset+4, 0, 0, 0);
-
- for(a=s->autom; a; a=a->link)
- if(a->type == D_AUTO)
- put(nil, a->asym->name, 'a', -a->aoffset, 0, 0, a->gotype);
- else
- if(a->type == D_PARAM)
- put(nil, a->asym->name, 'p', a->aoffset, 0, 0, a->gotype);
- }
- if(debug['v'] || debug['n'])
- Bprint(&bso, "symsize = %d\n", symsize);
- Bflush(&bso);
-}