]> Cypherpunks repositories - gostls13.git/commitdiff
gc, ld: detect stale or incompatible object files
authorRuss Cox <rsc@golang.org>
Thu, 3 Feb 2011 18:51:43 +0000 (13:51 -0500)
committerRuss Cox <rsc@golang.org>
Thu, 3 Feb 2011 18:51:43 +0000 (13:51 -0500)
The object files begin with a header that is

        $GOARCH

on a line by itself.  This CL changes that header to

        go object $GOOS $GOARCH release.2011-01-01 4567+

where the final two fields are the most recent release
tag and the current hg version number.

All objects imported into a Go compilation or linked into an
executable must have the same header line, and that header
line must match the compiler and linker versions.

The effect of this will be that if you update and run all.bash
and then try to link in objects compiled with an earlier version
of the compiler (or invoke the wrong version of the compiler),
you will get an error showing the different headers instead
of perhaps silent incompatibility.

Normal usage with all.bash should be unaffected, because
all.bash deletes all the object files in $GOROOT/pkg/$GOOS_$GOARCH
and cleans all intermediate object files before starting.

This change is intended to diagnose stale objects arising when
users maintaining alternate installation directories forget to
rebuild some of their files after updating.

It should help make the adoption of $GOPATH (CL 3780043)
less error-prone.

R=ken2, r
CC=golang-dev
https://golang.org/cl/4023063

14 files changed:
src/cmd/5a/lex.c
src/cmd/5c/swt.c
src/cmd/6a/lex.c
src/cmd/6c/swt.c
src/cmd/8a/lex.c
src/cmd/8c/swt.c
src/cmd/gc/align.c
src/cmd/gc/lex.c
src/cmd/gc/obj.c
src/cmd/gc/subr.c
src/cmd/gopack/ar.c
src/cmd/ld/lib.c
src/libmach/obj.c
src/version.bash

index b36094a784f7cb46ace4c32e87787fd50337184e..e762f5646224cd0e0d6c0dd09f4fe20142c8d908 100644 (file)
@@ -187,7 +187,7 @@ assemble(char *file)
        pass = 1;
        pinit(file);
 
-       Bprint(&obuf, "%s\n", thestring);
+       Bprint(&obuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion());
 
        for(i=0; i<nDlist; i++)
                dodefine(Dlist[i]);
index 43eb73c943ae814ddd6e10b8a7eebe5f787ff643..d45aabc5e60b48c487336d0a668f67e2e2d9826d 100644 (file)
@@ -373,7 +373,7 @@ outcode(void)
                }
        }
 
-       Bprint(&outbuf, "%s\n", thestring);
+       Bprint(&outbuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion());
        if(ndynimp > 0 || ndynexp > 0) {
                int i;
 
index 1b8bb63445e62c23d3b6d58b3aa2c7417b8213d4..37144c8884956f66075ece16d7b95dfe4eb99007 100644 (file)
@@ -189,7 +189,7 @@ assemble(char *file)
        pass = 1;
        pinit(file);
 
-       Bprint(&obuf, "%s\n", thestring);
+       Bprint(&obuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion());
 
        for(i=0; i<nDlist; i++)
                dodefine(Dlist[i]);
index 47975a0c8e7a36c64cd1539aa8ca0d4513a12245..6d886f4592746d5f61bd1afc88c6ef12e2b6d624 100644 (file)
@@ -231,7 +231,7 @@ outcode(void)
        }
        Binit(&b, f, OWRITE);
 
-       Bprint(&b, "%s\n", thestring);
+       Bprint(&b, "go object %s %s %s\n", getgoos(), thestring, getgoversion());
        if(ndynimp > 0 || ndynexp > 0) {
                int i;
 
index bf298b26659d91eefc9031ce9eb515090bb10352..d5fa959aa84a70b13a874864b190fab9ef6eee64 100644 (file)
@@ -189,7 +189,7 @@ assemble(char *file)
        pass = 1;
        pinit(file);
 
-       Bprint(&obuf, "%s\n", thestring);
+       Bprint(&obuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion());
 
        for(i=0; i<nDlist; i++)
                dodefine(Dlist[i]);
index be48885f8155f12a69bd829d87108438022f6619..d07a5439c2b32487ab3f75f6423712ea58f4a29b 100644 (file)
@@ -230,7 +230,7 @@ outcode(void)
        }
        Binit(&b, f, OWRITE);
 
