metasm 1.0.0 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +3 -0
- data/.gitignore +3 -0
- data/.hgtags +3 -0
- data/Gemfile +3 -0
- data/INSTALL +61 -0
- data/LICENCE +458 -0
- data/README +29 -21
- data/Rakefile +10 -0
- data/TODO +10 -12
- data/doc/code_organisation.txt +3 -1
- data/doc/core/DynLdr.txt +247 -0
- data/doc/core/ExeFormat.txt +43 -0
- data/doc/core/Expression.txt +220 -0
- data/doc/core/GNUExports.txt +27 -0
- data/doc/core/Ia32.txt +236 -0
- data/doc/core/SerialStruct.txt +108 -0
- data/doc/core/VirtualString.txt +145 -0
- data/doc/core/WindowsExports.txt +61 -0
- data/doc/core/index.txt +1 -0
- data/doc/style.css +6 -3
- data/doc/usage/debugger.txt +327 -0
- data/doc/usage/index.txt +1 -0
- data/doc/use_cases.txt +2 -2
- data/metasm.gemspec +23 -0
- data/{lib/metasm.rb → metasm.rb} +15 -3
- data/{lib/metasm → metasm}/compile_c.rb +15 -9
- data/metasm/cpu/arc.rb +8 -0
- data/metasm/cpu/arc/decode.rb +404 -0
- data/metasm/cpu/arc/main.rb +191 -0
- data/metasm/cpu/arc/opcodes.rb +588 -0
- data/metasm/cpu/arm.rb +14 -0
- data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
- data/{lib/metasm → metasm/cpu}/arm/decode.rb +15 -18
- data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
- data/{lib/metasm → metasm/cpu}/arm/main.rb +3 -6
- data/metasm/cpu/arm/opcodes.rb +324 -0
- data/{lib/metasm → metasm/cpu}/arm/parse.rb +25 -13
- data/{lib/metasm → metasm/cpu}/arm/render.rb +2 -2
- data/metasm/cpu/arm64.rb +15 -0
- data/metasm/cpu/arm64/debug.rb +38 -0
- data/metasm/cpu/arm64/decode.rb +285 -0
- data/metasm/cpu/arm64/encode.rb +41 -0
- data/metasm/cpu/arm64/main.rb +105 -0
- data/metasm/cpu/arm64/opcodes.rb +232 -0
- data/metasm/cpu/arm64/parse.rb +20 -0
- data/metasm/cpu/arm64/render.rb +95 -0
- data/{lib/metasm/mips/compile_c.rb → metasm/cpu/bpf.rb} +4 -2
- data/metasm/cpu/bpf/decode.rb +110 -0
- data/metasm/cpu/bpf/main.rb +60 -0
- data/metasm/cpu/bpf/opcodes.rb +81 -0
- data/metasm/cpu/bpf/render.rb +30 -0
- data/{lib/metasm/ppc.rb → metasm/cpu/cy16.rb} +2 -4
- data/metasm/cpu/cy16/decode.rb +247 -0
- data/metasm/cpu/cy16/main.rb +63 -0
- data/metasm/cpu/cy16/opcodes.rb +78 -0
- data/metasm/cpu/cy16/render.rb +30 -0
- data/metasm/cpu/dalvik.rb +11 -0
- data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +34 -34
- data/{lib/metasm → metasm/cpu}/dalvik/main.rb +71 -4
- data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +21 -12
- data/{lib/metasm/mips.rb → metasm/cpu/ebpf.rb} +3 -4
- data/metasm/cpu/ebpf/debug.rb +61 -0
- data/metasm/cpu/ebpf/decode.rb +142 -0
- data/metasm/cpu/ebpf/main.rb +58 -0
- data/metasm/cpu/ebpf/opcodes.rb +97 -0
- data/metasm/cpu/ebpf/render.rb +36 -0
- data/metasm/cpu/ia32.rb +17 -0
- data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +23 -9
- data/{lib/metasm → metasm/cpu}/ia32/debug.rb +44 -6
- data/{lib/metasm → metasm/cpu}/ia32/decode.rb +342 -128
- data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +75 -53
- data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
- data/{lib/metasm → metasm/cpu}/ia32/main.rb +66 -8
- data/metasm/cpu/ia32/opcodes.rb +1424 -0
- data/{lib/metasm → metasm/cpu}/ia32/parse.rb +55 -17
- data/{lib/metasm → metasm/cpu}/ia32/render.rb +32 -5
- data/metasm/cpu/mcs51.rb +8 -0
- data/metasm/cpu/mcs51/decode.rb +99 -0
- data/metasm/cpu/mcs51/main.rb +87 -0
- data/metasm/cpu/mcs51/opcodes.rb +120 -0
- data/metasm/cpu/mips.rb +14 -0
- data/metasm/cpu/mips/debug.rb +42 -0
- data/{lib/metasm → metasm/cpu}/mips/decode.rb +59 -38
- data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
- data/{lib/metasm → metasm/cpu}/mips/main.rb +13 -6
- data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +87 -18
- data/{lib/metasm → metasm/cpu}/mips/parse.rb +1 -1
- data/{lib/metasm → metasm/cpu}/mips/render.rb +1 -1
- data/{lib/metasm/dalvik.rb → metasm/cpu/msp430.rb} +1 -1
- data/metasm/cpu/msp430/decode.rb +243 -0
- data/metasm/cpu/msp430/main.rb +62 -0
- data/metasm/cpu/msp430/opcodes.rb +101 -0
- data/metasm/cpu/openrisc.rb +11 -0
- data/metasm/cpu/openrisc/debug.rb +106 -0
- data/metasm/cpu/openrisc/decode.rb +182 -0
- data/metasm/cpu/openrisc/decompile.rb +350 -0
- data/metasm/cpu/openrisc/main.rb +70 -0
- data/metasm/cpu/openrisc/opcodes.rb +109 -0
- data/metasm/cpu/openrisc/render.rb +37 -0
- data/{lib/metasm → metasm/cpu}/pic16c/decode.rb +6 -7
- data/{lib/metasm → metasm/cpu}/pic16c/main.rb +0 -0
- data/{lib/metasm → metasm/cpu}/pic16c/opcodes.rb +1 -1
- data/metasm/cpu/ppc.rb +11 -0
- data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -37
- data/{lib/metasm → metasm/cpu}/ppc/decompile.rb +3 -3
- data/{lib/metasm → metasm/cpu}/ppc/encode.rb +2 -2
- data/{lib/metasm → metasm/cpu}/ppc/main.rb +23 -18
- data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -6
- data/metasm/cpu/ppc/parse.rb +55 -0
- data/metasm/cpu/python.rb +8 -0
- data/metasm/cpu/python/decode.rb +116 -0
- data/metasm/cpu/python/main.rb +36 -0
- data/metasm/cpu/python/opcodes.rb +180 -0
- data/{lib/metasm → metasm/cpu}/sh4.rb +1 -1
- data/{lib/metasm → metasm/cpu}/sh4/decode.rb +50 -23
- data/{lib/metasm → metasm/cpu}/sh4/main.rb +38 -27
- data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
- data/metasm/cpu/st20.rb +9 -0
- data/metasm/cpu/st20/decode.rb +173 -0
- data/metasm/cpu/st20/decompile.rb +283 -0
- data/metasm/cpu/st20/main.rb +37 -0
- data/metasm/cpu/st20/opcodes.rb +140 -0
- data/{lib/metasm/arm.rb → metasm/cpu/webasm.rb} +4 -5
- data/metasm/cpu/webasm/debug.rb +31 -0
- data/metasm/cpu/webasm/decode.rb +321 -0
- data/metasm/cpu/webasm/decompile.rb +386 -0
- data/metasm/cpu/webasm/encode.rb +104 -0
- data/metasm/cpu/webasm/main.rb +81 -0
- data/metasm/cpu/webasm/opcodes.rb +214 -0
- data/metasm/cpu/x86_64.rb +15 -0
- data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +40 -25
- data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
- data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +58 -15
- data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +59 -28
- data/{lib/metasm → metasm/cpu}/x86_64/main.rb +18 -6
- data/metasm/cpu/x86_64/opcodes.rb +138 -0
- data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +12 -4
- data/metasm/cpu/x86_64/render.rb +35 -0
- data/metasm/cpu/z80.rb +9 -0
- data/metasm/cpu/z80/decode.rb +286 -0
- data/metasm/cpu/z80/main.rb +67 -0
- data/metasm/cpu/z80/opcodes.rb +224 -0
- data/metasm/cpu/z80/render.rb +48 -0
- data/{lib/metasm/os/main.rb → metasm/debug.rb} +201 -407
- data/{lib/metasm → metasm}/decode.rb +104 -24
- data/{lib/metasm → metasm}/decompile.rb +804 -478
- data/{lib/metasm → metasm}/disassemble.rb +385 -170
- data/{lib/metasm → metasm}/disassemble_api.rb +684 -105
- data/{lib/metasm → metasm}/dynldr.rb +231 -138
- data/{lib/metasm → metasm}/encode.rb +20 -5
- data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
- data/{lib/metasm → metasm}/exe_format/autoexe.rb +3 -0
- data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
- data/{lib/metasm → metasm}/exe_format/coff.rb +35 -7
- data/{lib/metasm → metasm}/exe_format/coff_decode.rb +70 -23
- data/{lib/metasm → metasm}/exe_format/coff_encode.rb +24 -22
- data/{lib/metasm → metasm}/exe_format/dex.rb +26 -8
- data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/elf.rb +108 -58
- data/{lib/metasm → metasm}/exe_format/elf_decode.rb +202 -36
- data/{lib/metasm → metasm}/exe_format/elf_encode.rb +126 -32
- data/metasm/exe_format/gb.rb +65 -0
- data/metasm/exe_format/javaclass.rb +424 -0
- data/{lib/metasm → metasm}/exe_format/macho.rb +218 -16
- data/{lib/metasm → metasm}/exe_format/main.rb +28 -3
- data/{lib/metasm → metasm}/exe_format/mz.rb +2 -0
- data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
- data/{lib/metasm → metasm}/exe_format/pe.rb +96 -11
- data/metasm/exe_format/pyc.rb +167 -0
- data/{lib/metasm → metasm}/exe_format/serialstruct.rb +67 -14
- data/{lib/metasm → metasm}/exe_format/shellcode.rb +7 -3
- data/metasm/exe_format/shellcode_rwx.rb +114 -0
- data/metasm/exe_format/swf.rb +205 -0
- data/metasm/exe_format/wasm.rb +402 -0
- data/{lib/metasm → metasm}/exe_format/xcoff.rb +7 -7
- data/metasm/exe_format/zip.rb +335 -0
- data/metasm/gui.rb +13 -0
- data/{lib/metasm → metasm}/gui/cstruct.rb +35 -41
- data/{lib/metasm → metasm}/gui/dasm_coverage.rb +11 -11
- data/{lib/metasm → metasm}/gui/dasm_decomp.rb +177 -114
- data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
- data/metasm/gui/dasm_graph.rb +1754 -0
- data/{lib/metasm → metasm}/gui/dasm_hex.rb +16 -12
- data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
- data/{lib/metasm → metasm}/gui/dasm_main.rb +360 -77
- data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
- data/{lib/metasm → metasm}/gui/debug.rb +109 -34
- data/{lib/metasm → metasm}/gui/gtk.rb +174 -44
- data/{lib/metasm → metasm}/gui/qt.rb +14 -4
- data/{lib/metasm → metasm}/gui/win32.rb +180 -43
- data/{lib/metasm → metasm}/gui/x11.rb +59 -59
- data/{lib/metasm → metasm}/main.rb +421 -286
- data/metasm/os/emulator.rb +175 -0
- data/{lib/metasm/os/remote.rb → metasm/os/gdbremote.rb} +146 -54
- data/{lib/metasm → metasm}/os/gnu_exports.rb +1 -1
- data/{lib/metasm → metasm}/os/linux.rb +628 -151
- data/metasm/os/main.rb +335 -0
- data/{lib/metasm → metasm}/os/windows.rb +151 -58
- data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
- data/{lib/metasm → metasm}/parse.rb +49 -36
- data/{lib/metasm → metasm}/parse_c.rb +405 -246
- data/{lib/metasm → metasm}/preprocessor.rb +71 -41
- data/{lib/metasm → metasm}/render.rb +14 -38
- data/misc/hexdump.rb +4 -3
- data/misc/lint.rb +58 -0
- data/misc/objdiff.rb +4 -1
- data/misc/objscan.rb +1 -1
- data/misc/openrisc-parser.rb +79 -0
- data/misc/txt2html.rb +9 -7
- data/samples/bindiff.rb +3 -4
- data/samples/dasm-plugins/bindiff.rb +15 -0
- data/samples/dasm-plugins/bookmark.rb +133 -0
- data/samples/dasm-plugins/c_constants.rb +57 -0
- data/samples/dasm-plugins/colortheme_solarized.rb +125 -0
- data/samples/dasm-plugins/cppobj_funcall.rb +60 -0
- data/samples/dasm-plugins/dasm_all.rb +70 -0
- data/samples/dasm-plugins/demangle_cpp.rb +31 -0
- data/samples/dasm-plugins/deobfuscate.rb +251 -0
- data/samples/dasm-plugins/dump_text.rb +35 -0
- data/samples/dasm-plugins/export_graph_svg.rb +86 -0
- data/samples/dasm-plugins/findgadget.rb +75 -0
- data/samples/dasm-plugins/hl_opcode.rb +32 -0
- data/samples/dasm-plugins/hotfix_gtk_dbg.rb +19 -0
- data/samples/dasm-plugins/imm2off.rb +34 -0
- data/samples/dasm-plugins/match_libsigs.rb +93 -0
- data/samples/dasm-plugins/patch_file.rb +95 -0
- data/samples/dasm-plugins/scanfuncstart.rb +36 -0
- data/samples/dasm-plugins/scanxrefs.rb +29 -0
- data/samples/dasm-plugins/selfmodify.rb +197 -0
- data/samples/dasm-plugins/stringsxrefs.rb +28 -0
- data/samples/dasmnavig.rb +1 -1
- data/samples/dbg-apihook.rb +24 -9
- data/samples/dbg-plugins/heapscan.rb +283 -0
- data/samples/dbg-plugins/heapscan/compiled_heapscan_lin.c +155 -0
- data/samples/dbg-plugins/heapscan/compiled_heapscan_win.c +128 -0
- data/samples/dbg-plugins/heapscan/graphheap.rb +616 -0
- data/samples/dbg-plugins/heapscan/heapscan.rb +709 -0
- data/samples/dbg-plugins/heapscan/winheap.h +174 -0
- data/samples/dbg-plugins/heapscan/winheap7.h +307 -0
- data/samples/dbg-plugins/trace_func.rb +214 -0
- data/samples/disassemble-gui.rb +48 -7
- data/samples/disassemble.rb +31 -6
- data/samples/dump_upx.rb +24 -12
- data/samples/dynamic_ruby.rb +35 -27
- data/samples/elfencode.rb +15 -0
- data/samples/emubios.rb +251 -0
- data/samples/emudbg.rb +127 -0
- data/samples/exeencode.rb +6 -5
- data/samples/factorize-headers-peimports.rb +1 -1
- data/samples/lindebug.rb +186 -391
- data/samples/metasm-shell.rb +68 -57
- data/samples/peldr.rb +2 -2
- data/tests/all.rb +1 -1
- data/tests/arc.rb +26 -0
- data/tests/dynldr.rb +22 -4
- data/tests/expression.rb +57 -0
- data/tests/graph_layout.rb +285 -0
- data/tests/ia32.rb +80 -26
- data/tests/mcs51.rb +27 -0
- data/tests/mips.rb +10 -3
- data/tests/preprocessor.rb +18 -0
- data/tests/x86_64.rb +66 -18
- metadata +465 -219
- metadata.gz.sig +2 -0
- data/lib/metasm/arm/opcodes.rb +0 -177
- data/lib/metasm/gui.rb +0 -23
- data/lib/metasm/gui/dasm_graph.rb +0 -1354
- data/lib/metasm/ia32.rb +0 -14
- data/lib/metasm/ia32/opcodes.rb +0 -872
- data/lib/metasm/ppc/parse.rb +0 -52
- data/lib/metasm/x86_64.rb +0 -12
- data/lib/metasm/x86_64/opcodes.rb +0 -118
- data/samples/gdbclient.rb +0 -583
- data/samples/rubstop.rb +0 -399
data/samples/dynamic_ruby.rb
CHANGED
@@ -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
|
453
|
-
# XXX will get the wrong order for "case x; when 1; when
|
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?
|
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?(
|
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?
|
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?
|
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?
|
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
|
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
|
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
|
-
|
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
|
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
|
data/samples/emubios.rb
ADDED
@@ -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
|