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
@@ -0,0 +1 @@
1
+ See <use_cases.txt>
@@ -8,11 +8,11 @@ There are quite a lot of possible usages that can be derived from the
8
8
  The major would be related to:
9
9
 
10
10
  * the scriptable <usage/debugger.txt>
11
- * the <usage/disassembler.txt> (with the optionnal <usage/disassembler_gui.txt>)
11
+ * the <usage/disassembler.txt> (with the optional <usage/disassembler_gui.txt>)
12
12
  * the <usage/assembler.txt>
13
13
  * the <usage/C_parser.txt>
14
14
  * the <usage/C_compiler.txt>
15
15
  * the <usage/exe_manipulation.txt> facilities
16
16
 
17
- and various interaction between those.
17
+ and various interactions among them.
18
18
 
@@ -0,0 +1,22 @@
1
+ lib = File.expand_path('.', File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'metasm'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'metasm'
7
+ s.version = '1.0.2'
8
+ s.summary =
9
+ "Metasm is a cross-architecture assembler, disassembler, linker, and debugger."
10
+ s.description = ""
11
+ s.authors = ["Yoann Guillot"]
12
+ s.email = ['john at ofjj.net']
13
+ s.files = `git ls-files -z`.split("\x0")
14
+ s.test_files = s.files.grep(%r{^tests/})
15
+ s.require_paths = ["."]
16
+ s.homepage = 'http://metasm.cr0.org'
17
+ s.license = 'LGPL'
18
+
19
+ s.add_development_dependency "bundler", "~> 1.7"
20
+ s.add_development_dependency "rake"
21
+ end
22
+
@@ -15,6 +15,7 @@ module Metasm
15
15
  Const_autorequire_equiv = {
16
16
  'X86' => 'Ia32', 'PPC' => 'PowerPC',
17
17
  'X64' => 'X86_64', 'AMD64' => 'X86_64',
18
+ 'MIPS64' => 'MIPS', 'AArch64' => 'ARM64',
18
19
  'UniversalBinary' => 'MachO', 'COFFArchive' => 'COFF',
19
20
  'DEY' => 'DEX',
20
21
  'PTrace' => 'LinOS', 'FatELF' => 'ELF',
@@ -32,8 +33,10 @@ module Metasm
32
33
 
33
34
  # files to require to get the definition of those constants
34
35
  Const_autorequire = {
35
- 'Ia32' => 'ia32', 'MIPS' => 'mips', 'PowerPC' => 'ppc', 'ARM' => 'arm',
36
- 'X86_64' => 'x86_64', 'Sh4' => 'sh4', 'Dalvik' => 'dalvik',
36
+ 'Ia32' => 'cpu/ia32', 'MIPS' => 'cpu/mips', 'PowerPC' => 'cpu/ppc', 'ARM' => 'cpu/arm',
37
+ 'X86_64' => 'cpu/x86_64', 'Sh4' => 'cpu/sh4', 'Dalvik' => 'cpu/dalvik', 'ARC' => 'cpu/arc',
38
+ 'Python' => 'cpu/python', 'Z80' => 'cpu/z80', 'CY16' => 'cpu/cy16', 'BPF' => 'cpu/bpf',
39
+ 'MSP430' => 'cpu/msp430', 'ARM64' => 'cpu/arm64',
37
40
  'C' => 'compile_c',
38
41
  'MZ' => 'exe_format/mz', 'PE' => 'exe_format/pe',
39
42
  'ELF' => 'exe_format/elf', 'COFF' => 'exe_format/coff',
@@ -41,12 +44,17 @@ module Metasm
41
44
  'AOut' => 'exe_format/a_out', 'MachO' => 'exe_format/macho',
42
45
  'DEX' => 'exe_format/dex',
43
46
  'NDS' => 'exe_format/nds', 'XCoff' => 'exe_format/xcoff',
47
+ 'GameBoyRom' => 'exe_format/gb',
44
48
  'Bflt' => 'exe_format/bflt', 'Dol' => 'exe_format/dol',
49
+ 'PYC' => 'exe_format/pyc', 'JavaClass' => 'exe_format/javaclass',
50
+ 'SWF' => 'exe_format/swf', 'ZIP' => 'exe_format/zip',
51
+ 'Shellcode_RWX' => 'exe_format/shellcode_rwx',
45
52
  'Gui' => 'gui',
46
53
  'WindowsExports' => 'os/windows_exports',
47
54
  'GNUExports' => 'os/gnu_exports',
55
+ 'Debugger' => 'debug',
48
56
  'LinOS' => 'os/linux', 'WinOS' => 'os/windows',
49
- 'GdbClient' => 'os/remote',
57
+ 'GdbClient' => 'os/gdbremote',
50
58
  'Disassembler' => 'disassemble',
51
59
  'Decompiler' => 'decompile',
52
60
  'DynLdr' => 'dynldr',
@@ -11,14 +11,14 @@ module Metasm
11
11
  module C
12
12
  class Parser
13
13
  def precompile
14
- @toplevel.precompile(Compiler.new(self))
14
+ @toplevel.precompile(Compiler.new(self, @program))
15
15
  self
16
16
  end
17
17
  end
18
18
 
19
19
  # each CPU defines a subclass of this one
20
20
  class Compiler
21
- # an ExeFormat (mostly used for unique label creation)
21
+ # an ExeFormat (mostly used for unique label creation, and cpu.check_reserved_name)
22
22
  attr_accessor :exeformat
23
23
  # the C Parser (destroyed by compilation)
24
24
  attr_accessor :parser
@@ -36,7 +36,8 @@ module C
36
36
  end
37
37
 
38
38
  # creates a new CCompiler from an ExeFormat and a C Parser
39
- def initialize(parser, exeformat=ExeFormat.new, source=[])
39
+ def initialize(parser, exeformat=nil, source=[])
40
+ exeformat ||= ExeFormat.new
40
41
  @parser, @exeformat, @source = parser, exeformat, source
41
42
  @auto_label_list = {}
42
43
  @label_oldname = {}
@@ -280,7 +281,7 @@ module C
280
281
  when :ptr; " d#{%w[x b w x d x x x q][@parser.typesize[type.name]]} "
281
282
  when :float; ' db ' + [value].pack(@parser.endianness == :little ? 'e' : 'g').unpack('C*').join(', ') + ' // '
282
283
  when :double; ' db ' + [value].pack(@parser.endianness == :little ? 'E' : 'G').unpack('C*').join(', ') + ' // '
283
- when :longdouble; ' db ' + [value].pack(@parser.endianness == :little ? 'E' : 'G').unpack('C*').join(', ') + ' // ' # XXX same as :double
284
+ when :longdouble; ' db ' + [value].pack(@parser.endianness == :little ? 'E' : 'G').unpack('C*').join(', ') + ' // ' # XXX same as :double
284
285
  else raise "unknown idata type #{type.inspect} #{value.inspect}"
285
286
  end
286
287
 
@@ -428,6 +429,7 @@ module C
428
429
  # return non-nil if the variable name is unsuitable to appear as is in the asm listing
429
430
  # eg filter out asm instruction names
430
431
  def check_reserved_name(var)
432
+ return true if @exeformat.cpu and @exeformat.cpu.check_reserved_name(var.name)
431
433
  %w[db dw dd dq].include?(var.name)
432
434
  end
433
435
  end
@@ -555,8 +557,12 @@ module C
555
557
  # reuse same name as predeclarations
556
558
  @var.name = n
557
559
  else
558
- @var.name = compiler.new_label @var.name until @var.name != old
559
- compiler.label_oldname[@var.name] = old
560
+ newname = old
561
+ newname = compiler.new_label newname until newname != old
562
+ if not compiler.check_reserved_name(@var)
563
+ compiler.label_oldname[newname] = old
564
+ end
565
+ @var.name = newname
560
566
  end
561
567
  ref ||= scope.symbol[@var.name] || @var
562
568
  # append only one actual declaration for all predecls (the one with init, or the last uninit)
@@ -684,7 +690,7 @@ module C
684
690
  if not init.op and init.rexpr.kind_of? ::String
685
691
  v = Variable.new
686
692
  v.storage = :static
687
- v.name = 'char_' + init.rexpr.tr('^a-zA-Z', '')[0, 8]
693
+ v.name = 'char_' + init.rexpr.gsub(/[^a-zA-Z]/, '')[0, 8]
688
694
  v.type = Array.new(type.type)
689
695
  v.type.length = init.rexpr.length + 1
690
696
  v.type.type.qualifier = [:const]
@@ -0,0 +1,8 @@
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
+
7
+ require 'metasm/main'
8
+ require 'metasm/cpu/arc/decode'
@@ -0,0 +1,425 @@
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/arc/opcodes'
7
+ require 'metasm/decode'
8
+
9
+ module Metasm
10
+ class ARC
11
+ def major_opcode(val, sz = 16)
12
+ return val >> (sz == 16 ? 0xB : 0x1B)
13
+ end
14
+
15
+ def sub_opcode(val)
16
+ return ((val >> 16) & 0x3f)
17
+ end
18
+
19
+ def build_opcode_bin_mask(op, sz)
20
+ op.bin_mask = 0
21
+ op.args.each { |f| op.bin_mask |= @fields_mask[f] << @fields_shift[f]}
22
+ op.bin_mask = ((1 << sz)-1) ^ op.bin_mask
23
+ end
24
+
25
+ def build_bin_lookaside
26
+ bin_lookaside = {}
27
+ opcode_list.each{|mode,oplist|
28
+ lookaside = {}
29
+ # 2nd level to speed up lookaside for major 5
30
+ lookaside[5] = {}
31
+ oplist.each { |op|
32
+ next if not op.bin.kind_of? Integer
33
+ build_opcode_bin_mask(op, mode)
34
+ mj = major_opcode(op.bin, mode)
35
+ if mode == 32 and mj == 5
36
+ (lookaside[mj][sub_opcode(op.bin)] ||= []) << op
37
+ else
38
+ (lookaside[mj] ||= []) << op
39
+ end
40
+ }
41
+ bin_lookaside[mode] = lookaside
42
+ }
43
+ bin_lookaside
44
+ end
45
+
46
+ def instruction_size(edata)
47
+ val = major_opcode(edata.decode_imm(:u16, @endianness))
48
+ edata.ptr -= 2
49
+ (val >= 0xC) ? 16 : 32
50
+ end
51
+
52
+ def memref_size(di)
53
+ case di.opcode.name
54
+ when 'ldb_s', 'stb_s', 'extb_s', 'sexb_s'; 1
55
+ when 'ldw_s', 'stw_s', 'extw_s', 'sexw_s'; 2
56
+ else 4
57
+ end
58
+ end
59
+
60
+ def decode_bin(edata, sz)
61
+ case sz
62
+ when 16; edata.decode_imm(:u16, @endianness)
63
+ when 32
64
+ # wordswap
65
+ val = edata.decode_imm(:u32, :little)
66
+ ((val >> 16) & 0xffff) | ((val & 0xffff) << 16)
67
+ end
68
+ end
69
+
70
+ def decode_findopcode(edata)
71
+ di = DecodedInstruction.new(self)
72
+
73
+ @instrlength = instruction_size(edata)
74
+ val = decode_bin(edata, @instrlength)
75
+ edata.ptr -= @instrlength/8
76
+
77
+ maj = major_opcode(val, @instrlength)
78
+ lookaside = @bin_lookaside[@instrlength][maj]
79
+ lookaside = lookaside[sub_opcode(val)] if @instrlength == 32 and maj == 5
80
+
81
+ op = lookaside.select { |opcode|
82
+ if $ARC_DEBUG and (val & opcode.bin_mask) == opcode.bin
83
+ puts "#{opcode.bin_mask.to_s(16)} - #{opcode.bin.to_s(16)} - #{(val & opcode.bin_mask).to_s(16)} - #{opcode.name} - #{opcode.args}"
84
+ end
85
+ (val & opcode.bin_mask) == opcode.bin
86
+ }
87
+
88
+ if op.size == 2 and op.first.name == 'mov' and op.last.name == 'nop'
89
+ op = op.last
90
+ elsif op == nil or op.size != 1
91
+ puts "[> I sense a disturbance in the force <]"
92
+ op.to_a.each { |opcode| puts "#{opcode.name} - #{opcode.args} - #{Expression[opcode.bin]} - #{Expression[opcode.bin_mask]}" }
93
+ puts "current value: #{Expression[val]}"
94
+ puts "current value: 0b#{val.to_s(2)}"
95
+ op = nil
96
+ else
97
+ op = op.first
98
+ end
99
+
100
+ di if di.opcode = op
101
+ end
102
+
103
+ Reduced_reg = [0, 1, 2, 3, 12, 13, 14, 15]
104
+ def reduced_reg_set(i)
105
+ Reduced_reg[i]
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
+ val = decode_bin(edata, @instrlength)
113
+
114
+ field_val = lambda { |f|
115
+ r = (val >> @fields_shift[f]) & @fields_mask[f]
116
+ case f
117
+
118
+ # 16-bits instruction operands ------------------------------------------"
119
+ when :ca, :cb, :cb2, :cb3, :cc; r = reduced_reg_set(r)
120
+ when :ch
121
+ r = (((r & 7) << 3) | (r >> 5))
122
+ when :@cbu7, :@cbu6, :@cbu5
123
+ r = r & 0b11111
124
+ r = (f == :@cbu7) ? r << 2 : ( (f == :@cbu6) ? r << 1 : r)
125
+ when :cu5ee; r = r << 2
126
+ when :cdisps13
127
+ r = (Expression.make_signed(r,11) << 2) + ((di.address >> 2) << 2)
128
+ when :cdisps10
129
+ r = (Expression.make_signed(r, 9) << 1) + ((di.address >> 2) << 2)
130
+ when :cdisps8
131
+ r = (Expression.make_signed(r, 7) << 1) + ((di.address >> 2) << 2)
132
+ when :cdisps7
133
+ r = (Expression.make_signed(r, 6) << 1) + ((di.address >> 2) << 2)
134
+ when :cs9, :cs10, :cs11
135
+ r = Expression.make_signed(r, ((f== :cs11 ? 11 : (f == :cs10 ? 10 : 9) )))
136
+ r = (f == :cs11) ? r << 2 : ((f == :cs10) ? r << 1 : r)
137
+ when :@cspu7;
138
+ r = r << 2
139
+
140
+ # 32-bits instruction operands ------------------------------------------"
141
+ when :b
142
+ r = (r >> 12) | ((r & 0x7) << 3)
143
+ when :s8e
144
+ r = ((r & 0x1) << 7) | (r >> 2)
145
+ r = (Expression.make_signed(r, 8) << 1) + ((di.address >> 2) << 2)
146
+
147
+ when :u6e
148
+ r = (r << 1) + ((di.address >> 2) << 2)
149
+ when :s9
150
+ r = (Expression.make_signed(r, 7) << 1) + ((di.address >> 2) << 2)
151
+
152
+ when :s12
153
+ r = (r >> 6) | ((r & 0x3f) << 6)
154
+ r = Expression.make_signed(r, 12)
155
+
156
+ when :s12e
157
+ r = (r >> 6) | ((r & 0x3f) << 6)
158
+ r = (Expression.make_signed(r, 12) <<1 ) + ((di.address >> 2) << 2)
159
+
160
+ when :s21e
161
+ r = ((r & 0x3ff) << 10) | (r >> 11)
162
+ r = (Expression.make_signed(r, 20) << 1) + ((di.address >> 2) << 2)
163
+
164
+ when :s21ee # pc-relative
165
+ r = ((r & 0x3ff) << 9) | (r >> 12)
166
+ r = (Expression.make_signed(r, 19) << 2) + ((di.address >> 2) << 2)
167
+
168
+ when :s25e # pc-relative
169
+ r = ((r & 0xf) << 20) | (((r >> 6) & 0x3ff) << 10) | (r >> 17)
170
+ r = (Expression.make_signed(r, 24) << 1) + ((di.address >> 2) << 2)
171
+
172
+ when :s25ee # pc-relative
173
+ r = ((r & 0xf) << 19) | (((r >> 6) & 0x3ff) << 9) | (r >> 18)
174
+ r = (Expression.make_signed(r, 23) << 2) + ((di.address >> 2) << 2)
175
+
176
+ when :@bs9
177
+ r = r >> 3
178
+ s9 = ((r & 1) << 8) | ((r >> 1) & 0xff)
179
+ r = Expression.make_signed(s9, 9)
180
+
181
+ when :bext, :cext, :@cext
182
+ if ((r = field_val[(f == :bext) ? :b : :c]) == 0x3E)
183
+ tmp = edata.decode_imm(:u32, :little)
184
+ r = Expression[(tmp >> 16) | ((tmp & 0xffff) << 16)]
185
+ else
186
+ r = GPR.new(r)
187
+ end
188
+
189
+ else r
190
+ end
191
+ r
192
+ }
193
+
194
+ # decode properties fields
195
+ op.args.each { |a|
196
+ case a
197
+ when :flags15, :flags16
198
+ di.instruction.opname += '.f' if field_val[a] != 0
199
+ when :ccond
200
+ di.instruction.opname += ('.' + @cond_suffix[field_val[a]]) if field_val[a] != 0
201
+ when :delay5, :delay16
202
+ di.instruction.opname += '.d' if field_val[a] != 0
203
+ when :cache5, :cache11, :cache16
204
+ di.instruction.opname +='.di' if field_val[a] != 0
205
+ when :signext6, :signext16
206
+ di.instruction.opname += '.x' if field_val[a] != 0
207
+ when :wb3, :wb9, :wb22
208
+ case field_val[a]
209
+ when 1; di.instruction.opname += ((memref_size(di) == 2) ? '.ab' : '.a')
210
+ when 2; di.instruction.opname += '.ab'
211
+ when 3; di.instruction.opname += '.as'
212
+ end
213
+ when :sz1, :sz7, :sz16, :sz17
214
+ case field_val[a]
215
+ when 1; di.instruction.opname += 'b'
216
+ when 2; di.instruction.opname += 'w'
217
+ end
218
+ else
219
+ di.instruction.args << case a
220
+
221
+ # 16-bits instruction operands ------------------------------------------"
222
+ when :cr0; GPR.new 0
223
+ when :ca, :cb, :cb2, :cb3, :cc; GPR.new(field_val[a])
224
+ when :ch
225
+ if ((r = field_val[a]) == 0x3E)
226
+ tmp = edata.decode_imm(:u32, :little)
227
+ Expression[(tmp >> 16) | ((tmp & 0xffff) << 16)]
228
+ else
229
+ GPR.new(r)
230
+ end
231
+
232
+ when :@gps9, :@gps10, :@gps11
233
+ imm = (a == :@gps11) ? :cs11 : (a == :@gps10) ? :cs10 : :cs9
234
+ Memref.new(GPR.new(26), Expression[field_val[imm]], memref_size(di))
235
+
236
+ when :cu3, :cu5, :cu5ee, :cu6, :cu7, :cu7l, :cu8; Expression[field_val[a]]
237
+ when :cs9, :cs10, :cs11; Expression[field_val[a]]
238
+ when :cdisps7, :cdisps8, :cdisps10, :cdisps13; Expression[field_val[a]]
239
+ when :@cb; Memref.new(GPR.new(field_val[:cb]), nil, memref_size(di))
240
+ when :@cbu7, :@cbu6, :@cbu5; Memref.new(GPR.new(field_val[:cb]), Expression[field_val[a]], memref_size(di))
241
+ when :@cspu7; Memref.new(GPR.new(28), field_val[a], memref_size(di))
242
+ when :@cbcc; Memref.new(field_val[:cb], field_val[:cc], memref_size(di))
243
+
244
+ # 32-bits instruction operands ------------------------------------------"
245
+ when :a, :b
246
+ ((r = field_val[a]) == 0x3E) ? :zero : GPR.new(r)
247
+ when :b2; GPR.new field_val[:b]
248
+ when :c; GPR.new field_val[a]
249
+ when :bext, :cext; field_val[a]
250
+ when :@cext
251
+ target = field_val[a]
252
+ (di.opcode.props[:setip] and target.kind_of? GPR) ? Memref.new(target, nil, memref_size(di)) : target
253
+
254
+ when :@bextcext
255
+ tmp = field_val[a]
256
+ #c = tmp & 0x3F
257
+ tmp = tmp >> 6
258
+ b = (tmp >> 12) | ((tmp & 0x7) << 3)
259
+ Memref.new(field_val[:bext], field_val[:cext], memref_size(di))
260
+
261
+ when :u6, :u6e, :s8e, :s9, :s12; Expression[field_val[a]]
262
+ when :s12e, :s21e, :s21ee, :s25e, :s25ee; Expression[field_val[a]]
263
+ when :auxs12; AUX.new field_val[:s12]
264
+ when :@c; Memref.new(GPR.new(field_val[a]), nil, memref_size(di))
265
+ when :@bcext; Memref.new(field_val[a], nil, memref_size(di))
266
+ when :@bcext; Memref.new(field_val[:b], field_val[:cext], memref_size(di))
267
+ when :@bs9
268
+ # [b,s9] or [limm] if b = 0x3E
269
+ base = field_val[:bext]
270
+ Memref.new(base, (base.kind_of? GPR) ? Expression[field_val[a]] : nil, memref_size(di))
271
+
272
+ # common instruction operands ------------------------------------------"
273
+ when :zero; Expression[0]
274
+ when :gp; GPR.new(26)
275
+ when :sp, :sp2; GPR.new(28)
276
+ when :blink; GPR.new(31)
277
+ when :@ilink1; Memref.new(GPR.new(29), nil, memref_size(di))
278
+ when :@ilink2; Memref.new(GPR.new(30), nil, memref_size(di))
279
+ when :@blink; Memref.new(GPR.new(31), nil, memref_size(di))
280
+
281
+ else raise SyntaxError, "Internal error: invalid argument #{a} in #{op.name}"
282
+ end
283
+ end
284
+ }
285
+
286
+ di.bin_length += edata.ptr - before_ptr
287
+
288
+ return if edata.ptr > edata.virtsize
289
+
290
+ di
291
+ end
292
+
293
+ def disassembler_default_func
294
+ df = DecodedFunction.new
295
+ df.backtrace_binding = {}
296
+ 15.times { |i|
297
+ df.backtrace_binding["r#{i}".to_sym] = Expression::Unknown
298
+ }
299
+ df.backtracked_for = []
300
+ df.btfor_callback = lambda { |dasm, btfor, funcaddr, calladdr|
301
+ if funcaddr != :default
302
+ btfor
303
+ elsif di = dasm.decoded[calladdr] and di.opcode.props[:saveip]
304
+ btfor
305
+ else []
306
+ end
307
+ }
308
+ df
309
+ end
310
+
311
+ REG_SYMS = [:r26, :r27, :r28, :r29, :r30, :r31, :r60]
312
+ def register_symbols
313
+ REG_SYMS
314
+ end
315
+
316
+ def backtrace_binding
317
+ @backtrace_binding ||= init_backtrace_binding
318
+ end
319
+
320
+ def opshift(op)
321
+ op[/\d/].to_i
322
+ end
323
+
324
+ def with_res(arg)
325
+ arg != :zero
326
+ end
327
+
328
+ def init_backtrace_binding
329
+ sp = :r28
330
+ blink = :r31
331
+
332
+ @backtrace_binding ||= {}
333
+
334
+ mask = lambda { |sz| (1 << sz)-1 } # 32bits => 0xffff_ffff
335
+
336
+ opcode_list.each{|mode, oplist|
337
+ oplist.map { |ol| ol.name }.uniq.each { |op|
338
+ binding = case op
339
+ when /^add/, /^sub/
340
+ lambda { |di, a0, a1, a2|
341
+ if (shift = opshift(op)) == 0
342
+ { a0 => Expression[[a1, :+, a2], :&, mask[32]] }
343
+ else
344
+ { a0 => Expression[[a1, :+, [a2, :<<, shift]], :&, mask[32]] }
345
+ end
346
+ }
347
+ when /^and/
348
+ lambda { |di, a0, a1, a2| { a0 => Expression[a1, :&, a2] } }
349
+ when /^asl/
350
+ lambda { |di, *a| { a[0] => Expression[[a[1], :<<, (a[2] ? a[2]:1)], :&, mask[32]] } }
351
+ when /^bxor/
352
+ lambda { |di, a0, a1, a2| { a0 => Expression[a1, :^, [1, :<<, a2]] }}
353
+ when /^bclr/; lambda { |di, a0, a1, a2| { a0 => Expression[a1, :&, Expression[mask[32], :^, Expression[1, :<<, a2]]] } }
354
+ when /^bset/; lambda { |di, a0, a1, a2| { a0 => Expression[a1, :|, Expression[1, :<<, a2]] } }
355
+ when /^jl/; lambda { |di, a0| { blink => Expression[di.next_addr] } }
356
+ when 'bl', 'bl_s', /^bl\./
357
+ # FIXME handle delay slot
358
+ # "This address is taken either from the first instruction following the branch (current PC) or the
359
+ # instruction after that (next PC) according to the delay slot mode (.d)."
360
+ lambda { |di, a0| { blink => Expression[di.next_addr] } }
361
+ when /^mov/, /^lr/, /^ld/; lambda { |di, a0, a1| { a0 => a1 } }
362
+ when /^neg/; lambda { |di, a0, a1| { a0 => Expression[[0, :-, a1], :&, mask[32]] } }
363
+ when /^not/; lambda { |di, a0, a1| { a0 => Expression[[:~, a1], :&, mask[32]] } }
364
+ when /^or/; lambda { |di, a0, a1, a2| { a0 => Expression[a1, :|, a2] } }
365
+ when /^st/, /^sr/; lambda { |di, a0, a1| { a1 => a0 } }
366
+ when /^ex/; lambda { |di, a0, a1| { a1 => a0 , a0 => a1 } }
367
+ when 'push_s'
368
+ lambda { |di, a0| {
369
+ sp => Expression[sp, :-, 4],
370
+ Indirection[sp, @size/8, di.address] => Expression[a0]
371
+ } }
372
+ when 'pop_s'
373
+ lambda { |di, a0| {
374
+ a0 => Indirection[sp, @size/8, di.address],
375
+ sp => Expression[sp, :+, 4]
376
+ } }
377
+ end
378
+ @backtrace_binding[op] ||= binding if binding
379
+ }
380
+ }
381
+
382
+ @backtrace_binding
383
+ end
384
+
385
+ def get_backtrace_binding(di)
386
+ a = di.instruction.args.map { |arg|
387
+ case arg
388
+ when GPR; arg.symbolic
389
+ when Memref; arg.symbolic(di.address)
390
+ else arg
391
+ end
392
+ }
393
+
394
+ if binding = backtrace_binding[di.opcode.basename]
395
+ binding[di, *a]
396
+ else
397
+ puts "unhandled instruction to backtrace: #{di}" if $VERBOSE
398
+ { :incomplete_binding => Expression[1] }
399
+ end
400
+ end
401
+
402
+ def get_xrefs_x(dasm, di)
403
+ return [] if not di.opcode.props[:setip]
404
+
405
+ arg = case di.opcode.name
406
+ when 'b', 'b_s', /^j/, /^bl/, /^br/, 'lp'
407
+ expr = di.instruction.args.last
408
+ expr.kind_of?(Memref) ? expr.base : expr
409
+ else di.instruction.args.last
410
+ end
411
+
412
+ [Expression[(arg.kind_of?(Reg) ? arg.symbolic : arg)]]
413
+ end
414
+
415
+ def backtrace_is_function_return(expr, di=nil)
416
+ Expression[expr].reduce == Expression[register_symbols[5]]
417
+ end
418
+
419
+ def delay_slot(di=nil)
420
+ return 0 if (not di) or (not di.opcode.props[:setip])
421
+ return 1 if di.opcode.props[:delay_slot]
422
+ (di.instruction.opname =~ /\.d/) ? 0 : 1
423
+ end
424
+ end
425
+ end