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 }