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