metasm 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. data/BUGS +11 -0
  2. data/CREDITS +17 -0
  3. data/README +270 -0
  4. data/TODO +114 -0
  5. data/doc/code_organisation.txt +146 -0
  6. data/doc/const_missing.txt +16 -0
  7. data/doc/core_classes.txt +75 -0
  8. data/doc/feature_list.txt +53 -0
  9. data/doc/index.txt +59 -0
  10. data/doc/install_notes.txt +170 -0
  11. data/doc/style.css +3 -0
  12. data/doc/use_cases.txt +18 -0
  13. data/lib/metasm.rb +80 -0
  14. data/lib/metasm/arm.rb +12 -0
  15. data/lib/metasm/arm/debug.rb +39 -0
  16. data/lib/metasm/arm/decode.rb +167 -0
  17. data/lib/metasm/arm/encode.rb +77 -0
  18. data/lib/metasm/arm/main.rb +75 -0
  19. data/lib/metasm/arm/opcodes.rb +177 -0
  20. data/lib/metasm/arm/parse.rb +130 -0
  21. data/lib/metasm/arm/render.rb +55 -0
  22. data/lib/metasm/compile_c.rb +1457 -0
  23. data/lib/metasm/dalvik.rb +8 -0
  24. data/lib/metasm/dalvik/decode.rb +196 -0
  25. data/lib/metasm/dalvik/main.rb +60 -0
  26. data/lib/metasm/dalvik/opcodes.rb +366 -0
  27. data/lib/metasm/decode.rb +213 -0
  28. data/lib/metasm/decompile.rb +2659 -0
  29. data/lib/metasm/disassemble.rb +2068 -0
  30. data/lib/metasm/disassemble_api.rb +1280 -0
  31. data/lib/metasm/dynldr.rb +1329 -0
  32. data/lib/metasm/encode.rb +333 -0
  33. data/lib/metasm/exe_format/a_out.rb +194 -0
  34. data/lib/metasm/exe_format/autoexe.rb +82 -0
  35. data/lib/metasm/exe_format/bflt.rb +189 -0
  36. data/lib/metasm/exe_format/coff.rb +455 -0
  37. data/lib/metasm/exe_format/coff_decode.rb +901 -0
  38. data/lib/metasm/exe_format/coff_encode.rb +1078 -0
  39. data/lib/metasm/exe_format/dex.rb +457 -0
  40. data/lib/metasm/exe_format/dol.rb +145 -0
  41. data/lib/metasm/exe_format/elf.rb +923 -0
  42. data/lib/metasm/exe_format/elf_decode.rb +979 -0
  43. data/lib/metasm/exe_format/elf_encode.rb +1375 -0
  44. data/lib/metasm/exe_format/macho.rb +827 -0
  45. data/lib/metasm/exe_format/main.rb +228 -0
  46. data/lib/metasm/exe_format/mz.rb +164 -0
  47. data/lib/metasm/exe_format/nds.rb +172 -0
  48. data/lib/metasm/exe_format/pe.rb +437 -0
  49. data/lib/metasm/exe_format/serialstruct.rb +246 -0
  50. data/lib/metasm/exe_format/shellcode.rb +114 -0
  51. data/lib/metasm/exe_format/xcoff.rb +167 -0
  52. data/lib/metasm/gui.rb +23 -0
  53. data/lib/metasm/gui/cstruct.rb +373 -0
  54. data/lib/metasm/gui/dasm_coverage.rb +199 -0
  55. data/lib/metasm/gui/dasm_decomp.rb +369 -0
  56. data/lib/metasm/gui/dasm_funcgraph.rb +103 -0
  57. data/lib/metasm/gui/dasm_graph.rb +1354 -0
  58. data/lib/metasm/gui/dasm_hex.rb +543 -0
  59. data/lib/metasm/gui/dasm_listing.rb +599 -0
  60. data/lib/metasm/gui/dasm_main.rb +906 -0
  61. data/lib/metasm/gui/dasm_opcodes.rb +291 -0
  62. data/lib/metasm/gui/debug.rb +1228 -0
  63. data/lib/metasm/gui/gtk.rb +884 -0
  64. data/lib/metasm/gui/qt.rb +495 -0
  65. data/lib/metasm/gui/win32.rb +3004 -0
  66. data/lib/metasm/gui/x11.rb +621 -0
  67. data/lib/metasm/ia32.rb +14 -0
  68. data/lib/metasm/ia32/compile_c.rb +1523 -0
  69. data/lib/metasm/ia32/debug.rb +193 -0
  70. data/lib/metasm/ia32/decode.rb +1167 -0
  71. data/lib/metasm/ia32/decompile.rb +564 -0
  72. data/lib/metasm/ia32/encode.rb +314 -0
  73. data/lib/metasm/ia32/main.rb +233 -0
  74. data/lib/metasm/ia32/opcodes.rb +872 -0
  75. data/lib/metasm/ia32/parse.rb +327 -0
  76. data/lib/metasm/ia32/render.rb +91 -0
  77. data/lib/metasm/main.rb +1193 -0
  78. data/lib/metasm/mips.rb +11 -0
  79. data/lib/metasm/mips/compile_c.rb +7 -0
  80. data/lib/metasm/mips/decode.rb +253 -0
  81. data/lib/metasm/mips/encode.rb +51 -0
  82. data/lib/metasm/mips/main.rb +72 -0
  83. data/lib/metasm/mips/opcodes.rb +443 -0
  84. data/lib/metasm/mips/parse.rb +51 -0
  85. data/lib/metasm/mips/render.rb +43 -0
  86. data/lib/metasm/os/gnu_exports.rb +270 -0
  87. data/lib/metasm/os/linux.rb +1112 -0
  88. data/lib/metasm/os/main.rb +1686 -0
  89. data/lib/metasm/os/remote.rb +527 -0
  90. data/lib/metasm/os/windows.rb +2027 -0
  91. data/lib/metasm/os/windows_exports.rb +745 -0
  92. data/lib/metasm/parse.rb +876 -0
  93. data/lib/metasm/parse_c.rb +3938 -0
  94. data/lib/metasm/pic16c/decode.rb +42 -0
  95. data/lib/metasm/pic16c/main.rb +17 -0
  96. data/lib/metasm/pic16c/opcodes.rb +68 -0
  97. data/lib/metasm/ppc.rb +11 -0
  98. data/lib/metasm/ppc/decode.rb +264 -0
  99. data/lib/metasm/ppc/decompile.rb +251 -0
  100. data/lib/metasm/ppc/encode.rb +51 -0
  101. data/lib/metasm/ppc/main.rb +129 -0
  102. data/lib/metasm/ppc/opcodes.rb +410 -0
  103. data/lib/metasm/ppc/parse.rb +52 -0
  104. data/lib/metasm/preprocessor.rb +1277 -0
  105. data/lib/metasm/render.rb +130 -0
  106. data/lib/metasm/sh4.rb +8 -0
  107. data/lib/metasm/sh4/decode.rb +336 -0
  108. data/lib/metasm/sh4/main.rb +292 -0
  109. data/lib/metasm/sh4/opcodes.rb +381 -0
  110. data/lib/metasm/x86_64.rb +12 -0
  111. data/lib/metasm/x86_64/compile_c.rb +1025 -0
  112. data/lib/metasm/x86_64/debug.rb +59 -0
  113. data/lib/metasm/x86_64/decode.rb +268 -0
  114. data/lib/metasm/x86_64/encode.rb +264 -0
  115. data/lib/metasm/x86_64/main.rb +135 -0
  116. data/lib/metasm/x86_64/opcodes.rb +118 -0
  117. data/lib/metasm/x86_64/parse.rb +68 -0
  118. data/misc/bottleneck.rb +61 -0
  119. data/misc/cheader-findpppath.rb +58 -0
  120. data/misc/hexdiff.rb +74 -0
  121. data/misc/hexdump.rb +55 -0
  122. data/misc/metasm-all.rb +13 -0
  123. data/misc/objdiff.rb +47 -0
  124. data/misc/objscan.rb +40 -0
  125. data/misc/pdfparse.rb +661 -0
  126. data/misc/ppc_pdf2oplist.rb +192 -0
  127. data/misc/tcp_proxy_hex.rb +84 -0
  128. data/misc/txt2html.rb +440 -0
  129. data/samples/a.out.rb +31 -0
  130. data/samples/asmsyntax.rb +77 -0
  131. data/samples/bindiff.rb +555 -0
  132. data/samples/compilation-steps.rb +49 -0
  133. data/samples/cparser_makestackoffset.rb +55 -0
  134. data/samples/dasm-backtrack.rb +38 -0
  135. data/samples/dasmnavig.rb +318 -0
  136. data/samples/dbg-apihook.rb +228 -0
  137. data/samples/dbghelp.rb +143 -0
  138. data/samples/disassemble-gui.rb +102 -0
  139. data/samples/disassemble.rb +133 -0
  140. data/samples/dump_upx.rb +95 -0
  141. data/samples/dynamic_ruby.rb +1929 -0
  142. data/samples/elf_list_needed.rb +46 -0
  143. data/samples/elf_listexports.rb +33 -0
  144. data/samples/elfencode.rb +25 -0
  145. data/samples/exeencode.rb +128 -0
  146. data/samples/factorize-headers-elfimports.rb +77 -0
  147. data/samples/factorize-headers-peimports.rb +109 -0
  148. data/samples/factorize-headers.rb +43 -0
  149. data/samples/gdbclient.rb +583 -0
  150. data/samples/generate_libsigs.rb +102 -0
  151. data/samples/hotfix_gtk_dbg.rb +59 -0
  152. data/samples/install_win_env.rb +78 -0
  153. data/samples/lindebug.rb +924 -0
  154. data/samples/linux_injectsyscall.rb +95 -0
  155. data/samples/machoencode.rb +31 -0
  156. data/samples/metasm-shell.rb +91 -0
  157. data/samples/pe-hook.rb +69 -0
  158. data/samples/pe-ia32-cpuid.rb +203 -0
  159. data/samples/pe-mips.rb +35 -0
  160. data/samples/pe-shutdown.rb +78 -0
  161. data/samples/pe-testrelocs.rb +51 -0
  162. data/samples/pe-testrsrc.rb +24 -0
  163. data/samples/pe_listexports.rb +31 -0
  164. data/samples/peencode.rb +19 -0
  165. data/samples/peldr.rb +494 -0
  166. data/samples/preprocess-flatten.rb +19 -0
  167. data/samples/r0trace.rb +308 -0
  168. data/samples/rubstop.rb +399 -0
  169. data/samples/scan_pt_gnu_stack.rb +54 -0
  170. data/samples/scanpeexports.rb +62 -0
  171. data/samples/shellcode-c.rb +40 -0
  172. data/samples/shellcode-dynlink.rb +146 -0
  173. data/samples/source.asm +34 -0
  174. data/samples/struct_offset.rb +47 -0
  175. data/samples/testpe.rb +32 -0
  176. data/samples/testraw.rb +45 -0
  177. data/samples/win32genloader.rb +132 -0
  178. data/samples/win32hooker-advanced.rb +169 -0
  179. data/samples/win32hooker.rb +96 -0
  180. data/samples/win32livedasm.rb +33 -0
  181. data/samples/win32remotescan.rb +133 -0
  182. data/samples/wintrace.rb +92 -0
  183. data/tests/all.rb +8 -0
  184. data/tests/dasm.rb +39 -0
  185. data/tests/dynldr.rb +35 -0
  186. data/tests/encodeddata.rb +132 -0
  187. data/tests/ia32.rb +82 -0
  188. data/tests/mips.rb +116 -0
  189. data/tests/parse_c.rb +239 -0
  190. data/tests/preprocessor.rb +269 -0
  191. data/tests/x86_64.rb +62 -0
  192. metadata +255 -0
