metasm 1.0.1 → 1.0.2

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 (235) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.hgtags +3 -0
  4. data/Gemfile +1 -0
  5. data/INSTALL +61 -0
  6. data/LICENCE +458 -0
  7. data/README +29 -21
  8. data/Rakefile +10 -0
  9. data/TODO +10 -12
  10. data/doc/code_organisation.txt +2 -0
  11. data/doc/core/DynLdr.txt +247 -0
  12. data/doc/core/ExeFormat.txt +43 -0
  13. data/doc/core/Expression.txt +220 -0
  14. data/doc/core/GNUExports.txt +27 -0
  15. data/doc/core/Ia32.txt +236 -0
  16. data/doc/core/SerialStruct.txt +108 -0
  17. data/doc/core/VirtualString.txt +145 -0
  18. data/doc/core/WindowsExports.txt +61 -0
  19. data/doc/core/index.txt +1 -0
  20. data/doc/style.css +6 -3
  21. data/doc/usage/debugger.txt +327 -0
  22. data/doc/usage/index.txt +1 -0
  23. data/doc/use_cases.txt +2 -2
  24. data/metasm.gemspec +22 -0
  25. data/{lib/metasm.rb → metasm.rb} +11 -3
  26. data/{lib/metasm → metasm}/compile_c.rb +13 -7
  27. data/metasm/cpu/arc.rb +8 -0
  28. data/metasm/cpu/arc/decode.rb +425 -0
  29. data/metasm/cpu/arc/main.rb +191 -0
  30. data/metasm/cpu/arc/opcodes.rb +588 -0
  31. data/{lib/metasm → metasm/cpu}/arm.rb +7 -5
  32. data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
  33. data/{lib/metasm → metasm/cpu}/arm/decode.rb +13 -12
  34. data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
  35. data/{lib/metasm → metasm/cpu}/arm/main.rb +0 -3
  36. data/metasm/cpu/arm/opcodes.rb +324 -0
  37. data/{lib/metasm → metasm/cpu}/arm/parse.rb +25 -13
  38. data/{lib/metasm → metasm/cpu}/arm/render.rb +2 -2
  39. data/metasm/cpu/arm64.rb +15 -0
  40. data/metasm/cpu/arm64/debug.rb +38 -0
  41. data/metasm/cpu/arm64/decode.rb +289 -0
  42. data/metasm/cpu/arm64/encode.rb +41 -0
  43. data/metasm/cpu/arm64/main.rb +105 -0
  44. data/metasm/cpu/arm64/opcodes.rb +232 -0
  45. data/metasm/cpu/arm64/parse.rb +20 -0
  46. data/metasm/cpu/arm64/render.rb +95 -0
  47. data/{lib/metasm/ppc.rb → metasm/cpu/bpf.rb} +2 -4
  48. data/metasm/cpu/bpf/decode.rb +142 -0
  49. data/metasm/cpu/bpf/main.rb +60 -0
  50. data/metasm/cpu/bpf/opcodes.rb +81 -0
  51. data/metasm/cpu/bpf/render.rb +41 -0
  52. data/metasm/cpu/cy16.rb +9 -0
  53. data/metasm/cpu/cy16/decode.rb +253 -0
  54. data/metasm/cpu/cy16/main.rb +63 -0
  55. data/metasm/cpu/cy16/opcodes.rb +78 -0
  56. data/metasm/cpu/cy16/render.rb +41 -0
  57. data/metasm/cpu/dalvik.rb +11 -0
  58. data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +35 -13
  59. data/{lib/metasm → metasm/cpu}/dalvik/main.rb +51 -2
  60. data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +19 -11
  61. data/metasm/cpu/ia32.rb +17 -0
  62. data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +5 -7
  63. data/{lib/metasm → metasm/cpu}/ia32/debug.rb +5 -5
  64. data/{lib/metasm → metasm/cpu}/ia32/decode.rb +246 -59
  65. data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +7 -7
  66. data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
  67. data/{lib/metasm → metasm/cpu}/ia32/main.rb +51 -8
  68. data/metasm/cpu/ia32/opcodes.rb +1424 -0
  69. data/{lib/metasm → metasm/cpu}/ia32/parse.rb +47 -16
  70. data/{lib/metasm → metasm/cpu}/ia32/render.rb +31 -4
  71. data/metasm/cpu/mips.rb +14 -0
  72. data/{lib/metasm → metasm/cpu}/mips/compile_c.rb +1 -1
  73. data/metasm/cpu/mips/debug.rb +42 -0
  74. data/{lib/metasm → metasm/cpu}/mips/decode.rb +46 -16
  75. data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
  76. data/{lib/metasm → metasm/cpu}/mips/main.rb +11 -4
  77. data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +86 -17
  78. data/{lib/metasm → metasm/cpu}/mips/parse.rb +1 -1
  79. data/{lib/metasm → metasm/cpu}/mips/render.rb +1 -1
  80. data/{lib/metasm/dalvik.rb → metasm/cpu/msp430.rb} +1 -1
  81. data/metasm/cpu/msp430/decode.rb +247 -0
  82. data/metasm/cpu/msp430/main.rb +62 -0
  83. data/metasm/cpu/msp430/opcodes.rb +101 -0
  84. data/{lib/metasm → metasm/cpu}/pic16c/decode.rb +6 -7
  85. data/{lib/metasm → metasm/cpu}/pic16c/main.rb +0 -0
  86. data/{lib/metasm → metasm/cpu}/pic16c/opcodes.rb +1 -1
  87. data/{lib/metasm/mips.rb → metasm/cpu/ppc.rb} +4 -4
  88. data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -12
  89. data/{lib/metasm → metasm/cpu}/ppc/decompile.rb +3 -3
  90. data/{lib/metasm → metasm/cpu}/ppc/encode.rb +2 -2
  91. data/{lib/metasm → metasm/cpu}/ppc/main.rb +17 -12
  92. data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -5
  93. data/metasm/cpu/ppc/parse.rb +55 -0
  94. data/metasm/cpu/python.rb +8 -0
  95. data/metasm/cpu/python/decode.rb +136 -0
  96. data/metasm/cpu/python/main.rb +36 -0
  97. data/metasm/cpu/python/opcodes.rb +180 -0
  98. data/{lib/metasm → metasm/cpu}/sh4.rb +1 -1
  99. data/{lib/metasm → metasm/cpu}/sh4/decode.rb +48 -17
  100. data/{lib/metasm → metasm/cpu}/sh4/main.rb +13 -4
  101. data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
  102. data/metasm/cpu/x86_64.rb +15 -0
  103. data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +28 -17
  104. data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
  105. data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +57 -15
  106. data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +55 -26
  107. data/{lib/metasm → metasm/cpu}/x86_64/main.rb +14 -6
  108. data/metasm/cpu/x86_64/opcodes.rb +136 -0
  109. data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +10 -2
  110. data/metasm/cpu/x86_64/render.rb +35 -0
  111. data/metasm/cpu/z80.rb +9 -0
  112. data/metasm/cpu/z80/decode.rb +313 -0
  113. data/metasm/cpu/z80/main.rb +67 -0
  114. data/metasm/cpu/z80/opcodes.rb +224 -0
  115. data/metasm/cpu/z80/render.rb +59 -0
  116. data/{lib/metasm/os/main.rb → metasm/debug.rb} +160 -401
  117. data/{lib/metasm → metasm}/decode.rb +35 -4
  118. data/{lib/metasm → metasm}/decompile.rb +15 -16
  119. data/{lib/metasm → metasm}/disassemble.rb +201 -45
  120. data/{lib/metasm → metasm}/disassemble_api.rb +651 -87
  121. data/{lib/metasm → metasm}/dynldr.rb +220 -133
  122. data/{lib/metasm → metasm}/encode.rb +10 -1
  123. data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
  124. data/{lib/metasm → metasm}/exe_format/autoexe.rb +1 -0
  125. data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
  126. data/{lib/metasm → metasm}/exe_format/coff.rb +11 -3
  127. data/{lib/metasm → metasm}/exe_format/coff_decode.rb +53 -20
  128. data/{lib/metasm → metasm}/exe_format/coff_encode.rb +11 -13
  129. data/{lib/metasm → metasm}/exe_format/dex.rb +13 -5
  130. data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
  131. data/{lib/metasm → metasm}/exe_format/elf.rb +93 -57
  132. data/{lib/metasm → metasm}/exe_format/elf_decode.rb +143 -34
  133. data/{lib/metasm → metasm}/exe_format/elf_encode.rb +122 -31
  134. data/metasm/exe_format/gb.rb +65 -0
  135. data/metasm/exe_format/javaclass.rb +424 -0
  136. data/{lib/metasm → metasm}/exe_format/macho.rb +204 -16
  137. data/{lib/metasm → metasm}/exe_format/main.rb +26 -3
  138. data/{lib/metasm → metasm}/exe_format/mz.rb +1 -0
  139. data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
  140. data/{lib/metasm → metasm}/exe_format/pe.rb +71 -8
  141. data/metasm/exe_format/pyc.rb +167 -0
  142. data/{lib/metasm → metasm}/exe_format/serialstruct.rb +67 -14
  143. data/{lib/metasm → metasm}/exe_format/shellcode.rb +7 -3
  144. data/metasm/exe_format/shellcode_rwx.rb +114 -0
  145. data/metasm/exe_format/swf.rb +205 -0
  146. data/{lib/metasm → metasm}/exe_format/xcoff.rb +7 -7
  147. data/metasm/exe_format/zip.rb +335 -0
  148. data/metasm/gui.rb +13 -0
  149. data/{lib/metasm → metasm}/gui/cstruct.rb +35 -41
  150. data/{lib/metasm → metasm}/gui/dasm_coverage.rb +11 -11
  151. data/{lib/metasm → metasm}/gui/dasm_decomp.rb +7 -20
  152. data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
  153. data/metasm/gui/dasm_graph.rb +1695 -0
  154. data/{lib/metasm → metasm}/gui/dasm_hex.rb +12 -8
  155. data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
  156. data/{lib/metasm → metasm}/gui/dasm_main.rb +310 -53
  157. data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
  158. data/{lib/metasm → metasm}/gui/debug.rb +93 -27
  159. data/{lib/metasm → metasm}/gui/gtk.rb +162 -40
  160. data/{lib/metasm → metasm}/gui/qt.rb +12 -2
  161. data/{lib/metasm → metasm}/gui/win32.rb +179 -42
  162. data/{lib/metasm → metasm}/gui/x11.rb +59 -59
  163. data/{lib/metasm → metasm}/main.rb +389 -264
  164. data/{lib/metasm/os/remote.rb → metasm/os/gdbremote.rb} +146 -54
  165. data/{lib/metasm → metasm}/os/gnu_exports.rb +1 -1
  166. data/{lib/metasm → metasm}/os/linux.rb +628 -151
  167. data/metasm/os/main.rb +330 -0
  168. data/{lib/metasm → metasm}/os/windows.rb +132 -42
  169. data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
  170. data/{lib/metasm → metasm}/parse.rb +26 -24
  171. data/{lib/metasm → metasm}/parse_c.rb +221 -116
  172. data/{lib/metasm → metasm}/preprocessor.rb +55 -40
  173. data/{lib/metasm → metasm}/render.rb +14 -38
  174. data/misc/hexdump.rb +2 -1
  175. data/misc/lint.rb +58 -0
  176. data/misc/txt2html.rb +9 -7
  177. data/samples/bindiff.rb +3 -4
  178. data/samples/dasm-plugins/bindiff.rb +15 -0
  179. data/samples/dasm-plugins/bookmark.rb +133 -0
  180. data/samples/dasm-plugins/c_constants.rb +57 -0
  181. data/samples/dasm-plugins/colortheme_solarized.rb +125 -0
  182. data/samples/dasm-plugins/cppobj_funcall.rb +60 -0
  183. data/samples/dasm-plugins/dasm_all.rb +70 -0
  184. data/samples/dasm-plugins/demangle_cpp.rb +31 -0
  185. data/samples/dasm-plugins/deobfuscate.rb +251 -0
  186. data/samples/dasm-plugins/dump_text.rb +35 -0
  187. data/samples/dasm-plugins/export_graph_svg.rb +86 -0
  188. data/samples/dasm-plugins/findgadget.rb +75 -0
  189. data/samples/dasm-plugins/hl_opcode.rb +32 -0
  190. data/samples/dasm-plugins/hotfix_gtk_dbg.rb +19 -0
  191. data/samples/dasm-plugins/imm2off.rb +34 -0
  192. data/samples/dasm-plugins/match_libsigs.rb +93 -0
  193. data/samples/dasm-plugins/patch_file.rb +95 -0
  194. data/samples/dasm-plugins/scanfuncstart.rb +36 -0
  195. data/samples/dasm-plugins/scanxrefs.rb +26 -0
  196. data/samples/dasm-plugins/selfmodify.rb +197 -0
  197. data/samples/dasm-plugins/stringsxrefs.rb +28 -0
  198. data/samples/dasmnavig.rb +1 -1
  199. data/samples/dbg-apihook.rb +24 -9
  200. data/samples/dbg-plugins/heapscan.rb +283 -0
  201. data/samples/dbg-plugins/heapscan/compiled_heapscan_lin.c +155 -0
  202. data/samples/dbg-plugins/heapscan/compiled_heapscan_win.c +128 -0
  203. data/samples/dbg-plugins/heapscan/graphheap.rb +616 -0
  204. data/samples/dbg-plugins/heapscan/heapscan.rb +709 -0
  205. data/samples/dbg-plugins/heapscan/winheap.h +174 -0
  206. data/samples/dbg-plugins/heapscan/winheap7.h +307 -0
  207. data/samples/dbg-plugins/trace_func.rb +214 -0
  208. data/samples/disassemble-gui.rb +35 -5
  209. data/samples/disassemble.rb +31 -6
  210. data/samples/dump_upx.rb +24 -12
  211. data/samples/dynamic_ruby.rb +12 -3
  212. data/samples/exeencode.rb +6 -5
  213. data/samples/factorize-headers-peimports.rb +1 -1
  214. data/samples/lindebug.rb +175 -381
  215. data/samples/metasm-shell.rb +1 -2
  216. data/samples/peldr.rb +2 -2
  217. data/tests/all.rb +1 -1
  218. data/tests/arc.rb +26 -0
  219. data/tests/dynldr.rb +22 -4
  220. data/tests/expression.rb +55 -0
  221. data/tests/graph_layout.rb +285 -0
  222. data/tests/ia32.rb +79 -26
  223. data/tests/mips.rb +9 -2
  224. data/tests/x86_64.rb +66 -18
  225. metadata +330 -218
  226. data/lib/metasm/arm/opcodes.rb +0 -177
  227. data/lib/metasm/gui.rb +0 -23
  228. data/lib/metasm/gui/dasm_graph.rb +0 -1354
  229. data/lib/metasm/ia32.rb +0 -14
  230. data/lib/metasm/ia32/opcodes.rb +0 -873
  231. data/lib/metasm/ppc/parse.rb +0 -52
  232. data/lib/metasm/x86_64.rb +0 -12
  233. data/lib/metasm/x86_64/opcodes.rb +0 -118
  234. data/samples/gdbclient.rb +0 -583
  235. data/samples/rubstop.rb +0 -399
