]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/ld: steps toward 386 host linking
authorRuss Cox <rsc@golang.org>
Fri, 8 Mar 2013 03:57:25 +0000 (19:57 -0800)
committerRuss Cox <rsc@golang.org>
Fri, 8 Mar 2013 03:57:25 +0000 (19:57 -0800)
- Introduce MaxAlign constant and use in data layout
and ELF section header.

- Allow up to 16-byte alignment for large objects
(will help Keith's hash changes).

- Emit ELF symbol for .rathole (global /dev/null used by 8c).

- Invoke gcc with -m32/-m64 as appropriate.

- Don't invoke gcc if writing the .o file failed.

R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/7563045

src/cmd/5l/l.h
src/cmd/6l/l.h
src/cmd/8l/l.h
src/cmd/8l/obj.c
src/cmd/ld/data.c
src/cmd/ld/elf.c
src/cmd/ld/lib.c
src/cmd/ld/lib.h

index 059e269a91d0b0418f3470622d155a1cf95a9114..0b31b07ab6a45f1bb67d3ce625ce60b82edab2bf 100644 (file)
@@ -38,6 +38,7 @@ enum
        thechar = '5',
        PtrSize = 4,
        IntSize = 4,
+       MaxAlign = 8,   // max data alignment
        FuncAlign = 4  // single-instruction alignment
 };
 
index 1790f718a9e4253249a442a440c51b981fb9b15d..a06dff8c09cc66133d33f211f86d18ba7bd98724 100644 (file)
@@ -42,6 +42,7 @@ enum
        thechar = '6',
        PtrSize = 8,
        IntSize = 8,
+       MaxAlign = 32,  // max data alignment
        
        // Loop alignment constants:
        // want to align loop entry to LoopAlign-byte boundary,
index 062dc056622bb5b11d8984a47d346eaeeba80f6f..f6de74646608607787e1262d6fe49c6737b9f8bf 100644 (file)
@@ -42,6 +42,7 @@ enum
        thechar = '8',
        PtrSize = 4,
        IntSize = 4,
+       MaxAlign = 32,  // max data alignment
        FuncAlign = 16
 };
 
index f06bc5d9dc996464453a9cb70995fa8712ddc021..8144dfadd07a815f2a4647d979e463513a0994ef 100644 (file)
@@ -130,6 +130,10 @@ main(int argc, char *argv[])
        
        flagparse(&argc, &argv, usage);
 
+       // TODO: link mode flag instead of isobj
+       if(isobj)
+               linkmode = LinkExternal;
+
        if(argc != 1)
                usage();
 
index b344abd9b0794b954b05fd95b3338821e8295c1d..3cdef28771e8f1d3e5e73df592371136cff14e06 100644 (file)
@@ -875,36 +875,38 @@ dosymtype(void)
 }
 
 static int32
-alignsymsize(int32 s)
+symalign(Sym *s)
 {
-       if(s >= 8)
-               s = rnd(s, 8);
-       else if(s >= PtrSize)
-               s = rnd(s, PtrSize);
-       else if(s > 2)
-               s = rnd(s, 4);
-       return s;
+       int32 align;
+
+       align = MaxAlign;
+       while(align > s->size && align > 1)
+               align >>= 1;
+       if(align < s->align)
+               align = s->align;
+       return align;
 }
-
+       
 static int32
 aligndatsize(int32 datsize, Sym *s)
 {
-       int32 t;
+       return rnd(datsize, symalign(s));
+}
 