@@ -0,0 +1,12 @@
1
+ # This file is part of Metasm, the Ruby assembly manipulation suite
2
+ # Copyright (C) 2006-2009 Yoann GUILLOT
3
+ #
4
+ # Licence is LGPL, see LICENCE in the top-level directory
5
+
6
+
7
+ require 'metasm/main'
8
+ require 'metasm/arm/parse'
9
+ require 'metasm/arm/encode'
10
+ require 'metasm/arm/decode'
11
+ require 'metasm/arm/render'
12
+ require 'metasm/arm/debug'
@@ -0,0 +1,39 @@
1
+ # This file is part of Metasm, the Ruby assembly manipulation suite
2
+ # Copyright (C) 2006-2009 Yoann GUILLOT
3
+ #
4
+ # Licence is LGPL, see LICENCE in the top-level directory
5
+
6
+
7
+ require 'metasm/arm/opcodes'
8
+
9
+ module Metasm
10
+ class ARM
11
+ def dbg_register_pc
12
+ @dbg_register_pc ||= :pc
13
+ end
14
+ def dbg_register_flags
15
+ @dbg_register_flags ||= :flags
16
+ end
17
+
18
+ def dbg_register_list
19
+ @dbg_register_list ||= [:r0, :r1, :r2, :r3, :r4, :r5, :r6, :r7, :r8, :r9, :r10, :r11, :r12, :sp, :lr, :pc]
20
+ end
21
+
22
+ def dbg_flag_list
23
+ @dbg_flag_list ||= []
24
+ end
25
+
26
+ def dbg_register_size
27
+ @dbg_register_size ||= Hash.new(32)
28
+ end
29
+
30
+ def dbg_need_stepover(dbg, addr, di)
31
+ di and di.opcode.props[:saveip]
32
+ end
33
+
34
+ def dbg_end_stepout(dbg, addr, di)
35
+ di and di.opcode.name == 'foobar' # TODO
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,167 @@
1
+ # This file is part of Metasm, the Ruby assembly manipulation suite
2
+ # Copyright (C) 2006-2009 Yoann GUILLOT
3
+ #
4
+ # Licence is LGPL, see LICENCE in the top-level directory
5
+
6
+ require 'metasm/arm/opcodes'
7
+ require 'metasm/decode'
8
+
9
+ module Metasm
10
+ class ARM
11
+ # create the bin_mask for a given opcode
12
+ def build_opcode_bin_mask(op)
13
+ # bit = 0 if can be mutated by an field value, 1 if fixed by opcode
14
+ op.bin_mask = 0
15
+ op.fields.each { |k, (m, s)|
16
+ op.bin_mask |= m << s
17
+ }
18
+ op.bin_mask = 0xffffffff ^ op.bin_mask
19
+ end
20
+
21
+ # create the lookaside hash from the first byte of the opcode
22
+ def build_bin_lookaside
23
+ lookaside = Array.new(256) { [] }
24
+
25
+ opcode_list.each { |op|
26
+ build_opcode_bin_mask op
27
+
28
+ b = (op.bin >> 20) & 0xff
29
+ msk = (op.bin_mask >> 20) & 0xff
30
+ b &= msk
31
+
32
+ for i in b..(b | (255^msk))
33
+ lookaside[i] << op if i & msk == b
34
+ end
35
+ }
36
+
37
+ lookaside
38
+ end
39
+
40
+ def decode_findopcode(edata)
41
+ return if edata.ptr >= edata.data.length
42
+ di = DecodedInstruction.new(self)
43
+ val = edata.decode_imm(:u32, @endianness)
44
+ di.instance_variable_set('@raw', val)
45
+ di if di.opcode = @bin_lookaside[(val >> 20) & 0xff].find { |op|
46
+ (not op.props[:cond] or
47
+ ((val >> @fields_shift[:cond]) & @fields_mask[:cond]) != 0xf) and
48
+ (op.bin & op.bin_mask) == (val & op.bin_mask)
49
+ }
50
+ end
51
+
52
+ def disassembler_default_func
53
+ df = DecodedFunction.new
54
+ df
55
+ end
56
+
57
+ def decode_instr_op(edata, di)
58
+ op = di.opcode
59
+ di.instruction.opname = op.name
60
+ val = di.instance_variable_get('@raw')
61
+
62
+ field_val = lambda { |f|
63
+ r = (val >> @fields_shift[f]) & @fields_mask[f]
64
+ case f
65
+ when :i16; Expression.make_signed(r, 16)
66
+ when :i24; Expression.make_signed(r, 24)
67
+ when :i8_12; ((r >> 4) & 0xf0) | (r & 0xf)
68
+ when :stype; [:lsl, :lsr, :asr, :ror][r]
69
+ when :u; [:-, :+][r]
70
+ else r
71
+ end
72
+ }
73
+
74
+ if op.props[:cond]
75
+ cd = %w[eq ne cs cc mi pl vs vc hi ls ge lt gt le al][field_val[:cond]]
76
+ if cd != 'al'
77
+ di.opcode = di.opcode.dup
78
+ di.instruction.opname = di.opcode.name.dup
79
+ di.instruction.opname[(op.props[:cond_name_off] || di.opcode.name.length), 0] = cd
80
+ if di.opcode.props[:stopexec]
81
+ di.opcode.props = di.opcode.props.dup
82
+ di.opcode.props.delete :stopexec
83
+ end
84
+ end
85
+ end
86
+
87
+ op.args.each { |a|
88
+ di.instruction.args << case a
89
+ when :rd, :rn, :rm; Reg.new field_val[a]
90
+ when :rm_rs; Reg.new field_val[:rm], field_val[:stype], Reg.new(field_val[:rs])
91
+ when :rm_is; Reg.new field_val[:rm], field_val[:stype], field_val[:shifti]*2
92
+ when :i24; Expression[field_val[a] << 2]
93
+ when :i8_r
94
+ i = field_val[:i8]
95
+ r = field_val[:rotate]*2
96
+ Expression[((i >> r) | (i << (32-r))) & 0xffff_ffff]
97
+ when :mem_rn_rm, :mem_rn_i8_12, :mem_rn_rms, :mem_rn_i12
98
+ b = Reg.new(field_val[:rn])
99
+ o = case a
100
+ when :mem_rn_rm; Reg.new(field_val[:rm])
101
+ when :mem_rn_i8_12; field_val[:i8_12]
102
+ when :mem_rn_rms; Reg.new(field_val[:rm], field_val[:stype], field_val[:shifti]*2)
103
+ when :mem_rn_i12; field_val[:i12]
104
+ end
105
+ Memref.new(b, o, field_val[:u], op.props[:baseincr])
106
+ when :reglist
107
+ di.instruction.args.last.updated = true if op.props[:baseincr]
108
+ msk = field_val[a]
109
+ l = RegList.new((0..15).map { |i| Reg.new(i) if (msk & (1 << i)) > 0 }.compact)
110
+ l.usermoderegs = true if op.props[:usermoderegs]
111
+ l
112
+ else raise SyntaxError, "Internal error: invalid argument #{a} in #{op.name}"
113
+ end
114
+ }
115
+
116
+ di.bin_length = 4
117
+ di
118
+ end
119
+
120
+ def decode_instr_interpret(di, addr)
121
+ if di.opcode.args.include? :i24
122
+ di.instruction.args[-1] = Expression[di.instruction.args[-1] + addr + 8]
123
+ end
124
+ di
125
+ end
126
+
127
+ def backtrace_binding
128
+ @backtrace_binding ||= init_backtrace_binding
129
+ end
130
+
131
+ def init_backtrace_binding
132
+ @backtrace_binding ||= {}
133
+ end
134
+
135
+ def get_backtrace_binding(di)
136
+ a = di.instruction.args.map { |arg|
137
+ case arg
138
+ when Reg; arg.symbolic
139
+ when Memref; arg.symbolic(di.address)
140
+ else arg
141
+ end
142
+ }
143
+
144
+ if binding = backtrace_binding[di.opcode.name]
145
+ bd = binding[di, *a]
146
+ else
147
+ puts "unhandled instruction to backtrace: #{di}" if $VERBOSE
148
+ # assume nothing except the 1st arg is modified
149
+ case a[0]
150
+ when Indirection, Symbol; { a[0] => Expression::Unknown }
151
+ when Expression; (x = a[0].externals.first) ? { x => Expression::Unknown } : {}
152
+ else {}
153
+ end.update(:incomplete_binding => Expression[1])
154
+ end
155
+
156
+ end
157
+
158
+ def get_xrefs_x(dasm, di)
159
+ if di.opcode.props[:setip]
160
+ [di.instruction.args.last]
161
+ else
162
+ # TODO ldr pc, ..
163
+ []
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,77 @@
1
+ # This file is part of Metasm, the Ruby assembly manipulation suite
2
+ # Copyright (C) 2006-2009 Yoann GUILLOT
3
+ #
4
+ # Licence is LGPL, see LICENCE in the top-level directory
5
+
6
+
7
+ require 'metasm/arm/opcodes'
8
+ require 'metasm/encode'
9
+
10
+ module Metasm
11
+ class ARM
12
+ def encode_instr_op(section, instr, op)
13
+ base = op.bin
14
+ set_field = lambda { |f, v|
15
+ v = v.reduce if v.kind_of? Expression
16
+ case f
17
+ when :i8_12
18
+ base = Expression[base, :|, [[v, :&, 0xf], :|, [[v, :<<, 4], :&, 0xf00]]]
19
+ next
20
+ when :stype; v = [:lsl, :lsr, :asr, :ror].index(v)
21
+ when :u; v = [:-, :+].index(v)
22
+ end
23
+ base = Expression[base, :|, [[v, :&, @fields_mask[f]], :<<, @fields_shift[f]]]
24
+ }
25
+
26
+ val, mask, shift = 0, 0, 0
27
+
28
+ if op.props[:cond]
29
+ coff = op.props[:cond_name_off] || op.name.length
30
+ cd = instr.opname[coff, 2]
31
+ cdi = %w[eq ne cs cc mi pl vs vc hi ls ge lt gt le al].index(cd) || 14 # default = al
32
+ set_field[:cond, cdi]
33
+ end
34
+
35
+ op.args.zip(instr.args).each { |sym, arg|
36
+ case sym
37
+ when :rd, :rs, :rn, :rm; set_field[sym, arg.i]
38
+ when :rm_rs
39
+ set_field[:rm, arg.i]
40
+ set_field[:stype, arg.stype]
41
+ set_field[:rs, arg.shift.i]
42
+ when :rm_is
43
+ set_field[:rm, arg.i]
44
+ set_field[:stype, arg.stype]
45
+ set_field[:shifti, arg.shift/2]
46
+ when :mem_rn_rm, :mem_rn_rms, :mem_rn_i8_12, :mem_rn_i12
47
+ set_field[:rn, arg.base.i]
48
+ case sym
49
+ when :mem_rn_rm
50
+ set_field[:rm, arg.offset.i]
51
+ when :mem_rn_rms
52
+ set_field[:rm, arg.offset.i]
53
+ set_field[:stype, arg.offset.stype]
54
+ set_field[:rs, arg.offset.shift.i]
55
+ when :mem_rn_i8_12
56
+ set_field[:i8_12, arg.offset]
57
+ when :mem_rn_i12
58
+ set_field[:i12, arg.offset]
59
+ end
60
+ # TODO set_field[:u] etc
61
+ when :reglist
62
+ set_field[sym, arg.list.inject(0) { |rl, r| rl | (1 << r.i) }]
63
+ when :i8_r
64
+ # XXX doublecheck this
65
+ b = arg.reduce & 0xffffffff
66
+ r = (0..15).find { next true if b < 0x10 ; b = (b >> 2) | ((b & 3) << 30) }
67
+ set_field[:i8, b]
68
+ set_field[:rotate, r]
69
+ when :i16, :i24
70
+ val, mask, shift = arg, @fields_mask[sym], @fields_shift[sym]
71
+ end
72
+ }
73
+
74
+ Expression[base, :|, [[val, :<<, shift], :&, mask]].encode(:u32, @endianness)
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,75 @@
1
+ # This file is part of Metasm, the Ruby assembly manipulation suite
2
+ # Copyright (C) 2006-2009 Yoann GUILLOT
3
+ #
4
+ # Licence is LGPL, see LICENCE in the top-level directory
5
+
6
+
7
+ require 'metasm/main'
8
+
9
+ module Metasm
10
+ class ARM < CPU
11
+ class Reg
12
+ class << self
13
+ attr_accessor :s_to_i, :i_to_s
14
+ end
15
+ @i_to_s = %w[r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 sp lr pc]
16
+ @s_to_i = { 'wr' => 7, 'sb' => 9, 'sl' => 10, 'fp' => 11, 'ip' => 12, 'sp' => 13, 'lr' => 14, 'pc' => 15 }
17
+ 15.times { |i| @s_to_i["r#{i}"] = i }
18
+ 4.times { |i| @s_to_i["a#{i+1}"] = i }
19
+ 8.times { |i| @s_to_i["v#{i+1}"] = i+4 }
20
+
21
+ attr_accessor :i, :stype, :shift, :updated
22
+ def initialize(i, stype=:lsl, shift=0)
23
+ @i = i
24
+ @stype = stype
25
+ @shift = shift
26
+ end
27
+
28
+ def symbolic
29
+ r = self.class.i_to_s[@i].to_sym
30
+ if @stype == :lsl and @shift == 0
31
+ r
32
+ else
33
+ r # TODO shift/rotate/...
34
+ end
35
+ end
36
+ end
37
+
38
+ class Memref
39
+ attr_accessor :base, :offset, :sign, :incr
40
+ def initialize(base, offset, sign=:+, incr=nil)
41
+ @base, @offset, @sign, @incr = base, offset, sign, incr
42
+ end
43
+
44
+ def symbolic(len=4, orig=nil)
45
+ o = @offset
46
+ o = o.symbolic if o.kind_of? Reg
47
+ p = Expression[@base.symbolic, @sign, o].reduce
48
+ Indirection[p, len, orig]
49
+ end
50
+ end
51
+
52
+ class RegList
53
+ attr_accessor :list, :usermoderegs
54
+
55
+ def initialize(l=[])
56
+ @list = l
57
+ end
58
+ end
59
+
60
+ def initialize(endianness = :little)
61
+ super()
62
+ @endianness = endianness
63
+ @size = 32
64
+ end
65
+
66
+ def init_opcode_list
67
+ init_latest
68
+ @opcode_list
69
+ end
70
+ end
71
+
72
+ class ARM_THUMB < ARM
73
+ end
74
+ end
75
+
@@ -0,0 +1,177 @@
1
+ # This file is part of Metasm, the Ruby assembly manipulation suite
2
+ # Copyright (C) 2006-2009 Yoann GUILLOT
3
+ #
4
+ # Licence is LGPL, see LICENCE in the top-level directory
5
+
6
+
7
+ require 'metasm/arm/main'
8
+
9
+ module Metasm
10
+ class ARM
11
+ private
12
+ def addop(name, bin, *args)
13
+ args << :cond if not args.delete :uncond
14
+
15
+ o = Opcode.new name, bin
16
+ o.args.concat(args & @valid_args)
17
+ (args & @valid_props).each { |p| o.props[p] = true }
18
+ args.grep(Hash).each { |h| o.props.update h }
19
+
20
+ # special args -> multiple fields
21
+ case (o.args & [:i8_r, :rm_is, :rm_rs, :mem_rn_rm, :mem_rn_i8_12, :mem_rn_rms, :mem_rn_i12]).first
22
+ when :i8_r; args << :i8 << :rotate
23
+ when :rm_is; args << :rm << :stype << :shifti
24
+ when :rm_rs; args << :rm << :stype << :rs
25
+ when :mem_rn_rm; args << :rn << :rm << :rsx << :u
26
+ when :mem_rn_i8_12; args << :rn << :i8_12 << :u
27
+ when :mem_rn_rms; args << :rn << :rm << :stype << :shifti << :u
28
+ when :mem_rn_i12; args << :rn << :i12 << :u
29
+ end
30
+
31
+ (args & @fields_mask.keys).each { |f|
32
+ o.fields[f] = [@fields_mask[f], @fields_shift[f]]
33
+ }
34
+
35
+ @opcode_list << o
36
+ end
37
+
38
+ def addop_data_s(name, op, a1, a2, *h)
39
+ addop name, op | (1 << 25), a1, a2, :i8_r, :rotate, *h
40
+ addop name, op, a1, a2, :rm_is, *h
41
+ addop name, op | (1 << 4), a1, a2, :rm_rs, *h
42
+ end
43
+ def addop_data(name, op, a1, a2)
44
+ addop_data_s name, op << 21, a1, a2
45
+ addop_data_s name+'s', (op << 21) | (1 << 20), a1, a2, :cond_name_off => name.length
46
+ end
47
+
48
+ def addop_load_puw(name, op, *a)
49
+ addop name, op, {:baseincr => :post}, :rd, :u, *a
50
+ addop name, op | (1 << 24), :rd, :u, *a
51
+ addop name, op | (1 << 24) | (1 << 21), {:baseincr => :pre}, :rd, :u, *a
52
+ end
53
+ def addop_load_lsh_o(name, op)
54
+ addop_load_puw name, op, :rsz, :mem_rn_rm, {:cond_name_off => 3}
55
+ addop_load_puw name, op | (1 << 22), :mem_rn_i8_12, {:cond_name_off => 3}
56
+ end
57
+ def addop_load_lsh
58
+ op = 9 << 4
59
+ addop_load_lsh_o 'strh', op | (1 << 5)
60
+ addop_load_lsh_o 'ldrd', op | (1 << 6)
61
+ addop_load_lsh_o 'strd', op | (1 << 6) | (1 << 5)
62
+ addop_load_lsh_o 'ldrh', op | (1 << 20) | (1 << 5)
63
+ addop_load_lsh_o 'ldrsb', op | (1 << 20) | (1 << 6)
64
+ addop_load_lsh_o 'ldrsh', op | (1 << 20) | (1 << 6) | (1 << 5)
65
+ end
66
+
67
+ def addop_load_puwt(name, op, *a)
68
+ addop_load_puw name, op, *a
69
+ addop name+'t', op | (1 << 21), {:baseincr => :post, :cond_name_off => name.length}, :rd, :u, *a
70
+ end
71
+ def addop_load_o(name, op, *a)
72
+ addop_load_puwt name, op, :mem_rn_i12, *a
73
+ addop_load_puwt name, op | (1 << 25), :mem_rn_rms, *a
74
+ end
75
+ def addop_load(name, op)
76
+ addop_load_o name, op
77
+ addop_load_o name+'b', op | (1 << 22), :cond_name_off => name.length
78
+ end
79
+
80
+ def addop_ldm_go(name, op, *a)
81
+ addop name, op, :rn, :reglist, {:cond_name_off => 3}, *a
82
+ end
83
+ def addop_ldm_w(name, op, *a)
84
+ addop_ldm_go name, op, *a # base reg untouched
85
+ addop_ldm_go name, op | (1 << 21), {:baseincr => :post}, *a # base updated
86
+ end
87
+ def addop_ldm_s(name, op)
88
+ addop_ldm_w name, op # transfer regs
89
+ addop_ldm_w name, op | (1 << 22), :usermoderegs # transfer usermode regs
90
+ end
91
+ def addop_ldm_p(name, op)
92
+ addop_ldm_s name+'a', op # target memory included
93
+ addop_ldm_s name+'b', op | (1 << 24) # target memory excluded, transfer starts at next addr
94
+ end
95
+ def addop_ldm_u(name, op)
96
+ addop_ldm_p name+'d', op # transfer made downward
97
+ addop_ldm_p name+'i', op | (1 << 23) # transfer made upward
98
+ end
99
+ def addop_ldm(name, op)
100
+ addop_ldm_u name, op
101
+ end
102
+
103
+ # ARMv6 instruction set, aka arm7/arm9
104
+ def init_arm_v6
105
+ @opcode_list = []
106
+ @valid_props << :baseincr << :cond << :cond_name_off << :usermoderegs <<
107
+ :tothumb << :tojazelle
108
+ @valid_args.concat [:rn, :rd, :rm, :crn, :crd, :crm, :cpn, :reglist, :i24,
109
+ :rm_rs, :rm_is, :i8_r, :mem_rn_rm, :mem_rn_i8_12, :mem_rn_rms, :mem_rn_i12]
110
+ @fields_mask.update :rn => 0xf, :rd => 0xf, :rs => 0xf, :rm => 0xf,
111
+ :crn => 0xf, :crd => 0xf, :crm => 0xf, :cpn => 0xf,
112
+ :rnx => 0xf, :rdx => 0xf, :rsx => 0xf,
113
+ :shifti => 0x1f, :stype => 3, :rotate => 0xf, :reglist => 0xffff,
114
+ :i8 => 0xff, :i12 => 0xfff, :i24 => 0xff_ffff, :i8_12 => 0xf0f,
115
+ :u => 1, :mask => 0xf, :sbo => 0xf, :cond => 0xf
116
+
117
+ @fields_shift.update :rn => 16, :rd => 12, :rs => 8, :rm => 0,
118
+ :crn => 16, :crd => 12, :crm => 0, :cpn => 8,
119
+ :rnx => 16, :rdx => 12, :rsx => 8,
120
+ :shifti => 7, :stype => 5, :rotate => 8, :reglist => 0,
121
+ :i8 => 0, :i12 => 0, :i24 => 0, :i8_12 => 0,
122
+ :u => 23, :mask => 16, :sbo => 12, :cond => 28
123
+
124
+ addop_data 'and', 0, :rd, :rn
125
+ addop_data 'eor', 1, :rd, :rn
126
+ addop_data 'xor', 1, :rd, :rn
127
+ addop_data 'sub', 2, :rd, :rn
128
+ addop_data 'rsb', 3, :rd, :rn
129
+ addop_data 'add', 4, :rd, :rn
130
+ addop_data 'adc', 5, :rd, :rn
131
+ addop_data 'sbc', 6, :rd, :rn
132
+ addop_data 'rsc', 7, :rd, :rn
133
+ addop_data 'tst', 8, :rdx, :rn
134
+ addop_data 'teq', 9, :rdx, :rn
135
+ addop_data 'cmp', 10, :rdx, :rn
136
+ addop_data 'cmn', 11, :rdx, :rn
137
+ addop_data 'orr', 12, :rd, :rn
138
+ addop_data 'or', 12, :rd, :rn
139
+ addop_data 'mov', 13, :rd, :rnx
140
+ addop_data 'bic', 14, :rd, :rn
141
+ addop_data 'mvn', 15, :rd, :rnx
142
+
143
+ addop 'b', 0b1010 << 24, :setip, :stopexec, :i24
144
+ addop 'bl', 0b1011 << 24, :setip, :stopexec, :i24, :saveip
145
+ addop 'bkpt', (0b00010010 << 20) | (0b0111 << 4) # other fields are available&unused, also cnd != AL is undef
146
+ addop 'blx', 0b1111101 << 25, :setip, :stopexec, :saveip, :tothumb, :h, :nocond, :i24
147
+ addop 'blx', (0b00010010 << 20) | (0b0011 << 4), :setip, :stopexec, :saveip, :tothumb, :rm
148
+ addop 'bx', (0b00010010 << 20) | (0b0001 << 4), :setip, :stopexec, :rm
149
+ addop 'bxj', (0b00010010 << 20) | (0b0010 << 4), :setip, :stopexec, :rm, :tojazelle
150
+
151
+ addop_load 'str', (1 << 26)
152
+ addop_load 'ldr', (1 << 26) | (1 << 20)
153
+ addop_load_lsh
154
+ addop_ldm 'stm', (1 << 27)
155
+ addop_ldm 'ldm', (1 << 27) | (1 << 20)
156
+ end
157
+ alias init_latest init_arm_v6
158
+ end
159
+ end
160
+
161
+ __END__
162
+ addop_cond 'mrs', 0b0001000011110000000000000000, :rd
163
+ addop_cond 'msr', 0b0001001010011111000000000000, :rd
164
+ addop_cond 'msrf', 0b0001001010001111000000000000, :rd
165
+
166
+ addop_cond 'mul', 0b000000000000001001 << 4, :rd, :rn, :rs, :rm
167
+ addop_cond 'mla', 0b100000000000001001 << 4, :rd, :rn, :rs, :rm
168
+
169
+ addop_cond 'swp', 0b0001000000000000000010010000, :rd, :rn, :rs, :rm
170
+ addop_cond 'swpb', 0b0001010000000000000010010000, :rd, :rn, :rs, :rm
171
+
172
+ addop_cond 'undef', 0b00000110000000000000000000010000
173
+
174
+ addop_cond 'swi', 0b00001111 << 24
175
+
176
+ addop_cond 'bkpt', 0b1001000000000000001110000
177
+ addop_cond 'movw', 0b0011 << 24, :movwimm