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/Format.h"
19 #include "llvm/Support/MemoryBuffer.h"
25 using namespace object;
30 MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, error_code &ec)
31 : ObjectFile(Binary::ID_MachO, Object) {
32 // MachOObject takes ownership of the Buffer we passed to it, and
33 // MachOObjectFile does, too, so we need to make sure they don't get the
34 // same object. A MemoryBuffer is cheap (it's just a reference to memory,
35 // not a copy of the memory itself), so just make a new copy here for
36 // the MachOObjectFile.
37 MemoryBuffer *NewBuffer =
38 MemoryBuffer::getMemBuffer(Object->getBuffer(),
39 Object->getBufferIdentifier(), false);
41 MachOObj.reset(MachOObject::LoadFromBuffer(NewBuffer, &ErrorStr));
43 ec = object_error::parse_failed;
48 moveToNextSection(DRI);
49 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
50 while (DRI.d.a < LoadCommandCount) {
51 Sections.push_back(DRI);
53 moveToNextSection(DRI);
57 bool MachOObjectFile::is64Bit() const {
58 return MachOObj->is64Bit();
61 const MachOFormat::LoadCommand *
62 MachOObjectFile::getLoadCommandInfo(unsigned Index) const {
64 uint64_t NewOffset = getHeaderSize();
65 const MachOFormat::LoadCommand *Load;
69 StringRef Data = getData(Offset, sizeof(MachOFormat::LoadCommand));
70 Load = reinterpret_cast<const MachOFormat::LoadCommand*>(Data.data());
71 NewOffset = Offset + Load->Size;
73 } while (I != Index + 1);
78 void MachOObjectFile::ReadULEB128s(uint64_t Index,
79 SmallVectorImpl<uint64_t> &Out) const {
80 return MachOObj->ReadULEB128s(Index, Out);
83 const MachOFormat::Header *MachOObjectFile::getHeader() const {
84 StringRef Data = getData(0, sizeof(MachOFormat::Header));
85 return reinterpret_cast<const MachOFormat::Header*>(Data.data());
88 unsigned MachOObjectFile::getHeaderSize() const {
89 return is64Bit() ? macho::Header64Size : macho::Header32Size;
92 StringRef MachOObjectFile::getData(size_t Offset, size_t Size) const {
93 return MachOObj->getData(Offset, Size);
96 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
98 ObjectFile *Ret = new MachOObjectFile(Buffer, ec);
104 /*===-- Symbols -----------------------------------------------------------===*/
106 void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
107 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
108 while (DRI.d.a < LoadCommandCount) {
109 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
110 if (Command->Type == macho::LCT_Symtab) {
111 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
112 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
113 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
122 const MachOFormat::SymbolTableEntry *
123 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
124 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
125 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
126 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
128 return getSymbolTableEntry(DRI, SymtabLoadCmd);
131 const MachOFormat::SymbolTableEntry *
132 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI,
133 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
134 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
135 unsigned Index = DRI.d.b;
136 uint64_t Offset = (SymbolTableOffset +
137 Index * sizeof(macho::SymbolTableEntry));
138 StringRef Data = getData(Offset, sizeof(MachOFormat::SymbolTableEntry));
139 return reinterpret_cast<const MachOFormat::SymbolTableEntry*>(Data.data());
142 const MachOFormat::Symbol64TableEntry*
143 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
144 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
145 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
146 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
148 return getSymbol64TableEntry(DRI, SymtabLoadCmd);
151 const MachOFormat::Symbol64TableEntry*
152 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI,
153 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
154 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
155 unsigned Index = DRI.d.b;
156 uint64_t Offset = (SymbolTableOffset +
157 Index * sizeof(macho::Symbol64TableEntry));
158 StringRef Data = getData(Offset, sizeof(MachOFormat::Symbol64TableEntry));
159 return reinterpret_cast<const MachOFormat::Symbol64TableEntry*>(Data.data());
162 error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
163 SymbolRef &Result) const {
165 moveToNextSymbol(DRI);
166 Result = SymbolRef(DRI, this);
167 return object_error::success;
170 error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
171 StringRef &Result) const {
172 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
173 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
174 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
176 StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset,
177 SymtabLoadCmd->StringTableSize);
179 uint32_t StringIndex;
181 const MachOFormat::Symbol64TableEntry *Entry =
182 getSymbol64TableEntry(DRI, SymtabLoadCmd);
183 StringIndex = Entry->StringIndex;
185 const MachOFormat::SymbolTableEntry *Entry =
186 getSymbolTableEntry(DRI, SymtabLoadCmd);
187 StringIndex = Entry->StringIndex;
190 const char *Start = &StringTable.data()[StringIndex];
191 Result = StringRef(Start);
193 return object_error::success;
196 error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI,
197 uint64_t &Result) const {
199 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
200 Result = Entry->Value;
201 if (Entry->SectionIndex) {
202 const MachOFormat::Section64 *Section =
203 getSection64(Sections[Entry->SectionIndex-1]);
204 Result += Section->Offset - Section->Address;
207 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
208 Result = Entry->Value;
209 if (Entry->SectionIndex) {
210 const MachOFormat::Section *Section =
211 getSection(Sections[Entry->SectionIndex-1]);
212 Result += Section->Offset - Section->Address;
216 return object_error::success;
219 error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
220 uint64_t &Result) const {
222 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
223 Result = Entry->Value;
225 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
226 Result = Entry->Value;
228 return object_error::success;
231 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
232 uint64_t &Result) const {
233 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
234 uint64_t BeginOffset;
235 uint64_t EndOffset = 0;
236 uint8_t SectionIndex;
238 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
239 BeginOffset = Entry->Value;
240 SectionIndex = Entry->SectionIndex;
242 uint32_t flags = SymbolRef::SF_None;
243 getSymbolFlags(DRI, flags);
244 if (flags & SymbolRef::SF_Common)
245 Result = Entry->Value;
247 Result = UnknownAddressOrSize;
248 return object_error::success;
250 // Unfortunately symbols are unsorted so we need to touch all
251 // symbols from load command
253 uint32_t Command = DRI.d.a;
254 while (Command == DRI.d.a) {
255 moveToNextSymbol(DRI);
256 if (DRI.d.a < LoadCommandCount) {
257 Entry = getSymbol64TableEntry(DRI);
258 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
259 if (!EndOffset || Entry->Value < EndOffset)
260 EndOffset = Entry->Value;
265 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
266 BeginOffset = Entry->Value;
267 SectionIndex = Entry->SectionIndex;
269 uint32_t flags = SymbolRef::SF_None;
270 getSymbolFlags(DRI, flags);
271 if (flags & SymbolRef::SF_Common)
272 Result = Entry->Value;
274 Result = UnknownAddressOrSize;
275 return object_error::success;
277 // Unfortunately symbols are unsorted so we need to touch all
278 // symbols from load command
280 uint32_t Command = DRI.d.a;
281 while (Command == DRI.d.a) {
282 moveToNextSymbol(DRI);
283 if (DRI.d.a < LoadCommandCount) {
284 Entry = getSymbolTableEntry(DRI);
285 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
286 if (!EndOffset || Entry->Value < EndOffset)
287 EndOffset = Entry->Value;
294 getSectionSize(Sections[SectionIndex-1], Size);
295 getSectionAddress(Sections[SectionIndex-1], EndOffset);
298 Result = EndOffset - BeginOffset;
299 return object_error::success;
302 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
303 char &Result) const {
306 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
308 Flags = Entry->Flags;
310 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
312 Flags = Entry->Flags;
316 switch (Type & macho::STF_TypeMask) {
317 case macho::STT_Undefined:
320 case macho::STT_Absolute:
321 case macho::STT_Section:
329 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
330 Char = toupper(static_cast<unsigned char>(Char));
332 return object_error::success;
335 error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
336 uint32_t &Result) const {
340 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
341 MachOFlags = Entry->Flags;
342 MachOType = Entry->Type;
344 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
345 MachOFlags = Entry->Flags;
346 MachOType = Entry->Type;
349 // TODO: Correctly set SF_ThreadLocal
350 Result = SymbolRef::SF_None;
352 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
353 Result |= SymbolRef::SF_Undefined;
355 if (MachOFlags & macho::STF_StabsEntryMask)
356 Result |= SymbolRef::SF_FormatSpecific;
358 if (MachOType & MachO::NlistMaskExternal) {
359 Result |= SymbolRef::SF_Global;
360 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
361 Result |= SymbolRef::SF_Common;
364 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
365 Result |= SymbolRef::SF_Weak;
367 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
368 Result |= SymbolRef::SF_Absolute;
370 return object_error::success;
373 error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
374 section_iterator &Res) const {
377 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
378 index = Entry->SectionIndex;
380 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
381 index = Entry->SectionIndex;
385 Res = end_sections();
387 Res = section_iterator(SectionRef(Sections[index-1], this));
389 return object_error::success;
392 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
393 SymbolRef::Type &Res) const {
396 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
397 n_type = Entry->Type;
399 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
400 n_type = Entry->Type;
402 Res = SymbolRef::ST_Other;
404 // If this is a STAB debugging symbol, we can do nothing more.
405 if (n_type & MachO::NlistMaskStab) {
406 Res = SymbolRef::ST_Debug;
407 return object_error::success;
410 switch (n_type & MachO::NlistMaskType) {
411 case MachO::NListTypeUndefined :
412 Res = SymbolRef::ST_Unknown;
414 case MachO::NListTypeSection :
415 Res = SymbolRef::ST_Function;
418 return object_error::success;
421 error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
422 uint64_t &Val) const {
423 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
426 symbol_iterator MachOObjectFile::begin_symbols() const {
427 // DRI.d.a = segment number; DRI.d.b = symbol index.
429 moveToNextSymbol(DRI);
430 return symbol_iterator(SymbolRef(DRI, this));
433 symbol_iterator MachOObjectFile::end_symbols() const {
435 DRI.d.a = getHeader()->NumLoadCommands;
436 return symbol_iterator(SymbolRef(DRI, this));
439 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
441 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
444 symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
446 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
449 library_iterator MachOObjectFile::begin_libraries_needed() const {
451 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
454 library_iterator MachOObjectFile::end_libraries_needed() const {
456 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
459 StringRef MachOObjectFile::getLoadName() const {
461 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
464 /*===-- Sections ----------------------------------------------------------===*/
466 void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
467 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
468 while (DRI.d.a < LoadCommandCount) {
469 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
470 if (Command->Type == macho::LCT_Segment) {
471 const MachOFormat::SegmentLoadCommand *SegmentLoadCmd =
472 reinterpret_cast<const MachOFormat::SegmentLoadCommand*>(Command);
473 if (DRI.d.b < SegmentLoadCmd->NumSections)
475 } else if (Command->Type == macho::LCT_Segment64) {
476 const MachOFormat::Segment64LoadCommand *Segment64LoadCmd =
477 reinterpret_cast<const MachOFormat::Segment64LoadCommand*>(Command);
478 if (DRI.d.b < Segment64LoadCmd->NumSections)
487 error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
488 SectionRef &Result) const {
490 moveToNextSection(DRI);
491 Result = SectionRef(DRI, this);
492 return object_error::success;
495 static bool is64BitLoadCommand(const MachOObjectFile *MachOObj,
497 const MachOFormat::LoadCommand *Command =
498 MachOObj->getLoadCommandInfo(DRI.d.a);
499 if (Command->Type == macho::LCT_Segment64)
501 assert(Command->Type == macho::LCT_Segment && "Unexpected Type.");
505 const MachOFormat::Section *MachOObjectFile::getSection(DataRefImpl DRI) const {
506 assert(!is64BitLoadCommand(this, DRI));
507 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
508 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
509 uintptr_t SectionAddr = CommandAddr + sizeof(macho::SegmentLoadCommand) +
510 DRI.d.b * sizeof(MachOFormat::Section);
511 return reinterpret_cast<const MachOFormat::Section*>(SectionAddr);
514 std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
515 SectionList::const_iterator loc =
516 std::find(Sections.begin(), Sections.end(), Sec);
517 assert(loc != Sections.end() && "Sec is not a valid section!");
518 return std::distance(Sections.begin(), loc);
521 const MachOFormat::Section64 *
522 MachOObjectFile::getSection64(DataRefImpl DRI) const {
523 assert(is64BitLoadCommand(this, DRI));
524 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
525 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
526 uintptr_t SectionAddr = CommandAddr + sizeof(macho::Segment64LoadCommand) +
527 DRI.d.b * sizeof(MachOFormat::Section64);
528 return reinterpret_cast<const MachOFormat::Section64*>(SectionAddr);
531 static StringRef parseSegmentOrSectionName(const char *P) {
535 // Not null terminated, so this is a 16 char string.
536 return StringRef(P, 16);
539 ArrayRef<char> MachOObjectFile::getSectionRawName(DataRefImpl DRI) const {
540 if (is64BitLoadCommand(this, DRI)) {
541 const MachOFormat::Section64 *sec = getSection64(DRI);
542 return ArrayRef<char>(sec->Name);
544 const MachOFormat::Section *sec = getSection(DRI);
545 return ArrayRef<char>(sec->Name);
549 error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
550 StringRef &Result) const {
551 ArrayRef<char> Raw = getSectionRawName(DRI);
552 Result = parseSegmentOrSectionName(Raw.data());
553 return object_error::success;
557 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
558 if (is64BitLoadCommand(this, Sec)) {
559 const MachOFormat::Section64 *sec = getSection64(Sec);
560 return ArrayRef<char>(sec->SegmentName, 16);
562 const MachOFormat::Section *sec = getSection(Sec);
563 return ArrayRef<char>(sec->SegmentName);
567 StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const {
568 ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
569 return parseSegmentOrSectionName(Raw.data());
572 error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
573 uint64_t &Result) const {
574 if (is64BitLoadCommand(this, DRI)) {
575 const MachOFormat::Section64 *Sect = getSection64(DRI);
576 Result = Sect->Address;
578 const MachOFormat::Section *Sect = getSection(DRI);
579 Result = Sect->Address;
581 return object_error::success;
584 error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
585 uint64_t &Result) const {
586 if (is64BitLoadCommand(this, DRI)) {
587 const MachOFormat::Section64 *Sect = getSection64(DRI);
590 const MachOFormat::Section *Sect = getSection(DRI);
593 return object_error::success;
596 error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
597 StringRef &Result) const {
598 if (is64BitLoadCommand(this, DRI)) {
599 const MachOFormat::Section64 *Sect = getSection64(DRI);
600 Result = getData(Sect->Offset, Sect->Size);
602 const MachOFormat::Section *Sect = getSection(DRI);
603 Result = getData(Sect->Offset, Sect->Size);
605 return object_error::success;
608 error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
609 uint64_t &Result) const {
610 if (is64BitLoadCommand(this, DRI)) {
611 const MachOFormat::Section64 *Sect = getSection64(DRI);
612 Result = uint64_t(1) << Sect->Align;
614 const MachOFormat::Section *Sect = getSection(DRI);
615 Result = uint64_t(1) << Sect->Align;
617 return object_error::success;
620 error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
621 bool &Result) const {
622 if (is64BitLoadCommand(this, DRI)) {
623 const MachOFormat::Section64 *Sect = getSection64(DRI);
624 Result = Sect->Flags & macho::SF_PureInstructions;
626 const MachOFormat::Section *Sect = getSection(DRI);
627 Result = Sect->Flags & macho::SF_PureInstructions;
629 return object_error::success;
632 error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
633 bool &Result) const {
634 // FIXME: Unimplemented.
636 return object_error::success;
639 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
640 bool &Result) const {
641 // FIXME: Unimplemented.
643 return object_error::success;
646 error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
647 bool &Result) const {
648 // FIXME: Unimplemented.
650 return object_error::success;
653 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
654 bool &Result) const {
655 // FIXME: Unimplemented.
657 return object_error::success;
660 error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI,
661 bool &Result) const {
663 const MachOFormat::Section64 *Sect = getSection64(DRI);
664 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
665 Result = (SectionType == MachO::SectionTypeZeroFill ||
666 SectionType == MachO::SectionTypeZeroFillLarge);
668 const MachOFormat::Section *Sect = getSection(DRI);
669 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
670 Result = (SectionType == MachO::SectionTypeZeroFill ||
671 SectionType == MachO::SectionTypeZeroFillLarge);
674 return object_error::success;
677 error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
678 bool &Result) const {
679 // Consider using the code from isSectionText to look for __const sections.
680 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
681 // to use section attributes to distinguish code from data.
683 // FIXME: Unimplemented.
685 return object_error::success;
688 error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
690 bool &Result) const {
692 getSymbolType(Symb, ST);
693 if (ST == SymbolRef::ST_Unknown) {
695 return object_error::success;
698 uint64_t SectBegin, SectEnd;
699 getSectionAddress(Sec, SectBegin);
700 getSectionSize(Sec, SectEnd);
701 SectEnd += SectBegin;
704 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
705 uint64_t SymAddr= Entry->Value;
706 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
708 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
709 uint64_t SymAddr= Entry->Value;
710 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
713 return object_error::success;
716 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
718 ret.d.b = getSectionIndex(Sec);
719 return relocation_iterator(RelocationRef(ret, this));
721 relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
723 if (is64BitLoadCommand(this, Sec)) {
724 const MachOFormat::Section64 *Sect = getSection64(Sec);
725 last_reloc = Sect->NumRelocationTableEntries;
727 const MachOFormat::Section *Sect = getSection(Sec);
728 last_reloc = Sect->NumRelocationTableEntries;
731 ret.d.a = last_reloc;
732 ret.d.b = getSectionIndex(Sec);
733 return relocation_iterator(RelocationRef(ret, this));
736 section_iterator MachOObjectFile::begin_sections() const {
738 moveToNextSection(DRI);
739 return section_iterator(SectionRef(DRI, this));
742 section_iterator MachOObjectFile::end_sections() const {
744 DRI.d.a = getHeader()->NumLoadCommands;
745 return section_iterator(SectionRef(DRI, this));
748 /*===-- Relocations -------------------------------------------------------===*/
750 const MachOFormat::RelocationEntry *
751 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
754 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
755 relOffset = Sect->RelocationTableOffset;
757 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
758 relOffset = Sect->RelocationTableOffset;
760 uint64_t Offset = relOffset + Rel.d.a * sizeof(MachOFormat::RelocationEntry);
761 StringRef Data = getData(Offset, sizeof(MachOFormat::RelocationEntry));
762 return reinterpret_cast<const MachOFormat::RelocationEntry*>(Data.data());
765 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
766 RelocationRef &Res) const {
768 Res = RelocationRef(Rel, this);
769 return object_error::success;
771 error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
772 uint64_t &Res) const {
773 const uint8_t* sectAddress = 0;
775 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
776 sectAddress += Sect->Address;
778 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
779 sectAddress += Sect->Address;
781 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
783 unsigned Arch = getArch();
784 bool isScattered = (Arch != Triple::x86_64) &&
785 (RE->Word0 & macho::RF_Scattered);
786 uint64_t RelAddr = 0;
788 RelAddr = RE->Word0 & 0xFFFFFF;
792 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
793 return object_error::success;
795 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
796 uint64_t &Res) const {
797 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
799 unsigned Arch = getArch();
800 bool isScattered = (Arch != Triple::x86_64) &&
801 (RE->Word0 & macho::RF_Scattered);
803 Res = RE->Word0 & 0xFFFFFF;
806 return object_error::success;
808 error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
809 SymbolRef &Res) const {
810 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
811 uint32_t SymbolIdx = RE->Word1 & 0xffffff;
812 bool isExtern = (RE->Word1 >> 27) & 1;
815 moveToNextSymbol(Sym);
817 for (unsigned i = 0; i < SymbolIdx; i++) {
819 moveToNextSymbol(Sym);
820 assert(Sym.d.a < getHeader()->NumLoadCommands &&
821 "Relocation symbol index out of range!");
824 Res = SymbolRef(Sym, this);
825 return object_error::success;
827 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
828 uint64_t &Res) const {
829 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
833 return object_error::success;
835 error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
836 SmallVectorImpl<char> &Result) const {
837 // TODO: Support scattered relocations.
839 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
841 unsigned Arch = getArch();
842 bool isScattered = (Arch != Triple::x86_64) &&
843 (RE->Word0 & macho::RF_Scattered);
847 r_type = (RE->Word0 >> 24) & 0xF;
849 r_type = (RE->Word1 >> 28) & 0xF;
853 static const char *const Table[] = {
854 "GENERIC_RELOC_VANILLA",
855 "GENERIC_RELOC_PAIR",
856 "GENERIC_RELOC_SECTDIFF",
857 "GENERIC_RELOC_PB_LA_PTR",
858 "GENERIC_RELOC_LOCAL_SECTDIFF",
859 "GENERIC_RELOC_TLV" };
867 case Triple::x86_64: {
868 static const char *const Table[] = {
869 "X86_64_RELOC_UNSIGNED",
870 "X86_64_RELOC_SIGNED",
871 "X86_64_RELOC_BRANCH",
872 "X86_64_RELOC_GOT_LOAD",
874 "X86_64_RELOC_SUBTRACTOR",
875 "X86_64_RELOC_SIGNED_1",
876 "X86_64_RELOC_SIGNED_2",
877 "X86_64_RELOC_SIGNED_4",
878 "X86_64_RELOC_TLV" };
887 static const char *const Table[] = {
890 "ARM_RELOC_SECTDIFF",
891 "ARM_RELOC_LOCAL_SECTDIFF",
892 "ARM_RELOC_PB_LA_PTR",
894 "ARM_THUMB_RELOC_BR22",
895 "ARM_THUMB_32BIT_BRANCH",
897 "ARM_RELOC_HALF_SECTDIFF" };
906 static const char *const Table[] = {
915 "PPC_RELOC_SECTDIFF",
916 "PPC_RELOC_PB_LA_PTR",
917 "PPC_RELOC_HI16_SECTDIFF",
918 "PPC_RELOC_LO16_SECTDIFF",
919 "PPC_RELOC_HA16_SECTDIFF",
921 "PPC_RELOC_LO14_SECTDIFF",
922 "PPC_RELOC_LOCAL_SECTDIFF" };
927 case Triple::UnknownArch:
931 Result.append(res.begin(), res.end());
932 return object_error::success;
934 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
935 int64_t &Res) const {
936 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
937 bool isExtern = (RE->Word1 >> 27) & 1;
940 const uint8_t* sectAddress = base();
942 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
943 sectAddress += Sect->Offset;
945 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
946 sectAddress += Sect->Offset;
948 Res = reinterpret_cast<uintptr_t>(sectAddress);
950 return object_error::success;
953 // Helper to advance a section or symbol iterator multiple increments at a time.
955 error_code advance(T &it, size_t Val) {
964 void advanceTo(T &it, size_t Val) {
965 if (error_code ec = advance(it, Val))
966 report_fatal_error(ec.message());
969 void MachOObjectFile::printRelocationTargetName(
970 const MachOFormat::RelocationEntry *RE,
971 raw_string_ostream &fmt) const {
972 unsigned Arch = getArch();
973 bool isScattered = (Arch != Triple::x86_64) &&
974 (RE->Word0 & macho::RF_Scattered);
976 // Target of a scattered relocation is an address. In the interest of
977 // generating pretty output, scan through the symbol table looking for a
978 // symbol that aligns with that address. If we find one, print it.
979 // Otherwise, we just print the hex address of the target.
981 uint32_t Val = RE->Word1;
984 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
986 if (ec) report_fatal_error(ec.message());
991 if ((ec = SI->getAddress(Addr)))
992 report_fatal_error(ec.message());
993 if (Addr != Val) continue;
994 if ((ec = SI->getName(Name)))
995 report_fatal_error(ec.message());
1000 // If we couldn't find a symbol that this relocation refers to, try
1001 // to find a section beginning instead.
1002 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
1004 if (ec) report_fatal_error(ec.message());
1009 if ((ec = SI->getAddress(Addr)))
1010 report_fatal_error(ec.message());
1011 if (Addr != Val) continue;
1012 if ((ec = SI->getName(Name)))
1013 report_fatal_error(ec.message());
1018 fmt << format("0x%x", Val);
1023 bool isExtern = (RE->Word1 >> 27) & 1;
1024 uint32_t Val = RE->Word1 & 0xFFFFFF;
1027 symbol_iterator SI = begin_symbols();
1031 section_iterator SI = begin_sections();
1039 error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
1040 SmallVectorImpl<char> &Result) const {
1041 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
1043 unsigned Arch = getArch();
1044 bool isScattered = (Arch != Triple::x86_64) &&
1045 (RE->Word0 & macho::RF_Scattered);
1048 raw_string_ostream fmt(fmtbuf);
1052 Type = (RE->Word0 >> 24) & 0xF;
1054 Type = (RE->Word1 >> 28) & 0xF;
1058 isPCRel = ((RE->Word0 >> 30) & 1);
1060 isPCRel = ((RE->Word1 >> 24) & 1);
1062 // Determine any addends that should be displayed with the relocation.
1063 // These require decoding the relocation type, which is triple-specific.
1065 // X86_64 has entirely custom relocation types.
1066 if (Arch == Triple::x86_64) {
1067 bool isPCRel = ((RE->Word1 >> 24) & 1);
1070 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
1071 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
1072 printRelocationTargetName(RE, fmt);
1074 if (isPCRel) fmt << "PCREL";
1077 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
1078 DataRefImpl RelNext = Rel;
1080 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1082 // X86_64_SUBTRACTOR must be followed by a relocation of type
1083 // X86_64_RELOC_UNSIGNED.
1084 // NOTE: Scattered relocations don't exist on x86_64.
1085 unsigned RType = (RENext->Word1 >> 28) & 0xF;
1087 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1088 "X86_64_RELOC_SUBTRACTOR.");
1090 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1091 // X86_64_SUBTRACTOR contains to the subtrahend.
1092 printRelocationTargetName(RENext, fmt);
1094 printRelocationTargetName(RE, fmt);
1097 case macho::RIT_X86_64_TLV:
1098 printRelocationTargetName(RE, fmt);
1100 if (isPCRel) fmt << "P";
1102 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1103 printRelocationTargetName(RE, fmt);
1106 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1107 printRelocationTargetName(RE, fmt);
1110 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1111 printRelocationTargetName(RE, fmt);
1115 printRelocationTargetName(RE, fmt);
1118 // X86 and ARM share some relocation types in common.
1119 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1120 // Generic relocation types...
1122 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1123 return object_error::success;
1124 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1125 DataRefImpl RelNext = Rel;
1127 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1129 // X86 sect diff's must be followed by a relocation of type
1130 // GENERIC_RELOC_PAIR.
1131 bool isNextScattered = (Arch != Triple::x86_64) &&
1132 (RENext->Word0 & macho::RF_Scattered);
1134 if (isNextScattered)
1135 RType = (RENext->Word0 >> 24) & 0xF;
1137 RType = (RENext->Word1 >> 28) & 0xF;
1139 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1140 "GENERIC_RELOC_SECTDIFF.");
1142 printRelocationTargetName(RE, fmt);
1144 printRelocationTargetName(RENext, fmt);
1149 if (Arch == Triple::x86) {
1150 // All X86 relocations that need special printing were already
1151 // handled in the generic code.
1153 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1154 DataRefImpl RelNext = Rel;
1156 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1158 // X86 sect diff's must be followed by a relocation of type
1159 // GENERIC_RELOC_PAIR.
1160 bool isNextScattered = (Arch != Triple::x86_64) &&
1161 (RENext->Word0 & macho::RF_Scattered);
1163 if (isNextScattered)
1164 RType = (RENext->Word0 >> 24) & 0xF;
1166 RType = (RENext->Word1 >> 28) & 0xF;
1168 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1169 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1171 printRelocationTargetName(RE, fmt);
1173 printRelocationTargetName(RENext, fmt);
1176 case macho::RIT_Generic_TLV: {
1177 printRelocationTargetName(RE, fmt);
1179 if (isPCRel) fmt << "P";
1183 printRelocationTargetName(RE, fmt);
1185 } else { // ARM-specific relocations
1187 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1188 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1189 // Half relocations steal a bit from the length field to encode
1190 // whether this is an upper16 or a lower16 relocation.
1193 isUpper = (RE->Word0 >> 28) & 1;
1195 isUpper = (RE->Word1 >> 25) & 1;
1198 fmt << ":upper16:(";
1200 fmt << ":lower16:(";
1201 printRelocationTargetName(RE, fmt);
1203 DataRefImpl RelNext = Rel;
1205 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1207 // ARM half relocs must be followed by a relocation of type
1209 bool isNextScattered = (Arch != Triple::x86_64) &&
1210 (RENext->Word0 & macho::RF_Scattered);
1212 if (isNextScattered)
1213 RType = (RENext->Word0 >> 24) & 0xF;
1215 RType = (RENext->Word1 >> 28) & 0xF;
1218 report_fatal_error("Expected ARM_RELOC_PAIR after "
1219 "GENERIC_RELOC_HALF");
1221 // NOTE: The half of the target virtual address is stashed in the
1222 // address field of the secondary relocation, but we can't reverse
1223 // engineer the constant offset from it without decoding the movw/movt
1224 // instruction to find the other half in its immediate field.
1226 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1227 // symbol/section pointer of the follow-on relocation.
1228 if (Type == macho::RIT_ARM_HalfDifference) {
1230 printRelocationTargetName(RENext, fmt);
1237 printRelocationTargetName(RE, fmt);
1242 printRelocationTargetName(RE, fmt);
1245 Result.append(fmtbuf.begin(), fmtbuf.end());
1246 return object_error::success;
1249 error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1250 bool &Result) const {
1251 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
1253 unsigned Arch = getArch();
1254 bool isScattered = (Arch != Triple::x86_64) &&
1255 (RE->Word0 & macho::RF_Scattered);
1258 Type = (RE->Word0 >> 24) & 0xF;
1260 Type = (RE->Word1 >> 28) & 0xF;
1264 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1265 // is always hidden.
1266 if (Arch == Triple::x86 || Arch == Triple::arm) {
1267 if (Type == macho::RIT_Pair) Result = true;
1268 } else if (Arch == Triple::x86_64) {
1269 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1270 // an X864_64_RELOC_SUBTRACTOR.
1271 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1272 DataRefImpl RelPrev = Rel;
1274 const MachOFormat::RelocationEntry *REPrev = getRelocation(RelPrev);
1276 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1278 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
1282 return object_error::success;
1285 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1286 LibraryRef &Res) const {
1287 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1290 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1291 StringRef &Res) const {
1292 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1296 /*===-- Miscellaneous -----------------------------------------------------===*/
1298 uint8_t MachOObjectFile::getBytesInAddress() const {
1299 return is64Bit() ? 8 : 4;
1302 StringRef MachOObjectFile::getFileFormatName() const {
1304 switch (getHeader()->CPUType) {
1305 case llvm::MachO::CPUTypeI386:
1306 return "Mach-O 32-bit i386";
1307 case llvm::MachO::CPUTypeARM:
1308 return "Mach-O arm";
1309 case llvm::MachO::CPUTypePowerPC:
1310 return "Mach-O 32-bit ppc";
1312 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) == 0 &&
1313 "64-bit object file when we're not 64-bit?");
1314 return "Mach-O 32-bit unknown";
1318 // Make sure the cpu type has the correct mask.
1319 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64)
1320 == llvm::MachO::CPUArchABI64 &&
1321 "32-bit object file when we're 64-bit?");
1323 switch (getHeader()->CPUType) {
1324 case llvm::MachO::CPUTypeX86_64:
1325 return "Mach-O 64-bit x86-64";
1326 case llvm::MachO::CPUTypePowerPC64:
1327 return "Mach-O 64-bit ppc64";
1329 return "Mach-O 64-bit unknown";
1333 unsigned MachOObjectFile::getArch() const {
1334 switch (getHeader()->CPUType) {
1335 case llvm::MachO::CPUTypeI386:
1337 case llvm::MachO::CPUTypeX86_64:
1338 return Triple::x86_64;
1339 case llvm::MachO::CPUTypeARM:
1341 case llvm::MachO::CPUTypePowerPC:
1343 case llvm::MachO::CPUTypePowerPC64:
1344 return Triple::ppc64;
1346 return Triple::UnknownArch;
1350 } // end namespace object
1351 } // end namespace llvm