1 //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the MachOObjectFile class, which binds the MachOObject
11 // class to the generic ObjectFile wrapper.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "llvm/Object/MachO.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/ADT/Triple.h"
19 #include "llvm/Support/DataExtractor.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/Format.h"
22 #include "llvm/Support/Host.h"
23 #include "llvm/Support/LEB128.h"
24 #include "llvm/Support/MachO.h"
25 #include "llvm/Support/MemoryBuffer.h"
26 #include "llvm/Support/raw_ostream.h"
27 #include <cctype>
28 #include <cstring>
29 #include <limits>
30
31 using namespace llvm;
32 using namespace object;
33
34 namespace {
35 struct section_base {
36 char sectname[16];
37 char segname[16];
38 };
39 }
40
41 template <typename T>
getStruct(const MachOObjectFile * O,const char * P)42 static T getStruct(const MachOObjectFile *O, const char *P) {
43 // Don't read before the beginning or past the end of the file
44 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
45 report_fatal_error("Malformed MachO file.");
46
47 T Cmd;
48 memcpy(&Cmd, P, sizeof(T));
49 if (O->isLittleEndian() != sys::IsLittleEndianHost)
50 MachO::swapStruct(Cmd);
51 return Cmd;
52 }
53
54 template <typename SegmentCmd>
getSegmentLoadCommandNumSections(const SegmentCmd & S,uint32_t Cmdsize)55 static uint32_t getSegmentLoadCommandNumSections(const SegmentCmd &S,
56 uint32_t Cmdsize) {
57 const unsigned SectionSize = sizeof(SegmentCmd);
58 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
59 S.nsects * SectionSize > Cmdsize - sizeof(S))
60 report_fatal_error(
61 "Number of sections too large for size of load command.");
62 return S.nsects;
63 }
64
65 static uint32_t
getSegmentLoadCommandNumSections(const MachOObjectFile * O,const MachOObjectFile::LoadCommandInfo & L)66 getSegmentLoadCommandNumSections(const MachOObjectFile *O,
67 const MachOObjectFile::LoadCommandInfo &L) {
68 if (O->is64Bit())
69 return getSegmentLoadCommandNumSections(O->getSegment64LoadCommand(L),
70 L.C.cmdsize);
71
72 return getSegmentLoadCommandNumSections(O->getSegmentLoadCommand(L),
73 L.C.cmdsize);
74 }
75
isPageZeroSegment(const MachOObjectFile * O,const MachOObjectFile::LoadCommandInfo & L)76 static bool isPageZeroSegment(const MachOObjectFile *O,
77 const MachOObjectFile::LoadCommandInfo &L) {
78 if (O->is64Bit()) {
79 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
80 return StringRef("__PAGEZERO").equals(S.segname);
81 }
82 MachO::segment_command S = O->getSegmentLoadCommand(L);
83 return StringRef("__PAGEZERO").equals(S.segname);
84 }
85
86
87 static const char *
getSectionPtr(const MachOObjectFile * O,MachOObjectFile::LoadCommandInfo L,unsigned Sec)88 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
89 unsigned Sec) {
90 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
91
92 bool Is64 = O->is64Bit();
93 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
94 sizeof(MachO::segment_command);
95 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
96 sizeof(MachO::section);
97
98 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
99 return reinterpret_cast<const char*>(SectionAddr);
100 }
101
getPtr(const MachOObjectFile * O,size_t Offset)102 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
103 return O->getData().substr(Offset, 1).data();
104 }
105
106 static MachO::nlist_base
getSymbolTableEntryBase(const MachOObjectFile * O,DataRefImpl DRI)107 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
108 const char *P = reinterpret_cast<const char *>(DRI.p);
109 return getStruct<MachO::nlist_base>(O, P);
110 }
111
parseSegmentOrSectionName(const char * P)112 static StringRef parseSegmentOrSectionName(const char *P) {
113 if (P[15] == 0)
114 // Null terminated.
115 return P;
116 // Not null terminated, so this is a 16 char string.
117 return StringRef(P, 16);
118 }
119
120 // Helper to advance a section or symbol iterator multiple increments at a time.
121 template<class T>
advance(T & it,size_t Val)122 static void advance(T &it, size_t Val) {
123 while (Val--)
124 ++it;
125 }
126
getCPUType(const MachOObjectFile * O)127 static unsigned getCPUType(const MachOObjectFile *O) {
128 return O->getHeader().cputype;
129 }
130
printRelocationTargetName(const MachOObjectFile * O,const MachO::any_relocation_info & RE,raw_string_ostream & fmt)131 static void printRelocationTargetName(const MachOObjectFile *O,
132 const MachO::any_relocation_info &RE,
133 raw_string_ostream &fmt) {
134 bool IsScattered = O->isRelocationScattered(RE);
135
136 // Target of a scattered relocation is an address. In the interest of
137 // generating pretty output, scan through the symbol table looking for a
138 // symbol that aligns with that address. If we find one, print it.
139 // Otherwise, we just print the hex address of the target.
140 if (IsScattered) {
141 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
142
143 for (const SymbolRef &Symbol : O->symbols()) {
144 std::error_code ec;
145 uint64_t Addr;
146 StringRef Name;
147
148 if ((ec = Symbol.getAddress(Addr)))
149 report_fatal_error(ec.message());
150 if (Addr != Val)
151 continue;
152 if ((ec = Symbol.getName(Name)))
153 report_fatal_error(ec.message());
154 fmt << Name;
155 return;
156 }
157
158 // If we couldn't find a symbol that this relocation refers to, try
159 // to find a section beginning instead.
160 for (const SectionRef &Section : O->sections()) {
161 std::error_code ec;
162
163 StringRef Name;
164 uint64_t Addr = Section.getAddress();
165 if (Addr != Val)
166 continue;
167 if ((ec = Section.getName(Name)))
168 report_fatal_error(ec.message());
169 fmt << Name;
170 return;
171 }
172
173 fmt << format("0x%x", Val);
174 return;
175 }
176
177 StringRef S;
178 bool isExtern = O->getPlainRelocationExternal(RE);
179 uint64_t Val = O->getPlainRelocationSymbolNum(RE);
180
181 if (isExtern) {
182 symbol_iterator SI = O->symbol_begin();
183 advance(SI, Val);
184 SI->getName(S);
185 } else {
186 section_iterator SI = O->section_begin();
187 // Adjust for the fact that sections are 1-indexed.
188 advance(SI, Val - 1);
189 SI->getName(S);
190 }
191
192 fmt << S;
193 }
194
195 static uint32_t
getPlainRelocationAddress(const MachO::any_relocation_info & RE)196 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
197 return RE.r_word0;
198 }
199
200 static unsigned
getScatteredRelocationAddress(const MachO::any_relocation_info & RE)201 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
202 return RE.r_word0 & 0xffffff;
203 }
204
getPlainRelocationPCRel(const MachOObjectFile * O,const MachO::any_relocation_info & RE)205 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
206 const MachO::any_relocation_info &RE) {
207 if (O->isLittleEndian())
208 return (RE.r_word1 >> 24) & 1;
209 return (RE.r_word1 >> 7) & 1;
210 }
211
212 static bool
getScatteredRelocationPCRel(const MachOObjectFile * O,const MachO::any_relocation_info & RE)213 getScatteredRelocationPCRel(const MachOObjectFile *O,
214 const MachO::any_relocation_info &RE) {
215 return (RE.r_word0 >> 30) & 1;
216 }
217
getPlainRelocationLength(const MachOObjectFile * O,const MachO::any_relocation_info & RE)218 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
219 const MachO::any_relocation_info &RE) {
220 if (O->isLittleEndian())
221 return (RE.r_word1 >> 25) & 3;
222 return (RE.r_word1 >> 5) & 3;
223 }
224
225 static unsigned
getScatteredRelocationLength(const MachO::any_relocation_info & RE)226 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
227 return (RE.r_word0 >> 28) & 3;
228 }
229
getPlainRelocationType(const MachOObjectFile * O,const MachO::any_relocation_info & RE)230 static unsigned getPlainRelocationType(const MachOObjectFile *O,
231 const MachO::any_relocation_info &RE) {
232 if (O->isLittleEndian())
233 return RE.r_word1 >> 28;
234 return RE.r_word1 & 0xf;
235 }
236
getSectionFlags(const MachOObjectFile * O,DataRefImpl Sec)237 static uint32_t getSectionFlags(const MachOObjectFile *O,
238 DataRefImpl Sec) {
239 if (O->is64Bit()) {
240 MachO::section_64 Sect = O->getSection64(Sec);
241 return Sect.flags;
242 }
243 MachO::section Sect = O->getSection(Sec);
244 return Sect.flags;
245 }
246
MachOObjectFile(MemoryBufferRef Object,bool IsLittleEndian,bool Is64bits,std::error_code & EC)247 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
248 bool Is64bits, std::error_code &EC)
249 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
250 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
251 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
252 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
253 HasPageZeroSegment(false) {
254 uint32_t LoadCommandCount = this->getHeader().ncmds;
255 if (LoadCommandCount == 0)
256 return;
257
258 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
259 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
260
261 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
262 for (unsigned I = 0; ; ++I) {
263 if (Load.C.cmd == MachO::LC_SYMTAB) {
264 // Multiple symbol tables
265 if (SymtabLoadCmd) {
266 EC = object_error::parse_failed;
267 return;
268 }
269 SymtabLoadCmd = Load.Ptr;
270 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
271 // Multiple dynamic symbol tables
272 if (DysymtabLoadCmd) {
273 EC = object_error::parse_failed;
274 return;
275 }
276 DysymtabLoadCmd = Load.Ptr;
277 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
278 // Multiple data in code tables
279 if (DataInCodeLoadCmd) {
280 EC = object_error::parse_failed;
281 return;
282 }
283 DataInCodeLoadCmd = Load.Ptr;
284 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
285 // Multiple linker optimization hint tables
286 if (LinkOptHintsLoadCmd) {
287 EC = object_error::parse_failed;
288 return;
289 }
290 LinkOptHintsLoadCmd = Load.Ptr;
291 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
292 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
293 // Multiple dyldinfo load commands
294 if (DyldInfoLoadCmd) {
295 EC = object_error::parse_failed;
296 return;
297 }
298 DyldInfoLoadCmd = Load.Ptr;
299 } else if (Load.C.cmd == MachO::LC_UUID) {
300 // Multiple UUID load commands
301 if (UuidLoadCmd) {
302 EC = object_error::parse_failed;
303 return;
304 }
305 UuidLoadCmd = Load.Ptr;
306 } else if (Load.C.cmd == SegmentLoadType) {
307 const unsigned SegmentLoadSize = this->is64Bit()
308 ? sizeof(MachO::segment_command_64)
309 : sizeof(MachO::segment_command);
310 if (Load.C.cmdsize < SegmentLoadSize)
311 report_fatal_error("Segment load command size is too small.");
312
313 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
314 for (unsigned J = 0; J < NumSections; ++J) {
315 const char *Sec = getSectionPtr(this, Load, J);
316 Sections.push_back(Sec);
317 }
318 if (isPageZeroSegment(this, Load))
319 HasPageZeroSegment = true;
320 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
321 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
322 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
323 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
324 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
325 Libraries.push_back(Load.Ptr);
326 }
327
328 if (I == LoadCommandCount - 1)
329 break;
330 else
331 Load = getNextLoadCommandInfo(Load);
332 }
333 }
334
moveSymbolNext(DataRefImpl & Symb) const335 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
336 unsigned SymbolTableEntrySize = is64Bit() ?
337 sizeof(MachO::nlist_64) :
338 sizeof(MachO::nlist);
339 Symb.p += SymbolTableEntrySize;
340 }
341
getSymbolName(DataRefImpl Symb,StringRef & Res) const342 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
343 StringRef &Res) const {
344 StringRef StringTable = getStringTableData();
345 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
346 const char *Start = &StringTable.data()[Entry.n_strx];
347 if (Start < getData().begin() || Start >= getData().end())
348 report_fatal_error(
349 "Symbol name entry points before beginning or past end of file.");
350 Res = StringRef(Start);
351 return object_error::success;
352 }
353
getSectionType(SectionRef Sec) const354 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
355 DataRefImpl DRI = Sec.getRawDataRefImpl();
356 uint32_t Flags = getSectionFlags(this, DRI);
357 return Flags & MachO::SECTION_TYPE;
358 }
359
360 // getIndirectName() returns the name of the alias'ed symbol who's string table
361 // index is in the n_value field.
getIndirectName(DataRefImpl Symb,StringRef & Res) const362 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
363 StringRef &Res) const {
364 StringRef StringTable = getStringTableData();
365 uint64_t NValue;
366 if (is64Bit()) {
367 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
368 NValue = Entry.n_value;
369 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
370 return object_error::parse_failed;
371 } else {
372 MachO::nlist Entry = getSymbolTableEntry(Symb);
373 NValue = Entry.n_value;
374 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
375 return object_error::parse_failed;
376 }
377 if (NValue >= StringTable.size())
378 return object_error::parse_failed;
379 const char *Start = &StringTable.data()[NValue];
380 Res = StringRef(Start);
381 return object_error::success;
382 }
383
getSymbolAddress(DataRefImpl Symb,uint64_t & Res) const384 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
385 uint64_t &Res) const {
386 if (is64Bit()) {
387 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
388 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
389 Entry.n_value == 0)
390 Res = UnknownAddressOrSize;
391 else
392 Res = Entry.n_value;
393 } else {
394 MachO::nlist Entry = getSymbolTableEntry(Symb);
395 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
396 Entry.n_value == 0)
397 Res = UnknownAddressOrSize;
398 else
399 Res = Entry.n_value;
400 }
401 return object_error::success;
402 }
403
getSymbolAlignment(DataRefImpl DRI,uint32_t & Result) const404 std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
405 uint32_t &Result) const {
406 uint32_t flags = getSymbolFlags(DRI);
407 if (flags & SymbolRef::SF_Common) {
408 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
409 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
410 } else {
411 Result = 0;
412 }
413 return object_error::success;
414 }
415
getSymbolSize(DataRefImpl DRI,uint64_t & Result) const416 std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
417 uint64_t &Result) const {
418 uint64_t BeginOffset;
419 uint64_t EndOffset = 0;
420 uint8_t SectionIndex;
421
422 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
423 uint64_t Value;
424 getSymbolAddress(DRI, Value);
425 if (Value == UnknownAddressOrSize) {
426 Result = UnknownAddressOrSize;
427 return object_error::success;
428 }
429
430 BeginOffset = Value;
431
432 SectionIndex = Entry.n_sect;
433 if (!SectionIndex) {
434 uint32_t flags = getSymbolFlags(DRI);
435 if (flags & SymbolRef::SF_Common)
436 Result = Value;
437 else
438 Result = UnknownAddressOrSize;
439 return object_error::success;
440 }
441 // Unfortunately symbols are unsorted so we need to touch all
442 // symbols from load command
443 for (const SymbolRef &Symbol : symbols()) {
444 DataRefImpl DRI = Symbol.getRawDataRefImpl();
445 Entry = getSymbolTableEntryBase(this, DRI);
446 getSymbolAddress(DRI, Value);
447 if (Value == UnknownAddressOrSize)
448 continue;
449 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
450 if (!EndOffset || Value < EndOffset)
451 EndOffset = Value;
452 }
453 if (!EndOffset) {
454 DataRefImpl Sec;
455 Sec.d.a = SectionIndex-1;
456 uint64_t Size = getSectionSize(Sec);
457 EndOffset = getSectionAddress(Sec);
458 EndOffset += Size;
459 }
460 Result = EndOffset - BeginOffset;
461 return object_error::success;
462 }
463
getSymbolType(DataRefImpl Symb,SymbolRef::Type & Res) const464 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
465 SymbolRef::Type &Res) const {
466 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
467 uint8_t n_type = Entry.n_type;
468
469 Res = SymbolRef::ST_Other;
470
471 // If this is a STAB debugging symbol, we can do nothing more.
472 if (n_type & MachO::N_STAB) {
473 Res = SymbolRef::ST_Debug;
474 return object_error::success;
475 }
476
477 switch (n_type & MachO::N_TYPE) {
478 case MachO::N_UNDF :
479 Res = SymbolRef::ST_Unknown;
480 break;
481 case MachO::N_SECT :
482 Res = SymbolRef::ST_Function;
483 break;
484 }
485 return object_error::success;
486 }
487
getSymbolFlags(DataRefImpl DRI) const488 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
489 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
490
491 uint8_t MachOType = Entry.n_type;
492 uint16_t MachOFlags = Entry.n_desc;
493
494 uint32_t Result = SymbolRef::SF_None;
495
496 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
497 Result |= SymbolRef::SF_Undefined;
498
499 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
500 Result |= SymbolRef::SF_Indirect;
501
502 if (MachOType & MachO::N_STAB)
503 Result |= SymbolRef::SF_FormatSpecific;
504
505 if (MachOType & MachO::N_EXT) {
506 Result |= SymbolRef::SF_Global;
507 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
508 uint64_t Value;
509 getSymbolAddress(DRI, Value);
510 if (Value && Value != UnknownAddressOrSize)
511 Result |= SymbolRef::SF_Common;
512 }
513
514 if (!(MachOType & MachO::N_PEXT))
515 Result |= SymbolRef::SF_Exported;
516 }
517
518 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
519 Result |= SymbolRef::SF_Weak;
520
521 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
522 Result |= SymbolRef::SF_Thumb;
523
524 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
525 Result |= SymbolRef::SF_Absolute;
526
527 return Result;
528 }
529
getSymbolSection(DataRefImpl Symb,section_iterator & Res) const530 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
531 section_iterator &Res) const {
532 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
533 uint8_t index = Entry.n_sect;
534
535 if (index == 0) {
536 Res = section_end();
537 } else {
538 DataRefImpl DRI;
539 DRI.d.a = index - 1;
540 Res = section_iterator(SectionRef(DRI, this));
541 }
542
543 return object_error::success;
544 }
545
moveSectionNext(DataRefImpl & Sec) const546 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
547 Sec.d.a++;
548 }
549
getSectionName(DataRefImpl Sec,StringRef & Result) const550 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
551 StringRef &Result) const {
552 ArrayRef<char> Raw = getSectionRawName(Sec);
553 Result = parseSegmentOrSectionName(Raw.data());
554 return object_error::success;
555 }
556
getSectionAddress(DataRefImpl Sec) const557 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
558 if (is64Bit())
559 return getSection64(Sec).addr;
560 return getSection(Sec).addr;
561 }
562
getSectionSize(DataRefImpl Sec) const563 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
564 if (is64Bit())
565 return getSection64(Sec).size;
566 return getSection(Sec).size;
567 }
568
getSectionContents(DataRefImpl Sec,StringRef & Res) const569 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
570 StringRef &Res) const {
571 uint32_t Offset;
572 uint64_t Size;
573
574 if (is64Bit()) {
575 MachO::section_64 Sect = getSection64(Sec);
576 Offset = Sect.offset;
577 Size = Sect.size;
578 } else {
579 MachO::section Sect = getSection(Sec);
580 Offset = Sect.offset;
581 Size = Sect.size;
582 }
583
584 Res = this->getData().substr(Offset, Size);
585 return object_error::success;
586 }
587
getSectionAlignment(DataRefImpl Sec) const588 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
589 uint32_t Align;
590 if (is64Bit()) {
591 MachO::section_64 Sect = getSection64(Sec);
592 Align = Sect.align;
593 } else {
594 MachO::section Sect = getSection(Sec);
595 Align = Sect.align;
596 }
597
598 return uint64_t(1) << Align;
599 }
600
isSectionText(DataRefImpl Sec) const601 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
602 uint32_t Flags = getSectionFlags(this, Sec);
603 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
604 }
605
isSectionData(DataRefImpl Sec) const606 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
607 uint32_t Flags = getSectionFlags(this, Sec);
608 unsigned SectionType = Flags & MachO::SECTION_TYPE;
609 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
610 !(SectionType == MachO::S_ZEROFILL ||
611 SectionType == MachO::S_GB_ZEROFILL);
612 }
613
isSectionBSS(DataRefImpl Sec) const614 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
615 uint32_t Flags = getSectionFlags(this, Sec);
616 unsigned SectionType = Flags & MachO::SECTION_TYPE;
617 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
618 (SectionType == MachO::S_ZEROFILL ||
619 SectionType == MachO::S_GB_ZEROFILL);
620 }
621
isSectionVirtual(DataRefImpl Sec) const622 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
623 // FIXME: Unimplemented.
624 return false;
625 }
626
sectionContainsSymbol(DataRefImpl Sec,DataRefImpl Symb) const627 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
628 DataRefImpl Symb) const {
629 SymbolRef::Type ST;
630 this->getSymbolType(Symb, ST);
631 if (ST == SymbolRef::ST_Unknown)
632 return false;
633
634 uint64_t SectBegin = getSectionAddress(Sec);
635 uint64_t SectEnd = getSectionSize(Sec);
636 SectEnd += SectBegin;
637
638 uint64_t SymAddr;
639 getSymbolAddress(Symb, SymAddr);
640 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
641 }
642
section_rel_begin(DataRefImpl Sec) const643 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
644 DataRefImpl Ret;
645 Ret.d.a = Sec.d.a;
646 Ret.d.b = 0;
647 return relocation_iterator(RelocationRef(Ret, this));
648 }
649
650 relocation_iterator
section_rel_end(DataRefImpl Sec) const651 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
652 uint32_t Num;
653 if (is64Bit()) {
654 MachO::section_64 Sect = getSection64(Sec);
655 Num = Sect.nreloc;
656 } else {
657 MachO::section Sect = getSection(Sec);
658 Num = Sect.nreloc;
659 }
660
661 DataRefImpl Ret;
662 Ret.d.a = Sec.d.a;
663 Ret.d.b = Num;
664 return relocation_iterator(RelocationRef(Ret, this));
665 }
666
moveRelocationNext(DataRefImpl & Rel) const667 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
668 ++Rel.d.b;
669 }
670
getRelocationAddress(DataRefImpl Rel,uint64_t & Res) const671 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
672 uint64_t &Res) const {
673 uint64_t Offset;
674 getRelocationOffset(Rel, Offset);
675
676 DataRefImpl Sec;
677 Sec.d.a = Rel.d.a;
678 uint64_t SecAddress = getSectionAddress(Sec);
679 Res = SecAddress + Offset;
680 return object_error::success;
681 }
682
getRelocationOffset(DataRefImpl Rel,uint64_t & Res) const683 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
684 uint64_t &Res) const {
685 assert(getHeader().filetype == MachO::MH_OBJECT &&
686 "Only implemented for MH_OBJECT");
687 MachO::any_relocation_info RE = getRelocation(Rel);
688 Res = getAnyRelocationAddress(RE);
689 return object_error::success;
690 }
691
692 symbol_iterator
getRelocationSymbol(DataRefImpl Rel) const693 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
694 MachO::any_relocation_info RE = getRelocation(Rel);
695 if (isRelocationScattered(RE))
696 return symbol_end();
697
698 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
699 bool isExtern = getPlainRelocationExternal(RE);
700 if (!isExtern)
701 return symbol_end();
702
703 MachO::symtab_command S = getSymtabLoadCommand();
704 unsigned SymbolTableEntrySize = is64Bit() ?
705 sizeof(MachO::nlist_64) :
706 sizeof(MachO::nlist);
707 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
708 DataRefImpl Sym;
709 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
710 return symbol_iterator(SymbolRef(Sym, this));
711 }
712
getRelocationType(DataRefImpl Rel,uint64_t & Res) const713 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
714 uint64_t &Res) const {
715 MachO::any_relocation_info RE = getRelocation(Rel);
716 Res = getAnyRelocationType(RE);
717 return object_error::success;
718 }
719
720 std::error_code
getRelocationTypeName(DataRefImpl Rel,SmallVectorImpl<char> & Result) const721 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
722 SmallVectorImpl<char> &Result) const {
723 StringRef res;
724 uint64_t RType;
725 getRelocationType(Rel, RType);
726
727 unsigned Arch = this->getArch();
728
729 switch (Arch) {
730 case Triple::x86: {
731 static const char *const Table[] = {
732 "GENERIC_RELOC_VANILLA",
733 "GENERIC_RELOC_PAIR",
734 "GENERIC_RELOC_SECTDIFF",
735 "GENERIC_RELOC_PB_LA_PTR",
736 "GENERIC_RELOC_LOCAL_SECTDIFF",
737 "GENERIC_RELOC_TLV" };
738
739 if (RType > 5)
740 res = "Unknown";
741 else
742 res = Table[RType];
743 break;
744 }
745 case Triple::x86_64: {
746 static const char *const Table[] = {
747 "X86_64_RELOC_UNSIGNED",
748 "X86_64_RELOC_SIGNED",
749 "X86_64_RELOC_BRANCH",
750 "X86_64_RELOC_GOT_LOAD",
751 "X86_64_RELOC_GOT",
752 "X86_64_RELOC_SUBTRACTOR",
753 "X86_64_RELOC_SIGNED_1",
754 "X86_64_RELOC_SIGNED_2",
755 "X86_64_RELOC_SIGNED_4",
756 "X86_64_RELOC_TLV" };
757
758 if (RType > 9)
759 res = "Unknown";
760 else
761 res = Table[RType];
762 break;
763 }
764 case Triple::arm: {
765 static const char *const Table[] = {
766 "ARM_RELOC_VANILLA",
767 "ARM_RELOC_PAIR",
768 "ARM_RELOC_SECTDIFF",
769 "ARM_RELOC_LOCAL_SECTDIFF",
770 "ARM_RELOC_PB_LA_PTR",
771 "ARM_RELOC_BR24",
772 "ARM_THUMB_RELOC_BR22",
773 "ARM_THUMB_32BIT_BRANCH",
774 "ARM_RELOC_HALF",
775 "ARM_RELOC_HALF_SECTDIFF" };
776
777 if (RType > 9)
778 res = "Unknown";
779 else
780 res = Table[RType];
781 break;
782 }
783 case Triple::aarch64: {
784 static const char *const Table[] = {
785 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
786 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
787 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
788 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
789 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
790 "ARM64_RELOC_ADDEND"
791 };
792
793 if (RType >= array_lengthof(Table))
794 res = "Unknown";
795 else
796 res = Table[RType];
797 break;
798 }
799 case Triple::ppc: {
800 static const char *const Table[] = {
801 "PPC_RELOC_VANILLA",
802 "PPC_RELOC_PAIR",
803 "PPC_RELOC_BR14",
804 "PPC_RELOC_BR24",
805 "PPC_RELOC_HI16",
806 "PPC_RELOC_LO16",
807 "PPC_RELOC_HA16",
808 "PPC_RELOC_LO14",
809 "PPC_RELOC_SECTDIFF",
810 "PPC_RELOC_PB_LA_PTR",
811 "PPC_RELOC_HI16_SECTDIFF",
812 "PPC_RELOC_LO16_SECTDIFF",
813 "PPC_RELOC_HA16_SECTDIFF",
814 "PPC_RELOC_JBSR",
815 "PPC_RELOC_LO14_SECTDIFF",
816 "PPC_RELOC_LOCAL_SECTDIFF" };
817
818 if (RType > 15)
819 res = "Unknown";
820 else
821 res = Table[RType];
822 break;
823 }
824 case Triple::UnknownArch:
825 res = "Unknown";
826 break;
827 }
828 Result.append(res.begin(), res.end());
829 return object_error::success;
830 }
831
832 std::error_code
getRelocationValueString(DataRefImpl Rel,SmallVectorImpl<char> & Result) const833 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
834 SmallVectorImpl<char> &Result) const {
835 MachO::any_relocation_info RE = getRelocation(Rel);
836
837 unsigned Arch = this->getArch();
838
839 std::string fmtbuf;
840 raw_string_ostream fmt(fmtbuf);
841 unsigned Type = this->getAnyRelocationType(RE);
842 bool IsPCRel = this->getAnyRelocationPCRel(RE);
843
844 // Determine any addends that should be displayed with the relocation.
845 // These require decoding the relocation type, which is triple-specific.
846
847 // X86_64 has entirely custom relocation types.
848 if (Arch == Triple::x86_64) {
849 bool isPCRel = getAnyRelocationPCRel(RE);
850
851 switch (Type) {
852 case MachO::X86_64_RELOC_GOT_LOAD:
853 case MachO::X86_64_RELOC_GOT: {
854 printRelocationTargetName(this, RE, fmt);
855 fmt << "@GOT";
856 if (isPCRel) fmt << "PCREL";
857 break;
858 }
859 case MachO::X86_64_RELOC_SUBTRACTOR: {
860 DataRefImpl RelNext = Rel;
861 moveRelocationNext(RelNext);
862 MachO::any_relocation_info RENext = getRelocation(RelNext);
863
864 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
865 // X86_64_RELOC_UNSIGNED.
866 // NOTE: Scattered relocations don't exist on x86_64.
867 unsigned RType = getAnyRelocationType(RENext);
868 if (RType != MachO::X86_64_RELOC_UNSIGNED)
869 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
870 "X86_64_RELOC_SUBTRACTOR.");
871
872 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
873 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
874 printRelocationTargetName(this, RENext, fmt);
875 fmt << "-";
876 printRelocationTargetName(this, RE, fmt);
877 break;
878 }
879 case MachO::X86_64_RELOC_TLV:
880 printRelocationTargetName(this, RE, fmt);
881 fmt << "@TLV";
882 if (isPCRel) fmt << "P";
883 break;
884 case MachO::X86_64_RELOC_SIGNED_1:
885 printRelocationTargetName(this, RE, fmt);
886 fmt << "-1";
887 break;
888 case MachO::X86_64_RELOC_SIGNED_2:
889 printRelocationTargetName(this, RE, fmt);
890 fmt << "-2";
891 break;
892 case MachO::X86_64_RELOC_SIGNED_4:
893 printRelocationTargetName(this, RE, fmt);
894 fmt << "-4";
895 break;
896 default:
897 printRelocationTargetName(this, RE, fmt);
898 break;
899 }
900 // X86 and ARM share some relocation types in common.
901 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
902 Arch == Triple::ppc) {
903 // Generic relocation types...
904 switch (Type) {
905 case MachO::GENERIC_RELOC_PAIR: // prints no info
906 return object_error::success;
907 case MachO::GENERIC_RELOC_SECTDIFF: {
908 DataRefImpl RelNext = Rel;
909 moveRelocationNext(RelNext);
910 MachO::any_relocation_info RENext = getRelocation(RelNext);
911
912 // X86 sect diff's must be followed by a relocation of type
913 // GENERIC_RELOC_PAIR.
914 unsigned RType = getAnyRelocationType(RENext);
915
916 if (RType != MachO::GENERIC_RELOC_PAIR)
917 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
918 "GENERIC_RELOC_SECTDIFF.");
919
920 printRelocationTargetName(this, RE, fmt);
921 fmt << "-";
922 printRelocationTargetName(this, RENext, fmt);
923 break;
924 }
925 }
926
927 if (Arch == Triple::x86 || Arch == Triple::ppc) {
928 switch (Type) {
929 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
930 DataRefImpl RelNext = Rel;
931 moveRelocationNext(RelNext);
932 MachO::any_relocation_info RENext = getRelocation(RelNext);
933
934 // X86 sect diff's must be followed by a relocation of type
935 // GENERIC_RELOC_PAIR.
936 unsigned RType = getAnyRelocationType(RENext);
937 if (RType != MachO::GENERIC_RELOC_PAIR)
938 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
939 "GENERIC_RELOC_LOCAL_SECTDIFF.");
940
941 printRelocationTargetName(this, RE, fmt);
942 fmt << "-";
943 printRelocationTargetName(this, RENext, fmt);
944 break;
945 }
946 case MachO::GENERIC_RELOC_TLV: {
947 printRelocationTargetName(this, RE, fmt);
948 fmt << "@TLV";
949 if (IsPCRel) fmt << "P";
950 break;
951 }
952 default:
953 printRelocationTargetName(this, RE, fmt);
954 }
955 } else { // ARM-specific relocations
956 switch (Type) {
957 case MachO::ARM_RELOC_HALF:
958 case MachO::ARM_RELOC_HALF_SECTDIFF: {
959 // Half relocations steal a bit from the length field to encode
960 // whether this is an upper16 or a lower16 relocation.
961 bool isUpper = getAnyRelocationLength(RE) >> 1;
962
963 if (isUpper)
964 fmt << ":upper16:(";
965 else
966 fmt << ":lower16:(";
967 printRelocationTargetName(this, RE, fmt);
968
969 DataRefImpl RelNext = Rel;
970 moveRelocationNext(RelNext);
971 MachO::any_relocation_info RENext = getRelocation(RelNext);
972
973 // ARM half relocs must be followed by a relocation of type
974 // ARM_RELOC_PAIR.
975 unsigned RType = getAnyRelocationType(RENext);
976 if (RType != MachO::ARM_RELOC_PAIR)
977 report_fatal_error("Expected ARM_RELOC_PAIR after "
978 "ARM_RELOC_HALF");
979
980 // NOTE: The half of the target virtual address is stashed in the
981 // address field of the secondary relocation, but we can't reverse
982 // engineer the constant offset from it without decoding the movw/movt
983 // instruction to find the other half in its immediate field.
984
985 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
986 // symbol/section pointer of the follow-on relocation.
987 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
988 fmt << "-";
989 printRelocationTargetName(this, RENext, fmt);
990 }
991
992 fmt << ")";
993 break;
994 }
995 default: {
996 printRelocationTargetName(this, RE, fmt);
997 }
998 }
999 }
1000 } else
1001 printRelocationTargetName(this, RE, fmt);
1002
1003 fmt.flush();
1004 Result.append(fmtbuf.begin(), fmtbuf.end());
1005 return object_error::success;
1006 }
1007
getRelocationHidden(DataRefImpl Rel,bool & Result) const1008 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1009 bool &Result) const {
1010 unsigned Arch = getArch();
1011 uint64_t Type;
1012 getRelocationType(Rel, Type);
1013
1014 Result = false;
1015
1016 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1017 // is always hidden.
1018 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
1019 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
1020 } else if (Arch == Triple::x86_64) {
1021 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1022 // an X86_64_RELOC_SUBTRACTOR.
1023 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
1024 DataRefImpl RelPrev = Rel;
1025 RelPrev.d.a--;
1026 uint64_t PrevType;
1027 getRelocationType(RelPrev, PrevType);
1028 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
1029 Result = true;
1030 }
1031 }
1032
1033 return object_error::success;
1034 }
1035
1036 //
1037 // guessLibraryShortName() is passed a name of a dynamic library and returns a
1038 // guess on what the short name is. Then name is returned as a substring of the
1039 // StringRef Name passed in. The name of the dynamic library is recognized as
1040 // a framework if it has one of the two following forms:
1041 // Foo.framework/Versions/A/Foo
1042 // Foo.framework/Foo
1043 // Where A and Foo can be any string. And may contain a trailing suffix
1044 // starting with an underbar. If the Name is recognized as a framework then
1045 // isFramework is set to true else it is set to false. If the Name has a
1046 // suffix then Suffix is set to the substring in Name that contains the suffix
1047 // else it is set to a NULL StringRef.
1048 //
1049 // The Name of the dynamic library is recognized as a library name if it has
1050 // one of the two following forms:
1051 // libFoo.A.dylib
1052 // libFoo.dylib
1053 // The library may have a suffix trailing the name Foo of the form:
1054 // libFoo_profile.A.dylib
1055 // libFoo_profile.dylib
1056 //
1057 // The Name of the dynamic library is also recognized as a library name if it
1058 // has the following form:
1059 // Foo.qtx
1060 //
1061 // If the Name of the dynamic library is none of the forms above then a NULL
1062 // StringRef is returned.
1063 //
guessLibraryShortName(StringRef Name,bool & isFramework,StringRef & Suffix)1064 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1065 bool &isFramework,
1066 StringRef &Suffix) {
1067 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1068 size_t a, b, c, d, Idx;
1069
1070 isFramework = false;
1071 Suffix = StringRef();
1072
1073 // Pull off the last component and make Foo point to it
1074 a = Name.rfind('/');
1075 if (a == Name.npos || a == 0)
1076 goto guess_library;
1077 Foo = Name.slice(a+1, Name.npos);
1078
1079 // Look for a suffix starting with a '_'
1080 Idx = Foo.rfind('_');
1081 if (Idx != Foo.npos && Foo.size() >= 2) {
1082 Suffix = Foo.slice(Idx, Foo.npos);
1083 Foo = Foo.slice(0, Idx);
1084 }
1085
1086 // First look for the form Foo.framework/Foo
1087 b = Name.rfind('/', a);
1088 if (b == Name.npos)
1089 Idx = 0;
1090 else
1091 Idx = b+1;
1092 F = Name.slice(Idx, Idx + Foo.size());
1093 DotFramework = Name.slice(Idx + Foo.size(),
1094 Idx + Foo.size() + sizeof(".framework/")-1);
1095 if (F == Foo && DotFramework == ".framework/") {
1096 isFramework = true;
1097 return Foo;
1098 }
1099
1100 // Next look for the form Foo.framework/Versions/A/Foo
1101 if (b == Name.npos)
1102 goto guess_library;
1103 c = Name.rfind('/', b);
1104 if (c == Name.npos || c == 0)
1105 goto guess_library;
1106 V = Name.slice(c+1, Name.npos);
1107 if (!V.startswith("Versions/"))
1108 goto guess_library;
1109 d = Name.rfind('/', c);
1110 if (d == Name.npos)
1111 Idx = 0;
1112 else
1113 Idx = d+1;
1114 F = Name.slice(Idx, Idx + Foo.size());
1115 DotFramework = Name.slice(Idx + Foo.size(),
1116 Idx + Foo.size() + sizeof(".framework/")-1);
1117 if (F == Foo && DotFramework == ".framework/") {
1118 isFramework = true;
1119 return Foo;
1120 }
1121
1122 guess_library:
1123 // pull off the suffix after the "." and make a point to it
1124 a = Name.rfind('.');
1125 if (a == Name.npos || a == 0)
1126 return StringRef();
1127 Dylib = Name.slice(a, Name.npos);
1128 if (Dylib != ".dylib")
1129 goto guess_qtx;
1130
1131 // First pull off the version letter for the form Foo.A.dylib if any.
1132 if (a >= 3) {
1133 Dot = Name.slice(a-2, a-1);
1134 if (Dot == ".")
1135 a = a - 2;
1136 }
1137
1138 b = Name.rfind('/', a);
1139 if (b == Name.npos)
1140 b = 0;
1141 else
1142 b = b+1;
1143 // ignore any suffix after an underbar like Foo_profile.A.dylib
1144 Idx = Name.find('_', b);
1145 if (Idx != Name.npos && Idx != b) {
1146 Lib = Name.slice(b, Idx);
1147 Suffix = Name.slice(Idx, a);
1148 }
1149 else
1150 Lib = Name.slice(b, a);
1151 // There are incorrect library names of the form:
1152 // libATS.A_profile.dylib so check for these.
1153 if (Lib.size() >= 3) {
1154 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1155 if (Dot == ".")
1156 Lib = Lib.slice(0, Lib.size()-2);
1157 }
1158 return Lib;
1159
1160 guess_qtx:
1161 Qtx = Name.slice(a, Name.npos);
1162 if (Qtx != ".qtx")
1163 return StringRef();
1164 b = Name.rfind('/', a);
1165 if (b == Name.npos)
1166 Lib = Name.slice(0, a);
1167 else
1168 Lib = Name.slice(b+1, a);
1169 // There are library names of the form: QT.A.qtx so check for these.
1170 if (Lib.size() >= 3) {
1171 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1172 if (Dot == ".")
1173 Lib = Lib.slice(0, Lib.size()-2);
1174 }
1175 return Lib;
1176 }
1177
1178 // getLibraryShortNameByIndex() is used to get the short name of the library
1179 // for an undefined symbol in a linked Mach-O binary that was linked with the
1180 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
1181 // It is passed the index (0 - based) of the library as translated from
1182 // GET_LIBRARY_ORDINAL (1 - based).
getLibraryShortNameByIndex(unsigned Index,StringRef & Res) const1183 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1184 StringRef &Res) const {
1185 if (Index >= Libraries.size())
1186 return object_error::parse_failed;
1187
1188 // If the cache of LibrariesShortNames is not built up do that first for
1189 // all the Libraries.
1190 if (LibrariesShortNames.size() == 0) {
1191 for (unsigned i = 0; i < Libraries.size(); i++) {
1192 MachO::dylib_command D =
1193 getStruct<MachO::dylib_command>(this, Libraries[i]);
1194 if (D.dylib.name >= D.cmdsize)
1195 return object_error::parse_failed;
1196 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
1197 StringRef Name = StringRef(P);
1198 if (D.dylib.name+Name.size() >= D.cmdsize)
1199 return object_error::parse_failed;
1200 StringRef Suffix;
1201 bool isFramework;
1202 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1203 if (shortName.empty())
1204 LibrariesShortNames.push_back(Name);
1205 else
1206 LibrariesShortNames.push_back(shortName);
1207 }
1208 }
1209
1210 Res = LibrariesShortNames[Index];
1211 return object_error::success;
1212 }
1213
symbol_begin_impl() const1214 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1215 return getSymbolByIndex(0);
1216 }
1217
symbol_end_impl() const1218 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1219 DataRefImpl DRI;
1220 if (!SymtabLoadCmd)
1221 return basic_symbol_iterator(SymbolRef(DRI, this));
1222
1223 MachO::symtab_command Symtab = getSymtabLoadCommand();
1224 unsigned SymbolTableEntrySize = is64Bit() ?
1225 sizeof(MachO::nlist_64) :
1226 sizeof(MachO::nlist);
1227 unsigned Offset = Symtab.symoff +
1228 Symtab.nsyms * SymbolTableEntrySize;
1229 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1230 return basic_symbol_iterator(SymbolRef(DRI, this));
1231 }
1232
getSymbolByIndex(unsigned Index) const1233 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1234 DataRefImpl DRI;
1235 if (!SymtabLoadCmd)
1236 return basic_symbol_iterator(SymbolRef(DRI, this));
1237
1238 MachO::symtab_command Symtab = getSymtabLoadCommand();
1239 if (Index >= Symtab.nsyms)
1240 report_fatal_error("Requested symbol index is out of range.");
1241 unsigned SymbolTableEntrySize =
1242 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1243 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1244 DRI.p += Index * SymbolTableEntrySize;
1245 return basic_symbol_iterator(SymbolRef(DRI, this));
1246 }
1247
section_begin() const1248 section_iterator MachOObjectFile::section_begin() const {
1249 DataRefImpl DRI;
1250 return section_iterator(SectionRef(DRI, this));
1251 }
1252
section_end() const1253 section_iterator MachOObjectFile::section_end() const {
1254 DataRefImpl DRI;
1255 DRI.d.a = Sections.size();
1256 return section_iterator(SectionRef(DRI, this));
1257 }
1258
getBytesInAddress() const1259 uint8_t MachOObjectFile::getBytesInAddress() const {
1260 return is64Bit() ? 8 : 4;
1261 }
1262
getFileFormatName() const1263 StringRef MachOObjectFile::getFileFormatName() const {
1264 unsigned CPUType = getCPUType(this);
1265 if (!is64Bit()) {
1266 switch (CPUType) {
1267 case llvm::MachO::CPU_TYPE_I386:
1268 return "Mach-O 32-bit i386";
1269 case llvm::MachO::CPU_TYPE_ARM:
1270 return "Mach-O arm";
1271 case llvm::MachO::CPU_TYPE_POWERPC:
1272 return "Mach-O 32-bit ppc";
1273 default:
1274 return "Mach-O 32-bit unknown";
1275 }
1276 }
1277
1278 switch (CPUType) {
1279 case llvm::MachO::CPU_TYPE_X86_64:
1280 return "Mach-O 64-bit x86-64";
1281 case llvm::MachO::CPU_TYPE_ARM64:
1282 return "Mach-O arm64";
1283 case llvm::MachO::CPU_TYPE_POWERPC64:
1284 return "Mach-O 64-bit ppc64";
1285 default:
1286 return "Mach-O 64-bit unknown";
1287 }
1288 }
1289
getArch(uint32_t CPUType)1290 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1291 switch (CPUType) {
1292 case llvm::MachO::CPU_TYPE_I386:
1293 return Triple::x86;
1294 case llvm::MachO::CPU_TYPE_X86_64:
1295 return Triple::x86_64;
1296 case llvm::MachO::CPU_TYPE_ARM:
1297 return Triple::arm;
1298 case llvm::MachO::CPU_TYPE_ARM64:
1299 return Triple::aarch64;
1300 case llvm::MachO::CPU_TYPE_POWERPC:
1301 return Triple::ppc;
1302 case llvm::MachO::CPU_TYPE_POWERPC64:
1303 return Triple::ppc64;
1304 default:
1305 return Triple::UnknownArch;
1306 }
1307 }
1308
getArch(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault)1309 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1310 const char **McpuDefault) {
1311 if (McpuDefault)
1312 *McpuDefault = nullptr;
1313
1314 switch (CPUType) {
1315 case MachO::CPU_TYPE_I386:
1316 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1317 case MachO::CPU_SUBTYPE_I386_ALL:
1318 return Triple("i386-apple-darwin");
1319 default:
1320 return Triple();
1321 }
1322 case MachO::CPU_TYPE_X86_64:
1323 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1324 case MachO::CPU_SUBTYPE_X86_64_ALL:
1325 return Triple("x86_64-apple-darwin");
1326 case MachO::CPU_SUBTYPE_X86_64_H:
1327 return Triple("x86_64h-apple-darwin");
1328 default:
1329 return Triple();
1330 }
1331 case MachO::CPU_TYPE_ARM:
1332 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1333 case MachO::CPU_SUBTYPE_ARM_V4T:
1334 return Triple("armv4t-apple-darwin");
1335 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1336 return Triple("armv5e-apple-darwin");
1337 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1338 return Triple("xscale-apple-darwin");
1339 case MachO::CPU_SUBTYPE_ARM_V6:
1340 return Triple("armv6-apple-darwin");
1341 case MachO::CPU_SUBTYPE_ARM_V6M:
1342 if (McpuDefault)
1343 *McpuDefault = "cortex-m0";
1344 return Triple("armv6m-apple-darwin");
1345 case MachO::CPU_SUBTYPE_ARM_V7:
1346 return Triple("armv7-apple-darwin");
1347 case MachO::CPU_SUBTYPE_ARM_V7EM:
1348 if (McpuDefault)
1349 *McpuDefault = "cortex-m4";
1350 return Triple("armv7em-apple-darwin");
1351 case MachO::CPU_SUBTYPE_ARM_V7K:
1352 return Triple("armv7k-apple-darwin");
1353 case MachO::CPU_SUBTYPE_ARM_V7M:
1354 if (McpuDefault)
1355 *McpuDefault = "cortex-m3";
1356 return Triple("armv7m-apple-darwin");
1357 case MachO::CPU_SUBTYPE_ARM_V7S:
1358 return Triple("armv7s-apple-darwin");
1359 default:
1360 return Triple();
1361 }
1362 case MachO::CPU_TYPE_ARM64:
1363 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1364 case MachO::CPU_SUBTYPE_ARM64_ALL:
1365 return Triple("arm64-apple-darwin");
1366 default:
1367 return Triple();
1368 }
1369 case MachO::CPU_TYPE_POWERPC:
1370 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1371 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1372 return Triple("ppc-apple-darwin");
1373 default:
1374 return Triple();
1375 }
1376 case MachO::CPU_TYPE_POWERPC64:
1377 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1378 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1379 return Triple("ppc64-apple-darwin");
1380 default:
1381 return Triple();
1382 }
1383 default:
1384 return Triple();
1385 }
1386 }
1387
getThumbArch(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault)1388 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1389 const char **McpuDefault) {
1390 if (McpuDefault)
1391 *McpuDefault = nullptr;
1392
1393 switch (CPUType) {
1394 case MachO::CPU_TYPE_ARM:
1395 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1396 case MachO::CPU_SUBTYPE_ARM_V4T:
1397 return Triple("thumbv4t-apple-darwin");
1398 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1399 return Triple("thumbv5e-apple-darwin");
1400 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1401 return Triple("xscale-apple-darwin");
1402 case MachO::CPU_SUBTYPE_ARM_V6:
1403 return Triple("thumbv6-apple-darwin");
1404 case MachO::CPU_SUBTYPE_ARM_V6M:
1405 if (McpuDefault)
1406 *McpuDefault = "cortex-m0";
1407 return Triple("thumbv6m-apple-darwin");
1408 case MachO::CPU_SUBTYPE_ARM_V7:
1409 return Triple("thumbv7-apple-darwin");
1410 case MachO::CPU_SUBTYPE_ARM_V7EM:
1411 if (McpuDefault)
1412 *McpuDefault = "cortex-m4";
1413 return Triple("thumbv7em-apple-darwin");
1414 case MachO::CPU_SUBTYPE_ARM_V7K:
1415 return Triple("thumbv7k-apple-darwin");
1416 case MachO::CPU_SUBTYPE_ARM_V7M:
1417 if (McpuDefault)
1418 *McpuDefault = "cortex-m3";
1419 return Triple("thumbv7m-apple-darwin");
1420 case MachO::CPU_SUBTYPE_ARM_V7S:
1421 return Triple("thumbv7s-apple-darwin");
1422 default:
1423 return Triple();
1424 }
1425 default:
1426 return Triple();
1427 }
1428 }
1429
getArch(uint32_t CPUType,uint32_t CPUSubType,const char ** McpuDefault,Triple * ThumbTriple)1430 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1431 const char **McpuDefault,
1432 Triple *ThumbTriple) {
1433 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1434 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1435 McpuDefault);
1436 return T;
1437 }
1438
getHostArch()1439 Triple MachOObjectFile::getHostArch() {
1440 return Triple(sys::getDefaultTargetTriple());
1441 }
1442
isValidArch(StringRef ArchFlag)1443 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1444 return StringSwitch<bool>(ArchFlag)
1445 .Case("i386", true)
1446 .Case("x86_64", true)
1447 .Case("x86_64h", true)
1448 .Case("armv4t", true)
1449 .Case("arm", true)
1450 .Case("armv5e", true)
1451 .Case("armv6", true)
1452 .Case("armv6m", true)
1453 .Case("armv7em", true)
1454 .Case("armv7k", true)
1455 .Case("armv7m", true)
1456 .Case("armv7s", true)
1457 .Case("arm64", true)
1458 .Case("ppc", true)
1459 .Case("ppc64", true)
1460 .Default(false);
1461 }
1462
getArch() const1463 unsigned MachOObjectFile::getArch() const {
1464 return getArch(getCPUType(this));
1465 }
1466
getArch(const char ** McpuDefault,Triple * ThumbTriple) const1467 Triple MachOObjectFile::getArch(const char **McpuDefault,
1468 Triple *ThumbTriple) const {
1469 Triple T;
1470 if (is64Bit()) {
1471 MachO::mach_header_64 H_64;
1472 H_64 = getHeader64();
1473 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1474 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1475 McpuDefault);
1476 } else {
1477 MachO::mach_header H;
1478 H = getHeader();
1479 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1480 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1481 McpuDefault);
1482 }
1483 return T;
1484 }
1485
section_rel_begin(unsigned Index) const1486 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1487 DataRefImpl DRI;
1488 DRI.d.a = Index;
1489 return section_rel_begin(DRI);
1490 }
1491
section_rel_end(unsigned Index) const1492 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1493 DataRefImpl DRI;
1494 DRI.d.a = Index;
1495 return section_rel_end(DRI);
1496 }
1497
begin_dices() const1498 dice_iterator MachOObjectFile::begin_dices() const {
1499 DataRefImpl DRI;
1500 if (!DataInCodeLoadCmd)
1501 return dice_iterator(DiceRef(DRI, this));
1502
1503 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1504 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1505 return dice_iterator(DiceRef(DRI, this));
1506 }
1507
end_dices() const1508 dice_iterator MachOObjectFile::end_dices() const {
1509 DataRefImpl DRI;
1510 if (!DataInCodeLoadCmd)
1511 return dice_iterator(DiceRef(DRI, this));
1512
1513 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1514 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1515 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1516 return dice_iterator(DiceRef(DRI, this));
1517 }
1518
ExportEntry(ArrayRef<uint8_t> T)1519 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1520 : Trie(T), Malformed(false), Done(false) { }
1521
moveToFirst()1522 void ExportEntry::moveToFirst() {
1523 pushNode(0);
1524 pushDownUntilBottom();
1525 }
1526
moveToEnd()1527 void ExportEntry::moveToEnd() {
1528 Stack.clear();
1529 Done = true;
1530 }
1531
operator ==(const ExportEntry & Other) const1532 bool ExportEntry::operator==(const ExportEntry &Other) const {
1533 // Common case, one at end, other iterating from begin.
1534 if (Done || Other.Done)
1535 return (Done == Other.Done);
1536 // Not equal if different stack sizes.
1537 if (Stack.size() != Other.Stack.size())
1538 return false;
1539 // Not equal if different cumulative strings.
1540 if (!CumulativeString.equals(Other.CumulativeString))
1541 return false;
1542 // Equal if all nodes in both stacks match.
1543 for (unsigned i=0; i < Stack.size(); ++i) {
1544 if (Stack[i].Start != Other.Stack[i].Start)
1545 return false;
1546 }
1547 return true;
1548 }
1549
readULEB128(const uint8_t * & Ptr)1550 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1551 unsigned Count;
1552 uint64_t Result = decodeULEB128(Ptr, &Count);
1553 Ptr += Count;
1554 if (Ptr > Trie.end()) {
1555 Ptr = Trie.end();
1556 Malformed = true;
1557 }
1558 return Result;
1559 }
1560
name() const1561 StringRef ExportEntry::name() const {
1562 return CumulativeString;
1563 }
1564
flags() const1565 uint64_t ExportEntry::flags() const {
1566 return Stack.back().Flags;
1567 }
1568
address() const1569 uint64_t ExportEntry::address() const {
1570 return Stack.back().Address;
1571 }
1572
other() const1573 uint64_t ExportEntry::other() const {
1574 return Stack.back().Other;
1575 }
1576
otherName() const1577 StringRef ExportEntry::otherName() const {
1578 const char* ImportName = Stack.back().ImportName;
1579 if (ImportName)
1580 return StringRef(ImportName);
1581 return StringRef();
1582 }
1583
nodeOffset() const1584 uint32_t ExportEntry::nodeOffset() const {
1585 return Stack.back().Start - Trie.begin();
1586 }
1587
NodeState(const uint8_t * Ptr)1588 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1589 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1590 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1591 ParentStringLength(0), IsExportNode(false) {
1592 }
1593
pushNode(uint64_t offset)1594 void ExportEntry::pushNode(uint64_t offset) {
1595 const uint8_t *Ptr = Trie.begin() + offset;
1596 NodeState State(Ptr);
1597 uint64_t ExportInfoSize = readULEB128(State.Current);
1598 State.IsExportNode = (ExportInfoSize != 0);
1599 const uint8_t* Children = State.Current + ExportInfoSize;
1600 if (State.IsExportNode) {
1601 State.Flags = readULEB128(State.Current);
1602 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1603 State.Address = 0;
1604 State.Other = readULEB128(State.Current); // dylib ordinal
1605 State.ImportName = reinterpret_cast<const char*>(State.Current);
1606 } else {
1607 State.Address = readULEB128(State.Current);
1608 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1609 State.Other = readULEB128(State.Current);
1610 }
1611 }
1612 State.ChildCount = *Children;
1613 State.Current = Children + 1;
1614 State.NextChildIndex = 0;
1615 State.ParentStringLength = CumulativeString.size();
1616 Stack.push_back(State);
1617 }
1618
pushDownUntilBottom()1619 void ExportEntry::pushDownUntilBottom() {
1620 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1621 NodeState &Top = Stack.back();
1622 CumulativeString.resize(Top.ParentStringLength);
1623 for (;*Top.Current != 0; Top.Current++) {
1624 char C = *Top.Current;
1625 CumulativeString.push_back(C);
1626 }
1627 Top.Current += 1;
1628 uint64_t childNodeIndex = readULEB128(Top.Current);
1629 Top.NextChildIndex += 1;
1630 pushNode(childNodeIndex);
1631 }
1632 if (!Stack.back().IsExportNode) {
1633 Malformed = true;
1634 moveToEnd();
1635 }
1636 }
1637
1638 // We have a trie data structure and need a way to walk it that is compatible
1639 // with the C++ iterator model. The solution is a non-recursive depth first
1640 // traversal where the iterator contains a stack of parent nodes along with a
1641 // string that is the accumulation of all edge strings along the parent chain
1642 // to this point.
1643 //
1644 // There is one "export" node for each exported symbol. But because some
1645 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1646 // node may have child nodes too.
1647 //
1648 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1649 // child until hitting a node with no children (which is an export node or
1650 // else the trie is malformed). On the way down, each node is pushed on the
1651 // stack ivar. If there is no more ways down, it pops up one and tries to go
1652 // down a sibling path until a childless node is reached.
moveNext()1653 void ExportEntry::moveNext() {
1654 if (Stack.empty() || !Stack.back().IsExportNode) {
1655 Malformed = true;
1656 moveToEnd();
1657 return;
1658 }
1659
1660 Stack.pop_back();
1661 while (!Stack.empty()) {
1662 NodeState &Top = Stack.back();
1663 if (Top.NextChildIndex < Top.ChildCount) {
1664 pushDownUntilBottom();
1665 // Now at the next export node.
1666 return;
1667 } else {
1668 if (Top.IsExportNode) {
1669 // This node has no children but is itself an export node.
1670 CumulativeString.resize(Top.ParentStringLength);
1671 return;
1672 }
1673 Stack.pop_back();
1674 }
1675 }
1676 Done = true;
1677 }
1678
1679 iterator_range<export_iterator>
exports(ArrayRef<uint8_t> Trie)1680 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1681 ExportEntry Start(Trie);
1682 if (Trie.size() == 0)
1683 Start.moveToEnd();
1684 else
1685 Start.moveToFirst();
1686
1687 ExportEntry Finish(Trie);
1688 Finish.moveToEnd();
1689
1690 return iterator_range<export_iterator>(export_iterator(Start),
1691 export_iterator(Finish));
1692 }
1693
exports() const1694 iterator_range<export_iterator> MachOObjectFile::exports() const {
1695 return exports(getDyldInfoExportsTrie());
1696 }
1697
1698
MachORebaseEntry(ArrayRef<uint8_t> Bytes,bool is64Bit)1699 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1700 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1701 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1702 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1703
moveToFirst()1704 void MachORebaseEntry::moveToFirst() {
1705 Ptr = Opcodes.begin();
1706 moveNext();
1707 }
1708
moveToEnd()1709 void MachORebaseEntry::moveToEnd() {
1710 Ptr = Opcodes.end();
1711 RemainingLoopCount = 0;
1712 Done = true;
1713 }
1714
moveNext()1715 void MachORebaseEntry::moveNext() {
1716 // If in the middle of some loop, move to next rebasing in loop.
1717 SegmentOffset += AdvanceAmount;
1718 if (RemainingLoopCount) {
1719 --RemainingLoopCount;
1720 return;
1721 }
1722 if (Ptr == Opcodes.end()) {
1723 Done = true;
1724 return;
1725 }
1726 bool More = true;
1727 while (More && !Malformed) {
1728 // Parse next opcode and set up next loop.
1729 uint8_t Byte = *Ptr++;
1730 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1731 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1732 switch (Opcode) {
1733 case MachO::REBASE_OPCODE_DONE:
1734 More = false;
1735 Done = true;
1736 moveToEnd();
1737 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1738 break;
1739 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1740 RebaseType = ImmValue;
1741 DEBUG_WITH_TYPE(
1742 "mach-o-rebase",
1743 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1744 << "RebaseType=" << (int) RebaseType << "\n");
1745 break;
1746 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1747 SegmentIndex = ImmValue;
1748 SegmentOffset = readULEB128();
1749 DEBUG_WITH_TYPE(
1750 "mach-o-rebase",
1751 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1752 << "SegmentIndex=" << SegmentIndex << ", "
1753 << format("SegmentOffset=0x%06X", SegmentOffset)
1754 << "\n");
1755 break;
1756 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1757 SegmentOffset += readULEB128();
1758 DEBUG_WITH_TYPE("mach-o-rebase",
1759 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1760 << format("SegmentOffset=0x%06X",
1761 SegmentOffset) << "\n");
1762 break;
1763 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1764 SegmentOffset += ImmValue * PointerSize;
1765 DEBUG_WITH_TYPE("mach-o-rebase",
1766 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1767 << format("SegmentOffset=0x%06X",
1768 SegmentOffset) << "\n");
1769 break;
1770 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1771 AdvanceAmount = PointerSize;
1772 RemainingLoopCount = ImmValue - 1;
1773 DEBUG_WITH_TYPE(
1774 "mach-o-rebase",
1775 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1776 << format("SegmentOffset=0x%06X", SegmentOffset)
1777 << ", AdvanceAmount=" << AdvanceAmount
1778 << ", RemainingLoopCount=" << RemainingLoopCount
1779 << "\n");
1780 return;
1781 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1782 AdvanceAmount = PointerSize;
1783 RemainingLoopCount = readULEB128() - 1;
1784 DEBUG_WITH_TYPE(
1785 "mach-o-rebase",
1786 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1787 << format("SegmentOffset=0x%06X", SegmentOffset)
1788 << ", AdvanceAmount=" << AdvanceAmount
1789 << ", RemainingLoopCount=" << RemainingLoopCount
1790 << "\n");
1791 return;
1792 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1793 AdvanceAmount = readULEB128() + PointerSize;
1794 RemainingLoopCount = 0;
1795 DEBUG_WITH_TYPE(
1796 "mach-o-rebase",
1797 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1798 << format("SegmentOffset=0x%06X", SegmentOffset)
1799 << ", AdvanceAmount=" << AdvanceAmount
1800 << ", RemainingLoopCount=" << RemainingLoopCount
1801 << "\n");
1802 return;
1803 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1804 RemainingLoopCount = readULEB128() - 1;
1805 AdvanceAmount = readULEB128() + PointerSize;
1806 DEBUG_WITH_TYPE(
1807 "mach-o-rebase",
1808 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1809 << format("SegmentOffset=0x%06X", SegmentOffset)
1810 << ", AdvanceAmount=" << AdvanceAmount
1811 << ", RemainingLoopCount=" << RemainingLoopCount
1812 << "\n");
1813 return;
1814 default:
1815 Malformed = true;
1816 }
1817 }
1818 }
1819
readULEB128()1820 uint64_t MachORebaseEntry::readULEB128() {
1821 unsigned Count;
1822 uint64_t Result = decodeULEB128(Ptr, &Count);
1823 Ptr += Count;
1824 if (Ptr > Opcodes.end()) {
1825 Ptr = Opcodes.end();
1826 Malformed = true;
1827 }
1828 return Result;
1829 }
1830
segmentIndex() const1831 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1832
segmentOffset() const1833 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1834
typeName() const1835 StringRef MachORebaseEntry::typeName() const {
1836 switch (RebaseType) {
1837 case MachO::REBASE_TYPE_POINTER:
1838 return "pointer";
1839 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1840 return "text abs32";
1841 case MachO::REBASE_TYPE_TEXT_PCREL32:
1842 return "text rel32";
1843 }
1844 return "unknown";
1845 }
1846
operator ==(const MachORebaseEntry & Other) const1847 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1848 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1849 return (Ptr == Other.Ptr) &&
1850 (RemainingLoopCount == Other.RemainingLoopCount) &&
1851 (Done == Other.Done);
1852 }
1853
1854 iterator_range<rebase_iterator>
rebaseTable(ArrayRef<uint8_t> Opcodes,bool is64)1855 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1856 MachORebaseEntry Start(Opcodes, is64);
1857 Start.moveToFirst();
1858
1859 MachORebaseEntry Finish(Opcodes, is64);
1860 Finish.moveToEnd();
1861
1862 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1863 rebase_iterator(Finish));
1864 }
1865
rebaseTable() const1866 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1867 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1868 }
1869
1870
MachOBindEntry(ArrayRef<uint8_t> Bytes,bool is64Bit,Kind BK)1871 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1872 Kind BK)
1873 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1874 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1875 BindType(0), PointerSize(is64Bit ? 8 : 4),
1876 TableKind(BK), Malformed(false), Done(false) {}
1877
moveToFirst()1878 void MachOBindEntry::moveToFirst() {
1879 Ptr = Opcodes.begin();
1880 moveNext();
1881 }
1882
moveToEnd()1883 void MachOBindEntry::moveToEnd() {
1884 Ptr = Opcodes.end();
1885 RemainingLoopCount = 0;
1886 Done = true;
1887 }
1888
moveNext()1889 void MachOBindEntry::moveNext() {
1890 // If in the middle of some loop, move to next binding in loop.
1891 SegmentOffset += AdvanceAmount;
1892 if (RemainingLoopCount) {
1893 --RemainingLoopCount;
1894 return;
1895 }
1896 if (Ptr == Opcodes.end()) {
1897 Done = true;
1898 return;
1899 }
1900 bool More = true;
1901 while (More && !Malformed) {
1902 // Parse next opcode and set up next loop.
1903 uint8_t Byte = *Ptr++;
1904 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1905 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1906 int8_t SignExtended;
1907 const uint8_t *SymStart;
1908 switch (Opcode) {
1909 case MachO::BIND_OPCODE_DONE:
1910 if (TableKind == Kind::Lazy) {
1911 // Lazying bindings have a DONE opcode between entries. Need to ignore
1912 // it to advance to next entry. But need not if this is last entry.
1913 bool NotLastEntry = false;
1914 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1915 if (*P) {
1916 NotLastEntry = true;
1917 }
1918 }
1919 if (NotLastEntry)
1920 break;
1921 }
1922 More = false;
1923 Done = true;
1924 moveToEnd();
1925 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1926 break;
1927 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1928 Ordinal = ImmValue;
1929 DEBUG_WITH_TYPE(
1930 "mach-o-bind",
1931 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1932 << "Ordinal=" << Ordinal << "\n");
1933 break;
1934 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1935 Ordinal = readULEB128();
1936 DEBUG_WITH_TYPE(
1937 "mach-o-bind",
1938 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1939 << "Ordinal=" << Ordinal << "\n");
1940 break;
1941 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1942 if (ImmValue) {
1943 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1944 Ordinal = SignExtended;
1945 } else
1946 Ordinal = 0;
1947 DEBUG_WITH_TYPE(
1948 "mach-o-bind",
1949 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1950 << "Ordinal=" << Ordinal << "\n");
1951 break;
1952 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1953 Flags = ImmValue;
1954 SymStart = Ptr;
1955 while (*Ptr) {
1956 ++Ptr;
1957 }
1958 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1959 Ptr-SymStart);
1960 ++Ptr;
1961 DEBUG_WITH_TYPE(
1962 "mach-o-bind",
1963 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1964 << "SymbolName=" << SymbolName << "\n");
1965 if (TableKind == Kind::Weak) {
1966 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1967 return;
1968 }
1969 break;
1970 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1971 BindType = ImmValue;
1972 DEBUG_WITH_TYPE(
1973 "mach-o-bind",
1974 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1975 << "BindType=" << (int)BindType << "\n");
1976 break;
1977 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1978 Addend = readSLEB128();
1979 if (TableKind == Kind::Lazy)
1980 Malformed = true;
1981 DEBUG_WITH_TYPE(
1982 "mach-o-bind",
1983 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1984 << "Addend=" << Addend << "\n");
1985 break;
1986 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1987 SegmentIndex = ImmValue;
1988 SegmentOffset = readULEB128();
1989 DEBUG_WITH_TYPE(
1990 "mach-o-bind",
1991 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1992 << "SegmentIndex=" << SegmentIndex << ", "
1993 << format("SegmentOffset=0x%06X", SegmentOffset)
1994 << "\n");
1995 break;
1996 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1997 SegmentOffset += readULEB128();
1998 DEBUG_WITH_TYPE("mach-o-bind",
1999 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
2000 << format("SegmentOffset=0x%06X",
2001 SegmentOffset) << "\n");
2002 break;
2003 case MachO::BIND_OPCODE_DO_BIND:
2004 AdvanceAmount = PointerSize;
2005 RemainingLoopCount = 0;
2006 DEBUG_WITH_TYPE("mach-o-bind",
2007 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
2008 << format("SegmentOffset=0x%06X",
2009 SegmentOffset) << "\n");
2010 return;
2011 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
2012 AdvanceAmount = readULEB128() + PointerSize;
2013 RemainingLoopCount = 0;
2014 if (TableKind == Kind::Lazy)
2015 Malformed = true;
2016 DEBUG_WITH_TYPE(
2017 "mach-o-bind",
2018 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
2019 << format("SegmentOffset=0x%06X", SegmentOffset)
2020 << ", AdvanceAmount=" << AdvanceAmount
2021 << ", RemainingLoopCount=" << RemainingLoopCount
2022 << "\n");
2023 return;
2024 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
2025 AdvanceAmount = ImmValue * PointerSize + PointerSize;
2026 RemainingLoopCount = 0;
2027 if (TableKind == Kind::Lazy)
2028 Malformed = true;
2029 DEBUG_WITH_TYPE("mach-o-bind",
2030 llvm::dbgs()
2031 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
2032 << format("SegmentOffset=0x%06X",
2033 SegmentOffset) << "\n");
2034 return;
2035 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2036 RemainingLoopCount = readULEB128() - 1;
2037 AdvanceAmount = readULEB128() + PointerSize;
2038 if (TableKind == Kind::Lazy)
2039 Malformed = true;
2040 DEBUG_WITH_TYPE(
2041 "mach-o-bind",
2042 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2043 << format("SegmentOffset=0x%06X", SegmentOffset)
2044 << ", AdvanceAmount=" << AdvanceAmount
2045 << ", RemainingLoopCount=" << RemainingLoopCount
2046 << "\n");
2047 return;
2048 default:
2049 Malformed = true;
2050 }
2051 }
2052 }
2053
readULEB128()2054 uint64_t MachOBindEntry::readULEB128() {
2055 unsigned Count;
2056 uint64_t Result = decodeULEB128(Ptr, &Count);
2057 Ptr += Count;
2058 if (Ptr > Opcodes.end()) {
2059 Ptr = Opcodes.end();
2060 Malformed = true;
2061 }
2062 return Result;
2063 }
2064
readSLEB128()2065 int64_t MachOBindEntry::readSLEB128() {
2066 unsigned Count;
2067 int64_t Result = decodeSLEB128(Ptr, &Count);
2068 Ptr += Count;
2069 if (Ptr > Opcodes.end()) {
2070 Ptr = Opcodes.end();
2071 Malformed = true;
2072 }
2073 return Result;
2074 }
2075
2076
segmentIndex() const2077 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2078
segmentOffset() const2079 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2080
typeName() const2081 StringRef MachOBindEntry::typeName() const {
2082 switch (BindType) {
2083 case MachO::BIND_TYPE_POINTER:
2084 return "pointer";
2085 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2086 return "text abs32";
2087 case MachO::BIND_TYPE_TEXT_PCREL32:
2088 return "text rel32";
2089 }
2090 return "unknown";
2091 }
2092
symbolName() const2093 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2094
addend() const2095 int64_t MachOBindEntry::addend() const { return Addend; }
2096
flags() const2097 uint32_t MachOBindEntry::flags() const { return Flags; }
2098
ordinal() const2099 int MachOBindEntry::ordinal() const { return Ordinal; }
2100
operator ==(const MachOBindEntry & Other) const2101 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2102 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2103 return (Ptr == Other.Ptr) &&
2104 (RemainingLoopCount == Other.RemainingLoopCount) &&
2105 (Done == Other.Done);
2106 }
2107
2108 iterator_range<bind_iterator>
bindTable(ArrayRef<uint8_t> Opcodes,bool is64,MachOBindEntry::Kind BKind)2109 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2110 MachOBindEntry::Kind BKind) {
2111 MachOBindEntry Start(Opcodes, is64, BKind);
2112 Start.moveToFirst();
2113
2114 MachOBindEntry Finish(Opcodes, is64, BKind);
2115 Finish.moveToEnd();
2116
2117 return iterator_range<bind_iterator>(bind_iterator(Start),
2118 bind_iterator(Finish));
2119 }
2120
bindTable() const2121 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2122 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2123 MachOBindEntry::Kind::Regular);
2124 }
2125
lazyBindTable() const2126 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2127 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2128 MachOBindEntry::Kind::Lazy);
2129 }
2130
weakBindTable() const2131 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2132 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2133 MachOBindEntry::Kind::Weak);
2134 }
2135
2136 StringRef
getSectionFinalSegmentName(DataRefImpl Sec) const2137 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2138 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2139 return parseSegmentOrSectionName(Raw.data());
2140 }
2141
2142 ArrayRef<char>
getSectionRawName(DataRefImpl Sec) const2143 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
2144 if (Sec.d.a >= Sections.size())
2145 report_fatal_error("getSectionRawName: Invalid section index");
2146 const section_base *Base =
2147 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2148 return makeArrayRef(Base->sectname);
2149 }
2150
2151 ArrayRef<char>
getSectionRawFinalSegmentName(DataRefImpl Sec) const2152 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
2153 if (Sec.d.a >= Sections.size())
2154 report_fatal_error("getSectionRawFinalSegmentName: Invalid section index");
2155 const section_base *Base =
2156 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2157 return makeArrayRef(Base->segname);
2158 }
2159
2160 bool
isRelocationScattered(const MachO::any_relocation_info & RE) const2161 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
2162 const {
2163 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
2164 return false;
2165 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
2166 }
2167
getPlainRelocationSymbolNum(const MachO::any_relocation_info & RE) const2168 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
2169 const MachO::any_relocation_info &RE) const {
2170 if (isLittleEndian())
2171 return RE.r_word1 & 0xffffff;
2172 return RE.r_word1 >> 8;
2173 }
2174
getPlainRelocationExternal(const MachO::any_relocation_info & RE) const2175 bool MachOObjectFile::getPlainRelocationExternal(
2176 const MachO::any_relocation_info &RE) const {
2177 if (isLittleEndian())
2178 return (RE.r_word1 >> 27) & 1;
2179 return (RE.r_word1 >> 4) & 1;
2180 }
2181
getScatteredRelocationScattered(const MachO::any_relocation_info & RE) const2182 bool MachOObjectFile::getScatteredRelocationScattered(
2183 const MachO::any_relocation_info &RE) const {
2184 return RE.r_word0 >> 31;
2185 }
2186
getScatteredRelocationValue(const MachO::any_relocation_info & RE) const2187 uint32_t MachOObjectFile::getScatteredRelocationValue(
2188 const MachO::any_relocation_info &RE) const {
2189 return RE.r_word1;
2190 }
2191
getScatteredRelocationType(const MachO::any_relocation_info & RE) const2192 uint32_t MachOObjectFile::getScatteredRelocationType(
2193 const MachO::any_relocation_info &RE) const {
2194 return (RE.r_word0 >> 24) & 0xf;
2195 }
2196
getAnyRelocationAddress(const MachO::any_relocation_info & RE) const2197 unsigned MachOObjectFile::getAnyRelocationAddress(
2198 const MachO::any_relocation_info &RE) const {
2199 if (isRelocationScattered(RE))
2200 return getScatteredRelocationAddress(RE);
2201 return getPlainRelocationAddress(RE);
2202 }
2203
getAnyRelocationPCRel(const MachO::any_relocation_info & RE) const2204 unsigned MachOObjectFile::getAnyRelocationPCRel(
2205 const MachO::any_relocation_info &RE) const {
2206 if (isRelocationScattered(RE))
2207 return getScatteredRelocationPCRel(this, RE);
2208 return getPlainRelocationPCRel(this, RE);
2209 }
2210
getAnyRelocationLength(const MachO::any_relocation_info & RE) const2211 unsigned MachOObjectFile::getAnyRelocationLength(
2212 const MachO::any_relocation_info &RE) const {
2213 if (isRelocationScattered(RE))
2214 return getScatteredRelocationLength(RE);
2215 return getPlainRelocationLength(this, RE);
2216 }
2217
2218 unsigned
getAnyRelocationType(const MachO::any_relocation_info & RE) const2219 MachOObjectFile::getAnyRelocationType(
2220 const MachO::any_relocation_info &RE) const {
2221 if (isRelocationScattered(RE))
2222 return getScatteredRelocationType(RE);
2223 return getPlainRelocationType(this, RE);
2224 }
2225
2226 SectionRef
getRelocationSection(const MachO::any_relocation_info & RE) const2227 MachOObjectFile::getRelocationSection(
2228 const MachO::any_relocation_info &RE) const {
2229 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2230 return *section_end();
2231 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2232 DataRefImpl DRI;
2233 DRI.d.a = SecNum;
2234 return SectionRef(DRI, this);
2235 }
2236
2237 MachOObjectFile::LoadCommandInfo
getFirstLoadCommandInfo() const2238 MachOObjectFile::getFirstLoadCommandInfo() const {
2239 MachOObjectFile::LoadCommandInfo Load;
2240
2241 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2242 sizeof(MachO::mach_header);
2243 Load.Ptr = getPtr(this, HeaderSize);
2244 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
2245 if (Load.C.cmdsize < 8)
2246 report_fatal_error("Load command with size < 8 bytes.");
2247 return Load;
2248 }
2249
2250 MachOObjectFile::LoadCommandInfo
getNextLoadCommandInfo(const LoadCommandInfo & L) const2251 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2252 MachOObjectFile::LoadCommandInfo Next;
2253 Next.Ptr = L.Ptr + L.C.cmdsize;
2254 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
2255 if (Next.C.cmdsize < 8)
2256 report_fatal_error("Load command with size < 8 bytes.");
2257 return Next;
2258 }
2259
getSection(DataRefImpl DRI) const2260 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2261 // TODO: What if Sections.size() == 0?
2262 if (DRI.d.a >= Sections.size())
2263 report_fatal_error("getSection: Invalid section index.");
2264 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2265 }
2266
getSection64(DataRefImpl DRI) const2267 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2268 // TODO: What if Sections.size() == 0?
2269 if (DRI.d.a >= Sections.size())
2270 report_fatal_error("getSection64: Invalid section index.");
2271 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2272 }
2273
getSection(const LoadCommandInfo & L,unsigned Index) const2274 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2275 unsigned Index) const {
2276 const char *Sec = getSectionPtr(this, L, Index);
2277 return getStruct<MachO::section>(this, Sec);
2278 }
2279
getSection64(const LoadCommandInfo & L,unsigned Index) const2280 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2281 unsigned Index) const {
2282 const char *Sec = getSectionPtr(this, L, Index);
2283 return getStruct<MachO::section_64>(this, Sec);
2284 }
2285
2286 MachO::nlist
getSymbolTableEntry(DataRefImpl DRI) const2287 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2288 const char *P = reinterpret_cast<const char *>(DRI.p);
2289 return getStruct<MachO::nlist>(this, P);
2290 }
2291
2292 MachO::nlist_64
getSymbol64TableEntry(DataRefImpl DRI) const2293 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2294 const char *P = reinterpret_cast<const char *>(DRI.p);
2295 return getStruct<MachO::nlist_64>(this, P);
2296 }
2297
2298 MachO::linkedit_data_command
getLinkeditDataLoadCommand(const LoadCommandInfo & L) const2299 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2300 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2301 }
2302
2303 MachO::segment_command
getSegmentLoadCommand(const LoadCommandInfo & L) const2304 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2305 return getStruct<MachO::segment_command>(this, L.Ptr);
2306 }
2307
2308 MachO::segment_command_64
getSegment64LoadCommand(const LoadCommandInfo & L) const2309 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2310 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2311 }
2312
2313 MachO::linker_option_command
getLinkerOptionLoadCommand(const LoadCommandInfo & L) const2314 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2315 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2316 }
2317
2318 MachO::version_min_command
getVersionMinLoadCommand(const LoadCommandInfo & L) const2319 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2320 return getStruct<MachO::version_min_command>(this, L.Ptr);
2321 }
2322
2323 MachO::dylib_command
getDylibIDLoadCommand(const LoadCommandInfo & L) const2324 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2325 return getStruct<MachO::dylib_command>(this, L.Ptr);
2326 }
2327
2328 MachO::dyld_info_command
getDyldInfoLoadCommand(const LoadCommandInfo & L) const2329 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2330 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2331 }
2332
2333 MachO::dylinker_command
getDylinkerCommand(const LoadCommandInfo & L) const2334 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2335 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2336 }
2337
2338 MachO::uuid_command
getUuidCommand(const LoadCommandInfo & L) const2339 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2340 return getStruct<MachO::uuid_command>(this, L.Ptr);
2341 }
2342
2343 MachO::rpath_command
getRpathCommand(const LoadCommandInfo & L) const2344 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2345 return getStruct<MachO::rpath_command>(this, L.Ptr);
2346 }
2347
2348 MachO::source_version_command
getSourceVersionCommand(const LoadCommandInfo & L) const2349 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2350 return getStruct<MachO::source_version_command>(this, L.Ptr);
2351 }
2352
2353 MachO::entry_point_command
getEntryPointCommand(const LoadCommandInfo & L) const2354 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2355 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2356 }
2357
2358 MachO::encryption_info_command
getEncryptionInfoCommand(const LoadCommandInfo & L) const2359 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2360 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2361 }
2362
2363 MachO::encryption_info_command_64
getEncryptionInfoCommand64(const LoadCommandInfo & L) const2364 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2365 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2366 }
2367
2368 MachO::sub_framework_command
getSubFrameworkCommand(const LoadCommandInfo & L) const2369 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2370 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2371 }
2372
2373 MachO::sub_umbrella_command
getSubUmbrellaCommand(const LoadCommandInfo & L) const2374 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2375 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2376 }
2377
2378 MachO::sub_library_command
getSubLibraryCommand(const LoadCommandInfo & L) const2379 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2380 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2381 }
2382
2383 MachO::sub_client_command
getSubClientCommand(const LoadCommandInfo & L) const2384 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2385 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2386 }
2387
2388 MachO::routines_command
getRoutinesCommand(const LoadCommandInfo & L) const2389 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2390 return getStruct<MachO::routines_command>(this, L.Ptr);
2391 }
2392
2393 MachO::routines_command_64
getRoutinesCommand64(const LoadCommandInfo & L) const2394 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2395 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2396 }
2397
2398 MachO::thread_command
getThreadCommand(const LoadCommandInfo & L) const2399 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2400 return getStruct<MachO::thread_command>(this, L.Ptr);
2401 }
2402
2403 MachO::any_relocation_info
getRelocation(DataRefImpl Rel) const2404 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2405 DataRefImpl Sec;
2406 Sec.d.a = Rel.d.a;
2407 uint32_t Offset;
2408 if (is64Bit()) {
2409 MachO::section_64 Sect = getSection64(Sec);
2410 Offset = Sect.reloff;
2411 } else {
2412 MachO::section Sect = getSection(Sec);
2413 Offset = Sect.reloff;
2414 }
2415
2416 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2417 getPtr(this, Offset)) + Rel.d.b;
2418 return getStruct<MachO::any_relocation_info>(
2419 this, reinterpret_cast<const char *>(P));
2420 }
2421
2422 MachO::data_in_code_entry
getDice(DataRefImpl Rel) const2423 MachOObjectFile::getDice(DataRefImpl Rel) const {
2424 const char *P = reinterpret_cast<const char *>(Rel.p);
2425 return getStruct<MachO::data_in_code_entry>(this, P);
2426 }
2427
getHeader() const2428 MachO::mach_header MachOObjectFile::getHeader() const {
2429 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
2430 }
2431
getHeader64() const2432 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2433 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
2434 }
2435
getIndirectSymbolTableEntry(const MachO::dysymtab_command & DLC,unsigned Index) const2436 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2437 const MachO::dysymtab_command &DLC,
2438 unsigned Index) const {
2439 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2440 return getStruct<uint32_t>(this, getPtr(this, Offset));
2441 }
2442
2443 MachO::data_in_code_entry
getDataInCodeTableEntry(uint32_t DataOffset,unsigned Index) const2444 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2445 unsigned Index) const {
2446 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2447 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2448 }
2449
getSymtabLoadCommand() const2450 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2451 if (SymtabLoadCmd)
2452 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2453
2454 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2455 MachO::symtab_command Cmd;
2456 Cmd.cmd = MachO::LC_SYMTAB;
2457 Cmd.cmdsize = sizeof(MachO::symtab_command);
2458 Cmd.symoff = 0;
2459 Cmd.nsyms = 0;
2460 Cmd.stroff = 0;
2461 Cmd.strsize = 0;
2462 return Cmd;
2463 }
2464
getDysymtabLoadCommand() const2465 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2466 if (DysymtabLoadCmd)
2467 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2468
2469 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2470 MachO::dysymtab_command Cmd;
2471 Cmd.cmd = MachO::LC_DYSYMTAB;
2472 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2473 Cmd.ilocalsym = 0;
2474 Cmd.nlocalsym = 0;
2475 Cmd.iextdefsym = 0;
2476 Cmd.nextdefsym = 0;
2477 Cmd.iundefsym = 0;
2478 Cmd.nundefsym = 0;
2479 Cmd.tocoff = 0;
2480 Cmd.ntoc = 0;
2481 Cmd.modtaboff = 0;
2482 Cmd.nmodtab = 0;
2483 Cmd.extrefsymoff = 0;
2484 Cmd.nextrefsyms = 0;
2485 Cmd.indirectsymoff = 0;
2486 Cmd.nindirectsyms = 0;
2487 Cmd.extreloff = 0;
2488 Cmd.nextrel = 0;
2489 Cmd.locreloff = 0;
2490 Cmd.nlocrel = 0;
2491 return Cmd;
2492 }
2493
2494 MachO::linkedit_data_command
getDataInCodeLoadCommand() const2495 MachOObjectFile::getDataInCodeLoadCommand() const {
2496 if (DataInCodeLoadCmd)
2497 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2498
2499 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2500 MachO::linkedit_data_command Cmd;
2501 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2502 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2503 Cmd.dataoff = 0;
2504 Cmd.datasize = 0;
2505 return Cmd;
2506 }
2507
2508 MachO::linkedit_data_command
getLinkOptHintsLoadCommand() const2509 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2510 if (LinkOptHintsLoadCmd)
2511 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2512
2513 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2514 // fields.
2515 MachO::linkedit_data_command Cmd;
2516 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2517 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2518 Cmd.dataoff = 0;
2519 Cmd.datasize = 0;
2520 return Cmd;
2521 }
2522
getDyldInfoRebaseOpcodes() const2523 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2524 if (!DyldInfoLoadCmd)
2525 return ArrayRef<uint8_t>();
2526
2527 MachO::dyld_info_command DyldInfo
2528 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2529 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2530 getPtr(this, DyldInfo.rebase_off));
2531 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2532 }
2533
getDyldInfoBindOpcodes() const2534 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2535 if (!DyldInfoLoadCmd)
2536 return ArrayRef<uint8_t>();
2537
2538 MachO::dyld_info_command DyldInfo
2539 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2540 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2541 getPtr(this, DyldInfo.bind_off));
2542 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2543 }
2544
getDyldInfoWeakBindOpcodes() const2545 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2546 if (!DyldInfoLoadCmd)
2547 return ArrayRef<uint8_t>();
2548
2549 MachO::dyld_info_command DyldInfo
2550 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2551 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2552 getPtr(this, DyldInfo.weak_bind_off));
2553 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2554 }
2555
getDyldInfoLazyBindOpcodes() const2556 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2557 if (!DyldInfoLoadCmd)
2558 return ArrayRef<uint8_t>();
2559
2560 MachO::dyld_info_command DyldInfo
2561 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2562 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2563 getPtr(this, DyldInfo.lazy_bind_off));
2564 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2565 }
2566
getDyldInfoExportsTrie() const2567 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2568 if (!DyldInfoLoadCmd)
2569 return ArrayRef<uint8_t>();
2570
2571 MachO::dyld_info_command DyldInfo
2572 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2573 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2574 getPtr(this, DyldInfo.export_off));
2575 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2576 }
2577
getUuid() const2578 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2579 if (!UuidLoadCmd)
2580 return ArrayRef<uint8_t>();
2581 // Returning a pointer is fine as uuid doesn't need endian swapping.
2582 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2583 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2584 }
2585
getStringTableData() const2586 StringRef MachOObjectFile::getStringTableData() const {
2587 MachO::symtab_command S = getSymtabLoadCommand();
2588 return getData().substr(S.stroff, S.strsize);
2589 }
2590
is64Bit() const2591 bool MachOObjectFile::is64Bit() const {
2592 return getType() == getMachOType(false, true) ||
2593 getType() == getMachOType(true, true);
2594 }
2595
ReadULEB128s(uint64_t Index,SmallVectorImpl<uint64_t> & Out) const2596 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2597 SmallVectorImpl<uint64_t> &Out) const {
2598 DataExtractor extractor(ObjectFile::getData(), true, 0);
2599
2600 uint32_t offset = Index;
2601 uint64_t data = 0;
2602 while (uint64_t delta = extractor.getULEB128(&offset)) {
2603 data += delta;
2604 Out.push_back(data);
2605 }
2606 }
2607
isRelocatableObject() const2608 bool MachOObjectFile::isRelocatableObject() const {
2609 return getHeader().filetype == MachO::MH_OBJECT;
2610 }
2611
2612 ErrorOr<std::unique_ptr<MachOObjectFile>>
createMachOObjectFile(MemoryBufferRef Buffer)2613 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2614 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2615 std::error_code EC;
2616 std::unique_ptr<MachOObjectFile> Ret;
2617 if (Magic == "\xFE\xED\xFA\xCE")
2618 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2619 else if (Magic == "\xCE\xFA\xED\xFE")
2620 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2621 else if (Magic == "\xFE\xED\xFA\xCF")
2622 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2623 else if (Magic == "\xCF\xFA\xED\xFE")
2624 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2625 else
2626 return object_error::parse_failed;
2627
2628 if (EC)
2629 return EC;
2630 return std::move(Ret);
2631 }
2632
2633