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