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
@@ -289,12 +289,15 @@ EOS
289
289
  m ? @cp.dump_definition(m) : @cp.to_s
290
290
  end
291
291
 
292
+ @@optim_hint = {}
293
+ def self.optim_hint; @@optim_hint; end
294
+
292
295
  attr_accessor :optim_hint
293
296
  def initialize(cp=nil)
294
297
  @cp = cp || DynLdr.host_cpu.new_cparser
295
298
  @cp.parse RUBY_H
296
299
  @iter_break = nil
297
- @optim_hint = {}
300
+ @optim_hint = @@optim_hint.dup
298
301
  end
299
302
 
300
303
  # convert a ruby AST to a new C function
@@ -449,8 +452,8 @@ EOS
449
452
  end
450
453
 
451
454
  # compile a case/when
452
- # create a real C switch() for Fixnums, and put the others === in the default case
453
- # XXX will get the wrong order for "case x; when 1; when Fixnum; when 3;" ...
455
+ # create a real C switch() for Integers, and put the others === in the default case
456
+ # XXX will get the wrong order for "case x; when 1; when Integer; when 3;" ...
454
457
  def compile_case(ast, scope, want_value)
455
458
  # this generates
456
459
  # var = stuff_to_test()
@@ -469,7 +472,7 @@ EOS
469
472
  # else {
470
473
  # default();
471
474
  # }
472
- #
475
+ #
473
476
  if want_value == true
474
477
  ret = get_new_tmp_var('case', want_value)
475
478
  want_value = ret
@@ -495,7 +498,7 @@ EOS
495
498
  raise Fail if cs[1][0] != :array
496
499
 
497
500
  # numeric case, add a case to body_int