-       Bprint(&b, "%s\n", thestring);
+       Bprint(&b, "go object %s %s %s\n", getgoos(), thestring, getgoversion());
        if(ndynimp > 0 || ndynexp > 0) {
                int i;
 
index ed20e7e8b4e5e4baae8f0a5f902a58134fb37c49..833eba19aeadcb73ccadcd6a7ca0d236636b1161 100644 (file)
@@ -54,7 +54,8 @@ widstruct(Type *t, uint32 o, int flag)
                if(f->type->width < 0)
                        fatal("invalid width %lld", f->type->width);
                w = f->type->width;
-               o = rnd(o, f->type->align);
+               if(f->type->align > 0)
+                       o = rnd(o, f->type->align);
                f->width = o;   // really offset for TFIELD
                if(f->nname != N) {
                        // this same stackparam logic is in addrescapes
index 45b1257fad0b4df75e214cb4837c4cf3d22a96b2..2148d7523b3e55e83fbd4bd8b638c585fd63d902 100644 (file)
@@ -405,7 +405,7 @@ void
 importfile(Val *f, int line)
 {
        Biobuf *imp;
-       char *file;
+       char *file, *p, *q;
        int32 c;
        int len;
        Strlit *path;
@@ -432,7 +432,7 @@ importfile(Val *f, int line)
                cannedimports("unsafe.6", unsafeimport);
                return;
        }
-
+       
        path = f->u.sval;
        if(islocalname(path)) {
                cleanbuf = mal(strlen(pathname) + strlen(path->s) + 2);
@@ -459,10 +459,25 @@ importfile(Val *f, int line)
        len = strlen(namebuf);
        if(len > 2 && namebuf[len-2] == '.' && namebuf[len-1] == 'a') {
                if(!skiptopkgdef(imp)) {
-                       yyerror("import not package file: %s", namebuf);
+                       yyerror("import %s: not a package file", file);
                        errorexit();
                }
        }
+       
+       // check object header
+       p = Brdstr(imp, '\n', 1);
+       if(strcmp(p, "empty archive") != 0) {
+               if(strncmp(p, "go object ", 10) != 0) {
+                       yyerror("import %s: not a go object file", file);
+                       errorexit();
+               }
+               q = smprint("%s %s %s", getgoos(), thestring, getgoversion());
+               if(strcmp(p+10, q) != 0) {
+                       yyerror("import %s: object is [%s] expected [%s]", file, p+10, q);
+                       errorexit();
+               }
+               free(q);
+       }
 
        // assume files move (get installed)
        // so don't record the full path.
@@ -479,6 +494,7 @@ importfile(Val *f, int line)
        curio.infile = file;
        curio.nlsemi = 0;
        typecheckok = 1;
+
        for(;;) {
                c = getc();
                if(c == EOF)
index 0d0d70ac965bd1f8bff16b2e48f56d651f7b1b35..fbabe0d43a5d70aba5464605a0c991b5a993bd43 100644 (file)
@@ -21,7 +21,7 @@ dumpobj(void)
                errorexit();
        }
 
-       Bprint(bout, "%s\n", thestring);
+       Bprint(bout, "go object %s %s %s\n", getgoos(), thestring, getgoversion());
        Bprint(bout, "  exports automatically generated from\n");
        Bprint(bout, "  %s in package \"%s\"\n", curio.infile, localpkg->name);
        dumpexport();
index cb5e2a831d9908042b2c2e7197bf1ebd2529ca8a..0755ca3cd5481b5b5d1ddc83d4db8f43a060ba9d 100644 (file)
@@ -203,6 +203,7 @@ fatal(char *fmt, ...)
 
        flusherrors();
 
+*(int*)0=0;
        print("%L: internal compiler error: ", lineno);
        va_start(arg, fmt);
        vfprint(1, fmt, arg);
@@ -213,7 +214,7 @@ fatal(char *fmt, ...)
        if(strncmp(getgoversion(), "release", 7) == 0) {
                print("\n");
                print("Please file a bug report including a short program that triggers the error.\n");
-               print("http://code.google.com/p/go/issues/entry?template=compilerbug");
+               print("http://code.google.com/p/go/issues/entry?template=compilerbug\n");
        }
        hcrash();
        errorexit();
index a16e98cfe54996783c4e2bda88ba3a7b8754e4a7..eed98967ad579e54b612215222d115936225c281 100644 (file)
@@ -131,6 +131,7 @@ Arfile *astart, *amiddle, *aend;    /* Temp file control block pointers */
 int    allobj = 1;                     /* set when all members are object files of the same type */
 int    symdefsize;                     /* size of symdef file */
 char   *pkgstmt;               /* string "package foo" */
+char   *objhdr;                /* string "go object darwin 386 release.2010-01-01 2345+" */
 int    dupfound;                       /* flag for duplicate symbol */
 Hashchain      *hash[NHASH];           /* hash table of text symbols */
 
@@ -246,6 +247,8 @@ main(int argc, char *argv[])
        argc -= 3;
        argv += 3;
        (*comfun)(cp, argc, argv);      /* do the command */
+       if(errors && cflag)
+               remove(cp);
        cp = 0;
        while (argc--) {
                if (*argv) {
@@ -590,10 +593,11 @@ void
 scanobj(Biobuf *b, Arfile *ap, long size)
 {
        int obj;
-       vlong offset;
+       vlong offset, offset1;
        Dir *d;
        static int lastobj = -1;
        uchar buf[4];
+       char *p, *t;
 
        if (!allobj)                    /* non-object file encountered */
                return;
@@ -628,14 +632,32 @@ scanobj(Biobuf *b, Arfile *ap, long size)
                Bseek(b, offset, 0);
                return;
        }
-       if (lastobj >= 0 && obj != lastobj) {
+
+       offset1 = Boffset(b);
+       Bseek(b, offset, 0);
+       p = Brdstr(b, '\n', 1);
+       Bseek(b, offset1, 0);
+       if(p == nil || strncmp(p, "go object ", 10) != 0) {
+               fprint(2, "gopack: malformed object file %s\n", file);
+               errors++;
+               Bseek(b, offset, 0);
+               free(p);
+               return;
+       }
+       
+       if ((lastobj >= 0 && obj != lastobj) || (objhdr != nil && strcmp(p, objhdr) != 0)) {
                fprint(2, "gopack: inconsistent object file %s\n", file);
                errors++;
                allobj = 0;
-               Bseek(b, offset, 0);
+               free(p);
                return;
        }
        lastobj = obj;
+       if(objhdr == nil)
+               objhdr = p;
+       else
+               free(p);
+               
        if (!readar(b, obj, offset+size, 0)) {
                fprint(2, "gopack: invalid symbol reference in file %s\n", file);
                errors++;
@@ -677,7 +699,7 @@ char*       importblock;
 void
 getpkgdef(char **datap, int *lenp)
 {
-       char *tag;
+       char *tag, *hdr;
 
        if(pkgname == nil) {
                pkgname = "__emptyarchive__";
@@ -688,7 +710,11 @@ getpkgdef(char **datap, int *lenp)
        if(safe || Sflag)
                tag = "safe";
 
-       *datap = smprint("import\n$$\npackage %s %s\n%s\n$$\n", pkgname, tag, importblock);
+       hdr = "empty archive";
+       if(objhdr != nil)
+               hdr = objhdr;
+
+       *datap = smprint("%s\nimport\n$$\npackage %s %s\n%s\n$$\n", hdr, pkgname, tag, importblock);
        *lenp = strlen(*datap);
 }
 
index b1a62f25ee7f25c70afeebfdd59dd30757eb8bef..0c9ea0b7c9ec6fe98a3678956560eba2d025d5a7 100644 (file)
@@ -378,10 +378,10 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
        int n, c1, c2, c3, c4;
        uint32 magic;
        vlong import0, import1, eof;
-       char src[1024];
+       char *fld[10], *s, *t;
+       int nfld;
 
        eof = Boffset(f) + len;
-       src[0] = '\0';
 
        pn = strdup(pn);
        
@@ -415,22 +415,34 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
        line = Brdline(f, '\n');
        if(line == nil) {
                if(Blinelen(f) > 0) {
-                       diag("%s: malformed object file", pn);
+                       diag("%s: not an object file", pn);
                        return;
                }
                goto eof;
        }
        n = Blinelen(f) - 1;
-       if(n != strlen(thestring) || strncmp(line, thestring, n) != 0) {
-               if(line)
-                       line[n] = '\0';
+       line[n] = '\0';
+       if(strncmp(line, "go object ", 10) != 0) {
                if(strlen(pn) > 3 && strcmp(pn+strlen(pn)-3, ".go") == 0) {
                        print("%cl: input %s is not .%c file (use %cg to compile .go files)\n", thechar, pn, thechar, thechar);
                        errorexit();
                }
-               diag("file not %s [%s]\n", thestring, line);
+               if(strcmp(line, thestring) == 0) {
+                       // old header format: just $GOOS
+                       diag("%s: stale object file", pn);
+                       return;
+               }
+               diag("%s: not an object file", pn);
+               return;
+       }
+       t = smprint("%s %s %s", getgoos(), thestring, getgoversion());
+       if(strcmp(line+10, t) != 0) {
+               diag("%s: object is [%s] expected [%s]", pn, line+10, t);
+               free(t);
                return;
        }
+       free(t);
+       line[n] = '\n';
 
        /* skip over exports and other info -- ends with \n!\n */
        import0 = Boffset(f);
index dacb2ae1fa76a76ffe57997d0f7909e9993af01f..1ffe7a0ee163cf962bc32ae145e5ece72d1faba2 100644 (file)
@@ -116,34 +116,24 @@ objtype(Biobuf *bp, char **name)
        int i;
        char buf[MAXIS];
        int c;
-
-Retry:
-       if(Bread(bp, buf, MAXIS) < MAXIS)
-               return -1;
-       Bseek(bp, -MAXIS, 1);
-       for (i = 0; i < Maxobjtype; i++) {
-               if (obj[i].is && (*obj[i].is)(buf)) {
-                       if (name)
-                               *name = obj[i].name;
-                       return i;
-               }
-       }
+       char *p;
 
        /*
-        * Maybe there's an import block we need to skip
+        * Look for import block.
         */
-       for(i = 0; i < MAXIS; i++) {
-               if(isalpha(buf[i]) || isdigit(buf[i]))
-                       continue;
-               if(i == 0 || buf[i] != '\n')
-                       return -1;
-               break;
-       }
+       p = Brdline(bp, '\n');
+       if(p == nil)
+               return -1;
+       if(Blinelen(bp) < 10 || strncmp(p, "go object ", 10) != 0)
+               return -1;
+       Bseek(bp, -1, 1);
 
        /*
         * Found one.  Skip until "\n!\n"
         */
-       while((c = Bgetc(bp)) != Beof) {
+       for(;;) {
+               if((c = Bgetc(bp)) == Beof)
+                       return -1;
                if(c != '\n')
                        continue;
                c = Bgetc(bp);
@@ -156,8 +146,20 @@ Retry:
                        Bungetc(bp);
                        continue;
                }
-               goto Retry;
+               break;
        }
+
+       if(Bread(bp, buf, MAXIS) < MAXIS)
+               return -1;
+       Bseek(bp, -MAXIS, 1);
+       for (i = 0; i < Maxobjtype; i++) {
+               if (obj[i].is && (*obj[i].is)(buf)) {
+                       if (name)
+                               *name = obj[i].name;
+                       return i;
+               }
+       }
+
        return -1;
 }
 
index 2d29825ff9130c5b55007e5552646b8c5d17e25d..0e6483150826ad96f0acfad81131c9191677a8ed 100755 (executable)
@@ -11,17 +11,16 @@ fi
 
 # Get numerical revision
 VERSION=$(hg identify -n 2>/dev/null)
-if [ $? = 0 ]; then
-       TAG=$(hg identify -t | sed 's!/release!!')
-else
+if [ $? != 0 ]; then
        OLD=$(hg identify | sed 1q)
        VERSION=$(echo $OLD | awk '{print $1}')
-       TAG=$(echo $OLD | awk '{print $2}' | sed 's!/release!!')
 fi
 
-# Append tag if not 'tip'
-if [[ "$TAG" != "tip" ]]; then
-       VERSION="$VERSION $TAG"
+# Find most recent known release tag.
+TAG=$(hg tags | awk '$1~/^release\./ {print $1}' | sed -n 1p)
+
+if [ "$TAG" != "" ]; then
+       VERSION="$TAG $VERSION"
 fi
 
 echo $VERSION