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::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);
125 return getSymbolTableEntry(DRI, SymtabLoadCmd);
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());
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);
145 return getSymbol64TableEntry(DRI, SymtabLoadCmd);
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());
159 error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
160 SymbolRef &Result) const {
162 moveToNextSymbol(DRI);
163 Result = SymbolRef(DRI, this);
164 return object_error::success;
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);
173 StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset,
174 SymtabLoadCmd->StringTableSize);
176 uint32_t StringIndex;
178 const MachOFormat::Symbol64TableEntry *Entry =
179 getSymbol64TableEntry(DRI, SymtabLoadCmd);
180 StringIndex = Entry->StringIndex;
182 const MachOFormat::SymbolTableEntry *Entry =
183 getSymbolTableEntry(DRI, SymtabLoadCmd);
184 StringIndex = Entry->StringIndex;
187 const char *Start = &StringTable.data()[StringIndex];
188 Result = StringRef(Start);
190 return object_error::success;
193 error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI,
194 uint64_t &Result) const {
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;
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;
213 return object_error::success;
216 error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
217 uint64_t &Result) const {
219 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
220 Result = Entry->Value;
222 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
223 Result = Entry->Value;
225 return object_error::success;
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;
235 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
236 BeginOffset = Entry->Value;
237 SectionIndex = Entry->SectionIndex;
239 uint32_t flags = SymbolRef::SF_None;
240 getSymbolFlags(DRI, flags);
241 if (flags & SymbolRef::SF_Common)
242 Result = Entry->Value;
244 Result = UnknownAddressOrSize;
245 return object_error::success;
247 // Unfortunately symbols are unsorted so we need to touch all
248 // symbols from load command
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;
262 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
263 BeginOffset = Entry->Value;
264 SectionIndex = Entry->SectionIndex;
266 uint32_t flags = SymbolRef::SF_None;
267 getSymbolFlags(DRI, flags);
268 if (flags & SymbolRef::SF_Common)
269 Result = Entry->Value;
271 Result = UnknownAddressOrSize;
272 return object_error::success;
274 // Unfortunately symbols are unsorted so we need to touch all
275 // symbols from load command
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;
291 getSectionSize(Sections[SectionIndex-1], Size);
292 getSectionAddress(Sections[SectionIndex-1], EndOffset);
295 Result = EndOffset - BeginOffset;
296 return object_error::success;
299 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
300 char &Result) const {
303 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
305 Flags = Entry->Flags;
307 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
309 Flags = Entry->Flags;
313 switch (Type & macho::STF_TypeMask) {
314 case macho::STT_Undefined:
317 case macho::STT_Absolute:
318 case macho::STT_Section:
326 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
327 Char = toupper(static_cast<unsigned char>(Char));
329 return object_error::success;
332 error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
333 uint32_t &Result) const {
337 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
338 MachOFlags = Entry->Flags;
339 MachOType = Entry->Type;
341 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
342 MachOFlags = Entry->Flags;
343 MachOType = Entry->Type;
346 // TODO: Correctly set SF_ThreadLocal
347 Result = SymbolRef::SF_None;
349 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
350 Result |= SymbolRef::SF_Undefined;
352 if (MachOFlags & macho::STF_StabsEntryMask)
353 Result |= SymbolRef::SF_FormatSpecific;
355 if (MachOType & MachO::NlistMaskExternal) {
356 Result |= SymbolRef::SF_Global;
357 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
358 Result |= SymbolRef::SF_Common;
361 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
362 Result |= SymbolRef::SF_Weak;
364 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
365 Result |= SymbolRef::SF_Absolute;
367 return object_error::success;
370 error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
371 section_iterator &Res) const {
374 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
375 index = Entry->SectionIndex;
377 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
378 index = Entry->SectionIndex;
382 Res = end_sections();
384 Res = section_iterator(SectionRef(Sections[index-1], this));
386 return object_error::success;
389 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
390 SymbolRef::Type &Res) const {
393 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
394 n_type = Entry->Type;
396 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
397 n_type = Entry->Type;
399 Res = SymbolRef::ST_Other;
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;
407 switch (n_type & MachO::NlistMaskType) {
408 case MachO::NListTypeUndefined :
409 Res = SymbolRef::ST_Unknown;
411 case MachO::NListTypeSection :
412 Res = SymbolRef::ST_Function;
415 return object_error::success;
418 error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
419 uint64_t &Val) const {
420 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
423 symbol_iterator MachOObjectFile::begin_symbols() const {
424 // DRI.d.a = segment number; DRI.d.b = symbol index.
426 moveToNextSymbol(DRI);
427 return symbol_iterator(SymbolRef(DRI, this));
430 symbol_iterator MachOObjectFile::end_symbols() const {
432 DRI.d.a = getHeader()->NumLoadCommands;
433 return symbol_iterator(SymbolRef(DRI, this));
436 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
438 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
441 symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
443 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
446 library_iterator MachOObjectFile::begin_libraries_needed() const {
448 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
451 library_iterator MachOObjectFile::end_libraries_needed() const {
453 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
456 StringRef MachOObjectFile::getLoadName() const {
458 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
461 /*===-- Sections ----------------------------------------------------------===*/
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)
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)
484 error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
485 SectionRef &Result) const {
487 moveToNextSection(DRI);
488 Result = SectionRef(DRI, this);
489 return object_error::success;
492 const MachOFormat::Section *MachOObjectFile::getSection(DataRefImpl DRI) const {
494 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
495 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
496 uintptr_t SectionAddr = CommandAddr + sizeof(macho::SegmentLoadCommand) +
497 DRI.d.b * sizeof(MachOFormat::Section);
498 return reinterpret_cast<const MachOFormat::Section*>(SectionAddr);
501 std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
502 SectionList::const_iterator loc =
503 std::find(Sections.begin(), Sections.end(), Sec);
504 assert(loc != Sections.end() && "Sec is not a valid section!");
505 return std::distance(Sections.begin(), loc);
508 const MachOFormat::Section64 *
509 MachOObjectFile::getSection64(DataRefImpl DRI) const {
511 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
512 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
513 uintptr_t SectionAddr = CommandAddr + sizeof(macho::Segment64LoadCommand) +
514 DRI.d.b * sizeof(MachOFormat::Section64);
515 return reinterpret_cast<const MachOFormat::Section64*>(SectionAddr);
518 static StringRef parseSegmentOrSectionName(const char *P) {
522 // Not null terminated, so this is a 16 char string.
523 return StringRef(P, 16);
526 ArrayRef<char> MachOObjectFile::getSectionRawName(DataRefImpl DRI) const {
528 const MachOFormat::Section64 *sec = getSection64(DRI);
529 return ArrayRef<char>(sec->Name);
531 const MachOFormat::Section *sec = getSection(DRI);
532 return ArrayRef<char>(sec->Name);
536 error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
537 StringRef &Result) const {
538 ArrayRef<char> Raw = getSectionRawName(DRI);
539 Result = parseSegmentOrSectionName(Raw.data());
540 return object_error::success;
544 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
546 const MachOFormat::Section64 *sec = getSection64(Sec);
547 return ArrayRef<char>(sec->SegmentName, 16);
549 const MachOFormat::Section *sec = getSection(Sec);
550 return ArrayRef<char>(sec->SegmentName);
554 StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const {
555 ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
556 return parseSegmentOrSectionName(Raw.data());
559 error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
560 uint64_t &Result) const {
562 const MachOFormat::Section64 *Sect = getSection64(DRI);
563 Result = Sect->Address;
565 const MachOFormat::Section *Sect = getSection(DRI);
566 Result = Sect->Address;
568 return object_error::success;
571 error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
572 uint64_t &Result) const {
574 const MachOFormat::Section64 *Sect = getSection64(DRI);
577 const MachOFormat::Section *Sect = getSection(DRI);
580 return object_error::success;
583 error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
584 StringRef &Result) const {
586 const MachOFormat::Section64 *Sect = getSection64(DRI);
587 Result = getData(Sect->Offset, Sect->Size);
589 const MachOFormat::Section *Sect = getSection(DRI);
590 Result = getData(Sect->Offset, Sect->Size);
592 return object_error::success;
595 error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
596 uint64_t &Result) const {
598 const MachOFormat::Section64 *Sect = getSection64(DRI);
599 Result = uint64_t(1) << Sect->Align;
601 const MachOFormat::Section *Sect = getSection(DRI);
602 Result = uint64_t(1) << Sect->Align;
604 return object_error::success;
607 error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
608 bool &Result) const {
610 const MachOFormat::Section64 *Sect = getSection64(DRI);
611 Result = Sect->Flags & macho::SF_PureInstructions;
613 const MachOFormat::Section *Sect = getSection(DRI);
614 Result = Sect->Flags & macho::SF_PureInstructions;
616 return object_error::success;
619 error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
620 bool &Result) const {
621 // FIXME: Unimplemented.
623 return object_error::success;
626 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
627 bool &Result) const {
628 // FIXME: Unimplemented.
630 return object_error::success;
633 error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
634 bool &Result) const {
635 // FIXME: Unimplemented.
637 return object_error::success;
640 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
641 bool &Result) const {
642 // FIXME: Unimplemented.
644 return object_error::success;
647 error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI,
648 bool &Result) const {
650 const MachOFormat::Section64 *Sect = getSection64(DRI);
651 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
652 Result = (SectionType == MachO::SectionTypeZeroFill ||
653 SectionType == MachO::SectionTypeZeroFillLarge);
655 const MachOFormat::Section *Sect = getSection(DRI);
656 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
657 Result = (SectionType == MachO::SectionTypeZeroFill ||
658 SectionType == MachO::SectionTypeZeroFillLarge);
661 return object_error::success;
664 error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
665 bool &Result) const {
666 // Consider using the code from isSectionText to look for __const sections.
667 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
668 // to use section attributes to distinguish code from data.
670 // FIXME: Unimplemented.
672 return object_error::success;
675 error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
677 bool &Result) const {
679 getSymbolType(Symb, ST);
680 if (ST == SymbolRef::ST_Unknown) {
682 return object_error::success;
685 uint64_t SectBegin, SectEnd;
686 getSectionAddress(Sec, SectBegin);
687 getSectionSize(Sec, SectEnd);
688 SectEnd += SectBegin;
691 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
692 uint64_t SymAddr= Entry->Value;
693 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
695 const MachOFormat::SymbolTableEntry *Entry = 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));
708 relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
711 const MachOFormat::Section64 *Sect = getSection64(Sec);
712 last_reloc = Sect->NumRelocationTableEntries;
714 const MachOFormat::Section *Sect = getSection(Sec);
715 last_reloc = Sect->NumRelocationTableEntries;
718 ret.d.a = last_reloc;
719 ret.d.b = getSectionIndex(Sec);
720 return relocation_iterator(RelocationRef(ret, this));
723 section_iterator MachOObjectFile::begin_sections() const {
725 moveToNextSection(DRI);
726 return section_iterator(SectionRef(DRI, this));
729 section_iterator MachOObjectFile::end_sections() const {
731 DRI.d.a = getHeader()->NumLoadCommands;
732 return section_iterator(SectionRef(DRI, this));
735 /*===-- Relocations -------------------------------------------------------===*/
737 const MachOFormat::RelocationEntry *
738 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
741 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
742 relOffset = Sect->RelocationTableOffset;
744 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
745 relOffset = Sect->RelocationTableOffset;
747 uint64_t Offset = relOffset + Rel.d.a * sizeof(MachOFormat::RelocationEntry);
748 StringRef Data = getData(Offset, sizeof(MachOFormat::RelocationEntry));
749 return reinterpret_cast<const MachOFormat::RelocationEntry*>(Data.data());
752 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
753 RelocationRef &Res) const {
755 Res = RelocationRef(Rel, this);
756 return object_error::success;
758 error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
759 uint64_t &Res) const {
760 const uint8_t* sectAddress = 0;
762 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
763 sectAddress += Sect->Address;
765 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
766 sectAddress += Sect->Address;
768 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
770 unsigned Arch = getArch();
771 bool isScattered = (Arch != Triple::x86_64) &&
772 (RE->Word0 & macho::RF_Scattered);
773 uint64_t RelAddr = 0;
775 RelAddr = RE->Word0 & 0xFFFFFF;
779 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
780 return object_error::success;
782 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
783 uint64_t &Res) const {
784 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
786 unsigned Arch = getArch();
787 bool isScattered = (Arch != Triple::x86_64) &&
788 (RE->Word0 & macho::RF_Scattered);
790 Res = RE->Word0 & 0xFFFFFF;
793 return object_error::success;
795 error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
796 SymbolRef &Res) const {
797 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
798 uint32_t SymbolIdx = RE->Word1 & 0xffffff;
799 bool isExtern = (RE->Word1 >> 27) & 1;
802 moveToNextSymbol(Sym);
804 for (unsigned i = 0; i < SymbolIdx; i++) {
806 moveToNextSymbol(Sym);
807 assert(Sym.d.a < getHeader()->NumLoadCommands &&
808 "Relocation symbol index out of range!");
811 Res = SymbolRef(Sym, this);
812 return object_error::success;
814 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
815 uint64_t &Res) const {
816 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
820 return object_error::success;
822 error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
823 SmallVectorImpl<char> &Result) const {
824 // TODO: Support scattered relocations.
826 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
828 unsigned Arch = getArch();
829 bool isScattered = (Arch != Triple::x86_64) &&
830 (RE->Word0 & macho::RF_Scattered);
834 r_type = (RE->Word0 >> 24) & 0xF;
836 r_type = (RE->Word1 >> 28) & 0xF;
840 static const char *const Table[] = {
841 "GENERIC_RELOC_VANILLA",
842 "GENERIC_RELOC_PAIR",
843 "GENERIC_RELOC_SECTDIFF",
844 "GENERIC_RELOC_PB_LA_PTR",
845 "GENERIC_RELOC_LOCAL_SECTDIFF",
846 "GENERIC_RELOC_TLV" };
854 case Triple::x86_64: {
855 static const char *const Table[] = {
856 "X86_64_RELOC_UNSIGNED",
857 "X86_64_RELOC_SIGNED",
858 "X86_64_RELOC_BRANCH",
859 "X86_64_RELOC_GOT_LOAD",
861 "X86_64_RELOC_SUBTRACTOR",
862 "X86_64_RELOC_SIGNED_1",
863 "X86_64_RELOC_SIGNED_2",
864 "X86_64_RELOC_SIGNED_4",
865 "X86_64_RELOC_TLV" };
874 static const char *const Table[] = {
877 "ARM_RELOC_SECTDIFF",
878 "ARM_RELOC_LOCAL_SECTDIFF",
879 "ARM_RELOC_PB_LA_PTR",
881 "ARM_THUMB_RELOC_BR22",
882 "ARM_THUMB_32BIT_BRANCH",
884 "ARM_RELOC_HALF_SECTDIFF" };
893 static const char *const Table[] = {
902 "PPC_RELOC_SECTDIFF",
903 "PPC_RELOC_PB_LA_PTR",
904 "PPC_RELOC_HI16_SECTDIFF",
905 "PPC_RELOC_LO16_SECTDIFF",
906 "PPC_RELOC_HA16_SECTDIFF",
908 "PPC_RELOC_LO14_SECTDIFF",
909 "PPC_RELOC_LOCAL_SECTDIFF" };
914 case Triple::UnknownArch:
918 Result.append(res.begin(), res.end());
919 return object_error::success;
921 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
922 int64_t &Res) const {
923 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
924 bool isExtern = (RE->Word1 >> 27) & 1;
927 const uint8_t* sectAddress = base();
929 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
930 sectAddress += Sect->Offset;
932 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
933 sectAddress += Sect->Offset;
935 Res = reinterpret_cast<uintptr_t>(sectAddress);
937 return object_error::success;
940 // Helper to advance a section or symbol iterator multiple increments at a time.
942 error_code advance(T &it, size_t Val) {
951 void advanceTo(T &it, size_t Val) {
952 if (error_code ec = advance(it, Val))
953 report_fatal_error(ec.message());
956 void MachOObjectFile::printRelocationTargetName(
957 const MachOFormat::RelocationEntry *RE,
958 raw_string_ostream &fmt) const {
959 unsigned Arch = getArch();
960 bool isScattered = (Arch != Triple::x86_64) &&
961 (RE->Word0 & macho::RF_Scattered);
963 // Target of a scattered relocation is an address. In the interest of
964 // generating pretty output, scan through the symbol table looking for a
965 // symbol that aligns with that address. If we find one, print it.
966 // Otherwise, we just print the hex address of the target.
968 uint32_t Val = RE->Word1;
971 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
973 if (ec) report_fatal_error(ec.message());
978 if ((ec = SI->getAddress(Addr)))
979 report_fatal_error(ec.message());
980 if (Addr != Val) continue;
981 if ((ec = SI->getName(Name)))
982 report_fatal_error(ec.message());
987 // If we couldn't find a symbol that this relocation refers to, try
988 // to find a section beginning instead.
989 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
991 if (ec) report_fatal_error(ec.message());
996 if ((ec = SI->getAddress(Addr)))
997 report_fatal_error(ec.message());
998 if (Addr != Val) continue;
999 if ((ec = SI->getName(Name)))
1000 report_fatal_error(ec.message());
1005 fmt << format("0x%x", Val);
1010 bool isExtern = (RE->Word1 >> 27) & 1;
1011 uint32_t Val = RE->Word1 & 0xFFFFFF;
1014 symbol_iterator SI = begin_symbols();
1018 section_iterator SI = begin_sections();
1026 error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
1027 SmallVectorImpl<char> &Result) const {
1028 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
1030 unsigned Arch = getArch();
1031 bool isScattered = (Arch != Triple::x86_64) &&
1032 (RE->Word0 & macho::RF_Scattered);
1035 raw_string_ostream fmt(fmtbuf);
1039 Type = (RE->Word0 >> 24) & 0xF;
1041 Type = (RE->Word1 >> 28) & 0xF;
1045 isPCRel = ((RE->Word0 >> 30) & 1);
1047 isPCRel = ((RE->Word1 >> 24) & 1);
1049 // Determine any addends that should be displayed with the relocation.
1050 // These require decoding the relocation type, which is triple-specific.
1052 // X86_64 has entirely custom relocation types.
1053 if (Arch == Triple::x86_64) {
1054 bool isPCRel = ((RE->Word1 >> 24) & 1);
1057 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
1058 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
1059 printRelocationTargetName(RE, fmt);
1061 if (isPCRel) fmt << "PCREL";
1064 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
1065 DataRefImpl RelNext = Rel;
1067 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1069 // X86_64_SUBTRACTOR must be followed by a relocation of type
1070 // X86_64_RELOC_UNSIGNED.
1071 // NOTE: Scattered relocations don't exist on x86_64.
1072 unsigned RType = (RENext->Word1 >> 28) & 0xF;
1074 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1075 "X86_64_RELOC_SUBTRACTOR.");
1077 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1078 // X86_64_SUBTRACTOR contains to the subtrahend.
1079 printRelocationTargetName(RENext, fmt);
1081 printRelocationTargetName(RE, fmt);
1084 case macho::RIT_X86_64_TLV:
1085 printRelocationTargetName(RE, fmt);
1087 if (isPCRel) fmt << "P";
1089 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1090 printRelocationTargetName(RE, fmt);
1093 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1094 printRelocationTargetName(RE, fmt);
1097 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1098 printRelocationTargetName(RE, fmt);
1102 printRelocationTargetName(RE, fmt);
1105 // X86 and ARM share some relocation types in common.
1106 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1107 // Generic relocation types...
1109 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1110 return object_error::success;
1111 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1112 DataRefImpl RelNext = Rel;
1114 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1116 // X86 sect diff's must be followed by a relocation of type
1117 // GENERIC_RELOC_PAIR.
1118 bool isNextScattered = (Arch != Triple::x86_64) &&
1119 (RENext->Word0 & macho::RF_Scattered);
1121 if (isNextScattered)
1122 RType = (RENext->Word0 >> 24) & 0xF;
1124 RType = (RENext->Word1 >> 28) & 0xF;
1126 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1127 "GENERIC_RELOC_SECTDIFF.");
1129 printRelocationTargetName(RE, fmt);
1131 printRelocationTargetName(RENext, fmt);
1136 if (Arch == Triple::x86) {
1137 // All X86 relocations that need special printing were already
1138 // handled in the generic code.
1140 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1141 DataRefImpl RelNext = Rel;
1143 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1145 // X86 sect diff's must be followed by a relocation of type
1146 // GENERIC_RELOC_PAIR.
1147 bool isNextScattered = (Arch != Triple::x86_64) &&
1148 (RENext->Word0 & macho::RF_Scattered);
1150 if (isNextScattered)
1151 RType = (RENext->Word0 >> 24) & 0xF;
1153 RType = (RENext->Word1 >> 28) & 0xF;
1155 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1156 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1158 printRelocationTargetName(RE, fmt);
1160 printRelocationTargetName(RENext, fmt);
1163 case macho::RIT_Generic_TLV: {
1164 printRelocationTargetName(RE, fmt);
1166 if (isPCRel) fmt << "P";
1170 printRelocationTargetName(RE, fmt);
1172 } else { // ARM-specific relocations
1174 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1175 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1176 // Half relocations steal a bit from the length field to encode
1177 // whether this is an upper16 or a lower16 relocation.
1180 isUpper = (RE->Word0 >> 28) & 1;
1182 isUpper = (RE->Word1 >> 25) & 1;
1185 fmt << ":upper16:(";
1187 fmt << ":lower16:(";
1188 printRelocationTargetName(RE, fmt);
1190 DataRefImpl RelNext = Rel;
1192 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1194 // ARM half relocs must be followed by a relocation of type
1196 bool isNextScattered = (Arch != Triple::x86_64) &&
1197 (RENext->Word0 & macho::RF_Scattered);
1199 if (isNextScattered)
1200 RType = (RENext->Word0 >> 24) & 0xF;
1202 RType = (RENext->Word1 >> 28) & 0xF;
1205 report_fatal_error("Expected ARM_RELOC_PAIR after "
1206 "GENERIC_RELOC_HALF");
1208 // NOTE: The half of the target virtual address is stashed in the
1209 // address field of the secondary relocation, but we can't reverse
1210 // engineer the constant offset from it without decoding the movw/movt
1211 // instruction to find the other half in its immediate field.
1213 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1214 // symbol/section pointer of the follow-on relocation.
1215 if (Type == macho::RIT_ARM_HalfDifference) {
1217 printRelocationTargetName(RENext, fmt);
1224 printRelocationTargetName(RE, fmt);
1229 printRelocationTargetName(RE, fmt);
1232 Result.append(fmtbuf.begin(), fmtbuf.end());
1233 return object_error::success;
1236 error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1237 bool &Result) const {
1238 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
1240 unsigned Arch = getArch();
1241 bool isScattered = (Arch != Triple::x86_64) &&
1242 (RE->Word0 & macho::RF_Scattered);
1245 Type = (RE->Word0 >> 24) & 0xF;
1247 Type = (RE->Word1 >> 28) & 0xF;
1251 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1252 // is always hidden.
1253 if (Arch == Triple::x86 || Arch == Triple::arm) {
1254 if (Type == macho::RIT_Pair) Result = true;
1255 } else if (Arch == Triple::x86_64) {
1256 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1257 // an X864_64_RELOC_SUBTRACTOR.
1258 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1259 DataRefImpl RelPrev = Rel;
1261 const MachOFormat::RelocationEntry *REPrev = getRelocation(RelPrev);
1263 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1265 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
1269 return object_error::success;
1272 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1273 LibraryRef &Res) const {
1274 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1277 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1278 StringRef &Res) const {
1279 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1283 /*===-- Miscellaneous -----------------------------------------------------===*/
1285 uint8_t MachOObjectFile::getBytesInAddress() const {
1286 return is64Bit() ? 8 : 4;
1289 StringRef MachOObjectFile::getFileFormatName() const {
1291 switch (getHeader()->CPUType) {
1292 case llvm::MachO::CPUTypeI386:
1293 return "Mach-O 32-bit i386";
1294 case llvm::MachO::CPUTypeARM:
1295 return "Mach-O arm";
1296 case llvm::MachO::CPUTypePowerPC:
1297 return "Mach-O 32-bit ppc";
1299 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) == 0 &&
1300 "64-bit object file when we're not 64-bit?");
1301 return "Mach-O 32-bit unknown";
1305 // Make sure the cpu type has the correct mask.
1306 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64)
1307 == llvm::MachO::CPUArchABI64 &&
1308 "32-bit object file when we're 64-bit?");
1310 switch (getHeader()->CPUType) {
1311 case llvm::MachO::CPUTypeX86_64:
1312 return "Mach-O 64-bit x86-64";
1313 case llvm::MachO::CPUTypePowerPC64:
1314 return "Mach-O 64-bit ppc64";
1316 return "Mach-O 64-bit unknown";
1320 unsigned MachOObjectFile::getArch() const {
1321 switch (getHeader()->CPUType) {
1322 case llvm::MachO::CPUTypeI386:
1324 case llvm::MachO::CPUTypeX86_64:
1325 return Triple::x86_64;
1326 case llvm::MachO::CPUTypeARM:
1328 case llvm::MachO::CPUTypePowerPC:
1330 case llvm::MachO::CPUTypePowerPC64:
1331 return Triple::ppc64;
1333 return Triple::UnknownArch;
1337 } // end namespace object
1338 } // end namespace llvm