diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c index e6c499fbf3..2fdae8b3c1 100644 --- a/src/cmd/6l/asm.c +++ b/src/cmd/6l/asm.c @@ -122,16 +122,13 @@ asmb(void) { Prog *p; int32 v, magic; - int a, nl, np; + int a, nl; uchar *op1; vlong vl, va, fo, w, symo; - int strtabsize; vlong symdatva = 0x99LL<<32; Elf64PHdr *ph; Elf64SHdr *sh; - strtabsize = 0; - if(debug['v']) Bprint(&bso, "%5.2f asmb\n", cputime()); Bflush(&bso); @@ -196,9 +193,6 @@ asmb(void) case 7: debug['8'] = 1; /* 64-bit addresses */ - seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0); - strtabsize = elf64strtable(); - cflush(); v = rnd(HEADR+textsize, INITRND); seek(cout, v, 0); break; @@ -241,7 +235,7 @@ asmb(void) symo = rnd(HEADR+textsize, INITRND)+rnd(datsize, INITRND); break; case 7: - symo = rnd(HEADR+textsize, INITRND)+datsize+strtabsize; + symo = rnd(HEADR+textsize, INITRND)+datsize+STRTABSIZE; symo = rnd(symo, INITRND); break; } @@ -421,31 +415,6 @@ asmb(void) break; case 7: /* elf amd-64 */ - strnput("\177ELF", 4); /* e_ident */ - cput(2); /* class = 64 bit */ - cput(1); /* data = LSB */ - cput(1); /* version = CURRENT */ - strnput("", 9); - - wputl(2); /* type = EXEC */ - wputl(62); /* machine = AMD64 */ - lputl(1L); /* version = CURRENT */ - vputl(entryvalue()); /* entry vaddr */ - vputl(64L); /* offset to first phdr */ - np = 3; - if(!debug['s']) - np++; - vputl(64L+56*np); /* offset to first shdr */ - lputl(0L); /* processor specific flags */ - wputl(64); /* Ehdr size */ - wputl(56); /* Phdr size */ - wputl(np); /* # of Phdrs */ - wputl(64); /* Shdr size */ - if (!debug['s']) - wputl(7); /* # of Shdrs */ - else - wputl(5); /* # of Shdrs */ - wputl(4); /* Shdr with strings */ fo = 0; va = INITTEXT & ~((vlong)INITRND - 1); @@ -459,7 +428,6 @@ asmb(void) ph->filesz = w; ph->memsz = w; ph->align = INITRND; - elf64phdr(ph); fo = rnd(fo+w, INITRND); va = rnd(va+w, INITRND); @@ -474,7 +442,6 @@ asmb(void) ph->filesz = w; ph->memsz = w+bsssize; ph->align = INITRND; - elf64phdr(ph); if(!debug['s']) { ph = newElf64PHdr(); @@ -486,66 +453,59 @@ asmb(void) ph->filesz = 8+symsize+lcsize; ph->memsz = 8+symsize+lcsize; ph->align = INITRND; - elf64phdr(ph); } ph = newElf64PHdr(); ph->type = 0x6474e551; /* gok */ ph->flags = PF_X+PF_W+PF_R; ph->align = 8; - elf64phdr(ph); - sh = newElf64SHdr(); - elf64shdr(nil, sh); + sh = newElf64SHdr(""); stroffset = 1; /* 0 means no name, so start at 1 */ fo = HEADR; va = (INITTEXT & ~((vlong)INITRND - 1)) + HEADR; w = textsize; - sh = newElf64SHdr(); + sh = newElf64SHdr(".text"); sh->type = SHT_PROGBITS; sh->flags = SHF_ALLOC+SHF_EXECINSTR; sh->addr = va; sh->off = fo; sh->size = w; sh->addralign = 8; - elf64shdr(".text", sh); fo = rnd(fo+w, INITRND); va = rnd(va+w, INITRND); w = datsize; - sh = newElf64SHdr(); + sh = newElf64SHdr(".data"); sh->type = SHT_PROGBITS; sh->flags = SHF_WRITE+SHF_ALLOC; sh->addr = va; sh->off = fo; sh->size = w; sh->addralign = 8; - elf64shdr(".data", sh); fo += w; va += w; w = bsssize; - sh = newElf64SHdr(); + sh = newElf64SHdr(".bss"); sh->type = SHT_NOBITS; sh->flags = SHF_WRITE+SHF_ALLOC; sh->addr = va; sh->off = fo; sh->size = w; sh->addralign = 8; - elf64shdr(".bss", sh); - w = strtabsize; + w = STRTABSIZE; - sh = newElf64SHdr(); + sh = newElf64SHdr(".shstrtab"); sh->type = SHT_STRTAB; sh->off = fo; sh->size = w; sh->addralign = 1; - elf64shdr(".shstrtab", sh); if (debug['s']) break; @@ -553,24 +513,52 @@ asmb(void) fo = symo+8; w = symsize; - sh = newElf64SHdr(); + sh = newElf64SHdr(".gosymtab"); sh->type = SHT_PROGBITS; sh->off = fo; sh->size = w; sh->addralign = 1; sh->entsize = 24; - elf64shdr(".gosymtab", sh); fo += w; w = lcsize; - sh = newElf64SHdr(); + sh = newElf64SHdr(".gopclntab"); sh->type = SHT_PROGBITS; sh->off = fo; sh->size = w; sh->addralign = 1; sh->entsize = 24; - elf64shdr(".gopclntab", sh); + + // write out the main header */ + strnput("\177ELF", 4); /* e_ident */ + cput(2); /* class = 64 bit */ + cput(1); /* data = LSB */ + cput(1); /* version = CURRENT */ + strnput("", 9); + + wputl(2); /* type = EXEC */ + wputl(62); /* machine = AMD64 */ + lputl(1L); /* version = CURRENT */ + vputl(entryvalue()); /* entry vaddr */ + vputl(64L); /* offset to first phdr */ + vputl(64L+56*nume64phdr); /* offset to first shdr */ + lputl(0L); /* processor specific flags */ + wputl(64); /* Ehdr size */ + wputl(56); /* Phdr size */ + wputl(nume64phdr); /* # of Phdrs */ + wputl(64); /* Shdr size */ + wputl(nume64shdr); /* # of Shdrs */ + wputl(4); /* Shdr with strings */ + + elf64writephdrs(); + elf64writeshdrs(); + cflush(); + + /* string table */ + seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0); + elf64writestrtable(); + cflush(); break; } diff --git a/src/cmd/ld/elf64.c b/src/cmd/ld/elf64.c index ba30f65522..647becd97d 100644 --- a/src/cmd/ld/elf64.c +++ b/src/cmd/ld/elf64.c @@ -6,6 +6,15 @@ #include "../ld/elf64.h" +#define NSECT 16 +int nume64phdr; +int nume64shdr; +int nume64str; +static Elf64PHdr *phdr[NSECT]; +static Elf64SHdr *shdr[NSECT]; +static char *sname[NSECT]; +static char *str[NSECT]; + void elf64phdr(Elf64PHdr *e) { @@ -32,9 +41,6 @@ elf64shdr(char *name, Elf64SHdr *e) lputl(e->info); vputl(e->addralign); vputl(e->entsize); - - if(name != nil) - stroffset += strlen(name)+1; } int @@ -47,25 +53,29 @@ putelf64strtab(char* name) return w; } - -int -elf64strtable(void) +void +elf64writestrtable(void) { + int i; int size; size = 0; - size += putelf64strtab(""); - size += putelf64strtab(".text"); - size += putelf64strtab(".data"); - size += putelf64strtab(".bss"); - size += putelf64strtab(".shstrtab"); - if (!debug['s']) { - size += putelf64strtab(".gosymtab"); - size += putelf64strtab(".gopclntab"); - } - return size; + for (i = 0; i < nume64str; i++) + size += putelf64strtab(str[i]); + if (size > STRTABSIZE) + diag("elf64 string table overflow"); } +void +e64addstr(char *name) +{ + if (nume64str >= NSECT) { + diag("too many elf strings"); + return; + } + str[nume64str++] = strdup(name); + stroffset += strlen(name)+1; +} uint32 elf64headr(void) @@ -74,6 +84,7 @@ elf64headr(void) a = 64; /* a.out header */ + /* TODO: calculate these byte counts properly */ a += 56; /* page zero seg */ a += 56; /* text seg */ a += 56; /* stack seg */ @@ -92,25 +103,51 @@ elf64headr(void) return a; } +void +elf64writeshdrs(void) +{ + int i; + + for (i = 0; i < nume64shdr; i++) + elf64shdr(sname[i], shdr[i]); +} + +void +elf64writephdrs(void) +{ + int i; + + for (i = 0; i < nume64phdr; i++) + elf64phdr(phdr[i]); +} + +Elf64PHdr* +newElf64PHdr(void) +{ + Elf64PHdr *e; + + e = malloc(sizeof *e); + memset(e, 0, sizeof *e); + if (nume64phdr >= NSECT) + diag("too many phdrs"); + else + phdr[nume64phdr++] = e; + return e; +} + Elf64SHdr* -newElf64SHdr() +newElf64SHdr(char *name) { Elf64SHdr *e; e = malloc(sizeof *e); memset(e, 0, sizeof *e); e->name = stroffset; + if (nume64shdr >= NSECT) { + diag("too many shdrs"); + } else { + e64addstr(name); + shdr[nume64shdr++] = e; + } return e; } - - -Elf64PHdr* -newElf64PHdr() -{ - Elf64PHdr *e; - - e = malloc(sizeof *e); - memset(e, 0, sizeof *e); - return e; -} - diff --git a/src/cmd/ld/elf64.h b/src/cmd/ld/elf64.h index 07d3cd68a6..34348a1dbc 100644 --- a/src/cmd/ld/elf64.h +++ b/src/cmd/ld/elf64.h @@ -132,9 +132,14 @@ struct Elf64SHdr #define SHF_MASKOS 0x0F000000 /* Environment-specific use */ #define SHF_MASKPROC 0xF0000000 /* Processor-specific use */ -Elf64SHdr *newElf64SHdr(); +Elf64SHdr *newElf64SHdr(char*); Elf64PHdr *newElf64PHdr(); uint32 elf64headr(void); -void elf64phdr(Elf64PHdr*); -void elf64shdr(char*, Elf64SHdr*); -int elf64strtable(void); +void elf64writephdrs(void); +void elf64writeshdrs(void); +void elf64writestrtable(void); + +extern int nume64phdr; +extern int nume64shdr; + +#define STRTABSIZE 256