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
115 bool version(uint32_t *platform
, uint32_t *minVersion
, uint32_t *sdkVersion
) const;
116 uint32_t platform() const { uint32_t ret
; return version(&ret
, NULL
, NULL
) ? ret
: 0; };
117 uint32_t minVersion() const { uint32_t ret
; return version(NULL
, &ret
, NULL
) ? ret
: 0; };
118 uint32_t sdkVersion() const { uint32_t ret
; return version(NULL
, NULL
, &ret
) ? ret
: 0; };
121 void initHeader(const mach_header
*address
);
122 void initCommands(const load_command
*commands
);
124 size_t headerSize() const; // size of header
125 size_t commandSize() const; // size of commands area
127 const version_min_command
*findMinVersion() const;
128 const build_version_command
*findBuildVersion() const;
131 const mach_header
*mHeader
; // Mach-O header
132 const load_command
*mCommands
; // load commands
133 const load_command
*mEndCommands
; // end of load commands
135 bool m64
; // is 64-bit
136 bool mFlip
; // wrong byte order (flip all integers)
141 // A Mach-O object image that resides on disk.
142 // We only read small parts of the contents into (discontinuous) memory.
144 class MachO
: public MachOBase
, public UnixPlusPlus::FileDesc
{
146 MachO(FileDesc fd
, size_t offset
= 0, size_t length
= 0);
149 size_t offset() const { return mOffset
; }
150 size_t length() const { return mLength
; }
151 size_t signingExtent() const; // signingOffset, or file length if none
153 void seek(size_t offset
); // relative to start of image
154 CFDataRef
dataAt(size_t offset
, size_t size
);
155 void validateStructure(); // is the structure of the mach-o sane
157 bool isSuspicious() const { return mSuspicious
; }
160 size_t mOffset
; // starting file offset
161 size_t mLength
; // Mach-O file length
163 mach_header mHeaderBuffer
; // read-in Mach-O header
164 load_command
*mCommandBuffer
; // read-in (malloc'ed) Mach-O load commands
166 bool mSuspicious
; // strict validation failed
171 // A Mach-O object image that was mapped into memory.
172 // We expect the entire image to be contiguously mapped starting at the
173 // address given. No particular alignment is required (beyond native
174 // alignment constraints on member variables).
176 class MachOImage
: public MachOBase
{
178 MachOImage(const void *address
);
180 const void *address() { return &this->header(); }
183 class MainMachOImage
: public MachOImage
{
187 static const void *mainImageAddress();
192 // A Universal object represents a Mach-O binary image (whole) file.
193 // It can represent a true Universal (aka "Fat") file with multiple
194 // architectures; but it will also represent a single Mach-O ("thin")
195 // binary and make you believe it's a Universal with just one architecture.
197 class Universal
: public UnixPlusPlus::FileDesc
{
199 Universal(FileDesc fd
, size_t offset
= 0, size_t length
= 0);
202 // return a genuine MachO object for the given architecture
203 MachO
*architecture() const; // native
204 MachO
*architecture(const Architecture
&arch
) const; // given
205 MachO
*architecture(size_t offset
) const; // given by file offset
207 // return (just) the starting offset of an architecture
208 size_t archOffset() const; // native
209 size_t archOffset(const Architecture
&arch
) const; // given
210 size_t archLength(const Architecture
&arch
) const; // given
211 bool narrowed() const { return mBase
!= 0; } // part of a fat file
213 // return a set of architectures contained
214 typedef std::set
<Architecture
> Architectures
;
215 void architectures(Architectures
&archs
) const;
217 bool isUniversal() const { return mArchList
!= NULL
; }
218 Architecture
bestNativeArch() const;
219 size_t lengthOfSlice(size_t offset
) const;
221 size_t offset() const { return mBase
; }
222 size_t length() const { return mLength
; }
224 bool isSuspicious() const;
227 static uint32_t typeOf(FileDesc fd
);
230 const fat_arch
*findArch(const Architecture
&arch
) const;
231 MachO
*findImage(const Architecture
&arch
) const;
232 MachO
*make(MachO
* macho
) const;
235 fat_arch
*mArchList
; // architectures (NULL if thin file)
236 unsigned mArchCount
; // number of architectures (if fat)
237 Architecture mThinArch
; // single architecture (if thin)
238 size_t mBase
; // overriding offset in file (all types)
239 size_t mLength
; // length of the architecture if thin file
240 typedef std::map
<size_t, size_t> OffsetsToLength
;
241 OffsetsToLength mSizes
; // the length for the slice at a given offset
242 mutable uint32_t mMachType
; // canonical Mach-O type (0 if not yet set)
243 bool mSuspicious
; // strict validation failed
247 } // end namespace Security
249 #endif // !_H_MACHOPLUSPLUS