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 Section s
= getStruct
<Section
>(Obj
, Sec
);
295 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
296 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
297 s
.flags
!= MachO::S_ZEROFILL
&&
298 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
&&
300 return malformedError("offset field of section " + Twine(J
) + " in " +
301 CmdName
+ " command " + Twine(LoadCommandIndex
) +
302 " extends past the end of the file");
303 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
304 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
305 s
.flags
!= MachO::S_ZEROFILL
&&
306 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
&& S
.fileoff
== 0 &&
307 s
.offset
< SizeOfHeaders
&& s
.size
!= 0)
308 return malformedError("offset field of section " + Twine(J
) + " in " +
309 CmdName
+ " command " + Twine(LoadCommandIndex
) +
310 " not past the headers of the file");
311 uint64_t BigSize
= s
.offset
;
313 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
314 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
315 s
.flags
!= MachO::S_ZEROFILL
&&
316 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
&&
318 return malformedError("offset field plus size field of section " +
319 Twine(J
) + " in " + CmdName
+ " command " +
320 Twine(LoadCommandIndex
) +
321 " extends past the end of the file");
322 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
323 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
324 s
.flags
!= MachO::S_ZEROFILL
&&
325 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
&&
327 return malformedError("size field of section " +
328 Twine(J
) + " in " + CmdName
+ " command " +
329 Twine(LoadCommandIndex
) +
330 " greater than the segment");
331 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
332 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&& s
.size
!= 0 &&
334 return malformedError("addr field of section " + Twine(J
) + " in " +
335 CmdName
+ " command " + Twine(LoadCommandIndex
) +
336 " less than the segment's vmaddr");
339 uint64_t BigEnd
= S
.vmaddr
;
341 if (S
.vmsize
!= 0 && s
.size
!= 0 && BigSize
> BigEnd
)
342 return malformedError("addr field plus size of section " + Twine(J
) +
343 " in " + CmdName
+ " command " +
344 Twine(LoadCommandIndex
) +
345 " greater than than "
346 "the segment's vmaddr plus vmsize");
347 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
&&
348 Obj
.getHeader().filetype
!= MachO::MH_DSYM
&&
349 s
.flags
!= MachO::S_ZEROFILL
&&
350 s
.flags
!= MachO::S_THREAD_LOCAL_ZEROFILL
)
351 if (Error Err
= checkOverlappingElement(Elements
, s
.offset
, s
.size
,
354 if (s
.reloff
> FileSize
)
355 return malformedError("reloff field of section " + Twine(J
) + " in " +
356 CmdName
+ " command " + Twine(LoadCommandIndex
) +
357 " extends past the end of the file");
359 BigSize
*= sizeof(struct MachO::relocation_info
);
361 if (BigSize
> FileSize
)
362 return malformedError("reloff field plus nreloc field times sizeof("
363 "struct relocation_info) of section " +
364 Twine(J
) + " in " + CmdName
+ " command " +
365 Twine(LoadCommandIndex
) +
366 " extends past the end of the file");
367 if (Error Err
= checkOverlappingElement(Elements
, s
.reloff
, s
.nreloc
*
369 MachO::relocation_info
),
370 "section relocation entries"))
373 if (S
.fileoff
> FileSize
)
374 return malformedError("load command " + Twine(LoadCommandIndex
) +
375 " fileoff field in " + CmdName
+
376 " extends past the end of the file");
377 uint64_t BigSize
= S
.fileoff
;
378 BigSize
+= S
.filesize
;
379 if (BigSize
> FileSize
)
380 return malformedError("load command " + Twine(LoadCommandIndex
) +
381 " fileoff field plus filesize field in " +
382 CmdName
+ " extends past the end of the file");
383 if (S
.vmsize
!= 0 && S
.filesize
> S
.vmsize
)
384 return malformedError("load command " + Twine(LoadCommandIndex
) +
385 " filesize field in " + CmdName
+
386 " greater than vmsize field");
387 IsPageZeroSegment
|= StringRef("__PAGEZERO").equals(S
.segname
);
389 return SegOrErr
.takeError();
391 return Error::success();
394 static Error
checkSymtabCommand(const MachOObjectFile
&Obj
,
395 const MachOObjectFile::LoadCommandInfo
&Load
,
396 uint32_t LoadCommandIndex
,
397 const char **SymtabLoadCmd
,
398 std::list
<MachOElement
> &Elements
) {
399 if (Load
.C
.cmdsize
< sizeof(MachO::symtab_command
))
400 return malformedError("load command " + Twine(LoadCommandIndex
) +
401 " LC_SYMTAB cmdsize too small");
402 if (*SymtabLoadCmd
!= nullptr)
403 return malformedError("more than one LC_SYMTAB command");
404 MachO::symtab_command Symtab
=
405 getStruct
<MachO::symtab_command
>(Obj
, Load
.Ptr
);
406 if (Symtab
.cmdsize
!= sizeof(MachO::symtab_command
))
407 return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex
) +
408 " has incorrect cmdsize");
409 uint64_t FileSize
= Obj
.getData().size();
410 if (Symtab
.symoff
> FileSize
)
411 return malformedError("symoff field of LC_SYMTAB command " +
412 Twine(LoadCommandIndex
) + " extends past the end "
414 uint64_t SymtabSize
= Symtab
.nsyms
;
415 const char *struct_nlist_name
;
417 SymtabSize
*= sizeof(MachO::nlist_64
);
418 struct_nlist_name
= "struct nlist_64";
420 SymtabSize
*= sizeof(MachO::nlist
);
421 struct_nlist_name
= "struct nlist";
423 uint64_t BigSize
= SymtabSize
;
424 BigSize
+= Symtab
.symoff
;
425 if (BigSize
> FileSize
)
426 return malformedError("symoff field plus nsyms field times sizeof(" +
427 Twine(struct_nlist_name
) + ") of LC_SYMTAB command " +
428 Twine(LoadCommandIndex
) + " extends past the end "
430 if (Error Err
= checkOverlappingElement(Elements
, Symtab
.symoff
, SymtabSize
,
433 if (Symtab
.stroff
> FileSize
)
434 return malformedError("stroff field of LC_SYMTAB command " +
435 Twine(LoadCommandIndex
) + " extends past the end "
437 BigSize
= Symtab
.stroff
;
438 BigSize
+= Symtab
.strsize
;
439 if (BigSize
> FileSize
)
440 return malformedError("stroff field plus strsize field of LC_SYMTAB "
441 "command " + Twine(LoadCommandIndex
) + " extends "
442 "past the end of the file");
443 if (Error Err
= checkOverlappingElement(Elements
, Symtab
.stroff
,
444 Symtab
.strsize
, "string table"))
446 *SymtabLoadCmd
= Load
.Ptr
;
447 return Error::success();
450 static Error
checkDysymtabCommand(const MachOObjectFile
&Obj
,
451 const MachOObjectFile::LoadCommandInfo
&Load
,
452 uint32_t LoadCommandIndex
,
453 const char **DysymtabLoadCmd
,
454 std::list
<MachOElement
> &Elements
) {
455 if (Load
.C
.cmdsize
< sizeof(MachO::dysymtab_command
))
456 return malformedError("load command " + Twine(LoadCommandIndex
) +
457 " LC_DYSYMTAB cmdsize too small");
458 if (*DysymtabLoadCmd
!= nullptr)
459 return malformedError("more than one LC_DYSYMTAB command");
460 MachO::dysymtab_command Dysymtab
=
461 getStruct
<MachO::dysymtab_command
>(Obj
, Load
.Ptr
);
462 if (Dysymtab
.cmdsize
!= sizeof(MachO::dysymtab_command
))
463 return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex
) +
464 " has incorrect cmdsize");
465 uint64_t FileSize
= Obj
.getData().size();
466 if (Dysymtab
.tocoff
> FileSize
)
467 return malformedError("tocoff field of LC_DYSYMTAB command " +
468 Twine(LoadCommandIndex
) + " extends past the end of "
470 uint64_t BigSize
= Dysymtab
.ntoc
;
471 BigSize
*= sizeof(MachO::dylib_table_of_contents
);
472 BigSize
+= Dysymtab
.tocoff
;
473 if (BigSize
> FileSize
)
474 return malformedError("tocoff field plus ntoc field times sizeof(struct "
475 "dylib_table_of_contents) of LC_DYSYMTAB command " +
476 Twine(LoadCommandIndex
) + " extends past the end of "
478 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.tocoff
,
479 Dysymtab
.ntoc
* sizeof(struct
480 MachO::dylib_table_of_contents
),
481 "table of contents"))
483 if (Dysymtab
.modtaboff
> FileSize
)
484 return malformedError("modtaboff field of LC_DYSYMTAB command " +
485 Twine(LoadCommandIndex
) + " extends past the end of "
487 BigSize
= Dysymtab
.nmodtab
;
488 const char *struct_dylib_module_name
;
489 uint64_t sizeof_modtab
;
491 sizeof_modtab
= sizeof(MachO::dylib_module_64
);
492 struct_dylib_module_name
= "struct dylib_module_64";
494 sizeof_modtab
= sizeof(MachO::dylib_module
);
495 struct_dylib_module_name
= "struct dylib_module";
497 BigSize
*= sizeof_modtab
;
498 BigSize
+= Dysymtab
.modtaboff
;
499 if (BigSize
> FileSize
)
500 return malformedError("modtaboff field plus nmodtab field times sizeof(" +
501 Twine(struct_dylib_module_name
) + ") of LC_DYSYMTAB "
502 "command " + Twine(LoadCommandIndex
) + " extends "
503 "past the end of the file");
504 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.modtaboff
,
505 Dysymtab
.nmodtab
* sizeof_modtab
,
508 if (Dysymtab
.extrefsymoff
> FileSize
)
509 return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
510 Twine(LoadCommandIndex
) + " extends past the end of "
512 BigSize
= Dysymtab
.nextrefsyms
;
513 BigSize
*= sizeof(MachO::dylib_reference
);
514 BigSize
+= Dysymtab
.extrefsymoff
;
515 if (BigSize
> FileSize
)
516 return malformedError("extrefsymoff field plus nextrefsyms field times "
517 "sizeof(struct dylib_reference) of LC_DYSYMTAB "
518 "command " + Twine(LoadCommandIndex
) + " extends "
519 "past the end of the file");
520 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.extrefsymoff
,
521 Dysymtab
.nextrefsyms
*
522 sizeof(MachO::dylib_reference
),
525 if (Dysymtab
.indirectsymoff
> FileSize
)
526 return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
527 Twine(LoadCommandIndex
) + " extends past the end of "
529 BigSize
= Dysymtab
.nindirectsyms
;
530 BigSize
*= sizeof(uint32_t);
531 BigSize
+= Dysymtab
.indirectsymoff
;
532 if (BigSize
> FileSize
)
533 return malformedError("indirectsymoff field plus nindirectsyms field times "
534 "sizeof(uint32_t) of LC_DYSYMTAB command " +
535 Twine(LoadCommandIndex
) + " extends past the end of "
537 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.indirectsymoff
,
538 Dysymtab
.nindirectsyms
*
542 if (Dysymtab
.extreloff
> FileSize
)
543 return malformedError("extreloff field of LC_DYSYMTAB command " +
544 Twine(LoadCommandIndex
) + " extends past the end of "
546 BigSize
= Dysymtab
.nextrel
;
547 BigSize
*= sizeof(MachO::relocation_info
);
548 BigSize
+= Dysymtab
.extreloff
;
549 if (BigSize
> FileSize
)
550 return malformedError("extreloff field plus nextrel field times sizeof"
551 "(struct relocation_info) of LC_DYSYMTAB command " +
552 Twine(LoadCommandIndex
) + " extends past the end of "
554 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.extreloff
,
556 sizeof(MachO::relocation_info
),
557 "external relocation table"))
559 if (Dysymtab
.locreloff
> FileSize
)
560 return malformedError("locreloff field of LC_DYSYMTAB command " +
561 Twine(LoadCommandIndex
) + " extends past the end of "
563 BigSize
= Dysymtab
.nlocrel
;
564 BigSize
*= sizeof(MachO::relocation_info
);
565 BigSize
+= Dysymtab
.locreloff
;
566 if (BigSize
> FileSize
)
567 return malformedError("locreloff field plus nlocrel field times sizeof"
568 "(struct relocation_info) of LC_DYSYMTAB command " +
569 Twine(LoadCommandIndex
) + " extends past the end of "
571 if (Error Err
= checkOverlappingElement(Elements
, Dysymtab
.locreloff
,
573 sizeof(MachO::relocation_info
),
574 "local relocation table"))
576 *DysymtabLoadCmd
= Load
.Ptr
;
577 return Error::success();
580 static Error
checkLinkeditDataCommand(const MachOObjectFile
&Obj
,
581 const MachOObjectFile::LoadCommandInfo
&Load
,
582 uint32_t LoadCommandIndex
,
583 const char **LoadCmd
, const char *CmdName
,
584 std::list
<MachOElement
> &Elements
,
585 const char *ElementName
) {
586 if (Load
.C
.cmdsize
< sizeof(MachO::linkedit_data_command
))
587 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
588 CmdName
+ " cmdsize too small");
589 if (*LoadCmd
!= nullptr)
590 return malformedError("more than one " + Twine(CmdName
) + " command");
591 MachO::linkedit_data_command LinkData
=
592 getStruct
<MachO::linkedit_data_command
>(Obj
, Load
.Ptr
);
593 if (LinkData
.cmdsize
!= sizeof(MachO::linkedit_data_command
))
594 return malformedError(Twine(CmdName
) + " command " +
595 Twine(LoadCommandIndex
) + " has incorrect cmdsize");
596 uint64_t FileSize
= Obj
.getData().size();
597 if (LinkData
.dataoff
> FileSize
)
598 return malformedError("dataoff field of " + Twine(CmdName
) + " command " +
599 Twine(LoadCommandIndex
) + " extends past the end of "
601 uint64_t BigSize
= LinkData
.dataoff
;
602 BigSize
+= LinkData
.datasize
;
603 if (BigSize
> FileSize
)
604 return malformedError("dataoff field plus datasize field of " +
605 Twine(CmdName
) + " command " +
606 Twine(LoadCommandIndex
) + " extends past the end of "
608 if (Error Err
= checkOverlappingElement(Elements
, LinkData
.dataoff
,
609 LinkData
.datasize
, ElementName
))
612 return Error::success();
615 static Error
checkDyldInfoCommand(const MachOObjectFile
&Obj
,
616 const MachOObjectFile::LoadCommandInfo
&Load
,
617 uint32_t LoadCommandIndex
,
618 const char **LoadCmd
, const char *CmdName
,
619 std::list
<MachOElement
> &Elements
) {
620 if (Load
.C
.cmdsize
< sizeof(MachO::dyld_info_command
))
621 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
622 CmdName
+ " cmdsize too small");
623 if (*LoadCmd
!= nullptr)
624 return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
626 MachO::dyld_info_command DyldInfo
=
627 getStruct
<MachO::dyld_info_command
>(Obj
, Load
.Ptr
);
628 if (DyldInfo
.cmdsize
!= sizeof(MachO::dyld_info_command
))
629 return malformedError(Twine(CmdName
) + " command " +
630 Twine(LoadCommandIndex
) + " has incorrect cmdsize");
631 uint64_t FileSize
= Obj
.getData().size();
632 if (DyldInfo
.rebase_off
> FileSize
)
633 return malformedError("rebase_off field of " + Twine(CmdName
) +
634 " command " + Twine(LoadCommandIndex
) + " extends "
635 "past the end of the file");
636 uint64_t BigSize
= DyldInfo
.rebase_off
;
637 BigSize
+= DyldInfo
.rebase_size
;
638 if (BigSize
> FileSize
)
639 return malformedError("rebase_off field plus rebase_size field of " +
640 Twine(CmdName
) + " command " +
641 Twine(LoadCommandIndex
) + " extends past the end of "
643 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.rebase_off
,
644 DyldInfo
.rebase_size
,
647 if (DyldInfo
.bind_off
> FileSize
)
648 return malformedError("bind_off field of " + Twine(CmdName
) +
649 " command " + Twine(LoadCommandIndex
) + " extends "
650 "past the end of the file");
651 BigSize
= DyldInfo
.bind_off
;
652 BigSize
+= DyldInfo
.bind_size
;
653 if (BigSize
> FileSize
)
654 return malformedError("bind_off field plus bind_size field of " +
655 Twine(CmdName
) + " command " +
656 Twine(LoadCommandIndex
) + " extends past the end of "
658 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.bind_off
,
662 if (DyldInfo
.weak_bind_off
> FileSize
)
663 return malformedError("weak_bind_off field of " + Twine(CmdName
) +
664 " command " + Twine(LoadCommandIndex
) + " extends "
665 "past the end of the file");
666 BigSize
= DyldInfo
.weak_bind_off
;
667 BigSize
+= DyldInfo
.weak_bind_size
;
668 if (BigSize
> FileSize
)
669 return malformedError("weak_bind_off field plus weak_bind_size field of " +
670 Twine(CmdName
) + " command " +
671 Twine(LoadCommandIndex
) + " extends past the end of "
673 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.weak_bind_off
,
674 DyldInfo
.weak_bind_size
,
675 "dyld weak bind info"))
677 if (DyldInfo
.lazy_bind_off
> FileSize
)
678 return malformedError("lazy_bind_off field of " + Twine(CmdName
) +
679 " command " + Twine(LoadCommandIndex
) + " extends "
680 "past the end of the file");
681 BigSize
= DyldInfo
.lazy_bind_off
;
682 BigSize
+= DyldInfo
.lazy_bind_size
;
683 if (BigSize
> FileSize
)
684 return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
685 Twine(CmdName
) + " command " +
686 Twine(LoadCommandIndex
) + " extends past the end of "
688 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.lazy_bind_off
,
689 DyldInfo
.lazy_bind_size
,
690 "dyld lazy bind info"))
692 if (DyldInfo
.export_off
> FileSize
)
693 return malformedError("export_off field of " + Twine(CmdName
) +
694 " command " + Twine(LoadCommandIndex
) + " extends "
695 "past the end of the file");
696 BigSize
= DyldInfo
.export_off
;
697 BigSize
+= DyldInfo
.export_size
;
698 if (BigSize
> FileSize
)
699 return malformedError("export_off field plus export_size field of " +
700 Twine(CmdName
) + " command " +
701 Twine(LoadCommandIndex
) + " extends past the end of "
703 if (Error Err
= checkOverlappingElement(Elements
, DyldInfo
.export_off
,
704 DyldInfo
.export_size
,
708 return Error::success();
711 static Error
checkDylibCommand(const MachOObjectFile
&Obj
,
712 const MachOObjectFile::LoadCommandInfo
&Load
,
713 uint32_t LoadCommandIndex
, const char *CmdName
) {
714 if (Load
.C
.cmdsize
< sizeof(MachO::dylib_command
))
715 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
716 CmdName
+ " cmdsize too small");
717 MachO::dylib_command D
= getStruct
<MachO::dylib_command
>(Obj
, Load
.Ptr
);
718 if (D
.dylib
.name
< sizeof(MachO::dylib_command
))
719 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
720 CmdName
+ " name.offset field too small, not past "
721 "the end of the dylib_command struct");
722 if (D
.dylib
.name
>= D
.cmdsize
)
723 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
724 CmdName
+ " name.offset field extends past the end "
725 "of the load command");
726 // Make sure there is a null between the starting offset of the name and
727 // the end of the load command.
729 const char *P
= (const char *)Load
.Ptr
;
730 for (i
= D
.dylib
.name
; i
< D
.cmdsize
; i
++)
734 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
735 CmdName
+ " library name extends past the end of the "
737 return Error::success();
740 static Error
checkDylibIdCommand(const MachOObjectFile
&Obj
,
741 const MachOObjectFile::LoadCommandInfo
&Load
,
742 uint32_t LoadCommandIndex
,
743 const char **LoadCmd
) {
744 if (Error Err
= checkDylibCommand(Obj
, Load
, LoadCommandIndex
,
747 if (*LoadCmd
!= nullptr)
748 return malformedError("more than one LC_ID_DYLIB command");
749 if (Obj
.getHeader().filetype
!= MachO::MH_DYLIB
&&
750 Obj
.getHeader().filetype
!= MachO::MH_DYLIB_STUB
)
751 return malformedError("LC_ID_DYLIB load command in non-dynamic library "
754 return Error::success();
757 static Error
checkDyldCommand(const MachOObjectFile
&Obj
,
758 const MachOObjectFile::LoadCommandInfo
&Load
,
759 uint32_t LoadCommandIndex
, const char *CmdName
) {
760 if (Load
.C
.cmdsize
< sizeof(MachO::dylinker_command
))
761 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
762 CmdName
+ " cmdsize too small");
763 MachO::dylinker_command D
= getStruct
<MachO::dylinker_command
>(Obj
, Load
.Ptr
);
764 if (D
.name
< sizeof(MachO::dylinker_command
))
765 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
766 CmdName
+ " name.offset field too small, not past "
767 "the end of the dylinker_command struct");
768 if (D
.name
>= D
.cmdsize
)
769 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
770 CmdName
+ " name.offset field extends past the end "
771 "of the load command");
772 // Make sure there is a null between the starting offset of the name and
773 // the end of the load command.
775 const char *P
= (const char *)Load
.Ptr
;
776 for (i
= D
.name
; i
< D
.cmdsize
; i
++)
780 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
781 CmdName
+ " dyld name extends past the end of the "
783 return Error::success();
786 static Error
checkVersCommand(const MachOObjectFile
&Obj
,
787 const MachOObjectFile::LoadCommandInfo
&Load
,
788 uint32_t LoadCommandIndex
,
789 const char **LoadCmd
, const char *CmdName
) {
790 if (Load
.C
.cmdsize
!= sizeof(MachO::version_min_command
))
791 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
792 CmdName
+ " has incorrect cmdsize");
793 if (*LoadCmd
!= nullptr)
794 return malformedError("more than one LC_VERSION_MIN_MACOSX, "
795 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
796 "LC_VERSION_MIN_WATCHOS command");
798 return Error::success();
801 static Error
checkNoteCommand(const MachOObjectFile
&Obj
,
802 const MachOObjectFile::LoadCommandInfo
&Load
,
803 uint32_t LoadCommandIndex
,
804 std::list
<MachOElement
> &Elements
) {
805 if (Load
.C
.cmdsize
!= sizeof(MachO::note_command
))
806 return malformedError("load command " + Twine(LoadCommandIndex
) +
807 " LC_NOTE has incorrect cmdsize");
808 MachO::note_command Nt
= getStruct
<MachO::note_command
>(Obj
, Load
.Ptr
);
809 uint64_t FileSize
= Obj
.getData().size();
810 if (Nt
.offset
> FileSize
)
811 return malformedError("offset field of LC_NOTE command " +
812 Twine(LoadCommandIndex
) + " extends "
813 "past the end of the file");
814 uint64_t BigSize
= Nt
.offset
;
816 if (BigSize
> FileSize
)
817 return malformedError("size field plus offset field of LC_NOTE command " +
818 Twine(LoadCommandIndex
) + " extends past the end of "
820 if (Error Err
= checkOverlappingElement(Elements
, Nt
.offset
, Nt
.size
,
823 return Error::success();
827 parseBuildVersionCommand(const MachOObjectFile
&Obj
,
828 const MachOObjectFile::LoadCommandInfo
&Load
,
829 SmallVectorImpl
<const char*> &BuildTools
,
830 uint32_t LoadCommandIndex
) {
831 MachO::build_version_command BVC
=
832 getStruct
<MachO::build_version_command
>(Obj
, Load
.Ptr
);
833 if (Load
.C
.cmdsize
!=
834 sizeof(MachO::build_version_command
) +
835 BVC
.ntools
* sizeof(MachO::build_tool_version
))
836 return malformedError("load command " + Twine(LoadCommandIndex
) +
837 " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
839 auto Start
= Load
.Ptr
+ sizeof(MachO::build_version_command
);
840 BuildTools
.resize(BVC
.ntools
);
841 for (unsigned i
= 0; i
< BVC
.ntools
; ++i
)
842 BuildTools
[i
] = Start
+ i
* sizeof(MachO::build_tool_version
);
844 return Error::success();
847 static Error
checkRpathCommand(const MachOObjectFile
&Obj
,
848 const MachOObjectFile::LoadCommandInfo
&Load
,
849 uint32_t LoadCommandIndex
) {
850 if (Load
.C
.cmdsize
< sizeof(MachO::rpath_command
))
851 return malformedError("load command " + Twine(LoadCommandIndex
) +
852 " LC_RPATH cmdsize too small");
853 MachO::rpath_command R
= getStruct
<MachO::rpath_command
>(Obj
, Load
.Ptr
);
854 if (R
.path
< sizeof(MachO::rpath_command
))
855 return malformedError("load command " + Twine(LoadCommandIndex
) +
856 " LC_RPATH path.offset field too small, not past "
857 "the end of the rpath_command struct");
858 if (R
.path
>= R
.cmdsize
)
859 return malformedError("load command " + Twine(LoadCommandIndex
) +
860 " LC_RPATH path.offset field extends past the end "
861 "of the load command");
862 // Make sure there is a null between the starting offset of the path and
863 // the end of the load command.
865 const char *P
= (const char *)Load
.Ptr
;
866 for (i
= R
.path
; i
< R
.cmdsize
; i
++)
870 return malformedError("load command " + Twine(LoadCommandIndex
) +
871 " LC_RPATH library name extends past the end of the "
873 return Error::success();
876 static Error
checkEncryptCommand(const MachOObjectFile
&Obj
,
877 const MachOObjectFile::LoadCommandInfo
&Load
,
878 uint32_t LoadCommandIndex
,
879 uint64_t cryptoff
, uint64_t cryptsize
,
880 const char **LoadCmd
, const char *CmdName
) {
881 if (*LoadCmd
!= nullptr)
882 return malformedError("more than one LC_ENCRYPTION_INFO and or "
883 "LC_ENCRYPTION_INFO_64 command");
884 uint64_t FileSize
= Obj
.getData().size();
885 if (cryptoff
> FileSize
)
886 return malformedError("cryptoff field of " + Twine(CmdName
) +
887 " command " + Twine(LoadCommandIndex
) + " extends "
888 "past the end of the file");
889 uint64_t BigSize
= cryptoff
;
890 BigSize
+= cryptsize
;
891 if (BigSize
> FileSize
)
892 return malformedError("cryptoff field plus cryptsize field of " +
893 Twine(CmdName
) + " command " +
894 Twine(LoadCommandIndex
) + " extends past the end of "
897 return Error::success();
900 static Error
checkLinkerOptCommand(const MachOObjectFile
&Obj
,
901 const MachOObjectFile::LoadCommandInfo
&Load
,
902 uint32_t LoadCommandIndex
) {
903 if (Load
.C
.cmdsize
< sizeof(MachO::linker_option_command
))
904 return malformedError("load command " + Twine(LoadCommandIndex
) +
905 " LC_LINKER_OPTION cmdsize too small");
906 MachO::linker_option_command L
=
907 getStruct
<MachO::linker_option_command
>(Obj
, Load
.Ptr
);
908 // Make sure the count of strings is correct.
909 const char *string
= (const char *)Load
.Ptr
+
910 sizeof(struct MachO::linker_option_command
);
911 uint32_t left
= L
.cmdsize
- sizeof(struct MachO::linker_option_command
);
914 while (*string
== '\0' && left
> 0) {
920 uint32_t NullPos
= StringRef(string
, left
).find('\0');
921 uint32_t len
= std::min(NullPos
, left
) + 1;
927 return malformedError("load command " + Twine(LoadCommandIndex
) +
928 " LC_LINKER_OPTION string count " + Twine(L
.count
) +
929 " does not match number of strings");
930 return Error::success();
933 static Error
checkSubCommand(const MachOObjectFile
&Obj
,
934 const MachOObjectFile::LoadCommandInfo
&Load
,
935 uint32_t LoadCommandIndex
, const char *CmdName
,
936 size_t SizeOfCmd
, const char *CmdStructName
,
937 uint32_t PathOffset
, const char *PathFieldName
) {
938 if (PathOffset
< SizeOfCmd
)
939 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
940 CmdName
+ " " + PathFieldName
+ ".offset field too "
941 "small, not past the end of the " + CmdStructName
);
942 if (PathOffset
>= Load
.C
.cmdsize
)
943 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
944 CmdName
+ " " + PathFieldName
+ ".offset field "
945 "extends past the end of the load command");
946 // Make sure there is a null between the starting offset of the path and
947 // the end of the load command.
949 const char *P
= (const char *)Load
.Ptr
;
950 for (i
= PathOffset
; i
< Load
.C
.cmdsize
; i
++)
953 if (i
>= Load
.C
.cmdsize
)
954 return malformedError("load command " + Twine(LoadCommandIndex
) + " " +
955 CmdName
+ " " + PathFieldName
+ " name extends past "
956 "the end of the load command");
957 return Error::success();
960 static Error
checkThreadCommand(const MachOObjectFile
&Obj
,
961 const MachOObjectFile::LoadCommandInfo
&Load
,
962 uint32_t LoadCommandIndex
,
963 const char *CmdName
) {
964 if (Load
.C
.cmdsize
< sizeof(MachO::thread_command
))
965 return malformedError("load command " + Twine(LoadCommandIndex
) +
966 CmdName
+ " cmdsize too small");
967 MachO::thread_command T
=
968 getStruct
<MachO::thread_command
>(Obj
, Load
.Ptr
);
969 const char *state
= Load
.Ptr
+ sizeof(MachO::thread_command
);
970 const char *end
= Load
.Ptr
+ T
.cmdsize
;
971 uint32_t nflavor
= 0;
972 uint32_t cputype
= getCPUType(Obj
);
973 while (state
< end
) {
974 if(state
+ sizeof(uint32_t) > end
)
975 return malformedError("load command " + Twine(LoadCommandIndex
) +
976 "flavor in " + CmdName
+ " extends past end of "
979 memcpy(&flavor
, state
, sizeof(uint32_t));
980 if (Obj
.isLittleEndian() != sys::IsLittleEndianHost
)
981 sys::swapByteOrder(flavor
);
982 state
+= sizeof(uint32_t);
984 if(state
+ sizeof(uint32_t) > end
)
985 return malformedError("load command " + Twine(LoadCommandIndex
) +
986 " count in " + CmdName
+ " extends past end of "
989 memcpy(&count
, state
, sizeof(uint32_t));
990 if (Obj
.isLittleEndian() != sys::IsLittleEndianHost
)
991 sys::swapByteOrder(count
);
992 state
+= sizeof(uint32_t);
994 if (cputype
== MachO::CPU_TYPE_I386
) {
995 if (flavor
== MachO::x86_THREAD_STATE32
) {
996 if (count
!= MachO::x86_THREAD_STATE32_COUNT
)
997 return malformedError("load command " + Twine(LoadCommandIndex
) +
998 " count not x86_THREAD_STATE32_COUNT for "
999 "flavor number " + Twine(nflavor
) + " which is "
1000 "a x86_THREAD_STATE32 flavor in " + CmdName
+
1002 if (state
+ sizeof(MachO::x86_thread_state32_t
) > end
)
1003 return malformedError("load command " + Twine(LoadCommandIndex
) +
1004 " x86_THREAD_STATE32 extends past end of "
1005 "command in " + CmdName
+ " command");
1006 state
+= sizeof(MachO::x86_thread_state32_t
);
1008 return malformedError("load command " + Twine(LoadCommandIndex
) +
1009 " unknown flavor (" + Twine(flavor
) + ") for "
1010 "flavor number " + Twine(nflavor
) + " in " +
1011 CmdName
+ " command");
1013 } else if (cputype
== MachO::CPU_TYPE_X86_64
) {
1014 if (flavor
== MachO::x86_THREAD_STATE
) {
1015 if (count
!= MachO::x86_THREAD_STATE_COUNT
)
1016 return malformedError("load command " + Twine(LoadCommandIndex
) +
1017 " count not x86_THREAD_STATE_COUNT for "
1018 "flavor number " + Twine(nflavor
) + " which is "
1019 "a x86_THREAD_STATE flavor in " + CmdName
+
1021 if (state
+ sizeof(MachO::x86_thread_state_t
) > end
)
1022 return malformedError("load command " + Twine(LoadCommandIndex
) +
1023 " x86_THREAD_STATE extends past end of "
1024 "command in " + CmdName
+ " command");
1025 state
+= sizeof(MachO::x86_thread_state_t
);
1026 } else if (flavor
== MachO::x86_FLOAT_STATE
) {
1027 if (count
!= MachO::x86_FLOAT_STATE_COUNT
)
1028 return malformedError("load command " + Twine(LoadCommandIndex
) +
1029 " count not x86_FLOAT_STATE_COUNT for "
1030 "flavor number " + Twine(nflavor
) + " which is "
1031 "a x86_FLOAT_STATE flavor in " + CmdName
+
1033 if (state
+ sizeof(MachO::x86_float_state_t
) > end
)
1034 return malformedError("load command " + Twine(LoadCommandIndex
) +
1035 " x86_FLOAT_STATE extends past end of "
1036 "command in " + CmdName
+ " command");
1037 state
+= sizeof(MachO::x86_float_state_t
);
1038 } else if (flavor
== MachO::x86_EXCEPTION_STATE
) {
1039 if (count
!= MachO::x86_EXCEPTION_STATE_COUNT
)
1040 return malformedError("load command " + Twine(LoadCommandIndex
) +
1041 " count not x86_EXCEPTION_STATE_COUNT for "
1042 "flavor number " + Twine(nflavor
) + " which is "
1043 "a x86_EXCEPTION_STATE flavor in " + CmdName
+
1045 if (state
+ sizeof(MachO::x86_exception_state_t
) > end
)
1046 return malformedError("load command " + Twine(LoadCommandIndex
) +
1047 " x86_EXCEPTION_STATE extends past end of "
1048 "command in " + CmdName
+ " command");
1049 state
+= sizeof(MachO::x86_exception_state_t
);
1050 } else if (flavor
== MachO::x86_THREAD_STATE64
) {
1051 if (count
!= MachO::x86_THREAD_STATE64_COUNT
)
1052 return malformedError("load command " + Twine(LoadCommandIndex
) +
1053 " count not x86_THREAD_STATE64_COUNT for "
1054 "flavor number " + Twine(nflavor
) + " which is "
1055 "a x86_THREAD_STATE64 flavor in " + CmdName
+
1057 if (state
+ sizeof(MachO::x86_thread_state64_t
) > end
)
1058 return malformedError("load command " + Twine(LoadCommandIndex
) +
1059 " x86_THREAD_STATE64 extends past end of "
1060 "command in " + CmdName
+ " command");
1061 state
+= sizeof(MachO::x86_thread_state64_t
);
1062 } else if (flavor
== MachO::x86_EXCEPTION_STATE64
) {
1063 if (count
!= MachO::x86_EXCEPTION_STATE64_COUNT
)
1064 return malformedError("load command " + Twine(LoadCommandIndex
) +
1065 " count not x86_EXCEPTION_STATE64_COUNT for "
1066 "flavor number " + Twine(nflavor
) + " which is "
1067 "a x86_EXCEPTION_STATE64 flavor in " + CmdName
+
1069 if (state
+ sizeof(MachO::x86_exception_state64_t
) > end
)
1070 return malformedError("load command " + Twine(LoadCommandIndex
) +
1071 " x86_EXCEPTION_STATE64 extends past end of "
1072 "command in " + CmdName
+ " command");
1073 state
+= sizeof(MachO::x86_exception_state64_t
);
1075 return malformedError("load command " + Twine(LoadCommandIndex
) +
1076 " unknown flavor (" + Twine(flavor
) + ") for "
1077 "flavor number " + Twine(nflavor
) + " in " +
1078 CmdName
+ " command");
1080 } else if (cputype
== MachO::CPU_TYPE_ARM
) {
1081 if (flavor
== MachO::ARM_THREAD_STATE
) {
1082 if (count
!= MachO::ARM_THREAD_STATE_COUNT
)
1083 return malformedError("load command " + Twine(LoadCommandIndex
) +
1084 " count not ARM_THREAD_STATE_COUNT for "
1085 "flavor number " + Twine(nflavor
) + " which is "
1086 "a ARM_THREAD_STATE flavor in " + CmdName
+
1088 if (state
+ sizeof(MachO::arm_thread_state32_t
) > end
)
1089 return malformedError("load command " + Twine(LoadCommandIndex
) +
1090 " ARM_THREAD_STATE extends past end of "
1091 "command in " + CmdName
+ " command");
1092 state
+= sizeof(MachO::arm_thread_state32_t
);
1094 return malformedError("load command " + Twine(LoadCommandIndex
) +
1095 " unknown flavor (" + Twine(flavor
) + ") for "
1096 "flavor number " + Twine(nflavor
) + " in " +
1097 CmdName
+ " command");
1099 } else if (cputype
== MachO::CPU_TYPE_ARM64
) {
1100 if (flavor
== MachO::ARM_THREAD_STATE64
) {
1101 if (count
!= MachO::ARM_THREAD_STATE64_COUNT
)
1102 return malformedError("load command " + Twine(LoadCommandIndex
) +
1103 " count not ARM_THREAD_STATE64_COUNT for "
1104 "flavor number " + Twine(nflavor
) + " which is "
1105 "a ARM_THREAD_STATE64 flavor in " + CmdName
+
1107 if (state
+ sizeof(MachO::arm_thread_state64_t
) > end
)
1108 return malformedError("load command " + Twine(LoadCommandIndex
) +
1109 " ARM_THREAD_STATE64 extends past end of "
1110 "command in " + CmdName
+ " command");
1111 state
+= sizeof(MachO::arm_thread_state64_t
);
1113 return malformedError("load command " + Twine(LoadCommandIndex
) +
1114 " unknown flavor (" + Twine(flavor
) + ") for "
1115 "flavor number " + Twine(nflavor
) + " in " +
1116 CmdName
+ " command");
1118 } else if (cputype
== MachO::CPU_TYPE_POWERPC
) {
1119 if (flavor
== MachO::PPC_THREAD_STATE
) {
1120 if (count
!= MachO::PPC_THREAD_STATE_COUNT
)
1121 return malformedError("load command " + Twine(LoadCommandIndex
) +
1122 " count not PPC_THREAD_STATE_COUNT for "
1123 "flavor number " + Twine(nflavor
) + " which is "
1124 "a PPC_THREAD_STATE flavor in " + CmdName
+
1126 if (state
+ sizeof(MachO::ppc_thread_state32_t
) > end
)
1127 return malformedError("load command " + Twine(LoadCommandIndex
) +
1128 " PPC_THREAD_STATE extends past end of "
1129 "command in " + CmdName
+ " command");
1130 state
+= sizeof(MachO::ppc_thread_state32_t
);
1132 return malformedError("load command " + Twine(LoadCommandIndex
) +
1133 " unknown flavor (" + Twine(flavor
) + ") for "
1134 "flavor number " + Twine(nflavor
) + " in " +
1135 CmdName
+ " command");
1138 return malformedError("unknown cputype (" + Twine(cputype
) + ") load "
1139 "command " + Twine(LoadCommandIndex
) + " for " +
1140 CmdName
+ " command can't be checked");
1144 return Error::success();
1147 static Error
checkTwoLevelHintsCommand(const MachOObjectFile
&Obj
,
1148 const MachOObjectFile::LoadCommandInfo
1150 uint32_t LoadCommandIndex
,
1151 const char **LoadCmd
,
1152 std::list
<MachOElement
> &Elements
) {
1153 if (Load
.C
.cmdsize
!= sizeof(MachO::twolevel_hints_command
))
1154 return malformedError("load command " + Twine(LoadCommandIndex
) +
1155 " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1156 if (*LoadCmd
!= nullptr)
1157 return malformedError("more than one LC_TWOLEVEL_HINTS command");
1158 MachO::twolevel_hints_command Hints
=
1159 getStruct
<MachO::twolevel_hints_command
>(Obj
, Load
.Ptr
);
1160 uint64_t FileSize
= Obj
.getData().size();
1161 if (Hints
.offset
> FileSize
)
1162 return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1163 Twine(LoadCommandIndex
) + " extends past the end of "
1165 uint64_t BigSize
= Hints
.nhints
;
1166 BigSize
*= sizeof(MachO::twolevel_hint
);
1167 BigSize
+= Hints
.offset
;
1168 if (BigSize
> FileSize
)
1169 return malformedError("offset field plus nhints times sizeof(struct "
1170 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1171 Twine(LoadCommandIndex
) + " extends past the end of "
1173 if (Error Err
= checkOverlappingElement(Elements
, Hints
.offset
, Hints
.nhints
*
1174 sizeof(MachO::twolevel_hint
),
1177 *LoadCmd
= Load
.Ptr
;
1178 return Error::success();
1181 // Returns true if the libObject code does not support the load command and its
1182 // contents. The cmd value it is treated as an unknown load command but with
1183 // an error message that says the cmd value is obsolete.
1184 static bool isLoadCommandObsolete(uint32_t cmd
) {
1185 if (cmd
== MachO::LC_SYMSEG
||
1186 cmd
== MachO::LC_LOADFVMLIB
||
1187 cmd
== MachO::LC_IDFVMLIB
||
1188 cmd
== MachO::LC_IDENT
||
1189 cmd
== MachO::LC_FVMFILE
||
1190 cmd
== MachO::LC_PREPAGE
||
1191 cmd
== MachO::LC_PREBOUND_DYLIB
||
1192 cmd
== MachO::LC_TWOLEVEL_HINTS
||
1193 cmd
== MachO::LC_PREBIND_CKSUM
)
1198 Expected
<std::unique_ptr
<MachOObjectFile
>>
1199 MachOObjectFile::create(MemoryBufferRef Object
, bool IsLittleEndian
,
1200 bool Is64Bits
, uint32_t UniversalCputype
,
1201 uint32_t UniversalIndex
) {
1202 Error Err
= Error::success();
1203 std::unique_ptr
<MachOObjectFile
> Obj(
1204 new MachOObjectFile(std::move(Object
), IsLittleEndian
,
1205 Is64Bits
, Err
, UniversalCputype
,
1208 return std::move(Err
);
1209 return std::move(Obj
);
1212 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object
, bool IsLittleEndian
,
1213 bool Is64bits
, Error
&Err
,
1214 uint32_t UniversalCputype
,
1215 uint32_t UniversalIndex
)
1216 : ObjectFile(getMachOType(IsLittleEndian
, Is64bits
), Object
) {
1217 ErrorAsOutParameter
ErrAsOutParam(&Err
);
1218 uint64_t SizeOfHeaders
;
1221 parseHeader(*this, Header64
, Err
);
1222 SizeOfHeaders
= sizeof(MachO::mach_header_64
);
1223 cputype
= Header64
.cputype
;
1225 parseHeader(*this, Header
, Err
);
1226 SizeOfHeaders
= sizeof(MachO::mach_header
);
1227 cputype
= Header
.cputype
;
1231 SizeOfHeaders
+= getHeader().sizeofcmds
;
1232 if (getData().data() + SizeOfHeaders
> getData().end()) {
1233 Err
= malformedError("load commands extend past the end of the file");
1236 if (UniversalCputype
!= 0 && cputype
!= UniversalCputype
) {
1237 Err
= malformedError("universal header architecture: " +
1238 Twine(UniversalIndex
) + "'s cputype does not match "
1239 "object file's mach header");
1242 std::list
<MachOElement
> Elements
;
1243 Elements
.push_back({0, SizeOfHeaders
, "Mach-O headers"});
1245 uint32_t LoadCommandCount
= getHeader().ncmds
;
1246 LoadCommandInfo Load
;
1247 if (LoadCommandCount
!= 0) {
1248 if (auto LoadOrErr
= getFirstLoadCommandInfo(*this))
1251 Err
= LoadOrErr
.takeError();
1256 const char *DyldIdLoadCmd
= nullptr;
1257 const char *FuncStartsLoadCmd
= nullptr;
1258 const char *SplitInfoLoadCmd
= nullptr;
1259 const char *CodeSignDrsLoadCmd
= nullptr;
1260 const char *CodeSignLoadCmd
= nullptr;
1261 const char *VersLoadCmd
= nullptr;
1262 const char *SourceLoadCmd
= nullptr;
1263 const char *EntryPointLoadCmd
= nullptr;
1264 const char *EncryptLoadCmd
= nullptr;
1265 const char *RoutinesLoadCmd
= nullptr;
1266 const char *UnixThreadLoadCmd
= nullptr;
1267 const char *TwoLevelHintsLoadCmd
= nullptr;
1268 for (unsigned I
= 0; I
< LoadCommandCount
; ++I
) {
1270 if (Load
.C
.cmdsize
% 8 != 0) {
1271 // We have a hack here to allow 64-bit Mach-O core files to have
1272 // LC_THREAD commands that are only a multiple of 4 and not 8 to be
1273 // allowed since the macOS kernel produces them.
1274 if (getHeader().filetype
!= MachO::MH_CORE
||
1275 Load
.C
.cmd
!= MachO::LC_THREAD
|| Load
.C
.cmdsize
% 4) {
1276 Err
= malformedError("load command " + Twine(I
) + " cmdsize not a "
1282 if (Load
.C
.cmdsize
% 4 != 0) {
1283 Err
= malformedError("load command " + Twine(I
) + " cmdsize not a "
1288 LoadCommands
.push_back(Load
);
1289 if (Load
.C
.cmd
== MachO::LC_SYMTAB
) {
1290 if ((Err
= checkSymtabCommand(*this, Load
, I
, &SymtabLoadCmd
, Elements
)))
1292 } else if (Load
.C
.cmd
== MachO::LC_DYSYMTAB
) {
1293 if ((Err
= checkDysymtabCommand(*this, Load
, I
, &DysymtabLoadCmd
,
1296 } else if (Load
.C
.cmd
== MachO::LC_DATA_IN_CODE
) {
1297 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &DataInCodeLoadCmd
,
1298 "LC_DATA_IN_CODE", Elements
,
1299 "data in code info")))
1301 } else if (Load
.C
.cmd
== MachO::LC_LINKER_OPTIMIZATION_HINT
) {
1302 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &LinkOptHintsLoadCmd
,
1303 "LC_LINKER_OPTIMIZATION_HINT",
1304 Elements
, "linker optimization "
1307 } else if (Load
.C
.cmd
== MachO::LC_FUNCTION_STARTS
) {
1308 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &FuncStartsLoadCmd
,
1309 "LC_FUNCTION_STARTS", Elements
,
1310 "function starts data")))
1312 } else if (Load
.C
.cmd
== MachO::LC_SEGMENT_SPLIT_INFO
) {
1313 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &SplitInfoLoadCmd
,
1314 "LC_SEGMENT_SPLIT_INFO", Elements
,
1315 "split info data")))
1317 } else if (Load
.C
.cmd
== MachO::LC_DYLIB_CODE_SIGN_DRS
) {
1318 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &CodeSignDrsLoadCmd
,
1319 "LC_DYLIB_CODE_SIGN_DRS", Elements
,
1320 "code signing RDs data")))
1322 } else if (Load
.C
.cmd
== MachO::LC_CODE_SIGNATURE
) {
1323 if ((Err
= checkLinkeditDataCommand(*this, Load
, I
, &CodeSignLoadCmd
,
1324 "LC_CODE_SIGNATURE", Elements
,
1325 "code signature data")))
1327 } else if (Load
.C
.cmd
== MachO::LC_DYLD_INFO
) {
1328 if ((Err
= checkDyldInfoCommand(*this, Load
, I
, &DyldInfoLoadCmd
,
1329 "LC_DYLD_INFO", Elements
)))
1331 } else if (Load
.C
.cmd
== MachO::LC_DYLD_INFO_ONLY
) {
1332 if ((Err
= checkDyldInfoCommand(*this, Load
, I
, &DyldInfoLoadCmd
,
1333 "LC_DYLD_INFO_ONLY", Elements
)))
1335 } else if (Load
.C
.cmd
== MachO::LC_UUID
) {
1336 if (Load
.C
.cmdsize
!= sizeof(MachO::uuid_command
)) {
1337 Err
= malformedError("LC_UUID command " + Twine(I
) + " has incorrect "
1342 Err
= malformedError("more than one LC_UUID command");
1345 UuidLoadCmd
= Load
.Ptr
;
1346 } else if (Load
.C
.cmd
== MachO::LC_SEGMENT_64
) {
1347 if ((Err
= parseSegmentLoadCommand
<MachO::segment_command_64
,
1349 *this, Load
, Sections
, HasPageZeroSegment
, I
,
1350 "LC_SEGMENT_64", SizeOfHeaders
, Elements
)))
1352 } else if (Load
.C
.cmd
== MachO::LC_SEGMENT
) {
1353 if ((Err
= parseSegmentLoadCommand
<MachO::segment_command
,
1355 *this, Load
, Sections
, HasPageZeroSegment
, I
,
1356 "LC_SEGMENT", SizeOfHeaders
, Elements
)))
1358 } else if (Load
.C
.cmd
== MachO::LC_ID_DYLIB
) {
1359 if ((Err
= checkDylibIdCommand(*this, Load
, I
, &DyldIdLoadCmd
)))
1361 } else if (Load
.C
.cmd
== MachO::LC_LOAD_DYLIB
) {
1362 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_LOAD_DYLIB")))
1364 Libraries
.push_back(Load
.Ptr
);
1365 } else if (Load
.C
.cmd
== MachO::LC_LOAD_WEAK_DYLIB
) {
1366 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_LOAD_WEAK_DYLIB")))
1368 Libraries
.push_back(Load
.Ptr
);
1369 } else if (Load
.C
.cmd
== MachO::LC_LAZY_LOAD_DYLIB
) {
1370 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_LAZY_LOAD_DYLIB")))
1372 Libraries
.push_back(Load
.Ptr
);
1373 } else if (Load
.C
.cmd
== MachO::LC_REEXPORT_DYLIB
) {
1374 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_REEXPORT_DYLIB")))
1376 Libraries
.push_back(Load
.Ptr
);
1377 } else if (Load
.C
.cmd
== MachO::LC_LOAD_UPWARD_DYLIB
) {
1378 if ((Err
= checkDylibCommand(*this, Load
, I
, "LC_LOAD_UPWARD_DYLIB")))
1380 Libraries
.push_back(Load
.Ptr
);
1381 } else if (Load
.C
.cmd
== MachO::LC_ID_DYLINKER
) {
1382 if ((Err
= checkDyldCommand(*this, Load
, I
, "LC_ID_DYLINKER")))
1384 } else if (Load
.C
.cmd
== MachO::LC_LOAD_DYLINKER
) {
1385 if ((Err
= checkDyldCommand(*this, Load
, I
, "LC_LOAD_DYLINKER")))
1387 } else if (Load
.C
.cmd
== MachO::LC_DYLD_ENVIRONMENT
) {
1388 if ((Err
= checkDyldCommand(*this, Load
, I
, "LC_DYLD_ENVIRONMENT")))
1390 } else if (Load
.C
.cmd
== MachO::LC_VERSION_MIN_MACOSX
) {
1391 if ((Err
= checkVersCommand(*this, Load
, I
, &VersLoadCmd
,
1392 "LC_VERSION_MIN_MACOSX")))
1394 } else if (Load
.C
.cmd
== MachO::LC_VERSION_MIN_IPHONEOS
) {
1395 if ((Err
= checkVersCommand(*this, Load
, I
, &VersLoadCmd
,
1396 "LC_VERSION_MIN_IPHONEOS")))
1398 } else if (Load
.C
.cmd
== MachO::LC_VERSION_MIN_TVOS
) {
1399 if ((Err
= checkVersCommand(*this, Load
, I
, &VersLoadCmd
,
1400 "LC_VERSION_MIN_TVOS")))
1402 } else if (Load
.C
.cmd
== MachO::LC_VERSION_MIN_WATCHOS
) {
1403 if ((Err
= checkVersCommand(*this, Load
, I
, &VersLoadCmd
,
1404 "LC_VERSION_MIN_WATCHOS")))
1406 } else if (Load
.C
.cmd
== MachO::LC_NOTE
) {
1407 if ((Err
= checkNoteCommand(*this, Load
, I
, Elements
)))
1409 } else if (Load
.C
.cmd
== MachO::LC_BUILD_VERSION
) {
1410 if ((Err
= parseBuildVersionCommand(*this, Load
, BuildTools
, I
)))
1412 } else if (Load
.C
.cmd
== MachO::LC_RPATH
) {
1413 if ((Err
= checkRpathCommand(*this, Load
, I
)))
1415 } else if (Load
.C
.cmd
== MachO::LC_SOURCE_VERSION
) {
1416 if (Load
.C
.cmdsize
!= sizeof(MachO::source_version_command
)) {
1417 Err
= malformedError("LC_SOURCE_VERSION command " + Twine(I
) +
1418 " has incorrect cmdsize");
1421 if (SourceLoadCmd
) {
1422 Err
= malformedError("more than one LC_SOURCE_VERSION command");
1425 SourceLoadCmd
= Load
.Ptr
;
1426 } else if (Load
.C
.cmd
== MachO::LC_MAIN
) {
1427 if (Load
.C
.cmdsize
!= sizeof(MachO::entry_point_command
)) {
1428 Err
= malformedError("LC_MAIN command " + Twine(I
) +
1429 " has incorrect cmdsize");
1432 if (EntryPointLoadCmd
) {
1433 Err
= malformedError("more than one LC_MAIN command");
1436 EntryPointLoadCmd
= Load
.Ptr
;
1437 } else if (Load
.C
.cmd
== MachO::LC_ENCRYPTION_INFO
) {
1438 if (Load
.C
.cmdsize
!= sizeof(MachO::encryption_info_command
)) {
1439 Err
= malformedError("LC_ENCRYPTION_INFO command " + Twine(I
) +
1440 " has incorrect cmdsize");
1443 MachO::encryption_info_command E
=
1444 getStruct
<MachO::encryption_info_command
>(*this, Load
.Ptr
);
1445 if ((Err
= checkEncryptCommand(*this, Load
, I
, E
.cryptoff
, E
.cryptsize
,
1446 &EncryptLoadCmd
, "LC_ENCRYPTION_INFO")))
1448 } else if (Load
.C
.cmd
== MachO::LC_ENCRYPTION_INFO_64
) {
1449 if (Load
.C
.cmdsize
!= sizeof(MachO::encryption_info_command_64
)) {
1450 Err
= malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I
) +
1451 " has incorrect cmdsize");
1454 MachO::encryption_info_command_64 E
=
1455 getStruct
<MachO::encryption_info_command_64
>(*this, Load
.Ptr
);
1456 if ((Err
= checkEncryptCommand(*this, Load
, I
, E
.cryptoff
, E
.cryptsize
,
1457 &EncryptLoadCmd
, "LC_ENCRYPTION_INFO_64")))
1459 } else if (Load
.C
.cmd
== MachO::LC_LINKER_OPTION
) {
1460 if ((Err
= checkLinkerOptCommand(*this, Load
, I
)))
1462 } else if (Load
.C
.cmd
== MachO::LC_SUB_FRAMEWORK
) {
1463 if (Load
.C
.cmdsize
< sizeof(MachO::sub_framework_command
)) {
1464 Err
= malformedError("load command " + Twine(I
) +
1465 " LC_SUB_FRAMEWORK cmdsize too small");
1468 MachO::sub_framework_command S
=
1469 getStruct
<MachO::sub_framework_command
>(*this, Load
.Ptr
);
1470 if ((Err
= checkSubCommand(*this, Load
, I
, "LC_SUB_FRAMEWORK",
1471 sizeof(MachO::sub_framework_command
),
1472 "sub_framework_command", S
.umbrella
,
1475 } else if (Load
.C
.cmd
== MachO::LC_SUB_UMBRELLA
) {
1476 if (Load
.C
.cmdsize
< sizeof(MachO::sub_umbrella_command
)) {
1477 Err
= malformedError("load command " + Twine(I
) +
1478 " LC_SUB_UMBRELLA cmdsize too small");
1481 MachO::sub_umbrella_command S
=
1482 getStruct
<MachO::sub_umbrella_command
>(*this, Load
.Ptr
);
1483 if ((Err
= checkSubCommand(*this, Load
, I
, "LC_SUB_UMBRELLA",
1484 sizeof(MachO::sub_umbrella_command
),
1485 "sub_umbrella_command", S
.sub_umbrella
,
1488 } else if (Load
.C
.cmd
== MachO::LC_SUB_LIBRARY
) {
1489 if (Load
.C
.cmdsize
< sizeof(MachO::sub_library_command
)) {
1490 Err
= malformedError("load command " + Twine(I
) +
1491 " LC_SUB_LIBRARY cmdsize too small");
1494 MachO::sub_library_command S
=
1495 getStruct
<MachO::sub_library_command
>(*this, Load
.Ptr
);
1496 if ((Err
= checkSubCommand(*this, Load
, I
, "LC_SUB_LIBRARY",
1497 sizeof(MachO::sub_library_command
),
1498 "sub_library_command", S
.sub_library
,
1501 } else if (Load
.C
.cmd
== MachO::LC_SUB_CLIENT
) {
1502 if (Load
.C
.cmdsize
< sizeof(MachO::sub_client_command
)) {
1503 Err
= malformedError("load command " + Twine(I
) +
1504 " LC_SUB_CLIENT cmdsize too small");
1507 MachO::sub_client_command S
=
1508 getStruct
<MachO::sub_client_command
>(*this, Load
.Ptr
);
1509 if ((Err
= checkSubCommand(*this, Load
, I
, "LC_SUB_CLIENT",
1510 sizeof(MachO::sub_client_command
),
1511 "sub_client_command", S
.client
, "client")))
1513 } else if (Load
.C
.cmd
== MachO::LC_ROUTINES
) {
1514 if (Load
.C
.cmdsize
!= sizeof(MachO::routines_command
)) {
1515 Err
= malformedError("LC_ROUTINES command " + Twine(I
) +
1516 " has incorrect cmdsize");
1519 if (RoutinesLoadCmd
) {
1520 Err
= malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1524 RoutinesLoadCmd
= Load
.Ptr
;
1525 } else if (Load
.C
.cmd
== MachO::LC_ROUTINES_64
) {
1526 if (Load
.C
.cmdsize
!= sizeof(MachO::routines_command_64
)) {
1527 Err
= malformedError("LC_ROUTINES_64 command " + Twine(I
) +
1528 " has incorrect cmdsize");
1531 if (RoutinesLoadCmd
) {
1532 Err
= malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1536 RoutinesLoadCmd
= Load
.Ptr
;
1537 } else if (Load
.C
.cmd
== MachO::LC_UNIXTHREAD
) {
1538 if ((Err
= checkThreadCommand(*this, Load
, I
, "LC_UNIXTHREAD")))
1540 if (UnixThreadLoadCmd
) {
1541 Err
= malformedError("more than one LC_UNIXTHREAD command");
1544 UnixThreadLoadCmd
= Load
.Ptr
;
1545 } else if (Load
.C
.cmd
== MachO::LC_THREAD
) {
1546 if ((Err
= checkThreadCommand(*this, Load
, I
, "LC_THREAD")))
1548 // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
1549 } else if (Load
.C
.cmd
== MachO::LC_TWOLEVEL_HINTS
) {
1550 if ((Err
= checkTwoLevelHintsCommand(*this, Load
, I
,
1551 &TwoLevelHintsLoadCmd
, Elements
)))
1553 } else if (isLoadCommandObsolete(Load
.C
.cmd
)) {
1554 Err
= malformedError("load command " + Twine(I
) + " for cmd value of: " +
1555 Twine(Load
.C
.cmd
) + " is obsolete and not "
1559 // TODO: generate a error for unknown load commands by default. But still
1560 // need work out an approach to allow or not allow unknown values like this
1561 // as an option for some uses like lldb.
1562 if (I
< LoadCommandCount
- 1) {
1563 if (auto LoadOrErr
= getNextLoadCommandInfo(*this, I
, Load
))
1566 Err
= LoadOrErr
.takeError();
1571 if (!SymtabLoadCmd
) {
1572 if (DysymtabLoadCmd
) {
1573 Err
= malformedError("contains LC_DYSYMTAB load command without a "
1574 "LC_SYMTAB load command");
1577 } else if (DysymtabLoadCmd
) {
1578 MachO::symtab_command Symtab
=
1579 getStruct
<MachO::symtab_command
>(*this, SymtabLoadCmd
);
1580 MachO::dysymtab_command Dysymtab
=
1581 getStruct
<MachO::dysymtab_command
>(*this, DysymtabLoadCmd
);
1582 if (Dysymtab
.nlocalsym
!= 0 && Dysymtab
.ilocalsym
> Symtab
.nsyms
) {
1583 Err
= malformedError("ilocalsym in LC_DYSYMTAB load command "
1584 "extends past the end of the symbol table");
1587 uint64_t BigSize
= Dysymtab
.ilocalsym
;
1588 BigSize
+= Dysymtab
.nlocalsym
;
1589 if (Dysymtab
.nlocalsym
!= 0 && BigSize
> Symtab
.nsyms
) {
1590 Err
= malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
1591 "command extends past the end of the symbol table");
1594 if (Dysymtab
.nextdefsym
!= 0 && Dysymtab
.iextdefsym
> Symtab
.nsyms
) {
1595 Err
= malformedError("iextdefsym in LC_DYSYMTAB load command "
1596 "extends past the end of the symbol table");
1599 BigSize
= Dysymtab
.iextdefsym
;
1600 BigSize
+= Dysymtab
.nextdefsym
;
1601 if (Dysymtab
.nextdefsym
!= 0 && BigSize
> Symtab
.nsyms
) {
1602 Err
= malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
1603 "load command extends past the end of the symbol "
1607 if (Dysymtab
.nundefsym
!= 0 && Dysymtab
.iundefsym
> Symtab
.nsyms
) {
1608 Err
= malformedError("iundefsym in LC_DYSYMTAB load command "
1609 "extends past the end of the symbol table");
1612 BigSize
= Dysymtab
.iundefsym
;
1613 BigSize
+= Dysymtab
.nundefsym
;
1614 if (Dysymtab
.nundefsym
!= 0 && BigSize
> Symtab
.nsyms
) {
1615 Err
= malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
1616 " command extends past the end of the symbol table");
1620 if ((getHeader().filetype
== MachO::MH_DYLIB
||
1621 getHeader().filetype
== MachO::MH_DYLIB_STUB
) &&
1622 DyldIdLoadCmd
== nullptr) {
1623 Err
= malformedError("no LC_ID_DYLIB load command in dynamic library "
1627 assert(LoadCommands
.size() == LoadCommandCount
);
1629 Err
= Error::success();
1632 Error
MachOObjectFile::checkSymbolTable() const {
1635 MachO::mach_header_64 H_64
= MachOObjectFile::getHeader64();
1638 MachO::mach_header H
= MachOObjectFile::getHeader();
1645 uint64_t NValue
= 0;
1646 uint32_t SymbolIndex
= 0;
1647 MachO::symtab_command S
= getSymtabLoadCommand();
1648 for (const SymbolRef
&Symbol
: symbols()) {
1649 DataRefImpl SymDRI
= Symbol
.getRawDataRefImpl();
1651 MachO::nlist_64 STE_64
= getSymbol64TableEntry(SymDRI
);
1652 NType
= STE_64
.n_type
;
1653 NSect
= STE_64
.n_sect
;
1654 NDesc
= STE_64
.n_desc
;
1655 NStrx
= STE_64
.n_strx
;
1656 NValue
= STE_64
.n_value
;
1658 MachO::nlist STE
= getSymbolTableEntry(SymDRI
);
1664 NValue
= STE
.n_value
;
1666 if ((NType
& MachO::N_STAB
) == 0 &&
1667 (NType
& MachO::N_TYPE
) == MachO::N_SECT
) {
1668 if (NSect
== 0 || NSect
> Sections
.size())
1669 return malformedError("bad section index: " + Twine((int)NSect
) +
1670 " for symbol at index " + Twine(SymbolIndex
));
1672 if ((NType
& MachO::N_STAB
) == 0 &&
1673 (NType
& MachO::N_TYPE
) == MachO::N_INDR
) {
1674 if (NValue
>= S
.strsize
)
1675 return malformedError("bad n_value: " + Twine((int)NValue
) + " past "
1676 "the end of string table, for N_INDR symbol at "
1677 "index " + Twine(SymbolIndex
));
1679 if ((Flags
& MachO::MH_TWOLEVEL
) == MachO::MH_TWOLEVEL
&&
1680 (((NType
& MachO::N_TYPE
) == MachO::N_UNDF
&& NValue
== 0) ||
1681 (NType
& MachO::N_TYPE
) == MachO::N_PBUD
)) {
1682 uint32_t LibraryOrdinal
= MachO::GET_LIBRARY_ORDINAL(NDesc
);
1683 if (LibraryOrdinal
!= 0 &&
1684 LibraryOrdinal
!= MachO::EXECUTABLE_ORDINAL
&&
1685 LibraryOrdinal
!= MachO::DYNAMIC_LOOKUP_ORDINAL
&&
1686 LibraryOrdinal
- 1 >= Libraries
.size() ) {
1687 return malformedError("bad library ordinal: " + Twine(LibraryOrdinal
) +
1688 " for symbol at index " + Twine(SymbolIndex
));
1691 if (NStrx
>= S
.strsize
)
1692 return malformedError("bad string table index: " + Twine((int)NStrx
) +
1693 " past the end of string table, for symbol at "
1694 "index " + Twine(SymbolIndex
));
1697 return Error::success();
1700 void MachOObjectFile::moveSymbolNext(DataRefImpl
&Symb
) const {
1701 unsigned SymbolTableEntrySize
= is64Bit() ?
1702 sizeof(MachO::nlist_64
) :
1703 sizeof(MachO::nlist
);
1704 Symb
.p
+= SymbolTableEntrySize
;
1707 Expected
<StringRef
> MachOObjectFile::getSymbolName(DataRefImpl Symb
) const {
1708 StringRef StringTable
= getStringTableData();
1709 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, Symb
);
1710 if (Entry
.n_strx
== 0)
1711 // A n_strx value of 0 indicates that no name is associated with a
1712 // particular symbol table entry.
1714 const char *Start
= &StringTable
.data()[Entry
.n_strx
];
1715 if (Start
< getData().begin() || Start
>= getData().end()) {
1716 return malformedError("bad string index: " + Twine(Entry
.n_strx
) +
1717 " for symbol at index " + Twine(getSymbolIndex(Symb
)));
1719 return StringRef(Start
);
1722 unsigned MachOObjectFile::getSectionType(SectionRef Sec
) const {
1723 DataRefImpl DRI
= Sec
.getRawDataRefImpl();
1724 uint32_t Flags
= getSectionFlags(*this, DRI
);
1725 return Flags
& MachO::SECTION_TYPE
;
1728 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym
) const {
1730 MachO::nlist_64 Entry
= getSymbol64TableEntry(Sym
);
1731 return Entry
.n_value
;
1733 MachO::nlist Entry
= getSymbolTableEntry(Sym
);
1734 return Entry
.n_value
;
1737 // getIndirectName() returns the name of the alias'ed symbol who's string table
1738 // index is in the n_value field.
1739 std::error_code
MachOObjectFile::getIndirectName(DataRefImpl Symb
,
1740 StringRef
&Res
) const {
1741 StringRef StringTable
= getStringTableData();
1742 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, Symb
);
1743 if ((Entry
.n_type
& MachO::N_TYPE
) != MachO::N_INDR
)
1744 return object_error::parse_failed
;
1745 uint64_t NValue
= getNValue(Symb
);
1746 if (NValue
>= StringTable
.size())
1747 return object_error::parse_failed
;
1748 const char *Start
= &StringTable
.data()[NValue
];
1749 Res
= StringRef(Start
);
1750 return std::error_code();
1753 uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym
) const {
1754 return getNValue(Sym
);
1757 Expected
<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym
) const {
1758 return getSymbolValue(Sym
);
1761 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI
) const {
1762 uint32_t flags
= getSymbolFlags(DRI
);
1763 if (flags
& SymbolRef::SF_Common
) {
1764 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, DRI
);
1765 return 1 << MachO::GET_COMM_ALIGN(Entry
.n_desc
);
1770 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI
) const {
1771 return getNValue(DRI
);
1774 Expected
<SymbolRef::Type
>
1775 MachOObjectFile::getSymbolType(DataRefImpl Symb
) const {
1776 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, Symb
);
1777 uint8_t n_type
= Entry
.n_type
;
1779 // If this is a STAB debugging symbol, we can do nothing more.
1780 if (n_type
& MachO::N_STAB
)
1781 return SymbolRef::ST_Debug
;
1783 switch (n_type
& MachO::N_TYPE
) {
1784 case MachO::N_UNDF
:
1785 return SymbolRef::ST_Unknown
;
1786 case MachO::N_SECT
:
1787 Expected
<section_iterator
> SecOrError
= getSymbolSection(Symb
);
1789 return SecOrError
.takeError();
1790 section_iterator Sec
= *SecOrError
;
1791 if (Sec
->isData() || Sec
->isBSS())
1792 return SymbolRef::ST_Data
;
1793 return SymbolRef::ST_Function
;
1795 return SymbolRef::ST_Other
;
1798 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI
) const {
1799 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, DRI
);
1801 uint8_t MachOType
= Entry
.n_type
;
1802 uint16_t MachOFlags
= Entry
.n_desc
;
1804 uint32_t Result
= SymbolRef::SF_None
;
1806 if ((MachOType
& MachO::N_TYPE
) == MachO::N_INDR
)
1807 Result
|= SymbolRef::SF_Indirect
;
1809 if (MachOType
& MachO::N_STAB
)
1810 Result
|= SymbolRef::SF_FormatSpecific
;
1812 if (MachOType
& MachO::N_EXT
) {
1813 Result
|= SymbolRef::SF_Global
;
1814 if ((MachOType
& MachO::N_TYPE
) == MachO::N_UNDF
) {
1816 Result
|= SymbolRef::SF_Common
;
1818 Result
|= SymbolRef::SF_Undefined
;
1821 if (!(MachOType
& MachO::N_PEXT
))
1822 Result
|= SymbolRef::SF_Exported
;
1825 if (MachOFlags
& (MachO::N_WEAK_REF
| MachO::N_WEAK_DEF
))
1826 Result
|= SymbolRef::SF_Weak
;
1828 if (MachOFlags
& (MachO::N_ARM_THUMB_DEF
))
1829 Result
|= SymbolRef::SF_Thumb
;
1831 if ((MachOType
& MachO::N_TYPE
) == MachO::N_ABS
)
1832 Result
|= SymbolRef::SF_Absolute
;
1837 Expected
<section_iterator
>
1838 MachOObjectFile::getSymbolSection(DataRefImpl Symb
) const {
1839 MachO::nlist_base Entry
= getSymbolTableEntryBase(*this, Symb
);
1840 uint8_t index
= Entry
.n_sect
;
1843 return section_end();
1845 DRI
.d
.a
= index
- 1;
1846 if (DRI
.d
.a
>= Sections
.size()){
1847 return malformedError("bad section index: " + Twine((int)index
) +
1848 " for symbol at index " + Twine(getSymbolIndex(Symb
)));
1850 return section_iterator(SectionRef(DRI
, this));
1853 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym
) const {
1854 MachO::nlist_base Entry
=
1855 getSymbolTableEntryBase(*this, Sym
.getRawDataRefImpl());
1856 return Entry
.n_sect
- 1;
1859 void MachOObjectFile::moveSectionNext(DataRefImpl
&Sec
) const {
1863 std::error_code
MachOObjectFile::getSectionName(DataRefImpl Sec
,
1864 StringRef
&Result
) const {
1865 ArrayRef
<char> Raw
= getSectionRawName(Sec
);
1866 Result
= parseSegmentOrSectionName(Raw
.data());
1867 return std::error_code();
1870 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec
) const {
1872 return getSection64(Sec
).addr
;
1873 return getSection(Sec
).addr
;
1876 uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec
) const {
1880 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec
) const {
1881 // In the case if a malformed Mach-O file where the section offset is past
1882 // the end of the file or some part of the section size is past the end of
1883 // the file return a size of zero or a size that covers the rest of the file
1884 // but does not extend past the end of the file.
1885 uint32_t SectOffset
, SectType
;
1889 MachO::section_64 Sect
= getSection64(Sec
);
1890 SectOffset
= Sect
.offset
;
1891 SectSize
= Sect
.size
;
1892 SectType
= Sect
.flags
& MachO::SECTION_TYPE
;
1894 MachO::section Sect
= getSection(Sec
);
1895 SectOffset
= Sect
.offset
;
1896 SectSize
= Sect
.size
;
1897 SectType
= Sect
.flags
& MachO::SECTION_TYPE
;
1899 if (SectType
== MachO::S_ZEROFILL
|| SectType
== MachO::S_GB_ZEROFILL
)
1901 uint64_t FileSize
= getData().size();
1902 if (SectOffset
> FileSize
)
1904 if (FileSize
- SectOffset
< SectSize
)
1905 return FileSize
- SectOffset
;
1909 std::error_code
MachOObjectFile::getSectionContents(DataRefImpl Sec
,
1910 StringRef
&Res
) const {
1915 MachO::section_64 Sect
= getSection64(Sec
);
1916 Offset
= Sect
.offset
;
1919 MachO::section Sect
= getSection(Sec
);
1920 Offset
= Sect
.offset
;
1924 Res
= this->getData().substr(Offset
, Size
);
1925 return std::error_code();
1928 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec
) const {
1931 MachO::section_64 Sect
= getSection64(Sec
);
1934 MachO::section Sect
= getSection(Sec
);
1938 return uint64_t(1) << Align
;
1941 Expected
<SectionRef
> MachOObjectFile::getSection(unsigned SectionIndex
) const {
1942 if (SectionIndex
< 1 || SectionIndex
> Sections
.size())
1943 return malformedError("bad section index: " + Twine((int)SectionIndex
));
1946 DRI
.d
.a
= SectionIndex
- 1;
1947 return SectionRef(DRI
, this);
1950 Expected
<SectionRef
> MachOObjectFile::getSection(StringRef SectionName
) const {
1952 for (const SectionRef
&Section
: sections()) {
1953 if (std::error_code E
= Section
.getName(SecName
))
1954 return errorCodeToError(E
);
1955 if (SecName
== SectionName
) {
1959 return errorCodeToError(object_error::parse_failed
);
1962 bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec
) const {
1966 bool MachOObjectFile::isSectionText(DataRefImpl Sec
) const {
1967 uint32_t Flags
= getSectionFlags(*this, Sec
);
1968 return Flags
& MachO::S_ATTR_PURE_INSTRUCTIONS
;
1971 bool MachOObjectFile::isSectionData(DataRefImpl Sec
) const {
1972 uint32_t Flags
= getSectionFlags(*this, Sec
);
1973 unsigned SectionType
= Flags
& MachO::SECTION_TYPE
;
1974 return !(Flags
& MachO::S_ATTR_PURE_INSTRUCTIONS
) &&
1975 !(SectionType
== MachO::S_ZEROFILL
||
1976 SectionType
== MachO::S_GB_ZEROFILL
);
1979 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec
) const {
1980 uint32_t Flags
= getSectionFlags(*this, Sec
);
1981 unsigned SectionType
= Flags
& MachO::SECTION_TYPE
;
1982 return !(Flags
& MachO::S_ATTR_PURE_INSTRUCTIONS
) &&
1983 (SectionType
== MachO::S_ZEROFILL
||
1984 SectionType
== MachO::S_GB_ZEROFILL
);
1987 unsigned MachOObjectFile::getSectionID(SectionRef Sec
) const {
1988 return Sec
.getRawDataRefImpl().d
.a
;
1991 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec
) const {
1992 uint32_t Flags
= getSectionFlags(*this, Sec
);
1993 unsigned SectionType
= Flags
& MachO::SECTION_TYPE
;
1994 return SectionType
== MachO::S_ZEROFILL
||
1995 SectionType
== MachO::S_GB_ZEROFILL
;
1998 bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec
) const {
1999 StringRef SegmentName
= getSectionFinalSegmentName(Sec
);
2001 if (!getSectionName(Sec
, SectName
))
2002 return (SegmentName
== "__LLVM" && SectName
== "__bitcode");
2006 bool MachOObjectFile::isSectionStripped(DataRefImpl Sec
) const {
2008 return getSection64(Sec
).offset
== 0;
2009 return getSection(Sec
).offset
== 0;
2012 relocation_iterator
MachOObjectFile::section_rel_begin(DataRefImpl Sec
) const {
2016 return relocation_iterator(RelocationRef(Ret
, this));
2020 MachOObjectFile::section_rel_end(DataRefImpl Sec
) const {
2023 MachO::section_64 Sect
= getSection64(Sec
);
2026 MachO::section Sect
= getSection(Sec
);
2033 return relocation_iterator(RelocationRef(Ret
, this));
2036 relocation_iterator
MachOObjectFile::extrel_begin() const {
2038 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2039 Ret
.d
.a
= 0; // Would normally be a section index.
2040 Ret
.d
.b
= 0; // Index into the external relocations
2041 return relocation_iterator(RelocationRef(Ret
, this));
2044 relocation_iterator
MachOObjectFile::extrel_end() const {
2045 MachO::dysymtab_command DysymtabLoadCmd
= getDysymtabLoadCommand();
2047 // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2048 Ret
.d
.a
= 0; // Would normally be a section index.
2049 Ret
.d
.b
= DysymtabLoadCmd
.nextrel
; // Index into the external relocations
2050 return relocation_iterator(RelocationRef(Ret
, this));
2053 relocation_iterator
MachOObjectFile::locrel_begin() const {
2055 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2056 Ret
.d
.a
= 1; // Would normally be a section index.
2057 Ret
.d
.b
= 0; // Index into the local relocations
2058 return relocation_iterator(RelocationRef(Ret
, this));
2061 relocation_iterator
MachOObjectFile::locrel_end() const {
2062 MachO::dysymtab_command DysymtabLoadCmd
= getDysymtabLoadCommand();
2064 // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2065 Ret
.d
.a
= 1; // Would normally be a section index.
2066 Ret
.d
.b
= DysymtabLoadCmd
.nlocrel
; // Index into the local relocations
2067 return relocation_iterator(RelocationRef(Ret
, this));
2070 void MachOObjectFile::moveRelocationNext(DataRefImpl
&Rel
) const {
2074 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel
) const {
2075 assert((getHeader().filetype
== MachO::MH_OBJECT
||
2076 getHeader().filetype
== MachO::MH_KEXT_BUNDLE
) &&
2077 "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
2078 MachO::any_relocation_info RE
= getRelocation(Rel
);
2079 return getAnyRelocationAddress(RE
);
2083 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel
) const {
2084 MachO::any_relocation_info RE
= getRelocation(Rel
);
2085 if (isRelocationScattered(RE
))
2086 return symbol_end();
2088 uint32_t SymbolIdx
= getPlainRelocationSymbolNum(RE
);
2089 bool isExtern
= getPlainRelocationExternal(RE
);
2091 return symbol_end();
2093 MachO::symtab_command S
= getSymtabLoadCommand();
2094 unsigned SymbolTableEntrySize
= is64Bit() ?
2095 sizeof(MachO::nlist_64
) :
2096 sizeof(MachO::nlist
);
2097 uint64_t Offset
= S
.symoff
+ SymbolIdx
* SymbolTableEntrySize
;
2099 Sym
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Offset
));
2100 return symbol_iterator(SymbolRef(Sym
, this));
2104 MachOObjectFile::getRelocationSection(DataRefImpl Rel
) const {
2105 return section_iterator(getAnyRelocationSection(getRelocation(Rel
)));
2108 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel
) const {
2109 MachO::any_relocation_info RE
= getRelocation(Rel
);
2110 return getAnyRelocationType(RE
);
2113 void MachOObjectFile::getRelocationTypeName(
2114 DataRefImpl Rel
, SmallVectorImpl
<char> &Result
) const {
2116 uint64_t RType
= getRelocationType(Rel
);
2118 unsigned Arch
= this->getArch();
2122 static const char *const Table
[] = {
2123 "GENERIC_RELOC_VANILLA",
2124 "GENERIC_RELOC_PAIR",
2125 "GENERIC_RELOC_SECTDIFF",
2126 "GENERIC_RELOC_PB_LA_PTR",
2127 "GENERIC_RELOC_LOCAL_SECTDIFF",
2128 "GENERIC_RELOC_TLV" };
2136 case Triple::x86_64
: {
2137 static const char *const Table
[] = {
2138 "X86_64_RELOC_UNSIGNED",
2139 "X86_64_RELOC_SIGNED",
2140 "X86_64_RELOC_BRANCH",
2141 "X86_64_RELOC_GOT_LOAD",
2143 "X86_64_RELOC_SUBTRACTOR",
2144 "X86_64_RELOC_SIGNED_1",
2145 "X86_64_RELOC_SIGNED_2",
2146 "X86_64_RELOC_SIGNED_4",
2147 "X86_64_RELOC_TLV" };
2156 static const char *const Table
[] = {
2157 "ARM_RELOC_VANILLA",
2159 "ARM_RELOC_SECTDIFF",
2160 "ARM_RELOC_LOCAL_SECTDIFF",
2161 "ARM_RELOC_PB_LA_PTR",
2163 "ARM_THUMB_RELOC_BR22",
2164 "ARM_THUMB_32BIT_BRANCH",
2166 "ARM_RELOC_HALF_SECTDIFF" };
2174 case Triple::aarch64
: {
2175 static const char *const Table
[] = {
2176 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
2177 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
2178 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
2179 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
2180 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
2181 "ARM64_RELOC_ADDEND"
2184 if (RType
>= array_lengthof(Table
))
2191 static const char *const Table
[] = {
2192 "PPC_RELOC_VANILLA",
2200 "PPC_RELOC_SECTDIFF",
2201 "PPC_RELOC_PB_LA_PTR",
2202 "PPC_RELOC_HI16_SECTDIFF",
2203 "PPC_RELOC_LO16_SECTDIFF",
2204 "PPC_RELOC_HA16_SECTDIFF",
2206 "PPC_RELOC_LO14_SECTDIFF",
2207 "PPC_RELOC_LOCAL_SECTDIFF" };
2215 case Triple::UnknownArch
:
2219 Result
.append(res
.begin(), res
.end());
2222 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel
) const {
2223 MachO::any_relocation_info RE
= getRelocation(Rel
);
2224 return getAnyRelocationLength(RE
);
2228 // guessLibraryShortName() is passed a name of a dynamic library and returns a
2229 // guess on what the short name is. Then name is returned as a substring of the
2230 // StringRef Name passed in. The name of the dynamic library is recognized as
2231 // a framework if it has one of the two following forms:
2232 // Foo.framework/Versions/A/Foo
2233 // Foo.framework/Foo
2234 // Where A and Foo can be any string. And may contain a trailing suffix
2235 // starting with an underbar. If the Name is recognized as a framework then
2236 // isFramework is set to true else it is set to false. If the Name has a
2237 // suffix then Suffix is set to the substring in Name that contains the suffix
2238 // else it is set to a NULL StringRef.
2240 // The Name of the dynamic library is recognized as a library name if it has
2241 // one of the two following forms:
2245 // The library may have a suffix trailing the name Foo of the form:
2246 // libFoo_profile.A.dylib
2247 // libFoo_profile.dylib
2248 // These dyld image suffixes are separated from the short name by a '_'
2249 // character. Because the '_' character is commonly used to separate words in
2250 // filenames guessLibraryShortName() cannot reliably separate a dylib's short
2251 // name from an arbitrary image suffix; imagine if both the short name and the
2252 // suffix contains an '_' character! To better deal with this ambiguity,
2253 // guessLibraryShortName() will recognize only "_debug" and "_profile" as valid
2254 // Suffix values. Calling code needs to be tolerant of guessLibraryShortName()
2255 // guessing incorrectly.
2257 // The Name of the dynamic library is also recognized as a library name if it
2258 // has the following form:
2261 // If the Name of the dynamic library is none of the forms above then a NULL
2262 // StringRef is returned.
2263 StringRef
MachOObjectFile::guessLibraryShortName(StringRef Name
,
2265 StringRef
&Suffix
) {
2266 StringRef Foo
, F
, DotFramework
, V
, Dylib
, Lib
, Dot
, Qtx
;
2267 size_t a
, b
, c
, d
, Idx
;
2269 isFramework
= false;
2270 Suffix
= StringRef();
2272 // Pull off the last component and make Foo point to it
2273 a
= Name
.rfind('/');
2274 if (a
== Name
.npos
|| a
== 0)
2276 Foo
= Name
.slice(a
+1, Name
.npos
);
2278 // Look for a suffix starting with a '_'
2279 Idx
= Foo
.rfind('_');
2280 if (Idx
!= Foo
.npos
&& Foo
.size() >= 2) {
2281 Suffix
= Foo
.slice(Idx
, Foo
.npos
);
2282 if (Suffix
!= "_debug" && Suffix
!= "_profile")
2283 Suffix
= StringRef();
2285 Foo
= Foo
.slice(0, Idx
);
2288 // First look for the form Foo.framework/Foo
2289 b
= Name
.rfind('/', a
);
2294 F
= Name
.slice(Idx
, Idx
+ Foo
.size());
2295 DotFramework
= Name
.slice(Idx
+ Foo
.size(),
2296 Idx
+ Foo
.size() + sizeof(".framework/")-1);
2297 if (F
== Foo
&& DotFramework
== ".framework/") {
2302 // Next look for the form Foo.framework/Versions/A/Foo
2305 c
= Name
.rfind('/', b
);
2306 if (c
== Name
.npos
|| c
== 0)
2308 V
= Name
.slice(c
+1, Name
.npos
);
2309 if (!V
.startswith("Versions/"))
2311 d
= Name
.rfind('/', c
);
2316 F
= Name
.slice(Idx
, Idx
+ Foo
.size());
2317 DotFramework
= Name
.slice(Idx
+ Foo
.size(),
2318 Idx
+ Foo
.size() + sizeof(".framework/")-1);
2319 if (F
== Foo
&& DotFramework
== ".framework/") {
2325 // pull off the suffix after the "." and make a point to it
2326 a
= Name
.rfind('.');
2327 if (a
== Name
.npos
|| a
== 0)
2329 Dylib
= Name
.slice(a
, Name
.npos
);
2330 if (Dylib
!= ".dylib")
2333 // First pull off the version letter for the form Foo.A.dylib if any.
2335 Dot
= Name
.slice(a
-2, a
-1);
2340 b
= Name
.rfind('/', a
);
2345 // ignore any suffix after an underbar like Foo_profile.A.dylib
2346 Idx
= Name
.rfind('_');
2347 if (Idx
!= Name
.npos
&& Idx
!= b
) {
2348 Lib
= Name
.slice(b
, Idx
);
2349 Suffix
= Name
.slice(Idx
, a
);
2350 if (Suffix
!= "_debug" && Suffix
!= "_profile") {
2351 Suffix
= StringRef();
2352 Lib
= Name
.slice(b
, a
);
2356 Lib
= Name
.slice(b
, a
);
2357 // There are incorrect library names of the form:
2358 // libATS.A_profile.dylib so check for these.
2359 if (Lib
.size() >= 3) {
2360 Dot
= Lib
.slice(Lib
.size()-2, Lib
.size()-1);
2362 Lib
= Lib
.slice(0, Lib
.size()-2);
2367 Qtx
= Name
.slice(a
, Name
.npos
);
2370 b
= Name
.rfind('/', a
);
2372 Lib
= Name
.slice(0, a
);
2374 Lib
= Name
.slice(b
+1, a
);
2375 // There are library names of the form: QT.A.qtx so check for these.
2376 if (Lib
.size() >= 3) {
2377 Dot
= Lib
.slice(Lib
.size()-2, Lib
.size()-1);
2379 Lib
= Lib
.slice(0, Lib
.size()-2);
2384 // getLibraryShortNameByIndex() is used to get the short name of the library
2385 // for an undefined symbol in a linked Mach-O binary that was linked with the
2386 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
2387 // It is passed the index (0 - based) of the library as translated from
2388 // GET_LIBRARY_ORDINAL (1 - based).
2389 std::error_code
MachOObjectFile::getLibraryShortNameByIndex(unsigned Index
,
2390 StringRef
&Res
) const {
2391 if (Index
>= Libraries
.size())
2392 return object_error::parse_failed
;
2394 // If the cache of LibrariesShortNames is not built up do that first for
2395 // all the Libraries.
2396 if (LibrariesShortNames
.size() == 0) {
2397 for (unsigned i
= 0; i
< Libraries
.size(); i
++) {
2398 MachO::dylib_command D
=
2399 getStruct
<MachO::dylib_command
>(*this, Libraries
[i
]);
2400 if (D
.dylib
.name
>= D
.cmdsize
)
2401 return object_error::parse_failed
;
2402 const char *P
= (const char *)(Libraries
[i
]) + D
.dylib
.name
;
2403 StringRef Name
= StringRef(P
);
2404 if (D
.dylib
.name
+Name
.size() >= D
.cmdsize
)
2405 return object_error::parse_failed
;
2408 StringRef shortName
= guessLibraryShortName(Name
, isFramework
, Suffix
);
2409 if (shortName
.empty())
2410 LibrariesShortNames
.push_back(Name
);
2412 LibrariesShortNames
.push_back(shortName
);
2416 Res
= LibrariesShortNames
[Index
];
2417 return std::error_code();
2420 uint32_t MachOObjectFile::getLibraryCount() const {
2421 return Libraries
.size();
2425 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel
) const {
2427 Sec
.d
.a
= Rel
->getRawDataRefImpl().d
.a
;
2428 return section_iterator(SectionRef(Sec
, this));
2431 basic_symbol_iterator
MachOObjectFile::symbol_begin() const {
2433 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2434 if (!SymtabLoadCmd
|| Symtab
.nsyms
== 0)
2435 return basic_symbol_iterator(SymbolRef(DRI
, this));
2437 return getSymbolByIndex(0);
2440 basic_symbol_iterator
MachOObjectFile::symbol_end() const {
2442 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2443 if (!SymtabLoadCmd
|| Symtab
.nsyms
== 0)
2444 return basic_symbol_iterator(SymbolRef(DRI
, this));
2446 unsigned SymbolTableEntrySize
= is64Bit() ?
2447 sizeof(MachO::nlist_64
) :
2448 sizeof(MachO::nlist
);
2449 unsigned Offset
= Symtab
.symoff
+
2450 Symtab
.nsyms
* SymbolTableEntrySize
;
2451 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Offset
));
2452 return basic_symbol_iterator(SymbolRef(DRI
, this));
2455 symbol_iterator
MachOObjectFile::getSymbolByIndex(unsigned Index
) const {
2456 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2457 if (!SymtabLoadCmd
|| Index
>= Symtab
.nsyms
)
2458 report_fatal_error("Requested symbol index is out of range.");
2459 unsigned SymbolTableEntrySize
=
2460 is64Bit() ? sizeof(MachO::nlist_64
) : sizeof(MachO::nlist
);
2462 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Symtab
.symoff
));
2463 DRI
.p
+= Index
* SymbolTableEntrySize
;
2464 return basic_symbol_iterator(SymbolRef(DRI
, this));
2467 uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb
) const {
2468 MachO::symtab_command Symtab
= getSymtabLoadCommand();
2470 report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2471 unsigned SymbolTableEntrySize
=
2472 is64Bit() ? sizeof(MachO::nlist_64
) : sizeof(MachO::nlist
);
2473 DataRefImpl DRIstart
;
2474 DRIstart
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Symtab
.symoff
));
2475 uint64_t Index
= (Symb
.p
- DRIstart
.p
) / SymbolTableEntrySize
;
2479 section_iterator
MachOObjectFile::section_begin() const {
2481 return section_iterator(SectionRef(DRI
, this));
2484 section_iterator
MachOObjectFile::section_end() const {
2486 DRI
.d
.a
= Sections
.size();
2487 return section_iterator(SectionRef(DRI
, this));
2490 uint8_t MachOObjectFile::getBytesInAddress() const {
2491 return is64Bit() ? 8 : 4;
2494 StringRef
MachOObjectFile::getFileFormatName() const {
2495 unsigned CPUType
= getCPUType(*this);
2498 case MachO::CPU_TYPE_I386
:
2499 return "Mach-O 32-bit i386";
2500 case MachO::CPU_TYPE_ARM
:
2501 return "Mach-O arm";
2502 case MachO::CPU_TYPE_POWERPC
:
2503 return "Mach-O 32-bit ppc";
2505 return "Mach-O 32-bit unknown";
2510 case MachO::CPU_TYPE_X86_64
:
2511 return "Mach-O 64-bit x86-64";
2512 case MachO::CPU_TYPE_ARM64
:
2513 return "Mach-O arm64";
2514 case MachO::CPU_TYPE_POWERPC64
:
2515 return "Mach-O 64-bit ppc64";
2517 return "Mach-O 64-bit unknown";
2521 Triple::ArchType
MachOObjectFile::getArch(uint32_t CPUType
) {
2523 case MachO::CPU_TYPE_I386
:
2525 case MachO::CPU_TYPE_X86_64
:
2526 return Triple::x86_64
;
2527 case MachO::CPU_TYPE_ARM
:
2529 case MachO::CPU_TYPE_ARM64
:
2530 return Triple::aarch64
;
2531 case MachO::CPU_TYPE_POWERPC
:
2533 case MachO::CPU_TYPE_POWERPC64
:
2534 return Triple::ppc64
;
2536 return Triple::UnknownArch
;
2540 Triple
MachOObjectFile::getArchTriple(uint32_t CPUType
, uint32_t CPUSubType
,
2541 const char **McpuDefault
,
2542 const char **ArchFlag
) {
2544 *McpuDefault
= nullptr;
2546 *ArchFlag
= nullptr;
2549 case MachO::CPU_TYPE_I386
:
2550 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2551 case MachO::CPU_SUBTYPE_I386_ALL
:
2554 return Triple("i386-apple-darwin");
2558 case MachO::CPU_TYPE_X86_64
:
2559 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2560 case MachO::CPU_SUBTYPE_X86_64_ALL
:
2562 *ArchFlag
= "x86_64";
2563 return Triple("x86_64-apple-darwin");
2564 case MachO::CPU_SUBTYPE_X86_64_H
:
2566 *ArchFlag
= "x86_64h";
2567 return Triple("x86_64h-apple-darwin");
2571 case MachO::CPU_TYPE_ARM
:
2572 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2573 case MachO::CPU_SUBTYPE_ARM_V4T
:
2575 *ArchFlag
= "armv4t";
2576 return Triple("armv4t-apple-darwin");
2577 case MachO::CPU_SUBTYPE_ARM_V5TEJ
:
2579 *ArchFlag
= "armv5e";
2580 return Triple("armv5e-apple-darwin");
2581 case MachO::CPU_SUBTYPE_ARM_XSCALE
:
2583 *ArchFlag
= "xscale";
2584 return Triple("xscale-apple-darwin");
2585 case MachO::CPU_SUBTYPE_ARM_V6
:
2587 *ArchFlag
= "armv6";
2588 return Triple("armv6-apple-darwin");
2589 case MachO::CPU_SUBTYPE_ARM_V6M
:
2591 *McpuDefault
= "cortex-m0";
2593 *ArchFlag
= "armv6m";
2594 return Triple("armv6m-apple-darwin");
2595 case MachO::CPU_SUBTYPE_ARM_V7
:
2597 *ArchFlag
= "armv7";
2598 return Triple("armv7-apple-darwin");
2599 case MachO::CPU_SUBTYPE_ARM_V7EM
:
2601 *McpuDefault
= "cortex-m4";
2603 *ArchFlag
= "armv7em";
2604 return Triple("thumbv7em-apple-darwin");
2605 case MachO::CPU_SUBTYPE_ARM_V7K
:
2607 *McpuDefault
= "cortex-a7";
2609 *ArchFlag
= "armv7k";
2610 return Triple("armv7k-apple-darwin");
2611 case MachO::CPU_SUBTYPE_ARM_V7M
:
2613 *McpuDefault
= "cortex-m3";
2615 *ArchFlag
= "armv7m";
2616 return Triple("thumbv7m-apple-darwin");
2617 case MachO::CPU_SUBTYPE_ARM_V7S
:
2619 *McpuDefault
= "cortex-a7";
2621 *ArchFlag
= "armv7s";
2622 return Triple("armv7s-apple-darwin");
2626 case MachO::CPU_TYPE_ARM64
:
2627 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2628 case MachO::CPU_SUBTYPE_ARM64_ALL
:
2630 *McpuDefault
= "cyclone";
2632 *ArchFlag
= "arm64";
2633 return Triple("arm64-apple-darwin");
2637 case MachO::CPU_TYPE_POWERPC
:
2638 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2639 case MachO::CPU_SUBTYPE_POWERPC_ALL
:
2642 return Triple("ppc-apple-darwin");
2646 case MachO::CPU_TYPE_POWERPC64
:
2647 switch (CPUSubType
& ~MachO::CPU_SUBTYPE_MASK
) {
2648 case MachO::CPU_SUBTYPE_POWERPC_ALL
:
2650 *ArchFlag
= "ppc64";
2651 return Triple("ppc64-apple-darwin");
2660 Triple
MachOObjectFile::getHostArch() {
2661 return Triple(sys::getDefaultTargetTriple());
2664 bool MachOObjectFile::isValidArch(StringRef ArchFlag
) {
2665 return StringSwitch
<bool>(ArchFlag
)
2667 .Case("x86_64", true)
2668 .Case("x86_64h", true)
2669 .Case("armv4t", true)
2671 .Case("armv5e", true)
2672 .Case("armv6", true)
2673 .Case("armv6m", true)
2674 .Case("armv7", true)
2675 .Case("armv7em", true)
2676 .Case("armv7k", true)
2677 .Case("armv7m", true)
2678 .Case("armv7s", true)
2679 .Case("arm64", true)
2681 .Case("ppc64", true)
2685 Triple::ArchType
MachOObjectFile::getArch() const {
2686 return getArch(getCPUType(*this));
2689 Triple
MachOObjectFile::getArchTriple(const char **McpuDefault
) const {
2690 return getArchTriple(Header
.cputype
, Header
.cpusubtype
, McpuDefault
);
2693 relocation_iterator
MachOObjectFile::section_rel_begin(unsigned Index
) const {
2696 return section_rel_begin(DRI
);
2699 relocation_iterator
MachOObjectFile::section_rel_end(unsigned Index
) const {
2702 return section_rel_end(DRI
);
2705 dice_iterator
MachOObjectFile::begin_dices() const {
2707 if (!DataInCodeLoadCmd
)
2708 return dice_iterator(DiceRef(DRI
, this));
2710 MachO::linkedit_data_command DicLC
= getDataInCodeLoadCommand();
2711 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, DicLC
.dataoff
));
2712 return dice_iterator(DiceRef(DRI
, this));
2715 dice_iterator
MachOObjectFile::end_dices() const {
2717 if (!DataInCodeLoadCmd
)
2718 return dice_iterator(DiceRef(DRI
, this));
2720 MachO::linkedit_data_command DicLC
= getDataInCodeLoadCommand();
2721 unsigned Offset
= DicLC
.dataoff
+ DicLC
.datasize
;
2722 DRI
.p
= reinterpret_cast<uintptr_t>(getPtr(*this, Offset
));
2723 return dice_iterator(DiceRef(DRI
, this));
2726 ExportEntry::ExportEntry(Error
*E
, const MachOObjectFile
*O
,
2727 ArrayRef
<uint8_t> T
) : E(E
), O(O
), Trie(T
) {}
2729 void ExportEntry::moveToFirst() {
2730 ErrorAsOutParameter
ErrAsOutParam(E
);
2734 pushDownUntilBottom();
2737 void ExportEntry::moveToEnd() {
2742 bool ExportEntry::operator==(const ExportEntry
&Other
) const {
2743 // Common case, one at end, other iterating from begin.
2744 if (Done
|| Other
.Done
)
2745 return (Done
== Other
.Done
);
2746 // Not equal if different stack sizes.
2747 if (Stack
.size() != Other
.Stack
.size())
2749 // Not equal if different cumulative strings.
2750 if (!CumulativeString
.equals(Other
.CumulativeString
))
2752 // Equal if all nodes in both stacks match.
2753 for (unsigned i
=0; i
< Stack
.size(); ++i
) {
2754 if (Stack
[i
].Start
!= Other
.Stack
[i
].Start
)
2760 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr
, const char **error
) {
2762 uint64_t Result
= decodeULEB128(Ptr
, &Count
, Trie
.end(), error
);
2764 if (Ptr
> Trie
.end())
2769 StringRef
ExportEntry::name() const {
2770 return CumulativeString
;
2773 uint64_t ExportEntry::flags() const {
2774 return Stack
.back().Flags
;
2777 uint64_t ExportEntry::address() const {
2778 return Stack
.back().Address
;
2781 uint64_t ExportEntry::other() const {
2782 return Stack
.back().Other
;
2785 StringRef
ExportEntry::otherName() const {
2786 const char* ImportName
= Stack
.back().ImportName
;
2788 return StringRef(ImportName
);
2792 uint32_t ExportEntry::nodeOffset() const {
2793 return Stack
.back().Start
- Trie
.begin();
2796 ExportEntry::NodeState::NodeState(const uint8_t *Ptr
)
2797 : Start(Ptr
), Current(Ptr
) {}
2799 void ExportEntry::pushNode(uint64_t offset
) {
2800 ErrorAsOutParameter
ErrAsOutParam(E
);
2801 const uint8_t *Ptr
= Trie
.begin() + offset
;
2802 NodeState
State(Ptr
);
2804 uint64_t ExportInfoSize
= readULEB128(State
.Current
, &error
);
2806 *E
= malformedError("export info size " + Twine(error
) +
2807 " in export trie data at node: 0x" +
2808 Twine::utohexstr(offset
));
2812 State
.IsExportNode
= (ExportInfoSize
!= 0);
2813 const uint8_t* Children
= State
.Current
+ ExportInfoSize
;
2814 if (Children
> Trie
.end()) {
2815 *E
= malformedError(
2816 "export info size: 0x" + Twine::utohexstr(ExportInfoSize
) +
2817 " in export trie data at node: 0x" + Twine::utohexstr(offset
) +
2818 " too big and extends past end of trie data");
2822 if (State
.IsExportNode
) {
2823 const uint8_t *ExportStart
= State
.Current
;
2824 State
.Flags
= readULEB128(State
.Current
, &error
);
2826 *E
= malformedError("flags " + Twine(error
) +
2827 " in export trie data at node: 0x" +
2828 Twine::utohexstr(offset
));
2832 uint64_t Kind
= State
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK
;
2833 if (State
.Flags
!= 0 &&
2834 (Kind
!= MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR
&&
2835 Kind
!= MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE
&&
2836 Kind
!= MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL
)) {
2837 *E
= malformedError(
2838 "unsupported exported symbol kind: " + Twine((int)Kind
) +
2839 " in flags: 0x" + Twine::utohexstr(State
.Flags
) +
2840 " in export trie data at node: 0x" + Twine::utohexstr(offset
));
2844 if (State
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_REEXPORT
) {
2846 State
.Other
= readULEB128(State
.Current
, &error
); // dylib ordinal
2848 *E
= malformedError("dylib ordinal of re-export " + Twine(error
) +
2849 " in export trie data at node: 0x" +
2850 Twine::utohexstr(offset
));
2855 if (State
.Other
> O
->getLibraryCount()) {
2856 *E
= malformedError(
2857 "bad library ordinal: " + Twine((int)State
.Other
) + " (max " +
2858 Twine((int)O
->getLibraryCount()) +
2859 ") in export trie data at node: 0x" + Twine::utohexstr(offset
));
2864 State
.ImportName
= reinterpret_cast<const char*>(State
.Current
);
2865 if (*State
.ImportName
== '\0') {
2868 const uint8_t *End
= State
.Current
+ 1;
2869 if (End
>= Trie
.end()) {
2870 *E
= malformedError("import name of re-export in export trie data at "
2872 Twine::utohexstr(offset
) +
2873 " starts past end of trie data");
2877 while(*End
!= '\0' && End
< Trie
.end())
2880 *E
= malformedError("import name of re-export in export trie data at "
2882 Twine::utohexstr(offset
) +
2883 " extends past end of trie data");
2887 State
.Current
= End
+ 1;
2890 State
.Address
= readULEB128(State
.Current
, &error
);
2892 *E
= malformedError("address " + Twine(error
) +
2893 " in export trie data at node: 0x" +
2894 Twine::utohexstr(offset
));
2898 if (State
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
) {
2899 State
.Other
= readULEB128(State
.Current
, &error
);
2901 *E
= malformedError("resolver of stub and resolver " + Twine(error
) +
2902 " in export trie data at node: 0x" +
2903 Twine::utohexstr(offset
));
2909 if(ExportStart
+ ExportInfoSize
!= State
.Current
) {
2910 *E
= malformedError(
2911 "inconsistant export info size: 0x" +
2912 Twine::utohexstr(ExportInfoSize
) + " where actual size was: 0x" +
2913 Twine::utohexstr(State
.Current
- ExportStart
) +
2914 " in export trie data at node: 0x" + Twine::utohexstr(offset
));
2919 State
.ChildCount
= *Children
;
2920 if (State
.ChildCount
!= 0 && Children
+ 1 >= Trie
.end()) {
2921 *E
= malformedError("byte for count of childern in export trie data at "
2923 Twine::utohexstr(offset
) +
2924 " extends past end of trie data");
2928 State
.Current
= Children
+ 1;
2929 State
.NextChildIndex
= 0;
2930 State
.ParentStringLength
= CumulativeString
.size();
2931 Stack
.push_back(State
);
2934 void ExportEntry::pushDownUntilBottom() {
2935 ErrorAsOutParameter
ErrAsOutParam(E
);
2937 while (Stack
.back().NextChildIndex
< Stack
.back().ChildCount
) {
2938 NodeState
&Top
= Stack
.back();
2939 CumulativeString
.resize(Top
.ParentStringLength
);
2940 for (;*Top
.Current
!= 0 && Top
.Current
< Trie
.end(); Top
.Current
++) {
2941 char C
= *Top
.Current
;
2942 CumulativeString
.push_back(C
);
2944 if (Top
.Current
>= Trie
.end()) {
2945 *E
= malformedError("edge sub-string in export trie data at node: 0x" +
2946 Twine::utohexstr(Top
.Start
- Trie
.begin()) +
2947 " for child #" + Twine((int)Top
.NextChildIndex
) +
2948 " extends past end of trie data");
2953 uint64_t childNodeIndex
= readULEB128(Top
.Current
, &error
);
2955 *E
= malformedError("child node offset " + Twine(error
) +
2956 " in export trie data at node: 0x" +
2957 Twine::utohexstr(Top
.Start
- Trie
.begin()));
2961 for (const NodeState
&node
: nodes()) {
2962 if (node
.Start
== Trie
.begin() + childNodeIndex
){
2963 *E
= malformedError("loop in childern in export trie data at node: 0x" +
2964 Twine::utohexstr(Top
.Start
- Trie
.begin()) +
2965 " back to node: 0x" +
2966 Twine::utohexstr(childNodeIndex
));
2971 Top
.NextChildIndex
+= 1;
2972 pushNode(childNodeIndex
);
2976 if (!Stack
.back().IsExportNode
) {
2977 *E
= malformedError("node is not an export node in export trie data at "
2979 Twine::utohexstr(Stack
.back().Start
- Trie
.begin()));
2985 // We have a trie data structure and need a way to walk it that is compatible
2986 // with the C++ iterator model. The solution is a non-recursive depth first
2987 // traversal where the iterator contains a stack of parent nodes along with a
2988 // string that is the accumulation of all edge strings along the parent chain
2991 // There is one "export" node for each exported symbol. But because some
2992 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
2993 // node may have child nodes too.
2995 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
2996 // child until hitting a node with no children (which is an export node or
2997 // else the trie is malformed). On the way down, each node is pushed on the
2998 // stack ivar. If there is no more ways down, it pops up one and tries to go
2999 // down a sibling path until a childless node is reached.
3000 void ExportEntry::moveNext() {
3001 assert(!Stack
.empty() && "ExportEntry::moveNext() with empty node stack");
3002 if (!Stack
.back().IsExportNode
) {
3003 *E
= malformedError("node is not an export node in export trie data at "
3005 Twine::utohexstr(Stack
.back().Start
- Trie
.begin()));
3011 while (!Stack
.empty()) {
3012 NodeState
&Top
= Stack
.back();
3013 if (Top
.NextChildIndex
< Top
.ChildCount
) {
3014 pushDownUntilBottom();
3015 // Now at the next export node.
3018 if (Top
.IsExportNode
) {
3019 // This node has no children but is itself an export node.
3020 CumulativeString
.resize(Top
.ParentStringLength
);
3029 iterator_range
<export_iterator
>
3030 MachOObjectFile::exports(Error
&E
, ArrayRef
<uint8_t> Trie
,
3031 const MachOObjectFile
*O
) {
3032 ExportEntry
Start(&E
, O
, Trie
);
3036 Start
.moveToFirst();
3038 ExportEntry
Finish(&E
, O
, Trie
);
3041 return make_range(export_iterator(Start
), export_iterator(Finish
));
3044 iterator_range
<export_iterator
> MachOObjectFile::exports(Error
&Err
) const {
3045 return exports(Err
, getDyldInfoExportsTrie(), this);
3048 MachORebaseEntry::MachORebaseEntry(Error
*E
, const MachOObjectFile
*O
,
3049 ArrayRef
<uint8_t> Bytes
, bool is64Bit
)
3050 : E(E
), O(O
), Opcodes(Bytes
), Ptr(Bytes
.begin()),
3051 PointerSize(is64Bit
? 8 : 4) {}
3053 void MachORebaseEntry::moveToFirst() {
3054 Ptr
= Opcodes
.begin();
3058 void MachORebaseEntry::moveToEnd() {
3059 Ptr
= Opcodes
.end();
3060 RemainingLoopCount
= 0;
3064 void MachORebaseEntry::moveNext() {
3065 ErrorAsOutParameter
ErrAsOutParam(E
);
3066 // If in the middle of some loop, move to next rebasing in loop.
3067 SegmentOffset
+= AdvanceAmount
;
3068 if (RemainingLoopCount
) {
3069 --RemainingLoopCount
;
3072 // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
3073 // pointer size. Therefore it is possible to reach the end without ever having
3074 // seen REBASE_OPCODE_DONE.
3075 if (Ptr
== Opcodes
.end()) {
3081 // Parse next opcode and set up next loop.
3082 const uint8_t *OpcodeStart
= Ptr
;
3083 uint8_t Byte
= *Ptr
++;
3084 uint8_t ImmValue
= Byte
& MachO::REBASE_IMMEDIATE_MASK
;
3085 uint8_t Opcode
= Byte
& MachO::REBASE_OPCODE_MASK
;
3086 uint32_t Count
, Skip
;
3087 const char *error
= nullptr;
3089 case MachO::REBASE_OPCODE_DONE
:
3093 DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n");
3095 case MachO::REBASE_OPCODE_SET_TYPE_IMM
:
3096 RebaseType
= ImmValue
;
3097 if (RebaseType
> MachO::REBASE_TYPE_TEXT_PCREL32
) {
3098 *E
= malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
3099 Twine((int)RebaseType
) + " for opcode at: 0x" +
3100 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3106 dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
3107 << "RebaseType=" << (int) RebaseType
<< "\n");
3109 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
:
3110 SegmentIndex
= ImmValue
;
3111 SegmentOffset
= readULEB128(&error
);
3113 *E
= malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3114 Twine(error
) + " for opcode at: 0x" +
3115 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3119 error
= O
->RebaseEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
,
3122 *E
= malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3123 Twine(error
) + " for opcode at: 0x" +
3124 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3130 dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3131 << "SegmentIndex=" << SegmentIndex
<< ", "
3132 << format("SegmentOffset=0x%06X", SegmentOffset
)
3135 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB
:
3136 SegmentOffset
+= readULEB128(&error
);
3138 *E
= malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3139 " for opcode at: 0x" +
3140 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3144 error
= O
->RebaseEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
,
3147 *E
= malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3148 " for opcode at: 0x" +
3149 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3153 DEBUG_WITH_TYPE("mach-o-rebase",
3154 dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
3155 << format("SegmentOffset=0x%06X",
3156 SegmentOffset
) << "\n");
3158 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED
:
3159 error
= O
->RebaseEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
,
3162 *E
= malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
3163 Twine(error
) + " for opcode at: 0x" +
3164 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3168 SegmentOffset
+= ImmValue
* PointerSize
;
3169 error
= O
->RebaseEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
,
3173 malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED "
3174 " (after adding immediate times the pointer size) " +
3175 Twine(error
) + " for opcode at: 0x" +
3176 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3180 DEBUG_WITH_TYPE("mach-o-rebase",
3181 dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
3182 << format("SegmentOffset=0x%06X",
3183 SegmentOffset
) << "\n");
3185 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES
:
3186 error
= O
->RebaseEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
,
3189 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
3190 Twine(error
) + " for opcode at: 0x" +
3191 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3195 AdvanceAmount
= PointerSize
;
3199 RemainingLoopCount
= ImmValue
- 1;
3201 RemainingLoopCount
= 0;
3202 error
= O
->RebaseEntryCheckCountAndSkip(Count
, Skip
, PointerSize
,
3203 SegmentIndex
, SegmentOffset
);
3205 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
3206 Twine(error
) + " for opcode at: 0x" +
3207 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3213 dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
3214 << format("SegmentOffset=0x%06X", SegmentOffset
)
3215 << ", AdvanceAmount=" << AdvanceAmount
3216 << ", RemainingLoopCount=" << RemainingLoopCount
3219 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES
:
3220 error
= O
->RebaseEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
,
3223 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3224 Twine(error
) + " for opcode at: 0x" +
3225 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3229 AdvanceAmount
= PointerSize
;
3231 Count
= readULEB128(&error
);
3233 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3234 Twine(error
) + " for opcode at: 0x" +
3235 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3240 RemainingLoopCount
= Count
- 1;
3242 RemainingLoopCount
= 0;
3243 error
= O
->RebaseEntryCheckCountAndSkip(Count
, Skip
, PointerSize
,
3244 SegmentIndex
, SegmentOffset
);
3246 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3247 Twine(error
) + " for opcode at: 0x" +
3248 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3254 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
3255 << format("SegmentOffset=0x%06X", SegmentOffset
)
3256 << ", AdvanceAmount=" << AdvanceAmount
3257 << ", RemainingLoopCount=" << RemainingLoopCount
3260 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB
:
3261 error
= O
->RebaseEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
,
3264 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3265 Twine(error
) + " for opcode at: 0x" +
3266 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3270 Skip
= readULEB128(&error
);
3272 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3273 Twine(error
) + " for opcode at: 0x" +
3274 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3278 AdvanceAmount
= Skip
+ PointerSize
;
3280 RemainingLoopCount
= 0;
3281 error
= O
->RebaseEntryCheckCountAndSkip(Count
, Skip
, PointerSize
,
3282 SegmentIndex
, SegmentOffset
);
3284 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3285 Twine(error
) + " for opcode at: 0x" +
3286 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3292 dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
3293 << format("SegmentOffset=0x%06X", SegmentOffset
)
3294 << ", AdvanceAmount=" << AdvanceAmount
3295 << ", RemainingLoopCount=" << RemainingLoopCount
3298 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB
:
3299 error
= O
->RebaseEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
,
3302 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3304 Twine(error
) + " for opcode at: 0x" +
3305 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3309 Count
= readULEB128(&error
);
3311 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3313 Twine(error
) + " for opcode at: 0x" +
3314 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3319 RemainingLoopCount
= Count
- 1;
3321 RemainingLoopCount
= 0;
3322 Skip
= readULEB128(&error
);
3324 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3326 Twine(error
) + " for opcode at: 0x" +
3327 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3331 AdvanceAmount
= Skip
+ PointerSize
;
3333 error
= O
->RebaseEntryCheckCountAndSkip(Count
, Skip
, PointerSize
,
3334 SegmentIndex
, SegmentOffset
);
3336 *E
= malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3338 Twine(error
) + " for opcode at: 0x" +
3339 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3345 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
3346 << format("SegmentOffset=0x%06X", SegmentOffset
)
3347 << ", AdvanceAmount=" << AdvanceAmount
3348 << ", RemainingLoopCount=" << RemainingLoopCount
3352 *E
= malformedError("bad rebase info (bad opcode value 0x" +
3353 Twine::utohexstr(Opcode
) + " for opcode at: 0x" +
3354 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3361 uint64_t MachORebaseEntry::readULEB128(const char **error
) {
3363 uint64_t Result
= decodeULEB128(Ptr
, &Count
, Opcodes
.end(), error
);
3365 if (Ptr
> Opcodes
.end())
3366 Ptr
= Opcodes
.end();
3370 int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex
; }
3372 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset
; }
3374 StringRef
MachORebaseEntry::typeName() const {
3375 switch (RebaseType
) {
3376 case MachO::REBASE_TYPE_POINTER
:
3378 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32
:
3379 return "text abs32";
3380 case MachO::REBASE_TYPE_TEXT_PCREL32
:
3381 return "text rel32";
3386 // For use with the SegIndex of a checked Mach-O Rebase entry
3387 // to get the segment name.
3388 StringRef
MachORebaseEntry::segmentName() const {
3389 return O
->BindRebaseSegmentName(SegmentIndex
);
3392 // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3393 // to get the section name.
3394 StringRef
MachORebaseEntry::sectionName() const {
3395 return O
->BindRebaseSectionName(SegmentIndex
, SegmentOffset
);
3398 // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3399 // to get the address.
3400 uint64_t MachORebaseEntry::address() const {
3401 return O
->BindRebaseAddress(SegmentIndex
, SegmentOffset
);
3404 bool MachORebaseEntry::operator==(const MachORebaseEntry
&Other
) const {
3405 #ifdef EXPENSIVE_CHECKS
3406 assert(Opcodes
== Other
.Opcodes
&& "compare iterators of different files");
3408 assert(Opcodes
.data() == Other
.Opcodes
.data() && "compare iterators of different files");
3410 return (Ptr
== Other
.Ptr
) &&
3411 (RemainingLoopCount
== Other
.RemainingLoopCount
) &&
3412 (Done
== Other
.Done
);
3415 iterator_range
<rebase_iterator
>
3416 MachOObjectFile::rebaseTable(Error
&Err
, MachOObjectFile
*O
,
3417 ArrayRef
<uint8_t> Opcodes
, bool is64
) {
3418 if (O
->BindRebaseSectionTable
== nullptr)
3419 O
->BindRebaseSectionTable
= llvm::make_unique
<BindRebaseSegInfo
>(O
);
3420 MachORebaseEntry
Start(&Err
, O
, Opcodes
, is64
);
3421 Start
.moveToFirst();
3423 MachORebaseEntry
Finish(&Err
, O
, Opcodes
, is64
);
3426 return make_range(rebase_iterator(Start
), rebase_iterator(Finish
));
3429 iterator_range
<rebase_iterator
> MachOObjectFile::rebaseTable(Error
&Err
) {
3430 return rebaseTable(Err
, this, getDyldInfoRebaseOpcodes(), is64Bit());
3433 MachOBindEntry::MachOBindEntry(Error
*E
, const MachOObjectFile
*O
,
3434 ArrayRef
<uint8_t> Bytes
, bool is64Bit
, Kind BK
)
3435 : E(E
), O(O
), Opcodes(Bytes
), Ptr(Bytes
.begin()),
3436 PointerSize(is64Bit
? 8 : 4), TableKind(BK
) {}
3438 void MachOBindEntry::moveToFirst() {
3439 Ptr
= Opcodes
.begin();
3443 void MachOBindEntry::moveToEnd() {
3444 Ptr
= Opcodes
.end();
3445 RemainingLoopCount
= 0;
3449 void MachOBindEntry::moveNext() {
3450 ErrorAsOutParameter
ErrAsOutParam(E
);
3451 // If in the middle of some loop, move to next binding in loop.
3452 SegmentOffset
+= AdvanceAmount
;
3453 if (RemainingLoopCount
) {
3454 --RemainingLoopCount
;
3457 // BIND_OPCODE_DONE is only used for padding if we are not aligned to
3458 // pointer size. Therefore it is possible to reach the end without ever having
3459 // seen BIND_OPCODE_DONE.
3460 if (Ptr
== Opcodes
.end()) {
3466 // Parse next opcode and set up next loop.
3467 const uint8_t *OpcodeStart
= Ptr
;
3468 uint8_t Byte
= *Ptr
++;
3469 uint8_t ImmValue
= Byte
& MachO::BIND_IMMEDIATE_MASK
;
3470 uint8_t Opcode
= Byte
& MachO::BIND_OPCODE_MASK
;
3471 int8_t SignExtended
;
3472 const uint8_t *SymStart
;
3473 uint32_t Count
, Skip
;
3474 const char *error
= nullptr;
3476 case MachO::BIND_OPCODE_DONE
:
3477 if (TableKind
== Kind::Lazy
) {
3478 // Lazying bindings have a DONE opcode between entries. Need to ignore
3479 // it to advance to next entry. But need not if this is last entry.
3480 bool NotLastEntry
= false;
3481 for (const uint8_t *P
= Ptr
; P
< Opcodes
.end(); ++P
) {
3483 NotLastEntry
= true;
3491 DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");
3493 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
:
3494 if (TableKind
== Kind::Weak
) {
3495 *E
= malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
3496 "weak bind table for opcode at: 0x" +
3497 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3502 LibraryOrdinalSet
= true;
3503 if (ImmValue
> O
->getLibraryCount()) {
3504 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3505 "library ordinal: " +
3506 Twine((int)ImmValue
) + " (max " +
3507 Twine((int)O
->getLibraryCount()) +
3508 ") for opcode at: 0x" +
3509 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3515 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
3516 << "Ordinal=" << Ordinal
<< "\n");
3518 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB
:
3519 if (TableKind
== Kind::Weak
) {
3520 *E
= malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
3521 "weak bind table for opcode at: 0x" +
3522 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3526 Ordinal
= readULEB128(&error
);
3527 LibraryOrdinalSet
= true;
3529 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
3530 Twine(error
) + " for opcode at: 0x" +
3531 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3535 if (Ordinal
> (int)O
->getLibraryCount()) {
3536 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3537 "library ordinal: " +
3538 Twine((int)Ordinal
) + " (max " +
3539 Twine((int)O
->getLibraryCount()) +
3540 ") for opcode at: 0x" +
3541 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3547 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
3548 << "Ordinal=" << Ordinal
<< "\n");
3550 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM
:
3551 if (TableKind
== Kind::Weak
) {
3552 *E
= malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
3553 "weak bind table for opcode at: 0x" +
3554 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3559 SignExtended
= MachO::BIND_OPCODE_MASK
| ImmValue
;
3560 Ordinal
= SignExtended
;
3561 if (Ordinal
< MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP
) {
3562 *E
= malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
3563 "special ordinal: " +
3564 Twine((int)Ordinal
) + " for opcode at: 0x" +
3565 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3571 LibraryOrdinalSet
= true;
3574 dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
3575 << "Ordinal=" << Ordinal
<< "\n");
3577 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
:
3580 while (*Ptr
&& (Ptr
< Opcodes
.end())) {
3583 if (Ptr
== Opcodes
.end()) {
3584 *E
= malformedError(
3585 "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
3586 "symbol name extends past opcodes for opcode at: 0x" +
3587 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3591 SymbolName
= StringRef(reinterpret_cast<const char*>(SymStart
),
3596 dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
3597 << "SymbolName=" << SymbolName
<< "\n");
3598 if (TableKind
== Kind::Weak
) {
3599 if (ImmValue
& MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION
)
3603 case MachO::BIND_OPCODE_SET_TYPE_IMM
:
3604 BindType
= ImmValue
;
3605 if (ImmValue
> MachO::BIND_TYPE_TEXT_PCREL32
) {
3606 *E
= malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
3607 Twine((int)ImmValue
) + " for opcode at: 0x" +
3608 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3614 dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
3615 << "BindType=" << (int)BindType
<< "\n");
3617 case MachO::BIND_OPCODE_SET_ADDEND_SLEB
:
3618 Addend
= readSLEB128(&error
);
3620 *E
= malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error
) +
3621 " for opcode at: 0x" +
3622 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3628 dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
3629 << "Addend=" << Addend
<< "\n");
3631 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
:
3632 SegmentIndex
= ImmValue
;
3633 SegmentOffset
= readULEB128(&error
);
3635 *E
= malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3636 Twine(error
) + " for opcode at: 0x" +
3637 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3641 error
= O
->BindEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
, true);
3643 *E
= malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3644 Twine(error
) + " for opcode at: 0x" +
3645 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3651 dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3652 << "SegmentIndex=" << SegmentIndex
<< ", "
3653 << format("SegmentOffset=0x%06X", SegmentOffset
)
3656 case MachO::BIND_OPCODE_ADD_ADDR_ULEB
:
3657 SegmentOffset
+= readULEB128(&error
);
3659 *E
= malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3660 " for opcode at: 0x" +
3661 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3665 error
= O
->BindEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
, true);
3667 *E
= malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error
) +
3668 " for opcode at: 0x" +
3669 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3673 DEBUG_WITH_TYPE("mach-o-bind",
3674 dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
3675 << format("SegmentOffset=0x%06X",
3676 SegmentOffset
) << "\n");
3678 case MachO::BIND_OPCODE_DO_BIND
:
3679 AdvanceAmount
= PointerSize
;
3680 RemainingLoopCount
= 0;
3681 error
= O
->BindEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
, true);
3683 *E
= malformedError("for BIND_OPCODE_DO_BIND " + Twine(error
) +
3684 " for opcode at: 0x" +
3685 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3689 if (SymbolName
== StringRef()) {
3690 *E
= malformedError(
3691 "for BIND_OPCODE_DO_BIND missing preceding "
3692 "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
3693 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3697 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
3699 malformedError("for BIND_OPCODE_DO_BIND missing preceding "
3700 "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3701 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3705 DEBUG_WITH_TYPE("mach-o-bind",
3706 dbgs() << "BIND_OPCODE_DO_BIND: "
3707 << format("SegmentOffset=0x%06X",
3708 SegmentOffset
) << "\n");
3710 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB
:
3711 if (TableKind
== Kind::Lazy
) {
3712 *E
= malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
3713 "lazy bind table for opcode at: 0x" +
3714 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3718 error
= O
->BindEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
, true);
3720 *E
= malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3721 Twine(error
) + " for opcode at: 0x" +
3722 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3726 if (SymbolName
== StringRef()) {
3727 *E
= malformedError(
3728 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3729 "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
3731 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3735 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
3736 *E
= malformedError(
3737 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3738 "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3739 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3743 AdvanceAmount
= readULEB128(&error
) + PointerSize
;
3745 *E
= malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3746 Twine(error
) + " for opcode at: 0x" +
3747 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3751 // Note, this is not really an error until the next bind but make no sense
3752 // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
3754 error
= O
->BindEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
+
3755 AdvanceAmount
, false);
3757 *E
= malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
3759 Twine(error
) + " for opcode at: 0x" +
3760 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3764 RemainingLoopCount
= 0;
3767 dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
3768 << format("SegmentOffset=0x%06X", SegmentOffset
)
3769 << ", AdvanceAmount=" << AdvanceAmount
3770 << ", RemainingLoopCount=" << RemainingLoopCount
3773 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED
:
3774 if (TableKind
== Kind::Lazy
) {
3775 *E
= malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
3776 "allowed in lazy bind table for opcode at: 0x" +
3777 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3781 error
= O
->BindEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
, true);
3783 *E
= malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
3784 Twine(error
) + " for opcode at: 0x" +
3785 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3789 if (SymbolName
== StringRef()) {
3790 *E
= malformedError(
3791 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3792 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3794 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3798 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
3799 *E
= malformedError(
3800 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3801 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3803 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3807 AdvanceAmount
= ImmValue
* PointerSize
+ PointerSize
;
3808 RemainingLoopCount
= 0;
3809 error
= O
->BindEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
+
3810 AdvanceAmount
, false);
3813 malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3814 " (after adding immediate times the pointer size) " +
3815 Twine(error
) + " for opcode at: 0x" +
3816 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3820 DEBUG_WITH_TYPE("mach-o-bind",
3822 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
3823 << format("SegmentOffset=0x%06X", SegmentOffset
) << "\n");
3825 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB
:
3826 if (TableKind
== Kind::Lazy
) {
3827 *E
= malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
3828 "allowed in lazy bind table for opcode at: 0x" +
3829 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3833 Count
= readULEB128(&error
);
3835 RemainingLoopCount
= Count
- 1;
3837 RemainingLoopCount
= 0;
3839 *E
= malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3841 Twine(error
) + " for opcode at: 0x" +
3842 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3846 Skip
= readULEB128(&error
);
3847 AdvanceAmount
= Skip
+ PointerSize
;
3849 *E
= malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3851 Twine(error
) + " for opcode at: 0x" +
3852 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3856 error
= O
->BindEntryCheckSegAndOffset(SegmentIndex
, SegmentOffset
, true);
3859 malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
3860 Twine(error
) + " for opcode at: 0x" +
3861 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3865 if (SymbolName
== StringRef()) {
3866 *E
= malformedError(
3867 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3868 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3870 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3874 if (!LibraryOrdinalSet
&& TableKind
!= Kind::Weak
) {
3875 *E
= malformedError(
3876 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3877 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3879 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3883 error
= O
->BindEntryCheckCountAndSkip(Count
, Skip
, PointerSize
,
3884 SegmentIndex
, SegmentOffset
);
3887 malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
3888 Twine(error
) + " for opcode at: 0x" +
3889 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3895 dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
3896 << format("SegmentOffset=0x%06X", SegmentOffset
)
3897 << ", AdvanceAmount=" << AdvanceAmount
3898 << ", RemainingLoopCount=" << RemainingLoopCount
3902 *E
= malformedError("bad bind info (bad opcode value 0x" +
3903 Twine::utohexstr(Opcode
) + " for opcode at: 0x" +
3904 Twine::utohexstr(OpcodeStart
- Opcodes
.begin()));
3911 uint64_t MachOBindEntry::readULEB128(const char **error
) {
3913 uint64_t Result
= decodeULEB128(Ptr
, &Count
, Opcodes
.end(), error
);
3915 if (Ptr
> Opcodes
.end())
3916 Ptr
= Opcodes
.end();
3920 int64_t MachOBindEntry::readSLEB128(const char **error
) {
3922 int64_t Result
= decodeSLEB128(Ptr
, &Count
, Opcodes
.end(), error
);
3924 if (Ptr
> Opcodes
.end())
3925 Ptr
= Opcodes
.end();
3929 int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex
; }
3931 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset
; }
3933 StringRef
MachOBindEntry::typeName() const {
3935 case MachO::BIND_TYPE_POINTER
:
3937 case MachO::BIND_TYPE_TEXT_ABSOLUTE32
:
3938 return "text abs32";
3939 case MachO::BIND_TYPE_TEXT_PCREL32
:
3940 return "text rel32";
3945 StringRef
MachOBindEntry::symbolName() const { return SymbolName
; }
3947 int64_t MachOBindEntry::addend() const { return Addend
; }
3949 uint32_t MachOBindEntry::flags() const { return Flags
; }
3951 int MachOBindEntry::ordinal() const { return Ordinal
; }
3953 // For use with the SegIndex of a checked Mach-O Bind entry
3954 // to get the segment name.
3955 StringRef
MachOBindEntry::segmentName() const {
3956 return O
->BindRebaseSegmentName(SegmentIndex
);
3959 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3960 // to get the section name.
3961 StringRef
MachOBindEntry::sectionName() const {
3962 return O
->BindRebaseSectionName(SegmentIndex
, SegmentOffset
);
3965 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3966 // to get the address.
3967 uint64_t MachOBindEntry::address() const {
3968 return O
->BindRebaseAddress(SegmentIndex
, SegmentOffset
);
3971 bool MachOBindEntry::operator==(const MachOBindEntry
&Other
) const {
3972 #ifdef EXPENSIVE_CHECKS
3973 assert(Opcodes
== Other
.Opcodes
&& "compare iterators of different files");
3975 assert(Opcodes
.data() == Other
.Opcodes
.data() && "compare iterators of different files");
3977 return (Ptr
== Other
.Ptr
) &&
3978 (RemainingLoopCount
== Other
.RemainingLoopCount
) &&
3979 (Done
== Other
.Done
);
3982 // Build table of sections so SegIndex/SegOffset pairs can be translated.
3983 BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile
*Obj
) {
3984 uint32_t CurSegIndex
= Obj
->hasPageZeroSegment() ? 1 : 0;
3985 StringRef CurSegName
;
3986 uint64_t CurSegAddress
;
3987 for (const SectionRef
&Section
: Obj
->sections()) {
3989 Section
.getName(Info
.SectionName
);
3990 Info
.Address
= Section
.getAddress();
3991 Info
.Size
= Section
.getSize();
3993 Obj
->getSectionFinalSegmentName(Section
.getRawDataRefImpl());
3994 if (!Info
.SegmentName
.equals(CurSegName
)) {
3996 CurSegName
= Info
.SegmentName
;
3997 CurSegAddress
= Info
.Address
;
3999 Info
.SegmentIndex
= CurSegIndex
- 1;
4000 Info
.OffsetInSegment
= Info
.Address
- CurSegAddress
;
4001 Info
.SegmentStartAddress
= CurSegAddress
;
4002 Sections
.push_back(Info
);
4004 MaxSegIndex
= CurSegIndex
;
4007 // For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to
4008 // validate a MachOBindEntry or MachORebaseEntry.
4009 const char * BindRebaseSegInfo::checkSegAndOffset(int32_t SegIndex
,
4013 return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
4014 if (SegIndex
>= MaxSegIndex
)
4015 return "bad segIndex (too large)";
4016 for (const SectionInfo
&SI
: Sections
) {
4017 if (SI
.SegmentIndex
!= SegIndex
)
4019 if (SI
.OffsetInSegment
> SegOffset
)
4021 if (SegOffset
> (SI
.OffsetInSegment
+ SI
.Size
))
4023 if (endInvalid
&& SegOffset
>= (SI
.OffsetInSegment
+ SI
.Size
))
4027 return "bad segOffset, too large";
4030 // For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for
4031 // the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode and for use in
4032 // MachORebaseEntry::moveNext() to validate a MachORebaseEntry for
4033 // REBASE_OPCODE_DO_*_TIMES* opcodes. The SegIndex and SegOffset must have
4034 // been already checked.
4035 const char * BindRebaseSegInfo::checkCountAndSkip(uint32_t Count
, uint32_t Skip
,
4036 uint8_t PointerSize
,
4038 uint64_t SegOffset
) {
4039 const SectionInfo
&SI
= findSection(SegIndex
, SegOffset
);
4040 uint64_t addr
= SI
.SegmentStartAddress
+ SegOffset
;
4041 if (addr
>= SI
.Address
+ SI
.Size
)
4042 return "bad segOffset, too large";
4045 i
= (Skip
+ PointerSize
) * (Count
- 1);
4046 else if (Count
== 1)
4047 i
= Skip
+ PointerSize
;
4048 if (addr
+ i
>= SI
.Address
+ SI
.Size
) {
4049 // For rebase opcodes they can step from one section to another.
4050 uint64_t TrailingSegOffset
= (addr
+ i
) - SI
.SegmentStartAddress
;
4051 const char *error
= checkSegAndOffset(SegIndex
, TrailingSegOffset
, false);
4053 return "bad count and skip, too large";
4058 // For use with the SegIndex of a checked Mach-O Bind or Rebase entry
4059 // to get the segment name.
4060 StringRef
BindRebaseSegInfo::segmentName(int32_t SegIndex
) {
4061 for (const SectionInfo
&SI
: Sections
) {
4062 if (SI
.SegmentIndex
== SegIndex
)
4063 return SI
.SegmentName
;
4065 llvm_unreachable("invalid SegIndex");
4068 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4069 // to get the SectionInfo.
4070 const BindRebaseSegInfo::SectionInfo
&BindRebaseSegInfo::findSection(
4071 int32_t SegIndex
, uint64_t SegOffset
) {
4072 for (const SectionInfo
&SI
: Sections
) {
4073 if (SI
.SegmentIndex
!= SegIndex
)
4075 if (SI
.OffsetInSegment
> SegOffset
)
4077 if (SegOffset
>= (SI
.OffsetInSegment
+ SI
.Size
))
4081 llvm_unreachable("SegIndex and SegOffset not in any section");
4084 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4085 // entry to get the section name.
4086 StringRef
BindRebaseSegInfo::sectionName(int32_t SegIndex
,
4087 uint64_t SegOffset
) {
4088 return findSection(SegIndex
, SegOffset
).SectionName
;
4091 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4092 // entry to get the address.
4093 uint64_t BindRebaseSegInfo::address(uint32_t SegIndex
, uint64_t OffsetInSeg
) {
4094 const SectionInfo
&SI
= findSection(SegIndex
, OffsetInSeg
);
4095 return SI
.SegmentStartAddress
+ OffsetInSeg
;
4098 iterator_range
<bind_iterator
>
4099 MachOObjectFile::bindTable(Error
&Err
, MachOObjectFile
*O
,
4100 ArrayRef
<uint8_t> Opcodes
, bool is64
,
4101 MachOBindEntry::Kind BKind
) {
4102 if (O
->BindRebaseSectionTable
== nullptr)
4103 O
->BindRebaseSectionTable
= llvm::make_unique
<BindRebaseSegInfo
>(O
);
4104 MachOBindEntry
Start(&Err
, O
, Opcodes
, is64
, BKind
);
4105 Start
.moveToFirst();
4107 MachOBindEntry
Finish(&Err
, O
, Opcodes
, is64
, BKind
);
4110 return make_range(bind_iterator(Start
), bind_iterator(Finish
));
4113 iterator_range
<bind_iterator
> MachOObjectFile::bindTable(Error
&Err
) {
4114 return bindTable(Err
, this, getDyldInfoBindOpcodes(), is64Bit(),
4115 MachOBindEntry::Kind::Regular
);
4118 iterator_range
<bind_iterator
> MachOObjectFile::lazyBindTable(Error
&Err
) {
4119 return bindTable(Err
, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
4120 MachOBindEntry::Kind::Lazy
);
4123 iterator_range
<bind_iterator
> MachOObjectFile::weakBindTable(Error
&Err
) {
4124 return bindTable(Err
, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
4125 MachOBindEntry::Kind::Weak
);
4128 MachOObjectFile::load_command_iterator
4129 MachOObjectFile::begin_load_commands() const {
4130 return LoadCommands
.begin();
4133 MachOObjectFile::load_command_iterator
4134 MachOObjectFile::end_load_commands() const {
4135 return LoadCommands
.end();
4138 iterator_range
<MachOObjectFile::load_command_iterator
>
4139 MachOObjectFile::load_commands() const {
4140 return make_range(begin_load_commands(), end_load_commands());
4144 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec
) const {
4145 ArrayRef
<char> Raw
= getSectionRawFinalSegmentName(Sec
);
4146 return parseSegmentOrSectionName(Raw
.data());
4150 MachOObjectFile::getSectionRawName(DataRefImpl Sec
) const {
4151 assert(Sec
.d
.a
< Sections
.size() && "Should have detected this earlier");
4152 const section_base
*Base
=
4153 reinterpret_cast<const section_base
*>(Sections
[Sec
.d
.a
]);
4154 return makeArrayRef(Base
->sectname
);
4158 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec
) const {
4159 assert(Sec
.d
.a
< Sections
.size() && "Should have detected this earlier");
4160 const section_base
*Base
=
4161 reinterpret_cast<const section_base
*>(Sections
[Sec
.d
.a
]);
4162 return makeArrayRef(Base
->segname
);
4166 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info
&RE
)
4168 if (getCPUType(*this) == MachO::CPU_TYPE_X86_64
)
4170 return getPlainRelocationAddress(RE
) & MachO::R_SCATTERED
;
4173 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
4174 const MachO::any_relocation_info
&RE
) const {
4175 if (isLittleEndian())
4176 return RE
.r_word1
& 0xffffff;
4177 return RE
.r_word1
>> 8;
4180 bool MachOObjectFile::getPlainRelocationExternal(
4181 const MachO::any_relocation_info
&RE
) const {
4182 if (isLittleEndian())
4183 return (RE
.r_word1
>> 27) & 1;
4184 return (RE
.r_word1
>> 4) & 1;
4187 bool MachOObjectFile::getScatteredRelocationScattered(
4188 const MachO::any_relocation_info
&RE
) const {
4189 return RE
.r_word0
>> 31;
4192 uint32_t MachOObjectFile::getScatteredRelocationValue(
4193 const MachO::any_relocation_info
&RE
) const {
4197 uint32_t MachOObjectFile::getScatteredRelocationType(
4198 const MachO::any_relocation_info
&RE
) const {
4199 return (RE
.r_word0
>> 24) & 0xf;
4202 unsigned MachOObjectFile::getAnyRelocationAddress(
4203 const MachO::any_relocation_info
&RE
) const {
4204 if (isRelocationScattered(RE
))
4205 return getScatteredRelocationAddress(RE
);
4206 return getPlainRelocationAddress(RE
);
4209 unsigned MachOObjectFile::getAnyRelocationPCRel(
4210 const MachO::any_relocation_info
&RE
) const {
4211 if (isRelocationScattered(RE
))
4212 return getScatteredRelocationPCRel(RE
);
4213 return getPlainRelocationPCRel(*this, RE
);
4216 unsigned MachOObjectFile::getAnyRelocationLength(
4217 const MachO::any_relocation_info
&RE
) const {
4218 if (isRelocationScattered(RE
))
4219 return getScatteredRelocationLength(RE
);
4220 return getPlainRelocationLength(*this, RE
);
4224 MachOObjectFile::getAnyRelocationType(
4225 const MachO::any_relocation_info
&RE
) const {
4226 if (isRelocationScattered(RE
))
4227 return getScatteredRelocationType(RE
);
4228 return getPlainRelocationType(*this, RE
);
4232 MachOObjectFile::getAnyRelocationSection(
4233 const MachO::any_relocation_info
&RE
) const {
4234 if (isRelocationScattered(RE
) || getPlainRelocationExternal(RE
))
4235 return *section_end();
4236 unsigned SecNum
= getPlainRelocationSymbolNum(RE
);
4237 if (SecNum
== MachO::R_ABS
|| SecNum
> Sections
.size())
4238 return *section_end();
4240 DRI
.d
.a
= SecNum
- 1;
4241 return SectionRef(DRI
, this);
4244 MachO::section
MachOObjectFile::getSection(DataRefImpl DRI
) const {
4245 assert(DRI
.d
.a
< Sections
.size() && "Should have detected this earlier");
4246 return getStruct
<MachO::section
>(*this, Sections
[DRI
.d
.a
]);
4249 MachO::section_64
MachOObjectFile::getSection64(DataRefImpl DRI
) const {
4250 assert(DRI
.d
.a
< Sections
.size() && "Should have detected this earlier");
4251 return getStruct
<MachO::section_64
>(*this, Sections
[DRI
.d
.a
]);
4254 MachO::section
MachOObjectFile::getSection(const LoadCommandInfo
&L
,
4255 unsigned Index
) const {
4256 const char *Sec
= getSectionPtr(*this, L
, Index
);
4257 return getStruct
<MachO::section
>(*this, Sec
);
4260 MachO::section_64
MachOObjectFile::getSection64(const LoadCommandInfo
&L
,
4261 unsigned Index
) const {
4262 const char *Sec
= getSectionPtr(*this, L
, Index
);
4263 return getStruct
<MachO::section_64
>(*this, Sec
);
4267 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI
) const {
4268 const char *P
= reinterpret_cast<const char *>(DRI
.p
);
4269 return getStruct
<MachO::nlist
>(*this, P
);
4273 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI
) const {
4274 const char *P
= reinterpret_cast<const char *>(DRI
.p
);
4275 return getStruct
<MachO::nlist_64
>(*this, P
);
4278 MachO::linkedit_data_command
4279 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo
&L
) const {
4280 return getStruct
<MachO::linkedit_data_command
>(*this, L
.Ptr
);
4283 MachO::segment_command
4284 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo
&L
) const {
4285 return getStruct
<MachO::segment_command
>(*this, L
.Ptr
);
4288 MachO::segment_command_64
4289 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo
&L
) const {
4290 return getStruct
<MachO::segment_command_64
>(*this, L
.Ptr
);
4293 MachO::linker_option_command
4294 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo
&L
) const {
4295 return getStruct
<MachO::linker_option_command
>(*this, L
.Ptr
);
4298 MachO::version_min_command
4299 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo
&L
) const {
4300 return getStruct
<MachO::version_min_command
>(*this, L
.Ptr
);
4304 MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo
&L
) const {
4305 return getStruct
<MachO::note_command
>(*this, L
.Ptr
);
4308 MachO::build_version_command
4309 MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo
&L
) const {
4310 return getStruct
<MachO::build_version_command
>(*this, L
.Ptr
);
4313 MachO::build_tool_version
4314 MachOObjectFile::getBuildToolVersion(unsigned index
) const {
4315 return getStruct
<MachO::build_tool_version
>(*this, BuildTools
[index
]);
4318 MachO::dylib_command
4319 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo
&L
) const {
4320 return getStruct
<MachO::dylib_command
>(*this, L
.Ptr
);
4323 MachO::dyld_info_command
4324 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo
&L
) const {
4325 return getStruct
<MachO::dyld_info_command
>(*this, L
.Ptr
);
4328 MachO::dylinker_command
4329 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo
&L
) const {
4330 return getStruct
<MachO::dylinker_command
>(*this, L
.Ptr
);
4334 MachOObjectFile::getUuidCommand(const LoadCommandInfo
&L
) const {
4335 return getStruct
<MachO::uuid_command
>(*this, L
.Ptr
);
4338 MachO::rpath_command
4339 MachOObjectFile::getRpathCommand(const LoadCommandInfo
&L
) const {
4340 return getStruct
<MachO::rpath_command
>(*this, L
.Ptr
);
4343 MachO::source_version_command
4344 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo
&L
) const {
4345 return getStruct
<MachO::source_version_command
>(*this, L
.Ptr
);
4348 MachO::entry_point_command
4349 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo
&L
) const {
4350 return getStruct
<MachO::entry_point_command
>(*this, L
.Ptr
);
4353 MachO::encryption_info_command
4354 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo
&L
) const {
4355 return getStruct
<MachO::encryption_info_command
>(*this, L
.Ptr
);
4358 MachO::encryption_info_command_64
4359 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo
&L
) const {
4360 return getStruct
<MachO::encryption_info_command_64
>(*this, L
.Ptr
);
4363 MachO::sub_framework_command
4364 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo
&L
) const {
4365 return getStruct
<MachO::sub_framework_command
>(*this, L
.Ptr
);
4368 MachO::sub_umbrella_command
4369 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo
&L
) const {
4370 return getStruct
<MachO::sub_umbrella_command
>(*this, L
.Ptr
);
4373 MachO::sub_library_command
4374 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo
&L
) const {
4375 return getStruct
<MachO::sub_library_command
>(*this, L
.Ptr
);
4378 MachO::sub_client_command
4379 MachOObjectFile::getSubClientCommand(const LoadCommandInfo
&L
) const {
4380 return getStruct
<MachO::sub_client_command
>(*this, L
.Ptr
);
4383 MachO::routines_command
4384 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo
&L
) const {
4385 return getStruct
<MachO::routines_command
>(*this, L
.Ptr
);
4388 MachO::routines_command_64
4389 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo
&L
) const {
4390 return getStruct
<MachO::routines_command_64
>(*this, L
.Ptr
);
4393 MachO::thread_command
4394 MachOObjectFile::getThreadCommand(const LoadCommandInfo
&L
) const {
4395 return getStruct
<MachO::thread_command
>(*this, L
.Ptr
);
4398 MachO::any_relocation_info
4399 MachOObjectFile::getRelocation(DataRefImpl Rel
) const {
4401 if (getHeader().filetype
== MachO::MH_OBJECT
) {
4405 MachO::section_64 Sect
= getSection64(Sec
);
4406 Offset
= Sect
.reloff
;
4408 MachO::section Sect
= getSection(Sec
);
4409 Offset
= Sect
.reloff
;
4412 MachO::dysymtab_command DysymtabLoadCmd
= getDysymtabLoadCommand();
4414 Offset
= DysymtabLoadCmd
.extreloff
; // Offset to the external relocations
4416 Offset
= DysymtabLoadCmd
.locreloff
; // Offset to the local relocations
4419 auto P
= reinterpret_cast<const MachO::any_relocation_info
*>(
4420 getPtr(*this, Offset
)) + Rel
.d
.b
;
4421 return getStruct
<MachO::any_relocation_info
>(
4422 *this, reinterpret_cast<const char *>(P
));
4425 MachO::data_in_code_entry
4426 MachOObjectFile::getDice(DataRefImpl Rel
) const {
4427 const char *P
= reinterpret_cast<const char *>(Rel
.p
);
4428 return getStruct
<MachO::data_in_code_entry
>(*this, P
);
4431 const MachO::mach_header
&MachOObjectFile::getHeader() const {
4435 const MachO::mach_header_64
&MachOObjectFile::getHeader64() const {
4440 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
4441 const MachO::dysymtab_command
&DLC
,
4442 unsigned Index
) const {
4443 uint64_t Offset
= DLC
.indirectsymoff
+ Index
* sizeof(uint32_t);
4444 return getStruct
<uint32_t>(*this, getPtr(*this, Offset
));
4447 MachO::data_in_code_entry
4448 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset
,
4449 unsigned Index
) const {
4450 uint64_t Offset
= DataOffset
+ Index
* sizeof(MachO::data_in_code_entry
);
4451 return getStruct
<MachO::data_in_code_entry
>(*this, getPtr(*this, Offset
));
4454 MachO::symtab_command
MachOObjectFile::getSymtabLoadCommand() const {
4456 return getStruct
<MachO::symtab_command
>(*this, SymtabLoadCmd
);
4458 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
4459 MachO::symtab_command Cmd
;
4460 Cmd
.cmd
= MachO::LC_SYMTAB
;
4461 Cmd
.cmdsize
= sizeof(MachO::symtab_command
);
4469 MachO::dysymtab_command
MachOObjectFile::getDysymtabLoadCommand() const {
4470 if (DysymtabLoadCmd
)
4471 return getStruct
<MachO::dysymtab_command
>(*this, DysymtabLoadCmd
);
4473 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
4474 MachO::dysymtab_command Cmd
;
4475 Cmd
.cmd
= MachO::LC_DYSYMTAB
;
4476 Cmd
.cmdsize
= sizeof(MachO::dysymtab_command
);
4487 Cmd
.extrefsymoff
= 0;
4488 Cmd
.nextrefsyms
= 0;
4489 Cmd
.indirectsymoff
= 0;
4490 Cmd
.nindirectsyms
= 0;
4498 MachO::linkedit_data_command
4499 MachOObjectFile::getDataInCodeLoadCommand() const {
4500 if (DataInCodeLoadCmd
)
4501 return getStruct
<MachO::linkedit_data_command
>(*this, DataInCodeLoadCmd
);
4503 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
4504 MachO::linkedit_data_command Cmd
;
4505 Cmd
.cmd
= MachO::LC_DATA_IN_CODE
;
4506 Cmd
.cmdsize
= sizeof(MachO::linkedit_data_command
);
4512 MachO::linkedit_data_command
4513 MachOObjectFile::getLinkOptHintsLoadCommand() const {
4514 if (LinkOptHintsLoadCmd
)
4515 return getStruct
<MachO::linkedit_data_command
>(*this, LinkOptHintsLoadCmd
);
4517 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
4519 MachO::linkedit_data_command Cmd
;
4520 Cmd
.cmd
= MachO::LC_LINKER_OPTIMIZATION_HINT
;
4521 Cmd
.cmdsize
= sizeof(MachO::linkedit_data_command
);
4527 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
4528 if (!DyldInfoLoadCmd
)
4531 MachO::dyld_info_command DyldInfo
=
4532 getStruct
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4533 const uint8_t *Ptr
=
4534 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.rebase_off
));
4535 return makeArrayRef(Ptr
, DyldInfo
.rebase_size
);
4538 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
4539 if (!DyldInfoLoadCmd
)
4542 MachO::dyld_info_command DyldInfo
=
4543 getStruct
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4544 const uint8_t *Ptr
=
4545 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.bind_off
));
4546 return makeArrayRef(Ptr
, DyldInfo
.bind_size
);
4549 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
4550 if (!DyldInfoLoadCmd
)
4553 MachO::dyld_info_command DyldInfo
=
4554 getStruct
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4555 const uint8_t *Ptr
=
4556 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.weak_bind_off
));
4557 return makeArrayRef(Ptr
, DyldInfo
.weak_bind_size
);
4560 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
4561 if (!DyldInfoLoadCmd
)
4564 MachO::dyld_info_command DyldInfo
=
4565 getStruct
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4566 const uint8_t *Ptr
=
4567 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.lazy_bind_off
));
4568 return makeArrayRef(Ptr
, DyldInfo
.lazy_bind_size
);
4571 ArrayRef
<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
4572 if (!DyldInfoLoadCmd
)
4575 MachO::dyld_info_command DyldInfo
=
4576 getStruct
<MachO::dyld_info_command
>(*this, DyldInfoLoadCmd
);
4577 const uint8_t *Ptr
=
4578 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo
.export_off
));
4579 return makeArrayRef(Ptr
, DyldInfo
.export_size
);
4582 ArrayRef
<uint8_t> MachOObjectFile::getUuid() const {
4585 // Returning a pointer is fine as uuid doesn't need endian swapping.
4586 const char *Ptr
= UuidLoadCmd
+ offsetof(MachO::uuid_command
, uuid
);
4587 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr
), 16);
4590 StringRef
MachOObjectFile::getStringTableData() const {
4591 MachO::symtab_command S
= getSymtabLoadCommand();
4592 return getData().substr(S
.stroff
, S
.strsize
);
4595 bool MachOObjectFile::is64Bit() const {
4596 return getType() == getMachOType(false, true) ||
4597 getType() == getMachOType(true, true);
4600 void MachOObjectFile::ReadULEB128s(uint64_t Index
,
4601 SmallVectorImpl
<uint64_t> &Out
) const {
4602 DataExtractor
extractor(ObjectFile::getData(), true, 0);
4604 uint32_t offset
= Index
;
4606 while (uint64_t delta
= extractor
.getULEB128(&offset
)) {
4608 Out
.push_back(data
);
4612 bool MachOObjectFile::isRelocatableObject() const {
4613 return getHeader().filetype
== MachO::MH_OBJECT
;
4616 Expected
<std::unique_ptr
<MachOObjectFile
>>
4617 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer
,
4618 uint32_t UniversalCputype
,
4619 uint32_t UniversalIndex
) {
4620 StringRef Magic
= Buffer
.getBuffer().slice(0, 4);
4621 if (Magic
== "\xFE\xED\xFA\xCE")
4622 return MachOObjectFile::create(Buffer
, false, false,
4623 UniversalCputype
, UniversalIndex
);
4624 if (Magic
== "\xCE\xFA\xED\xFE")
4625 return MachOObjectFile::create(Buffer
, true, false,
4626 UniversalCputype
, UniversalIndex
);
4627 if (Magic
== "\xFE\xED\xFA\xCF")
4628 return MachOObjectFile::create(Buffer
, false, true,
4629 UniversalCputype
, UniversalIndex
);
4630 if (Magic
== "\xCF\xFA\xED\xFE")
4631 return MachOObjectFile::create(Buffer
, true, true,
4632 UniversalCputype
, UniversalIndex
);
4633 return make_error
<GenericBinaryError
>("Unrecognized MachO magic number",
4634 object_error::invalid_file_type
);
4637 StringRef
MachOObjectFile::mapDebugSectionName(StringRef Name
) const {
4638 return StringSwitch
<StringRef
>(Name
)
4639 .Case("debug_str_offs", "debug_str_offsets")