diff options
author | Russ Cox <rsc@golang.org> | 2010-06-29 18:59:48 -0700 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2010-06-29 18:59:48 -0700 |
commit | ce4b0d17c6fa02e416c5d870bbcb3daa660ae129 (patch) | |
tree | d7dd4ed40ac61e7c65b914c34ba2ea27dbccacf2 | |
parent | cb1f89e9aa8f267c9af78ea0484422f00c98da55 (diff) | |
download | golang-ce4b0d17c6fa02e416c5d870bbcb3daa660ae129.tar.gz |
ld: fix implementation of -u
R=r
CC=golang-dev
http://codereview.appspot.com/1678046
-rw-r--r-- | src/cmd/ld/go.c | 31 | ||||
-rw-r--r-- | src/cmd/ld/lib.c | 34 | ||||
-rw-r--r-- | src/cmd/ld/lib.h | 11 |
3 files changed, 57 insertions, 19 deletions
diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c index 2598a528f..015f34db2 100644 --- a/src/cmd/ld/go.c +++ b/src/cmd/ld/go.c @@ -75,7 +75,7 @@ static int ndynexp; static Sym **dynexp; void -ldpkg(Biobuf *f, char *pkg, int64 len, char *filename) +ldpkg(Biobuf *f, char *pkg, int64 len, char *filename, int whence) { char *data, *p0, *p1, *name; @@ -100,7 +100,7 @@ ldpkg(Biobuf *f, char *pkg, int64 len, char *filename) // first \n$$ marks beginning of exports - skip rest of line p0 = strstr(data, "\n$$"); if(p0 == nil) { - if(debug['u']) { + if(debug['u'] && whence != ArchiveObj) { fprint(2, "%s: cannot find export data in %s\n", argv0, filename); errorexit(); } @@ -133,20 +133,31 @@ ldpkg(Biobuf *f, char *pkg, int64 len, char *filename) name = p0; while(p0 < p1 && *p0 != ' ' && *p0 != '\t' && *p0 != '\n') p0++; - if(debug['u'] && memcmp(p0, " safe\n", 6) != 0) { + if(debug['u'] && whence != ArchiveObj && + (p0+6 > p1 || memcmp(p0, " safe\n", 6) != 0)) { fprint(2, "%s: load of unsafe package %s\n", argv0, filename); errorexit(); } if(p0 < p1) { - *p0++ = '\0'; - if(strcmp(pkg, "main") == 0 && strcmp(name, "main") != 0) - fprint(2, "%s: %s: not package main (package %s)\n", argv0, filename, name); - else if(strcmp(pkg, "main") != 0 && strcmp(name, "main") == 0) - fprint(2, "%s: %s: importing %s, found package main", argv0, filename, pkg); + if(*p0 == '\n') + *p0++ = '\0'; + else { + *p0++ = '\0'; + while(p0 < p1 && *p0++ != '\n') + ; + } } + if(strcmp(pkg, "main") == 0 && strcmp(name, "main") != 0) + fprint(2, "%s: %s: not package main (package %s)\n", argv0, filename, name); + else if(strcmp(pkg, "main") != 0 && strcmp(name, "main") == 0) + fprint(2, "%s: %s: importing %s, found package main", argv0, filename, pkg); loadpkgdata(filename, pkg, p0, p1 - p0); } + // The __.PKGDEF archive summary has no local types. + if(whence == Pkgdef) + return; + // local types begin where exports end. // skip rest of line after $$ we found above p0 = p1 + 3; @@ -245,7 +256,7 @@ expandpkg(char *t0, char *pkg) int n; char *p; char *w, *w0, *t; - + n = 0; for(p=t0; (p=strstr(p, "\"\".")) != nil; p+=3) n++; @@ -343,7 +354,7 @@ loop: memmove(edef, meth, n); edef += n; } - + name = expandpkg(name, pkg); def = expandpkg(def, pkg); diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c index c13cd11c7..1af9f7a41 100644 --- a/src/cmd/ld/lib.c +++ b/src/cmd/ld/lib.c @@ -35,6 +35,7 @@ int iconv(Fmt*); char symname[] = SYMDEF; +char pkgname[] = "__.PKGDEF"; char* libdir[16]; int nlibdir = 0; int cout = -1; @@ -156,14 +157,14 @@ addlib(char *src, char *obj) }else strcpy(pname, name); cleanname(pname); - + /* runtime.a -> runtime */ if(strlen(name) > 2 && name[strlen(name)-2] == '.') name[strlen(name)-2] = '\0'; if(debug['v']) Bprint(&bso, "%5.2f addlib: %s %s pulls in %s\n", cputime(), obj, src, pname); - + addlibpath(src, obj, pname, name); } @@ -261,7 +262,7 @@ objfile(char *file, char *pkg) char name[100], pname[150]; struct ar_hdr arhdr; char *e, *start, *stop, *x; - + pkg = smprint("%i", pkg); if(file[0] == '-' && file[1] == 'l') { // TODO: fix this @@ -286,7 +287,7 @@ objfile(char *file, char *pkg) /* load it as a regular file */ l = Bseek(f, 0L, 2); Bseek(f, 0L, 0); - ldobj(f, pkg, l, file); + ldobj(f, pkg, l, file, FileObj); Bterm(f); return; } @@ -304,6 +305,25 @@ objfile(char *file, char *pkg) esym = SARMAG + SAR_HDR + atolwhex(arhdr.size); off = SARMAG + SAR_HDR; + if(debug['u']) { + struct ar_hdr pkghdr; + int n; + + // Read next ar header to check for package safe bit. + Bseek(f, esym+(esym&1), 0); + l = Bread(f, &pkghdr, SAR_HDR); + if(l != SAR_HDR) { + diag("%s: short read on second archive header", file); + goto out; + } + if(strncmp(pkghdr.name, pkgname, strlen(pkgname))) { + diag("%s: second entry not package header", file); + goto out; + } + n = atolwhex(pkghdr.size); + ldpkg(f, pkg, n, file, Pkgdef); + } + /* * just bang the whole symbol file into memory */ @@ -350,7 +370,7 @@ objfile(char *file, char *pkg) l--; sprint(pname, "%s(%.*s)", file, l, arhdr.name); l = atolwhex(arhdr.size); - ldobj(f, pkg, l, pname); + ldobj(f, pkg, l, pname, ArchiveObj); if(s->type == SXREF) { diag("%s: failed to load: %s", file, s->name); errorexit(); @@ -368,7 +388,7 @@ out: } void -ldobj(Biobuf *f, char *pkg, int64 len, char *pn) +ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence) { static int files; static char **filen; @@ -433,7 +453,7 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn) import1 = Boffset(f); Bseek(f, import0, 0); - ldpkg(f, pkg, import1 - import0 - 2, pn); // -2 for !\n + ldpkg(f, pkg, import1 - import0 - 2, pn, whence); // -2 for !\n Bseek(f, import1, 0); ldobj1(f, pkg, eof - Boffset(f), pn); diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h index 4307d2d41..652d845fb 100644 --- a/src/cmd/ld/lib.h +++ b/src/cmd/ld/lib.h @@ -88,8 +88,8 @@ void libinit(void); void Lflag(char *arg); void usage(void); void ldobj1(Biobuf *f, char*, int64 len, char *pn); -void ldobj(Biobuf*, char*, int64, char*); -void ldpkg(Biobuf*, char*, int64, char*); +void ldobj(Biobuf*, char*, int64, char*, int); +void ldpkg(Biobuf*, char*, int64, char*, int); void mark(Sym *s); char* expandpkg(char*, char*); void deadcode(void); @@ -102,3 +102,10 @@ void mywhatsys(void); extern char* goroot; extern char* goarch; extern char* goos; + +/* whence for ldpkg */ +enum { + FileObj = 0, + ArchiveObj, + Pkgdef +}; |