]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/ld: external linking fixes for linux/386
authorRuss Cox <rsc@golang.org>
Sat, 9 Mar 2013 04:22:38 +0000 (20:22 -0800)
committerRuss Cox <rsc@golang.org>
Sat, 9 Mar 2013 04:22:38 +0000 (20:22 -0800)
The sticking point on 386 has been the "PC relative" relocations
used to point the garbage collection metadata at the type info.
These aren't in the code segment, and I don't trust that the linker
isn't doing something special that would be okay in code but
not when interpreting the pointers as data (for example, a PLT
jump table would be terrible).

Solve the problem in two steps:

1. Handle "PC relative" relocations within a section internally,
so that the external linker never sees them.

2. Move the gcdata and gcbss tables into the rodata section,
where the type information lives, so that the relocations can
be handled internally.

(To answer the obvious question, we make the gc->type
references relative so that they need not be relocated
individually when generating a shared object file.)

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

src/cmd/ld/data.c
src/cmd/ld/elf.c
src/cmd/ld/lib.c
src/cmd/ld/lib.h
src/cmd/ld/symtab.c

index 3cdef28771e8f1d3e5e73df592371136cff14e06..22cb4f3e6058d322294fdb48f9298ff05785753f 100644 (file)
@@ -199,7 +199,7 @@ relocsym(Sym *s)
                        if(r->sym)
                                o += symaddr(r->sym);
                        o += r->add - (s->value + r->off + r->siz);
-                       if(isobj && r->sym->type != SCONST) {
+                       if(isobj && r->sym->type != SCONST && r->sym->sect != cursym->sect) {
                                if(thechar == '6')
                                        o = 0;
                                else
@@ -950,11 +950,11 @@ dodata(void)
        Bflush(&bso);
 
        // define garbage collection symbols
-       gcdata1 = lookup("gcdata1", 0);
-       gcdata1->type = SGCDATA;
+       gcdata1 = lookup("gcdata", 0);
+       gcdata1->type = STYPE;
        gcdata1->reachable = 1;
-       gcbss1 = lookup("gcbss1", 0);
-       gcbss1->type = SGCBSS;
+       gcbss1 = lookup("gcbss", 0);
+       gcbss1->type = STYPE;
        gcbss1->reachable = 1;
 
        // size of .data and .bss section. the zero value is later replaced by the actual size of the section.
@@ -1154,7 +1154,7 @@ dodata(void)
        }
        sect->len = datsize - sect->vaddr;
 
-       /* type */
+       /* typelink */
        sect = addsection(&segtext, ".typelink", 04);
        sect->align = maxalign(s, STYPELINK);
        datsize = rnd(datsize, sect->align);
@@ -1170,38 +1170,6 @@ dodata(void)
        }
        sect->len = datsize - sect->vaddr;
 
-       /* 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;
-
-       /* 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;
-
        /* gosymtab */
        sect = addsection(&segtext, ".gosymtab", 04);
        sect->align = maxalign(s, SPCLNTAB-1);
@@ -1295,7 +1263,7 @@ void
 address(void)
 {
        Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss, *datarelro;
-       Section *gcdata, *gcbss, *typelink;
+       Section *typelink;
        Sym *sym, *sub;
        uvlong va;
 
@@ -1349,9 +1317,7 @@ address(void)
        text = segtext.sect;
        rodata = text->next;
        typelink = rodata->next;
-       gcdata = typelink->next;
-       gcbss = gcdata->next;
-       symtab = gcbss->next;
+       symtab = typelink->next;
        pclntab = symtab->next;
 
        for(sym = datap; sym != nil; sym = sym->next) {
@@ -1374,10 +1340,15 @@ address(void)
                xdefine("datarelro", SRODATA, datarelro->vaddr);
                xdefine("edatarelro", SRODATA, datarelro->vaddr + datarelro->len);
        }
-       xdefine("gcdata", SGCDATA, gcdata->vaddr);
-       xdefine("egcdata", SGCDATA, gcdata->vaddr + gcdata->len);
-       xdefine("gcbss", SGCBSS, gcbss->vaddr);
-       xdefine("egcbss", SGCBSS, gcbss->vaddr + gcbss->len);
+
+       sym = lookup("gcdata", 0);
+       xdefine("egcdata", STYPE, symaddr(sym) + sym->size);
+       lookup("egcdata", 0)->sect = sym->sect;
+
+       sym = lookup("gcbss", 0);
+       xdefine("egcbss", STYPE, symaddr(sym) + sym->size);
+       lookup("egcbss", 0)->sect = sym->sect;
+
        xdefine("symtab", SRODATA, symtab->vaddr);
        xdefine("esymtab", SRODATA, symtab->vaddr + symtab->len);
        xdefine("pclntab", SRODATA, pclntab->vaddr);
index 0eb2fa531c1606c303bae191bfbb5bd9986e0835..0bd23d8ed00a9628ae4c06fe6e558e471bc976ac 100644 (file)
@@ -843,7 +843,9 @@ elfrelocsect(Section *sect, Sym *first)
                        case D_ADDR:
                        case D_PCREL:
                                if(r->sym->type == SCONST)
-                                       continue;
+                                       continue;       // handled in data.c:/^relocsym
+                               if(r->type == D_PCREL && r->sym->sect == sym->sect)
+                                       continue;       // handled in data.c:/^relocsym
                                break;
                        }
 
index 99ff86aab99b75cba76b850bc1ec1b4992819aa6..2ca1d3e0da5b97fb7b97349e21bd24a384292a7f 100644 (file)
@@ -1805,8 +1805,6 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
                case SSTRING:
                case SGOSTRING:
                case SWINDOWS:
-               case SGCDATA:
-               case SGCBSS:
                        if(!s->reachable)
                                continue;
                        put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
index 8b679323157c1fce6fc30fd5a9d456a8695e5210..4cb52c6ba465b6b8c2aea93bad1904259ff99739 100644 (file)
@@ -40,8 +40,6 @@ enum
        SGOSTRING,
        SRODATA,
        STYPELINK,
-       SGCDATA,
-       SGCBSS,
        SSYMTAB,
        SPCLNTAB,
        SELFROSECT,
index d8b8b932893d6d441a531bebdac50bda1f209e3b..6c69953cf1cdb89611076288bddda4dcd2b0daaa 100644 (file)
@@ -434,10 +434,8 @@ symtab(void)
                xdefine("datarelro", SDATARELRO, 0);
                xdefine("edatarelro", SDATARELRO, 0);
        }
-       xdefine("gcdata", SGCDATA, 0);
-       xdefine("egcdata", SGCDATA, 0);
-       xdefine("gcbss", SGCBSS, 0);
-       xdefine("egcbss", SGCBSS, 0);
+       xdefine("egcdata", STYPE, 0);
+       xdefine("egcbss", STYPE, 0);
        xdefine("noptrdata", SNOPTRDATA, 0);
        xdefine("enoptrdata", SNOPTRDATA, 0);
        xdefine("data", SDATA, 0);