1 //===- MachOObjectFile.cpp - Mach-O object file binding -------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the MachOObjectFile class, which binds the MachOObject
11 // class to the generic ObjectFile wrapper.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/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"
47 #include <system_error>
50 using namespace object
;
59 } // end anonymous namespace
61 static Error
malformedError(const Twine
&Msg
) {
62 return make_error
<GenericBinaryError
>("truncated or malformed object (" +
64 object_error::parse_failed
);
67 // FIXME: Replace all uses of this function with getStructOrErr.
69 static T
getStruct(const MachOObjectFile
&O
, const char *P
) {
70 // Don't read before the beginning or past the end of the file
71 if (P
< O
.getData().begin() || P
+ sizeof(T
) > O
.getData().end())
72 report_fatal_error("Malformed MachO file.");
75 memcpy(&Cmd
, P
, sizeof(T
));
76 if (O
.isLittleEndian() != sys::IsLittleEndianHost
)
77 MachO::swapStruct(Cmd
);
82 static Expected
<T
> getStructOrErr(const MachOObjectFile
&O
, const char *P
) {
83 // 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");
88 memcpy(&Cmd
, P
, sizeof(T
));
89 if (O
.isLittleEndian() != sys::IsLittleEndianHost
)
90 MachO::swapStruct(Cmd
);
95 getSectionPtr(const MachOObjectFile
&O
, MachOObjectFile::LoadCommandInfo L
,
97 uintptr_t CommandAddr
= reinterpret_cast<uintptr_t>(L
.Ptr
);
99 bool Is64
= O
.is64Bit();
100 unsigned SegmentLoadSize
= Is64
? sizeof(MachO::segment_command_64
) :
101 sizeof(MachO::segment_command
);
102 unsigned SectionSize
= Is64
? sizeof(MachO::section_64
) :
103 sizeof(MachO::section
);
105 uintptr_t SectionAddr
= CommandAddr
+ SegmentLoadSize
+ Sec
* SectionSize
;
106 return reinterpret_cast<const char*>(SectionAddr
);
109 static const char *getPtr(const MachOObjectFile
&O
, size_t Offset
) {
110 assert(Offset
<= O
.getData().size());
111 return O
.getData().data() + Offset
;
114 static MachO::nlist_base
115 getSymbolTableEntryBase(const MachOObjectFile
&O
, DataRefImpl DRI
) {
116 const char *P
= reinterpret_cast<const char *>(DRI
.p
);
117 return getStruct
<MachO::nlist_base
>(O
, P
);
120 static StringRef
parseSegmentOrSectionName(const char *P
) {
124 // Not null terminated, so this is a 16 char string.
125 return StringRef(P
, 16);
128 static unsigned getCPUType(const MachOObjectFile
&O
) {
129 return O
.getHeader().cputype
;
133 getPlainRelocationAddress(const MachO::any_relocation_info
&RE
) {
138 getScatteredRelocationAddress(const MachO::any_relocation_info
&RE
) {
139 return RE
.r_word0
& 0xffffff;
142 static bool getPlainRelocationPCRel(const MachOObjectFile
&O
,
143 const MachO::any_relocation_info
&RE
) {
144 if (O
.isLittleEndian())
145 return (RE
.r_word1
>> 24) & 1;
146 return (RE
.r_word1
>> 7) & 1;
150 getScatteredRelocationPCRel(const MachO::any_relocation_info
&RE
) {
151 return (RE
.r_word0
>> 30) & 1;
154 static unsigned getPlainRelocationLength(const MachOObjectFile
&O
,
155 const MachO::any_relocation_info
&RE
) {
156 if (O
.isLittleEndian())
157 return (RE
.r_word1
>> 25) & 3;
158 return (RE
.r_word1
>> 5) & 3;
162 getScatteredRelocationLength(const MachO::any_relocation_info
&RE
) {
163 return (RE
.r_word0
>> 28) & 3;
166 static unsigned getPlainRelocationType(const MachOObjectFile
&O
,
167 const MachO::any_relocation_info
&RE
) {
168 if (O
.isLittleEndian())
169 return RE
.r_word1
>> 28;
170 return RE
.r_word1
& 0xf;
173 static uint32_t getSectionFlags(const MachOObjectFile
&O
,
176 MachO::section_64 Sect
= O
.getSection64(Sec
);
179 MachO::section Sect
= O
.getSection(Sec
);
183 static Expected
<MachOObjectFile::LoadCommandInfo
>
184 getLoadCommandInfo(const MachOObjectFile
&Obj
, const char *Ptr
,
185 uint32_t LoadCommandIndex
) {
186 if (auto CmdOrErr
= getStructOrErr
<MachO::load_command
>(Obj
, Ptr
)) {
187 if (CmdOrErr
->cmdsize
+ Ptr
> Obj
.getData().end())
188 return malformedError("load command " + Twine(LoadCommandIndex
) +
189 " extends past end of file");
190 if (CmdOrErr
->cmdsize
< 8)
191 return malformedError("load command " + Twine(LoadCommandIndex
) +
192 " with size less than 8 bytes");
193 return MachOObjectFile::LoadCommandInfo({Ptr
, *CmdOrErr
});
195 return CmdOrErr
.takeError();
198 static Expected
<MachOObjectFile::LoadCommandInfo
>
199 getFirstLoadCommandInfo(const MachOObjectFile
&Obj
) {
200 unsigned HeaderSize
= Obj
.is64Bit() ? sizeof(MachO::mach_header_64
)
201 : sizeof(MachO::mach_header
);
202 if (sizeof(MachO::load_command
) > Obj
.getHeader().sizeofcmds
)
203 return malformedError("load command 0 extends past the end all load "
204 "commands in the file");
205 return getLoadCommandInfo(Obj
, getPtr(Obj
, HeaderSize
), 0);
208 static Expected
<MachOObjectFile::LoadCommandInfo
>
209 getNextLoadCommandInfo(const MachOObjectFile
&Obj
, uint32_t LoadCommandIndex
,
210 const MachOObjectFile::LoadCommandInfo
&L
) {
211 unsigned HeaderSize
= Obj
.is64Bit() ? sizeof(MachO::mach_header_64
)
212 : sizeof(MachO::mach_header
);
213 if (L
.Ptr
+ L
.C
.cmdsize
+ sizeof(MachO::load_command
) >
214 Obj
.getData().data() + HeaderSize
+ Obj
.getHeader().sizeofcmds
)
215 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);
220 template <typename T
>
221 static void parseHeader(const MachOObjectFile
&Obj
, T
&Header
,
223 if (sizeof(T
) > Obj
.getData().size()) {
224 Err
= malformedError("the mach header extends past the end of the "
228 if (auto HeaderOrErr
= getStructOrErr
<T
>(Obj
, getPtr(Obj
, 0)))
229 Header
= *HeaderOrErr
;
231 Err
= HeaderOrErr
.takeError();
234 // This is used to check for overlapping of Mach-O elements.
235 struct MachOElement
{
241 static Error
checkOverlappingElement(std::list
<MachOElement
> &Elements
,
242 uint64_t Offset
, uint64_t Size
,
245 return Error::success();
247 for (auto it
=Elements
.begin() ; it
!= Elements
.end(); ++it
) {
249 if ((Offset
>= E
.Offset
&& Offset
< E
.Offset
+ E
.Size
) ||
250 (Offset
+ Size
> E
.Offset
&& Offset
+ Size
< E
.Offset
+ E
.Size
) ||
251 (Offset
<= E
.Offset
&& Offset
+ Size
>= E
.Offset
+ E
.Size
))
252 return malformedError(Twine(Name
) + " at offset " + Twine(Offset
) +
253 " with a size of " + Twine(Size
) + ", overlaps " +
254 E
.Name
+ " at offset " + Twine(E
.Offset
) + " with "
255 "a size of " + Twine(E
.Size
));
258 if (nt
!= Elements
.end()) {
260 if (Offset
+ Size
<= N
.Offset
) {
261 Elements
.insert(nt
, {Offset
, Size
, Name
});
262 return Error::success();
266 Elements
.push_back({Offset
, Size
, Name
});
267 return Error::success();
270 // 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 template <typename Segment
, typename Section
>
274 static Error
parseSegmentLoadCommand(
275 const MachOObjectFile
&Obj
, const MachOObjectFile::LoadCommandInfo
&Load
,
276 SmallVectorImpl
<const char *> &Sections
, bool &IsPageZeroSegment
,
277 uint32_t LoadCommandIndex
, const char *CmdName
, uint64_t SizeOfHeaders
,
278 std::list
<MachOElement
> &Elements
) {
279 const unsigned SegmentLoadSize
= sizeof(Segment
);
280 if (Load
.C
.cmdsize
< SegmentLoadSize
)
281 return malformedError("load command " + Twine(LoadCommandIndex
) +
282 " " + CmdName
+ " cmdsize too small");
283 if (auto SegOrErr
= getStructOrErr
<Segment
>(Obj
, Load
.Ptr
)) {
284 Segment S
= SegOrErr
.get();
285 const unsigned SectionSize
= sizeof(Section
);
286 uint64_t FileSize
= Obj
.getData().size();
287 if (S
.nsects
> std::numeric_limits
<uint32_t>::max() / SectionSize
||
288 S
.nsects
* SectionSize
> Load
.C
.cmdsize
- SegmentLoadSize
)
289 return malformedError("load command " + Twine(LoadCommandIndex
) +
290 " inconsistent cmdsize in " + CmdName
+
291 " for the number of sections");
292 for (unsigned J
= 0; J
< S
.nsects
; ++J
) {
293 const char *Sec
= getSectionPtr(Obj
, Load
, J
);
294 Sections
.push_back(Sec
);
295 Section s
= getStruct
<Section
>(Obj
, Sec
);
296 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
297 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
298 s
.flags
!= MachO::S_ZEROFILL
&&
299 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
&&
301 return malformedError("offset field of section " + Twine(J
) + " in " +
302 CmdName
+ " command " + Twine(LoadCommandIndex
) +
303 " extends past the end of the file");
304 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
305 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
306 s
.flags
!= MachO::S_ZEROFILL
&&
307 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
&& S
.fileoff
== 0 &&
308 s
.offset
< SizeOfHeaders
&& s
.size
!= 0)
309 return malformedError("offset field of section " + Twine(J
) + " in " +
310 CmdName
+ " command " + Twine(LoadCommandIndex
) +
311 " not past the headers of the file");
312 uint64_t BigSize
= s
.offset
;
314 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
315 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
316 s
.flags
!= MachO::S_ZEROFILL
&&
317 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
&&
319 return malformedError("offset field plus size field of section " +
320 Twine(J
) + " in " + CmdName
+ " command " +
321 Twine(LoadCommandIndex
) +
322 " extends past the end of the file");
323 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
324 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
325 s
.flags
!= MachO::S_ZEROFILL
&&
326 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
&&
328 return malformedError("size field of section " +
329 Twine(J
) + " in " + CmdName
+ " command " +
330 Twine(LoadCommandIndex
) +
331 " greater than the segment");
332 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
333 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&& s
.size
!= 0 &&
335 return malformedError("addr field of section " + Twine(J
) + " in " +
336 CmdName
+ " command " + Twine(LoadCommandIndex
) +
337 " less than the segment's vmaddr");
340 uint64_t BigEnd
= S
.vmaddr
;
342 if (S
.vmsize
!= 0 && s
.size
!= 0 && BigSize
> BigEnd
)
343 return malformedError("addr field plus size of section " + Twine(J
) +
344 " in " + CmdName
+ " command " +
345 Twine(LoadCommandIndex
) +
346 " greater than than "
347 "the segment's vmaddr plus vmsize");
348 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
349 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
350 s
.flags
!= MachO::S_ZEROFILL
&&
351 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
)
352 if (Error Err
= checkOverlappingElement(Elements
, s
.offset
, s
.size
,
355 if (s
.reloff
> FileSize
)
356 return malformedError("reloff field of section " + Twine(J
) + " in " +
357 CmdName
+ " command " + Twine(LoadCommandIndex
) +
358 " extends past the end of the file");
360 BigSize
*= sizeof(struct MachO::relocation_info
);
362 if (BigSize
> FileSize
)
363 return malformedError("reloff field plus nreloc field times sizeof("
364 "struct relocation_info) of section " +
365 Twine(J
) + " in " + CmdName
+ " command " +
366 Twine(LoadCommandIndex
) +
367 " extends past the end of the file");
368 if (Error Err
= checkOverlappingElement(Elements
, s
.reloff
, s
.nreloc
*
370 MachO::relocation_info
),
371 "section relocation entries"))
374 if (S
.fileoff
> FileSize
)
375 return malformedError("load command " + Twine(LoadCommandIndex
) +
376 " fileoff field in " + CmdName
+
377 " extends past the end of the file");
378 uint64_t BigSize
= S
.fileoff
;
379 BigSize
+= S
.filesize
;
380 if (BigSize
> FileSize
)
381 return malformedError("load command " + Twine(LoadCommandIndex
) +
382 " fileoff field plus filesize field in " +
383 CmdName
+ " extends past the end of the file");
384 if (S
.vmsize
!= 0 && S
.filesize
> S
.vmsize
)
385 return malformedError("load command " + Twine(LoadCommandIndex
) +
386 " filesize field in " + CmdName
+
387 " greater than vmsize field");
388 IsPageZeroSegment
|= StringRef("__PAGEZERO").equals(S
.segname
);
390 return SegOrErr
.takeError();
392 return Error::success();
395 static Error
checkSymtabCommand(const MachOObjectFile
&Obj
,
396 const MachOObjectFile::LoadCommandInfo
&Load
,
397 uint32_t LoadCommandIndex
,
398 const char **SymtabLoadCmd
,
399 std::list
<MachOElement
> &Elements
) {
400 if (Load
.C
.cmdsize
< sizeof(MachO::symtab_command
))
401 return malformedError("load command " + Twine(LoadCommandIndex
) +
402 " LC_SYMTAB cmdsize too small");
403 if (*SymtabLoadCmd
!= nullptr)
404 return malformedError("more than one LC_SYMTAB command");
405 MachO::symtab_command Symtab
=
406 getStruct
<MachO::symtab_command
>(Obj
, Load
.Ptr
);
407 if (Symtab
.cmdsize
!= sizeof(MachO::symtab_command
))
408 return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex
) +
409 " has incorrect cmdsize");
410 uint64_t FileSize
= Obj
.getData().size();
411 if (Symtab
.symoff
> FileSize
)
412 return malformedError("symoff field of LC_SYMTAB command " +
413 Twine(LoadCommandIndex
) + " extends past the end "
415 uint64_t SymtabSize
= Symtab
.nsyms
;
416 const char *struct_nlist_name
;
418 SymtabSize
*= sizeof(MachO::nlist_64
);
419 struct_nlist_name
= "struct nlist_64";
421 SymtabSize
*= sizeof(MachO::nlist
);
422 struct_nlist_name
= "struct nlist";
424 uint64_t BigSize
= SymtabSize
;
425 BigSize
+= Symtab
.symoff
;
426 if (BigSize
> FileSize
)
427 return malformedError("symoff field plus nsyms field times sizeof(" +
428 Twine(struct_nlist_name
) + ") of LC_SYMTAB command " +
429 Twine(LoadCommandIndex
) + " extends past the end "
431 if (Error Err
= checkOverlappingElement(Elements
, Symtab
.symoff
, SymtabSize
,
434 if (Symtab
.stroff
> FileSize
)
435 return malformedError("stroff field of LC_SYMTAB command " +
436 Twine(LoadCommandIndex
) + " extends past the end "
438 BigSize
= Symtab
.stroff
;
439 BigSize
+= Symtab
.strsize
;
440 if (BigSize
> FileSize
)
441 return malformedError("stroff field plus strsize field of LC_SYMTAB "
442 "command " + Twine(LoadCommandIndex
) + " extends "
443 "past the end of the file");
444 if (Error Err
= checkOverlappingElement(Elements
, Symtab
.stroff
,
445 Symtab
.strsize
, "string table"))
447 *SymtabLoadCmd
= Load
.Ptr
;
448 return Error::success();
451 static Error
checkDysymtabCommand(const MachOObjectFile
&Obj
,
452 const MachOObjectFile::LoadCommandInfo
&Load
,
453 uint32_t LoadCommandIndex
,
454 const char **DysymtabLoadCmd
,
455 std::list
<MachOElement
> &Elements
) {
456 if (Load
.C
.cmdsize
< sizeof(MachO::dysymtab_command
))
457 return malformedError("load command " + Twine(LoadCommandIndex
) +
458 " LC_DYSYMTAB cmdsize too small");
459 if (*DysymtabLoadCmd
!= nullptr)
460 return malformedError("more than one LC_DYSYMTAB command");
461 MachO::dysymtab_command Dysymtab
=
462 getStruct
<MachO::dysymtab_command
>(Obj
, Load
.Ptr
);
463 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 if (Dysymtab
.tocoff
> FileSize
)
468 return malformedError("tocoff field of LC_DYSYMTAB command " +
469 Twine(LoadCommandIndex
) + " extends past the end of "
471 uint64_t BigSize
= Dysymtab
.ntoc
;
472 BigSize
*= sizeof(MachO::dylib_table_of_contents
);
473 BigSize
+= Dysymtab
.tocoff
;
474 if (BigSize
> FileSize
)
475 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 "
479 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.tocoff
,
480 Dysymtab
.ntoc
* sizeof(struct
481 MachO::dylib_table_of_contents
),
482 "table of contents"))
484 if (Dysymtab
.modtaboff
> FileSize
)
485 return malformedError("modtaboff field of LC_DYSYMTAB command " +
486 Twine(LoadCommandIndex
) + " extends past the end of "
488 BigSize
= Dysymtab
.nmodtab
;
489 const char *struct_dylib_module_name
;
490 uint64_t sizeof_modtab
;
492 sizeof_modtab
= sizeof(MachO::dylib_module_64
);
493 struct_dylib_module_name
= "struct dylib_module_64";
495 sizeof_modtab
= sizeof(MachO::dylib_module
);
496 struct_dylib_module_name
= "struct dylib_module";
498 BigSize
*= sizeof_modtab
;
499 BigSize
+= Dysymtab
.modtaboff
;
500 if (BigSize
> FileSize
)
501 return malformedError("modtaboff field plus nmodtab field times sizeof(" +
502 Twine(struct_dylib_module_name
) + ") of LC_DYSYMTAB "
503 "command " + Twine(LoadCommandIndex
) + " extends "
504 "past the end of the file");
505 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.modtaboff
,
506 Dysymtab
.nmodtab
* sizeof_modtab
,
509 if (Dysymtab
.extrefsymoff
> FileSize
)
510 return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
511 Twine(LoadCommandIndex
) + " extends past the end of "
513 BigSize
= Dysymtab
.nextrefsyms
;
514 BigSize
*= sizeof(MachO::dylib_reference
);
515 BigSize
+= Dysymtab
.extrefsymoff
;
516 if (BigSize
> FileSize
)
517 return malformedError("extrefsymoff field plus nextrefsyms field times "
518 "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 Dysymtab
.nextrefsyms
*
523 sizeof(MachO::dylib_reference
),
526 if (Dysymtab
.indirectsymoff
> FileSize
)
527 return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
528 Twine(LoadCommandIndex
) + " extends past the end of "
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 "sizeof(uint32_t) of LC_DYSYMTAB command " +
536 Twine(LoadCommandIndex
) + " extends past the end of "
538 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.indirectsymoff
,
539 Dysymtab
.nindirectsyms
*
543 if (Dysymtab
.extreloff
> FileSize
)
544 return malformedError("extreloff field of LC_DYSYMTAB command " +
545 Twine(LoadCommandIndex
) + " extends past the end of "
547 BigSize
= Dysymtab
.nextrel
;
548 BigSize
*= sizeof(MachO::relocation_info
);
549 BigSize
+= Dysymtab
.extreloff
;
550 if (BigSize
> FileSize
)
551 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 "
555 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.extreloff
,
557 sizeof(MachO::relocation_info
),
558 "external relocation table"))
560 if (Dysymtab
.locreloff
> FileSize
)
561 return malformedError("locreloff field of LC_DYSYMTAB command " +
562 Twine(LoadCommandIndex
) + " extends past the end of "
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 "(struct relocation_info) of LC_DYSYMTAB command " +
570 Twine(LoadCommandIndex
) + " extends past the end of "
572 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.locreloff
,
574 sizeof(MachO::relocation_info
),
575 "local relocation table"))
577 *DysymtabLoadCmd
= Load
.Ptr
;
578 return Error::success();
581 static Error
checkLinkeditDataCommand(const MachOObjectFile
&Obj
,
582 const MachOObjectFile::LoadCommandInfo
&Load
,
583 uint32_t LoadCommandIndex
,
584 const char **LoadCmd
, const char *CmdName
,
585 std::list
<MachOElement
> &Elements
,
586 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 if (*LoadCmd
!= nullptr)
591 return malformedError("more than one " + Twine(CmdName
) + " command");
592 MachO::linkedit_data_command LinkData
=
593 getStruct
<MachO::linkedit_data_command
>(Obj
, Load
.Ptr
);
594 if (LinkData
.cmdsize
!= sizeof(MachO::linkedit_data_command
))
595 return malformedError(Twine(CmdName
) + " command " +
596 Twine(LoadCommandIndex
) + " has incorrect cmdsize");
597 uint64_t FileSize
= Obj
.getData().size();
598 if (LinkData
.dataoff
> FileSize
)
599 return malformedError("dataoff field of " + Twine(CmdName
) + " command " +
600 Twine(LoadCommandIndex
) + " extends past the end of "
602 uint64_t BigSize
= LinkData
.dataoff
;
603 BigSize
+= LinkData
.datasize
;
604 if (BigSize
> FileSize
)
605 return malformedError("dataoff field plus datasize field of " +
606 Twine(CmdName
) + " command " +
607 Twine(LoadCommandIndex
) + " extends past the end of "
609 if (Error Err
= checkOverlappingElement(Elements
, LinkData
.dataoff
,
610 LinkData
.datasize
, ElementName
))
613 return Error::success();
616 static Error
checkDyldInfoCommand(const MachOObjectFile
&Obj
,
617 const MachOObjectFile::LoadCommandInfo
&Load
,
618 uint32_t LoadCommandIndex
,
619 const char **LoadCmd
, const char *CmdName
,
620 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 if (*LoadCmd
!= nullptr)
625 return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
627 MachO::dyld_info_command DyldInfo
=
628 getStruct
<MachO::dyld_info_command
>(Obj
, Load
.Ptr
);
629 if (DyldInfo
.cmdsize
!= sizeof(MachO::dyld_info_command
))
630 return malformedError(Twine(CmdName
) + " command " +
631 Twine(LoadCommandIndex
) + " has incorrect cmdsize");
632 uint64_t FileSize
= Obj
.getData().size();
633 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 if (BigSize
> FileSize
)
640 return malformedError("rebase_off field plus rebase_size field of " +
641 Twine(CmdName
) + " command " +
642 Twine(LoadCommandIndex
) + " extends past the end of "
644 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.rebase_off
,
645 DyldInfo
.rebase_size
,
648 if (DyldInfo
.bind_off
> FileSize
)
649 return malformedError("bind_off field of " + Twine(CmdName
) +
650 " command " + Twine(LoadCommandIndex
) + " extends "
651 "past the end of the file");
652 BigSize
= DyldInfo
.bind_off
;
653 BigSize
+= DyldInfo
.bind_size
;
654 if (BigSize
> FileSize
)
655 return malformedError("bind_off field plus bind_size field of " +
656 Twine(CmdName
) + " command " +
657 Twine(LoadCommandIndex
) + " extends past the end of "
659 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.bind_off
,
663 if (DyldInfo
.weak_bind_off
> FileSize
)
664 return malformedError("weak_bind_off field of " + Twine(CmdName
) +
665 " command " + Twine(LoadCommandIndex
) + " extends "
666 "past the end of the file");
667 BigSize
= DyldInfo
.weak_bind_off
;
668 BigSize
+= DyldInfo
.weak_bind_size
;
669 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 "
674 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.weak_bind_off
,
675 DyldInfo
.weak_bind_size
,
676 "dyld weak bind info"))
678 if (DyldInfo
.lazy_bind_off
> FileSize
)
679 return malformedError("lazy_bind_off field of " + Twine(CmdName
) +
680 " command " + Twine(LoadCommandIndex
) + " extends "
681 "past the end of the file");
682 BigSize
= DyldInfo
.lazy_bind_off
;
683 BigSize
+= DyldInfo
.lazy_bind_size
;
684 if (BigSize
> FileSize
)
685 return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
686 Twine(CmdName
) + " command " +
687 Twine(LoadCommandIndex
) + " extends past the end of "
689 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.lazy_bind_off
,
690 DyldInfo
.lazy_bind_size
,
691 "dyld lazy bind info"))
693 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 "
704 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.export_off
,
705 DyldInfo
.export_size
,
709 return Error::success();
712 static Error
checkDylibCommand(const MachOObjectFile
&Obj
,
713 const MachOObjectFile::LoadCommandInfo
&Load
,
714 uint32_t LoadCommandIndex
, const char *CmdName
) {
715 if (Load
.C
.cmdsize
< sizeof(MachO::dylib_command
))
716 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
717 CmdName
+ " cmdsize too small");
718 MachO::dylib_command D
= getStruct
<MachO::dylib_command
>(Obj
, Load
.Ptr
);
719 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 "the end of the dylib_command struct");
723 if (D
.dylib
.name
>= D
.cmdsize
)
724 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
725 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.
730 const char *P
= (const char *)Load
.Ptr
;
731 for (i
= D
.dylib
.name
; i
< D
.cmdsize
; i
++)
735 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
736 CmdName
+ " library name extends past the end of the "
738 return Error::success();
741 static Error
checkDylibIdCommand(const MachOObjectFile
&Obj
,
742 const MachOObjectFile::LoadCommandInfo
&Load
,
743 uint32_t LoadCommandIndex
,
744 const char **LoadCmd
) {
745 if (Error Err
= checkDylibCommand(Obj
, Load
, LoadCommandIndex
,
748 if (*LoadCmd
!= nullptr)
749 return malformedError("more than one LC_ID_DYLIB command");
750 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB
&&
751 Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
)
752 return malformedError("LC_ID_DYLIB load command in non-dynamic library "
755 return Error::success();
758 static Error
checkDyldCommand(const MachOObjectFile
&Obj
,
759 const MachOObjectFile::LoadCommandInfo
&Load
,
760 uint32_t LoadCommandIndex
, const char *CmdName
) {
761 if (Load
.C
.cmdsize
< sizeof(MachO::dylinker_command
))
762 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
763 CmdName
+ " cmdsize too small");
764 MachO::dylinker_command D
= getStruct
<MachO::dylinker_command
>(Obj
, Load
.Ptr
);
765 if (D
.name
< sizeof(MachO::dylinker_command
))
766 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
767 CmdName
+ " name.offset field too small, not past "
768 "the end of the dylinker_command struct");
769 if (D
.name
>= D
.cmdsize
)
770 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
771 CmdName
+ " name.offset field extends past the end "
772 "of the load command");
773 // Make sure there is a null between the starting offset of the name and
774 // the end of the load command.
776 const char *P
= (const char *)Load
.Ptr
;
777 for (i
= D
.name
; i
< D
.cmdsize
; i
++)
781 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
782 CmdName
+ " dyld name extends past the end of the "
784 return Error::success();
787 static Error
checkVersCommand(const MachOObjectFile
&Obj
,
788 const MachOObjectFile::LoadCommandInfo
&Load
,
789 uint32_t LoadCommandIndex
,
790 const char **LoadCmd
, const char *CmdName
) {
791 if (Load
.C
.cmdsize
!= sizeof(MachO::version_min_command
))
792 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
793 CmdName
+ " has incorrect cmdsize");
794 if (*LoadCmd
!= nullptr)
795 return malformedError("more than one LC_VERSION_MIN_MACOSX, "
796 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
797 "LC_VERSION_MIN_WATCHOS command");
799 return Error::success();
802 static Error
checkNoteCommand(const MachOObjectFile
&Obj
,
803 const MachOObjectFile::LoadCommandInfo
&Load
,
804 uint32_t LoadCommandIndex
,
805 std::list
<MachOElement
> &Elements
) {
806 if (Load
.C
.cmdsize
!= sizeof(MachO::note_command
))
807 return malformedError("load command " + Twine(LoadCommandIndex
) +
808 " LC_NOTE has incorrect cmdsize");
809 MachO::note_command Nt
= getStruct
<MachO::note_command
>(Obj
, Load
.Ptr
);
810 uint64_t FileSize
= Obj
.getData().size();
811 if (Nt
.offset
> FileSize
)
812 return malformedError("offset field of LC_NOTE command " +
813 Twine(LoadCommandIndex
) + " extends "
814 "past the end of the file");
815 uint64_t BigSize
= Nt
.offset
;
817 if (BigSize
> FileSize
)
818 return malformedError("size field plus offset field of LC_NOTE command " +
819 Twine(LoadCommandIndex
) + " extends past the end of "
821 if (Error Err
= checkOverlappingElement(Elements
, Nt
.offset
, Nt
.size
,
824 return Error::success();
828 parseBuildVersionCommand(const MachOObjectFile
&Obj
,
829 const MachOObjectFile::LoadCommandInfo
&Load
,
830 SmallVectorImpl
<const char*> &BuildTools
,
831 uint32_t LoadCommandIndex
) {
832 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 " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
840 auto Start
= Load
.Ptr
+ sizeof(MachO::build_version_command
);
841 BuildTools
.resize(BVC
.ntools
);
842 for (unsigned i
= 0; i
< BVC
.ntools
; ++i
)
843 BuildTools
[i
] = Start
+ i
* sizeof(MachO::build_tool_version
);
845 return Error::success();
848 static Error
checkRpathCommand(const MachOObjectFile
&Obj
,
849 const MachOObjectFile::LoadCommandInfo
&Load
,
850 uint32_t LoadCommandIndex
) {
851 if (Load
.C
.cmdsize
< sizeof(MachO::rpath_command
))
852 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 "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 // the end of the load command.
866 const char *P
= (const char *)Load
.Ptr
;
867 for (i
= R
.path
; i
< R
.cmdsize
; i
++)
871 return malformedError("load command " + Twine(LoadCommandIndex
) +
872 " LC_RPATH library name extends past the end of the "
874 return Error::success();
877 static Error
checkEncryptCommand(const MachOObjectFile
&Obj
,
878 const MachOObjectFile::LoadCommandInfo
&Load
,
879 uint32_t LoadCommandIndex
,
880 uint64_t cryptoff
, uint64_t cryptsize
,
881 const char **LoadCmd
, const char *CmdName
) {
882 if (*LoadCmd
!= nullptr)
883 return malformedError("more than one LC_ENCRYPTION_INFO and or "
884 "LC_ENCRYPTION_INFO_64 command");
885 uint64_t FileSize
= Obj
.getData().size();
886 if (cryptoff
> FileSize
)
887 return malformedError("cryptoff field of " + Twine(CmdName
) +
888 " command " + Twine(LoadCommandIndex
) + " extends "
889 "past the end of the file");
890 uint64_t BigSize
= cryptoff
;
891 BigSize
+= cryptsize
;
892 if (BigSize
> FileSize
)
893 return malformedError("cryptoff field plus cryptsize field of " +
894 Twine(CmdName
) + " command " +
895 Twine(LoadCommandIndex
) + " extends past the end of "
898 return Error::success();
901 static Error
checkLinkerOptCommand(const MachOObjectFile
&Obj
,
902 const MachOObjectFile::LoadCommandInfo
&Load
,
903 uint32_t LoadCommandIndex
) {
904 if (Load
.C
.cmdsize
< sizeof(MachO::linker_option_command
))
905 return malformedError("load command " + Twine(LoadCommandIndex
) +
906 " LC_LINKER_OPTION cmdsize too small");
907 MachO::linker_option_command L
=
908 getStruct
<MachO::linker_option_command
>(Obj
, Load
.Ptr
);
909 // Make sure the count of strings is correct.
910 const char *string
= (const char *)Load
.Ptr
+
911 sizeof(struct MachO::linker_option_command
);
912 uint32_t left
= L
.cmdsize
- sizeof(struct MachO::linker_option_command
);
915 while (*string
== '\0' && left
> 0) {
921 uint32_t NullPos
= StringRef(string
, left
).find('\0');
922 uint32_t len
= std::min(NullPos
, left
) + 1;
928 return malformedError("load command " + Twine(LoadCommandIndex
) +
929 " LC_LINKER_OPTION string count " + Twine(L
.count
) +
930 " does not match number of strings");
931 return Error::success();
934 static Error
checkSubCommand(const MachOObjectFile
&Obj
,
935 const MachOObjectFile::LoadCommandInfo
&Load
,
936 uint32_t LoadCommandIndex
, const char *CmdName
,
937 size_t SizeOfCmd
, const char *CmdStructName
,
938 uint32_t PathOffset
, const char *PathFieldName
) {
939 if (PathOffset
< SizeOfCmd
)
940 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
941 CmdName
+ " " + PathFieldName
+ ".offset field too "
942 "small, not past the end of the " + CmdStructName
);
943 if (PathOffset
>= Load
.C
.cmdsize
)
944 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
945 CmdName
+ " " + PathFieldName
+ ".offset field "
946 "extends past the end of the load command");
947 // Make sure there is a null between the starting offset of the path and
948 // the end of the load command.
950 const char *P
= (const char *)Load
.Ptr
;
951 for (i
= PathOffset
; i
< Load
.C
.cmdsize
; i
++)
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 return Error::success();
961 static Error
checkThreadCommand(const MachOObjectFile
&Obj
,
962 const MachOObjectFile::LoadCommandInfo
&Load
,
963 uint32_t LoadCommandIndex
,
964 const char *CmdName
) {
965 if (Load
.C
.cmdsize
< sizeof(MachO::thread_command
))
966 return malformedError("load command " + Twine(LoadCommandIndex
) +
967 CmdName
+ " cmdsize too small");
968 MachO::thread_command T
=
969 getStruct
<MachO::thread_command
>(Obj
, Load
.Ptr
);
970 const char *state
= Load
.Ptr
+ sizeof(MachO::thread_command
);
971 const char *end
= Load
.Ptr
+ T
.cmdsize
;
972 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 "
980 memcpy(&flavor
, state
, sizeof(uint32_t));
981 if (Obj
.isLittleEndian() != sys::IsLittleEndianHost
)
982 sys::swapByteOrder(flavor
);
983 state
+= sizeof(uint32_t);
985 if(state
+ sizeof(uint32_t) > end
)
986 return malformedError("load command " + Twine(LoadCommandIndex
) +
987 " count in " + CmdName
+ " extends past end of "
990 memcpy(&count
, state
, sizeof(uint32_t));
991 if (Obj
.isLittleEndian() != sys::IsLittleEndianHost
)
992 sys::swapByteOrder(count
);
993 state
+= sizeof(uint32_t);
995 if (cputype
== MachO::CPU_TYPE_I386
) {
996 if (flavor
== MachO::x86_THREAD_STATE32
) {
997 if (count
!= MachO::x86_THREAD_STATE32_COUNT
)
998 return malformedError("load command " + Twine(LoadCommandIndex
) +
999 " count not x86_THREAD_STATE32_COUNT for "
1000 "flavor number " + Twine(nflavor
) + " which is "
1001 "a x86_THREAD_STATE32 flavor in " + CmdName
+
1003 if (state
+ sizeof(MachO::x86_thread_state32_t
) > end
)
1004 return malformedError("load command " + Twine(LoadCommandIndex
) +
1005 " x86_THREAD_STATE32 extends past end of "
1006 "command in " + CmdName
+ " command");
1007 state
+= sizeof(MachO::x86_thread_state32_t
);
1009 return malformedError("load command " + Twine(LoadCommandIndex
) +
1010 " unknown flavor (" + Twine(flavor
) + ") for "
1011 "flavor number " + Twine(nflavor
) + " in " +
1012 CmdName
+ " command");
1014 } else if (cputype
== MachO::CPU_TYPE_X86_64
) {
1015 if (flavor
== MachO::x86_THREAD_STATE
) {
1016 if (count
!= MachO::x86_THREAD_STATE_COUNT
)
1017 return malformedError("load command " + Twine(LoadCommandIndex
) +
1018 " count not x86_THREAD_STATE_COUNT for "
1019 "flavor number " + Twine(nflavor
) + " which is "
1020 "a x86_THREAD_STATE flavor in " + CmdName
+
1022 if (state
+ sizeof(MachO::x86_thread_state_t
) > end
)
1023 return malformedError("load command " + Twine(LoadCommandIndex
) +
1024 " x86_THREAD_STATE extends past end of "
1025 "command in " + CmdName
+ " command");
1026 state
+= sizeof(MachO::x86_thread_state_t
);
1027 } else if (flavor
== MachO::x86_FLOAT_STATE
) {
1028 if (count
!= MachO::x86_FLOAT_STATE_COUNT
)
1029 return malformedError("load command " + Twine(LoadCommandIndex
) +
1030 " count not x86_FLOAT_STATE_COUNT for "
1031 "flavor number " + Twine(nflavor
) + " which is "
1032 "a x86_FLOAT_STATE flavor in " + CmdName
+
1034 if (state
+ sizeof(MachO::x86_float_state_t
) > end
)
1035 return malformedError("load command " + Twine(LoadCommandIndex
) +
1036 " x86_FLOAT_STATE extends past end of "
1037 "command in " + CmdName
+ " command");
1038 state
+= sizeof(MachO::x86_float_state_t
);
1039 } else if (flavor
== MachO::x86_EXCEPTION_STATE
) {
1040 if (count
!= MachO::x86_EXCEPTION_STATE_COUNT
)
1041 return malformedError("load command " + Twine(LoadCommandIndex
) +
1042 " count not x86_EXCEPTION_STATE_COUNT for "
1043 "flavor number " + Twine(nflavor
) + " which is "
1044 "a x86_EXCEPTION_STATE flavor in " + CmdName
+
1046 if (state
+ sizeof(MachO::x86_exception_state_t
) > end
)
1047 return malformedError("load command " + Twine(LoadCommandIndex
) +
1048 " x86_EXCEPTION_STATE extends past end of "
1049 "command in " + CmdName
+ " command");
1050 state
+= sizeof(MachO::x86_exception_state_t
);
1051 } else if (flavor
== MachO::x86_THREAD_STATE64
) {
1052 if (count
!= MachO::x86_THREAD_STATE64_COUNT
)
1053 return malformedError("load command " + Twine(LoadCommandIndex
) +
1054 " count not x86_THREAD_STATE64_COUNT for "
1055 "flavor number " + Twine(nflavor
) + " which is "
1056 "a x86_THREAD_STATE64 flavor in " + CmdName
+
1058 if (state
+ sizeof(MachO::x86_thread_state64_t
) > end
)
1059 return malformedError("load command " + Twine(LoadCommandIndex
) +
1060 " x86_THREAD_STATE64 extends past end of "
1061 "command in " + CmdName
+ " command");
1062 state
+= sizeof(MachO::x86_thread_state64_t
);
1063 } else if (flavor
== MachO::x86_EXCEPTION_STATE64
) {
1064 if (count
!= MachO::x86_EXCEPTION_STATE64_COUNT
)
1065 return malformedError("load command " + Twine(LoadCommandIndex
) +
1066 " count not x86_EXCEPTION_STATE64_COUNT for "
1067 "flavor number " + Twine(nflavor
) + " which is "
1068 "a x86_EXCEPTION_STATE64 flavor in " + CmdName
+
1070 if (state
+ sizeof(MachO::x86_exception_state64_t
) > end
)
1071 return malformedError("load command " + Twine(LoadCommandIndex
) +
1072 " x86_EXCEPTION_STATE64 extends past end of "
1073 "command in " + CmdName
+ " command");
1074 state
+= sizeof(MachO::x86_exception_state64_t
);
1076 return malformedError("load command " + Twine(LoadCommandIndex
) +
1077 " unknown flavor (" + Twine(flavor
) + ") for "
1078 "flavor number " + Twine(nflavor
) + " in " +
1079 CmdName
+ " command");
1081 } else if (cputype
== MachO::CPU_TYPE_ARM
) {
1082 if (flavor
== MachO::ARM_THREAD_STATE
) {
1083 if (count
!= MachO::ARM_THREAD_STATE_COUNT
)
1084 return malformedError("load command " + Twine(LoadCommandIndex
) +
1085 " count not ARM_THREAD_STATE_COUNT for "
1086 "flavor number " + Twine(nflavor
) + " which is "
1087 "a ARM_THREAD_STATE flavor in " + CmdName
+
1089 if (state
+ sizeof(MachO::arm_thread_state32_t
) > end
)
1090 return malformedError("load command " + Twine(LoadCommandIndex
) +
1091 " ARM_THREAD_STATE extends past end of "
1092 "command in " + CmdName
+ " command");
1093 state
+= sizeof(MachO::arm_thread_state32_t
);
1095 return malformedError("load command " + Twine(LoadCommandIndex
) +
1096 " unknown flavor (" + Twine(flavor
) + ") for "
1097 "flavor number " + Twine(nflavor
) + " in " +
1098 CmdName
+ " command");
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 " count not ARM_THREAD_STATE64_COUNT for "
1105 "flavor number " + Twine(nflavor
) + " which is "
1106 "a ARM_THREAD_STATE64 flavor in " + CmdName
+
1108 if (state
+ sizeof(MachO::arm_thread_state64_t
) > end
)
1109 return malformedError("load command " + Twine(LoadCommandIndex
) +
1110 " ARM_THREAD_STATE64 extends past end of "
1111 "command in " + CmdName
+ " command");
1112 state
+= sizeof(MachO::arm_thread_state64_t
);
1114 return malformedError("load command " + Twine(LoadCommandIndex
) +
1115 " unknown flavor (" + Twine(flavor
) + ") for "
1116 "flavor number " + Twine(nflavor
) + " in " +
1117 CmdName
+ " command");
1119 } else if (cputype
== MachO::CPU_TYPE_POWERPC
) {
1120 if (flavor
== MachO::PPC_THREAD_STATE
) {
1121 if (count
!= MachO::PPC_THREAD_STATE_COUNT
)
1122 return malformedError("load command " + Twine(LoadCommandIndex
) +
1123 " count not PPC_THREAD_STATE_COUNT for "
1124 "flavor number " + Twine(nflavor
) + " which is "
1125 "a PPC_THREAD_STATE flavor in " + CmdName
+
1127 if (state
+ sizeof(MachO::ppc_thread_state32_t
) > end
)
1128 return malformedError("load command " + Twine(LoadCommandIndex
) +
1129 " PPC_THREAD_STATE extends past end of "
1130 "command in " + CmdName
+ " command");
1131 state
+= sizeof(MachO::ppc_thread_state32_t
);
1133 return malformedError("load command " + Twine(LoadCommandIndex
) +
1134 " unknown flavor (" + Twine(flavor
) + ") for "
1135 "flavor number " + Twine(nflavor
) + " in " +
1136 CmdName
+ " command");
1139 return malformedError("unknown cputype (" + Twine(cputype
) + ") load "
1140 "command " + Twine(LoadCommandIndex
) + " for " +
1141 CmdName
+ " command can't be checked");
1145 return Error::success();
1148 static Error
checkTwoLevelHintsCommand(const MachOObjectFile
&Obj
,
1149 const MachOObjectFile::LoadCommandInfo
1151 uint32_t LoadCommandIndex
,
1152 const char **LoadCmd
,
1153 std::list
<MachOElement
> &Elements
) {
1154 if (Load
.C
.cmdsize
!= sizeof(MachO::twolevel_hints_command
))
1155 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 getStruct
<MachO::twolevel_hints_command
>(Obj
, Load
.Ptr
);
1161 uint64_t FileSize
= Obj
.getData().size();
1162 if (Hints
.offset
> FileSize
)
1163 return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1164 Twine(LoadCommandIndex
) + " extends past the end of "
1166 uint64_t BigSize
= Hints
.nhints
;
1167 BigSize
*= sizeof(MachO::twolevel_hint
);
1168 BigSize
+= Hints
.offset
;
1169 if (BigSize
> FileSize
)
1170 return malformedError("offset field plus nhints times sizeof(struct "
1171 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1172 Twine(LoadCommandIndex
) + " extends past the end of "
1174 if (Error Err
= checkOverlappingElement(Elements
, Hints
.offset
, Hints
.nhints
*
1175 sizeof(MachO::twolevel_hint
),
1178 *LoadCmd
= Load
.Ptr
;
1179 return Error::success();
1182 // Returns true if the libObject code does not support the load command and its
1183 // 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 if (cmd
== MachO::LC_SYMSEG
||
1187 cmd
== MachO::LC_LOADFVMLIB
||
1188 cmd
== MachO::LC_IDFVMLIB
||
1189 cmd
== MachO::LC_IDENT
||
1190 cmd
== MachO::LC_FVMFILE
||
1191 cmd
== MachO::LC_PREPAGE
||
1192 cmd
== MachO::LC_PREBOUND_DYLIB
||
1193 cmd
== MachO::LC_TWOLEVEL_HINTS
||
1194 cmd
== MachO::LC_PREBIND_CKSUM
)
1199 Expected
<std::unique_ptr
<MachOObjectFile
>>
1200 MachOObjectFile::create(MemoryBufferRef Object
, bool IsLittleEndian
,
1201 bool Is64Bits
, uint32_t UniversalCputype
,
1202 uint32_t UniversalIndex
) {
1203 Error Err
= Error::success();
1204 std::unique_ptr
<MachOObjectFile
> Obj(
1205 new MachOObjectFile(std::move(Object
), IsLittleEndian
,
1206 Is64Bits
, Err
, UniversalCputype
,
1209 return std::move(Err
);
1210 return std::move(Obj
);
1213 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object
, bool IsLittleEndian
,
1214 bool Is64bits
, Error
&Err
,
1215 uint32_t UniversalCputype
,
1216 uint32_t UniversalIndex
)
1217 : ObjectFile(getMachOType(IsLittleEndian
, Is64bits
), Object
) {
1218 ErrorAsOutParameter
ErrAsOutParam(&Err
);
1219 uint64_t SizeOfHeaders
;
1222 parseHeader(*this, Header64
, Err
);
1223 SizeOfHeaders
= sizeof(MachO::mach_header_64
);
1224 cputype
= Header64
.cputype
;
1226 parseHeader(*this, Header
, Err
);
1227 SizeOfHeaders
= sizeof(MachO::mach_header
);
1228 cputype
= Header
.cputype
;
1232 SizeOfHeaders
+= getHeader().sizeofcmds
;
1233 if (getData().data() + SizeOfHeaders
> getData().end()) {
1234 Err
= malformedError("load commands extend past the end of the file");
1237 if (UniversalCputype
!= 0 && cputype
!= UniversalCputype
) {
1238 Err
= malformedError("universal header architecture: " +
1239 Twine(UniversalIndex
) + "'s cputype does not match "
1240 "object file's mach header");
1243 std::list
<MachOElement
> Elements
;
1244 Elements
.push_back({0, SizeOfHeaders
, "Mach-O headers"});
1246 uint32_t LoadCommandCount
= getHeader().ncmds
;
1247 LoadCommandInfo Load
;
1248 if (LoadCommandCount
!= 0) {
1249 if (auto LoadOrErr
= getFirstLoadCommandInfo(*this))
1252 Err
= LoadOrErr
.takeError();
1257 const char *DyldIdLoadCmd
= nullptr;
1258 const char *FuncStartsLoadCmd
= nullptr;
1259 const char *SplitInfoLoadCmd
= nullptr;
1260 const char *CodeSignDrsLoadCmd
= nullptr;
1261 const char *CodeSignLoadCmd
= nullptr;
1262 const char *VersLoadCmd
= nullptr;
1263 const char *SourceLoadCmd
= nullptr;
1264 const char *EntryPointLoadCmd
= nullptr;
1265 const char *EncryptLoadCmd
= nullptr;
1266 const char *RoutinesLoadCmd
= nullptr;
1267 const char *UnixThreadLoadCmd
= nullptr;
1268 const char *TwoLevelHintsLoadCmd
= nullptr;
1269 for (unsigned I
= 0; I
< LoadCommandCount
; ++I
) {
1271 if (Load
.C
.cmdsize
% 8 != 0) {
1272 // We have a hack here to allow 64-bit Mach-O core files to have
1273 // LC_THREAD commands that are only a multiple of 4 and not 8 to be
1274 // allowed since the macOS kernel produces them.
1275 if (getHeader().filetype
!= MachO::MH_CORE
||
1276 Load
.C
.cmd
!= MachO::LC_THREAD
|| Load
.C
.cmdsize
% 4) {
1277 Err
= malformedError("load command " + Twine(I
) + " cmdsize not a "
1283 if (Load
.C
.cmdsize
% 4 != 0) {
1284 Err
= malformedError("load command " + Twine(I
) + " cmdsize not a "
1289 LoadCommands
.push_back(Load
);
1290 if (Load
.C
.cmd
== MachO::LC_SYMTAB
) {
1291 if ((Err
= checkSymtabCommand(*this, Load
, I
, &SymtabLoadCmd
, Elements
)))
1293 } else if (Load
.C
.cmd
== MachO::LC_DYSYMTAB
) {
1294 if ((Err
= checkDysymtabCommand(*this, Load
, I
, &DysymtabLoadCmd
,
1297 } else if (Load
.C
.cmd
== MachO::LC_DATA_IN_CODE
) {
1298 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &DataInCodeLoadCmd
,
1299 "LC_DATA_IN_CODE", Elements
,
1300 "data in code info")))
1302 } else if (Load
.C
.cmd
== MachO::LC_LINKER_OPTIMIZATION_HINT
) {
1303 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &LinkOptHintsLoadCmd
,
1304 "LC_LINKER_OPTIMIZATION_HINT",
1305 Elements
, "linker optimization "
1308 } else if (Load
.C
.cmd
== MachO::LC_FUNCTION_STARTS
) {
1309 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &FuncStartsLoadCmd
,
1310 "LC_FUNCTION_STARTS", Elements
,
1311 "function starts data")))
1313 } else if (Load
.C
.cmd
== MachO::LC_SEGMENT_SPLIT_INFO
) {
1314 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &SplitInfoLoadCmd
,
1315 "LC_SEGMENT_SPLIT_INFO", Elements
,
1316 "split info data")))
1318 } else if (Load
.C
.cmd
== MachO::LC_DYLIB_CODE_SIGN_DRS
) {
1319 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &CodeSignDrsLoadCmd
,
1320 "LC_DYLIB_CODE_SIGN_DRS", Elements
,
1321 "code signing RDs data")))
1323 } else if (Load
.C
.cmd
== MachO::LC_CODE_SIGNATURE
) {
1324 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &CodeSignLoadCmd
,
1325 "LC_CODE_SIGNATURE", Elements
,
1326 "code signature data")))
1328 } else if (Load
.C
.cmd
== MachO::LC_DYLD_INFO
) {
1329 if ((Err
= checkDyldInfoCommand(*this, Load
, I
, &DyldInfoLoadCmd
,
1330 "LC_DYLD_INFO", Elements
)))
1332 } else if (Load
.C
.cmd
== MachO::LC_DYLD_INFO_ONLY
) {
1333 if ((Err
= checkDyldInfoCommand(*this, Load
, I
, &DyldInfoLoadCmd
,
1334 "LC_DYLD_INFO_ONLY", Elements
)))
1336 } else if (Load
.C
.cmd
== MachO::LC_UUID
) {
1337 if (Load
.C
.cmdsize
!= sizeof(MachO::uuid_command
)) {
1338 Err
= malformedError("LC_UUID command " + Twine(I
) + " has incorrect "
1343 Err
= malformedError("more than one LC_UUID command");
1346 UuidLoadCmd
= Load
.Ptr
;
1347 } else if (Load
.C
.cmd
== MachO::LC_SEGMENT_64
) {
1348 if ((Err
= parseSegmentLoadCommand
<MachO::segment_command_64
,
1350 *this, Load
, Sections
, HasPageZeroSegment
, I
,
1351 "LC_SEGMENT_64", SizeOfHeaders
, Elements
)))
1353 } else if (Load
.C
.cmd
== MachO::LC_SEGMENT
) {
1354 if ((Err
= parseSegmentLoadCommand
<MachO::segment_command
,
1356 *this, Load
, Sections
, HasPageZeroSegment
, I
,
1357 "LC_SEGMENT", SizeOfHeaders
, Elements
)))
1359 } else if (Load
.C
.cmd
== MachO::LC_ID_DYLIB
) {
1360 if ((Err
= checkDylibIdCommand(*this, Load
, I
, &DyldIdLoadCmd
)))
1362 } else if (Load
.C
.cmd
== MachO::LC_LOAD_DYLIB
) {
1363 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_LOAD_DYLIB")))
1365 Libraries
.push_back(Load
.Ptr
);
1366 } else if (Load
.C
.cmd
== MachO::LC_LOAD_WEAK_DYLIB
) {
1367 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_LOAD_WEAK_DYLIB")))
1369 Libraries
.push_back(Load
.Ptr
);
1370 } else if (Load
.C
.cmd
== MachO::LC_LAZY_LOAD_DYLIB
) {
1371 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_LAZY_LOAD_DYLIB")))
1373 Libraries
.push_back(Load
.Ptr
);
1374 } else if (Load
.C
.cmd
== MachO::LC_REEXPORT_DYLIB
) {
1375 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_REEXPORT_DYLIB")))
1377 Libraries
.push_back(Load
.Ptr
);
1378 } else if (Load
.C
.cmd
== MachO::LC_LOAD_UPWARD_DYLIB
) {
1379 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_LOAD_UPWARD_DYLIB")))
1381 Libraries
.push_back(Load
.Ptr
);
1382 } else if (Load
.C
.cmd
== MachO::LC_ID_DYLINKER
) {
1383 if ((Err
= checkDyldCommand(*this, Load
, I
, "LC_ID_DYLINKER")))
1385 } else if (Load
.C
.cmd
== MachO::LC_LOAD_DYLINKER
) {
1386 if ((Err
= checkDyldCommand(*this, Load
, I
, "LC_LOAD_DYLINKER")))
1388 } else if (Load
.C
.cmd
== MachO::LC_DYLD_ENVIRONMENT
) {
1389 if ((Err
= checkDyldCommand(*this, Load
, I
, "LC_DYLD_ENVIRONMENT")))
1391 } else if (Load
.C
.cmd
== MachO::LC_VERSION_MIN_MACOSX
) {
1392 if ((Err
= checkVersCommand(*this, Load
, I
, &VersLoadCmd
,
1393 "LC_VERSION_MIN_MACOSX")))
1395 } else if (Load
.C
.cmd
== MachO::LC_VERSION_MIN_IPHONEOS
) {
1396 if ((Err
= checkVersCommand(*this, Load
, I
, &VersLoadCmd
,
1397 "LC_VERSION_MIN_IPHONEOS")))
1399 } else if (Load
.C
.cmd
== MachO::LC_VERSION_MIN_TVOS
) {
1400 if ((Err
= checkVersCommand(*this, Load
, I
, &VersLoadCmd
,
1401 "LC_VERSION_MIN_TVOS")))
1403 } else if (Load
.C
.cmd
== MachO::LC_VERSION_MIN_WATCHOS
) {
1404 if ((Err
= checkVersCommand(*this, Load
, I
, &VersLoadCmd
,
1405 "LC_VERSION_MIN_WATCHOS")))
1407 } else if (Load
.C
.cmd
== MachO::LC_NOTE
) {
1408 if ((Err
= checkNoteCommand(*this, Load
, I
, Elements
)))
1410 } else if (Load
.C
.cmd
== MachO::LC_BUILD_VERSION
) {
1411 if ((Err
= parseBuildVersionCommand(*this, Load
, BuildTools
, I
)))
1413 } else if (Load
.C
.cmd
== MachO::LC_RPATH
) {
1414 if ((Err
= checkRpathCommand(*this, Load
, I
)))
1416 } 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 " has incorrect cmdsize");
1422 if (SourceLoadCmd
) {
1423 Err
= malformedError("more than one LC_SOURCE_VERSION command");
1426 SourceLoadCmd
= Load
.Ptr
;
1427 } else if (Load
.C
.cmd
== MachO::LC_MAIN
) {
1428 if (Load
.C
.cmdsize
!= sizeof(MachO::entry_point_command
)) {
1429 Err
= malformedError("LC_MAIN command " + Twine(I
) +
1430 " has incorrect cmdsize");
1433 if (EntryPointLoadCmd
) {
1434 Err
= malformedError("more than one LC_MAIN command");
1437 EntryPointLoadCmd
= Load
.Ptr
;
1438 } else if (Load
.C
.cmd
== MachO::LC_ENCRYPTION_INFO
) {
1439 if (Load
.C
.cmdsize
!= sizeof(MachO::encryption_info_command
)) {
1440 Err
= malformedError("LC_ENCRYPTION_INFO command " + Twine(I
) +
1441 " has incorrect cmdsize");
1444 MachO::encryption_info_command E
=
1445 getStruct
<MachO::encryption_info_command
>(*this, Load
.Ptr
);
1446 if ((Err
= checkEncryptCommand(*this, Load
, I
, E
.cryptoff
, E
.cryptsize
,
1447 &EncryptLoadCmd
, "LC_ENCRYPTION_INFO")))
1449 } else if (Load
.C
.cmd
== MachO::LC_ENCRYPTION_INFO_64
) {
1450 if (Load
.C
.cmdsize
!= sizeof(MachO::encryption_info_command_64
)) {
1451 Err
= malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I
) +
1452 " has incorrect cmdsize");
1455 MachO::encryption_info_command_64 E
=
1456 getStruct
<MachO::encryption_info_command_64
>(*this, Load
.Ptr
);
1457 if ((Err
= checkEncryptCommand(*this, Load
, I
, E
.cryptoff
, E
.cryptsize
,
1458 &EncryptLoadCmd
, "LC_ENCRYPTION_INFO_64")))
1460 } else if (Load
.C
.cmd
== MachO::LC_LINKER_OPTION
) {
1461 if ((Err
= checkLinkerOptCommand(*this, Load
, I
)))
1463 } else if (Load
.C
.cmd
== MachO::LC_SUB_FRAMEWORK
) {
1464 if (Load
.C
.cmdsize
< sizeof(MachO::sub_framework_command
)) {
1465 Err
= malformedError("load command " + Twine(I
) +
1466 " LC_SUB_FRAMEWORK cmdsize too small");
1469 MachO::sub_framework_command S
=
1470 getStruct
<MachO::sub_framework_command
>(*this, Load
.Ptr
);
1471 if ((Err
= checkSubCommand(*this, Load
, I
, "LC_SUB_FRAMEWORK",
1472 sizeof(MachO::sub_framework_command
),
1473 "sub_framework_command", S
.umbrella
,
1476 } 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");
1482 MachO::sub_umbrella_command S
=
1483 getStruct
<MachO::sub_umbrella_command
>(*this, Load
.Ptr
);
1484 if ((Err
= checkSubCommand(*this, Load
, I
, "LC_SUB_UMBRELLA",
1485 sizeof(MachO::sub_umbrella_command
),
1486 "sub_umbrella_command", S
.sub_umbrella
,
1489 } else if (Load
.C
.cmd
== MachO::LC_SUB_LIBRARY
) {
1490 if (Load
.C
.cmdsize
< sizeof(MachO::sub_library_command
)) {
1491 Err
= malformedError("load command " + Twine(I
) +
1492 " LC_SUB_LIBRARY cmdsize too small");
1495 MachO::sub_library_command S
=
1496 getStruct
<MachO::sub_library_command
>(*this, Load
.Ptr
);
1497 if ((Err
= checkSubCommand(*this, Load
, I
, "LC_SUB_LIBRARY",
1498 sizeof(MachO::sub_library_command
),
1499 "sub_library_command", S
.sub_library
,
1502 } 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");
1508 MachO::sub_client_command S
=
1509 getStruct
<MachO::sub_client_command
>(*this, Load
.Ptr
);
1510 if ((Err
= checkSubCommand(*this, Load
, I
, "LC_SUB_CLIENT",
1511 sizeof(MachO::sub_client_command
),
1512 "sub_client_command", S
.client
, "client")))
1514 } else if (Load
.C
.cmd
== MachO::LC_ROUTINES
) {
1515 if (Load
.C
.cmdsize
!= sizeof(MachO::routines_command
)) {
1516 Err
= malformedError("LC_ROUTINES command " + Twine(I
) +
1517 " has incorrect cmdsize");
1520 if (RoutinesLoadCmd
) {
1521 Err
= malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1525 RoutinesLoadCmd
= Load
.Ptr
;
1526 } 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");
1532 if (RoutinesLoadCmd
) {
1533 Err
= malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1537 RoutinesLoadCmd
= Load
.Ptr
;
1538 } else if (Load
.C
.cmd
== MachO::LC_UNIXTHREAD
) {
1539 if ((Err
= checkThreadCommand(*this, Load
, I
, "LC_UNIXTHREAD")))
1541 if (UnixThreadLoadCmd
) {
1542 Err
= malformedError("more than one LC_UNIXTHREAD command");
1545 UnixThreadLoadCmd
= Load
.Ptr
;
1546 } else if (Load
.C
.cmd
== MachO::LC_THREAD
) {
1547 if ((Err
= checkThreadCommand(*this, Load
, I
, "LC_THREAD")))
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 &TwoLevelHintsLoadCmd
, Elements
)))
1554 } else if (isLoadCommandObsolete(Load
.C
.cmd
)) {
1555 Err
= malformedError("load command " + Twine(I
) + " for cmd value of: " +
1556 Twine(Load
.C
.cmd
) + " is obsolete and not "
1560 // 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 // as an option for some uses like lldb.
1563 if (I
< LoadCommandCount
- 1) {
1564 if (auto LoadOrErr
= getNextLoadCommandInfo(*this, I
, Load
))
1567 Err
= LoadOrErr
.takeError();
1572 if (!SymtabLoadCmd
) {
1573 if (DysymtabLoadCmd
) {
1574 Err
= malformedError("contains LC_DYSYMTAB load command without a "
1575 "LC_SYMTAB load command");
1578 } else if (DysymtabLoadCmd
) {
1579 MachO::symtab_command Symtab
=
1580 getStruct
<MachO::symtab_command
>(*this, SymtabLoadCmd
);
1581 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");
1588 uint64_t BigSize
= Dysymtab
.ilocalsym
;
1589 BigSize
+= Dysymtab
.nlocalsym
;
1590 if (Dysymtab
.nlocalsym
!= 0 && BigSize
> Symtab
.nsyms
) {
1591 Err
= malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
1592 "command extends past the end of the symbol table");
1595 if (Dysymtab
.nextdefsym
!= 0 && Dysymtab
.iextdefsym
> Symtab
.nsyms
) {
1596 Err
= malformedError("iextdefsym in LC_DYSYMTAB load command "
1597 "extends past the end of the symbol table");
1600 BigSize
= Dysymtab
.iextdefsym
;
1601 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 "
1608 if (Dysymtab
.nundefsym
!= 0 && Dysymtab
.iundefsym
> Symtab
.nsyms
) {
1609 Err
= malformedError("iundefsym in LC_DYSYMTAB load command "
1610 "extends past the end of the symbol table");
1613 BigSize
= Dysymtab
.iundefsym
;
1614 BigSize
+= Dysymtab
.nundefsym
;
1615 if (Dysymtab
.nundefsym
!= 0 && BigSize
> Symtab
.nsyms
) {
1616 Err
= malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
1617 " command extends past the end of the symbol table");
1621 if ((getHeader().filetype
== MachO::MH_DYLIB
||
1622 getHeader().filetype
== MachO::MH_DYLIB_STUB
) &&
1623 DyldIdLoadCmd
== nullptr) {
1624 Err
= malformedError("no LC_ID_DYLIB load command in dynamic library "
1628 assert(LoadCommands
.size() == LoadCommandCount
);
1630 Err
= Error::success();
1633 Error
MachOObjectFile::checkSymbolTable() const {
1636 MachO::mach_header_64 H_64
= MachOObjectFile::getHeader64();
1639 MachO::mach_header H
= MachOObjectFile::getHeader();
1646 uint64_t NValue
= 0;
1647 uint32_t SymbolIndex
= 0;
1648 MachO::symtab_command S
= getSymtabLoadCommand();
1649 for (const SymbolRef
&Symbol
: symbols()) {
1650 DataRefImpl SymDRI
= Symbol
.getRawDataRefImpl();
1652 MachO::nlist_64 STE_64
= getSymbol64TableEntry(SymDRI
);
1653 NType
= STE_64
.n_type
;
1654 NSect
= STE_64
.n_sect
;
1655 NDesc
= STE_64
.n_desc
;
1656 NStrx
= STE_64
.n_strx
;
1657 NValue
= STE_64
.n_value
;
1659 MachO::nlist STE
= getSymbolTableEntry(SymDRI
);
1665 NValue
= STE
.n_value
;
1667 if ((NType
& MachO::N_STAB
) == 0 &&
1668 (NType
& MachO::N_TYPE
) == MachO::N_SECT
) {
1669 if (NSect
== 0 || NSect
> Sections
.size())
1670 return malformedError("bad section index: " + Twine((int)NSect
) +
1671 " for symbol at index " + Twine(SymbolIndex
));
1673 if ((NType
& MachO::N_STAB
) == 0 &&
1674 (NType
& MachO::N_TYPE
) == MachO::N_INDR
) {
1675 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 "index " + Twine(SymbolIndex
));
1680 if ((Flags
& MachO::MH_TWOLEVEL
) == MachO::MH_TWOLEVEL
&&
1681 (((NType
& MachO::N_TYPE
) == MachO::N_UNDF
&& NValue
== 0) ||
1682 (NType
& MachO::N_TYPE
) == MachO::N_PBUD
)) {
1683 uint32_t LibraryOrdinal
= MachO::GET_LIBRARY_ORDINAL(NDesc
);
1684 if (LibraryOrdinal
!= 0 &&
1685 LibraryOrdinal
!= MachO::EXECUTABLE_ORDINAL
&&
1686 LibraryOrdinal
!= MachO::DYNAMIC_LOOKUP_ORDINAL
&&
1687 LibraryOrdinal
- 1 >= Libraries
.size() ) {
1688 return malformedError("bad library ordinal: " + Twine(LibraryOrdinal
) +
1689 " for symbol at index " + Twine(SymbolIndex
));
1692 if (NStrx
>= S
.strsize
)
1693 return malformedError("bad string table index: " + Twine((int)NStrx
) +
1694 " past the end of string table, for symbol at "
1695 "index " + Twine(SymbolIndex
));
1698 return Error::success();
1701 void MachOObjectFile::moveSymbolNext(DataRefImpl
&Symb
) const {
1702 unsigned SymbolTableEntrySize
= is64Bit() ?
1703 sizeof(MachO::nlist_64
) :
1704 sizeof(MachO::nlist
);
1705 Symb
.p
+= SymbolTableEntrySize
;
1708 Expected
<StringRef
> MachOObjectFile::getSymbolName(DataRefImpl Symb
) const {
1709 StringRef StringTable
= getStringTableData();
1710 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 // particular symbol table entry.
1715 const char *Start
= &StringTable
.data()[Entry
.n_strx
];
1716 if (Start
< getData().begin() || Start
>= getData().end()) {
1717 return malformedError("bad string index: " + Twine(Entry
.n_strx
) +
1718 " for symbol at index " + Twine(getSymbolIndex(Symb
)));
1720 return StringRef(Start
);
1723 unsigned MachOObjectFile::getSectionType(SectionRef Sec
) const {
1724 DataRefImpl DRI
= Sec
.getRawDataRefImpl();
1725 uint32_t Flags
= getSectionFlags(*this, DRI
);
1726 return Flags
& MachO::SECTION_TYPE
;
1729 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym
) const {
1731 MachO::nlist_64 Entry
= getSymbol64TableEntry(Sym
);
1732 return Entry
.n_value
;
1734 MachO::nlist Entry
= getSymbolTableEntry(Sym
);
1735 return Entry
.n_value
;
1738 // getIndirectName() returns the name of the alias'ed symbol who's string table
1739 // index is in the n_value field.
1740 std::error_code
MachOObjectFile::getIndirectName(DataRefImpl Symb
,
1741 StringRef
&Res
) const {
1742 StringRef StringTable
= getStringTableData();
1743 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, Symb
);
1744 if ((Entry
.n_type
& MachO::N_TYPE
) != MachO::N_INDR
)
1745 return object_error::parse_failed
;
1746 uint64_t NValue
= getNValue(Symb
);
1747 if (NValue
>= StringTable
.size())
1748 return object_error::parse_failed
;
1749 const char *Start
= &StringTable
.data()[NValue
];
1750 Res
= StringRef(Start
);
1751 return std::error_code();
1754 uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym
) const {
1755 return getNValue(Sym
);
1758 Expected
<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym
) const {
1759 return getSymbolValue(Sym
);
1762 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI
) const {
1763 uint32_t flags
= getSymbolFlags(DRI
);
1764 if (flags
& SymbolRef::SF_Common
) {
1765 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, DRI
);
1766 return 1 << MachO::GET_COMM_ALIGN(Entry
.n_desc
);
1771 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI
) const {
1772 return getNValue(DRI
);
1775 Expected
<SymbolRef::Type
>
1776 MachOObjectFile::getSymbolType(DataRefImpl Symb
) const {
1777 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, Symb
);
1778 uint8_t n_type
= Entry
.n_type
;
1780 // If this is a STAB debugging symbol, we can do nothing more.
1781 if (n_type
& MachO::N_STAB
)
1782 return SymbolRef::ST_Debug
;
1784 switch (n_type
& MachO::N_TYPE
) {
1785 case MachO::N_UNDF
:
1786 return SymbolRef::ST_Unknown
;
1787 case MachO::N_SECT
:
1788 Expected
<section_iterator
> SecOrError
= getSymbolSection(Symb
);
1790 return SecOrError
.takeError();
1791 section_iterator Sec
= *SecOrError
;
1792 if (Sec
->isData() || Sec
->isBSS())
1793 return SymbolRef::ST_Data
;
1794 return SymbolRef::ST_Function
;
1796 return SymbolRef::ST_Other
;
1799 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI
) const {
1800 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, DRI
);
1802 uint8_t MachOType
= Entry
.n_type
;
1803 uint16_t MachOFlags
= Entry
.n_desc
;
1805 uint32_t Result
= SymbolRef::SF_None
;
1807 if ((MachOType
& MachO::N_TYPE
) == MachO::N_INDR
)
1808 Result
|= SymbolRef::SF_Indirect
;
1810 if (MachOType
& MachO::N_STAB
)
1811 Result
|= SymbolRef::SF_FormatSpecific
;
1813 if (MachOType
& MachO::N_EXT
) {
1814 Result
|= SymbolRef::SF_Global
;
1815 if ((MachOType
& MachO::N_TYPE
) == MachO::N_UNDF
) {
1817 Result
|= SymbolRef::SF_Common
;
1819 Result
|= SymbolRef::SF_Undefined
;
1822 if (!(MachOType
& MachO::N_PEXT
))
1823 Result
|= SymbolRef::SF_Exported
;
1826 if (MachOFlags
& (MachO::N_WEAK_REF
| MachO::N_WEAK_DEF
))
1827 Result
|= SymbolRef::SF_Weak
;
1829 if (MachOFlags
& (MachO::N_ARM_THUMB_DEF
))
1830 Result
|= SymbolRef::SF_Thumb
;
1832 if ((MachOType
& MachO::N_TYPE
) == MachO::N_ABS
)
1833 Result
|= SymbolRef::SF_Absolute
;
1838 Expected
<section_iterator
>
1839 MachOObjectFile::getSymbolSection(DataRefImpl Symb
) const {
1840 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, Symb
);
1841 uint8_t index
= Entry
.n_sect
;
1844 return section_end();
1846 DRI
.d
.a
= index
- 1;
1847 if (DRI
.d
.a
>= Sections
.size()){
1848 return malformedError("bad section index: " + Twine((int)index
) +
1849 " for symbol at index " + Twine(getSymbolIndex(Symb
)));
1851 return section_iterator(SectionRef(DRI
, this));
1854 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym
) const {
1855 MachO::nlist_base Entry
=
1856 getSymbolTableEntryBase(*this, Sym
.getRawDataRefImpl());
1857 return Entry
.n_sect
- 1;
1860 void MachOObjectFile::moveSectionNext(DataRefImpl
&Sec
) const {
1864 std::error_code
MachOObjectFile::getSectionName(DataRefImpl Sec
,
1865 StringRef
&Result
) const {
1866 ArrayRef
<char> Raw
= getSectionRawName(Sec
);
1867 Result
= parseSegmentOrSectionName(Raw
.data());
1868 return std::error_code();
1871 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec
) const {
1873 return getSection64(Sec
).addr
;
1874 return getSection(Sec
).addr
;
1877 uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec
) const {
1881 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec
) const {
1882 // 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
;
1890 MachO::section_64 Sect
= getSection64(Sec
);
1891 SectOffset
= Sect
.offset
;
1892 SectSize
= Sect
.size
;
1893 SectType
= Sect
.flags
& MachO::SECTION_TYPE
;
1895 MachO::section Sect
= getSection(Sec
);
1896 SectOffset
= Sect
.offset
;
1897 SectSize
= Sect
.size
;
1898 SectType
= Sect
.flags
& MachO::SECTION_TYPE
;
1900 if (SectType
== MachO::S_ZEROFILL
|| SectType
== MachO::S_GB_ZEROFILL
)
1902 uint64_t FileSize
= getData().size();
1903 if (SectOffset
> FileSize
)
1905 if (FileSize
- SectOffset
< SectSize
)
1906 return FileSize
- SectOffset
;
1910 std::error_code
MachOObjectFile::getSectionContents(DataRefImpl Sec
,
1911 StringRef
&Res
) const {
1916 MachO::section_64 Sect
= getSection64(Sec
);
1917 Offset
= Sect
.offset
;
1920 MachO::section Sect
= getSection(Sec
);
1921 Offset
= Sect
.offset
;
1925 Res
= this->getData().substr(Offset
, Size
);
1926 return std::error_code();
1929 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec
) const {
1932 MachO::section_64 Sect
= getSection64(Sec
);
1935 MachO::section Sect
= getSection(Sec
);
1939 return uint64_t(1) << Align
;
1942 Expected
<SectionRef
> MachOObjectFile::getSection(unsigned SectionIndex
) const {
1943 if (SectionIndex
< 1 || SectionIndex
> Sections
.size())
1944 return malformedError("bad section index: " + Twine((int)SectionIndex
));
1947 DRI
.d
.a
= SectionIndex
- 1;
1948 return SectionRef(DRI
, this);
1951 Expected
<SectionRef
> MachOObjectFile::getSection(StringRef SectionName
) const {
1953 for (const SectionRef
&Section
: sections()) {
1954 if (std::error_code E
= Section
.getName(SecName
))
1955 return errorCodeToError(E
);
1956 if (SecName
== SectionName
) {
1960 return errorCodeToError(object_error::parse_failed
);
1963 bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec
) const {
1967 bool MachOObjectFile::isSectionText(DataRefImpl Sec
) const {
1968 uint32_t Flags
= getSectionFlags(*this, Sec
);
1969 return Flags
& MachO::S_ATTR_PURE_INSTRUCTIONS
;
1972 bool MachOObjectFile::isSectionData(DataRefImpl Sec
) const {
1973 uint32_t Flags
= getSectionFlags(*this, Sec
);
1974 unsigned SectionType
= Flags
& MachO::SECTION_TYPE
;
1975 return !(Flags
& MachO::S_ATTR_PURE_INSTRUCTIONS
) &&
1976 !(SectionType
== MachO::S_ZEROFILL
||
1977 SectionType
== MachO::S_GB_ZEROFILL
);
1980 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec
) const {
1981 uint32_t Flags
= getSectionFlags(*this, Sec
);
1982 unsigned SectionType
= Flags
& MachO::SECTION_TYPE
;
1983 return !(Flags
& MachO::S_ATTR_PURE_INSTRUCTIONS
) &&
1984 (SectionType
== MachO::S_ZEROFILL
||
1985 SectionType
== MachO::S_GB_ZEROFILL
);
1988 unsigned MachOObjectFile::getSectionID(SectionRef Sec
) const {
1989 return Sec
.getRawDataRefImpl().d
.a
;
1992 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec
) const {
1993 uint32_t Flags
= getSectionFlags(*this, Sec
);
1994 unsigned SectionType
= Flags
& MachO::SECTION_TYPE
;
1995 return SectionType
== MachO::S_ZEROFILL
||
1996 SectionType
== MachO::S_GB_ZEROFILL
;
1999 bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec
) const {
2000 StringRef SegmentName
= getSectionFinalSegmentName(Sec
);
2002 if (!getSectionName(Sec
, SectName
))
2003 return (SegmentName
== "__LLVM" && SectName
== "__bitcode");
2007 bool MachOObjectFile::isSectionStripped(DataRefImpl Sec
) const {
2009 return getSection64(Sec
).offset
== 0;
2010 return getSection(Sec
).offset
== 0;
2013 relocation_iterator
MachOObjectFile::section_rel_begin(DataRefImpl Sec
) const {
2017 return relocation_iterator(RelocationRef(Ret
, this));
2021 MachOObjectFile::section_rel_end(DataRefImpl Sec
) const {
2024 MachO::section_64 Sect
= getSection64(Sec
);
2027 MachO::section Sect
= getSection(Sec
);
2034 return relocation_iterator(RelocationRef(Ret
, this));
2037 relocation_iterator
MachOObjectFile::extrel_begin() const {
2039 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2040 Ret
.d
.a
= 0; // Would normally be a section index.
2041 Ret
.d
.b
= 0; // Index into the external relocations
2042 return relocation_iterator(RelocationRef(Ret
, this));
2045 relocation_iterator
MachOObjectFile::extrel_end() const {
2046 MachO::dysymtab_command DysymtabLoadCmd
= getDysymtabLoadCommand();
2048 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2049 Ret
.d
.a
= 0; // Would normally be a section index.
2050 Ret
.d
.b
= DysymtabLoadCmd
.nextrel
; // Index into the external relocations
2051 return relocation_iterator(RelocationRef(Ret
, this));
2054 relocation_iterator
MachOObjectFile::locrel_begin() const {
2056 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2057 Ret
.d
.a
= 1; // Would normally be a section index.
2058 Ret
.d
.b
= 0; // Index into the local relocations
2059 return relocation_iterator(RelocationRef(Ret
, this));
2062 relocation_iterator
MachOObjectFile::locrel_end() const {
2063 MachO::dysymtab_command DysymtabLoadCmd
= getDysymtabLoadCommand();
2065 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2066 Ret
.d
.a
= 1; // Would normally be a section index.
2067 Ret
.d
.b
= DysymtabLoadCmd
.nlocrel
; // Index into the local relocations
2068 return relocation_iterator(RelocationRef(Ret
, this));
2071 void MachOObjectFile::moveRelocationNext(DataRefImpl
&Rel
) const {
2075 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel
) const {
2076 assert((getHeader().filetype
== MachO::MH_OBJECT
||
2077 getHeader().filetype
== MachO::MH_KEXT_BUNDLE
) &&
2078 "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
2079 MachO::any_relocation_info RE
= getRelocation(Rel
);
2080 return getAnyRelocationAddress(RE
);
2084 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel
) const {
2085 MachO::any_relocation_info RE
= getRelocation(Rel
);
2086 if (isRelocationScattered(RE
))
2087 return symbol_end();
2089 uint32_t SymbolIdx
= getPlainRelocationSymbolNum(RE
);
2090 bool isExtern
= getPlainRelocationExternal(RE
);
2092 return symbol_end();
2094 MachO::symtab_command S
= getSymtabLoadCommand();
2095 unsigned SymbolTableEntrySize
= is64Bit() ?
2096 sizeof(MachO::nlist_64
) :
2097 sizeof(MachO::nlist
);
2098 uint64_t Offset
= S
.symoff
+ SymbolIdx
* SymbolTableEntrySize
;
2100 Sym
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Offset
));
2101 return symbol_iterator(SymbolRef(Sym
, this));
2105 MachOObjectFile::getRelocationSection(DataRefImpl Rel
) const {
2106 return section_iterator(getAnyRelocationSection(getRelocation(Rel
)));
2109 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel
) const {
2110 MachO::any_relocation_info RE
= getRelocation(Rel
);
2111 return getAnyRelocationType(RE
);
2114 void MachOObjectFile::getRelocationTypeName(
2115 DataRefImpl Rel
, SmallVectorImpl
<char> &Result
) const {
2117 uint64_t RType
= getRelocationType(Rel
);
2119 unsigned Arch
= this->getArch();
2123 static const char *const Table
[] = {
2124 "GENERIC_RELOC_VANILLA",
2125 "GENERIC_RELOC_PAIR",
2126 "GENERIC_RELOC_SECTDIFF",
2127 "GENERIC_RELOC_PB_LA_PTR",
2128 "GENERIC_RELOC_LOCAL_SECTDIFF",
2129 "GENERIC_RELOC_TLV" };
2137 case Triple::x86_64
: {
2138 static const char *const Table
[] = {
2139 "X86_64_RELOC_UNSIGNED",
2140 "X86_64_RELOC_SIGNED",
2141 "X86_64_RELOC_BRANCH",
2142 "X86_64_RELOC_GOT_LOAD",
2144 "X86_64_RELOC_SUBTRACTOR",
2145 "X86_64_RELOC_SIGNED_1",
2146 "X86_64_RELOC_SIGNED_2",
2147 "X86_64_RELOC_SIGNED_4",
2148 "X86_64_RELOC_TLV" };
2157 static const char *const Table
[] = {
2158 "ARM_RELOC_VANILLA",
2160 "ARM_RELOC_SECTDIFF",
2161 "ARM_RELOC_LOCAL_SECTDIFF",
2162 "ARM_RELOC_PB_LA_PTR",
2164 "ARM_THUMB_RELOC_BR22",
2165 "ARM_THUMB_32BIT_BRANCH",
2167 "ARM_RELOC_HALF_SECTDIFF" };
2175 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 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
2181 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
2182 "ARM64_RELOC_ADDEND"
2185 if (RType
>= array_lengthof(Table
))
2192 static const char *const Table
[] = {
2193 "PPC_RELOC_VANILLA",
2201 "PPC_RELOC_SECTDIFF",
2202 "PPC_RELOC_PB_LA_PTR",
2203 "PPC_RELOC_HI16_SECTDIFF",
2204 "PPC_RELOC_LO16_SECTDIFF",
2205 "PPC_RELOC_HA16_SECTDIFF",
2207 "PPC_RELOC_LO14_SECTDIFF",
2208 "PPC_RELOC_LOCAL_SECTDIFF" };
2216 case Triple::UnknownArch
:
2220 Result
.append(res
.begin(), res
.end());
2223 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel
) const {
2224 MachO::any_relocation_info RE
= getRelocation(Rel
);
2225 return getAnyRelocationLength(RE
);
2229 // guessLibraryShortName() is passed a name of a dynamic library and returns a
2230 // guess on what the short name is. Then name is returned as a substring of the
2231 // StringRef Name passed in. The name of the dynamic library is recognized as
2232 // a framework if it has one of the two following forms:
2233 // Foo.framework/Versions/A/Foo
2234 // Foo.framework/Foo
2235 // Where A and Foo can be any string. And may contain a trailing suffix
2236 // starting with an underbar. If the Name is recognized as a framework then
2237 // 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 // else it is set to a NULL StringRef.
2241 // The Name of the dynamic library is recognized as a library name if it has
2242 // one of the two following forms:
2245 // The library may have a suffix trailing the name Foo of the form:
2246 // libFoo_profile.A.dylib
2247 // libFoo_profile.dylib
2249 // The Name of the dynamic library is also recognized as a library name if it
2250 // has the following form:
2253 // If the Name of the dynamic library is none of the forms above then a NULL
2254 // StringRef is returned.
2256 StringRef
MachOObjectFile::guessLibraryShortName(StringRef Name
,
2258 StringRef
&Suffix
) {
2259 StringRef Foo
, F
, DotFramework
, V
, Dylib
, Lib
, Dot
, Qtx
;
2260 size_t a
, b
, c
, d
, Idx
;
2262 isFramework
= false;
2263 Suffix
= StringRef();
2265 // Pull off the last component and make Foo point to it
2266 a
= Name
.rfind('/');
2267 if (a
== Name
.npos
|| a
== 0)
2269 Foo
= Name
.slice(a
+1, Name
.npos
);
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
);
2278 // First look for the form Foo.framework/Foo
2279 b
= Name
.rfind('/', a
);
2284 F
= Name
.slice(Idx
, Idx
+ Foo
.size());
2285 DotFramework
= Name
.slice(Idx
+ Foo
.size(),
2286 Idx
+ Foo
.size() + sizeof(".framework/")-1);
2287 if (F
== Foo
&& DotFramework
== ".framework/") {
2292 // Next look for the form Foo.framework/Versions/A/Foo
2295 c
= Name
.rfind('/', b
);
2296 if (c
== Name
.npos
|| c
== 0)
2298 V
= Name
.slice(c
+1, Name
.npos
);
2299 if (!V
.startswith("Versions/"))
2301 d
= Name
.rfind('/', c
);
2306 F
= Name
.slice(Idx
, Idx
+ Foo
.size());
2307 DotFramework
= Name
.slice(Idx
+ Foo
.size(),
2308 Idx
+ Foo
.size() + sizeof(".framework/")-1);
2309 if (F
== Foo
&& DotFramework
== ".framework/") {
2315 // pull off the suffix after the "." and make a point to it
2316 a
= Name
.rfind('.');
2317 if (a
== Name
.npos
|| a
== 0)
2319 Dylib
= Name
.slice(a
, Name
.npos
);
2320 if (Dylib
!= ".dylib")
2323 // First pull off the version letter for the form Foo.A.dylib if any.
2325 Dot
= Name
.slice(a
-2, a
-1);
2330 b
= Name
.rfind('/', a
);
2335 // ignore any suffix after an underbar like Foo_profile.A.dylib
2336 Idx
= Name
.find('_', b
);
2337 if (Idx
!= Name
.npos
&& Idx
!= b
) {
2338 Lib
= Name
.slice(b
, Idx
);
2339 Suffix
= Name
.slice(Idx
, a
);
2342 Lib
= Name
.slice(b
, a
);
2343 // 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);
2348 Lib
= Lib
.slice(0, Lib
.size()-2);
2353 Qtx
= Name
.slice(a
, Name
.npos
);
2356 b
= Name
.rfind('/', a
);
2358 Lib
= Name
.slice(0, a
);
2360 Lib
= Name
.slice(b
+1, a
);
2361 // There are library names of the form: QT.A.qtx so check for these.
2362 if (Lib
.size() >= 3) {
2363 Dot
= Lib
.slice(Lib
.size()-2, Lib
.size()-1);
2365 Lib
= Lib
.slice(0, Lib
.size()-2);
2370 // getLibraryShortNameByIndex() is used to get the short name of the library
2371 // 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 // It is passed the index (0 - based) of the library as translated from
2374 // GET_LIBRARY_ORDINAL (1 - based).
2375 std::error_code
MachOObjectFile::getLibraryShortNameByIndex(unsigned Index
,
2376 StringRef
&Res
) const {
2377 if (Index
>= Libraries
.size())
2378 return object_error::parse_failed
;
2380 // If the cache of LibrariesShortNames is not built up do that first for
2381 // all the Libraries.
2382 if (LibrariesShortNames
.size() == 0) {
2383 for (unsigned i
= 0; i
< Libraries
.size(); i
++) {
2384 MachO::dylib_command D
=
2385 getStruct
<MachO::dylib_command
>(*this, Libraries
[i
]);
2386 if (D
.dylib
.name
>= D
.cmdsize
)
2387 return object_error::parse_failed
;
2388 const char *P
= (const char *)(Libraries
[i
]) + D
.dylib
.name
;
2389 StringRef Name
= StringRef(P
);
2390 if (D
.dylib
.name
+Name
.size() >= D
.cmdsize
)
2391 return object_error::parse_failed
;
2394 StringRef shortName
= guessLibraryShortName(Name
, isFramework
, Suffix
);
2395 if (shortName
.empty())
2396 LibrariesShortNames
.push_back(Name
);
2398 LibrariesShortNames
.push_back(shortName
);
2402 Res
= LibrariesShortNames
[Index
];
2403 return std::error_code();
2406 uint32_t MachOObjectFile::getLibraryCount() const {
2407 return Libraries
.size();
2411 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel
) const {
2413 Sec
.d
.a
= Rel
->getRawDataRefImpl().d
.a
;
2414 return section_iterator(SectionRef(Sec
, this));
2417 basic_symbol_iterator
MachOObjectFile::symbol_begin() const {
2419 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2420 if (!SymtabLoadCmd
|| Symtab
.nsyms
== 0)
2421 return basic_symbol_iterator(SymbolRef(DRI
, this));
2423 return getSymbolByIndex(0);
2426 basic_symbol_iterator
MachOObjectFile::symbol_end() const {
2428 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2429 if (!SymtabLoadCmd
|| Symtab
.nsyms
== 0)
2430 return basic_symbol_iterator(SymbolRef(DRI
, this));
2432 unsigned SymbolTableEntrySize
= is64Bit() ?
2433 sizeof(MachO::nlist_64
) :
2434 sizeof(MachO::nlist
);
2435 unsigned Offset
= Symtab
.symoff
+
2436 Symtab
.nsyms
* SymbolTableEntrySize
;
2437 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Offset
));
2438 return basic_symbol_iterator(SymbolRef(DRI
, this));
2441 basic_symbol_iterator
MachOObjectFile::getSymbolByIndex(unsigned Index
) const {
2442 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2443 if (!SymtabLoadCmd
|| Index
>= Symtab
.nsyms
)
2444 report_fatal_error("Requested symbol index is out of range.");
2445 unsigned SymbolTableEntrySize
=
2446 is64Bit() ? sizeof(MachO::nlist_64
) : sizeof(MachO::nlist
);
2448 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Symtab
.symoff
));
2449 DRI
.p
+= Index
* SymbolTableEntrySize
;
2450 return basic_symbol_iterator(SymbolRef(DRI
, this));
2453 uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb
) const {
2454 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2456 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2457 unsigned SymbolTableEntrySize
=
2458 is64Bit() ? sizeof(MachO::nlist_64
) : sizeof(MachO::nlist
);
2459 DataRefImpl DRIstart
;
2460 DRIstart
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Symtab
.symoff
));
2461 uint64_t Index
= (Symb
.p
- DRIstart
.p
) / SymbolTableEntrySize
;
2465 section_iterator
MachOObjectFile::section_begin() const {
2467 return section_iterator(SectionRef(DRI
, this));
2470 section_iterator
MachOObjectFile::section_end() const {
2472 DRI
.d
.a
= Sections
.size();
2473 return section_iterator(SectionRef(DRI
, this));
2476 uint8_t MachOObjectFile::getBytesInAddress() const {
2477 return is64Bit() ? 8 : 4;
2480 StringRef
MachOObjectFile::getFileFormatName() const {
2481 unsigned CPUType
= getCPUType(*this);
2484 case MachO::CPU_TYPE_I386
:
2485 return "Mach-O 32-bit i386";
2486 case MachO::CPU_TYPE_ARM
:
2487 return "Mach-O arm";
2488 case MachO::CPU_TYPE_POWERPC
:
2489 return "Mach-O 32-bit ppc";
2491 return "Mach-O 32-bit unknown";
2496 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";
2503 return "Mach-O 64-bit unknown";
2507 Triple::ArchType
MachOObjectFile::getArch(uint32_t CPUType
) {
2509 case MachO::CPU_TYPE_I386
:
2511 case MachO::CPU_TYPE_X86_64
:
2512 return Triple::x86_64
;
2513 case MachO::CPU_TYPE_ARM
:
2515 case MachO::CPU_TYPE_ARM64
:
2516 return Triple::aarch64
;
2517 case MachO::CPU_TYPE_POWERPC
:
2519 case MachO::CPU_TYPE_POWERPC64
:
2520 return Triple::ppc64
;
2522 return Triple::UnknownArch
;
2526 Triple
MachOObjectFile::getArchTriple(uint32_t CPUType
, uint32_t CPUSubType
,
2527 const char **McpuDefault
,
2528 const char **ArchFlag
) {
2530 *McpuDefault
= nullptr;
2532 *ArchFlag
= nullptr;
2535 case MachO::CPU_TYPE_I386
:
2536 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2537 case MachO::CPU_SUBTYPE_I386_ALL
:
2540 return Triple("i386-apple-darwin");
2544 case MachO::CPU_TYPE_X86_64
:
2545 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2546 case MachO::CPU_SUBTYPE_X86_64_ALL
:
2548 *ArchFlag
= "x86_64";
2549 return Triple("x86_64-apple-darwin");
2550 case MachO::CPU_SUBTYPE_X86_64_H
:
2552 *ArchFlag
= "x86_64h";
2553 return Triple("x86_64h-apple-darwin");
2557 case MachO::CPU_TYPE_ARM
:
2558 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2559 case MachO::CPU_SUBTYPE_ARM_V4T
:
2561 *ArchFlag
= "armv4t";
2562 return Triple("armv4t-apple-darwin");
2563 case MachO::CPU_SUBTYPE_ARM_V5TEJ
:
2565 *ArchFlag
= "armv5e";
2566 return Triple("armv5e-apple-darwin");
2567 case MachO::CPU_SUBTYPE_ARM_XSCALE
:
2569 *ArchFlag
= "xscale";
2570 return Triple("xscale-apple-darwin");
2571 case MachO::CPU_SUBTYPE_ARM_V6
:
2573 *ArchFlag
= "armv6";
2574 return Triple("armv6-apple-darwin");
2575 case MachO::CPU_SUBTYPE_ARM_V6M
:
2577 *McpuDefault
= "cortex-m0";
2579 *ArchFlag
= "armv6m";
2580 return Triple("armv6m-apple-darwin");
2581 case MachO::CPU_SUBTYPE_ARM_V7
:
2583 *ArchFlag
= "armv7";
2584 return Triple("armv7-apple-darwin");
2585 case MachO::CPU_SUBTYPE_ARM_V7EM
:
2587 *McpuDefault
= "cortex-m4";
2589 *ArchFlag
= "armv7em";
2590 return Triple("thumbv7em-apple-darwin");
2591 case MachO::CPU_SUBTYPE_ARM_V7K
:
2593 *McpuDefault
= "cortex-a7";
2595 *ArchFlag
= "armv7k";
2596 return Triple("armv7k-apple-darwin");
2597 case MachO::CPU_SUBTYPE_ARM_V7M
:
2599 *McpuDefault
= "cortex-m3";
2601 *ArchFlag
= "armv7m";
2602 return Triple("thumbv7m-apple-darwin");
2603 case MachO::CPU_SUBTYPE_ARM_V7S
:
2605 *McpuDefault
= "cortex-a7";
2607 *ArchFlag
= "armv7s";
2608 return Triple("armv7s-apple-darwin");
2612 case MachO::CPU_TYPE_ARM64
:
2613 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2614 case MachO::CPU_SUBTYPE_ARM64_ALL
:
2616 *McpuDefault
= "cyclone";
2618 *ArchFlag
= "arm64";
2619 return Triple("arm64-apple-darwin");
2623 case MachO::CPU_TYPE_POWERPC
:
2624 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2625 case MachO::CPU_SUBTYPE_POWERPC_ALL
:
2628 return Triple("ppc-apple-darwin");
2632 case MachO::CPU_TYPE_POWERPC64
:
2633 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2634 case MachO::CPU_SUBTYPE_POWERPC_ALL
:
2636 *ArchFlag
= "ppc64";
2637 return Triple("ppc64-apple-darwin");
2646 Triple
MachOObjectFile::getHostArch() {
2647 return Triple(sys::getDefaultTargetTriple());
2650 bool MachOObjectFile::isValidArch(StringRef ArchFlag
) {
2651 return StringSwitch
<bool>(ArchFlag
)
2653 .Case("x86_64", true)
2654 .Case("x86_64h", true)
2655 .Case("armv4t", true)
2657 .Case("armv5e", true)
2658 .Case("armv6", true)
2659 .Case("armv6m", true)
2660 .Case("armv7", true)
2661 .Case("armv7em", true)
2662 .Case("armv7k", true)
2663 .Case("armv7m", true)
2664 .Case("armv7s", true)
2665 .Case("arm64", true)
2667 .Case("ppc64", true)
2671 Triple::ArchType
MachOObjectFile::getArch() const {
2672 return getArch(getCPUType(*this));
2675 Triple
MachOObjectFile::getArchTriple(const char **McpuDefault
) const {
2676 return getArchTriple(Header
.cputype
, Header
.cpusubtype
, McpuDefault
);
2679 relocation_iterator
MachOObjectFile::section_rel_begin(unsigned Index
) const {
2682 return section_rel_begin(DRI
);
2685 relocation_iterator
MachOObjectFile::section_rel_end(unsigned Index
) const {
2688 return section_rel_end(DRI
);
2691 dice_iterator
MachOObjectFile::begin_dices() const {
2693 if (!DataInCodeLoadCmd
)
2694 return dice_iterator(DiceRef(DRI
, this));
2696 MachO::linkedit_data_command DicLC
= getDataInCodeLoadCommand();
2697 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, DicLC
.dataoff
));
2698 return dice_iterator(DiceRef(DRI
, this));
2701 dice_iterator
MachOObjectFile::end_dices() const {
2703 if (!DataInCodeLoadCmd
)
2704 return dice_iterator(DiceRef(DRI
, this));
2706 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));
2712 ExportEntry::ExportEntry(Error
*E
, const MachOObjectFile
*O
,
2713 ArrayRef
<uint8_t> T
) : E(E
), O(O
), Trie(T
) {}
2715 void ExportEntry::moveToFirst() {
2716 ErrorAsOutParameter
ErrAsOutParam(E
);
2720 pushDownUntilBottom();
2723 void ExportEntry::moveToEnd() {
2728 bool ExportEntry::operator==(const ExportEntry
&Other
) const {
2729 // Common case, one at end, other iterating from begin.
2730 if (Done
|| Other
.Done
)
2731 return (Done
== Other
.Done
);
2732 // Not equal if different stack sizes.
2733 if (Stack
.size() != Other
.Stack
.size())
2735 // Not equal if different cumulative strings.
2736 if (!CumulativeString
.equals(Other
.CumulativeString
))
2738 // 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
)
2746 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr
, const char **error
) {
2748 uint64_t Result
= decodeULEB128(Ptr
, &Count
, Trie
.end(), error
);
2750 if (Ptr
> Trie
.end())
2755 StringRef
ExportEntry::name() const {
2756 return CumulativeString
;
2759 uint64_t ExportEntry::flags() const {
2760 return Stack
.back().Flags
;
2763 uint64_t ExportEntry::address() const {
2764 return Stack
.back().Address
;
2767 uint64_t ExportEntry::other() const {
2768 return Stack
.back().Other
;
2771 StringRef
ExportEntry::otherName() const {
2772 const char* ImportName
= Stack
.back().ImportName
;
2774 return StringRef(ImportName
);
2778 uint32_t ExportEntry::nodeOffset() const {
2779 return Stack
.back().Start
- Trie
.begin();
2782 ExportEntry::NodeState::NodeState(const uint8_t *Ptr
)
2783 : Start(Ptr
), Current(Ptr
) {}
2785 void ExportEntry::pushNode(uint64_t offset
) {
2786 ErrorAsOutParameter
ErrAsOutParam(E
);
2787 const uint8_t *Ptr
= Trie
.begin() + offset
;
2788 NodeState
State(Ptr
);
2790 uint64_t ExportInfoSize
= readULEB128(State
.Current
, &error
);
2792 *E
= malformedError("export info size " + Twine(error
) +
2793 " in export trie data at node: 0x" +
2794 Twine::utohexstr(offset
));
2798 State
.IsExportNode
= (ExportInfoSize
!= 0);
2799 const uint8_t* Children
= State
.Current
+ ExportInfoSize
;
2800 if (Children
> Trie
.end()) {
2801 *E
= malformedError(
2802 "export info size: 0x" + Twine::utohexstr(ExportInfoSize
) +
2803 " in export trie data at node: 0x" + Twine::utohexstr(offset
) +
2804 " too big and extends past end of trie data");
2808 if (State
.IsExportNode
) {
2809 const uint8_t *ExportStart
= State
.Current
;
2810 State
.Flags
= readULEB128(State
.Current
, &error
);
2812 *E
= malformedError("flags " + Twine(error
) +
2813 " in export trie data at node: 0x" +
2814 Twine::utohexstr(offset
));
2818 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 Kind
!= MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE
&&
2822 Kind
!= MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL
)) {
2823 *E
= malformedError(
2824 "unsupported exported symbol kind: " + Twine((int)Kind
) +
2825 " in flags: 0x" + Twine::utohexstr(State
.Flags
) +
2826 " in export trie data at node: 0x" + Twine::utohexstr(offset
));
2830 if (State
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_REEXPORT
) {
2832 State
.Other
= readULEB128(State
.Current
, &error
); // dylib ordinal
2834 *E
= malformedError("dylib ordinal of re-export " + Twine(error
) +
2835 " in export trie data at node: 0x" +
2836 Twine::utohexstr(offset
));
2841 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
));
2850 State
.ImportName
= reinterpret_cast<const char*>(State
.Current
);
2851 if (*State
.ImportName
== '\0') {
2854 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 "
2858 Twine::utohexstr(offset
) +
2859 " starts past end of trie data");
2863 while(*End
!= '\0' && End
< Trie
.end())
2866 *E
= malformedError("import name of re-export in export trie data at "
2868 Twine::utohexstr(offset
) +
2869 " extends past end of trie data");
2873 State
.Current
= End
+ 1;
2876 State
.Address
= readULEB128(State
.Current
, &error
);
2878 *E
= malformedError("address " + Twine(error
) +
2879 " in export trie data at node: 0x" +
2880 Twine::utohexstr(offset
));
2884 if (State
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
) {
2885 State
.Other
= readULEB128(State
.Current
, &error
);
2887 *E
= malformedError("resolver of stub and resolver " + Twine(error
) +
2888 " in export trie data at node: 0x" +
2889 Twine::utohexstr(offset
));
2895 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
));
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 "
2909 Twine::utohexstr(offset
) +
2910 " extends past end of trie data");
2914 State
.Current
= Children
+ 1;
2915 State
.NextChildIndex
= 0;
2916 State
.ParentStringLength
= CumulativeString
.size();
2917 Stack
.push_back(State
);
2920 void ExportEntry::pushDownUntilBottom() {
2921 ErrorAsOutParameter
ErrAsOutParam(E
);
2923 while (Stack
.back().NextChildIndex
< Stack
.back().ChildCount
) {
2924 NodeState
&Top
= Stack
.back();
2925 CumulativeString
.resize(Top
.ParentStringLength
);
2926 for (;*Top
.Current
!= 0 && Top
.Current
< Trie
.end(); Top
.Current
++) {
2927 char C
= *Top
.Current
;
2928 CumulativeString
.push_back(C
);
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");
2939 uint64_t childNodeIndex
= readULEB128(Top
.Current
, &error
);
2941 *E
= malformedError("child node offset " + Twine(error
) +
2942 " in export trie data at node: 0x" +
2943 Twine::utohexstr(Top
.Start
- Trie
.begin()));
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
));
2957 Top
.NextChildIndex
+= 1;
2958 pushNode(childNodeIndex
);
2962 if (!Stack
.back().IsExportNode
) {
2963 *E
= malformedError("node is not an export node in export trie data at "
2965 Twine::utohexstr(Stack
.back().Start
- Trie
.begin()));
2971 // 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 // 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
2977 // There is one "export" node for each exported symbol. But because some
2978 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
2979 // node may have child nodes too.
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 // else the trie is malformed). On the way down, each node is pushed on the
2984 // 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 assert(!Stack
.empty() && "ExportEntry::moveNext() with empty node stack");
2988 if (!Stack
.back().IsExportNode
) {
2989 *E
= malformedError("node is not an export node in export trie data at "
2991 Twine::utohexstr(Stack
.back().Start
- Trie
.begin()));
2997 while (!Stack
.empty()) {
2998 NodeState
&Top
= Stack
.back();
2999 if (Top
.NextChildIndex
< Top
.ChildCount
) {
3000 pushDownUntilBottom();
3001 // Now at the next export node.
3004 if (Top
.IsExportNode
) {
3005 // This node has no children but is itself an export node.
3006 CumulativeString
.resize(Top
.ParentStringLength
);
3015 iterator_range
<export_iterator
>
3016 MachOObjectFile::exports(Error
&E
, ArrayRef
<uint8_t> Trie
,
3017 const MachOObjectFile
*O
) {
3018 ExportEntry
Start(&E
, O
, Trie
);
3022 Start
.moveToFirst();
3024 ExportEntry
Finish(&E
, O
, Trie
);
3027 return make_range(export_iterator(Start
), export_iterator(Finish
));
3030 iterator_range
<export_iterator
> MachOObjectFile::exports(Error
&Err
) const {
3031 return exports(Err
, getDyldInfoExportsTrie(), this);
3034 MachORebaseEntry::MachORebaseEntry(Error
*E
, const MachOObjectFile
*O
,
3035 ArrayRef
<uint8_t> Bytes
, bool is64Bit
)
3036 : E(E
), O(O
), Opcodes(Bytes
), Ptr(Bytes
.begin()),
3037 PointerSize(is64Bit
? 8 : 4) {}
3039 void MachORebaseEntry::moveToFirst() {
3040 Ptr
= Opcodes
.begin();
3044 void MachORebaseEntry::moveToEnd() {
3045 Ptr
= Opcodes
.end();
3046 RemainingLoopCount
= 0;
3050 void MachORebaseEntry::moveNext() {
3051 ErrorAsOutParameter
ErrAsOutParam(E
);
3052 // If in the middle of some loop, move to next rebasing in loop.
3053 SegmentOffset
+= AdvanceAmount
;
3054 if (RemainingLoopCount
) {
3055 --RemainingLoopCount
;
3058 // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
3059 // pointer size. Therefore it is possible to reach the end without ever having
3060 // seen REBASE_OPCODE_DONE.
3061 if (Ptr
== Opcodes
.end()) {
3067 // Parse next opcode and set up next loop.
3068 const uint8_t *OpcodeStart
= Ptr
;
3069 uint8_t Byte
= *Ptr
++;
3070 uint8_t ImmValue
= Byte
& MachO::REBASE_IMMEDIATE_MASK
;
3071 uint8_t Opcode
= Byte
& MachO::REBASE_OPCODE_MASK
;
3072 uint32_t Count
, Skip
;
3073 const char *error
= nullptr;
3075 case MachO::REBASE_OPCODE_DONE
:
3079 DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n");
3081 case MachO::REBASE_OPCODE_SET_TYPE_IMM
:
3082 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 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3092 dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
3093 << "RebaseType=" << (int) RebaseType
<< "\n");
3095 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
:
3096 SegmentIndex
= ImmValue
;
3097 SegmentOffset
= readULEB128(&error
);
3099 *E
= malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3100 Twine(error
) + " for opcode at: 0x" +
3101 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3105 error
= O
->RebaseEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
,
3108 *E
= malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3109 Twine(error
) + " for opcode at: 0x" +
3110 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3116 dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3117 << "SegmentIndex=" << SegmentIndex
<< ", "
3118 << format("SegmentOffset=0x%06X", SegmentOffset
)
3121 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB
:
3122 SegmentOffset
+= readULEB128(&error
);
3124 *E
= malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3125 " for opcode at: 0x" +
3126 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3130 error
= O
->RebaseEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
,
3133 *E
= malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3134 " for opcode at: 0x" +
3135 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3139 DEBUG_WITH_TYPE("mach-o-rebase",
3140 dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
3141 << format("SegmentOffset=0x%06X",
3142 SegmentOffset
) << "\n");
3144 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED
:
3145 error
= O
->RebaseEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
,
3148 *E
= malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
3149 Twine(error
) + " for opcode at: 0x" +
3150 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3154 SegmentOffset
+= ImmValue
* PointerSize
;
3155 error
= O
->RebaseEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
,
3159 malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED "
3160 " (after adding immediate times the pointer size) " +
3161 Twine(error
) + " for opcode at: 0x" +
3162 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3166 DEBUG_WITH_TYPE("mach-o-rebase",
3167 dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
3168 << format("SegmentOffset=0x%06X",
3169 SegmentOffset
) << "\n");
3171 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES
:
3172 error
= O
->RebaseEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
,
3175 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
3176 Twine(error
) + " for opcode at: 0x" +
3177 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3181 AdvanceAmount
= PointerSize
;
3185 RemainingLoopCount
= ImmValue
- 1;
3187 RemainingLoopCount
= 0;
3188 error
= O
->RebaseEntryCheckCountAndSkip(Count
, Skip
, PointerSize
,
3189 SegmentIndex
, SegmentOffset
);
3191 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
3192 Twine(error
) + " for opcode at: 0x" +
3193 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3199 dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
3200 << format("SegmentOffset=0x%06X", SegmentOffset
)
3201 << ", AdvanceAmount=" << AdvanceAmount
3202 << ", RemainingLoopCount=" << RemainingLoopCount
3205 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES
:
3206 error
= O
->RebaseEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
,
3209 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3210 Twine(error
) + " for opcode at: 0x" +
3211 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3215 AdvanceAmount
= PointerSize
;
3217 Count
= readULEB128(&error
);
3219 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3220 Twine(error
) + " for opcode at: 0x" +
3221 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3226 RemainingLoopCount
= Count
- 1;
3228 RemainingLoopCount
= 0;
3229 error
= O
->RebaseEntryCheckCountAndSkip(Count
, Skip
, PointerSize
,
3230 SegmentIndex
, SegmentOffset
);
3232 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3233 Twine(error
) + " for opcode at: 0x" +
3234 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3240 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
3241 << format("SegmentOffset=0x%06X", SegmentOffset
)
3242 << ", AdvanceAmount=" << AdvanceAmount
3243 << ", RemainingLoopCount=" << RemainingLoopCount
3246 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB
:
3247 error
= O
->RebaseEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
,
3250 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3251 Twine(error
) + " for opcode at: 0x" +
3252 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3256 Skip
= readULEB128(&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()));
3264 AdvanceAmount
= Skip
+ PointerSize
;
3266 RemainingLoopCount
= 0;
3267 error
= O
->RebaseEntryCheckCountAndSkip(Count
, Skip
, PointerSize
,
3268 SegmentIndex
, SegmentOffset
);
3270 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3271 Twine(error
) + " for opcode at: 0x" +
3272 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3278 dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
3279 << format("SegmentOffset=0x%06X", SegmentOffset
)
3280 << ", AdvanceAmount=" << AdvanceAmount
3281 << ", RemainingLoopCount=" << RemainingLoopCount
3284 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB
:
3285 error
= O
->RebaseEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
,
3288 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3290 Twine(error
) + " for opcode at: 0x" +
3291 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3295 Count
= readULEB128(&error
);
3297 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3299 Twine(error
) + " for opcode at: 0x" +
3300 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3305 RemainingLoopCount
= Count
- 1;
3307 RemainingLoopCount
= 0;
3308 Skip
= readULEB128(&error
);
3310 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3312 Twine(error
) + " for opcode at: 0x" +
3313 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3317 AdvanceAmount
= Skip
+ PointerSize
;
3319 error
= O
->RebaseEntryCheckCountAndSkip(Count
, Skip
, PointerSize
,
3320 SegmentIndex
, SegmentOffset
);
3322 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3324 Twine(error
) + " for opcode at: 0x" +
3325 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3331 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
3332 << format("SegmentOffset=0x%06X", SegmentOffset
)
3333 << ", AdvanceAmount=" << AdvanceAmount
3334 << ", RemainingLoopCount=" << RemainingLoopCount
3338 *E
= malformedError("bad rebase info (bad opcode value 0x" +
3339 Twine::utohexstr(Opcode
) + " for opcode at: 0x" +
3340 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3347 uint64_t MachORebaseEntry::readULEB128(const char **error
) {
3349 uint64_t Result
= decodeULEB128(Ptr
, &Count
, Opcodes
.end(), error
);
3351 if (Ptr
> Opcodes
.end())
3352 Ptr
= Opcodes
.end();
3356 int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex
; }
3358 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset
; }
3360 StringRef
MachORebaseEntry::typeName() const {
3361 switch (RebaseType
) {
3362 case MachO::REBASE_TYPE_POINTER
:
3364 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32
:
3365 return "text abs32";
3366 case MachO::REBASE_TYPE_TEXT_PCREL32
:
3367 return "text rel32";
3372 // For use with the SegIndex of a checked Mach-O Rebase entry
3373 // to get the segment name.
3374 StringRef
MachORebaseEntry::segmentName() const {
3375 return O
->BindRebaseSegmentName(SegmentIndex
);
3378 // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3379 // to get the section name.
3380 StringRef
MachORebaseEntry::sectionName() const {
3381 return O
->BindRebaseSectionName(SegmentIndex
, SegmentOffset
);
3384 // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3385 // to get the address.
3386 uint64_t MachORebaseEntry::address() const {
3387 return O
->BindRebaseAddress(SegmentIndex
, SegmentOffset
);
3390 bool MachORebaseEntry::operator==(const MachORebaseEntry
&Other
) const {
3391 #ifdef EXPENSIVE_CHECKS
3392 assert(Opcodes
== Other
.Opcodes
&& "compare iterators of different files");
3394 assert(Opcodes
.data() == Other
.Opcodes
.data() && "compare iterators of different files");
3396 return (Ptr
== Other
.Ptr
) &&
3397 (RemainingLoopCount
== Other
.RemainingLoopCount
) &&
3398 (Done
== Other
.Done
);
3401 iterator_range
<rebase_iterator
>
3402 MachOObjectFile::rebaseTable(Error
&Err
, MachOObjectFile
*O
,
3403 ArrayRef
<uint8_t> Opcodes
, bool is64
) {
3404 if (O
->BindRebaseSectionTable
== nullptr)
3405 O
->BindRebaseSectionTable
= llvm::make_unique
<BindRebaseSegInfo
>(O
);
3406 MachORebaseEntry
Start(&Err
, O
, Opcodes
, is64
);
3407 Start
.moveToFirst();
3409 MachORebaseEntry
Finish(&Err
, O
, Opcodes
, is64
);
3412 return make_range(rebase_iterator(Start
), rebase_iterator(Finish
));
3415 iterator_range
<rebase_iterator
> MachOObjectFile::rebaseTable(Error
&Err
) {
3416 return rebaseTable(Err
, this, getDyldInfoRebaseOpcodes(), is64Bit());
3419 MachOBindEntry::MachOBindEntry(Error
*E
, const MachOObjectFile
*O
,
3420 ArrayRef
<uint8_t> Bytes
, bool is64Bit
, Kind BK
)
3421 : E(E
), O(O
), Opcodes(Bytes
), Ptr(Bytes
.begin()),
3422 PointerSize(is64Bit
? 8 : 4), TableKind(BK
) {}
3424 void MachOBindEntry::moveToFirst() {
3425 Ptr
= Opcodes
.begin();
3429 void MachOBindEntry::moveToEnd() {
3430 Ptr
= Opcodes
.end();
3431 RemainingLoopCount
= 0;
3435 void MachOBindEntry::moveNext() {
3436 ErrorAsOutParameter
ErrAsOutParam(E
);
3437 // If in the middle of some loop, move to next binding in loop.
3438 SegmentOffset
+= AdvanceAmount
;
3439 if (RemainingLoopCount
) {
3440 --RemainingLoopCount
;
3443 // BIND_OPCODE_DONE is only used for padding if we are not aligned to
3444 // pointer size. Therefore it is possible to reach the end without ever having
3445 // seen BIND_OPCODE_DONE.
3446 if (Ptr
== Opcodes
.end()) {
3452 // Parse next opcode and set up next loop.
3453 const uint8_t *OpcodeStart
= Ptr
;
3454 uint8_t Byte
= *Ptr
++;
3455 uint8_t ImmValue
= Byte
& MachO::BIND_IMMEDIATE_MASK
;
3456 uint8_t Opcode
= Byte
& MachO::BIND_OPCODE_MASK
;
3457 int8_t SignExtended
;
3458 const uint8_t *SymStart
;
3459 uint32_t Count
, Skip
;
3460 const char *error
= nullptr;
3462 case MachO::BIND_OPCODE_DONE
:
3463 if (TableKind
== Kind::Lazy
) {
3464 // 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 for (const uint8_t *P
= Ptr
; P
< Opcodes
.end(); ++P
) {
3469 NotLastEntry
= true;
3477 DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");
3479 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 "weak bind table for opcode at: 0x" +
3483 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3488 LibraryOrdinalSet
= true;
3489 if (ImmValue
> O
->getLibraryCount()) {
3490 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3491 "library ordinal: " +
3492 Twine((int)ImmValue
) + " (max " +
3493 Twine((int)O
->getLibraryCount()) +
3494 ") for opcode at: 0x" +
3495 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3501 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
3502 << "Ordinal=" << Ordinal
<< "\n");
3504 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB
:
3505 if (TableKind
== Kind::Weak
) {
3506 *E
= malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
3507 "weak bind table for opcode at: 0x" +
3508 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3512 Ordinal
= readULEB128(&error
);
3513 LibraryOrdinalSet
= true;
3515 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
3516 Twine(error
) + " for opcode at: 0x" +
3517 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3521 if (Ordinal
> (int)O
->getLibraryCount()) {
3522 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3523 "library ordinal: " +
3524 Twine((int)Ordinal
) + " (max " +
3525 Twine((int)O
->getLibraryCount()) +
3526 ") for opcode at: 0x" +
3527 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3533 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
3534 << "Ordinal=" << Ordinal
<< "\n");
3536 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM
:
3537 if (TableKind
== Kind::Weak
) {
3538 *E
= malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
3539 "weak bind table for opcode at: 0x" +
3540 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3545 SignExtended
= MachO::BIND_OPCODE_MASK
| ImmValue
;
3546 Ordinal
= SignExtended
;
3547 if (Ordinal
< MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP
) {
3548 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
3549 "special ordinal: " +
3550 Twine((int)Ordinal
) + " for opcode at: 0x" +
3551 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3557 LibraryOrdinalSet
= true;
3560 dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
3561 << "Ordinal=" << Ordinal
<< "\n");
3563 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
:
3566 while (*Ptr
&& (Ptr
< Opcodes
.end())) {
3569 if (Ptr
== Opcodes
.end()) {
3570 *E
= malformedError(
3571 "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
3572 "symbol name extends past opcodes for opcode at: 0x" +
3573 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3577 SymbolName
= StringRef(reinterpret_cast<const char*>(SymStart
),
3582 dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
3583 << "SymbolName=" << SymbolName
<< "\n");
3584 if (TableKind
== Kind::Weak
) {
3585 if (ImmValue
& MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION
)
3589 case MachO::BIND_OPCODE_SET_TYPE_IMM
:
3590 BindType
= ImmValue
;
3591 if (ImmValue
> MachO::BIND_TYPE_TEXT_PCREL32
) {
3592 *E
= malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
3593 Twine((int)ImmValue
) + " for opcode at: 0x" +
3594 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3600 dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
3601 << "BindType=" << (int)BindType
<< "\n");
3603 case MachO::BIND_OPCODE_SET_ADDEND_SLEB
:
3604 Addend
= readSLEB128(&error
);
3606 *E
= malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error
) +
3607 " for opcode at: 0x" +
3608 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3614 dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
3615 << "Addend=" << Addend
<< "\n");
3617 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
:
3618 SegmentIndex
= ImmValue
;
3619 SegmentOffset
= readULEB128(&error
);
3621 *E
= malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3622 Twine(error
) + " for opcode at: 0x" +
3623 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3627 error
= O
->BindEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
, true);
3629 *E
= malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3630 Twine(error
) + " for opcode at: 0x" +
3631 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3637 dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3638 << "SegmentIndex=" << SegmentIndex
<< ", "
3639 << format("SegmentOffset=0x%06X", SegmentOffset
)
3642 case MachO::BIND_OPCODE_ADD_ADDR_ULEB
:
3643 SegmentOffset
+= readULEB128(&error
);
3645 *E
= malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3646 " for opcode at: 0x" +
3647 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3651 error
= O
->BindEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
, true);
3653 *E
= malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3654 " for opcode at: 0x" +
3655 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3659 DEBUG_WITH_TYPE("mach-o-bind",
3660 dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
3661 << format("SegmentOffset=0x%06X",
3662 SegmentOffset
) << "\n");
3664 case MachO::BIND_OPCODE_DO_BIND
:
3665 AdvanceAmount
= PointerSize
;
3666 RemainingLoopCount
= 0;
3667 error
= O
->BindEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
, true);
3669 *E
= malformedError("for BIND_OPCODE_DO_BIND " + Twine(error
) +
3670 " for opcode at: 0x" +
3671 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
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()));
3683 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
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()));
3691 DEBUG_WITH_TYPE("mach-o-bind",
3692 dbgs() << "BIND_OPCODE_DO_BIND: "
3693 << format("SegmentOffset=0x%06X",
3694 SegmentOffset
) << "\n");
3696 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB
:
3697 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()));
3704 error
= O
->BindEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
, true);
3706 *E
= malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3707 Twine(error
) + " for opcode at: 0x" +
3708 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
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 "
3717 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3721 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
3722 *E
= malformedError(
3723 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3724 "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3725 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3729 AdvanceAmount
= readULEB128(&error
) + PointerSize
;
3731 *E
= malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3732 Twine(error
) + " for opcode at: 0x" +
3733 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3737 // Note, this is not really an error until the next bind but make no sense
3738 // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
3740 error
= O
->BindEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
+
3741 AdvanceAmount
, false);
3743 *E
= malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
3745 Twine(error
) + " for opcode at: 0x" +
3746 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3750 RemainingLoopCount
= 0;
3753 dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
3754 << format("SegmentOffset=0x%06X", SegmentOffset
)
3755 << ", AdvanceAmount=" << AdvanceAmount
3756 << ", RemainingLoopCount=" << RemainingLoopCount
3759 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED
:
3760 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()));
3767 error
= O
->BindEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
, true);
3769 *E
= malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
3770 Twine(error
) + " for opcode at: 0x" +
3771 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3775 if (SymbolName
== StringRef()) {
3776 *E
= malformedError(
3777 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3778 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3780 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3784 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
3785 *E
= malformedError(
3786 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3787 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3789 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3793 AdvanceAmount
= ImmValue
* PointerSize
+ PointerSize
;
3794 RemainingLoopCount
= 0;
3795 error
= O
->BindEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
+
3796 AdvanceAmount
, false);
3799 malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3800 " (after adding immediate times the pointer size) " +
3801 Twine(error
) + " for opcode at: 0x" +
3802 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3806 DEBUG_WITH_TYPE("mach-o-bind",
3808 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
3809 << format("SegmentOffset=0x%06X", SegmentOffset
) << "\n");
3811 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB
:
3812 if (TableKind
== Kind::Lazy
) {
3813 *E
= malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
3814 "allowed in lazy bind table for opcode at: 0x" +
3815 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3819 Count
= readULEB128(&error
);
3821 RemainingLoopCount
= Count
- 1;
3823 RemainingLoopCount
= 0;
3825 *E
= malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3827 Twine(error
) + " for opcode at: 0x" +
3828 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3832 Skip
= readULEB128(&error
);
3833 AdvanceAmount
= Skip
+ PointerSize
;
3835 *E
= malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3837 Twine(error
) + " for opcode at: 0x" +
3838 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3842 error
= O
->BindEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
, true);
3845 malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
3846 Twine(error
) + " for opcode at: 0x" +
3847 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3851 if (SymbolName
== StringRef()) {
3852 *E
= malformedError(
3853 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3854 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3856 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3860 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
3861 *E
= malformedError(
3862 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3863 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3865 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3869 error
= O
->BindEntryCheckCountAndSkip(Count
, Skip
, PointerSize
,
3870 SegmentIndex
, SegmentOffset
);
3873 malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
3874 Twine(error
) + " for opcode at: 0x" +
3875 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3881 dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
3882 << format("SegmentOffset=0x%06X", SegmentOffset
)
3883 << ", AdvanceAmount=" << AdvanceAmount
3884 << ", RemainingLoopCount=" << RemainingLoopCount
3888 *E
= malformedError("bad bind info (bad opcode value 0x" +
3889 Twine::utohexstr(Opcode
) + " for opcode at: 0x" +
3890 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3897 uint64_t MachOBindEntry::readULEB128(const char **error
) {
3899 uint64_t Result
= decodeULEB128(Ptr
, &Count
, Opcodes
.end(), error
);
3901 if (Ptr
> Opcodes
.end())
3902 Ptr
= Opcodes
.end();
3906 int64_t MachOBindEntry::readSLEB128(const char **error
) {
3908 int64_t Result
= decodeSLEB128(Ptr
, &Count
, Opcodes
.end(), error
);
3910 if (Ptr
> Opcodes
.end())
3911 Ptr
= Opcodes
.end();
3915 int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex
; }
3917 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset
; }
3919 StringRef
MachOBindEntry::typeName() const {
3921 case MachO::BIND_TYPE_POINTER
:
3923 case MachO::BIND_TYPE_TEXT_ABSOLUTE32
:
3924 return "text abs32";
3925 case MachO::BIND_TYPE_TEXT_PCREL32
:
3926 return "text rel32";
3931 StringRef
MachOBindEntry::symbolName() const { return SymbolName
; }
3933 int64_t MachOBindEntry::addend() const { return Addend
; }
3935 uint32_t MachOBindEntry::flags() const { return Flags
; }
3937 int MachOBindEntry::ordinal() const { return Ordinal
; }
3939 // For use with the SegIndex of a checked Mach-O Bind entry
3940 // to get the segment name.
3941 StringRef
MachOBindEntry::segmentName() const {
3942 return O
->BindRebaseSegmentName(SegmentIndex
);
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
);
3951 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3952 // to get the address.
3953 uint64_t MachOBindEntry::address() const {
3954 return O
->BindRebaseAddress(SegmentIndex
, SegmentOffset
);
3957 bool MachOBindEntry::operator==(const MachOBindEntry
&Other
) const {
3958 #ifdef EXPENSIVE_CHECKS
3959 assert(Opcodes
== Other
.Opcodes
&& "compare iterators of different files");
3961 assert(Opcodes
.data() == Other
.Opcodes
.data() && "compare iterators of different files");
3963 return (Ptr
== Other
.Ptr
) &&
3964 (RemainingLoopCount
== Other
.RemainingLoopCount
) &&
3965 (Done
== Other
.Done
);
3968 // Build table of sections so SegIndex/SegOffset pairs can be translated.
3969 BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile
*Obj
) {
3970 uint32_t CurSegIndex
= Obj
->hasPageZeroSegment() ? 1 : 0;
3971 StringRef CurSegName
;
3972 uint64_t CurSegAddress
;
3973 for (const SectionRef
&Section
: Obj
->sections()) {
3975 Section
.getName(Info
.SectionName
);
3976 Info
.Address
= Section
.getAddress();
3977 Info
.Size
= Section
.getSize();
3979 Obj
->getSectionFinalSegmentName(Section
.getRawDataRefImpl());
3980 if (!Info
.SegmentName
.equals(CurSegName
)) {
3982 CurSegName
= Info
.SegmentName
;
3983 CurSegAddress
= Info
.Address
;
3985 Info
.SegmentIndex
= CurSegIndex
- 1;
3986 Info
.OffsetInSegment
= Info
.Address
- CurSegAddress
;
3987 Info
.SegmentStartAddress
= CurSegAddress
;
3988 Sections
.push_back(Info
);
3990 MaxSegIndex
= CurSegIndex
;
3993 // For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to
3994 // validate a MachOBindEntry or MachORebaseEntry.
3995 const char * BindRebaseSegInfo::checkSegAndOffset(int32_t SegIndex
,
3999 return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
4000 if (SegIndex
>= MaxSegIndex
)
4001 return "bad segIndex (too large)";
4002 for (const SectionInfo
&SI
: Sections
) {
4003 if (SI
.SegmentIndex
!= SegIndex
)
4005 if (SI
.OffsetInSegment
> SegOffset
)
4007 if (SegOffset
> (SI
.OffsetInSegment
+ SI
.Size
))
4009 if (endInvalid
&& SegOffset
>= (SI
.OffsetInSegment
+ SI
.Size
))
4013 return "bad segOffset, too large";
4016 // For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for
4017 // the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode and for use in
4018 // MachORebaseEntry::moveNext() to validate a MachORebaseEntry for
4019 // REBASE_OPCODE_DO_*_TIMES* opcodes. The SegIndex and SegOffset must have
4020 // been already checked.
4021 const char * BindRebaseSegInfo::checkCountAndSkip(uint32_t Count
, uint32_t Skip
,
4022 uint8_t PointerSize
,
4024 uint64_t SegOffset
) {
4025 const SectionInfo
&SI
= findSection(SegIndex
, SegOffset
);
4026 uint64_t addr
= SI
.SegmentStartAddress
+ SegOffset
;
4027 if (addr
>= SI
.Address
+ SI
.Size
)
4028 return "bad segOffset, too large";
4031 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);
4039 return "bad count and skip, too large";
4044 // For use with the SegIndex of a checked Mach-O Bind or Rebase entry
4045 // to get the segment name.
4046 StringRef
BindRebaseSegInfo::segmentName(int32_t SegIndex
) {
4047 for (const SectionInfo
&SI
: Sections
) {
4048 if (SI
.SegmentIndex
== SegIndex
)
4049 return SI
.SegmentName
;
4051 llvm_unreachable("invalid SegIndex");
4054 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4055 // to get the SectionInfo.
4056 const BindRebaseSegInfo::SectionInfo
&BindRebaseSegInfo::findSection(
4057 int32_t SegIndex
, uint64_t SegOffset
) {
4058 for (const SectionInfo
&SI
: Sections
) {
4059 if (SI
.SegmentIndex
!= SegIndex
)
4061 if (SI
.OffsetInSegment
> SegOffset
)
4063 if (SegOffset
>= (SI
.OffsetInSegment
+ SI
.Size
))
4067 llvm_unreachable("SegIndex and SegOffset not in any section");
4070 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4071 // entry to get the section name.
4072 StringRef
BindRebaseSegInfo::sectionName(int32_t SegIndex
,
4073 uint64_t SegOffset
) {
4074 return findSection(SegIndex
, SegOffset
).SectionName
;
4077 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4078 // entry to get the address.
4079 uint64_t BindRebaseSegInfo::address(uint32_t SegIndex
, uint64_t OffsetInSeg
) {
4080 const SectionInfo
&SI
= findSection(SegIndex
, OffsetInSeg
);
4081 return SI
.SegmentStartAddress
+ OffsetInSeg
;
4084 iterator_range
<bind_iterator
>
4085 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 MachOBindEntry
Start(&Err
, O
, Opcodes
, is64
, BKind
);
4091 Start
.moveToFirst();
4093 MachOBindEntry
Finish(&Err
, O
, Opcodes
, is64
, BKind
);
4096 return make_range(bind_iterator(Start
), bind_iterator(Finish
));
4099 iterator_range
<bind_iterator
> MachOObjectFile::bindTable(Error
&Err
) {
4100 return bindTable(Err
, this, getDyldInfoBindOpcodes(), is64Bit(),
4101 MachOBindEntry::Kind::Regular
);
4104 iterator_range
<bind_iterator
> MachOObjectFile::lazyBindTable(Error
&Err
) {
4105 return bindTable(Err
, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
4106 MachOBindEntry::Kind::Lazy
);
4109 iterator_range
<bind_iterator
> MachOObjectFile::weakBindTable(Error
&Err
) {
4110 return bindTable(Err
, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
4111 MachOBindEntry::Kind::Weak
);
4114 MachOObjectFile::load_command_iterator
4115 MachOObjectFile::begin_load_commands() const {
4116 return LoadCommands
.begin();
4119 MachOObjectFile::load_command_iterator
4120 MachOObjectFile::end_load_commands() const {
4121 return LoadCommands
.end();
4124 iterator_range
<MachOObjectFile::load_command_iterator
>
4125 MachOObjectFile::load_commands() const {
4126 return make_range(begin_load_commands(), end_load_commands());
4130 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec
) const {
4131 ArrayRef
<char> Raw
= getSectionRawFinalSegmentName(Sec
);
4132 return parseSegmentOrSectionName(Raw
.data());
4136 MachOObjectFile::getSectionRawName(DataRefImpl Sec
) const {
4137 assert(Sec
.d
.a
< Sections
.size() && "Should have detected this earlier");
4138 const section_base
*Base
=
4139 reinterpret_cast<const section_base
*>(Sections
[Sec
.d
.a
]);
4140 return makeArrayRef(Base
->sectname
);
4144 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec
) const {
4145 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
);
4152 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info
&RE
)
4154 if (getCPUType(*this) == MachO::CPU_TYPE_X86_64
)
4156 return getPlainRelocationAddress(RE
) & MachO::R_SCATTERED
;
4159 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
4160 const MachO::any_relocation_info
&RE
) const {
4161 if (isLittleEndian())
4162 return RE
.r_word1
& 0xffffff;
4163 return RE
.r_word1
>> 8;
4166 bool MachOObjectFile::getPlainRelocationExternal(
4167 const MachO::any_relocation_info
&RE
) const {
4168 if (isLittleEndian())
4169 return (RE
.r_word1
>> 27) & 1;
4170 return (RE
.r_word1
>> 4) & 1;
4173 bool MachOObjectFile::getScatteredRelocationScattered(
4174 const MachO::any_relocation_info
&RE
) const {
4175 return RE
.r_word0
>> 31;
4178 uint32_t MachOObjectFile::getScatteredRelocationValue(
4179 const MachO::any_relocation_info
&RE
) const {
4183 uint32_t MachOObjectFile::getScatteredRelocationType(
4184 const MachO::any_relocation_info
&RE
) const {
4185 return (RE
.r_word0
>> 24) & 0xf;
4188 unsigned MachOObjectFile::getAnyRelocationAddress(
4189 const MachO::any_relocation_info
&RE
) const {
4190 if (isRelocationScattered(RE
))
4191 return getScatteredRelocationAddress(RE
);
4192 return getPlainRelocationAddress(RE
);
4195 unsigned MachOObjectFile::getAnyRelocationPCRel(
4196 const MachO::any_relocation_info
&RE
) const {
4197 if (isRelocationScattered(RE
))
4198 return getScatteredRelocationPCRel(RE
);
4199 return getPlainRelocationPCRel(*this, RE
);
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
);
4210 MachOObjectFile::getAnyRelocationType(
4211 const MachO::any_relocation_info
&RE
) const {
4212 if (isRelocationScattered(RE
))
4213 return getScatteredRelocationType(RE
);
4214 return getPlainRelocationType(*this, RE
);
4218 MachOObjectFile::getAnyRelocationSection(
4219 const MachO::any_relocation_info
&RE
) const {
4220 if (isRelocationScattered(RE
) || getPlainRelocationExternal(RE
))
4221 return *section_end();
4222 unsigned SecNum
= getPlainRelocationSymbolNum(RE
);
4223 if (SecNum
== MachO::R_ABS
|| SecNum
> Sections
.size())
4224 return *section_end();
4226 DRI
.d
.a
= SecNum
- 1;
4227 return SectionRef(DRI
, this);
4230 MachO::section
MachOObjectFile::getSection(DataRefImpl DRI
) const {
4231 assert(DRI
.d
.a
< Sections
.size() && "Should have detected this earlier");
4232 return getStruct
<MachO::section
>(*this, Sections
[DRI
.d
.a
]);
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
]);
4240 MachO::section
MachOObjectFile::getSection(const LoadCommandInfo
&L
,
4241 unsigned Index
) const {
4242 const char *Sec
= getSectionPtr(*this, L
, Index
);
4243 return getStruct
<MachO::section
>(*this, Sec
);
4246 MachO::section_64
MachOObjectFile::getSection64(const LoadCommandInfo
&L
,
4247 unsigned Index
) const {
4248 const char *Sec
= getSectionPtr(*this, L
, Index
);
4249 return getStruct
<MachO::section_64
>(*this, Sec
);
4253 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI
) const {
4254 const char *P
= reinterpret_cast<const char *>(DRI
.p
);
4255 return getStruct
<MachO::nlist
>(*this, P
);
4259 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI
) const {
4260 const char *P
= reinterpret_cast<const char *>(DRI
.p
);
4261 return getStruct
<MachO::nlist_64
>(*this, P
);
4264 MachO::linkedit_data_command
4265 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo
&L
) const {
4266 return getStruct
<MachO::linkedit_data_command
>(*this, L
.Ptr
);
4269 MachO::segment_command
4270 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo
&L
) const {
4271 return getStruct
<MachO::segment_command
>(*this, L
.Ptr
);
4274 MachO::segment_command_64
4275 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo
&L
) const {
4276 return getStruct
<MachO::segment_command_64
>(*this, L
.Ptr
);
4279 MachO::linker_option_command
4280 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo
&L
) const {
4281 return getStruct
<MachO::linker_option_command
>(*this, L
.Ptr
);
4284 MachO::version_min_command
4285 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo
&L
) const {
4286 return getStruct
<MachO::version_min_command
>(*this, L
.Ptr
);
4290 MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo
&L
) const {
4291 return getStruct
<MachO::note_command
>(*this, L
.Ptr
);
4294 MachO::build_version_command
4295 MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo
&L
) const {
4296 return getStruct
<MachO::build_version_command
>(*this, L
.Ptr
);
4299 MachO::build_tool_version
4300 MachOObjectFile::getBuildToolVersion(unsigned index
) const {
4301 return getStruct
<MachO::build_tool_version
>(*this, BuildTools
[index
]);
4304 MachO::dylib_command
4305 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo
&L
) const {
4306 return getStruct
<MachO::dylib_command
>(*this, L
.Ptr
);
4309 MachO::dyld_info_command
4310 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo
&L
) const {
4311 return getStruct
<MachO::dyld_info_command
>(*this, L
.Ptr
);
4314 MachO::dylinker_command
4315 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo
&L
) const {
4316 return getStruct
<MachO::dylinker_command
>(*this, L
.Ptr
);
4320 MachOObjectFile::getUuidCommand(const LoadCommandInfo
&L
) const {
4321 return getStruct
<MachO::uuid_command
>(*this, L
.Ptr
);
4324 MachO::rpath_command
4325 MachOObjectFile::getRpathCommand(const LoadCommandInfo
&L
) const {
4326 return getStruct
<MachO::rpath_command
>(*this, L
.Ptr
);
4329 MachO::source_version_command
4330 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo
&L
) const {
4331 return getStruct
<MachO::source_version_command
>(*this, L
.Ptr
);
4334 MachO::entry_point_command
4335 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo
&L
) const {
4336 return getStruct
<MachO::entry_point_command
>(*this, L
.Ptr
);
4339 MachO::encryption_info_command
4340 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo
&L
) const {
4341 return getStruct
<MachO::encryption_info_command
>(*this, L
.Ptr
);
4344 MachO::encryption_info_command_64
4345 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo
&L
) const {
4346 return getStruct
<MachO::encryption_info_command_64
>(*this, L
.Ptr
);
4349 MachO::sub_framework_command
4350 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo
&L
) const {
4351 return getStruct
<MachO::sub_framework_command
>(*this, L
.Ptr
);
4354 MachO::sub_umbrella_command
4355 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo
&L
) const {
4356 return getStruct
<MachO::sub_umbrella_command
>(*this, L
.Ptr
);
4359 MachO::sub_library_command
4360 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo
&L
) const {
4361 return getStruct
<MachO::sub_library_command
>(*this, L
.Ptr
);
4364 MachO::sub_client_command
4365 MachOObjectFile::getSubClientCommand(const LoadCommandInfo
&L
) const {
4366 return getStruct
<MachO::sub_client_command
>(*this, L
.Ptr
);
4369 MachO::routines_command
4370 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo
&L
) const {
4371 return getStruct
<MachO::routines_command
>(*this, L
.Ptr
);
4374 MachO::routines_command_64
4375 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo
&L
) const {
4376 return getStruct
<MachO::routines_command_64
>(*this, L
.Ptr
);
4379 MachO::thread_command
4380 MachOObjectFile::getThreadCommand(const LoadCommandInfo
&L
) const {
4381 return getStruct
<MachO::thread_command
>(*this, L
.Ptr
);
4384 MachO::any_relocation_info
4385 MachOObjectFile::getRelocation(DataRefImpl Rel
) const {
4387 if (getHeader().filetype
== MachO::MH_OBJECT
) {
4391 MachO::section_64 Sect
= getSection64(Sec
);
4392 Offset
= Sect
.reloff
;
4394 MachO::section Sect
= getSection(Sec
);
4395 Offset
= Sect
.reloff
;
4398 MachO::dysymtab_command DysymtabLoadCmd
= getDysymtabLoadCommand();
4400 Offset
= DysymtabLoadCmd
.extreloff
; // Offset to the external relocations
4402 Offset
= DysymtabLoadCmd
.locreloff
; // Offset to the local relocations
4405 auto P
= reinterpret_cast<const MachO::any_relocation_info
*>(
4406 getPtr(*this, Offset
)) + Rel
.d
.b
;
4407 return getStruct
<MachO::any_relocation_info
>(
4408 *this, reinterpret_cast<const char *>(P
));
4411 MachO::data_in_code_entry
4412 MachOObjectFile::getDice(DataRefImpl Rel
) const {
4413 const char *P
= reinterpret_cast<const char *>(Rel
.p
);
4414 return getStruct
<MachO::data_in_code_entry
>(*this, P
);
4417 const MachO::mach_header
&MachOObjectFile::getHeader() const {
4421 const MachO::mach_header_64
&MachOObjectFile::getHeader64() const {
4426 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
4427 const MachO::dysymtab_command
&DLC
,
4428 unsigned Index
) const {
4429 uint64_t Offset
= DLC
.indirectsymoff
+ Index
* sizeof(uint32_t);
4430 return getStruct
<uint32_t>(*this, getPtr(*this, Offset
));
4433 MachO::data_in_code_entry
4434 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset
,
4435 unsigned Index
) const {
4436 uint64_t Offset
= DataOffset
+ Index
* sizeof(MachO::data_in_code_entry
);
4437 return getStruct
<MachO::data_in_code_entry
>(*this, getPtr(*this, Offset
));
4440 MachO::symtab_command
MachOObjectFile::getSymtabLoadCommand() const {
4442 return getStruct
<MachO::symtab_command
>(*this, SymtabLoadCmd
);
4444 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
4445 MachO::symtab_command Cmd
;
4446 Cmd
.cmd
= MachO::LC_SYMTAB
;
4447 Cmd
.cmdsize
= sizeof(MachO::symtab_command
);
4455 MachO::dysymtab_command
MachOObjectFile::getDysymtabLoadCommand() const {
4456 if (DysymtabLoadCmd
)
4457 return getStruct
<MachO::dysymtab_command
>(*this, DysymtabLoadCmd
);
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 Cmd
.cmdsize
= sizeof(MachO::dysymtab_command
);
4473 Cmd
.extrefsymoff
= 0;
4474 Cmd
.nextrefsyms
= 0;
4475 Cmd
.indirectsymoff
= 0;
4476 Cmd
.nindirectsyms
= 0;
4484 MachO::linkedit_data_command
4485 MachOObjectFile::getDataInCodeLoadCommand() const {
4486 if (DataInCodeLoadCmd
)
4487 return getStruct
<MachO::linkedit_data_command
>(*this, DataInCodeLoadCmd
);
4489 // 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 Cmd
.cmdsize
= sizeof(MachO::linkedit_data_command
);
4498 MachO::linkedit_data_command
4499 MachOObjectFile::getLinkOptHintsLoadCommand() const {
4500 if (LinkOptHintsLoadCmd
)
4501 return getStruct
<MachO::linkedit_data_command
>(*this, LinkOptHintsLoadCmd
);
4503 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
4505 MachO::linkedit_data_command Cmd
;
4506 Cmd
.cmd
= MachO::LC_LINKER_OPTIMIZATION_HINT
;
4507 Cmd
.cmdsize
= sizeof(MachO::linkedit_data_command
);
4513 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
4514 if (!DyldInfoLoadCmd
)
4517 MachO::dyld_info_command DyldInfo
=
4518 getStruct
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4519 const uint8_t *Ptr
=
4520 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.rebase_off
));
4521 return makeArrayRef(Ptr
, DyldInfo
.rebase_size
);
4524 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
4525 if (!DyldInfoLoadCmd
)
4528 MachO::dyld_info_command DyldInfo
=
4529 getStruct
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4530 const uint8_t *Ptr
=
4531 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.bind_off
));
4532 return makeArrayRef(Ptr
, DyldInfo
.bind_size
);
4535 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
4536 if (!DyldInfoLoadCmd
)
4539 MachO::dyld_info_command DyldInfo
=
4540 getStruct
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4541 const uint8_t *Ptr
=
4542 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.weak_bind_off
));
4543 return makeArrayRef(Ptr
, DyldInfo
.weak_bind_size
);
4546 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
4547 if (!DyldInfoLoadCmd
)
4550 MachO::dyld_info_command DyldInfo
=
4551 getStruct
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4552 const uint8_t *Ptr
=
4553 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.lazy_bind_off
));
4554 return makeArrayRef(Ptr
, DyldInfo
.lazy_bind_size
);
4557 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
4558 if (!DyldInfoLoadCmd
)
4561 MachO::dyld_info_command DyldInfo
=
4562 getStruct
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4563 const uint8_t *Ptr
=
4564 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.export_off
));
4565 return makeArrayRef(Ptr
, DyldInfo
.export_size
);
4568 ArrayRef
<uint8_t> MachOObjectFile::getUuid() const {
4571 // Returning a pointer is fine as uuid doesn't need endian swapping.
4572 const char *Ptr
= UuidLoadCmd
+ offsetof(MachO::uuid_command
, uuid
);
4573 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr
), 16);
4576 StringRef
MachOObjectFile::getStringTableData() const {
4577 MachO::symtab_command S
= getSymtabLoadCommand();
4578 return getData().substr(S
.stroff
, S
.strsize
);
4581 bool MachOObjectFile::is64Bit() const {
4582 return getType() == getMachOType(false, true) ||
4583 getType() == getMachOType(true, true);
4586 void MachOObjectFile::ReadULEB128s(uint64_t Index
,
4587 SmallVectorImpl
<uint64_t> &Out
) const {
4588 DataExtractor
extractor(ObjectFile::getData(), true, 0);
4590 uint32_t offset
= Index
;
4592 while (uint64_t delta
= extractor
.getULEB128(&offset
)) {
4594 Out
.push_back(data
);
4598 bool MachOObjectFile::isRelocatableObject() const {
4599 return getHeader().filetype
== MachO::MH_OBJECT
;
4602 Expected
<std::unique_ptr
<MachOObjectFile
>>
4603 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer
,
4604 uint32_t UniversalCputype
,
4605 uint32_t UniversalIndex
) {
4606 StringRef Magic
= Buffer
.getBuffer().slice(0, 4);
4607 if (Magic
== "\xFE\xED\xFA\xCE")
4608 return MachOObjectFile::create(Buffer
, false, false,
4609 UniversalCputype
, UniversalIndex
);
4610 if (Magic
== "\xCE\xFA\xED\xFE")
4611 return MachOObjectFile::create(Buffer
, true, false,
4612 UniversalCputype
, UniversalIndex
);
4613 if (Magic
== "\xFE\xED\xFA\xCF")
4614 return MachOObjectFile::create(Buffer
, false, true,
4615 UniversalCputype
, UniversalIndex
);
4616 if (Magic
== "\xCF\xFA\xED\xFE")
4617 return MachOObjectFile::create(Buffer
, true, true,
4618 UniversalCputype
, UniversalIndex
);
4619 return make_error
<GenericBinaryError
>("Unrecognized MachO magic number",
4620 object_error::invalid_file_type
);
4623 StringRef
MachOObjectFile::mapDebugSectionName(StringRef Name
) const {
4624 return StringSwitch
<StringRef
>(Name
)
4625 .Case("debug_str_offs", "debug_str_offsets")