]> gitweb.factorcode.org Git - factor.git/blobdiff - extra/macho/macho.factor
alien.c-types: not necessary to import `short` differently anymore
[factor.git] / extra / macho / macho.factor
index e3765260bb22a602023fd92bf4962fd96d28bd2c..1f0732b380e8c14ee5e0009fe30af66e019837cc 100644 (file)
@@ -1,23 +1,28 @@
 ! Copyright (C) 2010 Erik Charlebois.
 ! See http:// factorcode.org/license.txt for BSD license.
-USING: alien.c-types alien.syntax classes.struct kernel literals math ;
+USING: accessors alien alien.c-types alien.data alien.strings
+alien.syntax classes classes.struct combinators
+combinators.short-circuit io.encodings.ascii io.encodings.string
+kernel literals make math sequences specialized-arrays typed
+io.mmap formatting splitting endian ;
 IN: macho
 
+! FFI data
 TYPEDEF: int       integer_t
 TYPEDEF: int       vm_prot_t
 TYPEDEF: integer_t cpu_type_t
 TYPEDEF: integer_t cpu_subtype_t
 TYPEDEF: integer_t cpu_threadtype_t
 
-CONSTANT: VM_PROT_NONE        HEX: 00
-CONSTANT: VM_PROT_READ        HEX: 01
-CONSTANT: VM_PROT_WRITE       HEX: 02
-CONSTANT: VM_PROT_EXECUTE     HEX: 04
-CONSTANT: VM_PROT_DEFAULT     HEX: 03
-CONSTANT: VM_PROT_ALL         HEX: 07
-CONSTANT: VM_PROT_NO_CHANGE   HEX: 08
-CONSTANT: VM_PROT_COPY        HEX: 10
-CONSTANT: VM_PROT_WANTS_COPY  HEX: 10
+CONSTANT: VM_PROT_NONE        0x00
+CONSTANT: VM_PROT_READ        0x01
+CONSTANT: VM_PROT_WRITE       0x02
+CONSTANT: VM_PROT_EXECUTE     0x04
+CONSTANT: VM_PROT_DEFAULT     0x03
+CONSTANT: VM_PROT_ALL         0x07
+CONSTANT: VM_PROT_NO_CHANGE   0x08
+CONSTANT: VM_PROT_COPY        0x10
+CONSTANT: VM_PROT_WANTS_COPY  0x10
 
 ! loader.h
 STRUCT: mach_header
@@ -29,8 +34,8 @@ STRUCT: mach_header
     { sizeofcmds    uint          }
     { flags         uint          } ;
 
-CONSTANT: MH_MAGIC    HEX: feedface
-CONSTANT: MH_CIGAM    HEX: cefaedfe
+CONSTANT: MH_MAGIC    0xfeedface
+CONSTANT: MH_CIGAM    0xcefaedfe
 
 STRUCT: mach_header_64
     { magic         uint          }
@@ -42,86 +47,95 @@ STRUCT: mach_header_64
     { flags         uint          }
     { reserved      uint          } ;
 
-CONSTANT: MH_MAGIC_64 HEX: feedfacf
-CONSTANT: MH_CIGAM_64 HEX: cffaedfe
-
-CONSTANT: MH_OBJECT       HEX: 1
-CONSTANT: MH_EXECUTE      HEX: 2
-CONSTANT: MH_FVMLIB       HEX: 3
-CONSTANT: MH_CORE         HEX: 4
-CONSTANT: MH_PRELOAD      HEX: 5
-CONSTANT: MH_DYLIB        HEX: 6
-CONSTANT: MH_DYLINKER     HEX: 7
-CONSTANT: MH_BUNDLE       HEX: 8
-CONSTANT: MH_DYLIB_STUB   HEX: 9
-CONSTANT: MH_DSYM         HEX: a
-CONSTANT: MH_KEXT_BUNDLE  HEX: b
-
-CONSTANT: MH_NOUNDEFS                HEX: 1
-CONSTANT: MH_INCRLINK                HEX: 2
-CONSTANT: MH_DYLDLINK                HEX: 4
-CONSTANT: MH_BINDATLOAD              HEX: 8
-CONSTANT: MH_PREBOUND                HEX: 10
-CONSTANT: MH_SPLIT_SEGS              HEX: 20
-CONSTANT: MH_LAZY_INIT               HEX: 40
-CONSTANT: MH_TWOLEVEL                HEX: 80
-CONSTANT: MH_FORCE_FLAT              HEX: 100
-CONSTANT: MH_NOMULTIDEFS             HEX: 200
-CONSTANT: MH_NOFIXPREBINDING         HEX: 400
-CONSTANT: MH_PREBINDABLE             HEX: 800
-CONSTANT: MH_ALLMODSBOUND            HEX: 1000
-CONSTANT: MH_SUBSECTIONS_VIA_SYMBOLS HEX: 2000
-CONSTANT: MH_CANONICAL               HEX: 4000
-CONSTANT: MH_WEAK_DEFINES            HEX: 8000
-CONSTANT: MH_BINDS_TO_WEAK           HEX: 10000
-CONSTANT: MH_ALLOW_STACK_EXECUTION   HEX: 20000
-CONSTANT: MH_DEAD_STRIPPABLE_DYLIB   HEX: 400000
-CONSTANT: MH_ROOT_SAFE               HEX: 40000
-CONSTANT: MH_SETUID_SAFE             HEX: 80000
-CONSTANT: MH_NO_REEXPORTED_DYLIBS    HEX: 100000
-CONSTANT: MH_PIE                     HEX: 200000
+CONSTANT: MH_MAGIC_64 0xfeedfacf
+CONSTANT: MH_CIGAM_64 0xcffaedfe
+
+CONSTANT: MH_OBJECT       0x1
+CONSTANT: MH_EXECUTE      0x2
+CONSTANT: MH_FVMLIB       0x3
+CONSTANT: MH_CORE         0x4
+CONSTANT: MH_PRELOAD      0x5
+CONSTANT: MH_DYLIB        0x6
+CONSTANT: MH_DYLINKER     0x7
+CONSTANT: MH_BUNDLE       0x8
+CONSTANT: MH_DYLIB_STUB   0x9
+CONSTANT: MH_DSYM         0xa
+CONSTANT: MH_KEXT_BUNDLE  0xb
+
+CONSTANT: MH_NOUNDEFS                0x1
+CONSTANT: MH_INCRLINK                0x2
+CONSTANT: MH_DYLDLINK                0x4
+CONSTANT: MH_BINDATLOAD              0x8
+CONSTANT: MH_PREBOUND                0x10
+CONSTANT: MH_SPLIT_SEGS              0x20
+CONSTANT: MH_LAZY_INIT               0x40
+CONSTANT: MH_TWOLEVEL                0x80
+CONSTANT: MH_FORCE_FLAT              0x100
+CONSTANT: MH_NOMULTIDEFS             0x200
+CONSTANT: MH_NOFIXPREBINDING         0x400
+CONSTANT: MH_PREBINDABLE             0x800
+CONSTANT: MH_ALLMODSBOUND            0x1000
+CONSTANT: MH_SUBSECTIONS_VIA_SYMBOLS 0x2000
+CONSTANT: MH_CANONICAL               0x4000
+CONSTANT: MH_WEAK_DEFINES            0x8000
+CONSTANT: MH_BINDS_TO_WEAK           0x10000
+CONSTANT: MH_ALLOW_STACK_EXECUTION   0x20000
+CONSTANT: MH_DEAD_STRIPPABLE_DYLIB   0x400000
+CONSTANT: MH_ROOT_SAFE               0x40000
+CONSTANT: MH_SETUID_SAFE             0x80000
+CONSTANT: MH_NO_REEXPORTED_DYLIBS    0x100000
+CONSTANT: MH_PIE                     0x200000
 
 STRUCT: load_command
     { cmd     uint }
     { cmdsize uint } ;
 
