github.com/golang-haiku/go-1.4.3@v0.0.0-20190609233734-1f5ae41cc308/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  	{"haiku",	Hhaiku},
    52  	{"freebsd",	Hfreebsd},
    53  	{"linux",	Hlinux},
    54  	{"nacl",		Hnacl},
    55  	{"netbsd",	Hnetbsd},
    56  	{"openbsd",	Hopenbsd},
    57  	{"plan9",	Hplan9},
    58  	{"solaris",	Hsolaris},
    59  	{"windows",	Hwindows},
    60  	{"windowsgui",	Hwindows},
    61  	{0, 0},
    62  };
    63  
    64  int
    65  headtype(char *name)
    66  {
    67  	int i;
    68  
    69  	for(i=0; headers[i].name; i++)
    70  		if(strcmp(name, headers[i].name) == 0)
    71  			return headers[i].val;
    72  	return -1;
    73  }
    74  
    75  char*
    76  headstr(int v)
    77  {
    78  	static char buf[20];
    79  	int i;
    80  
    81  	for(i=0; headers[i].name; i++)
    82  		if(v == headers[i].val)
    83  			return headers[i].name;
    84  	snprint(buf, sizeof buf, "%d", v);
    85  	return buf;
    86  }
    87  
    88  Link*
    89  linknew(LinkArch *arch)
    90  {
    91  	Link *ctxt;
    92  	char *p;
    93  	char buf[1024];
    94  
    95  	nuxiinit(arch);
    96  	
    97  	ctxt = emallocz(sizeof *ctxt);
    98  	ctxt->arch = arch;
    99  	ctxt->version = HistVersion;
   100  	ctxt->goroot = getgoroot();
   101  	ctxt->goroot_final = getenv("GOROOT_FINAL");
   102  	if(ctxt->goroot_final != nil && ctxt->goroot_final[0] == '\0')
   103  		ctxt->goroot_final = nil;
   104  
   105  	p = getgoarch();
   106  	if(strcmp(p, arch->name) != 0)
   107  		sysfatal("invalid goarch %s (want %s)", p, arch->name);
   108  	
   109  	if(getwd(buf, sizeof buf) == 0)
   110  		strcpy(buf, "/???");
   111  	if(yy_isalpha(buf[0]) && buf[1] == ':') {
   112  		// On Windows.
   113  		ctxt->windows = 1;
   114  
   115  		// Canonicalize path by converting \ to / (Windows accepts both).
   116  		for(p=buf; *p; p++)
   117  			if(*p == '\\')
   118  				*p = '/';
   119  	}
   120  	ctxt->pathname = strdup(buf);
   121  	
   122  	ctxt->headtype = headtype(getgoos());
   123  	if(ctxt->headtype < 0)
   124  		sysfatal("unknown goos %s", getgoos());
   125  	
   126  	// Record thread-local storage offset.
   127  	// TODO(rsc): Move tlsoffset back into the linker.
   128  	switch(ctxt->headtype) {
   129  	default:
   130  		sysfatal("unknown thread-local storage offset for %s", headstr(ctxt->headtype));
   131  	case Hplan9:
   132  	case Hwindows:
   133  		break;
   134  	case Hhaiku:
   135   		/* FIXME */
   136  		// // on 64-bit we use the last two regular TLS slots
   137  		 if(ctxt->arch->thechar == '6') {
   138  		 	ctxt->tlsoffset = (64 - 2) * 8;
   139  		 }
   140  		break;
   141  	case Hlinux:
   142  	case Hfreebsd:
   143  	case Hnetbsd:
   144  	case Hopenbsd:
   145  	case Hdragonfly:
   146  	case Hsolaris:
   147  		/*
   148  		 * ELF uses TLS offset negative from FS.
   149  		 * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS).
   150  		 * Known to low-level assembly in package runtime and runtime/cgo.
   151  		 */
   152  		ctxt->tlsoffset = -2*ctxt->arch->ptrsize;
   153  		break;
   154  
   155  	case Hnacl:
   156  		switch(ctxt->arch->thechar) {
   157  		default:
   158  			sysfatal("unknown thread-local storage offset for nacl/%s", ctxt->arch->name);
   159  		case '6':
   160  			ctxt->tlsoffset = 0;
   161  			break;
   162  		case '8':
   163  			ctxt->tlsoffset = -8;
   164  			break;
   165  		case '5':
   166  			ctxt->tlsoffset = 0;
   167  			break;
   168  		}
   169  		break;
   170  
   171  	case Hdarwin:
   172  		/*
   173  		 * OS X system constants - offset from 0(GS) to our TLS.
   174  		 * Explained in ../../runtime/cgo/gcc_darwin_*.c.
   175  		 */
   176  		switch(ctxt->arch->thechar) {
   177  		default:
   178  			sysfatal("unknown thread-local storage offset for darwin/%s", ctxt->arch->name);
   179  		case '6':
   180  			ctxt->tlsoffset = 0x8a0;
   181  			break;
   182  		case '8':
   183  			ctxt->tlsoffset = 0x468;
   184  			break;
   185  		}
   186  		break;
   187  	}
   188  	
   189  	// On arm, record goarm.
   190  	if(ctxt->arch->thechar == '5') {
   191  		p = getgoarm();
   192  		if(p != nil)
   193  			ctxt->goarm = atoi(p);
   194  		else
   195  			ctxt->goarm = 6;
   196  	}
   197  
   198  	return ctxt;
   199  }
   200  
   201  LSym*
   202  linknewsym(Link *ctxt, char *symb, int v)
   203  {
   204  	LSym *s;
   205  
   206  	s = malloc(sizeof(*s));
   207  	memset(s, 0, sizeof(*s));
   208  
   209  	s->dynid = -1;
   210  	s->plt = -1;
   211  	s->got = -1;
   212  	s->name = estrdup(symb);
   213  	s->type = 0;
   214  	s->version = v;
   215  	s->value = 0;
   216  	s->sig = 0;
   217  	s->size = 0;
   218  	ctxt->nsymbol++;
   219  
   220  	s->allsym = ctxt->allsym;
   221  	ctxt->allsym = s;
   222  
   223  	return s;
   224  }
   225  
   226  static LSym*
   227  _lookup(Link *ctxt, char *symb, int v, int creat)
   228  {
   229  	LSym *s;
   230  	char *p;
   231  	uint32 h;
   232  	int c;
   233  
   234  	h = v;
   235  	for(p=symb; c = *p; p++)
   236  		h = h+h+h + c;
   237  	h &= 0xffffff;
   238  	h %= LINKHASH;
   239  	for(s = ctxt->hash[h]; s != nil; s = s->hash)
   240  		if(s->version == v && strcmp(s->name, symb) == 0)
   241  			return s;
   242  	if(!creat)
   243  		return nil;
   244  
   245  	s = linknewsym(ctxt, symb, v);
   246  	s->extname = s->name;
   247  	s->hash = ctxt->hash[h];
   248  	ctxt->hash[h] = s;
   249  
   250  	return s;
   251  }
   252  
   253  LSym*
   254  linklookup(Link *ctxt, char *name, int v)
   255  {
   256  	return _lookup(ctxt, name, v, 1);
   257  }
   258  
   259  // read-only lookup
   260  LSym*
   261  linkrlookup(Link *ctxt, char *name, int v)
   262  {
   263  	return _lookup(ctxt, name, v, 0);
   264  }
   265  
   266  int
   267  linksymfmt(Fmt *f)
   268  {
   269  	LSym *s;
   270  	
   271  	s = va_arg(f->args, LSym*);
   272  	if(s == nil)
   273  		return fmtstrcpy(f, "<nil>");
   274  	
   275  	return fmtstrcpy(f, s->name);
   276  }