metasm 1.0.3 → 1.0.4
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +3 -0
- data.tar.gz.sig +0 -0
- data/Gemfile +3 -2
- data/metasm.gemspec +3 -2
- data/metasm.rb +4 -1
- data/metasm/compile_c.rb +2 -2
- data/metasm/cpu/arc/decode.rb +0 -21
- data/metasm/cpu/arc/main.rb +4 -4
- data/metasm/cpu/arm/decode.rb +1 -5
- data/metasm/cpu/arm/main.rb +3 -3
- data/metasm/cpu/arm64/decode.rb +2 -6
- data/metasm/cpu/arm64/main.rb +5 -5
- data/metasm/cpu/bpf/decode.rb +3 -35
- data/metasm/cpu/bpf/main.rb +5 -5
- data/metasm/cpu/bpf/render.rb +1 -12
- data/metasm/cpu/cy16/decode.rb +0 -6
- data/metasm/cpu/cy16/main.rb +3 -3
- data/metasm/cpu/cy16/render.rb +0 -11
- data/metasm/cpu/dalvik/decode.rb +4 -26
- data/metasm/cpu/dalvik/main.rb +20 -2
- data/metasm/cpu/dalvik/opcodes.rb +3 -2
- data/metasm/cpu/{mips/compile_c.rb → ebpf.rb} +5 -2
- 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/debug.rb +39 -1
- data/metasm/cpu/ia32/decode.rb +111 -90
- data/metasm/cpu/ia32/decompile.rb +45 -37
- data/metasm/cpu/ia32/main.rb +10 -0
- data/metasm/cpu/ia32/parse.rb +6 -0
- data/metasm/cpu/mcs51/decode.rb +1 -1
- data/metasm/cpu/mcs51/main.rb +11 -0
- data/metasm/cpu/mips/decode.rb +8 -18
- data/metasm/cpu/mips/main.rb +3 -3
- data/metasm/cpu/mips/opcodes.rb +1 -1
- data/metasm/cpu/msp430/decode.rb +2 -6
- data/metasm/cpu/msp430/main.rb +3 -3
- 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/metasm/cpu/ppc/decode.rb +0 -25
- data/metasm/cpu/ppc/main.rb +6 -6
- data/metasm/cpu/ppc/opcodes.rb +3 -4
- data/metasm/cpu/python/decode.rb +0 -20
- data/metasm/cpu/python/main.rb +1 -1
- data/metasm/cpu/sh4/decode.rb +2 -6
- data/metasm/cpu/sh4/main.rb +25 -23
- data/metasm/cpu/st20/decode.rb +0 -7
- data/metasm/cpu/webasm.rb +11 -0
- 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/compile_c.rb +13 -9
- data/metasm/cpu/x86_64/parse.rb +1 -1
- data/metasm/cpu/z80/decode.rb +0 -27
- data/metasm/cpu/z80/main.rb +3 -3
- data/metasm/cpu/z80/render.rb +0 -11
- data/metasm/debug.rb +43 -8
- data/metasm/decode.rb +62 -14
- data/metasm/decompile.rb +793 -466
- data/metasm/disassemble.rb +188 -131
- data/metasm/disassemble_api.rb +30 -17
- data/metasm/dynldr.rb +2 -2
- data/metasm/encode.rb +8 -2
- data/metasm/exe_format/autoexe.rb +2 -0
- data/metasm/exe_format/coff.rb +21 -3
- data/metasm/exe_format/coff_decode.rb +12 -0
- data/metasm/exe_format/coff_encode.rb +6 -3
- data/metasm/exe_format/dex.rb +13 -3
- data/metasm/exe_format/elf.rb +12 -2
- data/metasm/exe_format/elf_decode.rb +59 -1
- data/metasm/exe_format/main.rb +2 -0
- data/metasm/exe_format/mz.rb +1 -0
- data/metasm/exe_format/pe.rb +25 -3
- data/metasm/exe_format/wasm.rb +402 -0
- data/metasm/gui/dasm_decomp.rb +171 -95
- data/metasm/gui/dasm_graph.rb +61 -2
- data/metasm/gui/dasm_hex.rb +2 -2
- data/metasm/gui/dasm_main.rb +45 -19
- data/metasm/gui/debug.rb +13 -4
- data/metasm/gui/gtk.rb +12 -4
- data/metasm/main.rb +108 -103
- data/metasm/os/emulator.rb +175 -0
- data/metasm/os/main.rb +11 -6
- data/metasm/parse.rb +23 -12
- data/metasm/parse_c.rb +189 -135
- data/metasm/preprocessor.rb +16 -1
- data/misc/openrisc-parser.rb +79 -0
- data/samples/dasm-plugins/scanxrefs.rb +6 -4
- data/samples/dasm-plugins/selfmodify.rb +8 -8
- data/samples/dbg-plugins/trace_func.rb +1 -1
- data/samples/disassemble-gui.rb +14 -3
- data/samples/emubios.rb +251 -0
- data/samples/emudbg.rb +127 -0
- data/samples/lindebug.rb +79 -78
- data/samples/metasm-shell.rb +8 -8
- data/tests/all.rb +1 -1
- data/tests/expression.rb +2 -0
- data/tests/graph_layout.rb +1 -1
- data/tests/ia32.rb +1 -0
- data/tests/mips.rb +1 -1
- data/tests/preprocessor.rb +18 -0
- metadata +124 -6
- metadata.gz.sig +0 -0
data/metasm/gui/debug.rb
CHANGED
|
@@ -119,7 +119,7 @@ class DbgWidget < ContainerVBoxWidget
|
|
|
119
119
|
@dbg.dasm_invalidate
|
|
120
120
|
@mem.gui_update
|
|
121
121
|
@dbg.disassembler.sections.clear if @dbg.state == :dead
|
|
122
|
-
@dbg.disassembler.disassemble_fast(@dbg.pc)
|
|
122
|
+
@dbg.disassembler.disassemble_fast(@dbg.pc) if not @dbg.disassembler.di_at(@dbg.pc)
|
|
123
123
|
@children.each { |c|
|
|
124
124
|
if wp = @watchpoint[c]
|
|
125
125
|
c.focus_addr @dbg.resolve_expr(wp), nil, true
|
|
@@ -251,7 +251,7 @@ class DbgRegWidget < DrawableWidget
|
|
|
251
251
|
@reg_pos = [] # list of x y w h vx of the reg drawing on widget, vx is x of value
|
|
252
252
|
|
|
253
253
|
@default_color_association = ColorTheme.merge :label => :text, :data => :blue, :write_pending => :darkred,
|
|
254
|
-
:changed => :
|
|
254
|
+
:changed => :darkgreen, :caret => :text, :inactive => :palegrey
|
|
255
255
|
end
|
|
256
256
|
|
|
257
257
|
def swapin_tid
|
|
@@ -313,7 +313,11 @@ class DbgRegWidget < DrawableWidget
|
|
|
313
313
|
render["#{reg}=".ljust(regstrlen), :label]
|
|
314
314
|
v = @write_pending[reg] || @reg_cache[reg]
|
|
315
315
|
col = running ? :inactive : @write_pending[reg] ? :write_pending : @reg_cache_old.fetch(reg, v) != v ? :changed : :data
|
|
316
|
-
|
|
316
|
+
if v.kind_of?(::Integer)
|
|
317
|
+
render["%0#{@register_size[reg]}x " % v, col]
|
|
318
|
+
else
|
|
319
|
+
render[v.to_s, col]
|
|
320
|
+
end
|
|
317
321
|
x += @font_width # space
|
|
318
322
|
}
|
|
319
323
|
|
|
@@ -974,7 +978,11 @@ class DbgConsoleWidget < DrawableWidget
|
|
|
974
978
|
}
|
|
975
979
|
new_command('?', 'display a value') { |arg|
|
|
976
980
|
next if not v = solve_expr(arg)
|
|
977
|
-
|
|
981
|
+
if v.kind_of?(Expression)
|
|
982
|
+
add_log "#{v}"
|
|
983
|
+
else
|
|
984
|
+
add_log "#{v} 0x#{v.to_s(16)} #{[v & 0xffff_ffff].pack('L').inspect} #{@dbg.addrname!(v)}"
|
|
985
|
+
end
|
|
978
986
|
}
|
|
979
987
|
new_command('exit', 'quit', 'quit the debugger interface') { p.win.destroy }
|
|
980
988
|
new_command('ruby', 'execute arbitrary ruby code') { |arg|
|
|
@@ -1232,6 +1240,7 @@ end
|
|
|
1232
1240
|
class DbgWindow < Window
|
|
1233
1241
|
attr_accessor :dbg_widget
|
|
1234
1242
|
def initialize_window(dbg = nil, title='metasm debugger')
|
|
1243
|
+
dbg, title = title, dbg if dbg.kind_of?(::String) or title.kind_of?(Debugger)
|
|
1235
1244
|
self.title = title
|
|
1236
1245
|
display(dbg) if dbg
|
|
1237
1246
|
end
|
data/metasm/gui/gtk.rb
CHANGED
|
@@ -128,13 +128,18 @@ class ContainerVBoxWidget < Gtk::VBox
|
|
|
128
128
|
def resize_child(cld, w, h)
|
|
129
129
|
pk = query_child_packing(cld)
|
|
130
130
|
if h <= 0
|
|
131
|
-
pk[0]
|
|
131
|
+
if pk[0] != true
|
|
132
|
+
pk[0] = true
|
|
133
|
+
set_child_packing(cld, *pk)
|
|
134
|
+
end
|
|
132
135
|
h = 1
|
|
133
136
|
else
|
|
134
|
-
pk[0]
|
|
137
|
+
if pk[0] == true
|
|
138
|
+
pk[0] = false
|
|
139
|
+
set_child_packing(cld, *pk)
|
|
140
|
+
end
|
|
135
141
|
end
|
|
136
142
|
return if h == cld.allocation.height
|
|
137
|
-
set_child_packing(cld, *pk)
|
|
138
143
|
cld.set_height_request(h)
|
|
139
144
|
end
|
|
140
145
|
|
|
@@ -582,12 +587,15 @@ class InputBox < Gtk::Dialog
|
|
|
582
587
|
key = DrawableWidget::Keyboard_trad[ev.keyval]
|
|
583
588
|
case key
|
|
584
589
|
when :escape
|
|
590
|
+
@history_off = @history.length
|
|
585
591
|
response(RESPONSE_REJECT)
|
|
586
592
|
true
|
|
587
593
|
when :enter
|
|
594
|
+
@history.pop if @history.last == ''
|
|
588
595
|
@history << @textwidget.buffer.text.to_s
|
|
589
596
|
@history.pop if @history.last == ''
|
|
590
597
|
@history.pop if @history.last == @history[-2]
|
|
598
|
+
@history_off = @history.length
|
|
591
599
|
response(RESPONSE_ACCEPT)
|
|
592
600
|
true
|
|
593
601
|
when :up, :down
|
|
@@ -596,7 +604,7 @@ class InputBox < Gtk::Dialog
|
|
|
596
604
|
@history[@history_off] = txt
|
|
597
605
|
end
|
|
598
606
|
@history_off += (key == :up ? -1 : 1)
|
|
599
|
-
@history_off %= @history.length
|
|
607
|
+
@history_off %= (@history.length > 0 ? @history.length : 1)
|
|
600
608
|
@textwidget.buffer.text = @history[@history_off].to_s
|
|
601
609
|
text_select_all
|
|
602
610
|
end
|
data/metasm/main.rb
CHANGED
|
@@ -327,12 +327,16 @@ end
|
|
|
327
327
|
class ExpressionType
|
|
328
328
|
def +(o) Expression[self, :+, o].reduce end
|
|
329
329
|
def -(o) Expression[self, :-, o].reduce end
|
|
330
|
+
# if the expression is constrained, this holds the mask of the maximum value
|
|
331
|
+
# (eg int16 => 0xffff)
|
|
332
|
+
attr_accessor :max_bits_mask
|
|
330
333
|
end
|
|
331
334
|
|
|
332
335
|
# handle immediate values, and arbitrary arithmetic/logic expression involving variables
|
|
333
336
|
# boolean values are treated as in C : true is 1, false is 0
|
|
334
337
|
# TODO replace #type with #size => bits + #type => [:signed/:unsigned/:any/:floating]
|
|
335
338
|
# TODO handle floats
|
|
339
|
+
# TODO ternary operator ?
|
|
336
340
|
class Expression < ExpressionType
|
|
337
341
|
INT_SIZE = {}
|
|
338
342
|
INT_MIN = {}
|
|
@@ -383,7 +387,7 @@ class Expression < ExpressionType
|
|
|
383
387
|
# checks if a given Expression/Integer is in the type range
|
|
384
388
|
# returns true if it is, false if it overflows, and nil if cannot be determined (eg unresolved variable)
|
|
385
389
|
def self.in_range?(val, type)
|
|
386
|
-
val = val.reduce if val.kind_of?
|
|
390
|
+
val = val.reduce if val.kind_of?(self)
|
|
387
391
|
return unless val.kind_of?(::Numeric)
|
|
388
392
|
|
|
389
393
|
if INT_MIN[type]
|
|
@@ -490,15 +494,13 @@ class Expression < ExpressionType
|
|
|
490
494
|
# returns a simplified copy of self
|
|
491
495
|
# can return an +Expression+ or a +Numeric+, may return self
|
|
492
496
|
# see +reduce_rec+ for simplifications description
|
|
493
|
-
# if given a block,
|
|
494
|
-
def reduce(&
|
|
495
|
-
|
|
496
|
-
case e = reduce_rec
|
|
497
|
+
# if given a block, will use it instead of @@reduce_lambda
|
|
498
|
+
def reduce(&cb)
|
|
499
|
+
cb ||= @@reduce_lambda
|
|
500
|
+
case e = reduce_rec(cb)
|
|
497
501
|
when Expression, Numeric; e
|
|
498
502
|
else Expression[e]
|
|
499
503
|
end
|
|
500
|
-
ensure
|
|
501
|
-
@@reduce_lambda = old_rp if b
|
|
502
504
|
end
|
|
503
505
|
|
|
504
506
|
# resolves logic operations (true || false, etc)
|
|
@@ -508,13 +510,13 @@ class Expression < ExpressionType
|
|
|
508
510
|
# reduces addition of 0 and unary +
|
|
509
511
|
# canonicalize additions: put variables in the lhs, descend addition tree in the rhs => (a + (b + (c + 12)))
|
|
510
512
|
# make formal reduction if finds somewhere in addition tree (a) and (-a)
|
|
511
|
-
def reduce_rec
|
|
512
|
-
l = @lexpr.kind_of?(ExpressionType) ? @lexpr.reduce_rec : @lexpr
|
|
513
|
-
r = @rexpr.kind_of?(ExpressionType) ? @rexpr.reduce_rec : @rexpr
|
|
513
|
+
def reduce_rec(cb = @@reduce_lambda)
|
|
514
|
+
l = @lexpr.kind_of?(ExpressionType) ? @lexpr.reduce_rec(cb) : @lexpr
|
|
515
|
+
r = @rexpr.kind_of?(ExpressionType) ? @rexpr.reduce_rec(cb) : @rexpr
|
|
514
516
|
|
|
515
|
-
if
|
|
516
|
-
l =
|
|
517
|
-
r =
|
|
517
|
+
if cb
|
|
518
|
+
l = cb[l] || l if l and not @lexpr.kind_of?(Expression)
|
|
519
|
+
r = cb[r] || r if r and not @rexpr.kind_of?(Expression)
|
|
518
520
|
end
|
|
519
521
|
|
|
520
522
|
v =
|
|
@@ -540,7 +542,7 @@ class Expression < ExpressionType
|
|
|
540
542
|
l.send(@op, r)
|
|
541
543
|
end
|
|
542
544
|
elsif rp = @@reduce_op[@op]
|
|
543
|
-
rp[self, l, r]
|
|
545
|
+
rp[self, l, r, cb]
|
|
544
546
|
end
|
|
545
547
|
|
|
546
548
|
ret = case v
|
|
@@ -552,9 +554,9 @@ class Expression < ExpressionType
|
|
|
552
554
|
(v.lexpr == :unknown or v.rexpr == :unknown) ? :unknown : v
|
|
553
555
|
else v
|
|
554
556
|
end
|
|
555
|
-
if
|
|
556
|
-
if newret.kind_of?
|
|
557
|
-
ret = newret.reduce_rec
|
|
557
|
+
if cb and ret.kind_of?(ExpressionType) and newret = cb[ret] and newret != ret
|
|
558
|
+
if newret.kind_of?(ExpressionType)
|
|
559
|
+
ret = newret.reduce_rec(cb)
|
|
558
560
|
else
|
|
559
561
|
ret = newret
|
|
560
562
|
end
|
|
@@ -563,21 +565,21 @@ class Expression < ExpressionType
|
|
|
563
565
|
end
|
|
564
566
|
|
|
565
567
|
@@reduce_op = {
|
|
566
|
-
:+ => lambda { |e, l, r| e.reduce_op_plus(l, r) },
|
|
567
|
-
:- => lambda { |e, l, r| e.reduce_op_minus(l, r) },
|
|
568
|
-
:'&&' => lambda { |e, l, r| e.reduce_op_andand(l, r) },
|
|
569
|
-
:'||' => lambda { |e, l, r| e.reduce_op_oror(l, r) },
|
|
570
|
-
:>> => lambda { |e, l, r| e.reduce_op_shr(l, r) },
|
|
571
|
-
:<< => lambda { |e, l, r| e.reduce_op_shl(l, r) },
|
|
572
|
-
:'!' => lambda { |e, l, r| e.reduce_op_not(l, r) },
|
|
573
|
-
:== => lambda { |e, l, r| e.reduce_op_eql(l, r) },
|
|
574
|
-
:'!=' => lambda { |e, l, r| e.reduce_op_neq(l, r) },
|
|
575
|
-
:^ => lambda { |e, l, r| e.reduce_op_xor(l, r) },
|
|
576
|
-
:& => lambda { |e, l, r| e.reduce_op_and(l, r) },
|
|
577
|
-
:| => lambda { |e, l, r| e.reduce_op_or(l, r) },
|
|
578
|
-
:* => lambda { |e, l, r| e.reduce_op_times(l, r) },
|
|
579
|
-
:/ => lambda { |e, l, r| e.reduce_op_div(l, r) },
|
|
580
|
-
:% => lambda { |e, l, r| e.reduce_op_mod(l, r) },
|
|
568
|
+
:+ => lambda { |e, l, r, cb| e.reduce_op_plus(l, r, cb) },
|
|
569
|
+
:- => lambda { |e, l, r, cb| e.reduce_op_minus(l, r, cb) },
|
|
570
|
+
:'&&' => lambda { |e, l, r, cb| e.reduce_op_andand(l, r, cb) },
|
|
571
|
+
:'||' => lambda { |e, l, r, cb| e.reduce_op_oror(l, r, cb) },
|
|
572
|
+
:>> => lambda { |e, l, r, cb| e.reduce_op_shr(l, r, cb) },
|
|
573
|
+
:<< => lambda { |e, l, r, cb| e.reduce_op_shl(l, r, cb) },
|
|
574
|
+
:'!' => lambda { |e, l, r, cb| e.reduce_op_not(l, r, cb) },
|
|
575
|
+
:== => lambda { |e, l, r, cb| e.reduce_op_eql(l, r, cb) },
|
|
576
|
+
:'!=' => lambda { |e, l, r, cb| e.reduce_op_neq(l, r, cb) },
|
|
577
|
+
:^ => lambda { |e, l, r, cb| e.reduce_op_xor(l, r, cb) },
|
|
578
|
+
:& => lambda { |e, l, r, cb| e.reduce_op_and(l, r, cb) },
|
|
579
|
+
:| => lambda { |e, l, r, cb| e.reduce_op_or(l, r, cb) },
|
|
580
|
+
:* => lambda { |e, l, r, cb| e.reduce_op_times(l, r, cb) },
|
|
581
|
+
:/ => lambda { |e, l, r, cb| e.reduce_op_div(l, r, cb) },
|
|
582
|
+
:% => lambda { |e, l, r, cb| e.reduce_op_mod(l, r, cb) },
|
|
581
583
|
}
|
|
582
584
|
|
|
583
585
|
|
|
@@ -585,47 +587,47 @@ class Expression < ExpressionType
|
|
|
585
587
|
@@reduce_op
|
|
586
588
|
end
|
|
587
589
|
|
|
588
|
-
def reduce_op_plus(l, r)
|
|
590
|
+
def reduce_op_plus(l, r, cb)
|
|
589
591
|
if not l; r # +x => x
|
|
590
592
|
elsif r == 0; l # x+0 => x
|
|
591
593
|
elsif l == :unknown or r == :unknown; :unknown
|
|
592
594
|
elsif l.kind_of?(::Numeric)
|
|
593
595
|
if r.kind_of? Expression and r.op == :+
|
|
594
596
|
# 1+(x+y) => x+(y+1)
|
|
595
|
-
Expression[r.lexpr, :+, [r.rexpr, :+, l]].reduce_rec
|
|
597
|
+
Expression[r.lexpr, :+, [r.rexpr, :+, l]].reduce_rec(cb)
|
|
596
598
|
else
|
|
597
599
|
# 1+a => a+1
|
|
598
|
-
Expression[r, :+, l].reduce_rec
|
|
600
|
+
Expression[r, :+, l].reduce_rec(cb)
|
|
599
601
|
end
|
|
600
602
|
# (a+b)+foo => a+(b+foo)
|
|
601
|
-
elsif l.kind_of? Expression and l.op == :+; Expression[l.lexpr, :+, [l.rexpr, :+, r]].reduce_rec
|
|
603
|
+
elsif l.kind_of? Expression and l.op == :+; Expression[l.lexpr, :+, [l.rexpr, :+, r]].reduce_rec(cb)
|
|
602
604
|
elsif l.kind_of? Expression and r.kind_of? Expression and l.op == :% and r.op == :% and l.rexpr.kind_of?(::Integer) and l.rexpr == r.rexpr
|
|
603
|
-
Expression[[l.lexpr, :+, r.lexpr], :%, l.rexpr].reduce_rec
|
|
605
|
+
Expression[[l.lexpr, :+, r.lexpr], :%, l.rexpr].reduce_rec(cb)
|
|
604
606
|
elsif l.kind_of? Expression and l.op == :- and not l.lexpr
|
|
605
|
-
reduce_rec_add_rec(r, l.rexpr)
|
|
607
|
+
reduce_rec_add_rec(r, l.rexpr, cb)
|
|
606
608
|
elsif l.kind_of? Expression and r.kind_of? Expression and l.op == :& and r.op == :& and l.rexpr.kind_of?(::Integer) and r.rexpr.kind_of?(::Integer) and l.rexpr & r.rexpr == 0
|
|
607
609
|
# (a&0xf0)+(b&0x0f) => (a&0xf0)|(b&0x0f)
|
|
608
|
-
Expression[l, :|, r].reduce_rec
|
|
610
|
+
Expression[l, :|, r].reduce_rec(cb)
|
|
609
611
|
else
|
|
610
|
-
reduce_rec_add_rec(r, Expression.new(:-, l, nil))
|
|
612
|
+
reduce_rec_add_rec(r, Expression.new(:-, l, nil), cb)
|
|
611
613
|
end
|
|
612
614
|
end
|
|
613
615
|
|
|
614
|
-
def reduce_rec_add_rec(cur, neg_l)
|
|
616
|
+
def reduce_rec_add_rec(cur, neg_l, cb)
|
|
615
617
|
if neg_l == cur
|
|
616
618
|
# -l found
|
|
617
619
|
0
|
|
618
620
|
elsif cur.kind_of?(Expression) and cur.op == :+
|
|
619
621
|
# recurse
|
|
620
|
-
if newl = reduce_rec_add_rec(cur.lexpr, neg_l)
|
|
621
|
-
Expression[newl, cur.op, cur.rexpr].reduce_rec
|
|
622
|
-
elsif newr = reduce_rec_add_rec(cur.rexpr, neg_l)
|
|
623
|
-
Expression[cur.lexpr, cur.op, newr].reduce_rec
|
|
622
|
+
if newl = reduce_rec_add_rec(cur.lexpr, neg_l, cb)
|
|
623
|
+
Expression[newl, cur.op, cur.rexpr].reduce_rec(cb)
|
|
624
|
+
elsif newr = reduce_rec_add_rec(cur.rexpr, neg_l, cb)
|
|
625
|
+
Expression[cur.lexpr, cur.op, newr].reduce_rec(cb)
|
|
624
626
|
end
|
|
625
627
|
end
|
|
626
628
|
end
|
|
627
629
|
|
|
628
|
-
def reduce_op_minus(l, r)
|
|
630
|
+
def reduce_op_minus(l, r, cb)
|
|
629
631
|
if l == :unknown or r == :unknown; :unknown
|
|
630
632
|
elsif not l and r.kind_of? Expression and (r.op == :- or r.op == :+)
|
|
631
633
|
if r.op == :- # no lexpr (reduced)
|
|
@@ -633,7 +635,7 @@ class Expression < ExpressionType
|
|
|
633
635
|
r.rexpr
|
|
634
636
|
else # :+ and lexpr (r is reduced)
|
|
635
637
|
# -(a+b) => (-a)+(-b)
|
|
636
|
-
Expression.new(:+, Expression.new(:-, r.rexpr, nil), Expression.new(:-, r.lexpr, nil)).reduce_rec
|
|
638
|
+
Expression.new(:+, Expression.new(:-, r.rexpr, nil), Expression.new(:-, r.lexpr, nil)).reduce_rec(cb)
|
|
637
639
|
end
|
|
638
640
|
elsif l.kind_of? Expression and l.op == :+ and l.lexpr == r
|
|
639
641
|
# shortcircuit for a common occurence [citation needed]
|
|
@@ -641,107 +643,107 @@ class Expression < ExpressionType
|
|
|
641
643
|
l.rexpr
|
|
642
644
|
elsif l
|
|
643
645
|
# a-b => a+(-b)
|
|
644
|
-
Expression[l, :+, [:-, r]].reduce_rec
|
|
646
|
+
Expression[l, :+, [:-, r]].reduce_rec(cb)
|
|
645
647
|
end
|
|
646
648
|
end
|
|
647
649
|
|
|
648
|
-
def reduce_op_andand(l, r)
|
|
650
|
+
def reduce_op_andand(l, r, cb)
|
|
649
651
|
if l == 0 # shortcircuit eval
|
|
650
652
|
0
|
|
651
653
|
elsif l == 1
|
|
652
|
-
Expression[r, :'!=', 0].reduce_rec
|
|
654
|
+
Expression[r, :'!=', 0].reduce_rec(cb)
|
|
653
655
|
elsif r == 0
|
|
654
656
|
0 # XXX l could be a special ExprType with sideeffects ?
|
|
655
657
|
end
|
|
656
658
|
end
|
|
657
659
|
|
|
658
|
-
def reduce_op_oror(l, r)
|
|
660
|
+
def reduce_op_oror(l, r, cb)
|
|
659
661
|
if l.kind_of?(::Numeric) and l != 0 # shortcircuit eval
|
|
660
662
|
1
|
|
661
663
|
elsif l == 0
|
|
662
|
-
Expression[r, :'!=', 0].reduce_rec
|
|
664
|
+
Expression[r, :'!=', 0].reduce_rec(cb)
|
|
663
665
|
elsif r == 0
|
|
664
|
-
Expression[l, :'!=', 0].reduce_rec
|
|
666
|
+
Expression[l, :'!=', 0].reduce_rec(cb)
|
|
665
667
|
end
|
|
666
668
|
end
|
|
667
669
|
|
|
668
|
-
def reduce_op_shr(l, r)
|
|
670
|
+
def reduce_op_shr(l, r, cb)
|
|
669
671
|
if l == 0; 0
|
|
670
672
|
elsif r == 0; l
|
|
671
673
|
elsif l.kind_of? Expression and l.op == :>>
|
|
672
|
-
Expression[l.lexpr, :>>, [l.rexpr, :+, r]].reduce_rec
|
|
674
|
+
Expression[l.lexpr, :>>, [l.rexpr, :+, r]].reduce_rec(cb)
|
|
673
675
|
elsif r.kind_of? Integer and l.kind_of? Expression and [:&, :|, :^].include? l.op
|
|
674
676
|
# (a | b) << i => (a<<i | b<<i)
|
|
675
|
-
Expression[[l.lexpr, :>>, r], l.op, [l.rexpr, :>>, r]].reduce_rec
|
|
677
|
+
Expression[[l.lexpr, :>>, r], l.op, [l.rexpr, :>>, r]].reduce_rec(cb)
|
|
676
678
|
end
|
|
677
679
|
end
|
|
678
680
|
|
|
679
|
-
def reduce_op_shl(l, r)
|
|
681
|
+
def reduce_op_shl(l, r, cb)
|
|
680
682
|
if l == 0; 0
|
|
681
683
|
elsif r == 0; l
|
|
682
684
|
elsif l.kind_of? Expression and l.op == :<<
|
|
683
|
-
Expression[l.lexpr, :<<, [l.rexpr, :+, r]].reduce_rec
|
|
685
|
+
Expression[l.lexpr, :<<, [l.rexpr, :+, r]].reduce_rec(cb)
|
|
684
686
|
elsif l.kind_of? Expression and l.op == :>> and r.kind_of? Integer and l.rexpr.kind_of? Integer
|
|
685
687
|
# (a >> 1) << 1 == a & 0xfffffe
|
|
686
688
|
if r == l.rexpr
|
|
687
|
-
Expression[l.lexpr, :&, (-1 << r)].reduce_rec
|
|
689
|
+
Expression[l.lexpr, :&, (-1 << r)].reduce_rec(cb)
|
|
688
690
|
elsif r > l.rexpr
|
|
689
|
-
Expression[[l.lexpr, :<<, r-l.rexpr], :&, (-1 << r)].reduce_rec
|
|
691
|
+
Expression[[l.lexpr, :<<, r-l.rexpr], :&, (-1 << r)].reduce_rec(cb)
|
|
690
692
|
else
|
|
691
|
-
Expression[[l.lexpr, :>>, l.rexpr-r], :&, (-1 << r)].reduce_rec
|
|
693
|
+
Expression[[l.lexpr, :>>, l.rexpr-r], :&, (-1 << r)].reduce_rec(cb)
|
|
692
694
|
end
|
|
693
|
-
elsif r.kind_of?
|
|
695
|
+
elsif r.kind_of?(::Integer) and l.kind_of?(Expression) and [:&, :|, :^].include?(l.op)
|
|
694
696
|
# (a | b) << i => (a<<i | b<<i)
|
|
695
|
-
Expression[[l.lexpr, :<<, r], l.op, [l.rexpr, :<<, r]].reduce_rec
|
|
697
|
+
Expression[[l.lexpr, :<<, r], l.op, [l.rexpr, :<<, r]].reduce_rec(cb)
|
|
696
698
|
end
|
|
697
699
|
end
|
|
698
700
|
|
|
699
701
|
NEG_OP = {:'==' => :'!=', :'!=' => :'==', :< => :>=, :> => :<=, :<= => :>, :>= => :<}
|
|
700
702
|
|
|
701
|
-
def reduce_op_not(l, r)
|
|
703
|
+
def reduce_op_not(l, r, cb)
|
|
702
704
|
if r.kind_of? Expression and nop = NEG_OP[r.op]
|
|
703
|
-
Expression[r.lexpr, nop, r.rexpr].reduce_rec
|
|
705
|
+
Expression[r.lexpr, nop, r.rexpr].reduce_rec(cb)
|
|
704
706
|
end
|
|
705
707
|
end
|
|
706
708
|
|
|
707
|
-
def reduce_op_eql(l, r)
|
|
709
|
+
def reduce_op_eql(l, r, cb)
|
|
708
710
|
if l == r; 1
|
|
709
711
|
elsif r == 0 and l.kind_of? Expression and nop = NEG_OP[l.op]
|
|
710
|
-
Expression[l.lexpr, nop, l.rexpr].reduce_rec
|
|
712
|
+
Expression[l.lexpr, nop, l.rexpr].reduce_rec(cb)
|
|
711
713
|
elsif r == 1 and l.kind_of? Expression and NEG_OP[l.op]
|
|
712
714
|
l
|
|
713
715
|
elsif r == 0 and l.kind_of? Expression and l.op == :+
|
|
714
716
|
if l.rexpr.kind_of? Expression and l.rexpr.op == :- and not l.rexpr.lexpr
|
|
715
|
-
Expression[l.lexpr, :==, l.rexpr.rexpr].reduce_rec
|
|
717
|
+
Expression[l.lexpr, :==, l.rexpr.rexpr].reduce_rec(cb)
|
|
716
718
|
elsif l.rexpr.kind_of?(::Integer)
|
|
717
|
-
Expression[l.lexpr, :==, -l.rexpr].reduce_rec
|
|
719
|
+
Expression[l.lexpr, :==, -l.rexpr].reduce_rec(cb)
|
|
718
720
|
end
|
|
719
721
|
end
|
|
720
722
|
end
|
|
721
723
|
|
|
722
|
-
def reduce_op_neq(l, r)
|
|
724
|
+
def reduce_op_neq(l, r, cb)
|
|
723
725
|
if l == r; 0
|
|
724
726
|
end
|
|
725
727
|
end
|
|
726
728
|
|
|
727
|
-
def reduce_op_xor(l, r)
|
|
729
|
+
def reduce_op_xor(l, r, cb)
|
|
728
730
|
if l == :unknown or r == :unknown; :unknown
|
|
729
731
|
elsif l == 0; r
|
|
730
732
|
elsif r == 0; l
|
|
731
733
|
elsif l == r; 0
|
|
732
734
|
elsif r == 1 and l.kind_of? Expression and NEG_OP[l.op]
|
|
733
|
-
Expression[nil, :'!', l].reduce_rec
|
|
735
|
+
Expression[nil, :'!', l].reduce_rec(cb)
|
|
734
736
|
elsif l.kind_of?(::Numeric)
|
|
735
737
|
if r.kind_of? Expression and r.op == :^
|
|
736
738
|
# 1^(x^y) => x^(y^1)
|
|
737
|
-
Expression[r.lexpr, :^, [r.rexpr, :^, l]].reduce_rec
|
|
739
|
+
Expression[r.lexpr, :^, [r.rexpr, :^, l]].reduce_rec(cb)
|
|
738
740
|
else
|
|
739
741
|
# 1^a => a^1
|
|
740
|
-
Expression[r, :^, l].reduce_rec
|
|
742
|
+
Expression[r, :^, l].reduce_rec(cb)
|
|
741
743
|
end
|
|
742
744
|
elsif l.kind_of? Expression and l.op == :^
|
|
743
745
|
# (a^b)^c => a^(b^c)
|
|
744
|
-
Expression[l.lexpr, :^, [l.rexpr, :^, r]].reduce_rec
|
|
746
|
+
Expression[l.lexpr, :^, [l.rexpr, :^, r]].reduce_rec(cb)
|
|
745
747
|
elsif r.kind_of? Expression and r.op == :^
|
|
746
748
|
if r.rexpr == l
|
|
747
749
|
# a^(a^b) => b
|
|
@@ -759,30 +761,32 @@ class Expression < ExpressionType
|
|
|
759
761
|
tr = tr.rexpr
|
|
760
762
|
end
|
|
761
763
|
if found
|
|
762
|
-
Expression[r.lexpr, :^, [l, :^, r.rexpr]].reduce_rec
|
|
764
|
+
Expression[r.lexpr, :^, [l, :^, r.rexpr]].reduce_rec(cb)
|
|
763
765
|
end
|
|
764
766
|
end
|
|
765
767
|
elsif l.kind_of?(Expression) and l.op == :& and l.rexpr.kind_of?(::Integer) and (l.rexpr & (l.rexpr+1)) == 0
|
|
766
768
|
if r.kind_of?(::Integer) and r & l.rexpr == r
|
|
767
769
|
# (a&0xfff)^12 => (a^12)&0xfff
|
|
768
|
-
Expression[[l.lexpr, :^, r], :&, l.rexpr].reduce_rec
|
|
770
|
+
Expression[[l.lexpr, :^, r], :&, l.rexpr].reduce_rec(cb)
|
|
769
771
|
elsif r.kind_of?(Expression) and r.op == :& and r.rexpr.kind_of?(::Integer) and r.rexpr == l.rexpr
|
|
770
772
|
# (a&0xfff)^(b&0xfff) => (a^b)&0xfff
|
|
771
|
-
Expression[[l.lexpr, :^, r.lexpr], :&, l.rexpr].reduce_rec
|
|
773
|
+
Expression[[l.lexpr, :^, r.lexpr], :&, l.rexpr].reduce_rec(cb)
|
|
772
774
|
end
|
|
773
775
|
end
|
|
774
776
|
end
|
|
775
777
|
|
|
776
|
-
def reduce_op_and(l, r)
|
|
778
|
+
def reduce_op_and(l, r, cb)
|
|
777
779
|
if l == 0 or r == 0; 0
|
|
778
780
|
elsif r == 1 and l.kind_of?(Expression) and [:'==', :'!=', :<, :>, :<=, :>=].include?(l.op)
|
|
779
781
|
l
|
|
780
782
|
elsif l == r; l
|
|
781
|
-
elsif l.kind_of?(Integer); Expression[r, :&, l].reduce_rec
|
|
782
|
-
elsif l.kind_of?(Expression) and l.op == :&; Expression[l.lexpr, :&, [l.rexpr, :&, r]].reduce_rec
|
|
783
|
+
elsif l.kind_of?(Integer); Expression[r, :&, l].reduce_rec(cb)
|
|
784
|
+
elsif l.kind_of?(Expression) and l.op == :&; Expression[l.lexpr, :&, [l.rexpr, :&, r]].reduce_rec(cb)
|
|
783
785
|
elsif l.kind_of?(Expression) and [:|, :^].include?(l.op) and r.kind_of?(Integer) and (l.op == :| or (r & (r+1)) != 0)
|
|
784
786
|
# (a ^| b) & i => (a&i ^| b&i)
|
|
785
|
-
Expression[[l.lexpr, :&, r], l.op, [l.rexpr, :&, r]].reduce_rec
|
|
787
|
+
Expression[[l.lexpr, :&, r], l.op, [l.rexpr, :&, r]].reduce_rec(cb)
|
|
788
|
+
elsif r.kind_of?(::Integer) and l.kind_of?(ExpressionType) and r == l.max_bits_mask
|
|
789
|
+
l
|
|
786
790
|
elsif r.kind_of?(::Integer) and l.kind_of?(Expression) and (r & (r+1)) == 0
|
|
787
791
|
# foo & 0xffff
|
|
788
792
|
case l.op
|
|
@@ -790,17 +794,17 @@ class Expression < ExpressionType
|
|
|
790
794
|
if l.lexpr.kind_of?(Expression) and l.lexpr.op == :& and
|
|
791
795
|
l.lexpr.rexpr.kind_of?(::Integer) and l.lexpr.rexpr & r == r
|
|
792
796
|
# ((a&m) + b) & m => (a+b) & m
|
|
793
|
-
Expression[[l.lexpr.lexpr, l.op, l.rexpr], :&, r].reduce_rec
|
|
797
|
+
Expression[[l.lexpr.lexpr, l.op, l.rexpr], :&, r].reduce_rec(cb)
|
|
794
798
|
elsif l.rexpr.kind_of?(Expression) and l.rexpr.op == :& and
|
|
795
799
|
l.rexpr.rexpr.kind_of?(::Integer) and l.rexpr.rexpr & r == r
|
|
796
800
|
# (a + (b&m)) & m => (a+b) & m
|
|
797
|
-
Expression[[l.lexpr, l.op, l.rexpr.lexpr], :&, r].reduce_rec
|
|
801
|
+
Expression[[l.lexpr, l.op, l.rexpr.lexpr], :&, r].reduce_rec(cb)
|
|
798
802
|
else
|
|
799
803
|
Expression[l, :&, r]
|
|
800
804
|
end
|
|
801
805
|
when :|
|
|
802
806
|
# rol/ror composition
|
|
803
|
-
reduce_rec_composerol
|
|
807
|
+
reduce_rec_composerol(l, r, cb)
|
|
804
808
|
else
|
|
805
809
|
Expression[l, :&, r]
|
|
806
810
|
end
|
|
@@ -809,7 +813,7 @@ class Expression < ExpressionType
|
|
|
809
813
|
|
|
810
814
|
# a check to see if an Expr is the composition of two rotations (rol eax, 4 ; rol eax, 6 => rol eax, 10)
|
|
811
815
|
# this is a bit too ugly to stay in the main reduce_rec body.
|
|
812
|
-
def reduce_rec_composerol(e, mask)
|
|
816
|
+
def reduce_rec_composerol(e, mask, cb)
|
|
813
817
|
m = Expression[['var', :sh_op, 'amt'], :|, ['var', :inv_sh_op, 'inv_amt']]
|
|
814
818
|
if vars = e.match(m, 'var', :sh_op, 'amt', :inv_sh_op, 'inv_amt') and vars[:sh_op] == {:>> => :<<, :<< => :>>}[vars[:inv_sh_op]] and
|
|
815
819
|
((vars['amt'].kind_of?(::Integer) and vars['inv_amt'].kind_of?(::Integer) and ampl = vars['amt'] + vars['inv_amt']) or
|
|
@@ -829,50 +833,50 @@ class Expression < ExpressionType
|
|
|
829
833
|
end
|
|
830
834
|
amt = Expression[[vars['amt'], :+, ivars['amt']], :%, ampl]
|
|
831
835
|
invamt = Expression[[vars['inv_amt'], :+, ivars['inv_amt']], :%, ampl]
|
|
832
|
-
Expression[[[[ivars['var'], :&, mask], vars[:sh_op], amt], :|, [[ivars['var'], :&, mask], vars[:inv_sh_op], invamt]], :&, mask].reduce_rec
|
|
836
|
+
Expression[[[[ivars['var'], :&, mask], vars[:sh_op], amt], :|, [[ivars['var'], :&, mask], vars[:inv_sh_op], invamt]], :&, mask].reduce_rec(cb)
|
|
833
837
|
else
|
|
834
838
|
Expression[e, :&, mask]
|
|
835
839
|
end
|
|
836
840
|
end
|
|
837
841
|
|
|
838
|
-
def reduce_op_or(l, r)
|
|
842
|
+
def reduce_op_or(l, r, cb)
|
|
839
843
|
if l == 0; r
|
|
840
844
|
elsif r == 0; l
|
|
841
845
|
elsif l == -1 or r == -1; -1
|
|
842
846
|
elsif l == r; l
|
|
843
|
-
elsif l.kind_of? Integer; Expression[r, :|, l].reduce_rec
|
|
847
|
+
elsif l.kind_of? Integer; Expression[r, :|, l].reduce_rec(cb)
|
|
844
848
|
elsif l.kind_of? Expression and l.op == :|
|
|
845
849
|
# (a|b)|c => a|(b|c)
|
|
846
|
-
Expression[l.lexpr, :|, [l.rexpr, :|, r]].reduce_rec
|
|
850
|
+
Expression[l.lexpr, :|, [l.rexpr, :|, r]].reduce_rec(cb)
|
|
847
851
|
elsif l.kind_of? Expression and l.op == :& and r.kind_of? Expression and r.op == :& and l.lexpr == r.lexpr
|
|
848
852
|
# (a&b)|(a&c) => a&(b|c)
|
|
849
|
-
Expression[l.lexpr, :&, [l.rexpr, :|, r.rexpr]].reduce_rec
|
|
853
|
+
Expression[l.lexpr, :&, [l.rexpr, :|, r.rexpr]].reduce_rec(cb)
|
|
850
854
|
end
|
|
851
855
|
end
|
|
852
856
|
|
|
853
|
-
def reduce_op_times(l, r)
|
|
857
|
+
def reduce_op_times(l, r, cb)
|
|
854
858
|
if l == 0 or r == 0; 0
|
|
855
859
|
elsif l == 1; r
|
|
856
860
|
elsif r == 1; l
|
|
857
|
-
elsif r.kind_of? Integer; Expression[r, :*, l].reduce_rec
|
|
858
|
-
elsif r.kind_of? Expression and r.op == :*; Expression[[l, :*, r.lexpr], :*, r.rexpr].reduce_rec
|
|
859
|
-
elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :* and r.lexpr.kind_of? Integer; Expression[l*r.lexpr, :*, r.rexpr].reduce_rec # XXX need & regsize..
|
|
860
|
-
elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :+ and r.rexpr.kind_of? Integer; Expression[[l, :*, r.lexpr], :+, l*r.rexpr].reduce_rec
|
|
861
|
+
elsif r.kind_of? Integer; Expression[r, :*, l].reduce_rec(cb)
|
|
862
|
+
elsif r.kind_of? Expression and r.op == :*; Expression[[l, :*, r.lexpr], :*, r.rexpr].reduce_rec(cb)
|
|
863
|
+
elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :* and r.lexpr.kind_of? Integer; Expression[l*r.lexpr, :*, r.rexpr].reduce_rec(cb) # XXX need & regsize..
|
|
864
|
+
elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :+ and r.rexpr.kind_of? Integer; Expression[[l, :*, r.lexpr], :+, l*r.rexpr].reduce_rec(cb)
|
|
861
865
|
end
|
|
862
866
|
end
|
|
863
867
|
|
|
864
|
-
def reduce_op_div(l, r)
|
|
868
|
+
def reduce_op_div(l, r, cb)
|
|
865
869
|
if r == 0
|
|
866
870
|
elsif r.kind_of? Integer and l.kind_of? Expression and l.op == :+ and l.rexpr.kind_of? Integer and l.rexpr % r == 0
|
|
867
|
-
Expression[[l.lexpr, :/, r], :+, l.rexpr/r].reduce_rec
|
|
871
|
+
Expression[[l.lexpr, :/, r], :+, l.rexpr/r].reduce_rec(cb)
|
|
868
872
|
elsif r.kind_of? Integer and l.kind_of? Expression and l.op == :* and l.lexpr % r == 0
|
|
869
|
-
Expression[l.lexpr/r, :*, l.rexpr].reduce_rec
|
|
873
|
+
Expression[l.lexpr/r, :*, l.rexpr].reduce_rec(cb)
|
|
870
874
|
end
|
|
871
875
|
end
|
|
872
876
|
|
|
873
|
-
def reduce_op_mod(l, r)
|
|
877
|
+
def reduce_op_mod(l, r, cb)
|
|
874
878
|
if r.kind_of?(Integer) and r != 0 and (r & (r-1) == 0)
|
|
875
|
-
Expression[l, :&, r-1].reduce_rec
|
|
879
|
+
Expression[l, :&, r-1].reduce_rec(cb)
|
|
876
880
|
end
|
|
877
881
|
end
|
|
878
882
|
|
|
@@ -941,12 +945,13 @@ end
|
|
|
941
945
|
# used to show #define constants, struct offsets, func local vars, etc
|
|
942
946
|
class ExpressionString < ExpressionType
|
|
943
947
|
attr_accessor :expr, :str, :type, :hide_str
|
|
944
|
-
def reduce; expr.reduce; end
|
|
945
|
-
def reduce_rec; expr.reduce_rec; end
|
|
948
|
+
def reduce(&b); expr.reduce(&b); end
|
|
949
|
+
def reduce_rec(cb=@@reduce_lambda); expr.reduce_rec(cb); end
|
|
946
950
|
def bind(*a); expr.bind(*a); end
|
|
947
951
|
def externals; expr.externals; end
|
|
948
952
|
def expr_externals; expr.expr_externals; end
|
|
949
953
|
def match_rec(*a); expr.match_rec(*a); end
|
|
954
|
+
def max_bits_mask; expr.max_bits_mask; end
|
|
950
955
|
def initialize(expr, str, type=nil)
|
|
951
956
|
@expr = Expression[expr]
|
|
952
957
|
@str = str
|