-CONSTANT: LC_REQ_DYLD HEX: 80000000
-
-CONSTANT: LC_SEGMENT            HEX: 1
-CONSTANT: LC_SYMTAB             HEX: 2
-CONSTANT: LC_SYMSEG             HEX: 3
-CONSTANT: LC_THREAD             HEX: 4
-CONSTANT: LC_UNIXTHREAD         HEX: 5
-CONSTANT: LC_LOADFVMLIB         HEX: 6
-CONSTANT: LC_IDFVMLIB           HEX: 7
-CONSTANT: LC_IDENT              HEX: 8
-CONSTANT: LC_FVMFILE            HEX: 9
-CONSTANT: LC_PREPAGE            HEX: a
-CONSTANT: LC_DYSYMTAB           HEX: b
-CONSTANT: LC_LOAD_DYLIB         HEX: c
-CONSTANT: LC_ID_DYLIB           HEX: d
-CONSTANT: LC_LOAD_DYLINKER      HEX: e
-CONSTANT: LC_ID_DYLINKER        HEX: f
-CONSTANT: LC_PREBOUND_DYLIB     HEX: 10
-CONSTANT: LC_ROUTINES           HEX: 11
-CONSTANT: LC_SUB_FRAMEWORK      HEX: 12
-CONSTANT: LC_SUB_UMBRELLA       HEX: 13
-CONSTANT: LC_SUB_CLIENT         HEX: 14
-CONSTANT: LC_SUB_LIBRARY        HEX: 15
-CONSTANT: LC_TWOLEVEL_HINTS     HEX: 16
-CONSTANT: LC_PREBIND_CKSUM      HEX: 17
-CONSTANT: LC_LOAD_WEAK_DYLIB    HEX: 80000018
-CONSTANT: LC_SEGMENT_64         HEX: 19
-CONSTANT: LC_ROUTINES_64        HEX: 1a
-CONSTANT: LC_UUID               HEX: 1b
-CONSTANT: LC_RPATH              HEX: 8000001c
-CONSTANT: LC_CODE_SIGNATURE     HEX: 1d
-CONSTANT: LC_SEGMENT_SPLIT_INFO HEX: 1e
-CONSTANT: LC_REEXPORT_DYLIB     HEX: 8000001f
-CONSTANT: LC_LAZY_LOAD_DYLIB    HEX: 20
-CONSTANT: LC_ENCRYPTION_INFO    HEX: 21
-CONSTANT: LC_DYLD_INFO          HEX: 22
-CONSTANT: LC_DYLD_INFO_ONLY     HEX: 80000022
+CONSTANT: LC_REQ_DYLD 0x80000000
+
+CONSTANT: LC_SEGMENT            0x1
+CONSTANT: LC_SYMTAB             0x2
+CONSTANT: LC_SYMSEG             0x3
+CONSTANT: LC_THREAD             0x4
+CONSTANT: LC_UNIXTHREAD         0x5
+CONSTANT: LC_LOADFVMLIB         0x6
+CONSTANT: LC_IDFVMLIB           0x7
+CONSTANT: LC_IDENT              0x8
+CONSTANT: LC_FVMFILE            0x9
+CONSTANT: LC_PREPAGE            0xa
+CONSTANT: LC_DYSYMTAB           0xb
+CONSTANT: LC_LOAD_DYLIB         0xc
+CONSTANT: LC_ID_DYLIB           0xd
+CONSTANT: LC_LOAD_DYLINKER      0xe
+CONSTANT: LC_ID_DYLINKER        0xf
+CONSTANT: LC_PREBOUND_DYLIB     0x10
+CONSTANT: LC_ROUTINES           0x11
+CONSTANT: LC_SUB_FRAMEWORK      0x12
+CONSTANT: LC_SUB_UMBRELLA       0x13
+CONSTANT: LC_SUB_CLIENT         0x14
+CONSTANT: LC_SUB_LIBRARY        0x15
+CONSTANT: LC_TWOLEVEL_HINTS     0x16
+CONSTANT: LC_PREBIND_CKSUM      0x17
+CONSTANT: LC_LOAD_WEAK_DYLIB    0x80000018
+CONSTANT: LC_SEGMENT_64         0x19
+CONSTANT: LC_ROUTINES_64        0x1a
+CONSTANT: LC_UUID               0x1b
+CONSTANT: LC_RPATH              0x8000001c
+CONSTANT: LC_CODE_SIGNATURE     0x1d
+CONSTANT: LC_SEGMENT_SPLIT_INFO 0x1e
+CONSTANT: LC_REEXPORT_DYLIB     0x8000001f
+CONSTANT: LC_LAZY_LOAD_DYLIB    0x20
+CONSTANT: LC_ENCRYPTION_INFO    0x21
+CONSTANT: LC_DYLD_INFO          0x22
+CONSTANT: LC_DYLD_INFO_ONLY     0x80000022
+CONSTANT: LC_LOAD_UPWARD_DYLIB 0x80000023
+CONSTANT: LC_VERSION_MIN_MACOSX 0x24
+CONSTANT: LC_VERSION_MIN_IPHONEOS 0x25
+CONSTANT: LC_FUNCTION_STARTS 0x26
+CONSTANT: LC_DYLD_ENVIRONMENT 0x27
+CONSTANT: LC_MAIN 0x80000028
+CONSTANT: LC_DATA_IN_CODE 0x29
+CONSTANT: LC_SOURCE_VERSION 0x2A
+CONSTANT: LC_DYLIB_CODE_SIGN_DRS 0x2B
 
 UNION-STRUCT: lc_str
     { offset    uint     }
