diff options
Diffstat (limited to 'src/cmd/ld/go.c')
-rw-r--r-- | src/cmd/ld/go.c | 710 |
1 files changed, 0 insertions, 710 deletions
diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c deleted file mode 100644 index 05d1cc136..000000000 --- a/src/cmd/ld/go.c +++ /dev/null @@ -1,710 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// go-specific code shared across loaders (5l, 6l, 8l). - -#include "l.h" -#include "../ld/lib.h" - -// accumulate all type information from .6 files. -// check for inconsistencies. - -// TODO: -// generate debugging section in binary. -// once the dust settles, try to move some code to -// libmach, so that other linkers and ar can share. - -/* - * package import data - */ -typedef struct Import Import; -struct Import -{ - Import *hash; // next in hash table - char *prefix; // "type", "var", "func", "const" - char *name; - char *def; - char *file; -}; -enum { - NIHASH = 1024 -}; -static Import *ihash[NIHASH]; -static int nimport; - -static int -hashstr(char *name) -{ - int h; - char *cp; - - h = 0; - for(cp = name; *cp; h += *cp++) - h *= 1119; - // not if(h < 0) h = ~h, because gcc 4.3 -O2 miscompiles it. - h &= 0xffffff; - return h; -} - -static Import * -ilookup(char *name) -{ - int h; - Import *x; - - h = hashstr(name) % NIHASH; - for(x=ihash[h]; x; x=x->hash) - if(x->name[0] == name[0] && strcmp(x->name, name) == 0) - return x; - x = mal(sizeof *x); - x->name = strdup(name); - x->hash = ihash[h]; - ihash[h] = x; - nimport++; - return x; -} - -static void loadpkgdata(char*, char*, char*, int); -static void loaddynimport(char*, char*, char*, int); -static void loaddynexport(char*, char*, char*, int); -static int parsemethod(char**, char*, char**); -static int parsepkgdata(char*, char*, char**, char*, char**, char**, char**); - -static Sym **dynexp; - -void -ldpkg(Biobuf *f, char *pkg, int64 len, char *filename, int whence) -{ - char *data, *p0, *p1, *name; - - if(debug['g']) - return; - - if((int)len != len) { - fprint(2, "%s: too much pkg data in %s\n", argv0, filename); - if(debug['u']) - errorexit(); - return; - } - data = mal(len+1); - if(Bread(f, data, len) != len) { - fprint(2, "%s: short pkg read %s\n", argv0, filename); - if(debug['u']) - errorexit(); - return; - } - data[len] = '\0'; - - // first \n$$ marks beginning of exports - skip rest of line - p0 = strstr(data, "\n$$"); - if(p0 == nil) { - if(debug['u'] && whence != ArchiveObj) { - fprint(2, "%s: cannot find export data in %s\n", argv0, filename); - errorexit(); - } - return; - } - p0 += 3; - while(*p0 != '\n' && *p0 != '\0') - p0++; - - // second marks end of exports / beginning of local data - p1 = strstr(p0, "\n$$"); - if(p1 == nil) { - fprint(2, "%s: cannot find end of exports in %s\n", argv0, filename); - if(debug['u']) - errorexit(); - return; - } - while(p0 < p1 && (*p0 == ' ' || *p0 == '\t' || *p0 == '\n')) - p0++; - if(p0 < p1) { - if(strncmp(p0, "package ", 8) != 0) { - fprint(2, "%s: bad package section in %s - %s\n", argv0, filename, p0); - if(debug['u']) - errorexit(); - return; - } - p0 += 8; - while(p0 < p1 && (*p0 == ' ' || *p0 == '\t' || *p0 == '\n')) - p0++; - name = p0; - while(p0 < p1 && *p0 != ' ' && *p0 != '\t' && *p0 != '\n') - p0++; - 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); - nerrors++; - errorexit(); - } - if(p0 < p1) { - 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); - 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; - while(*p0 != '\n' && *p0 != '\0') - p0++; - - // local types end at next \n$$. - p1 = strstr(p0, "\n$$"); - if(p1 == nil) { - fprint(2, "%s: cannot find end of local types in %s\n", argv0, filename); - if(debug['u']) - errorexit(); - return; - } - - loadpkgdata(filename, pkg, p0, p1 - p0); - - // look for dynimport section - p0 = strstr(p1, "\n$$ // dynimport"); - if(p0 != nil) { - p0 = strchr(p0+1, '\n'); - if(p0 == nil) { - fprint(2, "%s: found $$ // dynimport but no newline in %s\n", argv0, filename); - if(debug['u']) - errorexit(); - return; - } - p1 = strstr(p0, "\n$$"); - if(p1 == nil) - p1 = strstr(p0, "\n!\n"); - if(p1 == nil) { - fprint(2, "%s: cannot find end of // dynimport section in %s\n", argv0, filename); - if(debug['u']) - errorexit(); - return; - } - loaddynimport(filename, pkg, p0 + 1, p1 - (p0+1)); - } - - // look for dynexp section - p0 = strstr(p1, "\n$$ // dynexport"); - if(p0 != nil) { - p0 = strchr(p0+1, '\n'); - if(p0 == nil) { - fprint(2, "%s: found $$ // dynexporg but no newline in %s\n", argv0, filename); - if(debug['u']) - errorexit(); - return; - } - p1 = strstr(p0, "\n$$"); - if(p1 == nil) - p1 = strstr(p0, "\n!\n"); - if(p1 == nil) { - fprint(2, "%s: cannot find end of // dynexporg section in %s\n", argv0, filename); - if(debug['u']) - errorexit(); - return; - } - loaddynexport(filename, pkg, p0 + 1, p1 - (p0+1)); - } -} - -static void -loadpkgdata(char *file, char *pkg, char *data, int len) -{ - char *p, *ep, *prefix, *name, *def; - Import *x; - - file = strdup(file); - p = data; - ep = data + len; - while(parsepkgdata(file, pkg, &p, ep, &prefix, &name, &def) > 0) { - x = ilookup(name); - if(x->prefix == nil) { - x->prefix = prefix; - x->def = def; - x->file = file; - } else if(strcmp(x->prefix, prefix) != 0) { - fprint(2, "%s: conflicting definitions for %s\n", argv0, name); - 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) { - 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); - nerrors++; - } - } -} - -// 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); - if(w0 == nil) { - diag("out of memory"); - errorexit(); - } - 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 *pkg, char **pp, char *ep, char **prefixp, char **namep, char **defp) -{ - char *p, *prefix, *name, *def, *edef, *meth; - int n, inquote; - - // skip white space - p = *pp; -loop: - while(p < ep && (*p == ' ' || *p == '\t' || *p == '\n')) - p++; - if(p == ep || strncmp(p, "$$\n", 3) == 0) - return 0; - - // prefix: (var|type|func|const) - prefix = p; - if(p + 7 > ep) - return -1; - if(strncmp(p, "var ", 4) == 0) - p += 4; - else if(strncmp(p, "type ", 5) == 0) - p += 5; - else if(strncmp(p, "func ", 5) == 0) - 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++; - return -1; - } - p[-1] = '\0'; - - // name: a.b followed by space - name = p; - inquote = 0; - while(p < ep) { - if (*p == ' ' && !inquote) - break; - - if(*p == '\\') - p++; - else if(*p == '"') - inquote = !inquote; - - p++; - } - - if(p >= ep) - return -1; - *p++ = '\0'; - - // def: free form to new line - def = p; - while(p < ep && *p != '\n') - p++; - if(p >= ep) - return -1; - edef = p; - *p++ = '\0'; - - // include methods on successive lines in def of named type - while(parsemethod(&p, ep, &meth) > 0) { - *edef++ = '\n'; // overwrites '\0' - if(edef+1 > meth) { - // We want to indent methods with a single \t. - // 6g puts at least one char of indent before all method defs, - // so there will be room for the \t. If the method def wasn't - // indented we could do something more complicated, - // but for now just diagnose the problem and assume - // 6g will keep indenting for us. - fprint(2, "%s: %s: expected methods to be indented %p %p %.10s\n", argv0, - file, edef, meth, meth); - nerrors++; - return -1; - } - *edef++ = '\t'; - n = strlen(meth); - memmove(edef, meth, n); - edef += n; - } - - name = expandpkg(name, pkg); - def = expandpkg(def, pkg); - - // done - *pp = p; - *prefixp = prefix; - *namep = name; - *defp = def; - return 1; -} - -static int -parsemethod(char **pp, char *ep, char **methp) -{ - char *p; - - // skip white space - p = *pp; - while(p < ep && (*p == ' ' || *p == '\t')) - p++; - if(p == ep) - return 0; - - // if it says "func (", it's a method - if(p + 6 >= ep || strncmp(p, "func (", 6) != 0) - return 0; - - // definition to end of line - *methp = p; - while(p < ep && *p != '\n') - p++; - if(p >= ep) { - fprint(2, "%s: lost end of line in method definition\n", argv0); - *pp = ep; - return -1; - } - *p++ = '\0'; - *pp = p; - return 1; -} - -static void -loaddynimport(char *file, char *pkg, char *p, int n) -{ - char *pend, *next, *name, *def, *p0, *lib, *q; - Sym *s; - - USED(file); - pend = p + n; - for(; p<pend; p=next) { - next = strchr(p, '\n'); - if(next == nil) - next = ""; - else - *next++ = '\0'; - p0 = p; - if(strncmp(p, "dynimport ", 10) != 0) - goto err; - p += 10; - name = p; - p = strchr(name, ' '); - if(p == nil) - goto err; - while(*p == ' ') - p++; - def = p; - p = strchr(def, ' '); - if(p == nil) - goto err; - while(*p == ' ') - p++; - lib = p; - - // successful parse: now can edit the line - *strchr(name, ' ') = 0; - *strchr(def, ' ') = 0; - - if(debug['d']) { - fprint(2, "%s: %s: cannot use dynamic imports with -d flag\n", argv0, file); - nerrors++; - return; - } - - if(strcmp(name, "_") == 0 && strcmp(def, "_") == 0) { - // allow #pragma dynimport _ _ "foo.so" - // to force a link of foo.so. - havedynamic = 1; - adddynlib(lib); - continue; - } - - name = expandpkg(name, pkg); - q = strchr(def, '@'); - if(q) - *q++ = '\0'; - s = lookup(name, 0); - if(s->type == 0 || s->type == SXREF) { - s->dynimplib = lib; - s->dynimpname = def; - s->dynimpvers = q; - s->type = SDYNIMPORT; - havedynamic = 1; - } - } - return; - -err: - fprint(2, "%s: %s: invalid dynimport line: %s\n", argv0, file, p0); - nerrors++; -} - -static void -loaddynexport(char *file, char *pkg, char *p, int n) -{ - char *pend, *next, *local, *elocal, *remote, *p0; - Sym *s; - - USED(file); - pend = p + n; - for(; p<pend; p=next) { - next = strchr(p, '\n'); - if(next == nil) - next = ""; - else - *next++ = '\0'; - p0 = p; - if(strncmp(p, "dynexport ", 10) != 0) - goto err; - p += 10; - local = p; - p = strchr(local, ' '); - if(p == nil) - goto err; - while(*p == ' ') - p++; - remote = p; - - // successful parse: now can edit the line - *strchr(local, ' ') = 0; - - elocal = expandpkg(local, pkg); - - s = lookup(elocal, 0); - if(s->dynimplib != nil) { - fprint(2, "%s: symbol is both dynimport and dynexport %s\n", argv0, local); - nerrors++; - } - s->dynimpname = remote; - s->dynexport = 1; - - if(ndynexp%32 == 0) - dynexp = realloc(dynexp, (ndynexp+32)*sizeof dynexp[0]); - dynexp[ndynexp++] = s; - - if (elocal != local) - free(elocal); - } - return; - -err: - fprint(2, "%s: invalid dynexport line: %s\n", argv0, p0); - nerrors++; -} - -static int markdepth; - -static void -marktext(Sym *s) -{ - Auto *a; - Prog *p; - - if(s == S) - return; - markdepth++; - if(debug['v'] > 1) - Bprint(&bso, "%d marktext %s\n", markdepth, s->name); - for(a=s->autom; a; a=a->link) - mark(a->gotype); - for(p=s->text; p != P; p=p->link) { - if(p->from.sym) - mark(p->from.sym); - if(p->to.sym) - mark(p->to.sym); - } - markdepth--; -} - -void -mark(Sym *s) -{ - int i; - - if(s == S || s->reachable) - return; - if(strncmp(s->name, "weak.", 5) == 0) - return; - s->reachable = 1; - if(s->text) - marktext(s); - for(i=0; i<s->nr; i++) - mark(s->r[i].sym); - if(s->gotype) - mark(s->gotype); - if(s->sub) - mark(s->sub); - if(s->outer) - mark(s->outer); -} - -static char* -morename[] = -{ - "runtime.morestack", - "runtime.morestackx", - - "runtime.morestack00", - "runtime.morestack10", - "runtime.morestack01", - "runtime.morestack11", - - "runtime.morestack8", - "runtime.morestack16", - "runtime.morestack24", - "runtime.morestack32", - "runtime.morestack40", - "runtime.morestack48", -}; - -static int -isz(Auto *a) -{ - for(; a; a=a->link) - if(a->type == D_FILE || a->type == D_FILE1) - return 1; - return 0; -} - -static void -addz(Sym *s, Auto *z) -{ - Auto *a, *last; - - // strip out non-z - last = nil; - for(a = z; a != nil; a = a->link) { - if(a->type == D_FILE || a->type == D_FILE1) { - if(last == nil) - z = a; - else - last->link = a; - last = a; - } - } - if(last) { - last->link = s->autom; - s->autom = z; - } -} - -void -deadcode(void) -{ - int i; - Sym *s, *last; - Auto *z; - - if(debug['v']) - Bprint(&bso, "%5.2f deadcode\n", cputime()); - - mark(lookup(INITENTRY, 0)); - for(i=0; i<nelem(morename); i++) - mark(lookup(morename[i], 0)); - - for(i=0; i<ndynexp; i++) - mark(dynexp[i]); - - // remove dead text but keep file information (z symbols). - last = nil; - z = nil; - for(s = textp; s != nil; s = s->next) { - if(!s->reachable) { - if(isz(s->autom)) - z = s->autom; - continue; - } - if(last == nil) - textp = s; - else - last->next = s; - last = s; - if(z != nil) { - if(!isz(s->autom)) - addz(s, z); - z = nil; - } - } - if(last == nil) - textp = nil; - else - last->next = nil; - - for(s = allsym; s != S; s = s->allsym) - if(strncmp(s->name, "weak.", 5) == 0) { - s->special = 1; // do not lay out in data segment - s->reachable = 1; - s->hide = 1; - } -} - -void -doweak(void) -{ - Sym *s, *t; - - // resolve weak references only if - // target symbol will be in binary anyway. - for(s = allsym; s != S; s = s->allsym) { - if(strncmp(s->name, "weak.", 5) == 0) { - t = rlookup(s->name+5, s->version); - if(t && t->type != 0 && t->reachable) { - s->value = t->value; - s->type = t->type; - } else { - s->type = SCONST; - s->value = 0; - } - continue; - } - } -} - -void -addexport(void) -{ - int i; - - for(i=0; i<ndynexp; i++) - adddynsym(dynexp[i]); -} |