diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c index b1672f6a35d..3679e5cf405 100644 --- a/src/cmd/6l/asm.c +++ b/src/cmd/6l/asm.c @@ -113,126 +113,6 @@ vputl(uint64 v) lputl(v>>32); } -void -strnput(char *s, int n) -{ - int i; - - for(i=0; i= '0' && *a <= '9') - return atolwhex(a); - s = lookup(a, 0); - if(s->type == 0) - return INITTEXT; - switch(s->type) { - case STEXT: - break; - case SDATA: - if(dlm) - return s->value+INITDAT; - default: - diag("entry not text: %s", s->name); - } - return s->value; -} - -void -wputl(uint16 w) -{ - cput(w); - cput(w>>8); -} - -void -wputb(uint16 w) -{ - cput(w>>8); - cput(w); -} - -void -lputb(int32 l) -{ - cput(l>>24); - cput(l>>16); - cput(l>>8); - cput(l); -} - -void -vputb(uint64 v) -{ - lputb(v>>32); - lputb(v); -} - -void -lputl(int32 l) -{ - cput(l); - cput(l>>8); - cput(l>>16); - cput(l>>24); -} - -void -vputl(uint64 v) -{ - lputl(v); - lputl(v>>32); -} - void strnput(char *s, int n) { @@ -1373,1156 +1253,6 @@ datblk(int32 s, int32 n) } } -vlong -rnd(vlong v, vlong r) -{ - vlong c; - - if(r <= 0) - return v; - v += r - 1; - c = v % r; - if(c < 0) - c += r; - v -= c; - return v; -} - - - cput(*s); - if(*s != 0) - s++; - } -} - -vlong -addstring(Sym *s, char *str) -{ - int n, m; - vlong r; - Prog *p; - - if(s->type == 0) - s->type = SDATA; - s->reachable = 1; - r = s->value; - n = strlen(str)+1; - while(n > 0) { - m = n; - if(m > sizeof(p->to.scon)) - m = sizeof(p->to.scon); - p = newdata(s, s->value, m, D_EXTERN); - p->to.type = D_SCONST; - memmove(p->to.scon, str, m); - s->value += m; - str += m; - n -= m; - } - return r; -} - -vlong -adduintxx(Sym *s, uint64 v, int wid) -{ - vlong r; - Prog *p; - - if(s->type == 0) - s->type = SDATA; - s->reachable = 1; - r = s->value; - p = newdata(s, s->value, wid, D_EXTERN); - s->value += wid; - p->to.type = D_CONST; - p->to.offset = v; - return r; -} - -vlong -adduint8(Sym *s, uint8 v) -{ - return adduintxx(s, v, 1); -} - -vlong -adduint16(Sym *s, uint16 v) -{ - return adduintxx(s, v, 2); -} - -vlong -adduint32(Sym *s, uint32 v) -{ - return adduintxx(s, v, 4); -} - -vlong -adduint64(Sym *s, uint64 v) -{ - return adduintxx(s, v, 8); -} - -vlong -addaddr(Sym *s, Sym *t) -{ - vlong r; - Prog *p; - enum { Ptrsize = 8 }; - - if(s->type == 0) - s->type = SDATA; - s->reachable = 1; - r = s->value; - p = newdata(s, s->value, Ptrsize, D_EXTERN); - s->value += Ptrsize; - p->to.type = D_ADDR; - p->to.index = D_EXTERN; - p->to.offset = 0; - p->to.sym = t; - return r; -} - -vlong -addsize(Sym *s, Sym *t) -{ - vlong r; - Prog *p; - enum { Ptrsize = 8 }; - - if(s->type == 0) - s->type = SDATA; - s->reachable = 1; - r = s->value; - p = newdata(s, s->value, Ptrsize, D_EXTERN); - s->value += Ptrsize; - p->to.type = D_SIZE; - p->to.index = D_EXTERN; - p->to.offset = 0; - p->to.sym = t; - return r; -} - -vlong -datoff(vlong addr) -{ - if(addr >= INITDAT) - return addr - INITDAT + rnd(HEADR+textsize, INITRND); - diag("datoff %#llx", addr); - return 0; -} - -enum { - ElfStrEmpty, - ElfStrInterp, - ElfStrHash, - ElfStrGot, - ElfStrGotPlt, - ElfStrDynamic, - ElfStrDynsym, - ElfStrDynstr, - ElfStrRela, - ElfStrText, - ElfStrData, - ElfStrBss, - ElfStrGosymtab, - ElfStrGopclntab, - ElfStrShstrtab, - ElfStrSymtab, - ElfStrStrtab, - NElfStr -}; - -vlong elfstr[NElfStr]; - -static int -needlib(char *name) -{ - char *p; - Sym *s; - - /* reuse hash code in symbol table */ - p = smprint(".elfload.%s", name); - s = lookup(p, 0); - if(s->type == 0) { - s->type = 100; // avoid SDATA, etc. - return 1; - } - return 0; -} - -void -doelf(void) -{ - Sym *s, *shstrtab, *dynamic, *dynstr, *d; - int h, nsym, t; - - if(HEADTYPE != 7 && HEADTYPE != 9) - return; - - /* predefine strings we need for section headers */ - shstrtab = lookup(".shstrtab", 0); - elfstr[ElfStrEmpty] = addstring(shstrtab, ""); - elfstr[ElfStrText] = addstring(shstrtab, ".text"); - elfstr[ElfStrData] = addstring(shstrtab, ".data"); - elfstr[ElfStrBss] = addstring(shstrtab, ".bss"); - if(!debug['s']) { - elfstr[ElfStrGosymtab] = addstring(shstrtab, ".gosymtab"); - elfstr[ElfStrGopclntab] = addstring(shstrtab, ".gopclntab"); - if(debug['e']) { - elfstr[ElfStrSymtab] = addstring(shstrtab, ".symtab"); - elfstr[ElfStrStrtab] = addstring(shstrtab, ".strtab"); - } - } - 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"); - - /* interpreter string */ - s = lookup(".interp", 0); - s->reachable = 1; - s->type = SDATA; // TODO: rodata - switch(HEADTYPE) { - case 7: - addstring(lookup(".interp", 0), linuxdynld); - break; - case 9: - addstring(lookup(".interp", 0), freebsddynld); - break; - } - - /* - * hash table. - * only entries that other objects need to find when - * linking us need to be in the table. right now that is - * no entries. - * - * must have at least 1 bucket, though, to avoid - * a divide by zero bug in some copies of the glibc - * dynamic loader. - */ - s = lookup(".hash", 0); - s->type = SDATA; // TODO: rodata - s->reachable = 1; - adduint32(s, 1); // nbucket - adduint32(s, 1); // nchain - adduint32(s, 0); // bucket 0 - adduint32(s, 0); // chain 0 - - /* dynamic symbol table - first entry all zeros */ - s = lookup(".dynsym", 0); - s->type = SDATA; - s->reachable = 1; - s->value += ELF64SYMSIZE; - - /* dynamic string table */ - s = lookup(".dynstr", 0); - addstring(s, ""); - dynstr = s; - - /* relocation table */ - s = lookup(".rela", 0); - s->reachable = 1; - s->type = SDATA; - - /* global offset table */ - s = lookup(".got", 0); - s->reachable = 1; - s->type = SDATA; - - /* got.plt - ??? */ - s = lookup(".got.plt", 0); - s->reachable = 1; - s->type = SDATA; - - /* define dynamic elf table */ - s = lookup(".dynamic", 0); - dynamic = s; - - /* - * relocation entries for dynld symbols - */ - nsym = 1; // sym 0 is reserved - for(h=0; hlink) { - if(!s->reachable || (s->type != SDATA && s->type != SBSS) || s->dynldname == nil) - continue; - - d = lookup(".rela", 0); - addaddr(d, s); - adduint64(d, ELF64_R_INFO(nsym, R_X86_64_64)); - adduint64(d, 0); - nsym++; - - d = lookup(".dynsym", 0); - adduint32(d, addstring(lookup(".dynstr", 0), s->dynldname)); - t = STB_GLOBAL << 4; - t |= STT_OBJECT; // works for func too, empirically - adduint8(d, t); - adduint8(d, 0); /* reserved */ - adduint16(d, SHN_UNDEF); /* section where symbol is defined */ - adduint64(d, 0); /* value */ - adduint64(d, 0); /* size of object */ - - if(needlib(s->dynldlib)) - elfwritedynent(dynamic, DT_NEEDED, addstring(dynstr, s->dynldlib)); - } - } - - /* - * .dynamic table - */ - s = dynamic; - 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); - elfwritedynent(s, DT_NULL, 0); - } -} - -void -shsym(ElfShdr *sh, Sym *s) -{ - sh->addr = symaddr(s); - sh->off = datoff(sh->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) -{ - Prog *p; - int32 v, magic; - int a, dynsym; - uchar *op1; - vlong vl, va, startva, fo, w, symo, elfsymo, elfstro, elfsymsize, machlink; - vlong symdatva = 0x99LL<<32; - ElfEhdr *eh; - ElfPhdr *ph, *pph; - ElfShdr *sh; - - if(debug['v']) - Bprint(&bso, "%5.2f asmb\n", cputime()); - Bflush(&bso); - - elftextsh = 0; - elfsymsize = 0; - elfstro = 0; - elfsymo = 0; - seek(cout, HEADR, 0); - pc = INITTEXT; - curp = firstp; - for(p = firstp; p != P; p = p->link) { - if(p->as == ATEXT) - curtext = p; - if(p->pc != pc) { - if(!debug['a']) - print("%P\n", curp); - diag("phase error %llux sb %llux in %s", p->pc, pc, TNAME); - pc = p->pc; - } - curp = p; - asmins(p); - a = (andptr - and); - if(cbc < a) - cflush(); - if(debug['a']) { - Bprint(&bso, pcstr, pc); - for(op1 = and; op1 < andptr; op1++) - Bprint(&bso, "%.2ux", *op1); - for(; op1 < and+Maxand; op1++) - Bprint(&bso, " "); - Bprint(&bso, "%P\n", curp); - } - if(dlm) { - if(p->as == ATEXT) - reloca = nil; - else if(reloca != nil) - diag("reloc failure: %P", curp); - } - memmove(cbp, and, a); - cbp += a; - pc += a; - cbc -= a; - } - cflush(); - - - switch(HEADTYPE) { - default: - diag("unknown header type %ld", HEADTYPE); - case 2: - case 5: - seek(cout, HEADR+textsize, 0); - break; - case 6: - debug['8'] = 1; /* 64-bit addresses */ - v = HEADR+textsize; - seek(cout, v, 0); - v = rnd(v, 4096) - v; - while(v > 0) { - cput(0); - v--; - } - cflush(); - break; - - case 7: - case 9: - debug['8'] = 1; /* 64-bit addresses */ - v = rnd(HEADR+textsize, INITRND); - seek(cout, v, 0); - - /* index of elf text section; needed by asmelfsym, double-checked below */ - /* debug['d'] causes 8 extra sections before the .text section */ - elftextsh = 1; - if(!debug['d']) - elftextsh += 8; - break; - } - - if(debug['v']) - Bprint(&bso, "%5.2f datblk\n", cputime()); - Bflush(&bso); - - if(dlm){ - char buf[8]; - - write(cout, buf, INITDAT-textsize); - textsize = INITDAT; - } - - datap = datsort(datap); - for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) { - if(datsize-v > sizeof(buf)-Dbufslop) - datblk(v, sizeof(buf)-Dbufslop); - else - datblk(v, datsize-v); - } - - machlink = 0; - if(HEADTYPE == 6) - machlink = domacholink(); - - symsize = 0; - spsize = 0; - lcsize = 0; - symo = 0; - if(!debug['s']) { - if(debug['v']) - Bprint(&bso, "%5.2f sym\n", cputime()); - Bflush(&bso); - switch(HEADTYPE) { - default: - case 2: - case 5: - debug['s'] = 1; - symo = HEADR+textsize+datsize; - break; - case 6: - symo = rnd(HEADR+textsize, INITRND)+rnd(datsize, INITRND)+machlink; - break; - case 7: - case 9: - symo = rnd(HEADR+textsize, INITRND)+datsize; - symo = rnd(symo, INITRND); - break; - } - /* - * the symbol information is stored as - * 32-bit symbol table size - * 32-bit line number table size - * symbol table - * line number table - */ - seek(cout, symo+8, 0); - if(!debug['s']) - asmsym(); - if(debug['v']) - Bprint(&bso, "%5.2f sp\n", cputime()); - Bflush(&bso); - if(debug['v']) - Bprint(&bso, "%5.2f pc\n", cputime()); - Bflush(&bso); - if(!debug['s']) - asmlc(); - if(dlm) - asmdyn(); - cflush(); - seek(cout, symo, 0); - lputl(symsize); - lputl(lcsize); - cflush(); - if(!debug['s'] && debug['e']) { - elfsymo = symo+8+symsize+lcsize; - seek(cout, elfsymo, 0); - asmelfsym(); - cflush(); - elfstro = seek(cout, 0, 1); - elfsymsize = elfstro - elfsymo; - write(cout, elfstrdat, elfstrsize); - } - } else - if(dlm){ - seek(cout, HEADR+textsize+datsize, 0); - asmdyn(); - cflush(); - } - - if(debug['v']) - Bprint(&bso, "%5.2f headr\n", cputime()); - Bflush(&bso); - seek(cout, 0L, 0); - switch(HEADTYPE) { - default: - case 2: /* plan9 */ - magic = 4*26*26+7; - magic |= 0x00008000; /* fat header */ - if(dlm) - magic |= 0x80000000; /* dlm */ - lputb(magic); /* magic */ - lputb(textsize); /* sizes */ - lputb(datsize); - lputb(bsssize); - lputb(symsize); /* nsyms */ - vl = entryvalue(); - lputb(PADDR(vl)); /* va of entry */ - lputb(spsize); /* sp offsets */ - lputb(lcsize); /* line offsets */ - vputb(vl); /* va of entry */ - break; - case 3: /* plan9 */ - magic = 4*26*26+7; - if(dlm) - magic |= 0x80000000; - lputb(magic); /* magic */ - lputb(textsize); /* sizes */ - lputb(datsize); - lputb(bsssize); - lputb(symsize); /* nsyms */ - lputb(entryvalue()); /* va of entry */ - lputb(spsize); /* sp offsets */ - lputb(lcsize); /* line offsets */ - break; - case 6: - asmbmacho(symdatva, symo); - break; - case 7: - case 9: - /* elf amd-64 */ - - eh = getElfEhdr(); - fo = HEADR; - startva = INITTEXT - HEADR; - va = startva + fo; - w = textsize; - - /* This null SHdr must appear before all others */ - sh = 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; - shsym(sh, lookup(".interp", 0)); - - ph = newElfPhdr(); - ph->type = PT_INTERP; - ph->flags = PF_R; - phsh(ph, sh); - } - - ph = newElfPhdr(); - ph->type = PT_LOAD; - ph->flags = PF_X+PF_R; - ph->vaddr = va; - ph->paddr = va; - ph->off = fo; - ph->filesz = w; - ph->memsz = w; - ph->align = INITRND; - - fo = rnd(fo+w, INITRND); - va = rnd(va+w, INITRND); - w = datsize; - - ph = newElfPhdr(); - ph->type = PT_LOAD; - ph->flags = PF_W+PF_R; - ph->off = fo; - ph->vaddr = va; - ph->paddr = va; - ph->filesz = w; - ph->memsz = w+bsssize; - ph->align = INITRND; - - if(!debug['s']) { - ph = newElfPhdr(); - ph->type = PT_LOAD; - ph->flags = PF_W+PF_R; - ph->off = symo; - ph->vaddr = symdatva; - ph->paddr = symdatva; - ph->filesz = 8+symsize+lcsize; - ph->memsz = 8+symsize+lcsize; - ph->align = INITRND; - } - - /* 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)); - - 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); - } - - ph = newElfPhdr(); - ph->type = PT_GNU_STACK; - ph->flags = PF_W+PF_R; - ph->align = 8; - - fo = ELFRESERVE; - va = startva + fo; - w = textsize; - - if(elftextsh != eh->shnum) - diag("elftextsh = %d, want %d", elftextsh, eh->shnum); - sh = newElfShdr(elfstr[ElfStrText]); - sh->type = SHT_PROGBITS; - sh->flags = SHF_ALLOC+SHF_EXECINSTR; - sh->addr = va; - sh->off = fo; - sh->size = w; - sh->addralign = 8; - - fo = rnd(fo+w, INITRND); - va = rnd(va+w, INITRND); - w = datsize; - - sh = newElfShdr(elfstr[ElfStrData]); - sh->type = SHT_PROGBITS; - sh->flags = SHF_WRITE+SHF_ALLOC; - sh->addr = va; - sh->off = fo; - sh->size = w; - sh->addralign = 8; - - fo += w; - va += w; - w = bsssize; - - sh = newElfShdr(elfstr[ElfStrBss]); - sh->type = SHT_NOBITS; - sh->flags = SHF_WRITE+SHF_ALLOC; - sh->addr = va; - sh->off = fo; - sh->size = w; - sh->addralign = 8; - - if (!debug['s']) { - fo = symo+8; - w = symsize; - - sh = newElfShdr(elfstr[ElfStrGosymtab]); - sh->type = SHT_PROGBITS; - sh->off = fo; - sh->size = w; - sh->addralign = 1; - - fo += w; - w = lcsize; - - sh = newElfShdr(elfstr[ElfStrGopclntab]); - sh->type = SHT_PROGBITS; - sh->off = fo; - sh->size = w; - sh->addralign = 1; - - if(debug['e']) { - sh = newElfShdr(elfstr[ElfStrSymtab]); - sh->type = SHT_SYMTAB; - sh->off = elfsymo; - sh->size = elfsymsize; - sh->addralign = 8; - sh->entsize = 24; - sh->link = eh->shnum; // link to strtab - - sh = newElfShdr(elfstr[ElfStrStrtab]); - sh->type = SHT_STRTAB; - sh->off = elfstro; - sh->size = elfstrsize; - sh->addralign = 1; - } - } - - 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'; - if(HEADTYPE == 9) - eh->ident[EI_OSABI] = 9; - 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; - - seek(cout, 0, 0); - a = 0; - a += elfwritehdr(); - a += elfwritephdrs(); - a += elfwriteshdrs(); - if (a > ELFRESERVE) - diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE); - break; - } - cflush(); -} - -void -cflush(void) -{ - int n; - - n = sizeof(buf.cbuf) - cbc; - if(n) - write(cout, buf.cbuf, n); - cbp = buf.cbuf; - cbc = sizeof(buf.cbuf); -} - -void -outa(int n, uchar *cast, uchar *map, vlong l) -{ - int i, j; - - Bprint(&bso, pcstr, l); - for(i=0; ifrom.offset; - v2 = p2->from.offset; - if(v1 > v2) - return +1; - if(v1 < v2) - return -1; - return 0; -} - -Prog* -dsort(Prog *l) -{ - Prog *l1, *l2, *le; - - if(l == 0 || l->link == 0) - return l; - - l1 = l; - l2 = l; - for(;;) { - l2 = l2->link; - if(l2 == 0) - break; - l2 = l2->link; - if(l2 == 0) - break; - l1 = l1->link; - } - - l2 = l1->link; - l1->link = 0; - l1 = dsort(l); - l2 = dsort(l2); - - /* set up lead element */ - if(datcmp(l1, l2) < 0) { - l = l1; - l1 = l1->link; - } else { - l = l2; - l2 = l2->link; - } - le = l; - - for(;;) { - if(l1 == 0) { - while(l2) { - le->link = l2; - le = l2; - l2 = l2->link; - } - le->link = 0; - break; - } - if(l2 == 0) { - while(l1) { - le->link = l1; - le = l1; - l1 = l1->link; - } - break; - } - if(datcmp(l1, l2) < 0) { - le->link = l1; - le = l1; - l1 = l1->link; - } else { - le->link = l2; - le = l2; - l2 = l2->link; - } - } - le->link = 0; - return l; -} - -static Prog *datp; - -Prog* -datsort(Prog *l) -{ - Prog *p; - Adr *a; - - for(p = l; p != P; p = p->link) { - a = &p->from; - a->offset += a->sym->value; - } - datp = dsort(l); - return datp; -} - -void -datblk(int32 s, int32 n) -{ - Prog *p; - uchar *cast; - int32 l, fl, j; - vlong o; - int i, c; - Adr *a; - - for(p = datp; p != P; p = p->link) { - a = &p->from; - l = a->offset - s; - if(l+a->scale < 0) - continue; - datp = p; - break; - } - - memset(buf.dbuf, 0, n+Dbufslop); - for(p = datp; p != P; p = p->link) { - a = &p->from; - - l = a->offset - s; - if(l >= n) - break; - - c = a->scale; - i = 0; - if(l < 0) { - if(l+c <= 0) - continue; - i = -l; - l = 0; - } - - curp = p; - if(!a->sym->reachable) - diag("unreachable symbol in datblk - %s", a->sym->name); - if(a->sym->type == SMACHO) - continue; - - if(p->as != AINIT && p->as != ADYNT) { - for(j=l+(c-i)-1; j>=l; j--) - if(buf.dbuf[j]) { - print("%P\n", p); - diag("multiple initialization"); - break; - } - } - - switch(p->to.type) { - case D_FCONST: - switch(c) { - default: - case 4: - fl = ieeedtof(&p->to.ieee); - cast = (uchar*)&fl; - for(; ito.ieee; - for(; ito.scon[i]; - l++; - } - break; - - default: - o = p->to.offset; - if(p->to.type == D_SIZE) - o += p->to.sym->size; - if(p->to.type == D_ADDR) { - if(p->to.index != D_STATIC && p->to.index != D_EXTERN) - diag("DADDR type%P", p); - if(p->to.sym) { - if(p->to.sym->type == SUNDEF) - ckoff(p->to.sym, o); - if(p->to.sym->type == Sxxx) { - curtext = p; // show useful name in diag's output - diag("missing symbol %s", p->to.sym->name); - } - o += p->to.sym->value; - if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF) - o += INITDAT; - if(dlm) - dynreloc(p->to.sym, l+s+INITDAT, 1); - } - } - fl = o; - cast = (uchar*)&fl; - switch(c) { - default: - diag("bad nuxi %d %d\n%P", c, i, curp); - break; - case 1: - for(; ilink) { - a = &p->from; - - l = a->offset - s; - if(l >= n) - continue; - - c = a->scale; - i = 0; - if(l < 0) - continue; - - if(a->sym->type == SMACHO) - continue; - - switch(p->to.type) { - case D_FCONST: - switch(c) { - default: - case 4: - fl = ieeedtof(&p->to.ieee); - cast = (uchar*)&fl; - outa(c, cast, fnuxi4, l+s+INITDAT); - break; - case 8: - cast = (uchar*)&p->to.ieee; - outa(c, cast, fnuxi8, l+s+INITDAT); - break; - } - break; - - case D_SCONST: - outa(c, (uchar*)p->to.scon, nil, l+s+INITDAT); - break; - - default: - o = p->to.offset; - if(p->to.type == D_SIZE) - o += p->to.sym->size; - if(p->to.type == D_ADDR) { - if(p->to.sym) { - o += p->to.sym->value; - if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF) - o += INITDAT; - } - } - fl = o; - cast = (uchar*)&fl; - switch(c) { - case 1: - outa(c, cast, inuxi1, l+s+INITDAT); - break; - case 2: - outa(c, cast, inuxi2, l+s+INITDAT); - break; - case 4: - outa(c, cast, inuxi4, l+s+INITDAT); - break; - case 8: - cast = (uchar*)&o; - outa(c, cast, inuxi8, l+s+INITDAT); - break; - } - break; - } - } -} - vlong rnd(vlong v, vlong r) {