@@ -152,11 +166,11 @@ STRUCT: segment_command_64
     { initprot       vm_prot_t  }
     { nsects         uint       }
     { flags          uint       } ;
-    
-CONSTANT: SG_HIGHVM               HEX: 1
-CONSTANT: SG_FVMLIB               HEX: 2
-CONSTANT: SG_NORELOC              HEX: 4
-CONSTANT: SG_PROTECTED_VERSION_1  HEX: 8
+
+CONSTANT: SG_HIGHVM               0x1
+CONSTANT: SG_FVMLIB               0x2
+CONSTANT: SG_NORELOC              0x4
+CONSTANT: SG_PROTECTED_VERSION_1  0x8
 
 STRUCT: section
     { sectname        char[16] }
@@ -185,39 +199,39 @@ STRUCT: section_64
     { reserved2       uint      }
     { reserved3       uint      } ;
 
-CONSTANT: SECTION_TYPE         HEX: 000000ff
-CONSTANT: SECTION_ATTRIBUTES   HEX: ffffff00
-
-CONSTANT: S_REGULAR                       HEX: 0
-CONSTANT: S_ZEROFILL                      HEX: 1
-CONSTANT: S_CSTRING_LITERALS              HEX: 2
-CONSTANT: S_4BYTE_LITERALS                HEX: 3
-CONSTANT: S_8BYTE_LITERALS                HEX: 4
-CONSTANT: S_LITERAL_POINTERS              HEX: 5
-CONSTANT: S_NON_LAZY_SYMBOL_POINTERS      HEX: 6
-CONSTANT: S_LAZY_SYMBOL_POINTERS          HEX: 7
-CONSTANT: S_SYMBOL_STUBS                  HEX: 8
-CONSTANT: S_MOD_INIT_FUNC_POINTERS        HEX: 9
-CONSTANT: S_MOD_TERM_FUNC_POINTERS        HEX: a
-CONSTANT: S_COALESCED                     HEX: b
-CONSTANT: S_GB_ZEROFILL                   HEX: c
-CONSTANT: S_INTERPOSING                   HEX: d
-CONSTANT: S_16BYTE_LITERALS               HEX: e
-CONSTANT: S_DTRACE_DOF                    HEX: f
-CONSTANT: S_LAZY_DYLIB_SYMBOL_POINTERS    HEX: 10
-
-CONSTANT: SECTION_ATTRIBUTES_USR     HEX: ff000000
-CONSTANT: S_ATTR_PURE_INSTRUCTIONS   HEX: 80000000
-CONSTANT: S_ATTR_NO_TOC              HEX: 40000000
-CONSTANT: S_ATTR_STRIP_STATIC_SYMS   HEX: 20000000
-CONSTANT: S_ATTR_NO_DEAD_STRIP       HEX: 10000000
-CONSTANT: S_ATTR_LIVE_SUPPORT        HEX: 08000000
-CONSTANT: S_ATTR_SELF_MODIFYING_CODE HEX: 04000000
-CONSTANT: S_ATTR_DEBUG               HEX: 02000000
-CONSTANT: SECTION_ATTRIBUTES_SYS     HEX: 00ffff00
-CONSTANT: S_ATTR_SOME_INSTRUCTIONS   HEX: 00000400
-CONSTANT: S_ATTR_EXT_RELOC           HEX: 00000200
-CONSTANT: S_ATTR_LOC_RELOC           HEX: 00000100
+CONSTANT: SECTION_TYPE         0x000000ff
+CONSTANT: SECTION_ATTRIBUTES   0xffffff00
+
+CONSTANT: S_REGULAR                       0x0
+CONSTANT: S_ZEROFILL                      0x1
+CONSTANT: S_CSTRING_LITERALS              0x2
+CONSTANT: S_4BYTE_LITERALS                0x3
+CONSTANT: S_8BYTE_LITERALS                0x4
+CONSTANT: S_LITERAL_POINTERS              0x5
+CONSTANT: S_NON_LAZY_SYMBOL_POINTERS      0x6
+CONSTANT: S_LAZY_SYMBOL_POINTERS          0x7
+CONSTANT: S_SYMBOL_STUBS                  0x8
+CONSTANT: S_MOD_INIT_FUNC_POINTERS        0x9
+CONSTANT: S_MOD_TERM_FUNC_POINTERS        0xa
+CONSTANT: S_COALESCED                     0xb
+CONSTANT: S_GB_ZEROFILL                   0xc
+CONSTANT: S_INTERPOSING                   0xd
+CONSTANT: S_16BYTE_LITERALS               0xe
+CONSTANT: S_DTRACE_DOF                    0xf
+CONSTANT: S_LAZY_DYLIB_SYMBOL_POINTERS    0x10
+
+CONSTANT: SECTION_ATTRIBUTES_USR     0xff000000
+CONSTANT: S_ATTR_PURE_INSTRUCTIONS   0x80000000
+CONSTANT: S_ATTR_NO_TOC              0x40000000
+CONSTANT: S_ATTR_STRIP_STATIC_SYMS   0x20000000
+CONSTANT: S_ATTR_NO_DEAD_STRIP       0x10000000
+CONSTANT: S_ATTR_LIVE_SUPPORT        0x08000000
+CONSTANT: S_ATTR_SELF_MODIFYING_CODE 0x04000000
+CONSTANT: S_ATTR_DEBUG               0x02000000
+CONSTANT: SECTION_ATTRIBUTES_SYS     0x00ffff00
+CONSTANT: S_ATTR_SOME_INSTRUCTIONS   0x00000400
+CONSTANT: S_ATTR_EXT_RELOC           0x00000200
+CONSTANT: S_ATTR_LOC_RELOC           0x00000100
 
 CONSTANT: SEG_PAGEZERO      "__PAGEZERO"
 CONSTANT: SEG_TEXT          "__TEXT"
