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/ADT/Triple.h"
16 #include "llvm/Object/MachO.h"
17 #include "llvm/Object/MachOFormat.h"
18 #include "llvm/Support/Format.h"
19 #include "llvm/Support/MemoryBuffer.h"
26 using namespace object;
31 MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO,
33 : ObjectFile(Binary::isMachO, Object, ec),
35 RegisteredStringTable(std::numeric_limits<uint32_t>::max()) {
37 DRI.d.a = DRI.d.b = 0;
38 moveToNextSection(DRI);
39 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
40 while (DRI.d.a < LoadCommandCount) {
41 Sections.push_back(DRI);
43 moveToNextSection(DRI);
48 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
51 MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err);
54 return new MachOObjectFile(Buffer, MachOObj, ec);
57 /*===-- Symbols -----------------------------------------------------------===*/
59 void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
60 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
61 while (DRI.d.a < LoadCommandCount) {
62 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
63 if (LCI.Command.Type == macho::LCT_Symtab) {
64 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
65 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
66 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
75 void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI,
76 InMemoryStruct<macho::SymbolTableEntry> &Res) const {
77 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
78 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
79 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
81 if (RegisteredStringTable != DRI.d.a) {
82 MachOObj->RegisterStringTable(*SymtabLoadCmd);
83 RegisteredStringTable = DRI.d.a;
86 MachOObj->ReadSymbolTableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b,
90 void MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI,
91 InMemoryStruct<macho::Symbol64TableEntry> &Res) const {
92 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
93 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
94 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
96 if (RegisteredStringTable != DRI.d.a) {
97 MachOObj->RegisterStringTable(*SymtabLoadCmd);
98 RegisteredStringTable = DRI.d.a;
101 MachOObj->ReadSymbol64TableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b,
106 error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
107 SymbolRef &Result) const {
109 moveToNextSymbol(DRI);
110 Result = SymbolRef(DRI, this);
111 return object_error::success;
114 error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
115 StringRef &Result) const {
116 if (MachOObj->is64Bit()) {
117 InMemoryStruct<macho::Symbol64TableEntry> Entry;
118 getSymbol64TableEntry(DRI, Entry);
119 Result = MachOObj->getStringAtIndex(Entry->StringIndex);
121 InMemoryStruct<macho::SymbolTableEntry> Entry;
122 getSymbolTableEntry(DRI, Entry);
123 Result = MachOObj->getStringAtIndex(Entry->StringIndex);
125 return object_error::success;
128 error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI,
129 uint64_t &Result) const {
130 if (MachOObj->is64Bit()) {
131 InMemoryStruct<macho::Symbol64TableEntry> Entry;
132 getSymbol64TableEntry(DRI, Entry);
133 Result = Entry->Value;
134 if (Entry->SectionIndex) {
135 InMemoryStruct<macho::Section64> Section;
136 getSection64(Sections[Entry->SectionIndex-1], Section);
137 Result += Section->Offset - Section->Address;
140 InMemoryStruct<macho::SymbolTableEntry> Entry;
141 getSymbolTableEntry(DRI, Entry);
142 Result = Entry->Value;
143 if (Entry->SectionIndex) {
144 InMemoryStruct<macho::Section> Section;
145 getSection(Sections[Entry->SectionIndex-1], Section);
146 Result += Section->Offset - Section->Address;
150 return object_error::success;
153 error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
154 uint64_t &Result) const {
155 if (MachOObj->is64Bit()) {
156 InMemoryStruct<macho::Symbol64TableEntry> Entry;
157 getSymbol64TableEntry(DRI, Entry);
158 Result = Entry->Value;
160 InMemoryStruct<macho::SymbolTableEntry> Entry;
161 getSymbolTableEntry(DRI, Entry);
162 Result = Entry->Value;
164 return object_error::success;
167 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
168 uint64_t &Result) const {
169 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
170 uint64_t BeginOffset;
171 uint64_t EndOffset = 0;
172 uint8_t SectionIndex;
173 if (MachOObj->is64Bit()) {
174 InMemoryStruct<macho::Symbol64TableEntry> Entry;
175 getSymbol64TableEntry(DRI, Entry);
176 BeginOffset = Entry->Value;
177 SectionIndex = Entry->SectionIndex;
179 Result = UnknownAddressOrSize;
180 return object_error::success;
183 moveToNextSymbol(DRI);
184 if (DRI.d.a < LoadCommandCount) {
185 getSymbol64TableEntry(DRI, Entry);
186 if (Entry->SectionIndex == SectionIndex)
187 EndOffset += Entry->Value;
190 InMemoryStruct<macho::SymbolTableEntry> Entry;
191 getSymbolTableEntry(DRI, Entry);
192 BeginOffset = Entry->Value;
193 SectionIndex = Entry->SectionIndex;
195 Result = UnknownAddressOrSize;
196 return object_error::success;
199 moveToNextSymbol(DRI);
200 if (DRI.d.a < LoadCommandCount) {
201 getSymbolTableEntry(DRI, Entry);
202 if (Entry->SectionIndex == SectionIndex)
203 EndOffset += Entry->Value;
208 getSectionSize(Sections[SectionIndex-1], Size);
209 getSectionAddress(Sections[SectionIndex-1], EndOffset);
212 Result = EndOffset - BeginOffset;
213 return object_error::success;
216 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
217 char &Result) const {
219 if (MachOObj->is64Bit()) {
220 InMemoryStruct<macho::Symbol64TableEntry> Entry;
221 getSymbol64TableEntry(DRI, Entry);
223 Flags = Entry->Flags;
225 InMemoryStruct<macho::SymbolTableEntry> Entry;
226 getSymbolTableEntry(DRI, Entry);
228 Flags = Entry->Flags;
232 switch (Type & macho::STF_TypeMask) {
233 case macho::STT_Undefined:
236 case macho::STT_Absolute:
237 case macho::STT_Section:
245 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
246 Char = toupper(Char);
248 return object_error::success;
251 error_code MachOObjectFile::isSymbolInternal(DataRefImpl DRI,
252 bool &Result) const {
253 if (MachOObj->is64Bit()) {
254 InMemoryStruct<macho::Symbol64TableEntry> Entry;
255 getSymbol64TableEntry(DRI, Entry);
256 Result = Entry->Flags & macho::STF_StabsEntryMask;
258 InMemoryStruct<macho::SymbolTableEntry> Entry;
259 getSymbolTableEntry(DRI, Entry);
260 Result = Entry->Flags & macho::STF_StabsEntryMask;
262 return object_error::success;
265 error_code MachOObjectFile::isSymbolGlobal(DataRefImpl Symb, bool &Res) const {
267 if (MachOObj->is64Bit()) {
268 InMemoryStruct<macho::Symbol64TableEntry> Entry;
269 getSymbol64TableEntry(Symb, Entry);
270 Res = Entry->Type & MachO::NlistMaskExternal;
272 InMemoryStruct<macho::SymbolTableEntry> Entry;
273 getSymbolTableEntry(Symb, Entry);
274 Res = Entry->Type & MachO::NlistMaskExternal;
276 return object_error::success;
279 error_code MachOObjectFile::isSymbolWeak(DataRefImpl Symb, bool &Res) const {
281 if (MachOObj->is64Bit()) {
282 InMemoryStruct<macho::Symbol64TableEntry> Entry;
283 getSymbol64TableEntry(Symb, Entry);
284 Res = Entry->Flags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef);
286 InMemoryStruct<macho::SymbolTableEntry> Entry;
287 getSymbolTableEntry(Symb, Entry);
288 Res = Entry->Flags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef);
290 return object_error::success;
293 error_code MachOObjectFile::isSymbolAbsolute(DataRefImpl Symb, bool &Res) const{
295 if (MachOObj->is64Bit()) {
296 InMemoryStruct<macho::Symbol64TableEntry> Entry;
297 getSymbol64TableEntry(Symb, Entry);
298 n_type = Entry->Type;
300 InMemoryStruct<macho::SymbolTableEntry> Entry;
301 getSymbolTableEntry(Symb, Entry);
302 n_type = Entry->Type;
305 Res = (n_type & MachO::NlistMaskType) == MachO::NListTypeAbsolute;
306 return object_error::success;
309 error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
310 section_iterator &Res) const {
312 if (MachOObj->is64Bit()) {
313 InMemoryStruct<macho::Symbol64TableEntry> Entry;
314 getSymbol64TableEntry(Symb, Entry);
315 index = Entry->SectionIndex;
317 InMemoryStruct<macho::SymbolTableEntry> Entry;
318 getSymbolTableEntry(Symb, Entry);
319 index = Entry->SectionIndex;
323 Res = end_sections();
325 Res = section_iterator(SectionRef(Sections[index-1], this));
327 return object_error::success;
330 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
331 SymbolRef::Type &Res) const {
333 if (MachOObj->is64Bit()) {
334 InMemoryStruct<macho::Symbol64TableEntry> Entry;
335 getSymbol64TableEntry(Symb, Entry);
336 n_type = Entry->Type;
338 InMemoryStruct<macho::SymbolTableEntry> Entry;
339 getSymbolTableEntry(Symb, Entry);
340 n_type = Entry->Type;
342 Res = SymbolRef::ST_Other;
344 // If this is a STAB debugging symbol, we can do nothing more.
345 if (n_type & MachO::NlistMaskStab) {
346 Res = SymbolRef::ST_Debug;
347 return object_error::success;
350 switch (n_type & MachO::NlistMaskType) {
351 case MachO::NListTypeUndefined :
352 Res = SymbolRef::ST_External;
354 case MachO::NListTypeSection :
355 Res = SymbolRef::ST_Function;
358 return object_error::success;
362 symbol_iterator MachOObjectFile::begin_symbols() const {
363 // DRI.d.a = segment number; DRI.d.b = symbol index.
365 DRI.d.a = DRI.d.b = 0;
366 moveToNextSymbol(DRI);
367 return symbol_iterator(SymbolRef(DRI, this));
370 symbol_iterator MachOObjectFile::end_symbols() const {
372 DRI.d.a = MachOObj->getHeader().NumLoadCommands;
374 return symbol_iterator(SymbolRef(DRI, this));
378 /*===-- Sections ----------------------------------------------------------===*/
380 void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
381 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
382 while (DRI.d.a < LoadCommandCount) {
383 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
384 if (LCI.Command.Type == macho::LCT_Segment) {
385 InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd;
386 MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd);
387 if (DRI.d.b < SegmentLoadCmd->NumSections)
389 } else if (LCI.Command.Type == macho::LCT_Segment64) {
390 InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd;
391 MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd);
392 if (DRI.d.b < Segment64LoadCmd->NumSections)
401 error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
402 SectionRef &Result) const {
404 moveToNextSection(DRI);
405 Result = SectionRef(DRI, this);
406 return object_error::success;
410 MachOObjectFile::getSection(DataRefImpl DRI,
411 InMemoryStruct<macho::Section> &Res) const {
412 InMemoryStruct<macho::SegmentLoadCommand> SLC;
413 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
414 MachOObj->ReadSegmentLoadCommand(LCI, SLC);
415 MachOObj->ReadSection(LCI, DRI.d.b, Res);
418 std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
419 SectionList::const_iterator loc =
420 std::find(Sections.begin(), Sections.end(), Sec);
421 assert(loc != Sections.end() && "Sec is not a valid section!");
422 return std::distance(Sections.begin(), loc);
426 MachOObjectFile::getSection64(DataRefImpl DRI,
427 InMemoryStruct<macho::Section64> &Res) const {
428 InMemoryStruct<macho::Segment64LoadCommand> SLC;
429 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
430 MachOObj->ReadSegment64LoadCommand(LCI, SLC);
431 MachOObj->ReadSection64(LCI, DRI.d.b, Res);
434 static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) {
435 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
436 if (LCI.Command.Type == macho::LCT_Segment64)
438 assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type.");
442 error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
443 StringRef &Result) const {
444 // FIXME: thread safety.
445 static char result[34];
446 if (is64BitLoadCommand(MachOObj, DRI)) {
447 InMemoryStruct<macho::Segment64LoadCommand> SLC;
448 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
449 MachOObj->ReadSegment64LoadCommand(LCI, SLC);
450 InMemoryStruct<macho::Section64> Sect;
451 MachOObj->ReadSection64(LCI, DRI.d.b, Sect);
453 strcpy(result, Sect->SegmentName);
455 strcat(result, Sect->Name);
457 InMemoryStruct<macho::SegmentLoadCommand> SLC;
458 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
459 MachOObj->ReadSegmentLoadCommand(LCI, SLC);
460 InMemoryStruct<macho::Section> Sect;
461 MachOObj->ReadSection(LCI, DRI.d.b, Sect);
463 strcpy(result, Sect->SegmentName);
465 strcat(result, Sect->Name);
467 Result = StringRef(result);
468 return object_error::success;
471 error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
472 uint64_t &Result) const {
473 if (is64BitLoadCommand(MachOObj, DRI)) {
474 InMemoryStruct<macho::Section64> Sect;
475 getSection64(DRI, Sect);
476 Result = Sect->Address;
478 InMemoryStruct<macho::Section> Sect;
479 getSection(DRI, Sect);
480 Result = Sect->Address;
482 return object_error::success;
485 error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
486 uint64_t &Result) const {
487 if (is64BitLoadCommand(MachOObj, DRI)) {
488 InMemoryStruct<macho::Section64> Sect;
489 getSection64(DRI, Sect);
492 InMemoryStruct<macho::Section> Sect;
493 getSection(DRI, Sect);
496 return object_error::success;
499 error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
500 StringRef &Result) const {
501 if (is64BitLoadCommand(MachOObj, DRI)) {
502 InMemoryStruct<macho::Section64> Sect;
503 getSection64(DRI, Sect);
504 Result = MachOObj->getData(Sect->Offset, Sect->Size);
506 InMemoryStruct<macho::Section> Sect;
507 getSection(DRI, Sect);
508 Result = MachOObj->getData(Sect->Offset, Sect->Size);
510 return object_error::success;
513 error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
514 uint64_t &Result) const {
515 if (is64BitLoadCommand(MachOObj, DRI)) {
516 InMemoryStruct<macho::Section64> Sect;
517 getSection64(DRI, Sect);
518 Result = uint64_t(1) << Sect->Align;
520 InMemoryStruct<macho::Section> Sect;
521 getSection(DRI, Sect);
522 Result = uint64_t(1) << Sect->Align;
524 return object_error::success;
527 error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
528 bool &Result) const {
529 if (is64BitLoadCommand(MachOObj, DRI)) {
530 InMemoryStruct<macho::Section64> Sect;
531 getSection64(DRI, Sect);
532 Result = !strcmp(Sect->Name, "__text");
534 InMemoryStruct<macho::Section> Sect;
535 getSection(DRI, Sect);
536 Result = !strcmp(Sect->Name, "__text");
538 return object_error::success;
541 error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
542 bool &Result) const {
543 // FIXME: Unimplemented.
545 return object_error::success;
548 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
549 bool &Result) const {
550 // FIXME: Unimplemented.
552 return object_error::success;
555 error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
557 bool &Result) const {
559 getSymbolType(Symb, ST);
560 if (ST == SymbolRef::ST_External) {
562 return object_error::success;
565 uint64_t SectBegin, SectEnd;
566 getSectionAddress(Sec, SectBegin);
567 getSectionSize(Sec, SectEnd);
568 SectEnd += SectBegin;
570 if (MachOObj->is64Bit()) {
571 InMemoryStruct<macho::Symbol64TableEntry> Entry;
572 getSymbol64TableEntry(Symb, Entry);
573 uint64_t SymAddr= Entry->Value;
574 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
576 InMemoryStruct<macho::SymbolTableEntry> Entry;
577 getSymbolTableEntry(Symb, Entry);
578 uint64_t SymAddr= Entry->Value;
579 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
582 return object_error::success;
585 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
588 ret.d.b = getSectionIndex(Sec);
589 return relocation_iterator(RelocationRef(ret, this));
591 relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
593 if (is64BitLoadCommand(MachOObj, Sec)) {
594 InMemoryStruct<macho::Section64> Sect;
595 getSection64(Sec, Sect);
596 last_reloc = Sect->NumRelocationTableEntries;
598 InMemoryStruct<macho::Section> Sect;
599 getSection(Sec, Sect);
600 last_reloc = Sect->NumRelocationTableEntries;
603 ret.d.a = last_reloc;
604 ret.d.b = getSectionIndex(Sec);
605 return relocation_iterator(RelocationRef(ret, this));
608 section_iterator MachOObjectFile::begin_sections() const {
610 DRI.d.a = DRI.d.b = 0;
611 moveToNextSection(DRI);
612 return section_iterator(SectionRef(DRI, this));
615 section_iterator MachOObjectFile::end_sections() const {
617 DRI.d.a = MachOObj->getHeader().NumLoadCommands;
619 return section_iterator(SectionRef(DRI, this));
622 /*===-- Relocations -------------------------------------------------------===*/
624 void MachOObjectFile::
625 getRelocation(DataRefImpl Rel,
626 InMemoryStruct<macho::RelocationEntry> &Res) const {
628 if (MachOObj->is64Bit()) {
629 InMemoryStruct<macho::Section64> Sect;
630 getSection64(Sections[Rel.d.b], Sect);
631 relOffset = Sect->RelocationTableOffset;
633 InMemoryStruct<macho::Section> Sect;
634 getSection(Sections[Rel.d.b], Sect);
635 relOffset = Sect->RelocationTableOffset;
637 MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res);
639 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
640 RelocationRef &Res) const {
642 Res = RelocationRef(Rel, this);
643 return object_error::success;
645 error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
646 uint64_t &Res) const {
647 const uint8_t* sectAddress = 0;
648 if (MachOObj->is64Bit()) {
649 InMemoryStruct<macho::Section64> Sect;
650 getSection64(Sections[Rel.d.b], Sect);
651 sectAddress += Sect->Address;
653 InMemoryStruct<macho::Section> Sect;
654 getSection(Sections[Rel.d.b], Sect);
655 sectAddress += Sect->Address;
657 InMemoryStruct<macho::RelocationEntry> RE;
658 getRelocation(Rel, RE);
660 unsigned Arch = getArch();
661 bool isScattered = (Arch != Triple::x86_64) &&
662 (RE->Word0 & macho::RF_Scattered);
663 uint64_t RelAddr = 0;
665 RelAddr = RE->Word0 & 0xFFFFFF;
669 Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
670 return object_error::success;
672 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
673 uint64_t &Res) const {
674 InMemoryStruct<macho::RelocationEntry> RE;
675 getRelocation(Rel, RE);
677 unsigned Arch = getArch();
678 bool isScattered = (Arch != Triple::x86_64) &&
679 (RE->Word0 & macho::RF_Scattered);
681 Res = RE->Word0 & 0xFFFFFF;
684 return object_error::success;
686 error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
687 SymbolRef &Res) const {
688 InMemoryStruct<macho::RelocationEntry> RE;
689 getRelocation(Rel, RE);
690 uint32_t SymbolIdx = RE->Word1 & 0xffffff;
691 bool isExtern = (RE->Word1 >> 27) & 1;
694 Sym.d.a = Sym.d.b = 0;
695 moveToNextSymbol(Sym);
697 for (unsigned i = 0; i < SymbolIdx; i++) {
699 moveToNextSymbol(Sym);
700 assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands &&
701 "Relocation symbol index out of range!");
704 Res = SymbolRef(Sym, this);
705 return object_error::success;
707 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
708 uint64_t &Res) const {
709 InMemoryStruct<macho::RelocationEntry> RE;
710 getRelocation(Rel, RE);
714 return object_error::success;
716 error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
717 SmallVectorImpl<char> &Result) const {
718 // TODO: Support scattered relocations.
720 InMemoryStruct<macho::RelocationEntry> RE;
721 getRelocation(Rel, RE);
723 unsigned Arch = getArch();
724 bool isScattered = (Arch != Triple::x86_64) &&
725 (RE->Word0 & macho::RF_Scattered);
729 r_type = (RE->Word0 >> 24) & 0xF;
731 r_type = (RE->Word1 >> 28) & 0xF;
735 const char* Table[] = {
736 "GENERIC_RELOC_VANILLA",
737 "GENERIC_RELOC_PAIR",
738 "GENERIC_RELOC_SECTDIFF",
739 "GENERIC_RELOC_PB_LA_PTR",
740 "GENERIC_RELOC_LOCAL_SECTDIFF",
741 "GENERIC_RELOC_TLV" };
749 case Triple::x86_64: {
750 const char* Table[] = {
751 "X86_64_RELOC_UNSIGNED",
752 "X86_64_RELOC_SIGNED",
753 "X86_64_RELOC_BRANCH",
754 "X86_64_RELOC_GOT_LOAD",
756 "X86_64_RELOC_SUBTRACTOR",
757 "X86_64_RELOC_SIGNED_1",
758 "X86_64_RELOC_SIGNED_2",
759 "X86_64_RELOC_SIGNED_4",
760 "X86_64_RELOC_TLV" };
769 const char* Table[] = {
772 "ARM_RELOC_SECTDIFF",
773 "ARM_RELOC_LOCAL_SECTDIFF",
774 "ARM_RELOC_PB_LA_PTR",
776 "ARM_THUMB_RELOC_BR22",
777 "ARM_THUMB_32BIT_BRANCH",
779 "ARM_RELOC_HALF_SECTDIFF" };
788 const char* Table[] = {
797 "PPC_RELOC_SECTDIFF",
798 "PPC_RELOC_PB_LA_PTR",
799 "PPC_RELOC_HI16_SECTDIFF",
800 "PPC_RELOC_LO16_SECTDIFF",
801 "PPC_RELOC_HA16_SECTDIFF",
803 "PPC_RELOC_LO14_SECTDIFF",
804 "PPC_RELOC_LOCAL_SECTDIFF" };
809 case Triple::UnknownArch:
813 Result.append(res.begin(), res.end());
814 return object_error::success;
816 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
817 int64_t &Res) const {
818 InMemoryStruct<macho::RelocationEntry> RE;
819 getRelocation(Rel, RE);
820 bool isExtern = (RE->Word1 >> 27) & 1;
823 const uint8_t* sectAddress = base();
824 if (MachOObj->is64Bit()) {
825 InMemoryStruct<macho::Section64> Sect;
826 getSection64(Sections[Rel.d.b], Sect);
827 sectAddress += Sect->Offset;
829 InMemoryStruct<macho::Section> Sect;
830 getSection(Sections[Rel.d.b], Sect);
831 sectAddress += Sect->Offset;
833 Res = reinterpret_cast<uintptr_t>(sectAddress);
835 return object_error::success;
838 // Helper to advance a section or symbol iterator multiple increments at a time.
840 error_code advance(T &it, size_t Val) {
849 void advanceTo(T &it, size_t Val) {
850 if (error_code ec = advance(it, Val))
851 report_fatal_error(ec.message());
854 void MachOObjectFile::printRelocationTargetName(
855 InMemoryStruct<macho::RelocationEntry>& RE,
856 raw_string_ostream &fmt) const {
857 unsigned Arch = getArch();
858 bool isScattered = (Arch != Triple::x86_64) &&
859 (RE->Word0 & macho::RF_Scattered);
861 // Target of a scattered relocation is an address. In the interest of
862 // generating pretty output, scan through the symbol table looking for a
863 // symbol that aligns with that address. If we find one, print it.
864 // Otherwise, we just print the hex address of the target.
866 uint32_t Val = RE->Word1;
869 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
871 if (ec) report_fatal_error(ec.message());
876 if ((ec = SI->getAddress(Addr)))
877 report_fatal_error(ec.message());
878 if (Addr != Val) continue;
879 if ((ec = SI->getName(Name)))
880 report_fatal_error(ec.message());
885 // If we couldn't find a symbol that this relocation refers to, try
886 // to find a section beginning instead.
887 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
889 if (ec) report_fatal_error(ec.message());
894 if ((ec = SI->getAddress(Addr)))
895 report_fatal_error(ec.message());
896 if (Addr != Val) continue;
897 if ((ec = SI->getName(Name)))
898 report_fatal_error(ec.message());
903 fmt << format("0x%x", Val);
908 bool isExtern = (RE->Word1 >> 27) & 1;
909 uint32_t Val = RE->Word1 & 0xFFFFFF;
912 symbol_iterator SI = begin_symbols();
916 section_iterator SI = begin_sections();
924 error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
925 SmallVectorImpl<char> &Result) const {
926 InMemoryStruct<macho::RelocationEntry> RE;
927 getRelocation(Rel, RE);
929 unsigned Arch = getArch();
930 bool isScattered = (Arch != Triple::x86_64) &&
931 (RE->Word0 & macho::RF_Scattered);
934 raw_string_ostream fmt(fmtbuf);
938 Type = (RE->Word0 >> 24) & 0xF;
940 Type = (RE->Word1 >> 28) & 0xF;
944 isPCRel = ((RE->Word0 >> 30) & 1);
946 isPCRel = ((RE->Word1 >> 24) & 1);
948 // Determine any addends that should be displayed with the relocation.
949 // These require decoding the relocation type, which is triple-specific.
951 // X86_64 has entirely custom relocation types.
952 if (Arch == Triple::x86_64) {
953 bool isPCRel = ((RE->Word1 >> 24) & 1);
956 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
957 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
958 printRelocationTargetName(RE, fmt);
960 if (isPCRel) fmt << "PCREL";
963 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
964 InMemoryStruct<macho::RelocationEntry> RENext;
965 DataRefImpl RelNext = Rel;
967 getRelocation(RelNext, RENext);
969 // X86_64_SUBTRACTOR must be followed by a relocation of type
970 // X86_64_RELOC_UNSIGNED.
971 // NOTE: Scattered relocations don't exist on x86_64.
972 unsigned RType = (RENext->Word1 >> 28) & 0xF;
974 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
975 "X86_64_RELOC_SUBTRACTOR.");
977 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
978 // X86_64_SUBTRACTOR contains to the subtrahend.
979 printRelocationTargetName(RENext, fmt);
981 printRelocationTargetName(RE, fmt);
983 case macho::RIT_X86_64_TLV:
984 printRelocationTargetName(RE, fmt);
986 if (isPCRel) fmt << "P";
988 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
989 printRelocationTargetName(RE, fmt);
992 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
993 printRelocationTargetName(RE, fmt);
996 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
997 printRelocationTargetName(RE, fmt);
1001 printRelocationTargetName(RE, fmt);
1004 // X86 and ARM share some relocation types in common.
1005 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1006 // Generic relocation types...
1008 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1009 return object_error::success;
1010 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1011 InMemoryStruct<macho::RelocationEntry> RENext;
1012 DataRefImpl RelNext = Rel;
1014 getRelocation(RelNext, RENext);
1016 // X86 sect diff's must be followed by a relocation of type
1017 // GENERIC_RELOC_PAIR.
1018 bool isNextScattered = (Arch != Triple::x86_64) &&
1019 (RENext->Word0 & macho::RF_Scattered);
1021 if (isNextScattered)
1022 RType = (RENext->Word0 >> 24) & 0xF;
1024 RType = (RENext->Word1 >> 28) & 0xF;
1026 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1027 "GENERIC_RELOC_SECTDIFF.");
1029 printRelocationTargetName(RE, fmt);
1031 printRelocationTargetName(RENext, fmt);
1036 if (Arch == Triple::x86) {
1037 // All X86 relocations that need special printing were already
1038 // handled in the generic code.
1040 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1041 InMemoryStruct<macho::RelocationEntry> RENext;
1042 DataRefImpl RelNext = Rel;
1044 getRelocation(RelNext, RENext);
1046 // X86 sect diff's must be followed by a relocation of type
1047 // GENERIC_RELOC_PAIR.
1048 bool isNextScattered = (Arch != Triple::x86_64) &&
1049 (RENext->Word0 & macho::RF_Scattered);
1051 if (isNextScattered)
1052 RType = (RENext->Word0 >> 24) & 0xF;
1054 RType = (RENext->Word1 >> 28) & 0xF;
1056 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1057 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1059 printRelocationTargetName(RE, fmt);
1061 printRelocationTargetName(RENext, fmt);
1064 case macho::RIT_Generic_TLV: {
1065 printRelocationTargetName(RE, fmt);
1067 if (isPCRel) fmt << "P";
1071 printRelocationTargetName(RE, fmt);
1073 } else { // ARM-specific relocations
1075 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1076 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1077 // Half relocations steal a bit from the length field to encode
1078 // whether this is an upper16 or a lower16 relocation.
1081 isUpper = (RE->Word0 >> 28) & 1;
1083 isUpper = (RE->Word1 >> 25) & 1;
1086 fmt << ":upper16:(";
1088 fmt << ":lower16:(";
1089 printRelocationTargetName(RE, fmt);
1091 InMemoryStruct<macho::RelocationEntry> RENext;
1092 DataRefImpl RelNext = Rel;
1094 getRelocation(RelNext, RENext);
1096 // ARM half relocs must be followed by a relocation of type
1098 bool isNextScattered = (Arch != Triple::x86_64) &&
1099 (RENext->Word0 & macho::RF_Scattered);
1101 if (isNextScattered)
1102 RType = (RENext->Word0 >> 24) & 0xF;
1104 RType = (RENext->Word1 >> 28) & 0xF;
1107 report_fatal_error("Expected ARM_RELOC_PAIR after "
1108 "GENERIC_RELOC_HALF");
1110 // NOTE: The half of the target virtual address is stashed in the
1111 // address field of the secondary relocation, but we can't reverse
1112 // engineer the constant offset from it without decoding the movw/movt
1113 // instruction to find the other half in its immediate field.
1115 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1116 // symbol/section pointer of the follow-on relocation.
1117 if (Type == macho::RIT_ARM_HalfDifference) {
1119 printRelocationTargetName(RENext, fmt);
1126 printRelocationTargetName(RE, fmt);
1131 printRelocationTargetName(RE, fmt);
1134 Result.append(fmtbuf.begin(), fmtbuf.end());
1135 return object_error::success;
1138 error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1139 bool &Result) const {
1140 InMemoryStruct<macho::RelocationEntry> RE;
1141 getRelocation(Rel, RE);
1143 unsigned Arch = getArch();
1144 bool isScattered = (Arch != Triple::x86_64) &&
1145 (RE->Word0 & macho::RF_Scattered);
1148 Type = (RE->Word0 >> 24) & 0xF;
1150 Type = (RE->Word1 >> 28) & 0xF;
1154 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1155 // is always hidden.
1156 if (Arch == Triple::x86 || Arch == Triple::arm) {
1157 if (Type == macho::RIT_Pair) Result = true;
1158 } else if (Arch == Triple::x86_64) {
1159 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1160 // an X864_64_RELOC_SUBTRACTOR.
1161 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1162 DataRefImpl RelPrev = Rel;
1164 InMemoryStruct<macho::RelocationEntry> REPrev;
1165 getRelocation(RelPrev, REPrev);
1167 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
1169 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
1173 return object_error::success;
1176 /*===-- Miscellaneous -----------------------------------------------------===*/
1178 uint8_t MachOObjectFile::getBytesInAddress() const {
1179 return MachOObj->is64Bit() ? 8 : 4;
1182 StringRef MachOObjectFile::getFileFormatName() const {
1183 if (!MachOObj->is64Bit()) {
1184 switch (MachOObj->getHeader().CPUType) {
1185 case llvm::MachO::CPUTypeI386:
1186 return "Mach-O 32-bit i386";
1187 case llvm::MachO::CPUTypeARM:
1188 return "Mach-O arm";
1189 case llvm::MachO::CPUTypePowerPC:
1190 return "Mach-O 32-bit ppc";
1192 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
1193 "64-bit object file when we're not 64-bit?");
1194 return "Mach-O 32-bit unknown";
1198 switch (MachOObj->getHeader().CPUType) {
1199 case llvm::MachO::CPUTypeX86_64:
1200 return "Mach-O 64-bit x86-64";
1201 case llvm::MachO::CPUTypePowerPC64:
1202 return "Mach-O 64-bit ppc64";
1204 assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 &&
1205 "32-bit object file when we're 64-bit?");
1206 return "Mach-O 64-bit unknown";
1210 unsigned MachOObjectFile::getArch() const {
1211 switch (MachOObj->getHeader().CPUType) {
1212 case llvm::MachO::CPUTypeI386:
1214 case llvm::MachO::CPUTypeX86_64:
1215 return Triple::x86_64;
1216 case llvm::MachO::CPUTypeARM:
1218 case llvm::MachO::CPUTypePowerPC:
1220 case llvm::MachO::CPUTypePowerPC64:
1221 return Triple::ppc64;
1223 return Triple::UnknownArch;
1227 } // end namespace object
1228 } // end namespace llvm