-       if(s->align != 0) {
-               datsize = rnd(datsize, s->align);
-       } else {
-               t = alignsymsize(s->size);
-               if(t & 1) {
-                       ;
-               } else if(t & 2)
-                       datsize = rnd(datsize, 2);
-               else if(t & 4)
-                       datsize = rnd(datsize, 4);
-               else
-                       datsize = rnd(datsize, 8);
+// maxalign returns the maximum required alignment for
+// the list of symbols s; the list stops when s->type exceeds type.
+static int32
+maxalign(Sym *s, int type)
+{
+       int32 align, max;
+       
+       max = 0;
+       for(; s != S && s->type <= type; s = s->next) {
+               align = symalign(s);
+               if(max < align)
+                       max = align;
        }
-       return datsize;
+       return max;
 }
 
 static void
@@ -938,7 +940,7 @@ gcaddsym(Sym *gc, Sym *s, int32 off)
 void
 dodata(void)
 {
-       int32 t, datsize;
+       int32 datsize;
        Section *sect;
        Sym *s, *last, **l;
        Sym *gcdata1, *gcbss1;
@@ -1026,52 +1028,54 @@ dodata(void)
        datsize = 0;
        for(; s != nil && s->type < SNOPTRDATA; s = s->next) {
                sect = addsection(&segdata, s->name, 06);
-               if(s->align != 0)
-                       datsize = rnd(datsize, s->align);
+               sect->align = symalign(s);
+               datsize = rnd(datsize, sect->align);
                sect->vaddr = datsize;
                s->sect = sect;
                s->type = SDATA;
                s->value = datsize;
-               datsize += rnd(s->size, PtrSize);
+               datsize += s->size;
                sect->len = datsize - sect->vaddr;
        }
 
        /* pointer-free data */
        sect = addsection(&segdata, ".noptrdata", 06);
+       sect->align = maxalign(s, SDATARELRO-1);
+       datsize = rnd(datsize, sect->align);
        sect->vaddr = datsize;
        lookup("noptrdata", 0)->sect = sect;
        lookup("enoptrdata", 0)->sect = sect;
        for(; s != nil && s->type < SDATARELRO; s = s->next) {
+               datsize = aligndatsize(datsize, s);
                s->sect = sect;
                s->type = SDATA;
-               t = alignsymsize(s->size);
-               datsize = aligndatsize(datsize, s);
                s->value = datsize;
-               datsize += t;
+               datsize += s->size;
        }
        sect->len = datsize - sect->vaddr;
-       datsize = rnd(datsize, PtrSize);
 
        /* dynamic relocated rodata */
        if(flag_shared) {
                sect = addsection(&segdata, ".data.rel.ro", 06);
+               sect->align = maxalign(s, SDATARELRO);
+               datsize = rnd(datsize, sect->align);
                sect->vaddr = datsize;
                lookup("datarelro", 0)->sect = sect;
                lookup("edatarelro", 0)->sect = sect;
                for(; s != nil && s->type == SDATARELRO; s = s->next) {
-                       if(s->align != 0)
-                               datsize = rnd(datsize, s->align);
+                       datsize = aligndatsize(datsize, s);
                        s->sect = sect;
                        s->type = SDATA;
                        s->value = datsize;
-                       datsize += rnd(s->size, PtrSize);
+                       datsize += s->size;
                }
                sect->len = datsize - sect->vaddr;
-               datsize = rnd(datsize, PtrSize);
        }
 
        /* data */
        sect = addsection(&segdata, ".data", 06);
+       sect->align = maxalign(s, SBSS-1);
+       datsize = rnd(datsize, sect->align);
        sect->vaddr = datsize;
        lookup("data", 0)->sect = sect;
        lookup("edata", 0)->sect = sect;
@@ -1082,39 +1086,39 @@ dodata(void)
                }
                s->sect = sect;
                s->type = SDATA;
-               t = alignsymsize(s->size);
                datsize = aligndatsize(datsize, s);
                s->value = datsize;
                gcaddsym(gcdata1, s, datsize - sect->vaddr);  // gc
-               datsize += t;
+               datsize += s->size;
        }
        sect->len = datsize - sect->vaddr;
-       datsize = rnd(datsize, PtrSize);
 
        adduintxx(gcdata1, GC_END, PtrSize);
        setuintxx(gcdata1, 0, sect->len, PtrSize);
 
        /* bss */
        sect = addsection(&segdata, ".bss", 06);
+       sect->align = maxalign(s, SNOPTRBSS-1);
+       datsize = rnd(datsize, sect->align);
        sect->vaddr = datsize;
        lookup("bss", 0)->sect = sect;
        lookup("ebss", 0)->sect = sect;
        for(; s != nil && s->type < SNOPTRBSS; s = s->next) {
                s->sect = sect;
-               t = alignsymsize(s->size);
                datsize = aligndatsize(datsize, s);
                s->value = datsize;
                gcaddsym(gcbss1, s, datsize - sect->vaddr);  // gc
-               datsize += t;
+               datsize += s->size;
        }
        sect->len = datsize - sect->vaddr;
-       datsize = rnd(datsize, PtrSize);
 
        adduintxx(gcbss1, GC_END, PtrSize);
        setuintxx(gcbss1, 0, sect->len, PtrSize);
 
        /* pointer-free bss */
        sect = addsection(&segdata, ".noptrbss", 06);
+       sect->align = maxalign(s, SNOPTRBSS);
+       datsize = rnd(datsize, sect->align);
        sect->vaddr = datsize;
        lookup("noptrbss", 0)->sect = sect;
        lookup("enoptrbss", 0)->sect = sect;
@@ -1123,11 +1127,10 @@ dodata(void)
                        cursym = s;
                        diag("unexpected symbol type %d", s->type);
                }
-               s->sect = sect;
-               t = alignsymsize(s->size);
                datsize = aligndatsize(datsize, s);
+               s->sect = sect;
                s->value = datsize;