@@ -3,10 +3,12 @@
3
3
  #
4
4
  # Licence is LGPL, see LICENCE in the top-level directory
5
5
 
6
+ class Metasm::ARM < Metasm::CPU
7
+ end
6
8
 
7
9
  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'
10
+ require 'metasm/cpu/arm/parse'
11
+ require 'metasm/cpu/arm/encode'
12
+ require 'metasm/cpu/arm/decode'
13
+ require 'metasm/cpu/arm/render'
14
+ require 'metasm/cpu/arm/debug'
@@ -4,7 +4,7 @@
4
4
  # Licence is LGPL, see LICENCE in the top-level directory
5
5
 
6
6
 
7
- require 'metasm/arm/opcodes'
7
+ require 'metasm/cpu/arm/opcodes'
8
8
 
9
9
  module Metasm
10
10
  class ARM
@@ -15,7 +15,7 @@ class ARM
15
15
  @dbg_register_flags ||= :flags
16
16
  end
17
17
 
18
- def dbg_register_list
18
+ def dbg_register_list
19
19
  @dbg_register_list ||= [:r0, :r1, :r2, :r3, :r4, :r5, :r6, :r7, :r8, :r9, :r10, :r11, :r12, :sp, :lr, :pc]
20
20
  end
21
21
 
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # Licence is LGPL, see LICENCE in the top-level directory
5
5
 
