metasm 1.0.0 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (276) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +3 -0
  4. data/.gitignore +3 -0
  5. data/.hgtags +3 -0
  6. data/Gemfile +3 -0
  7. data/INSTALL +61 -0
  8. data/LICENCE +458 -0
  9. data/README +29 -21
  10. data/Rakefile +10 -0
  11. data/TODO +10 -12
  12. data/doc/code_organisation.txt +3 -1
  13. data/doc/core/DynLdr.txt +247 -0
  14. data/doc/core/ExeFormat.txt +43 -0
  15. data/doc/core/Expression.txt +220 -0
  16. data/doc/core/GNUExports.txt +27 -0
  17. data/doc/core/Ia32.txt +236 -0
  18. data/doc/core/SerialStruct.txt +108 -0
  19. data/doc/core/VirtualString.txt +145 -0
  20. data/doc/core/WindowsExports.txt +61 -0
  21. data/doc/core/index.txt +1 -0
  22. data/doc/style.css +6 -3
  23. data/doc/usage/debugger.txt +327 -0
  24. data/doc/usage/index.txt +1 -0
  25. data/doc/use_cases.txt +2 -2
  26. data/metasm.gemspec +23 -0
  27. data/{lib/metasm.rb → metasm.rb} +15 -3
  28. data/{lib/metasm → metasm}/compile_c.rb +15 -9
  29. data/metasm/cpu/arc.rb +8 -0
  30. data/metasm/cpu/arc/decode.rb +404 -0
  31. data/metasm/cpu/arc/main.rb +191 -0
  32. data/metasm/cpu/arc/opcodes.rb +588 -0
  33. data/metasm/cpu/arm.rb +14 -0
  34. data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
  35. data/{lib/metasm → metasm/cpu}/arm/decode.rb +15 -18
  36. data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
  37. data/{lib/metasm → metasm/cpu}/arm/main.rb +3 -6
  38. data/metasm/cpu/arm/opcodes.rb +324 -0
  39. data/{lib/metasm → metasm/cpu}/arm/parse.rb +25 -13
  40. data/{lib/metasm → metasm/cpu}/arm/render.rb +2 -2
  41. data/metasm/cpu/arm64.rb +15 -0
  42. data/metasm/cpu/arm64/debug.rb +38 -0
  43. data/metasm/cpu/arm64/decode.rb +285 -0
  44. data/metasm/cpu/arm64/encode.rb +41 -0
  45. data/metasm/cpu/arm64/main.rb +105 -0
  46. data/metasm/cpu/arm64/opcodes.rb +232 -0
  47. data/metasm/cpu/arm64/parse.rb +20 -0
  48. data/metasm/cpu/arm64/render.rb +95 -0
  49. data/{lib/metasm/mips/compile_c.rb → metasm/cpu/bpf.rb} +4 -2
  50. data/metasm/cpu/bpf/decode.rb +110 -0
  51. data/metasm/cpu/bpf/main.rb +60 -0
  52. data/metasm/cpu/bpf/opcodes.rb +81 -0
  53. data/metasm/cpu/bpf/render.rb +30 -0
  54. data/{lib/metasm/ppc.rb → metasm/cpu/cy16.rb} +2 -4
  55. data/metasm/cpu/cy16/decode.rb +247 -0
  56. data/metasm/cpu/cy16/main.rb +63 -0
  57. data/metasm/cpu/cy16/opcodes.rb +78 -0
  58. data/metasm/cpu/cy16/render.rb +30 -0
  59. data/metasm/cpu/dalvik.rb +11 -0
  60. data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +34 -34
  61. data/{lib/metasm → metasm/cpu}/dalvik/main.rb +71 -4
  62. data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +21 -12
  63. data/{lib/metasm/mips.rb → metasm/cpu/ebpf.rb} +3 -4
  64. data/metasm/cpu/ebpf/debug.rb +61 -0
  65. data/metasm/cpu/ebpf/decode.rb +142 -0
  66. data/metasm/cpu/ebpf/main.rb +58 -0
  67. data/metasm/cpu/ebpf/opcodes.rb +97 -0
  68. data/metasm/cpu/ebpf/render.rb +36 -0
  69. data/metasm/cpu/ia32.rb +17 -0
  70. data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +23 -9
  71. data/{lib/metasm → metasm/cpu}/ia32/debug.rb +44 -6
  72. data/{lib/metasm → metasm/cpu}/ia32/decode.rb +342 -128
  73. data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +75 -53
  74. data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
  75. data/{lib/metasm → metasm/cpu}/ia32/main.rb +66 -8
  76. data/metasm/cpu/ia32/opcodes.rb +1424 -0
  77. data/{lib/metasm → metasm/cpu}/ia32/parse.rb +55 -17
  78. data/{lib/metasm → metasm/cpu}/ia32/render.rb +32 -5
  79. data/metasm/cpu/mcs51.rb +8 -0
  80. data/metasm/cpu/mcs51/decode.rb +99 -0
  81. data/metasm/cpu/mcs51/main.rb +87 -0
  82. data/metasm/cpu/mcs51/opcodes.rb +120 -0
  83. data/metasm/cpu/mips.rb +14 -0
  84. data/metasm/cpu/mips/debug.rb +42 -0
  85. data/{lib/metasm → metasm/cpu}/mips/decode.rb +59 -38
  86. data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
  87. data/{lib/metasm → metasm/cpu}/mips/main.rb +13 -6
  88. data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +87 -18
  89. data/{lib/metasm → metasm/cpu}/mips/parse.rb +1 -1
  90. data/{lib/metasm → metasm/cpu}/mips/render.rb +1 -1
  91. data/{lib/metasm/dalvik.rb → metasm/cpu/msp430.rb} +1 -1
  92. data/metasm/cpu/msp430/decode.rb +243 -0
  93. data/metasm/cpu/msp430/main.rb +62 -0
  94. data/metasm/cpu/msp430/opcodes.rb +101 -0
  95. data/metasm/cpu/openrisc.rb +11 -0
  96. data/metasm/cpu/openrisc/debug.rb +106 -0
  97. data/metasm/cpu/openrisc/decode.rb +182 -0
  98. data/metasm/cpu/openrisc/decompile.rb +350 -0
  99. data/metasm/cpu/openrisc/main.rb +70 -0
  100. data/metasm/cpu/openrisc/opcodes.rb +109 -0
  101. data/metasm/cpu/openrisc/render.rb +37 -0
  102. data/{lib/metasm → metasm/cpu}/pic16c/decode.rb +6 -7
  103. data/{lib/metasm → metasm/cpu}/pic16c/main.rb +0 -0
  104. data/{lib/metasm → metasm/cpu}/pic16c/opcodes.rb +1 -1
  105. data/metasm/cpu/ppc.rb +11 -0
  106. data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -37
  107. data/{lib/metasm → metasm/cpu}/ppc/decompile.rb +3 -3
  108. data/{lib/metasm → metasm/cpu}/ppc/encode.rb +2 -2
  109. data/{lib/metasm → metasm/cpu}/ppc/main.rb +23 -18
  110. data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -6
  111. data/metasm/cpu/ppc/parse.rb +55 -0
  112. data/metasm/cpu/python.rb +8 -0
  113. data/metasm/cpu/python/decode.rb +116 -0
  114. data/metasm/cpu/python/main.rb +36 -0
  115. data/metasm/cpu/python/opcodes.rb +180 -0
  116. data/{lib/metasm → metasm/cpu}/sh4.rb +1 -1
  117. data/{lib/metasm → metasm/cpu}/sh4/decode.rb +50 -23
  118. data/{lib/metasm → metasm/cpu}/sh4/main.rb +38 -27
  119. data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
  120. data/metasm/cpu/st20.rb +9 -0
  121. data/metasm/cpu/st20/decode.rb +173 -0
  122. data/metasm/cpu/st20/decompile.rb +283 -0
  123. data/metasm/cpu/st20/main.rb +37 -0
  124. data/metasm/cpu/st20/opcodes.rb +140 -0
  125. data/{lib/metasm/arm.rb → metasm/cpu/webasm.rb} +4 -5
  126. data/metasm/cpu/webasm/debug.rb +31 -0
  127. data/metasm/cpu/webasm/decode.rb +321 -0
  128. data/metasm/cpu/webasm/decompile.rb +386 -0
  129. data/metasm/cpu/webasm/encode.rb +104 -0
  130. data/metasm/cpu/webasm/main.rb +81 -0
  131. data/metasm/cpu/webasm/opcodes.rb +214 -0
  132. data/metasm/cpu/x86_64.rb +15 -0
  133. data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +40 -25
  134. data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
  135. data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +58 -15
  136. data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +59 -28
  137. data/{lib/metasm → metasm/cpu}/x86_64/main.rb +18 -6
  138. data/metasm/cpu/x86_64/opcodes.rb +138 -0
  139. data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +12 -4
  140. data/metasm/cpu/x86_64/render.rb +35 -0
  141. data/metasm/cpu/z80.rb +9 -0
  142. data/metasm/cpu/z80/decode.rb +286 -0
  143. data/metasm/cpu/z80/main.rb +67 -0
  144. data/metasm/cpu/z80/opcodes.rb +224 -0
  145. data/metasm/cpu/z80/render.rb +48 -0
  146. data/{lib/metasm/os/main.rb → metasm/debug.rb} +201 -407
  147. data/{lib/metasm → metasm}/decode.rb +104 -24
  148. data/{lib/metasm → metasm}/decompile.rb +804 -478
  149. data/{lib/metasm → metasm}/disassemble.rb +385 -170
  150. data/{lib/metasm → metasm}/disassemble_api.rb +684 -105
  151. data/{lib/metasm → metasm}/dynldr.rb +231 -138
  152. data/{lib/metasm → metasm}/encode.rb +20 -5
  153. data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
  154. data/{lib/metasm → metasm}/exe_format/autoexe.rb +3 -0
  155. data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
  156. data/{lib/metasm → metasm}/exe_format/coff.rb +35 -7
  157. data/{lib/metasm → metasm}/exe_format/coff_decode.rb +70 -23
  158. data/{lib/metasm → metasm}/exe_format/coff_encode.rb +24 -22
  159. data/{lib/metasm → metasm}/exe_format/dex.rb +26 -8
  160. data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
  161. data/{lib/metasm → metasm}/exe_format/elf.rb +108 -58
  162. data/{lib/metasm → metasm}/exe_format/elf_decode.rb +202 -36
  163. data/{lib/metasm → metasm}/exe_format/elf_encode.rb +126 -32
  164. data/metasm/exe_format/gb.rb +65 -0
  165. data/metasm/exe_format/javaclass.rb +424 -0
  166. data/{lib/metasm → metasm}/exe_format/macho.rb +218 -16
  167. data/{lib/metasm → metasm}/exe_format/main.rb +28 -3
  168. data/{lib/metasm → metasm}/exe_format/mz.rb +2 -0
  169. data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
  170. data/{lib/metasm → metasm}/exe_format/pe.rb +96 -11
  171. data/metasm/exe_format/pyc.rb +167 -0
  172. data/{lib/metasm → metasm}/exe_format/serialstruct.rb +67 -14
  173. data/{lib/metasm → metasm}/exe_format/shellcode.rb +7 -3
  174. data/metasm/exe_format/shellcode_rwx.rb +114 -0
  175. data/metasm/exe_format/swf.rb +205 -0
  176. data/metasm/exe_format/wasm.rb +402 -0
  177. data/{lib/metasm → metasm}/exe_format/xcoff.rb +7 -7
  178. data/metasm/exe_format/zip.rb +335 -0
  179. data/metasm/gui.rb +13 -0
  180. data/{lib/metasm → metasm}/gui/cstruct.rb +35 -41
  181. data/{lib/metasm → metasm}/gui/dasm_coverage.rb +11 -11
  182. data/{lib/metasm → metasm}/gui/dasm_decomp.rb +177 -114
  183. data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
  184. data/metasm/gui/dasm_graph.rb +1754 -0
  185. data/{lib/metasm → metasm}/gui/dasm_hex.rb +16 -12
  186. data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
  187. data/{lib/metasm → metasm}/gui/dasm_main.rb +360 -77
  188. data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
  189. data/{lib/metasm → metasm}/gui/debug.rb +109 -34
  190. data/{lib/metasm → metasm}/gui/gtk.rb +174 -44
  191. data/{lib/metasm → metasm}/gui/qt.rb +14 -4
  192. data/{lib/metasm → metasm}/gui/win32.rb +180 -43
  193. data/{lib/metasm → metasm}/gui/x11.rb +59 -59
  194. data/{lib/metasm → metasm}/main.rb +421 -286
  195. data/metasm/os/emulator.rb +175 -0
  196. data/{lib/metasm/os/remote.rb → metasm/os/gdbremote.rb} +146 -54
  197. data/{lib/metasm → metasm}/os/gnu_exports.rb +1 -1
  198. data/{lib/metasm → metasm}/os/linux.rb +628 -151
  199. data/metasm/os/main.rb +335 -0
  200. data/{lib/metasm → metasm}/os/windows.rb +151 -58
  201. data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
  202. data/{lib/metasm → metasm}/parse.rb +49 -36
  203. data/{lib/metasm → metasm}/parse_c.rb +405 -246
  204. data/{lib/metasm → metasm}/preprocessor.rb +71 -41
  205. data/{lib/metasm → metasm}/render.rb +14 -38
  206. data/misc/hexdump.rb +4 -3
  207. data/misc/lint.rb +58 -0
  208. data/misc/objdiff.rb +4 -1
  209. data/misc/objscan.rb +1 -1
  210. data/misc/openrisc-parser.rb +79 -0
  211. data/misc/txt2html.rb +9 -7
  212. data/samples/bindiff.rb +3 -4
  213. data/samples/dasm-plugins/bindiff.rb +15 -0
  214. data/samples/dasm-plugins/bookmark.rb +133 -0
  215. data/samples/dasm-plugins/c_constants.rb +57 -0
  216. data/samples/dasm-plugins/colortheme_solarized.rb +125 -0
  217. data/samples/dasm-plugins/cppobj_funcall.rb +60 -0
  218. data/samples/dasm-plugins/dasm_all.rb +70 -0
  219. data/samples/dasm-plugins/demangle_cpp.rb +31 -0
  220. data/samples/dasm-plugins/deobfuscate.rb +251 -0
  221. data/samples/dasm-plugins/dump_text.rb +35 -0
  222. data/samples/dasm-plugins/export_graph_svg.rb +86 -0
  223. data/samples/dasm-plugins/findgadget.rb +75 -0
  224. data/samples/dasm-plugins/hl_opcode.rb +32 -0
  225. data/samples/dasm-plugins/hotfix_gtk_dbg.rb +19 -0
  226. data/samples/dasm-plugins/imm2off.rb +34 -0
  227. data/samples/dasm-plugins/match_libsigs.rb +93 -0
  228. data/samples/dasm-plugins/patch_file.rb +95 -0
  229. data/samples/dasm-plugins/scanfuncstart.rb +36 -0
  230. data/samples/dasm-plugins/scanxrefs.rb +29 -0
  231. data/samples/dasm-plugins/selfmodify.rb +197 -0
  232. data/samples/dasm-plugins/stringsxrefs.rb +28 -0
  233. data/samples/dasmnavig.rb +1 -1
  234. data/samples/dbg-apihook.rb +24 -9
  235. data/samples/dbg-plugins/heapscan.rb +283 -0
  236. data/samples/dbg-plugins/heapscan/compiled_heapscan_lin.c +155 -0
  237. data/samples/dbg-plugins/heapscan/compiled_heapscan_win.c +128 -0
  238. data/samples/dbg-plugins/heapscan/graphheap.rb +616 -0
  239. data/samples/dbg-plugins/heapscan/heapscan.rb +709 -0
  240. data/samples/dbg-plugins/heapscan/winheap.h +174 -0
  241. data/samples/dbg-plugins/heapscan/winheap7.h +307 -0
  242. data/samples/dbg-plugins/trace_func.rb +214 -0
  243. data/samples/disassemble-gui.rb +48 -7
  244. data/samples/disassemble.rb +31 -6
  245. data/samples/dump_upx.rb +24 -12
  246. data/samples/dynamic_ruby.rb +35 -27
  247. data/samples/elfencode.rb +15 -0
  248. data/samples/emubios.rb +251 -0
  249. data/samples/emudbg.rb +127 -0
  250. data/samples/exeencode.rb +6 -5
  251. data/samples/factorize-headers-peimports.rb +1 -1
  252. data/samples/lindebug.rb +186 -391
  253. data/samples/metasm-shell.rb +68 -57
  254. data/samples/peldr.rb +2 -2
  255. data/tests/all.rb +1 -1
  256. data/tests/arc.rb +26 -0
  257. data/tests/dynldr.rb +22 -4
  258. data/tests/expression.rb +57 -0
  259. data/tests/graph_layout.rb +285 -0
  260. data/tests/ia32.rb +80 -26
  261. data/tests/mcs51.rb +27 -0
  262. data/tests/mips.rb +10 -3
  263. data/tests/preprocessor.rb +18 -0
  264. data/tests/x86_64.rb +66 -18
  265. metadata +465 -219
  266. metadata.gz.sig +2 -0
  267. data/lib/metasm/arm/opcodes.rb +0 -177
  268. data/lib/metasm/gui.rb +0 -23
  269. data/lib/metasm/gui/dasm_graph.rb +0 -1354
  270. data/lib/metasm/ia32.rb +0 -14
  271. data/lib/metasm/ia32/opcodes.rb +0 -872
  272. data/lib/metasm/ppc/parse.rb +0 -52
  273. data/lib/metasm/x86_64.rb +0 -12
  274. data/lib/metasm/x86_64/opcodes.rb +0 -118
  275. data/samples/gdbclient.rb +0 -583
  276. data/samples/rubstop.rb +0 -399
