]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.cc] liblink: resolve bss vs other conflict regardless of order found
authorRuss Cox <rsc@golang.org>
Tue, 11 Nov 2014 06:28:26 +0000 (01:28 -0500)
committerRuss Cox <rsc@golang.org>
Tue, 11 Nov 2014 06:28:26 +0000 (01:28 -0500)
If the linker finds the same name given a BSS and a non-BSS
symbol, the assumption is that the non-BSS symbol is the
true one, and the BSS symbol is just the best Go can do toward
an "extern" declaration. This has always been the case,
as long as the object files were read in the right order.

The old code worked when the BSS symbol is found before
the non-BSS symbol. This CL adds equivalent logic for when
the non-BSS symbol is found before the BSS symbol.
This comes up when Go must refer to symbols defined in
host object files.

LGTM=r
R=r
CC=austin, golang-codereviews, iant, khr
https://golang.org/cl/171480043

src/liblink/objfile.c

index b2478ec17847f9d130587f7cd39455e7881be5c9..c765430344a616ad4c79dce77f7bd76cedacacf2 100644 (file)
@@ -546,9 +546,10 @@ ldobjfile(Link *ctxt, Biobuf *f, char *pkg, int64 len, char *pn)
 static void
 readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
 {
-       int i, j, c, t, v, n, size, dupok;
+       int i, j, c, t, v, n, ndata, nreloc, size, dupok;
        static int ndup;
        char *name;
+       uchar *data;
        Reloc *r;
        LSym *s, *dup, *typ;
        Pcln *pc;
@@ -564,12 +565,24 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
        dupok = rdint(f);
        dupok &= 1;
        size = rdint(f);
+       typ = rdsym(ctxt, f, pkg);
+       rddata(f, &data, &ndata);
+       nreloc = rdint(f);
        
        if(v != 0)
                v = ctxt->version;
        s = linklookup(ctxt, name, v);
        dup = nil;
        if(s->type != 0 && s->type != SXREF) {
+               if((t == SDATA || t == SBSS || t == SNOPTRBSS) && ndata == 0 && nreloc == 0) {
+                       if(s->size < size)
+                               s->size = size;
+                       if(typ != nil && s->gotype == nil)
+                               s->gotype = typ;
+                       return;
+               }
+               if((s->type == SDATA || s->type == SBSS || s->type == SNOPTRBSS) && s->np == 0 && s->nr == 0)
+                       goto overwrite;
                if(s->type != SBSS && s->type != SNOPTRBSS && !dupok && !s->dupok)
                        sysfatal("duplicate symbol %s (types %d and %d) in %s and %s", s->name, s->type, t, s->file, pn);
                if(s->np > 0) {
@@ -577,28 +590,30 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
                        s = linknewsym(ctxt, ".dup", ndup++); // scratch
                }
        }
+overwrite:
        s->file = pkg;
        s->dupok = dupok;
        if(t == SXREF)
                sysfatal("bad sxref");
        if(t == 0)
                sysfatal("missing type for %s in %s", name, pn);
+       if(t == SBSS && (s->type == SRODATA || s->type == SNOPTRBSS))
+               t = s->type;
        s->type = t;
        if(s->size < size)
                s->size = size;
-       typ = rdsym(ctxt, f, pkg);
        if(typ != nil) // if bss sym defined multiple times, take type from any one def
                s->gotype = typ;
        if(dup != nil && typ != nil)
                dup->gotype = typ;
-       rddata(f, &s->p, &s->np);
+       s->p = data;
+       s->np = ndata;
        s->maxp = s->np;
-       n = rdint(f);
-       if(n > 0) {
-               s->r = emallocz(n * sizeof s->r[0]);
-               s->nr = n;
-               s->maxr = n;
-               for(i=0; i<n; i++) {
+       if(nreloc > 0) {
+               s->r = emallocz(nreloc * sizeof s->r[0]);
+               s->nr = nreloc;
+               s->maxr = nreloc;
+               for(i=0; i<nreloc; i++) {
                        r = &s->r[i];
                        r->off = rdint(f);
                        r->siz = rdint(f);