github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/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  
    44  	if(elfstrsize == 0 && s[0] != 0) {
    45  		// first entry must be empty string
    46  		putelfstr("");
    47  	}
    48  
    49  	n = strlen(s)+1;
    50  	if(elfstrsize+n > maxelfstr) {
    51  		maxelfstr = 2*(elfstrsize+n+(1<<20));
    52  		elfstrdat = realloc(elfstrdat, maxelfstr);
    53  	}
    54  	off = elfstrsize;
    55  	elfstrsize += n;
    56  	memmove(elfstrdat+off, s, n);
    57  	return off;
    58  }
    59  
    60  static void
    61  putelfsyment(int off, vlong addr, vlong size, int info, int shndx, int other)
    62  {
    63  	switch(thechar) {
    64  	case '6':
    65  		LPUT(off);
    66  		cput(info);
    67  		cput(other);
    68  		WPUT(shndx);
    69  		VPUT(addr);
    70  		VPUT(size);
    71  		symsize += ELF64SYMSIZE;
    72  		break;
    73  	default:
    74  		LPUT(off);
    75  		LPUT(addr);
    76  		LPUT(size);
    77  		cput(info);
    78  		cput(other);
    79  		WPUT(shndx);
    80  		symsize += ELF32SYMSIZE;
    81  		break;
    82  	}
    83  }
    84  
    85  static int numelfsym = 1; // 0 is reserved
    86  static int elfbind;
    87  
    88  static void
    89  putelfsym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
    90  {
    91  	int bind, type, off;
    92  	Sym *xo;
    93  
    94  	USED(go);
    95  	switch(t) {
    96  	default:
    97  		return;
    98  	case 'T':
    99  		type = STT_FUNC;
   100  		break;
   101  	case 'D':
   102  		type = STT_OBJECT;
   103  		break;
   104  	case 'B':
   105  		type = STT_OBJECT;
   106  		break;
   107  	}
   108  	xo = x;
   109  	while(xo->outer != nil)
   110  		xo = xo->outer;
   111  	if(xo->sect == nil) {
   112  		cursym = x;
   113  		diag("missing section in putelfsym");
   114  		return;
   115  	}
   116  	if(xo->sect->elfsect == nil) {
   117  		cursym = x;
   118  		diag("missing ELF section in putelfsym");
   119  		return;
   120  	}
   121  
   122  	// One pass for each binding: STB_LOCAL, STB_GLOBAL,
   123  	// maybe one day STB_WEAK.
   124  	bind = STB_GLOBAL;
   125  	if(ver || (x->type & SHIDDEN))
   126  		bind = STB_LOCAL;
   127  
   128  	// In external linking mode, we have to invoke gcc with -rdynamic
   129  	// to get the exported symbols put into the dynamic symbol table.
   130  	// To avoid filling the dynamic table with lots of unnecessary symbols,
   131  	// mark all Go symbols local (not global) in the final executable.
   132  	if(linkmode == LinkExternal && !(x->cgoexport&CgoExportStatic))
   133  		bind = STB_LOCAL;
   134  
   135  	if(bind != elfbind)
   136  		return;
   137  
   138  	off = putelfstr(s);
   139  	if(linkmode == LinkExternal)
   140  		addr -= xo->sect->vaddr;
   141  	putelfsyment(off, addr, size, (bind<<4)|(type&0xf), xo->sect->elfsect->shnum, (x->type & SHIDDEN) ? 2 : 0);
   142  	x->elfsym = numelfsym++;
   143  }
   144  
   145  void
   146  putelfsectionsym(Sym* s, int shndx)
   147  {
   148  	putelfsyment(0, 0, 0, (STB_LOCAL<<4)|STT_SECTION, shndx, 0);
   149  	s->elfsym = numelfsym++;
   150  }
   151  
   152  void
   153  putelfsymshndx(vlong sympos, int shndx)
   154  {
   155  	vlong here;
   156  
   157  	here = cpos();
   158  	switch(thechar) {
   159  	case '6':
   160  		cseek(sympos+6);
   161  		break;
   162  	default:
   163  		cseek(sympos+14);
   164  		break;
   165  	}
   166  	WPUT(shndx);
   167  	cseek(here);
   168  }
   169  
   170  void
   171  asmelfsym(void)
   172  {
   173  	Sym *s;
   174  
   175  	// the first symbol entry is reserved
   176  	putelfsyment(0, 0, 0, (STB_LOCAL<<4)|STT_NOTYPE, 0, 0);
   177  
   178  	dwarfaddelfsectionsyms();
   179  
   180  	elfbind = STB_LOCAL;
   181  	genasmsym(putelfsym);
   182  	
   183  	if(linkmode == LinkExternal && HEADTYPE != Hopenbsd) {
   184  		s = lookup("runtime.tlsgm", 0);
   185  		if(s->sect == nil) {
   186  			cursym = nil;
   187  			diag("missing section for %s", s->name);
   188  			errorexit();
   189  		}
   190  		putelfsyment(putelfstr(s->name), 0, 2*PtrSize, (STB_LOCAL<<4)|STT_TLS, s->sect->elfsect->shnum, 0);
   191  		s->elfsym = numelfsym++;
   192  	}
   193  
   194  	elfbind = STB_GLOBAL;
   195  	elfglobalsymndx = numelfsym;
   196  	genasmsym(putelfsym);
   197  	
   198  	for(s=allsym; s!=S; s=s->allsym) {
   199  		if(s->type != SHOSTOBJ)
   200  			continue;
   201  		putelfsyment(putelfstr(s->name), 0, 0, (STB_GLOBAL<<4)|STT_NOTYPE, 0, 0);
   202  		s->elfsym = numelfsym++;
   203  	}
   204  }
   205  
   206  static void
   207  putplan9sym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
   208  {
   209  	int i, l;
   210  
   211  	USED(go);
   212  	USED(ver);
   213  	USED(size);
   214  	USED(x);
   215  	switch(t) {
   216  	case 'T':
   217  	case 'L':
   218  	case 'D':
   219  	case 'B':
   220  		if(ver)
   221  			t += 'a' - 'A';
   222  	case 'a':
   223  	case 'p':
   224  	case 'f':
   225  	case 'z':
   226  	case 'Z':
   227  	case 'm':
   228  		l = 4;
   229  		if(HEADTYPE == Hplan9x64 && !debug['8']) {
   230  			lputb(addr>>32);
   231  			l = 8;
   232  		}
   233  		lputb(addr);
   234  		cput(t+0x80); /* 0x80 is variable length */
   235  
   236  		if(t == 'z' || t == 'Z') {
   237  			cput(s[0]);
   238  			for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
   239  				cput(s[i]);
   240  				cput(s[i+1]);
   241  			}
   242  			cput(0);
   243  			cput(0);
   244  			i++;
   245  		} else {
   246  			/* skip the '<' in filenames */
   247  			if(t == 'f')
   248  				s++;
   249  			for(i=0; s[i]; i++)
   250  				cput(s[i]);
   251  			cput(0);
   252  		}
   253  		symsize += l + 1 + i + 1;
   254  		break;
   255  	default:
   256  		return;
   257  	};
   258  }
   259  
   260  void
   261  asmplan9sym(void)
   262  {
   263  	genasmsym(putplan9sym);
   264  }
   265  
   266  static Sym *symt;
   267  
   268  static void
   269  scput(int b)
   270  {
   271  	uchar *p;
   272  
   273  	symgrow(symt, symt->size+1);
   274  	p = symt->p + symt->size;
   275  	*p = b;
   276  	symt->size++;
   277  }
   278  
   279  static void
   280  slputb(int32 v)
   281  {
   282  	uchar *p;
   283  
   284  	symgrow(symt, symt->size+4);
   285  	p = symt->p + symt->size;
   286  	*p++ = v>>24;
   287  	*p++ = v>>16;
   288  	*p++ = v>>8;
   289  	*p = v;
   290  	symt->size += 4;
   291  }
   292  
   293  static void
   294  slputl(int32 v)
   295  {
   296  	uchar *p;
   297  
   298  	symgrow(symt, symt->size+4);
   299  	p = symt->p + symt->size;
   300  	*p++ = v;
   301  	*p++ = v>>8;
   302  	*p++ = v>>16;
   303  	*p = v>>24;
   304  	symt->size += 4;
   305  }
   306  
   307  static void (*slput)(int32);
   308  
   309  void
   310  wputl(ushort w)
   311  {
   312  	cput(w);
   313  	cput(w>>8);
   314  }
   315  
   316  void
   317  wputb(ushort w)
   318  {
   319  	cput(w>>8);
   320  	cput(w);
   321  }
   322  
   323  void
   324  lputb(int32 l)
   325  {
   326  	cput(l>>24);
   327  	cput(l>>16);
   328  	cput(l>>8);
   329  	cput(l);
   330  }
   331  
   332  void
   333  lputl(int32 l)
   334  {
   335  	cput(l);
   336  	cput(l>>8);
   337  	cput(l>>16);
   338  	cput(l>>24);
   339  }
   340  
   341  void
   342  vputb(uint64 v)
   343  {
   344  	lputb(v>>32);
   345  	lputb(v);
   346  }
   347  
   348  void
   349  vputl(uint64 v)
   350  {
   351  	lputl(v);
   352  	lputl(v >> 32);
   353  }
   354  
   355  // Emit symbol table entry.
   356  // The table format is described at the top of ../../pkg/runtime/symtab.c.
   357  void
   358  putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ)
   359  {
   360  	int i, f, c;
   361  	vlong v1;
   362  	Reloc *rel;
   363  
   364  	USED(size);
   365  
   366  	// type byte
   367  	if('A' <= t && t <= 'Z')
   368  		c = t - 'A' + (ver ? 26 : 0);
   369  	else if('a' <= t && t <= 'z')
   370  		c = t - 'a' + 26;
   371  	else {
   372  		diag("invalid symbol table type %c", t);
   373  		errorexit();
   374  		return;
   375  	}
   376  	
   377  	if(s != nil)
   378  		c |= 0x40; // wide value
   379  	if(typ != nil)
   380  		c |= 0x80; // has go type
   381  	scput(c);
   382  
   383  	// value
   384  	if(s != nil) {
   385  		// full width
   386  		rel = addrel(symt);
   387  		rel->siz = PtrSize;
   388  		rel->sym = s;
   389  		rel->type = D_ADDR;
   390  		rel->off = symt->size;
   391  		if(PtrSize == 8)
   392  			slput(0);
   393  		slput(0);
   394  	} else {
   395  		// varint
   396  		if(v < 0) {
   397  			diag("negative value in symbol table: %s %lld", name, v);
   398  			errorexit();
   399  		}
   400  		v1 = v;
   401  		while(v1 >= 0x80) {
   402  			scput(v1 | 0x80);
   403  			v1 >>= 7;
   404  		}
   405  		scput(v1);
   406  	}
   407  
   408  	// go type if present
   409  	if(typ != nil) {
   410  		if(!typ->reachable)
   411  			diag("unreachable type %s", typ->name);
   412  		rel = addrel(symt);
   413  		rel->siz = PtrSize;
   414  		rel->sym = typ;
   415  		rel->type = D_ADDR;
   416  		rel->off = symt->size;
   417  		if(PtrSize == 8)
   418  			slput(0);
   419  		slput(0);
   420  	}
   421  	
   422  	// name	
   423  	if(t == 'f')
   424  		name++;
   425  
   426  	if(t == 'Z' || t == 'z') {
   427  		scput(name[0]);
   428  		for(i=1; name[i] != 0 || name[i+1] != 0; i += 2) {
   429  			scput(name[i]);
   430  			scput(name[i+1]);
   431  		}
   432  		scput(0);
   433  		scput(0);
   434  	} else {
   435  		for(i=0; name[i]; i++)
   436  			scput(name[i]);
   437  		scput(0);
   438  	}
   439  
   440  	if(debug['n']) {
   441  		if(t == 'z' || t == 'Z') {
   442  			Bprint(&bso, "%c %.8llux ", t, v);
   443  			for(i=1; name[i] != 0 || name[i+1] != 0; i+=2) {
   444  				f = ((name[i]&0xff) << 8) | (name[i+1]&0xff);
   445  				Bprint(&bso, "/%x", f);
   446  			}
   447  			Bprint(&bso, "\n");
   448  			return;
   449  		}
   450  		if(ver)
   451  			Bprint(&bso, "%c %.8llux %s<%d> %s\n", t, v, name, ver, typ ? typ->name : "");
   452  		else
   453  			Bprint(&bso, "%c %.8llux %s %s\n", t, v, name, typ ? typ->name : "");
   454  	}
   455  }
   456  
   457  void
   458  symtab(void)
   459  {
   460  	Sym *s, *symtype, *symtypelink, *symgostring, *symgofunc;
   461  
   462  	dosymtype();
   463  
   464  	// Define these so that they'll get put into the symbol table.
   465  	// data.c:/^address will provide the actual values.
   466  	xdefine("text", STEXT, 0);
   467  	xdefine("etext", STEXT, 0);
   468  	xdefine("typelink", SRODATA, 0);
   469  	xdefine("etypelink", SRODATA, 0);
   470  	xdefine("rodata", SRODATA, 0);
   471  	xdefine("erodata", SRODATA, 0);
   472  	xdefine("noptrdata", SNOPTRDATA, 0);
   473  	xdefine("enoptrdata", SNOPTRDATA, 0);
   474  	xdefine("data", SDATA, 0);
   475  	xdefine("edata", SDATA, 0);
   476  	xdefine("bss", SBSS, 0);
   477  	xdefine("ebss", SBSS, 0);
   478  	xdefine("noptrbss", SNOPTRBSS, 0);
   479  	xdefine("enoptrbss", SNOPTRBSS, 0);
   480  	xdefine("end", SBSS, 0);
   481  	xdefine("epclntab", SRODATA, 0);
   482  	xdefine("esymtab", SRODATA, 0);
   483  
   484  	// garbage collection symbols
   485  	s = lookup("gcdata", 0);
   486  	s->type = SRODATA;
   487  	s->size = 0;
   488  	s->reachable = 1;
   489  	xdefine("egcdata", SRODATA, 0);
   490  
   491  	s = lookup("gcbss", 0);
   492  	s->type = SRODATA;
   493  	s->size = 0;
   494  	s->reachable = 1;
   495  	xdefine("egcbss", SRODATA, 0);
   496  
   497  	// pseudo-symbols to mark locations of type, string, and go string data.
   498  	s = lookup("type.*", 0);
   499  	s->type = STYPE;
   500  	s->size = 0;
   501  	s->reachable = 1;
   502  	symtype = s;
   503  
   504  	s = lookup("go.string.*", 0);
   505  	s->type = SGOSTRING;
   506  	s->size = 0;
   507  	s->reachable = 1;
   508  	symgostring = s;
   509  	
   510  	s = lookup("go.func.*", 0);
   511  	s->type = SGOFUNC;
   512  	s->size = 0;
   513  	s->reachable = 1;
   514  	symgofunc = s;
   515  	
   516  	symtypelink = lookup("typelink", 0);
   517  
   518  	symt = lookup("symtab", 0);
   519  	symt->type = SSYMTAB;
   520  	symt->size = 0;
   521  	symt->reachable = 1;
   522  
   523  	// assign specific types so that they sort together.
   524  	// within a type they sort by size, so the .* symbols
   525  	// just defined above will be first.
   526  	// hide the specific symbols.
   527  	for(s = allsym; s != S; s = s->allsym) {
   528  		if(!s->reachable || s->special || s->type != SRODATA)
   529  			continue;
   530  		if(strncmp(s->name, "type.", 5) == 0) {
   531  			s->type = STYPE;
   532  			s->hide = 1;
   533  			s->outer = symtype;
   534  		}
   535  		if(strncmp(s->name, "go.typelink.", 12) == 0) {
   536  			s->type = STYPELINK;
   537  			s->hide = 1;
   538  			s->outer = symtypelink;
   539  		}
   540  		if(strncmp(s->name, "go.string.", 10) == 0) {
   541  			s->type = SGOSTRING;
   542  			s->hide = 1;
   543  			s->outer = symgostring;
   544  		}
   545  		if(strncmp(s->name, "go.func.", 8) == 0) {
   546  			s->type = SGOFUNC;
   547  			s->hide = 1;
   548  			s->outer = symgofunc;
   549  		}
   550  	}
   551  
   552  	if(debug['s'])
   553  		return;
   554  
   555  	switch(thechar) {
   556  	default:
   557  		diag("unknown architecture %c", thechar);
   558  		errorexit();
   559  	case '5':
   560  	case '6':
   561  	case '8':
   562  		// little-endian symbol table
   563  		slput = slputl;
   564  		break;
   565  	case 'v':
   566  		// big-endian symbol table
   567  		slput = slputb;
   568  		break;
   569  	}
   570  	// new symbol table header.
   571  	slput(0xfffffffd);
   572  	scput(0);
   573  	scput(0);
   574  	scput(0);
   575  	scput(PtrSize);
   576  
   577  	genasmsym(putsymb);
   578  }