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