-               datsize += t;
+               datsize += s->size;
        }
        sect->len = datsize - sect->vaddr;
        lookup("end", 0)->sect = sect;
@@ -1135,103 +1138,112 @@ dodata(void)
        /* we finished segdata, begin segtext */
 
        /* read-only data */
+       s = datap;
        sect = addsection(&segtext, ".rodata", 04);
+       sect->align = maxalign(s, STYPELINK-1);
        sect->vaddr = 0;
        lookup("rodata", 0)->sect = sect;
        lookup("erodata", 0)->sect = sect;
        datsize = 0;
-       s = datap;
        for(; s != nil && s->type < STYPELINK; s = s->next) {
+               datsize = aligndatsize(datsize, s);
                s->sect = sect;
-               if(s->align != 0)
-                       datsize = rnd(datsize, s->align);
                s->type = SRODATA;
                s->value = datsize;
-               datsize += rnd(s->size, PtrSize);
+               datsize += s->size;
        }
        sect->len = datsize - sect->vaddr;
-       datsize = rnd(datsize, PtrSize);
 
        /* type */
        sect = addsection(&segtext, ".typelink", 04);
+       sect->align = maxalign(s, STYPELINK);
+       datsize = rnd(datsize, sect->align);
        sect->vaddr = datsize;
        lookup("typelink", 0)->sect = sect;
        lookup("etypelink", 0)->sect = sect;
        for(; s != nil && s->type == STYPELINK; s = s->next) {
+               datsize = aligndatsize(datsize, s);
                s->sect = sect;
                s->type = SRODATA;
                s->value = datsize;
                datsize += s->size;
        }
        sect->len = datsize - sect->vaddr;
-       datsize = rnd(datsize, PtrSize);
 
        /* gcdata */
        sect = addsection(&segtext, ".gcdata", 04);
+       sect->align = maxalign(s, SGCDATA);
+       datsize = rnd(datsize, sect->align);
        sect->vaddr = datsize;
        lookup("gcdata", 0)->sect = sect;
        lookup("egcdata", 0)->sect = sect;
        for(; s != nil && s->type == SGCDATA; s = s->next) {
+               datsize = aligndatsize(datsize, s);
                s->sect = sect;
                s->type = SRODATA;
                s->value = datsize;
                datsize += s->size;
        }
        sect->len = datsize - sect->vaddr;
-       datsize = rnd(datsize, PtrSize);
 
        /* gcbss */
        sect = addsection(&segtext, ".gcbss", 04);
+       sect->align = maxalign(s, SGCBSS);
+       datsize = rnd(datsize, sect->align);
        sect->vaddr = datsize;
        lookup("gcbss", 0)->sect = sect;
        lookup("egcbss", 0)->sect = sect;
        for(; s != nil && s->type == SGCBSS; s = s->next) {
+               datsize = aligndatsize(datsize, s);
                s->sect = sect;
                s->type = SRODATA;
                s->value = datsize;
                datsize += s->size;
        }
        sect->len = datsize - sect->vaddr;
-       datsize = rnd(datsize, PtrSize);
 
        /* gosymtab */
        sect = addsection(&segtext, ".gosymtab", 04);
+       sect->align = maxalign(s, SPCLNTAB-1);
+       datsize = rnd(datsize, sect->align);
        sect->vaddr = datsize;
        lookup("symtab", 0)->sect = sect;
        lookup("esymtab", 0)->sect = sect;
        for(; s != nil && s->type < SPCLNTAB; s = s->next) {
+               datsize = aligndatsize(datsize, s);
                s->sect = sect;
                s->type = SRODATA;
                s->value = datsize;
                datsize += s->size;
        }
        sect->len = datsize - sect->vaddr;
-       datsize = rnd(datsize, PtrSize);
 
        /* gopclntab */
        sect = addsection(&segtext, ".gopclntab", 04);
+       sect->align = maxalign(s, SELFROSECT-1);
+       datsize = rnd(datsize, sect->align);
        sect->vaddr = datsize;
        lookup("pclntab", 0)->sect = sect;
        lookup("epclntab", 0)->sect = sect;
        for(; s != nil && s->type < SELFROSECT; s = s->next) {
+               datsize = aligndatsize(datsize, s);
                s->sect = sect;
                s->type = SRODATA;
                s->value = datsize;
                datsize += s->size;
        }
        sect->len = datsize - sect->vaddr;
-       datsize = rnd(datsize, PtrSize);
 
        /* read-only ELF sections */
        for(; s != nil && s->type < SELFSECT; s = s->next) {
                sect = addsection(&segtext, s->name, 04);
-               if(s->align != 0)
-                       datsize = rnd(datsize, s->align);
+               sect->align = symalign(s);
+               datsize = rnd(datsize, sect->align);
                sect->vaddr = datsize;
                s->sect = sect;
                s->type = SRODATA;
                s->value = datsize;
-               datsize += rnd(s->size, PtrSize);
+               datsize += s->size;
                sect->len = datsize - sect->vaddr;
        }
 }