@@ -0,0 +1,37 @@
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 ST20 < CPU
11
+ def initialize(size=32)
12
+ super()
13
+ @endianness = :little
14
+ @size = size
15
+ init_opcodes
16
+ end
17
+
18
+ def register_symbols
19
+ [:a, :b, :c]
20
+ end
21
+
22
+ def render_instruction(i)
23
+ r = []
24
+ r << i.opname
25
+ if not i.args.empty?
26
+ r << ' '
27
+ i.args.each { |a_| r << a_ << ', ' }
28
+ r.pop
29
+ end
30
+ r
31
+ end
32
+ end
33
+
34
+ class TransPuter < ST20
35
+ end
36
+ end
37
+
@@ -0,0 +1,140 @@
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/cpu/st20/main'
7
+
8
+ module Metasm
9
+
10
+ class ST20
11
+ def init_opcodes
12
+ @op_function = op_get_function
13
+ @op_operate = op_get_operate
14
+ @opcode_list = @op_function.sort.map { |b, n|
15
+ op = Opcode.new(n, b)
16
+ op.props[:setip] = true if n == 'cj'
17
+ op.props[:setip] = op.props[:stopexec] = true if n == 'j'
18
+ op.props[:setip] = op.props[:stopexec] = op.props[:saveip] = true if n == 'fcall'
19
+ op
20
+ }
21
+ @opc_operate = {}
22
+ op = Opcode.new('ret', 0)
23
+ op.props[:setip] = op.props[:stopexec] = true
24
+ @opc_operate['ret'] = op
25
+ end
26
+
27
+ def op_get_function
28
+ {
29
+ 0x00 => 'j', 0x10 => 'ldlp', 0x20 => 'pfix', 0x30 => 'ldnl',
30
+ 0x40 => 'ldc', 0x50 => 'ldnlp', 0x60 => 'nfix', 0x70 => 'ldl',
31
+ 0x80 => 'adc', 0x90 => 'fcall', 0xa0 => 'cj', 0xb0 => 'ajw',
32
+ 0xc0 => 'eqc', 0xd0 => 'stl', 0xe0 => 'stnl', 0xf0 => 'opr'
33
+ }
34
+ end
35
+
36
+ def op_get_operate
37
+ {
38
+ 0x00 => 'rev', 0x01 => 'dup', 0x02 => 'rot', 0x03 => 'arot',
39
+ 0x04 => 'add', 0x05 => 'sub', 0x06 => 'mul', 0x07 => 'wsub',
40
+ 0x08 => 'not', 0x09 => 'and', 0x0A => 'or', 0x0B => 'shl',
41
+ 0x0C => 'shr', 0x0D => 'jab', 0x0E => 'timeslice', 0x0F => 'breakpoint',
42
+ 0x10 => 'addc', 0x11 => 'subc', 0x12 => 'mac', 0x13 => 'umac',
43
+ 0x14 => 'smul', 0x15 => 'smacinit', 0x16 => 'smacloop', 0x17 => 'biquad',
44
+ 0x18 => 'divstep', 0x19 => 'unsign', 0x1A => 'saturate', 0x1B => 'gt',
45
+ 0x1C => 'gtu', 0x1D => 'order', 0x1E => 'orderu', 0x1F => 'ashr',
46
+ 0x20 => 'xor', 0x21 => 'xbword', 0x22 => 'xsword', 0x23 => 'bitld',
47
+ 0x24 => 'bitst', 0x25 => 'bitmask', 0x26 => 'statusset', 0x27 => 'statusclr',
48
+ 0x28 => 'statustst', 0x29 => 'rmw', 0x2A => 'lbinc', 0x2B => 'sbinc',
49
+ 0x2C => 'lsinc', 0x2D => 'lsxinc', 0x2E => 'ssinc', 0x2F => 'lwinc',
50
+ 0x30 => 'swinc', 0x31 => 'ecall', 0x32 => 'eret', 0x33 => 'run',
51
+ 0x34 => 'stop', 0x35 => 'signal', 0x36 => 'wait', 0x37 => 'enqueue',
52
+ 0x38 => 'dequeue', 0x39 => 'ldtdesc', 0x3A => 'ldpi', 0x3B => 'gajw',
53
+ 0x3C => 'ldprodid', 0x3D => 'io', 0x3E => 'swap32', 0x3F => 'nop',
54
+ }
55
+ end
56
+ end
57
+
58
+ class TransPuter
59
+ def op_get_operate
60
+ {
61
+ 0x00 => 'rev', 0x01 => 'lb', 0x02 => 'bsub', 0x03 => 'endp',
62
+ 0x04 => 'diff', 0x05 => 'add', 0x06 => 'gcall', 0x07 => 'in',
63
+ 0x08 => 'prod', 0x09 => 'gt', 0x0a => 'wsub', 0x0b => 'out',
64
+ 0x0c => 'sub', 0x0d => 'startp', 0x0e => 'outbyte', 0x0f => 'outword',
65
+ 0x10 => 'seterr', 0x11 => 'mreleasep', 0x12 => 'resetch', 0x13 => 'csub0',
66
+ 0x14 => 'extvrfy', 0x15 => 'stopp', 0x16 => 'ladd', 0x17 => 'stlb',
67
+ 0x18 => 'sthf', 0x19 => 'norm', 0x1a => 'ldiv', 0x1b => 'ldpi',
68
+ 0x1c => 'stlf', 0x1d => 'xdble', 0x1e => 'ldpri', 0x1f => 'rem',
69
+ 0x20 => 'ret', 0x21 => 'lend', 0x22 => 'ldtimer', 0x23 => 'testlds',
70
+ 0x24 => 'testlde', 0x25 => 'testldd', 0x26 => 'teststs', 0x27 => 'testste',
71
+ 0x28 => 'teststd', 0x29 => 'testerr', 0x2a => 'testpranal', 0x2b => 'tin',
72
+ 0x2c => 'div', 0x2d => 'testhardchan', 0x2e => 'dist', 0x2f => 'disc',
73
+ 0x30 => 'diss', 0x31 => 'lmul', 0x32 => 'not', 0x33 => 'xor',
74
+ 0x34 => 'bcnt', 0x35 => 'lshr', 0x36 => 'lshl', 0x37 => 'lsum',
75
+ 0x38 => 'lsub', 0x39 => 'runp', 0x3a => 'xword', 0x3b => 'sb',
76
+ 0x3c => 'gajw', 0x3d => 'savel', 0x3e => 'saveh', 0x3f => 'wcnt',
77
+ 0x40 => 'shr', 0x41 => 'shl', 0x42 => 'mint', 0x43 => 'alt',
78
+ 0x44 => 'altwt', 0x45 => 'altend', 0x46 => 'and', 0x47 => 'enbt',
79
+ 0x48 => 'enbc', 0x49 => 'enbs', 0x4a => 'move', 0x4b => 'or',
80
+ 0x4c => 'csngl', 0x4d => 'ccnt1', 0x4e => 'talt', 0x4f => 'ldiff',
81
+ 0x50 => 'sthb', 0x51 => 'taltwt', 0x52 => 'sum', 0x53 => 'mul',
82
+ 0x54 => 'sttimer', 0x55 => 'stoperr', 0x56 => 'cword', 0x57 => 'clrhalterr',
83
+ 0x58 => 'sethalterr', 0x59 => 'testhalterr', 0x5a => 'dup', 0x5b => 'move2dinit',
84
+ 0x5c => 'move2dall', 0x5d => 'move2dnonzero', 0x5e => 'move2dzero', 0x5f => 'gtu',
85
+ 0x60 => 'extin', 0x61 => 'extout', 0x62 => 'minn', 0x63 => 'unpacksn',
86
+ 0x64 => 'moutn', 0x65 => 'xminn', 0x66 => 'extenbc', 0x67 => 'extndisc',
87
+ 0x68 => 'extmin', 0x69 => 'extmout', 0x6a => 'extmin64', 0x6b => 'extmout64',
88
+ 0x6c => 'postnormsn', 0x6d => 'roundsn', 0x6e => 'extminn', 0x6f => 'extmoutn',
89
+ 0x70 => 'enbc3', 0x71 => 'ldinf', 0x72 => 'fmul', 0x73 => 'cflerr',
90
+ 0x74 => 'crcword', 0x75 => 'crcbyte', 0x76 => 'bitcnt', 0x77 => 'bitrevword',
91
+ 0x78 => 'bitrevnbits', 0x79 => 'pop', 0x7a => 'timerdisableh', 0x7b => 'timerdisablel',
92
+ 0x7c => 'timerenableh', 0x7d => 'timerenablel', 0x7e => 'ldmemstartval',
93
+ 0x80 => 'fpsttest', 0x81 => 'wsubdb', 0x82 => 'fpldnldbi', 0x83 => 'fpchkerr',
94
+ 0x84 => 'fpstnldb', 0x85 => 'fpldtest', 0x86 => 'fpldnlsni', 0x87 => 'fpadd',
95
+ 0x88 => 'fpstnlsn', 0x89 => 'fpsub', 0x8a => 'fpldnldb', 0x8b => 'fpmul',
96
+ 0x8c => 'fpdiv', 0x8d => 'fprange', 0x8e => 'fpldnlsn', 0x8f => 'fpremfirst',
97
+ 0x90 => 'fpremstep', 0x91 => 'fpnan', 0x92 => 'fpordered', 0x93 => 'fpnotfinite',
98
+ 0x94 => 'fpgt', 0x95 => 'fpeq', 0x96 => 'fpi32tor32', 0x97 => 'fpge',
99
+ 0x98 => 'fpi32tor64', 0x99 => 'enbt3', 0x9a => 'fpb32tor64', 0x9b => 'fplg',
100
+ 0x9c => 'fptesterr', 0x9d => 'fprtoi32', 0x9e => 'fpstnli32', 0x9f => 'fpldzerosn',
101
+ 0xa0 => 'fpldzerodb', 0xa1 => 'fpint', 0xa2 => 'getpri', 0xa3 => 'fpdup',
102
+ 0xa4 => 'fprev', 0xa5 => 'setpri', 0xa6 => 'fpldnladddb', 0xa7 => 'fpentry3',
103
+ 0xa8 => 'fpldnlmuldb', 0xa9 => 'fpentry2', 0xaa => 'fpldnladdsn', 0xab => 'fpentry',
104
+ 0xac => 'fpldnlmulsn', 0xad => 'enbs3',
105
+ 0xb0 => 'settimeslice', 0xb1 => 'break', 0xb2 => 'clrj0break', 0xb3 => 'setj0break',
106
+ 0xb4 => 'testj0break', 0xb6 => 'ldflags', 0xb7 => 'stflags',
107
+ 0xb8 => 'xbword', 0xb9 => 'lbx', 0xba => 'cb', 0xbb => 'cbu',
108
+ 0xbc => 'insphdr', 0xbd => 'readbfr', 0xbe => 'ldconf', 0xbf => 'stconf',
109
+ 0xc0 => 'ldcnt', 0xc1 => 'ssub', 0xc2 => 'ldth', 0xc3 => 'ldchstatus',
110
+ 0xc4 => 'intdis', 0xc5 => 'intenb', 0xc6 => 'ldtrapped', 0xc7 => 'cir',
111
+ 0xc8 => 'ss', 0xc9 => 'chantype', 0xca => 'ls', 0xcb => 'sttrapped',
112
+ 0xcc => 'ciru', 0xcd => 'gintdis', 0xce => 'gintenb', 0xcf => 'fprem',
113
+ 0xd0 => 'fprn', 0xd1 => 'fpdivby2', 0xd2 => 'fpmulby2', 0xd3 => 'fpsqrt',
114
+ 0xd4 => 'fprp', 0xd5 => 'fprm', 0xd6 => 'fprz', 0xd7 => 'fpr32tor64',
115
+ 0xd8 => 'fpr64tor32', 0xd9 => 'fpexpdec32', 0xda => 'fpexpinc32', 0xdb => 'fpabs',
116
+ 0xdd => 'fpadddbsn', 0xde => 'fpchki32', 0xdf => 'fpchki64',
117
+ 0xe0 => 'mnew', 0xe1 => 'mfree', 0xe2 => 'malloc', 0xe3 => 'mrelease',
118
+ 0xe4 => 'min', 0xe5 => 'mout', 0xe6 => 'min64', 0xe7 => 'mout64',
119
+ 0xe8 => 'xable', 0xe9 => 'xin', 0xea => 'xmin', 0xeb => 'xmin64',
120
+ 0xec => 'xend', 0xed => 'ndisc', 0xee => 'ndist', 0xef => 'ndiss',
121
+ 0xf0 => 'devlb', 0xf1 => 'devsb', 0xf2 => 'devls', 0xf3 => 'devss',
122
+ 0xf4 => 'devlw', 0xf5 => 'devsw', 0xf8 => 'xsword', 0xf9 => 'lsx',
123
+ 0xfa => 'cs', 0xfb => 'csu', 0xfc => 'trap', 0xfd => 'null',
124
+ 0x1ff => 'start',
125
+ 0x17c => 'lddevid',
126
+ 0x200 => 'in8', 0x201 => 'in32', 0x202 => 'out8', 0x203 => 'out32',
127
+ 0x204 => 'xstl',
128
+ 0x22f => 'proc_alloc',
129
+ 0x230 => 'proc_param', 0x231 => 'proc_mt_copy', 0x232 => 'proc_mt_move', 0x233 => 'proc_start',
130
+ 0x234 => 'proc_end', 0x235 => 'getaff', 0x236 => 'setaff', 0x237 => 'getpas',
131
+ 0x238 => 'mt_alloc', 0x239 => 'mt_release', 0x23a => 'mt_clone', 0x23b => 'mt_in',
132
+ 0x23c => 'mt_out', 0x23d => 'mt_xchg', 0x23e => 'mt_lock', 0x23f => 'mt_unlock',
133
+ 0x240 => 'mt_enroll', 0x241 => 'mt_resign', 0x242 => 'mt_sync', 0x243 => 'mt_xin',
134
+ 0x244 => 'mt_xout', 0x245 => 'mt_xxchg', 0x246 => 'mt_dclone', 0x247 => 'mt_bind',
135
+ 0x248 => 'mb', 0x249 => 'rmb', 0x24a => 'wmb', 0x24b => 'ext_mt_in',
136
+ 0x24c => 'ext_mt_out', 0x24d => 'mt_resize',
137
+ }
138
+ end
139
+ end
140
+ end
@@ -5,8 +5,7 @@
5
5
 
