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