github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/src/liblink/ld.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  void
    38  addlib(Link *ctxt, char *src, char *obj, char *pathname)
    39  {
    40  	char name[1024], pname[1024], *p;
    41  	int i;
    42  
    43  	if(strlen(pathname) >= sizeof name)
    44  		sysfatal("addlib pathname too long");
    45  	strcpy(name, pathname);
    46  	cleanname(name);
    47  	
    48  	// runtime.a -> runtime
    49  	p = nil;
    50  	if(strlen(name) > 2 && name[strlen(name)-2] == '.') {
    51  		p = name+strlen(name)-2;
    52  		*p = '\0';
    53  	}
    54  	
    55  	// already loaded?
    56  	for(i=0; i<ctxt->libraryp; i++)
    57  		if(strcmp(ctxt->library[i].pkg, name) == 0)
    58  			return;
    59  	
    60  	// runtime -> runtime.a for search
    61  	if(p != nil)
    62  		*p = '.';
    63  
    64  	if((!ctxt->windows && name[0] == '/') || (ctxt->windows && name[1] == ':'))
    65  		snprint(pname, sizeof pname, "%s", name);
    66  	else {
    67  		// try dot, -L "libdir", and then goroot.
    68  		for(i=0; i<ctxt->nlibdir; i++) {
    69  			snprint(pname, sizeof pname, "%s/%s", ctxt->libdir[i], name);
    70  			if(access(pname, AEXIST) >= 0)
    71  				break;
    72  		}
    73  	}
    74  	cleanname(pname);
    75  
    76  	/* runtime.a -> runtime */
    77  	if(p != nil)
    78  		*p = '\0';
    79  
    80  	if(ctxt->debugvlog > 1 && ctxt->bso)
    81  		Bprint(ctxt->bso, "%5.2f addlib: %s %s pulls in %s\n", cputime(), obj, src, pname);
    82  
    83  	addlibpath(ctxt, src, obj, pname, name);
    84  }
    85  
    86  /*
    87   * add library to library list.
    88   *	srcref: src file referring to package
    89   *	objref: object file referring to package
    90   *	file: object file, e.g., /home/rsc/go/pkg/container/vector.a
    91   *	pkg: package import path, e.g. container/vector
    92   */
    93  void
    94  addlibpath(Link *ctxt, char *srcref, char *objref, char *file, char *pkg)
    95  {
    96  	int i;
    97  	Library *l;
    98  
    99  	for(i=0; i<ctxt->libraryp; i++)
   100  		if(strcmp(file, ctxt->library[i].file) == 0)
   101  			return;
   102  
   103  	if(ctxt->debugvlog > 1 && ctxt->bso)
   104  		Bprint(ctxt->bso, "%5.2f addlibpath: srcref: %s objref: %s file: %s pkg: %s\n",
   105  			cputime(), srcref, objref, file, pkg);
   106  
   107  	if(ctxt->libraryp == ctxt->nlibrary){
   108  		ctxt->nlibrary = 50 + 2*ctxt->libraryp;
   109  		ctxt->library = erealloc(ctxt->library, sizeof ctxt->library[0] * ctxt->nlibrary);
   110  	}
   111  
   112  	l = &ctxt->library[ctxt->libraryp++];
   113  	l->objref = estrdup(objref);
   114  	l->srcref = estrdup(srcref);
   115  	l->file = estrdup(file);
   116  	l->pkg = estrdup(pkg);
   117  }
   118  
   119  int
   120  find1(int32 l, int c)
   121  {
   122  	char *p;
   123  	int i;
   124  
   125  	p = (char*)&l;
   126  	for(i=0; i<4; i++)
   127  		if(*p++ == c)
   128  			return i;
   129  	return 0;
   130  }
   131  
   132  void
   133  nuxiinit(LinkArch *arch)
   134  {
   135  	int i, c;
   136  
   137  	if(arch->endian != BigEndian && arch->endian != LittleEndian)
   138  		sysfatal("unknown endian (%#x) for arch %s", arch->endian, arch->name);
   139  
   140  	for(i=0; i<4; i++) {
   141  		c = find1(arch->endian, i+1);
   142  		if(arch->endian == LittleEndian) {
   143  			if(i < 2)
   144  				inuxi2[i] = c;
   145  			if(i < 1)
   146  				inuxi1[i] = c;
   147  		} else {
   148  			if(i >= 2)
   149  				inuxi2[i-2] = c;
   150  			if(i >= 3)
   151  				inuxi1[i-3] = c;
   152  		}
   153  		inuxi4[i] = c;
   154  		if(c == i) {
   155  			inuxi8[i] = c;
   156  			inuxi8[i+4] = c+4;
   157  		} else {
   158  			inuxi8[i] = c+4;
   159  			inuxi8[i+4] = c;
   160  		}
   161  		fnuxi4[i] = c;
   162  		if(c == i) {
   163  			fnuxi8[i] = c;
   164  			fnuxi8[i+4] = c+4;
   165  		} else {
   166  			fnuxi8[i] = c+4;
   167  			fnuxi8[i+4] = c;
   168  		}
   169  	}
   170  }
   171  
   172  uchar	fnuxi8[8];
   173  uchar	fnuxi4[4];
   174  uchar	inuxi1[1];
   175  uchar	inuxi2[2];
   176  uchar	inuxi4[4];
   177  uchar	inuxi8[8];
   178  
   179  enum
   180  {
   181  	LOG = 5,
   182  };
   183  void
   184  mkfwd(LSym *sym)
   185  {
   186  	Prog *p;
   187  	int i;
   188  	int32 dwn[LOG], cnt[LOG];
   189  	Prog *lst[LOG];
   190  
   191  	for(i=0; i<LOG; i++) {
   192  		if(i == 0)
   193  			cnt[i] = 1;
   194  		else
   195  			cnt[i] = LOG * cnt[i-1];
   196  		dwn[i] = 1;
   197  		lst[i] = nil;
   198  	}
   199  	i = 0;
   200  	for(p = sym->text; p != nil && p->link != nil; p = p->link) {
   201  		i--;
   202  		if(i < 0)
   203  			i = LOG-1;
   204  		p->forwd = nil;
   205  		dwn[i]--;
   206  		if(dwn[i] <= 0) {
   207  			dwn[i] = cnt[i];
   208  			if(lst[i] != nil)
   209  				lst[i]->forwd = p;
   210  			lst[i] = p;
   211  		}
   212  	}
   213  }
   214  
   215  Prog*
   216  copyp(Link *ctxt, Prog *q)
   217  {
   218  	Prog *p;
   219  
   220  	p = ctxt->arch->prg();
   221  	*p = *q;
   222  	return p;
   223  }
   224  
   225  Prog*
   226  appendp(Link *ctxt, Prog *q)
   227  {
   228  	Prog *p;
   229  
   230  	p = ctxt->arch->prg();
   231  	p->link = q->link;
   232  	q->link = p;
   233  	p->lineno = q->lineno;
   234  	p->mode = q->mode;
   235  	return p;
   236  }
   237  
   238  vlong
   239  atolwhex(char *s)
   240  {
   241  	vlong n;
   242  	int f;
   243  
   244  	n = 0;
   245  	f = 0;
   246  	while(*s == ' ' || *s == '\t')
   247  		s++;
   248  	if(*s == '-' || *s == '+') {
   249  		if(*s++ == '-')
   250  			f = 1;
   251  		while(*s == ' ' || *s == '\t')
   252  			s++;
   253  	}
   254  	if(s[0]=='0' && s[1]){
   255  		if(s[1]=='x' || s[1]=='X'){
   256  			s += 2;
   257  			for(;;){
   258  				if(*s >= '0' && *s <= '9')
   259  					n = n*16 + *s++ - '0';
   260  				else if(*s >= 'a' && *s <= 'f')
   261  					n = n*16 + *s++ - 'a' + 10;
   262  				else if(*s >= 'A' && *s <= 'F')
   263  					n = n*16 + *s++ - 'A' + 10;
   264  				else
   265  					break;
   266  			}
   267  		} else
   268  			while(*s >= '0' && *s <= '7')
   269  				n = n*8 + *s++ - '0';
   270  	} else
   271  		while(*s >= '0' && *s <= '9')
   272  			n = n*10 + *s++ - '0';
   273  	if(f)
   274  		n = -n;
   275  	return n;
   276  }