summaryrefslogtreecommitdiff
path: root/src/cmd/ld/lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/ld/lib.c')
-rw-r--r--src/cmd/ld/lib.c66
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];