LLVM API Documentation
00001 //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the MachOObjectFile class, which binds the MachOObject 00011 // class to the generic ObjectFile wrapper. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "llvm/Object/MachO.h" 00016 #include "llvm/ADT/Triple.h" 00017 #include "llvm/Object/MachOFormat.h" 00018 #include "llvm/Support/DataExtractor.h" 00019 #include "llvm/Support/Format.h" 00020 #include "llvm/Support/Host.h" 00021 #include "llvm/Support/MemoryBuffer.h" 00022 #include <cctype> 00023 #include <cstring> 00024 #include <limits> 00025 00026 using namespace llvm; 00027 using namespace object; 00028 00029 namespace llvm { 00030 namespace object { 00031 00032 struct SymbolTableEntryBase { 00033 uint32_t StringIndex; 00034 uint8_t Type; 00035 uint8_t SectionIndex; 00036 uint16_t Flags; 00037 }; 00038 00039 struct SectionBase { 00040 char Name[16]; 00041 char SegmentName[16]; 00042 }; 00043 00044 template<typename T> 00045 static void SwapValue(T &Value) { 00046 Value = sys::SwapByteOrder(Value); 00047 } 00048 00049 template<typename T> 00050 static void SwapStruct(T &Value); 00051 00052 template<> 00053 void SwapStruct(macho::RelocationEntry &H) { 00054 SwapValue(H.Word0); 00055 SwapValue(H.Word1); 00056 } 00057 00058 template<> 00059 void SwapStruct(macho::LoadCommand &L) { 00060 SwapValue(L.Type); 00061 SwapValue(L.Size); 00062 } 00063 00064 template<> 00065 void SwapStruct(SymbolTableEntryBase &S) { 00066 SwapValue(S.StringIndex); 00067 SwapValue(S.Flags); 00068 } 00069 00070 template<> 00071 void SwapStruct(macho::Section &S) { 00072 SwapValue(S.Address); 00073 SwapValue(S.Size); 00074 SwapValue(S.Offset); 00075 SwapValue(S.Align); 00076 SwapValue(S.RelocationTableOffset); 00077 SwapValue(S.NumRelocationTableEntries); 00078 SwapValue(S.Flags); 00079 SwapValue(S.Reserved1); 00080 SwapValue(S.Reserved2); 00081 } 00082 00083 template<> 00084 void SwapStruct(macho::Section64 &S) { 00085 SwapValue(S.Address); 00086 SwapValue(S.Size); 00087 SwapValue(S.Offset); 00088 SwapValue(S.Align); 00089 SwapValue(S.RelocationTableOffset); 00090 SwapValue(S.NumRelocationTableEntries); 00091 SwapValue(S.Flags); 00092 SwapValue(S.Reserved1); 00093 SwapValue(S.Reserved2); 00094 SwapValue(S.Reserved3); 00095 } 00096 00097 template<> 00098 void SwapStruct(macho::SymbolTableEntry &S) { 00099 SwapValue(S.StringIndex); 00100 SwapValue(S.Flags); 00101 SwapValue(S.Value); 00102 } 00103 00104 template<> 00105 void SwapStruct(macho::Symbol64TableEntry &S) { 00106 SwapValue(S.StringIndex); 00107 SwapValue(S.Flags); 00108 SwapValue(S.Value); 00109 } 00110 00111 template<> 00112 void SwapStruct(macho::Header &H) { 00113 SwapValue(H.Magic); 00114 SwapValue(H.CPUType); 00115 SwapValue(H.CPUSubtype); 00116 SwapValue(H.FileType); 00117 SwapValue(H.NumLoadCommands); 00118 SwapValue(H.SizeOfLoadCommands); 00119 SwapValue(H.Flags); 00120 } 00121 00122 template<> 00123 void SwapStruct(macho::Header64Ext &E) { 00124 SwapValue(E.Reserved); 00125 } 00126 00127 template<> 00128 void SwapStruct(macho::SymtabLoadCommand &C) { 00129 SwapValue(C.Type); 00130 SwapValue(C.Size); 00131 SwapValue(C.SymbolTableOffset); 00132 SwapValue(C.NumSymbolTableEntries); 00133 SwapValue(C.StringTableOffset); 00134 SwapValue(C.StringTableSize); 00135 } 00136 00137 template<> 00138 void SwapStruct(macho::DysymtabLoadCommand &C) { 00139 SwapValue(C.Type); 00140 SwapValue(C.Size); 00141 SwapValue(C.LocalSymbolsIndex); 00142 SwapValue(C.NumLocalSymbols); 00143 SwapValue(C.ExternalSymbolsIndex); 00144 SwapValue(C.NumExternalSymbols); 00145 SwapValue(C.UndefinedSymbolsIndex); 00146 SwapValue(C.NumUndefinedSymbols); 00147 SwapValue(C.TOCOffset); 00148 SwapValue(C.NumTOCEntries); 00149 SwapValue(C.ModuleTableOffset); 00150 SwapValue(C.NumModuleTableEntries); 00151 SwapValue(C.ReferenceSymbolTableOffset); 00152 SwapValue(C.NumReferencedSymbolTableEntries); 00153 SwapValue(C.IndirectSymbolTableOffset); 00154 SwapValue(C.NumIndirectSymbolTableEntries); 00155 SwapValue(C.ExternalRelocationTableOffset); 00156 SwapValue(C.NumExternalRelocationTableEntries); 00157 SwapValue(C.LocalRelocationTableOffset); 00158 SwapValue(C.NumLocalRelocationTableEntries); 00159 } 00160 00161 template<> 00162 void SwapStruct(macho::LinkeditDataLoadCommand &C) { 00163 SwapValue(C.Type); 00164 SwapValue(C.Size); 00165 SwapValue(C.DataOffset); 00166 SwapValue(C.DataSize); 00167 } 00168 00169 template<> 00170 void SwapStruct(macho::SegmentLoadCommand &C) { 00171 SwapValue(C.Type); 00172 SwapValue(C.Size); 00173 SwapValue(C.VMAddress); 00174 SwapValue(C.VMSize); 00175 SwapValue(C.FileOffset); 00176 SwapValue(C.FileSize); 00177 SwapValue(C.MaxVMProtection); 00178 SwapValue(C.InitialVMProtection); 00179 SwapValue(C.NumSections); 00180 SwapValue(C.Flags); 00181 } 00182 00183 template<> 00184 void SwapStruct(macho::Segment64LoadCommand &C) { 00185 SwapValue(C.Type); 00186 SwapValue(C.Size); 00187 SwapValue(C.VMAddress); 00188 SwapValue(C.VMSize); 00189 SwapValue(C.FileOffset); 00190 SwapValue(C.FileSize); 00191 SwapValue(C.MaxVMProtection); 00192 SwapValue(C.InitialVMProtection); 00193 SwapValue(C.NumSections); 00194 SwapValue(C.Flags); 00195 } 00196 00197 template<> 00198 void SwapStruct(macho::IndirectSymbolTableEntry &C) { 00199 SwapValue(C.Index); 00200 } 00201 00202 template<> 00203 void SwapStruct(macho::LinkerOptionsLoadCommand &C) { 00204 SwapValue(C.Type); 00205 SwapValue(C.Size); 00206 SwapValue(C.Count); 00207 } 00208 00209 template<> 00210 void SwapStruct(macho::DataInCodeTableEntry &C) { 00211 SwapValue(C.Offset); 00212 SwapValue(C.Length); 00213 SwapValue(C.Kind); 00214 } 00215 00216 template<typename T> 00217 T getStruct(const MachOObjectFile *O, const char *P) { 00218 T Cmd; 00219 memcpy(&Cmd, P, sizeof(T)); 00220 if (O->isLittleEndian() != sys::IsLittleEndianHost) 00221 SwapStruct(Cmd); 00222 return Cmd; 00223 } 00224 00225 static uint32_t 00226 getSegmentLoadCommandNumSections(const MachOObjectFile *O, 00227 const MachOObjectFile::LoadCommandInfo &L) { 00228 if (O->is64Bit()) { 00229 macho::Segment64LoadCommand S = O->getSegment64LoadCommand(L); 00230 return S.NumSections; 00231 } 00232 macho::SegmentLoadCommand S = O->getSegmentLoadCommand(L); 00233 return S.NumSections; 00234 } 00235 00236 static const char * 00237 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L, 00238 unsigned Sec) { 00239 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr); 00240 00241 bool Is64 = O->is64Bit(); 00242 unsigned SegmentLoadSize = Is64 ? sizeof(macho::Segment64LoadCommand) : 00243 sizeof(macho::SegmentLoadCommand); 00244 unsigned SectionSize = Is64 ? sizeof(macho::Section64) : 00245 sizeof(macho::Section); 00246 00247 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize; 00248 return reinterpret_cast<const char*>(SectionAddr); 00249 } 00250 00251 static const char *getPtr(const MachOObjectFile *O, size_t Offset) { 00252 return O->getData().substr(Offset, 1).data(); 00253 } 00254 00255 static SymbolTableEntryBase 00256 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) { 00257 const char *P = reinterpret_cast<const char *>(DRI.p); 00258 return getStruct<SymbolTableEntryBase>(O, P); 00259 } 00260 00261 static StringRef parseSegmentOrSectionName(const char *P) { 00262 if (P[15] == 0) 00263 // Null terminated. 00264 return P; 00265 // Not null terminated, so this is a 16 char string. 00266 return StringRef(P, 16); 00267 } 00268 00269 // Helper to advance a section or symbol iterator multiple increments at a time. 00270 template<class T> 00271 static error_code advance(T &it, size_t Val) { 00272 error_code ec; 00273 while (Val--) { 00274 it.increment(ec); 00275 } 00276 return ec; 00277 } 00278 00279 template<class T> 00280 static void advanceTo(T &it, size_t Val) { 00281 if (error_code ec = advance(it, Val)) 00282 report_fatal_error(ec.message()); 00283 } 00284 00285 static unsigned getCPUType(const MachOObjectFile *O) { 00286 return O->getHeader().CPUType; 00287 } 00288 00289 static void printRelocationTargetName(const MachOObjectFile *O, 00290 const macho::RelocationEntry &RE, 00291 raw_string_ostream &fmt) { 00292 bool IsScattered = O->isRelocationScattered(RE); 00293 00294 // Target of a scattered relocation is an address. In the interest of 00295 // generating pretty output, scan through the symbol table looking for a 00296 // symbol that aligns with that address. If we find one, print it. 00297 // Otherwise, we just print the hex address of the target. 00298 if (IsScattered) { 00299 uint32_t Val = O->getPlainRelocationSymbolNum(RE); 00300 00301 error_code ec; 00302 for (symbol_iterator SI = O->begin_symbols(), SE = O->end_symbols(); 00303 SI != SE; SI.increment(ec)) { 00304 if (ec) report_fatal_error(ec.message()); 00305 00306 uint64_t Addr; 00307 StringRef Name; 00308 00309 if ((ec = SI->getAddress(Addr))) 00310 report_fatal_error(ec.message()); 00311 if (Addr != Val) continue; 00312 if ((ec = SI->getName(Name))) 00313 report_fatal_error(ec.message()); 00314 fmt << Name; 00315 return; 00316 } 00317 00318 // If we couldn't find a symbol that this relocation refers to, try 00319 // to find a section beginning instead. 00320 for (section_iterator SI = O->begin_sections(), SE = O->end_sections(); 00321 SI != SE; SI.increment(ec)) { 00322 if (ec) report_fatal_error(ec.message()); 00323 00324 uint64_t Addr; 00325 StringRef Name; 00326 00327 if ((ec = SI->getAddress(Addr))) 00328 report_fatal_error(ec.message()); 00329 if (Addr != Val) continue; 00330 if ((ec = SI->getName(Name))) 00331 report_fatal_error(ec.message()); 00332 fmt << Name; 00333 return; 00334 } 00335 00336 fmt << format("0x%x", Val); 00337 return; 00338 } 00339 00340 StringRef S; 00341 bool isExtern = O->getPlainRelocationExternal(RE); 00342 uint64_t Val = O->getPlainRelocationSymbolNum(RE); 00343 00344 if (isExtern) { 00345 symbol_iterator SI = O->begin_symbols(); 00346 advanceTo(SI, Val); 00347 SI->getName(S); 00348 } else { 00349 section_iterator SI = O->begin_sections(); 00350 // Adjust for the fact that sections are 1-indexed. 00351 advanceTo(SI, Val - 1); 00352 SI->getName(S); 00353 } 00354 00355 fmt << S; 00356 } 00357 00358 static uint32_t getPlainRelocationAddress(const macho::RelocationEntry &RE) { 00359 return RE.Word0; 00360 } 00361 00362 static unsigned 00363 getScatteredRelocationAddress(const macho::RelocationEntry &RE) { 00364 return RE.Word0 & 0xffffff; 00365 } 00366 00367 static bool getPlainRelocationPCRel(const MachOObjectFile *O, 00368 const macho::RelocationEntry &RE) { 00369 if (O->isLittleEndian()) 00370 return (RE.Word1 >> 24) & 1; 00371 return (RE.Word1 >> 7) & 1; 00372 } 00373 00374 static bool 00375 getScatteredRelocationPCRel(const MachOObjectFile *O, 00376 const macho::RelocationEntry &RE) { 00377 return (RE.Word0 >> 30) & 1; 00378 } 00379 00380 static unsigned getPlainRelocationLength(const MachOObjectFile *O, 00381 const macho::RelocationEntry &RE) { 00382 if (O->isLittleEndian()) 00383 return (RE.Word1 >> 25) & 3; 00384 return (RE.Word1 >> 5) & 3; 00385 } 00386 00387 static unsigned 00388 getScatteredRelocationLength(const macho::RelocationEntry &RE) { 00389 return (RE.Word0 >> 28) & 3; 00390 } 00391 00392 static unsigned getPlainRelocationType(const MachOObjectFile *O, 00393 const macho::RelocationEntry &RE) { 00394 if (O->isLittleEndian()) 00395 return RE.Word1 >> 28; 00396 return RE.Word1 & 0xf; 00397 } 00398 00399 static unsigned getScatteredRelocationType(const macho::RelocationEntry &RE) { 00400 return (RE.Word0 >> 24) & 0xf; 00401 } 00402 00403 static uint32_t getSectionFlags(const MachOObjectFile *O, 00404 DataRefImpl Sec) { 00405 if (O->is64Bit()) { 00406 macho::Section64 Sect = O->getSection64(Sec); 00407 return Sect.Flags; 00408 } 00409 macho::Section Sect = O->getSection(Sec); 00410 return Sect.Flags; 00411 } 00412 00413 MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, 00414 bool IsLittleEndian, bool Is64bits, 00415 error_code &ec) 00416 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), 00417 SymtabLoadCmd(NULL), DysymtabLoadCmd(NULL), DataInCodeLoadCmd(NULL) { 00418 uint32_t LoadCommandCount = this->getHeader().NumLoadCommands; 00419 macho::LoadCommandType SegmentLoadType = is64Bit() ? 00420 macho::LCT_Segment64 : macho::LCT_Segment; 00421 00422 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo(); 00423 for (unsigned I = 0; ; ++I) { 00424 if (Load.C.Type == macho::LCT_Symtab) { 00425 assert(!SymtabLoadCmd && "Multiple symbol tables"); 00426 SymtabLoadCmd = Load.Ptr; 00427 } else if (Load.C.Type == macho::LCT_Dysymtab) { 00428 assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables"); 00429 DysymtabLoadCmd = Load.Ptr; 00430 } else if (Load.C.Type == macho::LCT_DataInCode) { 00431 assert(!DataInCodeLoadCmd && "Multiple data in code tables"); 00432 DataInCodeLoadCmd = Load.Ptr; 00433 } else if (Load.C.Type == SegmentLoadType) { 00434 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load); 00435 for (unsigned J = 0; J < NumSections; ++J) { 00436 const char *Sec = getSectionPtr(this, Load, J); 00437 Sections.push_back(Sec); 00438 } 00439 } 00440 00441 if (I == LoadCommandCount - 1) 00442 break; 00443 else 00444 Load = getNextLoadCommandInfo(Load); 00445 } 00446 } 00447 00448 error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb, 00449 SymbolRef &Res) const { 00450 unsigned SymbolTableEntrySize = is64Bit() ? 00451 sizeof(macho::Symbol64TableEntry) : 00452 sizeof(macho::SymbolTableEntry); 00453 Symb.p += SymbolTableEntrySize; 00454 Res = SymbolRef(Symb, this); 00455 return object_error::success; 00456 } 00457 00458 error_code MachOObjectFile::getSymbolName(DataRefImpl Symb, 00459 StringRef &Res) const { 00460 StringRef StringTable = getStringTableData(); 00461 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb); 00462 const char *Start = &StringTable.data()[Entry.StringIndex]; 00463 Res = StringRef(Start); 00464 return object_error::success; 00465 } 00466 00467 error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, 00468 uint64_t &Res) const { 00469 if (is64Bit()) { 00470 macho::Symbol64TableEntry Entry = getSymbol64TableEntry(Symb); 00471 Res = Entry.Value; 00472 } else { 00473 macho::SymbolTableEntry Entry = getSymbolTableEntry(Symb); 00474 Res = Entry.Value; 00475 } 00476 return object_error::success; 00477 } 00478 00479 error_code 00480 MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb, 00481 uint64_t &Res) const { 00482 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb); 00483 getSymbolAddress(Symb, Res); 00484 if (Entry.SectionIndex) { 00485 uint64_t Delta; 00486 DataRefImpl SecRel; 00487 SecRel.d.a = Entry.SectionIndex-1; 00488 if (is64Bit()) { 00489 macho::Section64 Sec = getSection64(SecRel); 00490 Delta = Sec.Offset - Sec.Address; 00491 } else { 00492 macho::Section Sec = getSection(SecRel); 00493 Delta = Sec.Offset - Sec.Address; 00494 } 00495 00496 Res += Delta; 00497 } 00498 00499 return object_error::success; 00500 } 00501 00502 error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI, 00503 uint32_t &Result) const { 00504 uint32_t flags; 00505 this->getSymbolFlags(DRI, flags); 00506 if (flags & SymbolRef::SF_Common) { 00507 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI); 00508 Result = 1 << MachO::GET_COMM_ALIGN(Entry.Flags); 00509 } else { 00510 Result = 0; 00511 } 00512 return object_error::success; 00513 } 00514 00515 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, 00516 uint64_t &Result) const { 00517 uint64_t BeginOffset; 00518 uint64_t EndOffset = 0; 00519 uint8_t SectionIndex; 00520 00521 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI); 00522 uint64_t Value; 00523 getSymbolAddress(DRI, Value); 00524 00525 BeginOffset = Value; 00526 00527 SectionIndex = Entry.SectionIndex; 00528 if (!SectionIndex) { 00529 uint32_t flags = SymbolRef::SF_None; 00530 this->getSymbolFlags(DRI, flags); 00531 if (flags & SymbolRef::SF_Common) 00532 Result = Value; 00533 else 00534 Result = UnknownAddressOrSize; 00535 return object_error::success; 00536 } 00537 // Unfortunately symbols are unsorted so we need to touch all 00538 // symbols from load command 00539 error_code ec; 00540 for (symbol_iterator I = begin_symbols(), E = end_symbols(); I != E; 00541 I.increment(ec)) { 00542 DataRefImpl DRI = I->getRawDataRefImpl(); 00543 Entry = getSymbolTableEntryBase(this, DRI); 00544 getSymbolAddress(DRI, Value); 00545 if (Entry.SectionIndex == SectionIndex && Value > BeginOffset) 00546 if (!EndOffset || Value < EndOffset) 00547 EndOffset = Value; 00548 } 00549 if (!EndOffset) { 00550 uint64_t Size; 00551 DataRefImpl Sec; 00552 Sec.d.a = SectionIndex-1; 00553 getSectionSize(Sec, Size); 00554 getSectionAddress(Sec, EndOffset); 00555 EndOffset += Size; 00556 } 00557 Result = EndOffset - BeginOffset; 00558 return object_error::success; 00559 } 00560 00561 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, 00562 SymbolRef::Type &Res) const { 00563 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb); 00564 uint8_t n_type = Entry.Type; 00565 00566 Res = SymbolRef::ST_Other; 00567 00568 // If this is a STAB debugging symbol, we can do nothing more. 00569 if (n_type & MachO::NlistMaskStab) { 00570 Res = SymbolRef::ST_Debug; 00571 return object_error::success; 00572 } 00573 00574 switch (n_type & MachO::NlistMaskType) { 00575 case MachO::NListTypeUndefined : 00576 Res = SymbolRef::ST_Unknown; 00577 break; 00578 case MachO::NListTypeSection : 00579 Res = SymbolRef::ST_Function; 00580 break; 00581 } 00582 return object_error::success; 00583 } 00584 00585 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl Symb, 00586 char &Res) const { 00587 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb); 00588 uint8_t Type = Entry.Type; 00589 uint16_t Flags = Entry.Flags; 00590 00591 char Char; 00592 switch (Type & macho::STF_TypeMask) { 00593 case macho::STT_Undefined: 00594 Char = 'u'; 00595 break; 00596 case macho::STT_Absolute: 00597 case macho::STT_Section: 00598 Char = 's'; 00599 break; 00600 default: 00601 Char = '?'; 00602 break; 00603 } 00604 00605 if (Flags & (macho::STF_External | macho::STF_PrivateExtern)) 00606 Char = toupper(static_cast<unsigned char>(Char)); 00607 Res = Char; 00608 return object_error::success; 00609 } 00610 00611 error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, 00612 uint32_t &Result) const { 00613 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI); 00614 00615 uint8_t MachOType = Entry.Type; 00616 uint16_t MachOFlags = Entry.Flags; 00617 00618 // TODO: Correctly set SF_ThreadLocal 00619 Result = SymbolRef::SF_None; 00620 00621 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) 00622 Result |= SymbolRef::SF_Undefined; 00623 00624 if (MachOFlags & macho::STF_StabsEntryMask) 00625 Result |= SymbolRef::SF_FormatSpecific; 00626 00627 if (MachOType & MachO::NlistMaskExternal) { 00628 Result |= SymbolRef::SF_Global; 00629 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) { 00630 uint64_t Value; 00631 getSymbolAddress(DRI, Value); 00632 if (Value) 00633 Result |= SymbolRef::SF_Common; 00634 } 00635 } 00636 00637 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef)) 00638 Result |= SymbolRef::SF_Weak; 00639 00640 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute) 00641 Result |= SymbolRef::SF_Absolute; 00642 00643 return object_error::success; 00644 } 00645 00646 error_code 00647 MachOObjectFile::getSymbolSection(DataRefImpl Symb, 00648 section_iterator &Res) const { 00649 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb); 00650 uint8_t index = Entry.SectionIndex; 00651 00652 if (index == 0) { 00653 Res = end_sections(); 00654 } else { 00655 DataRefImpl DRI; 00656 DRI.d.a = index - 1; 00657 Res = section_iterator(SectionRef(DRI, this)); 00658 } 00659 00660 return object_error::success; 00661 } 00662 00663 error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb, 00664 uint64_t &Val) const { 00665 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile"); 00666 } 00667 00668 error_code MachOObjectFile::getSectionNext(DataRefImpl Sec, 00669 SectionRef &Res) const { 00670 Sec.d.a++; 00671 Res = SectionRef(Sec, this); 00672 return object_error::success; 00673 } 00674 00675 error_code 00676 MachOObjectFile::getSectionName(DataRefImpl Sec, StringRef &Result) const { 00677 ArrayRef<char> Raw = getSectionRawName(Sec); 00678 Result = parseSegmentOrSectionName(Raw.data()); 00679 return object_error::success; 00680 } 00681 00682 error_code 00683 MachOObjectFile::getSectionAddress(DataRefImpl Sec, uint64_t &Res) const { 00684 if (is64Bit()) { 00685 macho::Section64 Sect = getSection64(Sec); 00686 Res = Sect.Address; 00687 } else { 00688 macho::Section Sect = getSection(Sec); 00689 Res = Sect.Address; 00690 } 00691 return object_error::success; 00692 } 00693 00694 error_code 00695 MachOObjectFile::getSectionSize(DataRefImpl Sec, uint64_t &Res) const { 00696 if (is64Bit()) { 00697 macho::Section64 Sect = getSection64(Sec); 00698 Res = Sect.Size; 00699 } else { 00700 macho::Section Sect = getSection(Sec); 00701 Res = Sect.Size; 00702 } 00703 00704 return object_error::success; 00705 } 00706 00707 error_code 00708 MachOObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Res) const { 00709 uint32_t Offset; 00710 uint64_t Size; 00711 00712 if (is64Bit()) { 00713 macho::Section64 Sect = getSection64(Sec); 00714 Offset = Sect.Offset; 00715 Size = Sect.Size; 00716 } else { 00717 macho::Section Sect =getSection(Sec); 00718 Offset = Sect.Offset; 00719 Size = Sect.Size; 00720 } 00721 00722 Res = this->getData().substr(Offset, Size); 00723 return object_error::success; 00724 } 00725 00726 error_code 00727 MachOObjectFile::getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const { 00728 uint32_t Align; 00729 if (is64Bit()) { 00730 macho::Section64 Sect = getSection64(Sec); 00731 Align = Sect.Align; 00732 } else { 00733 macho::Section Sect = getSection(Sec); 00734 Align = Sect.Align; 00735 } 00736 00737 Res = uint64_t(1) << Align; 00738 return object_error::success; 00739 } 00740 00741 error_code 00742 MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const { 00743 uint32_t Flags = getSectionFlags(this, Sec); 00744 Res = Flags & macho::SF_PureInstructions; 00745 return object_error::success; 00746 } 00747 00748 error_code MachOObjectFile::isSectionData(DataRefImpl DRI, bool &Result) const { 00749 // FIXME: Unimplemented. 00750 Result = false; 00751 return object_error::success; 00752 } 00753 00754 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, bool &Result) const { 00755 // FIXME: Unimplemented. 00756 Result = false; 00757 return object_error::success; 00758 } 00759 00760 error_code 00761 MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, 00762 bool &Result) const { 00763 // FIXME: Unimplemented. 00764 Result = true; 00765 return object_error::success; 00766 } 00767 00768 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, 00769 bool &Result) const { 00770 // FIXME: Unimplemented. 00771 Result = false; 00772 return object_error::success; 00773 } 00774 00775 error_code 00776 MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const { 00777 uint32_t Flags = getSectionFlags(this, Sec); 00778 unsigned SectionType = Flags & MachO::SectionFlagMaskSectionType; 00779 Res = SectionType == MachO::SectionTypeZeroFill || 00780 SectionType == MachO::SectionTypeZeroFillLarge; 00781 return object_error::success; 00782 } 00783 00784 error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, 00785 bool &Result) const { 00786 // Consider using the code from isSectionText to look for __const sections. 00787 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS 00788 // to use section attributes to distinguish code from data. 00789 00790 // FIXME: Unimplemented. 00791 Result = false; 00792 return object_error::success; 00793 } 00794 00795 error_code 00796 MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, 00797 bool &Result) const { 00798 SymbolRef::Type ST; 00799 this->getSymbolType(Symb, ST); 00800 if (ST == SymbolRef::ST_Unknown) { 00801 Result = false; 00802 return object_error::success; 00803 } 00804 00805 uint64_t SectBegin, SectEnd; 00806 getSectionAddress(Sec, SectBegin); 00807 getSectionSize(Sec, SectEnd); 00808 SectEnd += SectBegin; 00809 00810 uint64_t SymAddr; 00811 getSymbolAddress(Symb, SymAddr); 00812 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 00813 00814 return object_error::success; 00815 } 00816 00817 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { 00818 uint32_t Offset; 00819 if (is64Bit()) { 00820 macho::Section64 Sect = getSection64(Sec); 00821 Offset = Sect.RelocationTableOffset; 00822 } else { 00823 macho::Section Sect = getSection(Sec); 00824 Offset = Sect.RelocationTableOffset; 00825 } 00826 00827 DataRefImpl Ret; 00828 Ret.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 00829 return relocation_iterator(RelocationRef(Ret, this)); 00830 } 00831 00832 relocation_iterator 00833 MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { 00834 uint32_t Offset; 00835 uint32_t Num; 00836 if (is64Bit()) { 00837 macho::Section64 Sect = getSection64(Sec); 00838 Offset = Sect.RelocationTableOffset; 00839 Num = Sect.NumRelocationTableEntries; 00840 } else { 00841 macho::Section Sect = getSection(Sec); 00842 Offset = Sect.RelocationTableOffset; 00843 Num = Sect.NumRelocationTableEntries; 00844 } 00845 00846 const macho::RelocationEntry *P = 00847 reinterpret_cast<const macho::RelocationEntry*>(getPtr(this, Offset)); 00848 00849 DataRefImpl Ret; 00850 Ret.p = reinterpret_cast<uintptr_t>(P + Num); 00851 return relocation_iterator(RelocationRef(Ret, this)); 00852 } 00853 00854 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, 00855 RelocationRef &Res) const { 00856 const macho::RelocationEntry *P = 00857 reinterpret_cast<const macho::RelocationEntry *>(Rel.p); 00858 Rel.p = reinterpret_cast<uintptr_t>(P + 1); 00859 Res = RelocationRef(Rel, this); 00860 return object_error::success; 00861 } 00862 00863 error_code 00864 MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const { 00865 report_fatal_error("getRelocationAddress not implemented in MachOObjectFile"); 00866 } 00867 00868 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, 00869 uint64_t &Res) const { 00870 macho::RelocationEntry RE = getRelocation(Rel); 00871 Res = getAnyRelocationAddress(RE); 00872 return object_error::success; 00873 } 00874 00875 symbol_iterator 00876 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 00877 macho::RelocationEntry RE = getRelocation(Rel); 00878 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); 00879 bool isExtern = getPlainRelocationExternal(RE); 00880 if (!isExtern) 00881 return end_symbols(); 00882 00883 macho::SymtabLoadCommand S = getSymtabLoadCommand(); 00884 unsigned SymbolTableEntrySize = is64Bit() ? 00885 sizeof(macho::Symbol64TableEntry) : 00886 sizeof(macho::SymbolTableEntry); 00887 uint64_t Offset = S.SymbolTableOffset + SymbolIdx * SymbolTableEntrySize; 00888 DataRefImpl Sym; 00889 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 00890 return symbol_iterator(SymbolRef(Sym, this)); 00891 } 00892 00893 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, 00894 uint64_t &Res) const { 00895 macho::RelocationEntry RE = getRelocation(Rel); 00896 Res = getAnyRelocationType(RE); 00897 return object_error::success; 00898 } 00899 00900 error_code 00901 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, 00902 SmallVectorImpl<char> &Result) const { 00903 StringRef res; 00904 uint64_t RType; 00905 getRelocationType(Rel, RType); 00906 00907 unsigned Arch = this->getArch(); 00908 00909 switch (Arch) { 00910 case Triple::x86: { 00911 static const char *const Table[] = { 00912 "GENERIC_RELOC_VANILLA", 00913 "GENERIC_RELOC_PAIR", 00914 "GENERIC_RELOC_SECTDIFF", 00915 "GENERIC_RELOC_PB_LA_PTR", 00916 "GENERIC_RELOC_LOCAL_SECTDIFF", 00917 "GENERIC_RELOC_TLV" }; 00918 00919 if (RType > 6) 00920 res = "Unknown"; 00921 else 00922 res = Table[RType]; 00923 break; 00924 } 00925 case Triple::x86_64: { 00926 static const char *const Table[] = { 00927 "X86_64_RELOC_UNSIGNED", 00928 "X86_64_RELOC_SIGNED", 00929 "X86_64_RELOC_BRANCH", 00930 "X86_64_RELOC_GOT_LOAD", 00931 "X86_64_RELOC_GOT", 00932 "X86_64_RELOC_SUBTRACTOR", 00933 "X86_64_RELOC_SIGNED_1", 00934 "X86_64_RELOC_SIGNED_2", 00935 "X86_64_RELOC_SIGNED_4", 00936 "X86_64_RELOC_TLV" }; 00937 00938 if (RType > 9) 00939 res = "Unknown"; 00940 else 00941 res = Table[RType]; 00942 break; 00943 } 00944 case Triple::arm: { 00945 static const char *const Table[] = { 00946 "ARM_RELOC_VANILLA", 00947 "ARM_RELOC_PAIR", 00948 "ARM_RELOC_SECTDIFF", 00949 "ARM_RELOC_LOCAL_SECTDIFF", 00950 "ARM_RELOC_PB_LA_PTR", 00951 "ARM_RELOC_BR24", 00952 "ARM_THUMB_RELOC_BR22", 00953 "ARM_THUMB_32BIT_BRANCH", 00954 "ARM_RELOC_HALF", 00955 "ARM_RELOC_HALF_SECTDIFF" }; 00956 00957 if (RType > 9) 00958 res = "Unknown"; 00959 else 00960 res = Table[RType]; 00961 break; 00962 } 00963 case Triple::ppc: { 00964 static const char *const Table[] = { 00965 "PPC_RELOC_VANILLA", 00966 "PPC_RELOC_PAIR", 00967 "PPC_RELOC_BR14", 00968 "PPC_RELOC_BR24", 00969 "PPC_RELOC_HI16", 00970 "PPC_RELOC_LO16", 00971 "PPC_RELOC_HA16", 00972 "PPC_RELOC_LO14", 00973 "PPC_RELOC_SECTDIFF", 00974 "PPC_RELOC_PB_LA_PTR", 00975 "PPC_RELOC_HI16_SECTDIFF", 00976 "PPC_RELOC_LO16_SECTDIFF", 00977 "PPC_RELOC_HA16_SECTDIFF", 00978 "PPC_RELOC_JBSR", 00979 "PPC_RELOC_LO14_SECTDIFF", 00980 "PPC_RELOC_LOCAL_SECTDIFF" }; 00981 00982 res = Table[RType]; 00983 break; 00984 } 00985 case Triple::UnknownArch: 00986 res = "Unknown"; 00987 break; 00988 } 00989 Result.append(res.begin(), res.end()); 00990 return object_error::success; 00991 } 00992 00993 error_code 00994 MachOObjectFile::getRelocationValueString(DataRefImpl Rel, 00995 SmallVectorImpl<char> &Result) const { 00996 macho::RelocationEntry RE = getRelocation(Rel); 00997 00998 unsigned Arch = this->getArch(); 00999 01000 std::string fmtbuf; 01001 raw_string_ostream fmt(fmtbuf); 01002 unsigned Type = this->getAnyRelocationType(RE); 01003 bool IsPCRel = this->getAnyRelocationPCRel(RE); 01004 01005 // Determine any addends that should be displayed with the relocation. 01006 // These require decoding the relocation type, which is triple-specific. 01007 01008 // X86_64 has entirely custom relocation types. 01009 if (Arch == Triple::x86_64) { 01010 bool isPCRel = getAnyRelocationPCRel(RE); 01011 01012 switch (Type) { 01013 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD 01014 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT 01015 printRelocationTargetName(this, RE, fmt); 01016 fmt << "@GOT"; 01017 if (isPCRel) fmt << "PCREL"; 01018 break; 01019 } 01020 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR 01021 DataRefImpl RelNext = Rel; 01022 RelNext.d.a++; 01023 macho::RelocationEntry RENext = getRelocation(RelNext); 01024 01025 // X86_64_SUBTRACTOR must be followed by a relocation of type 01026 // X86_64_RELOC_UNSIGNED. 01027 // NOTE: Scattered relocations don't exist on x86_64. 01028 unsigned RType = getAnyRelocationType(RENext); 01029 if (RType != 0) 01030 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " 01031 "X86_64_RELOC_SUBTRACTOR."); 01032 01033 // The X86_64_RELOC_UNSIGNED contains the minuend symbol, 01034 // X86_64_SUBTRACTOR contains to the subtrahend. 01035 printRelocationTargetName(this, RENext, fmt); 01036 fmt << "-"; 01037 printRelocationTargetName(this, RE, fmt); 01038 break; 01039 } 01040 case macho::RIT_X86_64_TLV: 01041 printRelocationTargetName(this, RE, fmt); 01042 fmt << "@TLV"; 01043 if (isPCRel) fmt << "P"; 01044 break; 01045 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1 01046 printRelocationTargetName(this, RE, fmt); 01047 fmt << "-1"; 01048 break; 01049 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2 01050 printRelocationTargetName(this, RE, fmt); 01051 fmt << "-2"; 01052 break; 01053 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4 01054 printRelocationTargetName(this, RE, fmt); 01055 fmt << "-4"; 01056 break; 01057 default: 01058 printRelocationTargetName(this, RE, fmt); 01059 break; 01060 } 01061 // X86 and ARM share some relocation types in common. 01062 } else if (Arch == Triple::x86 || Arch == Triple::arm) { 01063 // Generic relocation types... 01064 switch (Type) { 01065 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info 01066 return object_error::success; 01067 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF 01068 DataRefImpl RelNext = Rel; 01069 RelNext.d.a++; 01070 macho::RelocationEntry RENext = getRelocation(RelNext); 01071 01072 // X86 sect diff's must be followed by a relocation of type 01073 // GENERIC_RELOC_PAIR. 01074 unsigned RType = getAnyRelocationType(RENext); 01075 01076 if (RType != 1) 01077 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 01078 "GENERIC_RELOC_SECTDIFF."); 01079 01080 printRelocationTargetName(this, RE, fmt); 01081 fmt << "-"; 01082 printRelocationTargetName(this, RENext, fmt); 01083 break; 01084 } 01085 } 01086 01087 if (Arch == Triple::x86) { 01088 // All X86 relocations that need special printing were already 01089 // handled in the generic code. 01090 switch (Type) { 01091 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF 01092 DataRefImpl RelNext = Rel; 01093 RelNext.d.a++; 01094 macho::RelocationEntry RENext = getRelocation(RelNext); 01095 01096 // X86 sect diff's must be followed by a relocation of type 01097 // GENERIC_RELOC_PAIR. 01098 unsigned RType = getAnyRelocationType(RENext); 01099 if (RType != 1) 01100 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 01101 "GENERIC_RELOC_LOCAL_SECTDIFF."); 01102 01103 printRelocationTargetName(this, RE, fmt); 01104 fmt << "-"; 01105 printRelocationTargetName(this, RENext, fmt); 01106 break; 01107 } 01108 case macho::RIT_Generic_TLV: { 01109 printRelocationTargetName(this, RE, fmt); 01110 fmt << "@TLV"; 01111 if (IsPCRel) fmt << "P"; 01112 break; 01113 } 01114 default: 01115 printRelocationTargetName(this, RE, fmt); 01116 } 01117 } else { // ARM-specific relocations 01118 switch (Type) { 01119 case macho::RIT_ARM_Half: // ARM_RELOC_HALF 01120 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF 01121 // Half relocations steal a bit from the length field to encode 01122 // whether this is an upper16 or a lower16 relocation. 01123 bool isUpper = getAnyRelocationLength(RE) >> 1; 01124 01125 if (isUpper) 01126 fmt << ":upper16:("; 01127 else 01128 fmt << ":lower16:("; 01129 printRelocationTargetName(this, RE, fmt); 01130 01131 DataRefImpl RelNext = Rel; 01132 RelNext.d.a++; 01133 macho::RelocationEntry RENext = getRelocation(RelNext); 01134 01135 // ARM half relocs must be followed by a relocation of type 01136 // ARM_RELOC_PAIR. 01137 unsigned RType = getAnyRelocationType(RENext); 01138 if (RType != 1) 01139 report_fatal_error("Expected ARM_RELOC_PAIR after " 01140 "GENERIC_RELOC_HALF"); 01141 01142 // NOTE: The half of the target virtual address is stashed in the 01143 // address field of the secondary relocation, but we can't reverse 01144 // engineer the constant offset from it without decoding the movw/movt 01145 // instruction to find the other half in its immediate field. 01146 01147 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the 01148 // symbol/section pointer of the follow-on relocation. 01149 if (Type == macho::RIT_ARM_HalfDifference) { 01150 fmt << "-"; 01151 printRelocationTargetName(this, RENext, fmt); 01152 } 01153 01154 fmt << ")"; 01155 break; 01156 } 01157 default: { 01158 printRelocationTargetName(this, RE, fmt); 01159 } 01160 } 01161 } 01162 } else 01163 printRelocationTargetName(this, RE, fmt); 01164 01165 fmt.flush(); 01166 Result.append(fmtbuf.begin(), fmtbuf.end()); 01167 return object_error::success; 01168 } 01169 01170 error_code 01171 MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const { 01172 unsigned Arch = getArch(); 01173 uint64_t Type; 01174 getRelocationType(Rel, Type); 01175 01176 Result = false; 01177 01178 // On arches that use the generic relocations, GENERIC_RELOC_PAIR 01179 // is always hidden. 01180 if (Arch == Triple::x86 || Arch == Triple::arm) { 01181 if (Type == macho::RIT_Pair) Result = true; 01182 } else if (Arch == Triple::x86_64) { 01183 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows 01184 // an X864_64_RELOC_SUBTRACTOR. 01185 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) { 01186 DataRefImpl RelPrev = Rel; 01187 RelPrev.d.a--; 01188 uint64_t PrevType; 01189 getRelocationType(RelPrev, PrevType); 01190 if (PrevType == macho::RIT_X86_64_Subtractor) 01191 Result = true; 01192 } 01193 } 01194 01195 return object_error::success; 01196 } 01197 01198 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData, 01199 LibraryRef &Res) const { 01200 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 01201 } 01202 01203 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, 01204 StringRef &Res) const { 01205 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 01206 } 01207 01208 symbol_iterator MachOObjectFile::begin_symbols() const { 01209 DataRefImpl DRI; 01210 if (!SymtabLoadCmd) 01211 return symbol_iterator(SymbolRef(DRI, this)); 01212 01213 macho::SymtabLoadCommand Symtab = getSymtabLoadCommand(); 01214 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.SymbolTableOffset)); 01215 return symbol_iterator(SymbolRef(DRI, this)); 01216 } 01217 01218 symbol_iterator MachOObjectFile::end_symbols() const { 01219 DataRefImpl DRI; 01220 if (!SymtabLoadCmd) 01221 return symbol_iterator(SymbolRef(DRI, this)); 01222 01223 macho::SymtabLoadCommand Symtab = getSymtabLoadCommand(); 01224 unsigned SymbolTableEntrySize = is64Bit() ? 01225 sizeof(macho::Symbol64TableEntry) : 01226 sizeof(macho::SymbolTableEntry); 01227 unsigned Offset = Symtab.SymbolTableOffset + 01228 Symtab.NumSymbolTableEntries * SymbolTableEntrySize; 01229 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 01230 return symbol_iterator(SymbolRef(DRI, this)); 01231 } 01232 01233 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const { 01234 // TODO: implement 01235 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); 01236 } 01237 01238 symbol_iterator MachOObjectFile::end_dynamic_symbols() const { 01239 // TODO: implement 01240 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); 01241 } 01242 01243 section_iterator MachOObjectFile::begin_sections() const { 01244 DataRefImpl DRI; 01245 return section_iterator(SectionRef(DRI, this)); 01246 } 01247 01248 section_iterator MachOObjectFile::end_sections() const { 01249 DataRefImpl DRI; 01250 DRI.d.a = Sections.size(); 01251 return section_iterator(SectionRef(DRI, this)); 01252 } 01253 01254 library_iterator MachOObjectFile::begin_libraries_needed() const { 01255 // TODO: implement 01256 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 01257 } 01258 01259 library_iterator MachOObjectFile::end_libraries_needed() const { 01260 // TODO: implement 01261 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 01262 } 01263 01264 uint8_t MachOObjectFile::getBytesInAddress() const { 01265 return is64Bit() ? 8 : 4; 01266 } 01267 01268 StringRef MachOObjectFile::getFileFormatName() const { 01269 unsigned CPUType = getCPUType(this); 01270 if (!is64Bit()) { 01271 switch (CPUType) { 01272 case llvm::MachO::CPUTypeI386: 01273 return "Mach-O 32-bit i386"; 01274 case llvm::MachO::CPUTypeARM: 01275 return "Mach-O arm"; 01276 case llvm::MachO::CPUTypePowerPC: 01277 return "Mach-O 32-bit ppc"; 01278 default: 01279 assert((CPUType & llvm::MachO::CPUArchABI64) == 0 && 01280 "64-bit object file when we're not 64-bit?"); 01281 return "Mach-O 32-bit unknown"; 01282 } 01283 } 01284 01285 // Make sure the cpu type has the correct mask. 01286 assert((CPUType & llvm::MachO::CPUArchABI64) 01287 == llvm::MachO::CPUArchABI64 && 01288 "32-bit object file when we're 64-bit?"); 01289 01290 switch (CPUType) { 01291 case llvm::MachO::CPUTypeX86_64: 01292 return "Mach-O 64-bit x86-64"; 01293 case llvm::MachO::CPUTypePowerPC64: 01294 return "Mach-O 64-bit ppc64"; 01295 default: 01296 return "Mach-O 64-bit unknown"; 01297 } 01298 } 01299 01300 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { 01301 switch (CPUType) { 01302 case llvm::MachO::CPUTypeI386: 01303 return Triple::x86; 01304 case llvm::MachO::CPUTypeX86_64: 01305 return Triple::x86_64; 01306 case llvm::MachO::CPUTypeARM: 01307 return Triple::arm; 01308 case llvm::MachO::CPUTypePowerPC: 01309 return Triple::ppc; 01310 case llvm::MachO::CPUTypePowerPC64: 01311 return Triple::ppc64; 01312 default: 01313 return Triple::UnknownArch; 01314 } 01315 } 01316 01317 unsigned MachOObjectFile::getArch() const { 01318 return getArch(getCPUType(this)); 01319 } 01320 01321 StringRef MachOObjectFile::getLoadName() const { 01322 // TODO: Implement 01323 report_fatal_error("get_load_name() unimplemented in MachOObjectFile"); 01324 } 01325 01326 relocation_iterator MachOObjectFile::getSectionRelBegin(unsigned Index) const { 01327 DataRefImpl DRI; 01328 DRI.d.a = Index; 01329 return getSectionRelBegin(DRI); 01330 } 01331 01332 relocation_iterator MachOObjectFile::getSectionRelEnd(unsigned Index) const { 01333 DataRefImpl DRI; 01334 DRI.d.a = Index; 01335 return getSectionRelEnd(DRI); 01336 } 01337 01338 dice_iterator MachOObjectFile::begin_dices() const { 01339 DataRefImpl DRI; 01340 if (!DataInCodeLoadCmd) 01341 return dice_iterator(DiceRef(DRI, this)); 01342 01343 macho::LinkeditDataLoadCommand DicLC = getDataInCodeLoadCommand(); 01344 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.DataOffset)); 01345 return dice_iterator(DiceRef(DRI, this)); 01346 } 01347 01348 dice_iterator MachOObjectFile::end_dices() const { 01349 DataRefImpl DRI; 01350 if (!DataInCodeLoadCmd) 01351 return dice_iterator(DiceRef(DRI, this)); 01352 01353 macho::LinkeditDataLoadCommand DicLC = getDataInCodeLoadCommand(); 01354 unsigned Offset = DicLC.DataOffset + DicLC.DataSize; 01355 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 01356 return dice_iterator(DiceRef(DRI, this)); 01357 } 01358 01359 StringRef 01360 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 01361 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 01362 return parseSegmentOrSectionName(Raw.data()); 01363 } 01364 01365 ArrayRef<char> 01366 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 01367 const SectionBase *Base = 01368 reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]); 01369 return ArrayRef<char>(Base->Name); 01370 } 01371 01372 ArrayRef<char> 01373 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 01374 const SectionBase *Base = 01375 reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]); 01376 return ArrayRef<char>(Base->SegmentName); 01377 } 01378 01379 bool 01380 MachOObjectFile::isRelocationScattered(const macho::RelocationEntry &RE) 01381 const { 01382 if (getCPUType(this) == llvm::MachO::CPUTypeX86_64) 01383 return false; 01384 return getPlainRelocationAddress(RE) & macho::RF_Scattered; 01385 } 01386 01387 unsigned MachOObjectFile::getPlainRelocationSymbolNum(const macho::RelocationEntry &RE) const { 01388 if (isLittleEndian()) 01389 return RE.Word1 & 0xffffff; 01390 return RE.Word1 >> 8; 01391 } 01392 01393 bool MachOObjectFile::getPlainRelocationExternal(const macho::RelocationEntry &RE) const { 01394 if (isLittleEndian()) 01395 return (RE.Word1 >> 27) & 1; 01396 return (RE.Word1 >> 4) & 1; 01397 } 01398 01399 bool 01400 MachOObjectFile::getScatteredRelocationScattered(const macho::RelocationEntry &RE) const { 01401 return RE.Word0 >> 31; 01402 } 01403 01404 uint32_t 01405 MachOObjectFile::getScatteredRelocationValue(const macho::RelocationEntry &RE) const { 01406 return RE.Word1; 01407 } 01408 01409 unsigned 01410 MachOObjectFile::getAnyRelocationAddress(const macho::RelocationEntry &RE) const { 01411 if (isRelocationScattered(RE)) 01412 return getScatteredRelocationAddress(RE); 01413 return getPlainRelocationAddress(RE); 01414 } 01415 01416 unsigned 01417 MachOObjectFile::getAnyRelocationPCRel(const macho::RelocationEntry &RE) const { 01418 if (isRelocationScattered(RE)) 01419 return getScatteredRelocationPCRel(this, RE); 01420 return getPlainRelocationPCRel(this, RE); 01421 } 01422 01423 unsigned 01424 MachOObjectFile::getAnyRelocationLength(const macho::RelocationEntry &RE) const { 01425 if (isRelocationScattered(RE)) 01426 return getScatteredRelocationLength(RE); 01427 return getPlainRelocationLength(this, RE); 01428 } 01429 01430 unsigned 01431 MachOObjectFile::getAnyRelocationType(const macho::RelocationEntry &RE) const { 01432 if (isRelocationScattered(RE)) 01433 return getScatteredRelocationType(RE); 01434 return getPlainRelocationType(this, RE); 01435 } 01436 01437 SectionRef 01438 MachOObjectFile::getRelocationSection(const macho::RelocationEntry &RE) const { 01439 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) 01440 return *end_sections(); 01441 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1; 01442 DataRefImpl DRI; 01443 DRI.d.a = SecNum; 01444 return SectionRef(DRI, this); 01445 } 01446 01447 MachOObjectFile::LoadCommandInfo 01448 MachOObjectFile::getFirstLoadCommandInfo() const { 01449 MachOObjectFile::LoadCommandInfo Load; 01450 01451 unsigned HeaderSize = is64Bit() ? macho::Header64Size : macho::Header32Size; 01452 Load.Ptr = getPtr(this, HeaderSize); 01453 Load.C = getStruct<macho::LoadCommand>(this, Load.Ptr); 01454 return Load; 01455 } 01456 01457 MachOObjectFile::LoadCommandInfo 01458 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const { 01459 MachOObjectFile::LoadCommandInfo Next; 01460 Next.Ptr = L.Ptr + L.C.Size; 01461 Next.C = getStruct<macho::LoadCommand>(this, Next.Ptr); 01462 return Next; 01463 } 01464 01465 macho::Section MachOObjectFile::getSection(DataRefImpl DRI) const { 01466 return getStruct<macho::Section>(this, Sections[DRI.d.a]); 01467 } 01468 01469 macho::Section64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 01470 return getStruct<macho::Section64>(this, Sections[DRI.d.a]); 01471 } 01472 01473 macho::Section MachOObjectFile::getSection(const LoadCommandInfo &L, 01474 unsigned Index) const { 01475 const char *Sec = getSectionPtr(this, L, Index); 01476 return getStruct<macho::Section>(this, Sec); 01477 } 01478 01479 macho::Section64 MachOObjectFile::getSection64(const LoadCommandInfo &L, 01480 unsigned Index) const { 01481 const char *Sec = getSectionPtr(this, L, Index); 01482 return getStruct<macho::Section64>(this, Sec); 01483 } 01484 01485 macho::SymbolTableEntry 01486 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 01487 const char *P = reinterpret_cast<const char *>(DRI.p); 01488 return getStruct<macho::SymbolTableEntry>(this, P); 01489 } 01490 01491 macho::Symbol64TableEntry 01492 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 01493 const char *P = reinterpret_cast<const char *>(DRI.p); 01494 return getStruct<macho::Symbol64TableEntry>(this, P); 01495 } 01496 01497 macho::LinkeditDataLoadCommand 01498 MachOObjectFile::getLinkeditDataLoadCommand(const MachOObjectFile::LoadCommandInfo &L) const { 01499 return getStruct<macho::LinkeditDataLoadCommand>(this, L.Ptr); 01500 } 01501 01502 macho::SegmentLoadCommand 01503 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { 01504 return getStruct<macho::SegmentLoadCommand>(this, L.Ptr); 01505 } 01506 01507 macho::Segment64LoadCommand 01508 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { 01509 return getStruct<macho::Segment64LoadCommand>(this, L.Ptr); 01510 } 01511 01512 macho::LinkerOptionsLoadCommand 01513 MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const { 01514 return getStruct<macho::LinkerOptionsLoadCommand>(this, L.Ptr); 01515 } 01516 01517 macho::RelocationEntry 01518 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 01519 const char *P = reinterpret_cast<const char *>(Rel.p); 01520 return getStruct<macho::RelocationEntry>(this, P); 01521 } 01522 01523 macho::DataInCodeTableEntry 01524 MachOObjectFile::getDice(DataRefImpl Rel) const { 01525 const char *P = reinterpret_cast<const char *>(Rel.p); 01526 return getStruct<macho::DataInCodeTableEntry>(this, P); 01527 } 01528 01529 macho::Header MachOObjectFile::getHeader() const { 01530 return getStruct<macho::Header>(this, getPtr(this, 0)); 01531 } 01532 01533 macho::Header64Ext MachOObjectFile::getHeader64Ext() const { 01534 return 01535 getStruct<macho::Header64Ext>(this, getPtr(this, sizeof(macho::Header))); 01536 } 01537 01538 macho::IndirectSymbolTableEntry MachOObjectFile::getIndirectSymbolTableEntry( 01539 const macho::DysymtabLoadCommand &DLC, 01540 unsigned Index) const { 01541 uint64_t Offset = DLC.IndirectSymbolTableOffset + 01542 Index * sizeof(macho::IndirectSymbolTableEntry); 01543 return getStruct<macho::IndirectSymbolTableEntry>(this, getPtr(this, Offset)); 01544 } 01545 01546 macho::DataInCodeTableEntry 01547 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, 01548 unsigned Index) const { 01549 uint64_t Offset = DataOffset + Index * sizeof(macho::DataInCodeTableEntry); 01550 return getStruct<macho::DataInCodeTableEntry>(this, getPtr(this, Offset)); 01551 } 01552 01553 macho::SymtabLoadCommand MachOObjectFile::getSymtabLoadCommand() const { 01554 return getStruct<macho::SymtabLoadCommand>(this, SymtabLoadCmd); 01555 } 01556 01557 macho::DysymtabLoadCommand MachOObjectFile::getDysymtabLoadCommand() const { 01558 return getStruct<macho::DysymtabLoadCommand>(this, DysymtabLoadCmd); 01559 } 01560 01561 macho::LinkeditDataLoadCommand 01562 MachOObjectFile::getDataInCodeLoadCommand() const { 01563 if (DataInCodeLoadCmd) 01564 return getStruct<macho::LinkeditDataLoadCommand>(this, DataInCodeLoadCmd); 01565 01566 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. 01567 macho::LinkeditDataLoadCommand Cmd; 01568 Cmd.Type = macho::LCT_DataInCode; 01569 Cmd.Size = macho::LinkeditLoadCommandSize; 01570 Cmd.DataOffset = 0; 01571 Cmd.DataSize = 0; 01572 return Cmd; 01573 } 01574 01575 StringRef MachOObjectFile::getStringTableData() const { 01576 macho::SymtabLoadCommand S = getSymtabLoadCommand(); 01577 return getData().substr(S.StringTableOffset, S.StringTableSize); 01578 } 01579 01580 bool MachOObjectFile::is64Bit() const { 01581 return getType() == getMachOType(false, true) || 01582 getType() == getMachOType(true, true); 01583 } 01584 01585 void MachOObjectFile::ReadULEB128s(uint64_t Index, 01586 SmallVectorImpl<uint64_t> &Out) const { 01587 DataExtractor extractor(ObjectFile::getData(), true, 0); 01588 01589 uint32_t offset = Index; 01590 uint64_t data = 0; 01591 while (uint64_t delta = extractor.getULEB128(&offset)) { 01592 data += delta; 01593 Out.push_back(data); 01594 } 01595 } 01596 01597 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { 01598 StringRef Magic = Buffer->getBuffer().slice(0, 4); 01599 error_code ec; 01600 ObjectFile *Ret; 01601 if (Magic == "\xFE\xED\xFA\xCE") 01602 Ret = new MachOObjectFile(Buffer, false, false, ec); 01603 else if (Magic == "\xCE\xFA\xED\xFE") 01604 Ret = new MachOObjectFile(Buffer, true, false, ec); 01605 else if (Magic == "\xFE\xED\xFA\xCF") 01606 Ret = new MachOObjectFile(Buffer, false, true, ec); 01607 else if (Magic == "\xCF\xFA\xED\xFE") 01608 Ret = new MachOObjectFile(Buffer, true, true, ec); 01609 else 01610 return NULL; 01611 01612 if (ec) 01613 return NULL; 01614 return Ret; 01615 } 01616 01617 } // end namespace object 01618 } // end namespace llvm