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/Object/MachO.h" 16 #include "llvm/ADT/Triple.h" 17 #include "llvm/Object/MachOFormat.h" 18 #include "llvm/Support/Format.h" 19 #include "llvm/Support/MemoryBuffer.h" 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::ID_MachO, Object, ec), 33 MachOObj(MOO) { 34 DataRefImpl DRI; 35 moveToNextSection(DRI); 36 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; 37 while (DRI.d.a < LoadCommandCount) { 38 Sections.push_back(DRI); 39 DRI.d.b++; 40 moveToNextSection(DRI); 41 } 42 } 43 44 45 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { 46 error_code ec; 47 std::string Err; 48 MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err); 49 if (!MachOObj) 50 return NULL; 51 // MachOObject takes ownership of the Buffer we passed to it, and 52 // MachOObjectFile does, too, so we need to make sure they don't get the 53 // same object. A MemoryBuffer is cheap (it's just a reference to memory, 54 // not a copy of the memory itself), so just make a new copy here for 55 // the MachOObjectFile. 56 MemoryBuffer *NewBuffer = 57 MemoryBuffer::getMemBuffer(Buffer->getBuffer(), 58 Buffer->getBufferIdentifier(), false); 59 return new MachOObjectFile(NewBuffer, MachOObj, ec); 60 } 61 62 /*===-- Symbols -----------------------------------------------------------===*/ 63 64 const MachOFormat::SymtabLoadCommand * 65 MachOObjectFile::getSymtabLoadCommand(LoadCommandInfo LCI) const { 66 StringRef Data = MachOObj->getData(LCI.Offset, 67 sizeof(MachOFormat::SymtabLoadCommand)); 68 return reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Data.data()); 69 } 70 71 void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { 72 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; 73 while (DRI.d.a < LoadCommandCount) { 74 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 75 if (LCI.Command.Type == macho::LCT_Symtab) { 76 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = 77 getSymtabLoadCommand(LCI); 78 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries) 79 return; 80 } 81 82 DRI.d.a++; 83 DRI.d.b = 0; 84 } 85 } 86 87 const MachOFormat::SymbolTableEntry * 88 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 89 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 90 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = 91 getSymtabLoadCommand(LCI); 92 93 return getSymbolTableEntry(DRI, SymtabLoadCmd); 94 } 95 96 const MachOFormat::SymbolTableEntry * 97 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI, 98 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const { 99 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset; 100 unsigned Index = DRI.d.b; 101 uint64_t Offset = (SymbolTableOffset + 102 Index * sizeof(macho::SymbolTableEntry)); 103 StringRef Data = MachOObj->getData(Offset, 104 sizeof(MachOFormat::SymbolTableEntry)); 105 return reinterpret_cast<const MachOFormat::SymbolTableEntry*>(Data.data()); 106 } 107 108 const MachOFormat::Symbol64TableEntry* 109 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 110 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 111 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = 112 getSymtabLoadCommand(LCI); 113 114 return getSymbol64TableEntry(DRI, SymtabLoadCmd); 115 } 116 117 const MachOFormat::Symbol64TableEntry* 118 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI, 119 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const { 120 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset; 121 unsigned Index = DRI.d.b; 122 uint64_t Offset = (SymbolTableOffset + 123 Index * sizeof(macho::Symbol64TableEntry)); 124 StringRef Data = MachOObj->getData(Offset, 125 sizeof(MachOFormat::Symbol64TableEntry)); 126 return reinterpret_cast<const MachOFormat::Symbol64TableEntry*>(Data.data()); 127 } 128 129 error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI, 130 SymbolRef &Result) const { 131 DRI.d.b++; 132 moveToNextSymbol(DRI); 133 Result = SymbolRef(DRI, this); 134 return object_error::success; 135 } 136 137 error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, 138 StringRef &Result) const { 139 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 140 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = 141 getSymtabLoadCommand(LCI); 142 143 StringRef StringTable = 144 MachOObj->getData(SymtabLoadCmd->StringTableOffset, 145 SymtabLoadCmd->StringTableSize); 146 147 uint32_t StringIndex; 148 if (MachOObj->is64Bit()) { 149 const MachOFormat::Symbol64TableEntry *Entry = 150 getSymbol64TableEntry(DRI, SymtabLoadCmd); 151 StringIndex = Entry->StringIndex; 152 } else { 153 const MachOFormat::SymbolTableEntry *Entry = 154 getSymbolTableEntry(DRI, SymtabLoadCmd); 155 StringIndex = Entry->StringIndex; 156 } 157 158 const char *Start = &StringTable.data()[StringIndex]; 159 Result = StringRef(Start); 160 161 return object_error::success; 162 } 163 164 error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI, 165 uint64_t &Result) const { 166 if (MachOObj->is64Bit()) { 167 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); 168 Result = Entry->Value; 169 if (Entry->SectionIndex) { 170 const MachOFormat::Section64 *Section = 171 getSection64(Sections[Entry->SectionIndex-1]); 172 Result += Section->Offset - Section->Address; 173 } 174 } else { 175 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI); 176 Result = Entry->Value; 177 if (Entry->SectionIndex) { 178 const MachOFormat::Section *Section = 179 getSection(Sections[Entry->SectionIndex-1]); 180 Result += Section->Offset - Section->Address; 181 } 182 } 183 184 return object_error::success; 185 } 186 187 error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI, 188 uint64_t &Result) const { 189 if (MachOObj->is64Bit()) { 190 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); 191 Result = Entry->Value; 192 } else { 193 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI); 194 Result = Entry->Value; 195 } 196 return object_error::success; 197 } 198 199 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, 200 uint64_t &Result) const { 201 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; 202 uint64_t BeginOffset; 203 uint64_t EndOffset = 0; 204 uint8_t SectionIndex; 205 if (MachOObj->is64Bit()) { 206 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); 207 BeginOffset = Entry->Value; 208 SectionIndex = Entry->SectionIndex; 209 if (!SectionIndex) { 210 uint32_t flags = SymbolRef::SF_None; 211 getSymbolFlags(DRI, flags); 212 if (flags & SymbolRef::SF_Common) 213 Result = Entry->Value; 214 else 215 Result = UnknownAddressOrSize; 216 return object_error::success; 217 } 218 // Unfortunately symbols are unsorted so we need to touch all 219 // symbols from load command 220 DRI.d.b = 0; 221 uint32_t Command = DRI.d.a; 222 while (Command == DRI.d.a) { 223 moveToNextSymbol(DRI); 224 if (DRI.d.a < LoadCommandCount) { 225 Entry = getSymbol64TableEntry(DRI); 226 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset) 227 if (!EndOffset || Entry->Value < EndOffset) 228 EndOffset = Entry->Value; 229 } 230 DRI.d.b++; 231 } 232 } else { 233 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI); 234 BeginOffset = Entry->Value; 235 SectionIndex = Entry->SectionIndex; 236 if (!SectionIndex) { 237 uint32_t flags = SymbolRef::SF_None; 238 getSymbolFlags(DRI, flags); 239 if (flags & SymbolRef::SF_Common) 240 Result = Entry->Value; 241 else 242 Result = UnknownAddressOrSize; 243 return object_error::success; 244 } 245 // Unfortunately symbols are unsorted so we need to touch all 246 // symbols from load command 247 DRI.d.b = 0; 248 uint32_t Command = DRI.d.a; 249 while (Command == DRI.d.a) { 250 moveToNextSymbol(DRI); 251 if (DRI.d.a < LoadCommandCount) { 252 Entry = getSymbolTableEntry(DRI); 253 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset) 254 if (!EndOffset || Entry->Value < EndOffset) 255 EndOffset = Entry->Value; 256 } 257 DRI.d.b++; 258 } 259 } 260 if (!EndOffset) { 261 uint64_t Size; 262 getSectionSize(Sections[SectionIndex-1], Size); 263 getSectionAddress(Sections[SectionIndex-1], EndOffset); 264 EndOffset += Size; 265 } 266 Result = EndOffset - BeginOffset; 267 return object_error::success; 268 } 269 270 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI, 271 char &Result) const { 272 uint8_t Type, Flags; 273 if (MachOObj->is64Bit()) { 274 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); 275 Type = Entry->Type; 276 Flags = Entry->Flags; 277 } else { 278 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI); 279 Type = Entry->Type; 280 Flags = Entry->Flags; 281 } 282 283 char Char; 284 switch (Type & macho::STF_TypeMask) { 285 case macho::STT_Undefined: 286 Char = 'u'; 287 break; 288 case macho::STT_Absolute: 289 case macho::STT_Section: 290 Char = 's'; 291 break; 292 default: 293 Char = '?'; 294 break; 295 } 296 297 if (Flags & (macho::STF_External | macho::STF_PrivateExtern)) 298 Char = toupper(static_cast<unsigned char>(Char)); 299 Result = Char; 300 return object_error::success; 301 } 302 303 error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, 304 uint32_t &Result) const { 305 uint16_t MachOFlags; 306 uint8_t MachOType; 307 if (MachOObj->is64Bit()) { 308 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); 309 MachOFlags = Entry->Flags; 310 MachOType = Entry->Type; 311 } else { 312 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI); 313 MachOFlags = Entry->Flags; 314 MachOType = Entry->Type; 315 } 316 317 // TODO: Correctly set SF_ThreadLocal 318 Result = SymbolRef::SF_None; 319 320 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) 321 Result |= SymbolRef::SF_Undefined; 322 323 if (MachOFlags & macho::STF_StabsEntryMask) 324 Result |= SymbolRef::SF_FormatSpecific; 325 326 if (MachOType & MachO::NlistMaskExternal) { 327 Result |= SymbolRef::SF_Global; 328 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) 329 Result |= SymbolRef::SF_Common; 330 } 331 332 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef)) 333 Result |= SymbolRef::SF_Weak; 334 335 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute) 336 Result |= SymbolRef::SF_Absolute; 337 338 return object_error::success; 339 } 340 341 error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, 342 section_iterator &Res) const { 343 uint8_t index; 344 if (MachOObj->is64Bit()) { 345 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb); 346 index = Entry->SectionIndex; 347 } else { 348 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb); 349 index = Entry->SectionIndex; 350 } 351 352 if (index == 0) 353 Res = end_sections(); 354 else 355 Res = section_iterator(SectionRef(Sections[index-1], this)); 356 357 return object_error::success; 358 } 359 360 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, 361 SymbolRef::Type &Res) const { 362 uint8_t n_type; 363 if (MachOObj->is64Bit()) { 364 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb); 365 n_type = Entry->Type; 366 } else { 367 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb); 368 n_type = Entry->Type; 369 } 370 Res = SymbolRef::ST_Other; 371 372 // If this is a STAB debugging symbol, we can do nothing more. 373 if (n_type & MachO::NlistMaskStab) { 374 Res = SymbolRef::ST_Debug; 375 return object_error::success; 376 } 377 378 switch (n_type & MachO::NlistMaskType) { 379 case MachO::NListTypeUndefined : 380 Res = SymbolRef::ST_Unknown; 381 break; 382 case MachO::NListTypeSection : 383 Res = SymbolRef::ST_Function; 384 break; 385 } 386 return object_error::success; 387 } 388 389 error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb, 390 uint64_t &Val) const { 391 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile"); 392 } 393 394 symbol_iterator MachOObjectFile::begin_symbols() const { 395 // DRI.d.a = segment number; DRI.d.b = symbol index. 396 DataRefImpl DRI; 397 moveToNextSymbol(DRI); 398 return symbol_iterator(SymbolRef(DRI, this)); 399 } 400 401 symbol_iterator MachOObjectFile::end_symbols() const { 402 DataRefImpl DRI; 403 DRI.d.a = MachOObj->getHeader().NumLoadCommands; 404 return symbol_iterator(SymbolRef(DRI, this)); 405 } 406 407 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const { 408 // TODO: implement 409 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); 410 } 411 412 symbol_iterator MachOObjectFile::end_dynamic_symbols() const { 413 // TODO: implement 414 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); 415 } 416 417 library_iterator MachOObjectFile::begin_libraries_needed() const { 418 // TODO: implement 419 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 420 } 421 422 library_iterator MachOObjectFile::end_libraries_needed() const { 423 // TODO: implement 424 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 425 } 426 427 StringRef MachOObjectFile::getLoadName() const { 428 // TODO: Implement 429 report_fatal_error("get_load_name() unimplemented in MachOObjectFile"); 430 } 431 432 /*===-- Sections ----------------------------------------------------------===*/ 433 434 void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { 435 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; 436 while (DRI.d.a < LoadCommandCount) { 437 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 438 if (LCI.Command.Type == macho::LCT_Segment) { 439 InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd; 440 MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd); 441 if (DRI.d.b < SegmentLoadCmd->NumSections) 442 return; 443 } else if (LCI.Command.Type == macho::LCT_Segment64) { 444 InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd; 445 MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd); 446 if (DRI.d.b < Segment64LoadCmd->NumSections) 447 return; 448 } 449 450 DRI.d.a++; 451 DRI.d.b = 0; 452 } 453 } 454 455 error_code MachOObjectFile::getSectionNext(DataRefImpl DRI, 456 SectionRef &Result) const { 457 DRI.d.b++; 458 moveToNextSection(DRI); 459 Result = SectionRef(DRI, this); 460 return object_error::success; 461 } 462 463 static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) { 464 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 465 if (LCI.Command.Type == macho::LCT_Segment64) 466 return true; 467 assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type."); 468 return false; 469 } 470 471 const MachOFormat::Section *MachOObjectFile::getSection(DataRefImpl DRI) const { 472 assert(!is64BitLoadCommand(MachOObj.get(), DRI)); 473 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 474 unsigned SectionOffset = LCI.Offset + sizeof(macho::SegmentLoadCommand) + 475 DRI.d.b * sizeof(MachOFormat::Section); 476 StringRef Data = MachOObj->getData(SectionOffset, sizeof(MachOFormat::Section)); 477 return reinterpret_cast<const MachOFormat::Section*>(Data.data()); 478 } 479 480 std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { 481 SectionList::const_iterator loc = 482 std::find(Sections.begin(), Sections.end(), Sec); 483 assert(loc != Sections.end() && "Sec is not a valid section!"); 484 return std::distance(Sections.begin(), loc); 485 } 486 487 const MachOFormat::Section64 * 488 MachOObjectFile::getSection64(DataRefImpl DRI) const { 489 assert(is64BitLoadCommand(MachOObj.get(), DRI)); 490 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); 491 unsigned SectionOffset = LCI.Offset + sizeof(macho::Segment64LoadCommand) + 492 DRI.d.b * sizeof(MachOFormat::Section64); 493 StringRef Data = MachOObj->getData(SectionOffset, sizeof(MachOFormat::Section64)); 494 return reinterpret_cast<const MachOFormat::Section64*>(Data.data()); 495 } 496 497 static StringRef parseSegmentOrSectionName(const char *P) { 498 if (P[15] == 0) 499 // Null terminated. 500 return P; 501 // Not null terminated, so this is a 16 char string. 502 return StringRef(P, 16); 503 } 504 505 ArrayRef<char> MachOObjectFile::getSectionRawName(DataRefImpl DRI) const { 506 if (is64BitLoadCommand(MachOObj.get(), DRI)) { 507 const MachOFormat::Section64 *sec = getSection64(DRI); 508 return ArrayRef<char>(sec->Name); 509 } else { 510 const MachOFormat::Section *sec = getSection(DRI); 511 return ArrayRef<char>(sec->Name); 512 } 513 } 514 515 error_code MachOObjectFile::getSectionName(DataRefImpl DRI, 516 StringRef &Result) const { 517 ArrayRef<char> Raw = getSectionRawName(DRI); 518 Result = parseSegmentOrSectionName(Raw.data()); 519 return object_error::success; 520 } 521 522 ArrayRef<char> 523 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 524 if (is64BitLoadCommand(MachOObj.get(), Sec)) { 525 const MachOFormat::Section64 *sec = getSection64(Sec); 526 return ArrayRef<char>(sec->SegmentName, 16); 527 } else { 528 const MachOFormat::Section *sec = getSection(Sec); 529 return ArrayRef<char>(sec->SegmentName); 530 } 531 } 532 533 StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const { 534 ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI); 535 return parseSegmentOrSectionName(Raw.data()); 536 } 537 538 error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, 539 uint64_t &Result) const { 540 if (is64BitLoadCommand(MachOObj.get(), DRI)) { 541 const MachOFormat::Section64 *Sect = getSection64(DRI); 542 Result = Sect->Address; 543 } else { 544 const MachOFormat::Section *Sect = getSection(DRI); 545 Result = Sect->Address; 546 } 547 return object_error::success; 548 } 549 550 error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, 551 uint64_t &Result) const { 552 if (is64BitLoadCommand(MachOObj.get(), DRI)) { 553 const MachOFormat::Section64 *Sect = getSection64(DRI); 554 Result = Sect->Size; 555 } else { 556 const MachOFormat::Section *Sect = getSection(DRI); 557 Result = Sect->Size; 558 } 559 return object_error::success; 560 } 561 562 error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, 563 StringRef &Result) const { 564 if (is64BitLoadCommand(MachOObj.get(), DRI)) { 565 const MachOFormat::Section64 *Sect = getSection64(DRI); 566 Result = MachOObj->getData(Sect->Offset, Sect->Size); 567 } else { 568 const MachOFormat::Section *Sect = getSection(DRI); 569 Result = MachOObj->getData(Sect->Offset, Sect->Size); 570 } 571 return object_error::success; 572 } 573 574 error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, 575 uint64_t &Result) const { 576 if (is64BitLoadCommand(MachOObj.get(), DRI)) { 577 const MachOFormat::Section64 *Sect = getSection64(DRI); 578 Result = uint64_t(1) << Sect->Align; 579 } else { 580 const MachOFormat::Section *Sect = getSection(DRI); 581 Result = uint64_t(1) << Sect->Align; 582 } 583 return object_error::success; 584 } 585 586 error_code MachOObjectFile::isSectionText(DataRefImpl DRI, 587 bool &Result) const { 588 if (is64BitLoadCommand(MachOObj.get(), DRI)) { 589 const MachOFormat::Section64 *Sect = getSection64(DRI); 590 Result = Sect->Flags & macho::SF_PureInstructions; 591 } else { 592 const MachOFormat::Section *Sect = getSection(DRI); 593 Result = Sect->Flags & macho::SF_PureInstructions; 594 } 595 return object_error::success; 596 } 597 598 error_code MachOObjectFile::isSectionData(DataRefImpl DRI, 599 bool &Result) const { 600 // FIXME: Unimplemented. 601 Result = false; 602 return object_error::success; 603 } 604 605 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, 606 bool &Result) const { 607 // FIXME: Unimplemented. 608 Result = false; 609 return object_error::success; 610 } 611 612 error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, 613 bool &Result) const { 614 // FIXME: Unimplemented. 615 Result = true; 616 return object_error::success; 617 } 618 619 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, 620 bool &Result) const { 621 // FIXME: Unimplemented. 622 Result = false; 623 return object_error::success; 624 } 625 626 error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI, 627 bool &Result) const { 628 if (MachOObj->is64Bit()) { 629 const MachOFormat::Section64 *Sect = getSection64(DRI); 630 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType; 631 Result = (SectionType == MachO::SectionTypeZeroFill || 632 SectionType == MachO::SectionTypeZeroFillLarge); 633 } else { 634 const MachOFormat::Section *Sect = getSection(DRI); 635 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType; 636 Result = (SectionType == MachO::SectionTypeZeroFill || 637 SectionType == MachO::SectionTypeZeroFillLarge); 638 } 639 640 return object_error::success; 641 } 642 643 error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, 644 bool &Result) const { 645 // Consider using the code from isSectionText to look for __const sections. 646 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS 647 // to use section attributes to distinguish code from data. 648 649 // FIXME: Unimplemented. 650 Result = false; 651 return object_error::success; 652 } 653 654 error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, 655 DataRefImpl Symb, 656 bool &Result) const { 657 SymbolRef::Type ST; 658 getSymbolType(Symb, ST); 659 if (ST == SymbolRef::ST_Unknown) { 660 Result = false; 661 return object_error::success; 662 } 663 664 uint64_t SectBegin, SectEnd; 665 getSectionAddress(Sec, SectBegin); 666 getSectionSize(Sec, SectEnd); 667 SectEnd += SectBegin; 668 669 if (MachOObj->is64Bit()) { 670 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb); 671 uint64_t SymAddr= Entry->Value; 672 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 673 } else { 674 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb); 675 uint64_t SymAddr= Entry->Value; 676 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 677 } 678 679 return object_error::success; 680 } 681 682 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { 683 DataRefImpl ret; 684 ret.d.b = getSectionIndex(Sec); 685 return relocation_iterator(RelocationRef(ret, this)); 686 } 687 relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { 688 uint32_t last_reloc; 689 if (is64BitLoadCommand(MachOObj.get(), Sec)) { 690 const MachOFormat::Section64 *Sect = getSection64(Sec); 691 last_reloc = Sect->NumRelocationTableEntries; 692 } else { 693 const MachOFormat::Section *Sect = getSection(Sec); 694 last_reloc = Sect->NumRelocationTableEntries; 695 } 696 DataRefImpl ret; 697 ret.d.a = last_reloc; 698 ret.d.b = getSectionIndex(Sec); 699 return relocation_iterator(RelocationRef(ret, this)); 700 } 701 702 section_iterator MachOObjectFile::begin_sections() const { 703 DataRefImpl DRI; 704 moveToNextSection(DRI); 705 return section_iterator(SectionRef(DRI, this)); 706 } 707 708 section_iterator MachOObjectFile::end_sections() const { 709 DataRefImpl DRI; 710 DRI.d.a = MachOObj->getHeader().NumLoadCommands; 711 return section_iterator(SectionRef(DRI, this)); 712 } 713 714 /*===-- Relocations -------------------------------------------------------===*/ 715 716 const MachOFormat::RelocationEntry * 717 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 718 uint32_t relOffset; 719 if (MachOObj->is64Bit()) { 720 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]); 721 relOffset = Sect->RelocationTableOffset; 722 } else { 723 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]); 724 relOffset = Sect->RelocationTableOffset; 725 } 726 uint64_t Offset = relOffset + Rel.d.a * sizeof(MachOFormat::RelocationEntry); 727 StringRef Data = 728 MachOObj->getData(Offset, sizeof(MachOFormat::RelocationEntry)); 729 return reinterpret_cast<const MachOFormat::RelocationEntry*>(Data.data()); 730 } 731 732 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, 733 RelocationRef &Res) const { 734 ++Rel.d.a; 735 Res = RelocationRef(Rel, this); 736 return object_error::success; 737 } 738 error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, 739 uint64_t &Res) const { 740 const uint8_t* sectAddress = 0; 741 if (MachOObj->is64Bit()) { 742 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]); 743 sectAddress += Sect->Address; 744 } else { 745 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]); 746 sectAddress += Sect->Address; 747 } 748 const MachOFormat::RelocationEntry *RE = getRelocation(Rel); 749 750 unsigned Arch = getArch(); 751 bool isScattered = (Arch != Triple::x86_64) && 752 (RE->Word0 & macho::RF_Scattered); 753 uint64_t RelAddr = 0; 754 if (isScattered) 755 RelAddr = RE->Word0 & 0xFFFFFF; 756 else 757 RelAddr = RE->Word0; 758 759 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr); 760 return object_error::success; 761 } 762 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, 763 uint64_t &Res) const { 764 const MachOFormat::RelocationEntry *RE = getRelocation(Rel); 765 766 unsigned Arch = getArch(); 767 bool isScattered = (Arch != Triple::x86_64) && 768 (RE->Word0 & macho::RF_Scattered); 769 if (isScattered) 770 Res = RE->Word0 & 0xFFFFFF; 771 else 772 Res = RE->Word0; 773 return object_error::success; 774 } 775 error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, 776 SymbolRef &Res) const { 777 const MachOFormat::RelocationEntry *RE = getRelocation(Rel); 778 uint32_t SymbolIdx = RE->Word1 & 0xffffff; 779 bool isExtern = (RE->Word1 >> 27) & 1; 780 781 DataRefImpl Sym; 782 moveToNextSymbol(Sym); 783 if (isExtern) { 784 for (unsigned i = 0; i < SymbolIdx; i++) { 785 Sym.d.b++; 786 moveToNextSymbol(Sym); 787 assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands && 788 "Relocation symbol index out of range!"); 789 } 790 } 791 Res = SymbolRef(Sym, this); 792 return object_error::success; 793 } 794 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, 795 uint64_t &Res) const { 796 const MachOFormat::RelocationEntry *RE = getRelocation(Rel); 797 Res = RE->Word0; 798 Res <<= 32; 799 Res |= RE->Word1; 800 return object_error::success; 801 } 802 error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, 803 SmallVectorImpl<char> &Result) const { 804 // TODO: Support scattered relocations. 805 StringRef res; 806 const MachOFormat::RelocationEntry *RE = getRelocation(Rel); 807 808 unsigned Arch = getArch(); 809 bool isScattered = (Arch != Triple::x86_64) && 810 (RE->Word0 & macho::RF_Scattered); 811 812 unsigned r_type; 813 if (isScattered) 814 r_type = (RE->Word0 >> 24) & 0xF; 815 else 816 r_type = (RE->Word1 >> 28) & 0xF; 817 818 switch (Arch) { 819 case Triple::x86: { 820 static const char *const Table[] = { 821 "GENERIC_RELOC_VANILLA", 822 "GENERIC_RELOC_PAIR", 823 "GENERIC_RELOC_SECTDIFF", 824 "GENERIC_RELOC_PB_LA_PTR", 825 "GENERIC_RELOC_LOCAL_SECTDIFF", 826 "GENERIC_RELOC_TLV" }; 827 828 if (r_type > 6) 829 res = "Unknown"; 830 else 831 res = Table[r_type]; 832 break; 833 } 834 case Triple::x86_64: { 835 static const char *const Table[] = { 836 "X86_64_RELOC_UNSIGNED", 837 "X86_64_RELOC_SIGNED", 838 "X86_64_RELOC_BRANCH", 839 "X86_64_RELOC_GOT_LOAD", 840 "X86_64_RELOC_GOT", 841 "X86_64_RELOC_SUBTRACTOR", 842 "X86_64_RELOC_SIGNED_1", 843 "X86_64_RELOC_SIGNED_2", 844 "X86_64_RELOC_SIGNED_4", 845 "X86_64_RELOC_TLV" }; 846 847 if (r_type > 9) 848 res = "Unknown"; 849 else 850 res = Table[r_type]; 851 break; 852 } 853 case Triple::arm: { 854 static const char *const Table[] = { 855 "ARM_RELOC_VANILLA", 856 "ARM_RELOC_PAIR", 857 "ARM_RELOC_SECTDIFF", 858 "ARM_RELOC_LOCAL_SECTDIFF", 859 "ARM_RELOC_PB_LA_PTR", 860 "ARM_RELOC_BR24", 861 "ARM_THUMB_RELOC_BR22", 862 "ARM_THUMB_32BIT_BRANCH", 863 "ARM_RELOC_HALF", 864 "ARM_RELOC_HALF_SECTDIFF" }; 865 866 if (r_type > 9) 867 res = "Unknown"; 868 else 869 res = Table[r_type]; 870 break; 871 } 872 case Triple::ppc: { 873 static const char *const Table[] = { 874 "PPC_RELOC_VANILLA", 875 "PPC_RELOC_PAIR", 876 "PPC_RELOC_BR14", 877 "PPC_RELOC_BR24", 878 "PPC_RELOC_HI16", 879 "PPC_RELOC_LO16", 880 "PPC_RELOC_HA16", 881 "PPC_RELOC_LO14", 882 "PPC_RELOC_SECTDIFF", 883 "PPC_RELOC_PB_LA_PTR", 884 "PPC_RELOC_HI16_SECTDIFF", 885 "PPC_RELOC_LO16_SECTDIFF", 886 "PPC_RELOC_HA16_SECTDIFF", 887 "PPC_RELOC_JBSR", 888 "PPC_RELOC_LO14_SECTDIFF", 889 "PPC_RELOC_LOCAL_SECTDIFF" }; 890 891 res = Table[r_type]; 892 break; 893 } 894 case Triple::UnknownArch: 895 res = "Unknown"; 896 break; 897 } 898 Result.append(res.begin(), res.end()); 899 return object_error::success; 900 } 901 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, 902 int64_t &Res) const { 903 const MachOFormat::RelocationEntry *RE = getRelocation(Rel); 904 bool isExtern = (RE->Word1 >> 27) & 1; 905 Res = 0; 906 if (!isExtern) { 907 const uint8_t* sectAddress = base(); 908 if (MachOObj->is64Bit()) { 909 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]); 910 sectAddress += Sect->Offset; 911 } else { 912 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]); 913 sectAddress += Sect->Offset; 914 } 915 Res = reinterpret_cast<uintptr_t>(sectAddress); 916 } 917 return object_error::success; 918 } 919 920 // Helper to advance a section or symbol iterator multiple increments at a time. 921 template<class T> 922 error_code advance(T &it, size_t Val) { 923 error_code ec; 924 while (Val--) { 925 it.increment(ec); 926 } 927 return ec; 928 } 929 930 template<class T> 931 void advanceTo(T &it, size_t Val) { 932 if (error_code ec = advance(it, Val)) 933 report_fatal_error(ec.message()); 934 } 935 936 void MachOObjectFile::printRelocationTargetName( 937 const MachOFormat::RelocationEntry *RE, 938 raw_string_ostream &fmt) const { 939 unsigned Arch = getArch(); 940 bool isScattered = (Arch != Triple::x86_64) && 941 (RE->Word0 & macho::RF_Scattered); 942 943 // Target of a scattered relocation is an address. In the interest of 944 // generating pretty output, scan through the symbol table looking for a 945 // symbol that aligns with that address. If we find one, print it. 946 // Otherwise, we just print the hex address of the target. 947 if (isScattered) { 948 uint32_t Val = RE->Word1; 949 950 error_code ec; 951 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE; 952 SI.increment(ec)) { 953 if (ec) report_fatal_error(ec.message()); 954 955 uint64_t Addr; 956 StringRef Name; 957 958 if ((ec = SI->getAddress(Addr))) 959 report_fatal_error(ec.message()); 960 if (Addr != Val) continue; 961 if ((ec = SI->getName(Name))) 962 report_fatal_error(ec.message()); 963 fmt << Name; 964 return; 965 } 966 967 // If we couldn't find a symbol that this relocation refers to, try 968 // to find a section beginning instead. 969 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE; 970 SI.increment(ec)) { 971 if (ec) report_fatal_error(ec.message()); 972 973 uint64_t Addr; 974 StringRef Name; 975 976 if ((ec = SI->getAddress(Addr))) 977 report_fatal_error(ec.message()); 978 if (Addr != Val) continue; 979 if ((ec = SI->getName(Name))) 980 report_fatal_error(ec.message()); 981 fmt << Name; 982 return; 983 } 984 985 fmt << format("0x%x", Val); 986 return; 987 } 988 989 StringRef S; 990 bool isExtern = (RE->Word1 >> 27) & 1; 991 uint32_t Val = RE->Word1 & 0xFFFFFF; 992 993 if (isExtern) { 994 symbol_iterator SI = begin_symbols(); 995 advanceTo(SI, Val); 996 SI->getName(S); 997 } else { 998 section_iterator SI = begin_sections(); 999 advanceTo(SI, Val); 1000 SI->getName(S); 1001 } 1002 1003 fmt << S; 1004 } 1005 1006 error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel, 1007 SmallVectorImpl<char> &Result) const { 1008 const MachOFormat::RelocationEntry *RE = getRelocation(Rel); 1009 1010 unsigned Arch = getArch(); 1011 bool isScattered = (Arch != Triple::x86_64) && 1012 (RE->Word0 & macho::RF_Scattered); 1013 1014 std::string fmtbuf; 1015 raw_string_ostream fmt(fmtbuf); 1016 1017 unsigned Type; 1018 if (isScattered) 1019 Type = (RE->Word0 >> 24) & 0xF; 1020 else 1021 Type = (RE->Word1 >> 28) & 0xF; 1022 1023 bool isPCRel; 1024 if (isScattered) 1025 isPCRel = ((RE->Word0 >> 30) & 1); 1026 else 1027 isPCRel = ((RE->Word1 >> 24) & 1); 1028 1029 // Determine any addends that should be displayed with the relocation. 1030 // These require decoding the relocation type, which is triple-specific. 1031 1032 // X86_64 has entirely custom relocation types. 1033 if (Arch == Triple::x86_64) { 1034 bool isPCRel = ((RE->Word1 >> 24) & 1); 1035 1036 switch (Type) { 1037 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD 1038 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT 1039 printRelocationTargetName(RE, fmt); 1040 fmt << "@GOT"; 1041 if (isPCRel) fmt << "PCREL"; 1042 break; 1043 } 1044 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR 1045 DataRefImpl RelNext = Rel; 1046 RelNext.d.a++; 1047 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext); 1048 1049 // X86_64_SUBTRACTOR must be followed by a relocation of type 1050 // X86_64_RELOC_UNSIGNED. 1051 // NOTE: Scattered relocations don't exist on x86_64. 1052 unsigned RType = (RENext->Word1 >> 28) & 0xF; 1053 if (RType != 0) 1054 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " 1055 "X86_64_RELOC_SUBTRACTOR."); 1056 1057 // The X86_64_RELOC_UNSIGNED contains the minuend symbol, 1058 // X86_64_SUBTRACTOR contains to the subtrahend. 1059 printRelocationTargetName(RENext, fmt); 1060 fmt << "-"; 1061 printRelocationTargetName(RE, fmt); 1062 break; 1063 } 1064 case macho::RIT_X86_64_TLV: 1065 printRelocationTargetName(RE, fmt); 1066 fmt << "@TLV"; 1067 if (isPCRel) fmt << "P"; 1068 break; 1069 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1 1070 printRelocationTargetName(RE, fmt); 1071 fmt << "-1"; 1072 break; 1073 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2 1074 printRelocationTargetName(RE, fmt); 1075 fmt << "-2"; 1076 break; 1077 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4 1078 printRelocationTargetName(RE, fmt); 1079 fmt << "-4"; 1080 break; 1081 default: 1082 printRelocationTargetName(RE, fmt); 1083 break; 1084 } 1085 // X86 and ARM share some relocation types in common. 1086 } else if (Arch == Triple::x86 || Arch == Triple::arm) { 1087 // Generic relocation types... 1088 switch (Type) { 1089 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info 1090 return object_error::success; 1091 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF 1092 DataRefImpl RelNext = Rel; 1093 RelNext.d.a++; 1094 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext); 1095 1096 // X86 sect diff's must be followed by a relocation of type 1097 // GENERIC_RELOC_PAIR. 1098 bool isNextScattered = (Arch != Triple::x86_64) && 1099 (RENext->Word0 & macho::RF_Scattered); 1100 unsigned RType; 1101 if (isNextScattered) 1102 RType = (RENext->Word0 >> 24) & 0xF; 1103 else 1104 RType = (RENext->Word1 >> 28) & 0xF; 1105 if (RType != 1) 1106 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 1107 "GENERIC_RELOC_SECTDIFF."); 1108 1109 printRelocationTargetName(RE, fmt); 1110 fmt << "-"; 1111 printRelocationTargetName(RENext, fmt); 1112 break; 1113 } 1114 } 1115 1116 if (Arch == Triple::x86) { 1117 // All X86 relocations that need special printing were already 1118 // handled in the generic code. 1119 switch (Type) { 1120 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF 1121 DataRefImpl RelNext = Rel; 1122 RelNext.d.a++; 1123 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext); 1124 1125 // X86 sect diff's must be followed by a relocation of type 1126 // GENERIC_RELOC_PAIR. 1127 bool isNextScattered = (Arch != Triple::x86_64) && 1128 (RENext->Word0 & macho::RF_Scattered); 1129 unsigned RType; 1130 if (isNextScattered) 1131 RType = (RENext->Word0 >> 24) & 0xF; 1132 else 1133 RType = (RENext->Word1 >> 28) & 0xF; 1134 if (RType != 1) 1135 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 1136 "GENERIC_RELOC_LOCAL_SECTDIFF."); 1137 1138 printRelocationTargetName(RE, fmt); 1139 fmt << "-"; 1140 printRelocationTargetName(RENext, fmt); 1141 break; 1142 } 1143 case macho::RIT_Generic_TLV: { 1144 printRelocationTargetName(RE, fmt); 1145 fmt << "@TLV"; 1146 if (isPCRel) fmt << "P"; 1147 break; 1148 } 1149 default: 1150 printRelocationTargetName(RE, fmt); 1151 } 1152 } else { // ARM-specific relocations 1153 switch (Type) { 1154 case macho::RIT_ARM_Half: // ARM_RELOC_HALF 1155 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF 1156 // Half relocations steal a bit from the length field to encode 1157 // whether this is an upper16 or a lower16 relocation. 1158 bool isUpper; 1159 if (isScattered) 1160 isUpper = (RE->Word0 >> 28) & 1; 1161 else 1162 isUpper = (RE->Word1 >> 25) & 1; 1163 1164 if (isUpper) 1165 fmt << ":upper16:("; 1166 else 1167 fmt << ":lower16:("; 1168 printRelocationTargetName(RE, fmt); 1169 1170 DataRefImpl RelNext = Rel; 1171 RelNext.d.a++; 1172 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext); 1173 1174 // ARM half relocs must be followed by a relocation of type 1175 // ARM_RELOC_PAIR. 1176 bool isNextScattered = (Arch != Triple::x86_64) && 1177 (RENext->Word0 & macho::RF_Scattered); 1178 unsigned RType; 1179 if (isNextScattered) 1180 RType = (RENext->Word0 >> 24) & 0xF; 1181 else 1182 RType = (RENext->Word1 >> 28) & 0xF; 1183 1184 if (RType != 1) 1185 report_fatal_error("Expected ARM_RELOC_PAIR after " 1186 "GENERIC_RELOC_HALF"); 1187 1188 // NOTE: The half of the target virtual address is stashed in the 1189 // address field of the secondary relocation, but we can't reverse 1190 // engineer the constant offset from it without decoding the movw/movt 1191 // instruction to find the other half in its immediate field. 1192 1193 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the 1194 // symbol/section pointer of the follow-on relocation. 1195 if (Type == macho::RIT_ARM_HalfDifference) { 1196 fmt << "-"; 1197 printRelocationTargetName(RENext, fmt); 1198 } 1199 1200 fmt << ")"; 1201 break; 1202 } 1203 default: { 1204 printRelocationTargetName(RE, fmt); 1205 } 1206 } 1207 } 1208 } else 1209 printRelocationTargetName(RE, fmt); 1210 1211 fmt.flush(); 1212 Result.append(fmtbuf.begin(), fmtbuf.end()); 1213 return object_error::success; 1214 } 1215 1216 error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, 1217 bool &Result) const { 1218 const MachOFormat::RelocationEntry *RE = getRelocation(Rel); 1219 1220 unsigned Arch = getArch(); 1221 bool isScattered = (Arch != Triple::x86_64) && 1222 (RE->Word0 & macho::RF_Scattered); 1223 unsigned Type; 1224 if (isScattered) 1225 Type = (RE->Word0 >> 24) & 0xF; 1226 else 1227 Type = (RE->Word1 >> 28) & 0xF; 1228 1229 Result = false; 1230 1231 // On arches that use the generic relocations, GENERIC_RELOC_PAIR 1232 // is always hidden. 1233 if (Arch == Triple::x86 || Arch == Triple::arm) { 1234 if (Type == macho::RIT_Pair) Result = true; 1235 } else if (Arch == Triple::x86_64) { 1236 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows 1237 // an X864_64_RELOC_SUBTRACTOR. 1238 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) { 1239 DataRefImpl RelPrev = Rel; 1240 RelPrev.d.a--; 1241 const MachOFormat::RelocationEntry *REPrev = getRelocation(RelPrev); 1242 1243 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF; 1244 1245 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true; 1246 } 1247 } 1248 1249 return object_error::success; 1250 } 1251 1252 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData, 1253 LibraryRef &Res) const { 1254 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1255 } 1256 1257 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, 1258 StringRef &Res) const { 1259 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1260 } 1261 1262 1263 /*===-- Miscellaneous -----------------------------------------------------===*/ 1264 1265 uint8_t MachOObjectFile::getBytesInAddress() const { 1266 return MachOObj->is64Bit() ? 8 : 4; 1267 } 1268 1269 StringRef MachOObjectFile::getFileFormatName() const { 1270 if (!MachOObj->is64Bit()) { 1271 switch (MachOObj->getHeader().CPUType) { 1272 case llvm::MachO::CPUTypeI386: 1273 return "Mach-O 32-bit i386"; 1274 case llvm::MachO::CPUTypeARM: 1275 return "Mach-O arm"; 1276 case llvm::MachO::CPUTypePowerPC: 1277 return "Mach-O 32-bit ppc"; 1278 default: 1279 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 && 1280 "64-bit object file when we're not 64-bit?"); 1281 return "Mach-O 32-bit unknown"; 1282 } 1283 } 1284 1285 // Make sure the cpu type has the correct mask. 1286 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) 1287 == llvm::MachO::CPUArchABI64 && 1288 "32-bit object file when we're 64-bit?"); 1289 1290 switch (MachOObj->getHeader().CPUType) { 1291 case llvm::MachO::CPUTypeX86_64: 1292 return "Mach-O 64-bit x86-64"; 1293 case llvm::MachO::CPUTypePowerPC64: 1294 return "Mach-O 64-bit ppc64"; 1295 default: 1296 return "Mach-O 64-bit unknown"; 1297 } 1298 } 1299 1300 unsigned MachOObjectFile::getArch() const { 1301 switch (MachOObj->getHeader().CPUType) { 1302 case llvm::MachO::CPUTypeI386: 1303 return Triple::x86; 1304 case llvm::MachO::CPUTypeX86_64: 1305 return Triple::x86_64; 1306 case llvm::MachO::CPUTypeARM: 1307 return Triple::arm; 1308 case llvm::MachO::CPUTypePowerPC: 1309 return Triple::ppc; 1310 case llvm::MachO::CPUTypePowerPC64: 1311 return Triple::ppc64; 1312 default: 1313 return Triple::UnknownArch; 1314 } 1315 } 1316 1317 } // end namespace object 1318 } // end namespace llvm 1319