From 4e1896a1b54ec4315970e6770f394ecbb299b0a4 Mon Sep 17 00:00:00 2001 From: Kai Backman <kaib@golang.org> Date: Fri, 10 Apr 2009 16:35:36 -0700 Subject: [PATCH] Adding ARM elf support to the 5l linker. R=rsc APPROVED=rsc DELTA=312 (312 added, 0 deleted, 0 changed) OCL=27133 CL=27326 --- src/cmd/5l/asm.c | 292 +++++++++++++++++++++++++++++++++++++++++++++++ src/cmd/5l/l.h | 10 ++ src/cmd/5l/obj.c | 10 ++ 3 files changed, 312 insertions(+) diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c index 214c9adfd4..f0f3185a47 100644 --- a/src/cmd/5l/asm.c +++ b/src/cmd/5l/asm.c @@ -64,8 +64,15 @@ asmb(void) { Prog *p; int32 t, etext; + int np; + vlong va, fo, w, symo; + int strtabsize; + vlong symdatva = 0x99LL<<24; Optab *o; + strtabsize = 0; + symo = 0; + if(debug['v']) Bprint(&bso, "%5.2f asm\n", cputime()); Bflush(&bso); @@ -112,6 +119,7 @@ asmb(void) datblk(t, etext-t, 1); } + /* output section header strings */ curtext = P; switch(HEADTYPE) { case 0: @@ -125,6 +133,13 @@ asmb(void) OFFSET = rnd(HEADR+textsize, 4096); seek(cout, OFFSET, 0); break; + case 6: + seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0); + strtabsize = linuxstrtable(); + cflush(); + t = rnd(HEADR+textsize, INITRND); + seek(cout, t, 0); + break; } if(dlm){ char buf[8]; @@ -140,6 +155,7 @@ asmb(void) } cflush(); + /* output symbol table */ symsize = 0; lcsize = 0; if(!debug['s']) { @@ -161,6 +177,11 @@ asmb(void) OFFSET += rnd(datsize, 4096); seek(cout, OFFSET, 0); break; + case 6: + symo = rnd(HEADR+textsize, INITRND)+datsize+strtabsize; + symo = rnd(symo, INITRND); + seek(cout, symo + 8, 0); + break; } if(!debug['s']) asmsym(); @@ -251,6 +272,181 @@ asmb(void) lputl(0xe3300000); /* nop */ lputl(0xe3300000); /* nop */ break; + case 6: + /* elf arm */ + strnput("\177ELF", 4); /* e_ident */ + cput(1); /* class = 32 bit */ + cput(1); /* data = LSB */ + cput(1); /* version = CURRENT */ + strnput("", 9); + + wputl(2); /* type = EXEC */ + wputl(40); /* machine = ARM */ + lputl(1L); /* version = CURRENT */ + lputl(entryvalue()); /* entry vaddr */ + lputl(52L); /* offset to first phdr */ + np = 3; + if(!debug['s']) + np++; + lputl(52L+32*np); /* offset to first shdr */ + lputl(0L); /* processor specific flags */ + wputl(52); /* Ehdr size */ + wputl(32); /* Phdr size */ + wputl(np); /* # of Phdrs */ + wputl(40); /* 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); + w = HEADR+textsize; + + linuxphdr(1, /* text - type = PT_LOAD */ + 1L+4L, /* text - flags = PF_X+PF_R */ + 0, /* file offset */ + va, /* vaddr */ + va, /* paddr */ + w, /* file size */ + w, /* memory size */ + INITRND); /* alignment */ + + fo = rnd(fo+w, INITRND); + va = rnd(va+w, INITRND); + w = datsize; + + linuxphdr(1, /* data - type = PT_LOAD */ + 2L+4L, /* data - flags = PF_W+PF_R */ + fo, /* file offset */ + va, /* vaddr */ + va, /* paddr */ + w, /* file size */ + w+bsssize, /* memory size */ + INITRND); /* alignment */ + + if(!debug['s']) { + linuxphdr(1, /* data - type = PT_LOAD */ + 2L+4L, /* data - flags = PF_W+PF_R */ + symo, /* file offset */ + symdatva, /* vaddr */ + symdatva, /* paddr */ + 8+symsize+lcsize, /* file size */ + 8+symsize+lcsize, /* memory size */ + INITRND); /* alignment */ + } + + linuxphdr(0x6474e551, /* gok - type = gok */ + 1L+2L+4L, /* gok - flags = PF_X+PF_W+PF_R */ + 0, /* file offset */ + 0, /* vaddr */ + 0, /* paddr */ + 0, /* file size */ + 0, /* memory size */ + 8); /* alignment */ + + linuxshdr(nil, /* name */ + 0, /* type */ + 0, /* flags */ + 0, /* addr */ + 0, /* off */ + 0, /* size */ + 0, /* link */ + 0, /* info */ + 0, /* align */ + 0); /* entsize */ + + stroffset = 1; /* 0 means no name, so start at 1 */ + fo = HEADR; + va = (INITTEXT & ~((vlong)INITRND - 1)) + HEADR; + w = textsize; + + linuxshdr(".text", /* name */ + 1, /* type */ + 6, /* flags */ + va, /* addr */ + fo, /* off */ + w, /* size */ + 0, /* link */ + 0, /* info */ + 8, /* align */ + 0); /* entsize */ + + fo = rnd(fo+w, INITRND); + va = rnd(va+w, INITRND); + w = datsize; + + linuxshdr(".data", /* name */ + 1, /* type */ + 3, /* flags */ + va, /* addr */ + fo, /* off */ + w, /* size */ + 0, /* link */ + 0, /* info */ + 8, /* align */ + 0); /* entsize */ + + fo += w; + va += w; + w = bsssize; + + linuxshdr(".bss", /* name */ + 8, /* type */ + 3, /* flags */ + va, /* addr */ + fo, /* off */ + w, /* size */ + 0, /* link */ + 0, /* info */ + 8, /* align */ + 0); /* entsize */ + + w = strtabsize; + + linuxshdr(".shstrtab", /* name */ + 3, /* type */ + 0, /* flags */ + 0, /* addr */ + fo, /* off */ + w, /* size */ + 0, /* link */ + 0, /* info */ + 1, /* align */ + 0); /* entsize */ + + if (debug['s']) + break; + + fo = symo+8; + w = symsize; + + linuxshdr(".gosymtab", /* name */ + 1, /* type 1 = SHT_PROGBITS */ + 0, /* flags */ + 0, /* addr */ + fo, /* off */ + w, /* size */ + 0, /* link */ + 0, /* info */ + 1, /* align */ + 24); /* entsize */ + + fo += w; + w = lcsize; + + linuxshdr(".gopclntab", /* name */ + 1, /* type 1 = SHT_PROGBITS*/ + 0, /* flags */ + 0, /* addr */ + fo, /* off */ + w, /* size */ + 0, /* link */ + 0, /* info */ + 1, /* align */ + 24); /* entsize */ + break; } cflush(); if(debug['c']){ @@ -306,6 +502,14 @@ wput(int32 l) cflush(); } +void +wputl(ushort w) +{ + cput(w); + cput(w>>8); +} + + void hput(int32 l) { @@ -1829,3 +2033,91 @@ chipfloat(Ieee *e) } return -1; } + +uint32 +linuxheadr(void) +{ + uint32 a; + + a = 64; /* a.out header */ + + a += 56; /* page zero seg */ + a += 56; /* text seg */ + a += 56; /* stack seg */ + + a += 64; /* nil sect */ + a += 64; /* .text sect */ + a += 64; /* .data seg */ + a += 64; /* .bss sect */ + a += 64; /* .shstrtab sect - strings for headers */ + if (!debug['s']) { + a += 56; /* symdat seg */ + a += 64; /* .gosymtab sect */ + a += 64; /* .gopclntab sect */ + } + + return a; +} + +void +linuxphdr(int type, int flags, vlong foff, + vlong vaddr, vlong paddr, + vlong filesize, vlong memsize, vlong align) +{ + + lputl(type); /* text - type = PT_LOAD */ + lputl(foff); /* file offset */ + lputl(vaddr); /* vaddr */ + lputl(paddr); /* paddr */ + lputl(filesize); /* file size */ + lputl(memsize); /* memory size */ + lputl(flags); /* text - flags = PF_X+PF_R */ + lputl(align); /* alignment */ +} + +void +linuxshdr(char *name, uint32 type, vlong flags, vlong addr, vlong off, + vlong size, uint32 link, uint32 info, vlong align, vlong entsize) +{ + lputl(stroffset); + lputl(type); + lputl(flags); + lputl(addr); + lputl(off); + lputl(size); + lputl(link); + lputl(info); + lputl(align); + lputl(entsize); + + if(name != nil) + stroffset += strlen(name)+1; +} + +int +putstrtab(char* name) +{ + int w; + + w = strlen(name)+1; + strnput(name, w); + return w; +} + +int +linuxstrtable(void) +{ + int size; + + size = 0; + size += putstrtab(""); + size += putstrtab(".text"); + size += putstrtab(".data"); + size += putstrtab(".bss"); + size += putstrtab(".shstrtab"); + if (!debug['s']) { + size += putstrtab(".gosymtab"); + size += putstrtab(".gopclntab"); + } + return size; +} diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h index dc578f5f9c..8cd9d2010b 100644 --- a/src/cmd/5l/l.h +++ b/src/cmd/5l/l.h @@ -323,6 +323,7 @@ EXTERN Oprang thumboprange[ALAST]; EXTERN char* outfile; EXTERN int32 pc; EXTERN uchar repop[ALAST]; +EXTERN uint32 stroffset; EXTERN int32 symsize; EXTERN Prog* textp; EXTERN int32 textsize; @@ -456,6 +457,7 @@ void strnput(char*, int); void undef(void); void undefsym(Sym*); void wput(int32); +void wputl(ushort w); void xdefine(char*, int, int32); void xfol(Prog*); void zerosig(char*); @@ -471,4 +473,12 @@ void thumbcount(void); void reachable(void); void fnptrs(void); +uint32 linuxheadr(void); +void linuxphdr(int type, int flags, vlong foff, + vlong vaddr, vlong paddr, + vlong filesize, vlong memsize, vlong align); +void linuxshdr(char *name, uint32 type, vlong flags, vlong addr, vlong off, + vlong size, uint32 link, uint32 info, vlong align, vlong entsize); +int linuxstrtable(void); + #endif diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c index 275c3fe6e2..990c3597e1 100644 --- a/src/cmd/5l/obj.c +++ b/src/cmd/5l/obj.c @@ -153,6 +153,7 @@ main(int argc, char *argv[]) HEADTYPE = 1; if(debug['9']) HEADTYPE = 2; + HEADTYPE = 6; } switch(HEADTYPE) { default: @@ -212,6 +213,15 @@ main(int argc, char *argv[]) if(INITRND == -1) INITRND = 1024; break; + case 6: /* arm elf */ + HEADR = linuxheadr(); + if(INITTEXT == -1) + INITTEXT = 0x8000+HEADR; + if(INITDAT == -1) + INITDAT = 0; + if(INITRND == -1) + INITRND = 4096; + break; } if(INITDAT != 0 && INITRND != 0) print("warning: -D0x%lux is ignored because of -R0x%lux\n", -- 2.30.9