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.
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