]> git.saurik.com Git - apple/security.git/blob - libsecurity_utilities/lib/macho++.h
Security-55178.0.1.tar.gz
[apple/security.git] / libsecurity_utilities / lib / macho++.h
1 /*
2 * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
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>
37
38 namespace Security {
39
40
41 //
42 // An architecture specification.
43 // Simply a pair or (cpu type, cpu subtype), really.
44 //
45 class Architecture : public std::pair<cpu_type_t, cpu_subtype_t> {
46 typedef std::pair<cpu_type_t, cpu_subtype_t> _Pair;
47 public:
48 Architecture() { }
49 explicit Architecture(cpu_type_t type, cpu_subtype_t sub = CPU_SUBTYPE_MULTIPLE)
50 : std::pair<cpu_type_t, cpu_subtype_t>(type, sub) { }
51 Architecture(const fat_arch &archInFile);
52 Architecture(const char *name);
53
54 cpu_type_t cpuType() const { return this->first; }
55 cpu_subtype_t cpuSubtype() const { return this->second; }
56 const char *name() const; // NULL if unknown
57 std::string displayName() const; // always display-able
58
59 static const cpu_type_t none = 0;
60 operator bool () const { return cpuType() != none; }
61 bool operator ! () const { return cpuType() == none; }
62
63 public:
64 friend bool operator == (const Architecture &a1, const Architecture &a2)
65 { return _Pair(a1) == _Pair(a2); }
66
67 friend bool operator < (const Architecture &a1, const Architecture &a2)
68 { return _Pair(a1) < _Pair(a2); }
69
70 bool matches(const Architecture &templ) const;
71
72 public:
73 static Architecture local();
74 };
75
76
77 //
78 // Common features of Mach-O object images.
79 // MachOBase does not define where we get this from.
80 //
81 class MachOBase {
82 protected:
83 virtual ~MachOBase();
84
85 public:
86 template <class T>
87 T flip(T value) const
88 { return mFlip ? Security::flip(value) : value; }
89
90 bool isFlipped() const { return mFlip; }
91 bool is64() const { return m64; }
92
93 const mach_header &header() const { return *mHeader; }
94 Architecture architecture() const;
95 uint32_t type() const;
96 uint32_t flags() const;
97
98 const load_command *loadCommands() const { return mCommands; }
99 const load_command *nextCommand(const load_command *command) const;
100 size_t commandLength() const { return flip(mHeader->sizeofcmds); }
101
102 const load_command *findCommand(uint32_t cmd) const;
103 const segment_command *findSegment(const char *segname) const;
104 const section *findSection(const char *segname, const char *sectname) const;
105
106 const char *string(const load_command *cmd, const lc_str &str) const;
107
108 const linkedit_data_command *findCodeSignature() const;
109 const linkedit_data_command *findLibraryDependencies() const;
110
111 size_t signingOffset() const; // starting offset of CS section, or 0 if none
112 size_t signingLength() const; // length of CS section, or 0 if none
113
114 protected:
115 void initHeader(const mach_header *address);
116 void initCommands(const load_command *commands);
117
118 size_t headerSize() const; // size of header
119 size_t commandSize() const; // size of commands area
120
121 private:
122 const mach_header *mHeader; // Mach-O header
123 const load_command *mCommands; // load commands
124 const load_command *mEndCommands; // end of load commands
125
126 bool m64; // is 64-bit
127 bool mFlip; // wrong byte order (flip all integers)
128 };
129
130
131 //
132 // A Mach-O object image that resides on disk.
133 // We only read small parts of the contents into (discontinuous) memory.
134 //
135 class MachO : public MachOBase, public UnixPlusPlus::FileDesc {
136 public:
137 MachO(FileDesc fd, size_t offset = 0, size_t length = 0);
138 ~MachO();
139
140 size_t offset() const { return mOffset; }
141 size_t length() const { return mLength; }
142 size_t signingExtent() const; // signingOffset, or file length if none
143
144 void seek(size_t offset); // relative to start of image
145 CFDataRef dataAt(size_t offset, size_t size);
146
147 private:
148 size_t mOffset; // starting file offset
149 size_t mLength; // Mach-O file length
150
151 mach_header mHeaderBuffer; // read-in Mach-O header
152 load_command *mCommandBuffer; // read-in (malloc'ed) Mach-O load commands
153 };
154
155
156 //
157 // A Mach-O object image that was mapped into memory.
158 // We expect the entire image to be contiguously mapped starting at the
159 // address given. No particular alignment is required (beyond native
160 // alignment constraints on member variables).
161 //
162 class MachOImage : public MachOBase {
163 public:
164 MachOImage(const void *address);
165
166 const void *address() { return &this->header(); }
167 };
168
169 class MainMachOImage : public MachOImage {
170 public:
171 MainMachOImage();
172
173 static const void *mainImageAddress();
174 };
175
176
177 //
178 // A Universal object represents a Mach-O binary image (whole) file.
179 // It can represent a true Universal (aka "Fat") file with multiple
180 // architectures; but it will also represent a single Mach-O ("thin")
181 // binary and make you believe it's a Universal with just one architecture.
182 //
183 class Universal : public UnixPlusPlus::FileDesc {
184 public:
185 Universal(FileDesc fd, off_t offset = 0);
186 ~Universal();
187
188 // return a genuine MachO object for the given architecture
189 MachO *architecture() const; // native
190 MachO *architecture(const Architecture &arch) const; // given
191 MachO *architecture(off_t offset) const; // given by file offset
192
193 // return (just) the starting offset of an architecture
194 size_t archOffset() const; // native
195 size_t archOffset(const Architecture &arch) const; // given
196
197 // return a set of architectures contained
198 typedef std::set<Architecture> Architectures;
199 void architectures(Architectures &archs);
200
201 bool isUniversal() const { return mArchList != NULL; }
202 Architecture bestNativeArch() const;
203
204 public:
205 static uint32_t typeOf(FileDesc fd);
206
207 private:
208 const fat_arch *findArch(const Architecture &arch) const;
209 MachO *findImage(const Architecture &arch) const;
210
211 private:
212 fat_arch *mArchList; // architectures (NULL if thin file)
213 unsigned mArchCount; // number of architectures (if fat)
214 Architecture mThinArch; // single architecture (if thin)
215 off_t mBase; // overriding offset in file (all types)
216 };
217
218
219 } // end namespace Security
220
221 #endif // !_H_MACHOPLUSPLUS