1 //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the MachOObjectFile class, which binds the MachOObject 11 // class to the generic ObjectFile wrapper. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/ADT/Triple.h" 16 #include "llvm/Object/MachO.h" 17 #include "llvm/Object/MachOFormat.h" 18 #include "llvm/Support/Format.h" 19 #include "llvm/Support/MemoryBuffer.h" 20 21 #include <cctype> 22 #include <cstring> 23 #include <limits> 24 25 using namespace llvm; 26 using namespace object; 27 28 namespace llvm { 29 namespace object { 30 31 MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, 32 error_code &ec) 33 : ObjectFile(Binary::ID_MachO, Object, ec), 34 MachOObj(MOO), 35 RegisteredStringTable(std::numeric_limits<uint32_t>::max()) { 36 DataRefImpl DRI; 37 moveToNextSection(DRI); 38 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; 39 while (DRI.d.a < LoadCommandCount) { 40 Sections.push_back(DRI); 41 DRI.d.b++; 42 moveToNextSection(DRI); 43 } 44 } 45 46 47 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { 48 error_code ec; 49 std::string Err; 50 MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err); 51 if (!MachOObj) 52 return NULL; 53 return new MachOObjectFile(Buffer, MachOObj, ec); 54 } 55 56 /*===-- Symbols -----------------------------------------------------------===*/ 57 58 void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { 59 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; 60 while (DRI.d.a < LoadCommandCount) { 61 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 62 if (LCI.Command.Type == macho::LCT_Symtab) { 63 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd; 64 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); 65 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries) 66 return; 67 } 68 69 DRI.d.a++; 70 DRI.d.b = 0; 71 } 72 } 73 74 void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI, 75 InMemoryStruct<macho::SymbolTableEntry> &Res) const { 76 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd; 77 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 78 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); 79 80 if (RegisteredStringTable != DRI.d.a) { 81 MachOObj->RegisterStringTable(*SymtabLoadCmd); 82 RegisteredStringTable = DRI.d.a; 83 } 84 85 MachOObj->ReadSymbolTableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b, 86 Res); 87 } 88 89 void MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI, 90 InMemoryStruct<macho::Symbol64TableEntry> &Res) const { 91 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd; 92 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 93 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); 94 95 if (RegisteredStringTable != DRI.d.a) { 96 MachOObj->RegisterStringTable(*SymtabLoadCmd); 97 RegisteredStringTable = DRI.d.a; 98 } 99 100 MachOObj->ReadSymbol64TableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b, 101 Res); 102 } 103 104 105 error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI, 106 SymbolRef &Result) const { 107 DRI.d.b++; 108 moveToNextSymbol(DRI); 109 Result = SymbolRef(DRI, this); 110 return object_error::success; 111 } 112 113 error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, 114 StringRef &Result) const { 115 if (MachOObj->is64Bit()) { 116 InMemoryStruct<macho::Symbol64TableEntry> Entry; 117 getSymbol64TableEntry(DRI, Entry); 118 Result = MachOObj->getStringAtIndex(Entry->StringIndex); 119 } else { 120 InMemoryStruct<macho::SymbolTableEntry> Entry; 121 getSymbolTableEntry(DRI, Entry); 122 Result = MachOObj->getStringAtIndex(Entry->StringIndex); 123 } 124 return object_error::success; 125 } 126 127 error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI, 128 uint64_t &Result) const { 129 if (MachOObj->is64Bit()) { 130 InMemoryStruct<macho::Symbol64TableEntry> Entry; 131 getSymbol64TableEntry(DRI, Entry); 132 Result = Entry->Value; 133 if (Entry->SectionIndex) { 134 InMemoryStruct<macho::Section64> Section; 135 getSection64(Sections[Entry->SectionIndex-1], Section); 136 Result += Section->Offset - Section->Address; 137 } 138 } else { 139 InMemoryStruct<macho::SymbolTableEntry> Entry; 140 getSymbolTableEntry(DRI, Entry); 141 Result = Entry->Value; 142 if (Entry->SectionIndex) { 143 InMemoryStruct<macho::Section> Section; 144 getSection(Sections[Entry->SectionIndex-1], Section); 145 Result += Section->Offset - Section->Address; 146 } 147 } 148 149 return object_error::success; 150 } 151 152 error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI, 153 uint64_t &Result) const { 154 if (MachOObj->is64Bit()) { 155 InMemoryStruct<macho::Symbol64TableEntry> Entry; 156 getSymbol64TableEntry(DRI, Entry); 157 Result = Entry->Value; 158 } else { 159 InMemoryStruct<macho::SymbolTableEntry> Entry; 160 getSymbolTableEntry(DRI, Entry); 161 Result = Entry->Value; 162 } 163 return object_error::success; 164 } 165 166 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, 167 uint64_t &Result) const { 168 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; 169 uint64_t BeginOffset; 170 uint64_t EndOffset = 0; 171 uint8_t SectionIndex; 172 if (MachOObj->is64Bit()) { 173 InMemoryStruct<macho::Symbol64TableEntry> Entry; 174 getSymbol64TableEntry(DRI, Entry); 175 BeginOffset = Entry->Value; 176 SectionIndex = Entry->SectionIndex; 177 if (!SectionIndex) { 178 Result = UnknownAddressOrSize; 179 return object_error::success; 180 } 181 // Unfortunately symbols are unsorted so we need to touch all 182 // symbols from load command 183 DRI.d.b = 0; 184 uint32_t Command = DRI.d.a; 185 while (Command == DRI.d.a) { 186 moveToNextSymbol(DRI); 187 if (DRI.d.a < LoadCommandCount) { 188 getSymbol64TableEntry(DRI, Entry); 189 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset) 190 if (!EndOffset || Entry->Value < EndOffset) 191 EndOffset = Entry->Value; 192 } 193 DRI.d.b++; 194 } 195 } else { 196 InMemoryStruct<macho::SymbolTableEntry> Entry; 197 getSymbolTableEntry(DRI, Entry); 198 BeginOffset = Entry->Value; 199 SectionIndex = Entry->SectionIndex; 200 if (!SectionIndex) { 201 Result = UnknownAddressOrSize; 202 return object_error::success; 203 } 204 // Unfortunately symbols are unsorted so we need to touch all 205 // symbols from load command 206 DRI.d.b = 0; 207 uint32_t Command = DRI.d.a; 208 while (Command == DRI.d.a) { 209 moveToNextSymbol(DRI); 210 if (DRI.d.a < LoadCommandCount) { 211 getSymbolTableEntry(DRI, Entry); 212 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset) 213 if (!EndOffset || Entry->Value < EndOffset) 214 EndOffset = Entry->Value; 215 } 216 DRI.d.b++; 217 } 218 } 219 if (!EndOffset) { 220 uint64_t Size; 221 getSectionSize(Sections[SectionIndex-1], Size); 222 getSectionAddress(Sections[SectionIndex-1], EndOffset); 223 EndOffset += Size; 224 } 225 Result = EndOffset - BeginOffset; 226 return object_error::success; 227 } 228 229 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI, 230 char &Result) const { 231 uint8_t Type, Flags; 232 if (MachOObj->is64Bit()) { 233 InMemoryStruct<macho::Symbol64TableEntry> Entry; 234 getSymbol64TableEntry(DRI, Entry); 235 Type = Entry->Type; 236 Flags = Entry->Flags; 237 } else { 238 InMemoryStruct<macho::SymbolTableEntry> Entry; 239 getSymbolTableEntry(DRI, Entry); 240 Type = Entry->Type; 241 Flags = Entry->Flags; 242 } 243 244 char Char; 245 switch (Type & macho::STF_TypeMask) { 246 case macho::STT_Undefined: 247 Char = 'u'; 248 break; 249 case macho::STT_Absolute: 250 case macho::STT_Section: 251 Char = 's'; 252 break; 253 default: 254 Char = '?'; 255 break; 256 } 257 258 if (Flags & (macho::STF_External | macho::STF_PrivateExtern)) 259 Char = toupper(Char); 260 Result = Char; 261 return object_error::success; 262 } 263 264 error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, 265 uint32_t &Result) const { 266 uint16_t MachOFlags; 267 uint8_t MachOType; 268 if (MachOObj->is64Bit()) { 269 InMemoryStruct<macho::Symbol64TableEntry> Entry; 270 getSymbol64TableEntry(DRI, Entry); 271 MachOFlags = Entry->Flags; 272 MachOType = Entry->Type; 273 } else { 274 InMemoryStruct<macho::SymbolTableEntry> Entry; 275 getSymbolTableEntry(DRI, Entry); 276 MachOFlags = Entry->Flags; 277 MachOType = Entry->Type; 278 } 279 280 // TODO: Correctly set SF_ThreadLocal and SF_Common. 281 Result = SymbolRef::SF_None; 282 283 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) 284 Result |= SymbolRef::SF_Undefined; 285 286 if (MachOFlags & macho::STF_StabsEntryMask) 287 Result |= SymbolRef::SF_FormatSpecific; 288 289 if (MachOType & MachO::NlistMaskExternal) 290 Result |= SymbolRef::SF_Global; 291 292 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef)) 293 Result |= SymbolRef::SF_Weak; 294 295 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute) 296 Result |= SymbolRef::SF_Absolute; 297 298 return object_error::success; 299 } 300 301 error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, 302 section_iterator &Res) const { 303 uint8_t index; 304 if (MachOObj->is64Bit()) { 305 InMemoryStruct<macho::Symbol64TableEntry> Entry; 306 getSymbol64TableEntry(Symb, Entry); 307 index = Entry->SectionIndex; 308 } else { 309 InMemoryStruct<macho::SymbolTableEntry> Entry; 310 getSymbolTableEntry(Symb, Entry); 311 index = Entry->SectionIndex; 312 } 313 314 if (index == 0) 315 Res = end_sections(); 316 else 317 Res = section_iterator(SectionRef(Sections[index-1], this)); 318 319 return object_error::success; 320 } 321 322 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, 323 SymbolRef::Type &Res) const { 324 uint8_t n_type; 325 if (MachOObj->is64Bit()) { 326 InMemoryStruct<macho::Symbol64TableEntry> Entry; 327 getSymbol64TableEntry(Symb, Entry); 328 n_type = Entry->Type; 329 } else { 330 InMemoryStruct<macho::SymbolTableEntry> Entry; 331 getSymbolTableEntry(Symb, Entry); 332 n_type = Entry->Type; 333 } 334 Res = SymbolRef::ST_Other; 335 336 // If this is a STAB debugging symbol, we can do nothing more. 337 if (n_type & MachO::NlistMaskStab) { 338 Res = SymbolRef::ST_Debug; 339 return object_error::success; 340 } 341 342 switch (n_type & MachO::NlistMaskType) { 343 case MachO::NListTypeUndefined : 344 Res = SymbolRef::ST_Unknown; 345 break; 346 case MachO::NListTypeSection : 347 Res = SymbolRef::ST_Function; 348 break; 349 } 350 return object_error::success; 351 } 352 353 354 symbol_iterator MachOObjectFile::begin_symbols() const { 355 // DRI.d.a = segment number; DRI.d.b = symbol index. 356 DataRefImpl DRI; 357 moveToNextSymbol(DRI); 358 return symbol_iterator(SymbolRef(DRI, this)); 359 } 360 361 symbol_iterator MachOObjectFile::end_symbols() const { 362 DataRefImpl DRI; 363 DRI.d.a = MachOObj->getHeader().NumLoadCommands; 364 return symbol_iterator(SymbolRef(DRI, this)); 365 } 366 367 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const { 368 // TODO: implement 369 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); 370 } 371 372 symbol_iterator MachOObjectFile::end_dynamic_symbols() const { 373 // TODO: implement 374 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); 375 } 376 377 library_iterator MachOObjectFile::begin_libraries_needed() const { 378 // TODO: implement 379 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 380 } 381 382 library_iterator MachOObjectFile::end_libraries_needed() const { 383 // TODO: implement 384 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 385 } 386 387 StringRef MachOObjectFile::getLoadName() const { 388 // TODO: Implement 389 report_fatal_error("get_load_name() unimplemented in MachOObjectFile"); 390 } 391 392 /*===-- Sections ----------------------------------------------------------===*/ 393 394 void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { 395 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; 396 while (DRI.d.a < LoadCommandCount) { 397 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 398 if (LCI.Command.Type == macho::LCT_Segment) { 399 InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd; 400 MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd); 401 if (DRI.d.b < SegmentLoadCmd->NumSections) 402 return; 403 } else if (LCI.Command.Type == macho::LCT_Segment64) { 404 InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd; 405 MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd); 406 if (DRI.d.b < Segment64LoadCmd->NumSections) 407 return; 408 } 409 410 DRI.d.a++; 411 DRI.d.b = 0; 412 } 413 } 414 415 error_code MachOObjectFile::getSectionNext(DataRefImpl DRI, 416 SectionRef &Result) const { 417 DRI.d.b++; 418 moveToNextSection(DRI); 419 Result = SectionRef(DRI, this); 420 return object_error::success; 421 } 422 423 void 424 MachOObjectFile::getSection(DataRefImpl DRI, 425 InMemoryStruct<macho::Section> &Res) const { 426 InMemoryStruct<macho::SegmentLoadCommand> SLC; 427 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 428 MachOObj->ReadSegmentLoadCommand(LCI, SLC); 429 MachOObj->ReadSection(LCI, DRI.d.b, Res); 430 } 431 432 std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { 433 SectionList::const_iterator loc = 434 std::find(Sections.begin(), Sections.end(), Sec); 435 assert(loc != Sections.end() && "Sec is not a valid section!"); 436 return std::distance(Sections.begin(), loc); 437 } 438 439 void 440 MachOObjectFile::getSection64(DataRefImpl DRI, 441 InMemoryStruct<macho::Section64> &Res) const { 442 InMemoryStruct<macho::Segment64LoadCommand> SLC; 443 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 444 MachOObj->ReadSegment64LoadCommand(LCI, SLC); 445 MachOObj->ReadSection64(LCI, DRI.d.b, Res); 446 } 447 448 static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) { 449 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 450 if (LCI.Command.Type == macho::LCT_Segment64) 451 return true; 452 assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type."); 453 return false; 454 } 455 456 error_code MachOObjectFile::getSectionName(DataRefImpl DRI, 457 StringRef &Result) const { 458 // FIXME: thread safety. 459 static char result[34]; 460 if (is64BitLoadCommand(MachOObj, DRI)) { 461 InMemoryStruct<macho::Segment64LoadCommand> SLC; 462 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 463 MachOObj->ReadSegment64LoadCommand(LCI, SLC); 464 InMemoryStruct<macho::Section64> Sect; 465 MachOObj->ReadSection64(LCI, DRI.d.b, Sect); 466 467 strcpy(result, Sect->SegmentName); 468 strcat(result, ","); 469 strcat(result, Sect->Name); 470 } else { 471 InMemoryStruct<macho::SegmentLoadCommand> SLC; 472 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 473 MachOObj->ReadSegmentLoadCommand(LCI, SLC); 474 InMemoryStruct<macho::Section> Sect; 475 MachOObj->ReadSection(LCI, DRI.d.b, Sect); 476 477 strcpy(result, Sect->SegmentName); 478 strcat(result, ","); 479 strcat(result, Sect->Name); 480 } 481 Result = StringRef(result); 482 return object_error::success; 483 } 484 485 error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, 486 uint64_t &Result) const { 487 if (is64BitLoadCommand(MachOObj, DRI)) { 488 InMemoryStruct<macho::Section64> Sect; 489 getSection64(DRI, Sect); 490 Result = Sect->Address; 491 } else { 492 InMemoryStruct<macho::Section> Sect; 493 getSection(DRI, Sect); 494 Result = Sect->Address; 495 } 496 return object_error::success; 497 } 498 499 error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, 500 uint64_t &Result) const { 501 if (is64BitLoadCommand(MachOObj, DRI)) { 502 InMemoryStruct<macho::Section64> Sect; 503 getSection64(DRI, Sect); 504 Result = Sect->Size; 505 } else { 506 InMemoryStruct<macho::Section> Sect; 507 getSection(DRI, Sect); 508 Result = Sect->Size; 509 } 510 return object_error::success; 511 } 512 513 error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, 514 StringRef &Result) const { 515 if (is64BitLoadCommand(MachOObj, DRI)) { 516 InMemoryStruct<macho::Section64> Sect; 517 getSection64(DRI, Sect); 518 Result = MachOObj->getData(Sect->Offset, Sect->Size); 519 } else { 520 InMemoryStruct<macho::Section> Sect; 521 getSection(DRI, Sect); 522 Result = MachOObj->getData(Sect->Offset, Sect->Size); 523 } 524 return object_error::success; 525 } 526 527 error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, 528 uint64_t &Result) const { 529 if (is64BitLoadCommand(MachOObj, DRI)) { 530 InMemoryStruct<macho::Section64> Sect; 531 getSection64(DRI, Sect); 532 Result = uint64_t(1) << Sect->Align; 533 } else { 534 InMemoryStruct<macho::Section> Sect; 535 getSection(DRI, Sect); 536 Result = uint64_t(1) << Sect->Align; 537 } 538 return object_error::success; 539 } 540 541 error_code MachOObjectFile::isSectionText(DataRefImpl DRI, 542 bool &Result) const { 543 if (is64BitLoadCommand(MachOObj, DRI)) { 544 InMemoryStruct<macho::Section64> Sect; 545 getSection64(DRI, Sect); 546 Result = !strcmp(Sect->Name, "__text"); 547 } else { 548 InMemoryStruct<macho::Section> Sect; 549 getSection(DRI, Sect); 550 Result = !strcmp(Sect->Name, "__text"); 551 } 552 return object_error::success; 553 } 554 555 error_code MachOObjectFile::isSectionData(DataRefImpl DRI, 556 bool &Result) const { 557 // FIXME: Unimplemented. 558 Result = false; 559 return object_error::success; 560 } 561 562 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, 563 bool &Result) const { 564 // FIXME: Unimplemented. 565 Result = false; 566 return object_error::success; 567 } 568 569 error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, 570 DataRefImpl Symb, 571 bool &Result) const { 572 SymbolRef::Type ST; 573 getSymbolType(Symb, ST); 574 if (ST == SymbolRef::ST_Unknown) { 575 Result = false; 576 return object_error::success; 577 } 578 579 uint64_t SectBegin, SectEnd; 580 getSectionAddress(Sec, SectBegin); 581 getSectionSize(Sec, SectEnd); 582 SectEnd += SectBegin; 583 584 if (MachOObj->is64Bit()) { 585 InMemoryStruct<macho::Symbol64TableEntry> Entry; 586 getSymbol64TableEntry(Symb, Entry); 587 uint64_t SymAddr= Entry->Value; 588 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 589 } else { 590 InMemoryStruct<macho::SymbolTableEntry> Entry; 591 getSymbolTableEntry(Symb, Entry); 592 uint64_t SymAddr= Entry->Value; 593 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 594 } 595 596 return object_error::success; 597 } 598 599 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { 600 DataRefImpl ret; 601 ret.d.b = getSectionIndex(Sec); 602 return relocation_iterator(RelocationRef(ret, this)); 603 } 604 relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { 605 uint32_t last_reloc; 606 if (is64BitLoadCommand(MachOObj, Sec)) { 607 InMemoryStruct<macho::Section64> Sect; 608 getSection64(Sec, Sect); 609 last_reloc = Sect->NumRelocationTableEntries; 610 } else { 611 InMemoryStruct<macho::Section> Sect; 612 getSection(Sec, Sect); 613 last_reloc = Sect->NumRelocationTableEntries; 614 } 615 DataRefImpl ret; 616 ret.d.a = last_reloc; 617 ret.d.b = getSectionIndex(Sec); 618 return relocation_iterator(RelocationRef(ret, this)); 619 } 620 621 section_iterator MachOObjectFile::begin_sections() const { 622 DataRefImpl DRI; 623 moveToNextSection(DRI); 624 return section_iterator(SectionRef(DRI, this)); 625 } 626 627 section_iterator MachOObjectFile::end_sections() const { 628 DataRefImpl DRI; 629 DRI.d.a = MachOObj->getHeader().NumLoadCommands; 630 return section_iterator(SectionRef(DRI, this)); 631 } 632 633 /*===-- Relocations -------------------------------------------------------===*/ 634 635 void MachOObjectFile:: 636 getRelocation(DataRefImpl Rel, 637 InMemoryStruct<macho::RelocationEntry> &Res) const { 638 uint32_t relOffset; 639 if (MachOObj->is64Bit()) { 640 InMemoryStruct<macho::Section64> Sect; 641 getSection64(Sections[Rel.d.b], Sect); 642 relOffset = Sect->RelocationTableOffset; 643 } else { 644 InMemoryStruct<macho::Section> Sect; 645 getSection(Sections[Rel.d.b], Sect); 646 relOffset = Sect->RelocationTableOffset; 647 } 648 MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res); 649 } 650 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, 651 RelocationRef &Res) const { 652 ++Rel.d.a; 653 Res = RelocationRef(Rel, this); 654 return object_error::success; 655 } 656 error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, 657 uint64_t &Res) const { 658 const uint8_t* sectAddress = 0; 659 if (MachOObj->is64Bit()) { 660 InMemoryStruct<macho::Section64> Sect; 661 getSection64(Sections[Rel.d.b], Sect); 662 sectAddress += Sect->Address; 663 } else { 664 InMemoryStruct<macho::Section> Sect; 665 getSection(Sections[Rel.d.b], Sect); 666 sectAddress += Sect->Address; 667 } 668 InMemoryStruct<macho::RelocationEntry> RE; 669 getRelocation(Rel, RE); 670 671 unsigned Arch = getArch(); 672 bool isScattered = (Arch != Triple::x86_64) && 673 (RE->Word0 & macho::RF_Scattered); 674 uint64_t RelAddr = 0; 675 if (isScattered) 676 RelAddr = RE->Word0 & 0xFFFFFF; 677 else 678 RelAddr = RE->Word0; 679 680 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr); 681 return object_error::success; 682 } 683 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, 684 uint64_t &Res) const { 685 InMemoryStruct<macho::RelocationEntry> RE; 686 getRelocation(Rel, RE); 687 688 unsigned Arch = getArch(); 689 bool isScattered = (Arch != Triple::x86_64) && 690 (RE->Word0 & macho::RF_Scattered); 691 if (isScattered) 692 Res = RE->Word0 & 0xFFFFFF; 693 else 694 Res = RE->Word0; 695 return object_error::success; 696 } 697 error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, 698 SymbolRef &Res) const { 699 InMemoryStruct<macho::RelocationEntry> RE; 700 getRelocation(Rel, RE); 701 uint32_t SymbolIdx = RE->Word1 & 0xffffff; 702 bool isExtern = (RE->Word1 >> 27) & 1; 703 704 DataRefImpl Sym; 705 moveToNextSymbol(Sym); 706 if (isExtern) { 707 for (unsigned i = 0; i < SymbolIdx; i++) { 708 Sym.d.b++; 709 moveToNextSymbol(Sym); 710 assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands && 711 "Relocation symbol index out of range!"); 712 } 713 } 714 Res = SymbolRef(Sym, this); 715 return object_error::success; 716 } 717 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, 718 uint64_t &Res) const { 719 InMemoryStruct<macho::RelocationEntry> RE; 720 getRelocation(Rel, RE); 721 Res = RE->Word0; 722 Res <<= 32; 723 Res |= RE->Word1; 724 return object_error::success; 725 } 726 error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, 727 SmallVectorImpl<char> &Result) const { 728 // TODO: Support scattered relocations. 729 StringRef res; 730 InMemoryStruct<macho::RelocationEntry> RE; 731 getRelocation(Rel, RE); 732 733 unsigned Arch = getArch(); 734 bool isScattered = (Arch != Triple::x86_64) && 735 (RE->Word0 & macho::RF_Scattered); 736 737 unsigned r_type; 738 if (isScattered) 739 r_type = (RE->Word0 >> 24) & 0xF; 740 else 741 r_type = (RE->Word1 >> 28) & 0xF; 742 743 switch (Arch) { 744 case Triple::x86: { 745 const char* Table[] = { 746 "GENERIC_RELOC_VANILLA", 747 "GENERIC_RELOC_PAIR", 748 "GENERIC_RELOC_SECTDIFF", 749 "GENERIC_RELOC_PB_LA_PTR", 750 "GENERIC_RELOC_LOCAL_SECTDIFF", 751 "GENERIC_RELOC_TLV" }; 752 753 if (r_type > 6) 754 res = "Unknown"; 755 else 756 res = Table[r_type]; 757 break; 758 } 759 case Triple::x86_64: { 760 const char* Table[] = { 761 "X86_64_RELOC_UNSIGNED", 762 "X86_64_RELOC_SIGNED", 763 "X86_64_RELOC_BRANCH", 764 "X86_64_RELOC_GOT_LOAD", 765 "X86_64_RELOC_GOT", 766 "X86_64_RELOC_SUBTRACTOR", 767 "X86_64_RELOC_SIGNED_1", 768 "X86_64_RELOC_SIGNED_2", 769 "X86_64_RELOC_SIGNED_4", 770 "X86_64_RELOC_TLV" }; 771 772 if (r_type > 9) 773 res = "Unknown"; 774 else 775 res = Table[r_type]; 776 break; 777 } 778 case Triple::arm: { 779 const char* Table[] = { 780 "ARM_RELOC_VANILLA", 781 "ARM_RELOC_PAIR", 782 "ARM_RELOC_SECTDIFF", 783 "ARM_RELOC_LOCAL_SECTDIFF", 784 "ARM_RELOC_PB_LA_PTR", 785 "ARM_RELOC_BR24", 786 "ARM_THUMB_RELOC_BR22", 787 "ARM_THUMB_32BIT_BRANCH", 788 "ARM_RELOC_HALF", 789 "ARM_RELOC_HALF_SECTDIFF" }; 790 791 if (r_type > 9) 792 res = "Unknown"; 793 else 794 res = Table[r_type]; 795 break; 796 } 797 case Triple::ppc: { 798 const char* Table[] = { 799 "PPC_RELOC_VANILLA", 800 "PPC_RELOC_PAIR", 801 "PPC_RELOC_BR14", 802 "PPC_RELOC_BR24", 803 "PPC_RELOC_HI16", 804 "PPC_RELOC_LO16", 805 "PPC_RELOC_HA16", 806 "PPC_RELOC_LO14", 807 "PPC_RELOC_SECTDIFF", 808 "PPC_RELOC_PB_LA_PTR", 809 "PPC_RELOC_HI16_SECTDIFF", 810 "PPC_RELOC_LO16_SECTDIFF", 811 "PPC_RELOC_HA16_SECTDIFF", 812 "PPC_RELOC_JBSR", 813 "PPC_RELOC_LO14_SECTDIFF", 814 "PPC_RELOC_LOCAL_SECTDIFF" }; 815 816 res = Table[r_type]; 817 break; 818 } 819 case Triple::UnknownArch: 820 res = "Unknown"; 821 break; 822 } 823 Result.append(res.begin(), res.end()); 824 return object_error::success; 825 } 826 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, 827 int64_t &Res) const { 828 InMemoryStruct<macho::RelocationEntry> RE; 829 getRelocation(Rel, RE); 830 bool isExtern = (RE->Word1 >> 27) & 1; 831 Res = 0; 832 if (!isExtern) { 833 const uint8_t* sectAddress = base(); 834 if (MachOObj->is64Bit()) { 835 InMemoryStruct<macho::Section64> Sect; 836 getSection64(Sections[Rel.d.b], Sect); 837 sectAddress += Sect->Offset; 838 } else { 839 InMemoryStruct<macho::Section> Sect; 840 getSection(Sections[Rel.d.b], Sect); 841 sectAddress += Sect->Offset; 842 } 843 Res = reinterpret_cast<uintptr_t>(sectAddress); 844 } 845 return object_error::success; 846 } 847 848 // Helper to advance a section or symbol iterator multiple increments at a time. 849 template<class T> 850 error_code advance(T &it, size_t Val) { 851 error_code ec; 852 while (Val--) { 853 it.increment(ec); 854 } 855 return ec; 856 } 857 858 template<class T> 859 void advanceTo(T &it, size_t Val) { 860 if (error_code ec = advance(it, Val)) 861 report_fatal_error(ec.message()); 862 } 863 864 void MachOObjectFile::printRelocationTargetName( 865 InMemoryStruct<macho::RelocationEntry>& RE, 866 raw_string_ostream &fmt) const { 867 unsigned Arch = getArch(); 868 bool isScattered = (Arch != Triple::x86_64) && 869 (RE->Word0 & macho::RF_Scattered); 870 871 // Target of a scattered relocation is an address. In the interest of 872 // generating pretty output, scan through the symbol table looking for a 873 // symbol that aligns with that address. If we find one, print it. 874 // Otherwise, we just print the hex address of the target. 875 if (isScattered) { 876 uint32_t Val = RE->Word1; 877 878 error_code ec; 879 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE; 880 SI.increment(ec)) { 881 if (ec) report_fatal_error(ec.message()); 882 883 uint64_t Addr; 884 StringRef Name; 885 886 if ((ec = SI->getAddress(Addr))) 887 report_fatal_error(ec.message()); 888 if (Addr != Val) continue; 889 if ((ec = SI->getName(Name))) 890 report_fatal_error(ec.message()); 891 fmt << Name; 892 return; 893 } 894 895 // If we couldn't find a symbol that this relocation refers to, try 896 // to find a section beginning instead. 897 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE; 898 SI.increment(ec)) { 899 if (ec) report_fatal_error(ec.message()); 900 901 uint64_t Addr; 902 StringRef Name; 903 904 if ((ec = SI->getAddress(Addr))) 905 report_fatal_error(ec.message()); 906 if (Addr != Val) continue; 907 if ((ec = SI->getName(Name))) 908 report_fatal_error(ec.message()); 909 fmt << Name; 910 return; 911 } 912 913 fmt << format("0x%x", Val); 914 return; 915 } 916 917 StringRef S; 918 bool isExtern = (RE->Word1 >> 27) & 1; 919 uint32_t Val = RE->Word1 & 0xFFFFFF; 920 921 if (isExtern) { 922 symbol_iterator SI = begin_symbols(); 923 advanceTo(SI, Val); 924 SI->getName(S); 925 } else { 926 section_iterator SI = begin_sections(); 927 advanceTo(SI, Val); 928 SI->getName(S); 929 } 930 931 fmt << S; 932 } 933 934 error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel, 935 SmallVectorImpl<char> &Result) const { 936 InMemoryStruct<macho::RelocationEntry> RE; 937 getRelocation(Rel, RE); 938 939 unsigned Arch = getArch(); 940 bool isScattered = (Arch != Triple::x86_64) && 941 (RE->Word0 & macho::RF_Scattered); 942 943 std::string fmtbuf; 944 raw_string_ostream fmt(fmtbuf); 945 946 unsigned Type; 947 if (isScattered) 948 Type = (RE->Word0 >> 24) & 0xF; 949 else 950 Type = (RE->Word1 >> 28) & 0xF; 951 952 bool isPCRel; 953 if (isScattered) 954 isPCRel = ((RE->Word0 >> 30) & 1); 955 else 956 isPCRel = ((RE->Word1 >> 24) & 1); 957 958 // Determine any addends that should be displayed with the relocation. 959 // These require decoding the relocation type, which is triple-specific. 960 961 // X86_64 has entirely custom relocation types. 962 if (Arch == Triple::x86_64) { 963 bool isPCRel = ((RE->Word1 >> 24) & 1); 964 965 switch (Type) { 966 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD 967 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT 968 printRelocationTargetName(RE, fmt); 969 fmt << "@GOT"; 970 if (isPCRel) fmt << "PCREL"; 971 break; 972 } 973 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR 974 InMemoryStruct<macho::RelocationEntry> RENext; 975 DataRefImpl RelNext = Rel; 976 RelNext.d.a++; 977 getRelocation(RelNext, RENext); 978 979 // X86_64_SUBTRACTOR must be followed by a relocation of type 980 // X86_64_RELOC_UNSIGNED. 981 // NOTE: Scattered relocations don't exist on x86_64. 982 unsigned RType = (RENext->Word1 >> 28) & 0xF; 983 if (RType != 0) 984 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " 985 "X86_64_RELOC_SUBTRACTOR."); 986 987 // The X86_64_RELOC_UNSIGNED contains the minuend symbol, 988 // X86_64_SUBTRACTOR contains to the subtrahend. 989 printRelocationTargetName(RENext, fmt); 990 fmt << "-"; 991 printRelocationTargetName(RE, fmt); 992 } 993 case macho::RIT_X86_64_TLV: 994 printRelocationTargetName(RE, fmt); 995 fmt << "@TLV"; 996 if (isPCRel) fmt << "P"; 997 break; 998 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1 999 printRelocationTargetName(RE, fmt); 1000 fmt << "-1"; 1001 break; 1002 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2 1003 printRelocationTargetName(RE, fmt); 1004 fmt << "-2"; 1005 break; 1006 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4 1007 printRelocationTargetName(RE, fmt); 1008 fmt << "-4"; 1009 break; 1010 default: 1011 printRelocationTargetName(RE, fmt); 1012 break; 1013 } 1014 // X86 and ARM share some relocation types in common. 1015 } else if (Arch == Triple::x86 || Arch == Triple::arm) { 1016 // Generic relocation types... 1017 switch (Type) { 1018 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info 1019 return object_error::success; 1020 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF 1021 InMemoryStruct<macho::RelocationEntry> RENext; 1022 DataRefImpl RelNext = Rel; 1023 RelNext.d.a++; 1024 getRelocation(RelNext, RENext); 1025 1026 // X86 sect diff's must be followed by a relocation of type 1027 // GENERIC_RELOC_PAIR. 1028 bool isNextScattered = (Arch != Triple::x86_64) && 1029 (RENext->Word0 & macho::RF_Scattered); 1030 unsigned RType; 1031 if (isNextScattered) 1032 RType = (RENext->Word0 >> 24) & 0xF; 1033 else 1034 RType = (RENext->Word1 >> 28) & 0xF; 1035 if (RType != 1) 1036 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 1037 "GENERIC_RELOC_SECTDIFF."); 1038 1039 printRelocationTargetName(RE, fmt); 1040 fmt << "-"; 1041 printRelocationTargetName(RENext, fmt); 1042 break; 1043 } 1044 } 1045 1046 if (Arch == Triple::x86) { 1047 // All X86 relocations that need special printing were already 1048 // handled in the generic code. 1049 switch (Type) { 1050 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF 1051 InMemoryStruct<macho::RelocationEntry> RENext; 1052 DataRefImpl RelNext = Rel; 1053 RelNext.d.a++; 1054 getRelocation(RelNext, RENext); 1055 1056 // X86 sect diff's must be followed by a relocation of type 1057 // GENERIC_RELOC_PAIR. 1058 bool isNextScattered = (Arch != Triple::x86_64) && 1059 (RENext->Word0 & macho::RF_Scattered); 1060 unsigned RType; 1061 if (isNextScattered) 1062 RType = (RENext->Word0 >> 24) & 0xF; 1063 else 1064 RType = (RENext->Word1 >> 28) & 0xF; 1065 if (RType != 1) 1066 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 1067 "GENERIC_RELOC_LOCAL_SECTDIFF."); 1068 1069 printRelocationTargetName(RE, fmt); 1070 fmt << "-"; 1071 printRelocationTargetName(RENext, fmt); 1072 break; 1073 } 1074 case macho::RIT_Generic_TLV: { 1075 printRelocationTargetName(RE, fmt); 1076 fmt << "@TLV"; 1077 if (isPCRel) fmt << "P"; 1078 break; 1079 } 1080 default: 1081 printRelocationTargetName(RE, fmt); 1082 } 1083 } else { // ARM-specific relocations 1084 switch (Type) { 1085 case macho::RIT_ARM_Half: // ARM_RELOC_HALF 1086 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF 1087 // Half relocations steal a bit from the length field to encode 1088 // whether this is an upper16 or a lower16 relocation. 1089 bool isUpper; 1090 if (isScattered) 1091 isUpper = (RE->Word0 >> 28) & 1; 1092 else 1093 isUpper = (RE->Word1 >> 25) & 1; 1094 1095 if (isUpper) 1096 fmt << ":upper16:("; 1097 else 1098 fmt << ":lower16:("; 1099 printRelocationTargetName(RE, fmt); 1100 1101 InMemoryStruct<macho::RelocationEntry> RENext; 1102 DataRefImpl RelNext = Rel; 1103 RelNext.d.a++; 1104 getRelocation(RelNext, RENext); 1105 1106 // ARM half relocs must be followed by a relocation of type 1107 // ARM_RELOC_PAIR. 1108 bool isNextScattered = (Arch != Triple::x86_64) && 1109 (RENext->Word0 & macho::RF_Scattered); 1110 unsigned RType; 1111 if (isNextScattered) 1112 RType = (RENext->Word0 >> 24) & 0xF; 1113 else 1114 RType = (RENext->Word1 >> 28) & 0xF; 1115 1116 if (RType != 1) 1117 report_fatal_error("Expected ARM_RELOC_PAIR after " 1118 "GENERIC_RELOC_HALF"); 1119 1120 // NOTE: The half of the target virtual address is stashed in the 1121 // address field of the secondary relocation, but we can't reverse 1122 // engineer the constant offset from it without decoding the movw/movt 1123 // instruction to find the other half in its immediate field. 1124 1125 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the 1126 // symbol/section pointer of the follow-on relocation. 1127 if (Type == macho::RIT_ARM_HalfDifference) { 1128 fmt << "-"; 1129 printRelocationTargetName(RENext, fmt); 1130 } 1131 1132 fmt << ")"; 1133 break; 1134 } 1135 default: { 1136 printRelocationTargetName(RE, fmt); 1137 } 1138 } 1139 } 1140 } else 1141 printRelocationTargetName(RE, fmt); 1142 1143 fmt.flush(); 1144 Result.append(fmtbuf.begin(), fmtbuf.end()); 1145 return object_error::success; 1146 } 1147 1148 error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, 1149 bool &Result) const { 1150 InMemoryStruct<macho::RelocationEntry> RE; 1151 getRelocation(Rel, RE); 1152 1153 unsigned Arch = getArch(); 1154 bool isScattered = (Arch != Triple::x86_64) && 1155 (RE->Word0 & macho::RF_Scattered); 1156 unsigned Type; 1157 if (isScattered) 1158 Type = (RE->Word0 >> 24) & 0xF; 1159 else 1160 Type = (RE->Word1 >> 28) & 0xF; 1161 1162 Result = false; 1163 1164 // On arches that use the generic relocations, GENERIC_RELOC_PAIR 1165 // is always hidden. 1166 if (Arch == Triple::x86 || Arch == Triple::arm) { 1167 if (Type == macho::RIT_Pair) Result = true; 1168 } else if (Arch == Triple::x86_64) { 1169 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows 1170 // an X864_64_RELOC_SUBTRACTOR. 1171 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) { 1172 DataRefImpl RelPrev = Rel; 1173 RelPrev.d.a--; 1174 InMemoryStruct<macho::RelocationEntry> REPrev; 1175 getRelocation(RelPrev, REPrev); 1176 1177 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF; 1178 1179 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true; 1180 } 1181 } 1182 1183 return object_error::success; 1184 } 1185 1186 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData, 1187 LibraryRef &Res) const { 1188 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1189 } 1190 1191 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, 1192 StringRef &Res) const { 1193 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1194 } 1195 1196 1197 /*===-- Miscellaneous -----------------------------------------------------===*/ 1198 1199 uint8_t MachOObjectFile::getBytesInAddress() const { 1200 return MachOObj->is64Bit() ? 8 : 4; 1201 } 1202 1203 StringRef MachOObjectFile::getFileFormatName() const { 1204 if (!MachOObj->is64Bit()) { 1205 switch (MachOObj->getHeader().CPUType) { 1206 case llvm::MachO::CPUTypeI386: 1207 return "Mach-O 32-bit i386"; 1208 case llvm::MachO::CPUTypeARM: 1209 return "Mach-O arm"; 1210 case llvm::MachO::CPUTypePowerPC: 1211 return "Mach-O 32-bit ppc"; 1212 default: 1213 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 && 1214 "64-bit object file when we're not 64-bit?"); 1215 return "Mach-O 32-bit unknown"; 1216 } 1217 } 1218 1219 switch (MachOObj->getHeader().CPUType) { 1220 case llvm::MachO::CPUTypeX86_64: 1221 return "Mach-O 64-bit x86-64"; 1222 case llvm::MachO::CPUTypePowerPC64: 1223 return "Mach-O 64-bit ppc64"; 1224 default: 1225 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 && 1226 "32-bit object file when we're 64-bit?"); 1227 return "Mach-O 64-bit unknown"; 1228 } 1229 } 1230 1231 unsigned MachOObjectFile::getArch() const { 1232 switch (MachOObj->getHeader().CPUType) { 1233 case llvm::MachO::CPUTypeI386: 1234 return Triple::x86; 1235 case llvm::MachO::CPUTypeX86_64: 1236 return Triple::x86_64; 1237 case llvm::MachO::CPUTypeARM: 1238 return Triple::arm; 1239 case llvm::MachO::CPUTypePowerPC: 1240 return Triple::ppc; 1241 case llvm::MachO::CPUTypePowerPC64: 1242 return Triple::ppc64; 1243 default: 1244 return Triple::UnknownArch; 1245 } 1246 } 1247 1248 } // end namespace object 1249 } // end namespace llvm 1250