6
- require 'metasm/arm/opcodes'
6
+ require 'metasm/cpu/arm/opcodes'
7
7
  require 'metasm/decode'
8
8
 
9
9
  module Metasm
@@ -38,7 +38,7 @@ class ARM
38
38
  end
39
39
 
40
40
  def decode_findopcode(edata)
41
- return if edata.ptr >= edata.data.length
41
+ return if edata.ptr+4 > edata.length
42
42
  di = DecodedInstruction.new(self)
43
43
  val = edata.decode_imm(:u32, @endianness)
44
44
  di.instance_variable_set('@raw', val)
@@ -58,11 +58,11 @@ class ARM
58
58
  op = di.opcode
59
59
  di.instruction.opname = op.name
60
60
  val = di.instance_variable_get('@raw')
61
-
61
+
62
62
  field_val = lambda { |f|
63
63
  r = (val >> @fields_shift[f]) & @fields_mask[f]
64
64
  case f
65
- when :i16; Expression.make_signed(r, 16)
65
+ when :i12; Expression.make_signed(r, 12)
66
66
  when :i24; Expression.make_signed(r, 24)
67
67
  when :i8_12; ((r >> 4) & 0xf0) | (r & 0xf)
68
68
  when :stype; [:lsl, :lsr, :asr, :ror][r]
@@ -88,7 +88,8 @@ class ARM
88
88
  di.instruction.args << case a
89
89
  when :rd, :rn, :rm; Reg.new field_val[a]
90
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
91
+ when :rm_is; Reg.new field_val[:rm], field_val[:stype], field_val[:shifti]
92
+ when :i12; Expression[field_val[a]]
92
93
  when :i24; Expression[field_val[a] << 2]
93
94
  when :i8_r
94
95
  i = field_val[:i8]
@@ -99,14 +100,14 @@ class ARM
99
100
  o = case a
100
101
  when :mem_rn_rm; Reg.new(field_val[:rm])
101
102
  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_rms; Reg.new(field_val[:rm], field_val[:stype], field_val[:shifti])
103
104
  when :mem_rn_i12; field_val[:i12]
104
105
  end
105
106
  Memref.new(b, o, field_val[:u], op.props[:baseincr])
106
107
  when :reglist
107
108
  di.instruction.args.last.updated = true if op.props[:baseincr]
108
109
  msk = field_val[a]
109
- l = RegList.new((0..15).map { |i| Reg.new(i) if (msk & (1 << i)) > 0 }.compact)
110
+ l = RegList.new((0..15).map { |n| Reg.new(n) if (msk & (1 << n)) > 0 }.compact)
110
111
  l.usermoderegs = true if op.props[:usermoderegs]
111
112
  l
112
113
  else raise SyntaxError, "Internal error: invalid argument #{a} in #{op.name}"
@@ -118,7 +119,7 @@ class ARM
118
119
  end
119
120
 
120
121
  def decode_instr_interpret(di, addr)
121
- if di.opcode.args.include? :i24
122
+ if di.opcode.args[-1] == :i24
122
123
  di.instruction.args[-1] = Expression[di.instruction.args[-1] + addr + 8]
123
124
  end
124
125
  di
@@ -127,7 +128,7 @@ class ARM
127
128
  def backtrace_binding
128
129
  @backtrace_binding ||= init_backtrace_binding
129
130
  end
130
-
131
+
131
132
  def init_backtrace_binding
132
133
  @backtrace_binding ||= {}
133
134
  end
@@ -140,9 +141,9 @@ class ARM
140
141
  else arg
141
142
  end
142
143
  }
