{
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);
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;
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;
}
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);
ph->filesz = w;
ph->memsz = w;
ph->align = INITRND;
- elf64phdr(ph);
fo = rnd(fo+w, INITRND);
va = rnd(va+w, INITRND);
ph->filesz = w;
ph->memsz = w+bsssize;
ph->align = INITRND;
- elf64phdr(ph);
if(!debug['s']) {
ph = newElf64PHdr();
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;
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;
}
#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)
{
lputl(e->info);
vputl(e->addralign);
vputl(e->entsize);
-
- if(name != nil)
- stroffset += strlen(name)+1;
}
int
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)
a = 64; /* a.out header */
+ /* TODO: calculate these byte counts properly */
a += 56; /* page zero seg */
a += 56; /* text seg */
a += 56; /* stack seg */
return a;
}
-Elf64SHdr*
-newElf64SHdr()
+void
+elf64writeshdrs(void)
{
- Elf64SHdr *e;
+ int i;
- e = malloc(sizeof *e);
- memset(e, 0, sizeof *e);
- e->name = stroffset;
- return e;
+ 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()
+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(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;
+}