diff --git a/extra/elf/nm/nm-tests.factor b/extra/elf/nm/nm-tests.factor index 2ecb499081..9e529ae43d 100644 --- a/extra/elf/nm/nm-tests.factor +++ b/extra/elf/nm/nm-tests.factor @@ -6,46 +6,46 @@ IN: elf.nm.tests STRING: validation-output 0000000000000000 absolute init.c -0000000004195436 .text call_gmon_start +000000000040046c .text call_gmon_start 0000000000000000 absolute crtstuff.c -0000000006295064 .ctors __CTOR_LIST__ -0000000006295080 .dtors __DTOR_LIST__ -0000000006295096 .jcr __JCR_LIST__ -0000000004195472 .text __do_global_dtors_aux -0000000006295584 .bss completed.7342 -0000000006295592 .bss dtor_idx.7344 -0000000004195584 .text frame_dummy +0000000000600e18 .ctors __CTOR_LIST__ +0000000000600e28 .dtors __DTOR_LIST__ +0000000000600e38 .jcr __JCR_LIST__ +0000000000400490 .text __do_global_dtors_aux +0000000000601020 .bss completed.7342 +0000000000601028 .bss dtor_idx.7344 +0000000000400500 .text frame_dummy 0000000000000000 absolute crtstuff.c -0000000006295072 .ctors __CTOR_END__ -0000000004196056 .eh_frame __FRAME_END__ -0000000006295096 .jcr __JCR_END__ -0000000004195808 .text __do_global_ctors_aux +0000000000600e20 .ctors __CTOR_END__ +00000000004006d8 .eh_frame __FRAME_END__ +0000000000600e38 .jcr __JCR_END__ +00000000004005e0 .text __do_global_ctors_aux 0000000000000000 absolute test.c -0000000006295528 .got.plt _GLOBAL_OFFSET_TABLE_ -0000000006295060 .ctors __init_array_end -0000000006295060 .ctors __init_array_start -0000000006295104 .dynamic _DYNAMIC -0000000006295568 .data data_start +0000000000600fe8 .got.plt _GLOBAL_OFFSET_TABLE_ +0000000000600e14 .ctors __init_array_end +0000000000600e14 .ctors __init_array_start +0000000000600e40 .dynamic _DYNAMIC +0000000000601010 .data data_start 0000000000000000 undefined printf@@GLIBC_2.2.5 -0000000004195648 .text __libc_csu_fini -0000000004195392 .text _start +0000000000400540 .text __libc_csu_fini +0000000000400440 .text _start 0000000000000000 undefined __gmon_start__ 0000000000000000 undefined _Jv_RegisterClasses -0000000004195864 .fini _fini +0000000000400618 .fini _fini 0000000000000000 undefined __libc_start_main@@GLIBC_2.2.5 -0000000004195880 .rodata _IO_stdin_used -0000000006295568 .data __data_start -0000000006295576 .data __dso_handle -0000000006295088 .dtors __DTOR_END__ -0000000004195664 .text __libc_csu_init -0000000006295584 absolute __bss_start -0000000006295600 absolute _end -0000000006295584 absolute _edata -0000000004195620 .text main -0000000004195312 .init _init +0000000000400628 .rodata _IO_stdin_used +0000000000601010 .data __data_start +0000000000601018 .data __dso_handle +0000000000600e30 .dtors __DTOR_END__ +0000000000400550 .text __libc_csu_init +0000000000601020 absolute __bss_start +0000000000601030 absolute _end +0000000000601020 absolute _edata +0000000000400524 .text main +00000000004003f0 .init _init ; { $ validation-output } -[ dup [ "resource:extra/elf/a.elf" nm ] with-output-stream >string ] +[ dup [ "resource:extra/elf/a.elf" elf-nm ] with-output-stream >string ] unit-test diff --git a/extra/elf/nm/nm.factor b/extra/elf/nm/nm.factor index 87c9abf00b..52e1c66902 100644 --- a/extra/elf/nm/nm.factor +++ b/extra/elf/nm/nm.factor @@ -4,7 +4,7 @@ USING: accessors combinators elf formatting io.mmap kernel sequences ; IN: elf.nm : print-symbol ( sections symbol -- ) - [ sym>> st_value>> "%016d " printf ] + [ sym>> st_value>> "%016x " printf ] [ sym>> st_shndx>> { @@ -16,7 +16,7 @@ IN: elf.nm ] [ name>> "%s\n" printf ] tri ; -: nm ( path -- ) +: elf-nm ( path -- ) [ sections dup ".symtab" find-section symbols [ name>> empty? not ] filter diff --git a/extra/macho/a.macho b/extra/macho/a.macho new file mode 100755 index 0000000000..bc233d7095 Binary files /dev/null and b/extra/macho/a.macho differ diff --git a/extra/macho/macho-tests.factor b/extra/macho/macho-tests.factor new file mode 100644 index 0000000000..ca60d3dc9b --- /dev/null +++ b/extra/macho/macho-tests.factor @@ -0,0 +1,26 @@ +! Copyright (C) 2010 Erik Charlebois. +! See http://factorcode.org/license.txt for BSD license. +USING: io io.streams.string kernel literals macho multiline strings +tools.test ; +IN: macho.tests + +STRING: validation-output +0000000100000f1c __stub_helper stub helpers +0000000100001040 __program_vars _pvars +0000000100001068 __data _NXArgc +0000000100001070 __data _NXArgv +0000000100001080 __data ___progname +0000000100000000 __mh_execute_header +0000000100001078 __data _environ +0000000100000ef8 __text _main +0000000100000ebc __text start +0000000000000000 ___gxx_personality_v0 +0000000000000000 _exit +0000000000000000 _printf +0000000000000000 dyld_stub_binder + +; + +{ $ validation-output } +[ dup [ "resource:extra/macho/a.macho" macho-nm ] with-output-stream >string ] +unit-test diff --git a/extra/macho/macho.factor b/extra/macho/macho.factor index e3765260bb..b18ea57ce5 100644 --- a/extra/macho/macho.factor +++ b/extra/macho/macho.factor @@ -1,8 +1,13 @@ ! 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.strings alien.syntax +classes classes.struct combinators io.encodings.ascii +io.encodings.string kernel literals make math sequences +specialized-arrays typed fry io.mmap formatting locals ; +FROM: alien.c-types => short ; IN: macho +! FFI data TYPEDEF: int integer_t TYPEDEF: int vm_prot_t TYPEDEF: integer_t cpu_type_t @@ -804,3 +809,124 @@ 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 ; +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 ; + +TYPED: 64-bit? ( macho: mach_header_32/64 -- ? ) + magic>> { + { MH_MAGIC_64 [ t ] } + { MH_CIGAM_64 [ t ] } + [ drop f ] + } case ; + +TYPED: 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 ] } + } case ; + +: read-command ( cmd -- next-cmd ) + dup load_command memory>struct + [ cmd>> cmd>load-command memory>struct , ] + [ cmdsize>> swap ] 2bi ; + +TYPED: load-commands ( macho: mach_header_32/64 -- load-commands ) + [ + [ class heap-size ] + [ >c-ptr ] + [ 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 = not ] filter ; + +: segment-sections ( segment-command -- sections ) + { + [ class heap-size ] + [ >c-ptr ] + [ nsects>> ] + [ segment_command_64? ] + } cleave + [ ] + [ ] if ; + +: sections-array ( segment-commands -- sections-array ) + [ + dup first segment_command_64? + [ section_64 ] [ section ] if , + segment-commands [ segment-sections [ , ] each ] each + ] { } make ; + +: symbols ( mach-header symtab-command -- symbols string-table ) + [ symoff>> swap >c-ptr ] + [ nsyms>> swap 64-bit? + [ ] + [ ] if ] + [ stroff>> swap >c-ptr ] 2tri ; + +: symbol-name ( symbol string-table -- name ) + [ n_strx>> ] dip ascii alien>string ; + +: with-mapped-macho ( path quot -- ) + '[ + address>> macho-header @ + ] with-mapped-file ; 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 ;