github.com/reiver/go@v0.0.0-20150109200633-1d0c7792f172/src/cmd/ld/symtab.c (about)

     1  // Inferno utils/6l/span.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c
     3  //
     4  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     5  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     6  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     7  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
     8  //	Portions Copyright © 2004,2006 Bruce Ellis
     9  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    10  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    11  //	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    12  //
    13  // Permission is hereby granted, free of charge, to any person obtaining a copy
    14  // of this software and associated documentation files (the "Software"), to deal
    15  // in the Software without restriction, including without limitation the rights
    16  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    17  // copies of the Software, and to permit persons to whom the Software is
    18  // furnished to do so, subject to the following conditions:
    19  //
    20  // The above copyright notice and this permission notice shall be included in
    21  // all copies or substantial portions of the Software.
    22  //
    23  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    24  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    25  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    26  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    27  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    28  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    29  // THE SOFTWARE.
    30  
    31  // Symbol table.
    32  
    33  #include	"l.h"
    34  #include	"../ld/lib.h"
    35  #include	"../ld/elf.h"
    36  
    37  static int maxelfstr;
    38  
    39  static int
    40  putelfstr(char *s)
    41  {
    42  	int off, n;
    43  	char *p, *q;
    44  
    45  	if(elfstrsize == 0 && s[0] != 0) {
    46  		// first entry must be empty string
    47  		putelfstr("");
    48  	}
    49  
    50  	n = strlen(s)+1;
    51  	if(elfstrsize+n > maxelfstr) {
    52  		maxelfstr = 2*(elfstrsize+n+(1<<20));
    53  		elfstrdat = realloc(elfstrdat, maxelfstr);
    54  	}
    55  	off = elfstrsize;
    56  	elfstrsize += n;
    57  	memmove(elfstrdat+off, s, n);
    58  	// replace "·" as ".", because DTrace cannot handle it.
    59  	p = strstr(s, "·");
    60  	if(p != nil) {
    61  		p = q = elfstrdat+off;
    62  		while (*q != '\0') {
    63  			if((uchar)*q == 0xc2 && (uchar)*(q+1) == 0xb7) {
    64  				q += 2;
    65  				*p++ = '.';
    66  				elfstrsize--;
    67  			} else {
    68  				*p++ = *q++;
    69  			}
    70  		}
    71  		*p = '\0';
    72  	}
    73  	return off;
    74  }
    75  
    76  static void
    77  putelfsyment(int off, vlong addr, vlong size, int info, int shndx, int other)
    78  {
    79  	switch(thechar) {
    80  	case '6':
    81  	case '9':
    82  		LPUT(off);
    83  		cput(info);
    84  		cput(other);
    85  		WPUT(shndx);
    86  		VPUT(addr);
    87  		VPUT(size);
    88  		symsize += ELF64SYMSIZE;
    89  		break;
    90  	default:
    91  		LPUT(off);
    92  		LPUT(addr);
    93  		LPUT(size);
    94  		cput(info);
    95  		cput(other);
    96  		WPUT(shndx);
    97  		symsize += ELF32SYMSIZE;
    98  		break;
    99  	}
   100  }
   101  
   102  static int numelfsym = 1; // 0 is reserved
   103  static int elfbind;
   104  
   105  static void
   106  putelfsym(LSym *x, char *s, int t, vlong addr, vlong size, int ver, LSym *go)
   107  {
   108  	int bind, type, off;
   109  	LSym *xo;
   110  
   111  	USED(go);
   112  	switch(t) {
   113  	default:
   114  		return;
   115  	case 'T':
   116  		type = STT_FUNC;
   117  		break;
   118  	case 'D':
   119  		type = STT_OBJECT;
   120  		break;
   121  	case 'B':
   122  		type = STT_OBJECT;
   123  		break;
   124  	}
   125  	xo = x;
   126  	while(xo->outer != nil)
   127  		xo = xo->outer;
   128  	if(xo->sect == nil) {
   129  		ctxt->cursym = x;
   130  		diag("missing section in putelfsym");
   131  		return;
   132  	}
   133  	if(xo->sect->elfsect == nil) {
   134  		ctxt->cursym = x;
   135  		diag("missing ELF section in putelfsym");
   136  		return;
   137  	}
   138  
   139  	// One pass for each binding: STB_LOCAL, STB_GLOBAL,
   140  	// maybe one day STB_WEAK.
   141  	bind = STB_GLOBAL;
   142  	if(ver || (x->type & SHIDDEN))
   143  		bind = STB_LOCAL;
   144  
   145  	// In external linking mode, we have to invoke gcc with -rdynamic
   146  	// to get the exported symbols put into the dynamic symbol table.
   147  	// To avoid filling the dynamic table with lots of unnecessary symbols,
   148  	// mark all Go symbols local (not global) in the final executable.
   149  	if(linkmode == LinkExternal && !(x->cgoexport&CgoExportStatic))
   150  		bind = STB_LOCAL;
   151  
   152  	if(bind != elfbind)
   153  		return;
   154  
   155  	off = putelfstr(s);
   156  	if(linkmode == LinkExternal)
   157  		addr -= xo->sect->vaddr;
   158  	putelfsyment(off, addr, size, (bind<<4)|(type&0xf), xo->sect->elfsect->shnum, (x->type & SHIDDEN) ? 2 : 0);
   159  	x->elfsym = numelfsym++;
   160  }
   161  
   162  void
   163  putelfsectionsym(LSym* s, int shndx)
   164  {
   165  	putelfsyment(0, 0, 0, (STB_LOCAL<<4)|STT_SECTION, shndx, 0);
   166  	s->elfsym = numelfsym++;
   167  }
   168  
   169  void
   170  putelfsymshndx(vlong sympos, int shndx)
   171  {
   172  	vlong here;
   173  
   174  	here = cpos();
   175  	switch(thechar) {
   176  	case '6':
   177  		cseek(sympos+6);
   178  		break;
   179  	default:
   180  		cseek(sympos+14);
   181  		break;
   182  	}
   183  	WPUT(shndx);
   184  	cseek(here);
   185  }
   186  
   187  void
   188  asmelfsym(void)
   189  {
   190  	LSym *s;
   191  	char *name;
   192  
   193  	// the first symbol entry is reserved
   194  	putelfsyment(0, 0, 0, (STB_LOCAL<<4)|STT_NOTYPE, 0, 0);
   195  
   196  	dwarfaddelfsectionsyms();
   197  
   198  	elfbind = STB_LOCAL;
   199  	genasmsym(putelfsym);
   200  	
   201  	if(linkmode == LinkExternal && HEADTYPE != Hopenbsd) {
   202  		s = linklookup(ctxt, "runtime.tlsg", 0);
   203  		if(s->sect == nil) {
   204  			ctxt->cursym = nil;
   205  			diag("missing section for %s", s->name);
   206  			errorexit();
   207  		}
   208  		if (strcmp(goos, "android") == 0) {
   209  			// Android emulates runtime.tlsg as a regular variable.
   210  			putelfsyment(putelfstr(s->name), 0, s->size, (STB_LOCAL<<4)|STT_OBJECT, s->sect->elfsect->shnum, 0);
   211  		} else {
   212  			putelfsyment(putelfstr(s->name), 0, s->size, (STB_LOCAL<<4)|STT_TLS, s->sect->elfsect->shnum, 0);
   213  		}
   214  		s->elfsym = numelfsym++;
   215  	}
   216  
   217  	elfbind = STB_GLOBAL;
   218  	elfglobalsymndx = numelfsym;
   219  	genasmsym(putelfsym);
   220  	
   221  	for(s=ctxt->allsym; s!=S; s=s->allsym) {
   222  		if(s->type != SHOSTOBJ && !(s->type == SDYNIMPORT && s->reachable))
   223  			continue;
   224  		if(s->type == SDYNIMPORT)
   225  			name = s->extname;
   226  		else
   227  			name = s->name;
   228  		putelfsyment(putelfstr(name), 0, 0, (STB_GLOBAL<<4)|STT_NOTYPE, 0, 0);
   229  		s->elfsym = numelfsym++;
   230  	}
   231  }
   232  
   233  static void
   234  putplan9sym(LSym *x, char *s, int t, vlong addr, vlong size, int ver, LSym *go)
   235  {
   236  	int i, l;
   237  
   238  	USED(go);
   239  	USED(ver);
   240  	USED(size);
   241  	USED(x);
   242  	switch(t) {
   243  	case 'T':
   244  	case 'L':
   245  	case 'D':
   246  	case 'B':
   247  		if(ver)
   248  			t += 'a' - 'A';
   249  	case 'a':
   250  	case 'p':
   251  	case 'f':
   252  	case 'z':
   253  	case 'Z':
   254  	case 'm':
   255  		l = 4;
   256  		if(HEADTYPE == Hplan9 && thechar == '6' && !debug['8']) {
   257  			lputb(addr>>32);
   258  			l = 8;
   259  		}
   260  		lputb(addr);
   261  		cput(t+0x80); /* 0x80 is variable length */
   262  
   263  		if(t == 'z' || t == 'Z') {
   264  			cput(s[0]);
   265  			for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
   266  				cput(s[i]);
   267  				cput(s[i+1]);
   268  			}
   269  			cput(0);
   270  			cput(0);
   271  			i++;
   272  		} else {
   273  			/* skip the '<' in filenames */
   274  			if(t == 'f')
   275  				s++;
   276  			for(i=0; s[i]; i++)
   277  				cput(s[i]);
   278  			cput(0);
   279  		}
   280  		symsize += l + 1 + i + 1;
   281  		break;
   282  	default:
   283  		return;
   284  	};
   285  }
   286  
   287  void
   288  asmplan9sym(void)
   289  {
   290  	genasmsym(putplan9sym);
   291  }
   292  
   293  static LSym *symt;
   294  
   295  void
   296  wputl(ushort w)
   297  {
   298  	cput(w);
   299  	cput(w>>8);
   300  }
   301  
   302  void
   303  wputb(ushort w)
   304  {
   305  	cput(w>>8);
   306  	cput(w);
   307  }
   308  
   309  void
   310  lputb(int32 l)
   311  {
   312  	cput(l>>24);
   313  	cput(l>>16);
   314  	cput(l>>8);
   315  	cput(l);
   316  }
   317  
   318  void
   319  lputl(int32 l)
   320  {
   321  	cput(l);
   322  	cput(l>>8);
   323  	cput(l>>16);
   324  	cput(l>>24);
   325  }
   326  
   327  void
   328  vputb(uint64 v)
   329  {
   330  	lputb(v>>32);
   331  	lputb(v);
   332  }
   333  
   334  void
   335  vputl(uint64 v)
   336  {
   337  	lputl(v);
   338  	lputl(v >> 32);
   339  }
   340  
   341  void
   342  symtab(void)
   343  {
   344  	LSym *s, *symtype, *symtypelink, *symgostring, *symgofunc;
   345  
   346  	dosymtype();
   347  
   348  	// Define these so that they'll get put into the symbol table.
   349  	// data.c:/^address will provide the actual values.
   350  	xdefine("runtime.text", STEXT, 0);
   351  	xdefine("runtime.etext", STEXT, 0);
   352  	xdefine("runtime.typelink", SRODATA, 0);
   353  	xdefine("runtime.etypelink", SRODATA, 0);
   354  	xdefine("runtime.rodata", SRODATA, 0);
   355  	xdefine("runtime.erodata", SRODATA, 0);
   356  	xdefine("runtime.noptrdata", SNOPTRDATA, 0);
   357  	xdefine("runtime.enoptrdata", SNOPTRDATA, 0);
   358  	xdefine("runtime.data", SDATA, 0);
   359  	xdefine("runtime.edata", SDATA, 0);
   360  	xdefine("runtime.bss", SBSS, 0);
   361  	xdefine("runtime.ebss", SBSS, 0);
   362  	xdefine("runtime.noptrbss", SNOPTRBSS, 0);
   363  	xdefine("runtime.enoptrbss", SNOPTRBSS, 0);
   364  	xdefine("runtime.end", SBSS, 0);
   365  	xdefine("runtime.epclntab", SRODATA, 0);
   366  	xdefine("runtime.esymtab", SRODATA, 0);
   367  
   368  	// garbage collection symbols
   369  	s = linklookup(ctxt, "runtime.gcdata", 0);
   370  	s->type = SRODATA;
   371  	s->size = 0;
   372  	s->reachable = 1;
   373  	xdefine("runtime.egcdata", SRODATA, 0);
   374  
   375  	s = linklookup(ctxt, "runtime.gcbss", 0);
   376  	s->type = SRODATA;
   377  	s->size = 0;
   378  	s->reachable = 1;
   379  	xdefine("runtime.egcbss", SRODATA, 0);
   380  
   381  	// pseudo-symbols to mark locations of type, string, and go string data.
   382  	s = linklookup(ctxt, "type.*", 0);
   383  	s->type = STYPE;
   384  	s->size = 0;
   385  	s->reachable = 1;
   386  	symtype = s;
   387  
   388  	s = linklookup(ctxt, "go.string.*", 0);
   389  	s->type = SGOSTRING;
   390  	s->size = 0;
   391  	s->reachable = 1;
   392  	symgostring = s;
   393  	
   394  	s = linklookup(ctxt, "go.func.*", 0);
   395  	s->type = SGOFUNC;
   396  	s->size = 0;
   397  	s->reachable = 1;
   398  	symgofunc = s;
   399  	
   400  	symtypelink = linklookup(ctxt, "runtime.typelink", 0);
   401  
   402  	symt = linklookup(ctxt, "runtime.symtab", 0);
   403  	symt->type = SSYMTAB;
   404  	symt->size = 0;
   405  	symt->reachable = 1;
   406  
   407  	// assign specific types so that they sort together.
   408  	// within a type they sort by size, so the .* symbols
   409  	// just defined above will be first.
   410  	// hide the specific symbols.
   411  	for(s = ctxt->allsym; s != S; s = s->allsym) {
   412  		if(!s->reachable || s->special || s->type != SRODATA)
   413  			continue;
   414  		if(strncmp(s->name, "type.", 5) == 0) {
   415  			s->type = STYPE;
   416  			s->hide = 1;
   417  			s->outer = symtype;
   418  		}
   419  		if(strncmp(s->name, "go.typelink.", 12) == 0) {
   420  			s->type = STYPELINK;
   421  			s->hide = 1;
   422  			s->outer = symtypelink;
   423  		}
   424  		if(strncmp(s->name, "go.string.", 10) == 0) {
   425  			s->type = SGOSTRING;
   426  			s->hide = 1;
   427  			s->outer = symgostring;
   428  		}
   429  		if(strncmp(s->name, "go.func.", 8) == 0) {
   430  			s->type = SGOFUNC;
   431  			s->hide = 1;
   432  			s->outer = symgofunc;
   433  		}
   434  		if(strncmp(s->name, "gcargs.", 7) == 0 || strncmp(s->name, "gclocals.", 9) == 0 || strncmp(s->name, "gclocals·", 10) == 0) {
   435  			s->type = SGOFUNC;
   436  			s->hide = 1;
   437  			s->outer = symgofunc;
   438  			s->align = 4;
   439  			liveness += (s->size+s->align-1)&~(s->align-1);
   440  		}
   441  	}
   442  }