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