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