@@ -351,8 +365,8 @@ STRUCT: dysymtab_command
     { locreloff      uint }
     { nlocrel        uint } ;
 
-CONSTANT: INDIRECT_SYMBOL_LOCAL HEX: 80000000
-CONSTANT: INDIRECT_SYMBOL_ABS   HEX: 40000000
+CONSTANT: INDIRECT_SYMBOL_LOCAL 0x80000000
+CONSTANT: INDIRECT_SYMBOL_ABS   0x40000000
 
 STRUCT: dylib_table_of_contents
     { symbol_index uint }
@@ -442,21 +456,27 @@ STRUCT: dyld_info_command
     { export_off       uint }
     { export_size      uint } ;
 
+STRUCT: version_min_command
+    { cmd uint32_t }
+    { cmdsize uint32_t }
+    { version uint32_t }
+    { sdk uint32_t } ;
+
 CONSTANT: REBASE_TYPE_POINTER                     1
 CONSTANT: REBASE_TYPE_TEXT_ABSOLUTE32             2
 CONSTANT: REBASE_TYPE_TEXT_PCREL32                3
 
-CONSTANT: REBASE_OPCODE_MASK                                  HEX: F0
-CONSTANT: REBASE_IMMEDIATE_MASK                               HEX: 0F
-CONSTANT: REBASE_OPCODE_DONE                                  HEX: 00
-CONSTANT: REBASE_OPCODE_SET_TYPE_IMM                          HEX: 10
-CONSTANT: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB           HEX: 20
-CONSTANT: REBASE_OPCODE_ADD_ADDR_ULEB                         HEX: 30
-CONSTANT: REBASE_OPCODE_ADD_ADDR_IMM_SCALED                   HEX: 40
-CONSTANT: REBASE_OPCODE_DO_REBASE_IMM_TIMES                   HEX: 50
-CONSTANT: REBASE_OPCODE_DO_REBASE_ULEB_TIMES                  HEX: 60
-CONSTANT: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB               HEX: 70
-CONSTANT: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB    HEX: 80
+CONSTANT: REBASE_OPCODE_MASK                                  0xF0
+CONSTANT: REBASE_IMMEDIATE_MASK                               0x0F
+CONSTANT: REBASE_OPCODE_DONE                                  0x00
+CONSTANT: REBASE_OPCODE_SET_TYPE_IMM                          0x10
+CONSTANT: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB           0x20
+CONSTANT: REBASE_OPCODE_ADD_ADDR_ULEB                         0x30
+CONSTANT: REBASE_OPCODE_ADD_ADDR_IMM_SCALED                   0x40
+CONSTANT: REBASE_OPCODE_DO_REBASE_IMM_TIMES                   0x50
+CONSTANT: REBASE_OPCODE_DO_REBASE_ULEB_TIMES                  0x60
+CONSTANT: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB               0x70
+CONSTANT: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB    0x80
 
 CONSTANT: BIND_TYPE_POINTER                       1
 CONSTANT: BIND_TYPE_TEXT_ABSOLUTE32               2
@@ -466,31 +486,31 @@ CONSTANT: BIND_SPECIAL_DYLIB_SELF                     0
 CONSTANT: BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE          -1
 CONSTANT: BIND_SPECIAL_DYLIB_FLAT_LOOKUP              -2
 
