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 Expected
<ArrayRef
<uint8_t>>
1949 MachOObjectFile::getSectionContents(DataRefImpl Sec
) const {
1954 MachO::section_64 Sect
= getSection64(Sec
);
1955 Offset
= Sect
.offset
;
1958 MachO::section Sect
= getSection(Sec
);
1959 Offset
= Sect
.offset
;
1963 return arrayRefFromStringRef(getData().substr(Offset
, Size
));
1966 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec
) const {
1969 MachO::section_64 Sect
= getSection64(Sec
);
1972 MachO::section Sect
= getSection(Sec
);
1976 return uint64_t(1) << Align
;
1979 Expected
<SectionRef
> MachOObjectFile::getSection(unsigned SectionIndex
) const {
1980 if (SectionIndex
< 1 || SectionIndex
> Sections
.size())
1981 return malformedError("bad section index: " + Twine((int)SectionIndex
));
1984 DRI
.d
.a
= SectionIndex
- 1;
1985 return SectionRef(DRI
, this);
1988 Expected
<SectionRef
> MachOObjectFile::getSection(StringRef SectionName
) const {
1990 for (const SectionRef
&Section
: sections()) {
1991 if (std::error_code E
= Section
.getName(SecName
))
1992 return errorCodeToError(E
);
1993 if (SecName
== SectionName
) {
1997 return errorCodeToError(object_error::parse_failed
);
2000 bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec
) const {
2004 bool MachOObjectFile::isSectionText(DataRefImpl Sec
) const {
2005 uint32_t Flags
= getSectionFlags(*this, Sec
);
2006 return Flags
& MachO::S_ATTR_PURE_INSTRUCTIONS
;
2009 bool MachOObjectFile::isSectionData(DataRefImpl Sec
) const {
2010 uint32_t Flags
= getSectionFlags(*this, Sec
);
2011 unsigned SectionType
= Flags
& MachO::SECTION_TYPE
;
2012 return !(Flags
& MachO::S_ATTR_PURE_INSTRUCTIONS
) &&
2013 !(SectionType
== MachO::S_ZEROFILL
||
2014 SectionType
== MachO::S_GB_ZEROFILL
);
2017 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec
) const {
2018 uint32_t Flags
= getSectionFlags(*this, Sec
);
2019 unsigned SectionType
= Flags
& MachO::SECTION_TYPE
;
2020 return !(Flags
& MachO::S_ATTR_PURE_INSTRUCTIONS
) &&
2021 (SectionType
== MachO::S_ZEROFILL
||
2022 SectionType
== MachO::S_GB_ZEROFILL
);
2025 unsigned MachOObjectFile::getSectionID(SectionRef Sec
) const {
2026 return Sec
.getRawDataRefImpl().d
.a
;
2029 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec
) const {
2030 uint32_t Flags
= getSectionFlags(*this, Sec
);
2031 unsigned SectionType
= Flags
& MachO::SECTION_TYPE
;
2032 return SectionType
== MachO::S_ZEROFILL
||
2033 SectionType
== MachO::S_GB_ZEROFILL
;
2036 bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec
) const {
2037 StringRef SegmentName
= getSectionFinalSegmentName(Sec
);
2038 if (Expected
<StringRef
> NameOrErr
= getSectionName(Sec
))
2039 return (SegmentName
== "__LLVM" && *NameOrErr
== "__bitcode");
2043 bool MachOObjectFile::isSectionStripped(DataRefImpl Sec
) const {
2045 return getSection64(Sec
).offset
== 0;
2046 return getSection(Sec
).offset
== 0;
2049 relocation_iterator
MachOObjectFile::section_rel_begin(DataRefImpl Sec
) const {
2053 return relocation_iterator(RelocationRef(Ret
, this));
2057 MachOObjectFile::section_rel_end(DataRefImpl Sec
) const {
2060 MachO::section_64 Sect
= getSection64(Sec
);
2063 MachO::section Sect
= getSection(Sec
);
2070 return relocation_iterator(RelocationRef(Ret
, this));
2073 relocation_iterator
MachOObjectFile::extrel_begin() const {
2075 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2076 Ret
.d
.a
= 0; // Would normally be a section index.
2077 Ret
.d
.b
= 0; // Index into the external relocations
2078 return relocation_iterator(RelocationRef(Ret
, this));
2081 relocation_iterator
MachOObjectFile::extrel_end() const {
2082 MachO::dysymtab_command DysymtabLoadCmd
= getDysymtabLoadCommand();
2084 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2085 Ret
.d
.a
= 0; // Would normally be a section index.
2086 Ret
.d
.b
= DysymtabLoadCmd
.nextrel
; // Index into the external relocations
2087 return relocation_iterator(RelocationRef(Ret
, this));
2090 relocation_iterator
MachOObjectFile::locrel_begin() const {
2092 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2093 Ret
.d
.a
= 1; // Would normally be a section index.
2094 Ret
.d
.b
= 0; // Index into the local relocations
2095 return relocation_iterator(RelocationRef(Ret
, this));
2098 relocation_iterator
MachOObjectFile::locrel_end() const {
2099 MachO::dysymtab_command DysymtabLoadCmd
= getDysymtabLoadCommand();
2101 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2102 Ret
.d
.a
= 1; // Would normally be a section index.
2103 Ret
.d
.b
= DysymtabLoadCmd
.nlocrel
; // Index into the local relocations
2104 return relocation_iterator(RelocationRef(Ret
, this));
2107 void MachOObjectFile::moveRelocationNext(DataRefImpl
&Rel
) const {
2111 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel
) const {
2112 assert((getHeader().filetype
== MachO::MH_OBJECT
||
2113 getHeader().filetype
== MachO::MH_KEXT_BUNDLE
) &&
2114 "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
2115 MachO::any_relocation_info RE
= getRelocation(Rel
);
2116 return getAnyRelocationAddress(RE
);
2120 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel
) const {
2121 MachO::any_relocation_info RE
= getRelocation(Rel
);
2122 if (isRelocationScattered(RE
))
2123 return symbol_end();
2125 uint32_t SymbolIdx
= getPlainRelocationSymbolNum(RE
);
2126 bool isExtern
= getPlainRelocationExternal(RE
);
2128 return symbol_end();
2130 MachO::symtab_command S
= getSymtabLoadCommand();
2131 unsigned SymbolTableEntrySize
= is64Bit() ?
2132 sizeof(MachO::nlist_64
) :
2133 sizeof(MachO::nlist
);
2134 uint64_t Offset
= S
.symoff
+ SymbolIdx
* SymbolTableEntrySize
;
2136 Sym
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Offset
));
2137 return symbol_iterator(SymbolRef(Sym
, this));
2141 MachOObjectFile::getRelocationSection(DataRefImpl Rel
) const {
2142 return section_iterator(getAnyRelocationSection(getRelocation(Rel
)));
2145 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel
) const {
2146 MachO::any_relocation_info RE
= getRelocation(Rel
);
2147 return getAnyRelocationType(RE
);
2150 void MachOObjectFile::getRelocationTypeName(
2151 DataRefImpl Rel
, SmallVectorImpl
<char> &Result
) const {
2153 uint64_t RType
= getRelocationType(Rel
);
2155 unsigned Arch
= this->getArch();
2159 static const char *const Table
[] = {
2160 "GENERIC_RELOC_VANILLA",
2161 "GENERIC_RELOC_PAIR",
2162 "GENERIC_RELOC_SECTDIFF",
2163 "GENERIC_RELOC_PB_LA_PTR",
2164 "GENERIC_RELOC_LOCAL_SECTDIFF",
2165 "GENERIC_RELOC_TLV" };
2173 case Triple::x86_64
: {
2174 static const char *const Table
[] = {
2175 "X86_64_RELOC_UNSIGNED",
2176 "X86_64_RELOC_SIGNED",
2177 "X86_64_RELOC_BRANCH",
2178 "X86_64_RELOC_GOT_LOAD",
2180 "X86_64_RELOC_SUBTRACTOR",
2181 "X86_64_RELOC_SIGNED_1",
2182 "X86_64_RELOC_SIGNED_2",
2183 "X86_64_RELOC_SIGNED_4",
2184 "X86_64_RELOC_TLV" };
2193 static const char *const Table
[] = {
2194 "ARM_RELOC_VANILLA",
2196 "ARM_RELOC_SECTDIFF",
2197 "ARM_RELOC_LOCAL_SECTDIFF",
2198 "ARM_RELOC_PB_LA_PTR",
2200 "ARM_THUMB_RELOC_BR22",
2201 "ARM_THUMB_32BIT_BRANCH",
2203 "ARM_RELOC_HALF_SECTDIFF" };
2211 case Triple::aarch64
:
2212 case Triple::aarch64_32
: {
2213 static const char *const Table
[] = {
2214 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
2215 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
2216 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
2217 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
2218 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
2219 "ARM64_RELOC_ADDEND"
2222 if (RType
>= array_lengthof(Table
))
2229 static const char *const Table
[] = {
2230 "PPC_RELOC_VANILLA",
2238 "PPC_RELOC_SECTDIFF",
2239 "PPC_RELOC_PB_LA_PTR",
2240 "PPC_RELOC_HI16_SECTDIFF",
2241 "PPC_RELOC_LO16_SECTDIFF",
2242 "PPC_RELOC_HA16_SECTDIFF",
2244 "PPC_RELOC_LO14_SECTDIFF",
2245 "PPC_RELOC_LOCAL_SECTDIFF" };
2253 case Triple::UnknownArch
:
2257 Result
.append(res
.begin(), res
.end());
2260 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel
) const {
2261 MachO::any_relocation_info RE
= getRelocation(Rel
);
2262 return getAnyRelocationLength(RE
);
2266 // guessLibraryShortName() is passed a name of a dynamic library and returns a
2267 // guess on what the short name is. Then name is returned as a substring of the
2268 // StringRef Name passed in. The name of the dynamic library is recognized as
2269 // a framework if it has one of the two following forms:
2270 // Foo.framework/Versions/A/Foo
2271 // Foo.framework/Foo
2272 // Where A and Foo can be any string. And may contain a trailing suffix
2273 // starting with an underbar. If the Name is recognized as a framework then
2274 // isFramework is set to true else it is set to false. If the Name has a
2275 // suffix then Suffix is set to the substring in Name that contains the suffix
2276 // else it is set to a NULL StringRef.
2278 // The Name of the dynamic library is recognized as a library name if it has
2279 // one of the two following forms:
2283 // The library may have a suffix trailing the name Foo of the form:
2284 // libFoo_profile.A.dylib
2285 // libFoo_profile.dylib
2286 // These dyld image suffixes are separated from the short name by a '_'
2287 // character. Because the '_' character is commonly used to separate words in
2288 // filenames guessLibraryShortName() cannot reliably separate a dylib's short
2289 // name from an arbitrary image suffix; imagine if both the short name and the
2290 // suffix contains an '_' character! To better deal with this ambiguity,
2291 // guessLibraryShortName() will recognize only "_debug" and "_profile" as valid
2292 // Suffix values. Calling code needs to be tolerant of guessLibraryShortName()
2293 // guessing incorrectly.
2295 // The Name of the dynamic library is also recognized as a library name if it
2296 // has the following form:
2299 // If the Name of the dynamic library is none of the forms above then a NULL
2300 // StringRef is returned.
2301 StringRef
MachOObjectFile::guessLibraryShortName(StringRef Name
,
2303 StringRef
&Suffix
) {
2304 StringRef Foo
, F
, DotFramework
, V
, Dylib
, Lib
, Dot
, Qtx
;
2305 size_t a
, b
, c
, d
, Idx
;
2307 isFramework
= false;
2308 Suffix
= StringRef();
2310 // Pull off the last component and make Foo point to it
2311 a
= Name
.rfind('/');
2312 if (a
== Name
.npos
|| a
== 0)
2314 Foo
= Name
.slice(a
+1, Name
.npos
);
2316 // Look for a suffix starting with a '_'
2317 Idx
= Foo
.rfind('_');
2318 if (Idx
!= Foo
.npos
&& Foo
.size() >= 2) {
2319 Suffix
= Foo
.slice(Idx
, Foo
.npos
);
2320 if (Suffix
!= "_debug" && Suffix
!= "_profile")
2321 Suffix
= StringRef();
2323 Foo
= Foo
.slice(0, Idx
);
2326 // First look for the form Foo.framework/Foo
2327 b
= Name
.rfind('/', a
);
2332 F
= Name
.slice(Idx
, Idx
+ Foo
.size());
2333 DotFramework
= Name
.slice(Idx
+ Foo
.size(),
2334 Idx
+ Foo
.size() + sizeof(".framework/")-1);
2335 if (F
== Foo
&& DotFramework
== ".framework/") {
2340 // Next look for the form Foo.framework/Versions/A/Foo
2343 c
= Name
.rfind('/', b
);
2344 if (c
== Name
.npos
|| c
== 0)
2346 V
= Name
.slice(c
+1, Name
.npos
);
2347 if (!V
.startswith("Versions/"))
2349 d
= Name
.rfind('/', c
);
2354 F
= Name
.slice(Idx
, Idx
+ Foo
.size());
2355 DotFramework
= Name
.slice(Idx
+ Foo
.size(),
2356 Idx
+ Foo
.size() + sizeof(".framework/")-1);
2357 if (F
== Foo
&& DotFramework
== ".framework/") {
2363 // pull off the suffix after the "." and make a point to it
2364 a
= Name
.rfind('.');
2365 if (a
== Name
.npos
|| a
== 0)
2367 Dylib
= Name
.slice(a
, Name
.npos
);
2368 if (Dylib
!= ".dylib")
2371 // First pull off the version letter for the form Foo.A.dylib if any.
2373 Dot
= Name
.slice(a
-2, a
-1);
2378 b
= Name
.rfind('/', a
);
2383 // ignore any suffix after an underbar like Foo_profile.A.dylib
2384 Idx
= Name
.rfind('_');
2385 if (Idx
!= Name
.npos
&& Idx
!= b
) {
2386 Lib
= Name
.slice(b
, Idx
);
2387 Suffix
= Name
.slice(Idx
, a
);
2388 if (Suffix
!= "_debug" && Suffix
!= "_profile") {
2389 Suffix
= StringRef();
2390 Lib
= Name
.slice(b
, a
);
2394 Lib
= Name
.slice(b
, a
);
2395 // There are incorrect library names of the form:
2396 // libATS.A_profile.dylib so check for these.
2397 if (Lib
.size() >= 3) {
2398 Dot
= Lib
.slice(Lib
.size()-2, Lib
.size()-1);
2400 Lib
= Lib
.slice(0, Lib
.size()-2);
2405 Qtx
= Name
.slice(a
, Name
.npos
);
2408 b
= Name
.rfind('/', a
);
2410 Lib
= Name
.slice(0, a
);
2412 Lib
= Name
.slice(b
+1, a
);
2413 // There are library names of the form: QT.A.qtx so check for these.
2414 if (Lib
.size() >= 3) {
2415 Dot
= Lib
.slice(Lib
.size()-2, Lib
.size()-1);
2417 Lib
= Lib
.slice(0, Lib
.size()-2);
2422 // getLibraryShortNameByIndex() is used to get the short name of the library
2423 // for an undefined symbol in a linked Mach-O binary that was linked with the
2424 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
2425 // It is passed the index (0 - based) of the library as translated from
2426 // GET_LIBRARY_ORDINAL (1 - based).
2427 std::error_code
MachOObjectFile::getLibraryShortNameByIndex(unsigned Index
,
2428 StringRef
&Res
) const {
2429 if (Index
>= Libraries
.size())
2430 return object_error::parse_failed
;
2432 // If the cache of LibrariesShortNames is not built up do that first for
2433 // all the Libraries.
2434 if (LibrariesShortNames
.size() == 0) {
2435 for (unsigned i
= 0; i
< Libraries
.size(); i
++) {
2437 getStructOrErr
<MachO::dylib_command
>(*this, Libraries
[i
]);
2439 return object_error::parse_failed
;
2440 MachO::dylib_command D
= CommandOrErr
.get();
2441 if (D
.dylib
.name
>= D
.cmdsize
)
2442 return object_error::parse_failed
;
2443 const char *P
= (const char *)(Libraries
[i
]) + D
.dylib
.name
;
2444 StringRef Name
= StringRef(P
);
2445 if (D
.dylib
.name
+Name
.size() >= D
.cmdsize
)
2446 return object_error::parse_failed
;
2449 StringRef shortName
= guessLibraryShortName(Name
, isFramework
, Suffix
);
2450 if (shortName
.empty())
2451 LibrariesShortNames
.push_back(Name
);
2453 LibrariesShortNames
.push_back(shortName
);
2457 Res
= LibrariesShortNames
[Index
];
2458 return std::error_code();
2461 uint32_t MachOObjectFile::getLibraryCount() const {
2462 return Libraries
.size();
2466 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel
) const {
2468 Sec
.d
.a
= Rel
->getRawDataRefImpl().d
.a
;
2469 return section_iterator(SectionRef(Sec
, this));
2472 basic_symbol_iterator
MachOObjectFile::symbol_begin() const {
2474 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2475 if (!SymtabLoadCmd
|| Symtab
.nsyms
== 0)
2476 return basic_symbol_iterator(SymbolRef(DRI
, this));
2478 return getSymbolByIndex(0);
2481 basic_symbol_iterator
MachOObjectFile::symbol_end() const {
2483 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2484 if (!SymtabLoadCmd
|| Symtab
.nsyms
== 0)
2485 return basic_symbol_iterator(SymbolRef(DRI
, this));
2487 unsigned SymbolTableEntrySize
= is64Bit() ?
2488 sizeof(MachO::nlist_64
) :
2489 sizeof(MachO::nlist
);
2490 unsigned Offset
= Symtab
.symoff
+
2491 Symtab
.nsyms
* SymbolTableEntrySize
;
2492 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Offset
));
2493 return basic_symbol_iterator(SymbolRef(DRI
, this));
2496 symbol_iterator
MachOObjectFile::getSymbolByIndex(unsigned Index
) const {
2497 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2498 if (!SymtabLoadCmd
|| Index
>= Symtab
.nsyms
)
2499 report_fatal_error("Requested symbol index is out of range.");
2500 unsigned SymbolTableEntrySize
=
2501 is64Bit() ? sizeof(MachO::nlist_64
) : sizeof(MachO::nlist
);
2503 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Symtab
.symoff
));
2504 DRI
.p
+= Index
* SymbolTableEntrySize
;
2505 return basic_symbol_iterator(SymbolRef(DRI
, this));
2508 uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb
) const {
2509 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2511 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2512 unsigned SymbolTableEntrySize
=
2513 is64Bit() ? sizeof(MachO::nlist_64
) : sizeof(MachO::nlist
);
2514 DataRefImpl DRIstart
;
2515 DRIstart
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Symtab
.symoff
));
2516 uint64_t Index
= (Symb
.p
- DRIstart
.p
) / SymbolTableEntrySize
;
2520 section_iterator
MachOObjectFile::section_begin() const {
2522 return section_iterator(SectionRef(DRI
, this));
2525 section_iterator
MachOObjectFile::section_end() const {
2527 DRI
.d
.a
= Sections
.size();
2528 return section_iterator(SectionRef(DRI
, this));
2531 uint8_t MachOObjectFile::getBytesInAddress() const {
2532 return is64Bit() ? 8 : 4;
2535 StringRef
MachOObjectFile::getFileFormatName() const {
2536 unsigned CPUType
= getCPUType(*this);
2539 case MachO::CPU_TYPE_I386
:
2540 return "Mach-O 32-bit i386";
2541 case MachO::CPU_TYPE_ARM
:
2542 return "Mach-O arm";
2543 case MachO::CPU_TYPE_ARM64_32
:
2544 return "Mach-O arm64 (ILP32)";
2545 case MachO::CPU_TYPE_POWERPC
:
2546 return "Mach-O 32-bit ppc";
2548 return "Mach-O 32-bit unknown";
2553 case MachO::CPU_TYPE_X86_64
:
2554 return "Mach-O 64-bit x86-64";
2555 case MachO::CPU_TYPE_ARM64
:
2556 return "Mach-O arm64";
2557 case MachO::CPU_TYPE_POWERPC64
:
2558 return "Mach-O 64-bit ppc64";
2560 return "Mach-O 64-bit unknown";
2564 Triple::ArchType
MachOObjectFile::getArch(uint32_t CPUType
) {
2566 case MachO::CPU_TYPE_I386
:
2568 case MachO::CPU_TYPE_X86_64
:
2569 return Triple::x86_64
;
2570 case MachO::CPU_TYPE_ARM
:
2572 case MachO::CPU_TYPE_ARM64
:
2573 return Triple::aarch64
;
2574 case MachO::CPU_TYPE_ARM64_32
:
2575 return Triple::aarch64_32
;
2576 case MachO::CPU_TYPE_POWERPC
:
2578 case MachO::CPU_TYPE_POWERPC64
:
2579 return Triple::ppc64
;
2581 return Triple::UnknownArch
;
2585 Triple
MachOObjectFile::getArchTriple(uint32_t CPUType
, uint32_t CPUSubType
,
2586 const char **McpuDefault
,
2587 const char **ArchFlag
) {
2589 *McpuDefault
= nullptr;
2591 *ArchFlag
= nullptr;
2594 case MachO::CPU_TYPE_I386
:
2595 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2596 case MachO::CPU_SUBTYPE_I386_ALL
:
2599 return Triple("i386-apple-darwin");
2603 case MachO::CPU_TYPE_X86_64
:
2604 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2605 case MachO::CPU_SUBTYPE_X86_64_ALL
:
2607 *ArchFlag
= "x86_64";
2608 return Triple("x86_64-apple-darwin");
2609 case MachO::CPU_SUBTYPE_X86_64_H
:
2611 *ArchFlag
= "x86_64h";
2612 return Triple("x86_64h-apple-darwin");
2616 case MachO::CPU_TYPE_ARM
:
2617 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2618 case MachO::CPU_SUBTYPE_ARM_V4T
:
2620 *ArchFlag
= "armv4t";
2621 return Triple("armv4t-apple-darwin");
2622 case MachO::CPU_SUBTYPE_ARM_V5TEJ
:
2624 *ArchFlag
= "armv5e";
2625 return Triple("armv5e-apple-darwin");
2626 case MachO::CPU_SUBTYPE_ARM_XSCALE
:
2628 *ArchFlag
= "xscale";
2629 return Triple("xscale-apple-darwin");
2630 case MachO::CPU_SUBTYPE_ARM_V6
:
2632 *ArchFlag
= "armv6";
2633 return Triple("armv6-apple-darwin");
2634 case MachO::CPU_SUBTYPE_ARM_V6M
:
2636 *McpuDefault
= "cortex-m0";
2638 *ArchFlag
= "armv6m";
2639 return Triple("armv6m-apple-darwin");
2640 case MachO::CPU_SUBTYPE_ARM_V7
:
2642 *ArchFlag
= "armv7";
2643 return Triple("armv7-apple-darwin");
2644 case MachO::CPU_SUBTYPE_ARM_V7EM
:
2646 *McpuDefault
= "cortex-m4";
2648 *ArchFlag
= "armv7em";
2649 return Triple("thumbv7em-apple-darwin");
2650 case MachO::CPU_SUBTYPE_ARM_V7K
:
2652 *McpuDefault
= "cortex-a7";
2654 *ArchFlag
= "armv7k";
2655 return Triple("armv7k-apple-darwin");
2656 case MachO::CPU_SUBTYPE_ARM_V7M
:
2658 *McpuDefault
= "cortex-m3";
2660 *ArchFlag
= "armv7m";
2661 return Triple("thumbv7m-apple-darwin");
2662 case MachO::CPU_SUBTYPE_ARM_V7S
:
2664 *McpuDefault
= "cortex-a7";
2666 *ArchFlag
= "armv7s";
2667 return Triple("armv7s-apple-darwin");
2671 case MachO::CPU_TYPE_ARM64
:
2672 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2673 case MachO::CPU_SUBTYPE_ARM64_ALL
:
2675 *McpuDefault
= "cyclone";
2677 *ArchFlag
= "arm64";
2678 return Triple("arm64-apple-darwin");
2682 case MachO::CPU_TYPE_ARM64_32
:
2683 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2684 case MachO::CPU_SUBTYPE_ARM64_32_V8
:
2686 *McpuDefault
= "cyclone";
2688 *ArchFlag
= "arm64_32";
2689 return Triple("arm64_32-apple-darwin");
2693 case MachO::CPU_TYPE_POWERPC
:
2694 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2695 case MachO::CPU_SUBTYPE_POWERPC_ALL
:
2698 return Triple("ppc-apple-darwin");
2702 case MachO::CPU_TYPE_POWERPC64
:
2703 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2704 case MachO::CPU_SUBTYPE_POWERPC_ALL
:
2706 *ArchFlag
= "ppc64";
2707 return Triple("ppc64-apple-darwin");
2716 Triple
MachOObjectFile::getHostArch() {
2717 return Triple(sys::getDefaultTargetTriple());
2720 bool MachOObjectFile::isValidArch(StringRef ArchFlag
) {
2721 return StringSwitch
<bool>(ArchFlag
)
2723 .Case("x86_64", true)
2724 .Case("x86_64h", true)
2725 .Case("armv4t", true)
2727 .Case("armv5e", true)
2728 .Case("armv6", true)
2729 .Case("armv6m", true)
2730 .Case("armv7", true)
2731 .Case("armv7em", true)
2732 .Case("armv7k", true)
2733 .Case("armv7m", true)
2734 .Case("armv7s", true)
2735 .Case("arm64", true)
2736 .Case("arm64_32", true)
2738 .Case("ppc64", true)
2742 Triple::ArchType
MachOObjectFile::getArch() const {
2743 return getArch(getCPUType(*this));
2746 Triple
MachOObjectFile::getArchTriple(const char **McpuDefault
) const {
2747 return getArchTriple(Header
.cputype
, Header
.cpusubtype
, McpuDefault
);
2750 relocation_iterator
MachOObjectFile::section_rel_begin(unsigned Index
) const {
2753 return section_rel_begin(DRI
);
2756 relocation_iterator
MachOObjectFile::section_rel_end(unsigned Index
) const {
2759 return section_rel_end(DRI
);
2762 dice_iterator
MachOObjectFile::begin_dices() const {
2764 if (!DataInCodeLoadCmd
)
2765 return dice_iterator(DiceRef(DRI
, this));
2767 MachO::linkedit_data_command DicLC
= getDataInCodeLoadCommand();
2768 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, DicLC
.dataoff
));
2769 return dice_iterator(DiceRef(DRI
, this));
2772 dice_iterator
MachOObjectFile::end_dices() const {
2774 if (!DataInCodeLoadCmd
)
2775 return dice_iterator(DiceRef(DRI
, this));
2777 MachO::linkedit_data_command DicLC
= getDataInCodeLoadCommand();
2778 unsigned Offset
= DicLC
.dataoff
+ DicLC
.datasize
;
2779 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Offset
));
2780 return dice_iterator(DiceRef(DRI
, this));
2783 ExportEntry::ExportEntry(Error
*E
, const MachOObjectFile
*O
,
2784 ArrayRef
<uint8_t> T
) : E(E
), O(O
), Trie(T
) {}
2786 void ExportEntry::moveToFirst() {
2787 ErrorAsOutParameter
ErrAsOutParam(E
);
2791 pushDownUntilBottom();
2794 void ExportEntry::moveToEnd() {
2799 bool ExportEntry::operator==(const ExportEntry
&Other
) const {
2800 // Common case, one at end, other iterating from begin.
2801 if (Done
|| Other
.Done
)
2802 return (Done
== Other
.Done
);
2803 // Not equal if different stack sizes.
2804 if (Stack
.size() != Other
.Stack
.size())
2806 // Not equal if different cumulative strings.
2807 if (!CumulativeString
.equals(Other
.CumulativeString
))
2809 // Equal if all nodes in both stacks match.
2810 for (unsigned i
=0; i
< Stack
.size(); ++i
) {
2811 if (Stack
[i
].Start
!= Other
.Stack
[i
].Start
)
2817 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr
, const char **error
) {
2819 uint64_t Result
= decodeULEB128(Ptr
, &Count
, Trie
.end(), error
);
2821 if (Ptr
> Trie
.end())
2826 StringRef
ExportEntry::name() const {
2827 return CumulativeString
;
2830 uint64_t ExportEntry::flags() const {
2831 return Stack
.back().Flags
;
2834 uint64_t ExportEntry::address() const {
2835 return Stack
.back().Address
;
2838 uint64_t ExportEntry::other() const {
2839 return Stack
.back().Other
;
2842 StringRef
ExportEntry::otherName() const {
2843 const char* ImportName
= Stack
.back().ImportName
;
2845 return StringRef(ImportName
);
2849 uint32_t ExportEntry::nodeOffset() const {
2850 return Stack
.back().Start
- Trie
.begin();
2853 ExportEntry::NodeState::NodeState(const uint8_t *Ptr
)
2854 : Start(Ptr
), Current(Ptr
) {}
2856 void ExportEntry::pushNode(uint64_t offset
) {
2857 ErrorAsOutParameter
ErrAsOutParam(E
);
2858 const uint8_t *Ptr
= Trie
.begin() + offset
;
2859 NodeState
State(Ptr
);
2861 uint64_t ExportInfoSize
= readULEB128(State
.Current
, &error
);
2863 *E
= malformedError("export info size " + Twine(error
) +
2864 " in export trie data at node: 0x" +
2865 Twine::utohexstr(offset
));
2869 State
.IsExportNode
= (ExportInfoSize
!= 0);
2870 const uint8_t* Children
= State
.Current
+ ExportInfoSize
;
2871 if (Children
> Trie
.end()) {
2872 *E
= malformedError(
2873 "export info size: 0x" + Twine::utohexstr(ExportInfoSize
) +
2874 " in export trie data at node: 0x" + Twine::utohexstr(offset
) +
2875 " too big and extends past end of trie data");
2879 if (State
.IsExportNode
) {
2880 const uint8_t *ExportStart
= State
.Current
;
2881 State
.Flags
= readULEB128(State
.Current
, &error
);
2883 *E
= malformedError("flags " + Twine(error
) +
2884 " in export trie data at node: 0x" +
2885 Twine::utohexstr(offset
));
2889 uint64_t Kind
= State
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK
;
2890 if (State
.Flags
!= 0 &&
2891 (Kind
!= MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR
&&
2892 Kind
!= MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE
&&
2893 Kind
!= MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL
)) {
2894 *E
= malformedError(
2895 "unsupported exported symbol kind: " + Twine((int)Kind
) +
2896 " in flags: 0x" + Twine::utohexstr(State
.Flags
) +
2897 " in export trie data at node: 0x" + Twine::utohexstr(offset
));
2901 if (State
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_REEXPORT
) {
2903 State
.Other
= readULEB128(State
.Current
, &error
); // dylib ordinal
2905 *E
= malformedError("dylib ordinal of re-export " + Twine(error
) +
2906 " in export trie data at node: 0x" +
2907 Twine::utohexstr(offset
));
2912 if (State
.Other
> O
->getLibraryCount()) {
2913 *E
= malformedError(
2914 "bad library ordinal: " + Twine((int)State
.Other
) + " (max " +
2915 Twine((int)O
->getLibraryCount()) +
2916 ") in export trie data at node: 0x" + Twine::utohexstr(offset
));
2921 State
.ImportName
= reinterpret_cast<const char*>(State
.Current
);
2922 if (*State
.ImportName
== '\0') {
2925 const uint8_t *End
= State
.Current
+ 1;
2926 if (End
>= Trie
.end()) {
2927 *E
= malformedError("import name of re-export in export trie data at "
2929 Twine::utohexstr(offset
) +
2930 " starts past end of trie data");
2934 while(*End
!= '\0' && End
< Trie
.end())
2937 *E
= malformedError("import name of re-export in export trie data at "
2939 Twine::utohexstr(offset
) +
2940 " extends past end of trie data");
2944 State
.Current
= End
+ 1;
2947 State
.Address
= readULEB128(State
.Current
, &error
);
2949 *E
= malformedError("address " + Twine(error
) +
2950 " in export trie data at node: 0x" +
2951 Twine::utohexstr(offset
));
2955 if (State
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
) {
2956 State
.Other
= readULEB128(State
.Current
, &error
);
2958 *E
= malformedError("resolver of stub and resolver " + Twine(error
) +
2959 " in export trie data at node: 0x" +
2960 Twine::utohexstr(offset
));
2966 if(ExportStart
+ ExportInfoSize
!= State
.Current
) {
2967 *E
= malformedError(
2968 "inconsistant export info size: 0x" +
2969 Twine::utohexstr(ExportInfoSize
) + " where actual size was: 0x" +
2970 Twine::utohexstr(State
.Current
- ExportStart
) +
2971 " in export trie data at node: 0x" + Twine::utohexstr(offset
));
2976 State
.ChildCount
= *Children
;
2977 if (State
.ChildCount
!= 0 && Children
+ 1 >= Trie
.end()) {
2978 *E
= malformedError("byte for count of childern in export trie data at "
2980 Twine::utohexstr(offset
) +
2981 " extends past end of trie data");
2985 State
.Current
= Children
+ 1;
2986 State
.NextChildIndex
= 0;
2987 State
.ParentStringLength
= CumulativeString
.size();
2988 Stack
.push_back(State
);
2991 void ExportEntry::pushDownUntilBottom() {
2992 ErrorAsOutParameter
ErrAsOutParam(E
);
2994 while (Stack
.back().NextChildIndex
< Stack
.back().ChildCount
) {
2995 NodeState
&Top
= Stack
.back();
2996 CumulativeString
.resize(Top
.ParentStringLength
);
2997 for (;*Top
.Current
!= 0 && Top
.Current
< Trie
.end(); Top
.Current
++) {
2998 char C
= *Top
.Current
;
2999 CumulativeString
.push_back(C
);
3001 if (Top
.Current
>= Trie
.end()) {
3002 *E
= malformedError("edge sub-string in export trie data at node: 0x" +
3003 Twine::utohexstr(Top
.Start
- Trie
.begin()) +
3004 " for child #" + Twine((int)Top
.NextChildIndex
) +
3005 " extends past end of trie data");
3010 uint64_t childNodeIndex
= readULEB128(Top
.Current
, &error
);
3012 *E
= malformedError("child node offset " + Twine(error
) +
3013 " in export trie data at node: 0x" +
3014 Twine::utohexstr(Top
.Start
- Trie
.begin()));
3018 for (const NodeState
&node
: nodes()) {
3019 if (node
.Start
== Trie
.begin() + childNodeIndex
){
3020 *E
= malformedError("loop in childern in export trie data at node: 0x" +
3021 Twine::utohexstr(Top
.Start
- Trie
.begin()) +
3022 " back to node: 0x" +
3023 Twine::utohexstr(childNodeIndex
));
3028 Top
.NextChildIndex
+= 1;
3029 pushNode(childNodeIndex
);
3033 if (!Stack
.back().IsExportNode
) {
3034 *E
= malformedError("node is not an export node in export trie data at "
3036 Twine::utohexstr(Stack
.back().Start
- Trie
.begin()));
3042 // We have a trie data structure and need a way to walk it that is compatible
3043 // with the C++ iterator model. The solution is a non-recursive depth first
3044 // traversal where the iterator contains a stack of parent nodes along with a
3045 // string that is the accumulation of all edge strings along the parent chain
3048 // There is one "export" node for each exported symbol. But because some
3049 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
3050 // node may have child nodes too.
3052 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
3053 // child until hitting a node with no children (which is an export node or
3054 // else the trie is malformed). On the way down, each node is pushed on the
3055 // stack ivar. If there is no more ways down, it pops up one and tries to go
3056 // down a sibling path until a childless node is reached.
3057 void ExportEntry::moveNext() {
3058 assert(!Stack
.empty() && "ExportEntry::moveNext() with empty node stack");
3059 if (!Stack
.back().IsExportNode
) {
3060 *E
= malformedError("node is not an export node in export trie data at "
3062 Twine::utohexstr(Stack
.back().Start
- Trie
.begin()));
3068 while (!Stack
.empty()) {
3069 NodeState
&Top
= Stack
.back();
3070 if (Top
.NextChildIndex
< Top
.ChildCount
) {
3071 pushDownUntilBottom();
3072 // Now at the next export node.
3075 if (Top
.IsExportNode
) {
3076 // This node has no children but is itself an export node.
3077 CumulativeString
.resize(Top
.ParentStringLength
);
3086 iterator_range
<export_iterator
>
3087 MachOObjectFile::exports(Error
&E
, ArrayRef
<uint8_t> Trie
,
3088 const MachOObjectFile
*O
) {
3089 ExportEntry
Start(&E
, O
, Trie
);
3093 Start
.moveToFirst();
3095 ExportEntry
Finish(&E
, O
, Trie
);
3098 return make_range(export_iterator(Start
), export_iterator(Finish
));
3101 iterator_range
<export_iterator
> MachOObjectFile::exports(Error
&Err
) const {
3102 return exports(Err
, getDyldInfoExportsTrie(), this);
3105 MachORebaseEntry::MachORebaseEntry(Error
*E
, const MachOObjectFile
*O
,
3106 ArrayRef
<uint8_t> Bytes
, bool is64Bit
)
3107 : E(E
), O(O
), Opcodes(Bytes
), Ptr(Bytes
.begin()),
3108 PointerSize(is64Bit
? 8 : 4) {}
3110 void MachORebaseEntry::moveToFirst() {
3111 Ptr
= Opcodes
.begin();
3115 void MachORebaseEntry::moveToEnd() {
3116 Ptr
= Opcodes
.end();
3117 RemainingLoopCount
= 0;
3121 void MachORebaseEntry::moveNext() {
3122 ErrorAsOutParameter
ErrAsOutParam(E
);
3123 // If in the middle of some loop, move to next rebasing in loop.
3124 SegmentOffset
+= AdvanceAmount
;
3125 if (RemainingLoopCount
) {
3126 --RemainingLoopCount
;
3129 // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
3130 // pointer size. Therefore it is possible to reach the end without ever having
3131 // seen REBASE_OPCODE_DONE.
3132 if (Ptr
== Opcodes
.end()) {
3138 // Parse next opcode and set up next loop.
3139 const uint8_t *OpcodeStart
= Ptr
;
3140 uint8_t Byte
= *Ptr
++;
3141 uint8_t ImmValue
= Byte
& MachO::REBASE_IMMEDIATE_MASK
;
3142 uint8_t Opcode
= Byte
& MachO::REBASE_OPCODE_MASK
;
3143 uint32_t Count
, Skip
;
3144 const char *error
= nullptr;
3146 case MachO::REBASE_OPCODE_DONE
:
3150 DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n");
3152 case MachO::REBASE_OPCODE_SET_TYPE_IMM
:
3153 RebaseType
= ImmValue
;
3154 if (RebaseType
> MachO::REBASE_TYPE_TEXT_PCREL32
) {
3155 *E
= malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
3156 Twine((int)RebaseType
) + " for opcode at: 0x" +
3157 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3163 dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
3164 << "RebaseType=" << (int) RebaseType
<< "\n");
3166 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
:
3167 SegmentIndex
= ImmValue
;
3168 SegmentOffset
= readULEB128(&error
);
3170 *E
= malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3171 Twine(error
) + " for opcode at: 0x" +
3172 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3176 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3179 *E
= malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3180 Twine(error
) + " for opcode at: 0x" +
3181 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3187 dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3188 << "SegmentIndex=" << SegmentIndex
<< ", "
3189 << format("SegmentOffset=0x%06X", SegmentOffset
)
3192 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB
:
3193 SegmentOffset
+= readULEB128(&error
);
3195 *E
= malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3196 " for opcode at: 0x" +
3197 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3201 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3204 *E
= malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3205 " for opcode at: 0x" +
3206 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3210 DEBUG_WITH_TYPE("mach-o-rebase",
3211 dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
3212 << format("SegmentOffset=0x%06X",
3213 SegmentOffset
) << "\n");
3215 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED
:
3216 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3219 *E
= malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
3220 Twine(error
) + " for opcode at: 0x" +
3221 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3225 SegmentOffset
+= ImmValue
* PointerSize
;
3226 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3230 malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED "
3231 " (after adding immediate times the pointer size) " +
3232 Twine(error
) + " for opcode at: 0x" +
3233 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3237 DEBUG_WITH_TYPE("mach-o-rebase",
3238 dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
3239 << format("SegmentOffset=0x%06X",
3240 SegmentOffset
) << "\n");
3242 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES
:
3243 AdvanceAmount
= PointerSize
;
3247 RemainingLoopCount
= ImmValue
- 1;
3249 RemainingLoopCount
= 0;
3250 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3251 PointerSize
, Count
, Skip
);
3253 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
3254 Twine(error
) + " for opcode at: 0x" +
3255 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3261 dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
3262 << format("SegmentOffset=0x%06X", SegmentOffset
)
3263 << ", AdvanceAmount=" << AdvanceAmount
3264 << ", RemainingLoopCount=" << RemainingLoopCount
3267 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES
:
3268 AdvanceAmount
= PointerSize
;
3270 Count
= readULEB128(&error
);
3272 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3273 Twine(error
) + " for opcode at: 0x" +
3274 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3279 RemainingLoopCount
= Count
- 1;
3281 RemainingLoopCount
= 0;
3282 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3283 PointerSize
, Count
, Skip
);
3285 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3286 Twine(error
) + " for opcode at: 0x" +
3287 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3293 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
3294 << format("SegmentOffset=0x%06X", SegmentOffset
)
3295 << ", AdvanceAmount=" << AdvanceAmount
3296 << ", RemainingLoopCount=" << RemainingLoopCount
3299 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB
:
3300 Skip
= readULEB128(&error
);
3302 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3303 Twine(error
) + " for opcode at: 0x" +
3304 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3308 AdvanceAmount
= Skip
+ PointerSize
;
3310 RemainingLoopCount
= 0;
3311 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3312 PointerSize
, Count
, Skip
);
3314 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3315 Twine(error
) + " for opcode at: 0x" +
3316 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3322 dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
3323 << format("SegmentOffset=0x%06X", SegmentOffset
)
3324 << ", AdvanceAmount=" << AdvanceAmount
3325 << ", RemainingLoopCount=" << RemainingLoopCount
3328 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB
:
3329 Count
= readULEB128(&error
);
3331 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3333 Twine(error
) + " for opcode at: 0x" +
3334 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3339 RemainingLoopCount
= Count
- 1;
3341 RemainingLoopCount
= 0;
3342 Skip
= readULEB128(&error
);
3344 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3346 Twine(error
) + " for opcode at: 0x" +
3347 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3351 AdvanceAmount
= Skip
+ PointerSize
;
3353 error
= O
->RebaseEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3354 PointerSize
, Count
, Skip
);
3356 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3358 Twine(error
) + " for opcode at: 0x" +
3359 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3365 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
3366 << format("SegmentOffset=0x%06X", SegmentOffset
)
3367 << ", AdvanceAmount=" << AdvanceAmount
3368 << ", RemainingLoopCount=" << RemainingLoopCount
3372 *E
= malformedError("bad rebase info (bad opcode value 0x" +
3373 Twine::utohexstr(Opcode
) + " for opcode at: 0x" +
3374 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3381 uint64_t MachORebaseEntry::readULEB128(const char **error
) {
3383 uint64_t Result
= decodeULEB128(Ptr
, &Count
, Opcodes
.end(), error
);
3385 if (Ptr
> Opcodes
.end())
3386 Ptr
= Opcodes
.end();
3390 int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex
; }
3392 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset
; }
3394 StringRef
MachORebaseEntry::typeName() const {
3395 switch (RebaseType
) {
3396 case MachO::REBASE_TYPE_POINTER
:
3398 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32
:
3399 return "text abs32";
3400 case MachO::REBASE_TYPE_TEXT_PCREL32
:
3401 return "text rel32";
3406 // For use with the SegIndex of a checked Mach-O Rebase entry
3407 // to get the segment name.
3408 StringRef
MachORebaseEntry::segmentName() const {
3409 return O
->BindRebaseSegmentName(SegmentIndex
);
3412 // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3413 // to get the section name.
3414 StringRef
MachORebaseEntry::sectionName() const {
3415 return O
->BindRebaseSectionName(SegmentIndex
, SegmentOffset
);
3418 // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3419 // to get the address.
3420 uint64_t MachORebaseEntry::address() const {
3421 return O
->BindRebaseAddress(SegmentIndex
, SegmentOffset
);
3424 bool MachORebaseEntry::operator==(const MachORebaseEntry
&Other
) const {
3425 #ifdef EXPENSIVE_CHECKS
3426 assert(Opcodes
== Other
.Opcodes
&& "compare iterators of different files");
3428 assert(Opcodes
.data() == Other
.Opcodes
.data() && "compare iterators of different files");
3430 return (Ptr
== Other
.Ptr
) &&
3431 (RemainingLoopCount
== Other
.RemainingLoopCount
) &&
3432 (Done
== Other
.Done
);
3435 iterator_range
<rebase_iterator
>
3436 MachOObjectFile::rebaseTable(Error
&Err
, MachOObjectFile
*O
,
3437 ArrayRef
<uint8_t> Opcodes
, bool is64
) {
3438 if (O
->BindRebaseSectionTable
== nullptr)
3439 O
->BindRebaseSectionTable
= llvm::make_unique
<BindRebaseSegInfo
>(O
);
3440 MachORebaseEntry
Start(&Err
, O
, Opcodes
, is64
);
3441 Start
.moveToFirst();
3443 MachORebaseEntry
Finish(&Err
, O
, Opcodes
, is64
);
3446 return make_range(rebase_iterator(Start
), rebase_iterator(Finish
));
3449 iterator_range
<rebase_iterator
> MachOObjectFile::rebaseTable(Error
&Err
) {
3450 return rebaseTable(Err
, this, getDyldInfoRebaseOpcodes(), is64Bit());
3453 MachOBindEntry::MachOBindEntry(Error
*E
, const MachOObjectFile
*O
,
3454 ArrayRef
<uint8_t> Bytes
, bool is64Bit
, Kind BK
)
3455 : E(E
), O(O
), Opcodes(Bytes
), Ptr(Bytes
.begin()),
3456 PointerSize(is64Bit
? 8 : 4), TableKind(BK
) {}
3458 void MachOBindEntry::moveToFirst() {
3459 Ptr
= Opcodes
.begin();
3463 void MachOBindEntry::moveToEnd() {
3464 Ptr
= Opcodes
.end();
3465 RemainingLoopCount
= 0;
3469 void MachOBindEntry::moveNext() {
3470 ErrorAsOutParameter
ErrAsOutParam(E
);
3471 // If in the middle of some loop, move to next binding in loop.
3472 SegmentOffset
+= AdvanceAmount
;
3473 if (RemainingLoopCount
) {
3474 --RemainingLoopCount
;
3477 // BIND_OPCODE_DONE is only used for padding if we are not aligned to
3478 // pointer size. Therefore it is possible to reach the end without ever having
3479 // seen BIND_OPCODE_DONE.
3480 if (Ptr
== Opcodes
.end()) {
3486 // Parse next opcode and set up next loop.
3487 const uint8_t *OpcodeStart
= Ptr
;
3488 uint8_t Byte
= *Ptr
++;
3489 uint8_t ImmValue
= Byte
& MachO::BIND_IMMEDIATE_MASK
;
3490 uint8_t Opcode
= Byte
& MachO::BIND_OPCODE_MASK
;
3491 int8_t SignExtended
;
3492 const uint8_t *SymStart
;
3493 uint32_t Count
, Skip
;
3494 const char *error
= nullptr;
3496 case MachO::BIND_OPCODE_DONE
:
3497 if (TableKind
== Kind::Lazy
) {
3498 // Lazying bindings have a DONE opcode between entries. Need to ignore
3499 // it to advance to next entry. But need not if this is last entry.
3500 bool NotLastEntry
= false;
3501 for (const uint8_t *P
= Ptr
; P
< Opcodes
.end(); ++P
) {
3503 NotLastEntry
= true;
3511 DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");
3513 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
:
3514 if (TableKind
== Kind::Weak
) {
3515 *E
= malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
3516 "weak bind table for opcode at: 0x" +
3517 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3522 LibraryOrdinalSet
= true;
3523 if (ImmValue
> O
->getLibraryCount()) {
3524 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3525 "library ordinal: " +
3526 Twine((int)ImmValue
) + " (max " +
3527 Twine((int)O
->getLibraryCount()) +
3528 ") for opcode at: 0x" +
3529 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3535 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
3536 << "Ordinal=" << Ordinal
<< "\n");
3538 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB
:
3539 if (TableKind
== Kind::Weak
) {
3540 *E
= malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
3541 "weak bind table for opcode at: 0x" +
3542 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3546 Ordinal
= readULEB128(&error
);
3547 LibraryOrdinalSet
= true;
3549 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
3550 Twine(error
) + " for opcode at: 0x" +
3551 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3555 if (Ordinal
> (int)O
->getLibraryCount()) {
3556 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3557 "library ordinal: " +
3558 Twine((int)Ordinal
) + " (max " +
3559 Twine((int)O
->getLibraryCount()) +
3560 ") for opcode at: 0x" +
3561 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3567 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
3568 << "Ordinal=" << Ordinal
<< "\n");
3570 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM
:
3571 if (TableKind
== Kind::Weak
) {
3572 *E
= malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
3573 "weak bind table for opcode at: 0x" +
3574 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3579 SignExtended
= MachO::BIND_OPCODE_MASK
| ImmValue
;
3580 Ordinal
= SignExtended
;
3581 if (Ordinal
< MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP
) {
3582 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
3583 "special ordinal: " +
3584 Twine((int)Ordinal
) + " for opcode at: 0x" +
3585 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3591 LibraryOrdinalSet
= true;
3594 dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
3595 << "Ordinal=" << Ordinal
<< "\n");
3597 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
:
3600 while (*Ptr
&& (Ptr
< Opcodes
.end())) {
3603 if (Ptr
== Opcodes
.end()) {
3604 *E
= malformedError(
3605 "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
3606 "symbol name extends past opcodes for opcode at: 0x" +
3607 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3611 SymbolName
= StringRef(reinterpret_cast<const char*>(SymStart
),
3616 dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
3617 << "SymbolName=" << SymbolName
<< "\n");
3618 if (TableKind
== Kind::Weak
) {
3619 if (ImmValue
& MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION
)
3623 case MachO::BIND_OPCODE_SET_TYPE_IMM
:
3624 BindType
= ImmValue
;
3625 if (ImmValue
> MachO::BIND_TYPE_TEXT_PCREL32
) {
3626 *E
= malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
3627 Twine((int)ImmValue
) + " for opcode at: 0x" +
3628 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3634 dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
3635 << "BindType=" << (int)BindType
<< "\n");
3637 case MachO::BIND_OPCODE_SET_ADDEND_SLEB
:
3638 Addend
= readSLEB128(&error
);
3640 *E
= malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error
) +
3641 " for opcode at: 0x" +
3642 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3648 dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
3649 << "Addend=" << Addend
<< "\n");
3651 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
:
3652 SegmentIndex
= ImmValue
;
3653 SegmentOffset
= readULEB128(&error
);
3655 *E
= malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3656 Twine(error
) + " for opcode at: 0x" +
3657 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3661 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3664 *E
= malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3665 Twine(error
) + " for opcode at: 0x" +
3666 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3672 dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3673 << "SegmentIndex=" << SegmentIndex
<< ", "
3674 << format("SegmentOffset=0x%06X", SegmentOffset
)
3677 case MachO::BIND_OPCODE_ADD_ADDR_ULEB
:
3678 SegmentOffset
+= readULEB128(&error
);
3680 *E
= malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3681 " for opcode at: 0x" +
3682 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3686 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3689 *E
= malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3690 " for opcode at: 0x" +
3691 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3695 DEBUG_WITH_TYPE("mach-o-bind",
3696 dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
3697 << format("SegmentOffset=0x%06X",
3698 SegmentOffset
) << "\n");
3700 case MachO::BIND_OPCODE_DO_BIND
:
3701 AdvanceAmount
= PointerSize
;
3702 RemainingLoopCount
= 0;
3703 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3706 *E
= malformedError("for BIND_OPCODE_DO_BIND " + Twine(error
) +
3707 " for opcode at: 0x" +
3708 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3712 if (SymbolName
== StringRef()) {
3713 *E
= malformedError(
3714 "for BIND_OPCODE_DO_BIND missing preceding "
3715 "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
3716 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3720 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
3722 malformedError("for BIND_OPCODE_DO_BIND missing preceding "
3723 "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3724 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3728 DEBUG_WITH_TYPE("mach-o-bind",
3729 dbgs() << "BIND_OPCODE_DO_BIND: "
3730 << format("SegmentOffset=0x%06X",
3731 SegmentOffset
) << "\n");
3733 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB
:
3734 if (TableKind
== Kind::Lazy
) {
3735 *E
= malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
3736 "lazy bind table for opcode at: 0x" +
3737 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3741 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3744 *E
= malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3745 Twine(error
) + " for opcode at: 0x" +
3746 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3750 if (SymbolName
== StringRef()) {
3751 *E
= malformedError(
3752 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3753 "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
3755 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3759 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
3760 *E
= malformedError(
3761 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3762 "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3763 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3767 AdvanceAmount
= readULEB128(&error
) + PointerSize
;
3769 *E
= malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3770 Twine(error
) + " for opcode at: 0x" +
3771 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3775 // Note, this is not really an error until the next bind but make no sense
3776 // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
3778 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
+
3779 AdvanceAmount
, PointerSize
);
3781 *E
= malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
3783 Twine(error
) + " for opcode at: 0x" +
3784 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3788 RemainingLoopCount
= 0;
3791 dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
3792 << format("SegmentOffset=0x%06X", SegmentOffset
)
3793 << ", AdvanceAmount=" << AdvanceAmount
3794 << ", RemainingLoopCount=" << RemainingLoopCount
3797 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED
:
3798 if (TableKind
== Kind::Lazy
) {
3799 *E
= malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
3800 "allowed in lazy bind table for opcode at: 0x" +
3801 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3805 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3808 *E
= malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
3809 Twine(error
) + " for opcode at: 0x" +
3810 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3814 if (SymbolName
== StringRef()) {
3815 *E
= malformedError(
3816 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3817 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3819 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3823 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
3824 *E
= malformedError(
3825 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3826 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3828 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3832 AdvanceAmount
= ImmValue
* PointerSize
+ PointerSize
;
3833 RemainingLoopCount
= 0;
3834 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
+
3835 AdvanceAmount
, PointerSize
);
3838 malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3839 " (after adding immediate times the pointer size) " +
3840 Twine(error
) + " for opcode at: 0x" +
3841 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3845 DEBUG_WITH_TYPE("mach-o-bind",
3847 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
3848 << format("SegmentOffset=0x%06X", SegmentOffset
) << "\n");
3850 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB
:
3851 if (TableKind
== Kind::Lazy
) {
3852 *E
= malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
3853 "allowed in lazy bind table for opcode at: 0x" +
3854 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3858 Count
= readULEB128(&error
);
3860 RemainingLoopCount
= Count
- 1;
3862 RemainingLoopCount
= 0;
3864 *E
= malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3866 Twine(error
) + " for opcode at: 0x" +
3867 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3871 Skip
= readULEB128(&error
);
3872 AdvanceAmount
= Skip
+ PointerSize
;
3874 *E
= malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3876 Twine(error
) + " for opcode at: 0x" +
3877 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3881 if (SymbolName
== StringRef()) {
3882 *E
= malformedError(
3883 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3884 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3886 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3890 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
3891 *E
= malformedError(
3892 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3893 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3895 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3899 error
= O
->BindEntryCheckSegAndOffsets(SegmentIndex
, SegmentOffset
,
3900 PointerSize
, Count
, Skip
);
3903 malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
3904 Twine(error
) + " for opcode at: 0x" +
3905 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3911 dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
3912 << format("SegmentOffset=0x%06X", SegmentOffset
)
3913 << ", AdvanceAmount=" << AdvanceAmount
3914 << ", RemainingLoopCount=" << RemainingLoopCount
3918 *E
= malformedError("bad bind info (bad opcode value 0x" +
3919 Twine::utohexstr(Opcode
) + " for opcode at: 0x" +
3920 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3927 uint64_t MachOBindEntry::readULEB128(const char **error
) {
3929 uint64_t Result
= decodeULEB128(Ptr
, &Count
, Opcodes
.end(), error
);
3931 if (Ptr
> Opcodes
.end())
3932 Ptr
= Opcodes
.end();
3936 int64_t MachOBindEntry::readSLEB128(const char **error
) {
3938 int64_t Result
= decodeSLEB128(Ptr
, &Count
, Opcodes
.end(), error
);
3940 if (Ptr
> Opcodes
.end())
3941 Ptr
= Opcodes
.end();
3945 int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex
; }
3947 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset
; }
3949 StringRef
MachOBindEntry::typeName() const {
3951 case MachO::BIND_TYPE_POINTER
:
3953 case MachO::BIND_TYPE_TEXT_ABSOLUTE32
:
3954 return "text abs32";
3955 case MachO::BIND_TYPE_TEXT_PCREL32
:
3956 return "text rel32";
3961 StringRef
MachOBindEntry::symbolName() const { return SymbolName
; }
3963 int64_t MachOBindEntry::addend() const { return Addend
; }
3965 uint32_t MachOBindEntry::flags() const { return Flags
; }
3967 int MachOBindEntry::ordinal() const { return Ordinal
; }
3969 // For use with the SegIndex of a checked Mach-O Bind entry
3970 // to get the segment name.
3971 StringRef
MachOBindEntry::segmentName() const {
3972 return O
->BindRebaseSegmentName(SegmentIndex
);
3975 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3976 // to get the section name.
3977 StringRef
MachOBindEntry::sectionName() const {
3978 return O
->BindRebaseSectionName(SegmentIndex
, SegmentOffset
);
3981 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3982 // to get the address.
3983 uint64_t MachOBindEntry::address() const {
3984 return O
->BindRebaseAddress(SegmentIndex
, SegmentOffset
);
3987 bool MachOBindEntry::operator==(const MachOBindEntry
&Other
) const {
3988 #ifdef EXPENSIVE_CHECKS
3989 assert(Opcodes
== Other
.Opcodes
&& "compare iterators of different files");
3991 assert(Opcodes
.data() == Other
.Opcodes
.data() && "compare iterators of different files");
3993 return (Ptr
== Other
.Ptr
) &&
3994 (RemainingLoopCount
== Other
.RemainingLoopCount
) &&
3995 (Done
== Other
.Done
);
3998 // Build table of sections so SegIndex/SegOffset pairs can be translated.
3999 BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile
*Obj
) {
4000 uint32_t CurSegIndex
= Obj
->hasPageZeroSegment() ? 1 : 0;
4001 StringRef CurSegName
;
4002 uint64_t CurSegAddress
;
4003 for (const SectionRef
&Section
: Obj
->sections()) {
4005 Section
.getName(Info
.SectionName
);
4006 Info
.Address
= Section
.getAddress();
4007 Info
.Size
= Section
.getSize();
4009 Obj
->getSectionFinalSegmentName(Section
.getRawDataRefImpl());
4010 if (!Info
.SegmentName
.equals(CurSegName
)) {
4012 CurSegName
= Info
.SegmentName
;
4013 CurSegAddress
= Info
.Address
;
4015 Info
.SegmentIndex
= CurSegIndex
- 1;
4016 Info
.OffsetInSegment
= Info
.Address
- CurSegAddress
;
4017 Info
.SegmentStartAddress
= CurSegAddress
;
4018 Sections
.push_back(Info
);
4020 MaxSegIndex
= CurSegIndex
;
4023 // For use with a SegIndex, SegOffset, and PointerSize triple in
4024 // MachOBindEntry::moveNext() to validate a MachOBindEntry or MachORebaseEntry.
4026 // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
4027 // that fully contains a pointer at that location. Multiple fixups in a bind
4028 // (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can
4029 // be tested via the Count and Skip parameters.
4030 const char * BindRebaseSegInfo::checkSegAndOffsets(int32_t SegIndex
,
4032 uint8_t PointerSize
,
4036 return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
4037 if (SegIndex
>= MaxSegIndex
)
4038 return "bad segIndex (too large)";
4039 for (uint32_t i
= 0; i
< Count
; ++i
) {
4040 uint32_t Start
= SegOffset
+ i
* (PointerSize
+ Skip
);
4041 uint32_t End
= Start
+ PointerSize
;
4043 for (const SectionInfo
&SI
: Sections
) {
4044 if (SI
.SegmentIndex
!= SegIndex
)
4046 if ((SI
.OffsetInSegment
<=Start
) && (Start
<(SI
.OffsetInSegment
+SI
.Size
))) {
4047 if (End
<= SI
.OffsetInSegment
+ SI
.Size
) {
4052 return "bad offset, extends beyond section boundary";
4056 return "bad offset, not in section";
4061 // For use with the SegIndex of a checked Mach-O Bind or Rebase entry
4062 // to get the segment name.
4063 StringRef
BindRebaseSegInfo::segmentName(int32_t SegIndex
) {
4064 for (const SectionInfo
&SI
: Sections
) {
4065 if (SI
.SegmentIndex
== SegIndex
)
4066 return SI
.SegmentName
;
4068 llvm_unreachable("invalid SegIndex");
4071 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4072 // to get the SectionInfo.
4073 const BindRebaseSegInfo::SectionInfo
&BindRebaseSegInfo::findSection(
4074 int32_t SegIndex
, uint64_t SegOffset
) {
4075 for (const SectionInfo
&SI
: Sections
) {
4076 if (SI
.SegmentIndex
!= SegIndex
)
4078 if (SI
.OffsetInSegment
> SegOffset
)
4080 if (SegOffset
>= (SI
.OffsetInSegment
+ SI
.Size
))
4084 llvm_unreachable("SegIndex and SegOffset not in any section");
4087 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4088 // entry to get the section name.
4089 StringRef
BindRebaseSegInfo::sectionName(int32_t SegIndex
,
4090 uint64_t SegOffset
) {
4091 return findSection(SegIndex
, SegOffset
).SectionName
;
4094 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4095 // entry to get the address.
4096 uint64_t BindRebaseSegInfo::address(uint32_t SegIndex
, uint64_t OffsetInSeg
) {
4097 const SectionInfo
&SI
= findSection(SegIndex
, OffsetInSeg
);
4098 return SI
.SegmentStartAddress
+ OffsetInSeg
;
4101 iterator_range
<bind_iterator
>
4102 MachOObjectFile::bindTable(Error
&Err
, MachOObjectFile
*O
,
4103 ArrayRef
<uint8_t> Opcodes
, bool is64
,
4104 MachOBindEntry::Kind BKind
) {
4105 if (O
->BindRebaseSectionTable
== nullptr)
4106 O
->BindRebaseSectionTable
= llvm::make_unique
<BindRebaseSegInfo
>(O
);
4107 MachOBindEntry
Start(&Err
, O
, Opcodes
, is64
, BKind
);
4108 Start
.moveToFirst();
4110 MachOBindEntry
Finish(&Err
, O
, Opcodes
, is64
, BKind
);
4113 return make_range(bind_iterator(Start
), bind_iterator(Finish
));
4116 iterator_range
<bind_iterator
> MachOObjectFile::bindTable(Error
&Err
) {
4117 return bindTable(Err
, this, getDyldInfoBindOpcodes(), is64Bit(),
4118 MachOBindEntry::Kind::Regular
);
4121 iterator_range
<bind_iterator
> MachOObjectFile::lazyBindTable(Error
&Err
) {
4122 return bindTable(Err
, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
4123 MachOBindEntry::Kind::Lazy
);
4126 iterator_range
<bind_iterator
> MachOObjectFile::weakBindTable(Error
&Err
) {
4127 return bindTable(Err
, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
4128 MachOBindEntry::Kind::Weak
);
4131 MachOObjectFile::load_command_iterator
4132 MachOObjectFile::begin_load_commands() const {
4133 return LoadCommands
.begin();
4136 MachOObjectFile::load_command_iterator
4137 MachOObjectFile::end_load_commands() const {
4138 return LoadCommands
.end();
4141 iterator_range
<MachOObjectFile::load_command_iterator
>
4142 MachOObjectFile::load_commands() const {
4143 return make_range(begin_load_commands(), end_load_commands());
4147 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec
) const {
4148 ArrayRef
<char> Raw
= getSectionRawFinalSegmentName(Sec
);
4149 return parseSegmentOrSectionName(Raw
.data());
4153 MachOObjectFile::getSectionRawName(DataRefImpl Sec
) const {
4154 assert(Sec
.d
.a
< Sections
.size() && "Should have detected this earlier");
4155 const section_base
*Base
=
4156 reinterpret_cast<const section_base
*>(Sections
[Sec
.d
.a
]);
4157 return makeArrayRef(Base
->sectname
);
4161 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec
) const {
4162 assert(Sec
.d
.a
< Sections
.size() && "Should have detected this earlier");
4163 const section_base
*Base
=
4164 reinterpret_cast<const section_base
*>(Sections
[Sec
.d
.a
]);
4165 return makeArrayRef(Base
->segname
);
4169 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info
&RE
)
4171 if (getCPUType(*this) == MachO::CPU_TYPE_X86_64
)
4173 return getPlainRelocationAddress(RE
) & MachO::R_SCATTERED
;
4176 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
4177 const MachO::any_relocation_info
&RE
) const {
4178 if (isLittleEndian())
4179 return RE
.r_word1
& 0xffffff;
4180 return RE
.r_word1
>> 8;
4183 bool MachOObjectFile::getPlainRelocationExternal(
4184 const MachO::any_relocation_info
&RE
) const {
4185 if (isLittleEndian())
4186 return (RE
.r_word1
>> 27) & 1;
4187 return (RE
.r_word1
>> 4) & 1;
4190 bool MachOObjectFile::getScatteredRelocationScattered(
4191 const MachO::any_relocation_info
&RE
) const {
4192 return RE
.r_word0
>> 31;
4195 uint32_t MachOObjectFile::getScatteredRelocationValue(
4196 const MachO::any_relocation_info
&RE
) const {
4200 uint32_t MachOObjectFile::getScatteredRelocationType(
4201 const MachO::any_relocation_info
&RE
) const {
4202 return (RE
.r_word0
>> 24) & 0xf;
4205 unsigned MachOObjectFile::getAnyRelocationAddress(
4206 const MachO::any_relocation_info
&RE
) const {
4207 if (isRelocationScattered(RE
))
4208 return getScatteredRelocationAddress(RE
);
4209 return getPlainRelocationAddress(RE
);
4212 unsigned MachOObjectFile::getAnyRelocationPCRel(
4213 const MachO::any_relocation_info
&RE
) const {
4214 if (isRelocationScattered(RE
))
4215 return getScatteredRelocationPCRel(RE
);
4216 return getPlainRelocationPCRel(*this, RE
);
4219 unsigned MachOObjectFile::getAnyRelocationLength(
4220 const MachO::any_relocation_info
&RE
) const {
4221 if (isRelocationScattered(RE
))
4222 return getScatteredRelocationLength(RE
);
4223 return getPlainRelocationLength(*this, RE
);
4227 MachOObjectFile::getAnyRelocationType(
4228 const MachO::any_relocation_info
&RE
) const {
4229 if (isRelocationScattered(RE
))
4230 return getScatteredRelocationType(RE
);
4231 return getPlainRelocationType(*this, RE
);
4235 MachOObjectFile::getAnyRelocationSection(
4236 const MachO::any_relocation_info
&RE
) const {
4237 if (isRelocationScattered(RE
) || getPlainRelocationExternal(RE
))
4238 return *section_end();
4239 unsigned SecNum
= getPlainRelocationSymbolNum(RE
);
4240 if (SecNum
== MachO::R_ABS
|| SecNum
> Sections
.size())
4241 return *section_end();
4243 DRI
.d
.a
= SecNum
- 1;
4244 return SectionRef(DRI
, this);
4247 MachO::section
MachOObjectFile::getSection(DataRefImpl DRI
) const {
4248 assert(DRI
.d
.a
< Sections
.size() && "Should have detected this earlier");
4249 return getStruct
<MachO::section
>(*this, Sections
[DRI
.d
.a
]);
4252 MachO::section_64
MachOObjectFile::getSection64(DataRefImpl DRI
) const {
4253 assert(DRI
.d
.a
< Sections
.size() && "Should have detected this earlier");
4254 return getStruct
<MachO::section_64
>(*this, Sections
[DRI
.d
.a
]);
4257 MachO::section
MachOObjectFile::getSection(const LoadCommandInfo
&L
,
4258 unsigned Index
) const {
4259 const char *Sec
= getSectionPtr(*this, L
, Index
);
4260 return getStruct
<MachO::section
>(*this, Sec
);
4263 MachO::section_64
MachOObjectFile::getSection64(const LoadCommandInfo
&L
,
4264 unsigned Index
) const {
4265 const char *Sec
= getSectionPtr(*this, L
, Index
);
4266 return getStruct
<MachO::section_64
>(*this, Sec
);
4270 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI
) const {
4271 const char *P
= reinterpret_cast<const char *>(DRI
.p
);
4272 return getStruct
<MachO::nlist
>(*this, P
);
4276 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI
) const {
4277 const char *P
= reinterpret_cast<const char *>(DRI
.p
);
4278 return getStruct
<MachO::nlist_64
>(*this, P
);
4281 MachO::linkedit_data_command
4282 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo
&L
) const {
4283 return getStruct
<MachO::linkedit_data_command
>(*this, L
.Ptr
);
4286 MachO::segment_command
4287 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo
&L
) const {
4288 return getStruct
<MachO::segment_command
>(*this, L
.Ptr
);
4291 MachO::segment_command_64
4292 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo
&L
) const {
4293 return getStruct
<MachO::segment_command_64
>(*this, L
.Ptr
);
4296 MachO::linker_option_command
4297 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo
&L
) const {
4298 return getStruct
<MachO::linker_option_command
>(*this, L
.Ptr
);
4301 MachO::version_min_command
4302 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo
&L
) const {
4303 return getStruct
<MachO::version_min_command
>(*this, L
.Ptr
);
4307 MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo
&L
) const {
4308 return getStruct
<MachO::note_command
>(*this, L
.Ptr
);
4311 MachO::build_version_command
4312 MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo
&L
) const {
4313 return getStruct
<MachO::build_version_command
>(*this, L
.Ptr
);
4316 MachO::build_tool_version
4317 MachOObjectFile::getBuildToolVersion(unsigned index
) const {
4318 return getStruct
<MachO::build_tool_version
>(*this, BuildTools
[index
]);
4321 MachO::dylib_command
4322 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo
&L
) const {
4323 return getStruct
<MachO::dylib_command
>(*this, L
.Ptr
);
4326 MachO::dyld_info_command
4327 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo
&L
) const {
4328 return getStruct
<MachO::dyld_info_command
>(*this, L
.Ptr
);
4331 MachO::dylinker_command
4332 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo
&L
) const {
4333 return getStruct
<MachO::dylinker_command
>(*this, L
.Ptr
);
4337 MachOObjectFile::getUuidCommand(const LoadCommandInfo
&L
) const {
4338 return getStruct
<MachO::uuid_command
>(*this, L
.Ptr
);
4341 MachO::rpath_command
4342 MachOObjectFile::getRpathCommand(const LoadCommandInfo
&L
) const {
4343 return getStruct
<MachO::rpath_command
>(*this, L
.Ptr
);
4346 MachO::source_version_command
4347 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo
&L
) const {
4348 return getStruct
<MachO::source_version_command
>(*this, L
.Ptr
);
4351 MachO::entry_point_command
4352 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo
&L
) const {
4353 return getStruct
<MachO::entry_point_command
>(*this, L
.Ptr
);
4356 MachO::encryption_info_command
4357 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo
&L
) const {
4358 return getStruct
<MachO::encryption_info_command
>(*this, L
.Ptr
);
4361 MachO::encryption_info_command_64
4362 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo
&L
) const {
4363 return getStruct
<MachO::encryption_info_command_64
>(*this, L
.Ptr
);
4366 MachO::sub_framework_command
4367 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo
&L
) const {
4368 return getStruct
<MachO::sub_framework_command
>(*this, L
.Ptr
);
4371 MachO::sub_umbrella_command
4372 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo
&L
) const {
4373 return getStruct
<MachO::sub_umbrella_command
>(*this, L
.Ptr
);
4376 MachO::sub_library_command
4377 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo
&L
) const {
4378 return getStruct
<MachO::sub_library_command
>(*this, L
.Ptr
);
4381 MachO::sub_client_command
4382 MachOObjectFile::getSubClientCommand(const LoadCommandInfo
&L
) const {
4383 return getStruct
<MachO::sub_client_command
>(*this, L
.Ptr
);
4386 MachO::routines_command
4387 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo
&L
) const {
4388 return getStruct
<MachO::routines_command
>(*this, L
.Ptr
);
4391 MachO::routines_command_64
4392 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo
&L
) const {
4393 return getStruct
<MachO::routines_command_64
>(*this, L
.Ptr
);
4396 MachO::thread_command
4397 MachOObjectFile::getThreadCommand(const LoadCommandInfo
&L
) const {
4398 return getStruct
<MachO::thread_command
>(*this, L
.Ptr
);
4401 MachO::any_relocation_info
4402 MachOObjectFile::getRelocation(DataRefImpl Rel
) const {
4404 if (getHeader().filetype
== MachO::MH_OBJECT
) {
4408 MachO::section_64 Sect
= getSection64(Sec
);
4409 Offset
= Sect
.reloff
;
4411 MachO::section Sect
= getSection(Sec
);
4412 Offset
= Sect
.reloff
;
4415 MachO::dysymtab_command DysymtabLoadCmd
= getDysymtabLoadCommand();
4417 Offset
= DysymtabLoadCmd
.extreloff
; // Offset to the external relocations
4419 Offset
= DysymtabLoadCmd
.locreloff
; // Offset to the local relocations
4422 auto P
= reinterpret_cast<const MachO::any_relocation_info
*>(
4423 getPtr(*this, Offset
)) + Rel
.d
.b
;
4424 return getStruct
<MachO::any_relocation_info
>(
4425 *this, reinterpret_cast<const char *>(P
));
4428 MachO::data_in_code_entry
4429 MachOObjectFile::getDice(DataRefImpl Rel
) const {
4430 const char *P
= reinterpret_cast<const char *>(Rel
.p
);
4431 return getStruct
<MachO::data_in_code_entry
>(*this, P
);
4434 const MachO::mach_header
&MachOObjectFile::getHeader() const {
4438 const MachO::mach_header_64
&MachOObjectFile::getHeader64() const {
4443 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
4444 const MachO::dysymtab_command
&DLC
,
4445 unsigned Index
) const {
4446 uint64_t Offset
= DLC
.indirectsymoff
+ Index
* sizeof(uint32_t);
4447 return getStruct
<uint32_t>(*this, getPtr(*this, Offset
));
4450 MachO::data_in_code_entry
4451 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset
,
4452 unsigned Index
) const {
4453 uint64_t Offset
= DataOffset
+ Index
* sizeof(MachO::data_in_code_entry
);
4454 return getStruct
<MachO::data_in_code_entry
>(*this, getPtr(*this, Offset
));
4457 MachO::symtab_command
MachOObjectFile::getSymtabLoadCommand() const {
4459 return getStruct
<MachO::symtab_command
>(*this, SymtabLoadCmd
);
4461 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
4462 MachO::symtab_command Cmd
;
4463 Cmd
.cmd
= MachO::LC_SYMTAB
;
4464 Cmd
.cmdsize
= sizeof(MachO::symtab_command
);
4472 MachO::dysymtab_command
MachOObjectFile::getDysymtabLoadCommand() const {
4473 if (DysymtabLoadCmd
)
4474 return getStruct
<MachO::dysymtab_command
>(*this, DysymtabLoadCmd
);
4476 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
4477 MachO::dysymtab_command Cmd
;
4478 Cmd
.cmd
= MachO::LC_DYSYMTAB
;
4479 Cmd
.cmdsize
= sizeof(MachO::dysymtab_command
);
4490 Cmd
.extrefsymoff
= 0;
4491 Cmd
.nextrefsyms
= 0;
4492 Cmd
.indirectsymoff
= 0;
4493 Cmd
.nindirectsyms
= 0;
4501 MachO::linkedit_data_command
4502 MachOObjectFile::getDataInCodeLoadCommand() const {
4503 if (DataInCodeLoadCmd
)
4504 return getStruct
<MachO::linkedit_data_command
>(*this, DataInCodeLoadCmd
);
4506 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
4507 MachO::linkedit_data_command Cmd
;
4508 Cmd
.cmd
= MachO::LC_DATA_IN_CODE
;
4509 Cmd
.cmdsize
= sizeof(MachO::linkedit_data_command
);
4515 MachO::linkedit_data_command
4516 MachOObjectFile::getLinkOptHintsLoadCommand() const {
4517 if (LinkOptHintsLoadCmd
)
4518 return getStruct
<MachO::linkedit_data_command
>(*this, LinkOptHintsLoadCmd
);
4520 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
4522 MachO::linkedit_data_command Cmd
;
4523 Cmd
.cmd
= MachO::LC_LINKER_OPTIMIZATION_HINT
;
4524 Cmd
.cmdsize
= sizeof(MachO::linkedit_data_command
);
4530 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
4531 if (!DyldInfoLoadCmd
)
4534 auto DyldInfoOrErr
=
4535 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4538 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4539 const uint8_t *Ptr
=
4540 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.rebase_off
));
4541 return makeArrayRef(Ptr
, DyldInfo
.rebase_size
);
4544 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
4545 if (!DyldInfoLoadCmd
)
4548 auto DyldInfoOrErr
=
4549 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4552 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4553 const uint8_t *Ptr
=
4554 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.bind_off
));
4555 return makeArrayRef(Ptr
, DyldInfo
.bind_size
);
4558 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
4559 if (!DyldInfoLoadCmd
)
4562 auto DyldInfoOrErr
=
4563 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4566 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4567 const uint8_t *Ptr
=
4568 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.weak_bind_off
));
4569 return makeArrayRef(Ptr
, DyldInfo
.weak_bind_size
);
4572 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
4573 if (!DyldInfoLoadCmd
)
4576 auto DyldInfoOrErr
=
4577 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4580 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4581 const uint8_t *Ptr
=
4582 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.lazy_bind_off
));
4583 return makeArrayRef(Ptr
, DyldInfo
.lazy_bind_size
);
4586 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
4587 if (!DyldInfoLoadCmd
)
4590 auto DyldInfoOrErr
=
4591 getStructOrErr
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4594 MachO::dyld_info_command DyldInfo
= DyldInfoOrErr
.get();
4595 const uint8_t *Ptr
=
4596 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.export_off
));
4597 return makeArrayRef(Ptr
, DyldInfo
.export_size
);
4600 ArrayRef
<uint8_t> MachOObjectFile::getUuid() const {
4603 // Returning a pointer is fine as uuid doesn't need endian swapping.
4604 const char *Ptr
= UuidLoadCmd
+ offsetof(MachO::uuid_command
, uuid
);
4605 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr
), 16);
4608 StringRef
MachOObjectFile::getStringTableData() const {
4609 MachO::symtab_command S
= getSymtabLoadCommand();
4610 return getData().substr(S
.stroff
, S
.strsize
);
4613 bool MachOObjectFile::is64Bit() const {
4614 return getType() == getMachOType(false, true) ||
4615 getType() == getMachOType(true, true);
4618 void MachOObjectFile::ReadULEB128s(uint64_t Index
,
4619 SmallVectorImpl
<uint64_t> &Out
) const {
4620 DataExtractor
extractor(ObjectFile::getData(), true, 0);
4622 uint32_t offset
= Index
;
4624 while (uint64_t delta
= extractor
.getULEB128(&offset
)) {
4626 Out
.push_back(data
);
4630 bool MachOObjectFile::isRelocatableObject() const {
4631 return getHeader().filetype
== MachO::MH_OBJECT
;
4634 Expected
<std::unique_ptr
<MachOObjectFile
>>
4635 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer
,
4636 uint32_t UniversalCputype
,
4637 uint32_t UniversalIndex
) {
4638 StringRef Magic
= Buffer
.getBuffer().slice(0, 4);
4639 if (Magic
== "\xFE\xED\xFA\xCE")
4640 return MachOObjectFile::create(Buffer
, false, false,
4641 UniversalCputype
, UniversalIndex
);
4642 if (Magic
== "\xCE\xFA\xED\xFE")
4643 return MachOObjectFile::create(Buffer
, true, false,
4644 UniversalCputype
, UniversalIndex
);
4645 if (Magic
== "\xFE\xED\xFA\xCF")
4646 return MachOObjectFile::create(Buffer
, false, true,
4647 UniversalCputype
, UniversalIndex
);
4648 if (Magic
== "\xCF\xFA\xED\xFE")
4649 return MachOObjectFile::create(Buffer
, true, true,
4650 UniversalCputype
, UniversalIndex
);
4651 return make_error
<GenericBinaryError
>("Unrecognized MachO magic number",
4652 object_error::invalid_file_type
);
4655 StringRef
MachOObjectFile::mapDebugSectionName(StringRef Name
) const {
4656 return StringSwitch
<StringRef
>(Name
)
4657 .Case("debug_str_offs", "debug_str_offsets")