@@ -1251,6 +1263,7 @@ textaddress(void)
        // Could parallelize, by assigning to text
        // and then letting threads copy down, but probably not worth it.
        sect = segtext.sect;
+       sect->align = FuncAlign;
        lookup("text", 0)->sect = sect;
        lookup("etext", 0)->sect = sect;
        va = INITTEXT;
@@ -1274,11 +1287,6 @@ textaddress(void)
                }
                va += sym->size;
        }
-
-       // Align end of code so that rodata starts aligned.
-       // 128 bytes is likely overkill but definitely cheap.
-       va = rnd(va, 128);
-
        sect->len = va - sect->vaddr;
 }
 
@@ -1296,8 +1304,9 @@ address(void)
        segtext.vaddr = va;
        segtext.fileoff = HEADR;
        for(s=segtext.sect; s != nil; s=s->next) {
+               va = rnd(va, s->align);
                s->vaddr = va;
-               va += rnd(s->len, PtrSize);
+               va += s->len;
        }
        segtext.len = va - INITTEXT;
        segtext.filelen = segtext.len;
@@ -1318,6 +1327,8 @@ address(void)
        noptrbss = nil;
        datarelro = nil;
        for(s=segdata.sect; s != nil; s=s->next) {
+               if(s->next)
+                       s->len = s->next->vaddr - s->vaddr;
                s->vaddr = va;
                va += s->len;
                segdata.filelen += s->len;
@@ -1333,7 +1344,7 @@ address(void)
                if(strcmp(s->name, ".data.rel.ro") == 0)
                        datarelro = s;
        }
-       segdata.filelen -= bss->len + noptrbss->len; // deduct .bss
+       segdata.filelen = bss->vaddr - segdata.vaddr;
 
        text = segtext.sect;
        rodata = text->next;
index 630906653ec70116abc69763f9b49e4bd13f7c3a..0eb2fa531c1606c303bae191bfbb5bd9986e0835 100644 (file)
@@ -762,7 +762,7 @@ elfshbits(Section *sect)
                sh->flags |= SHF_WRITE;
        if(!isobj)
                sh->addr = sect->vaddr;
-       sh->addralign = PtrSize;
+       sh->addralign = sect->align;
        sh->size = sect->len;
        sh->off = sect->seg->fileoff + sect->vaddr - sect->seg->vaddr;
 
index db6b7761b7badba07675dea8cc3557c23798bd15..99ff86aab99b75cba76b850bc1ec1b4992819aa6 100644 (file)
@@ -598,7 +598,7 @@ hostlink(void)
        Biobuf *f;
        static char buf[64<<10];
 
-       if(linkmode != LinkExternal)
+       if(linkmode != LinkExternal || nerrors > 0)
                return;
 
        argv = malloc((10+nhostobj+nldflag)*sizeof argv[0]);
@@ -606,6 +606,14 @@ hostlink(void)
        // TODO: Add command-line flag to override gcc path and specify additional leading options.
        // TODO: Add command-line flag to specify additional trailing options.
        argv[argc++] = "gcc";
+       switch(thechar){
+       case '8':
+               argv[argc++] = "-m32";
+               break;
+       case '6':
+               argv[argc++] = "-m64";
+               break;
+       }
        if(!debug['s'])
                argv[argc++] = "-ggdb"; 
        argv[argc++] = "-o";
@@ -1249,6 +1257,7 @@ addsection(Segment *seg, char *name, int rwx)
        sect->rwx = rwx;
        sect->name = name;
        sect->seg = seg;
+       sect->align = PtrSize; // everything is at least pointer-aligned
        *l = sect;
        return sect;
 }
@@ -1781,7 +1790,7 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
                put(s, s->name, 'T', s->value, s->size, s->version, 0);
 
        for(s=allsym; s!=S; s=s->allsym) {
-               if(s->hide || (s->name[0] == '.' && s->version == 0))
+               if(s->hide || (s->name[0] == '.' && s->version == 0 && strcmp(s->name, ".rathole") != 0))
                        continue;
                switch(s->type&SMASK) {
                case SCONST:
index 0b7e48c8a2816ad068b7c12252c0eb190eb1c8fe..8b679323157c1fce6fc30fd5a9d456a8695e5210 100644 (file)
@@ -104,6 +104,7 @@ struct Segment
 struct Section
 {
        uchar   rwx;
+       int32   align;
        char    *name;
        uvlong  vaddr;
        uvlong  len;