2 * Copyright (c) 2006,2011-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 // macho++ - Mach-O object file helpers
27 #ifndef _H_MACHOPLUSPLUS
28 #define _H_MACHOPLUSPLUS
30 #include <mach-o/loader.h>
31 #include <mach-o/fat.h>
32 #include <mach-o/arch.h>
33 #include <security_utilities/globalizer.h>
34 #include <security_utilities/endian.h>
35 #include <security_utilities/unix++.h>
36 #include <security_utilities/cfutilities.h>
43 // An architecture specification.
44 // Simply a pair or (cpu type, cpu subtype), really.
46 class Architecture
: public std::pair
<cpu_type_t
, cpu_subtype_t
> {
47 typedef std::pair
<cpu_type_t
, cpu_subtype_t
> _Pair
;
50 explicit Architecture(cpu_type_t type
, cpu_subtype_t sub
= CPU_SUBTYPE_MULTIPLE
)
51 : std::pair
<cpu_type_t
, cpu_subtype_t
>(type
, sub
) { }
52 Architecture(const fat_arch
&archInFile
);
53 Architecture(const char *name
);
55 cpu_type_t
cpuType() const { return this->first
; }
56 cpu_subtype_t
cpuSubtype() const { return this->second
; }
57 const char *name() const; // NULL if unknown
58 std::string
displayName() const; // always display-able
60 static const cpu_type_t none
= 0;
61 operator bool () const { return cpuType() != none
; }
62 bool operator ! () const { return cpuType() == none
; }
65 friend bool operator == (const Architecture
&a1
, const Architecture
&a2
)
66 { return _Pair(a1
) == _Pair(a2
); }
68 friend bool operator < (const Architecture
&a1
, const Architecture
&a2
)
69 { return _Pair(a1
) < _Pair(a2
); }
71 bool matches(const Architecture
&templ
) const;
74 static Architecture
local();
79 // Common features of Mach-O object images.
80 // MachOBase does not define where we get this from.
89 { return mFlip
? Security::flip(value
) : value
; }
91 bool isFlipped() const { return mFlip
; }
92 bool is64() const { return m64
; }
94 const mach_header
&header() const { return *mHeader
; }
95 Architecture
architecture() const;
96 uint32_t type() const;
97 uint32_t flags() const;
99 const load_command
*loadCommands() const { return mCommands
; }
100 const load_command
*nextCommand(const load_command
*command
) const;
101 size_t commandLength() const { return flip(mHeader
->sizeofcmds
); }
103 const load_command
*findCommand(uint32_t cmd
) const;
104 const segment_command
*findSegment(const char *segname
) const;
105 const section
*findSection(const char *segname
, const char *sectname
) const;
107 const char *string(const load_command
*cmd
, const lc_str
&str
) const;
109 const linkedit_data_command
*findCodeSignature() const;
110 const linkedit_data_command
*findLibraryDependencies() const;
112 size_t signingOffset() const; // starting offset of CS section, or 0 if none
113 size_t signingLength() const; // length of CS section, or 0 if none
116 void initHeader(const mach_header
*address
);
117 void initCommands(const load_command
*commands
);
119 size_t headerSize() const; // size of header
120 size_t commandSize() const; // size of commands area
123 const mach_header
*mHeader
; // Mach-O header
124 const load_command
*mCommands
; // load commands
125 const load_command
*mEndCommands
; // end of load commands
127 bool m64
; // is 64-bit
128 bool mFlip
; // wrong byte order (flip all integers)
133 // A Mach-O object image that resides on disk.
134 // We only read small parts of the contents into (discontinuous) memory.
136 class MachO
: public MachOBase
, public UnixPlusPlus::FileDesc
{
138 MachO(FileDesc fd
, size_t offset
= 0, size_t length
= 0);
141 size_t offset() const { return mOffset
; }
142 size_t length() const { return mLength
; }
143 size_t signingExtent() const; // signingOffset, or file length if none
145 void seek(size_t offset
); // relative to start of image
146 CFDataRef
dataAt(size_t offset
, size_t size
);
147 void validateStructure(); // is the structure of the mach-o sane
149 bool isSuspicious() const { return mSuspicious
; }
152 size_t mOffset
; // starting file offset
153 size_t mLength
; // Mach-O file length
155 mach_header mHeaderBuffer
; // read-in Mach-O header
156 load_command
*mCommandBuffer
; // read-in (malloc'ed) Mach-O load commands
158 bool mSuspicious
; // strict validation failed
163 // A Mach-O object image that was mapped into memory.
164 // We expect the entire image to be contiguously mapped starting at the
165 // address given. No particular alignment is required (beyond native
166 // alignment constraints on member variables).
168 class MachOImage
: public MachOBase
{
170 MachOImage(const void *address
);
172 const void *address() { return &this->header(); }
175 class MainMachOImage
: public MachOImage
{
179 static const void *mainImageAddress();
184 // A Universal object represents a Mach-O binary image (whole) file.
185 // It can represent a true Universal (aka "Fat") file with multiple
186 // architectures; but it will also represent a single Mach-O ("thin")
187 // binary and make you believe it's a Universal with just one architecture.
189 class Universal
: public UnixPlusPlus::FileDesc
{
191 Universal(FileDesc fd
, size_t offset
= 0, size_t length
= 0);
194 // return a genuine MachO object for the given architecture
195 MachO
*architecture() const; // native
196 MachO
*architecture(const Architecture
&arch
) const; // given
197 MachO
*architecture(size_t offset
) const; // given by file offset
199 // return (just) the starting offset of an architecture
200 size_t archOffset() const; // native
201 size_t archOffset(const Architecture
&arch
) const; // given
202 size_t archLength(const Architecture
&arch
) const; // given
203 bool narrowed() const { return mBase
!= 0; } // part of a fat file
205 // return a set of architectures contained
206 typedef std::set
<Architecture
> Architectures
;
207 void architectures(Architectures
&archs
) const;
209 bool isUniversal() const { return mArchList
!= NULL
; }
210 Architecture
bestNativeArch() const;
211 const size_t lengthOfSlice(size_t offset
) const;
213 size_t offset() const { return mBase
; }
214 size_t length() const { return mLength
; }
216 bool isSuspicious() const;
219 static uint32_t typeOf(FileDesc fd
);
222 const fat_arch
*findArch(const Architecture
&arch
) const;
223 MachO
*findImage(const Architecture
&arch
) const;
226 fat_arch
*mArchList
; // architectures (NULL if thin file)
227 unsigned mArchCount
; // number of architectures (if fat)
228 Architecture mThinArch
; // single architecture (if thin)
229 size_t mBase
; // overriding offset in file (all types)
230 size_t mLength
; // length of the architecture if thin file
231 typedef std::map
<size_t, size_t> OffsetsToLength
;
232 OffsetsToLength mSizes
; // the length for the slice at a given offset
233 bool mSuspicious
; // strict validation failed
237 } // end namespace Security
239 #endif // !_H_MACHOPLUSPLUS