diff options
Diffstat (limited to 'src/cmd/6l/asm.c')
-rw-r--r-- | src/cmd/6l/asm.c | 643 |
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); -} |