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