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