diff options
Diffstat (limited to 'src/cmd/ld/lib.c')
-rw-r--r-- | src/cmd/ld/lib.c | 66 |
1 files changed, 52 insertions, 14 deletions
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c index 37379e186..34440b875 100644 --- a/src/cmd/ld/lib.c +++ b/src/cmd/ld/lib.c @@ -46,6 +46,7 @@ static int cout = -1; char* goroot; char* goarch; char* goos; +char* theline; void Lflag(char *arg) @@ -70,7 +71,12 @@ libinit(void) // add goroot to the end of the libdir list. libdir[nlibdir++] = smprint("%s/pkg/%s_%s", goroot, goos, goarch); + // Unix doesn't like it when we write to a running (or, sometimes, + // recently run) binary, so remove the output file before writing it. + // On Windows 7, remove() can force the following create() to fail. +#ifndef _WIN32 remove(outfile); +#endif cout = create(outfile, 1, 0775); if(cout < 0) { diag("cannot create %s", outfile); @@ -109,7 +115,7 @@ addlib(char *src, char *obj) sprint(name, ""); i = 1; } else - if(isalpha(histfrog[0]->name[1]) && histfrog[0]->name[2] == ':') { + if(isalpha((uchar)histfrog[0]->name[1]) && histfrog[0]->name[2] == ':') { strcpy(name, histfrog[0]->name+1); i = 1; } else @@ -268,6 +274,7 @@ loadlib(void) for(i=0; i<libraryp; i++) { if(debug['v']) Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i].file, library[i].objref); + iscgo |= strcmp(library[i].pkg, "runtime/cgo") == 0; objfile(library[i].file, library[i].pkg); } @@ -307,15 +314,9 @@ nextar(Biobuf *bp, int off, struct ar_hdr *a) return 0; return -1; } - if(r == SAR_HDR) { - memmove(a, buf, SAR_HDR); - } else if (r == SAR_HDR-SARNAME+16) { // old Plan 9 - memset(a->name, ' ', sizeof a->name); - memmove(a, buf, 16); - memmove((char*)a+SARNAME, buf+16, SAR_HDR-SARNAME); - } else { // unexpected + if(r != SAR_HDR) return -1; - } + memmove(a, buf, SAR_HDR); if(strncmp(a->fmag, ARFMAG, sizeof a->fmag)) return -1; arsize = strtol(a->size, 0, 0); @@ -350,6 +351,7 @@ objfile(char *file, char *pkg) Bseek(f, 0L, 0); ldobj(f, pkg, l, file, FileObj); Bterm(f); + free(pkg); return; } @@ -411,6 +413,7 @@ objfile(char *file, char *pkg) out: Bterm(f); + free(pkg); } void @@ -438,14 +441,17 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence) magic = c1<<24 | c2<<16 | c3<<8 | c4; if(magic == 0x7f454c46) { // \x7F E L F ldelf(f, pkg, len, pn); + free(pn); return; } if((magic&~1) == 0xfeedface || (magic&~0x01000000) == 0xcefaedfe) { ldmacho(f, pkg, len, pn); + free(pn); return; } if(c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86) { ldpe(f, pkg, len, pn); + free(pn); return; } @@ -471,14 +477,36 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence) return; } diag("%s: not an object file", pn); + free(pn); return; } - t = smprint("%s %s %s", getgoos(), thestring, getgoversion()); - if(strcmp(line+10, t) != 0 && !debug['f']) { + + // First, check that the basic goos, string, and version match. + t = smprint("%s %s %s ", goos, thestring, getgoversion()); + line[n] = ' '; + if(strncmp(line+10, t, strlen(t)) != 0 && !debug['f']) { + line[n] = '\0'; diag("%s: object is [%s] expected [%s]", pn, line+10, t); free(t); + free(pn); return; } + + // Second, check that longer lines match each other exactly, + // so that the Go compiler and write additional information + // that must be the same from run to run. + line[n] = '\0'; + if(n-10 > strlen(t)) { + if(theline == nil) + theline = strdup(line+10); + else if(strcmp(theline, line+10) != 0) { + line[n] = '\0'; + diag("%s: object is [%s] expected [%s]", pn, line+10, theline); + free(t); + free(pn); + return; + } + } free(t); line[n] = '\n'; @@ -501,10 +529,12 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence) Bseek(f, import1, 0); ldobj1(f, pkg, eof - Boffset(f), pn); + free(pn); return; eof: diag("truncated object file: %s", pn); + free(pn); } static Sym* @@ -884,18 +914,26 @@ unmal(void *v, uint32 n) * Convert raw string to the prefix that will be used in the symbol table. * Invalid bytes turn into %xx. Right now the only bytes that need * escaping are %, ., and ", but we escape all control characters too. + * + * Must be same as ../gc/subr.c:/^pathtoprefix. */ static char* pathtoprefix(char *s) { static char hex[] = "0123456789abcdef"; - char *p, *r, *w; + char *p, *r, *w, *l; int n; + // find first character past the last slash, if any. + l = s; + for(r=s; *r; r++) + if(*r == '/') + l = r+1; + // check for chars that need escaping n = 0; for(r=s; *r; r++) - if(*r <= ' ' || *r == '.' || *r == '%' || *r == '"') + if(*r <= ' ' || (*r == '.' && r >= l) || *r == '%' || *r == '"' || *r >= 0x7f) n++; // quick exit @@ -905,7 +943,7 @@ pathtoprefix(char *s) // escape p = mal((r-s)+1+2*n); for(r=s, w=p; *r; r++) { - if(*r <= ' ' || *r == '.' || *r == '%' || *r == '"') { + if(*r <= ' ' || (*r == '.' && r >= l) || *r == '%' || *r == '"' || *r >= 0x7f) { *w++ = '%'; *w++ = hex[(*r>>4)&0xF]; *w++ = hex[*r&0xF]; |