MachO.h revision e292347503cd7598429c08f9984ab3e0a44ab8a3
1//===- MachO.h - MachO object file implementation ---------------*- 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 declares the MachOObjectFile class, which binds the MachOObject 11// class to the generic ObjectFile wrapper. 12// 13//===----------------------------------------------------------------------===// 14 15#ifndef LLVM_OBJECT_MACHO_H 16#define LLVM_OBJECT_MACHO_H 17 18#include "llvm/ADT/ArrayRef.h" 19#include "llvm/ADT/SmallVector.h" 20#include "llvm/ADT/Triple.h" 21#include "llvm/Object/MachOFormat.h" 22#include "llvm/Object/ObjectFile.h" 23#include "llvm/Support/Endian.h" 24#include "llvm/Support/MachO.h" 25#include "llvm/Support/raw_ostream.h" 26 27namespace llvm { 28namespace object { 29 30using support::endianness; 31 32template<endianness E, bool B> 33struct MachOType { 34 static const endianness TargetEndianness = E; 35 static const bool Is64Bits = B; 36}; 37 38template<endianness TargetEndianness> 39struct MachODataTypeTypedefHelperCommon { 40 typedef support::detail::packed_endian_specific_integral 41 <uint16_t, TargetEndianness, support::unaligned> MachOInt16; 42 typedef support::detail::packed_endian_specific_integral 43 <uint32_t, TargetEndianness, support::unaligned> MachOInt32; 44 typedef support::detail::packed_endian_specific_integral 45 <uint64_t, TargetEndianness, support::unaligned> MachOInt64; 46}; 47 48#define LLVM_MACHOB_IMPORT_TYPES(E) \ 49typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt16 MachOInt16; \ 50typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt32 MachOInt32; \ 51typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt64 MachOInt64; 52 53template<class MachOT> 54struct MachODataTypeTypedefHelper; 55 56template<endianness TargetEndianness> 57struct MachODataTypeTypedefHelper<MachOType<TargetEndianness, false> > { 58 typedef MachODataTypeTypedefHelperCommon<TargetEndianness> Base; 59 typedef typename Base::MachOInt32 MachOIntPtr; 60}; 61 62template<endianness TargetEndianness> 63struct MachODataTypeTypedefHelper<MachOType<TargetEndianness, true> > { 64 typedef MachODataTypeTypedefHelperCommon<TargetEndianness> Base; 65 typedef typename Base::MachOInt64 MachOIntPtr; 66}; 67 68#define LLVM_MACHO_IMPORT_TYPES(MachOT, E, B) \ 69LLVM_MACHOB_IMPORT_TYPES(E) \ 70typedef typename \ 71 MachODataTypeTypedefHelper <MachOT<E, B> >::MachOIntPtr MachOIntPtr; 72 73namespace MachOFormat { 74 struct SectionBase { 75 char Name[16]; 76 char SegmentName[16]; 77 }; 78 79 template<class MachOT> 80 struct Section; 81 82 template<endianness TargetEndianness> 83 struct Section<MachOType<TargetEndianness, false> > { 84 LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) 85 char Name[16]; 86 char SegmentName[16]; 87 MachOInt32 Address; 88 MachOInt32 Size; 89 MachOInt32 Offset; 90 MachOInt32 Align; 91 MachOInt32 RelocationTableOffset; 92 MachOInt32 NumRelocationTableEntries; 93 MachOInt32 Flags; 94 MachOInt32 Reserved1; 95 MachOInt32 Reserved2; 96 }; 97 98 template<endianness TargetEndianness> 99 struct Section<MachOType<TargetEndianness, true> > { 100 LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) 101 char Name[16]; 102 char SegmentName[16]; 103 MachOInt64 Address; 104 MachOInt64 Size; 105 MachOInt32 Offset; 106 MachOInt32 Align; 107 MachOInt32 RelocationTableOffset; 108 MachOInt32 NumRelocationTableEntries; 109 MachOInt32 Flags; 110 MachOInt32 Reserved1; 111 MachOInt32 Reserved2; 112 MachOInt32 Reserved3; 113 }; 114 115 struct MachOInt24 { 116 uint8_t bytes[3]; 117 operator uint32_t() const { 118 return (bytes[2] << 24) | (bytes[1] << 16) | bytes[0]; 119 } 120 }; 121 122 template<endianness TargetEndianness> 123 struct RelocationEntry { 124 LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) 125 MachOInt32 Address; 126 MachOInt24 SymbolNum; 127 uint8_t Bits; 128 129 unsigned getPCRel() const { 130 return Bits & 0x1; 131 } 132 unsigned getLength() const { 133 return (Bits >> 1) & 0x3; 134 } 135 unsigned getExternal() const { 136 return (Bits >> 3) & 0x1; 137 } 138 unsigned getType() const { 139 return Bits >> 4; 140 } 141 }; 142 143 template<endianness TargetEndianness> 144 struct ScatteredRelocationEntry { 145 LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) 146 MachOInt24 Address; 147 uint8_t Bits; 148 MachOInt32 Value; 149 150 unsigned getType() const { 151 return Bits & 0xf; 152 } 153 unsigned getLength() const { 154 return (Bits >> 4) & 0x3; 155 } 156 unsigned getPCRel() const { 157 return (Bits >> 6) & 0x1; 158 } 159 unsigned getScattered() const { 160 return Bits >> 7; 161 } 162 }; 163 164 template<endianness TargetEndianness> 165 struct SymbolTableEntryBase { 166 LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) 167 MachOInt32 StringIndex; 168 uint8_t Type; 169 uint8_t SectionIndex; 170 MachOInt16 Flags; 171 }; 172 173 template<class MachOT> 174 struct SymbolTableEntry; 175 176 template<endianness TargetEndianness, bool Is64Bits> 177 struct SymbolTableEntry<MachOType<TargetEndianness, Is64Bits> > { 178 LLVM_MACHO_IMPORT_TYPES(MachOType, TargetEndianness, Is64Bits) 179 MachOInt32 StringIndex; 180 uint8_t Type; 181 uint8_t SectionIndex; 182 MachOInt16 Flags; 183 MachOIntPtr Value; 184 }; 185 186 template<endianness TargetEndianness> 187 struct LoadCommand { 188 LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) 189 MachOInt32 Type; 190 MachOInt32 Size; 191 }; 192 193 template<endianness TargetEndianness> 194 struct SymtabLoadCommand { 195 LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) 196 MachOInt32 Type; 197 MachOInt32 Size; 198 MachOInt32 SymbolTableOffset; 199 MachOInt32 NumSymbolTableEntries; 200 MachOInt32 StringTableOffset; 201 MachOInt32 StringTableSize; 202 }; 203 204 template<class MachOT> 205 struct SegmentLoadCommand; 206 207 template<endianness TargetEndianness, bool Is64Bits> 208 struct SegmentLoadCommand<MachOType<TargetEndianness, Is64Bits> > { 209 LLVM_MACHO_IMPORT_TYPES(MachOType, TargetEndianness, Is64Bits) 210 MachOInt32 Type; 211 MachOInt32 Size; 212 char Name[16]; 213 MachOIntPtr VMAddress; 214 MachOIntPtr VMSize; 215 MachOIntPtr FileOffset; 216 MachOIntPtr FileSize; 217 MachOInt32 MaxVMProtection; 218 MachOInt32 InitialVMProtection; 219 MachOInt32 NumSections; 220 MachOInt32 Flags; 221 }; 222 223 template<endianness TargetEndianness> 224 struct LinkeditDataLoadCommand { 225 LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) 226 MachOInt32 Type; 227 MachOInt32 Size; 228 MachOInt32 DataOffset; 229 MachOInt32 DataSize; 230 }; 231 232 template<endianness TargetEndianness> 233 struct Header { 234 LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) 235 MachOInt32 Magic; 236 MachOInt32 CPUType; 237 MachOInt32 CPUSubtype; 238 MachOInt32 FileType; 239 MachOInt32 NumLoadCommands; 240 MachOInt32 SizeOfLoadCommands; 241 MachOInt32 Flags; 242 }; 243} 244 245class MachOObjectFileBase : public ObjectFile { 246public: 247 typedef MachOFormat::SymbolTableEntryBase<support::little> 248 SymbolTableEntryBase; 249 typedef MachOFormat::SymtabLoadCommand<support::little> SymtabLoadCommand; 250 typedef MachOFormat::RelocationEntry<support::little> RelocationEntry; 251 typedef MachOFormat::ScatteredRelocationEntry<support::little> 252 ScatteredRelocationEntry; 253 typedef MachOFormat::SectionBase SectionBase; 254 typedef MachOFormat::LoadCommand<support::little> LoadCommand; 255 typedef MachOFormat::Header<support::little> Header; 256 typedef MachOFormat::LinkeditDataLoadCommand<support::little> 257 LinkeditDataLoadCommand; 258 259 MachOObjectFileBase(MemoryBuffer *Object, bool Is64Bits, error_code &ec); 260 261 virtual symbol_iterator begin_symbols() const; 262 virtual symbol_iterator end_symbols() const; 263 virtual symbol_iterator begin_dynamic_symbols() const; 264 virtual symbol_iterator end_dynamic_symbols() const; 265 virtual library_iterator begin_libraries_needed() const; 266 virtual library_iterator end_libraries_needed() const; 267 virtual section_iterator end_sections() const; 268 269 virtual uint8_t getBytesInAddress() const; 270 virtual StringRef getFileFormatName() const; 271 virtual unsigned getArch() const; 272 virtual StringRef getLoadName() const; 273 274 // In a MachO file, sections have a segment name. This is used in the .o 275 // files. They have a single segment, but this field specifies which segment 276 // a section should be put in in the final object. 277 StringRef getSectionFinalSegmentName(DataRefImpl Sec) const; 278 279 // Names are stored as 16 bytes. These returns the raw 16 bytes without 280 // interpreting them as a C string. 281 ArrayRef<char> getSectionRawName(DataRefImpl Sec) const; 282 ArrayRef<char>getSectionRawFinalSegmentName(DataRefImpl Sec) const; 283 284 bool is64Bit() const; 285 const LoadCommand *getLoadCommandInfo(unsigned Index) const; 286 void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const; 287 const Header *getHeader() const; 288 unsigned getHeaderSize() const; 289 StringRef getData(size_t Offset, size_t Size) const; 290 const RelocationEntry *getRelocation(DataRefImpl Rel) const; 291 bool isScattered(const RelocationEntry *RE) const; 292 bool isPCRel(const RelocationEntry *RE) const; 293 unsigned getLength(const RelocationEntry *RE) const; 294 unsigned getType(const RelocationEntry *RE) const; 295 296 static inline bool classof(const Binary *v) { 297 return v->isMachO(); 298 } 299 300protected: 301 virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; 302 virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; 303 virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; 304 virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; 305 virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; 306 virtual error_code getSymbolSection(DataRefImpl Symb, 307 section_iterator &Res) const; 308 virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; 309 virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; 310 virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; 311 virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; 312 virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, 313 bool &Res) const; 314 virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; 315 virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; 316 virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; 317 318 virtual error_code getRelocationNext(DataRefImpl Rel, 319 RelocationRef &Res) const; 320 321 virtual error_code getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const; 322 virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const; 323 virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, 324 int64_t &Res) const; 325 326 std::size_t getSectionIndex(DataRefImpl Sec) const; 327 328 typedef SmallVector<DataRefImpl, 1> SectionList; 329 SectionList Sections; 330 331 void moveToNextSymbol(DataRefImpl &DRI) const; 332 void printRelocationTargetName(const RelocationEntry *RE, 333 raw_string_ostream &fmt) const; 334 const SectionBase *getSectionBase(DataRefImpl DRI) const; 335 const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI) const; 336 337private: 338 339 const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI, 340 const SymtabLoadCommand *SymtabLoadCmd) const; 341}; 342 343template<class MachOT> 344struct MachOObjectFileHelperCommon; 345 346template<endianness TargetEndianness, bool Is64Bits> 347struct MachOObjectFileHelperCommon<MachOType<TargetEndianness, Is64Bits> > { 348 typedef 349 MachOFormat::SegmentLoadCommand<MachOType<TargetEndianness, Is64Bits> > 350 SegmentLoadCommand; 351 typedef MachOFormat::SymbolTableEntry<MachOType<TargetEndianness, Is64Bits> > 352 SymbolTableEntry; 353 typedef MachOFormat::Section<MachOType<TargetEndianness, Is64Bits> > Section; 354}; 355 356template<class MachOT> 357struct MachOObjectFileHelper; 358 359template<endianness TargetEndianness> 360struct MachOObjectFileHelper<MachOType<TargetEndianness, false> > : 361 public MachOObjectFileHelperCommon<MachOType<TargetEndianness, false> > { 362 static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment; 363}; 364 365template<endianness TargetEndianness> 366struct MachOObjectFileHelper<MachOType<TargetEndianness, true> > : 367 public MachOObjectFileHelperCommon<MachOType<TargetEndianness, true> > { 368 static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment64; 369}; 370 371template<class MachOT> 372class MachOObjectFile : public MachOObjectFileBase { 373public: 374 static const endianness TargetEndianness = MachOT::TargetEndianness; 375 static const bool Is64Bits = MachOT::Is64Bits; 376 377 typedef MachOObjectFileHelper<MachOT> Helper; 378 static const macho::LoadCommandType SegmentLoadType = Helper::SegmentLoadType; 379 typedef typename Helper::SegmentLoadCommand SegmentLoadCommand; 380 typedef typename Helper::SymbolTableEntry SymbolTableEntry; 381 typedef typename Helper::Section Section; 382 383 MachOObjectFile(MemoryBuffer *Object, error_code &ec); 384 static bool classof(const Binary *v); 385 386 const Section *getSection(DataRefImpl DRI) const; 387 const SymbolTableEntry *getSymbolTableEntry(DataRefImpl DRI) const; 388 const RelocationEntry *getRelocation(DataRefImpl Rel) const; 389 390 virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; 391 virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; 392 virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; 393 virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; 394 virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; 395 virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; 396 virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; 397 virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const; 398 virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; 399 virtual error_code getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const; 400 virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const; 401 virtual error_code getRelocationTypeName(DataRefImpl Rel, 402 SmallVectorImpl<char> &Result) const; 403 virtual error_code getRelocationValueString(DataRefImpl Rel, 404 SmallVectorImpl<char> &Result) const; 405 virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const; 406 virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; 407 virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, 408 bool &Result) const; 409 virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; 410 virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; 411 virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; 412 virtual section_iterator begin_sections() const; 413 void moveToNextSection(DataRefImpl &DRI) const; 414}; 415 416template<class MachOT> 417MachOObjectFile<MachOT>::MachOObjectFile(MemoryBuffer *Object, 418 error_code &ec) : 419 MachOObjectFileBase(Object, Is64Bits, ec) { 420 DataRefImpl DRI; 421 moveToNextSection(DRI); 422 uint32_t LoadCommandCount = getHeader()->NumLoadCommands; 423 while (DRI.d.a < LoadCommandCount) { 424 Sections.push_back(DRI); 425 DRI.d.b++; 426 moveToNextSection(DRI); 427 } 428} 429 430template<class MachOT> 431bool MachOObjectFile<MachOT>::classof(const Binary *v) { 432 return v->getType() == getMachOType(true, Is64Bits); 433} 434 435template<class MachOT> 436const typename MachOObjectFile<MachOT>::Section * 437MachOObjectFile<MachOT>::getSection(DataRefImpl DRI) const { 438 const SectionBase *Addr = getSectionBase(DRI); 439 return reinterpret_cast<const Section*>(Addr); 440} 441 442template<class MachOT> 443const typename MachOObjectFile<MachOT>::SymbolTableEntry * 444MachOObjectFile<MachOT>::getSymbolTableEntry(DataRefImpl DRI) const { 445 const SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI); 446 return reinterpret_cast<const SymbolTableEntry*>(Base); 447} 448 449template<class MachOT> 450const typename MachOObjectFile<MachOT>::RelocationEntry * 451MachOObjectFile<MachOT>::getRelocation(DataRefImpl Rel) const { 452 const Section *Sect = getSection(Sections[Rel.d.b]); 453 uint32_t RelOffset = Sect->RelocationTableOffset; 454 uint64_t Offset = RelOffset + Rel.d.a * sizeof(RelocationEntry); 455 StringRef Data = getData(Offset, sizeof(RelocationEntry)); 456 return reinterpret_cast<const RelocationEntry*>(Data.data()); 457} 458 459template<class MachOT> 460error_code 461MachOObjectFile<MachOT>::getSectionAddress(DataRefImpl Sec, 462 uint64_t &Res) const { 463 const Section *Sect = getSection(Sec); 464 Res = Sect->Address; 465 return object_error::success; 466} 467 468template<class MachOT> 469error_code 470MachOObjectFile<MachOT>::getSectionSize(DataRefImpl Sec, 471 uint64_t &Res) const { 472 const Section *Sect = getSection(Sec); 473 Res = Sect->Size; 474 return object_error::success; 475} 476 477template<class MachOT> 478error_code 479MachOObjectFile<MachOT>::getSectionContents(DataRefImpl Sec, 480 StringRef &Res) const { 481 const Section *Sect = getSection(Sec); 482 Res = getData(Sect->Offset, Sect->Size); 483 return object_error::success; 484} 485 486template<class MachOT> 487error_code 488MachOObjectFile<MachOT>::getSectionAlignment(DataRefImpl Sec, 489 uint64_t &Res) const { 490 const Section *Sect = getSection(Sec); 491 Res = uint64_t(1) << Sect->Align; 492 return object_error::success; 493} 494 495template<class MachOT> 496error_code 497MachOObjectFile<MachOT>::isSectionText(DataRefImpl Sec, bool &Res) const { 498 const Section *Sect = getSection(Sec); 499 Res = Sect->Flags & macho::SF_PureInstructions; 500 return object_error::success; 501} 502 503template<class MachOT> 504error_code 505MachOObjectFile<MachOT>::isSectionZeroInit(DataRefImpl Sec, bool &Res) const { 506 const Section *Sect = getSection(Sec); 507 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType; 508 Res = SectionType == MachO::SectionTypeZeroFill || 509 SectionType == MachO::SectionTypeZeroFillLarge; 510 return object_error::success; 511} 512 513template<class MachOT> 514relocation_iterator 515MachOObjectFile<MachOT>::getSectionRelEnd(DataRefImpl Sec) const { 516 const Section *Sect = getSection(Sec); 517 uint32_t LastReloc = Sect->NumRelocationTableEntries; 518 DataRefImpl Ret; 519 Ret.d.a = LastReloc; 520 Ret.d.b = getSectionIndex(Sec); 521 return relocation_iterator(RelocationRef(Ret, this)); 522} 523 524template<class MachOT> 525error_code 526MachOObjectFile<MachOT>::getRelocationAddress(DataRefImpl Rel, 527 uint64_t &Res) const { 528 const Section *Sect = getSection(Sections[Rel.d.b]); 529 uint64_t SectAddress = Sect->Address; 530 const RelocationEntry *RE = getRelocation(Rel); 531 532 uint64_t RelAddr; 533 if (isScattered(RE)) 534 RelAddr = RE->Address & 0xFFFFFF; 535 else 536 RelAddr = RE->Address; 537 538 Res = SectAddress + RelAddr; 539 return object_error::success; 540} 541 542template<class MachOT> 543error_code 544MachOObjectFile<MachOT>::getRelocationOffset(DataRefImpl Rel, 545 uint64_t &Res) const { 546 const RelocationEntry *RE = getRelocation(Rel); 547 if (isScattered(RE)) 548 Res = RE->Address & 0xFFFFFF; 549 else 550 Res = RE->Address; 551 return object_error::success; 552} 553 554template<class MachOT> 555error_code 556MachOObjectFile<MachOT>::getRelocationSymbol(DataRefImpl Rel, 557 SymbolRef &Res) const { 558 const RelocationEntry *RE = getRelocation(Rel); 559 uint32_t SymbolIdx = RE->SymbolNum; 560 bool isExtern = RE->getExternal(); 561 562 DataRefImpl Sym; 563 moveToNextSymbol(Sym); 564 if (isExtern) { 565 for (unsigned i = 0; i < SymbolIdx; i++) { 566 Sym.d.b++; 567 moveToNextSymbol(Sym); 568 assert(Sym.d.a < getHeader()->NumLoadCommands && 569 "Relocation symbol index out of range!"); 570 } 571 } 572 Res = SymbolRef(Sym, this); 573 return object_error::success; 574} 575 576template<class MachOT> 577error_code MachOObjectFile<MachOT>::getRelocationType(DataRefImpl Rel, 578 uint64_t &Res) const { 579 const RelocationEntry *RE = getRelocation(Rel); 580 Res = getType(RE); 581 return object_error::success; 582} 583 584template<class MachOT> 585error_code 586MachOObjectFile<MachOT>::getRelocationTypeName(DataRefImpl Rel, 587 SmallVectorImpl<char> &Result) const { 588 // TODO: Support scattered relocations. 589 StringRef res; 590 const RelocationEntry *RE = getRelocation(Rel); 591 592 unsigned Arch = getArch(); 593 594 unsigned r_type = getType(RE); 595 596 switch (Arch) { 597 case Triple::x86: { 598 static const char *const Table[] = { 599 "GENERIC_RELOC_VANILLA", 600 "GENERIC_RELOC_PAIR", 601 "GENERIC_RELOC_SECTDIFF", 602 "GENERIC_RELOC_PB_LA_PTR", 603 "GENERIC_RELOC_LOCAL_SECTDIFF", 604 "GENERIC_RELOC_TLV" }; 605 606 if (r_type > 6) 607 res = "Unknown"; 608 else 609 res = Table[r_type]; 610 break; 611 } 612 case Triple::x86_64: { 613 static const char *const Table[] = { 614 "X86_64_RELOC_UNSIGNED", 615 "X86_64_RELOC_SIGNED", 616 "X86_64_RELOC_BRANCH", 617 "X86_64_RELOC_GOT_LOAD", 618 "X86_64_RELOC_GOT", 619 "X86_64_RELOC_SUBTRACTOR", 620 "X86_64_RELOC_SIGNED_1", 621 "X86_64_RELOC_SIGNED_2", 622 "X86_64_RELOC_SIGNED_4", 623 "X86_64_RELOC_TLV" }; 624 625 if (r_type > 9) 626 res = "Unknown"; 627 else 628 res = Table[r_type]; 629 break; 630 } 631 case Triple::arm: { 632 static const char *const Table[] = { 633 "ARM_RELOC_VANILLA", 634 "ARM_RELOC_PAIR", 635 "ARM_RELOC_SECTDIFF", 636 "ARM_RELOC_LOCAL_SECTDIFF", 637 "ARM_RELOC_PB_LA_PTR", 638 "ARM_RELOC_BR24", 639 "ARM_THUMB_RELOC_BR22", 640 "ARM_THUMB_32BIT_BRANCH", 641 "ARM_RELOC_HALF", 642 "ARM_RELOC_HALF_SECTDIFF" }; 643 644 if (r_type > 9) 645 res = "Unknown"; 646 else 647 res = Table[r_type]; 648 break; 649 } 650 case Triple::ppc: { 651 static const char *const Table[] = { 652 "PPC_RELOC_VANILLA", 653 "PPC_RELOC_PAIR", 654 "PPC_RELOC_BR14", 655 "PPC_RELOC_BR24", 656 "PPC_RELOC_HI16", 657 "PPC_RELOC_LO16", 658 "PPC_RELOC_HA16", 659 "PPC_RELOC_LO14", 660 "PPC_RELOC_SECTDIFF", 661 "PPC_RELOC_PB_LA_PTR", 662 "PPC_RELOC_HI16_SECTDIFF", 663 "PPC_RELOC_LO16_SECTDIFF", 664 "PPC_RELOC_HA16_SECTDIFF", 665 "PPC_RELOC_JBSR", 666 "PPC_RELOC_LO14_SECTDIFF", 667 "PPC_RELOC_LOCAL_SECTDIFF" }; 668 669 res = Table[r_type]; 670 break; 671 } 672 case Triple::UnknownArch: 673 res = "Unknown"; 674 break; 675 } 676 Result.append(res.begin(), res.end()); 677 return object_error::success; 678} 679 680template<class MachOT> 681error_code 682MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel, 683 SmallVectorImpl<char> &Result) const { 684 const RelocationEntry *RE = getRelocation(Rel); 685 686 unsigned Arch = getArch(); 687 bool IsScattered = isScattered(RE); 688 689 std::string fmtbuf; 690 raw_string_ostream fmt(fmtbuf); 691 692 unsigned Type = getType(RE); 693 bool IsPCRel = isPCRel(RE); 694 695 // Determine any addends that should be displayed with the relocation. 696 // These require decoding the relocation type, which is triple-specific. 697 698 // X86_64 has entirely custom relocation types. 699 if (Arch == Triple::x86_64) { 700 bool isPCRel = RE->getPCRel(); 701 702 switch (Type) { 703 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD 704 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT 705 printRelocationTargetName(RE, fmt); 706 fmt << "@GOT"; 707 if (isPCRel) fmt << "PCREL"; 708 break; 709 } 710 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR 711 DataRefImpl RelNext = Rel; 712 RelNext.d.a++; 713 const RelocationEntry *RENext = getRelocation(RelNext); 714 715 // X86_64_SUBTRACTOR must be followed by a relocation of type 716 // X86_64_RELOC_UNSIGNED. 717 // NOTE: Scattered relocations don't exist on x86_64. 718 unsigned RType = RENext->getType(); 719 if (RType != 0) 720 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " 721 "X86_64_RELOC_SUBTRACTOR."); 722 723 // The X86_64_RELOC_UNSIGNED contains the minuend symbol, 724 // X86_64_SUBTRACTOR contains to the subtrahend. 725 printRelocationTargetName(RENext, fmt); 726 fmt << "-"; 727 printRelocationTargetName(RE, fmt); 728 break; 729 } 730 case macho::RIT_X86_64_TLV: 731 printRelocationTargetName(RE, fmt); 732 fmt << "@TLV"; 733 if (isPCRel) fmt << "P"; 734 break; 735 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1 736 printRelocationTargetName(RE, fmt); 737 fmt << "-1"; 738 break; 739 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2 740 printRelocationTargetName(RE, fmt); 741 fmt << "-2"; 742 break; 743 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4 744 printRelocationTargetName(RE, fmt); 745 fmt << "-4"; 746 break; 747 default: 748 printRelocationTargetName(RE, fmt); 749 break; 750 } 751 // X86 and ARM share some relocation types in common. 752 } else if (Arch == Triple::x86 || Arch == Triple::arm) { 753 // Generic relocation types... 754 switch (Type) { 755 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info 756 return object_error::success; 757 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF 758 DataRefImpl RelNext = Rel; 759 RelNext.d.a++; 760 const RelocationEntry *RENext = getRelocation(RelNext); 761 762 // X86 sect diff's must be followed by a relocation of type 763 // GENERIC_RELOC_PAIR. 764 bool isNextScattered = (Arch != Triple::x86_64) && 765 (RENext->Address & macho::RF_Scattered); 766 unsigned RType; 767 if (isNextScattered) 768 RType = (RENext->Address >> 24) & 0xF; 769 else 770 RType = RENext->getType(); 771 if (RType != 1) 772 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 773 "GENERIC_RELOC_SECTDIFF."); 774 775 printRelocationTargetName(RE, fmt); 776 fmt << "-"; 777 printRelocationTargetName(RENext, fmt); 778 break; 779 } 780 } 781 782 if (Arch == Triple::x86) { 783 // All X86 relocations that need special printing were already 784 // handled in the generic code. 785 switch (Type) { 786 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF 787 DataRefImpl RelNext = Rel; 788 RelNext.d.a++; 789 const RelocationEntry *RENext = getRelocation(RelNext); 790 791 // X86 sect diff's must be followed by a relocation of type 792 // GENERIC_RELOC_PAIR. 793 bool isNextScattered = (Arch != Triple::x86_64) && 794 (RENext->Address & macho::RF_Scattered); 795 unsigned RType; 796 if (isNextScattered) 797 RType = (RENext->Address >> 24) & 0xF; 798 else 799 RType = RENext->getType(); 800 if (RType != 1) 801 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 802 "GENERIC_RELOC_LOCAL_SECTDIFF."); 803 804 printRelocationTargetName(RE, fmt); 805 fmt << "-"; 806 printRelocationTargetName(RENext, fmt); 807 break; 808 } 809 case macho::RIT_Generic_TLV: { 810 printRelocationTargetName(RE, fmt); 811 fmt << "@TLV"; 812 if (IsPCRel) fmt << "P"; 813 break; 814 } 815 default: 816 printRelocationTargetName(RE, fmt); 817 } 818 } else { // ARM-specific relocations 819 switch (Type) { 820 case macho::RIT_ARM_Half: // ARM_RELOC_HALF 821 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF 822 // Half relocations steal a bit from the length field to encode 823 // whether this is an upper16 or a lower16 relocation. 824 bool isUpper; 825 if (IsScattered) 826 isUpper = (RE->Address >> 28) & 1; 827 else 828 isUpper = (RE->getLength() >> 1) & 1; 829 830 if (isUpper) 831 fmt << ":upper16:("; 832 else 833 fmt << ":lower16:("; 834 printRelocationTargetName(RE, fmt); 835 836 DataRefImpl RelNext = Rel; 837 RelNext.d.a++; 838 const RelocationEntry *RENext = getRelocation(RelNext); 839 840 // ARM half relocs must be followed by a relocation of type 841 // ARM_RELOC_PAIR. 842 bool isNextScattered = (Arch != Triple::x86_64) && 843 (RENext->Address & macho::RF_Scattered); 844 unsigned RType; 845 if (isNextScattered) 846 RType = (RENext->Address >> 24) & 0xF; 847 else 848 RType = RENext->getType(); 849 850 if (RType != 1) 851 report_fatal_error("Expected ARM_RELOC_PAIR after " 852 "GENERIC_RELOC_HALF"); 853 854 // NOTE: The half of the target virtual address is stashed in the 855 // address field of the secondary relocation, but we can't reverse 856 // engineer the constant offset from it without decoding the movw/movt 857 // instruction to find the other half in its immediate field. 858 859 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the 860 // symbol/section pointer of the follow-on relocation. 861 if (Type == macho::RIT_ARM_HalfDifference) { 862 fmt << "-"; 863 printRelocationTargetName(RENext, fmt); 864 } 865 866 fmt << ")"; 867 break; 868 } 869 default: { 870 printRelocationTargetName(RE, fmt); 871 } 872 } 873 } 874 } else 875 printRelocationTargetName(RE, fmt); 876 877 fmt.flush(); 878 Result.append(fmtbuf.begin(), fmtbuf.end()); 879 return object_error::success; 880} 881 882template<class MachOT> 883error_code 884MachOObjectFile<MachOT>::getRelocationHidden(DataRefImpl Rel, 885 bool &Result) const { 886 const RelocationEntry *RE = getRelocation(Rel); 887 unsigned Arch = getArch(); 888 unsigned Type = getType(RE); 889 890 Result = false; 891 892 // On arches that use the generic relocations, GENERIC_RELOC_PAIR 893 // is always hidden. 894 if (Arch == Triple::x86 || Arch == Triple::arm) { 895 if (Type == macho::RIT_Pair) Result = true; 896 } else if (Arch == Triple::x86_64) { 897 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows 898 // an X864_64_RELOC_SUBTRACTOR. 899 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) { 900 DataRefImpl RelPrev = Rel; 901 RelPrev.d.a--; 902 const RelocationEntry *REPrev = getRelocation(RelPrev); 903 904 unsigned PrevType = REPrev->getType(); 905 906 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true; 907 } 908 } 909 910 return object_error::success; 911} 912 913template<class MachOT> 914error_code 915MachOObjectFile<MachOT>::getSymbolFileOffset(DataRefImpl Symb, 916 uint64_t &Res) const { 917 const SymbolTableEntry *Entry = getSymbolTableEntry(Symb); 918 Res = Entry->Value; 919 if (Entry->SectionIndex) { 920 const Section *Sec = getSection(Sections[Entry->SectionIndex-1]); 921 Res += Sec->Offset - Sec->Address; 922 } 923 924 return object_error::success; 925} 926 927template<class MachOT> 928error_code 929MachOObjectFile<MachOT>::sectionContainsSymbol(DataRefImpl Sec, 930 DataRefImpl Symb, 931 bool &Result) const { 932 SymbolRef::Type ST; 933 getSymbolType(Symb, ST); 934 if (ST == SymbolRef::ST_Unknown) { 935 Result = false; 936 return object_error::success; 937 } 938 939 uint64_t SectBegin, SectEnd; 940 getSectionAddress(Sec, SectBegin); 941 getSectionSize(Sec, SectEnd); 942 SectEnd += SectBegin; 943 944 const SymbolTableEntry *Entry = getSymbolTableEntry(Symb); 945 uint64_t SymAddr= Entry->Value; 946 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 947 948 return object_error::success; 949} 950 951template<class MachOT> 952error_code MachOObjectFile<MachOT>::getSymbolAddress(DataRefImpl Symb, 953 uint64_t &Res) const { 954 const SymbolTableEntry *Entry = getSymbolTableEntry(Symb); 955 Res = Entry->Value; 956 return object_error::success; 957} 958 959template<class MachOT> 960error_code MachOObjectFile<MachOT>::getSymbolSize(DataRefImpl DRI, 961 uint64_t &Result) const { 962 uint32_t LoadCommandCount = getHeader()->NumLoadCommands; 963 uint64_t BeginOffset; 964 uint64_t EndOffset = 0; 965 uint8_t SectionIndex; 966 967 const SymbolTableEntry *Entry = getSymbolTableEntry(DRI); 968 BeginOffset = Entry->Value; 969 SectionIndex = Entry->SectionIndex; 970 if (!SectionIndex) { 971 uint32_t flags = SymbolRef::SF_None; 972 getSymbolFlags(DRI, flags); 973 if (flags & SymbolRef::SF_Common) 974 Result = Entry->Value; 975 else 976 Result = UnknownAddressOrSize; 977 return object_error::success; 978 } 979 // Unfortunately symbols are unsorted so we need to touch all 980 // symbols from load command 981 DRI.d.b = 0; 982 uint32_t Command = DRI.d.a; 983 while (Command == DRI.d.a) { 984 moveToNextSymbol(DRI); 985 if (DRI.d.a < LoadCommandCount) { 986 Entry = getSymbolTableEntry(DRI); 987 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset) 988 if (!EndOffset || Entry->Value < EndOffset) 989 EndOffset = Entry->Value; 990 } 991 DRI.d.b++; 992 } 993 if (!EndOffset) { 994 uint64_t Size; 995 getSectionSize(Sections[SectionIndex-1], Size); 996 getSectionAddress(Sections[SectionIndex-1], EndOffset); 997 EndOffset += Size; 998 } 999 Result = EndOffset - BeginOffset; 1000 return object_error::success; 1001} 1002 1003template<class MachOT> 1004error_code MachOObjectFile<MachOT>::getSectionNext(DataRefImpl Sec, 1005 SectionRef &Res) const { 1006 Sec.d.b++; 1007 moveToNextSection(Sec); 1008 Res = SectionRef(Sec, this); 1009 return object_error::success; 1010} 1011 1012template<class MachOT> 1013section_iterator MachOObjectFile<MachOT>::begin_sections() const { 1014 DataRefImpl DRI; 1015 moveToNextSection(DRI); 1016 return section_iterator(SectionRef(DRI, this)); 1017} 1018 1019template<class MachOT> 1020void MachOObjectFile<MachOT>::moveToNextSection(DataRefImpl &DRI) const { 1021 uint32_t LoadCommandCount = getHeader()->NumLoadCommands; 1022 while (DRI.d.a < LoadCommandCount) { 1023 const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); 1024 if (Command->Type == SegmentLoadType) { 1025 const SegmentLoadCommand *SegmentLoadCmd = 1026 reinterpret_cast<const SegmentLoadCommand*>(Command); 1027 if (DRI.d.b < SegmentLoadCmd->NumSections) 1028 return; 1029 } 1030 1031 DRI.d.a++; 1032 DRI.d.b = 0; 1033 } 1034} 1035 1036 typedef MachOObjectFile<MachOType<support::little, false> > 1037 MachOObjectFile32Le; 1038 typedef MachOObjectFile<MachOType<support::little, true> > 1039 MachOObjectFile64Le; 1040} 1041} 1042 1043#endif 1044 1045