1 //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the MachOObjectFile class, which binds the MachOObject
11 // class to the generic ObjectFile wrapper.
13 //===----------------------------------------------------------------------===//
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"
26 using namespace object;
31 MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, bool Is64bits,
33 : ObjectFile(getMachOType(true, Is64bits), Object) {
35 moveToNextSection(DRI);
36 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
37 while (DRI.d.a < LoadCommandCount) {
38 Sections.push_back(DRI);
40 moveToNextSection(DRI);
44 bool MachOObjectFile::is64Bit() const {
45 unsigned int Type = getType();
46 return Type == ID_MachO64L || Type == ID_MachO64B;
49 const MachOFormat::LoadCommand *
50 MachOObjectFile::getLoadCommandInfo(unsigned Index) const {
52 uint64_t NewOffset = getHeaderSize();
53 const MachOFormat::LoadCommand *Load;
57 StringRef Data = getData(Offset, sizeof(MachOFormat::LoadCommand));
58 Load = reinterpret_cast<const MachOFormat::LoadCommand*>(Data.data());
59 NewOffset = Offset + Load->Size;
61 } while (I != Index + 1);
66 void MachOObjectFile::ReadULEB128s(uint64_t Index,
67 SmallVectorImpl<uint64_t> &Out) const {
68 DataExtractor extractor(ObjectFile::getData(), true, 0);
70 uint32_t offset = Index;
72 while (uint64_t delta = extractor.getULEB128(&offset)) {
78 const MachOFormat::Header *MachOObjectFile::getHeader() const {
79 StringRef Data = getData(0, sizeof(MachOFormat::Header));
80 return reinterpret_cast<const MachOFormat::Header*>(Data.data());
83 unsigned MachOObjectFile::getHeaderSize() const {
84 return is64Bit() ? macho::Header64Size : macho::Header32Size;
87 StringRef MachOObjectFile::getData(size_t Offset, size_t Size) const {
88 return ObjectFile::getData().substr(Offset, Size);
91 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
92 StringRef Magic = Buffer->getBuffer().slice(0, 4);
94 bool Is64Bits = Magic == "\xFE\xED\xFA\xCF" || Magic == "\xCF\xFA\xED\xFE";
95 ObjectFile *Ret = new MachOObjectFile(Buffer, Is64Bits, ec);
101 /*===-- Symbols -----------------------------------------------------------===*/
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)
119 const MachOFormat::SymbolTableEntryBase *
120 MachOObjectFile::getSymbolTableEntryBase(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 return getSymbolTableEntryBase(DRI, SymtabLoadCmd);
127 const MachOFormat::SymbolTableEntry<false> *
128 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
129 const MachOFormat::SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI);
130 return reinterpret_cast<const MachOFormat::SymbolTableEntry<false>*>(Base);
133 const MachOFormat::SymbolTableEntryBase *
134 MachOObjectFile::getSymbolTableEntryBase(DataRefImpl DRI,
135 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
136 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
137 unsigned Index = DRI.d.b;
139 unsigned SymbolTableEntrySize = is64Bit() ?
140 sizeof(MachOFormat::SymbolTableEntry<true>) :
141 sizeof(MachOFormat::SymbolTableEntry<false>);
143 uint64_t Offset = SymbolTableOffset + Index * SymbolTableEntrySize;
144 StringRef Data = getData(Offset, SymbolTableEntrySize);
146 reinterpret_cast<const MachOFormat::SymbolTableEntryBase*>(Data.data());
149 const MachOFormat::SymbolTableEntry<true>*
150 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
151 const MachOFormat::SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI);
152 return reinterpret_cast<const MachOFormat::SymbolTableEntry<true>*>(Base);
155 error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
156 SymbolRef &Result) const {
158 moveToNextSymbol(DRI);
159 Result = SymbolRef(DRI, this);
160 return object_error::success;
163 error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
164 StringRef &Result) const {
165 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
166 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
167 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
169 StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset,
170 SymtabLoadCmd->StringTableSize);
172 const MachOFormat::SymbolTableEntryBase *Entry =
173 getSymbolTableEntryBase(DRI, SymtabLoadCmd);
174 uint32_t StringIndex = Entry->StringIndex;
176 const char *Start = &StringTable.data()[StringIndex];
177 Result = StringRef(Start);
179 return object_error::success;
182 error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI,
183 uint64_t &Result) const {
185 const MachOFormat::SymbolTableEntry<true> *Entry =
186 getSymbol64TableEntry(DRI);
187 Result = Entry->Value;
188 if (Entry->SectionIndex) {
189 const MachOFormat::Section<true> *Section =
190 getSection64(Sections[Entry->SectionIndex-1]);
191 Result += Section->Offset - Section->Address;
194 const MachOFormat::SymbolTableEntry<false> *Entry =
195 getSymbolTableEntry(DRI);
196 Result = Entry->Value;
197 if (Entry->SectionIndex) {
198 const MachOFormat::Section<false> *Section =
199 getSection(Sections[Entry->SectionIndex-1]);
200 Result += Section->Offset - Section->Address;
204 return object_error::success;
207 error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
208 uint64_t &Result) const {
210 const MachOFormat::SymbolTableEntry<true> *Entry =
211 getSymbol64TableEntry(DRI);
212 Result = Entry->Value;
214 const MachOFormat::SymbolTableEntry<false> *Entry =
215 getSymbolTableEntry(DRI);
216 Result = Entry->Value;
218 return object_error::success;
221 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
222 uint64_t &Result) const {
223 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
224 uint64_t BeginOffset;
225 uint64_t EndOffset = 0;
226 uint8_t SectionIndex;
228 const MachOFormat::SymbolTableEntry<true> *Entry =
229 getSymbol64TableEntry(DRI);
230 BeginOffset = Entry->Value;
231 SectionIndex = Entry->SectionIndex;
233 uint32_t flags = SymbolRef::SF_None;
234 getSymbolFlags(DRI, flags);
235 if (flags & SymbolRef::SF_Common)
236 Result = Entry->Value;
238 Result = UnknownAddressOrSize;
239 return object_error::success;
241 // Unfortunately symbols are unsorted so we need to touch all
242 // symbols from load command
244 uint32_t Command = DRI.d.a;
245 while (Command == DRI.d.a) {
246 moveToNextSymbol(DRI);
247 if (DRI.d.a < LoadCommandCount) {
248 Entry = getSymbol64TableEntry(DRI);
249 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
250 if (!EndOffset || Entry->Value < EndOffset)
251 EndOffset = Entry->Value;
256 const MachOFormat::SymbolTableEntry<false> *Entry =
257 getSymbolTableEntry(DRI);
258 BeginOffset = Entry->Value;
259 SectionIndex = Entry->SectionIndex;
261 uint32_t flags = SymbolRef::SF_None;
262 getSymbolFlags(DRI, flags);
263 if (flags & SymbolRef::SF_Common)
264 Result = Entry->Value;
266 Result = UnknownAddressOrSize;
267 return object_error::success;
269 // Unfortunately symbols are unsorted so we need to touch all
270 // symbols from load command
272 uint32_t Command = DRI.d.a;
273 while (Command == DRI.d.a) {
274 moveToNextSymbol(DRI);
275 if (DRI.d.a < LoadCommandCount) {
276 Entry = getSymbolTableEntry(DRI);
277 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
278 if (!EndOffset || Entry->Value < EndOffset)
279 EndOffset = Entry->Value;
286 getSectionSize(Sections[SectionIndex-1], Size);
287 getSectionAddress(Sections[SectionIndex-1], EndOffset);
290 Result = EndOffset - BeginOffset;
291 return object_error::success;
294 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
295 char &Result) const {
298 const MachOFormat::SymbolTableEntry<true> *Entry =
299 getSymbol64TableEntry(DRI);
301 Flags = Entry->Flags;
303 const MachOFormat::SymbolTableEntry<false> *Entry =
304 getSymbolTableEntry(DRI);
306 Flags = Entry->Flags;
310 switch (Type & macho::STF_TypeMask) {
311 case macho::STT_Undefined:
314 case macho::STT_Absolute:
315 case macho::STT_Section:
323 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
324 Char = toupper(static_cast<unsigned char>(Char));
326 return object_error::success;
329 error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
330 uint32_t &Result) const {
334 const MachOFormat::SymbolTableEntry<true> *Entry =
335 getSymbol64TableEntry(DRI);
336 MachOFlags = Entry->Flags;
337 MachOType = Entry->Type;
339 const MachOFormat::SymbolTableEntry<false> *Entry =
340 getSymbolTableEntry(DRI);
341 MachOFlags = Entry->Flags;
342 MachOType = Entry->Type;
345 // TODO: Correctly set SF_ThreadLocal
346 Result = SymbolRef::SF_None;
348 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
349 Result |= SymbolRef::SF_Undefined;
351 if (MachOFlags & macho::STF_StabsEntryMask)
352 Result |= SymbolRef::SF_FormatSpecific;
354 if (MachOType & MachO::NlistMaskExternal) {
355 Result |= SymbolRef::SF_Global;
356 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
357 Result |= SymbolRef::SF_Common;
360 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
361 Result |= SymbolRef::SF_Weak;
363 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
364 Result |= SymbolRef::SF_Absolute;
366 return object_error::success;
369 error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
370 section_iterator &Res) const {
373 const MachOFormat::SymbolTableEntry<true> *Entry =
374 getSymbol64TableEntry(Symb);
375 index = Entry->SectionIndex;
377 const MachOFormat::SymbolTableEntry<false> *Entry =
378 getSymbolTableEntry(Symb);
379 index = Entry->SectionIndex;
383 Res = end_sections();
385 Res = section_iterator(SectionRef(Sections[index-1], this));
387 return object_error::success;
390 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
391 SymbolRef::Type &Res) const {
392 const MachOFormat::SymbolTableEntryBase *Entry =
393 getSymbolTableEntryBase(Symb);
394 uint8_t n_type = Entry->Type;
396 Res = SymbolRef::ST_Other;
398 // If this is a STAB debugging symbol, we can do nothing more.
399 if (n_type & MachO::NlistMaskStab) {
400 Res = SymbolRef::ST_Debug;
401 return object_error::success;
404 switch (n_type & MachO::NlistMaskType) {
405 case MachO::NListTypeUndefined :
406 Res = SymbolRef::ST_Unknown;
408 case MachO::NListTypeSection :
409 Res = SymbolRef::ST_Function;
412 return object_error::success;
415 error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
416 uint64_t &Val) const {
417 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
420 symbol_iterator MachOObjectFile::begin_symbols() const {
421 // DRI.d.a = segment number; DRI.d.b = symbol index.
423 moveToNextSymbol(DRI);
424 return symbol_iterator(SymbolRef(DRI, this));
427 symbol_iterator MachOObjectFile::end_symbols() const {
429 DRI.d.a = getHeader()->NumLoadCommands;
430 return symbol_iterator(SymbolRef(DRI, this));
433 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
435 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
438 symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
440 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
443 library_iterator MachOObjectFile::begin_libraries_needed() const {
445 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
448 library_iterator MachOObjectFile::end_libraries_needed() const {
450 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
453 StringRef MachOObjectFile::getLoadName() const {
455 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
458 /*===-- Sections ----------------------------------------------------------===*/
460 void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
461 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
462 while (DRI.d.a < LoadCommandCount) {
463 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
464 if (Command->Type == macho::LCT_Segment) {
465 const MachOFormat::SegmentLoadCommand<false> *SegmentLoadCmd =
466 reinterpret_cast<const MachOFormat::SegmentLoadCommand<false>*>(Command);
467 if (DRI.d.b < SegmentLoadCmd->NumSections)
469 } else if (Command->Type == macho::LCT_Segment64) {
470 const MachOFormat::SegmentLoadCommand<true> *SegmentLoadCmd =
471 reinterpret_cast<const MachOFormat::SegmentLoadCommand<true>*>(Command);
472 if (DRI.d.b < SegmentLoadCmd->NumSections)
481 error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
482 SectionRef &Result) const {
484 moveToNextSection(DRI);
485 Result = SectionRef(DRI, this);
486 return object_error::success;
489 const MachOFormat::Section<false> *
490 MachOObjectFile::getSection(DataRefImpl DRI) const {
492 const MachOFormat::SectionBase *Addr = getSectionBase(DRI);
493 return reinterpret_cast<const MachOFormat::Section<false>*>(Addr);
496 std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
497 SectionList::const_iterator loc =
498 std::find(Sections.begin(), Sections.end(), Sec);
499 assert(loc != Sections.end() && "Sec is not a valid section!");
500 return std::distance(Sections.begin(), loc);
503 const MachOFormat::SectionBase*
504 MachOObjectFile::getSectionBase(DataRefImpl DRI) const {
505 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
506 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
508 bool Is64 = is64Bit();
509 unsigned SegmentLoadSize =
510 Is64 ? sizeof(MachOFormat::SegmentLoadCommand<true>) :
511 sizeof(MachOFormat::SegmentLoadCommand<false>);
512 unsigned SectionSize = Is64 ? sizeof(MachOFormat::Section<true>) :
513 sizeof(MachOFormat::Section<false>);
515 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize;
516 return reinterpret_cast<const MachOFormat::SectionBase*>(SectionAddr);
519 const MachOFormat::Section<true> *
520 MachOObjectFile::getSection64(DataRefImpl DRI) const {
522 const MachOFormat::SectionBase *Addr = getSectionBase(DRI);
523 return reinterpret_cast<const MachOFormat::Section<true>*>(Addr);
526 static StringRef parseSegmentOrSectionName(const char *P) {
530 // Not null terminated, so this is a 16 char string.
531 return StringRef(P, 16);
534 ArrayRef<char> MachOObjectFile::getSectionRawName(DataRefImpl DRI) const {
535 const MachOFormat::SectionBase *Base = getSectionBase(DRI);
536 return ArrayRef<char>(Base->Name);
539 error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
540 StringRef &Result) const {
541 ArrayRef<char> Raw = getSectionRawName(DRI);
542 Result = parseSegmentOrSectionName(Raw.data());
543 return object_error::success;
547 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
548 const MachOFormat::SectionBase *Base = getSectionBase(Sec);
549 return ArrayRef<char>(Base->SegmentName);
552 StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const {
553 ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
554 return parseSegmentOrSectionName(Raw.data());
557 error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
558 uint64_t &Result) const {
560 const MachOFormat::Section<true> *Sect = getSection64(DRI);
561 Result = Sect->Address;
563 const MachOFormat::Section<false> *Sect = getSection(DRI);
564 Result = Sect->Address;
566 return object_error::success;
569 error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
570 uint64_t &Result) const {
572 const MachOFormat::Section<true> *Sect = getSection64(DRI);
575 const MachOFormat::Section<false> *Sect = getSection(DRI);
578 return object_error::success;
581 error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
582 StringRef &Result) const {
584 const MachOFormat::Section<true> *Sect = getSection64(DRI);
585 Result = getData(Sect->Offset, Sect->Size);
587 const MachOFormat::Section<false> *Sect = getSection(DRI);
588 Result = getData(Sect->Offset, Sect->Size);
590 return object_error::success;
593 error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
594 uint64_t &Result) const {
596 const MachOFormat::Section<true> *Sect = getSection64(DRI);
597 Result = uint64_t(1) << Sect->Align;
599 const MachOFormat::Section<false> *Sect = getSection(DRI);
600 Result = uint64_t(1) << Sect->Align;
602 return object_error::success;
605 error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
606 bool &Result) const {
608 const MachOFormat::Section<true> *Sect = getSection64(DRI);
609 Result = Sect->Flags & macho::SF_PureInstructions;
611 const MachOFormat::Section<false> *Sect = getSection(DRI);
612 Result = Sect->Flags & macho::SF_PureInstructions;
614 return object_error::success;
617 error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
618 bool &Result) const {
619 // FIXME: Unimplemented.
621 return object_error::success;
624 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
625 bool &Result) const {
626 // FIXME: Unimplemented.
628 return object_error::success;
631 error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
632 bool &Result) const {
633 // FIXME: Unimplemented.
635 return object_error::success;
638 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
639 bool &Result) const {
640 // FIXME: Unimplemented.
642 return object_error::success;
645 error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI,
646 bool &Result) const {
648 const MachOFormat::Section<true> *Sect = getSection64(DRI);
649 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
650 Result = (SectionType == MachO::SectionTypeZeroFill ||
651 SectionType == MachO::SectionTypeZeroFillLarge);
653 const MachOFormat::Section<false> *Sect = getSection(DRI);
654 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
655 Result = (SectionType == MachO::SectionTypeZeroFill ||
656 SectionType == MachO::SectionTypeZeroFillLarge);
659 return object_error::success;
662 error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
663 bool &Result) const {
664 // Consider using the code from isSectionText to look for __const sections.
665 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
666 // to use section attributes to distinguish code from data.
668 // FIXME: Unimplemented.
670 return object_error::success;
673 error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
675 bool &Result) const {
677 getSymbolType(Symb, ST);
678 if (ST == SymbolRef::ST_Unknown) {
680 return object_error::success;
683 uint64_t SectBegin, SectEnd;
684 getSectionAddress(Sec, SectBegin);
685 getSectionSize(Sec, SectEnd);
686 SectEnd += SectBegin;
689 const MachOFormat::SymbolTableEntry<true> *Entry =
690 getSymbol64TableEntry(Symb);
691 uint64_t SymAddr= Entry->Value;
692 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
694 const MachOFormat::SymbolTableEntry<false> *Entry =
695 getSymbolTableEntry(Symb);
696 uint64_t SymAddr= Entry->Value;
697 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
700 return object_error::success;
703 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
705 ret.d.b = getSectionIndex(Sec);
706 return relocation_iterator(RelocationRef(ret, this));
709 relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
712 const MachOFormat::Section<true> *Sect = getSection64(Sec);
713 last_reloc = Sect->NumRelocationTableEntries;
715 const MachOFormat::Section<false> *Sect = getSection(Sec);
716 last_reloc = Sect->NumRelocationTableEntries;
719 ret.d.a = last_reloc;
720 ret.d.b = getSectionIndex(Sec);
721 return relocation_iterator(RelocationRef(ret, this));
724 section_iterator MachOObjectFile::begin_sections() const {
726 moveToNextSection(DRI);
727 return section_iterator(SectionRef(DRI, this));
730 section_iterator MachOObjectFile::end_sections() const {
732 DRI.d.a = getHeader()->NumLoadCommands;
733 return section_iterator(SectionRef(DRI, this));
736 /*===-- Relocations -------------------------------------------------------===*/
738 const MachOFormat::RelocationEntry *
739 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
742 const MachOFormat::Section<true> *Sect = getSection64(Sections[Rel.d.b]);
743 relOffset = Sect->RelocationTableOffset;
745 const MachOFormat::Section<false> *Sect = getSection(Sections[Rel.d.b]);
746 relOffset = Sect->RelocationTableOffset;
748 uint64_t Offset = relOffset + Rel.d.a * sizeof(MachOFormat::RelocationEntry);
749 StringRef Data = getData(Offset, sizeof(MachOFormat::RelocationEntry));
750 return reinterpret_cast<const MachOFormat::RelocationEntry*>(Data.data());
753 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
754 RelocationRef &Res) const {
756 Res = RelocationRef(Rel, this);
757 return object_error::success;
759 error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
760 uint64_t &Res) const {
761 const uint8_t* sectAddress = 0;
763 const MachOFormat::Section<true> *Sect = getSection64(Sections[Rel.d.b]);
764 sectAddress += Sect->Address;
766 const MachOFormat::Section<false> *Sect = getSection(Sections[Rel.d.b]);
767 sectAddress += Sect->Address;
769 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
771 unsigned Arch = getArch();
772 bool isScattered = (Arch != Triple::x86_64) &&
773 (RE->Word0 & macho::RF_Scattered);
774 uint64_t RelAddr = 0;
776 RelAddr = RE->Word0 & 0xFFFFFF;
780 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
781 return object_error::success;
783 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
784 uint64_t &Res) const {
785 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
787 unsigned Arch = getArch();
788 bool isScattered = (Arch != Triple::x86_64) &&
789 (RE->Word0 & macho::RF_Scattered);
791 Res = RE->Word0 & 0xFFFFFF;
794 return object_error::success;
796 error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
797 SymbolRef &Res) const {
798 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
799 uint32_t SymbolIdx = RE->Word1 & 0xffffff;
800 bool isExtern = (RE->Word1 >> 27) & 1;
803 moveToNextSymbol(Sym);
805 for (unsigned i = 0; i < SymbolIdx; i++) {
807 moveToNextSymbol(Sym);
808 assert(Sym.d.a < getHeader()->NumLoadCommands &&
809 "Relocation symbol index out of range!");
812 Res = SymbolRef(Sym, this);
813 return object_error::success;
815 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
816 uint64_t &Res) const {
817 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
821 return object_error::success;
823 error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
824 SmallVectorImpl<char> &Result) const {
825 // TODO: Support scattered relocations.
827 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
829 unsigned Arch = getArch();
830 bool isScattered = (Arch != Triple::x86_64) &&
831 (RE->Word0 & macho::RF_Scattered);
835 r_type = (RE->Word0 >> 24) & 0xF;
837 r_type = (RE->Word1 >> 28) & 0xF;
841 static const char *const Table[] = {
842 "GENERIC_RELOC_VANILLA",
843 "GENERIC_RELOC_PAIR",
844 "GENERIC_RELOC_SECTDIFF",
845 "GENERIC_RELOC_PB_LA_PTR",
846 "GENERIC_RELOC_LOCAL_SECTDIFF",
847 "GENERIC_RELOC_TLV" };
855 case Triple::x86_64: {
856 static const char *const Table[] = {
857 "X86_64_RELOC_UNSIGNED",
858 "X86_64_RELOC_SIGNED",
859 "X86_64_RELOC_BRANCH",
860 "X86_64_RELOC_GOT_LOAD",
862 "X86_64_RELOC_SUBTRACTOR",
863 "X86_64_RELOC_SIGNED_1",
864 "X86_64_RELOC_SIGNED_2",
865 "X86_64_RELOC_SIGNED_4",
866 "X86_64_RELOC_TLV" };
875 static const char *const Table[] = {
878 "ARM_RELOC_SECTDIFF",
879 "ARM_RELOC_LOCAL_SECTDIFF",
880 "ARM_RELOC_PB_LA_PTR",
882 "ARM_THUMB_RELOC_BR22",
883 "ARM_THUMB_32BIT_BRANCH",
885 "ARM_RELOC_HALF_SECTDIFF" };
894 static const char *const Table[] = {
903 "PPC_RELOC_SECTDIFF",
904 "PPC_RELOC_PB_LA_PTR",
905 "PPC_RELOC_HI16_SECTDIFF",
906 "PPC_RELOC_LO16_SECTDIFF",
907 "PPC_RELOC_HA16_SECTDIFF",
909 "PPC_RELOC_LO14_SECTDIFF",
910 "PPC_RELOC_LOCAL_SECTDIFF" };
915 case Triple::UnknownArch:
919 Result.append(res.begin(), res.end());
920 return object_error::success;
922 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
923 int64_t &Res) const {
924 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
925 bool isExtern = (RE->Word1 >> 27) & 1;
928 const uint8_t* sectAddress = base();
930 const MachOFormat::Section<true> *Sect = getSection64(Sections[Rel.d.b]);
931 sectAddress += Sect->Offset;
933 const MachOFormat::Section<false> *Sect = getSection(Sections[Rel.d.b]);
934 sectAddress += Sect->Offset;
936 Res = reinterpret_cast<uintptr_t>(sectAddress);
938 return object_error::success;
941 // Helper to advance a section or symbol iterator multiple increments at a time.
943 error_code advance(T &it, size_t Val) {
952 void advanceTo(T &it, size_t Val) {
953 if (error_code ec = advance(it, Val))
954 report_fatal_error(ec.message());
957 void MachOObjectFile::printRelocationTargetName(
958 const MachOFormat::RelocationEntry *RE,
959 raw_string_ostream &fmt) const {
960 unsigned Arch = getArch();
961 bool isScattered = (Arch != Triple::x86_64) &&
962 (RE->Word0 & macho::RF_Scattered);
964 // Target of a scattered relocation is an address. In the interest of
965 // generating pretty output, scan through the symbol table looking for a
966 // symbol that aligns with that address. If we find one, print it.
967 // Otherwise, we just print the hex address of the target.
969 uint32_t Val = RE->Word1;
972 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
974 if (ec) report_fatal_error(ec.message());
979 if ((ec = SI->getAddress(Addr)))
980 report_fatal_error(ec.message());
981 if (Addr != Val) continue;
982 if ((ec = SI->getName(Name)))
983 report_fatal_error(ec.message());
988 // If we couldn't find a symbol that this relocation refers to, try
989 // to find a section beginning instead.
990 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
992 if (ec) report_fatal_error(ec.message());
997 if ((ec = SI->getAddress(Addr)))
998 report_fatal_error(ec.message());
999 if (Addr != Val) continue;
1000 if ((ec = SI->getName(Name)))
1001 report_fatal_error(ec.message());
1006 fmt << format("0x%x", Val);
1011 bool isExtern = (RE->Word1 >> 27) & 1;
1012 uint32_t Val = RE->Word1 & 0xFFFFFF;
1015 symbol_iterator SI = begin_symbols();
1019 section_iterator SI = begin_sections();
1027 error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
1028 SmallVectorImpl<char> &Result) const {
1029 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
1031 unsigned Arch = getArch();
1032 bool isScattered = (Arch != Triple::x86_64) &&
1033 (RE->Word0 & macho::RF_Scattered);
1036 raw_string_ostream fmt(fmtbuf);
1040 Type = (RE->Word0 >> 24) & 0xF;
1042 Type = (RE->Word1 >> 28) & 0xF;
1046 isPCRel = ((RE->Word0 >> 30) & 1);
1048 isPCRel = ((RE->Word1 >> 24) & 1);
1050 // Determine any addends that should be displayed with the relocation.
1051 // These require decoding the relocation type, which is triple-specific.
1053 // X86_64 has entirely custom relocation types.
1054 if (Arch == Triple::x86_64) {
1055 bool isPCRel = ((RE->Word1 >> 24) & 1);
1058 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
1059 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
1060 printRelocationTargetName(RE, fmt);
1062 if (isPCRel) fmt << "PCREL";
1065 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
1066 DataRefImpl RelNext = Rel;
1068 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1070 // X86_64_SUBTRACTOR must be followed by a relocation of type
1071 // X86_64_RELOC_UNSIGNED.
1072 // NOTE: Scattered relocations don't exist on x86_64.
1073 unsigned RType = (RENext->Word1 >> 28) & 0xF;
1075 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1076 "X86_64_RELOC_SUBTRACTOR.");
1078 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1079 // X86_64_SUBTRACTOR contains to the subtrahend.
1080 printRelocationTargetName(RENext, fmt);
1082 printRelocationTargetName(RE, fmt);
1085 case macho::RIT_X86_64_TLV:
1086 printRelocationTargetName(RE, fmt);
1088 if (isPCRel) fmt << "P";
1090 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1091 printRelocationTargetName(RE, fmt);
1094 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1095 printRelocationTargetName(RE, fmt);
1098 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1099 printRelocationTargetName(RE, fmt);
1103 printRelocationTargetName(RE, fmt);
1106 // X86 and ARM share some relocation types in common.
1107 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1108 // Generic relocation types...
1110 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1111 return object_error::success;
1112 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1113 DataRefImpl RelNext = Rel;
1115 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1117 // X86 sect diff's must be followed by a relocation of type
1118 // GENERIC_RELOC_PAIR.
1119 bool isNextScattered = (Arch != Triple::x86_64) &&
1120 (RENext->Word0 & macho::RF_Scattered);
1122 if (isNextScattered)
1123 RType = (RENext->Word0 >> 24) & 0xF;
1125 RType = (RENext->Word1 >> 28) & 0xF;
1127 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1128 "GENERIC_RELOC_SECTDIFF.");
1130 printRelocationTargetName(RE, fmt);
1132 printRelocationTargetName(RENext, fmt);
1137 if (Arch == Triple::x86) {
1138 // All X86 relocations that need special printing were already
1139 // handled in the generic code.
1141 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1142 DataRefImpl RelNext = Rel;
1144 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1146 // X86 sect diff's must be followed by a relocation of type
1147 // GENERIC_RELOC_PAIR.
1148 bool isNextScattered = (Arch != Triple::x86_64) &&
1149 (RENext->Word0 & macho::RF_Scattered);
1151 if (isNextScattered)
1152 RType = (RENext->Word0 >> 24) & 0xF;
1154 RType = (RENext->Word1 >> 28) & 0xF;
1156 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1157 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1159 printRelocationTargetName(RE, fmt);
1161 printRelocationTargetName(RENext, fmt);
1164 case macho::RIT_Generic_TLV: {
1165 printRelocationTargetName(RE, fmt);
1167 if (isPCRel) fmt << "P";
1171 printRelocationTargetName(RE, fmt);
1173 } else { // ARM-specific relocations
1175 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1176 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1177 // Half relocations steal a bit from the length field to encode
1178 // whether this is an upper16 or a lower16 relocation.
1181 isUpper = (RE->Word0 >> 28) & 1;
1183 isUpper = (RE->Word1 >> 25) & 1;
1186 fmt << ":upper16:(";
1188 fmt << ":lower16:(";
1189 printRelocationTargetName(RE, fmt);
1191 DataRefImpl RelNext = Rel;
1193 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1195 // ARM half relocs must be followed by a relocation of type
1197 bool isNextScattered = (Arch != Triple::x86_64) &&
1198 (RENext->Word0 & macho::RF_Scattered);
1200 if (isNextScattered)
1201 RType = (RENext->Word0 >> 24) & 0xF;
1203 RType = (RENext->Word1 >> 28) & 0xF;
1206 report_fatal_error("Expected ARM_RELOC_PAIR after "
1207 "GENERIC_RELOC_HALF");
1209 // NOTE: The half of the target virtual address is stashed in the
1210 // address field of the secondary relocation, but we can't reverse
1211 // engineer the constant offset from it without decoding the movw/movt
1212 // instruction to find the other half in its immediate field.
1214 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1215 // symbol/section pointer of the follow-on relocation.
1216 if (Type == macho::RIT_ARM_HalfDifference) {
1218 printRelocationTargetName(RENext, fmt);
1225 printRelocationTargetName(RE, fmt);
1230 printRelocationTargetName(RE, fmt);
1233 Result.append(fmtbuf.begin(), fmtbuf.end());
1234 return object_error::success;
1237 error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1238 bool &Result) const {
1239 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
1241 unsigned Arch = getArch();
1242 bool isScattered = (Arch != Triple::x86_64) &&
1243 (RE->Word0 & macho::RF_Scattered);
1246 Type = (RE->Word0 >> 24) & 0xF;
1248 Type = (RE->Word1 >> 28) & 0xF;
1252 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1253 // is always hidden.
1254 if (Arch == Triple::x86 || Arch == Triple::arm) {
1255 if (Type == macho::RIT_Pair) Result = true;
1256 } else if (Arch == Triple::x86_64) {
1257 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1258 // an X864_64_RELOC_SUBTRACTOR.
1259 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1260 DataRefImpl RelPrev = Rel;
1262 const MachOFormat::RelocationEntry *REPrev = getRelocation(RelPrev);
1264 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1266 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
1270 return object_error::success;
1273 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1274 LibraryRef &Res) const {
1275 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1278 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1279 StringRef &Res) const {
1280 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1284 /*===-- Miscellaneous -----------------------------------------------------===*/
1286 uint8_t MachOObjectFile::getBytesInAddress() const {
1287 return is64Bit() ? 8 : 4;
1290 StringRef MachOObjectFile::getFileFormatName() const {
1292 switch (getHeader()->CPUType) {
1293 case llvm::MachO::CPUTypeI386:
1294 return "Mach-O 32-bit i386";
1295 case llvm::MachO::CPUTypeARM:
1296 return "Mach-O arm";
1297 case llvm::MachO::CPUTypePowerPC:
1298 return "Mach-O 32-bit ppc";
1300 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) == 0 &&
1301 "64-bit object file when we're not 64-bit?");
1302 return "Mach-O 32-bit unknown";
1306 // Make sure the cpu type has the correct mask.
1307 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64)
1308 == llvm::MachO::CPUArchABI64 &&
1309 "32-bit object file when we're 64-bit?");
1311 switch (getHeader()->CPUType) {
1312 case llvm::MachO::CPUTypeX86_64:
1313 return "Mach-O 64-bit x86-64";
1314 case llvm::MachO::CPUTypePowerPC64:
1315 return "Mach-O 64-bit ppc64";
1317 return "Mach-O 64-bit unknown";
1321 unsigned MachOObjectFile::getArch() const {
1322 switch (getHeader()->CPUType) {
1323 case llvm::MachO::CPUTypeI386:
1325 case llvm::MachO::CPUTypeX86_64:
1326 return Triple::x86_64;
1327 case llvm::MachO::CPUTypeARM:
1329 case llvm::MachO::CPUTypePowerPC:
1331 case llvm::MachO::CPUTypePowerPC64:
1332 return Triple::ppc64;
1334 return Triple::UnknownArch;
1338 } // end namespace object
1339 } // end namespace llvm