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
@@ -4,7 +4,7 @@
4
4
  # Licence is LGPL, see LICENCE in the top-level directory
5
5
 
6
6
 
7
- require 'metasm/mips/opcodes'
7
+ require 'metasm/cpu/mips/opcodes'
8
8
  require 'metasm/parse'
9
9
 
10
10
  module Metasm
@@ -4,7 +4,7 @@
4
4
  # Licence is LGPL, see LICENCE in the top-level directory
5
5
 
6
6
 
7
- require 'metasm/mips/opcodes'
7
+ require 'metasm/cpu/mips/opcodes'
8
8
  require 'metasm/render'
9
9
 
10
10
  module Metasm
@@ -5,4 +5,4 @@
5
5
 
6
6
 
7
7
  require 'metasm/main'
8
- require 'metasm/dalvik/decode'
8
+ require 'metasm/cpu/msp430/decode'
@@ -0,0 +1,247 @@
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/msp430/opcodes'
7
+ require 'metasm/decode'
8
+
9
+ module Metasm
10
+ class MSP430
11
+ def build_opcode_bin_mask(op)
12
+ op.bin_mask = 0
13
+ op.fields.each_key { |f|
14
+ op.bin_mask |= @fields_mask[f] << @fields_shift[f]
15
+ }
16
+ op.bin_mask ^= 0xffff
17
+ end
18
+
19
+ def build_bin_lookaside
20
+ lookaside = Array.new(256) { [] }
21
+ opcode_list.each { |op|
22
+ build_opcode_bin_mask op
23
+ b = (op.bin >> 8) & 255
24
+ msk = (op.bin_mask >> 8) & 255
25
+
26
+ for i in b..(b | (255^msk))
27
+ lookaside[i] << op if i & msk == b & msk
28
+ end
29
+ }
30
+ lookaside
31
+ end
32
+
33
+ def decode_findopcode(edata)
34
+ di = DecodedInstruction.new(self)
35
+ val = edata.decode_imm(:u16, @endianness)
36
+ edata.ptr -= 2
37
+ di.opcode = @bin_lookaside[(val >> 8) & 0xff].find { |opcode| (val & opcode.bin_mask) == opcode.bin }
38
+ di if di.opcode
39
+ end
40
+
41
+ def decode_instr_op(edata, di)
42
+ before_ptr = edata.ptr
43
+ op = di.opcode
44
+ di.instruction.opname = op.name
45
+ val = edata.decode_imm(:u16, @endianness)
46
+
47
+ field_val = lambda{ |f|
48
+ (val >> @fields_shift[f]) & @fields_mask[f]
49
+ }
50
+
51
+ # must decode rs first
52
+ vals = {}
53
+ ([:rs, :rd, :r_pc] & op.args).each { |a|
54
+ mod = { :rs => :as, :rd => :ad, :r_pc => :ad }[a]
55
+ mod = :as if mod == :ad and not op.fields[mod] # addop_macro1 -> rs + ad
56
+
57
+ if a == :r_pc
58
+ r = Reg.new(0)
59
+ else
60
+ r = Reg.new(field_val[a])
61
+ end
62
+
63
+ w = op.props[:byte] ? 1 : 2
64
+
65
+ case field_val[mod]
66
+ when 0
67
+ if r.i == 3 and a == :rs
68
+ vals[a] = Expression[0]
69
+ else
70
+ vals[a] = r
71
+ end
72
+ when 1
73
+ if r.i == 3 and a == :rs
74
+ vals[a] = Expression[1]
75
+ else
76
+ imm = edata.decode_imm(:u16, @endianness)
77
+ r = nil if r.i == 2 # [imm]
78
+ vals[a] = Memref.new(r, imm, w)
79
+ end
80
+ when 2
81
+ if r.i == 3
82
+ vals[a] = Expression[2]
83
+ elsif r.i == 2
84
+ vals[a] = Expression[4]
85
+ else
86
+ vals[a] = Memref.new(r, 0, w)
87
+ end
88
+ when 3
89
+ if r.i == 3
90
+ vals[a] = Expression[-1]
91
+ elsif r.i == 2
92
+ vals[a] = Expression[8]
93
+ elsif r.i == 0 # pc++
94
+ # XXX order wrt other edata.decode_imm ?
95
+ vals[a] = Expression[edata.decode_imm(:u16, @endianness)]
96
+ else
97
+ vals[a] = Memref.new(r, 0, w, true)
98
+ end
99
+ end
100
+ }
101
+
102
+ op.args.each { |a|
103
+ di.instruction.args << case a
104
+ when :joff; Expression[2 * Expression.make_signed(field_val[a], 10)]
105
+ when :rs, :rd, :r_pc; vals[a]
106
+ else raise SyntaxError, "Internal error: invalid argument #{a} in #{op.name}"
107
+ end
108
+ }
109
+
110
+ di.bin_length += edata.ptr - before_ptr
111
+
112
+ return if edata.ptr > edata.length
113
+
114
+ di
115
+ end
116
+
117
+ def decode_instr_interpret(di, addr)
118
+ if di.opcode.props[:setip] and di.opcode.name =~ /^j/
119
+ delta = di.instruction.args.last.reduce
120
+ arg = Expression[[addr, :+, di.bin_length], :+, delta].reduce
121
+ di.instruction.args[-1] = Expression[arg]
122
+ end
123
+
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
+
134
+ opcode_list.map { |ol| ol.name }.uniq.each { |op|
135
+ @backtrace_binding[op] ||= case op
136
+ when 'mov'; lambda { |di, a0, a1| { a0 => Expression[a1] }}
137
+ when 'cmp', 'test'; lambda { |di, *a| {} } # TODO
138
+ when 'add', 'adc' ; lambda { |di, a0, a1| { a0 => Expression[a0, :+, a1] } }
139
+ when 'sub', 'sbc'; lambda { |di, a0, a1| { a0 => Expression[a0, :-, a1] } }
140
+ when 'and'; lambda { |di, a0, a1| { a0 => Expression[a0, :&, a1] } }
141
+ when 'or'; lambda { |di, a0, a1| { a0 => Expression[a0, :|, a1] } }
142
+ when 'xor'; lambda { |di, a0, a1| { a0 => Expression[a0, :^, a1] } }
143
+ when 'push'; lambda { |di, a0| { Indirection[:sp, 2] => Expression[a0],
144
+ :sp => Expression[:sp, :-, 2] } }
145
+ when 'call'; lambda { |di, a0| { Indirection[:sp, 2] => Expression[di.next_addr],
146
+ :sp => Expression[:sp, :-, 2] } }
147
+ when 'pop'; lambda { |di, a0| { a0 => Expression[Indirection[:sp, 2]],
148
+ :sp => Expression[:sp, :+, 2] } }
149
+ when 'ret'; lambda { |di| { :sp => Expression[:sp, :+, 2] } }
150
+ when 'reti'; lambda { |di| { :sp => Expression[:sp, :+, 4] } }
151
+ when /^j/; lambda { |di, a0| {} }
152
+ end
153
+ }
154
+
155
+ @backtrace_binding
156
+ end
157
+
158
+ def get_backtrace_binding(di)
159
+ a = di.instruction.args.map { |arg|
160
+ case arg
161
+ when Reg; arg.symbolic
162
+ when Memref; arg.symbolic(di.address)
163
+ else arg
164
+ end
165
+ }
166
+
167
+ if binding = backtrace_binding[di.opcode.basename]
168
+ bd = binding[di, *a] || {}
169
+ di.instruction.args.grep(Memref).each { |m|
170
+ next unless r = m.base and m.postincr
171
+ r = m.base.symbolic
172
+ bd[r] ||= Expression[r, :+, m.size]
173
+ }
174
+ bd
175
+ else
176
+ puts "unhandled instruction to backtrace: #{di}" if $VERBOSE
177
+ { :incomplete_binding => Expression[1] }
178
+ end
179
+ end
180
+
181
+ def get_xrefs_x(dasm, di)
182
+ return [] if not di.opcode.props[:setip]
183
+
184
+ case di.instruction.opname
185
+ when 'ret'
186
+ return [Indirection[:sp, 2, di.address]]
187
+ when 'reti'
188
+ return [Indirection[[:sp, :+, 2], 2, di.address]]
189
+ end
190
+
191
+ # XXX add pc, 42 ?
192
+ val = di.instruction.args[0]
193
+ case val
194
+ when Reg; val = val.symbolic
195
+ when Memref; val = val.symbolic(di.address)
196
+ end
197
+
198
+ [Expression[val]]
199
+ end
200
+
201
+ def backtrace_is_function_return(expr, di=nil)
202
+ expr = Expression[expr].reduce_rec
203
+ expr.kind_of?(Indirection) and expr.len == 2 and expr.target == Expression[:sp]
204
+ end
205
+
206
+ # updates the function backtrace_binding
207
+ # if the function is big and no specific register is given, do nothing (the binding will be lazily updated later, on demand)
208
+ def backtrace_update_function_binding(dasm, faddr, f, retaddrlist, *wantregs)
209
+ b = f.backtrace_binding
210
+
211
+ bt_val = lambda { |r|
212
+ next if not retaddrlist
213
+ b[r] = Expression::Unknown
214
+ bt = []
215
+ retaddrlist.each { |retaddr|
216
+ bt |= dasm.backtrace(Expression[r], retaddr, :include_start => true,
217
+ :snapshot_addr => faddr, :origin => retaddr)
218
+ }
219
+ if bt.length != 1
220
+ b[r] = Expression::Unknown
221
+ else
222
+ b[r] = bt.first
223
+ end
224
+ }
225
+
226
+ if not wantregs.empty?
227
+ wantregs.each(&bt_val)
228
+ else
229
+ bt_val[:sp]
230
+ end
231
+
232
+ b
233
+ end
234
+
235
+ def replace_instr_arg_immediate(i, old, new)
236
+ i.args.map! { |a|
237
+ case a
238
+ when Expression; a == old ? new : Expression[a.bind(old => new).reduce]
239
+ when Memref
240
+ a.base = (a.base == old ? new : Expression[a.base.bind(old => new).reduce]) if a.base.kind_of?(Expression)
241
+ a
242
+ else a
243
+ end
244
+ }
245
+ end
246
+ end
247
+ end
@@ -0,0 +1,62 @@
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/main'
7
+
8
+ module Metasm
9
+
10
+ class MSP430 < CPU
11
+ def initialize(e = :little)
12
+ super()
13
+ @endianness = e
14
+ @size = 16
15
+ end
16
+
17
+ class Reg
18
+ include Renderable
19
+ Sym = (4..15).inject(0 => :pc, 1 => :sp, 2 => :flags, 3 => :rzero) { |h, i| h.update i => "r#{i}".to_sym }
20
+
21
+ attr_accessor :i
22
+ def initialize(i) ; @i = i end
23
+ def symbolic ; Sym[@i] end
24
+ def render ; [Sym[@i].to_s] end
25
+ def ==(o) ; o.class == self.class and o.i == @i end
26
+ end
27
+
28
+ class Memref
29
+ attr_accessor :base, :offset, :size, :postincr
30
+
31
+ def initialize(base, offset = 0, size = nil, postincr = false)
32
+ @base = base
33
+ @offset = Expression[offset]
34
+ @size = size
35
+ @postincr = postincr
36
+ end
37
+
38
+ def symbolic(orig=nil)
39
+ r = @base.symbolic if @base
40
+ e = Expression[r, :+, @offset].reduce
41
+ Indirection[e, (@size || 1), orig]
42
+ end
43
+
44
+ include Renderable
45
+
46
+ def render
47
+ b = @base
48
+ b = @base.to_s + '++' if @base and @postincr
49
+ p = Expression[b, :+, @offset].reduce
50
+ Indirection[p, @size].render
51
+ end
52
+ end
53
+
54
+ def init_opcode_list
55
+ init
56
+ end
57
+
58
+ def dbg_register_list
59
+ @dbg_register_list ||= Reg::Sym.sort.transpose.last
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,101 @@
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/msp430/main'
7
+
8
+ module Metasm
9
+ class MSP430
10
+ def addop(name, bin, *args)
11
+ o = Opcode.new name, bin
12
+
13
+ args.each { |a|
14
+ o.args << a if @valid_args[a]
15
+ o.props[a] = true if @valid_props[a]
16
+ o.fields[a] = [@fields_mask[a], @fields_shift[a]] if @fields_mask[a]
17
+ }
18
+
19
+ @opcode_list << o
20
+ end
21
+
22
+ def init
23
+ @opcode_list = []
24
+
25
+ @fields_mask = {
26
+ :as => 3, # adressing mode
27
+ :ad => 1, # adressing mode
28
+ :rd => 0xf,
29
+ :rs => 0xf,
30
+ :joff => 0x3ff, # signed offset for jumps
31
+ }
32
+ @fields_shift = {
33
+ :as => 4,
34
+ :ad => 7,
35
+ :rd => 0,
36
+ :rs => 8,
37
+ :joff => 0,
38
+ }
39
+ @valid_args = { :r_pc => true, :rd => true, :rs => true, :joff => true }
40
+ @valid_props = { :setip => true, :stopexec => true, :saveip => true, :byte => true }
41
+
42
+ # https://en.wikipedia.org/wiki/TI_MSP430
43
+
44
+ addop_macro1 'rrc', 0, :byte
45
+ addop_macro1 'swpb', 1
46
+ addop_macro1 'rra', 2, :byte
47
+ addop_macro1 'sxt', 3
48
+ addop_macro1 'push', 4, :byte
49
+ addop_macro1 'call', 5, :setip, :stopexec, :saveip
50
+
51
+ addop 'reti', 0b000100_110_0000000
52
+
53
+ addop_macro2 'jnz', 0
54
+ addop_macro2 'jz', 1
55
+ addop_macro2 'jnc', 2
56
+ addop_macro2 'jc', 3
57
+ addop_macro2 'jb', 4 # 'jn' jump if negative => jl unsigned ?
58
+ addop_macro2 'jge', 5
59
+ addop_macro2 'jl', 6
60
+ addop_macro2 'jmp', 7, :stopexec
61
+
62
+ addop 'ret', 0x4130, :setip, :stopexec # mov pc, [sp++]
63
+ addop 'pop', 0x4130, :rd, :ad # mov rd, [sp++]
64
+
65
+ addop_macro3 'mov', 4
66
+ addop_macro3 'add', 5
67
+ addop_macro3 'adc', 6 # 'addc'
68
+ addop_macro3 'sbc', 7
69
+ addop_macro3 'sub', 8
70
+ addop_macro3 'cmp', 9
71
+ addop_macro3 'dadd',10 # decimal add with carry
72
+ addop_macro3 'test',11 # 'bit'
73
+ addop_macro3 'andn',12 # 'bic'
74
+ addop_macro3 'or', 13 # 'bis'
75
+ addop_macro3 'xor', 14
76
+ addop_macro3 'and', 15
77
+ end
78
+
79
+ def addop_macro1(name, bin, *props)
80
+ if props.delete :byte
81
+ addop_byte name, (0b000100 << 10) | (bin << 7), :as, :rd, *props
82
+ else
83
+ addop name, (0b000100 << 10) | (bin << 7), :as, :rd, *props
84
+ end
85
+ end
86
+
87
+ def addop_macro2(name, bin, *props)
88
+ addop name, (0b001 << 13) | (bin << 10), :joff, :setip, *props
89
+ end
90
+
91
+ def addop_macro3(name, bin, *props)
92
+ addop_byte name, (bin << 12), :r_pc, :ad, :as, :rs, :setip, :stopexec # dst == pc
93
+ addop_byte name, (bin << 12), :rd, :ad, :as, :rs
94
+ end
95
+
96
+ def addop_byte(name, bin, *props)
97
+ addop name, bin, *props
98
+ addop name + '.b', bin | (1 << 6), :byte, *props
99
+ end
100
+ end
101
+ end
@@ -4,7 +4,7 @@
4
4
  # Licence is LGPL, see LICENCE in the top-level directory
5
5
 
6
6
 
7
- require 'metasm/pic16c/opcodes'
7
+ require 'metasm/cpu/pic16c/opcodes'
8
8
  require 'metasm/decode'
9
9
 
10
10
  module Metasm
@@ -17,22 +17,21 @@ class Pic16c
17
17
  }
18
18
  op.bin_mask.map! { |v| 255 ^ v }
19
19
  end
20
-
20
+
21
21
  def build_bin_lookaside
22
22
  # sets up a hash byte value => list of opcodes that may match
23
23
  # opcode.bin_mask is built here
24
24
  lookaside = Array.new(256) { [] }
25
25
  @opcode_list.each { |op|
26
-
26
+
27
27
  build_opcode_bin_mask op
28
-
28
+
29
29
  b = op.bin[0]
30
30
  msk = op.bin_mask[0]
31
-
32
-
31
+
33
32
  for i in b..(b | (255^msk))
34
33
  ext if i & msk != b & msk
35
-
34
+
36
35
  lookaside[i] << op
37
36
  end
38
37
  }