]>
Commit | Line | Data |
---|---|---|
d696c285 A |
1 | /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- |
2 | * | |
3 | * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. | |
4 | * | |
5 | * @APPLE_LICENSE_HEADER_START@ | |
6 | * | |
7 | * This file contains Original Code and/or Modifications of Original Code | |
8 | * as defined in and that are subject to the Apple Public Source License | |
9 | * Version 2.0 (the 'License'). You may not use this file except in | |
10 | * compliance with the License. Please obtain a copy of the License at | |
11 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
12 | * file. | |
13 | * | |
14 | * The Original Code and all software distributed under the License are | |
15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
19 | * Please see the License for the specific language governing rights and | |
20 | * limitations under the License. | |
21 | * | |
22 | * @APPLE_LICENSE_HEADER_END@ | |
23 | */ | |
24 | #ifndef __MACH_O_FILE_ABSTRACTION__ | |
25 | #define __MACH_O_FILE_ABSTRACTION__ | |
26 | ||
27 | #include <mach-o/loader.h> | |
28 | #include <mach-o/nlist.h> | |
29 | #include <mach-o/reloc.h> | |
30 | #include <mach/machine.h> | |
31 | ||
32 | // suport older versions of mach-o/loader.h | |
33 | #ifndef LC_UUID | |
34 | #define LC_UUID 0x1b | |
35 | struct uuid_command { | |
36 | uint32_t cmd; /* LC_UUID */ | |
37 | uint32_t cmdsize; /* sizeof(struct uuid_command) */ | |
38 | uint8_t uuid[16]; /* the 128-bit uuid */ | |
39 | }; | |
40 | #endif | |
41 | ||
69a49097 A |
42 | #ifndef S_16BYTE_LITERALS |
43 | #define S_16BYTE_LITERALS 0xE | |
44 | #endif | |
d696c285 A |
45 | |
46 | #include "FileAbstraction.hpp" | |
47 | #include "Architectures.hpp" | |
48 | ||
49 | ||
50 | ||
51 | // | |
52 | // This abstraction layer makes every mach-o file look like a 64-bit mach-o file with native endianness | |
53 | // | |
54 | ||
55 | ||
56 | ||
57 | // | |
58 | // mach-o file header | |
59 | // | |
60 | template <typename P> struct macho_header_content {}; | |
61 | template <> struct macho_header_content<Pointer32<BigEndian> > { mach_header fields; }; | |
62 | template <> struct macho_header_content<Pointer64<BigEndian> > { mach_header_64 fields; }; | |
63 | template <> struct macho_header_content<Pointer32<LittleEndian> > { mach_header fields; }; | |
64 | template <> struct macho_header_content<Pointer64<LittleEndian> > { mach_header_64 fields; }; | |
65 | ||
66 | template <typename P> | |
67 | class macho_header { | |
68 | public: | |
69 | uint32_t magic() const INLINE { return E::get32(header.fields.magic); } | |
70 | void set_magic(uint32_t value) INLINE { E::set32(header.fields.magic, value); } | |
71 | ||
72 | uint32_t cputype() const INLINE { return E::get32(header.fields.cputype); } | |
73 | void set_cputype(uint32_t value) INLINE { E::set32((uint32_t&)header.fields.cputype, value); } | |
74 | ||
75 | uint32_t cpusubtype() const INLINE { return E::get32(header.fields.cpusubtype); } | |
76 | void set_cpusubtype(uint32_t value) INLINE { E::set32((uint32_t&)header.fields.cpusubtype, value); } | |
77 | ||
78 | uint32_t filetype() const INLINE { return E::get32(header.fields.filetype); } | |
79 | void set_filetype(uint32_t value) INLINE { E::set32(header.fields.filetype, value); } | |
80 | ||
81 | uint32_t ncmds() const INLINE { return E::get32(header.fields.ncmds); } | |
82 | void set_ncmds(uint32_t value) INLINE { E::set32(header.fields.ncmds, value); } | |
83 | ||
84 | uint32_t sizeofcmds() const INLINE { return E::get32(header.fields.sizeofcmds); } | |
85 | void set_sizeofcmds(uint32_t value) INLINE { E::set32(header.fields.sizeofcmds, value); } | |
86 | ||
87 | uint32_t flags() const INLINE { return E::get32(header.fields.flags); } | |
88 | void set_flags(uint32_t value) INLINE { E::set32(header.fields.flags, value); } | |
89 | ||
90 | uint32_t reserved() const INLINE { return E::get32(header.fields.reserved); } | |
91 | void set_reserved(uint32_t value) INLINE { E::set32(header.fields.reserved, value); } | |
92 | ||
93 | typedef typename P::E E; | |
94 | private: | |
95 | macho_header_content<P> header; | |
96 | }; | |
97 | ||
98 | ||
99 | // | |
100 | // mach-o load command | |
101 | // | |
102 | template <typename P> | |
103 | class macho_load_command { | |
104 | public: | |
105 | uint32_t cmd() const INLINE { return E::get32(command.cmd); } | |
106 | void set_cmd(uint32_t value) INLINE { E::set32(command.cmd, value); } | |
107 | ||
108 | uint32_t cmdsize() const INLINE { return E::get32(command.cmdsize); } | |
109 | void set_cmdsize(uint32_t value) INLINE { E::set32(command.cmdsize, value); } | |
110 | ||
111 | typedef typename P::E E; | |
112 | private: | |
113 | load_command command; | |
114 | }; | |
115 | ||
116 | ||
117 | // | |
118 | // mach-o segment load command | |
119 | // | |
120 | template <typename P> struct macho_segment_content {}; | |
121 | template <> struct macho_segment_content<Pointer32<BigEndian> > { segment_command fields; enum { CMD = LC_SEGMENT }; }; | |
122 | template <> struct macho_segment_content<Pointer64<BigEndian> > { segment_command_64 fields; enum { CMD = LC_SEGMENT_64 }; }; | |
123 | template <> struct macho_segment_content<Pointer32<LittleEndian> > { segment_command fields; enum { CMD = LC_SEGMENT }; }; | |
124 | template <> struct macho_segment_content<Pointer64<LittleEndian> > { segment_command_64 fields; enum { CMD = LC_SEGMENT_64 }; }; | |
125 | ||
126 | template <typename P> | |
127 | class macho_segment_command { | |
128 | public: | |
129 | uint32_t cmd() const INLINE { return E::get32(segment.fields.cmd); } | |
130 | void set_cmd(uint32_t value) INLINE { E::set32(segment.fields.cmd, value); } | |
131 | ||
132 | uint32_t cmdsize() const INLINE { return E::get32(segment.fields.cmdsize); } | |
133 | void set_cmdsize(uint32_t value) INLINE { E::set32(segment.fields.cmdsize, value); } | |
134 | ||
135 | const char* segname() const INLINE { return segment.fields.segname; } | |
69a49097 | 136 | void set_segname(const char* value) INLINE { strncpy(segment.fields.segname, value, 16); } |
d696c285 A |
137 | |
138 | uint64_t vmaddr() const INLINE { return P::getP(segment.fields.vmaddr); } | |
139 | void set_vmaddr(uint64_t value) INLINE { P::setP(segment.fields.vmaddr, value); } | |
140 | ||
141 | uint64_t vmsize() const INLINE { return P::getP(segment.fields.vmsize); } | |
142 | void set_vmsize(uint64_t value) INLINE { P::setP(segment.fields.vmsize, value); } | |
143 | ||
144 | uint64_t fileoff() const INLINE { return P::getP(segment.fields.fileoff); } | |
145 | void set_fileoff(uint64_t value) INLINE { P::setP(segment.fields.fileoff, value); } | |
146 | ||
147 | uint64_t filesize() const INLINE { return P::getP(segment.fields.filesize); } | |
148 | void set_filesize(uint64_t value) INLINE { P::setP(segment.fields.filesize, value); } | |
149 | ||
150 | uint32_t maxprot() const INLINE { return E::get32(segment.fields.maxprot); } | |
151 | void set_maxprot(uint32_t value) INLINE { E::set32((uint32_t&)segment.fields.maxprot, value); } | |
152 | ||
153 | uint32_t initprot() const INLINE { return E::get32(segment.fields.initprot); } | |
154 | void set_initprot(uint32_t value) INLINE { E::set32((uint32_t&)segment.fields.initprot, value); } | |
155 | ||
156 | uint32_t nsects() const INLINE { return E::get32(segment.fields.nsects); } | |
157 | void set_nsects(uint32_t value) INLINE { E::set32(segment.fields.nsects, value); } | |
158 | ||
159 | uint32_t flags() const INLINE { return E::get32(segment.fields.flags); } | |
160 | void set_flags(uint32_t value) INLINE { E::set32(segment.fields.flags, value); } | |
161 | ||
162 | enum { | |
163 | CMD = macho_segment_content<P>::CMD | |
164 | }; | |
165 | ||
166 | typedef typename P::E E; | |
167 | private: | |
168 | macho_segment_content<P> segment; | |
169 | }; | |
170 | ||
171 | ||
172 | // | |
173 | // mach-o section | |
174 | // | |
175 | template <typename P> struct macho_section_content {}; | |
176 | template <> struct macho_section_content<Pointer32<BigEndian> > { section fields; }; | |
177 | template <> struct macho_section_content<Pointer64<BigEndian> > { section_64 fields; }; | |
178 | template <> struct macho_section_content<Pointer32<LittleEndian> > { section fields; }; | |
179 | template <> struct macho_section_content<Pointer64<LittleEndian> > { section_64 fields; }; | |
180 | ||
181 | template <typename P> | |
182 | class macho_section { | |
183 | public: | |
184 | const char* sectname() const INLINE { return section.fields.sectname; } | |
69a49097 | 185 | void set_sectname(const char* value) INLINE { strncpy(section.fields.sectname, value, 16); } |
d696c285 A |
186 | |
187 | const char* segname() const INLINE { return section.fields.segname; } | |
69a49097 | 188 | void set_segname(const char* value) INLINE { strncpy(section.fields.segname, value, 16); } |
d696c285 A |
189 | |
190 | uint64_t addr() const INLINE { return P::getP(section.fields.addr); } | |
191 | void set_addr(uint64_t value) INLINE { P::setP(section.fields.addr, value); } | |
192 | ||
193 | uint64_t size() const INLINE { return P::getP(section.fields.size); } | |
194 | void set_size(uint64_t value) INLINE { P::setP(section.fields.size, value); } | |
195 | ||
196 | uint32_t offset() const INLINE { return E::get32(section.fields.offset); } | |
197 | void set_offset(uint32_t value) INLINE { E::set32(section.fields.offset, value); } | |
198 | ||
199 | uint32_t align() const INLINE { return E::get32(section.fields.align); } | |
200 | void set_align(uint32_t value) INLINE { E::set32(section.fields.align, value); } | |
201 | ||
202 | uint32_t reloff() const INLINE { return E::get32(section.fields.reloff); } | |
203 | void set_reloff(uint32_t value) INLINE { E::set32(section.fields.reloff, value); } | |
204 | ||
205 | uint32_t nreloc() const INLINE { return E::get32(section.fields.nreloc); } | |
206 | void set_nreloc(uint32_t value) INLINE { E::set32(section.fields.nreloc, value); } | |
207 | ||
208 | uint32_t flags() const INLINE { return E::get32(section.fields.flags); } | |
209 | void set_flags(uint32_t value) INLINE { E::set32(section.fields.flags, value); } | |
210 | ||
211 | uint32_t reserved1() const INLINE { return E::get32(section.fields.reserved1); } | |
212 | void set_reserved1(uint32_t value) INLINE { E::set32(section.fields.reserved1, value); } | |
213 | ||
214 | uint32_t reserved2() const INLINE { return E::get32(section.fields.reserved2); } | |
215 | void set_reserved2(uint32_t value) INLINE { E::set32(section.fields.reserved2, value); } | |
216 | ||
217 | typedef typename P::E E; | |
218 | private: | |
219 | macho_section_content<P> section; | |
220 | }; | |
221 | ||
222 | ||
223 | // | |
224 | // mach-o dylib load command | |
225 | // | |
226 | template <typename P> | |
227 | class macho_dylib_command { | |
228 | public: | |
229 | uint32_t cmd() const INLINE { return E::get32(fields.cmd); } | |
230 | void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } | |
231 | ||
232 | uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } | |
233 | void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } | |
234 | ||
235 | uint32_t name_offset() const INLINE { return E::get32(fields.dylib.name.offset); } | |
236 | void set_name_offset(uint32_t value) INLINE { E::set32(fields.dylib.name.offset, value); } | |
237 | ||
238 | uint32_t timestamp() const INLINE { return E::get32(fields.dylib.timestamp); } | |
239 | void set_timestamp(uint32_t value) INLINE { E::set32(fields.dylib.timestamp, value); } | |
240 | ||
241 | uint32_t current_version() const INLINE { return E::get32(fields.dylib.current_version); } | |
242 | void set_current_version(uint32_t value) INLINE { E::set32(fields.dylib.current_version, value); } | |
243 | ||
244 | uint32_t compatibility_version() const INLINE { return E::get32(fields.dylib.compatibility_version); } | |
245 | void set_compatibility_version(uint32_t value) INLINE { E::set32(fields.dylib.compatibility_version, value); } | |
246 | ||
247 | const char* name() const INLINE { return (const char*)&fields + name_offset(); } | |
248 | void set_name_offset() INLINE { set_name_offset(sizeof(fields)); } | |
249 | ||
250 | typedef typename P::E E; | |
251 | private: | |
252 | dylib_command fields; | |
253 | }; | |
254 | ||
255 | ||
256 | // | |
257 | // mach-o dylinker load command | |
258 | // | |
259 | template <typename P> | |
260 | class macho_dylinker_command { | |
261 | public: | |
262 | uint32_t cmd() const INLINE { return E::get32(fields.cmd); } | |
263 | void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } | |
264 | ||
265 | uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } | |
266 | void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } | |
267 | ||
268 | uint32_t name_offset() const INLINE { return E::get32(fields.name.offset); } | |
269 | void set_name_offset(uint32_t value) INLINE { E::set32(fields.name.offset, value); } | |
270 | ||
271 | const char* name() const INLINE { return (const char*)&fields + name_offset(); } | |
272 | void set_name_offset() INLINE { set_name_offset(sizeof(fields)); } | |
273 | ||
274 | typedef typename P::E E; | |
275 | private: | |
276 | dylinker_command fields; | |
277 | }; | |
278 | ||
279 | ||
280 | // | |
281 | // mach-o sub_framework load command | |
282 | // | |
283 | template <typename P> | |
284 | class macho_sub_framework_command { | |
285 | public: | |
286 | uint32_t cmd() const INLINE { return E::get32(fields.cmd); } | |
287 | void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } | |
288 | ||
289 | uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } | |
290 | void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } | |
291 | ||
292 | uint32_t umbrella_offset() const INLINE { return E::get32(fields.umbrella.offset); } | |
293 | void set_umbrella_offset(uint32_t value) INLINE { E::set32(fields.umbrella.offset, value); } | |
294 | ||
295 | const char* umbrella() const INLINE { return (const char*)&fields + umbrella_offset(); } | |
296 | void set_umbrella_offset() INLINE { set_umbrella_offset(sizeof(fields)); } | |
297 | ||
298 | typedef typename P::E E; | |
299 | private: | |
300 | sub_framework_command fields; | |
301 | }; | |
302 | ||
303 | ||
304 | // | |
305 | // mach-o sub_client load command | |
306 | // | |
307 | template <typename P> | |
308 | class macho_sub_client_command { | |
309 | public: | |
310 | uint32_t cmd() const INLINE { return E::get32(fields.cmd); } | |
311 | void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } | |
312 | ||
313 | uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } | |
314 | void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } | |
315 | ||
316 | uint32_t client_offset() const INLINE { return E::get32(fields.client.offset); } | |
317 | void set_client_offset(uint32_t value) INLINE { E::set32(fields.client.offset, value); } | |
318 | ||
319 | const char* client() const INLINE { return (const char*)&fields + client_offset(); } | |
320 | void set_client_offset() INLINE { set_client_offset(sizeof(fields)); } | |
321 | ||
322 | typedef typename P::E E; | |
323 | private: | |
324 | sub_client_command fields; | |
325 | }; | |
326 | ||
327 | ||
328 | // | |
329 | // mach-o sub_umbrella load command | |
330 | // | |
331 | template <typename P> | |
332 | class macho_sub_umbrella_command { | |
333 | public: | |
334 | uint32_t cmd() const INLINE { return E::get32(fields.cmd); } | |
335 | void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } | |
336 | ||
337 | uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } | |
338 | void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } | |
339 | ||
340 | uint32_t sub_umbrella_offset() const INLINE { return E::get32(fields.sub_umbrella.offset); } | |
341 | void set_sub_umbrella_offset(uint32_t value) INLINE { E::set32(fields.sub_umbrella.offset, value); } | |
342 | ||
343 | const char* sub_umbrella() const INLINE { return (const char*)&fields + sub_umbrella_offset(); } | |
344 | void set_sub_umbrella_offset() INLINE { set_sub_umbrella_offset(sizeof(fields)); } | |
345 | ||
346 | typedef typename P::E E; | |
347 | private: | |
348 | sub_umbrella_command fields; | |
349 | }; | |
350 | ||
351 | ||
352 | // | |
353 | // mach-o sub_library load command | |
354 | // | |
355 | template <typename P> | |
356 | class macho_sub_library_command { | |
357 | public: | |
358 | uint32_t cmd() const INLINE { return E::get32(fields.cmd); } | |
359 | void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } | |
360 | ||
361 | uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } | |
362 | void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } | |
363 | ||
364 | uint32_t sub_library_offset() const INLINE { return E::get32(fields.sub_library.offset); } | |
365 | void set_sub_library_offset(uint32_t value) INLINE { E::set32(fields.sub_library.offset, value); } | |
366 | ||
367 | const char* sub_library() const INLINE { return (const char*)&fields + sub_library_offset(); } | |
368 | void set_sub_library_offset() INLINE { set_sub_library_offset(sizeof(fields)); } | |
369 | ||
370 | typedef typename P::E E; | |
371 | private: | |
372 | sub_library_command fields; | |
373 | }; | |
374 | ||
375 | ||
376 | // | |
377 | // mach-o uuid load command | |
378 | // | |
379 | template <typename P> | |
380 | class macho_uuid_command { | |
381 | public: | |
382 | uint32_t cmd() const INLINE { return E::get32(fields.cmd); } | |
383 | void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } | |
384 | ||
385 | uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } | |
386 | void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } | |
387 | ||
388 | const uint8_t* uuid() const INLINE { return fields.uuid; } | |
389 | void set_uuid(uint8_t uuid[16]) INLINE { memcpy(&fields.uuid, uuid, 16); } | |
390 | ||
391 | typedef typename P::E E; | |
392 | private: | |
393 | uuid_command fields; | |
394 | }; | |
395 | ||
396 | ||
397 | // | |
398 | // mach-o routines load command | |
399 | // | |
400 | template <typename P> struct macho_routines_content {}; | |
401 | template <> struct macho_routines_content<Pointer32<BigEndian> > { routines_command fields; enum { CMD = LC_ROUTINES }; }; | |
402 | template <> struct macho_routines_content<Pointer64<BigEndian> > { routines_command_64 fields; enum { CMD = LC_ROUTINES_64 }; }; | |
403 | template <> struct macho_routines_content<Pointer32<LittleEndian> > { routines_command fields; enum { CMD = LC_ROUTINES }; }; | |
404 | template <> struct macho_routines_content<Pointer64<LittleEndian> > { routines_command_64 fields; enum { CMD = LC_ROUTINES_64 }; }; | |
405 | ||
406 | template <typename P> | |
407 | class macho_routines_command { | |
408 | public: | |
409 | uint32_t cmd() const INLINE { return E::get32(routines.fields.cmd); } | |
410 | void set_cmd(uint32_t value) INLINE { E::set32(routines.fields.cmd, value); } | |
411 | ||
412 | uint32_t cmdsize() const INLINE { return E::get32(routines.fields.cmdsize); } | |
413 | void set_cmdsize(uint32_t value) INLINE { E::set32(routines.fields.cmdsize, value); } | |
414 | ||
415 | uint64_t init_address() const INLINE { return P::getP(routines.fields.init_address); } | |
416 | void set_init_address(uint64_t value) INLINE { P::setP(routines.fields.init_address, value); } | |
417 | ||
418 | uint64_t init_module() const INLINE { return P::getP(routines.fields.init_module); } | |
419 | void set_init_module(uint64_t value) INLINE { P::setP(routines.fields.init_module, value); } | |
420 | ||
421 | uint64_t reserved1() const INLINE { return P::getP(routines.fields.reserved1); } | |
422 | void set_reserved1(uint64_t value) INLINE { P::setP(routines.fields.reserved1, value); } | |
423 | ||
424 | uint64_t reserved2() const INLINE { return P::getP(routines.fields.reserved2); } | |
425 | void set_reserved2(uint64_t value) INLINE { P::setP(routines.fields.reserved2, value); } | |
426 | ||
427 | uint64_t reserved3() const INLINE { return P::getP(routines.fields.reserved3); } | |
428 | void set_reserved3(uint64_t value) INLINE { P::setP(routines.fields.reserved3, value); } | |
429 | ||
430 | uint64_t reserved4() const INLINE { return P::getP(routines.fields.reserved4); } | |
431 | void set_reserved4(uint64_t value) INLINE { P::setP(routines.fields.reserved4, value); } | |
432 | ||
433 | uint64_t reserved5() const INLINE { return P::getP(routines.fields.reserved5); } | |
434 | void set_reserved5(uint64_t value) INLINE { P::setP(routines.fields.reserved5, value); } | |
435 | ||
436 | uint64_t reserved6() const INLINE { return P::getP(routines.fields.reserved6); } | |
437 | void set_reserved6(uint64_t value) INLINE { P::setP(routines.fields.reserved6, value); } | |
438 | ||
439 | typedef typename P::E E; | |
440 | enum { | |
441 | CMD = macho_routines_content<P>::CMD | |
442 | }; | |
443 | private: | |
444 | macho_routines_content<P> routines; | |
445 | }; | |
446 | ||
447 | ||
448 | // | |
449 | // mach-o symbol table load command | |
450 | // | |
451 | template <typename P> | |
452 | class macho_symtab_command { | |
453 | public: | |
454 | uint32_t cmd() const INLINE { return E::get32(fields.cmd); } | |
455 | void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } | |
456 | ||
457 | uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } | |
458 | void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } | |
459 | ||
460 | uint32_t symoff() const INLINE { return E::get32(fields.symoff); } | |
461 | void set_symoff(uint32_t value) INLINE { E::set32(fields.symoff, value); } | |
462 | ||
463 | uint32_t nsyms() const INLINE { return E::get32(fields.nsyms); } | |
464 | void set_nsyms(uint32_t value) INLINE { E::set32(fields.nsyms, value); } | |
465 | ||
466 | uint32_t stroff() const INLINE { return E::get32(fields.stroff); } | |
467 | void set_stroff(uint32_t value) INLINE { E::set32(fields.stroff, value); } | |
468 | ||
469 | uint32_t strsize() const INLINE { return E::get32(fields.strsize); } | |
470 | void set_strsize(uint32_t value) INLINE { E::set32(fields.strsize, value); } | |
471 | ||
472 | ||
473 | typedef typename P::E E; | |
474 | private: | |
475 | symtab_command fields; | |
476 | }; | |
477 | ||
478 | ||
479 | // | |
480 | // mach-o dynamic symbol table load command | |
481 | // | |
482 | template <typename P> | |
483 | class macho_dysymtab_command { | |
484 | public: | |
485 | uint32_t cmd() const INLINE { return E::get32(fields.cmd); } | |
486 | void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } | |
487 | ||
488 | uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } | |
489 | void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } | |
490 | ||
491 | uint32_t ilocalsym() const INLINE { return E::get32(fields.ilocalsym); } | |
492 | void set_ilocalsym(uint32_t value) INLINE { E::set32(fields.ilocalsym, value); } | |
493 | ||
494 | uint32_t nlocalsym() const INLINE { return E::get32(fields.nlocalsym); } | |
495 | void set_nlocalsym(uint32_t value) INLINE { E::set32(fields.nlocalsym, value); } | |
496 | ||
497 | uint32_t iextdefsym() const INLINE { return E::get32(fields.iextdefsym); } | |
498 | void set_iextdefsym(uint32_t value) INLINE { E::set32(fields.iextdefsym, value); } | |
499 | ||
500 | uint32_t nextdefsym() const INLINE { return E::get32(fields.nextdefsym); } | |
501 | void set_nextdefsym(uint32_t value) INLINE { E::set32(fields.nextdefsym, value); } | |
502 | ||
503 | uint32_t iundefsym() const INLINE { return E::get32(fields.iundefsym); } | |
504 | void set_iundefsym(uint32_t value) INLINE { E::set32(fields.iundefsym, value); } | |
505 | ||
506 | uint32_t nundefsym() const INLINE { return E::get32(fields.nundefsym); } | |
507 | void set_nundefsym(uint32_t value) INLINE { E::set32(fields.nundefsym, value); } | |
508 | ||
509 | uint32_t tocoff() const INLINE { return E::get32(fields.tocoff); } | |
510 | void set_tocoff(uint32_t value) INLINE { E::set32(fields.tocoff, value); } | |
511 | ||
512 | uint32_t ntoc() const INLINE { return E::get32(fields.ntoc); } | |
513 | void set_ntoc(uint32_t value) INLINE { E::set32(fields.ntoc, value); } | |
514 | ||
515 | uint32_t modtaboff() const INLINE { return E::get32(fields.modtaboff); } | |
516 | void set_modtaboff(uint32_t value) INLINE { E::set32(fields.modtaboff, value); } | |
517 | ||
518 | uint32_t nmodtab() const INLINE { return E::get32(fields.nmodtab); } | |
519 | void set_nmodtab(uint32_t value) INLINE { E::set32(fields.nmodtab, value); } | |
520 | ||
521 | uint32_t extrefsymoff() const INLINE { return E::get32(fields.extrefsymoff); } | |
522 | void set_extrefsymoff(uint32_t value) INLINE { E::set32(fields.extrefsymoff, value); } | |
523 | ||
524 | uint32_t nextrefsyms() const INLINE { return E::get32(fields.nextrefsyms); } | |
525 | void set_nextrefsyms(uint32_t value) INLINE { E::set32(fields.nextrefsyms, value); } | |
526 | ||
527 | uint32_t indirectsymoff() const INLINE { return E::get32(fields.indirectsymoff); } | |
528 | void set_indirectsymoff(uint32_t value) INLINE { E::set32(fields.indirectsymoff, value); } | |
529 | ||
530 | uint32_t nindirectsyms() const INLINE { return E::get32(fields.nindirectsyms); } | |
531 | void set_nindirectsyms(uint32_t value) INLINE { E::set32(fields.nindirectsyms, value); } | |
532 | ||
533 | uint32_t extreloff() const INLINE { return E::get32(fields.extreloff); } | |
534 | void set_extreloff(uint32_t value) INLINE { E::set32(fields.extreloff, value); } | |
535 | ||
536 | uint32_t nextrel() const INLINE { return E::get32(fields.nextrel); } | |
537 | void set_nextrel(uint32_t value) INLINE { E::set32(fields.nextrel, value); } | |
538 | ||
539 | uint32_t locreloff() const INLINE { return E::get32(fields.locreloff); } | |
540 | void set_locreloff(uint32_t value) INLINE { E::set32(fields.locreloff, value); } | |
541 | ||
542 | uint32_t nlocrel() const INLINE { return E::get32(fields.nlocrel); } | |
543 | void set_nlocrel(uint32_t value) INLINE { E::set32(fields.nlocrel, value); } | |
544 | ||
545 | typedef typename P::E E; | |
546 | private: | |
547 | dysymtab_command fields; | |
548 | }; | |
549 | ||
550 | ||
a61fdf0a A |
551 | |
552 | ||
553 | // | |
554 | // mach-o module table entry (for compatibility with old ld/dyld) | |
555 | // | |
556 | template <typename P> struct macho_dylib_module_content {}; | |
557 | template <> struct macho_dylib_module_content<Pointer32<BigEndian> > { struct dylib_module fields; }; | |
558 | template <> struct macho_dylib_module_content<Pointer32<LittleEndian> > { struct dylib_module fields; }; | |
559 | template <> struct macho_dylib_module_content<Pointer64<BigEndian> > { struct dylib_module_64 fields; }; | |
560 | template <> struct macho_dylib_module_content<Pointer64<LittleEndian> > { struct dylib_module_64 fields; }; | |
561 | ||
562 | template <typename P> | |
563 | class macho_dylib_module { | |
564 | public: | |
565 | uint32_t module_name() const INLINE { return E::get32(module.fields.module_name); } | |
566 | void set_module_name(uint32_t value) INLINE { E::set32(module.fields.module_name, value); } | |
567 | ||
568 | uint32_t iextdefsym() const INLINE { return E::get32(module.fields.iextdefsym); } | |
569 | void set_iextdefsym(uint32_t value) INLINE { E::set32(module.fields.iextdefsym, value); } | |
570 | ||
571 | uint32_t nextdefsym() const INLINE { return E::get32(module.fields.nextdefsym); } | |
572 | void set_nextdefsym(uint32_t value) INLINE { E::set32(module.fields.nextdefsym, value); } | |
573 | ||
574 | uint32_t irefsym() const INLINE { return E::get32(module.fields.irefsym); } | |
575 | void set_irefsym(uint32_t value) INLINE { E::set32(module.fields.irefsym, value); } | |
576 | ||
577 | uint32_t nrefsym() const INLINE { return E::get32(module.fields.nrefsym); } | |
578 | void set_nrefsym(uint32_t value) INLINE { E::set32(module.fields.nrefsym, value); } | |
579 | ||
580 | uint32_t ilocalsym() const INLINE { return E::get32(module.fields.ilocalsym); } | |
581 | void set_ilocalsym(uint32_t value) INLINE { E::set32(module.fields.ilocalsym, value); } | |
582 | ||
583 | uint32_t nlocalsym() const INLINE { return E::get32(module.fields.nlocalsym); } | |
584 | void set_nlocalsym(uint32_t value) INLINE { E::set32(module.fields.nlocalsym, value); } | |
585 | ||
586 | uint32_t iextrel() const INLINE { return E::get32(module.fields.iextrel); } | |
587 | void set_iextrel(uint32_t value) INLINE { E::set32(module.fields.iextrel, value); } | |
588 | ||
589 | uint32_t nextrel() const INLINE { return E::get32(module.fields.nextrel); } | |
590 | void set_nextrel(uint32_t value) INLINE { E::set32(module.fields.nextrel, value); } | |
591 | ||
592 | uint16_t iinit() const INLINE { return E::get32(module.fields.iinit_iterm) & 0xFFFF; } | |
593 | uint16_t iterm() const INLINE { return E::get32(module.fields.iinit_iterm) > 16; } | |
594 | void set_iinit_iterm(uint16_t init, uint16_t term) INLINE { E::set32(module.fields.iinit_iterm, (term<<16) | (init &0xFFFF)); } | |
595 | ||
596 | uint16_t ninit() const INLINE { return E::get32(module.fields.ninit_nterm) & 0xFFFF; } | |
597 | uint16_t nterm() const INLINE { return E::get32(module.fields.ninit_nterm) > 16; } | |
598 | void set_ninit_nterm(uint16_t init, uint16_t term) INLINE { E::set32(module.fields.ninit_nterm, (term<<16) | (init &0xFFFF)); } | |
599 | ||
600 | uint64_t objc_module_info_addr() const INLINE { return P::getP(module.fields.objc_module_info_addr); } | |
601 | void set_objc_module_info_addr(uint64_t value) INLINE { P::setP(module.fields.objc_module_info_addr, value); } | |
602 | ||
603 | uint32_t objc_module_info_size() const INLINE { return E::get32(module.fields.objc_module_info_size); } | |
604 | void set_objc_module_info_size(uint32_t value) INLINE { E::set32(module.fields.objc_module_info_size, value); } | |
605 | ||
606 | ||
607 | typedef typename P::E E; | |
608 | private: | |
609 | macho_dylib_module_content<P> module; | |
610 | }; | |
611 | ||
612 | ||
613 | // | |
614 | // mach-o dylib_reference entry | |
615 | // | |
616 | template <typename P> | |
617 | class macho_dylib_reference { | |
618 | public: | |
619 | uint32_t isym() const INLINE { return E::getBits(fields, 0, 24); } | |
620 | void set_isym(uint32_t value) INLINE { E::setBits(fields, value, 0, 24); } | |
621 | ||
622 | uint8_t flags() const INLINE { return E::getBits(fields, 24, 8); } | |
623 | void set_flags(uint8_t value) INLINE { E::setBits(fields, value, 24, 8); } | |
624 | ||
625 | typedef typename P::E E; | |
626 | private: | |
627 | uint32_t fields; | |
628 | }; | |
629 | ||
630 | ||
631 | ||
632 | // | |
633 | // mach-o two-level hints load command | |
634 | // | |
635 | template <typename P> | |
636 | class macho_dylib_table_of_contents { | |
637 | public: | |
638 | uint32_t symbol_index() const INLINE { return E::get32(fields.symbol_index); } | |
639 | void set_symbol_index(uint32_t value) INLINE { E::set32(fields.symbol_index, value); } | |
640 | ||
641 | uint32_t module_index() const INLINE { return E::get32(fields.module_index); } | |
642 | void set_module_index(uint32_t value) INLINE { E::set32(fields.module_index, value); } | |
643 | ||
644 | typedef typename P::E E; | |
645 | private: | |
646 | dylib_table_of_contents fields; | |
647 | }; | |
648 | ||
649 | ||
650 | ||
d696c285 A |
651 | // |
652 | // mach-o two-level hints load command | |
653 | // | |
654 | template <typename P> | |
655 | class macho_twolevel_hints_command { | |
656 | public: | |
657 | uint32_t cmd() const INLINE { return E::get32(fields.cmd); } | |
658 | void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } | |
659 | ||
660 | uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } | |
661 | void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } | |
662 | ||
663 | uint32_t offset() const INLINE { return E::get32(fields.offset); } | |
664 | void set_offset(uint32_t value) INLINE { E::set32(fields.offset, value); } | |
665 | ||
666 | uint32_t nhints() const INLINE { return E::get32(fields.nhints); } | |
667 | void set_nhints(uint32_t value) INLINE { E::set32(fields.nhints, value); } | |
668 | ||
669 | typedef typename P::E E; | |
670 | private: | |
671 | twolevel_hints_command fields; | |
672 | }; | |
673 | ||
674 | ||
675 | // | |
676 | // mach-o threads load command | |
677 | // | |
678 | template <typename P> | |
679 | class macho_thread_command { | |
680 | public: | |
681 | uint32_t cmd() const INLINE { return E::get32(fields.cmd); } | |
682 | void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } | |
683 | ||
684 | uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } | |
685 | void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } | |
686 | ||
687 | uint32_t flavor() const INLINE { return E::get32(fields_flavor); } | |
688 | void set_flavor(uint32_t value) INLINE { E::set32(fields_flavor, value); } | |
689 | ||
690 | uint32_t count() const INLINE { return E::get32(fields_count); } | |
691 | void set_count(uint32_t value) INLINE { E::set32(fields_count, value); } | |
692 | ||
693 | uint64_t thread_register(uint32_t index) const INLINE { return P::getP(thread_registers[index]); } | |
694 | void set_thread_register(uint32_t index, uint64_t value) INLINE { P::setP(thread_registers[index], value); } | |
695 | ||
696 | typedef typename P::E E; | |
697 | typedef typename P::uint_t pint_t; | |
698 | private: | |
699 | struct thread_command fields; | |
700 | uint32_t fields_flavor; | |
701 | uint32_t fields_count; | |
702 | pint_t thread_registers[1]; | |
703 | }; | |
704 | ||
705 | ||
a61fdf0a A |
706 | // |
707 | // mach-o misc data | |
708 | // | |
709 | template <typename P> | |
710 | class macho_linkedit_data_command { | |
711 | public: | |
712 | uint32_t cmd() const INLINE { return E::get32(fields.cmd); } | |
713 | void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } | |
714 | ||
715 | uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } | |
716 | void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } | |
717 | ||
718 | uint32_t dataoff() const INLINE { return E::get32(fields.dataoff); } | |
719 | void set_dataoff(uint32_t value) INLINE { E::set32(fields.dataoff, value); } | |
720 | ||
721 | uint32_t datasize() const INLINE { return E::get32(fields.datasize); } | |
722 | void set_datasize(uint32_t value)INLINE { E::set32(fields.datasize, value); } | |
723 | ||
724 | ||
725 | typedef typename P::E E; | |
726 | private: | |
727 | linkedit_data_command fields; | |
728 | }; | |
729 | ||
730 | ||
731 | // | |
732 | // mach-o rpath | |
733 | // | |
734 | template <typename P> | |
735 | class macho_rpath_command { | |
736 | public: | |
737 | uint32_t cmd() const INLINE { return E::get32(fields.cmd); } | |
738 | void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } | |
739 | ||
740 | uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } | |
741 | void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } | |
742 | ||
743 | uint32_t path_offset() const INLINE { return E::get32(fields.path.offset); } | |
744 | void set_path_offset(uint32_t value) INLINE { E::set32(fields.path.offset, value); } | |
745 | ||
746 | const char* path() const INLINE { return (const char*)&fields + path_offset(); } | |
747 | void set_path_offset() INLINE { set_path_offset(sizeof(fields)); } | |
748 | ||
749 | ||
750 | typedef typename P::E E; | |
751 | private: | |
752 | rpath_command fields; | |
753 | }; | |
754 | ||
d696c285 A |
755 | |
756 | ||
757 | // | |
758 | // mach-o symbol table entry | |
759 | // | |
760 | template <typename P> struct macho_nlist_content {}; | |
761 | template <> struct macho_nlist_content<Pointer32<BigEndian> > { struct nlist fields; }; | |
762 | template <> struct macho_nlist_content<Pointer64<BigEndian> > { struct nlist_64 fields; }; | |
763 | template <> struct macho_nlist_content<Pointer32<LittleEndian> > { struct nlist fields; }; | |
764 | template <> struct macho_nlist_content<Pointer64<LittleEndian> > { struct nlist_64 fields; }; | |
765 | ||
766 | template <typename P> | |
767 | class macho_nlist { | |
768 | public: | |
769 | uint32_t n_strx() const INLINE { return E::get32(entry.fields.n_un.n_strx); } | |
770 | void set_n_strx(uint32_t value) INLINE { E::set32((uint32_t&)entry.fields.n_un.n_strx, value); } | |
771 | ||
772 | uint8_t n_type() const INLINE { return entry.fields.n_type; } | |
773 | void set_n_type(uint8_t value) INLINE { entry.fields.n_type = value; } | |
774 | ||
775 | uint8_t n_sect() const INLINE { return entry.fields.n_sect; } | |
776 | void set_n_sect(uint8_t value) INLINE { entry.fields.n_sect = value; } | |
777 | ||
778 | uint16_t n_desc() const INLINE { return E::get16(entry.fields.n_desc); } | |
779 | void set_n_desc(uint16_t value) INLINE { E::set16((uint16_t&)entry.fields.n_desc, value); } | |
780 | ||
781 | uint64_t n_value() const INLINE { return P::getP(entry.fields.n_value); } | |
782 | void set_n_value(uint64_t value) INLINE { P::setP(entry.fields.n_value, value); } | |
783 | ||
784 | typedef typename P::E E; | |
785 | private: | |
786 | macho_nlist_content<P> entry; | |
787 | }; | |
788 | ||
789 | ||
790 | ||
791 | // | |
792 | // mach-o relocation info | |
793 | // | |
794 | template <typename P> | |
795 | class macho_relocation_info { | |
796 | public: | |
797 | uint32_t r_address() const INLINE { return E::get32(address); } | |
798 | void set_r_address(uint32_t value) INLINE { E::set32(address, value); } | |
799 | ||
800 | uint32_t r_symbolnum() const INLINE { return E::getBits(other, 0, 24); } | |
801 | void set_r_symbolnum(uint32_t value) INLINE { E::setBits(other, value, 0, 24); } | |
802 | ||
803 | bool r_pcrel() const INLINE { return E::getBits(other, 24, 1); } | |
804 | void set_r_pcrel(bool value) INLINE { E::setBits(other, value, 24, 1); } | |
805 | ||
806 | uint8_t r_length() const INLINE { return E::getBits(other, 25, 2); } | |
807 | void set_r_length(uint8_t value) INLINE { E::setBits(other, value, 25, 2); } | |
808 | ||
809 | bool r_extern() const INLINE { return E::getBits(other, 27, 1); } | |
810 | void set_r_extern(bool value) INLINE { E::setBits(other, value, 27, 1); } | |
811 | ||
812 | uint8_t r_type() const INLINE { return E::getBits(other, 28, 4); } | |
813 | void set_r_type(uint8_t value) INLINE { E::setBits(other, value, 28, 4); } | |
814 | ||
815 | void set_r_length() INLINE { set_r_length((sizeof(typename P::uint_t)==8) ? 3 : 2); } | |
816 | ||
817 | typedef typename P::E E; | |
818 | private: | |
819 | uint32_t address; | |
820 | uint32_t other; | |
821 | }; | |
822 | ||
823 | ||
824 | // | |
825 | // mach-o scattered relocation info | |
826 | // The bit fields are always in big-endian order (see mach-o/reloc.h) | |
827 | // | |
828 | template <typename P> | |
829 | class macho_scattered_relocation_info { | |
830 | public: | |
831 | bool r_scattered() const INLINE { return BigEndian::getBitsRaw(E::get32(other), 0, 1); } | |
832 | void set_r_scattered(bool x) INLINE { uint32_t temp = E::get32(other); BigEndian::setBitsRaw(temp, x, 0, 1); E::set32(other, temp); } | |
833 | ||
834 | bool r_pcrel() const INLINE { return BigEndian::getBitsRaw(E::get32(other), 1, 1); } | |
835 | void set_r_pcrel(bool x) INLINE { uint32_t temp = E::get32(other); BigEndian::setBitsRaw(temp, x, 1, 1); E::set32(other, temp); } | |
836 | ||
837 | uint8_t r_length() const INLINE { return BigEndian::getBitsRaw(E::get32(other), 2, 2); } | |
838 | void set_r_length(uint8_t x) INLINE { uint32_t temp = E::get32(other); BigEndian::setBitsRaw(temp, x, 2, 2); E::set32(other, temp); } | |
839 | ||
840 | uint8_t r_type() const INLINE { return BigEndian::getBitsRaw(E::get32(other), 4, 4); } | |
841 | void set_r_type(uint8_t x) INLINE { uint32_t temp = E::get32(other); BigEndian::setBitsRaw(temp, x, 4, 4); E::set32(other, temp); } | |
842 | ||
843 | uint32_t r_address() const INLINE { return BigEndian::getBitsRaw(E::get32(other), 8, 24); } | |
a61fdf0a A |
844 | void set_r_address(uint32_t x) { if ( x > 0x00FFFFFF ) throw "scattered reloc r_address too large"; |
845 | uint32_t temp = E::get32(other); BigEndian::setBitsRaw(temp, x, 8, 24); E::set32(other, temp); } | |
d696c285 A |
846 | |
847 | uint32_t r_value() const INLINE { return E::get32(value); } | |
848 | void set_r_value(uint32_t x) INLINE { E::set32(value, x); } | |
849 | ||
850 | uint32_t r_other() const INLINE { return other; } | |
851 | ||
a61fdf0a A |
852 | void set_r_length() INLINE { set_r_length((sizeof(typename P::uint_t)==8) ? 3 : 2); } |
853 | ||
d696c285 A |
854 | typedef typename P::E E; |
855 | private: | |
856 | uint32_t other; | |
857 | uint32_t value; | |
858 | }; | |
859 | ||
860 | ||
861 | ||
862 | ||
863 | ||
864 | ||
865 | #endif // __MACH_O_FILE_ABSTRACTION__ | |
866 | ||
867 |