metasm 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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