diff options
| author | Russ Cox <rsc@golang.org> | 2010-01-22 17:06:20 -0800 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2010-01-22 17:06:20 -0800 |
| commit | 758f2bc556b19a3b46798b28741bacc322b243f6 (patch) | |
| tree | d7b13240b0ba1b00553ca9ccbc0ea1e72948ad67 /src/cmd/ld | |
| parent | 07d3e0dce46ce438c7b07949d0e1725d6860e40d (diff) | |
| download | go-758f2bc556b19a3b46798b28741bacc322b243f6.tar.xz | |
eliminate the package global name space assumption in object files
5g/6g/8g: add import statements to export metadata, mapping package path to package name.
recognize "" as the path of the package in export metadata.
use "" as the path of the package in object symbol names.
5c/6c/8c, 5a/6a/8a: rewrite leading . to "". so that ·Sin means Sin in this package.
5l/6l/8l: rewrite "" in symbol names as object files are read.
gotest: handle new symbol names.
gopack: handle new import lines in export metadata.
Collectively, these changes eliminate the assumption of a global
name space in the object file formats. Higher level pieces such as
reflect and the computation of type hashes still depend on the
assumption; we're not done yet.
R=ken2, r, ken3
CC=golang-dev
https://golang.org/cl/186263
Diffstat (limited to 'src/cmd/ld')
| -rw-r--r-- | src/cmd/ld/go.c | 89 | ||||
| -rw-r--r-- | src/cmd/ld/lib.c | 127 | ||||
| -rw-r--r-- | src/cmd/ld/lib.h | 23 |
3 files changed, 170 insertions, 69 deletions
diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c index 8f9d198bc2..1797f34d30 100644 --- a/src/cmd/ld/go.c +++ b/src/cmd/ld/go.c @@ -65,13 +65,13 @@ ilookup(char *name) return x; } -static void loadpkgdata(char*, char*, int); +static void loadpkgdata(char*, char*, char*, int); static void loaddynld(char*, char*, int); static int parsemethod(char**, char*, char**); -static int parsepkgdata(char*, char**, char*, char**, char**, char**); +static int parsepkgdata(char*, char*, char**, char*, char**, char**, char**); void -ldpkg(Biobuf *f, int64 len, char *filename) +ldpkg(Biobuf *f, char *pkg, int64 len, char *filename) { char *data, *p0, *p1; @@ -115,8 +115,7 @@ ldpkg(Biobuf *f, int64 len, char *filename) p0++; while(*p0 != ' ' && *p0 != '\t' && *p0 != '\n') p0++; - - loadpkgdata(filename, p0, p1 - p0); + loadpkgdata(filename, pkg, p0, p1 - p0); } // local types begin where exports end. @@ -132,7 +131,8 @@ ldpkg(Biobuf *f, int64 len, char *filename) return; } - loadpkgdata(filename, p0, p1 - p0); + // PGNS: Should be using import path, not pkg. + loadpkgdata(filename, pkg, p0, p1 - p0); // look for dynld section p0 = strstr(p1, "\n$$ // dynld"); @@ -153,38 +153,16 @@ ldpkg(Biobuf *f, int64 len, char *filename) } } -/* - * a and b don't match. - * is one a forward declaration and the other a valid completion? - * if so, return the one to keep. - */ -char* -forwardfix(char *a, char *b) -{ - char *t; - - if(strlen(a) > strlen(b)) { - t = a; - a = b; - b = t; - } - if(strcmp(a, "struct") == 0 && strncmp(b, "struct ", 7) == 0) - return b; - if(strcmp(a, "interface") == 0 && strncmp(b, "interface ", 10) == 0) - return b; - return nil; -} - static void -loadpkgdata(char *file, char *data, int len) +loadpkgdata(char *file, char *pkg, char *data, int len) { - char *p, *ep, *prefix, *name, *def, *ndef; + char *p, *ep, *prefix, *name, *def; Import *x; file = strdup(file); p = data; ep = data + len; - while(parsepkgdata(file, &p, ep, &prefix, &name, &def) > 0) { + while(parsepkgdata(file, pkg, &p, ep, &prefix, &name, &def) > 0) { x = ilookup(name); if(x->prefix == nil) { x->prefix = prefix; @@ -195,11 +173,7 @@ loadpkgdata(char *file, char *data, int len) fprint(2, "%s:\t%s %s ...\n", x->file, x->prefix, name); fprint(2, "%s:\t%s %s ...\n", file, prefix, name); nerrors++; - } else if(strcmp(x->def, def) == 0) { - // fine - } else if((ndef = forwardfix(x->def, def)) != nil) { - x->def = ndef; - } else { + } else if(strcmp(x->def, def) != 0) { fprint(2, "%s: conflicting definitions for %s\n", argv0, name); fprint(2, "%s:\t%s %s %s\n", x->file, x->prefix, name, x->def); fprint(2, "%s:\t%s %s %s\n", file, prefix, name, def); @@ -208,14 +182,44 @@ loadpkgdata(char *file, char *data, int len) } } +// replace all "". with pkg. +char* +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++; + + if(n == 0) + return t0; + + // use malloc, not mal, so that caller can free + w0 = malloc(strlen(t0) + strlen(pkg)*n); + w = w0; + for(p=t=t0; (p=strstr(p, "\"\".")) != nil; p=t) { + memmove(w, t, p - t); + w += p-t; + strcpy(w, pkg); + w += strlen(pkg); + t = p+2; + } + strcpy(w, t); + return w0; +} + static int -parsepkgdata(char *file, char **pp, char *ep, char **prefixp, char **namep, char **defp) +parsepkgdata(char *file, char *pkg, char **pp, char *ep, char **prefixp, char **namep, char **defp) { char *p, *prefix, *name, *def, *edef, *meth; int n; // skip white space p = *pp; +loop: while(p < ep && (*p == ' ' || *p == '\t' || *p == '\n')) p++; if(p == ep || strncmp(p, "$$\n", 3) == 0) @@ -223,7 +227,7 @@ parsepkgdata(char *file, char **pp, char *ep, char **prefixp, char **namep, char // prefix: (var|type|func|const) prefix = p; - if(p + 6 > ep) + if(p + 7 > ep) return -1; if(strncmp(p, "var ", 4) == 0) p += 4; @@ -233,6 +237,12 @@ parsepkgdata(char *file, char **pp, char *ep, char **prefixp, char **namep, char p += 5; else if(strncmp(p, "const ", 6) == 0) p += 6; + else if(strncmp(p, "import ", 7) == 0) { + p += 7; + while(p < ep && *p != '\n') + p++; + goto loop; + } else { fprint(2, "%s: confused in pkg data near <<%.40s>>\n", argv0, prefix); nerrors++; @@ -277,6 +287,9 @@ parsepkgdata(char *file, char **pp, char *ep, char **prefixp, char **namep, char memmove(edef, meth, n); edef += n; } + + name = expandpkg(name, pkg); + def = expandpkg(def, pkg); // done *pp = p; diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c index 8039bf8ee0..7ede8c89e1 100644 --- a/src/cmd/ld/lib.c +++ b/src/cmd/ld/lib.c @@ -32,6 +32,8 @@ #include "lib.h" #include <ar.h> +int iconv(Fmt*); + char symname[] = SYMDEF; char* libdir[16] = { "." }; int nlibdir = 1; @@ -54,6 +56,7 @@ Lflag(char *arg) void libinit(void) { + fmtinstall('i', iconv); mywhatsys(); // get goroot, goarch, goos if(strcmp(goarch, thestring) != 0) print("goarch is not known: %s\n", goarch); @@ -91,6 +94,7 @@ addlib(char *src, char *obj) { char name[1024], pname[1024], comp[256], *p; int i, search; + Library *l; if(histfrogp <= 0) return; @@ -133,9 +137,11 @@ addlib(char *src, char *obj) diag("library component too long"); return; } - strcat(name, "/"); + if(i > 0 || !search) + strcat(name, "/"); strcat(name, comp); } + cleanname(name); if(search) { // try dot, -L "libdir", and then goroot. @@ -144,28 +150,42 @@ addlib(char *src, char *obj) if(access(pname, AEXIST) >= 0) break; } - strcpy(name, pname); - } - cleanname(name); + }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, name); + Bprint(&bso, "%5.2f addlib: %s %s pulls in %s\n", cputime(), obj, src, pname); for(i=0; i<libraryp; i++) - if(strcmp(name, library[i]) == 0) + if(strcmp(pname, library[i].file) == 0) return; if(libraryp == nlibrary){ nlibrary = 50 + 2*libraryp; library = realloc(library, sizeof library[0] * nlibrary); - libraryobj = realloc(libraryobj, sizeof libraryobj[0] * nlibrary); } - p = mal(strlen(name) + 1); - strcpy(p, name); - library[libraryp] = p; + l = &library[libraryp++]; + p = mal(strlen(obj) + 1); strcpy(p, obj); - libraryobj[libraryp] = p; - libraryp++; + l->objref = p; + + p = mal(strlen(src) + 1); + strcpy(p, src); + l->srcref = p; + + p = mal(strlen(pname) + 1); + strcpy(p, pname); + l->file = p; + + p = mal(strlen(name) + 1); + strcpy(p, name); + l->pkg = p; } void @@ -180,8 +200,8 @@ loop: xrefresolv = 0; for(i=0; i<libraryp; i++) { if(debug['v']) - Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i], libraryobj[i]); - objfile(library[i]); + Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i].file, library[i].objref); + objfile(library[i].file, library[i].pkg); } if(xrefresolv) for(h=0; h<nelem(hash); h++) @@ -192,11 +212,11 @@ loop: i = strlen(goroot)+strlen(goarch)+strlen(goos)+20; a = mal(i); snprint(a, i, "%s/pkg/%s_%s/runtime.a", goroot, goos, goarch); - objfile(a); + objfile(a, "runtime"); } void -objfile(char *file) +objfile(char *file, char *pkg) { int32 off, esym, cnt, l; int work; @@ -205,7 +225,9 @@ objfile(char *file) char magbuf[SARMAG]; char name[100], pname[150]; struct ar_hdr arhdr; - char *e, *start, *stop; + char *e, *start, *stop, *x; + + pkg = smprint("%i", pkg); if(file[0] == '-' && file[1] == 'l') { // TODO: fix this if(debug['9']) @@ -217,7 +239,7 @@ objfile(char *file) file = name; } if(debug['v']) - Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file); + Bprint(&bso, "%5.2f ldobj: %s (%s)\n", cputime(), file, pkg); Bflush(&bso); f = Bopen(file, 0); if(f == nil) { @@ -229,7 +251,7 @@ objfile(char *file) /* load it as a regular file */ l = Bseek(f, 0L, 2); Bseek(f, 0L, 0); - ldobj(f, l, file); + ldobj(f, pkg, l, file); Bterm(f); return; } @@ -268,7 +290,10 @@ objfile(char *file) Bflush(&bso); work = 0; for(e = start; e < stop; e = strchr(e+5, 0) + 1) { - s = lookup(e+5, 0); + x = expandpkg(e+5, pkg); + s = lookup(x, 0); + if(x != e+5) + free(x); if(s->type != SXREF) continue; sprint(pname, "%s(%s)", file, s->name); @@ -290,7 +315,7 @@ objfile(char *file) l--; sprint(pname, "%s(%.*s)", file, l, arhdr.name); l = atolwhex(arhdr.size); - ldobj(f, l, pname); + ldobj(f, pkg, l, pname); if(s->type == SXREF) { diag("%s: failed to load: %s", file, s->name); errorexit(); @@ -308,7 +333,7 @@ out: } void -ldobj(Biobuf *f, int64 len, char *pn) +ldobj(Biobuf *f, char *pkg, int64 len, char *pn) { static int files; static char **filen; @@ -362,10 +387,11 @@ ldobj(Biobuf *f, int64 len, char *pn) import1 = Boffset(f); Bseek(f, import0, 0); - ldpkg(f, import1 - import0 - 2, pn); // -2 for !\n + ldpkg(f, pkg, import1 - import0 - 2, pn); // -2 for !\n Bseek(f, import1, 0); - ldobj1(f, eof - Boffset(f), pn); + // PGNS: Should be using import path, not pkg. + ldobj1(f, pkg, eof - Boffset(f), pn); return; eof: @@ -757,3 +783,56 @@ mal(uint32 n) memset(v, 0, n); return v; } + +// Copied from ../gc/subr.c:/^pathtoprefix; must stay in sync. +/* + * 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. + */ +static char* +pathtoprefix(char *s) +{ + static char hex[] = "0123456789abcdef"; + char *p, *r, *w; + int n; + + // check for chars that need escaping + n = 0; + for(r=s; *r; r++) + if(*r <= ' ' || *r == '.' || *r == '%' || *r == '"') + n++; + + // quick exit + if(n == 0) + return s; + + // escape + p = mal((r-s)+1+2*n); + for(r=s, w=p; *r; r++) { + if(*r <= ' ' || *r == '.' || *r == '%' || *r == '"') { + *w++ = '%'; + *w++ = hex[(*r>>4)&0xF]; + *w++ = hex[*r&0xF]; + } else + *w++ = *r; + } + *w = '\0'; + return p; +} + +int +iconv(Fmt *fp) +{ + char *p; + + p = va_arg(fp->args, char*); + if(p == nil) { + fmtstrcpy(fp, "<nil>"); + return 0; + } + p = pathtoprefix(p); + fmtstrcpy(fp, p); + return 0; +} + diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h index bf26ae87d8..8943b05aa6 100644 --- a/src/cmd/ld/lib.h +++ b/src/cmd/ld/lib.h @@ -28,6 +28,15 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +typedef struct Library Library; +struct Library +{ + char *objref; // object where we found the reference + char *srcref; // src file where we found the reference + char *file; // object file + char *pkg; // import path +}; + extern char symname[]; extern char *libdir[]; extern int nlibdir; @@ -36,8 +45,7 @@ extern int cout; EXTERN char* INITENTRY; EXTERN char thechar; EXTERN char* thestring; -EXTERN char** library; -EXTERN char** libraryobj; +EXTERN Library* library; EXTERN int libraryp; EXTERN int nlibrary; EXTERN Sym* hash[NHASH]; @@ -71,15 +79,16 @@ void readundefs(char *f, int t); int32 Bget4(Biobuf *f); void loadlib(void); void errorexit(void); -void objfile(char *file); +void objfile(char *file, char *pkg); void libinit(void); void Lflag(char *arg); void usage(void); -void ldobj1(Biobuf *f, int64 len, char *pn); -void ldobj(Biobuf*, int64, char*); -void ldpkg(Biobuf*, int64, char*); +void ldobj1(Biobuf *f, char*, int64 len, char *pn); +void ldobj(Biobuf*, char*, int64, char*); +void ldpkg(Biobuf*, char*, int64, char*); void mark(Sym *s); - +char* expandpkg(char*, char*); +void deadcode(void); int pathchar(void); void* mal(uint32); |
