github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/ld/go.c (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // go-specific code shared across loaders (5l, 6l, 8l).
     6  
     7  #include	"l.h"
     8  #include	"../ld/lib.h"
     9  
    10  // accumulate all type information from .6 files.
    11  // check for inconsistencies.
    12  
    13  // TODO:
    14  //	generate debugging section in binary.
    15  //	once the dust settles, try to move some code to
    16  //		libmach, so that other linkers and ar can share.
    17  
    18  /*
    19   *	package import data
    20   */
    21  typedef struct Import Import;
    22  struct Import
    23  {
    24  	Import *hash;	// next in hash table
    25  	char *prefix;	// "type", "var", "func", "const"
    26  	char *name;
    27  	char *def;
    28  	char *file;
    29  };
    30  enum {
    31  	NIHASH = 1024
    32  };
    33  static Import *ihash[NIHASH];
    34  static int nimport;
    35  static void imported(char *pkg, char *import);
    36  
    37  static int
    38  hashstr(char *name)
    39  {
    40  	int h;
    41  	char *cp;
    42  
    43  	h = 0;
    44  	for(cp = name; *cp; h += *cp++)
    45  		h *= 1119;
    46  	// not if(h < 0) h = ~h, because gcc 4.3 -O2 miscompiles it.
    47  	h &= 0xffffff;
    48  	return h;
    49  }
    50  
    51  static Import *
    52  ilookup(char *name)
    53  {
    54  	int h;
    55  	Import *x;
    56  
    57  	h = hashstr(name) % NIHASH;
    58  	for(x=ihash[h]; x; x=x->hash)
    59  		if(x->name[0] == name[0] && strcmp(x->name, name) == 0)
    60  			return x;
    61  	x = mal(sizeof *x);
    62  	x->name = estrdup(name);
    63  	x->hash = ihash[h];
    64  	ihash[h] = x;
    65  	nimport++;
    66  	return x;
    67  }
    68  
    69  static void loadpkgdata(char*, char*, char*, int);
    70  static void loadcgo(char*, char*, char*, int);
    71  static int parsemethod(char**, char*, char**);
    72  static int parsepkgdata(char*, char*, char**, char*, char**, char**, char**);
    73  
    74  void
    75  ldpkg(Biobuf *f, char *pkg, int64 len, char *filename, int whence)
    76  {
    77  	char *data, *p0, *p1, *name;
    78  
    79  	if(debug['g'])
    80  		return;
    81  
    82  	if((int)len != len) {
    83  		fprint(2, "%s: too much pkg data in %s\n", argv0, filename);
    84  		if(debug['u'])
    85  			errorexit();
    86  		return;
    87  	}
    88  	data = mal(len+1);
    89  	if(Bread(f, data, len) != len) {
    90  		fprint(2, "%s: short pkg read %s\n", argv0, filename);
    91  		if(debug['u'])
    92  			errorexit();
    93  		return;
    94  	}
    95  	data[len] = '\0';
    96  
    97  	// first \n$$ marks beginning of exports - skip rest of line
    98  	p0 = strstr(data, "\n$$");
    99  	if(p0 == nil) {
   100  		if(debug['u'] && whence != ArchiveObj) {
   101  			fprint(2, "%s: cannot find export data in %s\n", argv0, filename);
   102  			errorexit();
   103  		}
   104  		return;
   105  	}
   106  	p0 += 3;
   107  	while(*p0 != '\n' && *p0 != '\0')
   108  		p0++;
   109  
   110  	// second marks end of exports / beginning of local data
   111  	p1 = strstr(p0, "\n$$");
   112  	if(p1 == nil) {
   113  		fprint(2, "%s: cannot find end of exports in %s\n", argv0, filename);
   114  		if(debug['u'])
   115  			errorexit();
   116  		return;
   117  	}
   118  	while(p0 < p1 && (*p0 == ' ' || *p0 == '\t' || *p0 == '\n'))
   119  		p0++;
   120  	if(p0 < p1) {
   121  		if(strncmp(p0, "package ", 8) != 0) {
   122  			fprint(2, "%s: bad package section in %s - %s\n", argv0, filename, p0);
   123  			if(debug['u'])
   124  				errorexit();
   125  			return;
   126  		}
   127  		p0 += 8;
   128  		while(p0 < p1 && (*p0 == ' ' || *p0 == '\t' || *p0 == '\n'))
   129  			p0++;
   130  		name = p0;
   131  		while(p0 < p1 && *p0 != ' ' && *p0 != '\t' && *p0 != '\n')
   132  			p0++;
   133  		if(debug['u'] && whence != ArchiveObj &&
   134  		   (p0+6 > p1 || memcmp(p0, " safe\n", 6) != 0)) {
   135  			fprint(2, "%s: load of unsafe package %s\n", argv0, filename);
   136  			nerrors++;
   137  			errorexit();
   138  		}
   139  		if(p0 < p1) {
   140  			if(*p0 == '\n')
   141  				*p0++ = '\0';
   142  			else {
   143  				*p0++ = '\0';
   144  				while(p0 < p1 && *p0++ != '\n')
   145  					;
   146  			}
   147  		}
   148  		if(strcmp(pkg, "main") == 0 && strcmp(name, "main") != 0) {
   149  			fprint(2, "%s: %s: not package main (package %s)\n", argv0, filename, name);
   150  			nerrors++;
   151  			errorexit();
   152  		}
   153  		loadpkgdata(filename, pkg, p0, p1 - p0);
   154  	}
   155  
   156  	// The __.PKGDEF archive summary has no local types.
   157  	if(whence == Pkgdef)
   158  		return;
   159  
   160  	// local types begin where exports end.
   161  	// skip rest of line after $$ we found above
   162  	p0 = p1 + 3;
   163  	while(*p0 != '\n' && *p0 != '\0')
   164  		p0++;
   165  
   166  	// local types end at next \n$$.
   167  	p1 = strstr(p0, "\n$$");
   168  	if(p1 == nil) {
   169  		fprint(2, "%s: cannot find end of local types in %s\n", argv0, filename);
   170  		if(debug['u'])
   171  			errorexit();
   172  		return;
   173  	}
   174  
   175  	loadpkgdata(filename, pkg, p0, p1 - p0);
   176  
   177  	// look for cgo section
   178  	p0 = strstr(p1, "\n$$  // cgo");
   179  	if(p0 != nil) {
   180  		p0 = strchr(p0+1, '\n');
   181  		if(p0 == nil) {
   182  			fprint(2, "%s: found $$ // cgo but no newline in %s\n", argv0, filename);
   183  			if(debug['u'])
   184  				errorexit();
   185  			return;
   186  		}
   187  		p1 = strstr(p0, "\n$$");
   188  		if(p1 == nil)
   189  			p1 = strstr(p0, "\n!\n");
   190  		if(p1 == nil) {
   191  			fprint(2, "%s: cannot find end of // cgo section in %s\n", argv0, filename);
   192  			if(debug['u'])
   193  				errorexit();
   194  			return;
   195  		}
   196  		loadcgo(filename, pkg, p0 + 1, p1 - (p0+1));
   197  	}
   198  }
   199  
   200  static void
   201  loadpkgdata(char *file, char *pkg, char *data, int len)
   202  {
   203  	char *p, *ep, *prefix, *name, *def;
   204  	Import *x;
   205  
   206  	file = estrdup(file);
   207  	p = data;
   208  	ep = data + len;
   209  	while(parsepkgdata(file, pkg, &p, ep, &prefix, &name, &def) > 0) {
   210  		x = ilookup(name);
   211  		if(x->prefix == nil) {
   212  			x->prefix = prefix;
   213  			x->def = estrdup(def);
   214  			x->file = file;
   215  		} else if(strcmp(x->prefix, prefix) != 0) {
   216  			fprint(2, "%s: conflicting definitions for %s\n", argv0, name);
   217  			fprint(2, "%s:\t%s %s ...\n", x->file, x->prefix, name);
   218  			fprint(2, "%s:\t%s %s ...\n", file, prefix, name);
   219  			nerrors++;
   220  		} else if(strcmp(x->def, def) != 0) {
   221  			fprint(2, "%s: conflicting definitions for %s\n", argv0, name);
   222  			fprint(2, "%s:\t%s %s %s\n", x->file, x->prefix, name, x->def);
   223  			fprint(2, "%s:\t%s %s %s\n", file, prefix, name, def);
   224  			nerrors++;
   225  		}
   226  		free(name);
   227  		free(def);
   228  	}
   229  	free(file);
   230  }
   231  
   232  // replace all "". with pkg.
   233  char*
   234  expandpkg(char *t0, char *pkg)
   235  {
   236  	int n;
   237  	char *p;
   238  	char *w, *w0, *t;
   239  
   240  	n = 0;
   241  	for(p=t0; (p=strstr(p, "\"\".")) != nil; p+=3)
   242  		n++;
   243  
   244  	if(n == 0)
   245  		return estrdup(t0);
   246  
   247  	// use malloc, not mal, so that caller can free
   248  	w0 = malloc(strlen(t0) + strlen(pkg)*n);
   249  	if(w0 == nil) {
   250  		diag("out of memory");
   251  		errorexit();
   252  	}
   253  	w = w0;
   254  	for(p=t=t0; (p=strstr(p, "\"\".")) != nil; p=t) {
   255  		memmove(w, t, p - t);
   256  		w += p-t;
   257  		strcpy(w, pkg);
   258  		w += strlen(pkg);
   259  		t = p+2;
   260  	}
   261  	strcpy(w, t);
   262  	return w0;
   263  }
   264  
   265  static int
   266  parsepkgdata(char *file, char *pkg, char **pp, char *ep, char **prefixp, char **namep, char **defp)
   267  {
   268  	char *p, *prefix, *name, *def, *edef, *meth;
   269  	int n, inquote;
   270  
   271  	// skip white space
   272  	p = *pp;
   273  loop:
   274  	while(p < ep && (*p == ' ' || *p == '\t' || *p == '\n'))
   275  		p++;
   276  	if(p == ep || strncmp(p, "$$\n", 3) == 0)
   277  		return 0;
   278  
   279  	// prefix: (var|type|func|const)
   280  	prefix = p;
   281  	if(p + 7 > ep)
   282  		return -1;
   283  	if(strncmp(p, "var ", 4) == 0)
   284  		p += 4;
   285  	else if(strncmp(p, "type ", 5) == 0)
   286  		p += 5;
   287  	else if(strncmp(p, "func ", 5) == 0)
   288  		p += 5;
   289  	else if(strncmp(p, "const ", 6) == 0)
   290  		p += 6;
   291  	else if(strncmp(p, "import ", 7) == 0) {
   292  		p += 7;
   293  		while(p < ep && *p != ' ')
   294  			p++;
   295  		p++;
   296  		name = p;
   297  		while(p < ep && *p != '\n')
   298  			p++;
   299  		if(p >= ep) {
   300  			fprint(2, "%s: %s: confused in import line\n", argv0, file);
   301  			nerrors++;
   302  			return -1;
   303  		}
   304  		*p++ = '\0';
   305  		imported(pkg, name);
   306  		goto loop;
   307  	}
   308  	else {
   309  		fprint(2, "%s: %s: confused in pkg data near <<%.40s>>\n", argv0, file, prefix);
   310  		nerrors++;
   311  		return -1;
   312  	}
   313  	p[-1] = '\0';
   314  
   315  	// name: a.b followed by space
   316  	name = p;
   317  	inquote = 0;
   318  	while(p < ep) {
   319  		if (*p == ' ' && !inquote)
   320  			break;
   321  
   322  		if(*p == '\\')
   323  			p++;
   324  		else if(*p == '"')
   325  			inquote = !inquote;
   326  
   327  		p++;
   328  	}
   329  
   330  	if(p >= ep)
   331  		return -1;
   332  	*p++ = '\0';
   333  
   334  	// def: free form to new line
   335  	def = p;
   336  	while(p < ep && *p != '\n')
   337  		p++;
   338  	if(p >= ep)
   339  		return -1;
   340  	edef = p;
   341  	*p++ = '\0';
   342  
   343  	// include methods on successive lines in def of named type
   344  	while(parsemethod(&p, ep, &meth) > 0) {
   345  		*edef++ = '\n';	// overwrites '\0'
   346  		if(edef+1 > meth) {
   347  			// We want to indent methods with a single \t.
   348  			// 6g puts at least one char of indent before all method defs,
   349  			// so there will be room for the \t.  If the method def wasn't
   350  			// indented we could do something more complicated,
   351  			// but for now just diagnose the problem and assume
   352  			// 6g will keep indenting for us.
   353  			fprint(2, "%s: %s: expected methods to be indented %p %p %.10s\n", argv0,
   354  				file, edef, meth, meth);
   355  			nerrors++;
   356  			return -1;
   357  		}
   358  		*edef++ = '\t';
   359  		n = strlen(meth);
   360  		memmove(edef, meth, n);
   361  		edef += n;
   362  	}
   363  
   364  	name = expandpkg(name, pkg);
   365  	def = expandpkg(def, pkg);
   366  
   367  	// done
   368  	*pp = p;
   369  	*prefixp = prefix;
   370  	*namep = name;
   371  	*defp = def;
   372  	return 1;
   373  }
   374  
   375  static int
   376  parsemethod(char **pp, char *ep, char **methp)
   377  {
   378  	char *p;
   379  
   380  	// skip white space
   381  	p = *pp;
   382  	while(p < ep && (*p == ' ' || *p == '\t'))
   383  		p++;
   384  	if(p == ep)
   385  		return 0;
   386  
   387  	// might be a comment about the method
   388  	if(p + 2 < ep && strncmp(p, "//", 2) == 0)
   389  		goto useline;
   390  	
   391  	// if it says "func (", it's a method
   392  	if(p + 6 < ep && strncmp(p, "func (", 6) == 0)
   393  		goto useline;
   394  	return 0;
   395  
   396  useline:
   397  	// definition to end of line
   398  	*methp = p;
   399  	while(p < ep && *p != '\n')
   400  		p++;
   401  	if(p >= ep) {
   402  		fprint(2, "%s: lost end of line in method definition\n", argv0);
   403  		*pp = ep;
   404  		return -1;
   405  	}
   406  	*p++ = '\0';
   407  	*pp = p;
   408  	return 1;
   409  }
   410  
   411  static void
   412  loadcgo(char *file, char *pkg, char *p, int n)
   413  {
   414  	char *pend, *next, *p0, *q;
   415  	char *f[10], *local, *remote, *lib;
   416  	int nf;
   417  	Sym *s;
   418  
   419  	USED(file);
   420  	pend = p + n;
   421  	p0 = nil;
   422  	for(; p<pend; p=next) {
   423  		next = strchr(p, '\n');
   424  		if(next == nil)
   425  			next = "";
   426  		else
   427  			*next++ = '\0';
   428  
   429  		free(p0);
   430  		p0 = estrdup(p); // save for error message
   431  		nf = tokenize(p, f, nelem(f));
   432  		
   433  		if(strcmp(f[0], "cgo_import_dynamic") == 0) {
   434  			if(nf < 2 || nf > 4)
   435  				goto err;
   436  			
   437  			local = f[1];
   438  			remote = local;
   439  			if(nf > 2)
   440  				remote = f[2];
   441  			lib = "";
   442  			if(nf > 3)
   443  				lib = f[3];
   444  			
   445  			if(debug['d']) {
   446  				fprint(2, "%s: %s: cannot use dynamic imports with -d flag\n", argv0, file);
   447  				nerrors++;
   448  				return;
   449  			}
   450  		
   451  			if(strcmp(local, "_") == 0 && strcmp(remote, "_") == 0) {
   452  				// allow #pragma dynimport _ _ "foo.so"
   453  				// to force a link of foo.so.
   454  				havedynamic = 1;
   455  				adddynlib(lib);
   456  				continue;
   457  			}
   458  
   459  			local = expandpkg(local, pkg);
   460  			q = strchr(remote, '#');
   461  			if(q)
   462  				*q++ = '\0';
   463  			s = lookup(local, 0);
   464  			if(local != f[1])
   465  				free(local);
   466  			if(s->type == 0 || s->type == SXREF || s->type == SHOSTOBJ) {
   467  				s->dynimplib = lib;
   468  				s->extname = remote;
   469  				s->dynimpvers = q;
   470  				if(s->type != SHOSTOBJ)
   471  					s->type = SDYNIMPORT;
   472  				havedynamic = 1;
   473  			}
   474  			continue;
   475  		}
   476  		
   477  		if(strcmp(f[0], "cgo_import_static") == 0) {
   478  			if(nf != 2)
   479  				goto err;
   480  			local = f[1];
   481  			s = lookup(local, 0);
   482  			s->type = SHOSTOBJ;
   483  			s->size = 0;
   484  			continue;
   485  		}
   486  
   487  		if(strcmp(f[0], "cgo_export_static") == 0 || strcmp(f[0], "cgo_export_dynamic") == 0) {
   488  			// TODO: Remove once we know Windows is okay.
   489  			if(strcmp(f[0], "cgo_export_static") == 0 && HEADTYPE == Hwindows)
   490  				continue;
   491  
   492  			if(nf < 2 || nf > 3)
   493  				goto err;
   494  			local = f[1];
   495  			if(nf > 2)
   496  				remote = f[2];
   497  			else
   498  				remote = local;
   499  			local = expandpkg(local, pkg);
   500  			s = lookup(local, 0);
   501  
   502  			// export overrides import, for openbsd/cgo.
   503  			// see issue 4878.
   504  			if(s->dynimplib != nil) {
   505  				s->dynimplib = nil;
   506  				s->extname = nil;
   507  				s->dynimpvers = nil;
   508  				s->type = 0;
   509  			}
   510  
   511  			if(s->cgoexport == 0) {
   512  				s->extname = remote;
   513  				if(ndynexp%32 == 0)
   514  					dynexp = erealloc(dynexp, (ndynexp+32)*sizeof dynexp[0]);
   515  				dynexp[ndynexp++] = s;
   516  			} else if(strcmp(s->extname, remote) != 0) {
   517  				fprint(2, "%s: conflicting cgo_export directives: %s as %s and %s\n", argv0, s->name, s->extname, remote);
   518  				nerrors++;
   519  				return;
   520  			}
   521  			if(strcmp(f[0], "cgo_export_static") == 0)
   522  				s->cgoexport |= CgoExportStatic;
   523  			else
   524  				s->cgoexport |= CgoExportDynamic;
   525  			if(local != f[1])
   526  				free(local);
   527  			continue;
   528  		}
   529  		
   530  		if(strcmp(f[0], "cgo_dynamic_linker") == 0) {
   531  			if(nf != 2)
   532  				goto err;
   533  			
   534  			if(!debug['I']) { // not overridden by command line
   535  				if(interpreter != nil && strcmp(interpreter, f[1]) != 0) {
   536  					fprint(2, "%s: conflict dynlinker: %s and %s\n", argv0, interpreter, f[1]);
   537  					nerrors++;
   538  					return;
   539  				}
   540  				free(interpreter);
   541  				interpreter = estrdup(f[1]);
   542  			}
   543  			continue;
   544  		}
   545  		
   546  		if(strcmp(f[0], "cgo_ldflag") == 0) {
   547  			if(nf != 2)
   548  				goto err;
   549  			if(nldflag%32 == 0)
   550  				ldflag = erealloc(ldflag, (nldflag+32)*sizeof ldflag[0]);
   551  			ldflag[nldflag++] = estrdup(f[1]);
   552  			continue;
   553  		}
   554  	}
   555  	free(p0);
   556  	return;
   557  
   558  err:
   559  	fprint(2, "%s: %s: invalid dynimport line: %s\n", argv0, file, p0);
   560  	nerrors++;
   561  }
   562  
   563  static Sym *markq;
   564  static Sym *emarkq;
   565  
   566  static void
   567  mark1(Sym *s, Sym *parent)
   568  {
   569  	if(s == S || s->reachable)
   570  		return;
   571  	if(strncmp(s->name, "go.weak.", 8) == 0)
   572  		return;
   573  	s->reachable = 1;
   574  	s->reachparent = parent;
   575  	if(markq == nil)
   576  		markq = s;
   577  	else
   578  		emarkq->queue = s;
   579  	emarkq = s;
   580  }
   581  
   582  void
   583  mark(Sym *s)
   584  {
   585  	mark1(s, nil);
   586  }
   587  
   588  static void
   589  markflood(void)
   590  {
   591  	Auto *a;
   592  	Prog *p;
   593  	Sym *s;
   594  	int i;
   595  	
   596  	for(s=markq; s!=S; s=s->queue) {
   597  		if(s->text) {
   598  			if(debug['v'] > 1)
   599  				Bprint(&bso, "marktext %s\n", s->name);
   600  			for(a=s->autom; a; a=a->link)
   601  				mark1(a->gotype, s);
   602  			for(p=s->text; p != P; p=p->link) {
   603  				mark1(p->from.sym, s);
   604  				mark1(p->to.sym, s);
   605  			}
   606  		}
   607  		for(i=0; i<s->nr; i++)
   608  			mark1(s->r[i].sym, s);
   609  		mark1(s->gotype, s);
   610  		mark1(s->sub, s);
   611  		mark1(s->outer, s);
   612  	}
   613  }
   614  
   615  static char*
   616  morename[] =
   617  {
   618  	"runtime.morestack",
   619  	"runtime.morestackx",
   620  
   621  	"runtime.morestack00",
   622  	"runtime.morestack10",
   623  	"runtime.morestack01",
   624  	"runtime.morestack11",
   625  
   626  	"runtime.morestack8",
   627  	"runtime.morestack16",
   628  	"runtime.morestack24",
   629  	"runtime.morestack32",
   630  	"runtime.morestack40",
   631  	"runtime.morestack48",
   632  };
   633  
   634  static int
   635  isz(Auto *a)
   636  {
   637  	for(; a; a=a->link)
   638  		if(a->type == D_FILE || a->type == D_FILE1)
   639  			return 1;
   640  	return 0;
   641  }
   642  
   643  static void
   644  addz(Sym *s, Auto *z)
   645  {
   646  	Auto *a, *last;
   647  
   648  	// strip out non-z
   649  	last = nil;
   650  	for(a = z; a != nil; a = a->link) {
   651  		if(a->type == D_FILE || a->type == D_FILE1) {
   652  			if(last == nil)
   653  				z = a;
   654  			else
   655  				last->link = a;
   656  			last = a;
   657  		}
   658  	}
   659  	if(last) {
   660  		last->link = s->autom;
   661  		s->autom = z;
   662  	}
   663  }
   664  
   665  void
   666  deadcode(void)
   667  {
   668  	int i;
   669  	Sym *s, *last, *p;
   670  	Auto *z;
   671  	Fmt fmt;
   672  
   673  	if(debug['v'])
   674  		Bprint(&bso, "%5.2f deadcode\n", cputime());
   675  
   676  	mark(lookup(INITENTRY, 0));
   677  	if(flag_shared)
   678  		mark(lookup(LIBINITENTRY, 0));
   679  	for(i=0; i<nelem(morename); i++)
   680  		mark(lookup(morename[i], 0));
   681  
   682  	for(i=0; i<ndynexp; i++)
   683  		mark(dynexp[i]);
   684  
   685  	markflood();
   686  	
   687  	// keep each beginning with 'typelink.' if the symbol it points at is being kept.
   688  	for(s = allsym; s != S; s = s->allsym) {
   689  		if(strncmp(s->name, "go.typelink.", 12) == 0)
   690  			s->reachable = s->nr==1 && s->r[0].sym->reachable;
   691  	}
   692  
   693  	// remove dead text but keep file information (z symbols).
   694  	last = nil;
   695  	z = nil;
   696  	for(s = textp; s != nil; s = s->next) {
   697  		if(!s->reachable) {
   698  			if(isz(s->autom))
   699  				z = s->autom;
   700  			continue;
   701  		}
   702  		if(last == nil)
   703  			textp = s;
   704  		else
   705  			last->next = s;
   706  		last = s;
   707  		if(z != nil) {
   708  			if(!isz(s->autom))
   709  				addz(s, z);
   710  			z = nil;
   711  		}
   712  	}
   713  	if(last == nil)
   714  		textp = nil;
   715  	else
   716  		last->next = nil;
   717  	
   718  	for(s = allsym; s != S; s = s->allsym)
   719  		if(strncmp(s->name, "go.weak.", 8) == 0) {
   720  			s->special = 1;  // do not lay out in data segment
   721  			s->reachable = 1;
   722  			s->hide = 1;
   723  		}
   724  	
   725  	// record field tracking references
   726  	fmtstrinit(&fmt);
   727  	for(s = allsym; s != S; s = s->allsym) {
   728  		if(strncmp(s->name, "go.track.", 9) == 0) {
   729  			s->special = 1;  // do not lay out in data segment
   730  			s->hide = 1;
   731  			if(s->reachable) {
   732  				fmtprint(&fmt, "%s", s->name+9);
   733  				for(p=s->reachparent; p; p=p->reachparent)
   734  					fmtprint(&fmt, "\t%s", p->name);
   735  				fmtprint(&fmt, "\n");
   736  			}
   737  			s->type = SCONST;
   738  			s->value = 0;
   739  		}
   740  	}
   741  	if(tracksym == nil)
   742  		return;
   743  	s = lookup(tracksym, 0);
   744  	if(!s->reachable)
   745  		return;
   746  	addstrdata(tracksym, fmtstrflush(&fmt));
   747  }
   748  
   749  void
   750  doweak(void)
   751  {
   752  	Sym *s, *t;
   753  
   754  	// resolve weak references only if
   755  	// target symbol will be in binary anyway.
   756  	for(s = allsym; s != S; s = s->allsym) {
   757  		if(strncmp(s->name, "go.weak.", 8) == 0) {
   758  			t = rlookup(s->name+8, s->version);
   759  			if(t && t->type != 0 && t->reachable) {
   760  				s->value = t->value;
   761  				s->type = t->type;
   762  				s->outer = t;
   763  			} else {
   764  				s->type = SCONST;
   765  				s->value = 0;
   766  			}
   767  			continue;
   768  		}
   769  	}
   770  }
   771  
   772  void
   773  addexport(void)
   774  {
   775  	int i;
   776  	
   777  	if(HEADTYPE == Hdarwin)
   778  		return;
   779  
   780  	for(i=0; i<ndynexp; i++)
   781  		adddynsym(dynexp[i]);
   782  }
   783  
   784  /* %Z from gc, for quoting import paths */
   785  int
   786  Zconv(Fmt *fp)
   787  {
   788  	Rune r;
   789  	char *s, *se;
   790  	int n;
   791  
   792  	s = va_arg(fp->args, char*);
   793  	if(s == nil)
   794  		return fmtstrcpy(fp, "<nil>");
   795  
   796  	se = s + strlen(s);
   797  	while(s < se) {
   798  		n = chartorune(&r, s);
   799  		s += n;
   800  		switch(r) {
   801  		case Runeerror:
   802  			if(n == 1) {
   803  				fmtprint(fp, "\\x%02x", (uchar)*(s-1));
   804  				break;
   805  			}
   806  			// fall through
   807  		default:
   808  			if(r < ' ') {
   809  				fmtprint(fp, "\\x%02x", r);
   810  				break;
   811  			}
   812  			fmtrune(fp, r);
   813  			break;
   814  		case '\t':
   815  			fmtstrcpy(fp, "\\t");
   816  			break;
   817  		case '\n':
   818  			fmtstrcpy(fp, "\\n");
   819  			break;
   820  		case '\"':
   821  		case '\\':
   822  			fmtrune(fp, '\\');
   823  			fmtrune(fp, r);
   824  			break;
   825  		}
   826  	}
   827  	return 0;
   828  }
   829  
   830  
   831  typedef struct Pkg Pkg;
   832  struct Pkg
   833  {
   834  	uchar mark;
   835  	uchar checked;
   836  	Pkg *next;
   837  	char *path;
   838  	Pkg **impby;
   839  	int nimpby;
   840  	int mimpby;
   841  	Pkg *all;
   842  };
   843  
   844  static Pkg *phash[1024];
   845  static Pkg *pkgall;
   846  
   847  static Pkg*
   848  getpkg(char *path)
   849  {
   850  	Pkg *p;
   851  	int h;
   852  	
   853  	h = hashstr(path) % nelem(phash);
   854  	for(p=phash[h]; p; p=p->next)
   855  		if(strcmp(p->path, path) == 0)
   856  			return p;
   857  	p = mal(sizeof *p);
   858  	p->path = estrdup(path);
   859  	p->next = phash[h];
   860  	phash[h] = p;
   861  	p->all = pkgall;
   862  	pkgall = p;
   863  	return p;
   864  }
   865  
   866  static void
   867  imported(char *pkg, char *import)
   868  {
   869  	Pkg *p, *i;
   870  	
   871  	// everyone imports runtime, even runtime.
   872  	if(strcmp(import, "\"runtime\"") == 0)
   873  		return;
   874  
   875  	pkg = smprint("\"%Z\"", pkg);  // turn pkg path into quoted form, freed below
   876  	p = getpkg(pkg);
   877  	i = getpkg(import);
   878  	if(i->nimpby >= i->mimpby) {
   879  		i->mimpby *= 2;
   880  		if(i->mimpby == 0)
   881  			i->mimpby = 16;
   882  		i->impby = erealloc(i->impby, i->mimpby*sizeof i->impby[0]);
   883  	}
   884  	i->impby[i->nimpby++] = p;
   885  	free(pkg);
   886  }
   887  
   888  static Pkg*
   889  cycle(Pkg *p)
   890  {
   891  	int i;
   892  	Pkg *bad;
   893  
   894  	if(p->checked)
   895  		return 0;
   896  
   897  	if(p->mark) {
   898  		nerrors++;
   899  		print("import cycle:\n");
   900  		print("\t%s\n", p->path);
   901  		return p;
   902  	}
   903  	p->mark = 1;
   904  	for(i=0; i<p->nimpby; i++) {
   905  		if((bad = cycle(p->impby[i])) != nil) {
   906  			p->mark = 0;
   907  			p->checked = 1;
   908  			print("\timports %s\n", p->path);
   909  			if(bad == p)
   910  				return nil;
   911  			return bad;
   912  		}
   913  	}
   914  	p->checked = 1;
   915  	p->mark = 0;
   916  	return 0;
   917  }
   918  
   919  void
   920  importcycles(void)
   921  {
   922  	Pkg *p;
   923  	
   924  	for(p=pkgall; p; p=p->all)
   925  		cycle(p);
   926  }
   927  
   928  void
   929  setlinkmode(char *arg)
   930  {
   931  	if(strcmp(arg, "internal") == 0)
   932  		linkmode = LinkInternal;
   933  	else if(strcmp(arg, "external") == 0)
   934  		linkmode = LinkExternal;
   935  	else if(strcmp(arg, "auto") == 0)
   936  		linkmode = LinkAuto;
   937  	else {
   938  		fprint(2, "unknown link mode -linkmode %s\n", arg);
   939  		errorexit();
   940  	}
   941  }