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/Triple.h"
18 #include "llvm/Support/DataExtractor.h"
19 #include "llvm/Support/Format.h"
20 #include "llvm/Support/Host.h"
21 #include "llvm/Support/MemoryBuffer.h"
22 #include "llvm/Support/raw_ostream.h"
23 #include <cctype>
24 #include <cstring>
25 #include <limits>
26
27 using namespace llvm;
28 using namespace object;
29
30 namespace llvm {
31
32 namespace object {
33
34 struct nlist_base {
35 uint32_t n_strx;
36 uint8_t n_type;
37 uint8_t n_sect;
38 uint16_t n_desc;
39 };
40
41 struct section_base {
42 char sectname[16];
43 char segname[16];
44 };
45
46 template<typename T>
47 static void SwapStruct(T &Value);
48
49 template<>
SwapStruct(MachO::any_relocation_info & H)50 void SwapStruct(MachO::any_relocation_info &H) {
51 sys::swapByteOrder(H.r_word0);
52 sys::swapByteOrder(H.r_word1);
53 }
54
55 template<>
SwapStruct(MachO::load_command & L)56 void SwapStruct(MachO::load_command &L) {
57 sys::swapByteOrder(L.cmd);
58 sys::swapByteOrder(L.cmdsize);
59 }
60
61 template<>
SwapStruct(nlist_base & S)62 void SwapStruct(nlist_base &S) {
63 sys::swapByteOrder(S.n_strx);
64 sys::swapByteOrder(S.n_desc);
65 }
66
67 template<>
SwapStruct(MachO::section & S)68 void SwapStruct(MachO::section &S) {
69 sys::swapByteOrder(S.addr);
70 sys::swapByteOrder(S.size);
71 sys::swapByteOrder(S.offset);
72 sys::swapByteOrder(S.align);
73 sys::swapByteOrder(S.reloff);
74 sys::swapByteOrder(S.nreloc);
75 sys::swapByteOrder(S.flags);
76 sys::swapByteOrder(S.reserved1);
77 sys::swapByteOrder(S.reserved2);
78 }
79
80 template<>
SwapStruct(MachO::section_64 & S)81 void SwapStruct(MachO::section_64 &S) {
82 sys::swapByteOrder(S.addr);
83 sys::swapByteOrder(S.size);
84 sys::swapByteOrder(S.offset);
85 sys::swapByteOrder(S.align);
86 sys::swapByteOrder(S.reloff);
87 sys::swapByteOrder(S.nreloc);
88 sys::swapByteOrder(S.flags);
89 sys::swapByteOrder(S.reserved1);
90 sys::swapByteOrder(S.reserved2);
91 sys::swapByteOrder(S.reserved3);
92 }
93
94 template<>
SwapStruct(MachO::nlist & S)95 void SwapStruct(MachO::nlist &S) {
96 sys::swapByteOrder(S.n_strx);
97 sys::swapByteOrder(S.n_desc);
98 sys::swapByteOrder(S.n_value);
99 }
100
101 template<>
SwapStruct(MachO::nlist_64 & S)102 void SwapStruct(MachO::nlist_64 &S) {
103 sys::swapByteOrder(S.n_strx);
104 sys::swapByteOrder(S.n_desc);
105 sys::swapByteOrder(S.n_value);
106 }
107
108 template<>
SwapStruct(MachO::mach_header & H)109 void SwapStruct(MachO::mach_header &H) {
110 sys::swapByteOrder(H.magic);
111 sys::swapByteOrder(H.cputype);
112 sys::swapByteOrder(H.cpusubtype);
113 sys::swapByteOrder(H.filetype);
114 sys::swapByteOrder(H.ncmds);
115 sys::swapByteOrder(H.sizeofcmds);
116 sys::swapByteOrder(H.flags);
117 }
118
119 template<>
SwapStruct(MachO::mach_header_64 & H)120 void SwapStruct(MachO::mach_header_64 &H) {
121 sys::swapByteOrder(H.magic);
122 sys::swapByteOrder(H.cputype);
123 sys::swapByteOrder(H.cpusubtype);
124 sys::swapByteOrder(H.filetype);
125 sys::swapByteOrder(H.ncmds);
126 sys::swapByteOrder(H.sizeofcmds);
127 sys::swapByteOrder(H.flags);
128 sys::swapByteOrder(H.reserved);
129 }
130
131 template<>
SwapStruct(MachO::symtab_command & C)132 void SwapStruct(MachO::symtab_command &C) {
133 sys::swapByteOrder(C.cmd);
134 sys::swapByteOrder(C.cmdsize);
135 sys::swapByteOrder(C.symoff);
136 sys::swapByteOrder(C.nsyms);
137 sys::swapByteOrder(C.stroff);
138 sys::swapByteOrder(C.strsize);
139 }
140
141 template<>
SwapStruct(MachO::dysymtab_command & C)142 void SwapStruct(MachO::dysymtab_command &C) {
143 sys::swapByteOrder(C.cmd);
144 sys::swapByteOrder(C.cmdsize);
145 sys::swapByteOrder(C.ilocalsym);
146 sys::swapByteOrder(C.nlocalsym);
147 sys::swapByteOrder(C.iextdefsym);
148 sys::swapByteOrder(C.nextdefsym);
149 sys::swapByteOrder(C.iundefsym);
150 sys::swapByteOrder(C.nundefsym);
151 sys::swapByteOrder(C.tocoff);
152 sys::swapByteOrder(C.ntoc);
153 sys::swapByteOrder(C.modtaboff);
154 sys::swapByteOrder(C.nmodtab);
155 sys::swapByteOrder(C.extrefsymoff);
156 sys::swapByteOrder(C.nextrefsyms);
157 sys::swapByteOrder(C.indirectsymoff);
158 sys::swapByteOrder(C.nindirectsyms);
159 sys::swapByteOrder(C.extreloff);
160 sys::swapByteOrder(C.nextrel);
161 sys::swapByteOrder(C.locreloff);
162 sys::swapByteOrder(C.nlocrel);
163 }
164
165 template<>
SwapStruct(MachO::linkedit_data_command & C)166 void SwapStruct(MachO::linkedit_data_command &C) {
167 sys::swapByteOrder(C.cmd);
168 sys::swapByteOrder(C.cmdsize);
169 sys::swapByteOrder(C.dataoff);
170 sys::swapByteOrder(C.datasize);
171 }
172
173 template<>
SwapStruct(MachO::segment_command & C)174 void SwapStruct(MachO::segment_command &C) {
175 sys::swapByteOrder(C.cmd);
176 sys::swapByteOrder(C.cmdsize);
177 sys::swapByteOrder(C.vmaddr);
178 sys::swapByteOrder(C.vmsize);
179 sys::swapByteOrder(C.fileoff);
180 sys::swapByteOrder(C.filesize);
181 sys::swapByteOrder(C.maxprot);
182 sys::swapByteOrder(C.initprot);
183 sys::swapByteOrder(C.nsects);
184 sys::swapByteOrder(C.flags);
185 }
186
187 template<>
SwapStruct(MachO::segment_command_64 & C)188 void SwapStruct(MachO::segment_command_64 &C) {
189 sys::swapByteOrder(C.cmd);
190 sys::swapByteOrder(C.cmdsize);
191 sys::swapByteOrder(C.vmaddr);
192 sys::swapByteOrder(C.vmsize);
193 sys::swapByteOrder(C.fileoff);
194 sys::swapByteOrder(C.filesize);
195 sys::swapByteOrder(C.maxprot);
196 sys::swapByteOrder(C.initprot);
197 sys::swapByteOrder(C.nsects);
198 sys::swapByteOrder(C.flags);
199 }
200
201 template<>
SwapStruct(uint32_t & C)202 void SwapStruct(uint32_t &C) {
203 sys::swapByteOrder(C);
204 }
205
206 template<>
SwapStruct(MachO::linker_options_command & C)207 void SwapStruct(MachO::linker_options_command &C) {
208 sys::swapByteOrder(C.cmd);
209 sys::swapByteOrder(C.cmdsize);
210 sys::swapByteOrder(C.count);
211 }
212
213 template<>
SwapStruct(MachO::version_min_command & C)214 void SwapStruct(MachO::version_min_command&C) {
215 sys::swapByteOrder(C.cmd);
216 sys::swapByteOrder(C.cmdsize);
217 sys::swapByteOrder(C.version);
218 sys::swapByteOrder(C.reserved);
219 }
220
221 template<>
SwapStruct(MachO::dylib_command & C)222 void SwapStruct(MachO::dylib_command&C) {
223 sys::swapByteOrder(C.cmd);
224 sys::swapByteOrder(C.cmdsize);
225 sys::swapByteOrder(C.dylib.name);
226 sys::swapByteOrder(C.dylib.timestamp);
227 sys::swapByteOrder(C.dylib.current_version);
228 sys::swapByteOrder(C.dylib.compatibility_version);
229 }
230
231 template<>
SwapStruct(MachO::data_in_code_entry & C)232 void SwapStruct(MachO::data_in_code_entry &C) {
233 sys::swapByteOrder(C.offset);
234 sys::swapByteOrder(C.length);
235 sys::swapByteOrder(C.kind);
236 }
237
238 template<typename T>
getStruct(const MachOObjectFile * O,const char * P)239 T getStruct(const MachOObjectFile *O, const char *P) {
240 T Cmd;
241 memcpy(&Cmd, P, sizeof(T));
242 if (O->isLittleEndian() != sys::IsLittleEndianHost)
243 SwapStruct(Cmd);
244 return Cmd;
245 }
246
247 static uint32_t
getSegmentLoadCommandNumSections(const MachOObjectFile * O,const MachOObjectFile::LoadCommandInfo & L)248 getSegmentLoadCommandNumSections(const MachOObjectFile *O,
249 const MachOObjectFile::LoadCommandInfo &L) {
250 if (O->is64Bit()) {
251 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
252 return S.nsects;
253 }
254 MachO::segment_command S = O->getSegmentLoadCommand(L);
255 return S.nsects;
256 }
257
258 static const char *
getSectionPtr(const MachOObjectFile * O,MachOObjectFile::LoadCommandInfo L,unsigned Sec)259 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
260 unsigned Sec) {
261 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
262
263 bool Is64 = O->is64Bit();
264 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
265 sizeof(MachO::segment_command);
266 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
267 sizeof(MachO::section);
268
269 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
270 return reinterpret_cast<const char*>(SectionAddr);
271 }
272
getPtr(const MachOObjectFile * O,size_t Offset)273 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
274 return O->getData().substr(Offset, 1).data();
275 }
276
277 static nlist_base
getSymbolTableEntryBase(const MachOObjectFile * O,DataRefImpl DRI)278 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
279 const char *P = reinterpret_cast<const char *>(DRI.p);
280 return getStruct<nlist_base>(O, P);
281 }
282
parseSegmentOrSectionName(const char * P)283 static StringRef parseSegmentOrSectionName(const char *P) {
284 if (P[15] == 0)
285 // Null terminated.
286 return P;
287 // Not null terminated, so this is a 16 char string.
288 return StringRef(P, 16);
289 }
290
291 // Helper to advance a section or symbol iterator multiple increments at a time.
292 template<class T>
advance(T & it,size_t Val)293 static void advance(T &it, size_t Val) {
294 while (Val--)
295 ++it;
296 }
297
getCPUType(const MachOObjectFile * O)298 static unsigned getCPUType(const MachOObjectFile *O) {
299 return O->getHeader().cputype;
300 }
301
printRelocationTargetName(const MachOObjectFile * O,const MachO::any_relocation_info & RE,raw_string_ostream & fmt)302 static void printRelocationTargetName(const MachOObjectFile *O,
303 const MachO::any_relocation_info &RE,
304 raw_string_ostream &fmt) {
305 bool IsScattered = O->isRelocationScattered(RE);
306
307 // Target of a scattered relocation is an address. In the interest of
308 // generating pretty output, scan through the symbol table looking for a
309 // symbol that aligns with that address. If we find one, print it.
310 // Otherwise, we just print the hex address of the target.
311 if (IsScattered) {
312 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
313
314 for (const SymbolRef &Symbol : O->symbols()) {
315 std::error_code ec;
316 uint64_t Addr;
317 StringRef Name;
318
319 if ((ec = Symbol.getAddress(Addr)))
320 report_fatal_error(ec.message());
321 if (Addr != Val)
322 continue;
323 if ((ec = Symbol.getName(Name)))
324 report_fatal_error(ec.message());
325 fmt << Name;
326 return;
327 }
328
329 // If we couldn't find a symbol that this relocation refers to, try
330 // to find a section beginning instead.
331 for (const SectionRef &Section : O->sections()) {
332 std::error_code ec;
333 uint64_t Addr;
334 StringRef Name;
335
336 if ((ec = Section.getAddress(Addr)))
337 report_fatal_error(ec.message());
338 if (Addr != Val)
339 continue;
340 if ((ec = Section.getName(Name)))
341 report_fatal_error(ec.message());
342 fmt << Name;
343 return;
344 }
345
346 fmt << format("0x%x", Val);
347 return;
348 }
349
350 StringRef S;
351 bool isExtern = O->getPlainRelocationExternal(RE);
352 uint64_t Val = O->getPlainRelocationSymbolNum(RE);
353
354 if (isExtern) {
355 symbol_iterator SI = O->symbol_begin();
356 advance(SI, Val);
357 SI->getName(S);
358 } else {
359 section_iterator SI = O->section_begin();
360 // Adjust for the fact that sections are 1-indexed.
361 advance(SI, Val - 1);
362 SI->getName(S);
363 }
364
365 fmt << S;
366 }
367
368 static uint32_t
getPlainRelocationAddress(const MachO::any_relocation_info & RE)369 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
370 return RE.r_word0;
371 }
372
373 static unsigned
getScatteredRelocationAddress(const MachO::any_relocation_info & RE)374 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
375 return RE.r_word0 & 0xffffff;
376 }
377
getPlainRelocationPCRel(const MachOObjectFile * O,const MachO::any_relocation_info & RE)378 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
379 const MachO::any_relocation_info &RE) {
380 if (O->isLittleEndian())
381 return (RE.r_word1 >> 24) & 1;
382 return (RE.r_word1 >> 7) & 1;
383 }
384
385 static bool
getScatteredRelocationPCRel(const MachOObjectFile * O,const MachO::any_relocation_info & RE)386 getScatteredRelocationPCRel(const MachOObjectFile *O,
387 const MachO::any_relocation_info &RE) {
388 return (RE.r_word0 >> 30) & 1;
389 }
390
getPlainRelocationLength(const MachOObjectFile * O,const MachO::any_relocation_info & RE)391 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
392 const MachO::any_relocation_info &RE) {
393 if (O->isLittleEndian())
394 return (RE.r_word1 >> 25) & 3;
395 return (RE.r_word1 >> 5) & 3;
396 }
397
398 static unsigned
getScatteredRelocationLength(const MachO::any_relocation_info & RE)399 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
400 return (RE.r_word0 >> 28) & 3;
401 }
402
getPlainRelocationType(const MachOObjectFile * O,const MachO::any_relocation_info & RE)403 static unsigned getPlainRelocationType(const MachOObjectFile *O,
404 const MachO::any_relocation_info &RE) {
405 if (O->isLittleEndian())
406 return RE.r_word1 >> 28;
407 return RE.r_word1 & 0xf;
408 }
409
410 static unsigned
getScatteredRelocationType(const MachO::any_relocation_info & RE)411 getScatteredRelocationType(const MachO::any_relocation_info &RE) {
412 return (RE.r_word0 >> 24) & 0xf;
413 }
414
getSectionFlags(const MachOObjectFile * O,DataRefImpl Sec)415 static uint32_t getSectionFlags(const MachOObjectFile *O,
416 DataRefImpl Sec) {
417 if (O->is64Bit()) {
418 MachO::section_64 Sect = O->getSection64(Sec);
419 return Sect.flags;
420 }
421 MachO::section Sect = O->getSection(Sec);
422 return Sect.flags;
423 }
424
MachOObjectFile(std::unique_ptr<MemoryBuffer> Object,bool IsLittleEndian,bool Is64bits,std::error_code & EC)425 MachOObjectFile::MachOObjectFile(std::unique_ptr<MemoryBuffer> Object,
426 bool IsLittleEndian, bool Is64bits,
427 std::error_code &EC)
428 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), std::move(Object)),
429 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
430 DataInCodeLoadCmd(nullptr) {
431 uint32_t LoadCommandCount = this->getHeader().ncmds;
432 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
433 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
434
435 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
436 for (unsigned I = 0; ; ++I) {
437 if (Load.C.cmd == MachO::LC_SYMTAB) {
438 assert(!SymtabLoadCmd && "Multiple symbol tables");
439 SymtabLoadCmd = Load.Ptr;
440 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
441 assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables");
442 DysymtabLoadCmd = Load.Ptr;
443 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
444 assert(!DataInCodeLoadCmd && "Multiple data in code tables");
445 DataInCodeLoadCmd = Load.Ptr;
446 } else if (Load.C.cmd == SegmentLoadType) {
447 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
448 for (unsigned J = 0; J < NumSections; ++J) {
449 const char *Sec = getSectionPtr(this, Load, J);
450 Sections.push_back(Sec);
451 }
452 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
453 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
454 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
455 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
456 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
457 Libraries.push_back(Load.Ptr);
458 }
459
460 if (I == LoadCommandCount - 1)
461 break;
462 else
463 Load = getNextLoadCommandInfo(Load);
464 }
465 }
466
moveSymbolNext(DataRefImpl & Symb) const467 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
468 unsigned SymbolTableEntrySize = is64Bit() ?
469 sizeof(MachO::nlist_64) :
470 sizeof(MachO::nlist);
471 Symb.p += SymbolTableEntrySize;
472 }
473
getSymbolName(DataRefImpl Symb,StringRef & Res) const474 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
475 StringRef &Res) const {
476 StringRef StringTable = getStringTableData();
477 nlist_base Entry = getSymbolTableEntryBase(this, Symb);
478 const char *Start = &StringTable.data()[Entry.n_strx];
479 Res = StringRef(Start);
480 return object_error::success;
481 }
482
483 // getIndirectName() returns the name of the alias'ed symbol who's string table
484 // index is in the n_value field.
getIndirectName(DataRefImpl Symb,StringRef & Res) const485 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
486 StringRef &Res) const {
487 StringRef StringTable = getStringTableData();
488 uint64_t NValue;
489 if (is64Bit()) {
490 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
491 NValue = Entry.n_value;
492 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
493 return object_error::parse_failed;
494 } else {
495 MachO::nlist Entry = getSymbolTableEntry(Symb);
496 NValue = Entry.n_value;
497 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
498 return object_error::parse_failed;
499 }
500 if (NValue >= StringTable.size())
501 return object_error::parse_failed;
502 const char *Start = &StringTable.data()[NValue];
503 Res = StringRef(Start);
504 return object_error::success;
505 }
506
getSymbolAddress(DataRefImpl Symb,uint64_t & Res) const507 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
508 uint64_t &Res) const {
509 if (is64Bit()) {
510 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
511 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
512 Entry.n_value == 0)
513 Res = UnknownAddressOrSize;
514 else
515 Res = Entry.n_value;
516 } else {
517 MachO::nlist Entry = getSymbolTableEntry(Symb);
518 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
519 Entry.n_value == 0)
520 Res = UnknownAddressOrSize;
521 else
522 Res = Entry.n_value;
523 }
524 return object_error::success;
525 }
526
getSymbolAlignment(DataRefImpl DRI,uint32_t & Result) const527 std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
528 uint32_t &Result) const {
529 uint32_t flags = getSymbolFlags(DRI);
530 if (flags & SymbolRef::SF_Common) {
531 nlist_base Entry = getSymbolTableEntryBase(this, DRI);
532 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
533 } else {
534 Result = 0;
535 }
536 return object_error::success;
537 }
538
getSymbolSize(DataRefImpl DRI,uint64_t & Result) const539 std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
540 uint64_t &Result) const {
541 uint64_t BeginOffset;
542 uint64_t EndOffset = 0;
543 uint8_t SectionIndex;
544
545 nlist_base Entry = getSymbolTableEntryBase(this, DRI);
546 uint64_t Value;
547 getSymbolAddress(DRI, Value);
548 if (Value == UnknownAddressOrSize) {
549 Result = UnknownAddressOrSize;
550 return object_error::success;
551 }
552
553 BeginOffset = Value;
554
555 SectionIndex = Entry.n_sect;
556 if (!SectionIndex) {
557 uint32_t flags = getSymbolFlags(DRI);
558 if (flags & SymbolRef::SF_Common)
559 Result = Value;
560 else
561 Result = UnknownAddressOrSize;
562 return object_error::success;
563 }
564 // Unfortunately symbols are unsorted so we need to touch all
565 // symbols from load command
566 for (const SymbolRef &Symbol : symbols()) {
567 DataRefImpl DRI = Symbol.getRawDataRefImpl();
568 Entry = getSymbolTableEntryBase(this, DRI);
569 getSymbolAddress(DRI, Value);
570 if (Value == UnknownAddressOrSize)
571 continue;
572 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
573 if (!EndOffset || Value < EndOffset)
574 EndOffset = Value;
575 }
576 if (!EndOffset) {
577 uint64_t Size;
578 DataRefImpl Sec;
579 Sec.d.a = SectionIndex-1;
580 getSectionSize(Sec, Size);
581 getSectionAddress(Sec, EndOffset);
582 EndOffset += Size;
583 }
584 Result = EndOffset - BeginOffset;
585 return object_error::success;
586 }
587
getSymbolType(DataRefImpl Symb,SymbolRef::Type & Res) const588 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
589 SymbolRef::Type &Res) const {
590 nlist_base Entry = getSymbolTableEntryBase(this, Symb);
591 uint8_t n_type = Entry.n_type;
592
593 Res = SymbolRef::ST_Other;
594
595 // If this is a STAB debugging symbol, we can do nothing more.
596 if (n_type & MachO::N_STAB) {
597 Res = SymbolRef::ST_Debug;
598 return object_error::success;
599 }
600
601 switch (n_type & MachO::N_TYPE) {
602 case MachO::N_UNDF :
603 Res = SymbolRef::ST_Unknown;
604 break;
605 case MachO::N_SECT :
606 Res = SymbolRef::ST_Function;
607 break;
608 }
609 return object_error::success;
610 }
611
getSymbolFlags(DataRefImpl DRI) const612 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
613 nlist_base Entry = getSymbolTableEntryBase(this, DRI);
614
615 uint8_t MachOType = Entry.n_type;
616 uint16_t MachOFlags = Entry.n_desc;
617
618 uint32_t Result = SymbolRef::SF_None;
619
620 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
621 Result |= SymbolRef::SF_Undefined;
622
623 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
624 Result |= SymbolRef::SF_Indirect;
625
626 if (MachOType & MachO::N_STAB)
627 Result |= SymbolRef::SF_FormatSpecific;
628
629 if (MachOType & MachO::N_EXT) {
630 Result |= SymbolRef::SF_Global;
631 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
632 uint64_t Value;
633 getSymbolAddress(DRI, Value);
634 if (Value && Value != UnknownAddressOrSize)
635 Result |= SymbolRef::SF_Common;
636 }
637 }
638
639 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
640 Result |= SymbolRef::SF_Weak;
641
642 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
643 Result |= SymbolRef::SF_Absolute;
644
645 return Result;
646 }
647
getSymbolSection(DataRefImpl Symb,section_iterator & Res) const648 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
649 section_iterator &Res) const {
650 nlist_base Entry = getSymbolTableEntryBase(this, Symb);
651 uint8_t index = Entry.n_sect;
652
653 if (index == 0) {
654 Res = section_end();
655 } else {
656 DataRefImpl DRI;
657 DRI.d.a = index - 1;
658 Res = section_iterator(SectionRef(DRI, this));
659 }
660
661 return object_error::success;
662 }
663
moveSectionNext(DataRefImpl & Sec) const664 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
665 Sec.d.a++;
666 }
667
getSectionName(DataRefImpl Sec,StringRef & Result) const668 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
669 StringRef &Result) const {
670 ArrayRef<char> Raw = getSectionRawName(Sec);
671 Result = parseSegmentOrSectionName(Raw.data());
672 return object_error::success;
673 }
674
getSectionAddress(DataRefImpl Sec,uint64_t & Res) const675 std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec,
676 uint64_t &Res) const {
677 if (is64Bit()) {
678 MachO::section_64 Sect = getSection64(Sec);
679 Res = Sect.addr;
680 } else {
681 MachO::section Sect = getSection(Sec);
682 Res = Sect.addr;
683 }
684 return object_error::success;
685 }
686
getSectionSize(DataRefImpl Sec,uint64_t & Res) const687 std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec,
688 uint64_t &Res) const {
689 if (is64Bit()) {
690 MachO::section_64 Sect = getSection64(Sec);
691 Res = Sect.size;
692 } else {
693 MachO::section Sect = getSection(Sec);
694 Res = Sect.size;
695 }
696
697 return object_error::success;
698 }
699
getSectionContents(DataRefImpl Sec,StringRef & Res) const700 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
701 StringRef &Res) const {
702 uint32_t Offset;
703 uint64_t Size;
704
705 if (is64Bit()) {
706 MachO::section_64 Sect = getSection64(Sec);
707 Offset = Sect.offset;
708 Size = Sect.size;
709 } else {
710 MachO::section Sect = getSection(Sec);
711 Offset = Sect.offset;
712 Size = Sect.size;
713 }
714
715 Res = this->getData().substr(Offset, Size);
716 return object_error::success;
717 }
718
getSectionAlignment(DataRefImpl Sec,uint64_t & Res) const719 std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec,
720 uint64_t &Res) const {
721 uint32_t Align;
722 if (is64Bit()) {
723 MachO::section_64 Sect = getSection64(Sec);
724 Align = Sect.align;
725 } else {
726 MachO::section Sect = getSection(Sec);
727 Align = Sect.align;
728 }
729
730 Res = uint64_t(1) << Align;
731 return object_error::success;
732 }
733
isSectionText(DataRefImpl Sec,bool & Res) const734 std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec,
735 bool &Res) const {
736 uint32_t Flags = getSectionFlags(this, Sec);
737 Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
738 return object_error::success;
739 }
740
isSectionData(DataRefImpl Sec,bool & Result) const741 std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec,
742 bool &Result) const {
743 uint32_t Flags = getSectionFlags(this, Sec);
744 unsigned SectionType = Flags & MachO::SECTION_TYPE;
745 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
746 !(SectionType == MachO::S_ZEROFILL ||
747 SectionType == MachO::S_GB_ZEROFILL);
748 return object_error::success;
749 }
750
isSectionBSS(DataRefImpl Sec,bool & Result) const751 std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec,
752 bool &Result) const {
753 uint32_t Flags = getSectionFlags(this, Sec);
754 unsigned SectionType = Flags & MachO::SECTION_TYPE;
755 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
756 (SectionType == MachO::S_ZEROFILL ||
757 SectionType == MachO::S_GB_ZEROFILL);
758 return object_error::success;
759 }
760
761 std::error_code
isSectionRequiredForExecution(DataRefImpl Sec,bool & Result) const762 MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
763 bool &Result) const {
764 // FIXME: Unimplemented.
765 Result = true;
766 return object_error::success;
767 }
768
isSectionVirtual(DataRefImpl Sec,bool & Result) const769 std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
770 bool &Result) const {
771 // FIXME: Unimplemented.
772 Result = false;
773 return object_error::success;
774 }
775
isSectionZeroInit(DataRefImpl Sec,bool & Res) const776 std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec,
777 bool &Res) const {
778 uint32_t Flags = getSectionFlags(this, Sec);
779 unsigned SectionType = Flags & MachO::SECTION_TYPE;
780 Res = SectionType == MachO::S_ZEROFILL ||
781 SectionType == MachO::S_GB_ZEROFILL;
782 return object_error::success;
783 }
784
isSectionReadOnlyData(DataRefImpl Sec,bool & Result) const785 std::error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
786 bool &Result) const {
787 // Consider using the code from isSectionText to look for __const sections.
788 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
789 // to use section attributes to distinguish code from data.
790
791 // FIXME: Unimplemented.
792 Result = false;
793 return object_error::success;
794 }
795
sectionContainsSymbol(DataRefImpl Sec,DataRefImpl Symb,bool & Result) const796 std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
797 DataRefImpl Symb,
798 bool &Result) const {
799 SymbolRef::Type ST;
800 this->getSymbolType(Symb, ST);
801 if (ST == SymbolRef::ST_Unknown) {
802 Result = false;
803 return object_error::success;
804 }
805
806 uint64_t SectBegin, SectEnd;
807 getSectionAddress(Sec, SectBegin);
808 getSectionSize(Sec, SectEnd);
809 SectEnd += SectBegin;
810
811 uint64_t SymAddr;
812 getSymbolAddress(Symb, SymAddr);
813 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
814
815 return object_error::success;
816 }
817
section_rel_begin(DataRefImpl Sec) const818 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
819 DataRefImpl Ret;
820 Ret.d.a = Sec.d.a;
821 Ret.d.b = 0;
822 return relocation_iterator(RelocationRef(Ret, this));
823 }
824
825 relocation_iterator
section_rel_end(DataRefImpl Sec) const826 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
827 uint32_t Num;
828 if (is64Bit()) {
829 MachO::section_64 Sect = getSection64(Sec);
830 Num = Sect.nreloc;
831 } else {
832 MachO::section Sect = getSection(Sec);
833 Num = Sect.nreloc;
834 }
835
836 DataRefImpl Ret;
837 Ret.d.a = Sec.d.a;
838 Ret.d.b = Num;
839 return relocation_iterator(RelocationRef(Ret, this));
840 }
841
moveRelocationNext(DataRefImpl & Rel) const842 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
843 ++Rel.d.b;
844 }
845
getRelocationAddress(DataRefImpl Rel,uint64_t & Res) const846 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
847 uint64_t &Res) const {
848 uint64_t Offset;
849 getRelocationOffset(Rel, Offset);
850
851 DataRefImpl Sec;
852 Sec.d.a = Rel.d.a;
853 uint64_t SecAddress;
854 getSectionAddress(Sec, SecAddress);
855 Res = SecAddress + Offset;
856 return object_error::success;
857 }
858
getRelocationOffset(DataRefImpl Rel,uint64_t & Res) const859 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
860 uint64_t &Res) const {
861 assert(getHeader().filetype == MachO::MH_OBJECT &&
862 "Only implemented for MH_OBJECT");
863 MachO::any_relocation_info RE = getRelocation(Rel);
864 Res = getAnyRelocationAddress(RE);
865 return object_error::success;
866 }
867
868 symbol_iterator
getRelocationSymbol(DataRefImpl Rel) const869 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
870 MachO::any_relocation_info RE = getRelocation(Rel);
871 if (isRelocationScattered(RE))
872 return symbol_end();
873
874 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
875 bool isExtern = getPlainRelocationExternal(RE);
876 if (!isExtern)
877 return symbol_end();
878
879 MachO::symtab_command S = getSymtabLoadCommand();
880 unsigned SymbolTableEntrySize = is64Bit() ?
881 sizeof(MachO::nlist_64) :
882 sizeof(MachO::nlist);
883 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
884 DataRefImpl Sym;
885 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
886 return symbol_iterator(SymbolRef(Sym, this));
887 }
888
getRelocationType(DataRefImpl Rel,uint64_t & Res) const889 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
890 uint64_t &Res) const {
891 MachO::any_relocation_info RE = getRelocation(Rel);
892 Res = getAnyRelocationType(RE);
893 return object_error::success;
894 }
895
896 std::error_code
getRelocationTypeName(DataRefImpl Rel,SmallVectorImpl<char> & Result) const897 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
898 SmallVectorImpl<char> &Result) const {
899 StringRef res;
900 uint64_t RType;
901 getRelocationType(Rel, RType);
902
903 unsigned Arch = this->getArch();
904
905 switch (Arch) {
906 case Triple::x86: {
907 static const char *const Table[] = {
908 "GENERIC_RELOC_VANILLA",
909 "GENERIC_RELOC_PAIR",
910 "GENERIC_RELOC_SECTDIFF",
911 "GENERIC_RELOC_PB_LA_PTR",
912 "GENERIC_RELOC_LOCAL_SECTDIFF",
913 "GENERIC_RELOC_TLV" };
914
915 if (RType > 5)
916 res = "Unknown";
917 else
918 res = Table[RType];
919 break;
920 }
921 case Triple::x86_64: {
922 static const char *const Table[] = {
923 "X86_64_RELOC_UNSIGNED",
924 "X86_64_RELOC_SIGNED",
925 "X86_64_RELOC_BRANCH",
926 "X86_64_RELOC_GOT_LOAD",
927 "X86_64_RELOC_GOT",
928 "X86_64_RELOC_SUBTRACTOR",
929 "X86_64_RELOC_SIGNED_1",
930 "X86_64_RELOC_SIGNED_2",
931 "X86_64_RELOC_SIGNED_4",
932 "X86_64_RELOC_TLV" };
933
934 if (RType > 9)
935 res = "Unknown";
936 else
937 res = Table[RType];
938 break;
939 }
940 case Triple::arm: {
941 static const char *const Table[] = {
942 "ARM_RELOC_VANILLA",
943 "ARM_RELOC_PAIR",
944 "ARM_RELOC_SECTDIFF",
945 "ARM_RELOC_LOCAL_SECTDIFF",
946 "ARM_RELOC_PB_LA_PTR",
947 "ARM_RELOC_BR24",
948 "ARM_THUMB_RELOC_BR22",
949 "ARM_THUMB_32BIT_BRANCH",
950 "ARM_RELOC_HALF",
951 "ARM_RELOC_HALF_SECTDIFF" };
952
953 if (RType > 9)
954 res = "Unknown";
955 else
956 res = Table[RType];
957 break;
958 }
959 case Triple::arm64:
960 case Triple::aarch64: {
961 static const char *const Table[] = {
962 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
963 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
964 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
965 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
966 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
967 "ARM64_RELOC_ADDEND"
968 };
969
970 if (RType >= array_lengthof(Table))
971 res = "Unknown";
972 else
973 res = Table[RType];
974 break;
975 }
976 case Triple::ppc: {
977 static const char *const Table[] = {
978 "PPC_RELOC_VANILLA",
979 "PPC_RELOC_PAIR",
980 "PPC_RELOC_BR14",
981 "PPC_RELOC_BR24",
982 "PPC_RELOC_HI16",
983 "PPC_RELOC_LO16",
984 "PPC_RELOC_HA16",
985 "PPC_RELOC_LO14",
986 "PPC_RELOC_SECTDIFF",
987 "PPC_RELOC_PB_LA_PTR",
988 "PPC_RELOC_HI16_SECTDIFF",
989 "PPC_RELOC_LO16_SECTDIFF",
990 "PPC_RELOC_HA16_SECTDIFF",
991 "PPC_RELOC_JBSR",
992 "PPC_RELOC_LO14_SECTDIFF",
993 "PPC_RELOC_LOCAL_SECTDIFF" };
994
995 if (RType > 15)
996 res = "Unknown";
997 else
998 res = Table[RType];
999 break;
1000 }
1001 case Triple::UnknownArch:
1002 res = "Unknown";
1003 break;
1004 }
1005 Result.append(res.begin(), res.end());
1006 return object_error::success;
1007 }
1008
1009 std::error_code
getRelocationValueString(DataRefImpl Rel,SmallVectorImpl<char> & Result) const1010 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
1011 SmallVectorImpl<char> &Result) const {
1012 MachO::any_relocation_info RE = getRelocation(Rel);
1013
1014 unsigned Arch = this->getArch();
1015
1016 std::string fmtbuf;
1017 raw_string_ostream fmt(fmtbuf);
1018 unsigned Type = this->getAnyRelocationType(RE);
1019 bool IsPCRel = this->getAnyRelocationPCRel(RE);
1020
1021 // Determine any addends that should be displayed with the relocation.
1022 // These require decoding the relocation type, which is triple-specific.
1023
1024 // X86_64 has entirely custom relocation types.
1025 if (Arch == Triple::x86_64) {
1026 bool isPCRel = getAnyRelocationPCRel(RE);
1027
1028 switch (Type) {
1029 case MachO::X86_64_RELOC_GOT_LOAD:
1030 case MachO::X86_64_RELOC_GOT: {
1031 printRelocationTargetName(this, RE, fmt);
1032 fmt << "@GOT";
1033 if (isPCRel) fmt << "PCREL";
1034 break;
1035 }
1036 case MachO::X86_64_RELOC_SUBTRACTOR: {
1037 DataRefImpl RelNext = Rel;
1038 moveRelocationNext(RelNext);
1039 MachO::any_relocation_info RENext = getRelocation(RelNext);
1040
1041 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
1042 // X86_64_RELOC_UNSIGNED.
1043 // NOTE: Scattered relocations don't exist on x86_64.
1044 unsigned RType = getAnyRelocationType(RENext);
1045 if (RType != MachO::X86_64_RELOC_UNSIGNED)
1046 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1047 "X86_64_RELOC_SUBTRACTOR.");
1048
1049 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
1050 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
1051 printRelocationTargetName(this, RENext, fmt);
1052 fmt << "-";
1053 printRelocationTargetName(this, RE, fmt);
1054 break;
1055 }
1056 case MachO::X86_64_RELOC_TLV:
1057 printRelocationTargetName(this, RE, fmt);
1058 fmt << "@TLV";
1059 if (isPCRel) fmt << "P";
1060 break;
1061 case MachO::X86_64_RELOC_SIGNED_1:
1062 printRelocationTargetName(this, RE, fmt);
1063 fmt << "-1";
1064 break;
1065 case MachO::X86_64_RELOC_SIGNED_2:
1066 printRelocationTargetName(this, RE, fmt);
1067 fmt << "-2";
1068 break;
1069 case MachO::X86_64_RELOC_SIGNED_4:
1070 printRelocationTargetName(this, RE, fmt);
1071 fmt << "-4";
1072 break;
1073 default:
1074 printRelocationTargetName(this, RE, fmt);
1075 break;
1076 }
1077 // X86 and ARM share some relocation types in common.
1078 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
1079 Arch == Triple::ppc) {
1080 // Generic relocation types...
1081 switch (Type) {
1082 case MachO::GENERIC_RELOC_PAIR: // prints no info
1083 return object_error::success;
1084 case MachO::GENERIC_RELOC_SECTDIFF: {
1085 DataRefImpl RelNext = Rel;
1086 moveRelocationNext(RelNext);
1087 MachO::any_relocation_info RENext = getRelocation(RelNext);
1088
1089 // X86 sect diff's must be followed by a relocation of type
1090 // GENERIC_RELOC_PAIR.
1091 unsigned RType = getAnyRelocationType(RENext);
1092
1093 if (RType != MachO::GENERIC_RELOC_PAIR)
1094 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1095 "GENERIC_RELOC_SECTDIFF.");
1096
1097 printRelocationTargetName(this, RE, fmt);
1098 fmt << "-";
1099 printRelocationTargetName(this, RENext, fmt);
1100 break;
1101 }
1102 }
1103
1104 if (Arch == Triple::x86 || Arch == Triple::ppc) {
1105 switch (Type) {
1106 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
1107 DataRefImpl RelNext = Rel;
1108 moveRelocationNext(RelNext);
1109 MachO::any_relocation_info RENext = getRelocation(RelNext);
1110
1111 // X86 sect diff's must be followed by a relocation of type
1112 // GENERIC_RELOC_PAIR.
1113 unsigned RType = getAnyRelocationType(RENext);
1114 if (RType != MachO::GENERIC_RELOC_PAIR)
1115 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1116 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1117
1118 printRelocationTargetName(this, RE, fmt);
1119 fmt << "-";
1120 printRelocationTargetName(this, RENext, fmt);
1121 break;
1122 }
1123 case MachO::GENERIC_RELOC_TLV: {
1124 printRelocationTargetName(this, RE, fmt);
1125 fmt << "@TLV";
1126 if (IsPCRel) fmt << "P";
1127 break;
1128 }
1129 default:
1130 printRelocationTargetName(this, RE, fmt);
1131 }
1132 } else { // ARM-specific relocations
1133 switch (Type) {
1134 case MachO::ARM_RELOC_HALF:
1135 case MachO::ARM_RELOC_HALF_SECTDIFF: {
1136 // Half relocations steal a bit from the length field to encode
1137 // whether this is an upper16 or a lower16 relocation.
1138 bool isUpper = getAnyRelocationLength(RE) >> 1;
1139
1140 if (isUpper)
1141 fmt << ":upper16:(";
1142 else
1143 fmt << ":lower16:(";
1144 printRelocationTargetName(this, RE, fmt);
1145
1146 DataRefImpl RelNext = Rel;
1147 moveRelocationNext(RelNext);
1148 MachO::any_relocation_info RENext = getRelocation(RelNext);
1149
1150 // ARM half relocs must be followed by a relocation of type
1151 // ARM_RELOC_PAIR.
1152 unsigned RType = getAnyRelocationType(RENext);
1153 if (RType != MachO::ARM_RELOC_PAIR)
1154 report_fatal_error("Expected ARM_RELOC_PAIR after "
1155 "ARM_RELOC_HALF");
1156
1157 // NOTE: The half of the target virtual address is stashed in the
1158 // address field of the secondary relocation, but we can't reverse
1159 // engineer the constant offset from it without decoding the movw/movt
1160 // instruction to find the other half in its immediate field.
1161
1162 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1163 // symbol/section pointer of the follow-on relocation.
1164 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
1165 fmt << "-";
1166 printRelocationTargetName(this, RENext, fmt);
1167 }
1168
1169 fmt << ")";
1170 break;
1171 }
1172 default: {
1173 printRelocationTargetName(this, RE, fmt);
1174 }
1175 }
1176 }
1177 } else
1178 printRelocationTargetName(this, RE, fmt);
1179
1180 fmt.flush();
1181 Result.append(fmtbuf.begin(), fmtbuf.end());
1182 return object_error::success;
1183 }
1184
getRelocationHidden(DataRefImpl Rel,bool & Result) const1185 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1186 bool &Result) const {
1187 unsigned Arch = getArch();
1188 uint64_t Type;
1189 getRelocationType(Rel, Type);
1190
1191 Result = false;
1192
1193 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1194 // is always hidden.
1195 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
1196 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
1197 } else if (Arch == Triple::x86_64) {
1198 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1199 // an X86_64_RELOC_SUBTRACTOR.
1200 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
1201 DataRefImpl RelPrev = Rel;
1202 RelPrev.d.a--;
1203 uint64_t PrevType;
1204 getRelocationType(RelPrev, PrevType);
1205 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
1206 Result = true;
1207 }
1208 }
1209
1210 return object_error::success;
1211 }
1212
getLibraryNext(DataRefImpl LibData,LibraryRef & Res) const1213 std::error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1214 LibraryRef &Res) const {
1215 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1216 }
1217
getLibraryPath(DataRefImpl LibData,StringRef & Res) const1218 std::error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1219 StringRef &Res) const {
1220 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1221 }
1222
1223 //
1224 // guessLibraryShortName() is passed a name of a dynamic library and returns a
1225 // guess on what the short name is. Then name is returned as a substring of the
1226 // StringRef Name passed in. The name of the dynamic library is recognized as
1227 // a framework if it has one of the two following forms:
1228 // Foo.framework/Versions/A/Foo
1229 // Foo.framework/Foo
1230 // Where A and Foo can be any string. And may contain a trailing suffix
1231 // starting with an underbar. If the Name is recognized as a framework then
1232 // isFramework is set to true else it is set to false. If the Name has a
1233 // suffix then Suffix is set to the substring in Name that contains the suffix
1234 // else it is set to a NULL StringRef.
1235 //
1236 // The Name of the dynamic library is recognized as a library name if it has
1237 // one of the two following forms:
1238 // libFoo.A.dylib
1239 // libFoo.dylib
1240 // The library may have a suffix trailing the name Foo of the form:
1241 // libFoo_profile.A.dylib
1242 // libFoo_profile.dylib
1243 //
1244 // The Name of the dynamic library is also recognized as a library name if it
1245 // has the following form:
1246 // Foo.qtx
1247 //
1248 // If the Name of the dynamic library is none of the forms above then a NULL
1249 // StringRef is returned.
1250 //
guessLibraryShortName(StringRef Name,bool & isFramework,StringRef & Suffix)1251 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1252 bool &isFramework,
1253 StringRef &Suffix) {
1254 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1255 size_t a, b, c, d, Idx;
1256
1257 isFramework = false;
1258 Suffix = StringRef();
1259
1260 // Pull off the last component and make Foo point to it
1261 a = Name.rfind('/');
1262 if (a == Name.npos || a == 0)
1263 goto guess_library;
1264 Foo = Name.slice(a+1, Name.npos);
1265
1266 // Look for a suffix starting with a '_'
1267 Idx = Foo.rfind('_');
1268 if (Idx != Foo.npos && Foo.size() >= 2) {
1269 Suffix = Foo.slice(Idx, Foo.npos);
1270 Foo = Foo.slice(0, Idx);
1271 }
1272
1273 // First look for the form Foo.framework/Foo
1274 b = Name.rfind('/', a);
1275 if (b == Name.npos)
1276 Idx = 0;
1277 else
1278 Idx = b+1;
1279 F = Name.slice(Idx, Idx + Foo.size());
1280 DotFramework = Name.slice(Idx + Foo.size(),
1281 Idx + Foo.size() + sizeof(".framework/")-1);
1282 if (F == Foo && DotFramework == ".framework/") {
1283 isFramework = true;
1284 return Foo;
1285 }
1286
1287 // Next look for the form Foo.framework/Versions/A/Foo
1288 if (b == Name.npos)
1289 goto guess_library;
1290 c = Name.rfind('/', b);
1291 if (c == Name.npos || c == 0)
1292 goto guess_library;
1293 V = Name.slice(c+1, Name.npos);
1294 if (!V.startswith("Versions/"))
1295 goto guess_library;
1296 d = Name.rfind('/', c);
1297 if (d == Name.npos)
1298 Idx = 0;
1299 else
1300 Idx = d+1;
1301 F = Name.slice(Idx, Idx + Foo.size());
1302 DotFramework = Name.slice(Idx + Foo.size(),
1303 Idx + Foo.size() + sizeof(".framework/")-1);
1304 if (F == Foo && DotFramework == ".framework/") {
1305 isFramework = true;
1306 return Foo;
1307 }
1308
1309 guess_library:
1310 // pull off the suffix after the "." and make a point to it
1311 a = Name.rfind('.');
1312 if (a == Name.npos || a == 0)
1313 return StringRef();
1314 Dylib = Name.slice(a, Name.npos);
1315 if (Dylib != ".dylib")
1316 goto guess_qtx;
1317
1318 // First pull off the version letter for the form Foo.A.dylib if any.
1319 if (a >= 3) {
1320 Dot = Name.slice(a-2, a-1);
1321 if (Dot == ".")
1322 a = a - 2;
1323 }
1324
1325 b = Name.rfind('/', a);
1326 if (b == Name.npos)
1327 b = 0;
1328 else
1329 b = b+1;
1330 // ignore any suffix after an underbar like Foo_profile.A.dylib
1331 Idx = Name.find('_', b);
1332 if (Idx != Name.npos && Idx != b) {
1333 Lib = Name.slice(b, Idx);
1334 Suffix = Name.slice(Idx, a);
1335 }
1336 else
1337 Lib = Name.slice(b, a);
1338 // There are incorrect library names of the form:
1339 // libATS.A_profile.dylib so check for these.
1340 if (Lib.size() >= 3) {
1341 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1342 if (Dot == ".")
1343 Lib = Lib.slice(0, Lib.size()-2);
1344 }
1345 return Lib;
1346
1347 guess_qtx:
1348 Qtx = Name.slice(a, Name.npos);
1349 if (Qtx != ".qtx")
1350 return StringRef();
1351 b = Name.rfind('/', a);
1352 if (b == Name.npos)
1353 Lib = Name.slice(0, a);
1354 else
1355 Lib = Name.slice(b+1, a);
1356 // There are library names of the form: QT.A.qtx so check for these.
1357 if (Lib.size() >= 3) {
1358 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1359 if (Dot == ".")
1360 Lib = Lib.slice(0, Lib.size()-2);
1361 }
1362 return Lib;
1363 }
1364
1365 // getLibraryShortNameByIndex() is used to get the short name of the library
1366 // for an undefined symbol in a linked Mach-O binary that was linked with the
1367 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
1368 // It is passed the index (0 - based) of the library as translated from
1369 // GET_LIBRARY_ORDINAL (1 - based).
getLibraryShortNameByIndex(unsigned Index,StringRef & Res)1370 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1371 StringRef &Res) {
1372 if (Index >= Libraries.size())
1373 return object_error::parse_failed;
1374
1375 MachO::dylib_command D =
1376 getStruct<MachO::dylib_command>(this, Libraries[Index]);
1377 if (D.dylib.name >= D.cmdsize)
1378 return object_error::parse_failed;
1379
1380 // If the cache of LibrariesShortNames is not built up do that first for
1381 // all the Libraries.
1382 if (LibrariesShortNames.size() == 0) {
1383 for (unsigned i = 0; i < Libraries.size(); i++) {
1384 MachO::dylib_command D =
1385 getStruct<MachO::dylib_command>(this, Libraries[i]);
1386 if (D.dylib.name >= D.cmdsize) {
1387 LibrariesShortNames.push_back(StringRef());
1388 continue;
1389 }
1390 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
1391 StringRef Name = StringRef(P);
1392 StringRef Suffix;
1393 bool isFramework;
1394 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1395 if (shortName == StringRef())
1396 LibrariesShortNames.push_back(Name);
1397 else
1398 LibrariesShortNames.push_back(shortName);
1399 }
1400 }
1401
1402 Res = LibrariesShortNames[Index];
1403 return object_error::success;
1404 }
1405
symbol_begin_impl() const1406 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1407 return getSymbolByIndex(0);
1408 }
1409
symbol_end_impl() const1410 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1411 DataRefImpl DRI;
1412 if (!SymtabLoadCmd)
1413 return basic_symbol_iterator(SymbolRef(DRI, this));
1414
1415 MachO::symtab_command Symtab = getSymtabLoadCommand();
1416 unsigned SymbolTableEntrySize = is64Bit() ?
1417 sizeof(MachO::nlist_64) :
1418 sizeof(MachO::nlist);
1419 unsigned Offset = Symtab.symoff +
1420 Symtab.nsyms * SymbolTableEntrySize;
1421 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1422 return basic_symbol_iterator(SymbolRef(DRI, this));
1423 }
1424
getSymbolByIndex(unsigned Index) const1425 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1426 DataRefImpl DRI;
1427 if (!SymtabLoadCmd)
1428 return basic_symbol_iterator(SymbolRef(DRI, this));
1429
1430 MachO::symtab_command Symtab = getSymtabLoadCommand();
1431 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1432 unsigned SymbolTableEntrySize =
1433 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1434 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1435 DRI.p += Index * SymbolTableEntrySize;
1436 return basic_symbol_iterator(SymbolRef(DRI, this));
1437 }
1438
section_begin() const1439 section_iterator MachOObjectFile::section_begin() const {
1440 DataRefImpl DRI;
1441 return section_iterator(SectionRef(DRI, this));
1442 }
1443
section_end() const1444 section_iterator MachOObjectFile::section_end() const {
1445 DataRefImpl DRI;
1446 DRI.d.a = Sections.size();
1447 return section_iterator(SectionRef(DRI, this));
1448 }
1449
needed_library_begin() const1450 library_iterator MachOObjectFile::needed_library_begin() const {
1451 // TODO: implement
1452 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1453 }
1454
needed_library_end() const1455 library_iterator MachOObjectFile::needed_library_end() const {
1456 // TODO: implement
1457 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1458 }
1459
getBytesInAddress() const1460 uint8_t MachOObjectFile::getBytesInAddress() const {
1461 return is64Bit() ? 8 : 4;
1462 }
1463
getFileFormatName() const1464 StringRef MachOObjectFile::getFileFormatName() const {
1465 unsigned CPUType = getCPUType(this);
1466 if (!is64Bit()) {
1467 switch (CPUType) {
1468 case llvm::MachO::CPU_TYPE_I386:
1469 return "Mach-O 32-bit i386";
1470 case llvm::MachO::CPU_TYPE_ARM:
1471 return "Mach-O arm";
1472 case llvm::MachO::CPU_TYPE_POWERPC:
1473 return "Mach-O 32-bit ppc";
1474 default:
1475 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 &&
1476 "64-bit object file when we're not 64-bit?");
1477 return "Mach-O 32-bit unknown";
1478 }
1479 }
1480
1481 // Make sure the cpu type has the correct mask.
1482 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64)
1483 == llvm::MachO::CPU_ARCH_ABI64 &&
1484 "32-bit object file when we're 64-bit?");
1485
1486 switch (CPUType) {
1487 case llvm::MachO::CPU_TYPE_X86_64:
1488 return "Mach-O 64-bit x86-64";
1489 case llvm::MachO::CPU_TYPE_ARM64:
1490 return "Mach-O arm64";
1491 case llvm::MachO::CPU_TYPE_POWERPC64:
1492 return "Mach-O 64-bit ppc64";
1493 default:
1494 return "Mach-O 64-bit unknown";
1495 }
1496 }
1497
getArch(uint32_t CPUType)1498 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1499 switch (CPUType) {
1500 case llvm::MachO::CPU_TYPE_I386:
1501 return Triple::x86;
1502 case llvm::MachO::CPU_TYPE_X86_64:
1503 return Triple::x86_64;
1504 case llvm::MachO::CPU_TYPE_ARM:
1505 return Triple::arm;
1506 case llvm::MachO::CPU_TYPE_ARM64:
1507 return Triple::arm64;
1508 case llvm::MachO::CPU_TYPE_POWERPC:
1509 return Triple::ppc;
1510 case llvm::MachO::CPU_TYPE_POWERPC64:
1511 return Triple::ppc64;
1512 default:
1513 return Triple::UnknownArch;
1514 }
1515 }
1516
getArch(uint32_t CPUType,uint32_t CPUSubType)1517 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) {
1518 switch (CPUType) {
1519 case MachO::CPU_TYPE_I386:
1520 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1521 case MachO::CPU_SUBTYPE_I386_ALL:
1522 return Triple("i386-apple-darwin");
1523 default:
1524 return Triple();
1525 }
1526 case MachO::CPU_TYPE_X86_64:
1527 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1528 case MachO::CPU_SUBTYPE_X86_64_ALL:
1529 return Triple("x86_64-apple-darwin");
1530 case MachO::CPU_SUBTYPE_X86_64_H:
1531 return Triple("x86_64h-apple-darwin");
1532 default:
1533 return Triple();
1534 }
1535 case MachO::CPU_TYPE_ARM:
1536 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1537 case MachO::CPU_SUBTYPE_ARM_V4T:
1538 return Triple("armv4t-apple-darwin");
1539 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1540 return Triple("armv5e-apple-darwin");
1541 case MachO::CPU_SUBTYPE_ARM_V6:
1542 return Triple("armv6-apple-darwin");
1543 case MachO::CPU_SUBTYPE_ARM_V6M:
1544 return Triple("armv6m-apple-darwin");
1545 case MachO::CPU_SUBTYPE_ARM_V7EM:
1546 return Triple("armv7em-apple-darwin");
1547 case MachO::CPU_SUBTYPE_ARM_V7K:
1548 return Triple("armv7k-apple-darwin");
1549 case MachO::CPU_SUBTYPE_ARM_V7M:
1550 return Triple("armv7m-apple-darwin");
1551 case MachO::CPU_SUBTYPE_ARM_V7S:
1552 return Triple("armv7s-apple-darwin");
1553 default:
1554 return Triple();
1555 }
1556 case MachO::CPU_TYPE_ARM64:
1557 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1558 case MachO::CPU_SUBTYPE_ARM64_ALL:
1559 return Triple("arm64-apple-darwin");
1560 default:
1561 return Triple();
1562 }
1563 case MachO::CPU_TYPE_POWERPC:
1564 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1565 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1566 return Triple("ppc-apple-darwin");
1567 default:
1568 return Triple();
1569 }
1570 case MachO::CPU_TYPE_POWERPC64:
1571 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1572 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1573 return Triple("ppc64-apple-darwin");
1574 default:
1575 return Triple();
1576 }
1577 default:
1578 return Triple();
1579 }
1580 }
1581
getHostArch()1582 Triple MachOObjectFile::getHostArch() {
1583 return Triple(sys::getDefaultTargetTriple());
1584 }
1585
getArch(StringRef ArchFlag)1586 Triple MachOObjectFile::getArch(StringRef ArchFlag) {
1587 if (ArchFlag == "i386")
1588 return Triple("i386-apple-darwin");
1589 else if (ArchFlag == "x86_64")
1590 return Triple("x86_64-apple-darwin");
1591 else if (ArchFlag == "x86_64h")
1592 return Triple("x86_64h-apple-darwin");
1593 else if (ArchFlag == "armv4t" || ArchFlag == "arm")
1594 return Triple("armv4t-apple-darwin");
1595 else if (ArchFlag == "armv5e")
1596 return Triple("armv5e-apple-darwin");
1597 else if (ArchFlag == "armv6")
1598 return Triple("armv6-apple-darwin");
1599 else if (ArchFlag == "armv6m")
1600 return Triple("armv6m-apple-darwin");
1601 else if (ArchFlag == "armv7em")
1602 return Triple("armv7em-apple-darwin");
1603 else if (ArchFlag == "armv7k")
1604 return Triple("armv7k-apple-darwin");
1605 else if (ArchFlag == "armv7k")
1606 return Triple("armv7m-apple-darwin");
1607 else if (ArchFlag == "armv7s")
1608 return Triple("armv7s-apple-darwin");
1609 else if (ArchFlag == "arm64")
1610 return Triple("arm64-apple-darwin");
1611 else if (ArchFlag == "ppc")
1612 return Triple("ppc-apple-darwin");
1613 else if (ArchFlag == "ppc64")
1614 return Triple("ppc64-apple-darwin");
1615 else
1616 return Triple();
1617 }
1618
getArch() const1619 unsigned MachOObjectFile::getArch() const {
1620 return getArch(getCPUType(this));
1621 }
1622
getLoadName() const1623 StringRef MachOObjectFile::getLoadName() const {
1624 // TODO: Implement
1625 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
1626 }
1627
section_rel_begin(unsigned Index) const1628 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1629 DataRefImpl DRI;
1630 DRI.d.a = Index;
1631 return section_rel_begin(DRI);
1632 }
1633
section_rel_end(unsigned Index) const1634 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1635 DataRefImpl DRI;
1636 DRI.d.a = Index;
1637 return section_rel_end(DRI);
1638 }
1639
begin_dices() const1640 dice_iterator MachOObjectFile::begin_dices() const {
1641 DataRefImpl DRI;
1642 if (!DataInCodeLoadCmd)
1643 return dice_iterator(DiceRef(DRI, this));
1644
1645 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1646 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1647 return dice_iterator(DiceRef(DRI, this));
1648 }
1649
end_dices() const1650 dice_iterator MachOObjectFile::end_dices() const {
1651 DataRefImpl DRI;
1652 if (!DataInCodeLoadCmd)
1653 return dice_iterator(DiceRef(DRI, this));
1654
1655 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1656 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1657 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1658 return dice_iterator(DiceRef(DRI, this));
1659 }
1660
1661 StringRef
getSectionFinalSegmentName(DataRefImpl Sec) const1662 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1663 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1664 return parseSegmentOrSectionName(Raw.data());
1665 }
1666
1667 ArrayRef<char>
getSectionRawName(DataRefImpl Sec) const1668 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1669 const section_base *Base =
1670 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1671 return ArrayRef<char>(Base->sectname);
1672 }
1673
1674 ArrayRef<char>
getSectionRawFinalSegmentName(DataRefImpl Sec) const1675 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1676 const section_base *Base =
1677 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1678 return ArrayRef<char>(Base->segname);
1679 }
1680
1681 bool
isRelocationScattered(const MachO::any_relocation_info & RE) const1682 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1683 const {
1684 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1685 return false;
1686 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1687 }
1688
getPlainRelocationSymbolNum(const MachO::any_relocation_info & RE) const1689 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1690 const MachO::any_relocation_info &RE) const {
1691 if (isLittleEndian())
1692 return RE.r_word1 & 0xffffff;
1693 return RE.r_word1 >> 8;
1694 }
1695
getPlainRelocationExternal(const MachO::any_relocation_info & RE) const1696 bool MachOObjectFile::getPlainRelocationExternal(
1697 const MachO::any_relocation_info &RE) const {
1698 if (isLittleEndian())
1699 return (RE.r_word1 >> 27) & 1;
1700 return (RE.r_word1 >> 4) & 1;
1701 }
1702
getScatteredRelocationScattered(const MachO::any_relocation_info & RE) const1703 bool MachOObjectFile::getScatteredRelocationScattered(
1704 const MachO::any_relocation_info &RE) const {
1705 return RE.r_word0 >> 31;
1706 }
1707
getScatteredRelocationValue(const MachO::any_relocation_info & RE) const1708 uint32_t MachOObjectFile::getScatteredRelocationValue(
1709 const MachO::any_relocation_info &RE) const {
1710 return RE.r_word1;
1711 }
1712
getAnyRelocationAddress(const MachO::any_relocation_info & RE) const1713 unsigned MachOObjectFile::getAnyRelocationAddress(
1714 const MachO::any_relocation_info &RE) const {
1715 if (isRelocationScattered(RE))
1716 return getScatteredRelocationAddress(RE);
1717 return getPlainRelocationAddress(RE);
1718 }
1719
getAnyRelocationPCRel(const MachO::any_relocation_info & RE) const1720 unsigned MachOObjectFile::getAnyRelocationPCRel(
1721 const MachO::any_relocation_info &RE) const {
1722 if (isRelocationScattered(RE))
1723 return getScatteredRelocationPCRel(this, RE);
1724 return getPlainRelocationPCRel(this, RE);
1725 }
1726
getAnyRelocationLength(const MachO::any_relocation_info & RE) const1727 unsigned MachOObjectFile::getAnyRelocationLength(
1728 const MachO::any_relocation_info &RE) const {
1729 if (isRelocationScattered(RE))
1730 return getScatteredRelocationLength(RE);
1731 return getPlainRelocationLength(this, RE);
1732 }
1733
1734 unsigned
getAnyRelocationType(const MachO::any_relocation_info & RE) const1735 MachOObjectFile::getAnyRelocationType(
1736 const MachO::any_relocation_info &RE) const {
1737 if (isRelocationScattered(RE))
1738 return getScatteredRelocationType(RE);
1739 return getPlainRelocationType(this, RE);
1740 }
1741
1742 SectionRef
getRelocationSection(const MachO::any_relocation_info & RE) const1743 MachOObjectFile::getRelocationSection(
1744 const MachO::any_relocation_info &RE) const {
1745 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
1746 return *section_end();
1747 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
1748 DataRefImpl DRI;
1749 DRI.d.a = SecNum;
1750 return SectionRef(DRI, this);
1751 }
1752
1753 MachOObjectFile::LoadCommandInfo
getFirstLoadCommandInfo() const1754 MachOObjectFile::getFirstLoadCommandInfo() const {
1755 MachOObjectFile::LoadCommandInfo Load;
1756
1757 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
1758 sizeof(MachO::mach_header);
1759 Load.Ptr = getPtr(this, HeaderSize);
1760 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
1761 return Load;
1762 }
1763
1764 MachOObjectFile::LoadCommandInfo
getNextLoadCommandInfo(const LoadCommandInfo & L) const1765 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
1766 MachOObjectFile::LoadCommandInfo Next;
1767 Next.Ptr = L.Ptr + L.C.cmdsize;
1768 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
1769 return Next;
1770 }
1771
getSection(DataRefImpl DRI) const1772 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1773 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
1774 }
1775
getSection64(DataRefImpl DRI) const1776 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1777 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
1778 }
1779
getSection(const LoadCommandInfo & L,unsigned Index) const1780 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
1781 unsigned Index) const {
1782 const char *Sec = getSectionPtr(this, L, Index);
1783 return getStruct<MachO::section>(this, Sec);
1784 }
1785
getSection64(const LoadCommandInfo & L,unsigned Index) const1786 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1787 unsigned Index) const {
1788 const char *Sec = getSectionPtr(this, L, Index);
1789 return getStruct<MachO::section_64>(this, Sec);
1790 }
1791
1792 MachO::nlist
getSymbolTableEntry(DataRefImpl DRI) const1793 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1794 const char *P = reinterpret_cast<const char *>(DRI.p);
1795 return getStruct<MachO::nlist>(this, P);
1796 }
1797
1798 MachO::nlist_64
getSymbol64TableEntry(DataRefImpl DRI) const1799 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1800 const char *P = reinterpret_cast<const char *>(DRI.p);
1801 return getStruct<MachO::nlist_64>(this, P);
1802 }
1803
1804 MachO::linkedit_data_command
getLinkeditDataLoadCommand(const LoadCommandInfo & L) const1805 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1806 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
1807 }
1808
1809 MachO::segment_command
getSegmentLoadCommand(const LoadCommandInfo & L) const1810 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
1811 return getStruct<MachO::segment_command>(this, L.Ptr);
1812 }
1813
1814 MachO::segment_command_64
getSegment64LoadCommand(const LoadCommandInfo & L) const1815 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
1816 return getStruct<MachO::segment_command_64>(this, L.Ptr);
1817 }
1818
1819 MachO::linker_options_command
getLinkerOptionsLoadCommand(const LoadCommandInfo & L) const1820 MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
1821 return getStruct<MachO::linker_options_command>(this, L.Ptr);
1822 }
1823
1824 MachO::version_min_command
getVersionMinLoadCommand(const LoadCommandInfo & L) const1825 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
1826 return getStruct<MachO::version_min_command>(this, L.Ptr);
1827 }
1828
1829 MachO::dylib_command
getDylibIDLoadCommand(const LoadCommandInfo & L) const1830 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
1831 return getStruct<MachO::dylib_command>(this, L.Ptr);
1832 }
1833
1834
1835 MachO::any_relocation_info
getRelocation(DataRefImpl Rel) const1836 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
1837 DataRefImpl Sec;
1838 Sec.d.a = Rel.d.a;
1839 uint32_t Offset;
1840 if (is64Bit()) {
1841 MachO::section_64 Sect = getSection64(Sec);
1842 Offset = Sect.reloff;
1843 } else {
1844 MachO::section Sect = getSection(Sec);
1845 Offset = Sect.reloff;
1846 }
1847
1848 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
1849 getPtr(this, Offset)) + Rel.d.b;
1850 return getStruct<MachO::any_relocation_info>(
1851 this, reinterpret_cast<const char *>(P));
1852 }
1853
1854 MachO::data_in_code_entry
getDice(DataRefImpl Rel) const1855 MachOObjectFile::getDice(DataRefImpl Rel) const {
1856 const char *P = reinterpret_cast<const char *>(Rel.p);
1857 return getStruct<MachO::data_in_code_entry>(this, P);
1858 }
1859
getHeader() const1860 MachO::mach_header MachOObjectFile::getHeader() const {
1861 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
1862 }
1863
getHeader64() const1864 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
1865 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
1866 }
1867
getIndirectSymbolTableEntry(const MachO::dysymtab_command & DLC,unsigned Index) const1868 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
1869 const MachO::dysymtab_command &DLC,
1870 unsigned Index) const {
1871 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
1872 return getStruct<uint32_t>(this, getPtr(this, Offset));
1873 }
1874
1875 MachO::data_in_code_entry
getDataInCodeTableEntry(uint32_t DataOffset,unsigned Index) const1876 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
1877 unsigned Index) const {
1878 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
1879 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
1880 }
1881
getSymtabLoadCommand() const1882 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
1883 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
1884 }
1885
getDysymtabLoadCommand() const1886 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
1887 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
1888 }
1889
1890 MachO::linkedit_data_command
getDataInCodeLoadCommand() const1891 MachOObjectFile::getDataInCodeLoadCommand() const {
1892 if (DataInCodeLoadCmd)
1893 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
1894
1895 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
1896 MachO::linkedit_data_command Cmd;
1897 Cmd.cmd = MachO::LC_DATA_IN_CODE;
1898 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
1899 Cmd.dataoff = 0;
1900 Cmd.datasize = 0;
1901 return Cmd;
1902 }
1903
getStringTableData() const1904 StringRef MachOObjectFile::getStringTableData() const {
1905 MachO::symtab_command S = getSymtabLoadCommand();
1906 return getData().substr(S.stroff, S.strsize);
1907 }
1908
is64Bit() const1909 bool MachOObjectFile::is64Bit() const {
1910 return getType() == getMachOType(false, true) ||
1911 getType() == getMachOType(true, true);
1912 }
1913
ReadULEB128s(uint64_t Index,SmallVectorImpl<uint64_t> & Out) const1914 void MachOObjectFile::ReadULEB128s(uint64_t Index,
1915 SmallVectorImpl<uint64_t> &Out) const {
1916 DataExtractor extractor(ObjectFile::getData(), true, 0);
1917
1918 uint32_t offset = Index;
1919 uint64_t data = 0;
1920 while (uint64_t delta = extractor.getULEB128(&offset)) {
1921 data += delta;
1922 Out.push_back(data);
1923 }
1924 }
1925
getSectionPointer(DataRefImpl Rel) const1926 const char *MachOObjectFile::getSectionPointer(DataRefImpl Rel) const {
1927 return Sections[Rel.d.a];
1928 }
1929
1930 ErrorOr<ObjectFile *>
createMachOObjectFile(std::unique_ptr<MemoryBuffer> & Buffer)1931 ObjectFile::createMachOObjectFile(std::unique_ptr<MemoryBuffer> &Buffer) {
1932 StringRef Magic = Buffer->getBuffer().slice(0, 4);
1933 std::error_code EC;
1934 std::unique_ptr<MachOObjectFile> Ret;
1935 if (Magic == "\xFE\xED\xFA\xCE")
1936 Ret.reset(new MachOObjectFile(std::move(Buffer), false, false, EC));
1937 else if (Magic == "\xCE\xFA\xED\xFE")
1938 Ret.reset(new MachOObjectFile(std::move(Buffer), true, false, EC));
1939 else if (Magic == "\xFE\xED\xFA\xCF")
1940 Ret.reset(new MachOObjectFile(std::move(Buffer), false, true, EC));
1941 else if (Magic == "\xCF\xFA\xED\xFE")
1942 Ret.reset(new MachOObjectFile(std::move(Buffer), true, true, EC));
1943 else
1944 return object_error::parse_failed;
1945
1946 if (EC)
1947 return EC;
1948 return Ret.release();
1949 }
1950
1951 } // end namespace object
1952 } // end namespace llvm
1953