]> git.saurik.com Git - apple/security.git/blame - OSX/libsecurity_utilities/lib/macho++.h
Security-57337.60.2.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / macho++.h
CommitLineData
b1ab9ed8 1/*
d8f41ccd 2 * Copyright (c) 2006,2011-2014 Apple Inc. All Rights Reserved.
b1ab9ed8
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24//
25// macho++ - Mach-O object file helpers
26//
27#ifndef _H_MACHOPLUSPLUS
28#define _H_MACHOPLUSPLUS
29
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>
80e23899 37#include <map>
b1ab9ed8
A
38
39namespace Security {
40
41
42//
43// An architecture specification.
44// Simply a pair or (cpu type, cpu subtype), really.
45//
46class Architecture : public std::pair<cpu_type_t, cpu_subtype_t> {
47 typedef std::pair<cpu_type_t, cpu_subtype_t> _Pair;
48public:
49 Architecture() { }
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);
54
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
59
60 static const cpu_type_t none = 0;
61 operator bool () const { return cpuType() != none; }
62 bool operator ! () const { return cpuType() == none; }
63
64public:
65 friend bool operator == (const Architecture &a1, const Architecture &a2)
66 { return _Pair(a1) == _Pair(a2); }
67
68 friend bool operator < (const Architecture &a1, const Architecture &a2)
69 { return _Pair(a1) < _Pair(a2); }
70
71 bool matches(const Architecture &templ) const;
72
73public:
74 static Architecture local();
75};
76
77
78//
79// Common features of Mach-O object images.
80// MachOBase does not define where we get this from.
81//
82class MachOBase {
83protected:
84 virtual ~MachOBase();
85
86public:
87 template <class T>
88 T flip(T value) const
89 { return mFlip ? Security::flip(value) : value; }
90
91 bool isFlipped() const { return mFlip; }
92 bool is64() const { return m64; }
93
94 const mach_header &header() const { return *mHeader; }
95 Architecture architecture() const;
96 uint32_t type() const;
97 uint32_t flags() const;
98
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); }
102
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;
106
107 const char *string(const load_command *cmd, const lc_str &str) const;
108
109 const linkedit_data_command *findCodeSignature() const;
110 const linkedit_data_command *findLibraryDependencies() const;
e3d460c9 111 const version_min_command *findMinVersion() const;
b1ab9ed8
A
112
113 size_t signingOffset() const; // starting offset of CS section, or 0 if none
114 size_t signingLength() const; // length of CS section, or 0 if none
115
116protected:
117 void initHeader(const mach_header *address);
118 void initCommands(const load_command *commands);
119
120 size_t headerSize() const; // size of header
121 size_t commandSize() const; // size of commands area
122
123private:
124 const mach_header *mHeader; // Mach-O header
125 const load_command *mCommands; // load commands
126 const load_command *mEndCommands; // end of load commands
127
128 bool m64; // is 64-bit
129 bool mFlip; // wrong byte order (flip all integers)
130};
131
132
133//
134// A Mach-O object image that resides on disk.
135// We only read small parts of the contents into (discontinuous) memory.
136//
137class MachO : public MachOBase, public UnixPlusPlus::FileDesc {
138public:
139 MachO(FileDesc fd, size_t offset = 0, size_t length = 0);
140 ~MachO();
141
142 size_t offset() const { return mOffset; }
143 size_t length() const { return mLength; }
144 size_t signingExtent() const; // signingOffset, or file length if none
145
146 void seek(size_t offset); // relative to start of image
147 CFDataRef dataAt(size_t offset, size_t size);
80e23899
A
148 void validateStructure(); // is the structure of the mach-o sane
149
150 bool isSuspicious() const { return mSuspicious; }
b1ab9ed8
A
151
152private:
153 size_t mOffset; // starting file offset
154 size_t mLength; // Mach-O file length
155
156 mach_header mHeaderBuffer; // read-in Mach-O header
157 load_command *mCommandBuffer; // read-in (malloc'ed) Mach-O load commands
80e23899
A
158
159 bool mSuspicious; // strict validation failed
b1ab9ed8
A
160};
161
162
163//
164// A Mach-O object image that was mapped into memory.
165// We expect the entire image to be contiguously mapped starting at the
166// address given. No particular alignment is required (beyond native
167// alignment constraints on member variables).
168//
169class MachOImage : public MachOBase {
170public:
171 MachOImage(const void *address);
172
173 const void *address() { return &this->header(); }
174};
175
176class MainMachOImage : public MachOImage {
177public:
178 MainMachOImage();
179
180 static const void *mainImageAddress();
181};
182
183
184//
185// A Universal object represents a Mach-O binary image (whole) file.
186// It can represent a true Universal (aka "Fat") file with multiple
187// architectures; but it will also represent a single Mach-O ("thin")
188// binary and make you believe it's a Universal with just one architecture.
189//
190class Universal : public UnixPlusPlus::FileDesc {
191public:
80e23899 192 Universal(FileDesc fd, size_t offset = 0, size_t length = 0);
b1ab9ed8
A
193 ~Universal();
194
195 // return a genuine MachO object for the given architecture
196 MachO *architecture() const; // native
197 MachO *architecture(const Architecture &arch) const; // given
427c49bc 198 MachO *architecture(size_t offset) const; // given by file offset
b1ab9ed8
A
199
200 // return (just) the starting offset of an architecture
201 size_t archOffset() const; // native
202 size_t archOffset(const Architecture &arch) const; // given
80e23899 203 size_t archLength(const Architecture &arch) const; // given
427c49bc 204 bool narrowed() const { return mBase != 0; } // part of a fat file
b1ab9ed8
A
205
206 // return a set of architectures contained
207 typedef std::set<Architecture> Architectures;
80e23899 208 void architectures(Architectures &archs) const;
d8f41ccd 209
b1ab9ed8
A
210 bool isUniversal() const { return mArchList != NULL; }
211 Architecture bestNativeArch() const;
80e23899 212 const size_t lengthOfSlice(size_t offset) const;
d8f41ccd 213
e3d3b979 214 size_t offset() const { return mBase; }
80e23899 215 size_t length() const { return mLength; }
d8f41ccd 216
80e23899 217 bool isSuspicious() const;
e3d3b979 218
b1ab9ed8
A
219public:
220 static uint32_t typeOf(FileDesc fd);
221
222private:
223 const fat_arch *findArch(const Architecture &arch) const;
224 MachO *findImage(const Architecture &arch) const;
5c19dc3a 225 MachO *make(MachO* macho) const;
b1ab9ed8
A
226
227private:
228 fat_arch *mArchList; // architectures (NULL if thin file)
229 unsigned mArchCount; // number of architectures (if fat)
230 Architecture mThinArch; // single architecture (if thin)
427c49bc 231 size_t mBase; // overriding offset in file (all types)
80e23899
A
232 size_t mLength; // length of the architecture if thin file
233 typedef std::map<size_t, size_t> OffsetsToLength;
234 OffsetsToLength mSizes; // the length for the slice at a given offset
5c19dc3a 235 mutable uint32_t mMachType; // canonical Mach-O type (0 if not yet set)
80e23899 236 bool mSuspicious; // strict validation failed
b1ab9ed8
A
237};
238
239
240} // end namespace Security
241
242#endif // !_H_MACHOPLUSPLUS