-CONSTANT: BIND_SYMBOL_FLAGS_WEAK_IMPORT                   HEX: 1
-CONSTANT: BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION           HEX: 8
-
-CONSTANT: BIND_OPCODE_MASK                                    HEX: F0
-CONSTANT: BIND_IMMEDIATE_MASK                                 HEX: 0F
-CONSTANT: BIND_OPCODE_DONE                                    HEX: 00
-CONSTANT: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM                   HEX: 10
-CONSTANT: BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB                  HEX: 20
-CONSTANT: BIND_OPCODE_SET_DYLIB_SPECIAL_IMM                   HEX: 30
-CONSTANT: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM           HEX: 40
-CONSTANT: BIND_OPCODE_SET_TYPE_IMM                            HEX: 50
-CONSTANT: BIND_OPCODE_SET_ADDEND_SLEB                         HEX: 60
-CONSTANT: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB             HEX: 70
-CONSTANT: BIND_OPCODE_ADD_ADDR_ULEB                           HEX: 80
-CONSTANT: BIND_OPCODE_DO_BIND                                 HEX: 90
-CONSTANT: BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB                   HEX: A0
-CONSTANT: BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED             HEX: B0
-CONSTANT: BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB        HEX: C0
-
-CONSTANT: EXPORT_SYMBOL_FLAGS_KIND_MASK                   HEX: 03
-CONSTANT: EXPORT_SYMBOL_FLAGS_KIND_REGULAR                HEX: 00
-CONSTANT: EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL           HEX: 01
-CONSTANT: EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION             HEX: 04
-CONSTANT: EXPORT_SYMBOL_FLAGS_INDIRECT_DEFINITION         HEX: 08
-CONSTANT: EXPORT_SYMBOL_FLAGS_HAS_SPECIALIZATIONS         HEX: 10
+CONSTANT: BIND_SYMBOL_FLAGS_WEAK_IMPORT                   0x1
+CONSTANT: BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION           0x8
+
+CONSTANT: BIND_OPCODE_MASK                                    0xF0
+CONSTANT: BIND_IMMEDIATE_MASK                                 0x0F
+CONSTANT: BIND_OPCODE_DONE                                    0x00
+CONSTANT: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM                   0x10
+CONSTANT: BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB                  0x20
+CONSTANT: BIND_OPCODE_SET_DYLIB_SPECIAL_IMM                   0x30
+CONSTANT: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM           0x40
+CONSTANT: BIND_OPCODE_SET_TYPE_IMM                            0x50
+CONSTANT: BIND_OPCODE_SET_ADDEND_SLEB                         0x60
+CONSTANT: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB             0x70
+CONSTANT: BIND_OPCODE_ADD_ADDR_ULEB                           0x80
+CONSTANT: BIND_OPCODE_DO_BIND                                 0x90
+CONSTANT: BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB                   0xA0
+CONSTANT: BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED             0xB0
+CONSTANT: BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB        0xC0
+
+CONSTANT: EXPORT_SYMBOL_FLAGS_KIND_MASK                   0x03
+CONSTANT: EXPORT_SYMBOL_FLAGS_KIND_REGULAR                0x00
+CONSTANT: EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL           0x01
+CONSTANT: EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION             0x04
+CONSTANT: EXPORT_SYMBOL_FLAGS_INDIRECT_DEFINITION         0x08
+CONSTANT: EXPORT_SYMBOL_FLAGS_HAS_SPECIALIZATIONS         0x10
 
 STRUCT: symseg_command
     { cmd        uint }
@@ -508,6 +528,22 @@ STRUCT: fvmfile_command
     { name           lc_str   }
     { header_addr    uint     } ;
 
+STRUCT: entry_point_command
+    { cmd uint32_t }
+    { cmdsize uint32_t }
+    { entryoff uint64_t }
+    { stacksize uint64_t } ;
+
+STRUCT: source_version_command
+    { cmd uint32_t }
+    { cmdsize uint32_t }
+    { version uint64_t } ;
+
+STRUCT: data_in_code_entry
+    { offset uint32_t }
+    { length uint16_t }
+    { kind uint16_t } ;
+
 ! machine.h
 CONSTANT: CPU_STATE_MAX       4
 CONSTANT: CPU_STATE_USER      0
@@ -515,8 +551,8 @@ CONSTANT: CPU_STATE_SYSTEM    1
 CONSTANT: CPU_STATE_IDLE      2
 CONSTANT: CPU_STATE_NICE      3
 
-CONSTANT: CPU_ARCH_MASK   HEX: ff000000
-CONSTANT: CPU_ARCH_ABI64  HEX: 01000000
+CONSTANT: CPU_ARCH_MASK   0xff000000
+CONSTANT: CPU_ARCH_ABI64  0x01000000
 
 CONSTANT: CPU_TYPE_ANY            -1
 CONSTANT: CPU_TYPE_VAX            1
@@ -533,8 +569,8 @@ CONSTANT: CPU_TYPE_I860           15
 CONSTANT: CPU_TYPE_POWERPC        18
 CONSTANT: CPU_TYPE_POWERPC64      flags{ CPU_TYPE_POWERPC CPU_ARCH_ABI64 }
 
-CONSTANT: CPU_SUBTYPE_MASK    HEX: ff000000
-CONSTANT: CPU_SUBTYPE_LIB64   HEX: 80000000
+CONSTANT: CPU_SUBTYPE_MASK    0xff000000
+CONSTANT: CPU_SUBTYPE_LIB64   0x80000000
 
 CONSTANT: CPU_SUBTYPE_MULTIPLE        -1
 CONSTANT: CPU_SUBTYPE_LITTLE_ENDIAN   0