6
6
 
7
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'
8
+ require 'metasm/cpu/webasm/decode'
9
+ require 'metasm/cpu/webasm/encode'
10
+ require 'metasm/cpu/webasm/decompile'
11
+ require 'metasm/cpu/webasm/debug'
@@ -0,0 +1,31 @@
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/webasm/opcodes'
8
+
9
+ module Metasm
10
+ class WebAsm
11
+ def dbg_register_list
12
+ @dbg_register_list ||= [:pc, :opstack, :mem, :local_base]
13
+ end
14
+
15
+ def dbg_resolve_pc(di, fbd, pc_reg, dbg_ctx)
16
+ case di.opcode.name
17
+ when 'br_if', 'if'
18
+ if dbg_ctx.resolve(Indirection[:opstack, 8]) != 0
19
+ fbd[pc_reg] = (di.opcode.name == 'if' ? di.next_addr : di.misc[:x])
20
+ else
21
+ fbd[pc_reg] = (di.opcode.name == 'if' ? di.misc[:x] : di.next_addr)
22
+ end
23
+ else return super(di, fbd, pc_reg, dbg_ctx)
24
+ end
25
+ end
26
+
27
+ def dbg_end_stepout(dbg, addr, di)
28
+ di and di.opcode.props[:stopexec] and (di.opcode.name == 'return' or di.opcode.name == 'end')
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,321 @@
1
+ # This file is part of Metasm, the Ruby assembly manipulation suite
2
+ # Copyright (C) 2006-2010 Yoann GUILLOT
3
+ #
4
+ # Licence is LGPL, see LICENCE in the top-level directory
5
+
6
+ require 'metasm/cpu/webasm/opcodes'
7
+ require 'metasm/decode'
8
+
9
+ module Metasm
10
+ class WebAsm
11
+ def build_bin_lookaside
12
+ lookaside = (0..0xff).inject({}) { |h, i| h.update i => [] }
13
+ opcode_list.each { |op|
14
+ lookaside[op.bin] << op
15
+ }
16
+ lookaside
17
+ end
18
+
19
+ def decode_uleb(ed, signed=false)
20
+ v = s = 0
21
+ while s < 10*7
22
+ b = ed.read(1).unpack('C').first.to_i
23
+ v |= (b & 0x7f) << s
24
+ s += 7
25
+ break if (b&0x80) == 0
26
+ end
27
+ v = Expression.make_signed(v, s) if signed
28
+ v
29
+ end
30
+
31
+ # when starting disassembly, pre-decode all instructions until the final 'end' and fixup the xrefs (if/block/loop...)
32
+ def disassemble_init_context(dasm, addr)
33
+ dasm.misc ||= {}
34
+ dasm.misc[:cpu_context] ||= {}
35
+ cache = dasm.misc[:cpu_context][:di_cache] ||= {}
36
+ addr = dasm.normalize(addr)
37
+ return dasm.misc[:cpu_context] if cache[addr]
38
+
39
+ code_start = addr
40
+ stack = [[]]
41
+ set_misc_x = lambda { |di, tg| di.misc[:x] ||= [] ; di.misc[:x] |= [tg] }
42
+ while di = dasm.disassemble_instruction(addr)
43
+ cache[addr] = di
44
+ di.misc ||= {}
45
+ di.misc[:code_start] = code_start
46
+ case di.opcode.name
47
+ when 'if', 'loop', 'block'
48
+ stack << [di]
49
+ when 'else'
50
+ raise "bad #{di} #{stack.last.inspect}" if stack.last.empty? or stack.last.last.opcode.name != 'if'
51
+ stack.last.each { |ddi| set_misc_x[ddi, di.next_addr] } # 'if' points past here
52
+ di.misc[:end_of] = stack.last[0] # store matching 'if'
53
+ stack.last[0] = di # 'else' replace 'if'
54
+ when 'br', 'br_if', 'br_table'
55
+ if di.opcode.name == 'br_table'
56
+ depths = di.instruction.args.first.ary.uniq | [di.instruction.args.first.default]
57
+ else
58
+ depths = [di.instruction.args.first.reduce]
59
+ end
60
+ depths.each { |depth|
61
+ tg = stack[-depth-1] # XXX skip if/else in the stack ?
62
+ raise "bad #{di} (#{stack.length})" if not tg
63
+ if tg.first and tg.first.opcode.name == 'loop'
64
+ set_misc_x[di, tg.first.address]
65
+ else
66
+ tg << di
67
+ end
68
+ }
69
+ when 'end'
70
+ dis = stack.pop
71
+ dis.each { |ddi| set_misc_x[ddi, di.next_addr] if ddi.opcode.name != 'loop' and ddi.opcode.name != 'block' }
72
+ if stack.empty?
73
+ # stack empty: end of func
74
+ di.opcode = @opcode_list.find { |op| op.name == 'end' and op.props[:stopexec] }
75
+ break
76
+ else
77
+ if dis.first
78
+ di.misc[:end_of] = dis.first # store matching loop/block/if
79
+ if dis.first.opcode.name == 'else'
80
+ di.misc[:end_of] = dis.first.misc[:end_of] # else patched stack.last, recover original 'if'
81
+ end
82
+ end
83
+ di.opcode = @opcode_list.find { |op| op.name == 'end' and not op.props[:stopexec] }
84
+ end
85
+ end
86
+ addr = di.next_addr
87
+ end
88
+
89
+ dasm.misc[:cpu_context]
90
+ end
91
+
92
+ # reuse the instructions from the cache
93
+ def decode_instruction_context(dasm, edata, di_addr, ctx)
94
+ ctx ||= disassemble_init_context(dasm, di_addr)
95
+ if not ctx[:di_cache][di_addr]
96
+ di_addr = dasm.normalize(di_addr)
97
+ disassemble_init_context(dasm, di_addr)
98
+ end
99
+ ctx[:di_cache][di_addr]
100
+ end
101
+
102
+ def decode_findopcode(edata)
103
+ di = DecodedInstruction.new(self)
104
+ val = edata.decode_imm(:u8, @endianness)
105
+ di if di.opcode = bin_lookaside[val].first
106
+ end
107
+
108
+ def decode_instr_op(edata, di)
109
+ before_ptr = edata.ptr
110
+ op = di.opcode
111
+ di.instruction.opname = op.name
112
+
113
+ op.args.each { |a|
114
+ di.instruction.args << case a
115
+ when :f32; Expression[edata.decode_imm(:u32, @endianness)]
116
+ when :f64; Expression[edata.decode_imm(:u64, @endianness)]
117
+ when :memoff; Memref.new(decode_uleb(edata))
118
+ when :uleb; Expression[decode_uleb(edata)]
119
+ when :sleb; Expression[decode_uleb(edata, true)]
120
+ when :blocksig; BlockSignature.new(decode_uleb(edata, true))
121
+ when :br_table; decode_br_table(edata)
122
+ else raise SyntaxError, "Internal error: invalid argument #{a} in #{op.name}"
123
+ end
124
+ }
125
+
126
+ di.bin_length = 1 + edata.ptr - before_ptr
127
+ di
128
+ end
129
+
130
+ def decode_instr_interpret(di, addr)
131
+ case di.opcode.name
132
+ when 'call'
133
+ fnr = di.instruction.args.first.reduce
134
+ di.misc ||= {}
135
+ di.misc[:tg_func_nr] = fnr
136
+ if f = @wasm_file.get_function_nr(fnr)
137
+ tg = f[:init_offset] ? f[:init_offset] : "#{f[:module]}_#{f[:field]}"
138
+ di.instruction.args[0] = Expression[tg]
139
+ di.misc[:x] = [tg]
140
+ else
141
+ di.misc[:x] = [:default]
142
+ end
143
+ when 'call_indirect'
144
+ di.misc ||= {}
145
+ di.misc[:x] = [:default]
146
+ end
147
+ di
148
+ end
149
+
150
+ def decode_br_table(edata)
151
+ count = decode_uleb(edata)
152
+ ary = []
153
+ count.times { ary << decode_uleb(edata) }
154
+ default = decode_uleb(edata)
155
+ BrTable.new(ary, default)
156
+ end
157
+
158
+ def init_backtrace_binding
159
+ @backtrace_binding ||= {}
160
+
161
+ typesz = Hash.new(8).update 'i32' => 4, 'f32' => 4
162
+ opstack = lambda { |off, sz| Indirection[Expression[:opstack, :+, off].reduce, sz] }
163
+ add_opstack = lambda { |delta, hash| { :opstack => Expression[:opstack, :+, delta].reduce }.update hash }
164
+ globsz = lambda { |di|
165
+ glob_nr = Expression[di.instruction.args.first].reduce
166
+ g = @wasm_file.get_global_nr(glob_nr)
167
+ g ? typesz[g[:type]] : 8
168
+ }
169
+ global = lambda { |di|
170
+ glob_nr = Expression[di.instruction.args.first].reduce
171
+ g = @wasm_file.get_global_nr(glob_nr)
172
+ n = g && g[:module] ? "#{g[:module]}_#{g[:field]}" : "global_#{glob_nr}"
173
+ Indirection[n, globsz[di]]
174
+ }
175
+ locsz = lambda { |di|
176
+ loc_nr = Expression[di.instruction.args.first].reduce
177
+ ci = @wasm_file.code_info[di.misc[:code_start]]
178
+ next typesz[ci[:params][loc_nr]] if loc_nr < ci[:params].length
179
+ loc_nr -= ci[:params].length
180
+ next typesz[ci[:local_var][loc_nr]] if ci[:local_var][loc_nr]
181
+ 8
182
+ }
183
+ local = lambda { |di|
184
+ loc_nr = Expression[di.instruction.args.first].reduce
185
+ Indirection[[:local_base, :+, loc_nr*8], locsz[di]]
186
+ }
187
+
188
+ opcode_list.map { |ol| ol.name }.uniq.each { |opname|
189
+ sz = (opname[1, 2] == '32' ? 4 : 8)
190
+ @backtrace_binding[opname] ||= case opname
191
+ when 'call', 'call_indirect'
192
+ lambda { |di|
193
+ stack_off = 0
194
+ if opname == 'call'
195
+ f = @wasm_file.get_function_nr(di.misc[:tg_func_nr])
196
+ proto = f ? f[:type] : {}
197
+ # TODO use local_base
198
+ h = { :callstack => Expression[:callstack, :+, 8], Indirection[:callstack, 8] => Expression[di.next_addr] }
199
+ proto_params_offset = 0
200
+ else
201
+ proto = @wasm_file.type[di.instruction.args.first.reduce]
202
+ h = { :callstack => Expression[:callstack, :+, 8], Indirection[:callstack, 8] => Expression[di.next_addr], 'func_idx' => Expression[opstack[0, 4]] }
203
+ stack_off += 8
204
+ proto_params_offset = 1
205
+ end
206
+ stack_off -= 8*proto[:ret].to_a.length
207
+ stack_off += 8*proto[:params].to_a.length
208
+ h.update :opstack => Expression[:opstack, :+, stack_off]
209
+ proto[:ret].to_a.each_with_index { |rt, i| h.update opstack[8*i, typesz[rt]] => Expression["ret_#{i}"] }
210
+ proto[:params].to_a.each_with_index { |pt, i| h.update "param_#{i}" => Expression[opstack[8*(proto[:params].length-i-1+proto_params_offset), typesz[pt]]] }
211
+ h
212
+ }
213
+ when 'if', 'br_if'; lambda { |di| add_opstack[ 8, :flag => Expression[opstack[0, 8]]] }
214
+ when 'block', 'loop', 'br', 'nop', 'else'; lambda { |di| {} }
215
+ when 'end', 'return'; lambda { |di| di.opcode.props[:stopexec] ? { :callstack => Expression[:callstack, :-, 8] } : {} }
216
+ when 'drop'; lambda { |di| add_opstack[8, {}] }
217
+ when 'select'; lambda { |di| add_opstack[16, opstack[0, 8] => Expression[[opstack[8, 8], :*, [1, :-, opstack[0, 8]]], :|, [opstack[16, 8], :*, opstack[0, 8]]]] }
218
+ when 'get_local'; lambda { |di| add_opstack[-8, opstack[0, locsz[di]] => Expression[local[di]]] }
219
+ when 'set_local'; lambda { |di| add_opstack[ 8, local[di] => Expression[opstack[0, locsz[di]]]] }
220
+ when 'tee_local'; lambda { |di| add_opstack[ 0, local[di] => Expression[opstack[0, locsz[di]]]] }
221
+ when 'get_global'; lambda { |di| add_opstack[-8, opstack[0, globsz[di]] => Expression[global[di]]] }
222
+ when 'set_global'; lambda { |di| add_opstack[ 8, global[di] => Expression[opstack[0, globsz[di]]]] }
223
+ when /\.load(.*)/
224
+ mode = $1; memsz = (mode.include?('32') ? 4 : mode.include?('16') ? 2 : mode.include?('8') ? 1 : sz)
225
+ lambda { |di| add_opstack[ 0, opstack[0, sz] => Expression[Indirection[[opstack[0, 4], :+, [:mem, :+, di.instruction.args[1].off]], memsz]]] }
226
+ when /\.store(.*)/
227
+ mode = $1; memsz = (mode.include?('32') ? 4 : mode.include?('16') ? 2 : mode.include?('8') ? 1 : sz)
228
+ lambda { |di| add_opstack[ 16, Indirection[[opstack[8, 4], :+, [:mem, :+, di.instruction.args[1].off]], memsz] => Expression[opstack[0, sz], :&, (1 << (8*memsz)) - 1]] }
229
+ when /\.const/; lambda { |di| add_opstack[-8, opstack[0, sz] => Expression[di.instruction.args.first.reduce]] }
230
+ when /\.eqz/; lambda { |di| add_opstack[ 0, opstack[0, 8] => Expression[opstack[0, sz], :==, 0]] }
231
+ when /\.eq/; lambda { |di| add_opstack[ 8, opstack[0, 8] => Expression[opstack[8, sz], :==, opstack[0, sz]]] }
232
+ when /\.ne/; lambda { |di| add_opstack[ 8, opstack[0, 8] => Expression[opstack[8, sz], :!=, opstack[0, sz]]] }
233
+ when /\.lt/; lambda { |di| add_opstack[ 8, opstack[0, 8] => Expression[opstack[8, sz], :<, opstack[0, sz]]] }
234
+ when /\.gt/; lambda { |di| add_opstack[ 8, opstack[0, 8] => Expression[opstack[8, sz], :>, opstack[0, sz]]] }
235
+ when /\.le/; lambda { |di| add_opstack[ 8, opstack[0, 8] => Expression[opstack[8, sz], :<=, opstack[0, sz]]] }
236
+ when /\.ge/; lambda { |di| add_opstack[ 8, opstack[0, 8] => Expression[opstack[8, sz], :>=, opstack[0, sz]]] }
237
+
238
+ when /\.(clz|ctz|popcnt)/; lambda { |di| add_opstack[ 0, :bits => Expression[opstack[0, sz]]] }
239
+ when /\.add/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[opstack[8, sz], :+, opstack[0, sz]]] }
240
+ when /\.sub/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[opstack[8, sz], :-, opstack[0, sz]]] }
241
+ when /\.mul/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[opstack[8, sz], :*, opstack[0, sz]]] }
242
+ when /\.div/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[opstack[8, sz], :/, opstack[0, sz]]] }
243
+ when /\.rem/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[opstack[8, sz], :%, opstack[0, sz]]] }
244
+ when /\.and/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[opstack[8, sz], :&, opstack[0, sz]]] }
245
+ when /\.or/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[opstack[8, sz], :|, opstack[0, sz]]] }
246
+ when /\.xor/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[opstack[8, sz], :^, opstack[0, sz]]] }
247
+ when /\.shl/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[opstack[8, sz], :<<, opstack[0, sz]]] }
248
+ when /\.shr/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[opstack[8, sz], :>>, opstack[0, sz]]] }
249
+ when /\.rotl/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[[opstack[8, sz], :<<, opstack[0, sz]], :|, [opstack[8, sz], :>>, [8*sz, :-, opstack[0, sz]]]]] }
250
+ when /\.rotr/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[[opstack[8, sz], :>>, opstack[0, sz]], :|, [opstack[8, sz], :<<, [8*sz, :-, opstack[0, sz]]]]] }
251
+ when /f.*\.(abs|neg|ceil|floor|trunc|nearest|sqrt|copysign)/; lambda { |di| add_opstack[0, :incomplete_binding => 1] }
252
+ when /f.*\.(min|max)/; lambda { |di| add_opstack[8, :incomplete_binding => 1] }
253
+ when /i32.wrap/; lambda { |di| add_opstack[ 0, opstack[0, 4] => Expression[opstack[0, 8]]] }
254
+ when /i64.extend/; lambda { |di| add_opstack[ 0, opstack[0, 8] => Expression[opstack[0, 4]]] }
255
+ when /trunc|convert|promote|demote|reinterpret/; lambda { |di| add_opstack[0, :incomplete_binding => 1] }
256
+ end
257
+ }
258
+
259
+ @backtrace_binding
260
+ end
261
+
262
+ def get_backtrace_binding(di)
263
+ if binding = backtrace_binding[di.opcode.name]
264
+ binding[di] || {}
265
+ else
266
+ puts "unhandled instruction to backtrace: #{di}" if $VERBOSE
267
+ {:incomplete_binding => Expression[1]}
268
+ end
269
+ end
270
+
271
+ def fix_fwdemu_binding(di, fbd)
272
+ ori = fbd
273
+ fbd = {}
274
+ ori.each { |k, v|
275
+ if k.kind_of?(Indirection) and not k.target.lexpr.kind_of?(Indirection)
276
+ # dont fixup store8 etc
277
+ fbd[k.bind(:opstack => ori[:opstack]).reduce_rec] = v
278
+ else
279
+ fbd[k] = v
280
+ end
281
+ }
282
+ fbd
283
+ end
284
+
285
+ def get_xrefs_x(dasm, di)
286
+ if di.opcode.props[:stopexec]
287
+ case di.opcode.name
288
+ when 'return', 'end'
289
+ return [Indirection[:callstack, 8]]
290
+ end
291
+ end
292
+ return [] if not di.opcode.props[:setip]
293
+
294
+ di.misc ? [di.misc[:x]].flatten : []
295
+ end
296
+
297
+ def backtrace_is_function_return(expr, di=nil)
298
+ expr and Expression[expr] == Expression[Indirection[:callstack, 8]]
299
+ end
300
+
301
+ def disassembler_default_func
302
+ df = DecodedFunction.new
303
+ ra = Indirection[:callstack, 8]
304
+ df.backtracked_for << BacktraceTrace.new(ra, :default, ra, :x, nil)
305
+ df.backtrace_binding = { :callstack => Expression[:callstack, :-, 8] }
306
+ df
307
+ end
308
+
309
+ def backtrace_update_function_binding(dasm, faddr, f, retaddrlist, *wantregs)
310
+ f.backtrace_binding = { :callstack => Expression[:callstack, :-, 8] }
311
+ end
312
+
313
+ def backtrace_is_stack_address(expr)
314
+ ([:local_base, :opstack] & Expression[expr].expr_externals).first
315
+ end
316
+
317
+ def decode_c_function_prototype(cp, sym, orig=nil)
318
+ disassembler_default_func
319
+ end
320
+ end
321
+ end