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