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 LoadCommandInfo &
62 MachOObjectFile::getLoadCommandInfo(unsigned Index) const {
63 return MachOObj->getLoadCommandInfo(Index);
66 void MachOObjectFile::ReadULEB128s(uint64_t Index,
67 SmallVectorImpl<uint64_t> &Out) const {
68 return MachOObj->ReadULEB128s(Index, Out);
71 const macho::Header &MachOObjectFile::getHeader() const {
72 return MachOObj->getHeader();
75 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
77 ObjectFile *Ret = new MachOObjectFile(Buffer, ec);
83 /*===-- Symbols -----------------------------------------------------------===*/
85 const MachOFormat::SymtabLoadCommand *
86 MachOObjectFile::getSymtabLoadCommand(LoadCommandInfo LCI) const {
87 StringRef Data = MachOObj->getData(LCI.Offset,
88 sizeof(MachOFormat::SymtabLoadCommand));
89 return reinterpret_cast<const MachOFormat::SymtabLoadCommand*>(Data.data());
92 const MachOFormat::SegmentLoadCommand *
93 MachOObjectFile::getSegmentLoadCommand(LoadCommandInfo LCI) const {
94 StringRef Data = MachOObj->getData(LCI.Offset,
95 sizeof(MachOFormat::SegmentLoadCommand));
96 return reinterpret_cast<const MachOFormat::SegmentLoadCommand*>(Data.data());
99 const MachOFormat::LinkeditDataLoadCommand *
100 MachOObjectFile::getLinkeditDataLoadCommand(LoadCommandInfo LCI) const {
101 StringRef Data = MachOObj->getData(LCI.Offset,
102 sizeof(MachOFormat::LinkeditDataLoadCommand));
104 reinterpret_cast<const MachOFormat::LinkeditDataLoadCommand*>(Data.data());
107 const MachOFormat::Segment64LoadCommand *
108 MachOObjectFile::getSegment64LoadCommand(LoadCommandInfo LCI) const {
109 StringRef Data = MachOObj->getData(LCI.Offset,
110 sizeof(MachOFormat::Segment64LoadCommand));
112 reinterpret_cast<const MachOFormat::Segment64LoadCommand*>(Data.data());
115 void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
116 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
117 while (DRI.d.a < LoadCommandCount) {
118 LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a);
119 if (LCI.Command.Type == macho::LCT_Symtab) {
120 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
121 getSymtabLoadCommand(LCI);
122 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
131 const MachOFormat::SymbolTableEntry *
132 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
133 LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a);
134 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
135 getSymtabLoadCommand(LCI);
137 return getSymbolTableEntry(DRI, SymtabLoadCmd);
140 const MachOFormat::SymbolTableEntry *
141 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI,
142 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
143 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
144 unsigned Index = DRI.d.b;
145 uint64_t Offset = (SymbolTableOffset +
146 Index * sizeof(macho::SymbolTableEntry));
147 StringRef Data = MachOObj->getData(Offset,
148 sizeof(MachOFormat::SymbolTableEntry));
149 return reinterpret_cast<const MachOFormat::SymbolTableEntry*>(Data.data());
152 const MachOFormat::Symbol64TableEntry*
153 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
154 LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a);
155 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
156 getSymtabLoadCommand(LCI);
158 return getSymbol64TableEntry(DRI, SymtabLoadCmd);
161 const MachOFormat::Symbol64TableEntry*
162 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI,
163 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const {
164 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
165 unsigned Index = DRI.d.b;
166 uint64_t Offset = (SymbolTableOffset +
167 Index * sizeof(macho::Symbol64TableEntry));
168 StringRef Data = MachOObj->getData(Offset,
169 sizeof(MachOFormat::Symbol64TableEntry));
170 return reinterpret_cast<const MachOFormat::Symbol64TableEntry*>(Data.data());
173 error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
174 SymbolRef &Result) const {
176 moveToNextSymbol(DRI);
177 Result = SymbolRef(DRI, this);
178 return object_error::success;
181 error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
182 StringRef &Result) const {
183 LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a);
184 const MachOFormat::SymtabLoadCommand *SymtabLoadCmd =
185 getSymtabLoadCommand(LCI);
187 StringRef StringTable =
188 MachOObj->getData(SymtabLoadCmd->StringTableOffset,
189 SymtabLoadCmd->StringTableSize);
191 uint32_t StringIndex;
192 if (MachOObj->is64Bit()) {
193 const MachOFormat::Symbol64TableEntry *Entry =
194 getSymbol64TableEntry(DRI, SymtabLoadCmd);
195 StringIndex = Entry->StringIndex;
197 const MachOFormat::SymbolTableEntry *Entry =
198 getSymbolTableEntry(DRI, SymtabLoadCmd);
199 StringIndex = Entry->StringIndex;
202 const char *Start = &StringTable.data()[StringIndex];
203 Result = StringRef(Start);
205 return object_error::success;
208 error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI,
209 uint64_t &Result) const {
210 if (MachOObj->is64Bit()) {
211 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
212 Result = Entry->Value;
213 if (Entry->SectionIndex) {
214 const MachOFormat::Section64 *Section =
215 getSection64(Sections[Entry->SectionIndex-1]);
216 Result += Section->Offset - Section->Address;
219 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
220 Result = Entry->Value;
221 if (Entry->SectionIndex) {
222 const MachOFormat::Section *Section =
223 getSection(Sections[Entry->SectionIndex-1]);
224 Result += Section->Offset - Section->Address;
228 return object_error::success;
231 error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
232 uint64_t &Result) const {
233 if (MachOObj->is64Bit()) {
234 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
235 Result = Entry->Value;
237 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
238 Result = Entry->Value;
240 return object_error::success;
243 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
244 uint64_t &Result) const {
245 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
246 uint64_t BeginOffset;
247 uint64_t EndOffset = 0;
248 uint8_t SectionIndex;
249 if (MachOObj->is64Bit()) {
250 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
251 BeginOffset = Entry->Value;
252 SectionIndex = Entry->SectionIndex;
254 uint32_t flags = SymbolRef::SF_None;
255 getSymbolFlags(DRI, flags);
256 if (flags & SymbolRef::SF_Common)
257 Result = Entry->Value;
259 Result = UnknownAddressOrSize;
260 return object_error::success;
262 // Unfortunately symbols are unsorted so we need to touch all
263 // symbols from load command
265 uint32_t Command = DRI.d.a;
266 while (Command == DRI.d.a) {
267 moveToNextSymbol(DRI);
268 if (DRI.d.a < LoadCommandCount) {
269 Entry = getSymbol64TableEntry(DRI);
270 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
271 if (!EndOffset || Entry->Value < EndOffset)
272 EndOffset = Entry->Value;
277 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
278 BeginOffset = Entry->Value;
279 SectionIndex = Entry->SectionIndex;
281 uint32_t flags = SymbolRef::SF_None;
282 getSymbolFlags(DRI, flags);
283 if (flags & SymbolRef::SF_Common)
284 Result = Entry->Value;
286 Result = UnknownAddressOrSize;
287 return object_error::success;
289 // Unfortunately symbols are unsorted so we need to touch all
290 // symbols from load command
292 uint32_t Command = DRI.d.a;
293 while (Command == DRI.d.a) {
294 moveToNextSymbol(DRI);
295 if (DRI.d.a < LoadCommandCount) {
296 Entry = getSymbolTableEntry(DRI);
297 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
298 if (!EndOffset || Entry->Value < EndOffset)
299 EndOffset = Entry->Value;
306 getSectionSize(Sections[SectionIndex-1], Size);
307 getSectionAddress(Sections[SectionIndex-1], EndOffset);
310 Result = EndOffset - BeginOffset;
311 return object_error::success;
314 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
315 char &Result) const {
317 if (MachOObj->is64Bit()) {
318 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
320 Flags = Entry->Flags;
322 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
324 Flags = Entry->Flags;
328 switch (Type & macho::STF_TypeMask) {
329 case macho::STT_Undefined:
332 case macho::STT_Absolute:
333 case macho::STT_Section:
341 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
342 Char = toupper(static_cast<unsigned char>(Char));
344 return object_error::success;
347 error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
348 uint32_t &Result) const {
351 if (MachOObj->is64Bit()) {
352 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI);
353 MachOFlags = Entry->Flags;
354 MachOType = Entry->Type;
356 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
357 MachOFlags = Entry->Flags;
358 MachOType = Entry->Type;
361 // TODO: Correctly set SF_ThreadLocal
362 Result = SymbolRef::SF_None;
364 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
365 Result |= SymbolRef::SF_Undefined;
367 if (MachOFlags & macho::STF_StabsEntryMask)
368 Result |= SymbolRef::SF_FormatSpecific;
370 if (MachOType & MachO::NlistMaskExternal) {
371 Result |= SymbolRef::SF_Global;
372 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
373 Result |= SymbolRef::SF_Common;
376 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
377 Result |= SymbolRef::SF_Weak;
379 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
380 Result |= SymbolRef::SF_Absolute;
382 return object_error::success;
385 error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
386 section_iterator &Res) const {
388 if (MachOObj->is64Bit()) {
389 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
390 index = Entry->SectionIndex;
392 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
393 index = Entry->SectionIndex;
397 Res = end_sections();
399 Res = section_iterator(SectionRef(Sections[index-1], this));
401 return object_error::success;
404 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
405 SymbolRef::Type &Res) const {
407 if (MachOObj->is64Bit()) {
408 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
409 n_type = Entry->Type;
411 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
412 n_type = Entry->Type;
414 Res = SymbolRef::ST_Other;
416 // If this is a STAB debugging symbol, we can do nothing more.
417 if (n_type & MachO::NlistMaskStab) {
418 Res = SymbolRef::ST_Debug;
419 return object_error::success;
422 switch (n_type & MachO::NlistMaskType) {
423 case MachO::NListTypeUndefined :
424 Res = SymbolRef::ST_Unknown;
426 case MachO::NListTypeSection :
427 Res = SymbolRef::ST_Function;
430 return object_error::success;
433 error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
434 uint64_t &Val) const {
435 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
438 symbol_iterator MachOObjectFile::begin_symbols() const {
439 // DRI.d.a = segment number; DRI.d.b = symbol index.
441 moveToNextSymbol(DRI);
442 return symbol_iterator(SymbolRef(DRI, this));
445 symbol_iterator MachOObjectFile::end_symbols() const {
447 DRI.d.a = MachOObj->getHeader().NumLoadCommands;
448 return symbol_iterator(SymbolRef(DRI, this));
451 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
453 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
456 symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
458 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
461 library_iterator MachOObjectFile::begin_libraries_needed() const {
463 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
466 library_iterator MachOObjectFile::end_libraries_needed() const {
468 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
471 StringRef MachOObjectFile::getLoadName() const {
473 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
476 /*===-- Sections ----------------------------------------------------------===*/
478 void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
479 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
480 while (DRI.d.a < LoadCommandCount) {
481 LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a);
482 if (LCI.Command.Type == macho::LCT_Segment) {
483 const MachOFormat::SegmentLoadCommand *SegmentLoadCmd =
484 getSegmentLoadCommand(LCI);
485 if (DRI.d.b < SegmentLoadCmd->NumSections)
487 } else if (LCI.Command.Type == macho::LCT_Segment64) {
488 const MachOFormat::Segment64LoadCommand *Segment64LoadCmd =
489 getSegment64LoadCommand(LCI);
490 if (DRI.d.b < Segment64LoadCmd->NumSections)
499 error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
500 SectionRef &Result) const {
502 moveToNextSection(DRI);
503 Result = SectionRef(DRI, this);
504 return object_error::success;
507 static bool is64BitLoadCommand(const MachOObjectFile *MachOObj,
509 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
510 if (LCI.Command.Type == macho::LCT_Segment64)
512 assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type.");
516 const MachOFormat::Section *MachOObjectFile::getSection(DataRefImpl DRI) const {
517 assert(!is64BitLoadCommand(this, DRI));
518 LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a);
519 unsigned SectionOffset = LCI.Offset + sizeof(macho::SegmentLoadCommand) +
520 DRI.d.b * sizeof(MachOFormat::Section);
521 StringRef Data = MachOObj->getData(SectionOffset, sizeof(MachOFormat::Section));
522 return reinterpret_cast<const MachOFormat::Section*>(Data.data());
525 std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
526 SectionList::const_iterator loc =
527 std::find(Sections.begin(), Sections.end(), Sec);
528 assert(loc != Sections.end() && "Sec is not a valid section!");
529 return std::distance(Sections.begin(), loc);
532 const MachOFormat::Section64 *
533 MachOObjectFile::getSection64(DataRefImpl DRI) const {
534 assert(is64BitLoadCommand(this, DRI));
535 LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a);
536 unsigned SectionOffset = LCI.Offset + sizeof(macho::Segment64LoadCommand) +
537 DRI.d.b * sizeof(MachOFormat::Section64);
538 StringRef Data = MachOObj->getData(SectionOffset, sizeof(MachOFormat::Section64));
539 return reinterpret_cast<const MachOFormat::Section64*>(Data.data());
542 static StringRef parseSegmentOrSectionName(const char *P) {
546 // Not null terminated, so this is a 16 char string.
547 return StringRef(P, 16);
550 ArrayRef<char> MachOObjectFile::getSectionRawName(DataRefImpl DRI) const {
551 if (is64BitLoadCommand(this, DRI)) {
552 const MachOFormat::Section64 *sec = getSection64(DRI);
553 return ArrayRef<char>(sec->Name);
555 const MachOFormat::Section *sec = getSection(DRI);
556 return ArrayRef<char>(sec->Name);
560 error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
561 StringRef &Result) const {
562 ArrayRef<char> Raw = getSectionRawName(DRI);
563 Result = parseSegmentOrSectionName(Raw.data());
564 return object_error::success;
568 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
569 if (is64BitLoadCommand(this, Sec)) {
570 const MachOFormat::Section64 *sec = getSection64(Sec);
571 return ArrayRef<char>(sec->SegmentName, 16);
573 const MachOFormat::Section *sec = getSection(Sec);
574 return ArrayRef<char>(sec->SegmentName);
578 StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const {
579 ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
580 return parseSegmentOrSectionName(Raw.data());
583 error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
584 uint64_t &Result) const {
585 if (is64BitLoadCommand(this, DRI)) {
586 const MachOFormat::Section64 *Sect = getSection64(DRI);
587 Result = Sect->Address;
589 const MachOFormat::Section *Sect = getSection(DRI);
590 Result = Sect->Address;
592 return object_error::success;
595 error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
596 uint64_t &Result) const {
597 if (is64BitLoadCommand(this, DRI)) {
598 const MachOFormat::Section64 *Sect = getSection64(DRI);
601 const MachOFormat::Section *Sect = getSection(DRI);
604 return object_error::success;
607 error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
608 StringRef &Result) const {
609 if (is64BitLoadCommand(this, DRI)) {
610 const MachOFormat::Section64 *Sect = getSection64(DRI);
611 Result = MachOObj->getData(Sect->Offset, Sect->Size);
613 const MachOFormat::Section *Sect = getSection(DRI);
614 Result = MachOObj->getData(Sect->Offset, Sect->Size);
616 return object_error::success;
619 error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
620 uint64_t &Result) const {
621 if (is64BitLoadCommand(this, DRI)) {
622 const MachOFormat::Section64 *Sect = getSection64(DRI);
623 Result = uint64_t(1) << Sect->Align;
625 const MachOFormat::Section *Sect = getSection(DRI);
626 Result = uint64_t(1) << Sect->Align;
628 return object_error::success;
631 error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
632 bool &Result) const {
633 if (is64BitLoadCommand(this, DRI)) {
634 const MachOFormat::Section64 *Sect = getSection64(DRI);
635 Result = Sect->Flags & macho::SF_PureInstructions;
637 const MachOFormat::Section *Sect = getSection(DRI);
638 Result = Sect->Flags & macho::SF_PureInstructions;
640 return object_error::success;
643 error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
644 bool &Result) const {
645 // FIXME: Unimplemented.
647 return object_error::success;
650 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
651 bool &Result) const {
652 // FIXME: Unimplemented.
654 return object_error::success;
657 error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
658 bool &Result) const {
659 // FIXME: Unimplemented.
661 return object_error::success;
664 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
665 bool &Result) const {
666 // FIXME: Unimplemented.
668 return object_error::success;
671 error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI,
672 bool &Result) const {
673 if (MachOObj->is64Bit()) {
674 const MachOFormat::Section64 *Sect = getSection64(DRI);
675 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
676 Result = (SectionType == MachO::SectionTypeZeroFill ||
677 SectionType == MachO::SectionTypeZeroFillLarge);
679 const MachOFormat::Section *Sect = getSection(DRI);
680 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
681 Result = (SectionType == MachO::SectionTypeZeroFill ||
682 SectionType == MachO::SectionTypeZeroFillLarge);
685 return object_error::success;
688 error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
689 bool &Result) const {
690 // Consider using the code from isSectionText to look for __const sections.
691 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
692 // to use section attributes to distinguish code from data.
694 // FIXME: Unimplemented.
696 return object_error::success;
699 error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
701 bool &Result) const {
703 getSymbolType(Symb, ST);
704 if (ST == SymbolRef::ST_Unknown) {
706 return object_error::success;
709 uint64_t SectBegin, SectEnd;
710 getSectionAddress(Sec, SectBegin);
711 getSectionSize(Sec, SectEnd);
712 SectEnd += SectBegin;
714 if (MachOObj->is64Bit()) {
715 const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb);
716 uint64_t SymAddr= Entry->Value;
717 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
719 const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
720 uint64_t SymAddr= Entry->Value;
721 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
724 return object_error::success;
727 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
729 ret.d.b = getSectionIndex(Sec);
730 return relocation_iterator(RelocationRef(ret, this));
732 relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
734 if (is64BitLoadCommand(this, Sec)) {
735 const MachOFormat::Section64 *Sect = getSection64(Sec);
736 last_reloc = Sect->NumRelocationTableEntries;
738 const MachOFormat::Section *Sect = getSection(Sec);
739 last_reloc = Sect->NumRelocationTableEntries;
742 ret.d.a = last_reloc;
743 ret.d.b = getSectionIndex(Sec);
744 return relocation_iterator(RelocationRef(ret, this));
747 section_iterator MachOObjectFile::begin_sections() const {
749 moveToNextSection(DRI);
750 return section_iterator(SectionRef(DRI, this));
753 section_iterator MachOObjectFile::end_sections() const {
755 DRI.d.a = MachOObj->getHeader().NumLoadCommands;
756 return section_iterator(SectionRef(DRI, this));
759 /*===-- Relocations -------------------------------------------------------===*/
761 const MachOFormat::RelocationEntry *
762 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
764 if (MachOObj->is64Bit()) {
765 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
766 relOffset = Sect->RelocationTableOffset;
768 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
769 relOffset = Sect->RelocationTableOffset;
771 uint64_t Offset = relOffset + Rel.d.a * sizeof(MachOFormat::RelocationEntry);
773 MachOObj->getData(Offset, sizeof(MachOFormat::RelocationEntry));
774 return reinterpret_cast<const MachOFormat::RelocationEntry*>(Data.data());
777 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
778 RelocationRef &Res) const {
780 Res = RelocationRef(Rel, this);
781 return object_error::success;
783 error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
784 uint64_t &Res) const {
785 const uint8_t* sectAddress = 0;
786 if (MachOObj->is64Bit()) {
787 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
788 sectAddress += Sect->Address;
790 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
791 sectAddress += Sect->Address;
793 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
795 unsigned Arch = getArch();
796 bool isScattered = (Arch != Triple::x86_64) &&
797 (RE->Word0 & macho::RF_Scattered);
798 uint64_t RelAddr = 0;
800 RelAddr = RE->Word0 & 0xFFFFFF;
804 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
805 return object_error::success;
807 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
808 uint64_t &Res) const {
809 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
811 unsigned Arch = getArch();
812 bool isScattered = (Arch != Triple::x86_64) &&
813 (RE->Word0 & macho::RF_Scattered);
815 Res = RE->Word0 & 0xFFFFFF;
818 return object_error::success;
820 error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
821 SymbolRef &Res) const {
822 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
823 uint32_t SymbolIdx = RE->Word1 & 0xffffff;
824 bool isExtern = (RE->Word1 >> 27) & 1;
827 moveToNextSymbol(Sym);
829 for (unsigned i = 0; i < SymbolIdx; i++) {
831 moveToNextSymbol(Sym);
832 assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands &&
833 "Relocation symbol index out of range!");
836 Res = SymbolRef(Sym, this);
837 return object_error::success;
839 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
840 uint64_t &Res) const {
841 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
845 return object_error::success;
847 error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
848 SmallVectorImpl<char> &Result) const {
849 // TODO: Support scattered relocations.
851 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
853 unsigned Arch = getArch();
854 bool isScattered = (Arch != Triple::x86_64) &&
855 (RE->Word0 & macho::RF_Scattered);
859 r_type = (RE->Word0 >> 24) & 0xF;
861 r_type = (RE->Word1 >> 28) & 0xF;
865 static const char *const Table[] = {
866 "GENERIC_RELOC_VANILLA",
867 "GENERIC_RELOC_PAIR",
868 "GENERIC_RELOC_SECTDIFF",
869 "GENERIC_RELOC_PB_LA_PTR",
870 "GENERIC_RELOC_LOCAL_SECTDIFF",
871 "GENERIC_RELOC_TLV" };
879 case Triple::x86_64: {
880 static const char *const Table[] = {
881 "X86_64_RELOC_UNSIGNED",
882 "X86_64_RELOC_SIGNED",
883 "X86_64_RELOC_BRANCH",
884 "X86_64_RELOC_GOT_LOAD",
886 "X86_64_RELOC_SUBTRACTOR",
887 "X86_64_RELOC_SIGNED_1",
888 "X86_64_RELOC_SIGNED_2",
889 "X86_64_RELOC_SIGNED_4",
890 "X86_64_RELOC_TLV" };
899 static const char *const Table[] = {
902 "ARM_RELOC_SECTDIFF",
903 "ARM_RELOC_LOCAL_SECTDIFF",
904 "ARM_RELOC_PB_LA_PTR",
906 "ARM_THUMB_RELOC_BR22",
907 "ARM_THUMB_32BIT_BRANCH",
909 "ARM_RELOC_HALF_SECTDIFF" };
918 static const char *const Table[] = {
927 "PPC_RELOC_SECTDIFF",
928 "PPC_RELOC_PB_LA_PTR",
929 "PPC_RELOC_HI16_SECTDIFF",
930 "PPC_RELOC_LO16_SECTDIFF",
931 "PPC_RELOC_HA16_SECTDIFF",
933 "PPC_RELOC_LO14_SECTDIFF",
934 "PPC_RELOC_LOCAL_SECTDIFF" };
939 case Triple::UnknownArch:
943 Result.append(res.begin(), res.end());
944 return object_error::success;
946 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
947 int64_t &Res) const {
948 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
949 bool isExtern = (RE->Word1 >> 27) & 1;
952 const uint8_t* sectAddress = base();
953 if (MachOObj->is64Bit()) {
954 const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]);
955 sectAddress += Sect->Offset;
957 const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]);
958 sectAddress += Sect->Offset;
960 Res = reinterpret_cast<uintptr_t>(sectAddress);
962 return object_error::success;
965 // Helper to advance a section or symbol iterator multiple increments at a time.
967 error_code advance(T &it, size_t Val) {
976 void advanceTo(T &it, size_t Val) {
977 if (error_code ec = advance(it, Val))
978 report_fatal_error(ec.message());
981 void MachOObjectFile::printRelocationTargetName(
982 const MachOFormat::RelocationEntry *RE,
983 raw_string_ostream &fmt) const {
984 unsigned Arch = getArch();
985 bool isScattered = (Arch != Triple::x86_64) &&
986 (RE->Word0 & macho::RF_Scattered);
988 // Target of a scattered relocation is an address. In the interest of
989 // generating pretty output, scan through the symbol table looking for a
990 // symbol that aligns with that address. If we find one, print it.
991 // Otherwise, we just print the hex address of the target.
993 uint32_t Val = RE->Word1;
996 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
998 if (ec) report_fatal_error(ec.message());
1003 if ((ec = SI->getAddress(Addr)))
1004 report_fatal_error(ec.message());
1005 if (Addr != Val) continue;
1006 if ((ec = SI->getName(Name)))
1007 report_fatal_error(ec.message());
1012 // If we couldn't find a symbol that this relocation refers to, try
1013 // to find a section beginning instead.
1014 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
1016 if (ec) report_fatal_error(ec.message());
1021 if ((ec = SI->getAddress(Addr)))
1022 report_fatal_error(ec.message());
1023 if (Addr != Val) continue;
1024 if ((ec = SI->getName(Name)))
1025 report_fatal_error(ec.message());
1030 fmt << format("0x%x", Val);
1035 bool isExtern = (RE->Word1 >> 27) & 1;
1036 uint32_t Val = RE->Word1 & 0xFFFFFF;
1039 symbol_iterator SI = begin_symbols();
1043 section_iterator SI = begin_sections();
1051 error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
1052 SmallVectorImpl<char> &Result) const {
1053 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
1055 unsigned Arch = getArch();
1056 bool isScattered = (Arch != Triple::x86_64) &&
1057 (RE->Word0 & macho::RF_Scattered);
1060 raw_string_ostream fmt(fmtbuf);
1064 Type = (RE->Word0 >> 24) & 0xF;
1066 Type = (RE->Word1 >> 28) & 0xF;
1070 isPCRel = ((RE->Word0 >> 30) & 1);
1072 isPCRel = ((RE->Word1 >> 24) & 1);
1074 // Determine any addends that should be displayed with the relocation.
1075 // These require decoding the relocation type, which is triple-specific.
1077 // X86_64 has entirely custom relocation types.
1078 if (Arch == Triple::x86_64) {
1079 bool isPCRel = ((RE->Word1 >> 24) & 1);
1082 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
1083 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
1084 printRelocationTargetName(RE, fmt);
1086 if (isPCRel) fmt << "PCREL";
1089 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
1090 DataRefImpl RelNext = Rel;
1092 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1094 // X86_64_SUBTRACTOR must be followed by a relocation of type
1095 // X86_64_RELOC_UNSIGNED.
1096 // NOTE: Scattered relocations don't exist on x86_64.
1097 unsigned RType = (RENext->Word1 >> 28) & 0xF;
1099 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1100 "X86_64_RELOC_SUBTRACTOR.");
1102 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1103 // X86_64_SUBTRACTOR contains to the subtrahend.
1104 printRelocationTargetName(RENext, fmt);
1106 printRelocationTargetName(RE, fmt);
1109 case macho::RIT_X86_64_TLV:
1110 printRelocationTargetName(RE, fmt);
1112 if (isPCRel) fmt << "P";
1114 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1115 printRelocationTargetName(RE, fmt);
1118 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1119 printRelocationTargetName(RE, fmt);
1122 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1123 printRelocationTargetName(RE, fmt);
1127 printRelocationTargetName(RE, fmt);
1130 // X86 and ARM share some relocation types in common.
1131 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1132 // Generic relocation types...
1134 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1135 return object_error::success;
1136 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1137 DataRefImpl RelNext = Rel;
1139 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1141 // X86 sect diff's must be followed by a relocation of type
1142 // GENERIC_RELOC_PAIR.
1143 bool isNextScattered = (Arch != Triple::x86_64) &&
1144 (RENext->Word0 & macho::RF_Scattered);
1146 if (isNextScattered)
1147 RType = (RENext->Word0 >> 24) & 0xF;
1149 RType = (RENext->Word1 >> 28) & 0xF;
1151 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1152 "GENERIC_RELOC_SECTDIFF.");
1154 printRelocationTargetName(RE, fmt);
1156 printRelocationTargetName(RENext, fmt);
1161 if (Arch == Triple::x86) {
1162 // All X86 relocations that need special printing were already
1163 // handled in the generic code.
1165 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1166 DataRefImpl RelNext = Rel;
1168 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1170 // X86 sect diff's must be followed by a relocation of type
1171 // GENERIC_RELOC_PAIR.
1172 bool isNextScattered = (Arch != Triple::x86_64) &&
1173 (RENext->Word0 & macho::RF_Scattered);
1175 if (isNextScattered)
1176 RType = (RENext->Word0 >> 24) & 0xF;
1178 RType = (RENext->Word1 >> 28) & 0xF;
1180 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1181 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1183 printRelocationTargetName(RE, fmt);
1185 printRelocationTargetName(RENext, fmt);
1188 case macho::RIT_Generic_TLV: {
1189 printRelocationTargetName(RE, fmt);
1191 if (isPCRel) fmt << "P";
1195 printRelocationTargetName(RE, fmt);
1197 } else { // ARM-specific relocations
1199 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1200 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1201 // Half relocations steal a bit from the length field to encode
1202 // whether this is an upper16 or a lower16 relocation.
1205 isUpper = (RE->Word0 >> 28) & 1;
1207 isUpper = (RE->Word1 >> 25) & 1;
1210 fmt << ":upper16:(";
1212 fmt << ":lower16:(";
1213 printRelocationTargetName(RE, fmt);
1215 DataRefImpl RelNext = Rel;
1217 const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext);
1219 // ARM half relocs must be followed by a relocation of type
1221 bool isNextScattered = (Arch != Triple::x86_64) &&
1222 (RENext->Word0 & macho::RF_Scattered);
1224 if (isNextScattered)
1225 RType = (RENext->Word0 >> 24) & 0xF;
1227 RType = (RENext->Word1 >> 28) & 0xF;
1230 report_fatal_error("Expected ARM_RELOC_PAIR after "
1231 "GENERIC_RELOC_HALF");
1233 // NOTE: The half of the target virtual address is stashed in the
1234 // address field of the secondary relocation, but we can't reverse
1235 // engineer the constant offset from it without decoding the movw/movt
1236 // instruction to find the other half in its immediate field.
1238 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1239 // symbol/section pointer of the follow-on relocation.
1240 if (Type == macho::RIT_ARM_HalfDifference) {
1242 printRelocationTargetName(RENext, fmt);
1249 printRelocationTargetName(RE, fmt);
1254 printRelocationTargetName(RE, fmt);
1257 Result.append(fmtbuf.begin(), fmtbuf.end());
1258 return object_error::success;
1261 error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1262 bool &Result) const {
1263 const MachOFormat::RelocationEntry *RE = getRelocation(Rel);
1265 unsigned Arch = getArch();
1266 bool isScattered = (Arch != Triple::x86_64) &&
1267 (RE->Word0 & macho::RF_Scattered);
1270 Type = (RE->Word0 >> 24) & 0xF;
1272 Type = (RE->Word1 >> 28) & 0xF;
1276 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1277 // is always hidden.
1278 if (Arch == Triple::x86 || Arch == Triple::arm) {
1279 if (Type == macho::RIT_Pair) Result = true;
1280 } else if (Arch == Triple::x86_64) {
1281 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1282 // an X864_64_RELOC_SUBTRACTOR.
1283 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1284 DataRefImpl RelPrev = Rel;
1286 const MachOFormat::RelocationEntry *REPrev = getRelocation(RelPrev);
1288 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1290 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
1294 return object_error::success;
1297 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1298 LibraryRef &Res) const {
1299 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1302 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1303 StringRef &Res) const {
1304 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1308 /*===-- Miscellaneous -----------------------------------------------------===*/
1310 uint8_t MachOObjectFile::getBytesInAddress() const {
1311 return MachOObj->is64Bit() ? 8 : 4;
1314 StringRef MachOObjectFile::getFileFormatName() const {
1315 if (!MachOObj->is64Bit()) {
1316 switch (MachOObj->getHeader().CPUType) {
1317 case llvm::MachO::CPUTypeI386:
1318 return "Mach-O 32-bit i386";
1319 case llvm::MachO::CPUTypeARM:
1320 return "Mach-O arm";
1321 case llvm::MachO::CPUTypePowerPC:
1322 return "Mach-O 32-bit ppc";
1324 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
1325 "64-bit object file when we're not 64-bit?");
1326 return "Mach-O 32-bit unknown";
1330 // Make sure the cpu type has the correct mask.
1331 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64)
1332 == llvm::MachO::CPUArchABI64 &&
1333 "32-bit object file when we're 64-bit?");
1335 switch (MachOObj->getHeader().CPUType) {
1336 case llvm::MachO::CPUTypeX86_64:
1337 return "Mach-O 64-bit x86-64";
1338 case llvm::MachO::CPUTypePowerPC64:
1339 return "Mach-O 64-bit ppc64";
1341 return "Mach-O 64-bit unknown";
1345 unsigned MachOObjectFile::getArch() const {
1346 switch (MachOObj->getHeader().CPUType) {
1347 case llvm::MachO::CPUTypeI386:
1349 case llvm::MachO::CPUTypeX86_64:
1350 return Triple::x86_64;
1351 case llvm::MachO::CPUTypeARM:
1353 case llvm::MachO::CPUTypePowerPC:
1355 case llvm::MachO::CPUTypePowerPC64:
1356 return Triple::ppc64;
1358 return Triple::UnknownArch;
1362 } // end namespace object
1363 } // end namespace llvm