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::isSymbolAbsolute(DataRefImpl Symb, bool &Res) const{ 246 uint8_t n_type; 247 if (MachOObj->is64Bit()) { 248 InMemoryStruct<macho::Symbol64TableEntry> Entry; 249 getSymbol64TableEntry(Symb, Entry); 250 n_type = Entry->Type; 251 } else { 252 InMemoryStruct<macho::SymbolTableEntry> Entry; 253 getSymbolTableEntry(Symb, Entry); 254 n_type = Entry->Type; 255 } 256 257 Res = (n_type & MachO::NlistMaskType) == MachO::NListTypeAbsolute; 258 return object_error::success; 259 } 260 261 error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, 262 section_iterator &Res) const { 263 uint8_t index; 264 if (MachOObj->is64Bit()) { 265 InMemoryStruct<macho::Symbol64TableEntry> Entry; 266 getSymbol64TableEntry(Symb, Entry); 267 index = Entry->SectionIndex; 268 } else { 269 InMemoryStruct<macho::SymbolTableEntry> Entry; 270 getSymbolTableEntry(Symb, Entry); 271 index = Entry->SectionIndex; 272 } 273 274 if (index == 0) 275 Res = end_sections(); 276 else 277 Res = section_iterator(SectionRef(Sections[index], this)); 278 279 return object_error::success; 280 } 281 282 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, 283 SymbolRef::Type &Res) const { 284 uint8_t n_type; 285 if (MachOObj->is64Bit()) { 286 InMemoryStruct<macho::Symbol64TableEntry> Entry; 287 getSymbol64TableEntry(Symb, Entry); 288 n_type = Entry->Type; 289 } else { 290 InMemoryStruct<macho::SymbolTableEntry> Entry; 291 getSymbolTableEntry(Symb, Entry); 292 n_type = Entry->Type; 293 } 294 Res = SymbolRef::ST_Other; 295 296 // If this is a STAB debugging symbol, we can do nothing more. 297 if (n_type & MachO::NlistMaskStab) 298 return object_error::success; 299 300 switch (n_type & MachO::NlistMaskType) { 301 case MachO::NListTypeUndefined : 302 Res = SymbolRef::ST_External; 303 break; 304 case MachO::NListTypeSection : 305 Res = SymbolRef::ST_Function; 306 break; 307 } 308 return object_error::success; 309 } 310 311 312 symbol_iterator MachOObjectFile::begin_symbols() const { 313 // DRI.d.a = segment number; DRI.d.b = symbol index. 314 DataRefImpl DRI; 315 DRI.d.a = DRI.d.b = 0; 316 moveToNextSymbol(DRI); 317 return symbol_iterator(SymbolRef(DRI, this)); 318 } 319 320 symbol_iterator MachOObjectFile::end_symbols() const { 321 DataRefImpl DRI; 322 DRI.d.a = MachOObj->getHeader().NumLoadCommands; 323 DRI.d.b = 0; 324 return symbol_iterator(SymbolRef(DRI, this)); 325 } 326 327 328 /*===-- Sections ----------------------------------------------------------===*/ 329 330 void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { 331 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; 332 while (DRI.d.a < LoadCommandCount) { 333 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 334 if (LCI.Command.Type == macho::LCT_Segment) { 335 InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd; 336 MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd); 337 if (DRI.d.b < SegmentLoadCmd->NumSections) 338 return; 339 } else if (LCI.Command.Type == macho::LCT_Segment64) { 340 InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd; 341 MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd); 342 if (DRI.d.b < Segment64LoadCmd->NumSections) 343 return; 344 } 345 346 DRI.d.a++; 347 DRI.d.b = 0; 348 } 349 } 350 351 error_code MachOObjectFile::getSectionNext(DataRefImpl DRI, 352 SectionRef &Result) const { 353 DRI.d.b++; 354 moveToNextSection(DRI); 355 Result = SectionRef(DRI, this); 356 return object_error::success; 357 } 358 359 void 360 MachOObjectFile::getSection(DataRefImpl DRI, 361 InMemoryStruct<macho::Section> &Res) const { 362 InMemoryStruct<macho::SegmentLoadCommand> SLC; 363 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 364 MachOObj->ReadSegmentLoadCommand(LCI, SLC); 365 MachOObj->ReadSection(LCI, DRI.d.b, Res); 366 } 367 368 std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { 369 SectionList::const_iterator loc = 370 std::find(Sections.begin(), Sections.end(), Sec); 371 assert(loc != Sections.end() && "Sec is not a valid section!"); 372 return std::distance(Sections.begin(), loc); 373 } 374 375 void 376 MachOObjectFile::getSection64(DataRefImpl DRI, 377 InMemoryStruct<macho::Section64> &Res) const { 378 InMemoryStruct<macho::Segment64LoadCommand> SLC; 379 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 380 MachOObj->ReadSegment64LoadCommand(LCI, SLC); 381 MachOObj->ReadSection64(LCI, DRI.d.b, Res); 382 } 383 384 static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) { 385 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 386 if (LCI.Command.Type == macho::LCT_Segment64) 387 return true; 388 assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type."); 389 return false; 390 } 391 392 error_code MachOObjectFile::getSectionName(DataRefImpl DRI, 393 StringRef &Result) const { 394 // FIXME: thread safety. 395 static char result[34]; 396 if (is64BitLoadCommand(MachOObj, DRI)) { 397 InMemoryStruct<macho::Segment64LoadCommand> SLC; 398 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 399 MachOObj->ReadSegment64LoadCommand(LCI, SLC); 400 InMemoryStruct<macho::Section64> Sect; 401 MachOObj->ReadSection64(LCI, DRI.d.b, Sect); 402 403 strcpy(result, Sect->SegmentName); 404 strcat(result, ","); 405 strcat(result, Sect->Name); 406 } else { 407 InMemoryStruct<macho::SegmentLoadCommand> SLC; 408 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 409 MachOObj->ReadSegmentLoadCommand(LCI, SLC); 410 InMemoryStruct<macho::Section> Sect; 411 MachOObj->ReadSection(LCI, DRI.d.b, Sect); 412 413 strcpy(result, Sect->SegmentName); 414 strcat(result, ","); 415 strcat(result, Sect->Name); 416 } 417 Result = StringRef(result); 418 return object_error::success; 419 } 420 421 error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, 422 uint64_t &Result) const { 423 if (is64BitLoadCommand(MachOObj, DRI)) { 424 InMemoryStruct<macho::Section64> Sect; 425 getSection64(DRI, Sect); 426 Result = Sect->Address; 427 } else { 428 InMemoryStruct<macho::Section> Sect; 429 getSection(DRI, Sect); 430 Result = Sect->Address; 431 } 432 return object_error::success; 433 } 434 435 error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, 436 uint64_t &Result) const { 437 if (is64BitLoadCommand(MachOObj, DRI)) { 438 InMemoryStruct<macho::Section64> Sect; 439 getSection64(DRI, Sect); 440 Result = Sect->Size; 441 } else { 442 InMemoryStruct<macho::Section> Sect; 443 getSection(DRI, Sect); 444 Result = Sect->Size; 445 } 446 return object_error::success; 447 } 448 449 error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, 450 StringRef &Result) const { 451 if (is64BitLoadCommand(MachOObj, DRI)) { 452 InMemoryStruct<macho::Section64> Sect; 453 getSection64(DRI, Sect); 454 Result = MachOObj->getData(Sect->Offset, Sect->Size); 455 } else { 456 InMemoryStruct<macho::Section> Sect; 457 getSection(DRI, Sect); 458 Result = MachOObj->getData(Sect->Offset, Sect->Size); 459 } 460 return object_error::success; 461 } 462 463 error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, 464 uint64_t &Result) const { 465 if (is64BitLoadCommand(MachOObj, DRI)) { 466 InMemoryStruct<macho::Section64> Sect; 467 getSection64(DRI, Sect); 468 Result = uint64_t(1) << Sect->Align; 469 } else { 470 InMemoryStruct<macho::Section> Sect; 471 getSection(DRI, Sect); 472 Result = uint64_t(1) << Sect->Align; 473 } 474 return object_error::success; 475 } 476 477 error_code MachOObjectFile::isSectionText(DataRefImpl DRI, 478 bool &Result) const { 479 if (is64BitLoadCommand(MachOObj, DRI)) { 480 InMemoryStruct<macho::Section64> Sect; 481 getSection64(DRI, Sect); 482 Result = !strcmp(Sect->Name, "__text"); 483 } else { 484 InMemoryStruct<macho::Section> Sect; 485 getSection(DRI, Sect); 486 Result = !strcmp(Sect->Name, "__text"); 487 } 488 return object_error::success; 489 } 490 491 error_code MachOObjectFile::isSectionData(DataRefImpl DRI, 492 bool &Result) const { 493 // FIXME: Unimplemented. 494 Result = false; 495 return object_error::success; 496 } 497 498 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, 499 bool &Result) const { 500 // FIXME: Unimplemented. 501 Result = false; 502 return object_error::success; 503 } 504 505 error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, 506 DataRefImpl Symb, 507 bool &Result) const { 508 SymbolRef::Type ST; 509 getSymbolType(Symb, ST); 510 if (ST == SymbolRef::ST_External) { 511 Result = false; 512 return object_error::success; 513 } 514 515 uint64_t SectBegin, SectEnd; 516 getSectionAddress(Sec, SectBegin); 517 getSectionSize(Sec, SectEnd); 518 SectEnd += SectBegin; 519 520 if (MachOObj->is64Bit()) { 521 InMemoryStruct<macho::Symbol64TableEntry> Entry; 522 getSymbol64TableEntry(Symb, Entry); 523 uint64_t SymAddr= Entry->Value; 524 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 525 } else { 526 InMemoryStruct<macho::SymbolTableEntry> Entry; 527 getSymbolTableEntry(Symb, Entry); 528 uint64_t SymAddr= Entry->Value; 529 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 530 } 531 532 return object_error::success; 533 } 534 535 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { 536 DataRefImpl ret; 537 ret.d.a = 0; 538 ret.d.b = getSectionIndex(Sec); 539 return relocation_iterator(RelocationRef(ret, this)); 540 } 541 relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { 542 uint32_t last_reloc; 543 if (is64BitLoadCommand(MachOObj, Sec)) { 544 InMemoryStruct<macho::Section64> Sect; 545 getSection64(Sec, Sect); 546 last_reloc = Sect->NumRelocationTableEntries; 547 } else { 548 InMemoryStruct<macho::Section> Sect; 549 getSection(Sec, Sect); 550 last_reloc = Sect->NumRelocationTableEntries; 551 } 552 DataRefImpl ret; 553 ret.d.a = last_reloc; 554 ret.d.b = getSectionIndex(Sec); 555 return relocation_iterator(RelocationRef(ret, this)); 556 } 557 558 section_iterator MachOObjectFile::begin_sections() const { 559 DataRefImpl DRI; 560 DRI.d.a = DRI.d.b = 0; 561 moveToNextSection(DRI); 562 return section_iterator(SectionRef(DRI, this)); 563 } 564 565 section_iterator MachOObjectFile::end_sections() const { 566 DataRefImpl DRI; 567 DRI.d.a = MachOObj->getHeader().NumLoadCommands; 568 DRI.d.b = 0; 569 return section_iterator(SectionRef(DRI, this)); 570 } 571 572 /*===-- Relocations -------------------------------------------------------===*/ 573 574 void MachOObjectFile:: 575 getRelocation(DataRefImpl Rel, 576 InMemoryStruct<macho::RelocationEntry> &Res) const { 577 uint32_t relOffset; 578 if (MachOObj->is64Bit()) { 579 InMemoryStruct<macho::Section64> Sect; 580 getSection64(Sections[Rel.d.b], Sect); 581 relOffset = Sect->RelocationTableOffset; 582 } else { 583 InMemoryStruct<macho::Section> Sect; 584 getSection(Sections[Rel.d.b], Sect); 585 relOffset = Sect->RelocationTableOffset; 586 } 587 MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res); 588 } 589 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, 590 RelocationRef &Res) const { 591 ++Rel.d.a; 592 Res = RelocationRef(Rel, this); 593 return object_error::success; 594 } 595 error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, 596 uint64_t &Res) const { 597 const uint8_t* sectAddress = base(); 598 if (MachOObj->is64Bit()) { 599 InMemoryStruct<macho::Section64> Sect; 600 getSection64(Sections[Rel.d.b], Sect); 601 sectAddress += Sect->Offset; 602 } else { 603 InMemoryStruct<macho::Section> Sect; 604 getSection(Sections[Rel.d.b], Sect); 605 sectAddress += Sect->Offset; 606 } 607 InMemoryStruct<macho::RelocationEntry> RE; 608 getRelocation(Rel, RE); 609 Res = reinterpret_cast<uintptr_t>(sectAddress + RE->Word0); 610 return object_error::success; 611 } 612 error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, 613 SymbolRef &Res) const { 614 InMemoryStruct<macho::RelocationEntry> RE; 615 getRelocation(Rel, RE); 616 uint32_t SymbolIdx = RE->Word1 & 0xffffff; 617 bool isExtern = (RE->Word1 >> 27) & 1; 618 619 DataRefImpl Sym; 620 Sym.d.a = Sym.d.b = 0; 621 moveToNextSymbol(Sym); 622 if (isExtern) { 623 for (unsigned i = 0; i < SymbolIdx; i++) { 624 Sym.d.b++; 625 moveToNextSymbol(Sym); 626 assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands && 627 "Relocation symbol index out of range!"); 628 } 629 } 630 Res = SymbolRef(Sym, this); 631 return object_error::success; 632 } 633 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, 634 uint32_t &Res) const { 635 InMemoryStruct<macho::RelocationEntry> RE; 636 getRelocation(Rel, RE); 637 Res = RE->Word1; 638 return object_error::success; 639 } 640 error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, 641 SmallVectorImpl<char> &Result) const { 642 return object_error::success; 643 } 644 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, 645 int64_t &Res) const { 646 InMemoryStruct<macho::RelocationEntry> RE; 647 getRelocation(Rel, RE); 648 bool isExtern = (RE->Word1 >> 27) & 1; 649 Res = 0; 650 if (!isExtern) { 651 const uint8_t* sectAddress = base(); 652 if (MachOObj->is64Bit()) { 653 InMemoryStruct<macho::Section64> Sect; 654 getSection64(Sections[Rel.d.b], Sect); 655 sectAddress += Sect->Offset; 656 } else { 657 InMemoryStruct<macho::Section> Sect; 658 getSection(Sections[Rel.d.b], Sect); 659 sectAddress += Sect->Offset; 660 } 661 Res = reinterpret_cast<uintptr_t>(sectAddress); 662 } 663 return object_error::success; 664 } 665 error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel, 666 SmallVectorImpl<char> &Result) const { 667 return object_error::success; 668 } 669 670 /*===-- Miscellaneous -----------------------------------------------------===*/ 671 672 uint8_t MachOObjectFile::getBytesInAddress() const { 673 return MachOObj->is64Bit() ? 8 : 4; 674 } 675 676 StringRef MachOObjectFile::getFileFormatName() const { 677 if (!MachOObj->is64Bit()) { 678 switch (MachOObj->getHeader().CPUType) { 679 case llvm::MachO::CPUTypeI386: 680 return "Mach-O 32-bit i386"; 681 case llvm::MachO::CPUTypeARM: 682 return "Mach-O arm"; 683 case llvm::MachO::CPUTypePowerPC: 684 return "Mach-O 32-bit ppc"; 685 default: 686 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 && 687 "64-bit object file when we're not 64-bit?"); 688 return "Mach-O 32-bit unknown"; 689 } 690 } 691 692 switch (MachOObj->getHeader().CPUType) { 693 case llvm::MachO::CPUTypeX86_64: 694 return "Mach-O 64-bit x86-64"; 695 case llvm::MachO::CPUTypePowerPC64: 696 return "Mach-O 64-bit ppc64"; 697 default: 698 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 && 699 "32-bit object file when we're 64-bit?"); 700 return "Mach-O 64-bit unknown"; 701 } 702 } 703 704 unsigned MachOObjectFile::getArch() const { 705 switch (MachOObj->getHeader().CPUType) { 706 case llvm::MachO::CPUTypeI386: 707 return Triple::x86; 708 case llvm::MachO::CPUTypeX86_64: 709 return Triple::x86_64; 710 case llvm::MachO::CPUTypeARM: 711 return Triple::arm; 712 case llvm::MachO::CPUTypePowerPC: 713 return Triple::ppc; 714 case llvm::MachO::CPUTypePowerPC64: 715 return Triple::ppc64; 716 default: 717 return Triple::UnknownArch; 718 } 719 } 720 721 } // end namespace object 722 } // end namespace llvm 723