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/MachOFormat.h" 17 #include "llvm/Object/MachOObject.h" 18 #include "llvm/Object/ObjectFile.h" 19 #include "llvm/Support/MemoryBuffer.h" 20 #include "llvm/Support/MachO.h" 21 #include "llvm/ADT/SmallVector.h" 22 23 #include <cctype> 24 #include <cstring> 25 #include <limits> 26 27 using namespace llvm; 28 using namespace object; 29 30 namespace llvm { 31 32 typedef MachOObject::LoadCommandInfo LoadCommandInfo; 33 34 class MachOObjectFile : public ObjectFile { 35 public: 36 MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, error_code &ec); 37 38 virtual symbol_iterator begin_symbols() const; 39 virtual symbol_iterator end_symbols() const; 40 virtual section_iterator begin_sections() const; 41 virtual section_iterator end_sections() const; 42 43 virtual uint8_t getBytesInAddress() const; 44 virtual StringRef getFileFormatName() const; 45 virtual unsigned getArch() const; 46 47 protected: 48 virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; 49 virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; 50 virtual error_code getSymbolOffset(DataRefImpl Symb, uint64_t &Res) const; 51 virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; 52 virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; 53 virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; 54 virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const; 55 virtual error_code isSymbolGlobal(DataRefImpl Symb, bool &Res) const; 56 virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::SymbolType &Res) const; 57 58 virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; 59 virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; 60 virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; 61 virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; 62 virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; 63 virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; 64 virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; 65 virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; 66 virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; 67 virtual error_code sectionContainsSymbol(DataRefImpl DRI, DataRefImpl S, 68 bool &Result) const; 69 virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; 70 virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; 71 72 virtual error_code getRelocationNext(DataRefImpl Rel, 73 RelocationRef &Res) const; 74 virtual error_code getRelocationAddress(DataRefImpl Rel, 75 uint64_t &Res) const; 76 virtual error_code getRelocationSymbol(DataRefImpl Rel, 77 SymbolRef &Res) const; 78 virtual error_code getRelocationType(DataRefImpl Rel, 79 uint32_t &Res) const; 80 virtual error_code getRelocationTypeName(DataRefImpl Rel, 81 SmallVectorImpl<char> &Result) const; 82 virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, 83 int64_t &Res) const; 84 virtual error_code getRelocationValueString(DataRefImpl Rel, 85 SmallVectorImpl<char> &Result) const; 86 87 private: 88 MachOObject *MachOObj; 89 mutable uint32_t RegisteredStringTable; 90 typedef SmallVector<DataRefImpl, 1> SectionList; 91 SectionList Sections; 92 93 94 void moveToNextSection(DataRefImpl &DRI) const; 95 void getSymbolTableEntry(DataRefImpl DRI, 96 InMemoryStruct<macho::SymbolTableEntry> &Res) const; 97 void getSymbol64TableEntry(DataRefImpl DRI, 98 InMemoryStruct<macho::Symbol64TableEntry> &Res) const; 99 void moveToNextSymbol(DataRefImpl &DRI) const; 100 void getSection(DataRefImpl DRI, InMemoryStruct<macho::Section> &Res) const; 101 void getSection64(DataRefImpl DRI, 102 InMemoryStruct<macho::Section64> &Res) const; 103 void getRelocation(DataRefImpl Rel, 104 InMemoryStruct<macho::RelocationEntry> &Res) const; 105 std::size_t getSectionIndex(DataRefImpl Sec) const; 106 }; 107 108 MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, 109 error_code &ec) 110 : ObjectFile(Binary::isMachO, Object, ec), 111 MachOObj(MOO), 112 RegisteredStringTable(std::numeric_limits<uint32_t>::max()) { 113 DataRefImpl DRI; 114 DRI.d.a = DRI.d.b = 0; 115 moveToNextSection(DRI); 116 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; 117 while (DRI.d.a < LoadCommandCount) { 118 Sections.push_back(DRI); 119 DRI.d.b++; 120 moveToNextSection(DRI); 121 } 122 } 123 124 125 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { 126 error_code ec; 127 std::string Err; 128 MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err); 129 if (!MachOObj) 130 return NULL; 131 return new MachOObjectFile(Buffer, MachOObj, ec); 132 } 133 134 /*===-- Symbols -----------------------------------------------------------===*/ 135 136 void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { 137 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; 138 while (DRI.d.a < LoadCommandCount) { 139 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 140 if (LCI.Command.Type == macho::LCT_Symtab) { 141 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd; 142 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); 143 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries) 144 return; 145 } 146 147 DRI.d.a++; 148 DRI.d.b = 0; 149 } 150 } 151 152 void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI, 153 InMemoryStruct<macho::SymbolTableEntry> &Res) const { 154 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd; 155 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 156 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); 157 158 if (RegisteredStringTable != DRI.d.a) { 159 MachOObj->RegisterStringTable(*SymtabLoadCmd); 160 RegisteredStringTable = DRI.d.a; 161 } 162 163 MachOObj->ReadSymbolTableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b, 164 Res); 165 } 166 167 void MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI, 168 InMemoryStruct<macho::Symbol64TableEntry> &Res) const { 169 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd; 170 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 171 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); 172 173 if (RegisteredStringTable != DRI.d.a) { 174 MachOObj->RegisterStringTable(*SymtabLoadCmd); 175 RegisteredStringTable = DRI.d.a; 176 } 177 178 MachOObj->ReadSymbol64TableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b, 179 Res); 180 } 181 182 183 error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI, 184 SymbolRef &Result) const { 185 DRI.d.b++; 186 moveToNextSymbol(DRI); 187 Result = SymbolRef(DRI, this); 188 return object_error::success; 189 } 190 191 error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, 192 StringRef &Result) const { 193 if (MachOObj->is64Bit()) { 194 InMemoryStruct<macho::Symbol64TableEntry> Entry; 195 getSymbol64TableEntry(DRI, Entry); 196 Result = MachOObj->getStringAtIndex(Entry->StringIndex); 197 } else { 198 InMemoryStruct<macho::SymbolTableEntry> Entry; 199 getSymbolTableEntry(DRI, Entry); 200 Result = MachOObj->getStringAtIndex(Entry->StringIndex); 201 } 202 return object_error::success; 203 } 204 205 error_code MachOObjectFile::getSymbolOffset(DataRefImpl DRI, 206 uint64_t &Result) const { 207 if (MachOObj->is64Bit()) { 208 InMemoryStruct<macho::Symbol64TableEntry> Entry; 209 getSymbol64TableEntry(DRI, Entry); 210 Result = Entry->Value; 211 } else { 212 InMemoryStruct<macho::SymbolTableEntry> Entry; 213 getSymbolTableEntry(DRI, Entry); 214 Result = Entry->Value; 215 } 216 return object_error::success; 217 } 218 219 error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI, 220 uint64_t &Result) const { 221 uint64_t SymbolOffset; 222 uint8_t SectionIndex; 223 if (MachOObj->is64Bit()) { 224 InMemoryStruct<macho::Symbol64TableEntry> Entry; 225 getSymbol64TableEntry(DRI, Entry); 226 SymbolOffset = Entry->Value; 227 SectionIndex = Entry->SectionIndex; 228 } else { 229 InMemoryStruct<macho::SymbolTableEntry> Entry; 230 getSymbolTableEntry(DRI, Entry); 231 SymbolOffset = Entry->Value; 232 SectionIndex = Entry->SectionIndex; 233 } 234 getSectionAddress(Sections[SectionIndex], Result); 235 Result += SymbolOffset; 236 237 return object_error::success; 238 } 239 240 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, 241 uint64_t &Result) const { 242 Result = UnknownAddressOrSize; 243 return object_error::success; 244 } 245 246 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI, 247 char &Result) const { 248 uint8_t Type, Flags; 249 if (MachOObj->is64Bit()) { 250 InMemoryStruct<macho::Symbol64TableEntry> Entry; 251 getSymbol64TableEntry(DRI, Entry); 252 Type = Entry->Type; 253 Flags = Entry->Flags; 254 } else { 255 InMemoryStruct<macho::SymbolTableEntry> Entry; 256 getSymbolTableEntry(DRI, Entry); 257 Type = Entry->Type; 258 Flags = Entry->Flags; 259 } 260 261 char Char; 262 switch (Type & macho::STF_TypeMask) { 263 case macho::STT_Undefined: 264 Char = 'u'; 265 break; 266 case macho::STT_Absolute: 267 case macho::STT_Section: 268 Char = 's'; 269 break; 270 default: 271 Char = '?'; 272 break; 273 } 274 275 if (Flags & (macho::STF_External | macho::STF_PrivateExtern)) 276 Char = toupper(Char); 277 Result = Char; 278 return object_error::success; 279 } 280 281 error_code MachOObjectFile::isSymbolInternal(DataRefImpl DRI, 282 bool &Result) const { 283 if (MachOObj->is64Bit()) { 284 InMemoryStruct<macho::Symbol64TableEntry> Entry; 285 getSymbol64TableEntry(DRI, Entry); 286 Result = Entry->Flags & macho::STF_StabsEntryMask; 287 } else { 288 InMemoryStruct<macho::SymbolTableEntry> Entry; 289 getSymbolTableEntry(DRI, Entry); 290 Result = Entry->Flags & macho::STF_StabsEntryMask; 291 } 292 return object_error::success; 293 } 294 295 error_code MachOObjectFile::isSymbolGlobal(DataRefImpl Symb, bool &Res) const { 296 297 if (MachOObj->is64Bit()) { 298 InMemoryStruct<macho::Symbol64TableEntry> Entry; 299 getSymbol64TableEntry(Symb, Entry); 300 Res = Entry->Type & MachO::NlistMaskExternal; 301 } else { 302 InMemoryStruct<macho::SymbolTableEntry> Entry; 303 getSymbolTableEntry(Symb, Entry); 304 Res = Entry->Type & MachO::NlistMaskExternal; 305 } 306 return object_error::success; 307 } 308 309 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, 310 SymbolRef::SymbolType &Res) const { 311 uint8_t n_type; 312 if (MachOObj->is64Bit()) { 313 InMemoryStruct<macho::Symbol64TableEntry> Entry; 314 getSymbol64TableEntry(Symb, Entry); 315 n_type = Entry->Type; 316 } else { 317 InMemoryStruct<macho::SymbolTableEntry> Entry; 318 getSymbolTableEntry(Symb, Entry); 319 n_type = Entry->Type; 320 } 321 Res = SymbolRef::ST_Other; 322 switch (n_type & MachO::NlistMaskType) { 323 case MachO::NListTypeUndefined : 324 Res = SymbolRef::ST_External; 325 break; 326 case MachO::NListTypeSection : 327 Res = SymbolRef::ST_Function; 328 break; 329 } 330 return object_error::success; 331 } 332 333 334 symbol_iterator MachOObjectFile::begin_symbols() const { 335 // DRI.d.a = segment number; DRI.d.b = symbol index. 336 DataRefImpl DRI; 337 DRI.d.a = DRI.d.b = 0; 338 moveToNextSymbol(DRI); 339 return symbol_iterator(SymbolRef(DRI, this)); 340 } 341 342 symbol_iterator MachOObjectFile::end_symbols() const { 343 DataRefImpl DRI; 344 DRI.d.a = MachOObj->getHeader().NumLoadCommands; 345 DRI.d.b = 0; 346 return symbol_iterator(SymbolRef(DRI, this)); 347 } 348 349 350 /*===-- Sections ----------------------------------------------------------===*/ 351 352 void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { 353 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; 354 while (DRI.d.a < LoadCommandCount) { 355 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 356 if (LCI.Command.Type == macho::LCT_Segment) { 357 InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd; 358 MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd); 359 if (DRI.d.b < SegmentLoadCmd->NumSections) 360 return; 361 } else if (LCI.Command.Type == macho::LCT_Segment64) { 362 InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd; 363 MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd); 364 if (DRI.d.b < Segment64LoadCmd->NumSections) 365 return; 366 } 367 368 DRI.d.a++; 369 DRI.d.b = 0; 370 } 371 } 372 373 error_code MachOObjectFile::getSectionNext(DataRefImpl DRI, 374 SectionRef &Result) const { 375 DRI.d.b++; 376 moveToNextSection(DRI); 377 Result = SectionRef(DRI, this); 378 return object_error::success; 379 } 380 381 void 382 MachOObjectFile::getSection(DataRefImpl DRI, 383 InMemoryStruct<macho::Section> &Res) const { 384 InMemoryStruct<macho::SegmentLoadCommand> SLC; 385 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 386 MachOObj->ReadSegmentLoadCommand(LCI, SLC); 387 MachOObj->ReadSection(LCI, DRI.d.b, Res); 388 } 389 390 std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { 391 SectionList::const_iterator loc = 392 std::find(Sections.begin(), Sections.end(), Sec); 393 assert(loc != Sections.end() && "Sec is not a valid section!"); 394 return std::distance(Sections.begin(), loc); 395 } 396 397 void 398 MachOObjectFile::getSection64(DataRefImpl DRI, 399 InMemoryStruct<macho::Section64> &Res) const { 400 InMemoryStruct<macho::Segment64LoadCommand> SLC; 401 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 402 MachOObj->ReadSegment64LoadCommand(LCI, SLC); 403 MachOObj->ReadSection64(LCI, DRI.d.b, Res); 404 } 405 406 static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) { 407 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 408 if (LCI.Command.Type == macho::LCT_Segment64) 409 return true; 410 assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type."); 411 return false; 412 } 413 414 error_code MachOObjectFile::getSectionName(DataRefImpl DRI, 415 StringRef &Result) const { 416 // FIXME: thread safety. 417 static char result[34]; 418 if (is64BitLoadCommand(MachOObj, DRI)) { 419 InMemoryStruct<macho::Segment64LoadCommand> SLC; 420 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 421 MachOObj->ReadSegment64LoadCommand(LCI, SLC); 422 InMemoryStruct<macho::Section64> Sect; 423 MachOObj->ReadSection64(LCI, DRI.d.b, Sect); 424 425 strcpy(result, Sect->SegmentName); 426 strcat(result, ","); 427 strcat(result, Sect->Name); 428 } else { 429 InMemoryStruct<macho::SegmentLoadCommand> SLC; 430 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 431 MachOObj->ReadSegmentLoadCommand(LCI, SLC); 432 InMemoryStruct<macho::Section> Sect; 433 MachOObj->ReadSection(LCI, DRI.d.b, Sect); 434 435 strcpy(result, Sect->SegmentName); 436 strcat(result, ","); 437 strcat(result, Sect->Name); 438 } 439 Result = StringRef(result); 440 return object_error::success; 441 } 442 443 error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, 444 uint64_t &Result) const { 445 if (is64BitLoadCommand(MachOObj, DRI)) { 446 InMemoryStruct<macho::Section64> Sect; 447 getSection64(DRI, Sect); 448 Result = Sect->Address; 449 } else { 450 InMemoryStruct<macho::Section> Sect; 451 getSection(DRI, Sect); 452 Result = Sect->Address; 453 } 454 return object_error::success; 455 } 456 457 error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, 458 uint64_t &Result) const { 459 if (is64BitLoadCommand(MachOObj, DRI)) { 460 InMemoryStruct<macho::Section64> Sect; 461 getSection64(DRI, Sect); 462 Result = Sect->Size; 463 } else { 464 InMemoryStruct<macho::Section> Sect; 465 getSection(DRI, Sect); 466 Result = Sect->Size; 467 } 468 return object_error::success; 469 } 470 471 error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, 472 StringRef &Result) const { 473 if (is64BitLoadCommand(MachOObj, DRI)) { 474 InMemoryStruct<macho::Section64> Sect; 475 getSection64(DRI, Sect); 476 Result = MachOObj->getData(Sect->Offset, Sect->Size); 477 } else { 478 InMemoryStruct<macho::Section> Sect; 479 getSection(DRI, Sect); 480 Result = MachOObj->getData(Sect->Offset, Sect->Size); 481 } 482 return object_error::success; 483 } 484 485 error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, 486 uint64_t &Result) const { 487 if (is64BitLoadCommand(MachOObj, DRI)) { 488 InMemoryStruct<macho::Section64> Sect; 489 getSection64(DRI, Sect); 490 Result = uint64_t(1) << Sect->Align; 491 } else { 492 InMemoryStruct<macho::Section> Sect; 493 getSection(DRI, Sect); 494 Result = uint64_t(1) << Sect->Align; 495 } 496 return object_error::success; 497 } 498 499 error_code MachOObjectFile::isSectionText(DataRefImpl DRI, 500 bool &Result) const { 501 if (is64BitLoadCommand(MachOObj, DRI)) { 502 InMemoryStruct<macho::Section64> Sect; 503 getSection64(DRI, Sect); 504 Result = !strcmp(Sect->Name, "__text"); 505 } else { 506 InMemoryStruct<macho::Section> Sect; 507 getSection(DRI, Sect); 508 Result = !strcmp(Sect->Name, "__text"); 509 } 510 return object_error::success; 511 } 512 513 error_code MachOObjectFile::isSectionData(DataRefImpl DRI, 514 bool &Result) const { 515 // FIXME: Unimplemented. 516 Result = false; 517 return object_error::success; 518 } 519 520 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, 521 bool &Result) const { 522 // FIXME: Unimplemented. 523 Result = false; 524 return object_error::success; 525 } 526 527 error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, 528 DataRefImpl Symb, 529 bool &Result) const { 530 if (MachOObj->is64Bit()) { 531 InMemoryStruct<macho::Symbol64TableEntry> Entry; 532 getSymbol64TableEntry(Symb, Entry); 533 Result = Entry->SectionIndex == 1 + Sec.d.a + Sec.d.b; 534 } else { 535 InMemoryStruct<macho::SymbolTableEntry> Entry; 536 getSymbolTableEntry(Symb, Entry); 537 Result = Entry->SectionIndex == 1 + Sec.d.a + Sec.d.b; 538 } 539 return object_error::success; 540 } 541 542 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { 543 DataRefImpl ret; 544 ret.d.a = 0; 545 ret.d.b = getSectionIndex(Sec); 546 return relocation_iterator(RelocationRef(ret, this)); 547 } 548 relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { 549 uint32_t last_reloc; 550 if (is64BitLoadCommand(MachOObj, Sec)) { 551 InMemoryStruct<macho::Section64> Sect; 552 getSection64(Sec, Sect); 553 last_reloc = Sect->NumRelocationTableEntries; 554 } else { 555 InMemoryStruct<macho::Section> Sect; 556 getSection(Sec, Sect); 557 last_reloc = Sect->NumRelocationTableEntries; 558 } 559 DataRefImpl ret; 560 ret.d.a = last_reloc; 561 ret.d.b = getSectionIndex(Sec); 562 return relocation_iterator(RelocationRef(ret, this)); 563 } 564 565 section_iterator MachOObjectFile::begin_sections() const { 566 DataRefImpl DRI; 567 DRI.d.a = DRI.d.b = 0; 568 moveToNextSection(DRI); 569 return section_iterator(SectionRef(DRI, this)); 570 } 571 572 section_iterator MachOObjectFile::end_sections() const { 573 DataRefImpl DRI; 574 DRI.d.a = MachOObj->getHeader().NumLoadCommands; 575 DRI.d.b = 0; 576 return section_iterator(SectionRef(DRI, this)); 577 } 578 579 /*===-- Relocations -------------------------------------------------------===*/ 580 581 void MachOObjectFile:: 582 getRelocation(DataRefImpl Rel, 583 InMemoryStruct<macho::RelocationEntry> &Res) const { 584 uint32_t relOffset; 585 if (MachOObj->is64Bit()) { 586 InMemoryStruct<macho::Section64> Sect; 587 getSection64(Sections[Rel.d.b], Sect); 588 relOffset = Sect->RelocationTableOffset; 589 } else { 590 InMemoryStruct<macho::Section> Sect; 591 getSection(Sections[Rel.d.b], Sect); 592 relOffset = Sect->RelocationTableOffset; 593 } 594 MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res); 595 } 596 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, 597 RelocationRef &Res) const { 598 ++Rel.d.a; 599 Res = RelocationRef(Rel, this); 600 return object_error::success; 601 } 602 error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, 603 uint64_t &Res) const { 604 const uint8_t* sectAddress = base(); 605 if (MachOObj->is64Bit()) { 606 InMemoryStruct<macho::Section64> Sect; 607 getSection64(Sections[Rel.d.b], Sect); 608 sectAddress += Sect->Offset; 609 } else { 610 InMemoryStruct<macho::Section> Sect; 611 getSection(Sections[Rel.d.b], Sect); 612 sectAddress += Sect->Offset; 613 } 614 InMemoryStruct<macho::RelocationEntry> RE; 615 getRelocation(Rel, RE); 616 Res = reinterpret_cast<uintptr_t>(sectAddress + RE->Word0); 617 return object_error::success; 618 } 619 error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, 620 SymbolRef &Res) const { 621 InMemoryStruct<macho::RelocationEntry> RE; 622 getRelocation(Rel, RE); 623 uint32_t SymbolIdx = RE->Word1 & 0xffffff; 624 bool isExtern = (RE->Word1 >> 27) & 1; 625 626 DataRefImpl Sym; 627 Sym.d.a = Sym.d.b = 0; 628 moveToNextSymbol(Sym); 629 if (isExtern) { 630 for (unsigned i = 0; i < SymbolIdx; i++) { 631 Sym.d.b++; 632 moveToNextSymbol(Sym); 633 assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands && 634 "Relocation symbol index out of range!"); 635 } 636 } 637 Res = SymbolRef(Sym, this); 638 return object_error::success; 639 } 640 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, 641 uint32_t &Res) const { 642 InMemoryStruct<macho::RelocationEntry> RE; 643 getRelocation(Rel, RE); 644 Res = RE->Word1; 645 return object_error::success; 646 } 647 error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, 648 SmallVectorImpl<char> &Result) const { 649 return object_error::success; 650 } 651 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, 652 int64_t &Res) const { 653 InMemoryStruct<macho::RelocationEntry> RE; 654 getRelocation(Rel, RE); 655 bool isExtern = (RE->Word1 >> 27) & 1; 656 Res = 0; 657 if (!isExtern) { 658 const uint8_t* sectAddress = base(); 659 if (MachOObj->is64Bit()) { 660 InMemoryStruct<macho::Section64> Sect; 661 getSection64(Sections[Rel.d.b], Sect); 662 sectAddress += Sect->Offset; 663 } else { 664 InMemoryStruct<macho::Section> Sect; 665 getSection(Sections[Rel.d.b], Sect); 666 sectAddress += Sect->Offset; 667 } 668 Res = reinterpret_cast<uintptr_t>(sectAddress); 669 } 670 return object_error::success; 671 } 672 error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel, 673 SmallVectorImpl<char> &Result) const { 674 return object_error::success; 675 } 676 677 /*===-- Miscellaneous -----------------------------------------------------===*/ 678 679 uint8_t MachOObjectFile::getBytesInAddress() const { 680 return MachOObj->is64Bit() ? 8 : 4; 681 } 682 683 StringRef MachOObjectFile::getFileFormatName() const { 684 if (!MachOObj->is64Bit()) { 685 switch (MachOObj->getHeader().CPUType) { 686 case llvm::MachO::CPUTypeI386: 687 return "Mach-O 32-bit i386"; 688 case llvm::MachO::CPUTypeARM: 689 return "Mach-O arm"; 690 case llvm::MachO::CPUTypePowerPC: 691 return "Mach-O 32-bit ppc"; 692 default: 693 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 && 694 "64-bit object file when we're not 64-bit?"); 695 return "Mach-O 32-bit unknown"; 696 } 697 } 698 699 switch (MachOObj->getHeader().CPUType) { 700 case llvm::MachO::CPUTypeX86_64: 701 return "Mach-O 64-bit x86-64"; 702 case llvm::MachO::CPUTypePowerPC64: 703 return "Mach-O 64-bit ppc64"; 704 default: 705 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 && 706 "32-bit object file when we're 64-bit?"); 707 return "Mach-O 64-bit unknown"; 708 } 709 } 710 711 unsigned MachOObjectFile::getArch() const { 712 switch (MachOObj->getHeader().CPUType) { 713 case llvm::MachO::CPUTypeI386: 714 return Triple::x86; 715 case llvm::MachO::CPUTypeX86_64: 716 return Triple::x86_64; 717 case llvm::MachO::CPUTypeARM: 718 return Triple::arm; 719 case llvm::MachO::CPUTypePowerPC: 720 return Triple::ppc; 721 case llvm::MachO::CPUTypePowerPC64: 722 return Triple::ppc64; 723 default: 724 return Triple::UnknownArch; 725 } 726 } 727 728 } // end namespace llvm 729