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 macho::Header &MachOObjectFile::getHeader() const {
84 return MachOObj->getHeader();
87 unsigned MachOObjectFile::getHeaderSize() const {
88 return MachOObj->getHeaderSize();
91 StringRef MachOObjectFile::getData(size_t Offset, size_t Size) const {
92 return MachOObj->getData(Offset, Size);
95 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
97 ObjectFile *Ret = new MachOObjectFile(Buffer, ec);
103 /*===-- Symbols -----------------------------------------------------------===*/
105 void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
106 uint32_t LoadCommandCount = getHeader().NumLoadCommands;
107 while (DRI.d.a < LoadCommandCount) {
108 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
109 if (Command->Type == macho::LCT_Symtab) {
110 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
111 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
112 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
121 const MachOFormat::SymbolTableEntry *
122 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
123 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
124 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
125 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
127 return getSymbolTableEntry(DRI, SymtabLoadCmd);
130 const MachOFormat::SymbolTableEntry *
131 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI,
132 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
133 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
134 unsigned Index = DRI.d.b;
135 uint64_t Offset = (SymbolTableOffset +
136 Index * sizeof(macho::SymbolTableEntry));
137 StringRef Data = getData(Offset, sizeof(MachOFormat::SymbolTableEntry));
138 return reinterpret_cast<const MachOFormat::SymbolTableEntry*>(Data.data());
141 const MachOFormat::Symbol64TableEntry*
142 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
143 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
144 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
145 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
147 return getSymbol64TableEntry(DRI, SymtabLoadCmd);
150 const MachOFormat::Symbol64TableEntry*
151 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI,
152 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
153 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
154 unsigned Index = DRI.d.b;
155 uint64_t Offset = (SymbolTableOffset +
156 Index * sizeof(macho::Symbol64TableEntry));
157 StringRef Data = getData(Offset, sizeof(MachOFormat::Symbol64TableEntry));
158 return reinterpret_cast<const MachOFormat::Symbol64TableEntry*>(Data.data());
161 error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
162 SymbolRef &Result) const {
164 moveToNextSymbol(DRI);
165 Result = SymbolRef(DRI, this);
166 return object_error::success;
169 error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
170 StringRef &Result) const {
171 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
172 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
173 reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Command);
175 StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset,
176 SymtabLoadCmd->StringTableSize);
178 uint32_t StringIndex;
180 const MachOFormat::Symbol64TableEntry *Entry =
181 getSymbol64TableEntry(DRI, SymtabLoadCmd);
182 StringIndex = Entry->StringIndex;
184 const MachOFormat::SymbolTableEntry *Entry =
185 getSymbolTableEntry(DRI, SymtabLoadCmd);
186 StringIndex = Entry->StringIndex;
189 const char *Start = &StringTable.data()[StringIndex];
190 Result = StringRef(Start);
192 return object_error::success;
195 error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI,
196 uint64_t &Result) const {
198 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
199 Result = Entry->Value;
200 if (Entry->SectionIndex) {
201 const MachOFormat::Section64 *Section =
202 getSection64(Sections[Entry->SectionIndex-1]);
203 Result += Section->Offset - Section->Address;
206 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
207 Result = Entry->Value;
208 if (Entry->SectionIndex) {
209 const MachOFormat::Section *Section =
210 getSection(Sections[Entry->SectionIndex-1]);
211 Result += Section->Offset - Section->Address;
215 return object_error::success;
218 error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
219 uint64_t &Result) const {
221 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
222 Result = Entry->Value;
224 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
225 Result = Entry->Value;
227 return object_error::success;
230 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
231 uint64_t &Result) const {
232 uint32_t LoadCommandCount = getHeader().NumLoadCommands;
233 uint64_t BeginOffset;
234 uint64_t EndOffset = 0;
235 uint8_t SectionIndex;
237 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
238 BeginOffset = Entry->Value;
239 SectionIndex = Entry->SectionIndex;
241 uint32_t flags = SymbolRef::SF_None;
242 getSymbolFlags(DRI, flags);
243 if (flags & SymbolRef::SF_Common)
244 Result = Entry->Value;
246 Result = UnknownAddressOrSize;
247 return object_error::success;
249 // Unfortunately symbols are unsorted so we need to touch all
250 // symbols from load command
252 uint32_t Command = DRI.d.a;
253 while (Command == DRI.d.a) {
254 moveToNextSymbol(DRI);
255 if (DRI.d.a < LoadCommandCount) {
256 Entry = getSymbol64TableEntry(DRI);
257 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
258 if (!EndOffset || Entry->Value < EndOffset)
259 EndOffset = Entry->Value;
264 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
265 BeginOffset = Entry->Value;
266 SectionIndex = Entry->SectionIndex;
268 uint32_t flags = SymbolRef::SF_None;
269 getSymbolFlags(DRI, flags);
270 if (flags & SymbolRef::SF_Common)
271 Result = Entry->Value;
273 Result = UnknownAddressOrSize;
274 return object_error::success;
276 // Unfortunately symbols are unsorted so we need to touch all
277 // symbols from load command
279 uint32_t Command = DRI.d.a;
280 while (Command == DRI.d.a) {
281 moveToNextSymbol(DRI);
282 if (DRI.d.a < LoadCommandCount) {
283 Entry = getSymbolTableEntry(DRI);
284 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
285 if (!EndOffset || Entry->Value < EndOffset)
286 EndOffset = Entry->Value;
293 getSectionSize(Sections[SectionIndex-1], Size);
294 getSectionAddress(Sections[SectionIndex-1], EndOffset);
297 Result = EndOffset - BeginOffset;
298 return object_error::success;
301 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
302 char &Result) const {
305 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
307 Flags = Entry->Flags;
309 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
311 Flags = Entry->Flags;
315 switch (Type & macho::STF_TypeMask) {
316 case macho::STT_Undefined:
319 case macho::STT_Absolute:
320 case macho::STT_Section:
328 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
329 Char = toupper(static_cast<unsigned char>(Char));
331 return object_error::success;
334 error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
335 uint32_t &Result) const {
339 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
340 MachOFlags = Entry->Flags;
341 MachOType = Entry->Type;
343 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
344 MachOFlags = Entry->Flags;
345 MachOType = Entry->Type;
348 // TODO: Correctly set SF_ThreadLocal
349 Result = SymbolRef::SF_None;
351 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
352 Result |= SymbolRef::SF_Undefined;
354 if (MachOFlags & macho::STF_StabsEntryMask)
355 Result |= SymbolRef::SF_FormatSpecific;
357 if (MachOType & MachO::NlistMaskExternal) {
358 Result |= SymbolRef::SF_Global;
359 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
360 Result |= SymbolRef::SF_Common;
363 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
364 Result |= SymbolRef::SF_Weak;
366 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
367 Result |= SymbolRef::SF_Absolute;
369 return object_error::success;
372 error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
373 section_iterator &Res) const {
376 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
377 index = Entry->SectionIndex;
379 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
380 index = Entry->SectionIndex;
384 Res = end_sections();
386 Res = section_iterator(SectionRef(Sections[index-1], this));
388 return object_error::success;
391 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
392 SymbolRef::Type &Res) const {
395 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
396 n_type = Entry->Type;
398 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
399 n_type = Entry->Type;
401 Res = SymbolRef::ST_Other;
403 // If this is a STAB debugging symbol, we can do nothing more.
404 if (n_type & MachO::NlistMaskStab) {
405 Res = SymbolRef::ST_Debug;
406 return object_error::success;
409 switch (n_type & MachO::NlistMaskType) {
410 case MachO::NListTypeUndefined :
411 Res = SymbolRef::ST_Unknown;
413 case MachO::NListTypeSection :
414 Res = SymbolRef::ST_Function;
417 return object_error::success;
420 error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
421 uint64_t &Val) const {
422 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
425 symbol_iterator MachOObjectFile::begin_symbols() const {
426 // DRI.d.a = segment number; DRI.d.b = symbol index.
428 moveToNextSymbol(DRI);
429 return symbol_iterator(SymbolRef(DRI, this));
432 symbol_iterator MachOObjectFile::end_symbols() const {
434 DRI.d.a = getHeader().NumLoadCommands;
435 return symbol_iterator(SymbolRef(DRI, this));
438 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
440 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
443 symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
445 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
448 library_iterator MachOObjectFile::begin_libraries_needed() const {
450 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
453 library_iterator MachOObjectFile::end_libraries_needed() const {
455 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
458 StringRef MachOObjectFile::getLoadName() const {
460 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
463 /*===-- Sections ----------------------------------------------------------===*/
465 void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
466 uint32_t LoadCommandCount = getHeader().NumLoadCommands;
467 while (DRI.d.a < LoadCommandCount) {
468 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
469 if (Command->Type == macho::LCT_Segment) {
470 const MachOFormat::SegmentLoadCommand *SegmentLoadCmd =
471 reinterpret_cast<const MachOFormat::SegmentLoadCommand*>(Command);
472 if (DRI.d.b < SegmentLoadCmd->NumSections)
474 } else if (Command->Type == macho::LCT_Segment64) {
475 const MachOFormat::Segment64LoadCommand *Segment64LoadCmd =
476 reinterpret_cast<const MachOFormat::Segment64LoadCommand*>(Command);
477 if (DRI.d.b < Segment64LoadCmd->NumSections)
486 error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
487 SectionRef &Result) const {
489 moveToNextSection(DRI);
490 Result = SectionRef(DRI, this);
491 return object_error::success;
494 static bool is64BitLoadCommand(const MachOObjectFile *MachOObj,
496 const MachOFormat::LoadCommand *Command =
497 MachOObj->getLoadCommandInfo(DRI.d.a);
498 if (Command->Type == macho::LCT_Segment64)
500 assert(Command->Type == macho::LCT_Segment && "Unexpected Type.");
504 const MachOFormat::Section *MachOObjectFile::getSection(DataRefImpl DRI) const {
505 assert(!is64BitLoadCommand(this, DRI));
506 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
507 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
508 uintptr_t SectionAddr = CommandAddr + sizeof(macho::SegmentLoadCommand) +
509 DRI.d.b * sizeof(MachOFormat::Section);
510 return reinterpret_cast<const MachOFormat::Section*>(SectionAddr);
513 std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
514 SectionList::const_iterator loc =
515 std::find(Sections.begin(), Sections.end(), Sec);
516 assert(loc != Sections.end() && "Sec is not a valid section!");
517 return std::distance(Sections.begin(), loc);
520 const MachOFormat::Section64 *
521 MachOObjectFile::getSection64(DataRefImpl DRI) const {
522 assert(is64BitLoadCommand(this, DRI));
523 const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
524 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
525 uintptr_t SectionAddr = CommandAddr + sizeof(macho::Segment64LoadCommand) +
526 DRI.d.b * sizeof(MachOFormat::Section64);
527 return reinterpret_cast<const MachOFormat::Section64*>(SectionAddr);
530 static StringRef parseSegmentOrSectionName(const char *P) {
534 // Not null terminated, so this is a 16 char string.
535 return StringRef(P, 16);
538 ArrayRef<char> MachOObjectFile::getSectionRawName(DataRefImpl DRI) const {
539 if (is64BitLoadCommand(this, DRI)) {
540 const MachOFormat::Section64 *sec = getSection64(DRI);
541 return ArrayRef<char>(sec->Name);
543 const MachOFormat::Section *sec = getSection(DRI);
544 return ArrayRef<char>(sec->Name);
548 error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
549 StringRef &Result) const {
550 ArrayRef<char> Raw = getSectionRawName(DRI);
551 Result = parseSegmentOrSectionName(Raw.data());
552 return object_error::success;
556 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
557 if (is64BitLoadCommand(this, Sec)) {
558 const MachOFormat::Section64 *sec = getSection64(Sec);
559 return ArrayRef<char>(sec->SegmentName, 16);
561 const MachOFormat::Section *sec = getSection(Sec);
562 return ArrayRef<char>(sec->SegmentName);
566 StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const {
567 ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
568 return parseSegmentOrSectionName(Raw.data());
571 error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
572 uint64_t &Result) const {
573 if (is64BitLoadCommand(this, DRI)) {
574 const MachOFormat::Section64 *Sect = getSection64(DRI);
575 Result = Sect->Address;
577 const MachOFormat::Section *Sect = getSection(DRI);
578 Result = Sect->Address;
580 return object_error::success;
583 error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
584 uint64_t &Result) const {
585 if (is64BitLoadCommand(this, DRI)) {
586 const MachOFormat::Section64 *Sect = getSection64(DRI);
589 const MachOFormat::Section *Sect = getSection(DRI);
592 return object_error::success;
595 error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
596 StringRef &Result) const {
597 if (is64BitLoadCommand(this, DRI)) {
598 const MachOFormat::Section64 *Sect = getSection64(DRI);
599 Result = getData(Sect->Offset, Sect->Size);
601 const MachOFormat::Section *Sect = getSection(DRI);
602 Result = getData(Sect->Offset, Sect->Size);
604 return object_error::success;
607 error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
608 uint64_t &Result) const {
609 if (is64BitLoadCommand(this, DRI)) {
610 const MachOFormat::Section64 *Sect = getSection64(DRI);
611 Result = uint64_t(1) << Sect->Align;
613 const MachOFormat::Section *Sect = getSection(DRI);
614 Result = uint64_t(1) << Sect->Align;
616 return object_error::success;
619 error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
620 bool &Result) const {
621 if (is64BitLoadCommand(this, DRI)) {
622 const MachOFormat::Section64 *Sect = getSection64(DRI);
623 Result = Sect->Flags & macho::SF_PureInstructions;
625 const MachOFormat::Section *Sect = getSection(DRI);
626 Result = Sect->Flags & macho::SF_PureInstructions;
628 return object_error::success;
631 error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
632 bool &Result) const {
633 // FIXME: Unimplemented.
635 return object_error::success;
638 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
639 bool &Result) const {
640 // FIXME: Unimplemented.
642 return object_error::success;
645 error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
646 bool &Result) const {
647 // FIXME: Unimplemented.
649 return object_error::success;
652 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
653 bool &Result) const {
654 // FIXME: Unimplemented.
656 return object_error::success;
659 error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI,
660 bool &Result) const {
662 const MachOFormat::Section64 *Sect = getSection64(DRI);
663 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
664 Result = (SectionType == MachO::SectionTypeZeroFill ||
665 SectionType == MachO::SectionTypeZeroFillLarge);
667 const MachOFormat::Section *Sect = getSection(DRI);
668 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
669 Result = (SectionType == MachO::SectionTypeZeroFill ||
670 SectionType == MachO::SectionTypeZeroFillLarge);
673 return object_error::success;
676 error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
677 bool &Result) const {
678 // Consider using the code from isSectionText to look for __const sections.
679 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
680 // to use section attributes to distinguish code from data.
682 // FIXME: Unimplemented.
684 return object_error::success;
687 error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
689 bool &Result) const {
691 getSymbolType(Symb, ST);
692 if (ST == SymbolRef::ST_Unknown) {
694 return object_error::success;
697 uint64_t SectBegin, SectEnd;
698 getSectionAddress(Sec, SectBegin);
699 getSectionSize(Sec, SectEnd);
700 SectEnd += SectBegin;
703 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
704 uint64_t SymAddr= Entry->Value;
705 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
707 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
708 uint64_t SymAddr= Entry->Value;
709 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
712 return object_error::success;
715 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
717 ret.d.b = getSectionIndex(Sec);
718 return relocation_iterator(RelocationRef(ret, this));
720 relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
722 if (is64BitLoadCommand(this, Sec)) {
723 const MachOFormat::Section64 *Sect = getSection64(Sec);
724 last_reloc = Sect->NumRelocationTableEntries;
726 const MachOFormat::Section *Sect = getSection(Sec);
727 last_reloc = Sect->NumRelocationTableEntries;
730 ret.d.a = last_reloc;
731 ret.d.b = getSectionIndex(Sec);
732 return relocation_iterator(RelocationRef(ret, this));
735 section_iterator MachOObjectFile::begin_sections() const {
737 moveToNextSection(DRI);
738 return section_iterator(SectionRef(DRI, this));
741 section_iterator MachOObjectFile::end_sections() const {
743 DRI.d.a = getHeader().NumLoadCommands;
744 return section_iterator(SectionRef(DRI, this));
747 /*===-- Relocations -------------------------------------------------------===*/
749 const MachOFormat::RelocationEntry *
750 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
753 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
754 relOffset = Sect->RelocationTableOffset;
756 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
757 relOffset = Sect->RelocationTableOffset;
759 uint64_t Offset = relOffset + Rel.d.a * sizeof(MachOFormat::RelocationEntry);
760 StringRef Data = getData(Offset, sizeof(MachOFormat::RelocationEntry));
761 return reinterpret_cast<const MachOFormat::RelocationEntry*>(Data.data());
764 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
765 RelocationRef &Res) const {
767 Res = RelocationRef(Rel, this);
768 return object_error::success;
770 error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
771 uint64_t &Res) const {
772 const uint8_t* sectAddress = 0;
774 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
775 sectAddress += Sect->Address;
777 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
778 sectAddress += Sect->Address;
780 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
782 unsigned Arch = getArch();
783 bool isScattered = (Arch != Triple::x86_64) &&
784 (RE->Word0 & macho::RF_Scattered);
785 uint64_t RelAddr = 0;
787 RelAddr = RE->Word0 & 0xFFFFFF;
791 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
792 return object_error::success;
794 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
795 uint64_t &Res) const {
796 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
798 unsigned Arch = getArch();
799 bool isScattered = (Arch != Triple::x86_64) &&
800 (RE->Word0 & macho::RF_Scattered);
802 Res = RE->Word0 & 0xFFFFFF;
805 return object_error::success;
807 error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
808 SymbolRef &Res) const {
809 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
810 uint32_t SymbolIdx = RE->Word1 & 0xffffff;
811 bool isExtern = (RE->Word1 >> 27) & 1;
814 moveToNextSymbol(Sym);
816 for (unsigned i = 0; i < SymbolIdx; i++) {
818 moveToNextSymbol(Sym);
819 assert(Sym.d.a < getHeader().NumLoadCommands &&
820 "Relocation symbol index out of range!");
823 Res = SymbolRef(Sym, this);
824 return object_error::success;
826 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
827 uint64_t &Res) const {
828 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
832 return object_error::success;
834 error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
835 SmallVectorImpl<char> &Result) const {
836 // TODO: Support scattered relocations.
838 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
840 unsigned Arch = getArch();
841 bool isScattered = (Arch != Triple::x86_64) &&
842 (RE->Word0 & macho::RF_Scattered);
846 r_type = (RE->Word0 >> 24) & 0xF;
848 r_type = (RE->Word1 >> 28) & 0xF;
852 static const char *const Table[] = {
853 "GENERIC_RELOC_VANILLA",
854 "GENERIC_RELOC_PAIR",
855 "GENERIC_RELOC_SECTDIFF",
856 "GENERIC_RELOC_PB_LA_PTR",
857 "GENERIC_RELOC_LOCAL_SECTDIFF",
858 "GENERIC_RELOC_TLV" };
866 case Triple::x86_64: {
867 static const char *const Table[] = {
868 "X86_64_RELOC_UNSIGNED",
869 "X86_64_RELOC_SIGNED",
870 "X86_64_RELOC_BRANCH",
871 "X86_64_RELOC_GOT_LOAD",
873 "X86_64_RELOC_SUBTRACTOR",
874 "X86_64_RELOC_SIGNED_1",
875 "X86_64_RELOC_SIGNED_2",
876 "X86_64_RELOC_SIGNED_4",
877 "X86_64_RELOC_TLV" };
886 static const char *const Table[] = {
889 "ARM_RELOC_SECTDIFF",
890 "ARM_RELOC_LOCAL_SECTDIFF",
891 "ARM_RELOC_PB_LA_PTR",
893 "ARM_THUMB_RELOC_BR22",
894 "ARM_THUMB_32BIT_BRANCH",
896 "ARM_RELOC_HALF_SECTDIFF" };
905 static const char *const Table[] = {
914 "PPC_RELOC_SECTDIFF",
915 "PPC_RELOC_PB_LA_PTR",
916 "PPC_RELOC_HI16_SECTDIFF",
917 "PPC_RELOC_LO16_SECTDIFF",
918 "PPC_RELOC_HA16_SECTDIFF",
920 "PPC_RELOC_LO14_SECTDIFF",
921 "PPC_RELOC_LOCAL_SECTDIFF" };
926 case Triple::UnknownArch:
930 Result.append(res.begin(), res.end());
931 return object_error::success;
933 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
934 int64_t &Res) const {
935 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
936 bool isExtern = (RE->Word1 >> 27) & 1;
939 const uint8_t* sectAddress = base();
941 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
942 sectAddress += Sect->Offset;
944 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
945 sectAddress += Sect->Offset;
947 Res = reinterpret_cast<uintptr_t>(sectAddress);
949 return object_error::success;
952 // Helper to advance a section or symbol iterator multiple increments at a time.
954 error_code advance(T &it, size_t Val) {
963 void advanceTo(T &it, size_t Val) {
964 if (error_code ec = advance(it, Val))
965 report_fatal_error(ec.message());
968 void MachOObjectFile::printRelocationTargetName(
969 const MachOFormat::RelocationEntry *RE,
970 raw_string_ostream &fmt) const {
971 unsigned Arch = getArch();
972 bool isScattered = (Arch != Triple::x86_64) &&
973 (RE->Word0 & macho::RF_Scattered);
975 // Target of a scattered relocation is an address. In the interest of
976 // generating pretty output, scan through the symbol table looking for a
977 // symbol that aligns with that address. If we find one, print it.
978 // Otherwise, we just print the hex address of the target.
980 uint32_t Val = RE->Word1;
983 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
985 if (ec) report_fatal_error(ec.message());
990 if ((ec = SI->getAddress(Addr)))
991 report_fatal_error(ec.message());
992 if (Addr != Val) continue;
993 if ((ec = SI->getName(Name)))
994 report_fatal_error(ec.message());
999 // If we couldn't find a symbol that this relocation refers to, try
1000 // to find a section beginning instead.
1001 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
1003 if (ec) report_fatal_error(ec.message());
1008 if ((ec = SI->getAddress(Addr)))
1009 report_fatal_error(ec.message());
1010 if (Addr != Val) continue;
1011 if ((ec = SI->getName(Name)))
1012 report_fatal_error(ec.message());
1017 fmt << format("0x%x", Val);
1022 bool isExtern = (RE->Word1 >> 27) & 1;
1023 uint32_t Val = RE->Word1 & 0xFFFFFF;
1026 symbol_iterator SI = begin_symbols();
1030 section_iterator SI = begin_sections();
1038 error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
1039 SmallVectorImpl<char> &Result) const {
1040 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
1042 unsigned Arch = getArch();
1043 bool isScattered = (Arch != Triple::x86_64) &&
1044 (RE->Word0 & macho::RF_Scattered);
1047 raw_string_ostream fmt(fmtbuf);
1051 Type = (RE->Word0 >> 24) & 0xF;
1053 Type = (RE->Word1 >> 28) & 0xF;
1057 isPCRel = ((RE->Word0 >> 30) & 1);
1059 isPCRel = ((RE->Word1 >> 24) & 1);
1061 // Determine any addends that should be displayed with the relocation.
1062 // These require decoding the relocation type, which is triple-specific.
1064 // X86_64 has entirely custom relocation types.
1065 if (Arch == Triple::x86_64) {
1066 bool isPCRel = ((RE->Word1 >> 24) & 1);
1069 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
1070 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
1071 printRelocationTargetName(RE, fmt);
1073 if (isPCRel) fmt << "PCREL";
1076 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
1077 DataRefImpl RelNext = Rel;
1079 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1081 // X86_64_SUBTRACTOR must be followed by a relocation of type
1082 // X86_64_RELOC_UNSIGNED.
1083 // NOTE: Scattered relocations don't exist on x86_64.
1084 unsigned RType = (RENext->Word1 >> 28) & 0xF;
1086 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1087 "X86_64_RELOC_SUBTRACTOR.");
1089 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1090 // X86_64_SUBTRACTOR contains to the subtrahend.
1091 printRelocationTargetName(RENext, fmt);
1093 printRelocationTargetName(RE, fmt);
1096 case macho::RIT_X86_64_TLV:
1097 printRelocationTargetName(RE, fmt);
1099 if (isPCRel) fmt << "P";
1101 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1102 printRelocationTargetName(RE, fmt);
1105 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1106 printRelocationTargetName(RE, fmt);
1109 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1110 printRelocationTargetName(RE, fmt);
1114 printRelocationTargetName(RE, fmt);
1117 // X86 and ARM share some relocation types in common.
1118 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1119 // Generic relocation types...
1121 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1122 return object_error::success;
1123 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1124 DataRefImpl RelNext = Rel;
1126 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1128 // X86 sect diff's must be followed by a relocation of type
1129 // GENERIC_RELOC_PAIR.
1130 bool isNextScattered = (Arch != Triple::x86_64) &&
1131 (RENext->Word0 & macho::RF_Scattered);
1133 if (isNextScattered)
1134 RType = (RENext->Word0 >> 24) & 0xF;
1136 RType = (RENext->Word1 >> 28) & 0xF;
1138 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1139 "GENERIC_RELOC_SECTDIFF.");
1141 printRelocationTargetName(RE, fmt);
1143 printRelocationTargetName(RENext, fmt);
1148 if (Arch == Triple::x86) {
1149 // All X86 relocations that need special printing were already
1150 // handled in the generic code.
1152 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1153 DataRefImpl RelNext = Rel;
1155 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1157 // X86 sect diff's must be followed by a relocation of type
1158 // GENERIC_RELOC_PAIR.
1159 bool isNextScattered = (Arch != Triple::x86_64) &&
1160 (RENext->Word0 & macho::RF_Scattered);
1162 if (isNextScattered)
1163 RType = (RENext->Word0 >> 24) & 0xF;
1165 RType = (RENext->Word1 >> 28) & 0xF;
1167 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1168 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1170 printRelocationTargetName(RE, fmt);
1172 printRelocationTargetName(RENext, fmt);
1175 case macho::RIT_Generic_TLV: {
1176 printRelocationTargetName(RE, fmt);
1178 if (isPCRel) fmt << "P";
1182 printRelocationTargetName(RE, fmt);
1184 } else { // ARM-specific relocations
1186 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1187 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1188 // Half relocations steal a bit from the length field to encode
1189 // whether this is an upper16 or a lower16 relocation.
1192 isUpper = (RE->Word0 >> 28) & 1;
1194 isUpper = (RE->Word1 >> 25) & 1;
1197 fmt << ":upper16:(";
1199 fmt << ":lower16:(";
1200 printRelocationTargetName(RE, fmt);
1202 DataRefImpl RelNext = Rel;
1204 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1206 // ARM half relocs must be followed by a relocation of type
1208 bool isNextScattered = (Arch != Triple::x86_64) &&
1209 (RENext->Word0 & macho::RF_Scattered);
1211 if (isNextScattered)
1212 RType = (RENext->Word0 >> 24) & 0xF;
1214 RType = (RENext->Word1 >> 28) & 0xF;
1217 report_fatal_error("Expected ARM_RELOC_PAIR after "
1218 "GENERIC_RELOC_HALF");
1220 // NOTE: The half of the target virtual address is stashed in the
1221 // address field of the secondary relocation, but we can't reverse
1222 // engineer the constant offset from it without decoding the movw/movt
1223 // instruction to find the other half in its immediate field.
1225 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1226 // symbol/section pointer of the follow-on relocation.
1227 if (Type == macho::RIT_ARM_HalfDifference) {
1229 printRelocationTargetName(RENext, fmt);
1236 printRelocationTargetName(RE, fmt);
1241 printRelocationTargetName(RE, fmt);
1244 Result.append(fmtbuf.begin(), fmtbuf.end());
1245 return object_error::success;
1248 error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1249 bool &Result) const {
1250 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
1252 unsigned Arch = getArch();
1253 bool isScattered = (Arch != Triple::x86_64) &&
1254 (RE->Word0 & macho::RF_Scattered);
1257 Type = (RE->Word0 >> 24) & 0xF;
1259 Type = (RE->Word1 >> 28) & 0xF;
1263 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1264 // is always hidden.
1265 if (Arch == Triple::x86 || Arch == Triple::arm) {
1266 if (Type == macho::RIT_Pair) Result = true;
1267 } else if (Arch == Triple::x86_64) {
1268 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1269 // an X864_64_RELOC_SUBTRACTOR.
1270 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1271 DataRefImpl RelPrev = Rel;
1273 const MachOFormat::RelocationEntry *REPrev = getRelocation(RelPrev);
1275 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1277 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
1281 return object_error::success;
1284 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1285 LibraryRef &Res) const {
1286 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1289 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1290 StringRef &Res) const {
1291 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1295 /*===-- Miscellaneous -----------------------------------------------------===*/
1297 uint8_t MachOObjectFile::getBytesInAddress() const {
1298 return is64Bit() ? 8 : 4;
1301 StringRef MachOObjectFile::getFileFormatName() const {
1303 switch (getHeader().CPUType) {
1304 case llvm::MachO::CPUTypeI386:
1305 return "Mach-O 32-bit i386";
1306 case llvm::MachO::CPUTypeARM:
1307 return "Mach-O arm";
1308 case llvm::MachO::CPUTypePowerPC:
1309 return "Mach-O 32-bit ppc";
1311 assert((getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
1312 "64-bit object file when we're not 64-bit?");
1313 return "Mach-O 32-bit unknown";
1317 // Make sure the cpu type has the correct mask.
1318 assert((getHeader().CPUType & llvm::MachO::CPUArchABI64)
1319 == llvm::MachO::CPUArchABI64 &&
1320 "32-bit object file when we're 64-bit?");
1322 switch (getHeader().CPUType) {
1323 case llvm::MachO::CPUTypeX86_64:
1324 return "Mach-O 64-bit x86-64";
1325 case llvm::MachO::CPUTypePowerPC64:
1326 return "Mach-O 64-bit ppc64";
1328 return "Mach-O 64-bit unknown";
1332 unsigned MachOObjectFile::getArch() const {
1333 switch (getHeader().CPUType) {
1334 case llvm::MachO::CPUTypeI386:
1336 case llvm::MachO::CPUTypeX86_64:
1337 return Triple::x86_64;
1338 case llvm::MachO::CPUTypeARM:
1340 case llvm::MachO::CPUTypePowerPC:
1342 case llvm::MachO::CPUTypePowerPC64:
1343 return Triple::ppc64;
1345 return Triple::UnknownArch;
1349 } // end namespace object
1350 } // end namespace llvm