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/Casting.h"
19 #include "llvm/Support/DataExtractor.h"
20 #include "llvm/Support/Format.h"
21 #include "llvm/Support/MemoryBuffer.h"
27 using namespace object;
32 MachOObjectFileBase::MachOObjectFileBase(MemoryBuffer *Object, bool Is64bits,
34 : ObjectFile(getMachOType(true, Is64bits), Object) {
37 bool MachOObjectFileBase::is64Bit() const {
38 return isa<MachOObjectFile<true> >(this);
41 const MachOObjectFileBase::LoadCommand *
42 MachOObjectFileBase::getLoadCommandInfo(unsigned Index) const {
44 uint64_t NewOffset = getHeaderSize();
45 const LoadCommand *Load;
49 StringRef Data = getData(Offset, sizeof(LoadCommand));
50 Load = reinterpret_cast<const LoadCommand*>(Data.data());
51 NewOffset = Offset + Load->Size;
53 } while (I != Index + 1);
58 void MachOObjectFileBase::ReadULEB128s(uint64_t Index,
59 SmallVectorImpl<uint64_t> &Out) const {
60 DataExtractor extractor(ObjectFile::getData(), true, 0);
62 uint32_t offset = Index;
64 while (uint64_t delta = extractor.getULEB128(&offset)) {
70 const MachOObjectFileBase::Header *MachOObjectFileBase::getHeader() const {
71 StringRef Data = getData(0, sizeof(Header));
72 return reinterpret_cast<const Header*>(Data.data());
75 unsigned MachOObjectFileBase::getHeaderSize() const {
76 return is64Bit() ? macho::Header64Size : macho::Header32Size;
79 StringRef MachOObjectFileBase::getData(size_t Offset, size_t Size) const {
80 return ObjectFile::getData().substr(Offset, Size);
83 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
84 StringRef Magic = Buffer->getBuffer().slice(0, 4);
86 bool Is64Bits = Magic == "\xFE\xED\xFA\xCF" || Magic == "\xCF\xFA\xED\xFE";
89 Ret = new MachOObjectFile<true>(Buffer, ec);
91 Ret = new MachOObjectFile<false>(Buffer, ec);
97 /*===-- Symbols -----------------------------------------------------------===*/
99 void MachOObjectFileBase::moveToNextSymbol(DataRefImpl &DRI) const {
100 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
101 while (DRI.d.a < LoadCommandCount) {
102 const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
103 if (Command->Type == macho::LCT_Symtab) {
104 const SymtabLoadCommand *SymtabLoadCmd =
105 reinterpret_cast<const SymtabLoadCommand*>(Command);
106 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
115 const MachOObjectFileBase::SymbolTableEntryBase *
116 MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI) const {
117 const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
118 const SymtabLoadCommand *SymtabLoadCmd =
119 reinterpret_cast<const SymtabLoadCommand*>(Command);
120 return getSymbolTableEntryBase(DRI, SymtabLoadCmd);
123 const MachOObjectFileBase::SymbolTableEntryBase *
124 MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI,
125 const SymtabLoadCommand *SymtabLoadCmd) const {
126 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
127 unsigned Index = DRI.d.b;
129 unsigned SymbolTableEntrySize = is64Bit() ?
130 sizeof(MachOFormat::SymbolTableEntry<true>) :
131 sizeof(MachOFormat::SymbolTableEntry<false>);
133 uint64_t Offset = SymbolTableOffset + Index * SymbolTableEntrySize;
134 StringRef Data = getData(Offset, SymbolTableEntrySize);
135 return reinterpret_cast<const SymbolTableEntryBase*>(Data.data());
138 error_code MachOObjectFileBase::getSymbolNext(DataRefImpl DRI,
139 SymbolRef &Result) const {
141 moveToNextSymbol(DRI);
142 Result = SymbolRef(DRI, this);
143 return object_error::success;
146 error_code MachOObjectFileBase::getSymbolName(DataRefImpl DRI,
147 StringRef &Result) const {
148 const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
149 const SymtabLoadCommand *SymtabLoadCmd =
150 reinterpret_cast<const SymtabLoadCommand*>(Command);
152 StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset,
153 SymtabLoadCmd->StringTableSize);
155 const SymbolTableEntryBase *Entry =
156 getSymbolTableEntryBase(DRI, SymtabLoadCmd);
157 uint32_t StringIndex = Entry->StringIndex;
159 const char *Start = &StringTable.data()[StringIndex];
160 Result = StringRef(Start);
162 return object_error::success;
165 error_code MachOObjectFileBase::getSymbolNMTypeChar(DataRefImpl DRI,
166 char &Result) const {
167 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI);
168 uint8_t Type = Entry->Type;
169 uint16_t Flags = Entry->Flags;
172 switch (Type & macho::STF_TypeMask) {
173 case macho::STT_Undefined:
176 case macho::STT_Absolute:
177 case macho::STT_Section:
185 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
186 Char = toupper(static_cast<unsigned char>(Char));
188 return object_error::success;
191 error_code MachOObjectFileBase::getSymbolFlags(DataRefImpl DRI,
192 uint32_t &Result) const {
193 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI);
194 uint8_t MachOType = Entry->Type;
195 uint16_t MachOFlags = Entry->Flags;
197 // TODO: Correctly set SF_ThreadLocal
198 Result = SymbolRef::SF_None;
200 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
201 Result |= SymbolRef::SF_Undefined;
203 if (MachOFlags & macho::STF_StabsEntryMask)
204 Result |= SymbolRef::SF_FormatSpecific;
206 if (MachOType & MachO::NlistMaskExternal) {
207 Result |= SymbolRef::SF_Global;
208 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
209 Result |= SymbolRef::SF_Common;
212 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
213 Result |= SymbolRef::SF_Weak;
215 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
216 Result |= SymbolRef::SF_Absolute;
218 return object_error::success;
221 error_code MachOObjectFileBase::getSymbolSection(DataRefImpl Symb,
222 section_iterator &Res) const {
223 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
224 uint8_t index = Entry->SectionIndex;
227 Res = end_sections();
229 Res = section_iterator(SectionRef(Sections[index-1], this));
231 return object_error::success;
234 error_code MachOObjectFileBase::getSymbolType(DataRefImpl Symb,
235 SymbolRef::Type &Res) const {
236 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
237 uint8_t n_type = Entry->Type;
239 Res = SymbolRef::ST_Other;
241 // If this is a STAB debugging symbol, we can do nothing more.
242 if (n_type & MachO::NlistMaskStab) {
243 Res = SymbolRef::ST_Debug;
244 return object_error::success;
247 switch (n_type & MachO::NlistMaskType) {
248 case MachO::NListTypeUndefined :
249 Res = SymbolRef::ST_Unknown;
251 case MachO::NListTypeSection :
252 Res = SymbolRef::ST_Function;
255 return object_error::success;
258 error_code MachOObjectFileBase::getSymbolValue(DataRefImpl Symb,
259 uint64_t &Val) const {
260 report_fatal_error("getSymbolValue unimplemented in MachOObjectFileBase");
263 symbol_iterator MachOObjectFileBase::begin_symbols() const {
264 // DRI.d.a = segment number; DRI.d.b = symbol index.
266 moveToNextSymbol(DRI);
267 return symbol_iterator(SymbolRef(DRI, this));
270 symbol_iterator MachOObjectFileBase::end_symbols() const {
272 DRI.d.a = getHeader()->NumLoadCommands;
273 return symbol_iterator(SymbolRef(DRI, this));
276 symbol_iterator MachOObjectFileBase::begin_dynamic_symbols() const {
278 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase");
281 symbol_iterator MachOObjectFileBase::end_dynamic_symbols() const {
283 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase");
286 library_iterator MachOObjectFileBase::begin_libraries_needed() const {
288 report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
291 library_iterator MachOObjectFileBase::end_libraries_needed() const {
293 report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
296 StringRef MachOObjectFileBase::getLoadName() const {
298 report_fatal_error("get_load_name() unimplemented in MachOObjectFileBase");
301 /*===-- Sections ----------------------------------------------------------===*/
303 std::size_t MachOObjectFileBase::getSectionIndex(DataRefImpl Sec) const {
304 SectionList::const_iterator loc =
305 std::find(Sections.begin(), Sections.end(), Sec);
306 assert(loc != Sections.end() && "Sec is not a valid section!");
307 return std::distance(Sections.begin(), loc);
310 const MachOObjectFileBase::SectionBase*
311 MachOObjectFileBase::getSectionBase(DataRefImpl DRI) const {
312 const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
313 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
315 bool Is64 = is64Bit();
316 unsigned SegmentLoadSize =
317 Is64 ? sizeof(MachOFormat::SegmentLoadCommand<true>) :
318 sizeof(MachOFormat::SegmentLoadCommand<false>);
319 unsigned SectionSize = Is64 ? sizeof(MachOFormat::Section<true>) :
320 sizeof(MachOFormat::Section<false>);
322 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize;
323 return reinterpret_cast<const SectionBase*>(SectionAddr);
326 static StringRef parseSegmentOrSectionName(const char *P) {
330 // Not null terminated, so this is a 16 char string.
331 return StringRef(P, 16);
334 ArrayRef<char> MachOObjectFileBase::getSectionRawName(DataRefImpl DRI) const {
335 const SectionBase *Base = getSectionBase(DRI);
336 return ArrayRef<char>(Base->Name);
339 error_code MachOObjectFileBase::getSectionName(DataRefImpl DRI,
340 StringRef &Result) const {
341 ArrayRef<char> Raw = getSectionRawName(DRI);
342 Result = parseSegmentOrSectionName(Raw.data());
343 return object_error::success;
347 MachOObjectFileBase::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
348 const SectionBase *Base = getSectionBase(Sec);
349 return ArrayRef<char>(Base->SegmentName);
353 MachOObjectFileBase::getSectionFinalSegmentName(DataRefImpl DRI) const {
354 ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
355 return parseSegmentOrSectionName(Raw.data());
358 error_code MachOObjectFileBase::isSectionData(DataRefImpl DRI,
359 bool &Result) const {
360 // FIXME: Unimplemented.
362 return object_error::success;
365 error_code MachOObjectFileBase::isSectionBSS(DataRefImpl DRI,
366 bool &Result) const {
367 // FIXME: Unimplemented.
369 return object_error::success;
373 MachOObjectFileBase::isSectionRequiredForExecution(DataRefImpl Sec,
374 bool &Result) const {
375 // FIXME: Unimplemented.
377 return object_error::success;
380 error_code MachOObjectFileBase::isSectionVirtual(DataRefImpl Sec,
381 bool &Result) const {
382 // FIXME: Unimplemented.
384 return object_error::success;
387 error_code MachOObjectFileBase::isSectionReadOnlyData(DataRefImpl Sec,
388 bool &Result) const {
389 // Consider using the code from isSectionText to look for __const sections.
390 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
391 // to use section attributes to distinguish code from data.
393 // FIXME: Unimplemented.
395 return object_error::success;
398 relocation_iterator MachOObjectFileBase::getSectionRelBegin(DataRefImpl Sec) const {
400 ret.d.b = getSectionIndex(Sec);
401 return relocation_iterator(RelocationRef(ret, this));
404 section_iterator MachOObjectFileBase::end_sections() const {
406 DRI.d.a = getHeader()->NumLoadCommands;
407 return section_iterator(SectionRef(DRI, this));
410 /*===-- Relocations -------------------------------------------------------===*/
412 error_code MachOObjectFileBase::getRelocationNext(DataRefImpl Rel,
413 RelocationRef &Res) const {
415 Res = RelocationRef(Rel, this);
416 return object_error::success;
419 // Helper to advance a section or symbol iterator multiple increments at a time.
421 error_code advance(T &it, size_t Val) {
430 void advanceTo(T &it, size_t Val) {
431 if (error_code ec = advance(it, Val))
432 report_fatal_error(ec.message());
436 MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE,
437 raw_string_ostream &fmt) const {
438 unsigned Arch = getArch();
439 bool isScattered = (Arch != Triple::x86_64) &&
440 (RE->Word0 & macho::RF_Scattered);
442 // Target of a scattered relocation is an address. In the interest of
443 // generating pretty output, scan through the symbol table looking for a
444 // symbol that aligns with that address. If we find one, print it.
445 // Otherwise, we just print the hex address of the target.
447 uint32_t Val = RE->Word1;
450 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
452 if (ec) report_fatal_error(ec.message());
457 if ((ec = SI->getAddress(Addr)))
458 report_fatal_error(ec.message());
459 if (Addr != Val) continue;
460 if ((ec = SI->getName(Name)))
461 report_fatal_error(ec.message());
466 // If we couldn't find a symbol that this relocation refers to, try
467 // to find a section beginning instead.
468 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
470 if (ec) report_fatal_error(ec.message());
475 if ((ec = SI->getAddress(Addr)))
476 report_fatal_error(ec.message());
477 if (Addr != Val) continue;
478 if ((ec = SI->getName(Name)))
479 report_fatal_error(ec.message());
484 fmt << format("0x%x", Val);
489 bool isExtern = (RE->Word1 >> 27) & 1;
490 uint32_t Val = RE->Word1 & 0xFFFFFF;
493 symbol_iterator SI = begin_symbols();
497 section_iterator SI = begin_sections();
505 error_code MachOObjectFileBase::getLibraryNext(DataRefImpl LibData,
506 LibraryRef &Res) const {
507 report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
510 error_code MachOObjectFileBase::getLibraryPath(DataRefImpl LibData,
511 StringRef &Res) const {
512 report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
516 /*===-- Miscellaneous -----------------------------------------------------===*/
518 uint8_t MachOObjectFileBase::getBytesInAddress() const {
519 return is64Bit() ? 8 : 4;
522 StringRef MachOObjectFileBase::getFileFormatName() const {
524 switch (getHeader()->CPUType) {
525 case llvm::MachO::CPUTypeI386:
526 return "Mach-O 32-bit i386";
527 case llvm::MachO::CPUTypeARM:
529 case llvm::MachO::CPUTypePowerPC:
530 return "Mach-O 32-bit ppc";
532 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) == 0 &&
533 "64-bit object file when we're not 64-bit?");
534 return "Mach-O 32-bit unknown";
538 // Make sure the cpu type has the correct mask.
539 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64)
540 == llvm::MachO::CPUArchABI64 &&
541 "32-bit object file when we're 64-bit?");
543 switch (getHeader()->CPUType) {
544 case llvm::MachO::CPUTypeX86_64:
545 return "Mach-O 64-bit x86-64";
546 case llvm::MachO::CPUTypePowerPC64:
547 return "Mach-O 64-bit ppc64";
549 return "Mach-O 64-bit unknown";
553 unsigned MachOObjectFileBase::getArch() const {
554 switch (getHeader()->CPUType) {
555 case llvm::MachO::CPUTypeI386:
557 case llvm::MachO::CPUTypeX86_64:
558 return Triple::x86_64;
559 case llvm::MachO::CPUTypeARM:
561 case llvm::MachO::CPUTypePowerPC:
563 case llvm::MachO::CPUTypePowerPC64:
564 return Triple::ppc64;
566 return Triple::UnknownArch;
570 } // end namespace object
571 } // end namespace llvm