]> gitweb.factorcode.org Git - factor.git/blob - extra/macho/macho.factor
use reject instead of [ ... not ] filter.
[factor.git] / extra / macho / macho.factor
1 ! Copyright (C) 2010 Erik Charlebois.
2 ! See http:// factorcode.org/license.txt for BSD license.
3 USING: accessors alien alien.c-types alien.data alien.strings
4 alien.syntax classes classes.struct combinators
5 combinators.short-circuit io.encodings.ascii io.encodings.string
6 kernel literals make math sequences specialized-arrays typed
7 fry io.mmap formatting locals splitting io.binary arrays ;
8 FROM: alien.c-types => short ;
9 IN: macho
10
11 ! FFI data
12 TYPEDEF: int       integer_t
13 TYPEDEF: int       vm_prot_t
14 TYPEDEF: integer_t cpu_type_t
15 TYPEDEF: integer_t cpu_subtype_t
16 TYPEDEF: integer_t cpu_threadtype_t
17
18 CONSTANT: VM_PROT_NONE        0x00
19 CONSTANT: VM_PROT_READ        0x01
20 CONSTANT: VM_PROT_WRITE       0x02
21 CONSTANT: VM_PROT_EXECUTE     0x04
22 CONSTANT: VM_PROT_DEFAULT     0x03
23 CONSTANT: VM_PROT_ALL         0x07
24 CONSTANT: VM_PROT_NO_CHANGE   0x08
25 CONSTANT: VM_PROT_COPY        0x10
26 CONSTANT: VM_PROT_WANTS_COPY  0x10
27
28 ! loader.h
29 STRUCT: mach_header
30     { magic         uint          }
31     { cputype       cpu_type_t    }
32     { cpusubtype    cpu_subtype_t }
33     { filetype      uint          }
34     { ncmds         uint          }
35     { sizeofcmds    uint          }
36     { flags         uint          } ;
37
38 CONSTANT: MH_MAGIC    0xfeedface
39 CONSTANT: MH_CIGAM    0xcefaedfe
40
41 STRUCT: mach_header_64
42     { magic         uint          }
43     { cputype       cpu_type_t    }
44     { cpusubtype    cpu_subtype_t }
45     { filetype      uint          }
46     { ncmds         uint          }
47     { sizeofcmds    uint          }
48     { flags         uint          }
49     { reserved      uint          } ;
50
51 CONSTANT: MH_MAGIC_64 0xfeedfacf
52 CONSTANT: MH_CIGAM_64 0xcffaedfe
53
54 CONSTANT: MH_OBJECT       0x1
55 CONSTANT: MH_EXECUTE      0x2
56 CONSTANT: MH_FVMLIB       0x3
57 CONSTANT: MH_CORE         0x4
58 CONSTANT: MH_PRELOAD      0x5
59 CONSTANT: MH_DYLIB        0x6
60 CONSTANT: MH_DYLINKER     0x7
61 CONSTANT: MH_BUNDLE       0x8
62 CONSTANT: MH_DYLIB_STUB   0x9
63 CONSTANT: MH_DSYM         0xa
64 CONSTANT: MH_KEXT_BUNDLE  0xb
65
66 CONSTANT: MH_NOUNDEFS                0x1
67 CONSTANT: MH_INCRLINK                0x2
68 CONSTANT: MH_DYLDLINK                0x4
69 CONSTANT: MH_BINDATLOAD              0x8
70 CONSTANT: MH_PREBOUND                0x10
71 CONSTANT: MH_SPLIT_SEGS              0x20
72 CONSTANT: MH_LAZY_INIT               0x40
73 CONSTANT: MH_TWOLEVEL                0x80
74 CONSTANT: MH_FORCE_FLAT              0x100
75 CONSTANT: MH_NOMULTIDEFS             0x200
76 CONSTANT: MH_NOFIXPREBINDING         0x400
77 CONSTANT: MH_PREBINDABLE             0x800
78 CONSTANT: MH_ALLMODSBOUND            0x1000
79 CONSTANT: MH_SUBSECTIONS_VIA_SYMBOLS 0x2000
80 CONSTANT: MH_CANONICAL               0x4000
81 CONSTANT: MH_WEAK_DEFINES            0x8000
82 CONSTANT: MH_BINDS_TO_WEAK           0x10000
83 CONSTANT: MH_ALLOW_STACK_EXECUTION   0x20000
84 CONSTANT: MH_DEAD_STRIPPABLE_DYLIB   0x400000
85 CONSTANT: MH_ROOT_SAFE               0x40000
86 CONSTANT: MH_SETUID_SAFE             0x80000
87 CONSTANT: MH_NO_REEXPORTED_DYLIBS    0x100000
88 CONSTANT: MH_PIE                     0x200000
89
90 STRUCT: load_command
91     { cmd     uint }
92     { cmdsize uint } ;
93
94 CONSTANT: LC_REQ_DYLD 0x80000000
95
96 CONSTANT: LC_SEGMENT            0x1
97 CONSTANT: LC_SYMTAB             0x2
98 CONSTANT: LC_SYMSEG             0x3
99 CONSTANT: LC_THREAD             0x4
100 CONSTANT: LC_UNIXTHREAD         0x5
101 CONSTANT: LC_LOADFVMLIB         0x6
102 CONSTANT: LC_IDFVMLIB           0x7
103 CONSTANT: LC_IDENT              0x8
104 CONSTANT: LC_FVMFILE            0x9
105 CONSTANT: LC_PREPAGE            0xa
106 CONSTANT: LC_DYSYMTAB           0xb
107 CONSTANT: LC_LOAD_DYLIB         0xc
108 CONSTANT: LC_ID_DYLIB           0xd
109 CONSTANT: LC_LOAD_DYLINKER      0xe
110 CONSTANT: LC_ID_DYLINKER        0xf
111 CONSTANT: LC_PREBOUND_DYLIB     0x10
112 CONSTANT: LC_ROUTINES           0x11
113 CONSTANT: LC_SUB_FRAMEWORK      0x12
114 CONSTANT: LC_SUB_UMBRELLA       0x13
115 CONSTANT: LC_SUB_CLIENT         0x14
116 CONSTANT: LC_SUB_LIBRARY        0x15
117 CONSTANT: LC_TWOLEVEL_HINTS     0x16
118 CONSTANT: LC_PREBIND_CKSUM      0x17
119 CONSTANT: LC_LOAD_WEAK_DYLIB    0x80000018
120 CONSTANT: LC_SEGMENT_64         0x19
121 CONSTANT: LC_ROUTINES_64        0x1a
122 CONSTANT: LC_UUID               0x1b
123 CONSTANT: LC_RPATH              0x8000001c
124 CONSTANT: LC_CODE_SIGNATURE     0x1d
125 CONSTANT: LC_SEGMENT_SPLIT_INFO 0x1e
126 CONSTANT: LC_REEXPORT_DYLIB     0x8000001f
127 CONSTANT: LC_LAZY_LOAD_DYLIB    0x20
128 CONSTANT: LC_ENCRYPTION_INFO    0x21
129 CONSTANT: LC_DYLD_INFO          0x22
130 CONSTANT: LC_DYLD_INFO_ONLY     0x80000022
131
132 UNION-STRUCT: lc_str
133     { offset    uint     }
134     { ptr       char*    } ;
135
136 STRUCT: segment_command
137     { cmd            uint      }
138     { cmdsize        uint      }
139     { segname        char[16]  }
140     { vmaddr         uint      }
141     { vmsize         uint      }
142     { fileoff        uint      }
143     { filesize       uint      }
144     { maxprot        vm_prot_t }
145     { initprot       vm_prot_t }
146     { nsects         uint      }
147     { flags          uint      } ;
148
149 STRUCT: segment_command_64
150     { cmd            uint       }
151     { cmdsize        uint       }
152     { segname        char[16]   }
153     { vmaddr         ulonglong  }
154     { vmsize         ulonglong  }
155     { fileoff        ulonglong  }
156     { filesize       ulonglong  }
157     { maxprot        vm_prot_t  }
158     { initprot       vm_prot_t  }
159     { nsects         uint       }
160     { flags          uint       } ;
161     
162 CONSTANT: SG_HIGHVM               0x1
163 CONSTANT: SG_FVMLIB               0x2
164 CONSTANT: SG_NORELOC              0x4
165 CONSTANT: SG_PROTECTED_VERSION_1  0x8
166
167 STRUCT: section
168     { sectname        char[16] }
169     { segname         char[16] }
170     { addr            uint     }
171     { size            uint     }
172     { offset          uint     }
173     { align           uint     }
174     { reloff          uint     }
175     { nreloc          uint     }
176     { flags           uint     }
177     { reserved1       uint     }
178     { reserved2       uint     } ;
179
180 STRUCT: section_64
181     { sectname        char[16]  }
182     { segname         char[16]  }
183     { addr            ulonglong }
184     { size            ulonglong }
185     { offset          uint      }
186     { align           uint      }
187     { reloff          uint      }
188     { nreloc          uint      }
189     { flags           uint      }
190     { reserved1       uint      }
191     { reserved2       uint      }
192     { reserved3       uint      } ;
193
194 CONSTANT: SECTION_TYPE         0x000000ff
195 CONSTANT: SECTION_ATTRIBUTES   0xffffff00
196
197 CONSTANT: S_REGULAR                       0x0
198 CONSTANT: S_ZEROFILL                      0x1
199 CONSTANT: S_CSTRING_LITERALS              0x2
200 CONSTANT: S_4BYTE_LITERALS                0x3
201 CONSTANT: S_8BYTE_LITERALS                0x4
202 CONSTANT: S_LITERAL_POINTERS              0x5
203 CONSTANT: S_NON_LAZY_SYMBOL_POINTERS      0x6
204 CONSTANT: S_LAZY_SYMBOL_POINTERS          0x7
205 CONSTANT: S_SYMBOL_STUBS                  0x8
206 CONSTANT: S_MOD_INIT_FUNC_POINTERS        0x9
207 CONSTANT: S_MOD_TERM_FUNC_POINTERS        0xa
208 CONSTANT: S_COALESCED                     0xb
209 CONSTANT: S_GB_ZEROFILL                   0xc
210 CONSTANT: S_INTERPOSING                   0xd
211 CONSTANT: S_16BYTE_LITERALS               0xe
212 CONSTANT: S_DTRACE_DOF                    0xf
213 CONSTANT: S_LAZY_DYLIB_SYMBOL_POINTERS    0x10
214
215 CONSTANT: SECTION_ATTRIBUTES_USR     0xff000000
216 CONSTANT: S_ATTR_PURE_INSTRUCTIONS   0x80000000
217 CONSTANT: S_ATTR_NO_TOC              0x40000000
218 CONSTANT: S_ATTR_STRIP_STATIC_SYMS   0x20000000
219 CONSTANT: S_ATTR_NO_DEAD_STRIP       0x10000000
220 CONSTANT: S_ATTR_LIVE_SUPPORT        0x08000000
221 CONSTANT: S_ATTR_SELF_MODIFYING_CODE 0x04000000
222 CONSTANT: S_ATTR_DEBUG               0x02000000
223 CONSTANT: SECTION_ATTRIBUTES_SYS     0x00ffff00
224 CONSTANT: S_ATTR_SOME_INSTRUCTIONS   0x00000400
225 CONSTANT: S_ATTR_EXT_RELOC           0x00000200
226 CONSTANT: S_ATTR_LOC_RELOC           0x00000100
227
228 CONSTANT: SEG_PAGEZERO      "__PAGEZERO"
229 CONSTANT: SEG_TEXT          "__TEXT"
230 CONSTANT: SECT_TEXT         "__text"
231 CONSTANT: SECT_FVMLIB_INIT0 "__fvmlib_init0"
232 CONSTANT: SECT_FVMLIB_INIT1 "__fvmlib_init1"
233 CONSTANT: SEG_DATA          "__DATA"
234 CONSTANT: SECT_DATA         "__data"
235 CONSTANT: SECT_BSS          "__bss"
236 CONSTANT: SECT_COMMON       "__common"
237 CONSTANT: SEG_OBJC          "__OBJC"
238 CONSTANT: SECT_OBJC_SYMBOLS "__symbol_table"
239 CONSTANT: SECT_OBJC_MODULES "__module_info"
240 CONSTANT: SECT_OBJC_STRINGS "__selector_strs"
241 CONSTANT: SECT_OBJC_REFS    "__selector_refs"
242 CONSTANT: SEG_ICON          "__ICON"
243 CONSTANT: SECT_ICON_HEADER  "__header"
244 CONSTANT: SECT_ICON_TIFF    "__tiff"
245 CONSTANT: SEG_LINKEDIT      "__LINKEDIT"
246 CONSTANT: SEG_UNIXSTACK     "__UNIXSTACK"
247 CONSTANT: SEG_IMPORT        "__IMPORT"
248
249 STRUCT: fvmlib
250     { name             lc_str   }
251     { minor_version    uint     }
252     { header_addr      uint     } ;
253
254 STRUCT: fvmlib_command
255     { cmd        uint     }
256     { cmdsize    uint     }
257     { fvmlib     fvmlib   } ;
258
259 STRUCT: dylib
260     { name                  lc_str   }
261     { timestamp             uint     }
262     { current_version       uint     }
263     { compatibility_version uint     } ;
264
265 STRUCT: dylib_command
266     { cmd        uint     }
267     { cmdsize    uint     }
268     { dylib      dylib    } ;
269
270 STRUCT: sub_framework_command
271     { cmd         uint     }
272     { cmdsize     uint     }
273     { umbrella    lc_str   } ;
274
275 STRUCT: sub_client_command
276     { cmd        uint     }
277     { cmdsize    uint     }
278     { client     lc_str   } ;
279
280 STRUCT: sub_umbrella_command
281     { cmd             uint     }
282     { cmdsize         uint     }
283     { sub_umbrella    lc_str   } ;
284
285 STRUCT: sub_library_command
286     { cmd            uint     }
287     { cmdsize        uint     }
288     { sub_library    lc_str   } ;
289
290 STRUCT: prebound_dylib_command
291     { cmd               uint     }
292     { cmdsize           uint     }
293     { name              lc_str   }
294     { nmodules          uint     }
295     { linked_modules    lc_str   } ;
296
297 STRUCT: dylinker_command
298     { cmd        uint     }
299     { cmdsize    uint     }
300     { name       lc_str   } ;
301
302 STRUCT: thread_command
303     { cmd        uint }
304     { cmdsize    uint } ;
305
306 STRUCT: routines_command
307     { cmd             uint }
308     { cmdsize         uint }
309     { init_address    uint }
310     { init_module     uint }
311     { reserved1       uint }
312     { reserved2       uint }
313     { reserved3       uint }
314     { reserved4       uint }
315     { reserved5       uint }
316     { reserved6       uint } ;
317
318 STRUCT: routines_command_64
319     { cmd             uint      }
320     { cmdsize         uint      }
321     { init_address    ulonglong }
322     { init_module     ulonglong }
323     { reserved1       ulonglong }
324     { reserved2       ulonglong }
325     { reserved3       ulonglong }
326     { reserved4       ulonglong }
327     { reserved5       ulonglong }
328     { reserved6       ulonglong } ;
329
330 STRUCT: symtab_command
331     { cmd        uint }
332     { cmdsize    uint }
333     { symoff     uint }
334     { nsyms      uint }
335     { stroff     uint }
336     { strsize    uint } ;
337
338 STRUCT: dysymtab_command
339     { cmd            uint }
340     { cmdsize        uint }
341     { ilocalsym      uint }
342     { nlocalsym      uint }
343     { iextdefsym     uint }
344     { nextdefsym     uint }
345     { iundefsym      uint }
346     { nundefsym      uint }
347     { tocoff         uint }
348     { ntoc           uint }
349     { modtaboff      uint }
350     { nmodtab        uint }
351     { extrefsymoff   uint }
352     { nextrefsyms    uint }
353     { indirectsymoff uint }
354     { nindirectsyms  uint }
355     { extreloff      uint }
356     { nextrel        uint }
357     { locreloff      uint }
358     { nlocrel        uint } ;
359
360 CONSTANT: INDIRECT_SYMBOL_LOCAL 0x80000000
361 CONSTANT: INDIRECT_SYMBOL_ABS   0x40000000
362
363 STRUCT: dylib_table_of_contents
364     { symbol_index uint }
365     { module_index uint } ;
366
367 STRUCT: dylib_module
368     { module_name           uint }
369     { iextdefsym            uint }
370     { nextdefsym            uint }
371     { irefsym               uint }
372     { nrefsym               uint }
373     { ilocalsym             uint }
374     { nlocalsym             uint }
375     { iextrel               uint }
376     { nextrel               uint }
377     { iinit_iterm           uint }
378     { ninit_nterm           uint }
379     { objc_module_info_addr uint }
380     { objc_module_info_size uint } ;
381
382 STRUCT: dylib_module_64
383     { module_name           uint      }
384     { iextdefsym            uint      }
385     { nextdefsym            uint      }
386     { irefsym               uint      }
387     { nrefsym               uint      }
388     { ilocalsym             uint      }
389     { nlocalsym             uint      }
390     { iextrel               uint      }
391     { nextrel               uint      }
392     { iinit_iterm           uint      }
393     { ninit_nterm           uint      }
394     { objc_module_info_size uint      }
395     { objc_module_info_addr ulonglong } ;
396
397 STRUCT: dylib_reference
398     { isym_flags uint } ;
399
400 STRUCT: twolevel_hints_command
401     { cmd     uint }
402     { cmdsize uint }
403     { offset  uint }
404     { nhints  uint } ;
405
406 STRUCT: twolevel_hint
407     { isub_image_itoc uint } ;
408
409 STRUCT: prebind_cksum_command
410     { cmd     uint }
411     { cmdsize uint }
412     { cksum   uint } ;
413
414 STRUCT: uuid_command
415     { cmd        uint        }
416     { cmdsize    uint        }
417     { uuid       uchar[16]   } ;
418
419 STRUCT: rpath_command
420     { cmd         uint     }
421     { cmdsize     uint     }
422     { path        lc_str   } ;
423
424 STRUCT: linkedit_data_command
425     { cmd         uint }
426     { cmdsize     uint }
427     { dataoff     uint }
428     { datasize    uint } ;
429
430 STRUCT: encryption_info_command
431     { cmd       uint }
432     { cmdsize   uint }
433     { cryptoff  uint }
434     { cryptsize uint }
435     { cryptid   uint } ;
436
437 STRUCT: dyld_info_command
438     { cmd              uint }
439     { cmdsize          uint }
440     { rebase_off       uint }
441     { rebase_size      uint }
442     { bind_off         uint }
443     { bind_size        uint }
444     { weak_bind_off    uint }
445     { weak_bind_size   uint }
446     { lazy_bind_off    uint }
447     { lazy_bind_size   uint }
448     { export_off       uint }
449     { export_size      uint } ;
450
451 CONSTANT: REBASE_TYPE_POINTER                     1
452 CONSTANT: REBASE_TYPE_TEXT_ABSOLUTE32             2
453 CONSTANT: REBASE_TYPE_TEXT_PCREL32                3
454
455 CONSTANT: REBASE_OPCODE_MASK                                  0xF0
456 CONSTANT: REBASE_IMMEDIATE_MASK                               0x0F
457 CONSTANT: REBASE_OPCODE_DONE                                  0x00
458 CONSTANT: REBASE_OPCODE_SET_TYPE_IMM                          0x10
459 CONSTANT: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB           0x20
460 CONSTANT: REBASE_OPCODE_ADD_ADDR_ULEB                         0x30
461 CONSTANT: REBASE_OPCODE_ADD_ADDR_IMM_SCALED                   0x40
462 CONSTANT: REBASE_OPCODE_DO_REBASE_IMM_TIMES                   0x50
463 CONSTANT: REBASE_OPCODE_DO_REBASE_ULEB_TIMES                  0x60
464 CONSTANT: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB               0x70
465 CONSTANT: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB    0x80
466
467 CONSTANT: BIND_TYPE_POINTER                       1
468 CONSTANT: BIND_TYPE_TEXT_ABSOLUTE32               2
469 CONSTANT: BIND_TYPE_TEXT_PCREL32                  3
470
471 CONSTANT: BIND_SPECIAL_DYLIB_SELF                     0
472 CONSTANT: BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE          -1
473 CONSTANT: BIND_SPECIAL_DYLIB_FLAT_LOOKUP              -2
474
475 CONSTANT: BIND_SYMBOL_FLAGS_WEAK_IMPORT                   0x1
476 CONSTANT: BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION           0x8
477
478 CONSTANT: BIND_OPCODE_MASK                                    0xF0
479 CONSTANT: BIND_IMMEDIATE_MASK                                 0x0F
480 CONSTANT: BIND_OPCODE_DONE                                    0x00
481 CONSTANT: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM                   0x10
482 CONSTANT: BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB                  0x20
483 CONSTANT: BIND_OPCODE_SET_DYLIB_SPECIAL_IMM                   0x30
484 CONSTANT: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM           0x40
485 CONSTANT: BIND_OPCODE_SET_TYPE_IMM                            0x50
486 CONSTANT: BIND_OPCODE_SET_ADDEND_SLEB                         0x60
487 CONSTANT: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB             0x70
488 CONSTANT: BIND_OPCODE_ADD_ADDR_ULEB                           0x80
489 CONSTANT: BIND_OPCODE_DO_BIND                                 0x90
490 CONSTANT: BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB                   0xA0
491 CONSTANT: BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED             0xB0
492 CONSTANT: BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB        0xC0
493
494 CONSTANT: EXPORT_SYMBOL_FLAGS_KIND_MASK                   0x03
495 CONSTANT: EXPORT_SYMBOL_FLAGS_KIND_REGULAR                0x00
496 CONSTANT: EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL           0x01
497 CONSTANT: EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION             0x04
498 CONSTANT: EXPORT_SYMBOL_FLAGS_INDIRECT_DEFINITION         0x08
499 CONSTANT: EXPORT_SYMBOL_FLAGS_HAS_SPECIALIZATIONS         0x10
500
501 STRUCT: symseg_command
502     { cmd        uint }
503     { cmdsize    uint }
504     { offset     uint }
505     { size       uint } ;
506
507 STRUCT: ident_command
508     { cmd     uint }
509     { cmdsize uint } ;
510
511 STRUCT: fvmfile_command
512     { cmd            uint     }
513     { cmdsize        uint     }
514     { name           lc_str   }
515     { header_addr    uint     } ;
516
517 ! machine.h
518 CONSTANT: CPU_STATE_MAX       4
519 CONSTANT: CPU_STATE_USER      0
520 CONSTANT: CPU_STATE_SYSTEM    1
521 CONSTANT: CPU_STATE_IDLE      2
522 CONSTANT: CPU_STATE_NICE      3
523
524 CONSTANT: CPU_ARCH_MASK   0xff000000
525 CONSTANT: CPU_ARCH_ABI64  0x01000000
526
527 CONSTANT: CPU_TYPE_ANY            -1
528 CONSTANT: CPU_TYPE_VAX            1
529 CONSTANT: CPU_TYPE_MC680x0        6
530 CONSTANT: CPU_TYPE_X86            7
531 ALIAS: CPU_TYPE_I386              CPU_TYPE_X86
532 CONSTANT: CPU_TYPE_X86_64         flags{ CPU_TYPE_X86 CPU_ARCH_ABI64 }
533 CONSTANT: CPU_TYPE_MC98000        10
534 CONSTANT: CPU_TYPE_HPPA           11
535 CONSTANT: CPU_TYPE_ARM            12
536 CONSTANT: CPU_TYPE_MC88000        13
537 CONSTANT: CPU_TYPE_SPARC          14
538 CONSTANT: CPU_TYPE_I860           15
539 CONSTANT: CPU_TYPE_POWERPC        18
540 CONSTANT: CPU_TYPE_POWERPC64      flags{ CPU_TYPE_POWERPC CPU_ARCH_ABI64 }
541
542 CONSTANT: CPU_SUBTYPE_MASK    0xff000000
543 CONSTANT: CPU_SUBTYPE_LIB64   0x80000000
544
545 CONSTANT: CPU_SUBTYPE_MULTIPLE        -1
546 CONSTANT: CPU_SUBTYPE_LITTLE_ENDIAN   0
547 CONSTANT: CPU_SUBTYPE_BIG_ENDIAN      1
548
549 CONSTANT: CPU_THREADTYPE_NONE     0
550
551 CONSTANT: CPU_SUBTYPE_VAX_ALL 0
552 CONSTANT: CPU_SUBTYPE_VAX780  1
553 CONSTANT: CPU_SUBTYPE_VAX785  2
554 CONSTANT: CPU_SUBTYPE_VAX750  3
555 CONSTANT: CPU_SUBTYPE_VAX730  4
556 CONSTANT: CPU_SUBTYPE_UVAXI   5
557 CONSTANT: CPU_SUBTYPE_UVAXII  6
558 CONSTANT: CPU_SUBTYPE_VAX8200 7
559 CONSTANT: CPU_SUBTYPE_VAX8500 8
560 CONSTANT: CPU_SUBTYPE_VAX8600 9
561 CONSTANT: CPU_SUBTYPE_VAX8650 10
562 CONSTANT: CPU_SUBTYPE_VAX8800 11
563 CONSTANT: CPU_SUBTYPE_UVAXIII 12
564
565 CONSTANT: CPU_SUBTYPE_MC680x0_ALL     1
566 CONSTANT: CPU_SUBTYPE_MC68030     1
567 CONSTANT: CPU_SUBTYPE_MC68040     2
568 CONSTANT: CPU_SUBTYPE_MC68030_ONLY    3
569
570 : CPU_SUBTYPE_INTEL ( f m -- subtype ) 4 shift + ; inline
571
572 CONSTANT: CPU_SUBTYPE_I386_ALL              3
573 CONSTANT: CPU_SUBTYPE_386                   3
574 CONSTANT: CPU_SUBTYPE_486                   4
575 CONSTANT: CPU_SUBTYPE_486SX                 132
576 CONSTANT: CPU_SUBTYPE_586                   5
577 CONSTANT: CPU_SUBTYPE_PENT                  5
578 CONSTANT: CPU_SUBTYPE_PENTPRO               22
579 CONSTANT: CPU_SUBTYPE_PENTII_M3             54
580 CONSTANT: CPU_SUBTYPE_PENTII_M5             86
581 CONSTANT: CPU_SUBTYPE_CELERON               103
582 CONSTANT: CPU_SUBTYPE_CELERON_MOBILE        119
583 CONSTANT: CPU_SUBTYPE_PENTIUM_3             8
584 CONSTANT: CPU_SUBTYPE_PENTIUM_3_M           24
585 CONSTANT: CPU_SUBTYPE_PENTIUM_3_XEON        40
586 CONSTANT: CPU_SUBTYPE_PENTIUM_M             9
587 CONSTANT: CPU_SUBTYPE_PENTIUM_4             10
588 CONSTANT: CPU_SUBTYPE_PENTIUM_4_M           26
589 CONSTANT: CPU_SUBTYPE_ITANIUM               11
590 CONSTANT: CPU_SUBTYPE_ITANIUM_2             27
591 CONSTANT: CPU_SUBTYPE_XEON                  12
592 CONSTANT: CPU_SUBTYPE_XEON_MP               28
593
594 : CPU_SUBTYPE_INTEL_FAMILY ( x -- family ) 15 bitand ; inline
595
596 CONSTANT: CPU_SUBTYPE_INTEL_FAMILY_MAX    15
597
598 : CPU_SUBTYPE_INTEL_MODEL ( x -- model ) -4 shift ; inline
599
600 CONSTANT: CPU_SUBTYPE_INTEL_MODEL_ALL 0
601 CONSTANT: CPU_SUBTYPE_X86_ALL         3
602 CONSTANT: CPU_SUBTYPE_X86_64_ALL      3
603 CONSTANT: CPU_SUBTYPE_X86_ARCH1       4
604 CONSTANT: CPU_THREADTYPE_INTEL_HTT    1
605
606 CONSTANT: CPU_SUBTYPE_MIPS_ALL    0
607 CONSTANT: CPU_SUBTYPE_MIPS_R2300  1
608 CONSTANT: CPU_SUBTYPE_MIPS_R2600  2
609 CONSTANT: CPU_SUBTYPE_MIPS_R2800  3
610 CONSTANT: CPU_SUBTYPE_MIPS_R2000a 4
611 CONSTANT: CPU_SUBTYPE_MIPS_R2000  5
612 CONSTANT: CPU_SUBTYPE_MIPS_R3000a 6
613 CONSTANT: CPU_SUBTYPE_MIPS_R3000  7
614
615 CONSTANT: CPU_SUBTYPE_MC98000_ALL 0
616 CONSTANT: CPU_SUBTYPE_MC98601     1
617
618 CONSTANT: CPU_SUBTYPE_HPPA_ALL        0
619 CONSTANT: CPU_SUBTYPE_HPPA_7100       0
620 CONSTANT: CPU_SUBTYPE_HPPA_7100LC     1
621
622 CONSTANT: CPU_SUBTYPE_MC88000_ALL 0
623 CONSTANT: CPU_SUBTYPE_MC88100     1
624 CONSTANT: CPU_SUBTYPE_MC88110     2
625
626 CONSTANT: CPU_SUBTYPE_SPARC_ALL       0
627
628 CONSTANT: CPU_SUBTYPE_I860_ALL    0
629 CONSTANT: CPU_SUBTYPE_I860_860    1
630
631 CONSTANT: CPU_SUBTYPE_POWERPC_ALL     0
632 CONSTANT: CPU_SUBTYPE_POWERPC_601     1
633 CONSTANT: CPU_SUBTYPE_POWERPC_602     2
634 CONSTANT: CPU_SUBTYPE_POWERPC_603     3
635 CONSTANT: CPU_SUBTYPE_POWERPC_603e    4
636 CONSTANT: CPU_SUBTYPE_POWERPC_603ev   5
637 CONSTANT: CPU_SUBTYPE_POWERPC_604     6
638 CONSTANT: CPU_SUBTYPE_POWERPC_604e    7
639 CONSTANT: CPU_SUBTYPE_POWERPC_620     8
640 CONSTANT: CPU_SUBTYPE_POWERPC_750     9
641 CONSTANT: CPU_SUBTYPE_POWERPC_7400    10
642 CONSTANT: CPU_SUBTYPE_POWERPC_7450    11
643 CONSTANT: CPU_SUBTYPE_POWERPC_970     100
644
645 CONSTANT: CPU_SUBTYPE_ARM_ALL             0
646 CONSTANT: CPU_SUBTYPE_ARM_V4T             5
647 CONSTANT: CPU_SUBTYPE_ARM_V6              6
648 CONSTANT: CPU_SUBTYPE_ARM_V5TEJ           7
649 CONSTANT: CPU_SUBTYPE_ARM_XSCALE          8
650 CONSTANT: CPU_SUBTYPE_ARM_V7              9
651
652 CONSTANT: CPUFAMILY_UNKNOWN    0
653 CONSTANT: CPUFAMILY_POWERPC_G3 0xcee41549
654 CONSTANT: CPUFAMILY_POWERPC_G4 0x77c184ae
655 CONSTANT: CPUFAMILY_POWERPC_G5 0xed76d8aa
656 CONSTANT: CPUFAMILY_INTEL_6_13 0xaa33392b
657 CONSTANT: CPUFAMILY_INTEL_6_14 0x73d67300
658 CONSTANT: CPUFAMILY_INTEL_6_15 0x426f69ef
659 CONSTANT: CPUFAMILY_INTEL_6_23 0x78ea4fbc
660 CONSTANT: CPUFAMILY_INTEL_6_26 0x6b5a4cd2
661 CONSTANT: CPUFAMILY_ARM_9      0xe73283ae
662 CONSTANT: CPUFAMILY_ARM_11     0x8ff620d8
663 CONSTANT: CPUFAMILY_ARM_XSCALE 0x53b005f5
664 CONSTANT: CPUFAMILY_ARM_13     0x0cc90e64
665
666 ALIAS: CPUFAMILY_INTEL_YONAH   CPUFAMILY_INTEL_6_14
667 ALIAS: CPUFAMILY_INTEL_MEROM   CPUFAMILY_INTEL_6_15
668 ALIAS: CPUFAMILY_INTEL_PENRYN  CPUFAMILY_INTEL_6_23
669 ALIAS: CPUFAMILY_INTEL_NEHALEM CPUFAMILY_INTEL_6_26
670
671 ALIAS: CPUFAMILY_INTEL_CORE    CPUFAMILY_INTEL_6_14
672 ALIAS: CPUFAMILY_INTEL_CORE2   CPUFAMILY_INTEL_6_15
673
674 ! fat.h
675 CONSTANT: FAT_MAGIC 0xcafebabe
676 CONSTANT: FAT_CIGAM 0xbebafeca
677
678 STRUCT: fat_header
679     { magic        uint }
680     { nfat_arch    uint } ;
681
682 STRUCT: fat_arch
683     { cputype      cpu_type_t    }
684     { cpusubtype   cpu_subtype_t }
685     { offset       uint          }
686     { size         uint          }
687     { align        uint          } ;
688
689 ! nlist.h
690 STRUCT: nlist
691     { n_strx  int      }
692     { n_type  uchar    }
693     { n_sect  uchar    }
694     { n_desc  short    }
695     { n_value uint     } ;
696
697 STRUCT: nlist_64
698     { n_strx  uint      }
699     { n_type  uchar     }
700     { n_sect  uchar     }
701     { n_desc  ushort    }
702     { n_value ulonglong } ;
703
704 CONSTANT: N_STAB  0xe0
705 CONSTANT: N_PEXT  0x10
706 CONSTANT: N_TYPE  0x0e
707 CONSTANT: N_EXT   0x01
708
709 CONSTANT: N_UNDF  0x0
710 CONSTANT: N_ABS   0x2
711 CONSTANT: N_SECT  0xe
712 CONSTANT: N_PBUD  0xc
713 CONSTANT: N_INDR  0xa
714
715 CONSTANT: NO_SECT     0
716 CONSTANT: MAX_SECT    255
717
718 : GET_COMM_ALIGN ( n_desc -- align )
719     -8 shift 0x0f bitand ; inline
720
721 : SET_COMM_ALIGN ( n_desc align -- n_desc )
722     [ 0xf0ff bitand ]
723     [ 0x000f bitand 8 shift ] bi* bitor ; inline
724
725 CONSTANT: REFERENCE_TYPE                              7
726 CONSTANT: REFERENCE_FLAG_UNDEFINED_NON_LAZY           0
727 CONSTANT: REFERENCE_FLAG_UNDEFINED_LAZY               1
728 CONSTANT: REFERENCE_FLAG_DEFINED                      2
729 CONSTANT: REFERENCE_FLAG_PRIVATE_DEFINED              3
730 CONSTANT: REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY   4
731 CONSTANT: REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY       5
732
733 CONSTANT: REFERENCED_DYNAMICALLY  0x0010
734
735 : GET_LIBRARY_ORDINAL ( n_desc -- ordinal )
736     -8 shift 0xff bitand ; inline
737
738 : SET_LIBRARY_ORDINAL ( n_desc ordinal -- n_desc )
739     [ 0x00ff bitand ]
740     [ 0x00ff bitand 8 shift ] bi* bitor ; inline
741
742 CONSTANT: SELF_LIBRARY_ORDINAL   0x0
743 CONSTANT: MAX_LIBRARY_ORDINAL    0xfd
744 CONSTANT: DYNAMIC_LOOKUP_ORDINAL 0xfe
745 CONSTANT: EXECUTABLE_ORDINAL     0xff
746
747 CONSTANT: N_NO_DEAD_STRIP  0x0020
748 CONSTANT: N_DESC_DISCARDED 0x0020
749 CONSTANT: N_WEAK_REF       0x0040
750 CONSTANT: N_WEAK_DEF       0x0080
751 CONSTANT: N_REF_TO_WEAK    0x0080
752 CONSTANT: N_ARM_THUMB_DEF  0x0008
753
754 ! ranlib.h
755 CONSTANT: SYMDEF        "__.SYMDEF"
756 CONSTANT: SYMDEF_SORTED "__.SYMDEF SORTED"
757
758 STRUCT: ranlib
759     { ran_strx uint }
760     { ran_off  uint } ;
761
762 ! reloc.h
763 STRUCT: relocation_info
764     { r_address                            int  }
765     { r_symbolnum_pcrel_length_extern_type uint } ;
766
767 CONSTANT: R_ABS   0
768 CONSTANT: R_SCATTERED 0x80000000
769
770 STRUCT: scattered_relocation_info_big_endian
771     { r_scattered_pcrel_length_type_address  uint }
772     { r_value                                int  } ;
773
774 STRUCT: scattered_relocation_info_little_endian
775     { r_address_type_length_pcrel_scattered uint }
776     { r_value                               int  } ;
777
778 ENUM: reloc_type_generic
779     GENERIC_RELOC_VANILLA
780     GENERIC_RELOC_PAIR
781     GENERIC_RELOC_SECTDIFF
782     GENERIC_RELOC_PB_LA_PTR
783     GENERIC_RELOC_LOCAL_SECTDIFF ;
784
785 ENUM: reloc_type_x86_64
786     X86_64_RELOC_UNSIGNED
787     X86_64_RELOC_SIGNED
788     X86_64_RELOC_BRANCH
789     X86_64_RELOC_GOT_LOAD
790     X86_64_RELOC_GOT
791     X86_64_RELOC_SUBTRACTOR
792     X86_64_RELOC_SIGNED_1
793     X86_64_RELOC_SIGNED_2
794     X86_64_RELOC_SIGNED_4 ;
795
796 ENUM: reloc_type_ppc
797     PPC_RELOC_VANILLA
798     PPC_RELOC_PAIR
799     PPC_RELOC_BR14
800     PPC_RELOC_BR24
801     PPC_RELOC_HI16
802     PPC_RELOC_LO16
803     PPC_RELOC_HA16
804     PPC_RELOC_LO14
805     PPC_RELOC_SECTDIFF
806     PPC_RELOC_PB_LA_PTR
807     PPC_RELOC_HI16_SECTDIFF
808     PPC_RELOC_LO16_SECTDIFF
809     PPC_RELOC_HA16_SECTDIFF
810     PPC_RELOC_JBSR
811     PPC_RELOC_LO14_SECTDIFF
812     PPC_RELOC_LOCAL_SECTDIFF ;
813
814 ! Low-level interface
815 SPECIALIZED-ARRAYS: section section_64 nlist nlist_64 fat_arch uchar ;
816 UNION: mach_header_32/64 mach_header mach_header_64 ;
817 UNION: segment_command_32/64 segment_command segment_command_64 ;
818 UNION: load-command segment_command segment_command_64
819     dylib_command sub_framework_command
820     sub_client_command sub_umbrella_command sub_library_command
821     prebound_dylib_command dylinker_command thread_command
822     routines_command routines_command_64 symtab_command
823     dysymtab_command twolevel_hints_command uuid_command ;
824 UNION: section_32/64 section section_64 ;
825 UNION: section_32/64-array section-array section_64-array ;
826 UNION: nlist_32/64 nlist nlist_64 ;
827 UNION: nlist_32/64-array nlist-array nlist_64-array ;
828
829 TUPLE: fat-binary-member cpu-type cpu-subtype data ;
830 ERROR: not-fat-binary ;
831
832 : fat-binary-members ( >c-ptr -- fat-binary-members )
833     fat_header memory>struct dup magic>> {
834         { FAT_MAGIC [ ] }
835         { FAT_CIGAM [ ] }
836         [ 2drop not-fat-binary ]
837     } case dup
838     [ >c-ptr fat_header heap-size swap <displaced-alien> ]
839     [ nfat_arch>> 4 >be le> ] bi
840     fat_arch <c-direct-array> [
841         {
842             [ nip cputype>> 4 >be le> ]
843             [ nip cpusubtype>> 4 >be le> ]
844             [ offset>> 4 >be le> swap >c-ptr <displaced-alien> ]
845             [ nip size>> 4 >be le> uchar <c-direct-array> ]
846         } 2cleave fat-binary-member boa
847     ] with { } map-as ;
848
849 TYPED: 64-bit? ( macho: mach_header_32/64 -- ? )
850     magic>> {
851         { MH_MAGIC_64 [ t ] }
852         { MH_CIGAM_64 [ t ] }
853         [ drop f ]
854     } case ;
855
856 : macho-header ( c-ptr -- macho: mach_header_32/64 )
857     dup mach_header_64 memory>struct 64-bit?
858     [ mach_header_64 memory>struct ]
859     [ mach_header memory>struct ] if ;
860
861 : cmd>load-command ( cmd -- load-command )
862     {
863         { LC_UUID           [ uuid_command           ] }
864         { LC_SEGMENT        [ segment_command        ] }
865         { LC_SEGMENT_64     [ segment_command_64     ] }
866         { LC_SYMTAB         [ symtab_command         ] }
867         { LC_DYSYMTAB       [ dysymtab_command       ] }
868         { LC_THREAD         [ thread_command         ] }
869         { LC_UNIXTHREAD     [ thread_command         ] }
870         { LC_LOAD_DYLIB     [ dylib_command          ] }
871         { LC_ID_DYLIB       [ dylib_command          ] }
872         { LC_PREBOUND_DYLIB [ prebound_dylib_command ] }
873         { LC_LOAD_DYLINKER  [ dylinker_command       ] }
874         { LC_ID_DYLINKER    [ dylinker_command       ] }
875         { LC_ROUTINES       [ routines_command       ] }
876         { LC_ROUTINES_64    [ routines_command_64    ] }
877         { LC_TWOLEVEL_HINTS [ twolevel_hints_command ] }
878         { LC_SUB_FRAMEWORK  [ sub_framework_command  ] }
879         { LC_SUB_UMBRELLA   [ sub_umbrella_command   ] }
880         { LC_SUB_LIBRARY    [ sub_library_command    ] }
881         { LC_SUB_CLIENT     [ sub_client_command     ] }
882         { LC_DYLD_INFO      [ dyld_info_command      ] }
883         { LC_DYLD_INFO_ONLY [ dyld_info_command      ] }
884     } case ;
885
886 : read-command ( cmd -- next-cmd )
887     dup load_command memory>struct
888     [ cmd>> cmd>load-command memory>struct , ]
889     [ cmdsize>> swap <displaced-alien> ] 2bi ;
890
891 TYPED: load-commands ( macho: mach_header_32/64 -- load-commands )
892     [
893         [ class-of heap-size ]
894         [ >c-ptr <displaced-alien> ]
895         [ ncmds>> ] tri iota [
896             drop read-command
897         ] each drop
898     ] { } make ;
899
900 : segment-commands ( load-commands -- segment-commands )
901     [ segment_command_32/64? ] filter ; inline
902
903 : symtab-commands ( load-commands -- segment-commands )
904     [ symtab_command? ] filter ; inline
905
906 : read-array-string ( uchar-array -- string )
907     ascii decode [ 0 = ] reject ;
908
909 : segment-sections ( segment-command -- sections )
910     {
911         [ class-of heap-size ]
912         [ >c-ptr <displaced-alien> ]
913         [ nsects>> ]
914         [ segment_command_64? ]
915     } cleave
916     [ section_64 <c-direct-array> ]
917     [ section <c-direct-array> ] if ;
918
919 : sections-array ( segment-commands -- sections-array )
920     [
921         dup first segment_command_64?
922         [ section_64 ] [ section ] if <struct> ,
923         segment-commands [ segment-sections [ , ] each ] each
924     ] { } make ;
925
926 : symbols ( mach-header symtab-command -- symbols string-table )
927     [ symoff>> swap >c-ptr <displaced-alien> ]
928     [ nsyms>> swap 64-bit?
929       [ nlist_64 <c-direct-array> ]
930       [ nlist <c-direct-array> ] if ]
931     [ stroff>> swap >c-ptr <displaced-alien> ] 2tri ;
932     
933 : symbol-name ( symbol string-table -- name )
934     [ n_strx>> ] dip <displaced-alien> ascii alien>string ;
935
936 : c-symbol-name ( symbol string-table -- name )
937     symbol-name "_" ?head drop ;
938
939 : with-mapped-macho ( path quot -- )
940     '[
941         address>> macho-header @
942     ] with-mapped-file-reader ; inline
943
944 : macho-nm ( path -- )
945     [| macho |
946         macho load-commands segment-commands sections-array :> sections
947         macho load-commands symtab-commands [| symtab |
948             macho symtab symbols [
949                 [ drop n_value>> "%016x " printf ]
950                 [
951                     drop n_sect>> sections nth sectname>>
952                     read-array-string "%-16s" printf
953                 ]
954                 [ symbol-name "%s\n" printf ] 2tri
955             ] curry each
956         ] each
957     ] with-mapped-macho ;
958
959 : dylib-export? ( symtab-entry -- ? )
960     n_type>> {
961         [ N_EXT bitand zero? not ]
962         [ N_TYPE bitand N_UNDF = not ]
963     } 1&& ;
964
965 : dylib-exports ( path -- symbol-names )
966     [| macho |
967         macho load-commands symtab-commands [| symtab |
968             macho symtab symbols
969             [ [ dylib-export? ] filter ]
970             [ [ c-symbol-name ] curry { } map-as ] bi*
971         ] { } map-as concat
972     ] with-mapped-macho ;