metasm 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|