1 //===- MachOObjectFile.cpp - Mach-O object file binding -------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines the MachOObjectFile class, which binds the MachOObject
10 // class to the generic ObjectFile wrapper.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/ADT/ArrayRef.h"
15 #include "llvm/ADT/None.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/ADT/StringSwitch.h"
20 #include "llvm/ADT/Triple.h"
21 #include "llvm/ADT/Twine.h"
22 #include "llvm/BinaryFormat/MachO.h"
23 #include "llvm/Object/Error.h"
24 #include "llvm/Object/MachO.h"
25 #include "llvm/Object/ObjectFile.h"
26 #include "llvm/Object/SymbolicFile.h"
27 #include "llvm/Support/DataExtractor.h"
28 #include "llvm/Support/Debug.h"
29 #include "llvm/Support/Error.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/Format.h"
32 #include "llvm/Support/Host.h"
33 #include "llvm/Support/LEB128.h"
34 #include "llvm/Support/MemoryBuffer.h"
35 #include "llvm/Support/SwapByteOrder.h"
36 #include "llvm/Support/raw_ostream.h"
46 #include <system_error>
49 using namespace object
;
58 } // end anonymous namespace
60 static Error
malformedError(const Twine
&Msg
) {
61 return make_error
<GenericBinaryError
>("truncated or malformed object (" +
63 object_error::parse_failed
);
66 // FIXME: Replace all uses of this function with getStructOrErr.
68 static T
getStruct(const MachOObjectFile
&O
, const char *P
) {
69 // Don't read before the beginning or past the end of the file
70 if (P
< O
.getData().begin() || P
+ sizeof(T
) > O
.getData().end())
71 report_fatal_error("Malformed MachO file.");
74 memcpy(&Cmd
, P
, sizeof(T
));
75 if (O
.isLittleEndian() != sys::IsLittleEndianHost
)
76 MachO::swapStruct(Cmd
);
81 static Expected
<T
> getStructOrErr(const MachOObjectFile
&O
, const char *P
) {
82 // Don't read before the beginning or past the end of the file
83 if (P
< O
.getData().begin() || P
+ sizeof(T
) > O
.getData().end())
84 return malformedError("Structure read out-of-range");
87 memcpy(&Cmd
, P
, sizeof(T
));
88 if (O
.isLittleEndian() != sys::IsLittleEndianHost
)
89 MachO::swapStruct(Cmd
);
94 getSectionPtr(const MachOObjectFile
&O
, MachOObjectFile::LoadCommandInfo L
,
96 uintptr_t CommandAddr
= reinterpret_cast<uintptr_t>(L
.Ptr
);
98 bool Is64
= O
.is64Bit();
99 unsigned SegmentLoadSize
= Is64
? sizeof(MachO::segment_command_64
) :
100 sizeof(MachO::segment_command
);
101 unsigned SectionSize
= Is64
? sizeof(MachO::section_64
) :
102 sizeof(MachO::section
);
104 uintptr_t SectionAddr
= CommandAddr
+ SegmentLoadSize
+ Sec
* SectionSize
;
105 return reinterpret_cast<const char*>(SectionAddr
);
108 static const char *getPtr(const MachOObjectFile
&O
, size_t Offset
) {
109 assert(Offset
<= O
.getData().size());
110 return O
.getData().data() + Offset
;
113 static MachO::nlist_base
114 getSymbolTableEntryBase(const MachOObjectFile
&O
, DataRefImpl DRI
) {
115 const char *P
= reinterpret_cast<const char *>(DRI
.p
);
116 return getStruct
<MachO::nlist_base
>(O
, P
);
119 static StringRef
parseSegmentOrSectionName(const char *P
) {
123 // Not null terminated, so this is a 16 char string.
124 return StringRef(P
, 16);
127 static unsigned getCPUType(const MachOObjectFile
&O
) {
128 return O
.getHeader().cputype
;
132 getPlainRelocationAddress(const MachO::any_relocation_info
&RE
) {
137 getScatteredRelocationAddress(const MachO::any_relocation_info
&RE
) {
138 return RE
.r_word0
& 0xffffff;
141 static bool getPlainRelocationPCRel(const MachOObjectFile
&O
,
142 const MachO::any_relocation_info
&RE
) {
143 if (O
.isLittleEndian())
144 return (RE
.r_word1
>> 24) & 1;
145 return (RE
.r_word1
>> 7) & 1;
149 getScatteredRelocationPCRel(const MachO::any_relocation_info
&RE
) {
150 return (RE
.r_word0
>> 30) & 1;
153 static unsigned getPlainRelocationLength(const MachOObjectFile
&O
,
154 const MachO::any_relocation_info
&RE
) {
155 if (O
.isLittleEndian())
156 return (RE
.r_word1
>> 25) & 3;
157 return (RE
.r_word1
>> 5) & 3;
161 getScatteredRelocationLength(const MachO::any_relocation_info
&RE
) {
162 return (RE
.r_word0
>> 28) & 3;
165 static unsigned getPlainRelocationType(const MachOObjectFile
&O
,
166 const MachO::any_relocation_info
&RE
) {
167 if (O
.isLittleEndian())
168 return RE
.r_word1
>> 28;
169 return RE
.r_word1
& 0xf;
172 static uint32_t getSectionFlags(const MachOObjectFile
&O
,
175 MachO::section_64 Sect
= O
.getSection64(Sec
);
178 MachO::section Sect
= O
.getSection(Sec
);
182 static Expected
<MachOObjectFile::LoadCommandInfo
>
183 getLoadCommandInfo(const MachOObjectFile
&Obj
, const char *Ptr
,
184 uint32_t LoadCommandIndex
) {
185 if (auto CmdOrErr
= getStructOrErr
<MachO::load_command
>(Obj
, Ptr
)) {
186 if (CmdOrErr
->cmdsize
+ Ptr
> Obj
.getData().end())
187 return malformedError("load command " + Twine(LoadCommandIndex
) +
188 " extends past end of file");
189 if (CmdOrErr
->cmdsize
< 8)
190 return malformedError("load command " + Twine(LoadCommandIndex
) +
191 " with size less than 8 bytes");
192 return MachOObjectFile::LoadCommandInfo({Ptr
, *CmdOrErr
});
194 return CmdOrErr
.takeError();
197 static Expected
<MachOObjectFile::LoadCommandInfo
>
198 getFirstLoadCommandInfo(const MachOObjectFile
&Obj
) {
199 unsigned HeaderSize
= Obj
.is64Bit() ? sizeof(MachO::mach_header_64
)
200 : sizeof(MachO::mach_header
);
201 if (sizeof(MachO::load_command
) > Obj
.getHeader().sizeofcmds
)
202 return malformedError("load command 0 extends past the end all load "
203 "commands in the file");
204 return getLoadCommandInfo(Obj
, getPtr(Obj
, HeaderSize
), 0);
207 static Expected
<MachOObjectFile::LoadCommandInfo
>
208 getNextLoadCommandInfo(const MachOObjectFile
&Obj
, uint32_t LoadCommandIndex
,
209 const MachOObjectFile::LoadCommandInfo
&L
) {
210 unsigned HeaderSize
= Obj
.is64Bit() ? sizeof(MachO::mach_header_64
)
211 : sizeof(MachO::mach_header
);
212 if (L
.Ptr
+ L
.C
.cmdsize
+ sizeof(MachO::load_command
) >
213 Obj
.getData().data() + HeaderSize
+ Obj
.getHeader().sizeofcmds
)
214 return malformedError("load command " + Twine(LoadCommandIndex
+ 1) +
215 " extends past the end all load commands in the file");
216 return getLoadCommandInfo(Obj
, L
.Ptr
+ L
.C
.cmdsize
, LoadCommandIndex
+ 1);
219 template <typename T
>
220 static void parseHeader(const MachOObjectFile
&Obj
, T
&Header
,
222 if (sizeof(T
) > Obj
.getData().size()) {
223 Err
= malformedError("the mach header extends past the end of the "
227 if (auto HeaderOrErr
= getStructOrErr
<T
>(Obj
, getPtr(Obj
, 0)))
228 Header
= *HeaderOrErr
;
230 Err
= HeaderOrErr
.takeError();
233 // This is used to check for overlapping of Mach-O elements.
234 struct MachOElement
{
240 static Error
checkOverlappingElement(std::list
<MachOElement
> &Elements
,
241 uint64_t Offset
, uint64_t Size
,
244 return Error::success();
246 for (auto it
=Elements
.begin() ; it
!= Elements
.end(); ++it
) {
248 if ((Offset
>= E
.Offset
&& Offset
< E
.Offset
+ E
.Size
) ||
249 (Offset
+ Size
> E
.Offset
&& Offset
+ Size
< E
.Offset
+ E
.Size
) ||
250 (Offset
<= E
.Offset
&& Offset
+ Size
>= E
.Offset
+ E
.Size
))
251 return malformedError(Twine(Name
) + " at offset " + Twine(Offset
) +
252 " with a size of " + Twine(Size
) + ", overlaps " +
253 E
.Name
+ " at offset " + Twine(E
.Offset
) + " with "
254 "a size of " + Twine(E
.Size
));
257 if (nt
!= Elements
.end()) {
259 if (Offset
+ Size
<= N
.Offset
) {
260 Elements
.insert(nt
, {Offset
, Size
, Name
});
261 return Error::success();
265 Elements
.push_back({Offset
, Size
, Name
});
266 return Error::success();
269 // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
270 // sections to \param Sections, and optionally sets
271 // \param IsPageZeroSegment to true.
272 template <typename Segment
, typename Section
>
273 static Error
parseSegmentLoadCommand(
274 const MachOObjectFile
&Obj
, const MachOObjectFile::LoadCommandInfo
&Load
,
275 SmallVectorImpl
<const char *> &Sections
, bool &IsPageZeroSegment
,
276 uint32_t LoadCommandIndex
, const char *CmdName
, uint64_t SizeOfHeaders
,
277 std::list
<MachOElement
> &Elements
) {
278 const unsigned SegmentLoadSize
= sizeof(Segment
);
279 if (Load
.C
.cmdsize
< SegmentLoadSize
)
280 return malformedError("load command " + Twine(LoadCommandIndex
) +
281 " " + CmdName
+ " cmdsize too small");
282 if (auto SegOrErr
= getStructOrErr
<Segment
>(Obj
, Load
.Ptr
)) {
283 Segment S
= SegOrErr
.get();
284 const unsigned SectionSize
= sizeof(Section
);
285 uint64_t FileSize
= Obj
.getData().size();
286 if (S
.nsects
> std::numeric_limits
<uint32_t>::max() / SectionSize
||
287 S
.nsects
* SectionSize
> Load
.C
.cmdsize
- SegmentLoadSize
)
288 return malformedError("load command " + Twine(LoadCommandIndex
) +
289 " inconsistent cmdsize in " + CmdName
+
290 " for the number of sections");
291 for (unsigned J
= 0; J
< S
.nsects
; ++J
) {
292 const char *Sec
= getSectionPtr(Obj
, Load
, J
);
293 Sections
.push_back(Sec
);
294 auto SectionOrErr
= getStructOrErr
<Section
>(Obj
, Sec
);
296 return SectionOrErr
.takeError();
297 Section s
= SectionOrErr
.get();
298 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
299 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
300 s
.flags
!= MachO::S_ZEROFILL
&&
301 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
&&
303 return malformedError("offset field of section " + Twine(J
) + " in " +
304 CmdName
+ " command " + Twine(LoadCommandIndex
) +
305 " extends past the end of the file");
306 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
307 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
308 s
.flags
!= MachO::S_ZEROFILL
&&
309 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
&& S
.fileoff
== 0 &&
310 s
.offset
< SizeOfHeaders
&& s
.size
!= 0)
311 return malformedError("offset field of section " + Twine(J
) + " in " +
312 CmdName
+ " command " + Twine(LoadCommandIndex
) +
313 " not past the headers of the file");
314 uint64_t BigSize
= s
.offset
;
316 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
317 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
318 s
.flags
!= MachO::S_ZEROFILL
&&
319 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
&&
321 return malformedError("offset field plus size field of section " +
322 Twine(J
) + " in " + CmdName
+ " command " +
323 Twine(LoadCommandIndex
) +
324 " extends past the end of the file");
325 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
326 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
327 s
.flags
!= MachO::S_ZEROFILL
&&
328 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
&&
330 return malformedError("size field of section " +
331 Twine(J
) + " in " + CmdName
+ " command " +
332 Twine(LoadCommandIndex
) +
333 " greater than the segment");
334 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
335 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&& s
.size
!= 0 &&
337 return malformedError("addr field of section " + Twine(J
) + " in " +
338 CmdName
+ " command " + Twine(LoadCommandIndex
) +
339 " less than the segment's vmaddr");
342 uint64_t BigEnd
= S
.vmaddr
;
344 if (S
.vmsize
!= 0 && s
.size
!= 0 && BigSize
> BigEnd
)
345 return malformedError("addr field plus size of section " + Twine(J
) +
346 " in " + CmdName
+ " command " +
347 Twine(LoadCommandIndex
) +
348 " greater than than "
349 "the segment's vmaddr plus vmsize");
350 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
351 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
352 s
.flags
!= MachO::S_ZEROFILL
&&
353 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
)
354 if (Error Err
= checkOverlappingElement(Elements
, s
.offset
, s
.size
,
357 if (s
.reloff
> FileSize
)
358 return malformedError("reloff field of section " + Twine(J
) + " in " +
359 CmdName
+ " command " + Twine(LoadCommandIndex
) +
360 " extends past the end of the file");
362 BigSize
*= sizeof(struct MachO::relocation_info
);
364 if (BigSize
> FileSize
)
365 return malformedError("reloff field plus nreloc field times sizeof("
366 "struct relocation_info) of section " +
367 Twine(J
) + " in " + CmdName
+ " command " +
368 Twine(LoadCommandIndex
) +
369 " extends past the end of the file");
370 if (Error Err
= checkOverlappingElement(Elements
, s
.reloff
, s
.nreloc
*
372 MachO::relocation_info
),
373 "section relocation entries"))
376 if (S
.fileoff
> FileSize
)
377 return malformedError("load command " + Twine(LoadCommandIndex
) +
378 " fileoff field in " + CmdName
+
379 " extends past the end of the file");
380 uint64_t BigSize
= S
.fileoff
;
381 BigSize
+= S
.filesize
;
382 if (BigSize
> FileSize
)
383 return malformedError("load command " + Twine(LoadCommandIndex
) +
384 " fileoff field plus filesize field in " +
385 CmdName
+ " extends past the end of the file");
386 if (S
.vmsize
!= 0 && S
.filesize
> S
.vmsize
)
387 return malformedError("load command " + Twine(LoadCommandIndex
) +
388 " filesize field in " + CmdName
+
389 " greater than vmsize field");
390 IsPageZeroSegment
|= StringRef("__PAGEZERO").equals(S
.segname
);
392 return SegOrErr
.takeError();
394 return Error::success();
397 static Error
checkSymtabCommand(const MachOObjectFile
&Obj
,
398 const MachOObjectFile::LoadCommandInfo
&Load
,
399 uint32_t LoadCommandIndex
,
400 const char **SymtabLoadCmd
,
401 std::list
<MachOElement
> &Elements
) {
402 if (Load
.C
.cmdsize
< sizeof(MachO::symtab_command
))
403 return malformedError("load command " + Twine(LoadCommandIndex
) +
404 " LC_SYMTAB cmdsize too small");
405 if (*SymtabLoadCmd
!= nullptr)
406 return malformedError("more than one LC_SYMTAB command");
407 auto SymtabOrErr
= getStructOrErr
<MachO::symtab_command
>(Obj
, Load
.Ptr
);
409 return SymtabOrErr
.takeError();
410 MachO::symtab_command Symtab
= SymtabOrErr
.get();
411 if (Symtab
.cmdsize
!= sizeof(MachO::symtab_command
))
412 return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex
) +
413 " has incorrect cmdsize");
414 uint64_t FileSize
= Obj
.getData().size();
415 if (Symtab
.symoff
> FileSize
)
416 return malformedError("symoff field of LC_SYMTAB command " +
417 Twine(LoadCommandIndex
) + " extends past the end "
419 uint64_t SymtabSize
= Symtab
.nsyms
;
420 const char *struct_nlist_name
;
422 SymtabSize
*= sizeof(MachO::nlist_64
);
423 struct_nlist_name
= "struct nlist_64";
425 SymtabSize
*= sizeof(MachO::nlist
);
426 struct_nlist_name
= "struct nlist";
428 uint64_t BigSize
= SymtabSize
;
429 BigSize
+= Symtab
.symoff
;
430 if (BigSize
> FileSize
)
431 return malformedError("symoff field plus nsyms field times sizeof(" +
432 Twine(struct_nlist_name
) + ") of LC_SYMTAB command " +
433 Twine(LoadCommandIndex
) + " extends past the end "
435 if (Error Err
= checkOverlappingElement(Elements
, Symtab
.symoff
, SymtabSize
,
438 if (Symtab
.stroff
> FileSize
)
439 return malformedError("stroff field of LC_SYMTAB command " +
440 Twine(LoadCommandIndex
) + " extends past the end "
442 BigSize
= Symtab
.stroff
;
443 BigSize
+= Symtab
.strsize
;
444 if (BigSize
> FileSize
)
445 return malformedError("stroff field plus strsize field of LC_SYMTAB "
446 "command " + Twine(LoadCommandIndex
) + " extends "
447 "past the end of the file");
448 if (Error Err
= checkOverlappingElement(Elements
, Symtab
.stroff
,
449 Symtab
.strsize
, "string table"))
451 *SymtabLoadCmd
= Load
.Ptr
;
452 return Error::success();
455 static Error
checkDysymtabCommand(const MachOObjectFile
&Obj
,
456 const MachOObjectFile::LoadCommandInfo
&Load
,
457 uint32_t LoadCommandIndex
,
458 const char **DysymtabLoadCmd
,
459 std::list
<MachOElement
> &Elements
) {
460 if (Load
.C
.cmdsize
< sizeof(MachO::dysymtab_command
))
461 return malformedError("load command " + Twine(LoadCommandIndex
) +
462 " LC_DYSYMTAB cmdsize too small");
463 if (*DysymtabLoadCmd
!= nullptr)
464 return malformedError("more than one LC_DYSYMTAB command");
466 getStructOrErr
<MachO::dysymtab_command
>(Obj
, Load
.Ptr
);
468 return DysymtabOrErr
.takeError();
469 MachO::dysymtab_command Dysymtab
= DysymtabOrErr
.get();
470 if (Dysymtab
.cmdsize
!= sizeof(MachO::dysymtab_command
))
471 return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex
) +
472 " has incorrect cmdsize");
473 uint64_t FileSize
= Obj
.getData().size();
474 if (Dysymtab
.tocoff
> FileSize
)
475 return malformedError("tocoff field of LC_DYSYMTAB command " +
476 Twine(LoadCommandIndex
) + " extends past the end of "
478 uint64_t BigSize
= Dysymtab
.ntoc
;
479 BigSize
*= sizeof(MachO::dylib_table_of_contents
);
480 BigSize
+= Dysymtab
.tocoff
;
481 if (BigSize
> FileSize
)
482 return malformedError("tocoff field plus ntoc field times sizeof(struct "
483 "dylib_table_of_contents) of LC_DYSYMTAB command " +
484 Twine(LoadCommandIndex
) + " extends past the end of "
486 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.tocoff
,
487 Dysymtab
.ntoc
* sizeof(struct
488 MachO::dylib_table_of_contents
),
489 "table of contents"))
491 if (Dysymtab
.modtaboff
> FileSize
)
492 return malformedError("modtaboff field of LC_DYSYMTAB command " +
493 Twine(LoadCommandIndex
) + " extends past the end of "
495 BigSize
= Dysymtab
.nmodtab
;
496 const char *struct_dylib_module_name
;
497 uint64_t sizeof_modtab
;
499 sizeof_modtab
= sizeof(MachO::dylib_module_64
);
500 struct_dylib_module_name
= "struct dylib_module_64";
502 sizeof_modtab
= sizeof(MachO::dylib_module
);
503 struct_dylib_module_name
= "struct dylib_module";
505 BigSize
*= sizeof_modtab
;
506 BigSize
+= Dysymtab
.modtaboff
;
507 if (BigSize
> FileSize
)
508 return malformedError("modtaboff field plus nmodtab field times sizeof(" +
509 Twine(struct_dylib_module_name
) + ") of LC_DYSYMTAB "
510 "command " + Twine(LoadCommandIndex
) + " extends "
511 "past the end of the file");
512 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.modtaboff
,
513 Dysymtab
.nmodtab
* sizeof_modtab
,
516 if (Dysymtab
.extrefsymoff
> FileSize
)
517 return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
518 Twine(LoadCommandIndex
) + " extends past the end of "
520 BigSize
= Dysymtab
.nextrefsyms
;
521 BigSize
*= sizeof(MachO::dylib_reference
);
522 BigSize
+= Dysymtab
.extrefsymoff
;
523 if (BigSize
> FileSize
)
524 return malformedError("extrefsymoff field plus nextrefsyms field times "
525 "sizeof(struct dylib_reference) of LC_DYSYMTAB "
526 "command " + Twine(LoadCommandIndex
) + " extends "
527 "past the end of the file");
528 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.extrefsymoff
,
529 Dysymtab
.nextrefsyms
*
530 sizeof(MachO::dylib_reference
),
533 if (Dysymtab
.indirectsymoff
> FileSize
)
534 return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
535 Twine(LoadCommandIndex
) + " extends past the end of "
537 BigSize
= Dysymtab
.nindirectsyms
;
538 BigSize
*= sizeof(uint32_t);
539 BigSize
+= Dysymtab
.indirectsymoff
;
540 if (BigSize
> FileSize
)
541 return malformedError("indirectsymoff field plus nindirectsyms field times "
542 "sizeof(uint32_t) of LC_DYSYMTAB command " +
543 Twine(LoadCommandIndex
) + " extends past the end of "
545 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.indirectsymoff
,
546 Dysymtab
.nindirectsyms
*
550 if (Dysymtab
.extreloff
> FileSize
)
551 return malformedError("extreloff field of LC_DYSYMTAB command " +
552 Twine(LoadCommandIndex
) + " extends past the end of "
554 BigSize
= Dysymtab
.nextrel
;
555 BigSize
*= sizeof(MachO::relocation_info
);
556 BigSize
+= Dysymtab
.extreloff
;
557 if (BigSize
> FileSize
)
558 return malformedError("extreloff field plus nextrel field times sizeof"
559 "(struct relocation_info) of LC_DYSYMTAB command " +
560 Twine(LoadCommandIndex
) + " extends past the end of "
562 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.extreloff
,
564 sizeof(MachO::relocation_info
),
565 "external relocation table"))
567 if (Dysymtab
.locreloff
> FileSize
)
568 return malformedError("locreloff field of LC_DYSYMTAB command " +
569 Twine(LoadCommandIndex
) + " extends past the end of "
571 BigSize
= Dysymtab
.nlocrel
;
572 BigSize
*= sizeof(MachO::relocation_info
);
573 BigSize
+= Dysymtab
.locreloff
;
574 if (BigSize
> FileSize
)
575 return malformedError("locreloff field plus nlocrel field times sizeof"
576 "(struct relocation_info) of LC_DYSYMTAB command " +
577 Twine(LoadCommandIndex
) + " extends past the end of "
579 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.locreloff
,
581 sizeof(MachO::relocation_info
),
582 "local relocation table"))
584 *DysymtabLoadCmd
= Load
.Ptr
;
585 return Error::success();
588 static Error
checkLinkeditDataCommand(const MachOObjectFile
&Obj
,
589 const MachOObjectFile::LoadCommandInfo
&Load
,
590 uint32_t LoadCommandIndex
,
591 const char **LoadCmd
, const char *CmdName
,
592 std::list
<MachOElement
> &Elements
,
593 const char *ElementName
) {
594 if (Load
.C
.cmdsize
< sizeof(MachO::linkedit_data_command
))
595 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
596 CmdName
+ " cmdsize too small");
597 if (*LoadCmd
!= nullptr)
598 return malformedError("more than one " + Twine(CmdName
) + " command");
599 auto LinkDataOrError
=
600 getStructOrErr
<MachO::linkedit_data_command
>(Obj
, Load
.Ptr
);
601 if (!LinkDataOrError
)
602 return LinkDataOrError
.takeError();
603 MachO::linkedit_data_command LinkData
= LinkDataOrError
.get();
604 if (LinkData
.cmdsize
!= sizeof(MachO::linkedit_data_command
))
605 return malformedError(Twine(CmdName
) + " command " +
606 Twine(LoadCommandIndex
) + " has incorrect cmdsize");
607 uint64_t FileSize
= Obj
.getData().size();
608 if (LinkData
.dataoff
> FileSize
)
609 return malformedError("dataoff field of " + Twine(CmdName
) + " command " +
610 Twine(LoadCommandIndex
) + " extends past the end of "
612 uint64_t BigSize
= LinkData
.dataoff
;
613 BigSize
+= LinkData
.datasize
;
614 if (BigSize
> FileSize
)
615 return malformedError("dataoff field plus datasize field of " +
616 Twine(CmdName
) + " command " +
617 Twine(LoadCommandIndex
) + " extends past the end of "
619 if (Error Err
= checkOverlappingElement(Elements
, LinkData
.dataoff
,
620 LinkData
.datasize
, ElementName
))
623 return Error::success();
626 static Error
checkDyldInfoCommand(const MachOObjectFile
&Obj
,
627 const MachOObjectFile::LoadCommandInfo
&Load
,
628 uint32_t LoadCommandIndex
,
629 const char **LoadCmd
, const char *CmdName
,
630 std::list
<MachOElement
> &Elements
) {
631 if (Load
.C
.cmdsize
< sizeof(MachO::dyld_info_command
))
632 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
633 CmdName
+ " cmdsize too small");
634 if (*LoadCmd
!= nullptr)
635 return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
638 getStructOrErr
<MachO::dyld_info_command
>(Obj
, Load
.Ptr
);
640 return DyldInfoOrErr
.takeError();
641 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
642 if (DyldInfo
.cmdsize
!= sizeof(MachO::dyld_info_command
))
643 return malformedError(Twine(CmdName
) + " command " +
644 Twine(LoadCommandIndex
) + " has incorrect cmdsize");
645 uint64_t FileSize
= Obj
.getData().size();
646 if (DyldInfo
.rebase_off
> FileSize
)
647 return malformedError("rebase_off field of " + Twine(CmdName
) +
648 " command " + Twine(LoadCommandIndex
) + " extends "
649 "past the end of the file");
650 uint64_t BigSize
= DyldInfo
.rebase_off
;
651 BigSize
+= DyldInfo
.rebase_size
;
652 if (BigSize
> FileSize
)
653 return malformedError("rebase_off field plus rebase_size field of " +
654 Twine(CmdName
) + " command " +
655 Twine(LoadCommandIndex
) + " extends past the end of "
657 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.rebase_off
,
658 DyldInfo
.rebase_size
,
661 if (DyldInfo
.bind_off
> FileSize
)
662 return malformedError("bind_off field of " + Twine(CmdName
) +
663 " command " + Twine(LoadCommandIndex
) + " extends "
664 "past the end of the file");
665 BigSize
= DyldInfo
.bind_off
;
666 BigSize
+= DyldInfo
.bind_size
;
667 if (BigSize
> FileSize
)
668 return malformedError("bind_off field plus bind_size field of " +
669 Twine(CmdName
) + " command " +
670 Twine(LoadCommandIndex
) + " extends past the end of "
672 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.bind_off
,
676 if (DyldInfo
.weak_bind_off
> FileSize
)
677 return malformedError("weak_bind_off field of " + Twine(CmdName
) +
678 " command " + Twine(LoadCommandIndex
) + " extends "
679 "past the end of the file");
680 BigSize
= DyldInfo
.weak_bind_off
;
681 BigSize
+= DyldInfo
.weak_bind_size
;
682 if (BigSize
> FileSize
)
683 return malformedError("weak_bind_off field plus weak_bind_size field of " +
684 Twine(CmdName
) + " command " +
685 Twine(LoadCommandIndex
) + " extends past the end of "
687 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.weak_bind_off
,
688 DyldInfo
.weak_bind_size
,
689 "dyld weak bind info"))
691 if (DyldInfo
.lazy_bind_off
> FileSize
)
692 return malformedError("lazy_bind_off field of " + Twine(CmdName
) +
693 " command " + Twine(LoadCommandIndex
) + " extends "
694 "past the end of the file");
695 BigSize
= DyldInfo
.lazy_bind_off
;
696 BigSize
+= DyldInfo
.lazy_bind_size
;
697 if (BigSize
> FileSize
)
698 return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
699 Twine(CmdName
) + " command " +
700 Twine(LoadCommandIndex
) + " extends past the end of "
702 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.lazy_bind_off
,
703 DyldInfo
.lazy_bind_size
,
704 "dyld lazy bind info"))
706 if (DyldInfo
.export_off
> FileSize
)
707 return malformedError("export_off field of " + Twine(CmdName
) +
708 " command " + Twine(LoadCommandIndex
) + " extends "
709 "past the end of the file");
710 BigSize
= DyldInfo
.export_off
;
711 BigSize
+= DyldInfo
.export_size
;
712 if (BigSize
> FileSize
)
713 return malformedError("export_off field plus export_size field of " +
714 Twine(CmdName
) + " command " +
715 Twine(LoadCommandIndex
) + " extends past the end of "
717 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.export_off
,
718 DyldInfo
.export_size
,
722 return Error::success();
725 static Error
checkDylibCommand(const MachOObjectFile
&Obj
,
726 const MachOObjectFile::LoadCommandInfo
&Load
,
727 uint32_t LoadCommandIndex
, const char *CmdName
) {
728 if (Load
.C
.cmdsize
< sizeof(MachO::dylib_command
))
729 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
730 CmdName
+ " cmdsize too small");
731 auto CommandOrErr
= getStructOrErr
<MachO::dylib_command
>(Obj
, Load
.Ptr
);
733 return CommandOrErr
.takeError();
734 MachO::dylib_command D
= CommandOrErr
.get();
735 if (D
.dylib
.name
< sizeof(MachO::dylib_command
))
736 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
737 CmdName
+ " name.offset field too small, not past "
738 "the end of the dylib_command struct");
739 if (D
.dylib
.name
>= D
.cmdsize
)
740 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
741 CmdName
+ " name.offset field extends past the end "
742 "of the load command");
743 // Make sure there is a null between the starting offset of the name and
744 // the end of the load command.
746 const char *P
= (const char *)Load
.Ptr
;
747 for (i
= D
.dylib
.name
; i
< D
.cmdsize
; i
++)
751 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
752 CmdName
+ " library name extends past the end of the "
754 return Error::success();
757 static Error
checkDylibIdCommand(const MachOObjectFile
&Obj
,
758 const MachOObjectFile::LoadCommandInfo
&Load
,
759 uint32_t LoadCommandIndex
,
760 const char **LoadCmd
) {
761 if (Error Err
= checkDylibCommand(Obj
, Load
, LoadCommandIndex
,
764 if (*LoadCmd
!= nullptr)
765 return malformedError("more than one LC_ID_DYLIB command");
766 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB
&&
767 Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
)
768 return malformedError("LC_ID_DYLIB load command in non-dynamic library "
771 return Error::success();
774 static Error
checkDyldCommand(const MachOObjectFile
&Obj
,
775 const MachOObjectFile::LoadCommandInfo
&Load
,
776 uint32_t LoadCommandIndex
, const char *CmdName
) {
777 if (Load
.C
.cmdsize
< sizeof(MachO::dylinker_command
))
778 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
779 CmdName
+ " cmdsize too small");
780 auto CommandOrErr
= getStructOrErr
<MachO::dylinker_command
>(Obj
, Load
.Ptr
);
782 return CommandOrErr
.takeError();
783 MachO::dylinker_command D
= CommandOrErr
.get();
784 if (D
.name
< sizeof(MachO::dylinker_command
))
785 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
786 CmdName
+ " name.offset field too small, not past "
787 "the end of the dylinker_command struct");
788 if (D
.name
>= D
.cmdsize
)
789 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
790 CmdName
+ " name.offset field extends past the end "
791 "of the load command");
792 // Make sure there is a null between the starting offset of the name and
793 // the end of the load command.
795 const char *P
= (const char *)Load
.Ptr
;
796 for (i
= D
.name
; i
< D
.cmdsize
; i
++)
800 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
801 CmdName
+ " dyld name extends past the end of the "
803 return Error::success();
806 static Error
checkVersCommand(const MachOObjectFile
&Obj
,
807 const MachOObjectFile::LoadCommandInfo
&Load
,
808 uint32_t LoadCommandIndex
,
809 const char **LoadCmd
, const char *CmdName
) {
810 if (Load
.C
.cmdsize
!= sizeof(MachO::version_min_command
))
811 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
812 CmdName
+ " has incorrect cmdsize");
813 if (*LoadCmd
!= nullptr)
814 return malformedError("more than one LC_VERSION_MIN_MACOSX, "
815 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
816 "LC_VERSION_MIN_WATCHOS command");
818 return Error::success();
821 static Error
checkNoteCommand(const MachOObjectFile
&Obj
,
822 const MachOObjectFile::LoadCommandInfo
&Load
,
823 uint32_t LoadCommandIndex
,
824 std::list
<MachOElement
> &Elements
) {
825 if (Load
.C
.cmdsize
!= sizeof(MachO::note_command
))
826 return malformedError("load command " + Twine(LoadCommandIndex
) +
827 " LC_NOTE has incorrect cmdsize");
828 auto NoteCmdOrErr
= getStructOrErr
<MachO::note_command
>(Obj
, Load
.Ptr
);
830 return NoteCmdOrErr
.takeError();
831 MachO::note_command Nt
= NoteCmdOrErr
.get();
832 uint64_t FileSize
= Obj
.getData().size();
833 if (Nt
.offset
> FileSize
)
834 return malformedError("offset field of LC_NOTE command " +
835 Twine(LoadCommandIndex
) + " extends "
836 "past the end of the file");
837 uint64_t BigSize
= Nt
.offset
;
839 if (BigSize
> FileSize
)
840 return malformedError("size field plus offset field of LC_NOTE command " +
841 Twine(LoadCommandIndex
) + " extends past the end of "
843 if (Error Err
= checkOverlappingElement(Elements
, Nt
.offset
, Nt
.size
,
846 return Error::success();
850 parseBuildVersionCommand(const MachOObjectFile
&Obj
,
851 const MachOObjectFile::LoadCommandInfo
&Load
,
852 SmallVectorImpl
<const char*> &BuildTools
,
853 uint32_t LoadCommandIndex
) {
855 getStructOrErr
<MachO::build_version_command
>(Obj
, Load
.Ptr
);
857 return BVCOrErr
.takeError();
858 MachO::build_version_command BVC
= BVCOrErr
.get();
859 if (Load
.C
.cmdsize
!=
860 sizeof(MachO::build_version_command
) +
861 BVC
.ntools
* sizeof(MachO::build_tool_version
))
862 return malformedError("load command " + Twine(LoadCommandIndex
) +
863 " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
865 auto Start
= Load
.Ptr
+ sizeof(MachO::build_version_command
);
866 BuildTools
.resize(BVC
.ntools
);
867 for (unsigned i
= 0; i
< BVC
.ntools
; ++i
)
868 BuildTools
[i
] = Start
+ i
* sizeof(MachO::build_tool_version
);
870 return Error::success();
873 static Error
checkRpathCommand(const MachOObjectFile
&Obj
,
874 const MachOObjectFile::LoadCommandInfo
&Load
,
875 uint32_t LoadCommandIndex
) {
876 if (Load
.C
.cmdsize
< sizeof(MachO::rpath_command
))
877 return malformedError("load command " + Twine(LoadCommandIndex
) +
878 " LC_RPATH cmdsize too small");
879 auto ROrErr
= getStructOrErr
<MachO::rpath_command
>(Obj
, Load
.Ptr
);
881 return ROrErr
.takeError();
882 MachO::rpath_command R
= ROrErr
.get();
883 if (R
.path
< sizeof(MachO::rpath_command
))
884 return malformedError("load command " + Twine(LoadCommandIndex
) +
885 " LC_RPATH path.offset field too small, not past "
886 "the end of the rpath_command struct");
887 if (R
.path
>= R
.cmdsize
)
888 return malformedError("load command " + Twine(LoadCommandIndex
) +
889 " LC_RPATH path.offset field extends past the end "
890 "of the load command");
891 // Make sure there is a null between the starting offset of the path and
892 // the end of the load command.
894 const char *P
= (const char *)Load
.Ptr
;
895 for (i
= R
.path
; i
< R
.cmdsize
; i
++)
899 return malformedError("load command " + Twine(LoadCommandIndex
) +
900 " LC_RPATH library name extends past the end of the "
902 return Error::success();
905 static Error
checkEncryptCommand(const MachOObjectFile
&Obj
,
906 const MachOObjectFile::LoadCommandInfo
&Load
,
907 uint32_t LoadCommandIndex
,
908 uint64_t cryptoff
, uint64_t cryptsize
,
909 const char **LoadCmd
, const char *CmdName
) {
910 if (*LoadCmd
!= nullptr)
911 return malformedError("more than one LC_ENCRYPTION_INFO and or "
912 "LC_ENCRYPTION_INFO_64 command");
913 uint64_t FileSize
= Obj
.getData().size();
914 if (cryptoff
> FileSize
)
915 return malformedError("cryptoff field of " + Twine(CmdName
) +
916 " command " + Twine(LoadCommandIndex
) + " extends "
917 "past the end of the file");
918 uint64_t BigSize
= cryptoff
;
919 BigSize
+= cryptsize
;
920 if (BigSize
> FileSize
)
921 return malformedError("cryptoff field plus cryptsize field of " +
922 Twine(CmdName
) + " command " +
923 Twine(LoadCommandIndex
) + " extends past the end of "
926 return Error::success();
929 static Error
checkLinkerOptCommand(const MachOObjectFile
&Obj
,
930 const MachOObjectFile::LoadCommandInfo
&Load
,
931 uint32_t LoadCommandIndex
) {
932 if (Load
.C
.cmdsize
< sizeof(MachO::linker_option_command
))
933 return malformedError("load command " + Twine(LoadCommandIndex
) +
934 " LC_LINKER_OPTION cmdsize too small");
935 auto LinkOptionOrErr
=
936 getStructOrErr
<MachO::linker_option_command
>(Obj
, Load
.Ptr
);
937 if (!LinkOptionOrErr
)
938 return LinkOptionOrErr
.takeError();
939 MachO::linker_option_command L
= LinkOptionOrErr
.get();
940 // Make sure the count of strings is correct.
941 const char *string
= (const char *)Load
.Ptr
+
942 sizeof(struct MachO::linker_option_command
);
943 uint32_t left
= L
.cmdsize
- sizeof(struct MachO::linker_option_command
);
946 while (*string
== '\0' && left
> 0) {
952 uint32_t NullPos
= StringRef(string
, left
).find('\0');
953 if (0xffffffff == NullPos
)
954 return malformedError("load command " + Twine(LoadCommandIndex
) +
955 " LC_LINKER_OPTION string #" + Twine(i
) +
956 " is not NULL terminated");
957 uint32_t len
= std::min(NullPos
, left
) + 1;
963 return malformedError("load command " + Twine(LoadCommandIndex
) +
964 " LC_LINKER_OPTION string count " + Twine(L
.count
) +
965 " does not match number of strings");
966 return Error::success();
969 static Error
checkSubCommand(const MachOObjectFile
&Obj
,
970 const MachOObjectFile::LoadCommandInfo
&Load
,
971 uint32_t LoadCommandIndex
, const char *CmdName
,
972 size_t SizeOfCmd
, const char *CmdStructName
,
973 uint32_t PathOffset
, const char *PathFieldName
) {
974 if (PathOffset
< SizeOfCmd
)
975 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
976 CmdName
+ " " + PathFieldName
+ ".offset field too "
977 "small, not past the end of the " + CmdStructName
);
978 if (PathOffset
>= Load
.C
.cmdsize
)
979 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
980 CmdName
+ " " + PathFieldName
+ ".offset field "
981 "extends past the end of the load command");
982 // Make sure there is a null between the starting offset of the path and
983 // the end of the load command.
985 const char *P
= (const char *)Load
.Ptr
;
986 for (i
= PathOffset
; i
< Load
.C
.cmdsize
; i
++)
989 if (i
>= Load
.C
.cmdsize
)
990 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
991 CmdName
+ " " + PathFieldName
+ " name extends past "
992 "the end of the load command");
993 return Error::success();
996 static Error
checkThreadCommand(const MachOObjectFile
&Obj
,
997 const MachOObjectFile::LoadCommandInfo
&Load
,
998 uint32_t LoadCommandIndex
,
999 const char *CmdName
) {
1000 if (Load
.C
.cmdsize
< sizeof(MachO::thread_command
))
1001 return malformedError("load command " + Twine(LoadCommandIndex
) +
1002 CmdName
+ " cmdsize too small");
1003 auto ThreadCommandOrErr
=
1004 getStructOrErr
<MachO::thread_command
>(Obj
, Load
.Ptr
);
1005 if (!ThreadCommandOrErr
)
1006 return ThreadCommandOrErr
.takeError();
1007 MachO::thread_command T
= ThreadCommandOrErr
.get();
1008 const char *state
= Load
.Ptr
+ sizeof(MachO::thread_command
);
1009 const char *end
= Load
.Ptr
+ T
.cmdsize
;
1010 uint32_t nflavor
= 0;
1011 uint32_t cputype
= getCPUType(Obj
);
1012 while (state
< end
) {
1013 if(state
+ sizeof(uint32_t) > end
)
1014 return malformedError("load command " + Twine(LoadCommandIndex
) +
1015 "flavor in " + CmdName
+ " extends past end of "
1018 memcpy(&flavor
, state
, sizeof(uint32_t));
1019 if (Obj
.isLittleEndian() != sys::IsLittleEndianHost
)
1020 sys::swapByteOrder(flavor
);
1021 state
+= sizeof(uint32_t);
1023 if(state
+ sizeof(uint32_t) > end
)
1024 return malformedError("load command " + Twine(LoadCommandIndex
) +
1025 " count in " + CmdName
+ " extends past end of "
1028 memcpy(&count
, state
, sizeof(uint32_t));
1029 if (Obj
.isLittleEndian() != sys::IsLittleEndianHost
)
1030 sys::swapByteOrder(count
);
1031 state
+= sizeof(uint32_t);
1033 if (cputype
== MachO::CPU_TYPE_I386
) {
1034 if (flavor
== MachO::x86_THREAD_STATE32
) {
1035 if (count
!= MachO::x86_THREAD_STATE32_COUNT
)
1036 return malformedError("load command " + Twine(LoadCommandIndex
) +
1037 " count not x86_THREAD_STATE32_COUNT for "
1038 "flavor number " + Twine(nflavor
) + " which is "
1039 "a x86_THREAD_STATE32 flavor in " + CmdName
+
1041 if (state
+ sizeof(MachO::x86_thread_state32_t
) > end
)
1042 return malformedError("load command " + Twine(LoadCommandIndex
) +
1043 " x86_THREAD_STATE32 extends past end of "
1044 "command in " + CmdName
+ " command");
1045 state
+= sizeof(MachO::x86_thread_state32_t
);
1047 return malformedError("load command " + Twine(LoadCommandIndex
) +
1048 " unknown flavor (" + Twine(flavor
) + ") for "
1049 "flavor number " + Twine(nflavor
) + " in " +
1050 CmdName
+ " command");
1052 } else if (cputype
== MachO::CPU_TYPE_X86_64
) {
1053 if (flavor
== MachO::x86_THREAD_STATE
) {
1054 if (count
!= MachO::x86_THREAD_STATE_COUNT
)
1055 return malformedError("load command " + Twine(LoadCommandIndex
) +
1056 " count not x86_THREAD_STATE_COUNT for "
1057 "flavor number " + Twine(nflavor
) + " which is "
1058 "a x86_THREAD_STATE flavor in " + CmdName
+
1060 if (state
+ sizeof(MachO::x86_thread_state_t
) > end
)
1061 return malformedError("load command " + Twine(LoadCommandIndex
) +
1062 " x86_THREAD_STATE extends past end of "
1063 "command in " + CmdName
+ " command");
1064 state
+= sizeof(MachO::x86_thread_state_t
);
1065 } else if (flavor
== MachO::x86_FLOAT_STATE
) {
1066 if (count
!= MachO::x86_FLOAT_STATE_COUNT
)
1067 return malformedError("load command " + Twine(LoadCommandIndex
) +
1068 " count not x86_FLOAT_STATE_COUNT for "
1069 "flavor number " + Twine(nflavor
) + " which is "
1070 "a x86_FLOAT_STATE flavor in " + CmdName
+
1072 if (state
+ sizeof(MachO::x86_float_state_t
) > end
)
1073 return malformedError("load command " + Twine(LoadCommandIndex
) +
1074 " x86_FLOAT_STATE extends past end of "
1075 "command in " + CmdName
+ " command");
1076 state
+= sizeof(MachO::x86_float_state_t
);
1077 } else if (flavor
== MachO::x86_EXCEPTION_STATE
) {
1078 if (count
!= MachO::x86_EXCEPTION_STATE_COUNT
)
1079 return malformedError("load command " + Twine(LoadCommandIndex
) +
1080 " count not x86_EXCEPTION_STATE_COUNT for "
1081 "flavor number " + Twine(nflavor
) + " which is "
1082 "a x86_EXCEPTION_STATE flavor in " + CmdName
+
1084 if (state
+ sizeof(MachO::x86_exception_state_t
) > end
)
1085 return malformedError("load command " + Twine(LoadCommandIndex
) +
1086 " x86_EXCEPTION_STATE extends past end of "
1087 "command in " + CmdName
+ " command");
1088 state
+= sizeof(MachO::x86_exception_state_t
);
1089 } else if (flavor
== MachO::x86_THREAD_STATE64
) {
1090 if (count
!= MachO::x86_THREAD_STATE64_COUNT
)
1091 return malformedError("load command " + Twine(LoadCommandIndex
) +
1092 " count not x86_THREAD_STATE64_COUNT for "
1093 "flavor number " + Twine(nflavor
) + " which is "
1094 "a x86_THREAD_STATE64 flavor in " + CmdName
+
1096 if (state
+ sizeof(MachO::x86_thread_state64_t
) > end
)
1097 return malformedError("load command " + Twine(LoadCommandIndex
) +
1098 " x86_THREAD_STATE64 extends past end of "
1099 "command in " + CmdName
+ " command");
1100 state
+= sizeof(MachO::x86_thread_state64_t
);
1101 } else if (flavor
== MachO::x86_EXCEPTION_STATE64
) {
1102 if (count
!= MachO::x86_EXCEPTION_STATE64_COUNT
)
1103 return malformedError("load command " + Twine(LoadCommandIndex
) +
1104 " count not x86_EXCEPTION_STATE64_COUNT for "
1105 "flavor number " + Twine(nflavor
) + " which is "
1106 "a x86_EXCEPTION_STATE64 flavor in " + CmdName
+
1108 if (state
+ sizeof(MachO::x86_exception_state64_t
) > end
)
1109 return malformedError("load command " + Twine(LoadCommandIndex
) +
1110 " x86_EXCEPTION_STATE64 extends past end of "
1111 "command in " + CmdName
+ " command");
1112 state
+= sizeof(MachO::x86_exception_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_ARM
) {
1120 if (flavor
== MachO::ARM_THREAD_STATE
) {
1121 if (count
!= MachO::ARM_THREAD_STATE_COUNT
)
1122 return malformedError("load command " + Twine(LoadCommandIndex
) +
1123 " count not ARM_THREAD_STATE_COUNT for "
1124 "flavor number " + Twine(nflavor
) + " which is "
1125 "a ARM_THREAD_STATE flavor in " + CmdName
+
1127 if (state
+ sizeof(MachO::arm_thread_state32_t
) > end
)
1128 return malformedError("load command " + Twine(LoadCommandIndex
) +
1129 " ARM_THREAD_STATE extends past end of "
1130 "command in " + CmdName
+ " command");
1131 state
+= sizeof(MachO::arm_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");
1138 } else if (cputype
== MachO::CPU_TYPE_ARM64
||
1139 cputype
== MachO::CPU_TYPE_ARM64_32
) {
1140 if (flavor
== MachO::ARM_THREAD_STATE64
) {
1141 if (count
!= MachO::ARM_THREAD_STATE64_COUNT
)
1142 return malformedError("load command " + Twine(LoadCommandIndex
) +
1143 " count not ARM_THREAD_STATE64_COUNT for "
1144 "flavor number " + Twine(nflavor
) + " which is "
1145 "a ARM_THREAD_STATE64 flavor in " + CmdName
+
1147 if (state
+ sizeof(MachO::arm_thread_state64_t
) > end
)
1148 return malformedError("load command " + Twine(LoadCommandIndex
) +
1149 " ARM_THREAD_STATE64 extends past end of "
1150 "command in " + CmdName
+ " command");
1151 state
+= sizeof(MachO::arm_thread_state64_t
);
1153 return malformedError("load command " + Twine(LoadCommandIndex
) +
1154 " unknown flavor (" + Twine(flavor
) + ") for "
1155 "flavor number " + Twine(nflavor
) + " in " +
1156 CmdName
+ " command");
1158 } else if (cputype
== MachO::CPU_TYPE_POWERPC
) {
1159 if (flavor
== MachO::PPC_THREAD_STATE
) {
1160 if (count
!= MachO::PPC_THREAD_STATE_COUNT
)
1161 return malformedError("load command " + Twine(LoadCommandIndex
) +
1162 " count not PPC_THREAD_STATE_COUNT for "
1163 "flavor number " + Twine(nflavor
) + " which is "
1164 "a PPC_THREAD_STATE flavor in " + CmdName
+
1166 if (state
+ sizeof(MachO::ppc_thread_state32_t
) > end
)
1167 return malformedError("load command " + Twine(LoadCommandIndex
) +
1168 " PPC_THREAD_STATE extends past end of "
1169 "command in " + CmdName
+ " command");
1170 state
+= sizeof(MachO::ppc_thread_state32_t
);
1172 return malformedError("load command " + Twine(LoadCommandIndex
) +
1173 " unknown flavor (" + Twine(flavor
) + ") for "
1174 "flavor number " + Twine(nflavor
) + " in " +
1175 CmdName
+ " command");
1178 return malformedError("unknown cputype (" + Twine(cputype
) + ") load "
1179 "command " + Twine(LoadCommandIndex
) + " for " +
1180 CmdName
+ " command can't be checked");
1184 return Error::success();
1187 static Error
checkTwoLevelHintsCommand(const MachOObjectFile
&Obj
,
1188 const MachOObjectFile::LoadCommandInfo
1190 uint32_t LoadCommandIndex
,
1191 const char **LoadCmd
,
1192 std::list
<MachOElement
> &Elements
) {
1193 if (Load
.C
.cmdsize
!= sizeof(MachO::twolevel_hints_command
))
1194 return malformedError("load command " + Twine(LoadCommandIndex
) +
1195 " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1196 if (*LoadCmd
!= nullptr)
1197 return malformedError("more than one LC_TWOLEVEL_HINTS command");
1198 auto HintsOrErr
= getStructOrErr
<MachO::twolevel_hints_command
>(Obj
, Load
.Ptr
);
1200 return HintsOrErr
.takeError();
1201 MachO::twolevel_hints_command Hints
= HintsOrErr
.get();
1202 uint64_t FileSize
= Obj
.getData().size();
1203 if (Hints
.offset
> FileSize
)
1204 return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1205 Twine(LoadCommandIndex
) + " extends past the end of "
1207 uint64_t BigSize
= Hints
.nhints
;
1208 BigSize
*= sizeof(MachO::twolevel_hint
);
1209 BigSize
+= Hints
.offset
;
1210 if (BigSize
> FileSize
)
1211 return malformedError("offset field plus nhints times sizeof(struct "
1212 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1213 Twine(LoadCommandIndex
) + " extends past the end of "
1215 if (Error Err
= checkOverlappingElement(Elements
, Hints
.offset
, Hints
.nhints
*
1216 sizeof(MachO::twolevel_hint
),
1219 *LoadCmd
= Load
.Ptr
;
1220 return Error::success();
1223 // Returns true if the libObject code does not support the load command and its
1224 // contents. The cmd value it is treated as an unknown load command but with
1225 // an error message that says the cmd value is obsolete.
1226 static bool isLoadCommandObsolete(uint32_t cmd
) {
1227 if (cmd
== MachO::LC_SYMSEG
||
1228 cmd
== MachO::LC_LOADFVMLIB
||
1229 cmd
== MachO::LC_IDFVMLIB
||
1230 cmd
== MachO::LC_IDENT
||
1231 cmd
== MachO::LC_FVMFILE
||
1232 cmd
== MachO::LC_PREPAGE
||
1233 cmd
== MachO::LC_PREBOUND_DYLIB
||
1234 cmd
== MachO::LC_TWOLEVEL_HINTS
||
1235 cmd
== MachO::LC_PREBIND_CKSUM
)
1240 Expected
<std::unique_ptr
<MachOObjectFile
>>
1241 MachOObjectFile::create(MemoryBufferRef Object
, bool IsLittleEndian
,
1242 bool Is64Bits
, uint32_t UniversalCputype
,
1243 uint32_t UniversalIndex
) {
1244 Error Err
= Error::success();
1245 std::unique_ptr
<MachOObjectFile
> Obj(
1246 new MachOObjectFile(std::move(Object
), IsLittleEndian
,
1247 Is64Bits
, Err
, UniversalCputype
,
1250 return std::move(Err
);
1251 return std::move(Obj
);
1254 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object
, bool IsLittleEndian
,
1255 bool Is64bits
, Error
&Err
,
1256 uint32_t UniversalCputype
,
1257 uint32_t UniversalIndex
)
1258 : ObjectFile(getMachOType(IsLittleEndian
, Is64bits
), Object
) {
1259 ErrorAsOutParameter
ErrAsOutParam(&Err
);
1260 uint64_t SizeOfHeaders
;
1263 parseHeader(*this, Header64
, Err
);
1264 SizeOfHeaders
= sizeof(MachO::mach_header_64
);
1265 cputype
= Header64
.cputype
;
1267 parseHeader(*this, Header
, Err
);
1268 SizeOfHeaders
= sizeof(MachO::mach_header
);
1269 cputype
= Header
.cputype
;
1273 SizeOfHeaders
+= getHeader().sizeofcmds
;
1274 if (getData().data() + SizeOfHeaders
> getData().end()) {
1275 Err
= malformedError("load commands extend past the end of the file");
1278 if (UniversalCputype
!= 0 && cputype
!= UniversalCputype
) {
1279 Err
= malformedError("universal header architecture: " +
1280 Twine(UniversalIndex
) + "'s cputype does not match "
1281 "object file's mach header");
1284 std::list
<MachOElement
> Elements
;
1285 Elements
.push_back({0, SizeOfHeaders
, "Mach-O headers"});
1287 uint32_t LoadCommandCount
= getHeader().ncmds
;
1288 LoadCommandInfo Load
;
1289 if (LoadCommandCount
!= 0) {
1290 if (auto LoadOrErr
= getFirstLoadCommandInfo(*this))
1293 Err
= LoadOrErr
.takeError();
1298 const char *DyldIdLoadCmd
= nullptr;
1299 const char *FuncStartsLoadCmd
= nullptr;
1300 const char *SplitInfoLoadCmd
= nullptr;
1301 const char *CodeSignDrsLoadCmd
= nullptr;
1302 const char *CodeSignLoadCmd
= nullptr;
1303 const char *VersLoadCmd
= nullptr;
1304 const char *SourceLoadCmd
= nullptr;
1305 const char *EntryPointLoadCmd
= nullptr;
1306 const char *EncryptLoadCmd
= nullptr;
1307 const char *RoutinesLoadCmd
= nullptr;
1308 const char *UnixThreadLoadCmd
= nullptr;
1309 const char *TwoLevelHintsLoadCmd
= nullptr;
1310 for (unsigned I
= 0; I
< LoadCommandCount
; ++I
) {
1312 if (Load
.C
.cmdsize
% 8 != 0) {
1313 // We have a hack here to allow 64-bit Mach-O core files to have
1314 // LC_THREAD commands that are only a multiple of 4 and not 8 to be
1315 // allowed since the macOS kernel produces them.
1316 if (getHeader().filetype
!= MachO::MH_CORE
||
1317 Load
.C
.cmd
!= MachO::LC_THREAD
|| Load
.C
.cmdsize
% 4) {
1318 Err
= malformedError("load command " + Twine(I
) + " cmdsize not a "
1324 if (Load
.C
.cmdsize
% 4 != 0) {
1325 Err
= malformedError("load command " + Twine(I
) + " cmdsize not a "
1330 LoadCommands
.push_back(Load
);
1331 if (Load
.C
.cmd
== MachO::LC_SYMTAB
) {
1332 if ((Err
= checkSymtabCommand(*this, Load
, I
, &SymtabLoadCmd
, Elements
)))
1334 } else if (Load
.C
.cmd
== MachO::LC_DYSYMTAB
) {
1335 if ((Err
= checkDysymtabCommand(*this, Load
, I
, &DysymtabLoadCmd
,
1338 } else if (Load
.C
.cmd
== MachO::LC_DATA_IN_CODE
) {
1339 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &DataInCodeLoadCmd
,
1340 "LC_DATA_IN_CODE", Elements
,
1341 "data in code info")))
1343 } else if (Load
.C
.cmd
== MachO::LC_LINKER_OPTIMIZATION_HINT
) {
1344 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &LinkOptHintsLoadCmd
,
1345 "LC_LINKER_OPTIMIZATION_HINT",
1346 Elements
, "linker optimization "
1349 } else if (Load
.C
.cmd
== MachO::LC_FUNCTION_STARTS
) {
1350 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &FuncStartsLoadCmd
,
1351 "LC_FUNCTION_STARTS", Elements
,
1352 "function starts data")))
1354 } else if (Load
.C
.cmd
== MachO::LC_SEGMENT_SPLIT_INFO
) {
1355 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &SplitInfoLoadCmd
,
1356 "LC_SEGMENT_SPLIT_INFO", Elements
,
1357 "split info data")))
1359 } else if (Load
.C
.cmd
== MachO::LC_DYLIB_CODE_SIGN_DRS
) {
1360 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &CodeSignDrsLoadCmd
,
1361 "LC_DYLIB_CODE_SIGN_DRS", Elements
,
1362 "code signing RDs data")))
1364 } else if (Load
.C
.cmd
== MachO::LC_CODE_SIGNATURE
) {
1365 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &CodeSignLoadCmd
,
1366 "LC_CODE_SIGNATURE", Elements
,
1367 "code signature data")))
1369 } else if (Load
.C
.cmd
== MachO::LC_DYLD_INFO
) {
1370 if ((Err
= checkDyldInfoCommand(*this, Load
, I
, &DyldInfoLoadCmd
,
1371 "LC_DYLD_INFO", Elements
)))
1373 } else if (Load
.C
.cmd
== MachO::LC_DYLD_INFO_ONLY
) {
1374 if ((Err
= checkDyldInfoCommand(*this, Load
, I
, &DyldInfoLoadCmd
,
1375 "LC_DYLD_INFO_ONLY", Elements
)))
1377 } else if (Load
.C
.cmd
== MachO::LC_UUID
) {
1378 if (Load
.C
.cmdsize
!= sizeof(MachO::uuid_command
)) {
1379 Err
= malformedError("LC_UUID command " + Twine(I
) + " has incorrect "
1384 Err
= malformedError("more than one LC_UUID command");
1387 UuidLoadCmd
= Load
.Ptr
;
1388 } else if (Load
.C
.cmd
== MachO::LC_SEGMENT_64
) {
1389 if ((Err
= parseSegmentLoadCommand
<MachO::segment_command_64
,
1391 *this, Load
, Sections
, HasPageZeroSegment
, I
,
1392 "LC_SEGMENT_64", SizeOfHeaders
, Elements
)))
1394 } else if (Load
.C
.cmd
== MachO::LC_SEGMENT
) {
1395 if ((Err
= parseSegmentLoadCommand
<MachO::segment_command
,
1397 *this, Load
, Sections
, HasPageZeroSegment
, I
,
1398 "LC_SEGMENT", SizeOfHeaders
, Elements
)))
1400 } else if (Load
.C
.cmd
== MachO::LC_ID_DYLIB
) {
1401 if ((Err
= checkDylibIdCommand(*this, Load
, I
, &DyldIdLoadCmd
)))
1403 } else if (Load
.C
.cmd
== MachO::LC_LOAD_DYLIB
) {
1404 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_LOAD_DYLIB")))
1406 Libraries
.push_back(Load
.Ptr
);
1407 } else if (Load
.C
.cmd
== MachO::LC_LOAD_WEAK_DYLIB
) {
1408 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_LOAD_WEAK_DYLIB")))
1410 Libraries
.push_back(Load
.Ptr
);
1411 } else if (Load
.C
.cmd
== MachO::LC_LAZY_LOAD_DYLIB
) {
1412 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_LAZY_LOAD_DYLIB")))
1414 Libraries
.push_back(Load
.Ptr
);
1415 } else if (Load
.C
.cmd
== MachO::LC_REEXPORT_DYLIB
) {
1416 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_REEXPORT_DYLIB")))
1418 Libraries
.push_back(Load
.Ptr
);
1419 } else if (Load
.C
.cmd
== MachO::LC_LOAD_UPWARD_DYLIB
) {
1420 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_LOAD_UPWARD_DYLIB")))
1422 Libraries
.push_back(Load
.Ptr
);
1423 } else if (Load
.C
.cmd
== MachO::LC_ID_DYLINKER
) {
1424 if ((Err
= checkDyldCommand(*this, Load
, I
, "LC_ID_DYLINKER")))
1426 } else if (Load
.C
.cmd
== MachO::LC_LOAD_DYLINKER
) {
1427 if ((Err
= checkDyldCommand(*this, Load
, I
, "LC_LOAD_DYLINKER")))
1429 } else if (Load
.C
.cmd
== MachO::LC_DYLD_ENVIRONMENT
) {
1430 if ((Err
= checkDyldCommand(*this, Load
, I
, "LC_DYLD_ENVIRONMENT")))
1432 } else if (Load
.C
.cmd
== MachO::LC_VERSION_MIN_MACOSX
) {
1433 if ((Err
= checkVersCommand(*this, Load
, I
, &VersLoadCmd
,
1434 "LC_VERSION_MIN_MACOSX")))
1436 } else if (Load
.C
.cmd
== MachO::LC_VERSION_MIN_IPHONEOS
) {
1437 if ((Err
= checkVersCommand(*this, Load
, I
, &VersLoadCmd
,
1438 "LC_VERSION_MIN_IPHONEOS")))
1440 } else if (Load
.C
.cmd
== MachO::LC_VERSION_MIN_TVOS
) {
1441 if ((Err
= checkVersCommand(*this, Load
, I
, &VersLoadCmd
,
1442 "LC_VERSION_MIN_TVOS")))
1444 } else if (Load
.C
.cmd
== MachO::LC_VERSION_MIN_WATCHOS
) {
1445 if ((Err
= checkVersCommand(*this, Load
, I
, &VersLoadCmd
,
1446 "LC_VERSION_MIN_WATCHOS")))
1448 } else if (Load
.C
.cmd
== MachO::LC_NOTE
) {
1449 if ((Err
= checkNoteCommand(*this, Load
, I
, Elements
)))
1451 } else if (Load
.C
.cmd
== MachO::LC_BUILD_VERSION
) {
1452 if ((Err
= parseBuildVersionCommand(*this, Load
, BuildTools
, I
)))
1454 } else if (Load
.C
.cmd
== MachO::LC_RPATH
) {
1455 if ((Err
= checkRpathCommand(*this, Load
, I
)))
1457 } else if (Load
.C
.cmd
== MachO::LC_SOURCE_VERSION
) {
1458 if (Load
.C
.cmdsize
!= sizeof(MachO::source_version_command
)) {
1459 Err
= malformedError("LC_SOURCE_VERSION command " + Twine(I
) +
1460 " has incorrect cmdsize");
1463 if (SourceLoadCmd
) {
1464 Err
= malformedError("more than one LC_SOURCE_VERSION command");
1467 SourceLoadCmd
= Load
.Ptr
;
1468 } else if (Load
.C
.cmd
== MachO::LC_MAIN
) {
1469 if (Load
.C
.cmdsize
!= sizeof(MachO::entry_point_command
)) {
1470 Err
= malformedError("LC_MAIN command " + Twine(I
) +
1471 " has incorrect cmdsize");
1474 if (EntryPointLoadCmd
) {
1475 Err
= malformedError("more than one LC_MAIN command");
1478 EntryPointLoadCmd
= Load
.Ptr
;
1479 } else if (Load
.C
.cmd
== MachO::LC_ENCRYPTION_INFO
) {
1480 if (Load
.C
.cmdsize
!= sizeof(MachO::encryption_info_command
)) {
1481 Err
= malformedError("LC_ENCRYPTION_INFO command " + Twine(I
) +
1482 " has incorrect cmdsize");
1485 MachO::encryption_info_command E
=
1486 getStruct
<MachO::encryption_info_command
>(*this, Load
.Ptr
);
1487 if ((Err
= checkEncryptCommand(*this, Load
, I
, E
.cryptoff
, E
.cryptsize
,
1488 &EncryptLoadCmd
, "LC_ENCRYPTION_INFO")))
1490 } else if (Load
.C
.cmd
== MachO::LC_ENCRYPTION_INFO_64
) {
1491 if (Load
.C
.cmdsize
!= sizeof(MachO::encryption_info_command_64
)) {
1492 Err
= malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I
) +
1493 " has incorrect cmdsize");
1496 MachO::encryption_info_command_64 E
=
1497 getStruct
<MachO::encryption_info_command_64
>(*this, Load
.Ptr
);
1498 if ((Err
= checkEncryptCommand(*this, Load
, I
, E
.cryptoff
, E
.cryptsize
,
1499 &EncryptLoadCmd
, "LC_ENCRYPTION_INFO_64")))
1501 } else if (Load
.C
.cmd
== MachO::LC_LINKER_OPTION
) {
1502 if ((Err
= checkLinkerOptCommand(*this, Load
, I
)))
1504 } else if (Load
.C
.cmd
== MachO::LC_SUB_FRAMEWORK
) {
1505 if (Load
.C
.cmdsize
< sizeof(MachO::sub_framework_command
)) {
1506 Err
= malformedError("load command " + Twine(I
) +
1507 " LC_SUB_FRAMEWORK cmdsize too small");
1510 MachO::sub_framework_command S
=
1511 getStruct
<MachO::sub_framework_command
>(*this, Load
.Ptr
);
1512 if ((Err
= checkSubCommand(*this, Load
, I
, "LC_SUB_FRAMEWORK",
1513 sizeof(MachO::sub_framework_command
),
1514 "sub_framework_command", S
.umbrella
,
1517 } else if (Load
.C
.cmd
== MachO::LC_SUB_UMBRELLA
) {
1518 if (Load
.C
.cmdsize
< sizeof(MachO::sub_umbrella_command
)) {
1519 Err
= malformedError("load command " + Twine(I
) +
1520 " LC_SUB_UMBRELLA cmdsize too small");
1523 MachO::sub_umbrella_command S
=
1524 getStruct
<MachO::sub_umbrella_command
>(*this, Load
.Ptr
);
1525 if ((Err
= checkSubCommand(*this, Load
, I
, "LC_SUB_UMBRELLA",
1526 sizeof(MachO::sub_umbrella_command
),
1527 "sub_umbrella_command", S
.sub_umbrella
,
1530 } else if (Load
.C
.cmd
== MachO::LC_SUB_LIBRARY
) {
1531 if (Load
.C
.cmdsize
< sizeof(MachO::sub_library_command
)) {
1532 Err
= malformedError("load command " + Twine(I
) +
1533 " LC_SUB_LIBRARY cmdsize too small");
1536 MachO::sub_library_command S
=
1537 getStruct
<MachO::sub_library_command
>(*this, Load
.Ptr
);
1538 if ((Err
= checkSubCommand(*this, Load
, I
, "LC_SUB_LIBRARY",
1539 sizeof(MachO::sub_library_command
),
1540 "sub_library_command", S
.sub_library
,
1543 } else if (Load
.C
.cmd
== MachO::LC_SUB_CLIENT
) {
1544 if (Load
.C
.cmdsize
< sizeof(MachO::sub_client_command
)) {
1545 Err
= malformedError("load command " + Twine(I
) +
1546 " LC_SUB_CLIENT cmdsize too small");
1549 MachO::sub_client_command S
=
1550 getStruct
<MachO::sub_client_command
>(*this, Load
.Ptr
);
1551 if ((Err
= checkSubCommand(*this, Load
, I
, "LC_SUB_CLIENT",
1552 sizeof(MachO::sub_client_command
),
1553 "sub_client_command", S
.client
, "client")))
1555 } else if (Load
.C
.cmd
== MachO::LC_ROUTINES
) {
1556 if (Load
.C
.cmdsize
!= sizeof(MachO::routines_command
)) {
1557 Err
= malformedError("LC_ROUTINES command " + Twine(I
) +
1558 " has incorrect cmdsize");
1561 if (RoutinesLoadCmd
) {
1562 Err
= malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1566 RoutinesLoadCmd
= Load
.Ptr
;
1567 } else if (Load
.C
.cmd
== MachO::LC_ROUTINES_64
) {
1568 if (Load
.C
.cmdsize
!= sizeof(MachO::routines_command_64
)) {
1569 Err
= malformedError("LC_ROUTINES_64 command " + Twine(I
) +
1570 " has incorrect cmdsize");
1573 if (RoutinesLoadCmd
) {
1574 Err
= malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1578 RoutinesLoadCmd
= Load
.Ptr
;
1579 } else if (Load
.C
.cmd
== MachO::LC_UNIXTHREAD
) {
1580 if ((Err
= checkThreadCommand(*this, Load
, I
, "LC_UNIXTHREAD")))
1582 if (UnixThreadLoadCmd
) {
1583 Err
= malformedError("more than one LC_UNIXTHREAD command");
1586 UnixThreadLoadCmd
= Load
.Ptr
;
1587 } else if (Load
.C
.cmd
== MachO::LC_THREAD
) {
1588 if ((Err
= checkThreadCommand(*this, Load
, I
, "LC_THREAD")))
1590 // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
1591 } else if (Load
.C
.cmd
== MachO::LC_TWOLEVEL_HINTS
) {
1592 if ((Err
= checkTwoLevelHintsCommand(*this, Load
, I
,
1593 &TwoLevelHintsLoadCmd
, Elements
)))
1595 } else if (isLoadCommandObsolete(Load
.C
.cmd
)) {
1596 Err
= malformedError("load command " + Twine(I
) + " for cmd value of: " +
1597 Twine(Load
.C
.cmd
) + " is obsolete and not "
1601 // TODO: generate a error for unknown load commands by default. But still
1602 // need work out an approach to allow or not allow unknown values like this
1603 // as an option for some uses like lldb.
1604 if (I
< LoadCommandCount
- 1) {
1605 if (auto LoadOrErr
= getNextLoadCommandInfo(*this, I
, Load
))
1608 Err
= LoadOrErr
.takeError();
1613 if (!SymtabLoadCmd
) {
1614 if (DysymtabLoadCmd
) {
1615 Err
= malformedError("contains LC_DYSYMTAB load command without a "
1616 "LC_SYMTAB load command");
1619 } else if (DysymtabLoadCmd
) {
1620 MachO::symtab_command Symtab
=
1621 getStruct
<MachO::symtab_command
>(*this, SymtabLoadCmd
);
1622 MachO::dysymtab_command Dysymtab
=
1623 getStruct
<MachO::dysymtab_command
>(*this, DysymtabLoadCmd
);
1624 if (Dysymtab
.nlocalsym
!= 0 && Dysymtab
.ilocalsym
> Symtab
.nsyms
) {
1625 Err
= malformedError("ilocalsym in LC_DYSYMTAB load command "
1626 "extends past the end of the symbol table");
1629 uint64_t BigSize
= Dysymtab
.ilocalsym
;
1630 BigSize
+= Dysymtab
.nlocalsym
;
1631 if (Dysymtab
.nlocalsym
!= 0 && BigSize
> Symtab
.nsyms
) {
1632 Err
= malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
1633 "command extends past the end of the symbol table");
1636 if (Dysymtab
.nextdefsym
!= 0 && Dysymtab
.iextdefsym
> Symtab
.nsyms
) {
1637 Err
= malformedError("iextdefsym in LC_DYSYMTAB load command "
1638 "extends past the end of the symbol table");
1641 BigSize
= Dysymtab
.iextdefsym
;
1642 BigSize
+= Dysymtab
.nextdefsym
;
1643 if (Dysymtab
.nextdefsym
!= 0 && BigSize
> Symtab
.nsyms
) {
1644 Err
= malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
1645 "load command extends past the end of the symbol "
1649 if (Dysymtab
.nundefsym
!= 0 && Dysymtab
.iundefsym
> Symtab
.nsyms
) {
1650 Err
= malformedError("iundefsym in LC_DYSYMTAB load command "
1651 "extends past the end of the symbol table");
1654 BigSize
= Dysymtab
.iundefsym
;
1655 BigSize
+= Dysymtab
.nundefsym
;
1656 if (Dysymtab
.nundefsym
!= 0 && BigSize
> Symtab
.nsyms
) {
1657 Err
= malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
1658 " command extends past the end of the symbol table");
1662 if ((getHeader().filetype
== MachO::MH_DYLIB
||
1663 getHeader().filetype
== MachO::MH_DYLIB_STUB
) &&
1664 DyldIdLoadCmd
== nullptr) {
1665 Err
= malformedError("no LC_ID_DYLIB load command in dynamic library "
1669 assert(LoadCommands
.size() == LoadCommandCount
);
1671 Err
= Error::success();
1674 Error
MachOObjectFile::checkSymbolTable() const {
1677 MachO::mach_header_64 H_64
= MachOObjectFile::getHeader64();
1680 MachO::mach_header H
= MachOObjectFile::getHeader();
1687 uint64_t NValue
= 0;
1688 uint32_t SymbolIndex
= 0;
1689 MachO::symtab_command S
= getSymtabLoadCommand();
1690 for (const SymbolRef
&Symbol
: symbols()) {
1691 DataRefImpl SymDRI
= Symbol
.getRawDataRefImpl();
1693 MachO::nlist_64 STE_64
= getSymbol64TableEntry(SymDRI
);
1694 NType
= STE_64
.n_type
;
1695 NSect
= STE_64
.n_sect
;
1696 NDesc
= STE_64
.n_desc
;
1697 NStrx
= STE_64
.n_strx
;
1698 NValue
= STE_64
.n_value
;
1700 MachO::nlist STE
= getSymbolTableEntry(SymDRI
);
1705 NValue
= STE
.n_value
;
1707 if ((NType
& MachO::N_STAB
) == 0) {
1708 if ((NType
& MachO::N_TYPE
) == MachO::N_SECT
) {
1709 if (NSect
== 0 || NSect
> Sections
.size())
1710 return malformedError("bad section index: " + Twine((int)NSect
) +
1711 " for symbol at index " + Twine(SymbolIndex
));
1713 if ((NType
& MachO::N_TYPE
) == MachO::N_INDR
) {
1714 if (NValue
>= S
.strsize
)
1715 return malformedError("bad n_value: " + Twine((int)NValue
) + " past "
1716 "the end of string table, for N_INDR symbol at "
1717 "index " + Twine(SymbolIndex
));
1719 if ((Flags
& MachO::MH_TWOLEVEL
) == MachO::MH_TWOLEVEL
&&
1720 (((NType
& MachO::N_TYPE
) == MachO::N_UNDF
&& NValue
== 0) ||
1721 (NType
& MachO::N_TYPE
) == MachO::N_PBUD
)) {
1722 uint32_t LibraryOrdinal
= MachO::GET_LIBRARY_ORDINAL(NDesc
);
1723 if (LibraryOrdinal
!= 0 &&
1724 LibraryOrdinal
!= MachO::EXECUTABLE_ORDINAL
&&
1725 LibraryOrdinal
!= MachO::DYNAMIC_LOOKUP_ORDINAL
&&
1726 LibraryOrdinal
- 1 >= Libraries
.size() ) {
1727 return malformedError("bad library ordinal: " + Twine(LibraryOrdinal
) +
1728 " for symbol at index " + Twine(SymbolIndex
));
1732 if (NStrx
>= S
.strsize
)
1733 return malformedError("bad string table index: " + Twine((int)NStrx
) +
1734 " past the end of string table, for symbol at "
1735 "index " + Twine(SymbolIndex
));
1738 return Error::success();
1741 void MachOObjectFile::moveSymbolNext(DataRefImpl
&Symb
) const {
1742 unsigned SymbolTableEntrySize
= is64Bit() ?
1743 sizeof(MachO::nlist_64
) :
1744 sizeof(MachO::nlist
);
1745 Symb
.p
+= SymbolTableEntrySize
;
1748 Expected
<StringRef
> MachOObjectFile::getSymbolName(DataRefImpl Symb
) const {
1749 StringRef StringTable
= getStringTableData();
1750 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, Symb
);
1751 if (Entry
.n_strx
== 0)
1752 // A n_strx value of 0 indicates that no name is associated with a
1753 // particular symbol table entry.
1755 const char *Start
= &StringTable
.data()[Entry
.n_strx
];
1756 if (Start
< getData().begin() || Start
>= getData().end()) {
1757 return malformedError("bad string index: " + Twine(Entry
.n_strx
) +
1758 " for symbol at index " + Twine(getSymbolIndex(Symb
)));
1760 return StringRef(Start
);
1763 unsigned MachOObjectFile::getSectionType(SectionRef Sec
) const {
1764 DataRefImpl DRI
= Sec
.getRawDataRefImpl();
1765 uint32_t Flags
= getSectionFlags(*this, DRI
);
1766 return Flags
& MachO::SECTION_TYPE
;
1769 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym
) const {
1771 MachO::nlist_64 Entry
= getSymbol64TableEntry(Sym
);
1772 return Entry
.n_value
;
1774 MachO::nlist Entry
= getSymbolTableEntry(Sym
);
1775 return Entry
.n_value
;
1778 // getIndirectName() returns the name of the alias'ed symbol who's string table
1779 // index is in the n_value field.
1780 std::error_code
MachOObjectFile::getIndirectName(DataRefImpl Symb
,
1781 StringRef
&Res
) const {
1782 StringRef StringTable
= getStringTableData();
1783 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, Symb
);
1784 if ((Entry
.n_type
& MachO::N_TYPE
) != MachO::N_INDR
)
1785 return object_error::parse_failed
;
1786 uint64_t NValue
= getNValue(Symb
);
1787 if (NValue
>= StringTable
.size())
1788 return object_error::parse_failed
;
1789 const char *Start
= &StringTable
.data()[NValue
];
1790 Res
= StringRef(Start
);
1791 return std::error_code();
1794 uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym
) const {
1795 return getNValue(Sym
);
1798 Expected
<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym
) const {
1799 return getSymbolValue(Sym
);
1802 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI
) const {
1803 uint32_t flags
= getSymbolFlags(DRI
);
1804 if (flags
& SymbolRef::SF_Common
) {
1805 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, DRI
);
1806 return 1 << MachO::GET_COMM_ALIGN(Entry
.n_desc
);
1811 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI
) const {
1812 return getNValue(DRI
);
1815 Expected
<SymbolRef::Type
>
1816 MachOObjectFile::getSymbolType(DataRefImpl Symb
) const {
1817 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, Symb
);
1818 uint8_t n_type
= Entry
.n_type
;
1820 // If this is a STAB debugging symbol, we can do nothing more.
1821 if (n_type
& MachO::N_STAB
)
1822 return SymbolRef::ST_Debug
;
1824 switch (n_type
& MachO::N_TYPE
) {
1825 case MachO::N_UNDF
:
1826 return SymbolRef::ST_Unknown
;
1827 case MachO::N_SECT
:
1828 Expected
<section_iterator
> SecOrError
= getSymbolSection(Symb
);
1830 return SecOrError
.takeError();
1831 section_iterator Sec
= *SecOrError
;
1832 if (Sec
->isData() || Sec
->isBSS())
1833 return SymbolRef::ST_Data
;
1834 return SymbolRef::ST_Function
;
1836 return SymbolRef::ST_Other
;
1839 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI
) const {
1840 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, DRI
);
1842 uint8_t MachOType
= Entry
.n_type
;
1843 uint16_t MachOFlags
= Entry
.n_desc
;
1845 uint32_t Result
= SymbolRef::SF_None
;
1847 if ((MachOType
& MachO::N_TYPE
) == MachO::N_INDR
)
1848 Result
|= SymbolRef::SF_Indirect
;
1850 if (MachOType
& MachO::N_STAB
)
1851 Result
|= SymbolRef::SF_FormatSpecific
;
1853 if (MachOType
& MachO::N_EXT
) {
1854 Result
|= SymbolRef::SF_Global
;
1855 if ((MachOType
& MachO::N_TYPE
) == MachO::N_UNDF
) {
1857 Result
|= SymbolRef::SF_Common
;
1859 Result
|= SymbolRef::SF_Undefined
;
1862 if (!(MachOType
& MachO::N_PEXT
))
1863 Result
|= SymbolRef::SF_Exported
;
1866 if (MachOFlags
& (MachO::N_WEAK_REF
| MachO::N_WEAK_DEF
))
1867 Result
|= SymbolRef::SF_Weak
;
1869 if (MachOFlags
& (MachO::N_ARM_THUMB_DEF
))
1870 Result
|= SymbolRef::SF_Thumb
;
1872 if ((MachOType
& MachO::N_TYPE
) == MachO::N_ABS
)
1873 Result
|= SymbolRef::SF_Absolute
;
1878 Expected
<section_iterator
>
1879 MachOObjectFile::getSymbolSection(DataRefImpl Symb
) const {
1880 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, Symb
);
1881 uint8_t index
= Entry
.n_sect
;
1884 return section_end();
1886 DRI
.d
.a
= index
- 1;
1887 if (DRI
.d
.a
>= Sections
.size()){
1888 return malformedError("bad section index: " + Twine((int)index
) +
1889 " for symbol at index " + Twine(getSymbolIndex(Symb
)));
1891 return section_iterator(SectionRef(DRI
, this));
1894 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym
) const {
1895 MachO::nlist_base Entry
=
1896 getSymbolTableEntryBase(*this, Sym
.getRawDataRefImpl());
1897 return Entry
.n_sect
- 1;
1900 void MachOObjectFile::moveSectionNext(DataRefImpl
&Sec
) const {
1904 Expected
<StringRef
> MachOObjectFile::getSectionName(DataRefImpl Sec
) const {
1905 ArrayRef
<char> Raw
= getSectionRawName(Sec
);
1906 return parseSegmentOrSectionName(Raw
.data());
1909 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec
) const {
1911 return getSection64(Sec
).addr
;
1912 return getSection(Sec
).addr
;
1915 uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec
) const {
1919 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec
) const {
1920 // In the case if a malformed Mach-O file where the section offset is past
1921 // the end of the file or some part of the section size is past the end of
1922 // the file return a size of zero or a size that covers the rest of the file
1923 // but does not extend past the end of the file.
1924 uint32_t SectOffset
, SectType
;
1928 MachO::section_64 Sect
= getSection64(Sec
);
1929 SectOffset
= Sect
.offset
;
1930 SectSize
= Sect
.size
;
1931 SectType
= Sect
.flags
& MachO::SECTION_TYPE
;
1933 MachO::section Sect
= getSection(Sec
);
1934 SectOffset
= Sect
.offset
;
1935 SectSize
= Sect
.size
;
1936 SectType
= Sect
.flags
& MachO::SECTION_TYPE
;
1938 if (SectType
== MachO::S_ZEROFILL
|| SectType
== MachO::S_GB_ZEROFILL
)
1940 uint64_t FileSize
= getData().size();
1941 if (SectOffset
> FileSize
)
1943 if (FileSize
- SectOffset
< SectSize
)
1944 return FileSize
- SectOffset
;
1948 ArrayRef
<uint8_t> MachOObjectFile::getSectionContents(uint32_t Offset
,
1949 uint64_t Size
) const {
1950 return arrayRefFromStringRef(getData().substr(Offset
, Size
));
1953 Expected
<ArrayRef
<uint8_t>>
1954 MachOObjectFile::getSectionContents(DataRefImpl Sec
) const {
1959 MachO::section_64 Sect
= getSection64(Sec
);
1960 Offset
= Sect
.offset
;
1963 MachO::section Sect
= getSection(Sec
);
1964 Offset
= Sect
.offset
;
1968 return getSectionContents(Offset
, Size
);
1971 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec
) const {
1974 MachO::section_64 Sect
= getSection64(Sec
);
1977 MachO::section Sect
= getSection(Sec
);
1981 return uint64_t(1) << Align
;
1984 Expected
<SectionRef
> MachOObjectFile::getSection(unsigned SectionIndex
) const {
1985 if (SectionIndex
< 1 || SectionIndex
> Sections
.size())
1986 return malformedError("bad section index: " + Twine((int)SectionIndex
));
1989 DRI
.d
.a
= SectionIndex
- 1;
1990 return SectionRef(DRI
, this);
1993 Expected
<SectionRef
> MachOObjectFile::getSection(StringRef SectionName
) const {
1994 for (const SectionRef
&Section
: sections()) {
1995 auto NameOrErr
= Section
.getName();
1997 return NameOrErr
.takeError();
1998 if (*NameOrErr
== SectionName
)
2001 return errorCodeToError(object_error::parse_failed
);
2004 bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec
) const {
2008 bool MachOObjectFile::isSectionText(DataRefImpl Sec
) const {
2009 uint32_t Flags
= getSectionFlags(*this, Sec
);
2010 return Flags
& MachO::S_ATTR_PURE_INSTRUCTIONS
;
2013 bool MachOObjectFile::isSectionData(DataRefImpl Sec
) const {
2014 uint32_t Flags
= getSectionFlags(*this, Sec
);
2015 unsigned SectionType
= Flags
& MachO::SECTION_TYPE
;
2016 return !(Flags
& MachO::S_ATTR_PURE_INSTRUCTIONS
) &&
2017 !(SectionType
== MachO::S_ZEROFILL
||
2018 SectionType
== MachO::S_GB_ZEROFILL
);
2021 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec
) const {
2022 uint32_t Flags
= getSectionFlags(*this, Sec
);
2023 unsigned SectionType
= Flags
& MachO::SECTION_TYPE
;
2024 return !(Flags
& MachO::S_ATTR_PURE_INSTRUCTIONS
) &&
2025 (SectionType
== MachO::S_ZEROFILL
||
2026 SectionType
== MachO::S_GB_ZEROFILL
);
2029 unsigned MachOObjectFile::getSectionID(SectionRef Sec
) const {
2030 return Sec
.getRawDataRefImpl().d
.a
;
2033 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec
) const {
2034 uint32_t Flags
= getSectionFlags(*this, Sec
);
2035 unsigned SectionType
= Flags
& MachO::SECTION_TYPE
;
2036 return SectionType
== MachO::S_ZEROFILL
||
2037 SectionType
== MachO::S_GB_ZEROFILL
;
2040 bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec
) const {
2041 StringRef SegmentName
= getSectionFinalSegmentName(Sec
);
2042 if (Expected
<StringRef
> NameOrErr
= getSectionName(Sec
))
2043 return (SegmentName
== "__LLVM" && *NameOrErr
== "__bitcode");
2047 bool MachOObjectFile::isSectionStripped(DataRefImpl Sec
) const {
2049 return getSection64(Sec
).offset
== 0;
2050 return getSection(Sec
).offset
== 0;
2053 relocation_iterator
MachOObjectFile::section_rel_begin(DataRefImpl Sec
) const {
2057 return relocation_iterator(RelocationRef(Ret
, this));
2061 MachOObjectFile::section_rel_end(DataRefImpl Sec
) const {
2064 MachO::section_64 Sect
= getSection64(Sec
);
2067 MachO::section Sect
= getSection(Sec
);
2074 return relocation_iterator(RelocationRef(Ret
, this));
2077 relocation_iterator
MachOObjectFile::extrel_begin() const {
2079 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2080 Ret
.d
.a
= 0; // Would normally be a section index.
2081 Ret
.d
.b
= 0; // Index into the external relocations
2082 return relocation_iterator(RelocationRef(Ret
, this));
2085 relocation_iterator
MachOObjectFile::extrel_end() const {
2086 MachO::dysymtab_command DysymtabLoadCmd
= getDysymtabLoadCommand();
2088 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2089 Ret
.d
.a
= 0; // Would normally be a section index.
2090 Ret
.d
.b
= DysymtabLoadCmd
.nextrel
; // Index into the external relocations
2091 return relocation_iterator(RelocationRef(Ret
, this));
2094 relocation_iterator
MachOObjectFile::locrel_begin() const {
2096 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2097 Ret
.d
.a
= 1; // Would normally be a section index.
2098 Ret
.d
.b
= 0; // Index into the local relocations
2099 return relocation_iterator(RelocationRef(Ret
, this));
2102 relocation_iterator
MachOObjectFile::locrel_end() const {
2103 MachO::dysymtab_command DysymtabLoadCmd
= getDysymtabLoadCommand();
2105 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2106 Ret
.d
.a
= 1; // Would normally be a section index.
2107 Ret
.d
.b
= DysymtabLoadCmd
.nlocrel
; // Index into the local relocations
2108 return relocation_iterator(RelocationRef(Ret
, this));
2111 void MachOObjectFile::moveRelocationNext(DataRefImpl
&Rel
) const {
2115 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel
) const {
2116 assert((getHeader().filetype
== MachO::MH_OBJECT
||
2117 getHeader().filetype
== MachO::MH_KEXT_BUNDLE
) &&
2118 "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
2119 MachO::any_relocation_info RE
= getRelocation(Rel
);
2120 return getAnyRelocationAddress(RE
);
2124 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel
) const {
2125 MachO::any_relocation_info RE
= getRelocation(Rel
);
2126 if (isRelocationScattered(RE
))
2127 return symbol_end();
2129 uint32_t SymbolIdx
= getPlainRelocationSymbolNum(RE
);
2130 bool isExtern
= getPlainRelocationExternal(RE
);
2132 return symbol_end();
2134 MachO::symtab_command S
= getSymtabLoadCommand();
2135 unsigned SymbolTableEntrySize
= is64Bit() ?
2136 sizeof(MachO::nlist_64
) :
2137 sizeof(MachO::nlist
);
2138 uint64_t Offset
= S
.symoff
+ SymbolIdx
* SymbolTableEntrySize
;
2140 Sym
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Offset
));
2141 return symbol_iterator(SymbolRef(Sym
, this));
2145 MachOObjectFile::getRelocationSection(DataRefImpl Rel
) const {
2146 return section_iterator(getAnyRelocationSection(getRelocation(Rel
)));
2149 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel
) const {
2150 MachO::any_relocation_info RE
= getRelocation(Rel
);
2151 return getAnyRelocationType(RE
);
2154 void MachOObjectFile::getRelocationTypeName(
2155 DataRefImpl Rel
, SmallVectorImpl
<char> &Result
) const {
2157 uint64_t RType
= getRelocationType(Rel
);
2159 unsigned Arch
= this->getArch();
2163 static const char *const Table
[] = {
2164 "GENERIC_RELOC_VANILLA",
2165 "GENERIC_RELOC_PAIR",
2166 "GENERIC_RELOC_SECTDIFF",
2167 "GENERIC_RELOC_PB_LA_PTR",
2168 "GENERIC_RELOC_LOCAL_SECTDIFF",
2169 "GENERIC_RELOC_TLV" };
2177 case Triple::x86_64
: {
2178 static const char *const Table
[] = {
2179 "X86_64_RELOC_UNSIGNED",
2180 "X86_64_RELOC_SIGNED",
2181 "X86_64_RELOC_BRANCH",
2182 "X86_64_RELOC_GOT_LOAD",
2184 "X86_64_RELOC_SUBTRACTOR",
2185 "X86_64_RELOC_SIGNED_1",
2186 "X86_64_RELOC_SIGNED_2",
2187 "X86_64_RELOC_SIGNED_4",
2188 "X86_64_RELOC_TLV" };
2197 static const char *const Table
[] = {
2198 "ARM_RELOC_VANILLA",
2200 "ARM_RELOC_SECTDIFF",
2201 "ARM_RELOC_LOCAL_SECTDIFF",
2202 "ARM_RELOC_PB_LA_PTR",
2204 "ARM_THUMB_RELOC_BR22",
2205 "ARM_THUMB_32BIT_BRANCH",
2207 "ARM_RELOC_HALF_SECTDIFF" };
2215 case Triple::aarch64
:
2216 case Triple::aarch64_32
: {
2217 static const char *const Table
[] = {
2218 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
2219 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
2220 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
2221 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
2222 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
2223 "ARM64_RELOC_ADDEND"
2226 if (RType
>= array_lengthof(Table
))
2233 static const char *const Table
[] = {
2234 "PPC_RELOC_VANILLA",
2242 "PPC_RELOC_SECTDIFF",
2243 "PPC_RELOC_PB_LA_PTR",
2244 "PPC_RELOC_HI16_SECTDIFF",
2245 "PPC_RELOC_LO16_SECTDIFF",
2246 "PPC_RELOC_HA16_SECTDIFF",
2248 "PPC_RELOC_LO14_SECTDIFF",
2249 "PPC_RELOC_LOCAL_SECTDIFF" };
2257 case Triple::UnknownArch
:
2261 Result
.append(res
.begin(), res
.end());
2264 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel
) const {
2265 MachO::any_relocation_info RE
= getRelocation(Rel
);
2266 return getAnyRelocationLength(RE
);
2270 // guessLibraryShortName() is passed a name of a dynamic library and returns a
2271 // guess on what the short name is. Then name is returned as a substring of the
2272 // StringRef Name passed in. The name of the dynamic library is recognized as
2273 // a framework if it has one of the two following forms:
2274 // Foo.framework/Versions/A/Foo
2275 // Foo.framework/Foo
2276 // Where A and Foo can be any string. And may contain a trailing suffix
2277 // starting with an underbar. If the Name is recognized as a framework then
2278 // isFramework is set to true else it is set to false. If the Name has a
2279 // suffix then Suffix is set to the substring in Name that contains the suffix
2280 // else it is set to a NULL StringRef.
2282 // The Name of the dynamic library is recognized as a library name if it has
2283 // one of the two following forms:
2287 // The library may have a suffix trailing the name Foo of the form:
2288 // libFoo_profile.A.dylib
2289 // libFoo_profile.dylib
2290 // These dyld image suffixes are separated from the short name by a '_'
2291 // character. Because the '_' character is commonly used to separate words in
2292 // filenames guessLibraryShortName() cannot reliably separate a dylib's short
2293 // name from an arbitrary image suffix; imagine if both the short name and the
2294 // suffix contains an '_' character! To better deal with this ambiguity,
2295 // guessLibraryShortName() will recognize only "_debug" and "_profile" as valid
2296 // Suffix values. Calling code needs to be tolerant of guessLibraryShortName()
2297 // guessing incorrectly.
2299 // The Name of the dynamic library is also recognized as a library name if it
2300 // has the following form:
2303 // If the Name of the dynamic library is none of the forms above then a NULL
2304 // StringRef is returned.
2305 StringRef
MachOObjectFile::guessLibraryShortName(StringRef Name
,
2307 StringRef
&Suffix
) {
2308 StringRef Foo
, F
, DotFramework
, V
, Dylib
, Lib
, Dot
, Qtx
;
2309 size_t a
, b
, c
, d
, Idx
;
2311 isFramework
= false;
2312 Suffix
= StringRef();
2314 // Pull off the last component and make Foo point to it
2315 a
= Name
.rfind('/');
2316 if (a
== Name
.npos
|| a
== 0)
2318 Foo
= Name
.slice(a
+1, Name
.npos
);
2320 // Look for a suffix starting with a '_'
2321 Idx
= Foo
.rfind('_');
2322 if (Idx
!= Foo
.npos
&& Foo
.size() >= 2) {
2323 Suffix
= Foo
.slice(Idx
, Foo
.npos
);
2324 if (Suffix
!= "_debug" && Suffix
!= "_profile")
2325 Suffix
= StringRef();
2327 Foo
= Foo
.slice(0, Idx
);
2330 // First look for the form Foo.framework/Foo
2331 b
= Name
.rfind('/', a
);
2336 F
= Name
.slice(Idx
, Idx
+ Foo
.size());
2337 DotFramework
= Name
.slice(Idx
+ Foo
.size(),
2338 Idx
+ Foo
.size() + sizeof(".framework/")-1);
2339 if (F
== Foo
&& DotFramework
== ".framework/") {
2344 // Next look for the form Foo.framework/Versions/A/Foo
2347 c
= Name
.rfind('/', b
);
2348 if (c
== Name
.npos
|| c
== 0)
2350 V
= Name
.slice(c
+1, Name
.npos
);
2351 if (!V
.startswith("Versions/"))
2353 d
= Name
.rfind('/', c
);
2358 F
= Name
.slice(Idx
, Idx
+ Foo
.size());
2359 DotFramework
= Name
.slice(Idx
+ Foo
.size(),
2360 Idx
+ Foo
.size() + sizeof(".framework/")-1);
2361 if (F
== Foo
&& DotFramework
== ".framework/") {
2367 // pull off the suffix after the "." and make a point to it
2368 a
= Name
.rfind('.');
2369 if (a
== Name
.npos
|| a
== 0)
2371 Dylib
= Name
.slice(a
, Name
.npos
);
2372 if (Dylib
!= ".dylib")
2375 // First pull off the version letter for the form Foo.A.dylib if any.
2377 Dot
= Name
.slice(a
-2, a
-1);
2382 b
= Name
.rfind('/', a
);
2387 // ignore any suffix after an underbar like Foo_profile.A.dylib
2388 Idx
= Name
.rfind('_');
2389 if (Idx
!= Name
.npos
&& Idx
!= b
) {
2390 Lib
= Name
.slice(b
, Idx
);
2391 Suffix
= Name
.slice(Idx
, a
);
2392 if (Suffix
!= "_debug" && Suffix
!= "_profile") {
2393 Suffix
= StringRef();
2394 Lib
= Name
.slice(b
, a
);
2398 Lib
= Name
.slice(b
, a
);
2399 // There are incorrect library names of the form:
2400 // libATS.A_profile.dylib so check for these.
2401 if (Lib
.size() >= 3) {
2402 Dot
= Lib
.slice(Lib
.size()-2, Lib
.size()-1);
2404 Lib
= Lib
.slice(0, Lib
.size()-2);
2409 Qtx
= Name
.slice(a
, Name
.npos
);
2412 b
= Name
.rfind('/', a
);
2414 Lib
= Name
.slice(0, a
);
2416 Lib
= Name
.slice(b
+1, a
);
2417 // There are library names of the form: QT.A.qtx so check for these.
2418 if (Lib
.size() >= 3) {
2419 Dot
= Lib
.slice(Lib
.size()-2, Lib
.size()-1);
2421 Lib
= Lib
.slice(0, Lib
.size()-2);
2426 // getLibraryShortNameByIndex() is used to get the short name of the library
2427 // for an undefined symbol in a linked Mach-O binary that was linked with the
2428 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
2429 // It is passed the index (0 - based) of the library as translated from
2430 // GET_LIBRARY_ORDINAL (1 - based).
2431 std::error_code
MachOObjectFile::getLibraryShortNameByIndex(unsigned Index
,
2432 StringRef
&Res
) const {
2433 if (Index
>= Libraries
.size())
2434 return object_error::parse_failed
;
2436 // If the cache of LibrariesShortNames is not built up do that first for
2437 // all the Libraries.
2438 if (LibrariesShortNames
.size() == 0) {
2439 for (unsigned i
= 0; i
< Libraries
.size(); i
++) {
2441 getStructOrErr
<MachO::dylib_command
>(*this, Libraries
[i
]);
2443 return object_error::parse_failed
;
2444 MachO::dylib_command D
= CommandOrErr
.get();
2445 if (D
.dylib
.name
>= D
.cmdsize
)
2446 return object_error::parse_failed
;
2447 const char *P
= (const char *)(Libraries
[i
]) + D
.dylib
.name
;
2448 StringRef Name
= StringRef(P
);
2449 if (D
.dylib
.name
+Name
.size() >= D
.cmdsize
)
2450 return object_error::parse_failed
;
2453 StringRef shortName
= guessLibraryShortName(Name
, isFramework
, Suffix
);
2454 if (shortName
.empty())
2455 LibrariesShortNames
.push_back(Name
);
2457 LibrariesShortNames
.push_back(shortName
);
2461 Res
= LibrariesShortNames
[Index
];
2462 return std::error_code();
2465 uint32_t MachOObjectFile::getLibraryCount() const {
2466 return Libraries
.size();
2470 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel
) const {
2472 Sec
.d
.a
= Rel
->getRawDataRefImpl().d
.a
;
2473 return section_iterator(SectionRef(Sec
, this));
2476 basic_symbol_iterator
MachOObjectFile::symbol_begin() const {
2478 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2479 if (!SymtabLoadCmd
|| Symtab
.nsyms
== 0)
2480 return basic_symbol_iterator(SymbolRef(DRI
, this));
2482 return getSymbolByIndex(0);
2485 basic_symbol_iterator
MachOObjectFile::symbol_end() const {
2487 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2488 if (!SymtabLoadCmd
|| Symtab
.nsyms
== 0)
2489 return basic_symbol_iterator(SymbolRef(DRI
, this));
2491 unsigned SymbolTableEntrySize
= is64Bit() ?
2492 sizeof(MachO::nlist_64
) :
2493 sizeof(MachO::nlist
);
2494 unsigned Offset
= Symtab
.symoff
+
2495 Symtab
.nsyms
* SymbolTableEntrySize
;
2496 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Offset
));
2497 return basic_symbol_iterator(SymbolRef(DRI
, this));
2500 symbol_iterator
MachOObjectFile::getSymbolByIndex(unsigned Index
) const {
2501 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2502 if (!SymtabLoadCmd
|| Index
>= Symtab
.nsyms
)
2503 report_fatal_error("Requested symbol index is out of range.");
2504 unsigned SymbolTableEntrySize
=
2505 is64Bit() ? sizeof(MachO::nlist_64
) : sizeof(MachO::nlist
);
2507 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Symtab
.symoff
));
2508 DRI
.p
+= Index
* SymbolTableEntrySize
;
2509 return basic_symbol_iterator(SymbolRef(DRI
, this));
2512 uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb
) const {
2513 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2515 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2516 unsigned SymbolTableEntrySize
=
2517 is64Bit() ? sizeof(MachO::nlist_64
) : sizeof(MachO::nlist
);
2518 DataRefImpl DRIstart
;
2519 DRIstart
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Symtab
.symoff
));
2520 uint64_t Index
= (Symb
.p
- DRIstart
.p
) / SymbolTableEntrySize
;
2524 section_iterator
MachOObjectFile::section_begin() const {
2526 return section_iterator(SectionRef(DRI
, this));
2529 section_iterator
MachOObjectFile::section_end() const {
2531 DRI
.d
.a
= Sections
.size();
2532 return section_iterator(SectionRef(DRI
, this));
2535 uint8_t MachOObjectFile::getBytesInAddress() const {
2536 return is64Bit() ? 8 : 4;
2539 StringRef
MachOObjectFile::getFileFormatName() const {
2540 unsigned CPUType
= getCPUType(*this);
2543 case MachO::CPU_TYPE_I386
:
2544 return "Mach-O 32-bit i386";
2545 case MachO::CPU_TYPE_ARM
:
2546 return "Mach-O arm";
2547 case MachO::CPU_TYPE_ARM64_32
:
2548 return "Mach-O arm64 (ILP32)";
2549 case MachO::CPU_TYPE_POWERPC
:
2550 return "Mach-O 32-bit ppc";
2552 return "Mach-O 32-bit unknown";
2557 case MachO::CPU_TYPE_X86_64
:
2558 return "Mach-O 64-bit x86-64";
2559 case MachO::CPU_TYPE_ARM64
:
2560 return "Mach-O arm64";
2561 case MachO::CPU_TYPE_POWERPC64
:
2562 return "Mach-O 64-bit ppc64";
2564 return "Mach-O 64-bit unknown";
2568 Triple::ArchType
MachOObjectFile::getArch(uint32_t CPUType
) {
2570 case MachO::CPU_TYPE_I386
:
2572 case MachO::CPU_TYPE_X86_64
:
2573 return Triple::x86_64
;
2574 case MachO::CPU_TYPE_ARM
:
2576 case MachO::CPU_TYPE_ARM64
:
2577 return Triple::aarch64
;
2578 case MachO::CPU_TYPE_ARM64_32
:
2579 return Triple::aarch64_32
;
2580 case MachO::CPU_TYPE_POWERPC
:
2582 case MachO::CPU_TYPE_POWERPC64
:
2583 return Triple::ppc64
;
2585 return Triple::UnknownArch
;
2589 Triple
MachOObjectFile::getArchTriple(uint32_t CPUType
, uint32_t CPUSubType
,
2590 const char **McpuDefault
,
2591 const char **ArchFlag
) {
2593 *McpuDefault
= nullptr;
2595 *ArchFlag
= nullptr;
2598 case MachO::CPU_TYPE_I386
:
2599 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2600 case MachO::CPU_SUBTYPE_I386_ALL
:
2603 return Triple("i386-apple-darwin");
2607 case MachO::CPU_TYPE_X86_64
:
2608 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2609 case MachO::CPU_SUBTYPE_X86_64_ALL
:
2611 *ArchFlag
= "x86_64";
2612 return Triple("x86_64-apple-darwin");
2613 case MachO::CPU_SUBTYPE_X86_64_H
:
2615 *ArchFlag
= "x86_64h";
2616 return Triple("x86_64h-apple-darwin");
2620 case MachO::CPU_TYPE_ARM
:
2621 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2622 case MachO::CPU_SUBTYPE_ARM_V4T
:
2624 *ArchFlag
= "armv4t";
2625 return Triple("armv4t-apple-darwin");
2626 case MachO::CPU_SUBTYPE_ARM_V5TEJ
:
2628 *ArchFlag
= "armv5e";
2629 return Triple("armv5e-apple-darwin");
2630 case MachO::CPU_SUBTYPE_ARM_XSCALE
:
2632 *ArchFlag
= "xscale";
2633 return Triple("xscale-apple-darwin");
2634 case MachO::CPU_SUBTYPE_ARM_V6
:
2636 *ArchFlag
= "armv6";
2637 return Triple("armv6-apple-darwin");
2638 case MachO::CPU_SUBTYPE_ARM_V6M
:
2640 *McpuDefault
= "cortex-m0";
2642 *ArchFlag
= "armv6m";
2643 return Triple("armv6m-apple-darwin");
2644 case MachO::CPU_SUBTYPE_ARM_V7
:
2646 *ArchFlag
= "armv7";
2647 return Triple("armv7-apple-darwin");
2648 case MachO::CPU_SUBTYPE_ARM_V7EM
:
2650 *McpuDefault
= "cortex-m4";
2652 *ArchFlag
= "armv7em";
2653 return Triple("thumbv7em-apple-darwin");
2654 case MachO::CPU_SUBTYPE_ARM_V7K
:
2656 *McpuDefault
= "cortex-a7";
2658 *ArchFlag
= "armv7k";
2659 return Triple("armv7k-apple-darwin");
2660 case MachO::CPU_SUBTYPE_ARM_V7M
:
2662 *McpuDefault
= "cortex-m3";
2664 *ArchFlag
= "armv7m";
2665 return Triple("thumbv7m-apple-darwin");
2666 case MachO::CPU_SUBTYPE_ARM_V7S
:
2668 *McpuDefault
= "cortex-a7";
2670 *ArchFlag
= "armv7s";
2671 return Triple("armv7s-apple-darwin");
2675 case MachO::CPU_TYPE_ARM64
:
2676 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2677 case MachO::CPU_SUBTYPE_ARM64_ALL
:
2679 *McpuDefault
= "cyclone";
2681 *ArchFlag
= "arm64";
2682 return Triple("arm64-apple-darwin");
2686 case MachO::CPU_TYPE_ARM64_32
:
2687 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2688 case MachO::CPU_SUBTYPE_ARM64_32_V8
:
2690 *McpuDefault
= "cyclone";
2692 *ArchFlag
= "arm64_32";
2693 return Triple("arm64_32-apple-darwin");
2697 case MachO::CPU_TYPE_POWERPC
:
2698 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2699 case MachO::CPU_SUBTYPE_POWERPC_ALL
:
2702 return Triple("ppc-apple-darwin");
2706 case MachO::CPU_TYPE_POWERPC64
:
2707 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2708 case MachO::CPU_SUBTYPE_POWERPC_ALL
:
2710 *ArchFlag
= "ppc64";
2711 return Triple("ppc64-apple-darwin");
2720 Triple
MachOObjectFile::getHostArch() {
2721 return Triple(sys::getDefaultTargetTriple());
2724 bool MachOObjectFile::isValidArch(StringRef ArchFlag
) {
2725 auto validArchs
= getValidArchs();
2726 return llvm::find(validArchs
, ArchFlag
) != validArchs
.end();
2729 ArrayRef
<StringRef
> MachOObjectFile::getValidArchs() {
2730 static const std::array
<StringRef
, 17> validArchs
= {
2731 "i386", "x86_64", "x86_64h", "armv4t", "arm", "armv5e",
2732 "armv6", "armv6m", "armv7", "armv7em", "armv7k", "armv7m",
2733 "armv7s", "arm64", "arm64_32", "ppc", "ppc64",
2739 Triple::ArchType
MachOObjectFile::getArch() const {
2740 return getArch(getCPUType(*this));
2743 Triple
MachOObjectFile::getArchTriple(const char **McpuDefault
) const {
2744 return getArchTriple(Header
.cputype
, Header
.cpusubtype
, McpuDefault
);
2747 relocation_iterator
MachOObjectFile::section_rel_begin(unsigned Index
) const {
2750 return section_rel_begin(DRI
);
2753 relocation_iterator
MachOObjectFile::section_rel_end(unsigned Index
) const {
2756 return section_rel_end(DRI
);
2759 dice_iterator
MachOObjectFile::begin_dices() const {
2761 if (!DataInCodeLoadCmd
)
2762 return dice_iterator(DiceRef(DRI
, this));
2764 MachO::linkedit_data_command DicLC
= getDataInCodeLoadCommand();
2765 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, DicLC
.dataoff
));
2766 return dice_iterator(DiceRef(DRI
, this));
2769 dice_iterator
MachOObjectFile::end_dices() const {
2771 if (!DataInCodeLoadCmd
)
2772 return dice_iterator(DiceRef(DRI
, this));
2774 MachO::linkedit_data_command DicLC
= getDataInCodeLoadCommand();
2775 unsigned Offset
= DicLC
.dataoff
+ DicLC
.datasize
;
2776 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Offset
));
2777 return dice_iterator(DiceRef(DRI
, this));
2780 ExportEntry::ExportEntry(Error
*E
, const MachOObjectFile
*O
,
2781 ArrayRef
<uint8_t> T
) : E(E
), O(O
), Trie(T
) {}
2783 void ExportEntry::moveToFirst() {
2784 ErrorAsOutParameter
ErrAsOutParam(E
);
2788 pushDownUntilBottom();
2791 void ExportEntry::moveToEnd() {
2796 bool ExportEntry::operator==(const ExportEntry
&Other
) const {
2797 // Common case, one at end, other iterating from begin.
2798 if (Done
|| Other
.Done
)
2799 return (Done
== Other
.Done
);
2800 // Not equal if different stack sizes.
2801 if (Stack
.size() != Other
.Stack
.size())
2803 // Not equal if different cumulative strings.
2804 if (!CumulativeString
.equals(Other
.CumulativeString
))
2806 // Equal if all nodes in both stacks match.
2807 for (unsigned i
=0; i
< Stack
.size(); ++i
) {
2808 if (Stack
[i
].Start
!= Other
.Stack
[i
].Start
)
2814 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr
, const char **error
) {
2816 uint64_t Result
= decodeULEB128(Ptr
, &Count
, Trie
.end(), error
);
2818 if (Ptr
> Trie
.end())
2823 StringRef
ExportEntry::name() const {
2824 return CumulativeString
;
2827 uint64_t ExportEntry::flags() const {
2828 return Stack
.back().Flags
;
2831 uint64_t ExportEntry::address() const {
2832 return Stack
.back().Address
;
2835 uint64_t ExportEntry::other() const {
2836 return Stack
.back().Other
;
2839 StringRef
ExportEntry::otherName() const {
2840 const char* ImportName
= Stack
.back().ImportName
;
2842 return StringRef(ImportName
);
2846 uint32_t ExportEntry::nodeOffset() const {
2847 return Stack
.back().Start
- Trie
.begin();
2850 ExportEntry::NodeState::NodeState(const uint8_t *Ptr
)
2851 : Start(Ptr
), Current(Ptr
) {}
2853 void ExportEntry::pushNode(uint64_t offset
) {
2854 ErrorAsOutParameter
ErrAsOutParam(E
);
2855 const uint8_t *Ptr
= Trie
.begin() + offset
;
2856 NodeState
State(Ptr
);
2858 uint64_t ExportInfoSize
= readULEB128(State
.Current
, &error
);
2860 *E
= malformedError("export info size " + Twine(error
) +
2861 " in export trie data at node: 0x" +
2862 Twine::utohexstr(offset
));
2866 State
.IsExportNode
= (ExportInfoSize
!= 0);
2867 const uint8_t* Children
= State
.Current
+ ExportInfoSize
;
2868 if (Children
> Trie
.end()) {
2869 *E
= malformedError(
2870 "export info size: 0x" + Twine::utohexstr(ExportInfoSize
) +
2871 " in export trie data at node: 0x" + Twine::utohexstr(offset
) +
2872 " too big and extends past end of trie data");
2876 if (State
.IsExportNode
) {
2877 const uint8_t *ExportStart
= State
.Current
;
2878 State
.Flags
= readULEB128(State
.Current
, &error
);
2880 *E
= malformedError("flags " + Twine(error
) +
2881 " in export trie data at node: 0x" +
2882 Twine::utohexstr(offset
));
2886 uint64_t Kind
= State
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK
;
2887 if (State
.Flags
!= 0 &&
2888 (Kind
!= MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR
&&
2889 Kind
!= MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE
&&
2890 Kind
!= MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL
)) {
2891 *E
= malformedError(
2892 "unsupported exported symbol kind: " + Twine((int)Kind
) +
2893 " in flags: 0x" + Twine::utohexstr(State
.Flags
) +
2894 " in export trie data at node: 0x" + Twine::utohexstr(offset
));
2898 if (State
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_REEXPORT
) {
2900 State
.Other
= readULEB128(State
.Current
, &error
); // dylib ordinal
2902 *E
= malformedError("dylib ordinal of re-export " + Twine(error
) +
2903 " in export trie data at node: 0x" +
2904 Twine::utohexstr(offset
));
2909 if (State
.Other
> O
->getLibraryCount()) {
2910 *E
= malformedError(
2911 "bad library ordinal: " + Twine((int)State
.Other
) + " (max " +
2912 Twine((int)O
->getLibraryCount()) +
2913 ") in export trie data at node: 0x" + Twine::utohexstr(offset
));
2918 State
.ImportName
= reinterpret_cast<const char*>(State
.Current
);
2919 if (*State
.ImportName
== '\0') {
2922 const uint8_t *End
= State
.Current
+ 1;
2923 if (End
>= Trie
.end()) {
2924 *E
= malformedError("import name of re-export in export trie data at "
2926 Twine::utohexstr(offset
) +
2927 " starts past end of trie data");
2931 while(*End
!= '\0' && End
< Trie
.end())
2934 *E
= malformedError("import name of re-export in export trie data at "
2936 Twine::utohexstr(offset
) +
2937 " extends past end of trie data");
2941 State
.Current
= End
+ 1;
2944 State
.Address
= readULEB128(State
.Current
, &error
);
2946 *E
= malformedError("address " + Twine(error
) +
2947 " in export trie data at node: 0x" +
2948 Twine::utohexstr(offset
));
2952 if (State
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
) {
2953 State
.Other
= readULEB128(State
.Current
, &error
);
2955 *E
= malformedError("resolver of stub and resolver " + Twine(error
) +
2956 " in export trie data at node: 0x" +
2957 Twine::utohexstr(offset
));
2963 if(ExportStart
+ ExportInfoSize
!= State
.Current
) {
2964 *E
= malformedError(
2965 "inconsistant export info size: 0x" +
2966 Twine::utohexstr(ExportInfoSize
) + " where actual size was: 0x" +
2967 Twine::utohexstr(State
.Current
- ExportStart
) +
2968 " in export trie data at node: 0x" + Twine::utohexstr(offset
));
2973 State
.ChildCount
= *Children
;
2974 if (State
.ChildCount
!= 0 && Children
+ 1 >= Trie
.end()) {
2975 *E
= malformedError("byte for count of childern in export trie data at "
2977 Twine::utohexstr(offset
) +
2978 " extends past end of trie data");
2982 State
.Current
= Children
+ 1;
2983 State
.NextChildIndex
= 0;
2984 State
.ParentStringLength
= CumulativeString
.size();
2985 Stack
.push_back(State
);
2988 void ExportEntry::pushDownUntilBottom() {
2989 ErrorAsOutParameter
ErrAsOutParam(E
);
2991 while (Stack
.back().NextChildIndex
< Stack
.back().ChildCount
) {
2992 NodeState
&Top
= Stack
.back();
2993 CumulativeString
.resize(Top
.ParentStringLength
);
2994 for (;*Top
.Current
!= 0 && Top
.Current
< Trie
.end(); Top
.Current
++) {
2995 char C
= *Top
.Current
;
2996 CumulativeString
.push_back(C
);
2998 if (Top
.Current
>= Trie
.end()) {
2999 *E
= malformedError("edge sub-string in export trie data at node: 0x" +
3000 Twine::utohexstr(Top
.Start
- Trie
.begin()) +
3001 " for child #" + Twine((int)Top
.NextChildIndex
) +
3002 " extends past end of trie data");
3007 uint64_t childNodeIndex
= readULEB128(Top
.Current
, &error
);
3009 *E
= malformedError("child node offset " + Twine(error
) +
3010 " in export trie data at node: 0x" +
3011 Twine::utohexstr(Top
.Start
- Trie
.begin()));
3015 for (const NodeState
&node
: nodes()) {
3016 if (node
.Start
== Trie
.begin() + childNodeIndex
){
3017 *E
= malformedError("loop in childern in export trie data at node: 0x" +
3018 Twine::utohexstr(Top
.Start
- Trie
.begin()) +
3019 " back to node: 0x" +
3020 Twine::utohexstr(childNodeIndex
));
3025 Top
.NextChildIndex
+= 1;
3026 pushNode(childNodeIndex
);
3030 if (!Stack
.back().IsExportNode
) {
3031 *E
= malformedError("node is not an export node in export trie data at "
3033 Twine::utohexstr(Stack
.back().Start
- Trie
.begin()));
3039 // We have a trie data structure and need a way to walk it that is compatible
3040 // with the C++ iterator model. The solution is a non-recursive depth first
3041 // traversal where the iterator contains a stack of parent nodes along with a
3042 // string that is the accumulation of all edge strings along the parent chain
3045 // There is one "export" node for each exported symbol. But because some
3046 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
3047 // node may have child nodes too.
3049 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
3050 // child until hitting a node with no children (which is an export node or
3051 // else the trie is malformed). On the way down, each node is pushed on the
3052 // stack ivar. If there is no more ways down, it pops up one and tries to go
3053 // down a sibling path until a childless node is reached.
3054 void ExportEntry::moveNext() {
3055 assert(!Stack
.empty() && "ExportEntry::moveNext() with empty node stack");
3056 if (!Stack
.back().IsExportNode
) {
3057 *E
= malformedError("node is not an export node in export trie data at "
3059 Twine::utohexstr(Stack
.back().Start
- Trie
.begin()));
3065 while (!Stack
.empty()) {
3066 NodeState
&Top
= Stack
.back();
3067 if (Top
.NextChildIndex
< Top
.ChildCount
) {
3068 pushDownUntilBottom();
3069 // Now at the next export node.
3072 if (Top
.IsExportNode
) {
3073 // This node has no children but is itself an export node.
3074 CumulativeString
.resize(Top
.ParentStringLength
);
3083 iterator_range
<export_iterator
>
3084 MachOObjectFile::exports(Error
&E
, ArrayRef
<uint8_t> Trie
,
3085 const MachOObjectFile
*O
) {
3086 ExportEntry
Start(&E
, O
, Trie
);
3090 Start
.moveToFirst();
3092 ExportEntry
Finish(&E
, O
, Trie
);
3095 return make_range(export_iterator(Start
), export_iterator(Finish
));
3098 iterator_range
<export_iterator
> MachOObjectFile::exports(Error
&Err
) const {
3099 return exports(Err
, getDyldInfoExportsTrie(), this);
3102 MachORebaseEntry::MachORebaseEntry(Error
*E
, const MachOObjectFile
*O
,
3103 ArrayRef
<uint8_t> Bytes
, bool is64Bit
)
3104 : E(E
), O(O
), Opcodes(Bytes
), Ptr(Bytes
.begin()),
3105 PointerSize(is64Bit
? 8 : 4) {}
3107 void MachORebaseEntry::moveToFirst() {
3108 Ptr
= Opcodes
.begin();
3112 void MachORebaseEntry::moveToEnd() {
3113 Ptr
= Opcodes
.end();
3114 RemainingLoopCount
= 0;
3118 void MachORebaseEntry::moveNext() {
3119 ErrorAsOutParameter
ErrAsOutParam(E
);
3120 // If in the middle of some loop, move to next rebasing in loop.
3121 SegmentOffset
+= AdvanceAmount
;
3122 if (RemainingLoopCount
) {
3123 --RemainingLoopCount
;
3126 // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
3127 // pointer size. Therefore it is possible to reach the end without ever having
3128 // seen REBASE_OPCODE_DONE.
3129 if (Ptr
== Opcodes
.end()) {
3135 // Parse next opcode and set up next loop.
3136 const uint8_t *OpcodeStart
= Ptr
;
3137 uint8_t Byte
= *Ptr
++;
3138 uint8_t ImmValue
= Byte
& MachO::REBASE_IMMEDIATE_MASK
;
3139 uint8_t Opcode
= Byte
& MachO::REBASE_OPCODE_MASK
;
3140 uint32_t Count
, Skip
;
3141 const char *error
= nullptr;
3143 case MachO::REBASE_OPCODE_DONE
:
3147 DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n");
3149 case MachO::REBASE_OPCODE_SET_TYPE_IMM
:
3150 RebaseType
= ImmValue
;
3151 if (RebaseType
> MachO::REBASE_TYPE_TEXT_PCREL32
) {
3152 *E
= malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
3153 Twine((int)RebaseType
) + " for opcode at: 0x" +
3154 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3160 dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
3161 << "RebaseType=" << (int) RebaseType
<< "\n");
3163 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
:
3164 SegmentIndex
= ImmValue
;
3165 SegmentOffset
= readULEB128(&error
);
3167 *E
= malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3168 Twine(error
) + " for opcode at: 0x" +
3169 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3173 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3176 *E
= malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3177 Twine(error
) + " for opcode at: 0x" +
3178 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3184 dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3185 << "SegmentIndex=" << SegmentIndex
<< ", "
3186 << format("SegmentOffset=0x%06X", SegmentOffset
)
3189 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB
:
3190 SegmentOffset
+= readULEB128(&error
);
3192 *E
= malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3193 " for opcode at: 0x" +
3194 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3198 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3201 *E
= malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3202 " for opcode at: 0x" +
3203 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3207 DEBUG_WITH_TYPE("mach-o-rebase",
3208 dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
3209 << format("SegmentOffset=0x%06X",
3210 SegmentOffset
) << "\n");
3212 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED
:
3213 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3216 *E
= malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
3217 Twine(error
) + " for opcode at: 0x" +
3218 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3222 SegmentOffset
+= ImmValue
* PointerSize
;
3223 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3227 malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED "
3228 " (after adding immediate times the pointer size) " +
3229 Twine(error
) + " for opcode at: 0x" +
3230 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3234 DEBUG_WITH_TYPE("mach-o-rebase",
3235 dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
3236 << format("SegmentOffset=0x%06X",
3237 SegmentOffset
) << "\n");
3239 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES
:
3240 AdvanceAmount
= PointerSize
;
3244 RemainingLoopCount
= ImmValue
- 1;
3246 RemainingLoopCount
= 0;
3247 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3248 PointerSize
, Count
, Skip
);
3250 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
3251 Twine(error
) + " for opcode at: 0x" +
3252 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3258 dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
3259 << format("SegmentOffset=0x%06X", SegmentOffset
)
3260 << ", AdvanceAmount=" << AdvanceAmount
3261 << ", RemainingLoopCount=" << RemainingLoopCount
3264 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES
:
3265 AdvanceAmount
= PointerSize
;
3267 Count
= readULEB128(&error
);
3269 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3270 Twine(error
) + " for opcode at: 0x" +
3271 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3276 RemainingLoopCount
= Count
- 1;
3278 RemainingLoopCount
= 0;
3279 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3280 PointerSize
, Count
, Skip
);
3282 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3283 Twine(error
) + " for opcode at: 0x" +
3284 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3290 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
3291 << format("SegmentOffset=0x%06X", SegmentOffset
)
3292 << ", AdvanceAmount=" << AdvanceAmount
3293 << ", RemainingLoopCount=" << RemainingLoopCount
3296 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB
:
3297 Skip
= readULEB128(&error
);
3299 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3300 Twine(error
) + " for opcode at: 0x" +
3301 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3305 AdvanceAmount
= Skip
+ PointerSize
;
3307 RemainingLoopCount
= 0;
3308 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3309 PointerSize
, Count
, Skip
);
3311 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3312 Twine(error
) + " for opcode at: 0x" +
3313 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3319 dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
3320 << format("SegmentOffset=0x%06X", SegmentOffset
)
3321 << ", AdvanceAmount=" << AdvanceAmount
3322 << ", RemainingLoopCount=" << RemainingLoopCount
3325 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB
:
3326 Count
= readULEB128(&error
);
3328 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3330 Twine(error
) + " for opcode at: 0x" +
3331 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3336 RemainingLoopCount
= Count
- 1;
3338 RemainingLoopCount
= 0;
3339 Skip
= readULEB128(&error
);
3341 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3343 Twine(error
) + " for opcode at: 0x" +
3344 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3348 AdvanceAmount
= Skip
+ PointerSize
;
3350 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3351 PointerSize
, Count
, Skip
);
3353 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3355 Twine(error
) + " for opcode at: 0x" +
3356 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3362 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
3363 << format("SegmentOffset=0x%06X", SegmentOffset
)
3364 << ", AdvanceAmount=" << AdvanceAmount
3365 << ", RemainingLoopCount=" << RemainingLoopCount
3369 *E
= malformedError("bad rebase info (bad opcode value 0x" +
3370 Twine::utohexstr(Opcode
) + " for opcode at: 0x" +
3371 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3378 uint64_t MachORebaseEntry::readULEB128(const char **error
) {
3380 uint64_t Result
= decodeULEB128(Ptr
, &Count
, Opcodes
.end(), error
);
3382 if (Ptr
> Opcodes
.end())
3383 Ptr
= Opcodes
.end();
3387 int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex
; }
3389 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset
; }
3391 StringRef
MachORebaseEntry::typeName() const {
3392 switch (RebaseType
) {
3393 case MachO::REBASE_TYPE_POINTER
:
3395 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32
:
3396 return "text abs32";
3397 case MachO::REBASE_TYPE_TEXT_PCREL32
:
3398 return "text rel32";
3403 // For use with the SegIndex of a checked Mach-O Rebase entry
3404 // to get the segment name.
3405 StringRef
MachORebaseEntry::segmentName() const {
3406 return O
->BindRebaseSegmentName(SegmentIndex
);
3409 // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3410 // to get the section name.
3411 StringRef
MachORebaseEntry::sectionName() const {
3412 return O
->BindRebaseSectionName(SegmentIndex
, SegmentOffset
);
3415 // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3416 // to get the address.
3417 uint64_t MachORebaseEntry::address() const {
3418 return O
->BindRebaseAddress(SegmentIndex
, SegmentOffset
);
3421 bool MachORebaseEntry::operator==(const MachORebaseEntry
&Other
) const {
3422 #ifdef EXPENSIVE_CHECKS
3423 assert(Opcodes
== Other
.Opcodes
&& "compare iterators of different files");
3425 assert(Opcodes
.data() == Other
.Opcodes
.data() && "compare iterators of different files");
3427 return (Ptr
== Other
.Ptr
) &&
3428 (RemainingLoopCount
== Other
.RemainingLoopCount
) &&
3429 (Done
== Other
.Done
);
3432 iterator_range
<rebase_iterator
>
3433 MachOObjectFile::rebaseTable(Error
&Err
, MachOObjectFile
*O
,
3434 ArrayRef
<uint8_t> Opcodes
, bool is64
) {
3435 if (O
->BindRebaseSectionTable
== nullptr)
3436 O
->BindRebaseSectionTable
= std::make_unique
<BindRebaseSegInfo
>(O
);
3437 MachORebaseEntry
Start(&Err
, O
, Opcodes
, is64
);
3438 Start
.moveToFirst();
3440 MachORebaseEntry
Finish(&Err
, O
, Opcodes
, is64
);
3443 return make_range(rebase_iterator(Start
), rebase_iterator(Finish
));
3446 iterator_range
<rebase_iterator
> MachOObjectFile::rebaseTable(Error
&Err
) {
3447 return rebaseTable(Err
, this, getDyldInfoRebaseOpcodes(), is64Bit());
3450 MachOBindEntry::MachOBindEntry(Error
*E
, const MachOObjectFile
*O
,
3451 ArrayRef
<uint8_t> Bytes
, bool is64Bit
, Kind BK
)
3452 : E(E
), O(O
), Opcodes(Bytes
), Ptr(Bytes
.begin()),
3453 PointerSize(is64Bit
? 8 : 4), TableKind(BK
) {}
3455 void MachOBindEntry::moveToFirst() {
3456 Ptr
= Opcodes
.begin();
3460 void MachOBindEntry::moveToEnd() {
3461 Ptr
= Opcodes
.end();
3462 RemainingLoopCount
= 0;
3466 void MachOBindEntry::moveNext() {
3467 ErrorAsOutParameter
ErrAsOutParam(E
);
3468 // If in the middle of some loop, move to next binding in loop.
3469 SegmentOffset
+= AdvanceAmount
;
3470 if (RemainingLoopCount
) {
3471 --RemainingLoopCount
;
3474 // BIND_OPCODE_DONE is only used for padding if we are not aligned to
3475 // pointer size. Therefore it is possible to reach the end without ever having
3476 // seen BIND_OPCODE_DONE.
3477 if (Ptr
== Opcodes
.end()) {
3483 // Parse next opcode and set up next loop.
3484 const uint8_t *OpcodeStart
= Ptr
;
3485 uint8_t Byte
= *Ptr
++;
3486 uint8_t ImmValue
= Byte
& MachO::BIND_IMMEDIATE_MASK
;
3487 uint8_t Opcode
= Byte
& MachO::BIND_OPCODE_MASK
;
3488 int8_t SignExtended
;
3489 const uint8_t *SymStart
;
3490 uint32_t Count
, Skip
;
3491 const char *error
= nullptr;
3493 case MachO::BIND_OPCODE_DONE
:
3494 if (TableKind
== Kind::Lazy
) {
3495 // Lazying bindings have a DONE opcode between entries. Need to ignore
3496 // it to advance to next entry. But need not if this is last entry.
3497 bool NotLastEntry
= false;
3498 for (const uint8_t *P
= Ptr
; P
< Opcodes
.end(); ++P
) {
3500 NotLastEntry
= true;
3508 DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");
3510 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
:
3511 if (TableKind
== Kind::Weak
) {
3512 *E
= malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
3513 "weak bind table for opcode at: 0x" +
3514 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3519 LibraryOrdinalSet
= true;
3520 if (ImmValue
> O
->getLibraryCount()) {
3521 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3522 "library ordinal: " +
3523 Twine((int)ImmValue
) + " (max " +
3524 Twine((int)O
->getLibraryCount()) +
3525 ") for opcode at: 0x" +
3526 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3532 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
3533 << "Ordinal=" << Ordinal
<< "\n");
3535 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB
:
3536 if (TableKind
== Kind::Weak
) {
3537 *E
= malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
3538 "weak bind table for opcode at: 0x" +
3539 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3543 Ordinal
= readULEB128(&error
);
3544 LibraryOrdinalSet
= true;
3546 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
3547 Twine(error
) + " for opcode at: 0x" +
3548 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3552 if (Ordinal
> (int)O
->getLibraryCount()) {
3553 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3554 "library ordinal: " +
3555 Twine((int)Ordinal
) + " (max " +
3556 Twine((int)O
->getLibraryCount()) +
3557 ") for opcode at: 0x" +
3558 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3564 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
3565 << "Ordinal=" << Ordinal
<< "\n");
3567 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM
:
3568 if (TableKind
== Kind::Weak
) {
3569 *E
= malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
3570 "weak bind table for opcode at: 0x" +
3571 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3576 SignExtended
= MachO::BIND_OPCODE_MASK
| ImmValue
;
3577 Ordinal
= SignExtended
;
3578 if (Ordinal
< MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP
) {
3579 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
3580 "special ordinal: " +
3581 Twine((int)Ordinal
) + " for opcode at: 0x" +
3582 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3588 LibraryOrdinalSet
= true;
3591 dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
3592 << "Ordinal=" << Ordinal
<< "\n");
3594 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
:
3597 while (*Ptr
&& (Ptr
< Opcodes
.end())) {
3600 if (Ptr
== Opcodes
.end()) {
3601 *E
= malformedError(
3602 "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
3603 "symbol name extends past opcodes for opcode at: 0x" +
3604 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3608 SymbolName
= StringRef(reinterpret_cast<const char*>(SymStart
),
3613 dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
3614 << "SymbolName=" << SymbolName
<< "\n");
3615 if (TableKind
== Kind::Weak
) {
3616 if (ImmValue
& MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION
)
3620 case MachO::BIND_OPCODE_SET_TYPE_IMM
:
3621 BindType
= ImmValue
;
3622 if (ImmValue
> MachO::BIND_TYPE_TEXT_PCREL32
) {
3623 *E
= malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
3624 Twine((int)ImmValue
) + " for opcode at: 0x" +
3625 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3631 dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
3632 << "BindType=" << (int)BindType
<< "\n");
3634 case MachO::BIND_OPCODE_SET_ADDEND_SLEB
:
3635 Addend
= readSLEB128(&error
);
3637 *E
= malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error
) +
3638 " for opcode at: 0x" +
3639 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3645 dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
3646 << "Addend=" << Addend
<< "\n");
3648 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
:
3649 SegmentIndex
= ImmValue
;
3650 SegmentOffset
= readULEB128(&error
);
3652 *E
= malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3653 Twine(error
) + " for opcode at: 0x" +
3654 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3658 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3661 *E
= malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3662 Twine(error
) + " for opcode at: 0x" +
3663 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3669 dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3670 << "SegmentIndex=" << SegmentIndex
<< ", "
3671 << format("SegmentOffset=0x%06X", SegmentOffset
)
3674 case MachO::BIND_OPCODE_ADD_ADDR_ULEB
:
3675 SegmentOffset
+= readULEB128(&error
);
3677 *E
= malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3678 " for opcode at: 0x" +
3679 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3683 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3686 *E
= malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3687 " for opcode at: 0x" +
3688 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3692 DEBUG_WITH_TYPE("mach-o-bind",
3693 dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
3694 << format("SegmentOffset=0x%06X",
3695 SegmentOffset
) << "\n");
3697 case MachO::BIND_OPCODE_DO_BIND
:
3698 AdvanceAmount
= PointerSize
;
3699 RemainingLoopCount
= 0;
3700 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3703 *E
= malformedError("for BIND_OPCODE_DO_BIND " + Twine(error
) +
3704 " for opcode at: 0x" +
3705 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3709 if (SymbolName
== StringRef()) {
3710 *E
= malformedError(
3711 "for BIND_OPCODE_DO_BIND missing preceding "
3712 "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
3713 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3717 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
3719 malformedError("for BIND_OPCODE_DO_BIND missing preceding "
3720 "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3721 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3725 DEBUG_WITH_TYPE("mach-o-bind",
3726 dbgs() << "BIND_OPCODE_DO_BIND: "
3727 << format("SegmentOffset=0x%06X",
3728 SegmentOffset
) << "\n");
3730 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB
:
3731 if (TableKind
== Kind::Lazy
) {
3732 *E
= malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
3733 "lazy bind table for opcode at: 0x" +
3734 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3738 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3741 *E
= malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3742 Twine(error
) + " for opcode at: 0x" +
3743 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3747 if (SymbolName
== StringRef()) {
3748 *E
= malformedError(
3749 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3750 "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
3752 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3756 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
3757 *E
= malformedError(
3758 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3759 "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3760 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3764 AdvanceAmount
= readULEB128(&error
) + PointerSize
;
3766 *E
= malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3767 Twine(error
) + " for opcode at: 0x" +
3768 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3772 // Note, this is not really an error until the next bind but make no sense
3773 // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
3775 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
+
3776 AdvanceAmount
, PointerSize
);
3778 *E
= malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
3780 Twine(error
) + " for opcode at: 0x" +
3781 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3785 RemainingLoopCount
= 0;
3788 dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
3789 << format("SegmentOffset=0x%06X", SegmentOffset
)
3790 << ", AdvanceAmount=" << AdvanceAmount
3791 << ", RemainingLoopCount=" << RemainingLoopCount
3794 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED
:
3795 if (TableKind
== Kind::Lazy
) {
3796 *E
= malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
3797 "allowed in lazy bind table for opcode at: 0x" +
3798 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3802 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3805 *E
= malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
3806 Twine(error
) + " for opcode at: 0x" +
3807 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3811 if (SymbolName
== StringRef()) {
3812 *E
= malformedError(
3813 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3814 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3816 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3820 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
3821 *E
= malformedError(
3822 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3823 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3825 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3829 AdvanceAmount
= ImmValue
* PointerSize
+ PointerSize
;
3830 RemainingLoopCount
= 0;
3831 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
+
3832 AdvanceAmount
, PointerSize
);
3835 malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3836 " (after adding immediate times the pointer size) " +
3837 Twine(error
) + " for opcode at: 0x" +
3838 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3842 DEBUG_WITH_TYPE("mach-o-bind",
3844 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
3845 << format("SegmentOffset=0x%06X", SegmentOffset
) << "\n");
3847 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB
:
3848 if (TableKind
== Kind::Lazy
) {
3849 *E
= malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
3850 "allowed in lazy bind table for opcode at: 0x" +
3851 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3855 Count
= readULEB128(&error
);
3857 RemainingLoopCount
= Count
- 1;
3859 RemainingLoopCount
= 0;
3861 *E
= malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3863 Twine(error
) + " for opcode at: 0x" +
3864 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3868 Skip
= readULEB128(&error
);
3869 AdvanceAmount
= Skip
+ PointerSize
;
3871 *E
= malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3873 Twine(error
) + " for opcode at: 0x" +
3874 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3878 if (SymbolName
== StringRef()) {
3879 *E
= malformedError(
3880 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3881 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3883 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3887 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
3888 *E
= malformedError(
3889 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3890 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3892 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3896 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3897 PointerSize
, Count
, Skip
);
3900 malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
3901 Twine(error
) + " for opcode at: 0x" +
3902 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3908 dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
3909 << format("SegmentOffset=0x%06X", SegmentOffset
)
3910 << ", AdvanceAmount=" << AdvanceAmount
3911 << ", RemainingLoopCount=" << RemainingLoopCount
3915 *E
= malformedError("bad bind info (bad opcode value 0x" +
3916 Twine::utohexstr(Opcode
) + " for opcode at: 0x" +
3917 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3924 uint64_t MachOBindEntry::readULEB128(const char **error
) {
3926 uint64_t Result
= decodeULEB128(Ptr
, &Count
, Opcodes
.end(), error
);
3928 if (Ptr
> Opcodes
.end())
3929 Ptr
= Opcodes
.end();
3933 int64_t MachOBindEntry::readSLEB128(const char **error
) {
3935 int64_t Result
= decodeSLEB128(Ptr
, &Count
, Opcodes
.end(), error
);
3937 if (Ptr
> Opcodes
.end())
3938 Ptr
= Opcodes
.end();
3942 int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex
; }
3944 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset
; }
3946 StringRef
MachOBindEntry::typeName() const {
3948 case MachO::BIND_TYPE_POINTER
:
3950 case MachO::BIND_TYPE_TEXT_ABSOLUTE32
:
3951 return "text abs32";
3952 case MachO::BIND_TYPE_TEXT_PCREL32
:
3953 return "text rel32";
3958 StringRef
MachOBindEntry::symbolName() const { return SymbolName
; }
3960 int64_t MachOBindEntry::addend() const { return Addend
; }
3962 uint32_t MachOBindEntry::flags() const { return Flags
; }
3964 int MachOBindEntry::ordinal() const { return Ordinal
; }
3966 // For use with the SegIndex of a checked Mach-O Bind entry
3967 // to get the segment name.
3968 StringRef
MachOBindEntry::segmentName() const {
3969 return O
->BindRebaseSegmentName(SegmentIndex
);
3972 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3973 // to get the section name.
3974 StringRef
MachOBindEntry::sectionName() const {
3975 return O
->BindRebaseSectionName(SegmentIndex
, SegmentOffset
);
3978 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3979 // to get the address.
3980 uint64_t MachOBindEntry::address() const {
3981 return O
->BindRebaseAddress(SegmentIndex
, SegmentOffset
);
3984 bool MachOBindEntry::operator==(const MachOBindEntry
&Other
) const {
3985 #ifdef EXPENSIVE_CHECKS
3986 assert(Opcodes
== Other
.Opcodes
&& "compare iterators of different files");
3988 assert(Opcodes
.data() == Other
.Opcodes
.data() && "compare iterators of different files");
3990 return (Ptr
== Other
.Ptr
) &&
3991 (RemainingLoopCount
== Other
.RemainingLoopCount
) &&
3992 (Done
== Other
.Done
);
3995 // Build table of sections so SegIndex/SegOffset pairs can be translated.
3996 BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile
*Obj
) {
3997 uint32_t CurSegIndex
= Obj
->hasPageZeroSegment() ? 1 : 0;
3998 StringRef CurSegName
;
3999 uint64_t CurSegAddress
;
4000 for (const SectionRef
&Section
: Obj
->sections()) {
4002 Expected
<StringRef
> NameOrErr
= Section
.getName();
4004 consumeError(NameOrErr
.takeError());
4006 Info
.SectionName
= *NameOrErr
;
4007 Info
.Address
= Section
.getAddress();
4008 Info
.Size
= Section
.getSize();
4010 Obj
->getSectionFinalSegmentName(Section
.getRawDataRefImpl());
4011 if (!Info
.SegmentName
.equals(CurSegName
)) {
4013 CurSegName
= Info
.SegmentName
;
4014 CurSegAddress
= Info
.Address
;
4016 Info
.SegmentIndex
= CurSegIndex
- 1;
4017 Info
.OffsetInSegment
= Info
.Address
- CurSegAddress
;
4018 Info
.SegmentStartAddress
= CurSegAddress
;
4019 Sections
.push_back(Info
);
4021 MaxSegIndex
= CurSegIndex
;
4024 // For use with a SegIndex, SegOffset, and PointerSize triple in
4025 // MachOBindEntry::moveNext() to validate a MachOBindEntry or MachORebaseEntry.
4027 // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
4028 // that fully contains a pointer at that location. Multiple fixups in a bind
4029 // (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can
4030 // be tested via the Count and Skip parameters.
4031 const char * BindRebaseSegInfo::checkSegAndOffsets(int32_t SegIndex
,
4033 uint8_t PointerSize
,
4037 return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
4038 if (SegIndex
>= MaxSegIndex
)
4039 return "bad segIndex (too large)";
4040 for (uint32_t i
= 0; i
< Count
; ++i
) {
4041 uint32_t Start
= SegOffset
+ i
* (PointerSize
+ Skip
);
4042 uint32_t End
= Start
+ PointerSize
;
4044 for (const SectionInfo
&SI
: Sections
) {
4045 if (SI
.SegmentIndex
!= SegIndex
)
4047 if ((SI
.OffsetInSegment
<=Start
) && (Start
<(SI
.OffsetInSegment
+SI
.Size
))) {
4048 if (End
<= SI
.OffsetInSegment
+ SI
.Size
) {
4053 return "bad offset, extends beyond section boundary";
4057 return "bad offset, not in section";
4062 // For use with the SegIndex of a checked Mach-O Bind or Rebase entry
4063 // to get the segment name.
4064 StringRef
BindRebaseSegInfo::segmentName(int32_t SegIndex
) {
4065 for (const SectionInfo
&SI
: Sections
) {
4066 if (SI
.SegmentIndex
== SegIndex
)
4067 return SI
.SegmentName
;
4069 llvm_unreachable("invalid SegIndex");
4072 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4073 // to get the SectionInfo.
4074 const BindRebaseSegInfo::SectionInfo
&BindRebaseSegInfo::findSection(
4075 int32_t SegIndex
, uint64_t SegOffset
) {
4076 for (const SectionInfo
&SI
: Sections
) {
4077 if (SI
.SegmentIndex
!= SegIndex
)
4079 if (SI
.OffsetInSegment
> SegOffset
)
4081 if (SegOffset
>= (SI
.OffsetInSegment
+ SI
.Size
))
4085 llvm_unreachable("SegIndex and SegOffset not in any section");
4088 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4089 // entry to get the section name.
4090 StringRef
BindRebaseSegInfo::sectionName(int32_t SegIndex
,
4091 uint64_t SegOffset
) {
4092 return findSection(SegIndex
, SegOffset
).SectionName
;
4095 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4096 // entry to get the address.
4097 uint64_t BindRebaseSegInfo::address(uint32_t SegIndex
, uint64_t OffsetInSeg
) {
4098 const SectionInfo
&SI
= findSection(SegIndex
, OffsetInSeg
);
4099 return SI
.SegmentStartAddress
+ OffsetInSeg
;
4102 iterator_range
<bind_iterator
>
4103 MachOObjectFile::bindTable(Error
&Err
, MachOObjectFile
*O
,
4104 ArrayRef
<uint8_t> Opcodes
, bool is64
,
4105 MachOBindEntry::Kind BKind
) {
4106 if (O
->BindRebaseSectionTable
== nullptr)
4107 O
->BindRebaseSectionTable
= std::make_unique
<BindRebaseSegInfo
>(O
);
4108 MachOBindEntry
Start(&Err
, O
, Opcodes
, is64
, BKind
);
4109 Start
.moveToFirst();
4111 MachOBindEntry
Finish(&Err
, O
, Opcodes
, is64
, BKind
);
4114 return make_range(bind_iterator(Start
), bind_iterator(Finish
));
4117 iterator_range
<bind_iterator
> MachOObjectFile::bindTable(Error
&Err
) {
4118 return bindTable(Err
, this, getDyldInfoBindOpcodes(), is64Bit(),
4119 MachOBindEntry::Kind::Regular
);
4122 iterator_range
<bind_iterator
> MachOObjectFile::lazyBindTable(Error
&Err
) {
4123 return bindTable(Err
, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
4124 MachOBindEntry::Kind::Lazy
);
4127 iterator_range
<bind_iterator
> MachOObjectFile::weakBindTable(Error
&Err
) {
4128 return bindTable(Err
, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
4129 MachOBindEntry::Kind::Weak
);
4132 MachOObjectFile::load_command_iterator
4133 MachOObjectFile::begin_load_commands() const {
4134 return LoadCommands
.begin();
4137 MachOObjectFile::load_command_iterator
4138 MachOObjectFile::end_load_commands() const {
4139 return LoadCommands
.end();
4142 iterator_range
<MachOObjectFile::load_command_iterator
>
4143 MachOObjectFile::load_commands() const {
4144 return make_range(begin_load_commands(), end_load_commands());
4148 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec
) const {
4149 ArrayRef
<char> Raw
= getSectionRawFinalSegmentName(Sec
);
4150 return parseSegmentOrSectionName(Raw
.data());
4154 MachOObjectFile::getSectionRawName(DataRefImpl Sec
) const {
4155 assert(Sec
.d
.a
< Sections
.size() && "Should have detected this earlier");
4156 const section_base
*Base
=
4157 reinterpret_cast<const section_base
*>(Sections
[Sec
.d
.a
]);
4158 return makeArrayRef(Base
->sectname
);
4162 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec
) const {
4163 assert(Sec
.d
.a
< Sections
.size() && "Should have detected this earlier");
4164 const section_base
*Base
=
4165 reinterpret_cast<const section_base
*>(Sections
[Sec
.d
.a
]);
4166 return makeArrayRef(Base
->segname
);
4170 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info
&RE
)
4172 if (getCPUType(*this) == MachO::CPU_TYPE_X86_64
)
4174 return getPlainRelocationAddress(RE
) & MachO::R_SCATTERED
;
4177 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
4178 const MachO::any_relocation_info
&RE
) const {
4179 if (isLittleEndian())
4180 return RE
.r_word1
& 0xffffff;
4181 return RE
.r_word1
>> 8;
4184 bool MachOObjectFile::getPlainRelocationExternal(
4185 const MachO::any_relocation_info
&RE
) const {
4186 if (isLittleEndian())
4187 return (RE
.r_word1
>> 27) & 1;
4188 return (RE
.r_word1
>> 4) & 1;
4191 bool MachOObjectFile::getScatteredRelocationScattered(
4192 const MachO::any_relocation_info
&RE
) const {
4193 return RE
.r_word0
>> 31;
4196 uint32_t MachOObjectFile::getScatteredRelocationValue(
4197 const MachO::any_relocation_info
&RE
) const {
4201 uint32_t MachOObjectFile::getScatteredRelocationType(
4202 const MachO::any_relocation_info
&RE
) const {
4203 return (RE
.r_word0
>> 24) & 0xf;
4206 unsigned MachOObjectFile::getAnyRelocationAddress(
4207 const MachO::any_relocation_info
&RE
) const {
4208 if (isRelocationScattered(RE
))
4209 return getScatteredRelocationAddress(RE
);
4210 return getPlainRelocationAddress(RE
);
4213 unsigned MachOObjectFile::getAnyRelocationPCRel(
4214 const MachO::any_relocation_info
&RE
) const {
4215 if (isRelocationScattered(RE
))
4216 return getScatteredRelocationPCRel(RE
);
4217 return getPlainRelocationPCRel(*this, RE
);
4220 unsigned MachOObjectFile::getAnyRelocationLength(
4221 const MachO::any_relocation_info
&RE
) const {
4222 if (isRelocationScattered(RE
))
4223 return getScatteredRelocationLength(RE
);
4224 return getPlainRelocationLength(*this, RE
);
4228 MachOObjectFile::getAnyRelocationType(
4229 const MachO::any_relocation_info
&RE
) const {
4230 if (isRelocationScattered(RE
))
4231 return getScatteredRelocationType(RE
);
4232 return getPlainRelocationType(*this, RE
);
4236 MachOObjectFile::getAnyRelocationSection(
4237 const MachO::any_relocation_info
&RE
) const {
4238 if (isRelocationScattered(RE
) || getPlainRelocationExternal(RE
))
4239 return *section_end();
4240 unsigned SecNum
= getPlainRelocationSymbolNum(RE
);
4241 if (SecNum
== MachO::R_ABS
|| SecNum
> Sections
.size())
4242 return *section_end();
4244 DRI
.d
.a
= SecNum
- 1;
4245 return SectionRef(DRI
, this);
4248 MachO::section
MachOObjectFile::getSection(DataRefImpl DRI
) const {
4249 assert(DRI
.d
.a
< Sections
.size() && "Should have detected this earlier");
4250 return getStruct
<MachO::section
>(*this, Sections
[DRI
.d
.a
]);
4253 MachO::section_64
MachOObjectFile::getSection64(DataRefImpl DRI
) const {
4254 assert(DRI
.d
.a
< Sections
.size() && "Should have detected this earlier");
4255 return getStruct
<MachO::section_64
>(*this, Sections
[DRI
.d
.a
]);
4258 MachO::section
MachOObjectFile::getSection(const LoadCommandInfo
&L
,
4259 unsigned Index
) const {
4260 const char *Sec
= getSectionPtr(*this, L
, Index
);
4261 return getStruct
<MachO::section
>(*this, Sec
);
4264 MachO::section_64
MachOObjectFile::getSection64(const LoadCommandInfo
&L
,
4265 unsigned Index
) const {
4266 const char *Sec
= getSectionPtr(*this, L
, Index
);
4267 return getStruct
<MachO::section_64
>(*this, Sec
);
4271 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI
) const {
4272 const char *P
= reinterpret_cast<const char *>(DRI
.p
);
4273 return getStruct
<MachO::nlist
>(*this, P
);
4277 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI
) const {
4278 const char *P
= reinterpret_cast<const char *>(DRI
.p
);
4279 return getStruct
<MachO::nlist_64
>(*this, P
);
4282 MachO::linkedit_data_command
4283 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo
&L
) const {
4284 return getStruct
<MachO::linkedit_data_command
>(*this, L
.Ptr
);
4287 MachO::segment_command
4288 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo
&L
) const {
4289 return getStruct
<MachO::segment_command
>(*this, L
.Ptr
);
4292 MachO::segment_command_64
4293 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo
&L
) const {
4294 return getStruct
<MachO::segment_command_64
>(*this, L
.Ptr
);
4297 MachO::linker_option_command
4298 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo
&L
) const {
4299 return getStruct
<MachO::linker_option_command
>(*this, L
.Ptr
);
4302 MachO::version_min_command
4303 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo
&L
) const {
4304 return getStruct
<MachO::version_min_command
>(*this, L
.Ptr
);
4308 MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo
&L
) const {
4309 return getStruct
<MachO::note_command
>(*this, L
.Ptr
);
4312 MachO::build_version_command
4313 MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo
&L
) const {
4314 return getStruct
<MachO::build_version_command
>(*this, L
.Ptr
);
4317 MachO::build_tool_version
4318 MachOObjectFile::getBuildToolVersion(unsigned index
) const {
4319 return getStruct
<MachO::build_tool_version
>(*this, BuildTools
[index
]);
4322 MachO::dylib_command
4323 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo
&L
) const {
4324 return getStruct
<MachO::dylib_command
>(*this, L
.Ptr
);
4327 MachO::dyld_info_command
4328 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo
&L
) const {
4329 return getStruct
<MachO::dyld_info_command
>(*this, L
.Ptr
);
4332 MachO::dylinker_command
4333 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo
&L
) const {
4334 return getStruct
<MachO::dylinker_command
>(*this, L
.Ptr
);
4338 MachOObjectFile::getUuidCommand(const LoadCommandInfo
&L
) const {
4339 return getStruct
<MachO::uuid_command
>(*this, L
.Ptr
);
4342 MachO::rpath_command
4343 MachOObjectFile::getRpathCommand(const LoadCommandInfo
&L
) const {
4344 return getStruct
<MachO::rpath_command
>(*this, L
.Ptr
);
4347 MachO::source_version_command
4348 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo
&L
) const {
4349 return getStruct
<MachO::source_version_command
>(*this, L
.Ptr
);
4352 MachO::entry_point_command
4353 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo
&L
) const {
4354 return getStruct
<MachO::entry_point_command
>(*this, L
.Ptr
);
4357 MachO::encryption_info_command
4358 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo
&L
) const {
4359 return getStruct
<MachO::encryption_info_command
>(*this, L
.Ptr
);
4362 MachO::encryption_info_command_64
4363 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo
&L
) const {
4364 return getStruct
<MachO::encryption_info_command_64
>(*this, L
.Ptr
);
4367 MachO::sub_framework_command
4368 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo
&L
) const {
4369 return getStruct
<MachO::sub_framework_command
>(*this, L
.Ptr
);
4372 MachO::sub_umbrella_command
4373 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo
&L
) const {
4374 return getStruct
<MachO::sub_umbrella_command
>(*this, L
.Ptr
);
4377 MachO::sub_library_command
4378 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo
&L
) const {
4379 return getStruct
<MachO::sub_library_command
>(*this, L
.Ptr
);
4382 MachO::sub_client_command
4383 MachOObjectFile::getSubClientCommand(const LoadCommandInfo
&L
) const {
4384 return getStruct
<MachO::sub_client_command
>(*this, L
.Ptr
);
4387 MachO::routines_command
4388 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo
&L
) const {
4389 return getStruct
<MachO::routines_command
>(*this, L
.Ptr
);
4392 MachO::routines_command_64
4393 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo
&L
) const {
4394 return getStruct
<MachO::routines_command_64
>(*this, L
.Ptr
);
4397 MachO::thread_command
4398 MachOObjectFile::getThreadCommand(const LoadCommandInfo
&L
) const {
4399 return getStruct
<MachO::thread_command
>(*this, L
.Ptr
);
4402 MachO::any_relocation_info
4403 MachOObjectFile::getRelocation(DataRefImpl Rel
) const {
4405 if (getHeader().filetype
== MachO::MH_OBJECT
) {
4409 MachO::section_64 Sect
= getSection64(Sec
);
4410 Offset
= Sect
.reloff
;
4412 MachO::section Sect
= getSection(Sec
);
4413 Offset
= Sect
.reloff
;
4416 MachO::dysymtab_command DysymtabLoadCmd
= getDysymtabLoadCommand();
4418 Offset
= DysymtabLoadCmd
.extreloff
; // Offset to the external relocations
4420 Offset
= DysymtabLoadCmd
.locreloff
; // Offset to the local relocations
4423 auto P
= reinterpret_cast<const MachO::any_relocation_info
*>(
4424 getPtr(*this, Offset
)) + Rel
.d
.b
;
4425 return getStruct
<MachO::any_relocation_info
>(
4426 *this, reinterpret_cast<const char *>(P
));
4429 MachO::data_in_code_entry
4430 MachOObjectFile::getDice(DataRefImpl Rel
) const {
4431 const char *P
= reinterpret_cast<const char *>(Rel
.p
);
4432 return getStruct
<MachO::data_in_code_entry
>(*this, P
);
4435 const MachO::mach_header
&MachOObjectFile::getHeader() const {
4439 const MachO::mach_header_64
&MachOObjectFile::getHeader64() const {
4444 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
4445 const MachO::dysymtab_command
&DLC
,
4446 unsigned Index
) const {
4447 uint64_t Offset
= DLC
.indirectsymoff
+ Index
* sizeof(uint32_t);
4448 return getStruct
<uint32_t>(*this, getPtr(*this, Offset
));
4451 MachO::data_in_code_entry
4452 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset
,
4453 unsigned Index
) const {
4454 uint64_t Offset
= DataOffset
+ Index
* sizeof(MachO::data_in_code_entry
);
4455 return getStruct
<MachO::data_in_code_entry
>(*this, getPtr(*this, Offset
));
4458 MachO::symtab_command
MachOObjectFile::getSymtabLoadCommand() const {
4460 return getStruct
<MachO::symtab_command
>(*this, SymtabLoadCmd
);
4462 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
4463 MachO::symtab_command Cmd
;
4464 Cmd
.cmd
= MachO::LC_SYMTAB
;
4465 Cmd
.cmdsize
= sizeof(MachO::symtab_command
);
4473 MachO::dysymtab_command
MachOObjectFile::getDysymtabLoadCommand() const {
4474 if (DysymtabLoadCmd
)
4475 return getStruct
<MachO::dysymtab_command
>(*this, DysymtabLoadCmd
);
4477 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
4478 MachO::dysymtab_command Cmd
;
4479 Cmd
.cmd
= MachO::LC_DYSYMTAB
;
4480 Cmd
.cmdsize
= sizeof(MachO::dysymtab_command
);
4491 Cmd
.extrefsymoff
= 0;
4492 Cmd
.nextrefsyms
= 0;
4493 Cmd
.indirectsymoff
= 0;
4494 Cmd
.nindirectsyms
= 0;
4502 MachO::linkedit_data_command
4503 MachOObjectFile::getDataInCodeLoadCommand() const {
4504 if (DataInCodeLoadCmd
)
4505 return getStruct
<MachO::linkedit_data_command
>(*this, DataInCodeLoadCmd
);
4507 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
4508 MachO::linkedit_data_command Cmd
;
4509 Cmd
.cmd
= MachO::LC_DATA_IN_CODE
;
4510 Cmd
.cmdsize
= sizeof(MachO::linkedit_data_command
);
4516 MachO::linkedit_data_command
4517 MachOObjectFile::getLinkOptHintsLoadCommand() const {
4518 if (LinkOptHintsLoadCmd
)
4519 return getStruct
<MachO::linkedit_data_command
>(*this, LinkOptHintsLoadCmd
);
4521 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
4523 MachO::linkedit_data_command Cmd
;
4524 Cmd
.cmd
= MachO::LC_LINKER_OPTIMIZATION_HINT
;
4525 Cmd
.cmdsize
= sizeof(MachO::linkedit_data_command
);
4531 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
4532 if (!DyldInfoLoadCmd
)
4535 auto DyldInfoOrErr
=
4536 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4539 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4540 const uint8_t *Ptr
=
4541 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.rebase_off
));
4542 return makeArrayRef(Ptr
, DyldInfo
.rebase_size
);
4545 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
4546 if (!DyldInfoLoadCmd
)
4549 auto DyldInfoOrErr
=
4550 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4553 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4554 const uint8_t *Ptr
=
4555 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.bind_off
));
4556 return makeArrayRef(Ptr
, DyldInfo
.bind_size
);
4559 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
4560 if (!DyldInfoLoadCmd
)
4563 auto DyldInfoOrErr
=
4564 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4567 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4568 const uint8_t *Ptr
=
4569 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.weak_bind_off
));
4570 return makeArrayRef(Ptr
, DyldInfo
.weak_bind_size
);
4573 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
4574 if (!DyldInfoLoadCmd
)
4577 auto DyldInfoOrErr
=
4578 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4581 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4582 const uint8_t *Ptr
=
4583 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.lazy_bind_off
));
4584 return makeArrayRef(Ptr
, DyldInfo
.lazy_bind_size
);
4587 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
4588 if (!DyldInfoLoadCmd
)
4591 auto DyldInfoOrErr
=
4592 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4595 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4596 const uint8_t *Ptr
=
4597 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.export_off
));
4598 return makeArrayRef(Ptr
, DyldInfo
.export_size
);
4601 ArrayRef
<uint8_t> MachOObjectFile::getUuid() const {
4604 // Returning a pointer is fine as uuid doesn't need endian swapping.
4605 const char *Ptr
= UuidLoadCmd
+ offsetof(MachO::uuid_command
, uuid
);
4606 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr
), 16);
4609 StringRef
MachOObjectFile::getStringTableData() const {
4610 MachO::symtab_command S
= getSymtabLoadCommand();
4611 return getData().substr(S
.stroff
, S
.strsize
);
4614 bool MachOObjectFile::is64Bit() const {
4615 return getType() == getMachOType(false, true) ||
4616 getType() == getMachOType(true, true);
4619 void MachOObjectFile::ReadULEB128s(uint64_t Index
,
4620 SmallVectorImpl
<uint64_t> &Out
) const {
4621 DataExtractor
extractor(ObjectFile::getData(), true, 0);
4623 uint64_t offset
= Index
;
4625 while (uint64_t delta
= extractor
.getULEB128(&offset
)) {
4627 Out
.push_back(data
);
4631 bool MachOObjectFile::isRelocatableObject() const {
4632 return getHeader().filetype
== MachO::MH_OBJECT
;
4635 Expected
<std::unique_ptr
<MachOObjectFile
>>
4636 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer
,
4637 uint32_t UniversalCputype
,
4638 uint32_t UniversalIndex
) {
4639 StringRef Magic
= Buffer
.getBuffer().slice(0, 4);
4640 if (Magic
== "\xFE\xED\xFA\xCE")
4641 return MachOObjectFile::create(Buffer
, false, false,
4642 UniversalCputype
, UniversalIndex
);
4643 if (Magic
== "\xCE\xFA\xED\xFE")
4644 return MachOObjectFile::create(Buffer
, true, false,
4645 UniversalCputype
, UniversalIndex
);
4646 if (Magic
== "\xFE\xED\xFA\xCF")
4647 return MachOObjectFile::create(Buffer
, false, true,
4648 UniversalCputype
, UniversalIndex
);
4649 if (Magic
== "\xCF\xFA\xED\xFE")
4650 return MachOObjectFile::create(Buffer
, true, true,
4651 UniversalCputype
, UniversalIndex
);
4652 return make_error
<GenericBinaryError
>("Unrecognized MachO magic number",
4653 object_error::invalid_file_type
);
4656 StringRef
MachOObjectFile::mapDebugSectionName(StringRef Name
) const {
4657 return StringSwitch
<StringRef
>(Name
)
4658 .Case("debug_str_offs", "debug_str_offsets")