diff options
Diffstat (limited to 'src/cmd/8l/asm.c')
-rw-r--r-- | src/cmd/8l/asm.c | 97 |
1 files changed, 44 insertions, 53 deletions
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c index e1ccfb8a3..22abd8049 100644 --- a/src/cmd/8l/asm.c +++ b/src/cmd/8l/asm.c @@ -519,7 +519,7 @@ doelf(void) /* predefine strings we need for section headers */ shstrtab = lookup(".shstrtab", 0); - shstrtab->type = SELFDATA; + shstrtab->type = SELFROSECT; shstrtab->reachable = 1; elfstr[ElfStrEmpty] = addstring(shstrtab, ""); @@ -551,21 +551,16 @@ doelf(void) 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->type = SELFROSECT; s->reachable = 1; s->size += ELF32SYMSIZE; /* dynamic string table */ s = lookup(".dynstr", 0); s->reachable = 1; - s->type = SELFDATA; + s->type = SELFROSECT; if(s->size == 0) addstring(s, ""); dynstr = s; @@ -573,45 +568,45 @@ doelf(void) /* relocation table */ s = lookup(".rel", 0); s->reachable = 1; - s->type = SELFDATA; + s->type = SELFROSECT; /* global offset table */ s = lookup(".got", 0); s->reachable = 1; - s->type = SDATA; // writable, so not SELFDATA + s->type = SELFSECT; // writable /* hash */ s = lookup(".hash", 0); s->reachable = 1; - s->type = SELFDATA; + s->type = SELFROSECT; /* got.plt */ s = lookup(".got.plt", 0); s->reachable = 1; - s->type = SDATA; // writable, so not SELFDATA + s->type = SELFSECT; // writable s = lookup(".plt", 0); s->reachable = 1; - s->type = SELFDATA; + s->type = SELFROSECT; s = lookup(".rel.plt", 0); s->reachable = 1; - s->type = SELFDATA; + s->type = SELFROSECT; s = lookup(".gnu.version", 0); s->reachable = 1; - s->type = SELFDATA; + s->type = SELFROSECT; s = lookup(".gnu.version_r", 0); s->reachable = 1; - s->type = SELFDATA; + s->type = SELFROSECT; elfsetupplt(); /* define dynamic elf table */ s = lookup(".dynamic", 0); s->reachable = 1; - s->type = SELFDATA; + s->type = SELFROSECT; /* * .dynamic table @@ -638,8 +633,11 @@ doelf(void) void shsym(Elf64_Shdr *sh, Sym *s) { - sh->addr = symaddr(s); - sh->off = datoff(sh->addr); + vlong addr; + addr = symaddr(s); + if(sh->flags&SHF_ALLOC) + sh->addr = addr; + sh->off = datoff(addr); sh->size = s->size; } @@ -665,6 +663,7 @@ asmb(void) ElfShdr *sh; Section *sect; Sym *sym; + int o; int i; if(debug['v']) @@ -672,12 +671,12 @@ asmb(void) Bflush(&bso); sect = segtext.sect; - seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0); + cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); 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); + cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); datblk(sect->vaddr, sect->len); } @@ -685,7 +684,7 @@ asmb(void) Bprint(&bso, "%5.2f datblk\n", cputime()); Bflush(&bso); - seek(cout, segdata.fileoff, 0); + cseek(segdata.fileoff); datblk(segdata.vaddr, segdata.filelen); machlink = 0; @@ -695,7 +694,7 @@ asmb(void) if(iself) { /* index of elf text section; needed by asmelfsym, double-checked below */ /* !debug['d'] causes extra sections before the .text section */ - elftextsh = 1; + elftextsh = 2; if(!debug['d']) { elftextsh += 10; if(elfverneed) @@ -742,7 +741,7 @@ asmb(void) symo = rnd(symo, PEFILEALIGN); break; } - seek(cout, symo, 0); + cseek(symo); switch(HEADTYPE) { default: if(iself) { @@ -750,7 +749,7 @@ asmb(void) Bprint(&bso, "%5.2f elfsym\n", cputime()); asmelfsym(); cflush(); - ewrite(cout, elfstrdat, elfstrsize); + cwrite(elfstrdat, elfstrsize); if(debug['v']) Bprint(&bso, "%5.2f dwarf\n", cputime()); @@ -781,7 +780,7 @@ asmb(void) if(debug['v']) Bprint(&bso, "%5.2f headr\n", cputime()); Bflush(&bso); - seek(cout, 0L, 0); + cseek(0L); switch(HEADTYPE) { default: if(iself) @@ -932,6 +931,17 @@ asmb(void) 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]); @@ -1072,6 +1082,11 @@ asmb(void) ph->flags = PF_W+PF_R; ph->align = 4; + 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) @@ -1097,11 +1112,6 @@ asmb(void) 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'; @@ -1126,13 +1136,13 @@ asmb(void) pph->memsz = pph->filesz; } - seek(cout, 0, 0); + cseek(0); a = 0; a += elfwritehdr(); a += elfwritephdrs(); a += elfwriteshdrs(); cflush(); - if(a+elfwriteinterp() > ELFRESERVE) + if(a+elfwriteinterp() > ELFRESERVE) diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE); break; @@ -1154,25 +1164,6 @@ s8put(char *n) 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) { @@ -1207,7 +1198,7 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*)) case SCONST: case SRODATA: case SDATA: - case SELFDATA: + case SELFROSECT: case SMACHO: case SMACHOGOT: case STYPE: |