@@ -644,18 +680,18 @@ CONSTANT: CPU_SUBTYPE_ARM_XSCALE          8
 CONSTANT: CPU_SUBTYPE_ARM_V7              9
 
 CONSTANT: CPUFAMILY_UNKNOWN    0
-CONSTANT: CPUFAMILY_POWERPC_G3 HEX: cee41549
-CONSTANT: CPUFAMILY_POWERPC_G4 HEX: 77c184ae
-CONSTANT: CPUFAMILY_POWERPC_G5 HEX: ed76d8aa
-CONSTANT: CPUFAMILY_INTEL_6_13 HEX: aa33392b
-CONSTANT: CPUFAMILY_INTEL_6_14 HEX: 73d67300
-CONSTANT: CPUFAMILY_INTEL_6_15 HEX: 426f69ef
-CONSTANT: CPUFAMILY_INTEL_6_23 HEX: 78ea4fbc
-CONSTANT: CPUFAMILY_INTEL_6_26 HEX: 6b5a4cd2
-CONSTANT: CPUFAMILY_ARM_9      HEX: e73283ae
-CONSTANT: CPUFAMILY_ARM_11     HEX: 8ff620d8
-CONSTANT: CPUFAMILY_ARM_XSCALE HEX: 53b005f5
-CONSTANT: CPUFAMILY_ARM_13     HEX: 0cc90e64
+CONSTANT: CPUFAMILY_POWERPC_G3 0xcee41549
+CONSTANT: CPUFAMILY_POWERPC_G4 0x77c184ae
+CONSTANT: CPUFAMILY_POWERPC_G5 0xed76d8aa
+CONSTANT: CPUFAMILY_INTEL_6_13 0xaa33392b
+CONSTANT: CPUFAMILY_INTEL_6_14 0x73d67300
+CONSTANT: CPUFAMILY_INTEL_6_15 0x426f69ef
+CONSTANT: CPUFAMILY_INTEL_6_23 0x78ea4fbc
+CONSTANT: CPUFAMILY_INTEL_6_26 0x6b5a4cd2
+CONSTANT: CPUFAMILY_ARM_9      0xe73283ae
+CONSTANT: CPUFAMILY_ARM_11     0x8ff620d8
+CONSTANT: CPUFAMILY_ARM_XSCALE 0x53b005f5
+CONSTANT: CPUFAMILY_ARM_13     0x0cc90e64
 
 ALIAS: CPUFAMILY_INTEL_YONAH   CPUFAMILY_INTEL_6_14
 ALIAS: CPUFAMILY_INTEL_MEROM   CPUFAMILY_INTEL_6_15
@@ -666,8 +702,8 @@ ALIAS: CPUFAMILY_INTEL_CORE    CPUFAMILY_INTEL_6_14
 ALIAS: CPUFAMILY_INTEL_CORE2   CPUFAMILY_INTEL_6_15
 
 ! fat.h
-CONSTANT: FAT_MAGIC HEX: cafebabe
-CONSTANT: FAT_CIGAM HEX: bebafeca
+CONSTANT: FAT_MAGIC 0xcafebabe
+CONSTANT: FAT_CIGAM 0xbebafeca
 
 STRUCT: fat_header
     { magic        uint }
@@ -695,26 +731,26 @@ STRUCT: nlist_64
     { n_desc  ushort    }
     { n_value ulonglong } ;
 
-CONSTANT: N_STAB  HEX: e0
-CONSTANT: N_PEXT  HEX: 10
-CONSTANT: N_TYPE  HEX: 0e
-CONSTANT: N_EXT   HEX: 01
+CONSTANT: N_STAB  0xe0
+CONSTANT: N_PEXT  0x10
+CONSTANT: N_TYPE  0x0e
+CONSTANT: N_EXT   0x01
 
-CONSTANT: N_UNDF  HEX: 0
-CONSTANT: N_ABS   HEX: 2
-CONSTANT: N_SECT  HEX: e
-CONSTANT: N_PBUD  HEX: c
-CONSTANT: N_INDR  HEX: a
+CONSTANT: N_UNDF  0x0
+CONSTANT: N_ABS   0x2
+CONSTANT: N_SECT  0xe
+CONSTANT: N_PBUD  0xc
+CONSTANT: N_INDR  0xa
 
 CONSTANT: NO_SECT     0
 CONSTANT: MAX_SECT    255
 
 : GET_COMM_ALIGN ( n_desc -- align )
-    -8 shift HEX: 0f bitand ; inline
+    -8 shift 0x0f bitand ; inline
 
 : SET_COMM_ALIGN ( n_desc align -- n_desc )
-    [ HEX: f0ff bitand ]
-    [ HEX: 000f bitand 8 shift ] bi* bitor ; inline
+    [ 0xf0ff bitand ]
+    [ 0x000f bitand 8 shift ] bi* bitor ; inline
 
 CONSTANT: REFERENCE_TYPE                              7
 CONSTANT: REFERENCE_FLAG_UNDEFINED_NON_LAZY           0
@@ -724,26 +760,26 @@ CONSTANT: REFERENCE_FLAG_PRIVATE_DEFINED              3
 CONSTANT: REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY   4
 CONSTANT: REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY       5
 
-CONSTANT: REFERENCED_DYNAMICALLY  HEX: 0010
+CONSTANT: REFERENCED_DYNAMICALLY  0x0010
 
 : GET_LIBRARY_ORDINAL ( n_desc -- ordinal )
-    -8 shift HEX: ff bitand ; inline
+    -8 shift 0xff bitand ; inline
 
 : SET_LIBRARY_ORDINAL ( n_desc ordinal -- n_desc )
