github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/src/liblink/data.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  mangle(char *file)
    39  {
    40  	sysfatal("%s: mangled input file", file);
    41  }
    42  
    43  void
    44  symgrow(Link *ctxt, LSym *s, vlong lsiz)
    45  {
    46  	int32 siz;
    47  
    48  	USED(ctxt);
    49  
    50  	siz = (int32)lsiz;
    51  	if((vlong)siz != lsiz)
    52  		sysfatal("symgrow size %lld too long", lsiz);
    53  
    54  	if(s->np >= siz)
    55  		return;
    56  
    57  	if(s->np > s->maxp) {
    58  		ctxt->cursym = s;
    59  		sysfatal("corrupt symbol data: np=%lld > maxp=%lld", (vlong)s->np, (vlong)s->maxp);
    60  	}
    61  
    62  	if(s->maxp < siz) {
    63  		if(s->maxp == 0)
    64  			s->maxp = 8;
    65  		while(s->maxp < siz)
    66  			s->maxp <<= 1;
    67  		s->p = erealloc(s->p, s->maxp);
    68  		memset(s->p+s->np, 0, s->maxp-s->np);
    69  	}
    70  	s->np = siz;
    71  }
    72  
    73  void
    74  savedata(Link *ctxt, LSym *s, Prog *p, char *pn)
    75  {
    76  	int32 off, siz, i, fl;
    77  	float32 flt;
    78  	uchar *cast;
    79  	vlong o;
    80  	Reloc *r;
    81  
    82  	off = p->from.offset;
    83  	siz = ctxt->arch->datasize(p);
    84  	if(off < 0 || siz < 0 || off >= 1<<30 || siz >= 100)
    85  		mangle(pn);
    86  	if(ctxt->enforce_data_order && off < s->np)
    87  		ctxt->diag("data out of order (already have %d)\n%P", p);
    88  	symgrow(ctxt, s, off+siz);
    89  
    90  	if(p->to.type == ctxt->arch->D_FCONST) {
    91  		switch(siz) {
    92  		default:
    93  		case 4:
    94  			flt = p->to.u.dval;
    95  			cast = (uchar*)&flt;
    96  			for(i=0; i<4; i++)
    97  				s->p[off+i] = cast[fnuxi4[i]];
    98  			break;
    99  		case 8:
   100  			cast = (uchar*)&p->to.u.dval;
   101  			for(i=0; i<8; i++)
   102  				s->p[off+i] = cast[fnuxi8[i]];
   103  			break;
   104  		}
   105  	} else if(p->to.type == ctxt->arch->D_SCONST) {
   106  		for(i=0; i<siz; i++)
   107  			s->p[off+i] = p->to.u.sval[i];
   108  	} else if(p->to.type == ctxt->arch->D_CONST) {
   109  		if(p->to.sym)
   110  			goto addr;
   111  		o = p->to.offset;
   112  		fl = o;
   113  		cast = (uchar*)&fl;
   114  		switch(siz) {
   115  		default:
   116  			ctxt->diag("bad nuxi %d\n%P", siz, p);
   117  			break;
   118  		case 1:
   119  			s->p[off] = cast[inuxi1[0]];
   120  			break;
   121  		case 2:
   122  			for(i=0; i<2; i++)
   123  				s->p[off+i] = cast[inuxi2[i]];
   124  			break;
   125  		case 4:
   126  			for(i=0; i<4; i++)
   127  				s->p[off+i] = cast[inuxi4[i]];
   128  			break;
   129  		case 8:
   130  			cast = (uchar*)&o;
   131  			for(i=0; i<8; i++)
   132  				s->p[off+i] = cast[inuxi8[i]];
   133  			break;
   134  		}
   135  	} else if(p->to.type == ctxt->arch->D_ADDR) {
   136  	addr:
   137  		r = addrel(s);
   138  		r->off = off;
   139  		r->siz = siz;
   140  		r->sym = p->to.sym;
   141  		r->type = R_ADDR;
   142  		r->add = p->to.offset;
   143  	} else {
   144  		ctxt->diag("bad data: %P", p);
   145  	}
   146  }
   147  
   148  Reloc*
   149  addrel(LSym *s)
   150  {
   151  	if(s->nr >= s->maxr) {
   152  		if(s->maxr == 0)
   153  			s->maxr = 4;
   154  		else
   155  			s->maxr <<= 1;
   156  		s->r = erealloc(s->r, s->maxr*sizeof s->r[0]);
   157  		memset(s->r+s->nr, 0, (s->maxr-s->nr)*sizeof s->r[0]);
   158  	}
   159  	return &s->r[s->nr++];
   160  }
   161  
   162  vlong
   163  setuintxx(Link *ctxt, LSym *s, vlong off, uint64 v, vlong wid)
   164  {
   165  	int32 i, fl;
   166  	vlong o;
   167  	uchar *cast;
   168  
   169  	if(s->type == 0)
   170  		s->type = SDATA;
   171  	s->reachable = 1;
   172  	if(s->size < off+wid) {
   173  		s->size = off+wid;
   174  		symgrow(ctxt, s, s->size);
   175  	}
   176  	fl = v;
   177  	cast = (uchar*)&fl;
   178  	switch(wid) {
   179  	case 1:
   180  		s->p[off] = cast[inuxi1[0]];
   181  		break;
   182  	case 2:
   183  		for(i=0; i<2; i++)
   184  			s->p[off+i] = cast[inuxi2[i]];
   185  		break;
   186  	case 4:
   187  		for(i=0; i<4; i++)
   188  			s->p[off+i] = cast[inuxi4[i]];
   189  		break;
   190  	case 8:
   191  		o = v;
   192  		cast = (uchar*)&o;
   193  		for(i=0; i<8; i++)
   194  			s->p[off+i] = cast[inuxi8[i]];
   195  		break;
   196  	}
   197  	return off+wid;
   198  }
   199  
   200  vlong
   201  adduintxx(Link *ctxt, LSym *s, uint64 v, int wid)
   202  {
   203  	vlong off;
   204  
   205  	off = s->size;
   206  	setuintxx(ctxt, s, off, v, wid);
   207  	return off;
   208  }
   209  
   210  vlong
   211  adduint8(Link *ctxt, LSym *s, uint8 v)
   212  {
   213  	return adduintxx(ctxt, s, v, 1);
   214  }
   215  
   216  vlong
   217  adduint16(Link *ctxt, LSym *s, uint16 v)
   218  {
   219  	return adduintxx(ctxt, s, v, 2);
   220  }
   221  
   222  vlong
   223  adduint32(Link *ctxt, LSym *s, uint32 v)
   224  {
   225  	return adduintxx(ctxt, s, v, 4);
   226  }
   227  
   228  vlong
   229  adduint64(Link *ctxt, LSym *s, uint64 v)
   230  {
   231  	return adduintxx(ctxt, s, v, 8);
   232  }
   233  
   234  vlong
   235  setuint8(Link *ctxt, LSym *s, vlong r, uint8 v)
   236  {
   237  	return setuintxx(ctxt, s, r, v, 1);
   238  }
   239  
   240  vlong
   241  setuint16(Link *ctxt, LSym *s, vlong r, uint16 v)
   242  {
   243  	return setuintxx(ctxt, s, r, v, 2);
   244  }
   245  
   246  vlong
   247  setuint32(Link *ctxt, LSym *s, vlong r, uint32 v)
   248  {
   249  	return setuintxx(ctxt, s, r, v, 4);
   250  }
   251  
   252  vlong
   253  setuint64(Link *ctxt, LSym *s, vlong r, uint64 v)
   254  {
   255  	return setuintxx(ctxt, s, r, v, 8);
   256  }
   257  
   258  vlong
   259  addaddrplus(Link *ctxt, LSym *s, LSym *t, vlong add)
   260  {
   261  	vlong i;
   262  	Reloc *r;
   263  
   264  	if(s->type == 0)
   265  		s->type = SDATA;
   266  	s->reachable = 1;
   267  	i = s->size;
   268  	s->size += ctxt->arch->ptrsize;
   269  	symgrow(ctxt, s, s->size);
   270  	r = addrel(s);
   271  	r->sym = t;
   272  	r->off = i;
   273  	r->siz = ctxt->arch->ptrsize;
   274  	r->type = R_ADDR;
   275  	r->add = add;
   276  	return i + r->siz;
   277  }
   278  
   279  vlong
   280  addpcrelplus(Link *ctxt, LSym *s, LSym *t, vlong add)
   281  {
   282  	vlong i;
   283  	Reloc *r;
   284  
   285  	if(s->type == 0)
   286  		s->type = SDATA;
   287  	s->reachable = 1;
   288  	i = s->size;
   289  	s->size += 4;
   290  	symgrow(ctxt, s, s->size);
   291  	r = addrel(s);
   292  	r->sym = t;
   293  	r->off = i;
   294  	r->add = add;
   295  	r->type = R_PCREL;
   296  	r->siz = 4;
   297  	return i + r->siz;
   298  }
   299  
   300  vlong
   301  addaddr(Link *ctxt, LSym *s, LSym *t)
   302  {
   303  	return addaddrplus(ctxt, s, t, 0);
   304  }
   305  
   306  vlong
   307  setaddrplus(Link *ctxt, LSym *s, vlong off, LSym *t, vlong add)
   308  {
   309  	Reloc *r;
   310  
   311  	if(s->type == 0)
   312  		s->type = SDATA;
   313  	s->reachable = 1;
   314  	if(off+ctxt->arch->ptrsize > s->size) {
   315  		s->size = off + ctxt->arch->ptrsize;
   316  		symgrow(ctxt, s, s->size);
   317  	}
   318  	r = addrel(s);
   319  	r->sym = t;
   320  	r->off = off;
   321  	r->siz = ctxt->arch->ptrsize;
   322  	r->type = R_ADDR;
   323  	r->add = add;
   324  	return off + r->siz;
   325  }
   326  
   327  vlong
   328  setaddr(Link *ctxt, LSym *s, vlong off, LSym *t)
   329  {
   330  	return setaddrplus(ctxt, s, off, t, 0);
   331  }
   332  
   333  vlong
   334  addsize(Link *ctxt, LSym *s, LSym *t)
   335  {
   336  	vlong i;
   337  	Reloc *r;
   338  
   339  	if(s->type == 0)
   340  		s->type = SDATA;
   341  	s->reachable = 1;
   342  	i = s->size;
   343  	s->size += ctxt->arch->ptrsize;
   344  	symgrow(ctxt, s, s->size);
   345  	r = addrel(s);
   346  	r->sym = t;
   347  	r->off = i;
   348  	r->siz = ctxt->arch->ptrsize;
   349  	r->type = R_SIZE;
   350  	return i + r->siz;
   351  }
   352  
   353  vlong
   354  addaddrplus4(Link *ctxt, LSym *s, LSym *t, vlong add)
   355  {
   356  	vlong i;
   357  	Reloc *r;
   358  
   359  	if(s->type == 0)
   360  		s->type = SDATA;
   361  	s->reachable = 1;
   362  	i = s->size;
   363  	s->size += 4;
   364  	symgrow(ctxt, s, s->size);
   365  	r = addrel(s);
   366  	r->sym = t;
   367  	r->off = i;
   368  	r->siz = 4;
   369  	r->type = R_ADDR;
   370  	r->add = add;
   371  	return i + r->siz;
   372  }