498
- if cs[1][1..-1].all? { |cd| cd[0] == :lit and (cd[1].kind_of? Fixnum or cd[1].kind_of? Range) }
501
+ if cs[1][1..-1].all? { |cd| cd[0] == :lit and (cd[1].kind_of? Integer or cd[1].kind_of? Range) }
499
502
  cs[1][1..-1].each { |cd|
500
503
  if cd[1].kind_of? Range
501
504
  b = cd[1].begin
@@ -517,7 +520,7 @@ EOS
517
520
  else
518
521
  cnd = nil
519
522
  cs[1][1..-1].each { |cd|
520
- if (cd[0] == :lit and (cd[1].kind_of?(Fixnum) or cd[1].kind_of?(Symbol))) or
523
+ if (cd[0] == :lit and (cd[1].kind_of?(Integer) or cd[1].kind_of?(Symbol))) or
521
524
  [:nil, :true, :false].include?(cd[0])
522
525
  # true C equality
523
526
  cd = C::CExpression[var, :==, ast_to_c(cd, scope)]
@@ -538,7 +541,7 @@ EOS
538
541
  cb = C::Block.new(scope)
539
542
  v = ast_to_c(cs[2], cb, want_value)
540
543
  cb.statements << C::CExpression[ret, :'=', v] if want_value and v != ret
541
-
544
+
542
545
  fu = C::If.new(cnd, cb, nil)
543
546
 
544
547
  if body_other
@@ -656,7 +659,7 @@ EOS
656
659
  end
657
660
 
658
661
  # retrieve the current class, from self->klass
659
- # XXX will segfault with self.kind_of? Fixnum/true/false/nil/sym
662
+ # XXX will segfault with self.kind_of? Integer/true/false/nil/sym
660
663
  def rb_selfclass
661
664
  rb_cast_pvalue(rb_self, 1)
662
665
  end
@@ -807,7 +810,7 @@ EOS
807
810
  # if want_value is a C::Variable, the statements should try to populate this var instead of some random tmp var
808
811
  # eg to simplify :if encoding unless we have 'foo = if 42;..'
809
812
  def ast_to_c(ast, scope, want_value = true)
810
- ret =
813
+ ret =
811
814
  case ast.to_a[0]
812
815
  when :block
813
816
  if ast[1]
@@ -1082,13 +1085,13 @@ EOS
1082
1085
  case ast[1][0]
1083
1086
  when :ivar
1084
1087
  fcall('rb_ivar_defined', rb_self, rb_intern(ast[1][1]))
1085
- else
1088
+ else
1086
1089
  raise Fail, "unsupported #{ast.inspect}"
1087
1090
  end
1088
1091
  when :masgn
1089
1092
  # parallel assignment: put everything in an Array, then pop everything back?
1090
1093
  rb_masgn(ast, scope, want_value)
1091
-
1094
+
1092
1095
  when :evstr
1093
1096
  fcall('rb_obj_as_string', ast_to_c(ast[1], scope))
1094
1097
  when :dot2, :dot3
@@ -1135,15 +1138,15 @@ EOS
1135
1138
  args = ast[3][1..-1] if ast[3] and ast[3][0] == :array
1136
1139
  arg0 = args[0] if args and args[0]
1137
1140
 
1138
- if arg0 and arg0[0] == :lit and arg0[1].kind_of? Fixnum
1141
+ if arg0 and arg0[0] == :lit and arg0[1].kind_of?(Integer) and %w[== > < >= <= + -].include?(op)
1142
+ # TODO or @optim_hint[ast[1]] == 'fixnum'
1139
1143
  # optimize 'x==42', 'x+42', 'x-42'
1140
1144
  o2 = arg0[1]
1141
- return if not %w[== > < >= <= + -].include? op
1142
1145
  if o2 < 0 and ['+', '-'].include? op
1143
1146
  # need o2 >= 0 for overflow detection
1144
1147
  op = {'+' => '-', '-' => '+'}[op]
1145
1148
  o2 = -o2
1146
- return if not o2.kind_of? Fixnum # -0x40000000
1149
+ return if not o2.kind_of? Integer # -0x40000000
1147
1150
  end
1148
1151
 
1149
1152
  int_v = o2.object_id
@@ -1156,11 +1159,11 @@ EOS
1156
1159
 
1157
1160
  case op
1158
1161
  when '=='
1159
- # XXX assume == only return true for full equality: if not Fixnum, then always false
1162
+ # XXX assume == only return true for full equality: if not Integer, then always false
1160
1163
  # which breaks 1.0 == 1 and maybe others, but its ok
1161
1164
  scope.statements << C::If.new(ce[recv, :'==', [int_v]], ce[tmp, :'=', rb_true], ce[tmp, :'=', rb_false])
1162
1165
  when '>', '<', '>=', '<='
1163
- # do the actual comparison on signed >>1 if both Fixnum
1166
+ # do the actual comparison on signed >>1 if both Integer
1164
1167
  t = C::If.new(
1165
1168
  ce[[[[recv], int], :>>, [1]], op.to_sym, [[[int_v], int], :>>, [1]]],
1166
1169
  ce[tmp, :'=', rb_true],
@@ -1191,7 +1194,7 @@ EOS
1191
1194
  end
1192
1195
  end
1193
1196
  tmp
1194
-
1197
+
1195
1198
  # Symbol#==
1196
1199
  elsif arg0 and arg0[0] == :lit and arg0[1].kind_of? Symbol and op == '=='
1197
1200
  s_v = ast_to_c(arg0, scope)
@@ -1241,13 +1244,13 @@ EOS
1241
1244
 
1242
1245
  ar = C::Block.new(scope)
1243
1246
  ar.statements << ce[idx, :'=', [[[arg], int], :>>, [1]]]
1244
- ar.statements << C::If.new(ce[idx, :<, [0]], ce[idx, :'=', [idx, :+, rb_ary_len(recv)]], nil)
1247
+ ar.statements << C::If.new(ce[idx, :<, [0]], ce[idx, :'=', [idx, :+, rb_ary_len(recv)]], nil)
1245
1248
  ar.statements << C::If.new(ce[[idx, :<, [0]], :'||', [idx, :>=, [[rb_ary_len(recv)], int]]],
1246
1249
  ce[tmp, :'=', rb_nil],
1247
1250
  ce[tmp, :'=', rb_ary_ptr(recv, idx)])
1248
1251
  st = C::Block.new(scope)
1249
1252
  st.statements << ce[idx, :'=', [[[arg], int], :>>, [1]]]
1250
- st.statements << C::If.new(ce[idx, :<, [0]], ce[idx, :'=', [idx, :+, rb_str_len(recv)]], nil)
1253
+ st.statements << C::If.new(ce[idx, :<, [0]], ce[idx, :'=', [idx, :+, rb_str_len(recv)]], nil)
1251
1254
  st.statements << C::If.new(ce[[idx, :<, [0]], :'||', [idx, :>=, [[rb_str_len(recv)], int]]],
1252
1255
  ce[tmp, :'=', rb_nil],
1253
1256
  ce[tmp, :'=', [[[[rb_str_ptr(recv, idx), :&, [0xff]], :<<, [1]], :|, [1]], value]])
@@ -1301,8 +1304,7 @@ EOS
1301
1304
  when 'Symbol'
1302
1305
  tmp = get_new_tmp_var('kindof', want_value)
1303
1306
  ce[[ast_to_c(ast[1], scope, tmp), :'&', [0xf]], :'==', [0xe]]
1304
- #when 'Numeric', 'Integer'
1305
- when 'Fixnum'
1307
+ when 'Integer'
1306
1308
  tmp = get_new_tmp_var('kindof', want_value)
1307
1309
  ce[ast_to_c(ast[1], scope, tmp), :'&', [0x1]]
1308
1310
  when 'Array'
@@ -1500,7 +1502,7 @@ puts "shortcut may be incorrect for #{ast.inspect}" if arg0[0] == :const
1500
1502
  elsif b_recv[0] == :call and not b_recv[3] and b_recv[2] == 'times'
1501
1503
  limit = get_new_tmp_var('limit')
1502
1504
  recv = ast_to_c(b_recv[1], scope, limit)
1503
- scope.statements << C::If.new(C::CExpression[:'!', [recv, :&, 1]], rb_raise('only Fixnum#times handled'), nil)
1505
+ scope.statements << C::If.new(C::CExpression[:'!', [recv, :&, 1]], rb_raise('only Integer#times handled'), nil)
1504
1506
  if want_value
1505
1507
  scope.statements << C::CExpression[@iter_break, :'=', recv]
1506
1508
  end
@@ -1550,7 +1552,7 @@ puts "shortcut may be incorrect for #{ast.inspect}" if arg0[0] == :const
1550
1552
  body.statements << C::CExpression[dvar(b_args[1]), :'=', [rb_ary_ptr(ary), :'[]', [cntr]]]
1551
1553
  end
1552
1554
  # same as #each up to this point (except default retval), now add a 'if (body_value) break ary[cntr];'
1553
- # XXX 'find { next true }'
1555
+ # XXX 'find { next true }'
1554
1556
 
1555
1557
  found = ast_to_c(b_body, body)
1556
1558
  t = C::Block.new(body)
@@ -1577,7 +1579,7 @@ puts "shortcut may be incorrect for #{ast.inspect}" if arg0[0] == :const
1577
1579
  body.statements << C::CExpression[dvar(b_args[1]), :'=', [rb_ary_ptr(ary), :'[]', [cntr]]]
1578
1580
  end
1579
1581
  # same as #each up to this point (except default retval), now add a '@iter_break << body_value'
1580
- # XXX 'next' unhandled
1582
+ # XXX 'next' unhandled
1581
1583
 
1582
1584
  val = ast_to_c(b_body, body)
1583
1585
  body.statements << fcall('rb_ary_push', @iter_break, val)
@@ -1639,7 +1641,7 @@ static void do_init_once(void) {
1639
1641
  // rb_define_method(const_Lol, "method", method, 2);
1640
1642
  }
1641
1643
 
1642
- int Init_compiledruby(void) __attribute__((export)) {
1644
+ int Init_compiledruby(void) __attribute__((export)) {
1643
1645
  // use a separate func to avoid having to append statements before the 'return'
1644
1646
  do_init_once();
1645
1647
  return 0;
@@ -1661,7 +1663,7 @@ EOS
1661
1663
  @compiled_func_cache[[klass, method.to_s, singleton]] = @cur_cfunc
1662
1664
 
1663
1665
  cls = rb_const(nil, klass)
1664
-
1666
+
1665
1667
  init.statements << fcall("rb_define#{'_singleton' if singleton}_method", cls, method.to_s, @cur_cfunc, method_arity)
1666
1668
 
1667
1669
  mname
@@ -1696,7 +1698,7 @@ EOS
1696
1698
  @cp.toplevel.symbol[n] || declare_newtopvar(n, fcall('rb_intern', sym.to_s), C::BaseType.new(:int, :unsigned))
1697
1699
  end
1698
1700
 
1699
- # rb_const 'FOO', Bar::Baz ==>
1701
+ # rb_const 'FOO', Bar::Baz ==>
1700
1702
  # const_Bar = rb_const_get(rb_cObject, rb_intern("Bar"));
1701
1703
  # const_Bar_Baz = rb_const_get(const_Bar, rb_intern("Baz"));
1702
1704
  # const_Bar_Baz_FOO = rb_const_get(const_Bar_Baz, rb_intern("FOO"));
@@ -1819,6 +1821,12 @@ end
1819
1821
 
1820
1822
  if __FILE__ == $0 or ARGV.delete('ignore_argv0')
1821
1823
 
1824
+ while i = ARGV.index('-e')
1825
+ # setup optim_hint etc
1826
+ ARGV.delete_at(i)
1827
+ eval ARGV.delete_at(i)
1828
+ end
1829
+
1822
1830
  demo = case ARGV.first
1823
1831
  when nil; :test_jit
1824
1832
  when 'asm'; :inlineasm
data/samples/elfencode.rb CHANGED
@@ -14,12 +14,27 @@ __END__
14
14
  // .nointerp // to disable the dynamic section, eg for stuff with int80 only
15
15
  .text
16
16
  .entrypoint
17
+ #if defined __i386__
17
18
  push bla
18
19
  push fmt
19
20
  call printf
21
+
20
22
  push 0
21
23
  call exit
22
24
 
25
+ #elif defined __amd64__
26
+ lea rsi, [rip+bla-$_]
27
+ lea rdi, [rip+fmt-$_]
28
+ xor rax, rax
29
+ call printf
30
+
31
+ mov rdi, 0
32
+ call exit
33
+
34
+ #else
35
+ unsupported architecture!
36
+ #endif
37
+
23
38
  .data
24
39
  bla db "world", 0
25
40
  fmt db "Hello, %s !\n", 0
@@ -0,0 +1,251 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # Sample to show the EmuDebugger working on X86 16bit realmode code (eg hard disk MBR)
4
+
5
+ require 'metasm'
6
+ include Metasm
7
+
8
+ # use global vars for read_sector()
9
+ $dasm = $dbg = nil
10
+
11
+ $rawname = ARGV.shift || 'mbr.bin'
12
+ cpu = Ia32.new(16)
13
+ # add register tracking for the segment registers
14
+ cpu.dbg_register_list << :cs << :ds << :es << :fs << :gs << :ss
15
+ $dasm = dasm = Shellcode.new(Ia32.new(16), 0).disassembler
16
+ dasm.backtrace_maxblocks_data = -1
17
+
18
+ # initial memory
19
+ dasm.add_section(EncodedData.new("\x00"*0x40000), 0)
20
+
21
+ # read one sector from the drive to memory, invalidate already disassembled instruction from the address range
22
+ def read_sector(addr, fileoff, len)
23
+ e, o = $dasm.get_section_at(addr)
24
+ $dasm.decoded.keys.grep(addr..(addr+len)).each { |k| $dasm.decoded.delete k }
25
+ raw_chunk = File.open($rawname, 'rb') { |fd| fd.pos = fileoff ; fd.read len } || ''
26
+ raw_chunk << 0.chr until raw_chunk.length >= len
27
+ e[e.ptr, len] = raw_chunk
28
+ $dbg.invalidate if $dbg
29
+ end
30
+
31
+ # load as BIOS MBR code
32
+ read_sector(0x7c00, 0, 0x200)
33
+
34
+ # buffer used for int 16h read keyboard
35
+ $stdin_buf = "moo\r\n"
36
+
37
+ $dbg = dbg = Metasm::EmuDebugger.new(dasm)
38
+ dbg.set_reg_value(:eip, 0x7c00)
39
+ dbg.set_reg_value(:esp, 0x7c00)
40
+
41
+ # reset trace file
42
+ File.open('emudbg.trace', 'w') {}
43
+ def trace(thing)
44
+ File.open('emudbg.trace', 'a') { |fd| fd.puts thing }
45
+ end
46
+ def puts_trace(str)
47
+ trace str
48
+ puts str
49
+ end
50
+
51
+ # custom emulation of various instrs for realmode-specific behavior
52
+ # this is a very bad realmode emulator
53
+ # eg segment selectors are mostly ignored except for a few specific cases described here
54
+ # seems to work for the few crackme i worked on !
55
+ dbg.callback_emulate_di = lambda { |di|
56
+ puts di if $VERBOSE
57
+ trace di
58
+ case di.opcode.name
59
+ when 'jmp'
60
+ tg = di.instruction.args.first
61
+ if di.address == dbg.resolve(tg)
62
+ # break from simulation on ebfe
63
+ puts "EB FE !"
64
+ dbg.bpx(di.address)
65
+ break true
66
+ elsif tg.kind_of?(Ia32::Farptr)
67
+ # handle far jumps
68
+ dbg.pc = dbg.resolve(Expression[[tg.seg, :<<, 4], :+, tg.addr])
69
+ break true
70
+ end
71
+ when 'retf.i16'
72
+ # XXX really ss:esp, but we'd need to fix push/pop etc too, so keep to 0:esp for now
73
+ w1 = dbg.memory_read_int(:esp, 2)
74
+ dbg.set_reg_value(:esp, dbg.resolve(Expression[:esp, :+, 2]))
75
+ w2 = dbg.memory_read_int(:esp, 2)
76
+ dbg.set_reg_value(:esp, dbg.resolve(Expression[:esp, :+, 2]))
77
+ dbg.set_reg_value(:cs, w2)
78
+ dbg.pc = dbg.resolve(Expression[[w2, :<<, 4], :+, w1])
79
+ break true
80
+ when 'ret'
81
+ w1 = dbg.memory_read_int(:esp, 2)
82
+ dbg.set_reg_value(:esp, dbg.resolve(Expression[:esp, :+, 2]))
83
+ dbg.pc = dbg.resolve(Expression[[:cs, :<<, 4], :+, w1])
84
+ break true
85
+ when 'lodsb'
86
+ # read from ds:si instead of 0:esi
87
+ # XXX rep
88
+ dbg.set_reg_value(:eax, dbg.resolve(Expression[[:eax, :&, 0xffffff00], :|, Indirection[[[:ds, :<<, 4], :+, [:esi, :&, 0xffff]], 1]]))
89
+ dbg.set_reg_value(:esi, dbg.resolve(Expression[[:esi, :&, 0xffff0000], :|, [[:esi, :&, 0xffff], :+, 1]]))
90
+ dbg.pc += di.bin_length
91
+ true
92
+ when 'lodsd'
93
+ # read from ds:si instead of 0:esi
94
+ # XXX rep
95
+ dbg.set_reg_value(:eax, dbg.resolve(Expression[Indirection[[[:ds, :<<, 4], :+, [:esi, :&, 0xffff]], 4]]))
96
+ dbg.set_reg_value(:esi, dbg.resolve(Expression[[:esi, :&, 0xffff0000], :|, [[:esi, :&, 0xffff], :+, 4]]))
97
+ dbg.pc += di.bin_length
98
+ true
99
+ when 'stosd'
100
+ # write to es:di instead of 0:edi
101
+ # XXX rep
102
+ dbg.memory_write_int(Expression[[:es, :<<, 4], :+, [:edi, :&, 0xffff]], :eax, 4)
103
+ dbg.set_reg_value(:edi, dbg.resolve(Expression[[:edi, :&, 0xffff0000], :|, [[:edi, :&, 0xffff], :+, 4]]))
104
+ dbg.pc += di.bin_length
105
+ true
106
+ when /movs([bwdq])/
107
+ sz = { 'b' => 1, 'w' => 2, 'd' => 4, 'q' => 8 }[$1]
108
+ # XXX repz
109
+ if di.instruction.prefix[:rep]
110
+ count = dbg[:ecx] & 0xffff
111
+ else
112
+ count = 1
113
+ end
114
+ count.times {
115
+ val = dbg.resolve(Expression[Indirection[[[:ds, :<<, 4], :+, [:esi, :&, 0xffff]], sz]])
116
+ dbg.memory_write_int(Expression[[:es, :<<, 4], :+, [:edi, :&, 0xffff]], val, sz)
117
+ dbg[:esi] = (dbg[:esi] + sz) & 0xffff
118
+ dbg[:edi] = (dbg[:edi] + sz) & 0xffff
119
+ dbg[:ecx] -= 1 if di.instruction.prefix[:rep]
120
+ }
121
+ dbg.pc += di.bin_length
122
+ true
123
+ when 'les'
124
+ dst = di.instruction.args[0].symbolic(di)
125
+ dst = dst.externals.first if dst.kind_of?(Expression)
126
+ src = di.instruction.args[1].symbolic(di)
127
+ dbg.set_reg_value(dst, dbg.resolve(Indirection[[[:es, :<<, 4], :+, src.pointer], 2]))
128
+ dbg.pc += di.bin_length
129
+ true
130
+ when 'div'
131
+ op = di.instruction.args[0].symbolic(di)
132
+ sz = op.kind_of?(Expression) ? { 0xff => 1, 0xffff => 2 }[op.rexpr] : 4
133
+ dv = dbg.resolve(op)
134
+ case sz
135
+ when 1
136
+ dv2 = dbg[:eax] & 0xffff
137
+ dbg[:eax] = ((dv2 / dv) & 0xff) | (((dv2 % dv) & 0xff) << 8)
138
+ when 2
139
+ dv2 = ((dbg[:edx] & 0xffff) << 16) | (dbg[:eax] & 0xffff)
140
+ dbg[:eax] = (dv2 / dv) & 0xffff
141
+ dbg[:edx] = (dv2 % dv) & 0xffff
142
+ when 4
143
+ dv2 = (dbg[:edx] << 32) | dbg[:eax]
144
+ dbg[:eax] = (dv2 / dv)
145
+ dbg[:edx] = (dv2 % dv)
146
+ end
147
+ dbg.pc += di.bin_length
148
+ true
149
+ when 'loop'
150
+ # movzx ecx, cx
151
+ dbg.set_reg_value(:ecx, dbg.resolve(Expression[:ecx, :&, 0xffff]))
152
+ false
153
+ when 'int'
154
+ intnr = di.instruction.args.first.reduce
155
+ eax = dbg[:eax]
156
+ ah = (eax >> 8) & 0xff
157
+ al = eax & 0xff
158
+ case intnr
159
+ when 0x10
160
+ # print screen interrupt
161
+ $screenbuf ||= []
162
+ $screenx ||= 0
163
+ $screeny ||= 0
164
+ case ah
165
+ when 0x00
166
+ $screenbuf = []
167
+ $screenx = 0
168
+ $screeny = 0
169
+ when 0x02
170
+ dh = (dbg[:edx] >> 8) & 0xff
171
+ dl = dbg[:edx] & 0xff
172
+ puts_trace "movc(#{dh}, #{dl})"
173
+ puts $screenbuf
174
+ $screenx = dl
175
+ $screeny = dh
176
+ when 0x0e
177
+ puts_trace "putc(#{[al].pack('C*').inspect})"
178
+ $screenbuf << '' until $screenbuf.length > $screeny
179
+ $screenbuf[$screeny] << '.' until $screenbuf[$screeny].length > $screenx
180
+ $screenbuf[$screeny][$screenx, 1] = [al].pack('C*')
181
+ $screenx += 1
182
+ else
183
+ puts_trace "unk int #{'%02xh' % intnr} #{'%02x' % ah}"
184
+ end
185
+ when 0x13
186
+ # read disk interrupt
187
+ drive_nr = dbg[:edx] & 0xff
188
+ case ah
189
+ when 0x00
190
+ dbg.unset_flag(:c)
191
+ puts_trace "reset_disk_drive #{'%x' % drive_nr}"
192
+ when 0x02
193
+ sect_cnt = al
194
+ sect_c = ((dbg[:ecx] >> 8) & 0xff) | ((dbg[:ecx] << 2) & 0x300)
195
+ sect_h = (dbg[:edx] >> 8) & 0xff
196
+ sect_s = (dbg[:ecx] & 0x3f)
197
+ sect_lba = (sect_c * 16 + sect_h) * 63 + sect_s - 1
198
+ sect_drv = dbg[:edx] & 0xff
199
+ dst_addr = dbg[:es] * 16 + dbg[:ebx]
200
+ puts_trace "read #{sect_cnt} sect at #{'%03X:%02X:%02X' % [sect_c, sect_h, sect_s]} (#{'0x%X' % sect_lba}) to #{'0x%X' % dst_addr} drv #{'%x' % drive_nr}"
201
+ read_sector(dst_addr, sect_lba * 512, sect_cnt * 512)
202
+ when 0x08
203
+ dbg.unset_flag(:c)
204
+ dbg[:eax] = 0 # ah = return code
205
+ dbg[:ebx] = 0 # bl = drive type
206
+ dbg[:ecx] = 0x1010 # ch = cyl_max, cl >> 6 = cyl_max_hi, cl & 3f = sector_per_track
207
+ dbg[:edx] = 0x1001 # dh = head_max, dl = nr_of_drives
208
+ puts_trace "read_drive_parameters #{'%x' % drive_nr}"
209
+ when 0x41
210
+ dbg.unset_flag(:c)
211
+ dbg[:ebx] = 0xaa55
212
+ dbg[:ecx] = 1 # 1: device access through packet structure (cf 42), 2: lock & eject, 4: enhanced drive support
213
+ puts_trace "drive_check_extension_present #{'%x' % drive_nr}"
214
+ when 0x42
215
+ sect_cnt = dbg.memory_read_int(Expression[[:ds, :<<, 4], :+, [[:esi, :+, 2], :&, 0xffff]], 2)
216
+ dst_addr = dbg.memory_read_int(Expression[[:ds, :<<, 4], :+, [[:esi, :+, 4], :&, 0xffff]], 2)
217
+ dst_seg = dbg.memory_read_int(Expression[[:ds, :<<, 4], :+, [[:esi, :+, 6], :&, 0xffff]], 2)
218
+ sect_lba = dbg.memory_read_int(Expression[[:ds, :<<, 4], :+, [[:esi, :+, 8], :&, 0xffff]], 8)
219
+ dst_addr += dst_seg << 4
220
+ puts_trace "read extended #{sect_cnt} sect at #{'0x%X' % sect_lba} to #{'0x%X' % dst_addr} drv #{'%x' % drive_nr}"
221
+ read_sector(dst_addr, sect_lba * 512, sect_cnt * 512)
222
+ else
223
+ puts_trace "unk int #{'%02xh' % intnr} #{'%02x' % ah}"
224
+ end
225
+ when 0x16
226
+ # read keyboard interrupt
227
+ case ah
228
+ when 0x00
229
+ al = $stdin_buf.unpack('C').first || 0
230
+ $stdin_buf[0, 1] = ''
231
+ dbg[:eax] = al
232
+ puts_trace "getc => #{[al].pack('C*').inspect}"
233
+ else
234
+ puts_trace "unk int #{'%02xh' % intnr} #{'%02x' % ah}"
235
+ end
236
+ else
237
+ puts_trace "unk int #{'%02xh' % intnr} #{'%02x' % ah}"
238
+ end
239
+ dbg.pc += di.bin_length
240
+ true
241
+ end
242
+ }
243
+
244
+ # Start the GUI
245
+ Gui::DbgWindow.new.display(dbg)
246
+ # some pretty settings for the initial view
247
+ dbg.gui.run_command('wd 16')
248
+ dbg.gui.run_command('wp 6')
249
+ dbg.gui.parent.code.toggle_view(:graph)
250
+
251
+ Gui.main