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