143
-
144
+
144
145
  if binding = backtrace_binding[di.opcode.name]
145
- bd = binding[di, *a]
146
+ binding[di, *a]
146
147
  else
147
148
  puts "unhandled instruction to backtrace: #{di}" if $VERBOSE
148
149
  # assume nothing except the 1st arg is modified
@@ -154,7 +155,7 @@ class ARM
154
155
  end
155
156
 
156
157
  end
157
-
158
+
158
159
  def get_xrefs_x(dasm, di)
159
160
  if di.opcode.props[:setip]
160
161
  [di.instruction.args.last]
@@ -4,15 +4,15 @@
4
4
  # Licence is LGPL, see LICENCE in the top-level directory
5
5
 
6
6
 
7
- require 'metasm/arm/opcodes'
7
+ require 'metasm/cpu/arm/opcodes'
8
8
  require 'metasm/encode'
9
9
 
10
10
  module Metasm
11
11
  class ARM
12
- def encode_instr_op(section, instr, op)
12
+ def encode_instr_op(program, instr, op)
13
13
  base = op.bin
14
14
  set_field = lambda { |f, v|
15
- v = v.reduce if v.kind_of? Expression
15
+ v = v.reduce if v.kind_of?(Expression)
16
16
  case f
17
17
  when :i8_12
18
18
  base = Expression[base, :|, [[v, :&, 0xf], :|, [[v, :<<, 4], :&, 0xf00]]]
@@ -42,7 +42,7 @@ class ARM
42
42
  when :rm_is
43
43
  set_field[:rm, arg.i]
44
44
  set_field[:stype, arg.stype]
45
- set_field[:shifti, arg.shift/2]
45
+ set_field[:shifti, arg.shift]
46
46
  when :mem_rn_rm, :mem_rn_rms, :mem_rn_i8_12, :mem_rn_i12
47
47
  set_field[:rn, arg.base.i]
48
48
  case sym
@@ -61,17 +61,32 @@ class ARM
61
61
  when :reglist
62
62
  set_field[sym, arg.list.inject(0) { |rl, r| rl | (1 << r.i) }]
63
63
  when :i8_r
64
- # XXX doublecheck this
65
64
  b = arg.reduce & 0xffffffff
66
- r = (0..15).find { next true if b < 0x10 ; b = (b >> 2) | ((b & 3) << 30) }
65
+ r = (0..15).find {
66
+ next true if b < 0x100
67
+ b = ((b << 2) & 0xffff_ffff) | ((b >> 30) & 3)
68
+ false
69
+ }
70
+ raise EncodeError, "Invalid constant" if not r
67
71
  set_field[:i8, b]
68
72
  set_field[:rotate, r]
69
- when :i16, :i24
73
+ when :i12, :i24
70
74
  val, mask, shift = arg, @fields_mask[sym], @fields_shift[sym]
71
75
  end
72
76
  }
