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