Line data Source code
1 : //===- MachOObjectFile.cpp - Mach-O object file binding -------------------===//
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/ADT/ArrayRef.h"
16 : #include "llvm/ADT/None.h"
17 : #include "llvm/ADT/STLExtras.h"
18 : #include "llvm/ADT/SmallVector.h"
19 : #include "llvm/ADT/StringRef.h"
20 : #include "llvm/ADT/StringSwitch.h"
21 : #include "llvm/ADT/Triple.h"
22 : #include "llvm/ADT/Twine.h"
23 : #include "llvm/BinaryFormat/MachO.h"
24 : #include "llvm/Object/Error.h"
25 : #include "llvm/Object/MachO.h"
26 : #include "llvm/Object/ObjectFile.h"
27 : #include "llvm/Object/SymbolicFile.h"
28 : #include "llvm/Support/DataExtractor.h"
29 : #include "llvm/Support/Debug.h"
30 : #include "llvm/Support/Error.h"
31 : #include "llvm/Support/ErrorHandling.h"
32 : #include "llvm/Support/Format.h"
33 : #include "llvm/Support/Host.h"
34 : #include "llvm/Support/LEB128.h"
35 : #include "llvm/Support/MemoryBuffer.h"
36 : #include "llvm/Support/SwapByteOrder.h"
37 : #include "llvm/Support/raw_ostream.h"
38 : #include <algorithm>
39 : #include <cassert>
40 : #include <cstddef>
41 : #include <cstdint>
42 : #include <cstring>
43 : #include <limits>
44 : #include <list>
45 : #include <memory>
46 : #include <string>
47 : #include <system_error>
48 :
49 : using namespace llvm;
50 : using namespace object;
51 :
52 : namespace {
53 :
54 : struct section_base {
55 : char sectname[16];
56 : char segname[16];
57 : };
58 :
59 : } // end anonymous namespace
60 :
61 217 : static Error malformedError(const Twine &Msg) {
62 217 : return make_error<GenericBinaryError>("truncated or malformed object (" +
63 434 : Msg + ")",
64 217 : object_error::parse_failed);
65 : }
66 :
67 : // FIXME: Replace all uses of this function with getStructOrErr.
68 : template <typename T>
69 130338 : static T getStruct(const MachOObjectFile &O, const char *P) {
70 : // Don't read before the beginning or past the end of the file
71 130338 : if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
72 0 : report_fatal_error("Malformed MachO file.");
73 :
74 : T Cmd;
75 130338 : memcpy(&Cmd, P, sizeof(T));
76 130338 : if (O.isLittleEndian() != sys::IsLittleEndianHost)
77 417 : MachO::swapStruct(Cmd);
78 130338 : return Cmd;
79 : }
80 3 :
81 : template <typename T>
82 3 : static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
83 0 : // Don't read before the beginning or past the end of the file
84 : if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
85 : return malformedError("Structure read out-of-range");
86 3 :
87 3 : T Cmd;
88 : memcpy(&Cmd, P, sizeof(T));
89 3 : if (O.isLittleEndian() != sys::IsLittleEndianHost)
90 : MachO::swapStruct(Cmd);
91 3 : return Cmd;
92 : }
93 3 :
94 0 : static const char *
95 : getSectionPtr(const MachOObjectFile &O, MachOObjectFile::LoadCommandInfo L,
96 : unsigned Sec) {
97 3 : uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
98 3 :
99 : bool Is64 = O.is64Bit();
100 3 : unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
101 : sizeof(MachO::segment_command);
102 6 : unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
103 : sizeof(MachO::section);
104 6 :
105 0 : uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
106 : return reinterpret_cast<const char*>(SectionAddr);
107 : }
108 6 :
109 6 : static const char *getPtr(const MachOObjectFile &O, size_t Offset) {
110 : assert(Offset <= O.getData().size());
111 6 : return O.getData().data() + Offset;
112 : }
113 18 :
114 : static MachO::nlist_base
115 18 : getSymbolTableEntryBase(const MachOObjectFile &O, DataRefImpl DRI) {
116 0 : const char *P = reinterpret_cast<const char *>(DRI.p);
117 : return getStruct<MachO::nlist_base>(O, P);
118 : }
119 18 :
120 18 : static StringRef parseSegmentOrSectionName(const char *P) {
121 : if (P[15] == 0)
122 18 : // Null terminated.
123 : return P;
124 5 : // Not null terminated, so this is a 16 char string.
125 : return StringRef(P, 16);
126 5 : }
127 0 :
128 : static unsigned getCPUType(const MachOObjectFile &O) {
129 : return O.getHeader().cputype;
130 5 : }
131 5 :
132 : static uint32_t
133 5 : getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
134 : return RE.r_word0;
135 6 : }
136 :
137 6 : static unsigned
138 0 : getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
139 : return RE.r_word0 & 0xffffff;
140 : }
141 6 :
142 6 : static bool getPlainRelocationPCRel(const MachOObjectFile &O,
143 : const MachO::any_relocation_info &RE) {
144 6 : if (O.isLittleEndian())
145 : return (RE.r_word1 >> 24) & 1;
146 24 : return (RE.r_word1 >> 7) & 1;
147 : }
148 24 :
149 0 : static bool
150 : getScatteredRelocationPCRel(const MachO::any_relocation_info &RE) {
151 : return (RE.r_word0 >> 30) & 1;
152 24 : }
153 24 :
154 : static unsigned getPlainRelocationLength(const MachOObjectFile &O,
155 24 : const MachO::any_relocation_info &RE) {
156 : if (O.isLittleEndian())
157 114 : return (RE.r_word1 >> 25) & 3;
158 : return (RE.r_word1 >> 5) & 3;
159 114 : }
160 0 :
161 : static unsigned
162 : getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
163 114 : return (RE.r_word0 >> 28) & 3;
164 114 : }
165 :
166 114 : static unsigned getPlainRelocationType(const MachOObjectFile &O,
167 : const MachO::any_relocation_info &RE) {
168 12 : if (O.isLittleEndian())
169 : return RE.r_word1 >> 28;
170 12 : return RE.r_word1 & 0xf;
171 0 : }
172 :
173 : static uint32_t getSectionFlags(const MachOObjectFile &O,
174 12 : DataRefImpl Sec) {
175 12 : if (O.is64Bit()) {
176 : MachO::section_64 Sect = O.getSection64(Sec);
177 12 : return Sect.flags;
178 : }
179 3 : MachO::section Sect = O.getSection(Sec);
180 : return Sect.flags;
181 3 : }
182 0 :
183 : static Expected<MachOObjectFile::LoadCommandInfo>
184 : getLoadCommandInfo(const MachOObjectFile &Obj, const char *Ptr,
185 3 : uint32_t LoadCommandIndex) {
186 3 : if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
187 : if (CmdOrErr->cmdsize + Ptr > Obj.getData().end())
188 3 : return malformedError("load command " + Twine(LoadCommandIndex) +
189 : " extends past end of file");
190 3 : if (CmdOrErr->cmdsize < 8)
191 : return malformedError("load command " + Twine(LoadCommandIndex) +
192 3 : " with size less than 8 bytes");
193 0 : return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
194 : } else
195 : return CmdOrErr.takeError();
196 3 : }
197 3 :
198 : static Expected<MachOObjectFile::LoadCommandInfo>
199 3 : getFirstLoadCommandInfo(const MachOObjectFile &Obj) {
200 : unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
201 323 : : sizeof(MachO::mach_header);
202 : if (sizeof(MachO::load_command) > Obj.getHeader().sizeofcmds)
203 323 : return malformedError("load command 0 extends past the end all load "
204 0 : "commands in the file");
205 : return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0);
206 : }
207 323 :
208 323 : static Expected<MachOObjectFile::LoadCommandInfo>
209 : getNextLoadCommandInfo(const MachOObjectFile &Obj, uint32_t LoadCommandIndex,
210 323 : const MachOObjectFile::LoadCommandInfo &L) {
211 : unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
212 828 : : sizeof(MachO::mach_header);
213 : if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >
214 828 : Obj.getData().data() + HeaderSize + Obj.getHeader().sizeofcmds)
215 0 : return malformedError("load command " + Twine(LoadCommandIndex + 1) +
216 : " extends past the end all load commands in the file");
217 : return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);
218 828 : }
219 828 :
220 : template <typename T>
221 828 : static void parseHeader(const MachOObjectFile &Obj, T &Header,
222 : Error &Err) {
223 613 : if (sizeof(T) > Obj.getData().size()) {
224 : Err = malformedError("the mach header extends past the end of the "
225 613 : "file");
226 0 : return;
227 : }
228 : if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
229 613 : Header = *HeaderOrErr;
230 613 : else
231 0 : Err = HeaderOrErr.takeError();
232 613 : }
233 :
234 1219 : // This is used to check for overlapping of Mach-O elements.
235 : struct MachOElement {
236 1219 : uint64_t Offset;
237 0 : uint64_t Size;
238 : const char *Name;
239 : };
240 1219 :
241 1219 : static Error checkOverlappingElement(std::list<MachOElement> &Elements,
242 : uint64_t Offset, uint64_t Size,
243 1219 : const char *Name) {
244 : if (Size == 0)
245 3916 : return Error::success();
246 :
247 3916 : for (auto it=Elements.begin() ; it != Elements.end(); ++it) {
248 0 : auto E = *it;
249 : if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||
250 : (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) ||
251 3916 : (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))
252 3916 : return malformedError(Twine(Name) + " at offset " + Twine(Offset) +
253 24 : " with a size of " + Twine(Size) + ", overlaps " +
254 3916 : E.Name + " at offset " + Twine(E.Offset) + " with "
255 : "a size of " + Twine(E.Size));
256 13324 : auto nt = it;
257 : nt++;
258 13324 : if (nt != Elements.end()) {
259 0 : auto N = *nt;
260 : if (Offset + Size <= N.Offset) {
261 : Elements.insert(nt, {Offset, Size, Name});
262 13324 : return Error::success();
263 13324 : }
264 : }
265 13324 : }
266 : Elements.push_back({Offset, Size, Name});
267 18249 : return Error::success();
268 : }
269 18249 :
270 0 : // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
271 : // sections to \param Sections, and optionally sets
272 : // \param IsPageZeroSegment to true.
273 18249 : template <typename Segment, typename Section>
274 18249 : static Error parseSegmentLoadCommand(
275 : const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load,
276 18249 : SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
277 : uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders,
278 56 : std::list<MachOElement> &Elements) {
279 : const unsigned SegmentLoadSize = sizeof(Segment);
280 56 : if (Load.C.cmdsize < SegmentLoadSize)
281 0 : return malformedError("load command " + Twine(LoadCommandIndex) +
282 : " " + CmdName + " cmdsize too small");
283 : if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
284 56 : Segment S = SegOrErr.get();
285 56 : const unsigned SectionSize = sizeof(Section);
286 : uint64_t FileSize = Obj.getData().size();
287 56 : if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
288 : S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
289 79 : return malformedError("load command " + Twine(LoadCommandIndex) +
290 : " inconsistent cmdsize in " + CmdName +
291 79 : " for the number of sections");
292 0 : for (unsigned J = 0; J < S.nsects; ++J) {
293 : const char *Sec = getSectionPtr(Obj, Load, J);
294 : Sections.push_back(Sec);
295 79 : Section s = getStruct<Section>(Obj, Sec);
296 79 : if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
297 : Obj.getHeader().filetype != MachO::MH_DSYM &&
298 79 : s.flags != MachO::S_ZEROFILL &&
299 : s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
300 7528 : s.offset > FileSize)
301 : return malformedError("offset field of section " + Twine(J) + " in " +
302 7528 : CmdName + " command " + Twine(LoadCommandIndex) +
303 0 : " extends past the end of the file");
304 : if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
305 : Obj.getHeader().filetype != MachO::MH_DSYM &&
306 7528 : s.flags != MachO::S_ZEROFILL &&
307 7528 : s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 &&
308 : s.offset < SizeOfHeaders && s.size != 0)
309 7528 : return malformedError("offset field of section " + Twine(J) + " in " +
310 : CmdName + " command " + Twine(LoadCommandIndex) +
311 1 : " not past the headers of the file");
312 : uint64_t BigSize = s.offset;
313 1 : BigSize += s.size;
314 0 : if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
315 : Obj.getHeader().filetype != MachO::MH_DSYM &&
316 : s.flags != MachO::S_ZEROFILL &&
317 1 : s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
318 1 : BigSize > FileSize)
319 0 : return malformedError("offset field plus size field of section " +
320 1 : Twine(J) + " in " + CmdName + " command " +
321 : Twine(LoadCommandIndex) +
322 0 : " extends past the end of the file");
323 : if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
324 0 : Obj.getHeader().filetype != MachO::MH_DSYM &&
325 0 : s.flags != MachO::S_ZEROFILL &&
326 : s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
327 : s.size > S.filesize)
328 0 : return malformedError("size field of section " +
329 0 : Twine(J) + " in " + CmdName + " command " +
330 0 : Twine(LoadCommandIndex) +
331 0 : " greater than the segment");
332 : if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
333 31 : Obj.getHeader().filetype != MachO::MH_DSYM && s.size != 0 &&
334 : s.addr < S.vmaddr)
335 31 : return malformedError("addr field of section " + Twine(J) + " in " +
336 0 : CmdName + " command " + Twine(LoadCommandIndex) +
337 : " less than the segment's vmaddr");
338 : BigSize = s.addr;
339 31 : BigSize += s.size;
340 31 : uint64_t BigEnd = S.vmaddr;
341 : BigEnd += S.vmsize;
342 31 : if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd)
343 : return malformedError("addr field plus size of section " + Twine(J) +
344 52 : " in " + CmdName + " command " +
345 : Twine(LoadCommandIndex) +
346 52 : " greater than than "
347 0 : "the segment's vmaddr plus vmsize");
348 : if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
349 : Obj.getHeader().filetype != MachO::MH_DSYM &&
350 52 : s.flags != MachO::S_ZEROFILL &&
351 52 : s.flags != MachO::S_THREAD_LOCAL_ZEROFILL)
352 : if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,
353 52 : "section contents"))
354 : return Err;
355 67 : if (s.reloff > FileSize)
356 : return malformedError("reloff field of section " + Twine(J) + " in " +
357 67 : CmdName + " command " + Twine(LoadCommandIndex) +
358 0 : " extends past the end of the file");
359 : BigSize = s.nreloc;
360 : BigSize *= sizeof(struct MachO::relocation_info);
361 67 : BigSize += s.reloff;
362 67 : if (BigSize > FileSize)
363 : return malformedError("reloff field plus nreloc field times sizeof("
364 67 : "struct relocation_info) of section " +
365 : Twine(J) + " in " + CmdName + " command " +
366 0 : Twine(LoadCommandIndex) +
367 : " extends past the end of the file");
368 0 : if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *
369 0 : sizeof(struct
370 : MachO::relocation_info),
371 : "section relocation entries"))
372 0 : return Err;
373 0 : }
374 : if (S.fileoff > FileSize)
375 0 : return malformedError("load command " + Twine(LoadCommandIndex) +
376 : " fileoff field in " + CmdName +
377 86 : " extends past the end of the file");
378 : uint64_t BigSize = S.fileoff;
379 86 : BigSize += S.filesize;
380 0 : if (BigSize > FileSize)
381 : return malformedError("load command " + Twine(LoadCommandIndex) +
382 : " fileoff field plus filesize field in " +
383 86 : CmdName + " extends past the end of the file");
384 86 : if (S.vmsize != 0 && S.filesize > S.vmsize)
385 : return malformedError("load command " + Twine(LoadCommandIndex) +
386 86 : " filesize field in " + CmdName +
387 : " greater than vmsize field");
388 1424 : IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
389 : } else
390 1424 : return SegOrErr.takeError();
391 0 :
392 : return Error::success();
393 : }
394 1424 :
395 1424 : static Error checkSymtabCommand(const MachOObjectFile &Obj,
396 0 : const MachOObjectFile::LoadCommandInfo &Load,
397 1424 : uint32_t LoadCommandIndex,
398 : const char **SymtabLoadCmd,
399 177 : std::list<MachOElement> &Elements) {
400 : if (Load.C.cmdsize < sizeof(MachO::symtab_command))
401 177 : return malformedError("load command " + Twine(LoadCommandIndex) +
402 0 : " LC_SYMTAB cmdsize too small");
403 : if (*SymtabLoadCmd != nullptr)
404 : return malformedError("more than one LC_SYMTAB command");
405 177 : MachO::symtab_command Symtab =
406 177 : getStruct<MachO::symtab_command>(Obj, Load.Ptr);
407 0 : if (Symtab.cmdsize != sizeof(MachO::symtab_command))
408 177 : return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +
409 : " has incorrect cmdsize");
410 8373 : uint64_t FileSize = Obj.getData().size();
411 : if (Symtab.symoff > FileSize)
412 8373 : return malformedError("symoff field of LC_SYMTAB command " +
413 0 : Twine(LoadCommandIndex) + " extends past the end "
414 : "of the file");
415 : uint64_t SymtabSize = Symtab.nsyms;
416 8373 : const char *struct_nlist_name;
417 8373 : if (Obj.is64Bit()) {
418 : SymtabSize *= sizeof(MachO::nlist_64);
419 8373 : struct_nlist_name = "struct nlist_64";
420 : } else {
421 1819 : SymtabSize *= sizeof(MachO::nlist);
422 : struct_nlist_name = "struct nlist";
423 1819 : }
424 0 : uint64_t BigSize = SymtabSize;
425 : BigSize += Symtab.symoff;
426 : if (BigSize > FileSize)
427 1819 : return malformedError("symoff field plus nsyms field times sizeof(" +
428 1819 : Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
429 : Twine(LoadCommandIndex) + " extends past the end "
430 1819 : "of the file");
431 : if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,
432 54404 : "symbol table"))
433 : return Err;
434 54404 : if (Symtab.stroff > FileSize)
435 0 : return malformedError("stroff field of LC_SYMTAB command " +
436 : Twine(LoadCommandIndex) + " extends past the end "
437 : "of the file");
438 54404 : BigSize = Symtab.stroff;
439 54404 : BigSize += Symtab.strsize;
440 114 : if (BigSize > FileSize)
441 54404 : return malformedError("stroff field plus strsize field of LC_SYMTAB "
442 : "command " + Twine(LoadCommandIndex) + " extends "
443 17569 : "past the end of the file");
444 : if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,
445 17569 : Symtab.strsize, "string table"))
446 0 : return Err;
447 : *SymtabLoadCmd = Load.Ptr;
448 : return Error::success();
449 17569 : }
450 17569 :
451 279 : static Error checkDysymtabCommand(const MachOObjectFile &Obj,
452 17569 : const MachOObjectFile::LoadCommandInfo &Load,
453 : uint32_t LoadCommandIndex,
454 3 : const char **DysymtabLoadCmd,
455 : std::list<MachOElement> &Elements) {
456 3 : if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))
457 0 : return malformedError("load command " + Twine(LoadCommandIndex) +
458 : " LC_DYSYMTAB cmdsize too small");
459 : if (*DysymtabLoadCmd != nullptr)
460 3 : return malformedError("more than one LC_DYSYMTAB command");
461 3 : MachO::dysymtab_command Dysymtab =
462 : getStruct<MachO::dysymtab_command>(Obj, Load.Ptr);
463 3 : if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))
464 : return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +
465 : " has incorrect cmdsize");
466 : uint64_t FileSize = Obj.getData().size();
467 15567 : if (Dysymtab.tocoff > FileSize)
468 : return malformedError("tocoff field of LC_DYSYMTAB command " +
469 15567 : Twine(LoadCommandIndex) + " extends past the end of "
470 0 : "the file");
471 : uint64_t BigSize = Dysymtab.ntoc;
472 : BigSize *= sizeof(MachO::dylib_table_of_contents);
473 15567 : BigSize += Dysymtab.tocoff;
474 15567 : if (BigSize > FileSize)
475 16 : return malformedError("tocoff field plus ntoc field times sizeof(struct "
476 : "dylib_table_of_contents) of LC_DYSYMTAB command " +
477 : Twine(LoadCommandIndex) + " extends past the end of "
478 544 : "the file");
479 : if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff,
480 544 : Dysymtab.ntoc * sizeof(struct
481 0 : MachO::dylib_table_of_contents),
482 : "table of contents"))
483 : return Err;
484 544 : if (Dysymtab.modtaboff > FileSize)
485 544 : return malformedError("modtaboff field of LC_DYSYMTAB command " +
486 12 : Twine(LoadCommandIndex) + " extends past the end of "
487 : "the file");
488 : BigSize = Dysymtab.nmodtab;
489 2527 : const char *struct_dylib_module_name;
490 : uint64_t sizeof_modtab;
491 2527 : if (Obj.is64Bit()) {
492 0 : sizeof_modtab = sizeof(MachO::dylib_module_64);
493 : struct_dylib_module_name = "struct dylib_module_64";
494 : } else {
495 2527 : sizeof_modtab = sizeof(MachO::dylib_module);
496 2527 : struct_dylib_module_name = "struct dylib_module";
497 4 : }
498 : BigSize *= sizeof_modtab;
499 : BigSize += Dysymtab.modtaboff;
500 490 : if (BigSize > FileSize)
501 : return malformedError("modtaboff field plus nmodtab field times sizeof(" +
502 490 : Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "
503 0 : "command " + Twine(LoadCommandIndex) + " extends "
504 : "past the end of the file");
505 : if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff,
506 490 : Dysymtab.nmodtab * sizeof_modtab,
507 490 : "module table"))
508 : return Err;
509 : if (Dysymtab.extrefsymoff > FileSize)
510 : return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
511 1344 : Twine(LoadCommandIndex) + " extends past the end of "
512 : "the file");
513 1344 : BigSize = Dysymtab.nextrefsyms;
514 0 : BigSize *= sizeof(MachO::dylib_reference);
515 : BigSize += Dysymtab.extrefsymoff;
516 : if (BigSize > FileSize)
517 1344 : return malformedError("extrefsymoff field plus nextrefsyms field times "
518 1344 : "sizeof(struct dylib_reference) of LC_DYSYMTAB "
519 : "command " + Twine(LoadCommandIndex) + " extends "
520 : "past the end of the file");
521 : if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff,
522 10662 : Dysymtab.nextrefsyms *
523 : sizeof(MachO::dylib_reference),
524 10662 : "reference table"))
525 0 : return Err;
526 : if (Dysymtab.indirectsymoff > FileSize)
527 : return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
528 10662 : Twine(LoadCommandIndex) + " extends past the end of "
529 10662 : "the file");
530 : BigSize = Dysymtab.nindirectsyms;
531 : BigSize *= sizeof(uint32_t);
532 : BigSize += Dysymtab.indirectsymoff;
533 : if (BigSize > FileSize)
534 : return malformedError("indirectsymoff field plus nindirectsyms field times "
535 0 : "sizeof(uint32_t) of LC_DYSYMTAB command " +
536 : Twine(LoadCommandIndex) + " extends past the end of "
537 15560 : "the file");
538 : if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff,
539 0 : Dysymtab.nindirectsyms *
540 15560 : sizeof(uint32_t),
541 : "indirect table"))
542 15560 : return Err;
543 : if (Dysymtab.extreloff > FileSize)
544 : return malformedError("extreloff field of LC_DYSYMTAB command " +
545 15560 : Twine(LoadCommandIndex) + " extends past the end of "
546 15560 : "the file");
547 : BigSize = Dysymtab.nextrel;
548 : BigSize *= sizeof(MachO::relocation_info);
549 : BigSize += Dysymtab.extreloff;
550 : if (BigSize > FileSize)
551 372 : return malformedError("extreloff field plus nextrel field times sizeof"
552 : "(struct relocation_info) of LC_DYSYMTAB command " +
553 : Twine(LoadCommandIndex) + " extends past the end of "
554 : "the file");
555 : if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff,
556 18249 : Dysymtab.nextrel *
557 3513 : sizeof(MachO::relocation_info),
558 : "external relocation table"))
559 : return Err;
560 : if (Dysymtab.locreloff > FileSize)
561 34816 : return malformedError("locreloff field of LC_DYSYMTAB command " +
562 : Twine(LoadCommandIndex) + " extends past the end of "
563 : "the file");
564 : BigSize = Dysymtab.nlocrel;
565 : BigSize *= sizeof(MachO::relocation_info);
566 : BigSize += Dysymtab.locreloff;
567 : if (BigSize > FileSize)
568 : return malformedError("locreloff field plus nlocrel field times sizeof"
569 0 : "(struct relocation_info) of LC_DYSYMTAB command " +
570 : Twine(LoadCommandIndex) + " extends past the end of "
571 : "the file");
572 : if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff,
573 0 : Dysymtab.nlocrel *
574 0 : sizeof(MachO::relocation_info),
575 : "local relocation table"))
576 : return Err;
577 : *DysymtabLoadCmd = Load.Ptr;
578 0 : return Error::success();
579 160 : }
580 :
581 : static Error checkLinkeditDataCommand(const MachOObjectFile &Obj,
582 0 : const MachOObjectFile::LoadCommandInfo &Load,
583 : uint32_t LoadCommandIndex,
584 0 : const char **LoadCmd, const char *CmdName,
585 443 : std::list<MachOElement> &Elements,
586 10 : const char *ElementName) {
587 : if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
588 : return malformedError("load command " + Twine(LoadCommandIndex) + " " +
589 : CmdName + " cmdsize too small");
590 0 : if (*LoadCmd != nullptr)
591 98 : return malformedError("more than one " + Twine(CmdName) + " command");
592 : MachO::linkedit_data_command LinkData =
593 : getStruct<MachO::linkedit_data_command>(Obj, Load.Ptr);
594 0 : if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
595 : return malformedError(Twine(CmdName) + " command " +
596 0 : Twine(LoadCommandIndex) + " has incorrect cmdsize");
597 1317 : uint64_t FileSize = Obj.getData().size();
598 10 : if (LinkData.dataoff > FileSize)
599 : return malformedError("dataoff field of " + Twine(CmdName) + " command " +
600 : Twine(LoadCommandIndex) + " extends past the end of "
601 : "the file");
602 0 : uint64_t BigSize = LinkData.dataoff;
603 105 : BigSize += LinkData.datasize;
604 : if (BigSize > FileSize)
605 : return malformedError("dataoff field plus datasize field of " +
606 0 : Twine(CmdName) + " command " +
607 : Twine(LoadCommandIndex) + " extends past the end of "
608 0 : "the file");
609 1700 : if (Error Err = checkOverlappingElement(Elements, LinkData.dataoff,
610 20 : LinkData.datasize, ElementName))
611 : return Err;
612 : *LoadCmd = Load.Ptr;
613 18213 : return Error::success();
614 : }
615 18213 :
616 15950 : static Error checkDyldInfoCommand(const MachOObjectFile &Obj,
617 15950 : const MachOObjectFile::LoadCommandInfo &Load,
618 : uint32_t LoadCommandIndex,
619 2263 : const char **LoadCmd, const char *CmdName,
620 2263 : std::list<MachOElement> &Elements) {
621 : if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))
622 : return malformedError("load command " + Twine(LoadCommandIndex) + " " +
623 : CmdName + " cmdsize too small");
624 10662 : if (*LoadCmd != nullptr)
625 : return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
626 10662 : "command");
627 10662 : MachO::dyld_info_command DyldInfo =
628 0 : getStruct<MachO::dyld_info_command>(Obj, Load.Ptr);
629 0 : if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))
630 10662 : return malformedError(Twine(CmdName) + " command " +
631 1 : Twine(LoadCommandIndex) + " has incorrect cmdsize");
632 1 : uint64_t FileSize = Obj.getData().size();
633 10661 : if (DyldInfo.rebase_off > FileSize)
634 : return malformedError("rebase_off field of " + Twine(CmdName) +
635 : " command " + Twine(LoadCommandIndex) + " extends "
636 : "past the end of the file");
637 : uint64_t BigSize = DyldInfo.rebase_off;
638 : BigSize += DyldInfo.rebase_size;
639 1821 : if (BigSize > FileSize)
640 1821 : return malformedError("rebase_off field plus rebase_size field of " +
641 1821 : Twine(CmdName) + " command " +
642 1821 : Twine(LoadCommandIndex) + " extends past the end of "
643 1 : "the file");
644 : if (Error Err = checkOverlappingElement(Elements, DyldInfo.rebase_off,
645 1820 : DyldInfo.rebase_size,
646 : "dyld rebase info"))
647 : return Err;
648 : if (DyldInfo.bind_off > FileSize)
649 0 : return malformedError("bind_off field of " + Twine(CmdName) +
650 : " command " + Twine(LoadCommandIndex) + " extends "
651 0 : "past the end of the file");
652 0 : BigSize = DyldInfo.bind_off;
653 0 : BigSize += DyldInfo.bind_size;
654 0 : if (BigSize > FileSize)
655 0 : return malformedError("bind_off field plus bind_size field of " +
656 0 : Twine(CmdName) + " command " +
657 0 : Twine(LoadCommandIndex) + " extends past the end of "
658 : "the file");
659 : if (Error Err = checkOverlappingElement(Elements, DyldInfo.bind_off,
660 : DyldInfo.bind_size,
661 0 : "dyld bind info"))
662 : return Err;
663 0 : if (DyldInfo.weak_bind_off > FileSize)
664 0 : return malformedError("weak_bind_off field of " + Twine(CmdName) +
665 : " command " + Twine(LoadCommandIndex) + " extends "
666 0 : "past the end of the file");
667 : BigSize = DyldInfo.weak_bind_off;
668 0 : BigSize += DyldInfo.weak_bind_size;
669 0 : if (BigSize > FileSize)
670 : return malformedError("weak_bind_off field plus weak_bind_size field of " +
671 : Twine(CmdName) + " command " +
672 : Twine(LoadCommandIndex) + " extends past the end of "
673 0 : "the file");
674 : if (Error Err = checkOverlappingElement(Elements, DyldInfo.weak_bind_off,
675 0 : DyldInfo.weak_bind_size,
676 0 : "dyld weak bind info"))
677 : return Err;
678 0 : if (DyldInfo.lazy_bind_off > FileSize)
679 : return malformedError("lazy_bind_off field of " + Twine(CmdName) +
680 0 : " command " + Twine(LoadCommandIndex) + " extends "
681 0 : "past the end of the file");
682 : BigSize = DyldInfo.lazy_bind_off;
683 : BigSize += DyldInfo.lazy_bind_size;
684 : if (BigSize > FileSize)
685 0 : return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
686 : Twine(CmdName) + " command " +
687 0 : Twine(LoadCommandIndex) + " extends past the end of "
688 0 : "the file");
689 : if (Error Err = checkOverlappingElement(Elements, DyldInfo.lazy_bind_off,
690 0 : DyldInfo.lazy_bind_size,
691 : "dyld lazy bind info"))
692 0 : return Err;
693 0 : if (DyldInfo.export_off > FileSize)
694 : return malformedError("export_off field of " + Twine(CmdName) +
695 : " command " + Twine(LoadCommandIndex) + " extends "
696 : "past the end of the file");
697 : BigSize = DyldInfo.export_off;
698 : BigSize += DyldInfo.export_size;
699 : if (BigSize > FileSize)
700 : return malformedError("export_off field plus export_size field of " +
701 : Twine(CmdName) + " command " +
702 : Twine(LoadCommandIndex) + " extends past the end of "
703 : "the file");
704 : if (Error Err = checkOverlappingElement(Elements, DyldInfo.export_off,
705 40801 : DyldInfo.export_size,
706 : "dyld export info"))
707 : return Err;
708 40801 : *LoadCmd = Load.Ptr;
709 : return Error::success();
710 : }
711 146584 :
712 135271 : static Error checkDylibCommand(const MachOObjectFile &Obj,
713 135271 : const MachOObjectFile::LoadCommandInfo &Load,
714 135251 : uint32_t LoadCommandIndex, const char *CmdName) {
715 0 : if (Load.C.cmdsize < sizeof(MachO::dylib_command))
716 20 : return malformedError("load command " + Twine(LoadCommandIndex) + " " +
717 40 : CmdName + " cmdsize too small");
718 20 : MachO::dylib_command D = getStruct<MachO::dylib_command>(Obj, Load.Ptr);
719 20 : if (D.dylib.name < sizeof(MachO::dylib_command))
720 : return malformedError("load command " + Twine(LoadCommandIndex) + " " +
721 : CmdName + " name.offset field too small, not past "
722 135251 : "the end of the dylib_command struct");
723 123938 : if (D.dylib.name >= D.cmdsize)
724 123938 : return malformedError("load command " + Twine(LoadCommandIndex) + " " +
725 7158 : CmdName + " name.offset field extends past the end "
726 : "of the load command");
727 : // Make sure there is a null between the starting offset of the name and
728 : // the end of the load command.
729 : uint32_t i;
730 11313 : const char *P = (const char *)Load.Ptr;
731 : for (i = D.dylib.name; i < D.cmdsize; i++)
732 : if (P[i] == '\0')
733 : break;
734 : if (i >= D.cmdsize)
735 : return malformedError("load command " + Twine(LoadCommandIndex) + " " +
736 : CmdName + " library name extends past the end of the "
737 : "load command");
738 3072 : return Error::success();
739 : }
740 :
741 : static Error checkDylibIdCommand(const MachOObjectFile &Obj,
742 : const MachOObjectFile::LoadCommandInfo &Load,
743 : uint32_t LoadCommandIndex,
744 3072 : const char **LoadCmd) {
745 1 : if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,
746 1 : "LC_ID_DYLIB"))
747 3071 : return Err;
748 3071 : if (*LoadCmd != nullptr)
749 : return malformedError("more than one LC_ID_DYLIB command");
750 3071 : if (Obj.getHeader().filetype != MachO::MH_DYLIB &&
751 3071 : Obj.getHeader().filetype != MachO::MH_DYLIB_STUB)
752 3071 : return malformedError("LC_ID_DYLIB load command in non-dynamic library "
753 2 : "file type");
754 2 : *LoadCmd = Load.Ptr;
755 2 : return Error::success();
756 16953 : }
757 13899 :
758 13899 : static Error checkDyldCommand(const MachOObjectFile &Obj,
759 13899 : const MachOObjectFile::LoadCommandInfo &Load,
760 13899 : uint32_t LoadCommandIndex, const char *CmdName) {
761 13897 : if (Load.C.cmdsize < sizeof(MachO::dylinker_command))
762 12080 : return malformedError("load command " + Twine(LoadCommandIndex) + " " +
763 13899 : CmdName + " cmdsize too small");
764 12069 : MachO::dylinker_command D = getStruct<MachO::dylinker_command>(Obj, Load.Ptr);
765 1 : if (D.name < sizeof(MachO::dylinker_command))
766 1 : return malformedError("load command " + Twine(LoadCommandIndex) + " " +
767 1 : CmdName + " name.offset field too small, not past "
768 13898 : "the end of the dylinker_command struct");
769 13896 : if (D.name >= D.cmdsize)
770 12079 : return malformedError("load command " + Twine(LoadCommandIndex) + " " +
771 12068 : CmdName + " name.offset field extends past the end "
772 15136 : "of the load command");
773 1 : // Make sure there is a null between the starting offset of the name and
774 1 : // the end of the load command.
775 1 : uint32_t i;
776 13897 : const char *P = (const char *)Load.Ptr;
777 13897 : for (i = D.name; i < D.cmdsize; i++)
778 13897 : if (P[i] == '\0')
779 13895 : break;
780 12078 : if (i >= D.cmdsize)
781 25964 : return malformedError("load command " + Twine(LoadCommandIndex) + " " +
782 : CmdName + " dyld name extends past the end of the "
783 2 : "load command");
784 4 : return Error::success();
785 2 : }
786 2 :
787 13895 : static Error checkVersCommand(const MachOObjectFile &Obj,
788 13893 : const MachOObjectFile::LoadCommandInfo &Load,
789 12076 : uint32_t LoadCommandIndex,
790 13895 : const char **LoadCmd, const char *CmdName) {
791 12065 : if (Load.C.cmdsize != sizeof(MachO::version_min_command))
792 1 : return malformedError("load command " + Twine(LoadCommandIndex) + " " +
793 2 : CmdName + " has incorrect cmdsize");
794 1 : if (*LoadCmd != nullptr)
795 1 : return malformedError("more than one LC_VERSION_MIN_MACOSX, "
796 13894 : "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
797 13894 : "LC_VERSION_MIN_WATCHOS command");
798 10857 : *LoadCmd = Load.Ptr;
799 1 : return Error::success();
800 1 : }
801 1 :
802 1700 : static Error checkNoteCommand(const MachOObjectFile &Obj,
803 13893 : const MachOObjectFile::LoadCommandInfo &Load,
804 13893 : uint32_t LoadCommandIndex,
805 13893 : std::list<MachOElement> &Elements) {
806 13893 : if (Load.C.cmdsize != sizeof(MachO::note_command))
807 3 : return malformedError("load command " + Twine(LoadCommandIndex) +
808 6 : " LC_NOTE has incorrect cmdsize");
809 3 : MachO::note_command Nt = getStruct<MachO::note_command>(Obj, Load.Ptr);
810 : uint64_t FileSize = Obj.getData().size();
811 3 : if (Nt.offset > FileSize)
812 13890 : return malformedError("offset field of LC_NOTE command " +
813 13888 : Twine(LoadCommandIndex) + " extends "
814 25961 : "past the end of the file");
815 : uint64_t BigSize = Nt.offset;
816 24120 : BigSize += Nt.size;
817 : if (BigSize > FileSize)
818 : return malformedError("size field plus offset field of LC_NOTE command " +
819 13888 : Twine(LoadCommandIndex) + " extends past the end of "
820 1 : "the file");
821 1 : if (Error Err = checkOverlappingElement(Elements, Nt.offset, Nt.size,
822 1 : "LC_NOTE data"))
823 13887 : return Err;
824 13887 : return Error::success();
825 13887 : }
826 13887 :
827 : static Error
828 1 : parseBuildVersionCommand(const MachOObjectFile &Obj,
829 2 : const MachOObjectFile::LoadCommandInfo &Load,
830 1 : SmallVectorImpl<const char*> &BuildTools,
831 1 : uint32_t LoadCommandIndex) {
832 27772 : MachO::build_version_command BVC =
833 : getStruct<MachO::build_version_command>(Obj, Load.Ptr);
834 : if (Load.C.cmdsize !=
835 : sizeof(MachO::build_version_command) +
836 : BVC.ntools * sizeof(MachO::build_tool_version))
837 : return malformedError("load command " + Twine(LoadCommandIndex) +
838 3054 : " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
839 3 :
840 3 : auto Start = Load.Ptr + sizeof(MachO::build_version_command);
841 3 : BuildTools.resize(BVC.ntools);
842 : for (unsigned i = 0; i < BVC.ntools; ++i)
843 3051 : BuildTools[i] = Start + i * sizeof(MachO::build_tool_version);
844 3051 :
845 1 : return Error::success();
846 2 : }
847 1 :
848 3050 : static Error checkRpathCommand(const MachOObjectFile &Obj,
849 1 : const MachOObjectFile::LoadCommandInfo &Load,
850 1 : uint32_t LoadCommandIndex) {
851 1 : if (Load.C.cmdsize < sizeof(MachO::rpath_command))
852 3049 : return malformedError("load command " + Twine(LoadCommandIndex) +
853 : " LC_RPATH cmdsize too small");
854 : MachO::rpath_command R = getStruct<MachO::rpath_command>(Obj, Load.Ptr);
855 : if (R.path < sizeof(MachO::rpath_command))
856 : return malformedError("load command " + Twine(LoadCommandIndex) +
857 : " LC_RPATH path.offset field too small, not past "
858 545 : "the end of the rpath_command struct");
859 : if (R.path >= R.cmdsize)
860 : return malformedError("load command " + Twine(LoadCommandIndex) +
861 : " LC_RPATH path.offset field extends past the end "
862 : "of the load command");
863 : // Make sure there is a null between the starting offset of the path and
864 545 : // the end of the load command.
865 1 : uint32_t i;
866 1 : const char *P = (const char *)Load.Ptr;
867 544 : for (i = R.path; i < R.cmdsize; i++)
868 544 : if (P[i] == '\0')
869 : break;
870 544 : if (i >= R.cmdsize)
871 544 : return malformedError("load command " + Twine(LoadCommandIndex) +
872 544 : " LC_RPATH library name extends past the end of the "
873 1 : "load command");
874 1 : return Error::success();
875 1 : }
876 2239 :
877 1705 : static Error checkEncryptCommand(const MachOObjectFile &Obj,
878 1705 : const MachOObjectFile::LoadCommandInfo &Load,
879 1705 : uint32_t LoadCommandIndex,
880 1705 : uint64_t cryptoff, uint64_t cryptsize,
881 1705 : const char **LoadCmd, const char *CmdName) {
882 1628 : if (*LoadCmd != nullptr)
883 1705 : return malformedError("more than one LC_ENCRYPTION_INFO and or "
884 1627 : "LC_ENCRYPTION_INFO_64 command");
885 1 : uint64_t FileSize = Obj.getData().size();
886 1 : if (cryptoff > FileSize)
887 1 : return malformedError("cryptoff field of " + Twine(CmdName) +
888 1704 : " command " + Twine(LoadCommandIndex) + " extends "
889 1704 : "past the end of the file");
890 1627 : uint64_t BigSize = cryptoff;
891 1626 : BigSize += cryptsize;
892 1854 : if (BigSize > FileSize)
893 1 : return malformedError("cryptoff field plus cryptsize field of " +
894 1 : Twine(CmdName) + " command " +
895 1 : Twine(LoadCommandIndex) + " extends past the end of "
896 1703 : "the file");
897 1703 : *LoadCmd = Load.Ptr;
898 1703 : return Error::success();
899 1703 : }
900 1626 :
901 3328 : static Error checkLinkerOptCommand(const MachOObjectFile &Obj,
902 : const MachOObjectFile::LoadCommandInfo &Load,
903 1 : uint32_t LoadCommandIndex) {
904 2 : if (Load.C.cmdsize < sizeof(MachO::linker_option_command))
905 1 : return malformedError("load command " + Twine(LoadCommandIndex) +
906 1 : " LC_LINKER_OPTION cmdsize too small");
907 1702 : MachO::linker_option_command L =
908 1702 : getStruct<MachO::linker_option_command>(Obj, Load.Ptr);
909 1625 : // Make sure the count of strings is correct.
910 1702 : const char *string = (const char *)Load.Ptr +
911 1624 : sizeof(struct MachO::linker_option_command);
912 1 : uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);
913 2 : uint32_t i = 0;
914 1 : while (left > 0) {
915 1 : while (*string == '\0' && left > 0) {
916 1701 : string++;
917 1701 : left--;
918 1361 : }
919 1 : if (left > 0) {
920 1 : i++;
921 1 : uint32_t NullPos = StringRef(string, left).find('\0');
922 1700 : uint32_t len = std::min(NullPos, left) + 1;
923 1700 : string += len;
924 1700 : left -= len;
925 1700 : }
926 1700 : }
927 1 : if (L.count != i)
928 2 : return malformedError("load command " + Twine(LoadCommandIndex) +
929 1 : " LC_LINKER_OPTION string count " + Twine(L.count) +
930 : " does not match number of strings");
931 1 : return Error::success();
932 1699 : }
933 1699 :
934 3321 : static Error checkSubCommand(const MachOObjectFile &Obj,
935 : const MachOObjectFile::LoadCommandInfo &Load,
936 3242 : uint32_t LoadCommandIndex, const char *CmdName,
937 : size_t SizeOfCmd, const char *CmdStructName,
938 : uint32_t PathOffset, const char *PathFieldName) {
939 1699 : if (PathOffset < SizeOfCmd)
940 1 : return malformedError("load command " + Twine(LoadCommandIndex) + " " +
941 1 : CmdName + " " + PathFieldName + ".offset field too "
942 1 : "small, not past the end of the " + CmdStructName);
943 1698 : if (PathOffset >= Load.C.cmdsize)
944 1698 : return malformedError("load command " + Twine(LoadCommandIndex) + " " +
945 1698 : CmdName + " " + PathFieldName + ".offset field "
946 1698 : "extends past the end of the load command");
947 : // Make sure there is a null between the starting offset of the path and
948 1 : // the end of the load command.
949 2 : uint32_t i;
950 1 : const char *P = (const char *)Load.Ptr;
951 1 : for (i = PathOffset; i < Load.C.cmdsize; i++)
952 3394 : if (P[i] == '\0')
953 : break;
954 : if (i >= Load.C.cmdsize)
955 : return malformedError("load command " + Twine(LoadCommandIndex) + " " +
956 : CmdName + " " + PathFieldName + " name extends past "
957 : "the end of the load command");
958 534 : return Error::success();
959 3 : }
960 3 :
961 3 : static Error checkThreadCommand(const MachOObjectFile &Obj,
962 : const MachOObjectFile::LoadCommandInfo &Load,
963 531 : uint32_t LoadCommandIndex,
964 531 : const char *CmdName) {
965 1 : if (Load.C.cmdsize < sizeof(MachO::thread_command))
966 2 : return malformedError("load command " + Twine(LoadCommandIndex) +
967 1 : CmdName + " cmdsize too small");
968 530 : MachO::thread_command T =
969 1 : getStruct<MachO::thread_command>(Obj, Load.Ptr);
970 1 : const char *state = Load.Ptr + sizeof(MachO::thread_command);
971 1 : const char *end = Load.Ptr + T.cmdsize;
972 529 : uint32_t nflavor = 0;
973 : uint32_t cputype = getCPUType(Obj);
974 : while (state < end) {
975 : if(state + sizeof(uint32_t) > end)
976 : return malformedError("load command " + Twine(LoadCommandIndex) +
977 : "flavor in " + CmdName + " extends past end of "
978 2527 : "command");
979 : uint32_t flavor;
980 : memcpy(&flavor, state, sizeof(uint32_t));
981 : if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
982 : sys::swapByteOrder(flavor);
983 : state += sizeof(uint32_t);
984 2527 :
985 0 : if(state + sizeof(uint32_t) > end)
986 0 : return malformedError("load command " + Twine(LoadCommandIndex) +
987 2527 : " count in " + CmdName + " extends past end of "
988 2527 : "command");
989 : uint32_t count;
990 2527 : memcpy(&count, state, sizeof(uint32_t));
991 2527 : if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
992 2527 : sys::swapByteOrder(count);
993 1 : state += sizeof(uint32_t);
994 1 :
995 1 : if (cputype == MachO::CPU_TYPE_I386) {
996 14714 : if (flavor == MachO::x86_THREAD_STATE32) {
997 12194 : if (count != MachO::x86_THREAD_STATE32_COUNT)
998 12194 : return malformedError("load command " + Twine(LoadCommandIndex) +
999 12194 : " count not x86_THREAD_STATE32_COUNT for "
1000 12194 : "flavor number " + Twine(nflavor) + " which is "
1001 12192 : "a x86_THREAD_STATE32 flavor in " + CmdName +
1002 10452 : " command");
1003 12194 : if (state + sizeof(MachO::x86_thread_state32_t) > end)
1004 10442 : return malformedError("load command " + Twine(LoadCommandIndex) +
1005 0 : " x86_THREAD_STATE32 extends past end of "
1006 0 : "command in " + CmdName + " command");
1007 0 : state += sizeof(MachO::x86_thread_state32_t);
1008 12194 : } else {
1009 12192 : return malformedError("load command " + Twine(LoadCommandIndex) +
1010 10452 : " unknown flavor (" + Twine(flavor) + ") for "
1011 10442 : "flavor number " + Twine(nflavor) + " in " +
1012 13282 : CmdName + " command");
1013 0 : }
1014 0 : } else if (cputype == MachO::CPU_TYPE_X86_64) {
1015 0 : if (flavor == MachO::x86_THREAD_STATE) {
1016 12194 : if (count != MachO::x86_THREAD_STATE_COUNT)
1017 12194 : return malformedError("load command " + Twine(LoadCommandIndex) +
1018 12194 : " count not x86_THREAD_STATE_COUNT for "
1019 12192 : "flavor number " + Twine(nflavor) + " which is "
1020 10452 : "a x86_THREAD_STATE flavor in " + CmdName +
1021 22636 : " command");
1022 : if (state + sizeof(MachO::x86_thread_state_t) > end)
1023 1 : return malformedError("load command " + Twine(LoadCommandIndex) +
1024 2 : " x86_THREAD_STATE extends past end of "
1025 1 : "command in " + CmdName + " command");
1026 1 : state += sizeof(MachO::x86_thread_state_t);
1027 12193 : } else if (flavor == MachO::x86_FLOAT_STATE) {
1028 12191 : if (count != MachO::x86_FLOAT_STATE_COUNT)
1029 10451 : return malformedError("load command " + Twine(LoadCommandIndex) +
1030 12193 : " count not x86_FLOAT_STATE_COUNT for "
1031 10441 : "flavor number " + Twine(nflavor) + " which is "
1032 0 : "a x86_FLOAT_STATE flavor in " + CmdName +
1033 0 : " command");
1034 0 : if (state + sizeof(MachO::x86_float_state_t) > end)
1035 0 : return malformedError("load command " + Twine(LoadCommandIndex) +
1036 12193 : " x86_FLOAT_STATE extends past end of "
1037 12193 : "command in " + CmdName + " command");
1038 9496 : state += sizeof(MachO::x86_float_state_t);
1039 0 : } else if (flavor == MachO::x86_EXCEPTION_STATE) {
1040 0 : if (count != MachO::x86_EXCEPTION_STATE_COUNT)
1041 0 : return malformedError("load command " + Twine(LoadCommandIndex) +
1042 : " count not x86_EXCEPTION_STATE_COUNT for "
1043 12193 : "flavor number " + Twine(nflavor) + " which is "
1044 12193 : "a x86_EXCEPTION_STATE flavor in " + CmdName +
1045 12193 : " command");
1046 12193 : if (state + sizeof(MachO::x86_exception_state_t) > end)
1047 2 : return malformedError("load command " + Twine(LoadCommandIndex) +
1048 4 : " x86_EXCEPTION_STATE extends past end of "
1049 2 : "command in " + CmdName + " command");
1050 : state += sizeof(MachO::x86_exception_state_t);
1051 2 : } else if (flavor == MachO::x86_THREAD_STATE64) {
1052 12191 : if (count != MachO::x86_THREAD_STATE64_COUNT)
1053 12189 : return malformedError("load command " + Twine(LoadCommandIndex) +
1054 22640 : " count not x86_THREAD_STATE64_COUNT for "
1055 : "flavor number " + Twine(nflavor) + " which is "
1056 20878 : "a x86_THREAD_STATE64 flavor in " + CmdName +
1057 : " command");
1058 : if (state + sizeof(MachO::x86_thread_state64_t) > end)
1059 12189 : return malformedError("load command " + Twine(LoadCommandIndex) +
1060 0 : " x86_THREAD_STATE64 extends past end of "
1061 0 : "command in " + CmdName + " command");
1062 0 : state += sizeof(MachO::x86_thread_state64_t);
1063 12189 : } else if (flavor == MachO::x86_EXCEPTION_STATE64) {
1064 12189 : if (count != MachO::x86_EXCEPTION_STATE64_COUNT)
1065 12189 : return malformedError("load command " + Twine(LoadCommandIndex) +
1066 12189 : " count not x86_EXCEPTION_STATE64_COUNT for "
1067 : "flavor number " + Twine(nflavor) + " which is "
1068 0 : "a x86_EXCEPTION_STATE64 flavor in " + CmdName +
1069 0 : " command");
1070 0 : if (state + sizeof(MachO::x86_exception_state64_t) > end)
1071 0 : return malformedError("load command " + Twine(LoadCommandIndex) +
1072 24378 : " x86_EXCEPTION_STATE64 extends past end of "
1073 : "command in " + CmdName + " command");
1074 : state += sizeof(MachO::x86_exception_state64_t);
1075 : } else {
1076 : return malformedError("load command " + Twine(LoadCommandIndex) +
1077 : " unknown flavor (" + Twine(flavor) + ") for "
1078 2520 : "flavor number " + Twine(nflavor) + " in " +
1079 0 : CmdName + " command");
1080 0 : }
1081 0 : } else if (cputype == MachO::CPU_TYPE_ARM) {
1082 : if (flavor == MachO::ARM_THREAD_STATE) {
1083 2520 : if (count != MachO::ARM_THREAD_STATE_COUNT)
1084 2520 : return malformedError("load command " + Twine(LoadCommandIndex) +
1085 0 : " count not ARM_THREAD_STATE_COUNT for "
1086 0 : "flavor number " + Twine(nflavor) + " which is "
1087 0 : "a ARM_THREAD_STATE flavor in " + CmdName +
1088 2520 : " command");
1089 0 : if (state + sizeof(MachO::arm_thread_state32_t) > end)
1090 0 : return malformedError("load command " + Twine(LoadCommandIndex) +
1091 0 : " ARM_THREAD_STATE extends past end of "
1092 2520 : "command in " + CmdName + " command");
1093 : state += sizeof(MachO::arm_thread_state32_t);
1094 : } else {
1095 : return malformedError("load command " + Twine(LoadCommandIndex) +
1096 : " unknown flavor (" + Twine(flavor) + ") for "
1097 : "flavor number " + Twine(nflavor) + " in " +
1098 : CmdName + " command");
1099 0 : }
1100 : } else if (cputype == MachO::CPU_TYPE_ARM64) {
1101 : if (flavor == MachO::ARM_THREAD_STATE64) {
1102 : if (count != MachO::ARM_THREAD_STATE64_COUNT)
1103 : return malformedError("load command " + Twine(LoadCommandIndex) +
1104 0 : " count not ARM_THREAD_STATE64_COUNT for "
1105 0 : "flavor number " + Twine(nflavor) + " which is "
1106 0 : "a ARM_THREAD_STATE64 flavor in " + CmdName +
1107 0 : " command");
1108 0 : if (state + sizeof(MachO::arm_thread_state64_t) > end)
1109 : return malformedError("load command " + Twine(LoadCommandIndex) +
1110 0 : " ARM_THREAD_STATE64 extends past end of "
1111 0 : "command in " + CmdName + " command");
1112 0 : state += sizeof(MachO::arm_thread_state64_t);
1113 0 : } else {
1114 0 : return malformedError("load command " + Twine(LoadCommandIndex) +
1115 0 : " unknown flavor (" + Twine(flavor) + ") for "
1116 0 : "flavor number " + Twine(nflavor) + " in " +
1117 0 : CmdName + " command");
1118 0 : }
1119 0 : } else if (cputype == MachO::CPU_TYPE_POWERPC) {
1120 : if (flavor == MachO::PPC_THREAD_STATE) {
1121 0 : if (count != MachO::PPC_THREAD_STATE_COUNT)
1122 0 : return malformedError("load command " + Twine(LoadCommandIndex) +
1123 : " count not PPC_THREAD_STATE_COUNT for "
1124 : "flavor number " + Twine(nflavor) + " which is "
1125 0 : "a PPC_THREAD_STATE flavor in " + CmdName +
1126 : " command");
1127 : if (state + sizeof(MachO::ppc_thread_state32_t) > end)
1128 : return malformedError("load command " + Twine(LoadCommandIndex) +
1129 0 : " PPC_THREAD_STATE extends past end of "
1130 0 : "command in " + CmdName + " command");
1131 0 : state += sizeof(MachO::ppc_thread_state32_t);
1132 0 : } else {
1133 0 : return malformedError("load command " + Twine(LoadCommandIndex) +
1134 0 : " unknown flavor (" + Twine(flavor) + ") for "
1135 0 : "flavor number " + Twine(nflavor) + " in " +
1136 0 : CmdName + " command");
1137 : }
1138 0 : } else {
1139 0 : return malformedError("unknown cputype (" + Twine(cputype) + ") load "
1140 0 : "command " + Twine(LoadCommandIndex) + " for " +
1141 0 : CmdName + " command can't be checked");
1142 : }
1143 0 : nflavor++;
1144 0 : }
1145 : return Error::success();
1146 0 : }
1147 0 :
1148 0 : static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj,
1149 0 : const MachOObjectFile::LoadCommandInfo
1150 : &Load,
1151 0 : uint32_t LoadCommandIndex,
1152 : const char **LoadCmd,
1153 : std::list<MachOElement> &Elements) {
1154 : if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
1155 0 : return malformedError("load command " + Twine(LoadCommandIndex) +
1156 : " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1157 : if (*LoadCmd != nullptr)
1158 : return malformedError("more than one LC_TWOLEVEL_HINTS command");
1159 : MachO::twolevel_hints_command Hints =
1160 0 : getStruct<MachO::twolevel_hints_command>(Obj, Load.Ptr);
1161 0 : uint64_t FileSize = Obj.getData().size();
1162 0 : if (Hints.offset > FileSize)
1163 0 : return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1164 0 : Twine(LoadCommandIndex) + " extends past the end of "
1165 : "the file");
1166 0 : uint64_t BigSize = Hints.nhints;
1167 0 : BigSize *= sizeof(MachO::twolevel_hint);
1168 0 : BigSize += Hints.offset;
1169 0 : if (BigSize > FileSize)
1170 0 : return malformedError("offset field plus nhints times sizeof(struct "
1171 0 : "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1172 0 : Twine(LoadCommandIndex) + " extends past the end of "
1173 0 : "the file");
1174 0 : if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints *
1175 0 : sizeof(MachO::twolevel_hint),
1176 0 : "two level hints"))
1177 0 : return Err;
1178 0 : *LoadCmd = Load.Ptr;
1179 : return Error::success();
1180 0 : }
1181 0 :
1182 0 : // Returns true if the libObject code does not support the load command and its
1183 0 : // contents. The cmd value it is treated as an unknown load command but with
1184 : // an error message that says the cmd value is obsolete.
1185 : static bool isLoadCommandObsolete(uint32_t cmd) {
1186 0 : if (cmd == MachO::LC_SYMSEG ||
1187 : cmd == MachO::LC_LOADFVMLIB ||
1188 0 : cmd == MachO::LC_IDFVMLIB ||
1189 0 : cmd == MachO::LC_IDENT ||
1190 0 : cmd == MachO::LC_FVMFILE ||
1191 0 : cmd == MachO::LC_PREPAGE ||
1192 0 : cmd == MachO::LC_PREBOUND_DYLIB ||
1193 : cmd == MachO::LC_TWOLEVEL_HINTS ||
1194 : cmd == MachO::LC_PREBIND_CKSUM)
1195 0 : return true;
1196 : return false;
1197 : }
1198 :
1199 : Expected<std::unique_ptr<MachOObjectFile>>
1200 : MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
1201 : bool Is64Bits, uint32_t UniversalCputype,
1202 0 : uint32_t UniversalIndex) {
1203 0 : Error Err = Error::success();
1204 0 : std::unique_ptr<MachOObjectFile> Obj(
1205 0 : new MachOObjectFile(std::move(Object), IsLittleEndian,
1206 0 : Is64Bits, Err, UniversalCputype,
1207 0 : UniversalIndex));
1208 0 : if (Err)
1209 0 : return std::move(Err);
1210 : return std::move(Obj);
1211 0 : }
1212 :
1213 0 : MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
1214 0 : bool Is64bits, Error &Err,
1215 0 : uint32_t UniversalCputype,
1216 0 : uint32_t UniversalIndex)
1217 0 : : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object) {
1218 0 : ErrorAsOutParameter ErrAsOutParam(&Err);
1219 0 : uint64_t SizeOfHeaders;
1220 0 : uint32_t cputype;
1221 : if (is64Bit()) {
1222 : parseHeader(*this, Header64, Err);
1223 0 : SizeOfHeaders = sizeof(MachO::mach_header_64);
1224 0 : cputype = Header64.cputype;
1225 0 : } else {
1226 : parseHeader(*this, Header, Err);
1227 : SizeOfHeaders = sizeof(MachO::mach_header);
1228 0 : cputype = Header.cputype;
1229 : }
1230 0 : if (Err)
1231 0 : return;
1232 0 : SizeOfHeaders += getHeader().sizeofcmds;
1233 0 : if (getData().data() + SizeOfHeaders > getData().end()) {
1234 0 : Err = malformedError("load commands extend past the end of the file");
1235 0 : return;
1236 0 : }
1237 0 : if (UniversalCputype != 0 && cputype != UniversalCputype) {
1238 : Err = malformedError("universal header architecture: " +
1239 0 : Twine(UniversalIndex) + "'s cputype does not match "
1240 0 : "object file's mach header");
1241 0 : return;
1242 0 : }
1243 : std::list<MachOElement> Elements;
1244 : Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
1245 0 :
1246 : uint32_t LoadCommandCount = getHeader().ncmds;
1247 0 : LoadCommandInfo Load;
1248 0 : if (LoadCommandCount != 0) {
1249 0 : if (auto LoadOrErr = getFirstLoadCommandInfo(*this))
1250 0 : Load = *LoadOrErr;
1251 0 : else {
1252 0 : Err = LoadOrErr.takeError();
1253 0 : return;
1254 0 : }
1255 : }
1256 0 :
1257 0 : const char *DyldIdLoadCmd = nullptr;
1258 0 : const char *FuncStartsLoadCmd = nullptr;
1259 0 : const char *SplitInfoLoadCmd = nullptr;
1260 : const char *CodeSignDrsLoadCmd = nullptr;
1261 : const char *CodeSignLoadCmd = nullptr;
1262 0 : const char *VersLoadCmd = nullptr;
1263 : const char *SourceLoadCmd = nullptr;
1264 0 : const char *EntryPointLoadCmd = nullptr;
1265 0 : const char *EncryptLoadCmd = nullptr;
1266 0 : const char *RoutinesLoadCmd = nullptr;
1267 0 : const char *UnixThreadLoadCmd = nullptr;
1268 0 : const char *TwoLevelHintsLoadCmd = nullptr;
1269 0 : for (unsigned I = 0; I < LoadCommandCount; ++I) {
1270 0 : if (is64Bit()) {
1271 0 : if (Load.C.cmdsize % 8 != 0) {
1272 : // We have a hack here to allow 64-bit Mach-O core files to have
1273 0 : // LC_THREAD commands that are only a multiple of 4 and not 8 to be
1274 0 : // allowed since the macOS kernel produces them.
1275 0 : if (getHeader().filetype != MachO::MH_CORE ||
1276 0 : Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
1277 : Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1278 : "multiple of 8");
1279 0 : return;
1280 : }
1281 0 : }
1282 : } else {
1283 : if (Load.C.cmdsize % 4 != 0) {
1284 : Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1285 0 : "multiple of 4");
1286 : return;
1287 : }
1288 : }
1289 : LoadCommands.push_back(Load);
1290 : if (Load.C.cmd == MachO::LC_SYMTAB) {
1291 0 : if ((Err = checkSymtabCommand(*this, Load, I, &SymtabLoadCmd, Elements)))
1292 0 : return;
1293 0 : } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
1294 0 : if ((Err = checkDysymtabCommand(*this, Load, I, &DysymtabLoadCmd,
1295 0 : Elements)))
1296 : return;
1297 0 : } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
1298 0 : if ((Err = checkLinkeditDataCommand(*this, Load, I, &DataInCodeLoadCmd,
1299 0 : "LC_DATA_IN_CODE", Elements,
1300 0 : "data in code info")))
1301 0 : return;
1302 0 : } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
1303 0 : if ((Err = checkLinkeditDataCommand(*this, Load, I, &LinkOptHintsLoadCmd,
1304 0 : "LC_LINKER_OPTIMIZATION_HINT",
1305 0 : Elements, "linker optimization "
1306 : "hints")))
1307 0 : return;
1308 0 : } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
1309 0 : if ((Err = checkLinkeditDataCommand(*this, Load, I, &FuncStartsLoadCmd,
1310 0 : "LC_FUNCTION_STARTS", Elements,
1311 0 : "function starts data")))
1312 0 : return;
1313 0 : } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
1314 0 : if ((Err = checkLinkeditDataCommand(*this, Load, I, &SplitInfoLoadCmd,
1315 : "LC_SEGMENT_SPLIT_INFO", Elements,
1316 0 : "split info data")))
1317 : return;
1318 : } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
1319 : if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignDrsLoadCmd,
1320 0 : "LC_DYLIB_CODE_SIGN_DRS", Elements,
1321 : "code signing RDs data")))
1322 : return;
1323 : } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
1324 : if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignLoadCmd,
1325 0 : "LC_CODE_SIGNATURE", Elements,
1326 0 : "code signature data")))
1327 0 : return;
1328 0 : } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
1329 : if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
1330 0 : "LC_DYLD_INFO", Elements)))
1331 : return;
1332 0 : } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
1333 0 : if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
1334 0 : "LC_DYLD_INFO_ONLY", Elements)))
1335 0 : return;
1336 0 : } else if (Load.C.cmd == MachO::LC_UUID) {
1337 0 : if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
1338 0 : Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
1339 0 : "cmdsize");
1340 0 : return;
1341 : }
1342 0 : if (UuidLoadCmd) {
1343 0 : Err = malformedError("more than one LC_UUID command");
1344 0 : return;
1345 0 : }
1346 0 : UuidLoadCmd = Load.Ptr;
1347 0 : } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
1348 0 : if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
1349 : MachO::section_64>(
1350 0 : *this, Load, Sections, HasPageZeroSegment, I,
1351 : "LC_SEGMENT_64", SizeOfHeaders, Elements)))
1352 0 : return;
1353 0 : } else if (Load.C.cmd == MachO::LC_SEGMENT) {
1354 0 : if ((Err = parseSegmentLoadCommand<MachO::segment_command,
1355 0 : MachO::section>(
1356 : *this, Load, Sections, HasPageZeroSegment, I,
1357 0 : "LC_SEGMENT", SizeOfHeaders, Elements)))
1358 0 : return;
1359 0 : } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
1360 0 : if ((Err = checkDylibIdCommand(*this, Load, I, &DyldIdLoadCmd)))
1361 0 : return;
1362 0 : } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
1363 0 : if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_DYLIB")))
1364 : return;
1365 0 : Libraries.push_back(Load.Ptr);
1366 : } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
1367 0 : if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_WEAK_DYLIB")))
1368 0 : return;
1369 0 : Libraries.push_back(Load.Ptr);
1370 0 : } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
1371 : if ((Err = checkDylibCommand(*this, Load, I, "LC_LAZY_LOAD_DYLIB")))
1372 0 : return;
1373 0 : Libraries.push_back(Load.Ptr);
1374 0 : } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
1375 0 : if ((Err = checkDylibCommand(*this, Load, I, "LC_REEXPORT_DYLIB")))
1376 0 : return;
1377 0 : Libraries.push_back(Load.Ptr);
1378 0 : } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
1379 : if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
1380 0 : return;
1381 : Libraries.push_back(Load.Ptr);
1382 0 : } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
1383 0 : if ((Err = checkDyldCommand(*this, Load, I, "LC_ID_DYLINKER")))
1384 0 : return;
1385 0 : } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
1386 : if ((Err = checkDyldCommand(*this, Load, I, "LC_LOAD_DYLINKER")))
1387 0 : return;
1388 0 : } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
1389 0 : if ((Err = checkDyldCommand(*this, Load, I, "LC_DYLD_ENVIRONMENT")))
1390 0 : return;
1391 0 : } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
1392 0 : if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1393 0 : "LC_VERSION_MIN_MACOSX")))
1394 : return;
1395 0 : } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
1396 : if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1397 0 : "LC_VERSION_MIN_IPHONEOS")))
1398 0 : return;
1399 0 : } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
1400 0 : if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1401 : "LC_VERSION_MIN_TVOS")))
1402 0 : return;
1403 0 : } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
1404 0 : if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1405 0 : "LC_VERSION_MIN_WATCHOS")))
1406 0 : return;
1407 0 : } else if (Load.C.cmd == MachO::LC_NOTE) {
1408 0 : if ((Err = checkNoteCommand(*this, Load, I, Elements)))
1409 : return;
1410 0 : } else if (Load.C.cmd == MachO::LC_BUILD_VERSION) {
1411 : if ((Err = parseBuildVersionCommand(*this, Load, BuildTools, I)))
1412 0 : return;
1413 : } else if (Load.C.cmd == MachO::LC_RPATH) {
1414 : if ((Err = checkRpathCommand(*this, Load, I)))
1415 : return;
1416 0 : } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
1417 : if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
1418 : Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
1419 0 : " has incorrect cmdsize");
1420 0 : return;
1421 0 : }
1422 0 : if (SourceLoadCmd) {
1423 0 : Err = malformedError("more than one LC_SOURCE_VERSION command");
1424 0 : return;
1425 0 : }
1426 0 : SourceLoadCmd = Load.Ptr;
1427 0 : } else if (Load.C.cmd == MachO::LC_MAIN) {
1428 0 : if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
1429 0 : Err = malformedError("LC_MAIN command " + Twine(I) +
1430 0 : " has incorrect cmdsize");
1431 : return;
1432 : }
1433 : if (EntryPointLoadCmd) {
1434 0 : Err = malformedError("more than one LC_MAIN command");
1435 0 : return;
1436 0 : }
1437 : EntryPointLoadCmd = Load.Ptr;
1438 0 : } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
1439 0 : if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
1440 0 : Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
1441 0 : " has incorrect cmdsize");
1442 : return;
1443 : }
1444 : MachO::encryption_info_command E =
1445 117 : getStruct<MachO::encryption_info_command>(*this, Load.Ptr);
1446 : if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
1447 : &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
1448 : return;
1449 117 : } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
1450 117 : if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
1451 : Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
1452 117 : " has incorrect cmdsize");
1453 1 : return;
1454 116 : }
1455 2 : MachO::encryption_info_command_64 E =
1456 : getStruct<MachO::encryption_info_command_64>(*this, Load.Ptr);
1457 1 : if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
1458 115 : &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
1459 : return;
1460 : } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
1461 : if ((Err = checkLinkerOptCommand(*this, Load, I)))
1462 0 : return;
1463 : } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
1464 : if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
1465 0 : Err = malformedError("load command " + Twine(I) +
1466 0 : " LC_SUB_FRAMEWORK cmdsize too small");
1467 0 : return;
1468 0 : }
1469 0 : MachO::sub_framework_command S =
1470 0 : getStruct<MachO::sub_framework_command>(*this, Load.Ptr);
1471 0 : if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_FRAMEWORK",
1472 0 : sizeof(MachO::sub_framework_command),
1473 0 : "sub_framework_command", S.umbrella,
1474 0 : "umbrella")))
1475 0 : return;
1476 0 : } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
1477 : if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
1478 : Err = malformedError("load command " + Twine(I) +
1479 : " LC_SUB_UMBRELLA cmdsize too small");
1480 0 : return;
1481 0 : }
1482 0 : MachO::sub_umbrella_command S =
1483 : getStruct<MachO::sub_umbrella_command>(*this, Load.Ptr);
1484 0 : if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_UMBRELLA",
1485 0 : sizeof(MachO::sub_umbrella_command),
1486 0 : "sub_umbrella_command", S.sub_umbrella,
1487 0 : "sub_umbrella")))
1488 : return;
1489 : } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
1490 : if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
1491 0 : Err = malformedError("load command " + Twine(I) +
1492 : " LC_SUB_LIBRARY cmdsize too small");
1493 : return;
1494 : }
1495 0 : MachO::sub_library_command S =
1496 0 : getStruct<MachO::sub_library_command>(*this, Load.Ptr);
1497 0 : if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_LIBRARY",
1498 0 : sizeof(MachO::sub_library_command),
1499 : "sub_library_command", S.sub_library,
1500 : "sub_library")))
1501 0 : return;
1502 0 : } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
1503 : if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
1504 : Err = malformedError("load command " + Twine(I) +
1505 : " LC_SUB_CLIENT cmdsize too small");
1506 0 : return;
1507 : }
1508 : MachO::sub_client_command S =
1509 : getStruct<MachO::sub_client_command>(*this, Load.Ptr);
1510 0 : if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_CLIENT",
1511 0 : sizeof(MachO::sub_client_command),
1512 0 : "sub_client_command", S.client, "client")))
1513 0 : return;
1514 0 : } else if (Load.C.cmd == MachO::LC_ROUTINES) {
1515 0 : if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
1516 0 : Err = malformedError("LC_ROUTINES command " + Twine(I) +
1517 0 : " has incorrect cmdsize");
1518 0 : return;
1519 : }
1520 0 : if (RoutinesLoadCmd) {
1521 0 : Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1522 0 : "command");
1523 0 : return;
1524 0 : }
1525 0 : RoutinesLoadCmd = Load.Ptr;
1526 0 : } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
1527 : if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
1528 : Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
1529 : " has incorrect cmdsize");
1530 : return;
1531 : }
1532 0 : if (RoutinesLoadCmd) {
1533 : Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1534 : "command");
1535 : return;
1536 : }
1537 0 : RoutinesLoadCmd = Load.Ptr;
1538 0 : } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
1539 : if ((Err = checkThreadCommand(*this, Load, I, "LC_UNIXTHREAD")))
1540 0 : return;
1541 0 : if (UnixThreadLoadCmd) {
1542 0 : Err = malformedError("more than one LC_UNIXTHREAD command");
1543 : return;
1544 0 : }
1545 0 : UnixThreadLoadCmd = Load.Ptr;
1546 0 : } else if (Load.C.cmd == MachO::LC_THREAD) {
1547 0 : if ((Err = checkThreadCommand(*this, Load, I, "LC_THREAD")))
1548 : return;
1549 : // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
1550 : } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
1551 : if ((Err = checkTwoLevelHintsCommand(*this, Load, I,
1552 0 : &TwoLevelHintsLoadCmd, Elements)))
1553 : return;
1554 : } else if (isLoadCommandObsolete(Load.C.cmd)) {
1555 0 : Err = malformedError("load command " + Twine(I) + " for cmd value of: " +
1556 0 : Twine(Load.C.cmd) + " is obsolete and not "
1557 0 : "supported");
1558 0 : return;
1559 0 : }
1560 0 : // TODO: generate a error for unknown load commands by default. But still
1561 : // need work out an approach to allow or not allow unknown values like this
1562 0 : // as an option for some uses like lldb.
1563 0 : if (I < LoadCommandCount - 1) {
1564 0 : if (auto LoadOrErr = getNextLoadCommandInfo(*this, I, Load))
1565 : Load = *LoadOrErr;
1566 0 : else {
1567 : Err = LoadOrErr.takeError();
1568 : return;
1569 : }
1570 0 : }
1571 0 : }
1572 0 : if (!SymtabLoadCmd) {
1573 : if (DysymtabLoadCmd) {
1574 0 : Err = malformedError("contains LC_DYSYMTAB load command without a "
1575 0 : "LC_SYMTAB load command");
1576 : return;
1577 0 : }
1578 : } else if (DysymtabLoadCmd) {
1579 : MachO::symtab_command Symtab =
1580 : getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
1581 0 : MachO::dysymtab_command Dysymtab =
1582 : getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
1583 : if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
1584 : Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
1585 : "extends past the end of the symbol table");
1586 0 : return;
1587 : }
1588 0 : uint64_t BigSize = Dysymtab.ilocalsym;
1589 0 : BigSize += Dysymtab.nlocalsym;
1590 0 : if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
1591 0 : Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
1592 0 : "command extends past the end of the symbol table");
1593 0 : return;
1594 : }
1595 0 : if (Dysymtab.nextdefsym != 0 && Dysymtab.iextdefsym > Symtab.nsyms) {
1596 0 : Err = malformedError("iextdefsym in LC_DYSYMTAB load command "
1597 0 : "extends past the end of the symbol table");
1598 0 : return;
1599 0 : }
1600 0 : BigSize = Dysymtab.iextdefsym;
1601 0 : BigSize += Dysymtab.nextdefsym;
1602 : if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
1603 : Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
1604 : "load command extends past the end of the symbol "
1605 0 : "table");
1606 : return;
1607 : }
1608 0 : if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
1609 0 : Err = malformedError("iundefsym in LC_DYSYMTAB load command "
1610 0 : "extends past the end of the symbol table");
1611 : return;
1612 0 : }
1613 : BigSize = Dysymtab.iundefsym;
1614 0 : BigSize += Dysymtab.nundefsym;
1615 : if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
1616 0 : Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
1617 : " command extends past the end of the symbol table");
1618 0 : return;
1619 0 : }
1620 0 : }
1621 0 : if ((getHeader().filetype == MachO::MH_DYLIB ||
1622 : getHeader().filetype == MachO::MH_DYLIB_STUB) &&
1623 0 : DyldIdLoadCmd == nullptr) {
1624 0 : Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
1625 0 : "filetype");
1626 0 : return;
1627 0 : }
1628 0 : assert(LoadCommands.size() == LoadCommandCount);
1629 :
1630 : Err = Error::success();
1631 0 : }
1632 0 :
1633 0 : Error MachOObjectFile::checkSymbolTable() const {
1634 0 : uint32_t Flags = 0;
1635 : if (is64Bit()) {
1636 : MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64();
1637 : Flags = H_64.flags;
1638 0 : } else {
1639 : MachO::mach_header H = MachOObjectFile::getHeader();
1640 : Flags = H.flags;
1641 : }
1642 : uint8_t NType = 0;
1643 0 : uint8_t NSect = 0;
1644 0 : uint16_t NDesc = 0;
1645 0 : uint32_t NStrx = 0;
1646 0 : uint64_t NValue = 0;
1647 0 : uint32_t SymbolIndex = 0;
1648 0 : MachO::symtab_command S = getSymtabLoadCommand();
1649 0 : for (const SymbolRef &Symbol : symbols()) {
1650 0 : DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
1651 : if (is64Bit()) {
1652 : MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI);
1653 : NType = STE_64.n_type;
1654 0 : NSect = STE_64.n_sect;
1655 0 : NDesc = STE_64.n_desc;
1656 0 : NStrx = STE_64.n_strx;
1657 : NValue = STE_64.n_value;
1658 0 : } else {
1659 0 : MachO::nlist STE = getSymbolTableEntry(SymDRI);
1660 0 : NType = STE.n_type;
1661 0 : NType = STE.n_type;
1662 : NSect = STE.n_sect;
1663 : NDesc = STE.n_desc;
1664 : NStrx = STE.n_strx;
1665 0 : NValue = STE.n_value;
1666 : }
1667 : if ((NType & MachO::N_STAB) == 0 &&
1668 : (NType & MachO::N_TYPE) == MachO::N_SECT) {
1669 0 : if (NSect == 0 || NSect > Sections.size())
1670 0 : return malformedError("bad section index: " + Twine((int)NSect) +
1671 0 : " for symbol at index " + Twine(SymbolIndex));
1672 : }
1673 0 : if ((NType & MachO::N_STAB) == 0 &&
1674 0 : (NType & MachO::N_TYPE) == MachO::N_INDR) {
1675 0 : if (NValue >= S.strsize)
1676 : return malformedError("bad n_value: " + Twine((int)NValue) + " past "
1677 : "the end of string table, for N_INDR symbol at "
1678 0 : "index " + Twine(SymbolIndex));
1679 0 : }
1680 0 : if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
1681 0 : (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
1682 0 : (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
1683 : uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
1684 0 : if (LibraryOrdinal != 0 &&
1685 0 : LibraryOrdinal != MachO::EXECUTABLE_ORDINAL &&
1686 : LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL &&
1687 : LibraryOrdinal - 1 >= Libraries.size() ) {
1688 : return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) +
1689 0 : " for symbol at index " + Twine(SymbolIndex));
1690 0 : }
1691 0 : }
1692 0 : if (NStrx >= S.strsize)
1693 : return malformedError("bad string table index: " + Twine((int)NStrx) +
1694 0 : " past the end of string table, for symbol at "
1695 : "index " + Twine(SymbolIndex));
1696 : SymbolIndex++;
1697 : }
1698 : return Error::success();
1699 0 : }
1700 0 :
1701 0 : void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
1702 0 : unsigned SymbolTableEntrySize = is64Bit() ?
1703 : sizeof(MachO::nlist_64) :
1704 0 : sizeof(MachO::nlist);
1705 0 : Symb.p += SymbolTableEntrySize;
1706 0 : }
1707 0 :
1708 0 : Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
1709 : StringRef StringTable = getStringTableData();
1710 0 : MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1711 : if (Entry.n_strx == 0)
1712 : // A n_strx value of 0 indicates that no name is associated with a
1713 0 : // particular symbol table entry.
1714 0 : return StringRef();
1715 0 : const char *Start = &StringTable.data()[Entry.n_strx];
1716 0 : if (Start < getData().begin() || Start >= getData().end()) {
1717 : return malformedError("bad string index: " + Twine(Entry.n_strx) +
1718 0 : " for symbol at index " + Twine(getSymbolIndex(Symb)));
1719 0 : }
1720 0 : return StringRef(Start);
1721 0 : }
1722 :
1723 0 : unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
1724 0 : DataRefImpl DRI = Sec.getRawDataRefImpl();
1725 0 : uint32_t Flags = getSectionFlags(*this, DRI);
1726 0 : return Flags & MachO::SECTION_TYPE;
1727 0 : }
1728 :
1729 0 : uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
1730 : if (is64Bit()) {
1731 0 : MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
1732 0 : return Entry.n_value;
1733 0 : }
1734 : MachO::nlist Entry = getSymbolTableEntry(Sym);
1735 0 : return Entry.n_value;
1736 0 : }
1737 0 :
1738 0 : // getIndirectName() returns the name of the alias'ed symbol who's string table
1739 0 : // index is in the n_value field.
1740 : std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
1741 0 : StringRef &Res) const {
1742 : StringRef StringTable = getStringTableData();
1743 0 : MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1744 0 : if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
1745 0 : return object_error::parse_failed;
1746 : uint64_t NValue = getNValue(Symb);
1747 0 : if (NValue >= StringTable.size())
1748 0 : return object_error::parse_failed;
1749 0 : const char *Start = &StringTable.data()[NValue];
1750 0 : Res = StringRef(Start);
1751 0 : return std::error_code();
1752 : }
1753 0 :
1754 : uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
1755 0 : return getNValue(Sym);
1756 0 : }
1757 0 :
1758 : Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
1759 0 : return getSymbolValue(Sym);
1760 0 : }
1761 0 :
1762 0 : uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
1763 0 : uint32_t flags = getSymbolFlags(DRI);
1764 : if (flags & SymbolRef::SF_Common) {
1765 0 : MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
1766 : return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
1767 0 : }
1768 0 : return 0;
1769 0 : }
1770 :
1771 0 : uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
1772 0 : return getNValue(DRI);
1773 0 : }
1774 0 :
1775 0 : Expected<SymbolRef::Type>
1776 : MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
1777 0 : MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1778 : uint8_t n_type = Entry.n_type;
1779 :
1780 0 : // If this is a STAB debugging symbol, we can do nothing more.
1781 0 : if (n_type & MachO::N_STAB)
1782 0 : return SymbolRef::ST_Debug;
1783 0 :
1784 : switch (n_type & MachO::N_TYPE) {
1785 0 : case MachO::N_UNDF :
1786 0 : return SymbolRef::ST_Unknown;
1787 0 : case MachO::N_SECT :
1788 0 : Expected<section_iterator> SecOrError = getSymbolSection(Symb);
1789 : if (!SecOrError)
1790 0 : return SecOrError.takeError();
1791 0 : section_iterator Sec = *SecOrError;
1792 0 : if (Sec->isData() || Sec->isBSS())
1793 0 : return SymbolRef::ST_Data;
1794 0 : return SymbolRef::ST_Function;
1795 : }
1796 0 : return SymbolRef::ST_Other;
1797 : }
1798 :
1799 0 : uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
1800 0 : MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
1801 0 :
1802 0 : uint8_t MachOType = Entry.n_type;
1803 : uint16_t MachOFlags = Entry.n_desc;
1804 0 :
1805 0 : uint32_t Result = SymbolRef::SF_None;
1806 0 :
1807 0 : if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
1808 : Result |= SymbolRef::SF_Indirect;
1809 0 :
1810 0 : if (MachOType & MachO::N_STAB)
1811 0 : Result |= SymbolRef::SF_FormatSpecific;
1812 0 :
1813 0 : if (MachOType & MachO::N_EXT) {
1814 : Result |= SymbolRef::SF_Global;
1815 0 : if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
1816 : if (getNValue(DRI))
1817 : Result |= SymbolRef::SF_Common;
1818 0 : else
1819 0 : Result |= SymbolRef::SF_Undefined;
1820 0 : }
1821 0 :
1822 : if (!(MachOType & MachO::N_PEXT))
1823 0 : Result |= SymbolRef::SF_Exported;
1824 0 : }
1825 0 :
1826 0 : if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
1827 : Result |= SymbolRef::SF_Weak;
1828 0 :
1829 0 : if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
1830 0 : Result |= SymbolRef::SF_Thumb;
1831 0 :
1832 0 : if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
1833 : Result |= SymbolRef::SF_Absolute;
1834 0 :
1835 : return Result;
1836 : }
1837 0 :
1838 0 : Expected<section_iterator>
1839 0 : MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
1840 0 : MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1841 : uint8_t index = Entry.n_sect;
1842 :
1843 0 : if (index == 0)
1844 0 : return section_end();
1845 0 : DataRefImpl DRI;
1846 : DRI.d.a = index - 1;
1847 0 : if (DRI.d.a >= Sections.size()){
1848 : return malformedError("bad section index: " + Twine((int)index) +
1849 : " for symbol at index " + Twine(getSymbolIndex(Symb)));
1850 : }
1851 : return section_iterator(SectionRef(DRI, this));
1852 0 : }
1853 :
1854 : unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
1855 : MachO::nlist_base Entry =
1856 : getSymbolTableEntryBase(*this, Sym.getRawDataRefImpl());
1857 : return Entry.n_sect - 1;
1858 0 : }
1859 0 :
1860 0 : void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
1861 0 : Sec.d.a++;
1862 0 : }
1863 :
1864 0 : std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
1865 0 : StringRef &Result) const {
1866 0 : ArrayRef<char> Raw = getSectionRawName(Sec);
1867 0 : Result = parseSegmentOrSectionName(Raw.data());
1868 0 : return std::error_code();
1869 0 : }
1870 0 :
1871 0 : uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
1872 0 : if (is64Bit())
1873 0 : return getSection64(Sec).addr;
1874 : return getSection(Sec).addr;
1875 0 : }
1876 0 :
1877 0 : uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
1878 0 : return Sec.d.a;
1879 : }
1880 0 :
1881 : uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
1882 0 : // In the case if a malformed Mach-O file where the section offset is past
1883 : // the end of the file or some part of the section size is past the end of
1884 : // the file return a size of zero or a size that covers the rest of the file
1885 : // but does not extend past the end of the file.
1886 : uint32_t SectOffset, SectType;
1887 : uint64_t SectSize;
1888 :
1889 10 : if (is64Bit()) {
1890 20 : MachO::section_64 Sect = getSection64(Sec);
1891 10 : SectOffset = Sect.offset;
1892 8 : SectSize = Sect.size;
1893 : SectType = Sect.flags & MachO::SECTION_TYPE;
1894 6 : } else {
1895 : MachO::section Sect = getSection(Sec);
1896 8 : SectOffset = Sect.offset;
1897 4 : SectSize = Sect.size;
1898 : SectType = Sect.flags & MachO::SECTION_TYPE;
1899 8 : }
1900 : if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
1901 : return SectSize;
1902 : uint64_t FileSize = getData().size();
1903 : if (SectOffset > FileSize)
1904 1834 : return 0;
1905 : if (FileSize - SectOffset < SectSize)
1906 : return FileSize - SectOffset;
1907 : return SectSize;
1908 : }
1909 :
1910 : std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
1911 1834 : StringRef &Res) const {
1912 1834 : uint32_t Offset;
1913 : uint64_t Size;
1914 :
1915 : if (is64Bit()) {
1916 : MachO::section_64 Sect = getSection64(Sec);
1917 1834 : Offset = Sect.offset;
1918 : Size = Sect.size;
1919 : } else {
1920 1834 : MachO::section Sect = getSection(Sec);
1921 3668 : Offset = Sect.offset;
1922 : Size = Sect.size;
1923 : }
1924 :
1925 1834 : Res = this->getData().substr(Offset, Size);
1926 1344 : return std::error_code();
1927 : }
1928 1344 :
1929 : uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1930 490 : uint32_t Align;
1931 : if (is64Bit()) {
1932 490 : MachO::section_64 Sect = getSection64(Sec);
1933 : Align = Sect.align;
1934 1834 : } else {
1935 : MachO::section Sect = getSection(Sec);
1936 1834 : Align = Sect.align;
1937 1834 : }
1938 6 :
1939 6 : return uint64_t(1) << Align;
1940 : }
1941 1828 :
1942 1 : Expected<SectionRef> MachOObjectFile::getSection(unsigned SectionIndex) const {
1943 2 : if (SectionIndex < 1 || SectionIndex > Sections.size())
1944 1 : return malformedError("bad section index: " + Twine((int)SectionIndex));
1945 1 :
1946 : DataRefImpl DRI;
1947 : DRI.d.a = SectionIndex - 1;
1948 1827 : return SectionRef(DRI, this);
1949 : }
1950 1827 :
1951 : Expected<SectionRef> MachOObjectFile::getSection(StringRef SectionName) const {
1952 1827 : StringRef SecName;
1953 1821 : for (const SectionRef &Section : sections()) {
1954 1820 : if (std::error_code E = Section.getName(SecName))
1955 : return errorCodeToError(E);
1956 : if (SecName == SectionName) {
1957 : return Section;
1958 : }
1959 : }
1960 : return errorCodeToError(object_error::parse_failed);
1961 1826 : }
1962 1826 :
1963 1826 : bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1964 1826 : return false;
1965 1826 : }
1966 1826 :
1967 : bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
1968 : uint32_t Flags = getSectionFlags(*this, Sec);
1969 1826 : return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
1970 : }
1971 :
1972 1826 : bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
1973 12348 : uint32_t Flags = getSectionFlags(*this, Sec);
1974 10661 : unsigned SectionType = Flags & MachO::SECTION_TYPE;
1975 8617 : return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1976 : !(SectionType == MachO::S_ZEROFILL ||
1977 : SectionType == MachO::S_GB_ZEROFILL);
1978 : }
1979 1 :
1980 1 : bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
1981 1 : uint32_t Flags = getSectionFlags(*this, Sec);
1982 1 : unsigned SectionType = Flags & MachO::SECTION_TYPE;
1983 1 : return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
1984 : (SectionType == MachO::S_ZEROFILL ||
1985 : SectionType == MachO::S_GB_ZEROFILL);
1986 : }
1987 2044 :
1988 1 : unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
1989 1 : return Sec.getRawDataRefImpl().d.a;
1990 1 : }
1991 :
1992 : bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
1993 10659 : uint32_t Flags = getSectionFlags(*this, Sec);
1994 10659 : unsigned SectionType = Flags & MachO::SECTION_TYPE;
1995 3134 : return SectionType == MachO::S_ZEROFILL ||
1996 : SectionType == MachO::S_GB_ZEROFILL;
1997 9092 : }
1998 2908 :
1999 : bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
2000 : StringRef SegmentName = getSectionFinalSegmentName(Sec);
2001 7638 : StringRef SectName;
2002 866 : if (!getSectionName(Sec, SectName))
2003 : return (SegmentName == "__LLVM" && SectName == "__bitcode");
2004 : return false;
2005 : }
2006 7205 :
2007 8 : bool MachOObjectFile::isSectionStripped(DataRefImpl Sec) const {
2008 : if (is64Bit())
2009 : return getSection64(Sec).offset == 0;
2010 : return getSection(Sec).offset == 0;
2011 : }
2012 7201 :
2013 792 : relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
2014 : DataRefImpl Ret;
2015 : Ret.d.a = Sec.d.a;
2016 : Ret.d.b = 0;
2017 6805 : return relocation_iterator(RelocationRef(Ret, this));
2018 16 : }
2019 :
2020 : relocation_iterator
2021 : MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
2022 6797 : uint32_t Num;
2023 366 : if (is64Bit()) {
2024 : MachO::section_64 Sect = getSection64(Sec);
2025 : Num = Sect.nreloc;
2026 : } else {
2027 6614 : MachO::section Sect = getSection(Sec);
2028 12 : Num = Sect.nreloc;
2029 : }
2030 :
2031 : DataRefImpl Ret;
2032 6608 : Ret.d.a = Sec.d.a;
2033 26 : Ret.d.b = Num;
2034 : return relocation_iterator(RelocationRef(Ret, this));
2035 : }
2036 6595 :
2037 820 : relocation_iterator MachOObjectFile::extrel_begin() const {
2038 : DataRefImpl Ret;
2039 : // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2040 6185 : Ret.d.a = 0; // Would normally be a section index.
2041 410 : Ret.d.b = 0; // Index into the external relocations
2042 1 : return relocation_iterator(RelocationRef(Ret, this));
2043 1 : }
2044 1 :
2045 : relocation_iterator MachOObjectFile::extrel_end() const {
2046 409 : MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
2047 1 : DataRefImpl Ret;
2048 1 : // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2049 : Ret.d.a = 0; // Would normally be a section index.
2050 408 : Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations
2051 5775 : return relocation_iterator(RelocationRef(Ret, this));
2052 2527 : }
2053 2527 :
2054 2527 : relocation_iterator MachOObjectFile::locrel_begin() const {
2055 : DataRefImpl Ret;
2056 : // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2057 3248 : Ret.d.a = 1; // Would normally be a section index.
2058 545 : Ret.d.b = 0; // Index into the local relocations
2059 545 : return relocation_iterator(RelocationRef(Ret, this));
2060 545 : }
2061 :
2062 : relocation_iterator MachOObjectFile::locrel_end() const {
2063 2703 : MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
2064 234 : DataRefImpl Ret;
2065 : // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2066 2586 : Ret.d.a = 1; // Would normally be a section index.
2067 1032 : Ret.d.b = DysymtabLoadCmd.nlocrel; // Index into the local relocations
2068 : return relocation_iterator(RelocationRef(Ret, this));
2069 515 : }
2070 2070 :
2071 8 : void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
2072 : ++Rel.d.b;
2073 3 : }
2074 2066 :
2075 8 : uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
2076 : assert((getHeader().filetype == MachO::MH_OBJECT ||
2077 3 : getHeader().filetype == MachO::MH_KEXT_BUNDLE) &&
2078 2062 : "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
2079 6 : MachO::any_relocation_info RE = getRelocation(Rel);
2080 : return getAnyRelocationAddress(RE);
2081 3 : }
2082 2059 :
2083 4 : symbol_iterator
2084 : MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
2085 1 : MachO::any_relocation_info RE = getRelocation(Rel);
2086 2057 : if (isRelocationScattered(RE))
2087 6 : return symbol_end();
2088 :
2089 2054 : uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
2090 578 : bool isExtern = getPlainRelocationExternal(RE);
2091 : if (!isExtern)
2092 1765 : return symbol_end();
2093 2 :
2094 : MachO::symtab_command S = getSymtabLoadCommand();
2095 1764 : unsigned SymbolTableEntrySize = is64Bit() ?
2096 1572 : sizeof(MachO::nlist_64) :
2097 : sizeof(MachO::nlist);
2098 : uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
2099 978 : DataRefImpl Sym;
2100 204 : Sym.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2101 : return symbol_iterator(SymbolRef(Sym, this));
2102 : }
2103 876 :
2104 4 : section_iterator
2105 : MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
2106 : return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
2107 874 : }
2108 8 :
2109 : uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
2110 : MachO::any_relocation_info RE = getRelocation(Rel);
2111 870 : return getAnyRelocationType(RE);
2112 4 : }
2113 :
2114 868 : void MachOObjectFile::getRelocationTypeName(
2115 4 : DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
2116 : StringRef res;
2117 866 : uint64_t RType = getRelocationType(Rel);
2118 22 :
2119 : unsigned Arch = this->getArch();
2120 855 :
2121 386 : switch (Arch) {
2122 1 : case Triple::x86: {
2123 1 : static const char *const Table[] = {
2124 1 : "GENERIC_RELOC_VANILLA",
2125 : "GENERIC_RELOC_PAIR",
2126 385 : "GENERIC_RELOC_SECTDIFF",
2127 1 : "GENERIC_RELOC_PB_LA_PTR",
2128 1 : "GENERIC_RELOC_LOCAL_SECTDIFF",
2129 : "GENERIC_RELOC_TLV" };
2130 384 :
2131 469 : if (RType > 5)
2132 284 : res = "Unknown";
2133 1 : else
2134 1 : res = Table[RType];
2135 1 : break;
2136 : }
2137 283 : case Triple::x86_64: {
2138 1 : static const char *const Table[] = {
2139 1 : "X86_64_RELOC_UNSIGNED",
2140 : "X86_64_RELOC_SIGNED",
2141 282 : "X86_64_RELOC_BRANCH",
2142 185 : "X86_64_RELOC_GOT_LOAD",
2143 5 : "X86_64_RELOC_GOT",
2144 1 : "X86_64_RELOC_SUBTRACTOR",
2145 1 : "X86_64_RELOC_SIGNED_1",
2146 2 : "X86_64_RELOC_SIGNED_2",
2147 : "X86_64_RELOC_SIGNED_4",
2148 : "X86_64_RELOC_TLV" };
2149 4 :
2150 8 : if (RType > 9)
2151 : res = "Unknown";
2152 : else
2153 180 : res = Table[RType];
2154 18 : break;
2155 1 : }
2156 1 : case Triple::arm: {
2157 3 : static const char *const Table[] = {
2158 : "ARM_RELOC_VANILLA",
2159 : "ARM_RELOC_PAIR",
2160 17 : "ARM_RELOC_SECTDIFF",
2161 34 : "ARM_RELOC_LOCAL_SECTDIFF",
2162 : "ARM_RELOC_PB_LA_PTR",
2163 : "ARM_RELOC_BR24",
2164 162 : "ARM_THUMB_RELOC_BR22",
2165 216 : "ARM_THUMB_32BIT_BRANCH",
2166 : "ARM_RELOC_HALF",
2167 54 : "ARM_RELOC_HALF_SECTDIFF" };
2168 4 :
2169 1 : if (RType > 9)
2170 1 : res = "Unknown";
2171 1 : else
2172 : res = Table[RType];
2173 : break;
2174 3 : }
2175 6 : case Triple::aarch64: {
2176 : static const char *const Table[] = {
2177 : "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
2178 : "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
2179 : "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
2180 50 : "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
2181 2 : "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
2182 0 : "ARM64_RELOC_ADDEND"
2183 0 : };
2184 1 :
2185 : if (RType >= array_lengthof(Table))
2186 : res = "Unknown";
2187 2 : else
2188 4 : res = Table[RType];
2189 : break;
2190 : }
2191 : case Triple::ppc: {
2192 : static const char *const Table[] = {
2193 48 : "PPC_RELOC_VANILLA",
2194 2 : "PPC_RELOC_PAIR",
2195 0 : "PPC_RELOC_BR14",
2196 0 : "PPC_RELOC_BR24",
2197 1 : "PPC_RELOC_HI16",
2198 : "PPC_RELOC_LO16",
2199 : "PPC_RELOC_HA16",
2200 2 : "PPC_RELOC_LO14",
2201 4 : "PPC_RELOC_SECTDIFF",
2202 : "PPC_RELOC_PB_LA_PTR",
2203 : "PPC_RELOC_HI16_SECTDIFF",
2204 : "PPC_RELOC_LO16_SECTDIFF",
2205 : "PPC_RELOC_HA16_SECTDIFF",
2206 46 : "PPC_RELOC_JBSR",
2207 2 : "PPC_RELOC_LO14_SECTDIFF",
2208 0 : "PPC_RELOC_LOCAL_SECTDIFF" };
2209 0 :
2210 1 : if (RType > 15)
2211 : res = "Unknown";
2212 : else
2213 2 : res = Table[RType];
2214 4 : break;
2215 : }
2216 : case Triple::UnknownArch:
2217 : res = "Unknown";
2218 44 : break;
2219 2 : }
2220 1 : Result.append(res.begin(), res.end());
2221 1 : }
2222 1 :
2223 : uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
2224 1 : MachO::any_relocation_info RE = getRelocation(Rel);
2225 0 : return getAnyRelocationLength(RE);
2226 : }
2227 0 :
2228 : //
2229 1 : // guessLibraryShortName() is passed a name of a dynamic library and returns a
2230 42 : // guess on what the short name is. Then name is returned as a substring of the
2231 4 : // StringRef Name passed in. The name of the dynamic library is recognized as
2232 0 : // a framework if it has one of the two following forms:
2233 0 : // Foo.framework/Versions/A/Foo
2234 0 : // Foo.framework/Foo
2235 : // Where A and Foo can be any string. And may contain a trailing suffix
2236 4 : // starting with an underbar. If the Name is recognized as a framework then
2237 1 : // isFramework is set to true else it is set to false. If the Name has a
2238 : // suffix then Suffix is set to the substring in Name that contains the suffix
2239 1 : // else it is set to a NULL StringRef.
2240 : //
2241 3 : // The Name of the dynamic library is recognized as a library name if it has
2242 38 : // one of the two following forms:
2243 30 : // libFoo.A.dylib
2244 : // libFoo.dylib
2245 14 : // The library may have a suffix trailing the name Foo of the form:
2246 1 : // libFoo_profile.A.dylib
2247 1 : // libFoo_profile.dylib
2248 : //
2249 13 : // The Name of the dynamic library is also recognized as a library name if it
2250 23 : // has the following form:
2251 10 : // Foo.qtx
2252 : //
2253 : // If the Name of the dynamic library is none of the forms above then a NULL
2254 18 : // StringRef is returned.
2255 16 : //
2256 : StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
2257 : bool &isFramework,
2258 10 : StringRef &Suffix) {
2259 8 : StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
2260 16 : size_t a, b, c, d, Idx;
2261 8 :
2262 8 : isFramework = false;
2263 : Suffix = StringRef();
2264 :
2265 : // Pull off the last component and make Foo point to it
2266 : a = Name.rfind('/');
2267 10524 : if (a == Name.npos || a == 0)
2268 8843 : goto guess_library;
2269 8841 : Foo = Name.slice(a+1, Name.npos);
2270 :
2271 : // Look for a suffix starting with a '_'
2272 : Idx = Foo.rfind('_');
2273 : if (Idx != Foo.npos && Foo.size() >= 2) {
2274 : Suffix = Foo.slice(Idx, Foo.npos);
2275 : Foo = Foo.slice(0, Idx);
2276 1687 : }
2277 132 :
2278 0 : // First look for the form Foo.framework/Foo
2279 : b = Name.rfind('/', a);
2280 0 : if (b == Name.npos)
2281 : Idx = 0;
2282 1555 : else
2283 : Idx = b+1;
2284 1432 : F = Name.slice(Idx, Idx + Foo.size());
2285 : DotFramework = Name.slice(Idx + Foo.size(),
2286 1432 : Idx + Foo.size() + sizeof(".framework/")-1);
2287 1432 : if (F == Foo && DotFramework == ".framework/") {
2288 0 : isFramework = true;
2289 : return Foo;
2290 2 : }
2291 :
2292 1432 : // Next look for the form Foo.framework/Versions/A/Foo
2293 1432 : if (b == Name.npos)
2294 1432 : goto guess_library;
2295 1 : c = Name.rfind('/', b);
2296 : if (c == Name.npos || c == 0)
2297 1 : goto guess_library;
2298 : V = Name.slice(c+1, Name.npos);
2299 1431 : if (!V.startswith("Versions/"))
2300 1 : goto guess_library;
2301 : d = Name.rfind('/', c);
2302 1 : if (d == Name.npos)
2303 : Idx = 0;
2304 1430 : else
2305 1430 : Idx = d+1;
2306 1430 : F = Name.slice(Idx, Idx + Foo.size());
2307 0 : DotFramework = Name.slice(Idx + Foo.size(),
2308 : Idx + Foo.size() + sizeof(".framework/")-1);
2309 : if (F == Foo && DotFramework == ".framework/") {
2310 0 : isFramework = true;
2311 : return Foo;
2312 1430 : }
2313 0 :
2314 : guess_library:
2315 0 : // pull off the suffix after the "." and make a point to it
2316 : a = Name.rfind('.');
2317 1430 : if (a == Name.npos || a == 0)
2318 1430 : return StringRef();
2319 1430 : Dylib = Name.slice(a, Name.npos);
2320 0 : if (Dylib != ".dylib")
2321 : goto guess_qtx;
2322 0 :
2323 : // First pull off the version letter for the form Foo.A.dylib if any.
2324 : if (a >= 3) {
2325 1685 : Dot = Name.slice(a-2, a-1);
2326 1685 : if (Dot == ".")
2327 115 : a = a - 2;
2328 1 : }
2329 :
2330 1 : b = Name.rfind('/', a);
2331 : if (b == Name.npos)
2332 : b = 0;
2333 : else
2334 : b = b+1;
2335 : // ignore any suffix after an underbar like Foo_profile.A.dylib
2336 : Idx = Name.find('_', b);
2337 96 : if (Idx != Name.npos && Idx != b) {
2338 : Lib = Name.slice(b, Idx);
2339 96 : Suffix = Name.slice(Idx, a);
2340 55 : }
2341 : else
2342 : Lib = Name.slice(b, a);
2343 41 : // There are incorrect library names of the form:
2344 : // libATS.A_profile.dylib so check for these.
2345 : if (Lib.size() >= 3) {
2346 : Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2347 : if (Dot == ".")
2348 : Lib = Lib.slice(0, Lib.size()-2);
2349 : }
2350 : return Lib;
2351 :
2352 96 : guess_qtx:
2353 447 : Qtx = Name.slice(a, Name.npos);
2354 358 : if (Qtx != ".qtx")
2355 358 : return StringRef();
2356 265 : b = Name.rfind('/', a);
2357 265 : if (b == Name.npos)
2358 265 : Lib = Name.slice(0, a);
2359 265 : else
2360 265 : Lib = Name.slice(b+1, a);
2361 265 : // There are library names of the form: QT.A.qtx so check for these.
2362 : if (Lib.size() >= 3) {
2363 93 : Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2364 : if (Dot == ".")
2365 : Lib = Lib.slice(0, Lib.size()-2);
2366 93 : }
2367 93 : return Lib;
2368 93 : }
2369 93 :
2370 : // getLibraryShortNameByIndex() is used to get the short name of the library
2371 358 : // for an undefined symbol in a linked Mach-O binary that was linked with the
2372 : // normal two-level namespace default (that is MH_TWOLEVEL in the header).
2373 234 : // It is passed the index (0 - based) of the library as translated from
2374 2 : // GET_LIBRARY_ORDINAL (1 - based).
2375 2 : std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
2376 : StringRef &Res) const {
2377 356 : if (Index >= Libraries.size())
2378 : return object_error::parse_failed;
2379 2 :
2380 2 : // If the cache of LibrariesShortNames is not built up do that first for
2381 : // all the Libraries.
2382 2 : if (LibrariesShortNames.size() == 0) {
2383 : for (unsigned i = 0; i < Libraries.size(); i++) {
2384 354 : MachO::dylib_command D =
2385 182 : getStruct<MachO::dylib_command>(*this, Libraries[i]);
2386 : if (D.dylib.name >= D.cmdsize)
2387 91 : return object_error::parse_failed;
2388 182 : const char *P = (const char *)(Libraries[i]) + D.dylib.name;
2389 89 : StringRef Name = StringRef(P);
2390 91 : if (D.dylib.name+Name.size() >= D.cmdsize)
2391 87 : return object_error::parse_failed;
2392 1 : StringRef Suffix;
2393 1 : bool isFramework;
2394 : StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
2395 : if (shortName.empty())
2396 353 : LibrariesShortNames.push_back(Name);
2397 2 : else
2398 : LibrariesShortNames.push_back(shortName);
2399 2 : }
2400 351 : }
2401 :
2402 : Res = LibrariesShortNames[Index];
2403 : return std::error_code();
2404 : }
2405 10547 :
2406 10547 : uint32_t MachOObjectFile::getLibraryCount() const {
2407 : return Libraries.size();
2408 10547 : }
2409 10547 :
2410 10547 : section_iterator
2411 : MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
2412 3500 : DataRefImpl Sec;
2413 3500 : Sec.d.a = Rel->getRawDataRefImpl().d.a;
2414 : return section_iterator(SectionRef(Sec, this));
2415 3500 : }
2416 :
2417 : basic_symbol_iterator MachOObjectFile::symbol_begin() const {
2418 : DataRefImpl DRI;
2419 3498 : MachO::symtab_command Symtab = getSymtabLoadCommand();
2420 3498 : if (!SymtabLoadCmd || Symtab.nsyms == 0)
2421 7 : return basic_symbol_iterator(SymbolRef(DRI, this));
2422 14 :
2423 : return getSymbolByIndex(0);
2424 : }
2425 :
2426 : basic_symbol_iterator MachOObjectFile::symbol_end() const {
2427 40 : DataRefImpl DRI;
2428 40 : MachO::symtab_command Symtab = getSymtabLoadCommand();
2429 40 : if (!SymtabLoadCmd || Symtab.nsyms == 0)
2430 40 : return basic_symbol_iterator(SymbolRef(DRI, this));
2431 :
2432 : unsigned SymbolTableEntrySize = is64Bit() ?
2433 3902 : sizeof(MachO::nlist_64) :
2434 3902 : sizeof(MachO::nlist);
2435 3228 : unsigned Offset = Symtab.symoff +
2436 3228 : Symtab.nsyms * SymbolTableEntrySize;
2437 : DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2438 674 : return basic_symbol_iterator(SymbolRef(DRI, this));
2439 674 : }
2440 :
2441 : basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
2442 : MachO::symtab_command Symtab = getSymtabLoadCommand();
2443 : if (!SymtabLoadCmd || Index >= Symtab.nsyms)
2444 1 : report_fatal_error("Requested symbol index is out of range.");
2445 : unsigned SymbolTableEntrySize =
2446 1 : is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2447 : DataRefImpl DRI;
2448 1 : DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
2449 0 : DRI.p += Index * SymbolTableEntrySize;
2450 1 : return basic_symbol_iterator(SymbolRef(DRI, this));
2451 1 : }
2452 0 :
2453 1 : uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
2454 1 : MachO::symtab_command Symtab = getSymtabLoadCommand();
2455 1 : if (!SymtabLoadCmd)
2456 : report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2457 : unsigned SymbolTableEntrySize =
2458 2559 : is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2459 2559 : DataRefImpl DRIstart;
2460 : DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
2461 : uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
2462 912 : return Index;
2463 912 : }
2464 :
2465 : section_iterator MachOObjectFile::section_begin() const {
2466 12 : DataRefImpl DRI;
2467 12 : return section_iterator(SectionRef(DRI, this));
2468 12 : }
2469 :
2470 24 : section_iterator MachOObjectFile::section_end() const {
2471 : DataRefImpl DRI;
2472 : DRI.d.a = Sections.size();
2473 : return section_iterator(SectionRef(DRI, this));
2474 : }
2475 78 :
2476 78 : uint8_t MachOObjectFile::getBytesInAddress() const {
2477 : return is64Bit() ? 8 : 4;
2478 : }
2479 :
2480 4599 : StringRef MachOObjectFile::getFileFormatName() const {
2481 : unsigned CPUType = getCPUType(*this);
2482 : if (!is64Bit()) {
2483 : switch (CPUType) {
2484 : case MachO::CPU_TYPE_I386:
2485 4599 : return "Mach-O 32-bit i386";
2486 : case MachO::CPU_TYPE_ARM:
2487 : return "Mach-O arm";
2488 2769 : case MachO::CPU_TYPE_POWERPC:
2489 909 : return "Mach-O 32-bit ppc";
2490 : default:
2491 1855 : return "Mach-O 32-bit unknown";
2492 1855 : }
2493 1855 : }
2494 :
2495 1854 : switch (CPUType) {
2496 3355 : case MachO::CPU_TYPE_X86_64:
2497 : return "Mach-O 64-bit x86-64";
2498 : case MachO::CPU_TYPE_ARM64:
2499 : return "Mach-O arm64";
2500 : case MachO::CPU_TYPE_POWERPC64:
2501 : return "Mach-O 64-bit ppc64";
2502 : default:
2503 6450 : return "Mach-O 64-bit unknown";
2504 : }
2505 : }
2506 :
2507 : Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
2508 : switch (CPUType) {
2509 : case MachO::CPU_TYPE_I386:
2510 : return Triple::x86;
2511 6450 : case MachO::CPU_TYPE_X86_64:
2512 : return Triple::x86_64;
2513 : case MachO::CPU_TYPE_ARM:
2514 6450 : return Triple::arm;
2515 499 : case MachO::CPU_TYPE_ARM64:
2516 : return Triple::aarch64;
2517 6450 : case MachO::CPU_TYPE_POWERPC:
2518 4070 : return Triple::ppc;
2519 4070 : case MachO::CPU_TYPE_POWERPC64:
2520 1264 : return Triple::ppc64;
2521 203 : default:
2522 : return Triple::UnknownArch;
2523 1061 : }
2524 : }
2525 :
2526 4070 : Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
2527 4010 : const char **McpuDefault,
2528 : const char **ArchFlag) {
2529 : if (McpuDefault)
2530 6450 : *McpuDefault = nullptr;
2531 71 : if (ArchFlag)
2532 : *ArchFlag = nullptr;
2533 6450 :
2534 237 : switch (CPUType) {
2535 : case MachO::CPU_TYPE_I386:
2536 6450 : switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2537 13 : case MachO::CPU_SUBTYPE_I386_ALL:
2538 : if (ArchFlag)
2539 6450 : *ArchFlag = "i386";
2540 : return Triple("i386-apple-darwin");
2541 : default:
2542 : return Triple();
2543 3559 : }
2544 : case MachO::CPU_TYPE_X86_64:
2545 : switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2546 : case MachO::CPU_SUBTYPE_X86_64_ALL:
2547 3559 : if (ArchFlag)
2548 236 : *ArchFlag = "x86_64";
2549 : return Triple("x86_64-apple-darwin");
2550 3323 : case MachO::CPU_SUBTYPE_X86_64_H:
2551 3323 : if (ArchFlag)
2552 5 : *ArchFlag = "x86_64h";
2553 10 : return Triple("x86_64h-apple-darwin");
2554 : default:
2555 13272 : return Triple();
2556 : }
2557 : case MachO::CPU_TYPE_ARM:
2558 128 : switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2559 : case MachO::CPU_SUBTYPE_ARM_V4T:
2560 128 : if (ArchFlag)
2561 128 : *ArchFlag = "armv4t";
2562 : return Triple("armv4t-apple-darwin");
2563 : case MachO::CPU_SUBTYPE_ARM_V5TEJ:
2564 13303 : if (ArchFlag)
2565 13303 : *ArchFlag = "armv5e";
2566 13303 : return Triple("armv5e-apple-darwin");
2567 : case MachO::CPU_SUBTYPE_ARM_XSCALE:
2568 28635 : if (ArchFlag)
2569 : *ArchFlag = "xscale";
2570 28635 : return Triple("xscale-apple-darwin");
2571 28635 : case MachO::CPU_SUBTYPE_ARM_V6:
2572 28635 : if (ArchFlag)
2573 : *ArchFlag = "armv6";
2574 : return Triple("armv6-apple-darwin");
2575 7245 : case MachO::CPU_SUBTYPE_ARM_V6M:
2576 7245 : if (McpuDefault)
2577 2336 : *McpuDefault = "cortex-m0";
2578 4909 : if (ArchFlag)
2579 : *ArchFlag = "armv6m";
2580 : return Triple("armv6m-apple-darwin");
2581 49 : case MachO::CPU_SUBTYPE_ARM_V7:
2582 49 : if (ArchFlag)
2583 : *ArchFlag = "armv7";
2584 : return Triple("armv7-apple-darwin");
2585 7243 : case MachO::CPU_SUBTYPE_ARM_V7EM:
2586 : if (McpuDefault)
2587 : *McpuDefault = "cortex-m4";
2588 : if (ArchFlag)
2589 : *ArchFlag = "armv7em";
2590 : return Triple("thumbv7em-apple-darwin");
2591 : case MachO::CPU_SUBTYPE_ARM_V7K:
2592 : if (McpuDefault)
2593 7243 : *McpuDefault = "cortex-a7";
2594 2466 : if (ArchFlag)
2595 2466 : *ArchFlag = "armv7k";
2596 2466 : return Triple("armv7k-apple-darwin");
2597 2466 : case MachO::CPU_SUBTYPE_ARM_V7M:
2598 : if (McpuDefault)
2599 4777 : *McpuDefault = "cortex-m3";
2600 4777 : if (ArchFlag)
2601 4777 : *ArchFlag = "armv7m";
2602 4777 : return Triple("thumbv7m-apple-darwin");
2603 : case MachO::CPU_SUBTYPE_ARM_V7S:
2604 7243 : if (McpuDefault)
2605 : *McpuDefault = "cortex-a7";
2606 7238 : if (ArchFlag)
2607 7238 : *ArchFlag = "armv7s";
2608 : return Triple("armv7s-apple-darwin");
2609 7238 : default:
2610 0 : return Triple();
2611 : }
2612 : case MachO::CPU_TYPE_ARM64:
2613 : switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2614 7714 : case MachO::CPU_SUBTYPE_ARM64_ALL:
2615 : if (McpuDefault)
2616 : *McpuDefault = "cyclone";
2617 : if (ArchFlag)
2618 : *ArchFlag = "arm64";
2619 7714 : return Triple("arm64-apple-darwin");
2620 6449 : default:
2621 6449 : return Triple();
2622 6449 : }
2623 : case MachO::CPU_TYPE_POWERPC:
2624 1265 : switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2625 1265 : case MachO::CPU_SUBTYPE_POWERPC_ALL:
2626 1265 : if (ArchFlag)
2627 : *ArchFlag = "ppc";
2628 : return Triple("ppc-apple-darwin");
2629 7714 : default:
2630 7714 : return Triple();
2631 : }
2632 : case MachO::CPU_TYPE_POWERPC64:
2633 73 : switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2634 : case MachO::CPU_SUBTYPE_POWERPC_ALL:
2635 73 : if (ArchFlag)
2636 58 : *ArchFlag = "ppc64";
2637 58 : return Triple("ppc64-apple-darwin");
2638 : default:
2639 15 : return Triple();
2640 15 : }
2641 : default:
2642 : return Triple();
2643 73 : }
2644 : }
2645 :
2646 0 : Triple MachOObjectFile::getHostArch() {
2647 0 : return Triple(sys::getDefaultTargetTriple());
2648 0 : }
2649 :
2650 : bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
2651 0 : return StringSwitch<bool>(ArchFlag)
2652 0 : .Case("i386", true)
2653 : .Case("x86_64", true)
2654 : .Case("x86_64h", true)
2655 0 : .Case("armv4t", true)
2656 0 : .Case("arm", true)
2657 0 : .Case("armv5e", true)
2658 0 : .Case("armv6", true)
2659 0 : .Case("armv6m", true)
2660 : .Case("armv7", true)
2661 : .Case("armv7em", true)
2662 : .Case("armv7k", true)
2663 : .Case("armv7m", true)
2664 0 : .Case("armv7s", true)
2665 : .Case("arm64", true)
2666 : .Case("ppc", true)
2667 6455 : .Case("ppc64", true)
2668 6455 : .Default(false);
2669 : }
2670 :
2671 567 : Triple::ArchType MachOObjectFile::getArch() const {
2672 567 : return getArch(getCPUType(*this));
2673 567 : }
2674 :
2675 : Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
2676 1890 : return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
2677 1890 : }
2678 1890 :
2679 1890 : relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
2680 1256 : DataRefImpl DRI;
2681 628 : DRI.d.a = Index;
2682 : return section_rel_begin(DRI);
2683 : }
2684 8761 :
2685 8761 : relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
2686 8761 : DataRefImpl DRI;
2687 8761 : DRI.d.a = Index;
2688 13726 : return section_rel_end(DRI);
2689 6863 : }
2690 :
2691 : dice_iterator MachOObjectFile::begin_dices() const {
2692 165 : DataRefImpl DRI;
2693 165 : if (!DataInCodeLoadCmd)
2694 : return dice_iterator(DiceRef(DRI, this));
2695 :
2696 6955 : MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2697 6955 : DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff));
2698 6955 : return dice_iterator(DiceRef(DRI, this));
2699 6955 : }
2700 6955 :
2701 : dice_iterator MachOObjectFile::end_dices() const {
2702 : DataRefImpl DRI;
2703 177 : if (!DataInCodeLoadCmd)
2704 177 : return dice_iterator(DiceRef(DRI, this));
2705 177 :
2706 177 : MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2707 : unsigned Offset = DicLC.dataoff + DicLC.datasize;
2708 : DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2709 : return dice_iterator(DiceRef(DRI, this));
2710 : }
2711 6796 :
2712 6796 : ExportEntry::ExportEntry(Error *E, const MachOObjectFile *O,
2713 6224 : ArrayRef<uint8_t> T) : E(E), O(O), Trie(T) {}
2714 572 :
2715 : void ExportEntry::moveToFirst() {
2716 : ErrorAsOutParameter ErrAsOutParam(E);
2717 1063 : pushNode(0);
2718 : if (*E)
2719 1063 : return;
2720 : pushDownUntilBottom();
2721 3189 : }
2722 :
2723 : void ExportEntry::moveToEnd() {
2724 : Stack.clear();
2725 1063 : Done = true;
2726 : }
2727 1063 :
2728 723 : bool ExportEntry::operator==(const ExportEntry &Other) const {
2729 723 : // Common case, one at end, other iterating from begin.
2730 : if (Done || Other.Done)
2731 340 : return (Done == Other.Done);
2732 340 : // Not equal if different stack sizes.
2733 : if (Stack.size() != Other.Stack.size())
2734 : return false;
2735 : // Not equal if different cumulative strings.
2736 1063 : if (!CumulativeString.equals(Other.CumulativeString))
2737 1063 : return false;
2738 3189 : // Equal if all nodes in both stacks match.
2739 : for (unsigned i=0; i < Stack.size(); ++i) {
2740 : if (Stack[i].Start != Other.Stack[i].Start)
2741 750 : return false;
2742 : }
2743 : return true;
2744 : }
2745 :
2746 2250 : uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr, const char **error) {
2747 : unsigned Count;
2748 : uint64_t Result = decodeULEB128(Ptr, &Count, Trie.end(), error);
2749 750 : Ptr += Count;
2750 750 : if (Ptr > Trie.end())
2751 : Ptr = Trie.end();
2752 : return Result;
2753 : }
2754 750 :
2755 2250 : StringRef ExportEntry::name() const {
2756 : return CumulativeString;
2757 : }
2758 1 :
2759 : uint64_t ExportEntry::flags() const {
2760 : return Stack.back().Flags;
2761 1 : }
2762 :
2763 3 : uint64_t ExportEntry::address() const {
2764 : return Stack.back().Address;
2765 : }
2766 1 :
2767 1 : uint64_t ExportEntry::other() const {
2768 : return Stack.back().Other;
2769 : }
2770 1 :
2771 1 : StringRef ExportEntry::otherName() const {
2772 3 : const char* ImportName = Stack.back().ImportName;
2773 : if (ImportName)
2774 : return StringRef(ImportName);
2775 3835 : return StringRef();
2776 3835 : }
2777 3835 :
2778 : uint32_t ExportEntry::nodeOffset() const {
2779 3868 : return Stack.back().Start - Trie.begin();
2780 : }
2781 :
2782 : ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
2783 3868 : : Start(Ptr), Current(Ptr) {}
2784 3868 :
2785 : void ExportEntry::pushNode(uint64_t offset) {
2786 : ErrorAsOutParameter ErrAsOutParam(E);
2787 : const uint8_t *Ptr = Trie.begin() + offset;
2788 1294 : NodeState State(Ptr);
2789 1294 : const char *error;
2790 1294 : uint64_t ExportInfoSize = readULEB128(State.Current, &error);
2791 1 : if (error) {
2792 : *E = malformedError("export info size " + Twine(error) +
2793 1293 : " in export trie data at node: 0x" +
2794 1293 : Twine::utohexstr(offset));
2795 1293 : moveToEnd();
2796 921 : return;
2797 : }
2798 372 : State.IsExportNode = (ExportInfoSize != 0);
2799 372 : const uint8_t* Children = State.Current + ExportInfoSize;
2800 : if (Children > Trie.end()) {
2801 372 : *E = malformedError(
2802 372 : "export info size: 0x" + Twine::utohexstr(ExportInfoSize) +
2803 : " in export trie data at node: 0x" + Twine::utohexstr(offset) +
2804 372 : " too big and extends past end of trie data");
2805 1116 : moveToEnd();
2806 : return;
2807 : }
2808 : if (State.IsExportNode) {
2809 107 : const uint8_t *ExportStart = State.Current;
2810 107 : State.Flags = readULEB128(State.Current, &error);
2811 : if (error) {
2812 : *E = malformedError("flags " + Twine(error) +
2813 515 : " in export trie data at node: 0x" +
2814 515 : Twine::utohexstr(offset));
2815 515 : moveToEnd();
2816 : return;
2817 : }
2818 454 : uint64_t Kind = State.Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK;
2819 : if (State.Flags != 0 &&
2820 : (Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR &&
2821 454 : Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE &&
2822 : Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL)) {
2823 454 : *E = malformedError(
2824 : "unsupported exported symbol kind: " + Twine((int)Kind) +
2825 454 : " in flags: 0x" + Twine::utohexstr(State.Flags) +
2826 80 : " in export trie data at node: 0x" + Twine::utohexstr(offset));
2827 : moveToEnd();
2828 : return;
2829 : }
2830 : if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
2831 : State.Address = 0;
2832 : State.Other = readULEB128(State.Current, &error); // dylib ordinal
2833 : if (error) {
2834 : *E = malformedError("dylib ordinal of re-export " + Twine(error) +
2835 80 : " in export trie data at node: 0x" +
2836 : Twine::utohexstr(offset));
2837 : moveToEnd();
2838 80 : return;
2839 : }
2840 : if (O != nullptr) {
2841 174 : if (State.Other > O->getLibraryCount()) {
2842 : *E = malformedError(
2843 : "bad library ordinal: " + Twine((int)State.Other) + " (max " +
2844 : Twine((int)O->getLibraryCount()) +
2845 : ") in export trie data at node: 0x" + Twine::utohexstr(offset));
2846 : moveToEnd();
2847 : return;
2848 : }
2849 : }
2850 : State.ImportName = reinterpret_cast<const char*>(State.Current);
2851 : if (*State.ImportName == '\0') {
2852 : State.Current++;
2853 : } else {
2854 174 : const uint8_t *End = State.Current + 1;
2855 : if (End >= Trie.end()) {
2856 : *E = malformedError("import name of re-export in export trie data at "
2857 174 : "node: 0x" +
2858 : Twine::utohexstr(offset) +
2859 : " starts past end of trie data");
2860 94 : moveToEnd();
2861 : return;
2862 : }
2863 : while(*End != '\0' && End < Trie.end())
2864 : End++;
2865 : if (*End != '\0') {
2866 : *E = malformedError("import name of re-export in export trie data at "
2867 : "node: 0x" +
2868 : Twine::utohexstr(offset) +
2869 : " extends past end of trie data");
2870 : moveToEnd();
2871 : return;
2872 : }
2873 94 : State.Current = End + 1;
2874 : }
2875 : } else {
2876 94 : State.Address = readULEB128(State.Current, &error);
2877 : if (error) {
2878 : *E = malformedError("address " + Twine(error) +
2879 56 : " in export trie data at node: 0x" +
2880 : Twine::utohexstr(offset));
2881 : moveToEnd();
2882 : return;
2883 : }
2884 : if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
2885 : State.Other = readULEB128(State.Current, &error);
2886 : if (error) {
2887 : *E = malformedError("resolver of stub and resolver " + Twine(error) +
2888 : " in export trie data at node: 0x" +
2889 56 : Twine::utohexstr(offset));
2890 : moveToEnd();
2891 : return;
2892 56 : }
2893 : }
2894 : }
2895 30 : if(ExportStart + ExportInfoSize != State.Current) {
2896 : *E = malformedError(
2897 : "inconsistant export info size: 0x" +
2898 : Twine::utohexstr(ExportInfoSize) + " where actual size was: 0x" +
2899 : Twine::utohexstr(State.Current - ExportStart) +
2900 : " in export trie data at node: 0x" + Twine::utohexstr(offset));
2901 : moveToEnd();
2902 : return;
2903 : }
2904 : }
2905 : State.ChildCount = *Children;
2906 : if (State.ChildCount != 0 && Children + 1 >= Trie.end()) {
2907 : *E = malformedError("byte for count of childern in export trie data at "
2908 : "node: 0x" +
2909 : Twine::utohexstr(offset) +
2910 : " extends past end of trie data");
2911 : moveToEnd();
2912 : return;
2913 : }
2914 30 : State.Current = Children + 1;
2915 : State.NextChildIndex = 0;
2916 : State.ParentStringLength = CumulativeString.size();
2917 30 : Stack.push_back(State);
2918 : }
2919 :
2920 : void ExportEntry::pushDownUntilBottom() {
2921 : ErrorAsOutParameter ErrAsOutParam(E);
2922 0 : const char *error;
2923 : while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
2924 454 : NodeState &Top = Stack.back();
2925 454 : CumulativeString.resize(Top.ParentStringLength);
2926 : for (;*Top.Current != 0 && Top.Current < Trie.end(); Top.Current++) {
2927 0 : char C = *Top.Current;
2928 0 : CumulativeString.push_back(C);
2929 0 : }
2930 : if (Top.Current >= Trie.end()) {
2931 : *E = malformedError("edge sub-string in export trie data at node: 0x" +
2932 : Twine::utohexstr(Top.Start - Trie.begin()) +
2933 : " for child #" + Twine((int)Top.NextChildIndex) +
2934 : " extends past end of trie data");
2935 : moveToEnd();
2936 : return;
2937 : }
2938 : Top.Current += 1;
2939 : uint64_t childNodeIndex = readULEB128(Top.Current, &error);
2940 : if (error) {
2941 : *E = malformedError("child node offset " + Twine(error) +
2942 : " in export trie data at node: 0x" +
2943 : Twine::utohexstr(Top.Start - Trie.begin()));
2944 : moveToEnd();
2945 : return;
2946 : }
2947 : for (const NodeState &node : nodes()) {
2948 : if (node.Start == Trie.begin() + childNodeIndex){
2949 : *E = malformedError("loop in childern in export trie data at node: 0x" +
2950 : Twine::utohexstr(Top.Start - Trie.begin()) +
2951 : " back to node: 0x" +
2952 : Twine::utohexstr(childNodeIndex));
2953 : moveToEnd();
2954 : return;
2955 : }
2956 : }
2957 : Top.NextChildIndex += 1;
2958 : pushNode(childNodeIndex);
2959 : if (*E)
2960 88 : return;
2961 : }
2962 : if (!Stack.back().IsExportNode) {
2963 88 : *E = malformedError("node is not an export node in export trie data at "
2964 : "node: 0x" +
2965 : Twine::utohexstr(Stack.back().Start - Trie.begin()));
2966 88 : moveToEnd();
2967 88 : return;
2968 : }
2969 : }
2970 88 :
2971 88 : // We have a trie data structure and need a way to walk it that is compatible
2972 : // with the C++ iterator model. The solution is a non-recursive depth first
2973 146 : // traversal where the iterator contains a stack of parent nodes along with a
2974 : // string that is the accumulation of all edge strings along the parent chain
2975 : // to this point.
2976 73 : //
2977 73 : // There is one "export" node for each exported symbol. But because some
2978 4 : // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
2979 4 : // node may have child nodes too.
2980 : //
2981 : // The algorithm for moveNext() is to keep moving down the leftmost unvisited
2982 : // child until hitting a node with no children (which is an export node or
2983 73 : // else the trie is malformed). On the way down, each node is pushed on the
2984 73 : // stack ivar. If there is no more ways down, it pops up one and tries to go
2985 : // down a sibling path until a childless node is reached.
2986 : void ExportEntry::moveNext() {
2987 71 : assert(!Stack.empty() && "ExportEntry::moveNext() with empty node stack");
2988 73 : if (!Stack.back().IsExportNode) {
2989 : *E = malformedError("node is not an export node in export trie data at "
2990 146 : "node: 0x" +
2991 : Twine::utohexstr(Stack.back().Start - Trie.begin()));
2992 4 : moveToEnd();
2993 4 : return;
2994 : }
2995 :
2996 : Stack.pop_back();
2997 69 : while (!Stack.empty()) {
2998 : NodeState &Top = Stack.back();
2999 69 : if (Top.NextChildIndex < Top.ChildCount) {
3000 69 : pushDownUntilBottom();
3001 : // Now at the next export node.
3002 6 : return;
3003 : } else {
3004 : if (Top.IsExportNode) {
3005 2 : // This node has no children but is itself an export node.
3006 2 : CumulativeString.resize(Top.ParentStringLength);
3007 : return;
3008 : }
3009 1 : Stack.pop_back();
3010 2 : }
3011 : }
3012 4 : Done = true;
3013 : }
3014 2 :
3015 2 : iterator_range<export_iterator>
3016 : MachOObjectFile::exports(Error &E, ArrayRef<uint8_t> Trie,
3017 : const MachOObjectFile *O) {
3018 82 : ExportEntry Start(&E, O, Trie);
3019 : if (Trie.empty())
3020 82 : Start.moveToEnd();
3021 82 : else
3022 0 : Start.moveToFirst();
3023 82 :
3024 : ExportEntry Finish(&E, O, Trie);
3025 : Finish.moveToEnd();
3026 :
3027 : return make_range(export_iterator(Start), export_iterator(Finish));
3028 80 : }
3029 160 :
3030 : iterator_range<export_iterator> MachOObjectFile::exports(Error &Err) const {
3031 : return exports(Err, getDyldInfoExportsTrie(), this);
3032 : }
3033 :
3034 80 : MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,
3035 80 : ArrayRef<uint8_t> Bytes, bool is64Bit)
3036 : : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
3037 : PointerSize(is64Bit ? 8 : 4) {}
3038 66 :
3039 : void MachORebaseEntry::moveToFirst() {
3040 80 : Ptr = Opcodes.begin();
3041 80 : moveNext();
3042 4 : }
3043 4 :
3044 : void MachORebaseEntry::moveToEnd() {
3045 : Ptr = Opcodes.end();
3046 76 : RemainingLoopCount = 0;
3047 : Done = true;
3048 : }
3049 80 :
3050 160 : void MachORebaseEntry::moveNext() {
3051 : ErrorAsOutParameter ErrAsOutParam(E);
3052 2 : // If in the middle of some loop, move to next rebasing in loop.
3053 : SegmentOffset += AdvanceAmount;
3054 80 : if (RemainingLoopCount) {
3055 : --RemainingLoopCount;
3056 : return;
3057 2 : }
3058 : // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
3059 0 : // pointer size. Therefore it is possible to reach the end without ever having
3060 2 : // seen REBASE_OPCODE_DONE.
3061 2 : if (Ptr == Opcodes.end()) {
3062 1 : Done = true;
3063 : return;
3064 2 : }
3065 : bool More = true;
3066 2 : while (More) {
3067 4 : // Parse next opcode and set up next loop.
3068 : const uint8_t *OpcodeStart = Ptr;
3069 1 : uint8_t Byte = *Ptr++;
3070 : uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
3071 2 : uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
3072 : uint32_t Count, Skip;
3073 : const char *error = nullptr;
3074 : switch (Opcode) {
3075 : case MachO::REBASE_OPCODE_DONE:
3076 : More = false;
3077 : Done = true;
3078 : moveToEnd();
3079 95 : DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n");
3080 : break;
3081 95 : case MachO::REBASE_OPCODE_SET_TYPE_IMM:
3082 0 : RebaseType = ImmValue;
3083 : if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) {
3084 : *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
3085 : Twine((int)RebaseType) + " for opcode at: 0x" +
3086 95 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3087 135 : moveToEnd();
3088 : return;
3089 88 : }
3090 88 : DEBUG_WITH_TYPE(
3091 0 : "mach-o-rebase",
3092 88 : dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
3093 : << "RebaseType=" << (int) RebaseType << "\n");
3094 88 : break;
3095 0 : case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
3096 88 : SegmentIndex = ImmValue;
3097 : SegmentOffset = readULEB128(&error);
3098 88 : if (error) {
3099 88 : *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3100 0 : Twine(error) + " for opcode at: 0x" +
3101 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3102 88 : moveToEnd();
3103 : return;
3104 : }
3105 : error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3106 95 : true);
3107 95 : if (error) {
3108 : *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3109 : Twine(error) + " for opcode at: 0x" +
3110 66 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3111 66 : moveToEnd();
3112 : return;
3113 : }
3114 : DEBUG_WITH_TYPE(
3115 8 : "mach-o-rebase",
3116 : dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3117 8 : << "SegmentIndex=" << SegmentIndex << ", "
3118 24 : << format("SegmentOffset=0x%06X", SegmentOffset)
3119 : << "\n");
3120 : break;
3121 1055 : case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
3122 : SegmentOffset += readULEB128(&error);
3123 1055 : if (error) {
3124 1055 : *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3125 216 : " for opcode at: 0x" +
3126 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3127 983 : moveToEnd();
3128 : return;
3129 : }
3130 3881 : error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3131 : true);
3132 3881 : if (error) {
3133 3881 : *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3134 216 : " for opcode at: 0x" +
3135 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3136 3809 : moveToEnd();
3137 : return;
3138 3809 : }
3139 7618 : DEBUG_WITH_TYPE("mach-o-rebase",
3140 3809 : dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
3141 3809 : << format("SegmentOffset=0x%06X",
3142 11427 : SegmentOffset) << "\n");
3143 : break;
3144 : case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
3145 1068 : error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3146 1068 : true);
3147 1068 : if (error) {
3148 0 : *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
3149 : Twine(error) + " for opcode at: 0x" +
3150 1068 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3151 : moveToEnd();
3152 1068 : return;
3153 1068 : }
3154 3204 : SegmentOffset += ImmValue * PointerSize;
3155 : error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3156 : false);
3157 12 : if (error) {
3158 12 : *E =
3159 12 : malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED "
3160 0 : " (after adding immediate times the pointer size) " +
3161 : Twine(error) + " for opcode at: 0x" +
3162 12 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3163 : moveToEnd();
3164 12 : return;
3165 12 : }
3166 12 : DEBUG_WITH_TYPE("mach-o-rebase",
3167 : dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
3168 : << format("SegmentOffset=0x%06X",
3169 1698 : SegmentOffset) << "\n");
3170 : break;
3171 5094 : case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
3172 : error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3173 : true);
3174 10352 : if (error) {
3175 : *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
3176 10352 : Twine(error) + " for opcode at: 0x" +
3177 31056 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3178 : moveToEnd();
3179 : return;
3180 846 : }
3181 846 : AdvanceAmount = PointerSize;
3182 : Skip = 0;
3183 : Count = ImmValue;
3184 646 : if (ImmValue != 0)
3185 : RemainingLoopCount = ImmValue - 1;
3186 646 : else
3187 187 : RemainingLoopCount = 0;
3188 : error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3189 93 : SegmentIndex, SegmentOffset);
3190 : if (error) {
3191 88 : *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
3192 : Twine(error) + " for opcode at: 0x" +
3193 6 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3194 : moveToEnd();
3195 0 : return;
3196 : }
3197 : DEBUG_WITH_TYPE(
3198 : "mach-o-rebase",
3199 459 : dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
3200 : << format("SegmentOffset=0x%06X", SegmentOffset)
3201 415 : << ", AdvanceAmount=" << AdvanceAmount
3202 : << ", RemainingLoopCount=" << RemainingLoopCount
3203 40 : << "\n");
3204 : return;
3205 4 : case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
3206 : error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3207 0 : true);
3208 : if (error) {
3209 : *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3210 : Twine(error) + " for opcode at: 0x" +
3211 10461 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3212 10461 : moveToEnd();
3213 : return;
3214 : }
3215 4717 : AdvanceAmount = PointerSize;
3216 4717 : Skip = 0;
3217 592 : Count = readULEB128(&error);
3218 592 : if (error) {
3219 4704 : *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3220 4704 : Twine(error) + " for opcode at: 0x" +
3221 36 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3222 36 : moveToEnd();
3223 24 : return;
3224 24 : }
3225 0 : if (Count != 0)
3226 0 : RemainingLoopCount = Count - 1;
3227 : else
3228 : RemainingLoopCount = 0;
3229 : error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3230 893 : SegmentIndex, SegmentOffset);
3231 : if (error) {
3232 : *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3233 893 : Twine(error) + " for opcode at: 0x" +
3234 179 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3235 893 : moveToEnd();
3236 126 : return;
3237 : }
3238 893 : DEBUG_WITH_TYPE(
3239 83 : "mach-o-rebase",
3240 83 : dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
3241 83 : << format("SegmentOffset=0x%06X", SegmentOffset)
3242 83 : << ", AdvanceAmount=" << AdvanceAmount
3243 42 : << ", RemainingLoopCount=" << RemainingLoopCount
3244 83 : << "\n");
3245 : return;
3246 : case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
3247 : error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3248 675 : true);
3249 675 : if (error) {
3250 649 : *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3251 649 : Twine(error) + " for opcode at: 0x" +
3252 59 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3253 649 : moveToEnd();
3254 26 : return;
3255 26 : }
3256 10 : Skip = readULEB128(&error);
3257 26 : if (error) {
3258 : *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3259 : Twine(error) + " for opcode at: 0x" +
3260 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3261 101 : moveToEnd();
3262 101 : return;
3263 0 : }
3264 0 : AdvanceAmount = Skip + PointerSize;
3265 0 : Count = 1;
3266 0 : RemainingLoopCount = 0;
3267 0 : error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3268 0 : SegmentIndex, SegmentOffset);
3269 0 : if (error) {
3270 0 : *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3271 0 : Twine(error) + " for opcode at: 0x" +
3272 0 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3273 0 : moveToEnd();
3274 0 : return;
3275 0 : }
3276 0 : DEBUG_WITH_TYPE(
3277 0 : "mach-o-rebase",
3278 0 : dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
3279 0 : << format("SegmentOffset=0x%06X", SegmentOffset)
3280 0 : << ", AdvanceAmount=" << AdvanceAmount
3281 0 : << ", RemainingLoopCount=" << RemainingLoopCount
3282 0 : << "\n");
3283 0 : return;
3284 0 : case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
3285 49 : error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
3286 49 : true);
3287 5 : if (error) {
3288 49 : *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3289 3 : "ULEB " +
3290 3 : Twine(error) + " for opcode at: 0x" +
3291 3 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3292 3 : moveToEnd();
3293 2 : return;
3294 3 : }
3295 0 : Count = readULEB128(&error);
3296 0 : if (error) {
3297 0 : *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3298 0 : "ULEB " +
3299 0 : Twine(error) + " for opcode at: 0x" +
3300 0 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3301 18 : moveToEnd();
3302 18 : return;
3303 8 : }
3304 18 : if (Count != 0)
3305 5 : RemainingLoopCount = Count - 1;
3306 18 : else
3307 30 : RemainingLoopCount = 0;
3308 30 : Skip = readULEB128(&error);
3309 3 : if (error) {
3310 30 : *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3311 1 : "ULEB " +
3312 30 : Twine(error) + " for opcode at: 0x" +
3313 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3314 : moveToEnd();
3315 : return;
3316 34 : }
3317 34 : AdvanceAmount = Skip + PointerSize;
3318 34 :
3319 34 : error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
3320 10 : SegmentIndex, SegmentOffset);
3321 34 : if (error) {
3322 1 : *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3323 34 : "ULEB " +
3324 : Twine(error) + " for opcode at: 0x" +
3325 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3326 : moveToEnd();
3327 0 : return;
3328 0 : }
3329 0 : DEBUG_WITH_TYPE(
3330 0 : "mach-o-rebase",
3331 0 : dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
3332 0 : << format("SegmentOffset=0x%06X", SegmentOffset)
3333 : << ", AdvanceAmount=" << AdvanceAmount
3334 : << ", RemainingLoopCount=" << RemainingLoopCount
3335 : << "\n");
3336 0 : return;
3337 0 : default:
3338 0 : *E = malformedError("bad rebase info (bad opcode value 0x" +
3339 0 : Twine::utohexstr(Opcode) + " for opcode at: 0x" +
3340 0 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3341 0 : moveToEnd();
3342 : return;
3343 : }
3344 : }
3345 : }
3346 :
3347 : uint64_t MachORebaseEntry::readULEB128(const char **error) {
3348 : unsigned Count;
3349 : uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
3350 4 : Ptr += Count;
3351 4 : if (Ptr > Opcodes.end())
3352 : Ptr = Opcodes.end();
3353 : return Result;
3354 29 : }
3355 29 :
3356 29 : int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
3357 29 :
3358 29 : uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
3359 29 :
3360 29 : StringRef MachORebaseEntry::typeName() const {
3361 29 : switch (RebaseType) {
3362 29 : case MachO::REBASE_TYPE_POINTER:
3363 29 : return "pointer";
3364 29 : case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
3365 29 : return "text abs32";
3366 29 : case MachO::REBASE_TYPE_TEXT_PCREL32:
3367 29 : return "text rel32";
3368 29 : }
3369 29 : return "unknown";
3370 29 : }
3371 29 :
3372 29 : // For use with the SegIndex of a checked Mach-O Rebase entry
3373 : // to get the segment name.
3374 : StringRef MachORebaseEntry::segmentName() const {
3375 10461 : return O->BindRebaseSegmentName(SegmentIndex);
3376 10461 : }
3377 :
3378 : // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3379 767 : // to get the section name.
3380 767 : StringRef MachORebaseEntry::sectionName() const {
3381 : return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3382 : }
3383 0 :
3384 : // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3385 0 : // to get the address.
3386 0 : uint64_t MachORebaseEntry::address() const {
3387 : return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3388 : }
3389 0 :
3390 : bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
3391 0 : #ifdef EXPENSIVE_CHECKS
3392 0 : assert(Opcodes == Other.Opcodes && "compare iterators of different files");
3393 : #else
3394 : assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3395 61 : #endif
3396 : return (Ptr == Other.Ptr) &&
3397 61 : (RemainingLoopCount == Other.RemainingLoopCount) &&
3398 108 : (Done == Other.Done);
3399 : }
3400 25 :
3401 25 : iterator_range<rebase_iterator>
3402 75 : MachOObjectFile::rebaseTable(Error &Err, MachOObjectFile *O,
3403 : ArrayRef<uint8_t> Opcodes, bool is64) {
3404 : if (O->BindRebaseSectionTable == nullptr)
3405 61 : O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
3406 : MachORebaseEntry Start(&Err, O, Opcodes, is64);
3407 61 : Start.moveToFirst();
3408 108 :
3409 : MachORebaseEntry Finish(&Err, O, Opcodes, is64);
3410 25 : Finish.moveToEnd();
3411 25 :
3412 25 : return make_range(rebase_iterator(Start), rebase_iterator(Finish));
3413 75 : }
3414 :
3415 : iterator_range<rebase_iterator> MachOObjectFile::rebaseTable(Error &Err) {
3416 50 : return rebaseTable(Err, this, getDyldInfoRebaseOpcodes(), is64Bit());
3417 100 : }
3418 :
3419 24 : MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O,
3420 24 : ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
3421 24 : : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
3422 24 : PointerSize(is64Bit ? 8 : 4), TableKind(BK) {}
3423 :
3424 24 : void MachOBindEntry::moveToFirst() {
3425 : Ptr = Opcodes.begin();
3426 : moveNext();
3427 38 : }
3428 :
3429 38 : void MachOBindEntry::moveToEnd() {
3430 38 : Ptr = Opcodes.end();
3431 : RemainingLoopCount = 0;
3432 97 : Done = true;
3433 : }
3434 97 :
3435 97 : void MachOBindEntry::moveNext() {
3436 : ErrorAsOutParameter ErrAsOutParam(E);
3437 0 : // If in the middle of some loop, move to next binding in loop.
3438 : SegmentOffset += AdvanceAmount;
3439 : if (RemainingLoopCount) {
3440 0 : --RemainingLoopCount;
3441 : return;
3442 : }
3443 0 : // BIND_OPCODE_DONE is only used for padding if we are not aligned to
3444 0 : // pointer size. Therefore it is possible to reach the end without ever having
3445 : // seen BIND_OPCODE_DONE.
3446 : if (Ptr == Opcodes.end()) {
3447 : Done = true;
3448 : return;
3449 : }
3450 415 : bool More = true;
3451 : while (More) {
3452 830 : // Parse next opcode and set up next loop.
3453 415 : const uint8_t *OpcodeStart = Ptr;
3454 830 : uint8_t Byte = *Ptr++;
3455 0 : uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
3456 415 : uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
3457 : int8_t SignExtended;
3458 : const uint8_t *SymStart;
3459 90 : uint32_t Count, Skip;
3460 90 : const char *error = nullptr;
3461 : switch (Opcode) {
3462 : case MachO::BIND_OPCODE_DONE:
3463 75 : if (TableKind == Kind::Lazy) {
3464 75 : // Lazying bindings have a DONE opcode between entries. Need to ignore
3465 : // it to advance to next entry. But need not if this is last entry.
3466 : bool NotLastEntry = false;
3467 70 : for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
3468 70 : if (*P) {
3469 : NotLastEntry = true;
3470 : }
3471 24 : }
3472 24 : if (NotLastEntry)
3473 : break;
3474 : }
3475 28 : More = false;
3476 28 : moveToEnd();
3477 28 : DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");
3478 24 : break;
3479 4 : case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
3480 : if (TableKind == Kind::Weak) {
3481 : *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
3482 0 : "weak bind table for opcode at: 0x" +
3483 0 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3484 : moveToEnd();
3485 : return;
3486 140 : }
3487 140 : Ordinal = ImmValue;
3488 : LibraryOrdinalSet = true;
3489 140 : if (ImmValue > O->getLibraryCount()) {
3490 140 : *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3491 140 : "library ordinal: " +
3492 140 : Twine((int)ImmValue) + " (max " +
3493 : Twine((int)O->getLibraryCount()) +
3494 140 : ") for opcode at: 0x" +
3495 140 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3496 2 : moveToEnd();
3497 4 : return;
3498 2 : }
3499 2 : DEBUG_WITH_TYPE(
3500 2 : "mach-o-bind",
3501 : dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
3502 138 : << "Ordinal=" << Ordinal << "\n");
3503 138 : break;
3504 276 : case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
3505 1 : if (TableKind == Kind::Weak) {
3506 1 : *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
3507 2 : "weak bind table for opcode at: 0x" +
3508 1 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3509 1 : moveToEnd();
3510 1 : return;
3511 : }
3512 137 : Ordinal = readULEB128(&error);
3513 : LibraryOrdinalSet = true;
3514 77 : if (error) {
3515 77 : *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
3516 0 : Twine(error) + " for opcode at: 0x" +
3517 0 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3518 0 : moveToEnd();
3519 0 : return;
3520 0 : }
3521 : if (Ordinal > (int)O->getLibraryCount()) {
3522 77 : *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3523 77 : "library ordinal: " +
3524 80 : Twine((int)Ordinal) + " (max " +
3525 40 : Twine((int)O->getLibraryCount()) +
3526 : ") for opcode at: 0x" +
3527 1 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3528 1 : moveToEnd();
3529 2 : return;
3530 2 : }
3531 1 : DEBUG_WITH_TYPE(
3532 1 : "mach-o-bind",
3533 : dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
3534 76 : << "Ordinal=" << Ordinal << "\n");
3535 19 : break;
3536 19 : case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
3537 19 : if (TableKind == Kind::Weak) {
3538 0 : *E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
3539 0 : "weak bind table for opcode at: 0x" +
3540 0 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3541 0 : moveToEnd();
3542 0 : return;
3543 : }
3544 19 : if (ImmValue) {
3545 19 : SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
3546 1 : Ordinal = SignExtended;
3547 1 : if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {
3548 1 : *E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
3549 2 : "special ordinal: " +
3550 1 : Twine((int)Ordinal) + " for opcode at: 0x" +
3551 1 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3552 : moveToEnd();
3553 : return;
3554 18 : }
3555 18 : } else
3556 8 : Ordinal = 0;
3557 : LibraryOrdinalSet = true;
3558 10 : DEBUG_WITH_TYPE(
3559 20 : "mach-o-bind",
3560 1 : dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
3561 1 : << "Ordinal=" << Ordinal << "\n");
3562 2 : break;
3563 1 : case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
3564 1 : Flags = ImmValue;
3565 1 : SymStart = Ptr;
3566 : while (*Ptr && (Ptr < Opcodes.end())) {
3567 42 : ++Ptr;
3568 33 : }
3569 9 : if (Ptr == Opcodes.end()) {
3570 1 : *E = malformedError(
3571 1 : "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
3572 2 : "symbol name extends past opcodes for opcode at: 0x" +
3573 1 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3574 1 : moveToEnd();
3575 1 : return;
3576 : }
3577 8 : SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
3578 : Ptr-SymStart);
3579 : ++Ptr;
3580 57 : DEBUG_WITH_TYPE(
3581 57 : "mach-o-bind",
3582 0 : dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
3583 0 : << "SymbolName=" << SymbolName << "\n");
3584 0 : if (TableKind == Kind::Weak) {
3585 0 : if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
3586 0 : return;
3587 : }
3588 57 : break;
3589 5 : case MachO::BIND_OPCODE_SET_TYPE_IMM:
3590 5 : BindType = ImmValue;
3591 0 : if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) {
3592 0 : *E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
3593 0 : Twine((int)ImmValue) + " for opcode at: 0x" +
3594 0 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3595 0 : moveToEnd();
3596 : return;
3597 : }
3598 : DEBUG_WITH_TYPE(
3599 73 : "mach-o-bind",
3600 1 : dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
3601 1 : << "BindType=" << (int)BindType << "\n");
3602 2 : break;
3603 1 : case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
3604 2 : Addend = readSLEB128(&error);
3605 1 : if (error) {
3606 1 : *E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error) +
3607 : " for opcode at: 0x" +
3608 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3609 132 : moveToEnd();
3610 132 : return;
3611 1 : }
3612 1 : DEBUG_WITH_TYPE(
3613 2 : "mach-o-bind",
3614 1 : dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
3615 1 : << "Addend=" << Addend << "\n");
3616 1 : break;
3617 : case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
3618 131 : SegmentIndex = ImmValue;
3619 131 : SegmentOffset = readULEB128(&error);
3620 131 : if (error) {
3621 131 : *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3622 : Twine(error) + " for opcode at: 0x" +
3623 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3624 84 : moveToEnd();
3625 84 : return;
3626 : }
3627 191 : error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3628 : if (error) {
3629 118 : *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3630 735 : Twine(error) + " for opcode at: 0x" +
3631 617 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3632 617 : moveToEnd();
3633 : return;
3634 236 : }
3635 1 : DEBUG_WITH_TYPE(
3636 1 : "mach-o-bind",
3637 1 : dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3638 1 : << "SegmentIndex=" << SegmentIndex << ", "
3639 1 : << format("SegmentOffset=0x%06X", SegmentOffset)
3640 11 : << "\n");
3641 : break;
3642 117 : case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
3643 117 : SegmentOffset += readULEB128(&error);
3644 117 : if (error) {
3645 0 : *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3646 0 : " for opcode at: 0x" +
3647 0 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3648 0 : moveToEnd();
3649 0 : return;
3650 : }
3651 364 : error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3652 248 : if (error) {
3653 1 : *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3654 1 : " for opcode at: 0x" +
3655 2 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3656 1 : moveToEnd();
3657 1 : return;
3658 1 : }
3659 : DEBUG_WITH_TYPE("mach-o-bind",
3660 : dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
3661 116 : << format("SegmentOffset=0x%06X",
3662 116 : SegmentOffset) << "\n");
3663 125 : break;
3664 : case MachO::BIND_OPCODE_DO_BIND:
3665 : AdvanceAmount = PointerSize;
3666 73 : RemainingLoopCount = 0;
3667 1 : error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3668 1 : if (error) {
3669 1 : *E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) +
3670 1 : " for opcode at: 0x" +
3671 1 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3672 : moveToEnd();
3673 : return;
3674 : }
3675 : if (SymbolName == StringRef()) {
3676 : *E = malformedError(
3677 : "for BIND_OPCODE_DO_BIND missing preceding "
3678 : "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
3679 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3680 : moveToEnd();
3681 : return;
3682 : }
3683 : if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3684 : *E =
3685 : malformedError("for BIND_OPCODE_DO_BIND missing preceding "
3686 : "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3687 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3688 : moveToEnd();
3689 : return;
3690 72 : }
3691 : DEBUG_WITH_TYPE("mach-o-bind",
3692 72 : dbgs() << "BIND_OPCODE_DO_BIND: "
3693 0 : << format("SegmentOffset=0x%06X",
3694 0 : SegmentOffset) << "\n");
3695 0 : return;
3696 0 : case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
3697 0 : if (TableKind == Kind::Lazy) {
3698 : *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
3699 : "lazy bind table for opcode at: 0x" +
3700 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3701 100 : moveToEnd();
3702 : return;
3703 88 : }
3704 60 : error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3705 : if (error) {
3706 60 : *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3707 : Twine(error) + " for opcode at: 0x" +
3708 28 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3709 : moveToEnd();
3710 0 : return;
3711 0 : }
3712 : if (SymbolName == StringRef()) {
3713 : *E = malformedError(
3714 : "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3715 : "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
3716 12 : "at: 0x" +
3717 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3718 : moveToEnd();
3719 : return;
3720 25 : }
3721 : if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3722 50 : *E = malformedError(
3723 25 : "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3724 1 : "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3725 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3726 24 : moveToEnd();
3727 : return;
3728 25 : }
3729 25 : AdvanceAmount = readULEB128(&error) + PointerSize;
3730 : if (error) {
3731 100 : *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3732 : Twine(error) + " for opcode at: 0x" +
3733 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3734 21 : moveToEnd();
3735 21 : return;
3736 : }
3737 : // Note, this is not really an error until the next bind but make no sense
3738 24 : // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
3739 24 : // bind operation.
3740 24 : error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
3741 24 : AdvanceAmount, false);
3742 : if (error) {
3743 12 : *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
3744 12 : "ULEB) " +
3745 12 : Twine(error) + " for opcode at: 0x" +
3746 12 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3747 : moveToEnd();
3748 24 : return;
3749 48 : }
3750 24 : RemainingLoopCount = 0;
3751 24 : DEBUG_WITH_TYPE(
3752 24 : "mach-o-bind",
3753 : dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
3754 23 : << format("SegmentOffset=0x%06X", SegmentOffset)
3755 23 : << ", AdvanceAmount=" << AdvanceAmount
3756 : << ", RemainingLoopCount=" << RemainingLoopCount
3757 23 : << "\n");
3758 23 : return;
3759 5 : case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
3760 5 : if (TableKind == Kind::Lazy) {
3761 : *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
3762 : "allowed in lazy bind table for opcode at: 0x" +
3763 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3764 : moveToEnd();
3765 36 : return;
3766 0 : }
3767 0 : error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3768 : if (error) {
3769 : *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
3770 20 : Twine(error) + " for opcode at: 0x" +
3771 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3772 38 : moveToEnd();
3773 38 : return;
3774 38 : }
3775 38 : if (SymbolName == StringRef()) {
3776 : *E = malformedError(
3777 38 : "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3778 38 : "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3779 1 : "opcode at: 0x" +
3780 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3781 1 : moveToEnd();
3782 1 : return;
3783 : }
3784 : if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3785 12 : *E = malformedError(
3786 12 : "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3787 12 : "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3788 1 : "at: 0x" +
3789 1 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3790 1 : moveToEnd();
3791 1 : return;
3792 17 : }
3793 : AdvanceAmount = ImmValue * PointerSize + PointerSize;
3794 : RemainingLoopCount = 0;
3795 : error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
3796 : AdvanceAmount, false);
3797 : if (error) {
3798 : *E =
3799 11 : malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3800 11 : " (after adding immediate times the pointer size) " +
3801 11 : Twine(error) + " for opcode at: 0x" +
3802 11 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3803 1 : moveToEnd();
3804 2 : return;
3805 1 : }
3806 1 : DEBUG_WITH_TYPE("mach-o-bind",
3807 1 : dbgs()
3808 : << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
3809 10 : << format("SegmentOffset=0x%06X", SegmentOffset) << "\n");
3810 : return;
3811 10 : case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
3812 2 : if (TableKind == Kind::Lazy) {
3813 4 : *E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
3814 2 : "allowed in lazy bind table for opcode at: 0x" +
3815 2 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3816 2 : moveToEnd();
3817 : return;
3818 : }
3819 : Count = readULEB128(&error);
3820 : if (Count != 0)
3821 : RemainingLoopCount = Count - 1;
3822 : else
3823 : RemainingLoopCount = 0;
3824 : if (error) {
3825 2 : *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3826 2 : " (count value) " +
3827 2 : Twine(error) + " for opcode at: 0x" +
3828 0 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3829 0 : moveToEnd();
3830 0 : return;
3831 0 : }
3832 0 : Skip = readULEB128(&error);
3833 : AdvanceAmount = Skip + PointerSize;
3834 2 : if (error) {
3835 : *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3836 2 : " (skip value) " +
3837 1 : Twine(error) + " for opcode at: 0x" +
3838 2 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3839 1 : moveToEnd();
3840 1 : return;
3841 1 : }
3842 : error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
3843 : if (error) {
3844 : *E =
3845 : malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
3846 : Twine(error) + " for opcode at: 0x" +
3847 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3848 1 : moveToEnd();
3849 1 : return;
3850 : }
3851 1 : if (SymbolName == StringRef()) {
3852 0 : *E = malformedError(
3853 0 : "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3854 0 : "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3855 0 : "opcode at: 0x" +
3856 0 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3857 : moveToEnd();
3858 1 : return;
3859 1 : }
3860 : if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
3861 1 : *E = malformedError(
3862 1 : "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3863 1 : "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3864 1 : "at: 0x" +
3865 2 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3866 1 : moveToEnd();
3867 1 : return;
3868 1 : }
3869 : error = O->BindEntryCheckCountAndSkip(Count, Skip, PointerSize,
3870 : SegmentIndex, SegmentOffset);
3871 : if (error) {
3872 : *E =
3873 : malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
3874 : Twine(error) + " for opcode at: 0x" +
3875 4 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3876 4 : moveToEnd();
3877 : return;
3878 4 : }
3879 0 : DEBUG_WITH_TYPE(
3880 0 : "mach-o-bind",
3881 0 : dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
3882 0 : << format("SegmentOffset=0x%06X", SegmentOffset)
3883 0 : << ", AdvanceAmount=" << AdvanceAmount
3884 : << ", RemainingLoopCount=" << RemainingLoopCount
3885 4 : << "\n");
3886 : return;
3887 4 : default:
3888 4 : *E = malformedError("bad bind info (bad opcode value 0x" +
3889 4 : Twine::utohexstr(Opcode) + " for opcode at: 0x" +
3890 : Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3891 0 : moveToEnd();
3892 4 : return;
3893 : }
3894 4 : }
3895 1 : }
3896 2 :
3897 1 : uint64_t MachOBindEntry::readULEB128(const char **error) {
3898 1 : unsigned Count;
3899 1 : uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
3900 : Ptr += Count;
3901 : if (Ptr > Opcodes.end())
3902 : Ptr = Opcodes.end();
3903 : return Result;
3904 : }
3905 :
3906 : int64_t MachOBindEntry::readSLEB128(const char **error) {
3907 : unsigned Count;
3908 : int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error);
3909 1 : Ptr += Count;
3910 1 : if (Ptr > Opcodes.end())
3911 : Ptr = Opcodes.end();
3912 1 : return Result;
3913 0 : }
3914 0 :
3915 0 : int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
3916 0 :
3917 0 : uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
3918 :
3919 1 : StringRef MachOBindEntry::typeName() const {
3920 : switch (BindType) {
3921 1 : case MachO::BIND_TYPE_POINTER:
3922 1 : return "pointer";
3923 0 : case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
3924 0 : return "text abs32";
3925 0 : case MachO::BIND_TYPE_TEXT_PCREL32:
3926 0 : return "text rel32";
3927 0 : }
3928 : return "unknown";
3929 1 : }
3930 1 :
3931 : StringRef MachOBindEntry::symbolName() const { return SymbolName; }
3932 0 :
3933 1 : int64_t MachOBindEntry::addend() const { return Addend; }
3934 :
3935 1 : uint32_t MachOBindEntry::flags() const { return Flags; }
3936 1 :
3937 2 : int MachOBindEntry::ordinal() const { return Ordinal; }
3938 1 :
3939 1 : // For use with the SegIndex of a checked Mach-O Bind entry
3940 1 : // to get the segment name.
3941 : StringRef MachOBindEntry::segmentName() const {
3942 : return O->BindRebaseSegmentName(SegmentIndex);
3943 : }
3944 :
3945 : // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3946 : // to get the section name.
3947 : StringRef MachOBindEntry::sectionName() const {
3948 : return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3949 : }
3950 3 :
3951 3 : // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3952 : // to get the address.
3953 3 : uint64_t MachOBindEntry::address() const {
3954 0 : return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3955 0 : }
3956 0 :
3957 0 : bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
3958 0 : #ifdef EXPENSIVE_CHECKS
3959 : assert(Opcodes == Other.Opcodes && "compare iterators of different files");
3960 3 : #else
3961 3 : assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3962 0 : #endif
3963 0 : return (Ptr == Other.Ptr) &&
3964 0 : (RemainingLoopCount == Other.RemainingLoopCount) &&
3965 0 : (Done == Other.Done);
3966 0 : }
3967 :
3968 3 : // Build table of sections so SegIndex/SegOffset pairs can be translated.
3969 : BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
3970 3 : uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
3971 3 : StringRef CurSegName;
3972 : uint64_t CurSegAddress;
3973 3 : for (const SectionRef &Section : Obj->sections()) {
3974 1 : SectionInfo Info;
3975 2 : Section.getName(Info.SectionName);
3976 1 : Info.Address = Section.getAddress();
3977 1 : Info.Size = Section.getSize();
3978 1 : Info.SegmentName =
3979 : Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
3980 : if (!Info.SegmentName.equals(CurSegName)) {
3981 : ++CurSegIndex;
3982 : CurSegName = Info.SegmentName;
3983 : CurSegAddress = Info.Address;
3984 : }
3985 : Info.SegmentIndex = CurSegIndex - 1;
3986 : Info.OffsetInSegment = Info.Address - CurSegAddress;
3987 : Info.SegmentStartAddress = CurSegAddress;
3988 2 : Sections.push_back(Info);
3989 2 : }
3990 : MaxSegIndex = CurSegIndex;
3991 2 : }
3992 0 :
3993 0 : // For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to
3994 0 : // validate a MachOBindEntry or MachORebaseEntry.
3995 0 : const char * BindRebaseSegInfo::checkSegAndOffset(int32_t SegIndex,
3996 0 : uint64_t SegOffset,
3997 0 : bool endInvalid) {
3998 : if (SegIndex == -1)
3999 2 : return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
4000 2 : if (SegIndex >= MaxSegIndex)
4001 0 : return "bad segIndex (too large)";
4002 0 : for (const SectionInfo &SI : Sections) {
4003 0 : if (SI.SegmentIndex != SegIndex)
4004 0 : continue;
4005 0 : if (SI.OffsetInSegment > SegOffset)
4006 0 : continue;
4007 : if (SegOffset > (SI.OffsetInSegment + SI.Size))
4008 2 : continue;
4009 2 : if (endInvalid && SegOffset >= (SI.OffsetInSegment + SI.Size))
4010 : continue;
4011 0 : return nullptr;
4012 2 : }
4013 2 : return "bad segOffset, too large";
4014 0 : }
4015 0 :
4016 0 : // For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for
4017 0 : // the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode and for use in
4018 0 : // MachORebaseEntry::moveNext() to validate a MachORebaseEntry for
4019 0 : // REBASE_OPCODE_DO_*_TIMES* opcodes. The SegIndex and SegOffset must have
4020 : // been already checked.
4021 2 : const char * BindRebaseSegInfo::checkCountAndSkip(uint32_t Count, uint32_t Skip,
4022 : uint8_t PointerSize,
4023 2 : int32_t SegIndex,
4024 : uint64_t SegOffset) {
4025 2 : const SectionInfo &SI = findSection(SegIndex, SegOffset);
4026 1 : uint64_t addr = SI.SegmentStartAddress + SegOffset;
4027 1 : if (addr >= SI.Address + SI.Size)
4028 2 : return "bad segOffset, too large";
4029 1 : uint64_t i = 0;
4030 1 : if (Count > 1)
4031 1 : i = (Skip + PointerSize) * (Count - 1);
4032 : else if (Count == 1)
4033 : i = Skip + PointerSize;
4034 : if (addr + i >= SI.Address + SI.Size) {
4035 : // For rebase opcodes they can step from one section to another.
4036 : uint64_t TrailingSegOffset = (addr + i) - SI.SegmentStartAddress;
4037 : const char *error = checkSegAndOffset(SegIndex, TrailingSegOffset, false);
4038 : if (error)
4039 : return "bad count and skip, too large";
4040 : }
4041 1 : return nullptr;
4042 1 : }
4043 1 :
4044 1 : // For use with the SegIndex of a checked Mach-O Bind or Rebase entry
4045 1 : // to get the segment name.
4046 1 : StringRef BindRebaseSegInfo::segmentName(int32_t SegIndex) {
4047 : for (const SectionInfo &SI : Sections) {
4048 : if (SI.SegmentIndex == SegIndex)
4049 : return SI.SegmentName;
4050 : }
4051 21 : llvm_unreachable("invalid SegIndex");
4052 : }
4053 42 :
4054 21 : // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4055 42 : // to get the SectionInfo.
4056 0 : const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection(
4057 21 : int32_t SegIndex, uint64_t SegOffset) {
4058 : for (const SectionInfo &SI : Sections) {
4059 : if (SI.SegmentIndex != SegIndex)
4060 0 : continue;
4061 : if (SI.OffsetInSegment > SegOffset)
4062 0 : continue;
4063 : if (SegOffset >= (SI.OffsetInSegment + SI.Size))
4064 11 : continue;
4065 11 : return SI;
4066 : }
4067 11 : llvm_unreachable("SegIndex and SegOffset not in any section");
4068 : }
4069 0 :
4070 : // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4071 0 : // entry to get the section name.
4072 : StringRef BindRebaseSegInfo::sectionName(int32_t SegIndex,
4073 0 : uint64_t SegOffset) {
4074 : return findSection(SegIndex, SegOffset).SectionName;
4075 : }
4076 :
4077 : // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4078 11 : // entry to get the address.
4079 11 : uint64_t BindRebaseSegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {
4080 : const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
4081 : return SI.SegmentStartAddress + OffsetInSeg;
4082 : }
4083 :
4084 11 : iterator_range<bind_iterator>
4085 11 : MachOObjectFile::bindTable(Error &Err, MachOObjectFile *O,
4086 : ArrayRef<uint8_t> Opcodes, bool is64,
4087 : MachOBindEntry::Kind BKind) {
4088 : if (O->BindRebaseSectionTable == nullptr)
4089 : O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
4090 11 : MachOBindEntry Start(&Err, O, Opcodes, is64, BKind);
4091 11 : Start.moveToFirst();
4092 :
4093 : MachOBindEntry Finish(&Err, O, Opcodes, is64, BKind);
4094 23 : Finish.moveToEnd();
4095 :
4096 : return make_range(bind_iterator(Start), bind_iterator(Finish));
4097 : }
4098 :
4099 : iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) {
4100 35 : return bindTable(Err, this, getDyldInfoBindOpcodes(), is64Bit(),
4101 23 : MachOBindEntry::Kind::Regular);
4102 12 : }
4103 :
4104 : iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) {
4105 : return bindTable(Err, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
4106 12 : MachOBindEntry::Kind::Lazy);
4107 : }
4108 12 :
4109 : iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) {
4110 12 : return bindTable(Err, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
4111 12 : MachOBindEntry::Kind::Weak);
4112 : }
4113 12 :
4114 12 : MachOObjectFile::load_command_iterator
4115 : MachOObjectFile::begin_load_commands() const {
4116 12 : return LoadCommands.begin();
4117 : }
4118 :
4119 12 : MachOObjectFile::load_command_iterator
4120 12 : MachOObjectFile::end_load_commands() const {
4121 : return LoadCommands.end();
4122 : }
4123 96 :
4124 96 : iterator_range<MachOObjectFile::load_command_iterator>
4125 96 : MachOObjectFile::load_commands() const {
4126 192 : return make_range(begin_load_commands(), end_load_commands());
4127 : }
4128 48 :
4129 48 : StringRef
4130 48 : MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
4131 48 : ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
4132 : return parseSegmentOrSectionName(Raw.data());
4133 87 : }
4134 174 :
4135 87 : ArrayRef<char>
4136 87 : MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
4137 87 : assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
4138 : const section_base *Base =
4139 107 : reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
4140 107 : return makeArrayRef(Base->sectname);
4141 : }
4142 107 :
4143 107 : ArrayRef<char>
4144 2 : MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
4145 2 : assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
4146 : const section_base *Base =
4147 : reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
4148 : return makeArrayRef(Base->segname);
4149 : }
4150 210 :
4151 9 : bool
4152 9 : MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
4153 : const {
4154 : if (getCPUType(*this) == MachO::CPU_TYPE_X86_64)
4155 180 : return false;
4156 : return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
4157 276 : }
4158 276 :
4159 276 : unsigned MachOObjectFile::getPlainRelocationSymbolNum(
4160 276 : const MachO::any_relocation_info &RE) const {
4161 : if (isLittleEndian())
4162 : return RE.r_word1 & 0xffffff;
4163 : return RE.r_word1 >> 8;
4164 276 : }
4165 276 :
4166 18 : bool MachOObjectFile::getPlainRelocationExternal(
4167 18 : const MachO::any_relocation_info &RE) const {
4168 : if (isLittleEndian())
4169 : return (RE.r_word1 >> 27) & 1;
4170 : return (RE.r_word1 >> 4) & 1;
4171 125 : }
4172 109 :
4173 : bool MachOObjectFile::getScatteredRelocationScattered(
4174 : const MachO::any_relocation_info &RE) const {
4175 : return RE.r_word0 >> 31;
4176 8 : }
4177 :
4178 : uint32_t MachOObjectFile::getScatteredRelocationValue(
4179 : const MachO::any_relocation_info &RE) const {
4180 14 : return RE.r_word1;
4181 : }
4182 :
4183 30 : uint32_t MachOObjectFile::getScatteredRelocationType(
4184 30 : const MachO::any_relocation_info &RE) const {
4185 1 : return (RE.r_word0 >> 24) & 0xf;
4186 1 : }
4187 1 :
4188 1 : unsigned MachOObjectFile::getAnyRelocationAddress(
4189 82 : const MachO::any_relocation_info &RE) const {
4190 : if (isRelocationScattered(RE))
4191 29 : return getScatteredRelocationAddress(RE);
4192 29 : return getPlainRelocationAddress(RE);
4193 29 : }
4194 1 :
4195 1 : unsigned MachOObjectFile::getAnyRelocationPCRel(
4196 2 : const MachO::any_relocation_info &RE) const {
4197 1 : if (isRelocationScattered(RE))
4198 2 : return getScatteredRelocationPCRel(RE);
4199 1 : return getPlainRelocationPCRel(*this, RE);
4200 1 : }
4201 1 :
4202 : unsigned MachOObjectFile::getAnyRelocationLength(
4203 : const MachO::any_relocation_info &RE) const {
4204 : if (isRelocationScattered(RE))
4205 : return getScatteredRelocationLength(RE);
4206 : return getPlainRelocationLength(*this, RE);
4207 : }
4208 17 :
4209 17 : unsigned
4210 1 : MachOObjectFile::getAnyRelocationType(
4211 1 : const MachO::any_relocation_info &RE) const {
4212 1 : if (isRelocationScattered(RE))
4213 1 : return getScatteredRelocationType(RE);
4214 1 : return getPlainRelocationType(*this, RE);
4215 : }
4216 16 :
4217 16 : SectionRef
4218 16 : MachOObjectFile::getAnyRelocationSection(
4219 2 : const MachO::any_relocation_info &RE) const {
4220 4 : if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
4221 2 : return *section_end();
4222 2 : unsigned SecNum = getPlainRelocationSymbolNum(RE);
4223 2 : if (SecNum == MachO::R_ABS || SecNum > Sections.size())
4224 : return *section_end();
4225 14 : DataRefImpl DRI;
4226 2 : DRI.d.a = SecNum - 1;
4227 2 : return SectionRef(DRI, this);
4228 2 : }
4229 2 :
4230 4 : MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
4231 2 : assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
4232 2 : return getStruct<MachO::section>(*this, Sections[DRI.d.a]);
4233 2 : }
4234 :
4235 : MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
4236 : assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
4237 : return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]);
4238 : }
4239 :
4240 5 : MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
4241 5 : unsigned Index) const {
4242 1 : const char *Sec = getSectionPtr(*this, L, Index);
4243 1 : return getStruct<MachO::section>(*this, Sec);
4244 1 : }
4245 1 :
4246 1 : MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
4247 : unsigned Index) const {
4248 4 : const char *Sec = getSectionPtr(*this, L, Index);
4249 3 : return getStruct<MachO::section_64>(*this, Sec);
4250 3 : }
4251 3 :
4252 1 : MachO::nlist
4253 1 : MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
4254 2 : const char *P = reinterpret_cast<const char *>(DRI.p);
4255 1 : return getStruct<MachO::nlist>(*this, P);
4256 1 : }
4257 1 :
4258 : MachO::nlist_64
4259 : MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
4260 1 : const char *P = reinterpret_cast<const char *>(DRI.p);
4261 3 : return getStruct<MachO::nlist_64>(*this, P);
4262 : }
4263 :
4264 : MachO::linkedit_data_command
4265 : MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
4266 3 : return getStruct<MachO::linkedit_data_command>(*this, L.Ptr);
4267 61 : }
4268 61 :
4269 : MachO::segment_command
4270 887 : MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
4271 826 : return getStruct<MachO::segment_command>(*this, L.Ptr);
4272 : }
4273 122 :
4274 1 : MachO::segment_command_64
4275 : MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
4276 1 : return getStruct<MachO::segment_command_64>(*this, L.Ptr);
4277 1 : }
4278 1 :
4279 1 : MachO::linker_option_command
4280 : MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
4281 60 : return getStruct<MachO::linker_option_command>(*this, L.Ptr);
4282 60 : }
4283 60 :
4284 : MachO::version_min_command
4285 : MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
4286 : return getStruct<MachO::version_min_command>(*this, L.Ptr);
4287 : }
4288 60 :
4289 4 : MachO::note_command
4290 : MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo &L) const {
4291 : return getStruct<MachO::note_command>(*this, L.Ptr);
4292 : }
4293 21 :
4294 21 : MachO::build_version_command
4295 21 : MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo &L) const {
4296 1 : return getStruct<MachO::build_version_command>(*this, L.Ptr);
4297 1 : }
4298 1 :
4299 1 : MachO::build_tool_version
4300 1 : MachOObjectFile::getBuildToolVersion(unsigned index) const {
4301 : return getStruct<MachO::build_tool_version>(*this, BuildTools[index]);
4302 : }
4303 :
4304 : MachO::dylib_command
4305 : MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
4306 : return getStruct<MachO::dylib_command>(*this, L.Ptr);
4307 1 : }
4308 1 :
4309 1 : MachO::dyld_info_command
4310 1 : MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
4311 2 : return getStruct<MachO::dyld_info_command>(*this, L.Ptr);
4312 1 : }
4313 1 :
4314 1 : MachO::dylinker_command
4315 : MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
4316 : return getStruct<MachO::dylinker_command>(*this, L.Ptr);
4317 : }
4318 :
4319 : MachO::uuid_command
4320 : MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
4321 40 : return getStruct<MachO::uuid_command>(*this, L.Ptr);
4322 40 : }
4323 40 :
4324 40 : MachO::rpath_command
4325 0 : MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
4326 0 : return getStruct<MachO::rpath_command>(*this, L.Ptr);
4327 0 : }
4328 0 :
4329 0 : MachO::source_version_command
4330 : MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
4331 40 : return getStruct<MachO::source_version_command>(*this, L.Ptr);
4332 40 : }
4333 2 :
4334 4 : MachO::entry_point_command
4335 2 : MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
4336 2 : return getStruct<MachO::entry_point_command>(*this, L.Ptr);
4337 2 : }
4338 :
4339 : MachO::encryption_info_command
4340 : MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
4341 : return getStruct<MachO::encryption_info_command>(*this, L.Ptr);
4342 : }
4343 :
4344 : MachO::encryption_info_command_64
4345 : MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
4346 18 : return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr);
4347 18 : }
4348 18 :
4349 0 : MachO::sub_framework_command
4350 0 : MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
4351 0 : return getStruct<MachO::sub_framework_command>(*this, L.Ptr);
4352 0 : }
4353 0 :
4354 : MachO::sub_umbrella_command
4355 18 : MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
4356 18 : return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr);
4357 1 : }
4358 2 :
4359 1 : MachO::sub_library_command
4360 1 : MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
4361 1 : return getStruct<MachO::sub_library_command>(*this, L.Ptr);
4362 : }
4363 :
4364 : MachO::sub_client_command
4365 : MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
4366 : return getStruct<MachO::sub_client_command>(*this, L.Ptr);
4367 : }
4368 51 :
4369 51 : MachO::routines_command
4370 51 : MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
4371 51 : return getStruct<MachO::routines_command>(*this, L.Ptr);
4372 51 : }
4373 1 :
4374 2 : MachO::routines_command_64
4375 1 : MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
4376 1 : return getStruct<MachO::routines_command_64>(*this, L.Ptr);
4377 1 : }
4378 :
4379 : MachO::thread_command
4380 0 : MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
4381 : return getStruct<MachO::thread_command>(*this, L.Ptr);
4382 0 : }
4383 0 :
4384 0 : MachO::any_relocation_info
4385 0 : MachOObjectFile::getRelocation(DataRefImpl Rel) const {
4386 : uint32_t Offset;
4387 50 : if (getHeader().filetype == MachO::MH_OBJECT) {
4388 0 : DataRefImpl Sec;
4389 0 : Sec.d.a = Rel.d.a;
4390 0 : if (is64Bit()) {
4391 0 : MachO::section_64 Sect = getSection64(Sec);
4392 0 : Offset = Sect.reloff;
4393 0 : } else {
4394 : MachO::section Sect = getSection(Sec);
4395 : Offset = Sect.reloff;
4396 : }
4397 : } else {
4398 : MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
4399 : if (Rel.d.a == 0)
4400 5 : Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations
4401 5 : else
4402 1 : Offset = DysymtabLoadCmd.locreloff; // Offset to the local relocations
4403 1 : }
4404 1 :
4405 1 : auto P = reinterpret_cast<const MachO::any_relocation_info *>(
4406 1 : getPtr(*this, Offset)) + Rel.d.b;
4407 : return getStruct<MachO::any_relocation_info>(
4408 4 : *this, reinterpret_cast<const char *>(P));
4409 4 : }
4410 0 :
4411 0 : MachO::data_in_code_entry
4412 0 : MachOObjectFile::getDice(DataRefImpl Rel) const {
4413 0 : const char *P = reinterpret_cast<const char *>(Rel.p);
4414 0 : return getStruct<MachO::data_in_code_entry>(*this, P);
4415 : }
4416 :
4417 1 : const MachO::mach_header &MachOObjectFile::getHeader() const {
4418 : return Header;
4419 : }
4420 1 :
4421 1 : const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
4422 1 : assert(is64Bit());
4423 1 : return Header64;
4424 : }
4425 3 :
4426 1 : uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
4427 : const MachO::dysymtab_command &DLC,
4428 1 : unsigned Index) const {
4429 1 : uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
4430 1 : return getStruct<uint32_t>(*this, getPtr(*this, Offset));
4431 1 : }
4432 :
4433 2 : MachO::data_in_code_entry
4434 2 : MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
4435 0 : unsigned Index) const {
4436 0 : uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
4437 0 : return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset));
4438 0 : }
4439 0 :
4440 : MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
4441 : if (SymtabLoadCmd)
4442 : return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
4443 :
4444 2 : // If there is no SymtabLoadCmd return a load command with zero'ed fields.
4445 : MachO::symtab_command Cmd;
4446 2 : Cmd.cmd = MachO::LC_SYMTAB;
4447 1 : Cmd.cmdsize = sizeof(MachO::symtab_command);
4448 1 : Cmd.symoff = 0;
4449 2 : Cmd.nsyms = 0;
4450 1 : Cmd.stroff = 0;
4451 1 : Cmd.strsize = 0;
4452 1 : return Cmd;
4453 : }
4454 1 :
4455 : MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
4456 : if (DysymtabLoadCmd)
4457 : return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
4458 :
4459 : // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
4460 : MachO::dysymtab_command Cmd;
4461 : Cmd.cmd = MachO::LC_DYSYMTAB;
4462 1 : Cmd.cmdsize = sizeof(MachO::dysymtab_command);
4463 5 : Cmd.ilocalsym = 0;
4464 5 : Cmd.nlocalsym = 0;
4465 1 : Cmd.iextdefsym = 0;
4466 1 : Cmd.nextdefsym = 0;
4467 1 : Cmd.iundefsym = 0;
4468 1 : Cmd.nundefsym = 0;
4469 1 : Cmd.tocoff = 0;
4470 : Cmd.ntoc = 0;
4471 4 : Cmd.modtaboff = 0;
4472 4 : Cmd.nmodtab = 0;
4473 0 : Cmd.extrefsymoff = 0;
4474 0 : Cmd.nextrefsyms = 0;
4475 0 : Cmd.indirectsymoff = 0;
4476 0 : Cmd.nindirectsyms = 0;
4477 0 : Cmd.extreloff = 0;
4478 : Cmd.nextrel = 0;
4479 : Cmd.locreloff = 0;
4480 0 : Cmd.nlocrel = 0;
4481 : return Cmd;
4482 : }
4483 0 :
4484 0 : MachO::linkedit_data_command
4485 0 : MachOObjectFile::getDataInCodeLoadCommand() const {
4486 0 : if (DataInCodeLoadCmd)
4487 : return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd);
4488 4 :
4489 0 : // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
4490 : MachO::linkedit_data_command Cmd;
4491 : Cmd.cmd = MachO::LC_DATA_IN_CODE;
4492 0 : Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4493 0 : Cmd.dataoff = 0;
4494 0 : Cmd.datasize = 0;
4495 0 : return Cmd;
4496 : }
4497 4 :
4498 4 : MachO::linkedit_data_command
4499 4 : MachOObjectFile::getLinkOptHintsLoadCommand() const {
4500 : if (LinkOptHintsLoadCmd)
4501 4 : return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd);
4502 1 :
4503 1 : // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
4504 1 : // fields.
4505 2 : MachO::linkedit_data_command Cmd;
4506 1 : Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
4507 1 : Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4508 1 : Cmd.dataoff = 0;
4509 : Cmd.datasize = 0;
4510 : return Cmd;
4511 : }
4512 :
4513 : ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
4514 : if (!DyldInfoLoadCmd)
4515 3 : return None;
4516 3 :
4517 1 : MachO::dyld_info_command DyldInfo =
4518 1 : getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4519 1 : const uint8_t *Ptr =
4520 1 : reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off));
4521 1 : return makeArrayRef(Ptr, DyldInfo.rebase_size);
4522 : }
4523 2 :
4524 2 : ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
4525 2 : if (!DyldInfoLoadCmd)
4526 : return None;
4527 0 :
4528 2 : MachO::dyld_info_command DyldInfo =
4529 0 : getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4530 0 : const uint8_t *Ptr =
4531 0 : reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off));
4532 0 : return makeArrayRef(Ptr, DyldInfo.bind_size);
4533 0 : }
4534 0 :
4535 : ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
4536 2 : if (!DyldInfoLoadCmd)
4537 2 : return None;
4538 2 :
4539 0 : MachO::dyld_info_command DyldInfo =
4540 0 : getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4541 0 : const uint8_t *Ptr =
4542 0 : reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off));
4543 0 : return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
4544 0 : }
4545 :
4546 2 : ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
4547 2 : if (!DyldInfoLoadCmd)
4548 0 : return None;
4549 0 :
4550 0 : MachO::dyld_info_command DyldInfo =
4551 0 : getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4552 0 : const uint8_t *Ptr =
4553 0 : reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off));
4554 : return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
4555 : }
4556 0 :
4557 : ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
4558 : if (!DyldInfoLoadCmd)
4559 0 : return None;
4560 0 :
4561 0 : MachO::dyld_info_command DyldInfo =
4562 0 : getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4563 : const uint8_t *Ptr =
4564 2 : reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));
4565 0 : return makeArrayRef(Ptr, DyldInfo.export_size);
4566 : }
4567 :
4568 0 : ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
4569 0 : if (!UuidLoadCmd)
4570 0 : return None;
4571 0 : // Returning a pointer is fine as uuid doesn't need endian swapping.
4572 : const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
4573 2 : return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
4574 : }
4575 2 :
4576 1 : StringRef MachOObjectFile::getStringTableData() const {
4577 1 : MachO::symtab_command S = getSymtabLoadCommand();
4578 2 : return getData().substr(S.stroff, S.strsize);
4579 1 : }
4580 1 :
4581 1 : bool MachOObjectFile::is64Bit() const {
4582 : return getType() == getMachOType(false, true) ||
4583 : getType() == getMachOType(true, true);
4584 : }
4585 :
4586 : void MachOObjectFile::ReadULEB128s(uint64_t Index,
4587 : SmallVectorImpl<uint64_t> &Out) const {
4588 : DataExtractor extractor(ObjectFile::getData(), true, 0);
4589 :
4590 : uint32_t offset = Index;
4591 1 : uint64_t data = 0;
4592 1 : while (uint64_t delta = extractor.getULEB128(&offset)) {
4593 1 : data += delta;
4594 1 : Out.push_back(data);
4595 1 : }
4596 1 : }
4597 :
4598 : bool MachOObjectFile::isRelocatableObject() const {
4599 : return getHeader().filetype == MachO::MH_OBJECT;
4600 : }
4601 80 :
4602 : Expected<std::unique_ptr<MachOObjectFile>>
4603 160 : ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer,
4604 80 : uint32_t UniversalCputype,
4605 160 : uint32_t UniversalIndex) {
4606 0 : StringRef Magic = Buffer.getBuffer().slice(0, 4);
4607 80 : if (Magic == "\xFE\xED\xFA\xCE")
4608 : return MachOObjectFile::create(Buffer, false, false,
4609 : UniversalCputype, UniversalIndex);
4610 1 : if (Magic == "\xCE\xFA\xED\xFE")
4611 : return MachOObjectFile::create(Buffer, true, false,
4612 2 : UniversalCputype, UniversalIndex);
4613 1 : if (Magic == "\xFE\xED\xFA\xCF")
4614 2 : return MachOObjectFile::create(Buffer, false, true,
4615 0 : UniversalCputype, UniversalIndex);
4616 1 : if (Magic == "\xCF\xFA\xED\xFE")
4617 : return MachOObjectFile::create(Buffer, true, true,
4618 : UniversalCputype, UniversalIndex);
4619 0 : return make_error<GenericBinaryError>("Unrecognized MachO magic number",
4620 : object_error::invalid_file_type);
4621 0 : }
4622 :
4623 21 : StringRef MachOObjectFile::mapDebugSectionName(StringRef Name) const {
4624 21 : return StringSwitch<StringRef>(Name)
4625 : .Case("debug_str_offs", "debug_str_offsets")
4626 21 : .Default(Name);
4627 : }
|