73
77
 
74
- Expression[base, :|, [[val, :<<, shift], :&, mask]].encode(:u32, @endianness)
78
+ if op.args[-1] == :i24
79
+ # convert label name for branch to relative offset
80
+ label = program.new_label('l_'+op.name)
81
+ target = val
82
+ target = target.rexpr if target.kind_of?(Expression) and target.op == :+ and not target.lexpr
83
+ val = Expression[[target, :-, [label, :+, 8]], :>>, 2]
84
+
85
+ EncodedData.new('', :export => { label => 0 }) <<
86
+ Expression[base, :|, [[val, :<<, shift], :&, mask]].encode(:u32, @endianness)
87
+ else
88
+ Expression[base, :|, [[val, :<<, shift], :&, mask]].encode(:u32, @endianness)
89
+ end
75
90
  end
76
91
  end
77
92
  end
@@ -68,8 +68,5 @@ class ARM < CPU
68
68
  @opcode_list
69
69
  end
70
70
  end
71
-
72
- class ARM_THUMB < ARM
73
- end
74
71
  end
75
72
 
@@ -0,0 +1,324 @@
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/cpu/arm/main'
8
+
9
+ module Metasm
10
+ class ARM
11
+ private
12
+
13
+ # ARM MODE
14
+
15
+ def addop(name, bin, *args)
16
+ args << :cond if not args.delete :uncond
17
+
18
+ suppl = nil
19
+ o = Opcode.new name, bin
20
+ args.each { |a|
21
+ # Should Be One fields
22
+ if a == :sbo16 ; o.bin |= 0b1111 << 16 ; next ; end
23
+ if a == :sbo12 ; o.bin |= 0b1111 << 12 ; next ; end
24
+ if a == :sbo8 ; o.bin |= 0b1111 << 8 ; next ; end
25
+ if a == :sbo0 ; o.bin |= 0b1111 << 0 ; next ; end
26
+
27
+ o.args << a if @valid_args[a]
28
+ o.props[a] = true if @valid_props[a]
29
+ o.props.update a if a.kind_of?(Hash)
30
+ # special args -> multiple fields
31
+ suppl ||= { :i8_r => [:i8, :rotate], :rm_is => [:rm, :stype, :shifti],
32
+ :rm_rs => [:rm, :stype, :rs], :mem_rn_rm => [:rn, :rm, :rsx, :u],
33
+ :mem_rn_i8_12 => [:rn, :i8_12, :u],
34
+ :mem_rn_rms => [:rn, :rm, :stype, :shifti, :i],
35
+ :mem_rn_i12 => [:rn, :i12, :u]
36
+ }[a]
37
+ }
38
+
39
+ args.concat suppl if suppl
40
+
41
+ args.each { |a| o.fields[a] = [@fields_mask[a], @fields_shift[a]] if @fields_mask[a] }
42
+
43
+ @opcode_list << o
44
+ end
45
+
46
+ def addop_data_s(name, op, a1, a2, *h)
47
+ addop name, op | (1 << 25), a1, a2, :i8_r, :rotate, *h
48
+ addop name, op, a1, a2, :rm_is, *h
49
+ addop name, op | (1 << 4), a1, a2, :rm_rs, *h
50
+ end
51
+ def addop_data(name, op, a1, a2)
52
+ addop_data_s name, op << 21, a1, a2
53
+ addop_data_s name+'s', (op << 21) | (1 << 20), a1, a2, :cond_name_off => name.length
54
+ end
55
+
56
+ def addop_load_puw(name, op, *a)
57
+ addop name, op, {:baseincr => :post}, :rd, :u, *a
58
+ addop name, op | (1 << 24), :rd, :u, *a
59
+ addop name, op | (1 << 24) | (1 << 21), {:baseincr => :pre}, :rd, :u, *a
60
+ end
61
+ def addop_load_lsh_o(name, op)
62
+ addop_load_puw name, op, :rsz, :mem_rn_rm, {:cond_name_off => 3}
63
+ addop_load_puw name, op | (1 << 22), :mem_rn_i8_12, {:cond_name_off => 3}
64
+ end
65
+ def addop_load_lsh
66
+ op = 9 << 4
67
+ addop_load_lsh_o 'strh', op | (1 << 5)
68
+ addop_load_lsh_o 'ldrd', op | (1 << 6)
69
+ addop_load_lsh_o 'strd', op | (1 << 6) | (1 << 5)
70
+ addop_load_lsh_o 'ldrh', op | (1 << 20) | (1 << 5)
71
+ addop_load_lsh_o 'ldrsb', op | (1 << 20) | (1 << 6)
72
+ addop_load_lsh_o 'ldrsh', op | (1 << 20) | (1 << 6) | (1 << 5)
73
+ end
74
+
75
+ def addop_load_puwt(name, op, *a)
76
+ addop_load_puw name, op, *a
77
+ addop name+'t', op | (1 << 21), {:baseincr => :post, :cond_name_off => name.length}, :rd, :u, *a
78
+ end
79
+ def addop_load_o(name, op, *a)
80
+ addop_load_puwt name, op, :mem_rn_i12, *a
81
+ addop_load_puwt name, op | (1 << 25), :mem_rn_rms, *a
82
+ end
83
+ def addop_load(name, op)
84
+ addop_load_o name, op
85
+ addop_load_o name+'b', op | (1 << 22), :cond_name_off => name.length
86
+ end
87
+
88
+ def addop_ldm_go(name, op, *a)
89
+ addop name, op, :rn, :reglist, {:cond_name_off => 3}, *a
90
+ addop name, op, :rn, :reglist, {:cond_name_off => name.length}, *a # post-ARMv6 the condition code is at the end of the opname
91
+ end
92
+ def addop_ldm_w(name, op, *a)
93
+ addop_ldm_go name, op, *a # base reg untouched
94
+ addop_ldm_go name, op | (1 << 21), {:baseincr => :post}, *a # base updated
95
+ end
96
+ def addop_ldm_s(name, op)
97
+ addop_ldm_w name, op # transfer regs
98
+ addop_ldm_w name, op | (1 << 22), :usermoderegs # transfer usermode regs
99
+ end
100
+ def addop_ldm_p(name, op)
101
+ addop_ldm_s name+'a', op # target memory included
102
+ addop_ldm_s name+'b', op | (1 << 24) # target memory excluded, transfer starts at next addr
103
+ end
104
+ def addop_ldm_u(name, op)
105
+ addop_ldm_p name+'d', op # transfer made downward
106
+ addop_ldm_p name+'i', op | (1 << 23) # transfer made upward
107
+ end
108
+ def addop_ldm(name, op)
109
+ addop_ldm_u name, op
110
+ end
111
+
112
+ # ARMv6 instruction set, aka arm7/arm9
113
+ def init_arm_v6
114
+ @opcode_list = []
115
+
116
+ [:baseincr, :cond, :cond_name_off, :usermoderegs, :tothumb, :tojazelle
117
+ ].each { |p| @valid_props[p] = true }
118
+
119
+ [:rn, :rd, :rm, :crn, :crd, :crm, :cpn, :reglist, :i24, :rm_rs, :rm_is,
120
+ :i8_r, :mem_rn_rm, :mem_rn_i8_12, :mem_rn_rms, :mem_rn_i12
121
+ ].each { |p| @valid_args[p] = true }
122
+
123
+ @fields_mask.update :rn => 0xf, :rd => 0xf, :rs => 0xf, :rm => 0xf,
124
+ :crn => 0xf, :crd => 0xf, :crm => 0xf, :cpn => 0xf,
125
+ :rnx => 0xf, :rdx => 0xf, :rsx => 0xf,
126
+ :shifti => 0x1f, :stype => 3, :rotate => 0xf, :reglist => 0xffff,
127
+ :i8 => 0xff, :i12 => 0xfff, :i24 => 0xff_ffff, :i8_12 => 0xf0f,
128
+ :u => 1, :mask => 0xf, :sbo => 0xf, :cond => 0xf
129
+
130
+ @fields_shift.update :rn => 16, :rd => 12, :rs => 8, :rm => 0,
131
+ :crn => 16, :crd => 12, :crm => 0, :cpn => 8,
132
+ :rnx => 16, :rdx => 12, :rsx => 8,
133
+ :shifti => 7, :stype => 5, :rotate => 8, :reglist => 0,
134
+ :i8 => 0, :i12 => 0, :i24 => 0, :i8_12 => 0,
135
+ :u => 23, :mask => 16, :sbo => 12, :cond => 28
136
+
137
+ addop_data 'and', 0, :rd, :rn
138
+ addop_data 'eor', 1, :rd, :rn
139
+ addop_data 'xor', 1, :rd, :rn
140
+ addop_data 'sub', 2, :rd, :rn
141
+ addop_data 'rsb', 3, :rd, :rn
142
+ addop_data 'add', 4, :rd, :rn
143
+ addop_data 'adc', 5, :rd, :rn
144
+ addop_data 'sbc', 6, :rd, :rn
145
+ addop_data 'rsc', 7, :rd, :rn
146
+ addop_data_s 'tst', (8 << 21) | (1 << 20), :rdx, :rn
147
+ addop_data_s 'teq', (9 << 21) | (1 << 20), :rdx, :rn
148
+ addop_data_s 'cmp', (10 << 21) | (1 << 20), :rdx, :rn
149
+ addop_data_s 'cmn', (11 << 21) | (1 << 20), :rdx, :rn
150
+ addop_data 'orr', 12, :rd, :rn
151
+ addop_data 'or', 12, :rd, :rn
152
+ addop_data 'mov', 13, :rd, :rnx
153
+ addop_data 'bic', 14, :rd, :rn
154
+ addop_data 'mvn', 15, :rd, :rnx
155
+
156
+ addop 'b', 0b1010 << 24, :setip, :stopexec, :i24
157
+ addop 'bl', 0b1011 << 24, :setip, :stopexec, :i24, :saveip
158
+ addop 'bkpt', (0b00010010 << 20) | (0b0111 << 4) # other fields are available&unused, also cnd != AL is undef
159
+ addop 'blx', 0b1111101 << 25, :setip, :stopexec, :saveip, :tothumb, :h, :uncond, :i24
160
+ addop 'blx', (0b00010010 << 20) | (0b0011 << 4), :setip, :stopexec, :saveip, :tothumb, :rm, :sbo16, :sbo12, :sbo8
161
+ addop 'bx', (0b00010010 << 20) | (0b0001 << 4), :setip, :stopexec, :rm, :sbo16, :sbo12, :sbo8
162
+ addop 'bxj', (0b00010010 << 20) | (0b0010 << 4), :setip, :stopexec, :rm, :tojazelle, :sbo16, :sbo12, :sbo8
163
+
164
+ addop_load 'str', (1 << 26)
165
+ addop_load 'ldr', (1 << 26) | (1 << 20)
166
+ addop_load_lsh
167
+ addop_ldm 'stm', (1 << 27)
168
+ addop_ldm 'ldm', (1 << 27) | (1 << 20)
169
+ # TODO aliases (http://www.davespace.co.uk/arm/introduction-to-arm/stack.html)
170
+ # fd = full descending stmfd/ldmfd = stmdb/ldmia
171
+ # ed = empty descending stmed/ldmed = stmda/ldmib
172
+ # fa = full ascending stmfa/ldmfa = stmib/ldmda
173
+ # ea = empty ascending stmea/ldmea = stmia/ldmdb
174
+
175
+ # TODO mrs, [qus]add/sub*
176
+ addop 'clz', (0b00010110 << 20) | (0b0001 << 4), :rd, :rm, :sbo16, :sbo8
177
+ addop 'ldrex', (0b00011001 << 20) | (0b1001 << 4), :rd, :rn, :sbo8, :sbo0
178
+ addop 'strex', (0b00011000 << 20) | (0b1001 << 4), :rd, :rm, :rn, :sbo8
179
+ addop 'rev', (0b01101011 << 20) | (0b0011 << 4), :rd, :rm, :sbo16, :sbo8
180
+ addop 'rev16', (0b01101011 << 20) | (0b1011 << 4), :rd, :rm, :sbo16, :sbo8
181
+ addop 'revsh', (0b01101111 << 20) | (0b1011 << 4), :rd, :rm, :sbo16, :sbo8
182
+ addop 'sel', (0b01101000 << 20) | (0b1011 << 4), :rd, :rn, :rm, :sbo8
183
+
184
+ end
185
+
186
+
187
+
188
+ # THUMB2 MODE
189
+
190
+ def addop_t(name, bin, *args)
191
+ o = Opcode.new name, bin
192
+ args.each { |a|
193
+ o.args << a if @valid_args[a]
194
+ o.props[a] = true if @valid_props[a]
195
+ o.props.update a if a.kind_of?(Hash)
196
+ }
197
+
198
+ args.each { |a| o.fields[a] = [@fields_mask[a], @fields_shift[a]] if @fields_mask[a] }
199
+
200
+ @opcode_list_t << o
201
+ end
202
+
203
+ def init_arm_thumb2
204
+ @opcode_list_t = []
205
+ @valid_props_t = {}
206
+ @valid_args_t = {}
207
+ @fields_mask_t = {}
208
+ @fields_shift_t = {}
209
+
210
+ [:i16, :i16_3_8, :i16_rd].each { |p| @valid_props_t[p] = true }
211
+ [:i5, :rm, :rn, :rd].each { |p| @valid_args_t[p] = true }
212
+ @fields_mask_t.update :i5 => 0x1f, :i3 => 7, :i51 => 0x5f,
213
+ :rm => 7, :rn => 7, :rd => 7, :rdn => 7, :rdn8 => 7
214
+ @fields_shift_t.update :i5 => 6, :i3 => 6, :i51 => 3,
215
+ :rm => 6, :rn => 3, :rd => 0, :rdn => 0, :rdn8 => 8
216
+
217
+ addop_t 'mov', 0b000_00 << 11, :rd, :rm
218
+ addop_t 'lsl', 0b000_00 << 11, :rd, :rm, :i5
219
+ addop_t 'lsr', 0b000_01 << 11, :rd, :rm, :i5
220
+ addop_t 'asr', 0b000_10 << 11, :rd, :rm, :i5
221
+
222
+ addop_t 'add', 0b000_1100 << 9, :rd, :rn, :rm
223
+ addop_t 'add', 0b000_1110 << 9, :rd, :rn, :i3
224
+ addop_t 'sub', 0b000_1101 << 9, :rd, :rn, :rm
225
+ addop_t 'sub', 0b000_1111 << 9, :rd, :rn, :i3
226
+
227
+ addop_t 'mov', 0b001_00 << 10, :rdn8, :i8
228
+ addop_t 'cmp', 0b001_01 << 10, :rdn8, :i8
229
+ addop_t 'add', 0b001_10 << 10, :rdn8, :i8
230
+ addop_t 'sub', 0b001_11 << 10, :rdn8, :i8
231
+
232
+ addop_t 'and', (0b010000 << 10) | ( 0 << 6), :rdn, :rm
233
+ addop_t 'eor', (0b010000 << 10) | ( 1 << 6), :rdn, :rm # xor
234
+ addop_t 'lsl', (0b010000 << 10) | ( 2 << 6), :rdn, :rm
235
+ addop_t 'lsr', (0b010000 << 10) | ( 3 << 6), :rdn, :rm
236
+ addop_t 'asr', (0b010000 << 10) | ( 4 << 6), :rdn, :rm
237
+ addop_t 'adc', (0b010000 << 10) | ( 5 << 6), :rdn, :rm
238
+ addop_t 'sbc', (0b010000 << 10) | ( 6 << 6), :rdn, :rm
239
+ addop_t 'ror', (0b010000 << 10) | ( 7 << 6), :rdn, :rm
240
+ addop_t 'tst', (0b010000 << 10) | ( 8 << 6), :rdn, :rm
241
+ addop_t 'rsb', (0b010000 << 10) | ( 9 << 6), :rdn, :rm
242
+ addop_t 'cmp', (0b010000 << 10) | (10 << 6), :rdn, :rm
243
+ addop_t 'cmn', (0b010000 << 10) | (11 << 6), :rdn, :rm
244
+ addop_t 'orr', (0b010000 << 10) | (12 << 6), :rdn, :rm # or
245
+ addop_t 'mul', (0b010000 << 10) | (13 << 6), :rdn, :rm
246
+ addop_t 'bic', (0b010000 << 10) | (14 << 6), :rdn, :rm
247
+ addop_t 'mvn', (0b010000 << 10) | (15 << 6), :rdn, :rm
248
+
249
+ addop_t 'add', 0b010001_00 << 8, :rdn, :rm, :dn
250
+ addop_t 'cmp', 0b010001_01 << 8, :rdn, :rm, :dn
251
+ addop_t 'mov', 0b010001_10 << 8, :rdn, :rm, :dn
252
+
253
+ addop_t 'bx', 0b010001_110 << 7, :rm
254
+ addop_t 'blx', 0b010001_111 << 7, :rm
255
+
256
+ addop_t 'ldr', 0b01001 << 11, :rd, :pc_i8
257
+ addop_t 'str', 0b0101_000 << 9, :rd, :rn, :rm
258
+ addop_t 'strh', 0b0101_001 << 9, :rd, :rn, :rm
259
+ addop_t 'strb', 0b0101_010 << 9, :rd, :rn, :rm
260
+ addop_t 'ldrsb', 0b0101_011 << 9, :rd, :rn, :rm
261
+ addop_t 'ldr', 0b0101_100 << 9, :rd, :rn, :rm
262
+ addop_t 'ldrh', 0b0101_101 << 9, :rd, :rn, :rm
263
+ addop_t 'ldrb', 0b0101_110 << 9, :rd, :rn, :rm
264
+ addop_t 'ldrsh', 0b0101_111 << 9, :rd, :rn, :rm
265
+
266
+ addop_t 'str', 0b01100 << 11, :rd, :rn, :i5
267
+ addop_t 'ldr', 0b01101 << 11, :rd, :rn, :i5
268
+ addop_t 'strb', 0b01110 << 11, :rd, :rn, :i5
269
+ addop_t 'ldrb', 0b01111 << 11, :rd, :rn, :i5
270
+ addop_t 'strh', 0b10000 << 11, :rd, :rn, :i5
271
+ addop_t 'ldrh', 0b10001 << 11, :rd, :rn, :i5
272
+ addop_t 'str', 0b10010 << 11, :rd, :sp_i8
273
+ addop_t 'ldr', 0b10011 << 11, :rd, :sp_i8
274
+ addop_t 'adr', 0b10100 << 11, :rd, :pc, :i8
275
+ addop_t 'add', 0b10101 << 11, :rd, :sp, :i8
276
+
277
+ # 0b1011 misc
278
+ addop_t 'add', 0b1011_0000_0 << 7, :sp, :i7
279
+ addop_t 'sub', 0b1011_0000_1 << 7, :sp, :i7
280
+ addop_t 'sxth', 0b1011_0010_00 << 6, :rd, :rn
281
+ addop_t 'sxtb', 0b1011_0010_01 << 6, :rd, :rn
282
+ addop_t 'uxth', 0b1011_0010_10 << 6, :rd, :rn
283
+ addop_t 'uxtb', 0b1011_0010_11 << 6, :rd, :rn
284
+ addop_t 'cbz', 0b1011_0001 << 8, :rd, :i51
285
+ addop_t 'cbnz', 0b1011_1001 << 8, :rd, :i51
286
+ addop_t 'push', 0b1011_0100 << 8, :rlist
287
+ addop_t 'push', 0b1011_0101 << 8, :rlist
288
+ addop_t 'pop', 0b1011_1100 << 8, :rlist
289
+ addop_t 'pop', 0b1011_1101 << 8, :rlist
290
+ #addop_t 'unpredictable', 0b1011_0110_0100_0000, :i4
291
+ addop_t 'setendle', 0b1011_0110_0101_0000
292
+ addop_t 'setendbe', 0b1011_0110_0101_1000
293
+ addop_t 'cps', 0b1011_0110_0110_0000
294
+ #addop_t 'unpredictable', 0b1011_0110_0110_1000, :msk_0001_0111
295
+ addop_t 'rev', 0b1011_1010_00 << 6, :rd, :rn
296
+ addop_t 'rev16', 0b1011_1010_01 << 6, :rd, :rn
297
+ addop_t 'revsh', 0b1011_1010_11 << 6, :rd, :rn
298
+ addop_t 'bkpt', 0b1011_1110 << 8, :i8
299
+ addop_t 'it', 0b1011_1111 << 8, :itcond, :itmsk
300
+ addop_t 'nop', 0b1011_1111_0000_0000
301
+ addop_t 'yield', 0b1011_1111_0000_0001
302
+ addop_t 'wfe', 0b1011_1111_0000_0010
303
+ addop_t 'wfi', 0b1011_1111_0000_0011
304
+ addop_t 'sev', 0b1011_1111_0000_0100
305
+ addop_t 'nop', 0b1011_1111_0000_0000, :i4
306
+
307
+
308
+ addop_t 'stmia', 0b11000 << 11, :rn, :rlist # stmea
309
+ addop_t 'ldmia', 0b11001 << 11, :rn, :rlist # ldmfd
310
+ addop_t 'undef', 0b1101_1110 << 8, :i8
311
+ addop_t 'svc', 0b1101_1111 << 8, :i8
312
+ addop_t 'b', 0b1101 << 12, :cond, :i8
313
+ addop_t 'b', 0b11100 << 11, :i11
314
+
315
+ # thumb-32
316
+ end
317
+
318
+ def init_arm_v6_thumb2
319
+ init_arm_v6
320
+ init_arm_thumb2
321
+ end
322
+ alias init_latest init_arm_v6_thumb2
323
+ end
324
+ end