]> Cypherpunks repositories - gostls13.git/commitdiff
Adding ARM elf support to the 5l linker.
authorKai Backman <kaib@golang.org>
Fri, 10 Apr 2009 23:35:36 +0000 (16:35 -0700)
committerKai Backman <kaib@golang.org>
Fri, 10 Apr 2009 23:35:36 +0000 (16:35 -0700)
R=rsc
APPROVED=rsc
DELTA=312  (312 added, 0 deleted, 0 changed)
OCL=27133
CL=27326

src/cmd/5l/asm.c
src/cmd/5l/l.h
src/cmd/5l/obj.c

index 214c9adfd40ea09080f54d8aec06a2d9368248cb..f0f3185a47712d94ae9b68d2f4244dbb28c861c4 100644 (file)
@@ -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;
+}
index dc578f5f9cec19ed4b0c90841bb0c5af217998a2..8cd9d2010b81d1b40acbb02277269e82da38fcbb 100644 (file)
@@ -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
index 275c3fe6e22ed812611c4f25a9fa6a32211aeeba..990c3597e194c6f93769f5e046ff11a8dce57ed9 100644 (file)
@@ -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",