-    [ HEX: 00ff bitand ]
-    [ HEX: 00ff bitand 8 shift ] bi* bitor ; inline
+    [ 0x00ff bitand ]
+    [ 0x00ff bitand 8 shift ] bi* bitor ; inline
 
-CONSTANT: SELF_LIBRARY_ORDINAL   HEX: 0
-CONSTANT: MAX_LIBRARY_ORDINAL    HEX: fd
-CONSTANT: DYNAMIC_LOOKUP_ORDINAL HEX: fe
-CONSTANT: EXECUTABLE_ORDINAL     HEX: ff
+CONSTANT: SELF_LIBRARY_ORDINAL   0x0
+CONSTANT: MAX_LIBRARY_ORDINAL    0xfd
+CONSTANT: DYNAMIC_LOOKUP_ORDINAL 0xfe
+CONSTANT: EXECUTABLE_ORDINAL     0xff
 
-CONSTANT: N_NO_DEAD_STRIP  HEX: 0020
-CONSTANT: N_DESC_DISCARDED HEX: 0020
-CONSTANT: N_WEAK_REF       HEX: 0040
-CONSTANT: N_WEAK_DEF       HEX: 0080
-CONSTANT: N_REF_TO_WEAK    HEX: 0080
-CONSTANT: N_ARM_THUMB_DEF  HEX: 0008
+CONSTANT: N_NO_DEAD_STRIP  0x0020
+CONSTANT: N_DESC_DISCARDED 0x0020
+CONSTANT: N_WEAK_REF       0x0040
+CONSTANT: N_WEAK_DEF       0x0080
+CONSTANT: N_REF_TO_WEAK    0x0080
+CONSTANT: N_ARM_THUMB_DEF  0x0008
 
 ! ranlib.h
 CONSTANT: SYMDEF        "__.SYMDEF"
@@ -759,7 +795,7 @@ STRUCT: relocation_info
     { r_symbolnum_pcrel_length_extern_type uint } ;
 
 CONSTANT: R_ABS   0
-CONSTANT: R_SCATTERED HEX: 80000000
+CONSTANT: R_SCATTERED 0x80000000
 
 STRUCT: scattered_relocation_info_big_endian
     { r_scattered_pcrel_length_type_address  uint }
@@ -769,14 +805,14 @@ STRUCT: scattered_relocation_info_little_endian
     { r_address_type_length_pcrel_scattered uint }
     { r_value                               int  } ;
 
-C-ENUM: reloc_type_generic
+ENUM: reloc_type_generic
     GENERIC_RELOC_VANILLA
     GENERIC_RELOC_PAIR
     GENERIC_RELOC_SECTDIFF
     GENERIC_RELOC_PB_LA_PTR
     GENERIC_RELOC_LOCAL_SECTDIFF ;
 
-C-ENUM: reloc_type_x86_64
+ENUM: reloc_type_x86_64
     X86_64_RELOC_UNSIGNED
     X86_64_RELOC_SIGNED
     X86_64_RELOC_BRANCH
@@ -787,7 +823,7 @@ C-ENUM: reloc_type_x86_64
     X86_64_RELOC_SIGNED_2
     X86_64_RELOC_SIGNED_4 ;
 
-C-ENUM: reloc_type_ppc
+ENUM: reloc_type_ppc
     PPC_RELOC_VANILLA
     PPC_RELOC_PAIR
     PPC_RELOC_BR14
@@ -804,3 +840,172 @@ C-ENUM: reloc_type_ppc
     PPC_RELOC_JBSR
     PPC_RELOC_LO14_SECTDIFF
     PPC_RELOC_LOCAL_SECTDIFF ;
