summaryrefslogtreecommitdiff
path: root/src/cmd/6l/asm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/6l/asm.c')
-rw-r--r--src/cmd/6l/asm.c643
1 files changed, 104 insertions, 539 deletions
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index ee31a05cd..5fb75ba4d 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -74,34 +74,6 @@ datoff(vlong addr)
return 0;
}
-enum {
- ElfStrEmpty,
- ElfStrInterp,
- ElfStrHash,
- ElfStrGot,
- ElfStrGotPlt,
- ElfStrDynamic,
- ElfStrDynsym,
- ElfStrDynstr,
- ElfStrRela,
- ElfStrText,
- ElfStrData,
- ElfStrBss,
- ElfStrShstrtab,
- ElfStrSymtab,
- ElfStrStrtab,
- ElfStrRelaPlt,
- ElfStrPlt,
- ElfStrGnuVersion,
- ElfStrGnuVersionR,
- ElfStrNoteNetbsdIdent,
- ElfStrNoPtrData,
- ElfStrNoPtrBss,
- NElfStr
-};
-
-vlong elfstr[NElfStr];
-
static int
needlib(char *name)
{
@@ -127,6 +99,20 @@ int nelfsym = 1;
static void addpltsym(Sym*);
static void addgotsym(Sym*);
+Sym *
+lookuprel(void)
+{
+ return lookup(".rela", 0);
+}
+
+void
+adddynrela(Sym *rela, Sym *s, Reloc *r)
+{
+ addaddrplus(rela, s, r->off);
+ adduint64(rela, R_X86_64_RELATIVE);
+ addaddrplus(rela, r->sym, r->add); // Addend
+}
+
void
adddynrel(Sym *s, Reloc *r)
{
@@ -299,6 +285,37 @@ adddynrel(Sym *s, Reloc *r)
}
int
+elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add)
+{
+ VPUT(off);
+
+ switch(r->type) {
+ default:
+ return -1;
+
+ case D_ADDR:
+ if(r->siz == 4)
+ VPUT(R_X86_64_32 | (uint64)elfsym<<32);
+ else if(r->siz == 8)
+ VPUT(R_X86_64_64 | (uint64)elfsym<<32);
+ else
+ return -1;
+ break;
+
+ case D_PCREL:
+ if(r->siz == 4)
+ VPUT(R_X86_64_PC32 | (uint64)elfsym<<32);
+ else
+ return -1;
+ add -= r->siz;
+ break;
+ }
+
+ VPUT(add);
+ return 0;
+}
+
+int
archreloc(Reloc *r, Sym *s, vlong *val)
{
USED(r);
@@ -307,7 +324,7 @@ archreloc(Reloc *r, Sym *s, vlong *val)
return -1;
}
-static void
+void
elfsetupplt(void)
{
Sym *plt, *got;
@@ -434,6 +451,7 @@ adddynsym(Sym *s)
Sym *d, *str;
int t;
char *name;
+ vlong off;
if(s->dynid >= 0)
return;
@@ -452,7 +470,7 @@ adddynsym(Sym *s)
adduint32(d, addstring(lookup(".dynstr", 0), name));
/* type */
t = STB_GLOBAL << 4;
- if(s->dynexport && s->type == STEXT)
+ if(s->dynexport && (s->type&SMASK) == STEXT)
t |= STT_FUNC;
else
t |= STT_OBJECT;
@@ -490,7 +508,7 @@ adddynsym(Sym *s)
addaddr(d, s);
/* size of object */
- adduint64(d, 0);
+ adduint64(d, s->size);
if(!s->dynexport && s->dynimplib && needlib(s->dynimplib)) {
elfwritedynent(lookup(".dynamic", 0), DT_NEEDED,
@@ -502,35 +520,51 @@ adddynsym(Sym *s)
name = s->dynimpname;
if(name == nil)
name = s->name;
- s->dynid = d->size/16;
+ if(d->size == 0 && ndynexp > 0) { // pre-allocate for dynexps
+ symgrow(d, ndynexp*16);
+ }
+ if(s->dynid <= -100) { // pre-allocated, see cmd/ld/go.c:^sortdynexp()
+ s->dynid = -s->dynid-100;
+ off = s->dynid*16;
+ } else {
+ off = d->size;
+ s->dynid = off/16;
+ }
// darwin still puts _ prefixes on all C symbols
str = lookup(".dynstr", 0);
- adduint32(d, str->size);
+ setuint32(d, off, str->size);
+ off += 4;
adduint8(str, '_');
addstring(str, name);
if(s->type == SDYNIMPORT) {
- adduint8(d, 0x01); // type - N_EXT - external symbol
- adduint8(d, 0); // section
+ setuint8(d, off, 0x01); // type - N_EXT - external symbol
+ off++;
+ setuint8(d, off, 0); // section
+ off++;
} else {
- adduint8(d, 0x0f);
+ setuint8(d, off, 0x0f);
+ off++;
switch(s->type) {
default:
case STEXT:
- adduint8(d, 1);
+ setuint8(d, off, 1);
break;
case SDATA:
- adduint8(d, 2);
+ setuint8(d, off, 2);
break;
case SBSS:
- adduint8(d, 4);
+ setuint8(d, off, 4);
break;
}
+ off++;
}
- adduint16(d, 0); // desc
+ setuint16(d, off, 0); // desc
+ off += 2;
if(s->type == SDYNIMPORT)
- adduint64(d, 0); // value
+ setuint64(d, off, 0); // value
else
- addaddr(d, s);
+ setaddr(d, off, s);
+ off += 8;
} else if(HEADTYPE != Hwindows) {
diag("adddynsym: unsupported binary format");
}
@@ -557,181 +591,30 @@ adddynlib(char *lib)
}
void
-doelf(void)
-{
- Sym *s, *shstrtab, *dynstr;
-
- if(HEADTYPE != Hlinux && HEADTYPE != Hfreebsd && HEADTYPE != Hopenbsd && HEADTYPE != Hnetbsd)
- return;
-
- /* predefine strings we need for section headers */
- shstrtab = lookup(".shstrtab", 0);
- shstrtab->type = SELFROSECT;
- shstrtab->reachable = 1;
-
- 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");
- 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[ElfStrRela] = addstring(shstrtab, ".rela");
- elfstr[ElfStrRelaPlt] = addstring(shstrtab, ".rela.plt");
- elfstr[ElfStrPlt] = addstring(shstrtab, ".plt");
- elfstr[ElfStrGnuVersion] = addstring(shstrtab, ".gnu.version");
- elfstr[ElfStrGnuVersionR] = addstring(shstrtab, ".gnu.version_r");
-
- /* dynamic symbol table - first entry all zeros */
- s = lookup(".dynsym", 0);
- s->type = SELFROSECT;
- s->reachable = 1;
- s->size += ELF64SYMSIZE;
-
- /* dynamic string table */
- s = lookup(".dynstr", 0);
- s->type = SELFROSECT;
- s->reachable = 1;
- if(s->size == 0)
- addstring(s, "");
- dynstr = s;
-
- /* relocation table */
- s = lookup(".rela", 0);
- s->reachable = 1;
- s->type = SELFROSECT;
-
- /* global offset table */
- s = lookup(".got", 0);
- s->reachable = 1;
- s->type = SELFSECT; // writable
-
- /* hash */
- s = lookup(".hash", 0);
- s->reachable = 1;
- s->type = SELFROSECT;
-
- s = lookup(".got.plt", 0);
- s->reachable = 1;
- s->type = SELFSECT; // writable
-
- s = lookup(".plt", 0);
- s->reachable = 1;
- s->type = SELFROSECT;
-
- elfsetupplt();
-
- s = lookup(".rela.plt", 0);
- s->reachable = 1;
- s->type = SELFROSECT;
-
- s = lookup(".gnu.version", 0);
- s->reachable = 1;
- s->type = SELFROSECT;
-
- s = lookup(".gnu.version_r", 0);
- s->reachable = 1;
- s->type = SELFROSECT;
-
- /* define dynamic elf table */
- s = lookup(".dynamic", 0);
- s->reachable = 1;
- s->type = SELFSECT; // writable
-
- /*
- * .dynamic table
- */
- elfwritedynentsym(s, DT_HASH, lookup(".hash", 0));
- elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0));
- elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE);
- elfwritedynentsym(s, DT_STRTAB, lookup(".dynstr", 0));
- elfwritedynentsymsize(s, DT_STRSZ, lookup(".dynstr", 0));
- elfwritedynentsym(s, DT_RELA, lookup(".rela", 0));
- elfwritedynentsymsize(s, DT_RELASZ, lookup(".rela", 0));
- elfwritedynent(s, DT_RELAENT, ELF64RELASIZE);
- if(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_DEBUG, 0);
-
- // Do not write DT_NULL. elfdynhash will finish it.
- }
-}
-
-void
-shsym(ElfShdr *sh, Sym *s)
-{
- vlong addr;
- addr = symaddr(s);
- if(sh->flags&SHF_ALLOC)
- sh->addr = addr;
- sh->off = datoff(addr);
- sh->size = s->size;
-}
-
-void
-phsh(ElfPhdr *ph, ElfShdr *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 magic;
- int a, dynsym;
- vlong vl, startva, symo, dwarfoff, machlink, resoff;
- ElfEhdr *eh;
- ElfPhdr *ph, *pph;
- ElfShdr *sh;
+ int i;
+ vlong vl, symo, dwarfoff, machlink;
Section *sect;
- int o;
+ Sym *sym;
if(debug['v'])
Bprint(&bso, "%5.2f asmb\n", cputime());
Bflush(&bso);
- elftextsh = 0;
-
if(debug['v'])
Bprint(&bso, "%5.2f codeblk\n", cputime());
Bflush(&bso);
+ if(iself)
+ asmbelfsetup();
+
sect = segtext.sect;
cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
codeblk(sect->vaddr, sect->len);
- /* output read-only data in text segment (rodata, gosymtab and pclntab) */
+ /* output read-only data in text segment (rodata, gosymtab, pclntab, ...) */
for(sect = sect->next; sect != nil; sect = sect->next) {
cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
datblk(sect->vaddr, sect->len);
@@ -763,6 +646,7 @@ asmb(void)
default:
diag("unknown header type %d", HEADTYPE);
case Hplan9x32:
+ case Hplan9x64:
case Helf:
break;
case Hdarwin:
@@ -773,16 +657,6 @@ asmb(void)
case Hnetbsd:
case Hopenbsd:
debug['8'] = 1; /* 64-bit addresses */
- /* index of elf text section; needed by asmelfsym, double-checked below */
- /* !debug['d'] causes extra sections before the .text section */
- elftextsh = 2;
- if(!debug['d']) {
- elftextsh += 10;
- if(elfverneed)
- elftextsh += 2;
- }
- if(HEADTYPE == Hnetbsd)
- elftextsh += 1;
break;
case Hwindows:
break;
@@ -798,7 +672,7 @@ asmb(void)
Bflush(&bso);
switch(HEADTYPE) {
default:
- case Hplan9x32:
+ case Hplan9x64:
case Helf:
debug['s'] = 1;
symo = HEADR+segtext.len+segdata.filelen;
@@ -831,6 +705,22 @@ asmb(void)
Bprint(&bso, "%5.2f dwarf\n", cputime());
dwarfemitdebugsections();
+
+ if(isobj)
+ elfemitreloc();
+ }
+ break;
+ case Hplan9x64:
+ 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 Hwindows:
@@ -848,7 +738,7 @@ asmb(void)
cseek(0L);
switch(HEADTYPE) {
default:
- case Hplan9x32: /* plan9 */
+ case Hplan9x64: /* plan9 */
magic = 4*26*26+7;
magic |= 0x00008000; /* fat header */
lputb(magic); /* magic */
@@ -862,7 +752,7 @@ asmb(void)
lputb(lcsize); /* line offsets */
vputb(vl); /* va of entry */
break;
- case Hplan9x64: /* plan9 */
+ case Hplan9x32: /* plan9 */
magic = 4*26*26+7;
lputb(magic); /* magic */
lputb(segtext.filelen); /* sizes */
@@ -880,257 +770,7 @@ asmb(void)
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]);
-
- /* 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;
-
- /*
- * PHDR must be in a loaded segment. Adjust the text
- * segment boundaries downwards to include it.
- */
- o = segtext.vaddr - pph->vaddr;
- segtext.vaddr -= o;
- segtext.len += o;
- o = segtext.fileoff - pph->off;
- segtext.fileoff -= o;
- segtext.filelen += o;
-
- 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;
- case Hnetbsd:
- interpreter = netbsddynld;
- break;
- case Hopenbsd:
- interpreter = openbsddynld;
- break;
- }
- }
- resoff -= elfinterp(sh, startva, resoff, interpreter);
-
- ph = newElfPhdr();
- ph->type = PT_INTERP;
- ph->flags = PF_R;
- 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 */
- /* S headers for dynamic linking */
- sh = newElfShdr(elfstr[ElfStrGot]);
- sh->type = SHT_PROGBITS;
- sh->flags = SHF_ALLOC+SHF_WRITE;
- sh->entsize = 8;
- sh->addralign = 8;
- shsym(sh, lookup(".got", 0));
-
- sh = newElfShdr(elfstr[ElfStrGotPlt]);
- sh->type = SHT_PROGBITS;
- sh->flags = SHF_ALLOC+SHF_WRITE;
- sh->entsize = 8;
- sh->addralign = 8;
- shsym(sh, lookup(".got.plt", 0));
-
- dynsym = eh->shnum;
- sh = newElfShdr(elfstr[ElfStrDynsym]);
- sh->type = SHT_DYNSYM;
- sh->flags = SHF_ALLOC;
- sh->entsize = ELF64SYMSIZE;
- sh->addralign = 8;
- 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 = 8;
- sh->info = elfverneed;
- sh->link = dynsym+1; // dynstr
- shsym(sh, lookup(".gnu.version_r", 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->type = SHT_HASH;
- sh->flags = SHF_ALLOC;
- sh->entsize = 4;
- sh->addralign = 8;
- sh->link = dynsym;
- shsym(sh, lookup(".hash", 0));
-
- sh = newElfShdr(elfstr[ElfStrRela]);
- sh->type = SHT_RELA;
- sh->flags = SHF_ALLOC;
- sh->entsize = ELF64RELASIZE;
- sh->addralign = 8;
- sh->link = dynsym;
- shsym(sh, lookup(".rela", 0));
-
- /* sh and PT_DYNAMIC for .dynamic section */
- sh = newElfShdr(elfstr[ElfStrDynamic]);
- sh->type = SHT_DYNAMIC;
- sh->flags = SHF_ALLOC+SHF_WRITE;
- sh->entsize = 16;
- sh->addralign = 8;
- 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 = 8;
- }
- }
-
- ph = newElfPhdr();
- ph->type = PT_GNU_STACK;
- ph->flags = PF_W+PF_R;
- ph->align = 8;
-
- sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
- sh->type = SHT_STRTAB;
- sh->addralign = 1;
- shsym(sh, lookup(".shstrtab", 0));
-
- 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 = 8;
- sh->entsize = 24;
- 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();
- }
-
- /* Main header */
- eh->ident[EI_MAG0] = '\177';
- eh->ident[EI_MAG1] = 'E';
- eh->ident[EI_MAG2] = 'L';
- 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;
- eh->ident[EI_DATA] = ELFDATA2LSB;
- eh->ident[EI_VERSION] = EV_CURRENT;
-
- eh->type = ET_EXEC;
- eh->machine = EM_X86_64;
- eh->version = EV_CURRENT;
- eh->entry = entryvalue();
-
- pph->filesz = eh->phnum * eh->phentsize;
- pph->memsz = pph->filesz;
-
- cseek(0);
- a = 0;
- a += elfwritehdr();
- a += elfwritephdrs();
- a += elfwriteshdrs();
- a += elfwriteinterp(elfstr[ElfStrInterp]);
- if(HEADTYPE == Hnetbsd)
- a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
- if(a > ELFRESERVE)
- diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
+ asmbelf(symo);
break;
case Hwindows:
asmbpe();
@@ -1153,78 +793,3 @@ rnd(vlong v, vlong r)
v -= c;
return v;
}
-
-void
-genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
-{
- Auto *a;
- Sym *s;
-
- s = lookup("etext", 0);
- if(s->type == STEXT)
- put(s, s->name, 'T', s->value, s->size, s->version, 0);
-
- for(s=allsym; s!=S; s=s->allsym) {
- if(s->hide)
- continue;
- switch(s->type&~SSUB) {
- case SCONST:
- case SRODATA:
- case SSYMTAB:
- case SPCLNTAB:
- case SDATA:
- case SNOPTRDATA:
- case SELFROSECT:
- 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:
- 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;
-
- 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+8, 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 = %ud\n", symsize);
- Bflush(&bso);
-}