github.com/bgentry/go@v0.0.0-20150121062915-6cf5a733d54d/src/liblink/sym.c (about)

     1  // Derived from Inferno utils/6l/obj.c and utils/6l/span.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c
     3  // http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c
     4  //
     5  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     6  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     7  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     8  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
     9  //	Portions Copyright © 2004,2006 Bruce Ellis
    10  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    11  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    12  //	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    13  //
    14  // Permission is hereby granted, free of charge, to any person obtaining a copy
    15  // of this software and associated documentation files (the "Software"), to deal
    16  // in the Software without restriction, including without limitation the rights
    17  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    18  // copies of the Software, and to permit persons to whom the Software is
    19  // furnished to do so, subject to the following conditions:
    20  //
    21  // The above copyright notice and this permission notice shall be included in
    22  // all copies or substantial portions of the Software.
    23  //
    24  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    25  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    26  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    27  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    28  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    29  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    30  // THE SOFTWARE.
    31  
    32  #include <u.h>
    33  #include <libc.h>
    34  #include <bio.h>
    35  #include <link.h>
    36  
    37  static int
    38  yy_isalpha(int c)
    39  {
    40  	return c >= 0 && c <= 0xFF && isalpha(c);
    41  }
    42  
    43  static struct {
    44  	char *name;
    45  	int val;
    46  } headers[] = {
    47  	{"android",	Hlinux},
    48  	{"darwin",	Hdarwin},
    49  	{"dragonfly",	Hdragonfly},
    50  	{"elf",		Helf},
    51  	{"freebsd",	Hfreebsd},
    52  	{"linux",	Hlinux},
    53  	{"nacl",		Hnacl},
    54  	{"netbsd",	Hnetbsd},
    55  	{"openbsd",	Hopenbsd},
    56  	{"plan9",	Hplan9},
    57  	{"solaris",	Hsolaris},
    58  	{"windows",	Hwindows},
    59  	{"windowsgui",	Hwindows},
    60  };
    61  
    62  int
    63  headtype(char *name)
    64  {
    65  	int i;
    66  
    67  	for(i=0; i < nelem(headers); i++)
    68  		if(strcmp(name, headers[i].name) == 0)
    69  			return headers[i].val;
    70  	return -1;
    71  }
    72  
    73  char*
    74  headstr(int v)
    75  {
    76  	static char buf[20];
    77  	int i;
    78  
    79  	for(i=0; i < nelem(headers); i++)
    80  		if(v == headers[i].val)
    81  			return headers[i].name;
    82  	snprint(buf, sizeof buf, "%d", v);
    83  	return buf;
    84  }
    85  
    86  Link*
    87  linknew(LinkArch *arch)
    88  {
    89  	Link *ctxt;
    90  	char *p;
    91  	char buf[1024];
    92  
    93  	linksetexp();
    94  	nuxiinit(arch);
    95  	
    96  	ctxt = emallocz(sizeof *ctxt);
    97  	ctxt->arch = arch;
    98  	ctxt->version = HistVersion;
    99  	ctxt->goroot = getgoroot();
   100  	ctxt->goroot_final = getenv("GOROOT_FINAL");
   101  	if(ctxt->goroot_final != nil && ctxt->goroot_final[0] == '\0')
   102  		ctxt->goroot_final = nil;
   103  
   104  	p = getgoarch();
   105  	if(strcmp(p, arch->name) != 0)
   106  		sysfatal("invalid goarch %s (want %s)", p, arch->name);
   107  	
   108  	if(getwd(buf, sizeof buf) == 0)
   109  		strcpy(buf, "/???");
   110  	if(yy_isalpha(buf[0]) && buf[1] == ':') {
   111  		// On Windows.
   112  		ctxt->windows = 1;
   113  
   114  		// Canonicalize path by converting \ to / (Windows accepts both).
   115  		for(p=buf; *p; p++)
   116  			if(*p == '\\')
   117  				*p = '/';
   118  	}
   119  	ctxt->pathname = strdup(buf);
   120  	
   121  	ctxt->headtype = headtype(getgoos());
   122  	if(ctxt->headtype < 0)
   123  		sysfatal("unknown goos %s", getgoos());
   124  	
   125  	// Record thread-local storage offset.
   126  	// TODO(rsc): Move tlsoffset back into the linker.
   127  	switch(ctxt->headtype) {
   128  	default:
   129  		sysfatal("unknown thread-local storage offset for %s", headstr(ctxt->headtype));
   130  	case Hplan9:
   131  	case Hwindows:
   132  		break;
   133  	case Hlinux:
   134  	case Hfreebsd:
   135  	case Hnetbsd:
   136  	case Hopenbsd:
   137  	case Hdragonfly:
   138  	case Hsolaris:
   139  		/*
   140  		 * ELF uses TLS offset negative from FS.
   141  		 * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS).
   142  		 * Known to low-level assembly in package runtime and runtime/cgo.
   143  		 */
   144  		ctxt->tlsoffset = -2*ctxt->arch->ptrsize;
   145  		break;
   146  
   147  	case Hnacl:
   148  		switch(ctxt->arch->thechar) {
   149  		default:
   150  			sysfatal("unknown thread-local storage offset for nacl/%s", ctxt->arch->name);
   151  		case '6':
   152  			ctxt->tlsoffset = 0;
   153  			break;
   154  		case '8':
   155  			ctxt->tlsoffset = -8;
   156  			break;
   157  		case '5':
   158  			ctxt->tlsoffset = 0;
   159  			break;
   160  		}
   161  		break;
   162  
   163  	case Hdarwin:
   164  		/*
   165  		 * OS X system constants - offset from 0(GS) to our TLS.
   166  		 * Explained in ../../runtime/cgo/gcc_darwin_*.c.
   167  		 */
   168  		switch(ctxt->arch->thechar) {
   169  		default:
   170  			sysfatal("unknown thread-local storage offset for darwin/%s", ctxt->arch->name);
   171  		case '6':
   172  			ctxt->tlsoffset = 0x8a0;
   173  			break;
   174  		case '8':
   175  			ctxt->tlsoffset = 0x468;
   176  			break;
   177  		}
   178  		break;
   179  	}
   180  	
   181  	// On arm, record goarm.
   182  	if(ctxt->arch->thechar == '5') {
   183  		p = getgoarm();
   184  		if(p != nil)
   185  			ctxt->goarm = atoi(p);
   186  		else
   187  			ctxt->goarm = 6;
   188  	}
   189  
   190  	return ctxt;
   191  }
   192  
   193  LSym*
   194  linknewsym(Link *ctxt, char *symb, int v)
   195  {
   196  	LSym *s;
   197  
   198  	s = malloc(sizeof(*s));
   199  	memset(s, 0, sizeof(*s));
   200  
   201  	s->dynid = -1;
   202  	s->plt = -1;
   203  	s->got = -1;
   204  	s->name = estrdup(symb);
   205  	s->type = 0;
   206  	s->version = v;
   207  	s->value = 0;
   208  	s->sig = 0;
   209  	s->size = 0;
   210  	ctxt->nsymbol++;
   211  
   212  	s->allsym = ctxt->allsym;
   213  	ctxt->allsym = s;
   214  
   215  	return s;
   216  }
   217  
   218  static LSym*
   219  _lookup(Link *ctxt, char *symb, int v, int creat)
   220  {
   221  	LSym *s;
   222  	char *p;
   223  	uint32 h;
   224  	int c;
   225  
   226  	h = v;
   227  	for(p=symb; c = *p; p++)
   228  		h = h+h+h + c;
   229  	h &= 0xffffff;
   230  	h %= LINKHASH;
   231  	for(s = ctxt->hash[h]; s != nil; s = s->hash)
   232  		if(s->version == v && strcmp(s->name, symb) == 0)
   233  			return s;
   234  	if(!creat)
   235  		return nil;
   236  
   237  	s = linknewsym(ctxt, symb, v);
   238  	s->extname = s->name;
   239  	s->hash = ctxt->hash[h];
   240  	ctxt->hash[h] = s;
   241  
   242  	return s;
   243  }
   244  
   245  LSym*
   246  linklookup(Link *ctxt, char *name, int v)
   247  {
   248  	return _lookup(ctxt, name, v, 1);
   249  }
   250  
   251  // read-only lookup
   252  LSym*
   253  linkrlookup(Link *ctxt, char *name, int v)
   254  {
   255  	return _lookup(ctxt, name, v, 0);
   256  }
   257  
   258  int
   259  linksymfmt(Fmt *f)
   260  {
   261  	LSym *s;
   262  	
   263  	s = va_arg(f->args, LSym*);
   264  	if(s == nil)
   265  		return fmtstrcpy(f, "<nil>");
   266  	
   267  	return fmtstrcpy(f, s->name);
   268  }