github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/cmd/ld/ldmacho.c (about) 1 /* 2 Derived from Plan 9 from User Space's src/libmach/elf.h, elf.c 3 http://code.swtch.com/plan9port/src/tip/src/libmach/ 4 5 Copyright © 2004 Russ Cox. 6 Portions Copyright © 2008-2010 Google Inc. 7 Portions Copyright © 2010 The Go Authors. 8 9 Permission is hereby granted, free of charge, to any person obtaining a copy 10 of this software and associated documentation files (the "Software"), to deal 11 in the Software without restriction, including without limitation the rights 12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 copies of the Software, and to permit persons to whom the Software is 14 furnished to do so, subject to the following conditions: 15 16 The above copyright notice and this permission notice shall be included in 17 all copies or substantial portions of the Software. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 THE SOFTWARE. 26 */ 27 28 #include "l.h" 29 #include "lib.h" 30 31 enum { 32 MACHO_FAKE_GOTPCREL = 100, // from macho.h 33 34 N_EXT = 0x01, 35 N_TYPE = 0x1e, 36 N_STAB = 0xe0, 37 }; 38 39 typedef struct MachoObj MachoObj; 40 typedef struct MachoCmd MachoCmd; 41 typedef struct MachoSeg MachoSeg; 42 typedef struct MachoSect MachoSect; 43 typedef struct MachoRel MachoRel; 44 typedef struct MachoSymtab MachoSymtab; 45 typedef struct MachoSym MachoSym; 46 typedef struct MachoDysymtab MachoDysymtab; 47 48 enum 49 { 50 MachoCpuVax = 1, 51 MachoCpu68000 = 6, 52 MachoCpu386 = 7, 53 MachoCpuAmd64 = 0x1000007, 54 MachoCpuMips = 8, 55 MachoCpu98000 = 10, 56 MachoCpuHppa = 11, 57 MachoCpuArm = 12, 58 MachoCpu88000 = 13, 59 MachoCpuSparc = 14, 60 MachoCpu860 = 15, 61 MachoCpuAlpha = 16, 62 MachoCpuPower = 18, 63 64 MachoCmdSegment = 1, 65 MachoCmdSymtab = 2, 66 MachoCmdSymseg = 3, 67 MachoCmdThread = 4, 68 MachoCmdDysymtab = 11, 69 MachoCmdSegment64 = 25, 70 71 MachoFileObject = 1, 72 MachoFileExecutable = 2, 73 MachoFileFvmlib = 3, 74 MachoFileCore = 4, 75 MachoFilePreload = 5, 76 }; 77 78 struct MachoSeg 79 { 80 char name[16+1]; 81 uint64 vmaddr; 82 uint64 vmsize; 83 uint32 fileoff; 84 uint32 filesz; 85 uint32 maxprot; 86 uint32 initprot; 87 uint32 nsect; 88 uint32 flags; 89 MachoSect *sect; 90 }; 91 92 struct MachoSect 93 { 94 char name[16+1]; 95 char segname[16+1]; 96 uint64 addr; 97 uint64 size; 98 uint32 off; 99 uint32 align; 100 uint32 reloff; 101 uint32 nreloc; 102 uint32 flags; 103 uint32 res1; 104 uint32 res2; 105 Sym *sym; 106 107 MachoRel *rel; 108 }; 109 110 struct MachoRel 111 { 112 uint32 addr; 113 uint32 symnum; 114 uint8 pcrel; 115 uint8 length; 116 uint8 extrn; 117 uint8 type; 118 uint8 scattered; 119 uint32 value; 120 }; 121 122 struct MachoSymtab 123 { 124 uint32 symoff; 125 uint32 nsym; 126 uint32 stroff; 127 uint32 strsize; 128 129 char *str; 130 MachoSym *sym; 131 }; 132 133 struct MachoSym 134 { 135 char *name; 136 uint8 type; 137 uint8 sectnum; 138 uint16 desc; 139 char kind; 140 uint64 value; 141 Sym *sym; 142 }; 143 144 struct MachoDysymtab 145 { 146 uint32 ilocalsym; 147 uint32 nlocalsym; 148 uint32 iextdefsym; 149 uint32 nextdefsym; 150 uint32 iundefsym; 151 uint32 nundefsym; 152 uint32 tocoff; 153 uint32 ntoc; 154 uint32 modtaboff; 155 uint32 nmodtab; 156 uint32 extrefsymoff; 157 uint32 nextrefsyms; 158 uint32 indirectsymoff; 159 uint32 nindirectsyms; 160 uint32 extreloff; 161 uint32 nextrel; 162 uint32 locreloff; 163 uint32 nlocrel; 164 uint32 *indir; 165 }; 166 167 struct MachoCmd 168 { 169 int type; 170 uint32 off; 171 uint32 size; 172 MachoSeg seg; 173 MachoSymtab sym; 174 MachoDysymtab dsym; 175 }; 176 177 struct MachoObj 178 { 179 Biobuf *f; 180 int64 base; // off in f where Mach-O begins 181 int64 len; // length of Mach-O 182 int is64; 183 char *name; 184 185 Endian *e; 186 uint cputype; 187 uint subcputype; 188 uint32 filetype; 189 uint32 flags; 190 MachoCmd *cmd; 191 uint ncmd; 192 }; 193 194 static int 195 unpackcmd(uchar *p, MachoObj *m, MachoCmd *c, uint type, uint sz) 196 { 197 uint32 (*e4)(uchar*); 198 uint64 (*e8)(uchar*); 199 MachoSect *s; 200 int i; 201 202 e4 = m->e->e32; 203 e8 = m->e->e64; 204 205 c->type = type; 206 c->size = sz; 207 switch(type){ 208 default: 209 return -1; 210 case MachoCmdSegment: 211 if(sz < 56) 212 return -1; 213 strecpy(c->seg.name, c->seg.name+sizeof c->seg.name, (char*)p+8); 214 c->seg.vmaddr = e4(p+24); 215 c->seg.vmsize = e4(p+28); 216 c->seg.fileoff = e4(p+32); 217 c->seg.filesz = e4(p+36); 218 c->seg.maxprot = e4(p+40); 219 c->seg.initprot = e4(p+44); 220 c->seg.nsect = e4(p+48); 221 c->seg.flags = e4(p+52); 222 c->seg.sect = mal(c->seg.nsect * sizeof c->seg.sect[0]); 223 if(sz < 56+c->seg.nsect*68) 224 return -1; 225 p += 56; 226 for(i=0; i<c->seg.nsect; i++) { 227 s = &c->seg.sect[i]; 228 strecpy(s->name, s->name+sizeof s->name, (char*)p+0); 229 strecpy(s->segname, s->segname+sizeof s->segname, (char*)p+16); 230 s->addr = e4(p+32); 231 s->size = e4(p+36); 232 s->off = e4(p+40); 233 s->align = e4(p+44); 234 s->reloff = e4(p+48); 235 s->nreloc = e4(p+52); 236 s->flags = e4(p+56); 237 s->res1 = e4(p+60); 238 s->res2 = e4(p+64); 239 p += 68; 240 } 241 break; 242 case MachoCmdSegment64: 243 if(sz < 72) 244 return -1; 245 strecpy(c->seg.name, c->seg.name+sizeof c->seg.name, (char*)p+8); 246 c->seg.vmaddr = e8(p+24); 247 c->seg.vmsize = e8(p+32); 248 c->seg.fileoff = e8(p+40); 249 c->seg.filesz = e8(p+48); 250 c->seg.maxprot = e4(p+56); 251 c->seg.initprot = e4(p+60); 252 c->seg.nsect = e4(p+64); 253 c->seg.flags = e4(p+68); 254 c->seg.sect = mal(c->seg.nsect * sizeof c->seg.sect[0]); 255 if(sz < 72+c->seg.nsect*80) 256 return -1; 257 p += 72; 258 for(i=0; i<c->seg.nsect; i++) { 259 s = &c->seg.sect[i]; 260 strecpy(s->name, s->name+sizeof s->name, (char*)p+0); 261 strecpy(s->segname, s->segname+sizeof s->segname, (char*)p+16); 262 s->addr = e8(p+32); 263 s->size = e8(p+40); 264 s->off = e4(p+48); 265 s->align = e4(p+52); 266 s->reloff = e4(p+56); 267 s->nreloc = e4(p+60); 268 s->flags = e4(p+64); 269 s->res1 = e4(p+68); 270 s->res2 = e4(p+72); 271 // p+76 is reserved 272 p += 80; 273 } 274 break; 275 case MachoCmdSymtab: 276 if(sz < 24) 277 return -1; 278 c->sym.symoff = e4(p+8); 279 c->sym.nsym = e4(p+12); 280 c->sym.stroff = e4(p+16); 281 c->sym.strsize = e4(p+20); 282 break; 283 case MachoCmdDysymtab: 284 if(sz < 80) 285 return -1; 286 c->dsym.ilocalsym = e4(p+8); 287 c->dsym.nlocalsym = e4(p+12); 288 c->dsym.iextdefsym = e4(p+16); 289 c->dsym.nextdefsym = e4(p+20); 290 c->dsym.iundefsym = e4(p+24); 291 c->dsym.nundefsym = e4(p+28); 292 c->dsym.tocoff = e4(p+32); 293 c->dsym.ntoc = e4(p+36); 294 c->dsym.modtaboff = e4(p+40); 295 c->dsym.nmodtab = e4(p+44); 296 c->dsym.extrefsymoff = e4(p+48); 297 c->dsym.nextrefsyms = e4(p+52); 298 c->dsym.indirectsymoff = e4(p+56); 299 c->dsym.nindirectsyms = e4(p+60); 300 c->dsym.extreloff = e4(p+64); 301 c->dsym.nextrel = e4(p+68); 302 c->dsym.locreloff = e4(p+72); 303 c->dsym.nlocrel = e4(p+76); 304 break; 305 } 306 return 0; 307 } 308 309 static int 310 macholoadrel(MachoObj *m, MachoSect *sect) 311 { 312 MachoRel *rel, *r; 313 uchar *buf, *p; 314 int i, n; 315 uint32 v; 316 317 if(sect->rel != nil || sect->nreloc == 0) 318 return 0; 319 rel = mal(sect->nreloc * sizeof r[0]); 320 n = sect->nreloc * 8; 321 buf = mal(n); 322 if(Bseek(m->f, m->base + sect->reloff, 0) < 0 || Bread(m->f, buf, n) != n) 323 return -1; 324 for(i=0; i<sect->nreloc; i++) { 325 r = &rel[i]; 326 p = buf+i*8; 327 r->addr = m->e->e32(p); 328 329 // TODO(rsc): Wrong interpretation for big-endian bitfields? 330 if(r->addr & 0x80000000) { 331 // scatterbrained relocation 332 r->scattered = 1; 333 v = r->addr >> 24; 334 r->addr &= 0xFFFFFF; 335 r->type = v & 0xF; 336 v >>= 4; 337 r->length = 1<<(v&3); 338 v >>= 2; 339 r->pcrel = v & 1; 340 r->value = m->e->e32(p+4); 341 } else { 342 v = m->e->e32(p+4); 343 r->symnum = v & 0xFFFFFF; 344 v >>= 24; 345 r->pcrel = v&1; 346 v >>= 1; 347 r->length = 1<<(v&3); 348 v >>= 2; 349 r->extrn = v&1; 350 v >>= 1; 351 r->type = v; 352 } 353 } 354 sect->rel = rel; 355 return 0; 356 } 357 358 static int 359 macholoaddsym(MachoObj *m, MachoDysymtab *d) 360 { 361 uchar *p; 362 int i, n; 363 364 n = d->nindirectsyms; 365 366 p = mal(n*4); 367 if(Bseek(m->f, m->base + d->indirectsymoff, 0) < 0 || Bread(m->f, p, n*4) != n*4) 368 return -1; 369 370 d->indir = (uint32*)p; 371 for(i=0; i<n; i++) 372 d->indir[i] = m->e->e32(p+4*i); 373 return 0; 374 } 375 376 static int 377 macholoadsym(MachoObj *m, MachoSymtab *symtab) 378 { 379 char *strbuf; 380 uchar *symbuf, *p; 381 int i, n, symsize; 382 MachoSym *sym, *s; 383 uint32 v; 384 385 if(symtab->sym != nil) 386 return 0; 387 388 strbuf = mal(symtab->strsize); 389 if(Bseek(m->f, m->base + symtab->stroff, 0) < 0 || Bread(m->f, strbuf, symtab->strsize) != symtab->strsize) 390 return -1; 391 392 symsize = 12; 393 if(m->is64) 394 symsize = 16; 395 n = symtab->nsym * symsize; 396 symbuf = mal(n); 397 if(Bseek(m->f, m->base + symtab->symoff, 0) < 0 || Bread(m->f, symbuf, n) != n) 398 return -1; 399 sym = mal(symtab->nsym * sizeof sym[0]); 400 p = symbuf; 401 for(i=0; i<symtab->nsym; i++) { 402 s = &sym[i]; 403 v = m->e->e32(p); 404 if(v >= symtab->strsize) 405 return -1; 406 s->name = strbuf + v; 407 s->type = p[4]; 408 s->sectnum = p[5]; 409 s->desc = m->e->e16(p+6); 410 if(m->is64) 411 s->value = m->e->e64(p+8); 412 else 413 s->value = m->e->e32(p+8); 414 p += symsize; 415 } 416 symtab->str = strbuf; 417 symtab->sym = sym; 418 return 0; 419 } 420 421 void 422 ldmacho(Biobuf *f, char *pkg, int64 len, char *pn) 423 { 424 int i, j, is64; 425 uint64 secaddr; 426 uchar hdr[7*4], *cmdp; 427 uchar tmp[4]; 428 uchar *dat; 429 ulong ncmd, cmdsz, ty, sz, off; 430 MachoObj *m; 431 Endian *e; 432 int64 base; 433 MachoSect *sect; 434 MachoRel *rel; 435 Sym *s, *s1, *outer; 436 MachoCmd *c; 437 MachoSymtab *symtab; 438 MachoDysymtab *dsymtab; 439 MachoSym *sym; 440 Reloc *r, *rp; 441 char *name; 442 443 version++; 444 base = Boffset(f); 445 if(Bread(f, hdr, sizeof hdr) != sizeof hdr) 446 goto bad; 447 448 if((be.e32(hdr)&~1) == 0xFEEDFACE){ 449 e = &be; 450 }else if((le.e32(hdr)&~1) == 0xFEEDFACE){ 451 e = ≤ 452 }else{ 453 werrstr("bad magic - not mach-o file"); 454 goto bad; 455 } 456 457 is64 = e->e32(hdr) == 0xFEEDFACF; 458 ncmd = e->e32(hdr+4*4); 459 cmdsz = e->e32(hdr+5*4); 460 if(ncmd > 0x10000 || cmdsz >= 0x01000000){ 461 werrstr("implausible mach-o header ncmd=%lud cmdsz=%lud", ncmd, cmdsz); 462 goto bad; 463 } 464 if(is64) 465 Bread(f, tmp, 4); // skip reserved word in header 466 467 m = mal(sizeof(*m)+ncmd*sizeof(MachoCmd)+cmdsz); 468 m->f = f; 469 m->e = e; 470 m->cputype = e->e32(hdr+1*4); 471 m->subcputype = e->e32(hdr+2*4); 472 m->filetype = e->e32(hdr+3*4); 473 m->ncmd = ncmd; 474 m->flags = e->e32(hdr+6*4); 475 m->is64 = is64; 476 m->base = base; 477 m->len = len; 478 m->name = pn; 479 480 switch(thechar) { 481 default: 482 diag("%s: mach-o %s unimplemented", pn, thestring); 483 return; 484 case '6': 485 if(e != &le || m->cputype != MachoCpuAmd64) { 486 diag("%s: mach-o object but not amd64", pn); 487 return; 488 } 489 break; 490 case '8': 491 if(e != &le || m->cputype != MachoCpu386) { 492 diag("%s: mach-o object but not 386", pn); 493 return; 494 } 495 break; 496 } 497 498 m->cmd = (MachoCmd*)(m+1); 499 off = sizeof hdr; 500 cmdp = (uchar*)(m->cmd+ncmd); 501 if(Bread(f, cmdp, cmdsz) != cmdsz){ 502 werrstr("reading cmds: %r"); 503 goto bad; 504 } 505 506 // read and parse load commands 507 c = nil; 508 symtab = nil; 509 dsymtab = nil; 510 for(i=0; i<ncmd; i++){ 511 ty = e->e32(cmdp); 512 sz = e->e32(cmdp+4); 513 m->cmd[i].off = off; 514 unpackcmd(cmdp, m, &m->cmd[i], ty, sz); 515 cmdp += sz; 516 off += sz; 517 if(ty == MachoCmdSymtab) { 518 if(symtab != nil) { 519 werrstr("multiple symbol tables"); 520 goto bad; 521 } 522 symtab = &m->cmd[i].sym; 523 macholoadsym(m, symtab); 524 } 525 if(ty == MachoCmdDysymtab) { 526 dsymtab = &m->cmd[i].dsym; 527 macholoaddsym(m, dsymtab); 528 } 529 if((is64 && ty == MachoCmdSegment64) || (!is64 && ty == MachoCmdSegment)) { 530 if(c != nil) { 531 werrstr("multiple load commands"); 532 goto bad; 533 } 534 c = &m->cmd[i]; 535 } 536 } 537 538 // load text and data segments into memory. 539 // they are not as small as the load commands, but we'll need 540 // the memory anyway for the symbol images, so we might 541 // as well use one large chunk. 542 if(c == nil) { 543 werrstr("no load command"); 544 goto bad; 545 } 546 if(symtab == nil) { 547 // our work is done here - no symbols means nothing can refer to this file 548 return; 549 } 550 551 if(c->seg.fileoff+c->seg.filesz >= len) { 552 werrstr("load segment out of range"); 553 goto bad; 554 } 555 556 dat = mal(c->seg.filesz); 557 if(Bseek(f, m->base + c->seg.fileoff, 0) < 0 || Bread(f, dat, c->seg.filesz) != c->seg.filesz) { 558 werrstr("cannot load object data: %r"); 559 goto bad; 560 } 561 562 for(i=0; i<c->seg.nsect; i++) { 563 sect = &c->seg.sect[i]; 564 if(strcmp(sect->segname, "__TEXT") != 0 && strcmp(sect->segname, "__DATA") != 0) 565 continue; 566 if(strcmp(sect->name, "__eh_frame") == 0) 567 continue; 568 name = smprint("%s(%s/%s)", pkg, sect->segname, sect->name); 569 s = lookup(name, version); 570 if(s->type != 0) { 571 werrstr("duplicate %s/%s", sect->segname, sect->name); 572 goto bad; 573 } 574 free(name); 575 576 s->np = sect->size; 577 s->size = s->np; 578 if((sect->flags & 0xff) == 1) // S_ZEROFILL 579 s->p = mal(s->size); 580 else { 581 s->p = dat + sect->addr - c->seg.vmaddr; 582 } 583 584 if(strcmp(sect->segname, "__TEXT") == 0) { 585 if(strcmp(sect->name, "__text") == 0) 586 s->type = STEXT; 587 else 588 s->type = SRODATA; 589 } else { 590 if (strcmp(sect->name, "__bss") == 0) { 591 s->type = SBSS; 592 s->np = 0; 593 } else 594 s->type = SDATA; 595 } 596 sect->sym = s; 597 } 598 599 // enter sub-symbols into symbol table. 600 // have to guess sizes from next symbol. 601 for(i=0; i<symtab->nsym; i++) { 602 int v; 603 sym = &symtab->sym[i]; 604 if(sym->type&N_STAB) 605 continue; 606 // TODO: check sym->type against outer->type. 607 name = sym->name; 608 if(name[0] == '_' && name[1] != '\0') 609 name++; 610 v = 0; 611 if(!(sym->type&N_EXT)) 612 v = version; 613 s = lookup(name, v); 614 sym->sym = s; 615 if(sym->sectnum == 0) // undefined 616 continue; 617 if(sym->sectnum > c->seg.nsect) { 618 werrstr("reference to invalid section %d", sym->sectnum); 619 goto bad; 620 } 621 sect = &c->seg.sect[sym->sectnum-1]; 622 outer = sect->sym; 623 if(outer == nil) { 624 werrstr("reference to invalid section %s/%s", sect->segname, sect->name); 625 continue; 626 } 627 if(s->outer != S) { 628 if(s->dupok) 629 continue; 630 diag("%s: duplicate symbol reference: %s in both %s and %s", pn, s->name, s->outer->name, sect->sym->name); 631 errorexit(); 632 } 633 s->type = outer->type | SSUB; 634 s->sub = outer->sub; 635 outer->sub = s; 636 s->outer = outer; 637 s->value = sym->value - sect->addr; 638 if(!(s->cgoexport & CgoExportDynamic)) 639 s->dynimplib = nil; // satisfy dynimport 640 if(outer->type == STEXT) { 641 Prog *p; 642 643 if(s->text != P) 644 diag("%s sym#%d: duplicate definition of %s", pn, i, s->name); 645 // build a TEXT instruction with a unique pc 646 // just to make the rest of the linker happy. 647 // TODO: this is too 6l-specific ? 648 p = prg(); 649 p->as = ATEXT; 650 p->from.type = D_EXTERN; 651 p->from.sym = s; 652 p->textflag = 7; 653 p->to.type = D_CONST; 654 p->link = nil; 655 p->pc = pc++; 656 s->text = p; 657 } 658 sym->sym = s; 659 } 660 661 // Sort outer lists by address, adding to textp. 662 // This keeps textp in increasing address order. 663 for(i=0; i<c->seg.nsect; i++) { 664 sect = &c->seg.sect[i]; 665 if((s = sect->sym) == S) 666 continue; 667 if(s->sub) { 668 s->sub = listsort(s->sub, valuecmp, offsetof(Sym, sub)); 669 670 // assign sizes, now that we know symbols in sorted order. 671 for(s1 = s->sub; s1 != S; s1 = s1->sub) { 672 if(s1->sub) 673 s1->size = s1->sub->value - s1->value; 674 else 675 s1->size = s->value + s->size - s1->value; 676 } 677 } 678 if(s->type == STEXT) { 679 if(etextp) 680 etextp->next = s; 681 else 682 textp = s; 683 etextp = s; 684 for(s1 = s->sub; s1 != S; s1 = s1->sub) { 685 etextp->next = s1; 686 etextp = s1; 687 } 688 } 689 } 690 691 // load relocations 692 for(i=0; i<c->seg.nsect; i++) { 693 sect = &c->seg.sect[i]; 694 if((s = sect->sym) == S) 695 continue; 696 macholoadrel(m, sect); 697 if(sect->rel == nil) 698 continue; 699 r = mal(sect->nreloc*sizeof r[0]); 700 rp = r; 701 rel = sect->rel; 702 for(j=0; j<sect->nreloc; j++, rel++) { 703 if(rel->scattered) { 704 int k; 705 MachoSect *ks; 706 707 if(thechar != '8') { 708 // mach-o only uses scattered relocation on 32-bit platforms 709 diag("unexpected scattered relocation"); 710 continue; 711 } 712 713 // on 386, rewrite scattered 4/1 relocation and some 714 // scattered 2/1 relocation into the pseudo-pc-relative 715 // reference that it is. 716 // assume that the second in the pair is in this section 717 // and use that as the pc-relative base. 718 if(j+1 >= sect->nreloc) { 719 werrstr("unsupported scattered relocation %d", (int)rel->type); 720 goto bad; 721 } 722 if(!(rel+1)->scattered || (rel+1)->type != 1 || 723 (rel->type != 4 && rel->type != 2) || 724 (rel+1)->value < sect->addr || (rel+1)->value >= sect->addr+sect->size) { 725 werrstr("unsupported scattered relocation %d/%d", (int)rel->type, (int)(rel+1)->type); 726 goto bad; 727 } 728 729 rp->siz = rel->length; 730 rp->off = rel->addr; 731 732 // NOTE(rsc): I haven't worked out why (really when) 733 // we should ignore the addend on a 734 // scattered relocation, but it seems that the 735 // common case is we ignore it. 736 // It's likely that this is not strictly correct 737 // and that the math should look something 738 // like the non-scattered case below. 739 rp->add = 0; 740 741 // want to make it pc-relative aka relative to rp->off+4 742 // but the scatter asks for relative to off = (rel+1)->value - sect->addr. 743 // adjust rp->add accordingly. 744 rp->type = D_PCREL; 745 rp->add += (rp->off+4) - ((rel+1)->value - sect->addr); 746 747 // now consider the desired symbol. 748 // find the section where it lives. 749 for(k=0; k<c->seg.nsect; k++) { 750 ks = &c->seg.sect[k]; 751 if(ks->addr <= rel->value && rel->value < ks->addr+ks->size) 752 goto foundk; 753 } 754 werrstr("unsupported scattered relocation: invalid address %#ux", rel->addr); 755 goto bad; 756 foundk: 757 if(ks->sym != S) { 758 rp->sym = ks->sym; 759 rp->add += rel->value - ks->addr; 760 } else if(strcmp(ks->segname, "__IMPORT") == 0 && strcmp(ks->name, "__pointers") == 0) { 761 // handle reference to __IMPORT/__pointers. 762 // how much worse can this get? 763 // why are we supporting 386 on the mac anyway? 764 rp->type = 512 + MACHO_FAKE_GOTPCREL; 765 // figure out which pointer this is a reference to. 766 k = ks->res1 + (rel->value - ks->addr) / 4; 767 // load indirect table for __pointers 768 // fetch symbol number 769 if(dsymtab == nil || k < 0 || k >= dsymtab->nindirectsyms || dsymtab->indir == nil) { 770 werrstr("invalid scattered relocation: indirect symbol reference out of range"); 771 goto bad; 772 } 773 k = dsymtab->indir[k]; 774 if(k < 0 || k >= symtab->nsym) { 775 werrstr("invalid scattered relocation: symbol reference out of range"); 776 goto bad; 777 } 778 rp->sym = symtab->sym[k].sym; 779 } else { 780 werrstr("unsupported scattered relocation: reference to %s/%s", ks->segname, ks->name); 781 goto bad; 782 } 783 rp++; 784 // skip #1 of 2 rel; continue skips #2 of 2. 785 rel++; 786 j++; 787 continue; 788 } 789 790 rp->siz = rel->length; 791 rp->type = 512 + (rel->type<<1) + rel->pcrel; 792 rp->off = rel->addr; 793 794 // Handle X86_64_RELOC_SIGNED referencing a section (rel->extrn == 0). 795 if (thechar == '6' && rel->extrn == 0 && rel->type == 1) { 796 // Calculate the addend as the offset into the section. 797 // 798 // The rip-relative offset stored in the object file is encoded 799 // as follows: 800 // 801 // movsd 0x00000360(%rip),%xmm0 802 // 803 // To get the absolute address of the value this rip-relative address is pointing 804 // to, we must add the address of the next instruction to it. This is done by 805 // taking the address of the relocation and adding 4 to it (since the rip-relative 806 // offset can at most be 32 bits long). To calculate the offset into the section the 807 // relocation is referencing, we subtract the vaddr of the start of the referenced 808 // section found in the original object file. 809 // 810 // [For future reference, see Darwin's /usr/include/mach-o/x86_64/reloc.h] 811 secaddr = c->seg.sect[rel->symnum-1].addr; 812 rp->add = (int32)e->e32(s->p+rp->off) + rp->off + 4 - secaddr; 813 } else 814 rp->add = (int32)e->e32(s->p+rp->off); 815 816 // For i386 Mach-O PC-relative, the addend is written such that 817 // it *is* the PC being subtracted. Use that to make 818 // it match our version of PC-relative. 819 if(rel->pcrel && thechar == '8') 820 rp->add += rp->off+rp->siz; 821 if(!rel->extrn) { 822 if(rel->symnum < 1 || rel->symnum > c->seg.nsect) { 823 werrstr("invalid relocation: section reference out of range %d vs %d", rel->symnum, c->seg.nsect); 824 goto bad; 825 } 826 rp->sym = c->seg.sect[rel->symnum-1].sym; 827 if(rp->sym == nil) { 828 werrstr("invalid relocation: %s", c->seg.sect[rel->symnum-1].name); 829 goto bad; 830 } 831 // References to symbols in other sections 832 // include that information in the addend. 833 // We only care about the delta from the 834 // section base. 835 if(thechar == '8') 836 rp->add -= c->seg.sect[rel->symnum-1].addr; 837 } else { 838 if(rel->symnum >= symtab->nsym) { 839 werrstr("invalid relocation: symbol reference out of range"); 840 goto bad; 841 } 842 rp->sym = symtab->sym[rel->symnum].sym; 843 } 844 rp++; 845 } 846 qsort(r, rp - r, sizeof r[0], rbyoff); 847 s->r = r; 848 s->nr = rp - r; 849 } 850 return; 851 852 bad: 853 diag("%s: malformed mach-o file: %r", pn); 854 }