+
+! Low-level interface
+SPECIALIZED-ARRAYS: section section_64 nlist nlist_64 fat_arch uchar ;
+UNION: mach_header_32/64 mach_header mach_header_64 ;
+UNION: segment_command_32/64 segment_command segment_command_64 ;
+UNION: load-command segment_command segment_command_64
+    dylib_command sub_framework_command
+    sub_client_command sub_umbrella_command sub_library_command
+    prebound_dylib_command dylinker_command thread_command
+    routines_command routines_command_64 symtab_command
+    dysymtab_command twolevel_hints_command uuid_command ;
+UNION: section_32/64 section section_64 ;
+UNION: section_32/64-array section-array section_64-array ;
+UNION: nlist_32/64 nlist nlist_64 ;
+UNION: nlist_32/64-array nlist-array nlist_64-array ;
+
+TUPLE: fat-binary-member cpu-type cpu-subtype data ;
+ERROR: not-fat-binary ;
+
+: fat-binary-members ( >c-ptr -- fat-binary-members )
+    fat_header memory>struct dup magic>> {
+        { FAT_MAGIC [ ] }
+        { FAT_CIGAM [ ] }
+        [ 2drop not-fat-binary ]
+    } case dup
+    [ >c-ptr fat_header heap-size swap <displaced-alien> ]
+    [ nfat_arch>> 4 >be le> ] bi
+    fat_arch <c-direct-array> [
+        {
+            [ nip cputype>> 4 >be le> ]
+            [ nip cpusubtype>> 4 >be le> ]
+            [ offset>> 4 >be le> swap >c-ptr <displaced-alien> ]
+            [ nip size>> 4 >be le> uchar <c-direct-array> ]
+        } 2cleave fat-binary-member boa
+    ] with { } map-as ;
+
+TYPED: 64-bit? ( macho: mach_header_32/64 -- ? )
+    magic>> {
+        { MH_MAGIC_64 [ t ] }
+        { MH_CIGAM_64 [ t ] }
+        [ drop f ]
+    } case ;
+
+: macho-header ( c-ptr -- macho: mach_header_32/64 )
+    dup mach_header_64 memory>struct 64-bit?
+    [ mach_header_64 memory>struct ]
+    [ mach_header memory>struct ] if ;
+
+: cmd>load-command ( cmd -- load-command )
+    {
+        { LC_UUID           [ uuid_command           ] }
+        { LC_SEGMENT        [ segment_command        ] }
+        { LC_SEGMENT_64     [ segment_command_64     ] }
+        { LC_SYMTAB         [ symtab_command         ] }
+        { LC_DYSYMTAB       [ dysymtab_command       ] }
+        { LC_THREAD         [ thread_command         ] }
+        { LC_UNIXTHREAD     [ thread_command         ] }
+        { LC_LOAD_DYLIB     [ dylib_command          ] }
+        { LC_ID_DYLIB       [ dylib_command          ] }
+        { LC_PREBOUND_DYLIB [ prebound_dylib_command ] }
+        { LC_LOAD_DYLINKER  [ dylinker_command       ] }
+        { LC_ID_DYLINKER    [ dylinker_command       ] }
+        { LC_ROUTINES       [ routines_command       ] }
+        { LC_ROUTINES_64    [ routines_command_64    ] }
+        { LC_TWOLEVEL_HINTS [ twolevel_hints_command ] }
+        { LC_SUB_FRAMEWORK  [ sub_framework_command  ] }
+        { LC_SUB_UMBRELLA   [ sub_umbrella_command   ] }
+        { LC_SUB_LIBRARY    [ sub_library_command    ] }
+        { LC_SUB_CLIENT     [ sub_client_command     ] }
+        { LC_DYLD_INFO      [ dyld_info_command      ] }
+        { LC_DYLD_INFO_ONLY [ dyld_info_command      ] }
+        { LC_LOAD_UPWARD_DYLIB [ dylib_command ] }
+        { LC_VERSION_MIN_MACOSX [ version_min_command ] }
+        { LC_VERSION_MIN_IPHONEOS [ version_min_command ] }
+        { LC_FUNCTION_STARTS [ linkedit_data_command ] }
+        { LC_DYLD_ENVIRONMENT [ dylinker_command ] }
+        { LC_MAIN [ entry_point_command ] }
+        { LC_DATA_IN_CODE [ data_in_code_entry ] }
+        { LC_SOURCE_VERSION [ source_version_command ] }
+        { LC_DYLIB_CODE_SIGN_DRS [ linkedit_data_command ] }
+    } case ;
+
+: read-command ( cmd -- next-cmd )
+    dup load_command memory>struct
+    [ cmd>> cmd>load-command memory>struct , ]
+    [ cmdsize>> swap <displaced-alien> ] 2bi ;
+
+TYPED: load-commands ( macho: mach_header_32/64 -- load-commands )
+    [
+        [ class-of heap-size ]
+        [ >c-ptr <displaced-alien> ]
+        [ ncmds>> ] tri <iota> [
+            drop read-command
+        ] each drop
+    ] { } make ;
+
+: segment-commands ( load-commands -- segment-commands )
+    [ segment_command_32/64? ] filter ; inline
+
+: symtab-commands ( load-commands -- segment-commands )
+    [ symtab_command? ] filter ; inline
+
+: read-array-string ( uchar-array -- string )
+    ascii decode 0 swap remove ;
+
+: segment-sections ( segment-command -- sections )
+    {
+        [ class-of heap-size ]
+        [ >c-ptr <displaced-alien> ]
+        [ nsects>> ]
+        [ segment_command_64? ]
+    } cleave
+    [ section_64 <c-direct-array> ]
+    [ section <c-direct-array> ] if ;
+
+: sections-array ( segment-commands -- sections-array )
+    [
+        dup first segment_command_64?
+        [ section_64 ] [ section ] if new ,
+        segment-commands [ segment-sections [ , ] each ] each
+    ] { } make ;
+
+: symbols ( mach-header symtab-command -- symbols string-table )
+    [ symoff>> swap >c-ptr <displaced-alien> ]
+    [ nsyms>> swap 64-bit?
+      [ nlist_64 <c-direct-array> ]
+      [ nlist <c-direct-array> ] if ]
+    [ stroff>> swap >c-ptr <displaced-alien> ] 2tri ;
+
+: symbol-name ( symbol string-table -- name )
+    [ n_strx>> ] dip <displaced-alien> ascii alien>string ;
+
+: c-symbol-name ( symbol string-table -- name )
+    symbol-name "_" ?head drop ;
+
+: with-mapped-macho ( path quot -- )
+    '[
+        address>> macho-header @
+    ] with-mapped-file-reader ; inline
+
+: macho-nm ( path -- )
+    [| macho |
+        macho load-commands segment-commands sections-array :> sections
+        macho load-commands symtab-commands [| symtab |
+            macho symtab symbols [
+                [ drop n_value>> "%016x " printf ]
+                [
+                    drop n_sect>> sections nth sectname>>
+                    read-array-string "%-16s" printf
+                ]
+                [ symbol-name "%s\n" printf ] 2tri
+            ] curry each
+        ] each
+    ] with-mapped-macho ;
+
+: dylib-export? ( symtab-entry -- ? )
+    n_type>> {
+        [ N_EXT bitand zero? not ]
+        [ N_TYPE bitand N_UNDF = not ]
+    } 1&& ;
+
+: dylib-exports ( path -- symbol-names )
+    [| macho |
+        macho load-commands symtab-commands [| symtab |
+            macho symtab symbols
+            [ [ dylib-export? ] filter ]
+            [ [ c-symbol-name ] curry { } map-as ] bi*
+        ] { } map-as concat
+    ] with-mapped-macho ;