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 = MachOObj->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 = MachOObj->getHeaderSize();
65 const MachOFormat::LoadCommand *Load;
69 StringRef Data = MachOObj->getData(Offset,
70 sizeof(MachOFormat::LoadCommand));
71 Load = reinterpret_cast<const MachOFormat::LoadCommand*>(Data.data());
72 NewOffset = Offset + Load->Size;
74 } while (I != Index + 1);
79 void MachOObjectFile::ReadULEB128s(uint64_t Index,
80 SmallVectorImpl<uint64_t> &Out) const {
81 return MachOObj->ReadULEB128s(Index, Out);
84 const macho::Header &MachOObjectFile::getHeader() const {
85 return MachOObj->getHeader();
88 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
90 ObjectFile *Ret = new MachOObjectFile(Buffer, ec);
96 /*===-- Symbols -----------------------------------------------------------===*/
98 void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
99 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
100 while (DRI.d.a < LoadCommandCount) {
101 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
102 if (Command->Type == macho::LCT_Symtab) {
103 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
104 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
105 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
114 const MachOFormat::SymbolTableEntry *
115 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
116 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
117 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
118 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
120 return getSymbolTableEntry(DRI, SymtabLoadCmd);
123 const MachOFormat::SymbolTableEntry *
124 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI,
125 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
126 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
127 unsigned Index = DRI.d.b;
128 uint64_t Offset = (SymbolTableOffset +
129 Index * sizeof(macho::SymbolTableEntry));
130 StringRef Data = MachOObj->getData(Offset,
131 sizeof(MachOFormat::SymbolTableEntry));
132 return reinterpret_cast<const MachOFormat::SymbolTableEntry*>(Data.data());
135 const MachOFormat::Symbol64TableEntry*
136 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
137 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
138 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
139 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
141 return getSymbol64TableEntry(DRI, SymtabLoadCmd);
144 const MachOFormat::Symbol64TableEntry*
145 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI,
146 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
147 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
148 unsigned Index = DRI.d.b;
149 uint64_t Offset = (SymbolTableOffset +
150 Index * sizeof(macho::Symbol64TableEntry));
151 StringRef Data = MachOObj->getData(Offset,
152 sizeof(MachOFormat::Symbol64TableEntry));
153 return reinterpret_cast<const MachOFormat::Symbol64TableEntry*>(Data.data());
156 error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
157 SymbolRef &Result) const {
159 moveToNextSymbol(DRI);
160 Result = SymbolRef(DRI, this);
161 return object_error::success;
164 error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
165 StringRef &Result) const {
166 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
167 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
168 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
170 StringRef StringTable =
171 MachOObj->getData(SymtabLoadCmd->StringTableOffset,
172 SymtabLoadCmd->StringTableSize);
174 uint32_t StringIndex;
175 if (MachOObj->is64Bit()) {
176 const MachOFormat::Symbol64TableEntry *Entry =
177 getSymbol64TableEntry(DRI, SymtabLoadCmd);
178 StringIndex = Entry->StringIndex;
180 const MachOFormat::SymbolTableEntry *Entry =
181 getSymbolTableEntry(DRI, SymtabLoadCmd);
182 StringIndex = Entry->StringIndex;
185 const char *Start = &StringTable.data()[StringIndex];
186 Result = StringRef(Start);
188 return object_error::success;
191 error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI,
192 uint64_t &Result) const {
193 if (MachOObj->is64Bit()) {
194 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
195 Result = Entry->Value;
196 if (Entry->SectionIndex) {
197 const MachOFormat::Section64 *Section =
198 getSection64(Sections[Entry->SectionIndex-1]);
199 Result += Section->Offset - Section->Address;
202 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
203 Result = Entry->Value;
204 if (Entry->SectionIndex) {
205 const MachOFormat::Section *Section =
206 getSection(Sections[Entry->SectionIndex-1]);
207 Result += Section->Offset - Section->Address;
211 return object_error::success;
214 error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
215 uint64_t &Result) const {
216 if (MachOObj->is64Bit()) {
217 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
218 Result = Entry->Value;
220 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
221 Result = Entry->Value;
223 return object_error::success;
226 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
227 uint64_t &Result) const {
228 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
229 uint64_t BeginOffset;
230 uint64_t EndOffset = 0;
231 uint8_t SectionIndex;
232 if (MachOObj->is64Bit()) {
233 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
234 BeginOffset = Entry->Value;
235 SectionIndex = Entry->SectionIndex;
237 uint32_t flags = SymbolRef::SF_None;
238 getSymbolFlags(DRI, flags);
239 if (flags & SymbolRef::SF_Common)
240 Result = Entry->Value;
242 Result = UnknownAddressOrSize;
243 return object_error::success;
245 // Unfortunately symbols are unsorted so we need to touch all
246 // symbols from load command
248 uint32_t Command = DRI.d.a;
249 while (Command == DRI.d.a) {
250 moveToNextSymbol(DRI);
251 if (DRI.d.a < LoadCommandCount) {
252 Entry = getSymbol64TableEntry(DRI);
253 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
254 if (!EndOffset || Entry->Value < EndOffset)
255 EndOffset = Entry->Value;
260 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
261 BeginOffset = Entry->Value;
262 SectionIndex = Entry->SectionIndex;
264 uint32_t flags = SymbolRef::SF_None;
265 getSymbolFlags(DRI, flags);
266 if (flags & SymbolRef::SF_Common)
267 Result = Entry->Value;
269 Result = UnknownAddressOrSize;
270 return object_error::success;
272 // Unfortunately symbols are unsorted so we need to touch all
273 // symbols from load command
275 uint32_t Command = DRI.d.a;
276 while (Command == DRI.d.a) {
277 moveToNextSymbol(DRI);
278 if (DRI.d.a < LoadCommandCount) {
279 Entry = getSymbolTableEntry(DRI);
280 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
281 if (!EndOffset || Entry->Value < EndOffset)
282 EndOffset = Entry->Value;
289 getSectionSize(Sections[SectionIndex-1], Size);
290 getSectionAddress(Sections[SectionIndex-1], EndOffset);
293 Result = EndOffset - BeginOffset;
294 return object_error::success;
297 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
298 char &Result) const {
300 if (MachOObj->is64Bit()) {
301 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
303 Flags = Entry->Flags;
305 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
307 Flags = Entry->Flags;
311 switch (Type & macho::STF_TypeMask) {
312 case macho::STT_Undefined:
315 case macho::STT_Absolute:
316 case macho::STT_Section:
324 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
325 Char = toupper(static_cast<unsigned char>(Char));
327 return object_error::success;
330 error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
331 uint32_t &Result) const {
334 if (MachOObj->is64Bit()) {
335 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
336 MachOFlags = Entry->Flags;
337 MachOType = Entry->Type;
339 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
340 MachOFlags = Entry->Flags;
341 MachOType = Entry->Type;
344 // TODO: Correctly set SF_ThreadLocal
345 Result = SymbolRef::SF_None;
347 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
348 Result |= SymbolRef::SF_Undefined;
350 if (MachOFlags & macho::STF_StabsEntryMask)
351 Result |= SymbolRef::SF_FormatSpecific;
353 if (MachOType & MachO::NlistMaskExternal) {
354 Result |= SymbolRef::SF_Global;
355 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
356 Result |= SymbolRef::SF_Common;
359 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
360 Result |= SymbolRef::SF_Weak;
362 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
363 Result |= SymbolRef::SF_Absolute;
365 return object_error::success;
368 error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
369 section_iterator &Res) const {
371 if (MachOObj->is64Bit()) {
372 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
373 index = Entry->SectionIndex;
375 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
376 index = Entry->SectionIndex;
380 Res = end_sections();
382 Res = section_iterator(SectionRef(Sections[index-1], this));
384 return object_error::success;
387 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
388 SymbolRef::Type &Res) const {
390 if (MachOObj->is64Bit()) {
391 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
392 n_type = Entry->Type;
394 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
395 n_type = Entry->Type;
397 Res = SymbolRef::ST_Other;
399 // If this is a STAB debugging symbol, we can do nothing more.
400 if (n_type & MachO::NlistMaskStab) {
401 Res = SymbolRef::ST_Debug;
402 return object_error::success;
405 switch (n_type & MachO::NlistMaskType) {
406 case MachO::NListTypeUndefined :
407 Res = SymbolRef::ST_Unknown;
409 case MachO::NListTypeSection :
410 Res = SymbolRef::ST_Function;
413 return object_error::success;
416 error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
417 uint64_t &Val) const {
418 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
421 symbol_iterator MachOObjectFile::begin_symbols() const {
422 // DRI.d.a = segment number; DRI.d.b = symbol index.
424 moveToNextSymbol(DRI);
425 return symbol_iterator(SymbolRef(DRI, this));
428 symbol_iterator MachOObjectFile::end_symbols() const {
430 DRI.d.a = MachOObj->getHeader().NumLoadCommands;
431 return symbol_iterator(SymbolRef(DRI, this));
434 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
436 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
439 symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
441 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
444 library_iterator MachOObjectFile::begin_libraries_needed() const {
446 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
449 library_iterator MachOObjectFile::end_libraries_needed() const {
451 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
454 StringRef MachOObjectFile::getLoadName() const {
456 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
459 /*===-- Sections ----------------------------------------------------------===*/
461 void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
462 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
463 while (DRI.d.a < LoadCommandCount) {
464 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
465 if (Command->Type == macho::LCT_Segment) {
466 const MachOFormat::SegmentLoadCommand *SegmentLoadCmd =
467 reinterpret_cast<const MachOFormat::SegmentLoadCommand*>(Command);
468 if (DRI.d.b < SegmentLoadCmd->NumSections)
470 } else if (Command->Type == macho::LCT_Segment64) {
471 const MachOFormat::Segment64LoadCommand *Segment64LoadCmd =
472 reinterpret_cast<const MachOFormat::Segment64LoadCommand*>(Command);
473 if (DRI.d.b < Segment64LoadCmd->NumSections)
482 error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
483 SectionRef &Result) const {
485 moveToNextSection(DRI);
486 Result = SectionRef(DRI, this);
487 return object_error::success;
490 static bool is64BitLoadCommand(const MachOObjectFile *MachOObj,
492 const MachOFormat::LoadCommand *Command =
493 MachOObj->getLoadCommandInfo(DRI.d.a);
494 if (Command->Type == macho::LCT_Segment64)
496 assert(Command->Type == macho::LCT_Segment && "Unexpected Type.");
500 const MachOFormat::Section *MachOObjectFile::getSection(DataRefImpl DRI) const {
501 assert(!is64BitLoadCommand(this, DRI));
502 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
503 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
504 uintptr_t SectionAddr = CommandAddr + sizeof(macho::SegmentLoadCommand) +
505 DRI.d.b * sizeof(MachOFormat::Section);
506 return reinterpret_cast<const MachOFormat::Section*>(SectionAddr);
509 std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
510 SectionList::const_iterator loc =
511 std::find(Sections.begin(), Sections.end(), Sec);
512 assert(loc != Sections.end() && "Sec is not a valid section!");
513 return std::distance(Sections.begin(), loc);
516 const MachOFormat::Section64 *
517 MachOObjectFile::getSection64(DataRefImpl DRI) const {
518 assert(is64BitLoadCommand(this, DRI));
519 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
520 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
521 uintptr_t SectionAddr = CommandAddr + sizeof(macho::Segment64LoadCommand) +
522 DRI.d.b * sizeof(MachOFormat::Section64);
523 return reinterpret_cast<const MachOFormat::Section64*>(SectionAddr);
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 if (is64BitLoadCommand(this, DRI)) {
536 const MachOFormat::Section64 *sec = getSection64(DRI);
537 return ArrayRef<char>(sec->Name);
539 const MachOFormat::Section *sec = getSection(DRI);
540 return ArrayRef<char>(sec->Name);
544 error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
545 StringRef &Result) const {
546 ArrayRef<char> Raw = getSectionRawName(DRI);
547 Result = parseSegmentOrSectionName(Raw.data());
548 return object_error::success;
552 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
553 if (is64BitLoadCommand(this, Sec)) {
554 const MachOFormat::Section64 *sec = getSection64(Sec);
555 return ArrayRef<char>(sec->SegmentName, 16);
557 const MachOFormat::Section *sec = getSection(Sec);
558 return ArrayRef<char>(sec->SegmentName);
562 StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const {
563 ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
564 return parseSegmentOrSectionName(Raw.data());
567 error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
568 uint64_t &Result) const {
569 if (is64BitLoadCommand(this, DRI)) {
570 const MachOFormat::Section64 *Sect = getSection64(DRI);
571 Result = Sect->Address;
573 const MachOFormat::Section *Sect = getSection(DRI);
574 Result = Sect->Address;
576 return object_error::success;
579 error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
580 uint64_t &Result) const {
581 if (is64BitLoadCommand(this, DRI)) {
582 const MachOFormat::Section64 *Sect = getSection64(DRI);
585 const MachOFormat::Section *Sect = getSection(DRI);
588 return object_error::success;
591 error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
592 StringRef &Result) const {
593 if (is64BitLoadCommand(this, DRI)) {
594 const MachOFormat::Section64 *Sect = getSection64(DRI);
595 Result = MachOObj->getData(Sect->Offset, Sect->Size);
597 const MachOFormat::Section *Sect = getSection(DRI);
598 Result = MachOObj->getData(Sect->Offset, Sect->Size);
600 return object_error::success;
603 error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
604 uint64_t &Result) const {
605 if (is64BitLoadCommand(this, DRI)) {
606 const MachOFormat::Section64 *Sect = getSection64(DRI);
607 Result = uint64_t(1) << Sect->Align;
609 const MachOFormat::Section *Sect = getSection(DRI);
610 Result = uint64_t(1) << Sect->Align;
612 return object_error::success;
615 error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
616 bool &Result) const {
617 if (is64BitLoadCommand(this, DRI)) {
618 const MachOFormat::Section64 *Sect = getSection64(DRI);
619 Result = Sect->Flags & macho::SF_PureInstructions;
621 const MachOFormat::Section *Sect = getSection(DRI);
622 Result = Sect->Flags & macho::SF_PureInstructions;
624 return object_error::success;
627 error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
628 bool &Result) const {
629 // FIXME: Unimplemented.
631 return object_error::success;
634 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
635 bool &Result) const {
636 // FIXME: Unimplemented.
638 return object_error::success;
641 error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
642 bool &Result) const {
643 // FIXME: Unimplemented.
645 return object_error::success;
648 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
649 bool &Result) const {
650 // FIXME: Unimplemented.
652 return object_error::success;
655 error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI,
656 bool &Result) const {
657 if (MachOObj->is64Bit()) {
658 const MachOFormat::Section64 *Sect = getSection64(DRI);
659 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
660 Result = (SectionType == MachO::SectionTypeZeroFill ||
661 SectionType == MachO::SectionTypeZeroFillLarge);
663 const MachOFormat::Section *Sect = getSection(DRI);
664 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
665 Result = (SectionType == MachO::SectionTypeZeroFill ||
666 SectionType == MachO::SectionTypeZeroFillLarge);
669 return object_error::success;
672 error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
673 bool &Result) const {
674 // Consider using the code from isSectionText to look for __const sections.
675 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
676 // to use section attributes to distinguish code from data.
678 // FIXME: Unimplemented.
680 return object_error::success;
683 error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
685 bool &Result) const {
687 getSymbolType(Symb, ST);
688 if (ST == SymbolRef::ST_Unknown) {
690 return object_error::success;
693 uint64_t SectBegin, SectEnd;
694 getSectionAddress(Sec, SectBegin);
695 getSectionSize(Sec, SectEnd);
696 SectEnd += SectBegin;
698 if (MachOObj->is64Bit()) {
699 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
700 uint64_t SymAddr= Entry->Value;
701 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
703 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
704 uint64_t SymAddr= Entry->Value;
705 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
708 return object_error::success;
711 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
713 ret.d.b = getSectionIndex(Sec);
714 return relocation_iterator(RelocationRef(ret, this));
716 relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
718 if (is64BitLoadCommand(this, Sec)) {
719 const MachOFormat::Section64 *Sect = getSection64(Sec);
720 last_reloc = Sect->NumRelocationTableEntries;
722 const MachOFormat::Section *Sect = getSection(Sec);
723 last_reloc = Sect->NumRelocationTableEntries;
726 ret.d.a = last_reloc;
727 ret.d.b = getSectionIndex(Sec);
728 return relocation_iterator(RelocationRef(ret, this));
731 section_iterator MachOObjectFile::begin_sections() const {
733 moveToNextSection(DRI);
734 return section_iterator(SectionRef(DRI, this));
737 section_iterator MachOObjectFile::end_sections() const {
739 DRI.d.a = MachOObj->getHeader().NumLoadCommands;
740 return section_iterator(SectionRef(DRI, this));
743 /*===-- Relocations -------------------------------------------------------===*/
745 const MachOFormat::RelocationEntry *
746 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
748 if (MachOObj->is64Bit()) {
749 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
750 relOffset = Sect->RelocationTableOffset;
752 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
753 relOffset = Sect->RelocationTableOffset;
755 uint64_t Offset = relOffset + Rel.d.a * sizeof(MachOFormat::RelocationEntry);
757 MachOObj->getData(Offset, sizeof(MachOFormat::RelocationEntry));
758 return reinterpret_cast<const MachOFormat::RelocationEntry*>(Data.data());
761 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
762 RelocationRef &Res) const {
764 Res = RelocationRef(Rel, this);
765 return object_error::success;
767 error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
768 uint64_t &Res) const {
769 const uint8_t* sectAddress = 0;
770 if (MachOObj->is64Bit()) {
771 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
772 sectAddress += Sect->Address;
774 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
775 sectAddress += Sect->Address;
777 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
779 unsigned Arch = getArch();
780 bool isScattered = (Arch != Triple::x86_64) &&
781 (RE->Word0 & macho::RF_Scattered);
782 uint64_t RelAddr = 0;
784 RelAddr = RE->Word0 & 0xFFFFFF;
788 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
789 return object_error::success;
791 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
792 uint64_t &Res) const {
793 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
795 unsigned Arch = getArch();
796 bool isScattered = (Arch != Triple::x86_64) &&
797 (RE->Word0 & macho::RF_Scattered);
799 Res = RE->Word0 & 0xFFFFFF;
802 return object_error::success;
804 error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
805 SymbolRef &Res) const {
806 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
807 uint32_t SymbolIdx = RE->Word1 & 0xffffff;
808 bool isExtern = (RE->Word1 >> 27) & 1;
811 moveToNextSymbol(Sym);
813 for (unsigned i = 0; i < SymbolIdx; i++) {
815 moveToNextSymbol(Sym);
816 assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands &&
817 "Relocation symbol index out of range!");
820 Res = SymbolRef(Sym, this);
821 return object_error::success;
823 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
824 uint64_t &Res) const {
825 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
829 return object_error::success;
831 error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
832 SmallVectorImpl<char> &Result) const {
833 // TODO: Support scattered relocations.
835 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
837 unsigned Arch = getArch();
838 bool isScattered = (Arch != Triple::x86_64) &&
839 (RE->Word0 & macho::RF_Scattered);
843 r_type = (RE->Word0 >> 24) & 0xF;
845 r_type = (RE->Word1 >> 28) & 0xF;
849 static const char *const Table[] = {
850 "GENERIC_RELOC_VANILLA",
851 "GENERIC_RELOC_PAIR",
852 "GENERIC_RELOC_SECTDIFF",
853 "GENERIC_RELOC_PB_LA_PTR",
854 "GENERIC_RELOC_LOCAL_SECTDIFF",
855 "GENERIC_RELOC_TLV" };
863 case Triple::x86_64: {
864 static const char *const Table[] = {
865 "X86_64_RELOC_UNSIGNED",
866 "X86_64_RELOC_SIGNED",
867 "X86_64_RELOC_BRANCH",
868 "X86_64_RELOC_GOT_LOAD",
870 "X86_64_RELOC_SUBTRACTOR",
871 "X86_64_RELOC_SIGNED_1",
872 "X86_64_RELOC_SIGNED_2",
873 "X86_64_RELOC_SIGNED_4",
874 "X86_64_RELOC_TLV" };
883 static const char *const Table[] = {
886 "ARM_RELOC_SECTDIFF",
887 "ARM_RELOC_LOCAL_SECTDIFF",
888 "ARM_RELOC_PB_LA_PTR",
890 "ARM_THUMB_RELOC_BR22",
891 "ARM_THUMB_32BIT_BRANCH",
893 "ARM_RELOC_HALF_SECTDIFF" };
902 static const char *const Table[] = {
911 "PPC_RELOC_SECTDIFF",
912 "PPC_RELOC_PB_LA_PTR",
913 "PPC_RELOC_HI16_SECTDIFF",
914 "PPC_RELOC_LO16_SECTDIFF",
915 "PPC_RELOC_HA16_SECTDIFF",
917 "PPC_RELOC_LO14_SECTDIFF",
918 "PPC_RELOC_LOCAL_SECTDIFF" };
923 case Triple::UnknownArch:
927 Result.append(res.begin(), res.end());
928 return object_error::success;
930 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
931 int64_t &Res) const {
932 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
933 bool isExtern = (RE->Word1 >> 27) & 1;
936 const uint8_t* sectAddress = base();
937 if (MachOObj->is64Bit()) {
938 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
939 sectAddress += Sect->Offset;
941 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
942 sectAddress += Sect->Offset;
944 Res = reinterpret_cast<uintptr_t>(sectAddress);
946 return object_error::success;
949 // Helper to advance a section or symbol iterator multiple increments at a time.
951 error_code advance(T &it, size_t Val) {
960 void advanceTo(T &it, size_t Val) {
961 if (error_code ec = advance(it, Val))
962 report_fatal_error(ec.message());
965 void MachOObjectFile::printRelocationTargetName(
966 const MachOFormat::RelocationEntry *RE,
967 raw_string_ostream &fmt) const {
968 unsigned Arch = getArch();
969 bool isScattered = (Arch != Triple::x86_64) &&
970 (RE->Word0 & macho::RF_Scattered);
972 // Target of a scattered relocation is an address. In the interest of
973 // generating pretty output, scan through the symbol table looking for a
974 // symbol that aligns with that address. If we find one, print it.
975 // Otherwise, we just print the hex address of the target.
977 uint32_t Val = RE->Word1;
980 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
982 if (ec) report_fatal_error(ec.message());
987 if ((ec = SI->getAddress(Addr)))
988 report_fatal_error(ec.message());
989 if (Addr != Val) continue;
990 if ((ec = SI->getName(Name)))
991 report_fatal_error(ec.message());
996 // If we couldn't find a symbol that this relocation refers to, try
997 // to find a section beginning instead.
998 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
1000 if (ec) report_fatal_error(ec.message());
1005 if ((ec = SI->getAddress(Addr)))
1006 report_fatal_error(ec.message());
1007 if (Addr != Val) continue;
1008 if ((ec = SI->getName(Name)))
1009 report_fatal_error(ec.message());
1014 fmt << format("0x%x", Val);
1019 bool isExtern = (RE->Word1 >> 27) & 1;
1020 uint32_t Val = RE->Word1 & 0xFFFFFF;
1023 symbol_iterator SI = begin_symbols();
1027 section_iterator SI = begin_sections();
1035 error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
1036 SmallVectorImpl<char> &Result) const {
1037 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
1039 unsigned Arch = getArch();
1040 bool isScattered = (Arch != Triple::x86_64) &&
1041 (RE->Word0 & macho::RF_Scattered);
1044 raw_string_ostream fmt(fmtbuf);
1048 Type = (RE->Word0 >> 24) & 0xF;
1050 Type = (RE->Word1 >> 28) & 0xF;
1054 isPCRel = ((RE->Word0 >> 30) & 1);
1056 isPCRel = ((RE->Word1 >> 24) & 1);
1058 // Determine any addends that should be displayed with the relocation.
1059 // These require decoding the relocation type, which is triple-specific.
1061 // X86_64 has entirely custom relocation types.
1062 if (Arch == Triple::x86_64) {
1063 bool isPCRel = ((RE->Word1 >> 24) & 1);
1066 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
1067 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
1068 printRelocationTargetName(RE, fmt);
1070 if (isPCRel) fmt << "PCREL";
1073 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
1074 DataRefImpl RelNext = Rel;
1076 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1078 // X86_64_SUBTRACTOR must be followed by a relocation of type
1079 // X86_64_RELOC_UNSIGNED.
1080 // NOTE: Scattered relocations don't exist on x86_64.
1081 unsigned RType = (RENext->Word1 >> 28) & 0xF;
1083 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1084 "X86_64_RELOC_SUBTRACTOR.");
1086 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1087 // X86_64_SUBTRACTOR contains to the subtrahend.
1088 printRelocationTargetName(RENext, fmt);
1090 printRelocationTargetName(RE, fmt);
1093 case macho::RIT_X86_64_TLV:
1094 printRelocationTargetName(RE, fmt);
1096 if (isPCRel) fmt << "P";
1098 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1099 printRelocationTargetName(RE, fmt);
1102 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1103 printRelocationTargetName(RE, fmt);
1106 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1107 printRelocationTargetName(RE, fmt);
1111 printRelocationTargetName(RE, fmt);
1114 // X86 and ARM share some relocation types in common.
1115 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1116 // Generic relocation types...
1118 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1119 return object_error::success;
1120 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1121 DataRefImpl RelNext = Rel;
1123 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1125 // X86 sect diff's must be followed by a relocation of type
1126 // GENERIC_RELOC_PAIR.
1127 bool isNextScattered = (Arch != Triple::x86_64) &&
1128 (RENext->Word0 & macho::RF_Scattered);
1130 if (isNextScattered)
1131 RType = (RENext->Word0 >> 24) & 0xF;
1133 RType = (RENext->Word1 >> 28) & 0xF;
1135 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1136 "GENERIC_RELOC_SECTDIFF.");
1138 printRelocationTargetName(RE, fmt);
1140 printRelocationTargetName(RENext, fmt);
1145 if (Arch == Triple::x86) {
1146 // All X86 relocations that need special printing were already
1147 // handled in the generic code.
1149 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1150 DataRefImpl RelNext = Rel;
1152 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1154 // X86 sect diff's must be followed by a relocation of type
1155 // GENERIC_RELOC_PAIR.
1156 bool isNextScattered = (Arch != Triple::x86_64) &&
1157 (RENext->Word0 & macho::RF_Scattered);
1159 if (isNextScattered)
1160 RType = (RENext->Word0 >> 24) & 0xF;
1162 RType = (RENext->Word1 >> 28) & 0xF;
1164 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1165 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1167 printRelocationTargetName(RE, fmt);
1169 printRelocationTargetName(RENext, fmt);
1172 case macho::RIT_Generic_TLV: {
1173 printRelocationTargetName(RE, fmt);
1175 if (isPCRel) fmt << "P";
1179 printRelocationTargetName(RE, fmt);
1181 } else { // ARM-specific relocations
1183 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1184 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1185 // Half relocations steal a bit from the length field to encode
1186 // whether this is an upper16 or a lower16 relocation.
1189 isUpper = (RE->Word0 >> 28) & 1;
1191 isUpper = (RE->Word1 >> 25) & 1;
1194 fmt << ":upper16:(";
1196 fmt << ":lower16:(";
1197 printRelocationTargetName(RE, fmt);
1199 DataRefImpl RelNext = Rel;
1201 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1203 // ARM half relocs must be followed by a relocation of type
1205 bool isNextScattered = (Arch != Triple::x86_64) &&
1206 (RENext->Word0 & macho::RF_Scattered);
1208 if (isNextScattered)
1209 RType = (RENext->Word0 >> 24) & 0xF;
1211 RType = (RENext->Word1 >> 28) & 0xF;
1214 report_fatal_error("Expected ARM_RELOC_PAIR after "
1215 "GENERIC_RELOC_HALF");
1217 // NOTE: The half of the target virtual address is stashed in the
1218 // address field of the secondary relocation, but we can't reverse
1219 // engineer the constant offset from it without decoding the movw/movt
1220 // instruction to find the other half in its immediate field.
1222 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1223 // symbol/section pointer of the follow-on relocation.
1224 if (Type == macho::RIT_ARM_HalfDifference) {
1226 printRelocationTargetName(RENext, fmt);
1233 printRelocationTargetName(RE, fmt);
1238 printRelocationTargetName(RE, fmt);
1241 Result.append(fmtbuf.begin(), fmtbuf.end());
1242 return object_error::success;
1245 error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1246 bool &Result) const {
1247 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
1249 unsigned Arch = getArch();
1250 bool isScattered = (Arch != Triple::x86_64) &&
1251 (RE->Word0 & macho::RF_Scattered);
1254 Type = (RE->Word0 >> 24) & 0xF;
1256 Type = (RE->Word1 >> 28) & 0xF;
1260 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1261 // is always hidden.
1262 if (Arch == Triple::x86 || Arch == Triple::arm) {
1263 if (Type == macho::RIT_Pair) Result = true;
1264 } else if (Arch == Triple::x86_64) {
1265 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1266 // an X864_64_RELOC_SUBTRACTOR.
1267 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1268 DataRefImpl RelPrev = Rel;
1270 const MachOFormat::RelocationEntry *REPrev = getRelocation(RelPrev);
1272 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1274 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
1278 return object_error::success;
1281 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1282 LibraryRef &Res) const {
1283 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1286 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1287 StringRef &Res) const {
1288 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1292 /*===-- Miscellaneous -----------------------------------------------------===*/
1294 uint8_t MachOObjectFile::getBytesInAddress() const {
1295 return MachOObj->is64Bit() ? 8 : 4;
1298 StringRef MachOObjectFile::getFileFormatName() const {
1299 if (!MachOObj->is64Bit()) {
1300 switch (MachOObj->getHeader().CPUType) {
1301 case llvm::MachO::CPUTypeI386:
1302 return "Mach-O 32-bit i386";
1303 case llvm::MachO::CPUTypeARM:
1304 return "Mach-O arm";
1305 case llvm::MachO::CPUTypePowerPC:
1306 return "Mach-O 32-bit ppc";
1308 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
1309 "64-bit object file when we're not 64-bit?");
1310 return "Mach-O 32-bit unknown";
1314 // Make sure the cpu type has the correct mask.
1315 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64)
1316 == llvm::MachO::CPUArchABI64 &&
1317 "32-bit object file when we're 64-bit?");
1319 switch (MachOObj->getHeader().CPUType) {
1320 case llvm::MachO::CPUTypeX86_64:
1321 return "Mach-O 64-bit x86-64";
1322 case llvm::MachO::CPUTypePowerPC64:
1323 return "Mach-O 64-bit ppc64";
1325 return "Mach-O 64-bit unknown";
1329 unsigned MachOObjectFile::getArch() const {
1330 switch (MachOObj->getHeader().CPUType) {
1331 case llvm::MachO::CPUTypeI386:
1333 case llvm::MachO::CPUTypeX86_64:
1334 return Triple::x86_64;
1335 case llvm::MachO::CPUTypeARM:
1337 case llvm::MachO::CPUTypePowerPC:
1339 case llvm::MachO::CPUTypePowerPC64:
1340 return Triple::ppc64;
1342 return Triple::UnknownArch;
1346 } // end namespace object
1347 } // end namespace llvm