metasm 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +3 -0
  3. data.tar.gz.sig +0 -0
  4. data/Gemfile +3 -2
  5. data/metasm.gemspec +3 -2
  6. data/metasm.rb +4 -1
  7. data/metasm/compile_c.rb +2 -2
  8. data/metasm/cpu/arc/decode.rb +0 -21
  9. data/metasm/cpu/arc/main.rb +4 -4
  10. data/metasm/cpu/arm/decode.rb +1 -5
  11. data/metasm/cpu/arm/main.rb +3 -3
  12. data/metasm/cpu/arm64/decode.rb +2 -6
  13. data/metasm/cpu/arm64/main.rb +5 -5
  14. data/metasm/cpu/bpf/decode.rb +3 -35
  15. data/metasm/cpu/bpf/main.rb +5 -5
  16. data/metasm/cpu/bpf/render.rb +1 -12
  17. data/metasm/cpu/cy16/decode.rb +0 -6
  18. data/metasm/cpu/cy16/main.rb +3 -3
  19. data/metasm/cpu/cy16/render.rb +0 -11
  20. data/metasm/cpu/dalvik/decode.rb +4 -26
  21. data/metasm/cpu/dalvik/main.rb +20 -2
  22. data/metasm/cpu/dalvik/opcodes.rb +3 -2
  23. data/metasm/cpu/{mips/compile_c.rb → ebpf.rb} +5 -2
  24. data/metasm/cpu/ebpf/debug.rb +61 -0
  25. data/metasm/cpu/ebpf/decode.rb +142 -0
  26. data/metasm/cpu/ebpf/main.rb +58 -0
  27. data/metasm/cpu/ebpf/opcodes.rb +97 -0
  28. data/metasm/cpu/ebpf/render.rb +36 -0
  29. data/metasm/cpu/ia32/debug.rb +39 -1
  30. data/metasm/cpu/ia32/decode.rb +111 -90
  31. data/metasm/cpu/ia32/decompile.rb +45 -37
  32. data/metasm/cpu/ia32/main.rb +10 -0
  33. data/metasm/cpu/ia32/parse.rb +6 -0
  34. data/metasm/cpu/mcs51/decode.rb +1 -1
  35. data/metasm/cpu/mcs51/main.rb +11 -0
  36. data/metasm/cpu/mips/decode.rb +8 -18
  37. data/metasm/cpu/mips/main.rb +3 -3
  38. data/metasm/cpu/mips/opcodes.rb +1 -1
  39. data/metasm/cpu/msp430/decode.rb +2 -6
  40. data/metasm/cpu/msp430/main.rb +3 -3
  41. data/metasm/cpu/openrisc.rb +11 -0
  42. data/metasm/cpu/openrisc/debug.rb +106 -0
  43. data/metasm/cpu/openrisc/decode.rb +182 -0
  44. data/metasm/cpu/openrisc/decompile.rb +350 -0
  45. data/metasm/cpu/openrisc/main.rb +70 -0
  46. data/metasm/cpu/openrisc/opcodes.rb +109 -0
  47. data/metasm/cpu/openrisc/render.rb +37 -0
  48. data/metasm/cpu/ppc/decode.rb +0 -25
  49. data/metasm/cpu/ppc/main.rb +6 -6
  50. data/metasm/cpu/ppc/opcodes.rb +3 -4
  51. data/metasm/cpu/python/decode.rb +0 -20
  52. data/metasm/cpu/python/main.rb +1 -1
  53. data/metasm/cpu/sh4/decode.rb +2 -6
  54. data/metasm/cpu/sh4/main.rb +25 -23
  55. data/metasm/cpu/st20/decode.rb +0 -7
  56. data/metasm/cpu/webasm.rb +11 -0
  57. data/metasm/cpu/webasm/debug.rb +31 -0
  58. data/metasm/cpu/webasm/decode.rb +321 -0
  59. data/metasm/cpu/webasm/decompile.rb +386 -0
  60. data/metasm/cpu/webasm/encode.rb +104 -0
  61. data/metasm/cpu/webasm/main.rb +81 -0
  62. data/metasm/cpu/webasm/opcodes.rb +214 -0
  63. data/metasm/cpu/x86_64/compile_c.rb +13 -9
  64. data/metasm/cpu/x86_64/parse.rb +1 -1
  65. data/metasm/cpu/z80/decode.rb +0 -27
  66. data/metasm/cpu/z80/main.rb +3 -3
  67. data/metasm/cpu/z80/render.rb +0 -11
  68. data/metasm/debug.rb +43 -8
  69. data/metasm/decode.rb +62 -14
  70. data/metasm/decompile.rb +793 -466
  71. data/metasm/disassemble.rb +188 -131
  72. data/metasm/disassemble_api.rb +30 -17
  73. data/metasm/dynldr.rb +2 -2
  74. data/metasm/encode.rb +8 -2
  75. data/metasm/exe_format/autoexe.rb +2 -0
  76. data/metasm/exe_format/coff.rb +21 -3
  77. data/metasm/exe_format/coff_decode.rb +12 -0
  78. data/metasm/exe_format/coff_encode.rb +6 -3
  79. data/metasm/exe_format/dex.rb +13 -3
  80. data/metasm/exe_format/elf.rb +12 -2
  81. data/metasm/exe_format/elf_decode.rb +59 -1
  82. data/metasm/exe_format/main.rb +2 -0
  83. data/metasm/exe_format/mz.rb +1 -0
  84. data/metasm/exe_format/pe.rb +25 -3
  85. data/metasm/exe_format/wasm.rb +402 -0
  86. data/metasm/gui/dasm_decomp.rb +171 -95
  87. data/metasm/gui/dasm_graph.rb +61 -2
  88. data/metasm/gui/dasm_hex.rb +2 -2
  89. data/metasm/gui/dasm_main.rb +45 -19
  90. data/metasm/gui/debug.rb +13 -4
  91. data/metasm/gui/gtk.rb +12 -4
  92. data/metasm/main.rb +108 -103
  93. data/metasm/os/emulator.rb +175 -0
  94. data/metasm/os/main.rb +11 -6
  95. data/metasm/parse.rb +23 -12
  96. data/metasm/parse_c.rb +189 -135
  97. data/metasm/preprocessor.rb +16 -1
  98. data/misc/openrisc-parser.rb +79 -0
  99. data/samples/dasm-plugins/scanxrefs.rb +6 -4
  100. data/samples/dasm-plugins/selfmodify.rb +8 -8
  101. data/samples/dbg-plugins/trace_func.rb +1 -1
  102. data/samples/disassemble-gui.rb +14 -3
  103. data/samples/emubios.rb +251 -0
  104. data/samples/emudbg.rb +127 -0
  105. data/samples/lindebug.rb +79 -78
  106. data/samples/metasm-shell.rb +8 -8
  107. data/tests/all.rb +1 -1
  108. data/tests/expression.rb +2 -0
  109. data/tests/graph_layout.rb +1 -1
  110. data/tests/ia32.rb +1 -0
  111. data/tests/mips.rb +1 -1
  112. data/tests/preprocessor.rb +18 -0
  113. metadata +124 -6
  114. metadata.gz.sig +0 -0
@@ -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 => :green, :caret => :text, :inactive => :palegrey
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
- render["%0#{@register_size[reg]}x " % v, col]
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
- add_log "#{v} 0x#{v.to_s(16)} #{[v & 0xffff_ffff].pack('L').inspect} #{@dbg.addrname!(v)}"
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
@@ -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] = true
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] = false
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
@@ -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? self
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, it will temporarily overwrite the global @@reduce_lambda XXX THIS IS NOT THREADSAFE
494
- def reduce(&b)
495
- old_rp, @@reduce_lambda = @@reduce_lambda, b if b
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 @@reduce_lambda
516
- l = @@reduce_lambda[l] || l if not @lexpr.kind_of? Expression
517
- r = @@reduce_lambda[r] || r if not @rexpr.kind_of? Expression
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 @@reduce_lambda and ret.kind_of? ExpressionType and newret = @@reduce_lambda[ret] and newret != ret
556
- if newret.kind_of? ExpressionType
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? Integer and l.kind_of? Expression and [:&, :|, :^].include? l.op
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 l, r
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