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
@@ -49,7 +49,7 @@ class X86_64
49
49
 
50
50
  # check if the argument matches the opcode's argument spec
51
51
  def parse_arg_valid?(o, spec, arg)
52
- return if arg.kind_of? ModRM and ((arg.b and arg.b.val == 16 and arg.i) or (arg.i and arg.i.val == 16 and (arg.b or arg.s != 1)))
52
+ return if arg.kind_of? ModRM and ((arg.b and arg.b.val == 16 and arg.i) or (arg.i and arg.i.val == 16 and (arg.b or arg.s != 1))) # cannot encode [rip+base], only [rip+imm]
53
53
  return if arg.kind_of? Reg and arg.sz >= 32 and arg.val == 16 # eip/rip only in modrm
54
54
  return if o.props[:auto64] and arg.respond_to? :sz and arg.sz == 32
55
55
  # vex c4/c5
@@ -151,12 +151,6 @@ class Z80
151
151
  di
152
152
  end
153
153
 
154
- # hash opcode_name => lambda { |dasm, di, *symbolic_args| instr_binding }
155
- def backtrace_binding
156
- @backtrace_binding ||= init_backtrace_binding
157
- end
158
- def backtrace_binding=(b) @backtrace_binding = b end
159
-
160
154
  # populate the @backtrace_binding hash with default values
161
155
  def init_backtrace_binding
162
156
  @backtrace_binding ||= {}
@@ -206,27 +200,6 @@ class Z80
206
200
  @backtrace_binding
207
201
  end
208
202
 
209
- def get_backtrace_binding(di)
210
- a = di.instruction.args.map { |arg|
211
- case arg
212
- when Memref, Reg; arg.symbolic(di)
213
- else arg
214
- end
215
- }
216
-
217
- if binding = backtrace_binding[di.opcode.basename]
218
- binding[di, *a]
219
- else
220
- puts "unhandled instruction to backtrace: #{di}" if $VERBOSE
221
- # assume nothing except the 1st arg is modified
222
- case a[0]
223
- when Indirection, Symbol; { a[0] => Expression::Unknown }
224
- when Expression; (x = a[0].externals.first) ? { x => Expression::Unknown } : {}
225
- else {}
226
- end.update(:incomplete_binding => Expression[1])
227
- end
228
- end
229
-
230
203
  # patch a forward binding from the backtrace binding
231
204
  def fix_fwdemu_binding(di, fbd)
232
205
  case di.opcode.name
@@ -26,7 +26,7 @@ class Z80 < CPU
26
26
  @i = i
27
27
  end
28
28
 
29
- def symbolic(orig=nil) ; to_s.to_sym ; end
29
+ def symbolic(di=nil) ; to_s.to_sym ; end
30
30
 
31
31
  def self.from_str(s)
32
32
  raise "Bad name #{s.inspect}" if not x = @s_to_i[s]
@@ -43,11 +43,11 @@ class Z80 < CPU
43
43
  @sz = sz
44
44
  end
45
45
 
46
- def symbolic(orig)
46
+ def symbolic(di=nil)
47
47
  p = nil
48
48
  p = Expression[p, :+, @base.symbolic] if base
49
49
  p = Expression[p, :+, @offset] if offset
50
- Indirection[p.reduce, @sz, orig]
50
+ Indirection[p.reduce, @sz, (di.address if di)]
51
51
  end
52
52
  end
53
53
 
@@ -24,17 +24,6 @@ class Z80
24
24
  end
25
25
  end
26
26
 
27
- def render_instruction(i)
28
- r = []
29
- r << i.opname
30
- if not i.args.empty?
31
- r << ' '
32
- i.args.each { |a_| r << a_ << ', ' }
33
- r.pop
34
- end
35
- r
36
- end
37
-
38
27
  def gui_hilight_word_regexp_init
39
28
  ret = {}
40
29
 
@@ -16,7 +16,7 @@ class Debugger
16
16
  :state,
17
17
  # type: type of breakpoint (:bpx = soft, :hwbp = hard, :bpm = memory)
18
18
  :type,
19
- # Expression if this is a conditionnal bp
19
+ # Expression if this is a conditional bp
20
20
  # may be a Proc, String or Expression, evaluated every time the breakpoint hits
21
21
  # if it returns 0 or false, the breakpoint is ignored
22
22
  :condition,
@@ -460,7 +460,7 @@ class Debugger
460
460
  # TODO make it so this doesn't interfere with other 'real' disassembler later commands, eg disassemble() or disassemble_fast_deep()
461
461
  # (right now, when they see the block already present they stop all processing)
462
462
  def init_bpx_disassemble(addr)
463
- @disassembler.disassemble_fast_block(addr)
463
+ @disassembler.disassemble_fast(addr)
464
464
  @disassembler.di_at(addr)
465
465
  end
466
466
 
@@ -612,10 +612,10 @@ class Debugger
612
612
  # due to a side-effect of the debugger (bpx with wrong condition etc)
613
613
  # returns nil if the execution should be avoided (just deleted the dead thread/process)
614
614
  def check_pre_run(run_m, *run_a)
615
- if @dead_process
615
+ if @dead_process ||= nil
616
616
  del_pid
617
617
  return
618
- elsif @dead_thread
618
+ elsif @dead_thread ||= nil
619
619
  del_tid
620
620
  return
621
621
  elsif @state == :running
@@ -894,7 +894,7 @@ class Debugger
894
894
 
895
895
  # checks if @breakpoint_cause is valid, or was obsoleted by the user changing pc
896
896
  def check_breakpoint_cause
897
- if bp = @breakpoint_cause and
897
+ if bp = breakpoint_cause and
898
898
  (bp.type == :bpx or (bp.type == :hwbp and bp.internal[:type] == :x)) and
899
899
  pc != bp.address
900
900
  bp = @breakpoint_cause = nil
@@ -1274,7 +1274,7 @@ class Debugger
1274
1274
  if i.kind_of? Indirection and p = i.pointer.reduce and p.kind_of? ::Integer
1275
1275
  i.len ||= @cpu.size/8
1276
1276
  p &= (1 << @cpu.size) - 1 if p < 0
1277
- Expression.decode_imm(@memory, i.len, @cpu, p)
1277
+ @memory.decode_imm(p, i.len, @cpu)
1278
1278
  end
1279
1279
  }
1280
1280
  end
@@ -1290,11 +1290,11 @@ class Debugger
1290
1290
  if arg1
1291
1291
  arg0 = resolve_expr(arg0) if not arg0.kind_of? ::Integer
1292
1292
  arg1 = resolve_expr(arg1) if not arg1.kind_of? ::Integer
1293
- @memory[arg0, arg1].to_str
1293
+ (@memory[arg0, arg1] || '').to_str
1294
1294
  elsif arg0.kind_of? ::Range
1295
1295
  arg0.begin = resolve_expr(arg0.begin) if not arg0.begin.kind_of? ::Integer # cannot happen, invalid ruby Range
1296
1296
  arg0.end = resolve_expr(arg0.end) if not arg0.end.kind_of? ::Integer
1297
- @memory[arg0].to_str
1297
+ (@memory[arg0] || '').to_str
1298
1298
  else
1299
1299
  get_reg_value(arg0)
1300
1300
  end
@@ -1442,4 +1442,39 @@ class Debugger
1442
1442
  s.length == len ? s : (s = @memory[addr, len] ? s.to_str : nil)
1443
1443
  end
1444
1444
  end
1445
+
1446
+ class CPU
1447
+ # return the CPU register used to store the current instruction pointer
1448
+ def dbg_register_pc
1449
+ @dbg_register_pc ||= :pc
1450
+ end
1451
+
1452
+ # return the list of CPU registers
1453
+ def dbg_register_list
1454
+ @dbg_register_list ||= [dbg_register_pc]
1455
+ end
1456
+
1457
+ # return the list of flags for the CPU
1458
+ def dbg_flag_list
1459
+ @dbg_flag_list ||= []
1460
+ end
1461
+
1462
+ # return a hash with register name => register size in bits
1463
+ def dbg_register_size
1464
+ @dbg_register_size ||= Hash.new(@size)
1465
+ end
1466
+
1467
+ # returns true if stepover is different from stepinto for this instruction
1468
+ def dbg_need_stepover(dbg, addr, di)
1469
+ di and di.opcode.props[:saveip]
1470
+ end
1471
+
1472
+ # activate a software breakpoint
1473
+ def dbg_enable_bp(dbg, bp)
1474
+ end
1475
+
1476
+ # deactivate a software breakpoint
1477
+ def dbg_disable_bp(dbg, bp)
1478
+ end
1479
+ end
1445
1480
  end
@@ -17,16 +17,22 @@ class Indirection < ExpressionType
17
17
  alias pointer target
18
18
  alias pointer= target=
19
19
  # length in bytes of data referenced
20
- attr_accessor :len
20
+ attr_reader :len
21
21
  # address of the instruction who generated the indirection
22
22
  attr_accessor :origin
23
23
 
24
24
  def initialize(target, len, origin)
25
- @target, @len, @origin = target, len, origin
25
+ @target, @origin = target, origin
26
+ self.len = len
26
27
  end
27
28
 
28
- def reduce_rec
29
- ptr = Expression[@target.reduce]
29
+ def len=(len)
30
+ @len = len
31
+ @max_bits_mask ||= (1 << (len*8)) - 1 if len.kind_of?(::Integer)
32
+ end
33
+
34
+ def reduce_rec(cb=nil)
35
+ ptr = Expression[@target.reduce(&cb)]
30
36
  (ptr == Expression::Unknown) ? ptr : Indirection.new(ptr, @len, @origin)
31
37
  end
32
38
 
@@ -180,10 +186,14 @@ class Expression
180
186
  end
181
187
 
182
188
  class CPU
189
+ def bin_lookaside
190
+ @bin_lookaside ||= build_bin_lookaside
191
+ end
192
+
183
193
  # decodes the instruction at edata.ptr, mapped at virtual address off
184
194
  # returns a DecodedInstruction or nil
185
195
  def decode_instruction(edata, addr)
186
- @bin_lookaside ||= build_bin_lookaside
196
+ bin_lookaside
187
197
  di = decode_findopcode edata if edata.ptr <= edata.length
188
198
  di.address = addr if di
189
199
  di = decode_instr_op(edata, di) if di
@@ -207,6 +217,18 @@ class CPU
207
217
  di
208
218
  end
209
219
 
220
+ # return a symbolic representation of an instruction argument (eg Reg[0] => :eax)
221
+ def symbolic(arg, di=nil)
222
+ case arg
223
+ when ExpressionType
224
+ arg
225
+ when Integer
226
+ Expression[arg]
227
+ else
228
+ arg.symbolic(di)
229
+ end
230
+ end
231
+
210
232
  # number of instructions following a jump that are still executed
211
233
  def delay_slot(di=nil)
212
234
  0
@@ -216,24 +238,50 @@ class CPU
216
238
  DecodedFunction.new
217
239
  end
218
240
 
241
+ # hash opcode_name => lambda { |dasm, di, *symbolic_args| instr_binding }
242
+ def backtrace_binding
243
+ @backtrace_binding ||= init_backtrace_binding
244
+ end
245
+ def backtrace_binding=(b) @backtrace_binding = b end
246
+
247
+ # return the backtrace binding for a specific di
248
+ def get_backtrace_binding(di)
249
+ a = di.instruction.args.map { |arg| symbolic(arg, di) }
250
+
251
+ if binding = backtrace_binding[di.opcode.name]
252
+ binding[di, *a]
253
+ else
254
+ puts "unhandled instruction to backtrace: #{di}" if $VERBOSE
255
+ {:incomplete_binding => Expression[1]}
256
+ end
257
+ end
258
+
219
259
  # return something like backtrace_binding in the forward direction
220
260
  # set pc_reg to some reg name (eg :pc) to include effects on the instruction pointer
221
- def get_fwdemu_binding(di, pc_reg=nil)
222
- fdi = di.backtrace_binding ||= get_backtrace_binding(di)
223
- fdi = fix_fwdemu_binding(di, fdi)
261
+ # pass a debugger to allow reading the context and actually resolve the next pc in case of conditional jumps
262
+ def get_fwdemu_binding(di, pc_reg=nil, dbg_ctx=nil)
263
+ fbd = di.backtrace_binding ||= get_backtrace_binding(di)
264
+ fbd = fix_fwdemu_binding(di, fbd)
224
265
  if pc_reg
266
+ n_a = Expression[pc_reg, :+, di.bin_length]
225
267
  if di.opcode.props[:setip]
226
- xr = get_xrefs_x(nil, di)
227
- if xr and xr.length == 1
228
- fdi[pc_reg] = xr[0]
268
+ xr = get_xrefs_x(nil, di).to_a
269
+ xr |= [n_a] if not di.opcode.props[:stopexec]
270
+ if xr.length == 1
271
+ fbd[pc_reg] = xr[0]
229
272
  else
230
- fdi[:incomplete_binding] = Expression[1]
273
+ dbg_resolve_pc(di, fbd, pc_reg, dbg_ctx)
231
274
  end
232
275
  else
233
- fdi[pc_reg] = Expression[pc_reg, :+, di.bin_length]
276
+ fbd[pc_reg] = Expression[pc_reg, :+, di.bin_length]
234
277
  end
235
278
  end
236
- fdi
279
+ fbd
280
+ end
281
+
282
+ # resolve the program counter following a conditional jump using a debugging context
283
+ def dbg_resolve_pc(di, fbd, pc_reg, dbg_ctx)
284
+ fbd[:incomplete_binding] = Expression[1]
237
285
  end
238
286
 
239
287
  # patch a forward binding from the backtrace binding
@@ -13,24 +13,19 @@ class C::Variable; attr_accessor :stackoff; end
13
13
  class C::Block; attr_accessor :decompdata; end
14
14
  class DecodedFunction; attr_accessor :decompdata; end
15
15
 
16
- class CPU
17
- def decompile_check_abi(dcmp, entry, func)
18
- end
19
- end
20
-
21
16
  class Decompiler
22
- # TODO add methods to C::CExpr
23
- AssignOp = [:'=', :'+=', :'-=', :'*=', :'/=', :'%=', :'^=', :'&=', :'|=', :'>>=', :'<<=', :'++', :'--']
24
-
25
17
  attr_accessor :dasm, :c_parser
26
- attr_accessor :forbid_optimize_dataflow, :forbid_optimize_code, :forbid_decompile_ifwhile, :forbid_decompile_types, :forbid_optimize_labels
18
+ attr_accessor :forbid_optimize_dataflow, :forbid_optimize_code, :forbid_decompile_ifwhile, :forbid_decompile_types, :forbid_optimize_labels, :forbid_all_optimizations
27
19
  # recursive flag: for each subfunction, recurse is decremented, when 0 only the prototype is decompiled, when <0 nothing is done
28
20
  attr_accessor :recurse
29
21
 
22
+ def disassembler ; dasm ; end
23
+
30
24
  def initialize(dasm, cp = dasm.c_parser)
31
25
  @dasm = dasm
32
26
  @recurse = 1/0.0 # Infinity
33
27
  @c_parser = cp || @dasm.cpu.new_cparser
28
+ @dasm.cpu.decompile_init(self) if @dasm.cpu.respond_to?(:decompile_init)
34
29
  end
35
30
 
36
31
  # decompile recursively function from an entrypoint, then perform global optimisation (static vars, ...)
@@ -103,6 +98,7 @@ class Decompiler
103
98
  myblocks = listblocks_func(entry)
104
99
 
105
100
  # [esp+8] => [:frameptr-12]
101
+ # TODO slow
106
102
  makestackvars entry, myblocks.map { |b, to| @dasm.decoded[b].block }
107
103
 
108
104
  # find registry dependencies between blocks
@@ -110,24 +106,31 @@ class Decompiler
110
106
 
111
107
  scope = func.initializer = C::Block.new(@c_parser.toplevel)
112
108
  if df = @dasm.function[entry]
113
- scope.decompdata = df.decompdata ||= {:stackoff_type => {}, :stackoff_name => {}}
109
+ scope.decompdata = df.decompdata ||= {:unalias_type => {}, :unalias_name => {}}
114
110
  else
115
- scope.decompdata ||= {:stackoff_type => {}, :stackoff_name => {}}
111
+ scope.decompdata ||= {:unalias_type => {}, :unalias_name => {}}
116
112
  end
117
113
 
118
114
  # di blocks => raw c statements, declare variables
119
115
  @dasm.cpu.decompile_blocks(self, myblocks, deps, func)
116
+ puts "dcmp debug #{func.name} {", scope, '}' if $DEBUG
117
+
118
+ return if forbid_all_optimizations
120
119
 
121
120
  simplify_goto(scope)
122
121
  namestackvars(scope)
123
122
  unalias_vars(scope, func)
124
123
  decompile_c_types(scope)
125
- optimize(scope)
124
+ optimize_code(scope)
125
+ optimize_vars(scope)
126
+ optimize_vars(scope) # 1st run may transform i = i+1 into i++ which second run may coalesce into if(i)
126
127
  remove_unreferenced_vars(scope)
128
+ decompile_c_types_again(scope)
127
129
  cleanup_var_decl(scope, func)
128
130
  if @recurse > 0
129
131
  decompile_controlseq(scope)
130
132
  optimize_vars(scope)
133
+ optimize_code(scope)
131
134
  optimize_ctrl(scope)
132
135
  optimize_vars(scope)
133
136
  remove_unreferenced_vars(scope)
@@ -143,7 +146,7 @@ class Decompiler
143
146
  scope.statements.pop
144
147
  else
145
148
  v = ret.value
146
- v = v.rexpr if v.kind_of? C::CExpression and not v.op and v.rexpr.kind_of? C::Typed
149
+ v = v.rexpr if v.kind_of?(C::CExpression) and not v.op and v.rexpr.kind_of?(C::Typed)
147
150
  func.type.type = v.type
148
151
  end
149
152
  end
@@ -156,21 +159,21 @@ class Decompiler
156
159
 
157
160
  # redecompile a function, redecompiles functions calling it if its prototype changed
158
161
  def redecompile(name)
159
- @c_parser.toplevel.statements.delete_if { |st| st.kind_of? C::Declaration and st.var.name == name }
162
+ @c_parser.toplevel.statements.delete_if { |st| st.kind_of?(C::Declaration) and st.var.name == name }
160
163
  oldvar = @c_parser.toplevel.symbol.delete name
161
164
 
162
165
  decompile_func(name)
163
166
 
164
- if oldvar and newvar = @c_parser.toplevel.symbol[name] and oldvar.type.kind_of? C::Function and newvar.type.kind_of? C::Function
167
+ if oldvar and newvar = @c_parser.toplevel.symbol[name] and oldvar.type.kind_of?(C::Function) and newvar.type.kind_of?(C::Function)
165
168
  o, n = oldvar.type, newvar.type
166
169
  if o.type != n.type or o.args.to_a.length != n.args.to_a.length or o.args.to_a.zip(n.args.to_a).find { |oa, na| oa.type != na.type }
167
170
  # XXX a may depend on b and c, and b may depend on c -> redecompile c twice
168
171
  # XXX if the dcmp is unstable, may also infinite loop on mutually recursive funcs..
169
172
  @c_parser.toplevel.statements.dup.each { |st|
170
- next if not st.kind_of? C::Declaration
173
+ next if not st.kind_of?(C::Declaration)
171
174
  next if not st.var.initializer
172
175
  next if st.var.name == name
173
- next if not walk_ce(st) { |ce| break true if ce.op == :funcall and ce.lexpr.kind_of? C::Variable and ce.lexpr.name == name }
176
+ next if not walk_ce(st) { |ce| break true if ce.op == :funcall and ce.lexpr.kind_of?(C::Variable) and ce.lexpr.name == name }
174
177
  redecompile(st.var.name)
175
178
  }
176
179
  end
@@ -181,38 +184,39 @@ class Decompiler
181
184
  addr = @dasm.normalize(addr)
182
185
 
183
186
  # (almost) NULL ptr
184
- return if addr.kind_of? Integer and addr >= 0 and addr < 32
187
+ return if addr.kind_of?(Integer) and addr >= 0 and addr < 32
185
188
 
186
189
  # check preceding structure we're hitting
187
190
  # TODO check what we step over when defining a new static struct
188
191
  0x100.times { |i_|
189
192
  next if not n = @dasm.get_label_at(addr-i_)
190
193
  next if not v = @c_parser.toplevel.symbol[n]
191
- next if not v.type.pointer? or not v.type.pointed.untypedef.kind_of? C::Union
194
+ next if not v.type.pointer? or not v.type.pointed.untypedef.kind_of?(C::Union)
192
195
  break if i_ == 0 # XXX it crashes later if we dont break here
193
196
  next if sizeof(v.type.pointed) <= i_
194
197
  return structoffset(v.type.pointed.untypedef, C::CExpression[v], i_, nil)
195
198
  }
196
199
 
197
200
  ptype = type.pointed.untypedef if type.pointer?
198
- if ptype.kind_of? C::Function
201
+ if ptype.kind_of?(C::Function)
199
202
  name = @dasm.auto_label_at(addr, 'sub', 'xref', 'byte', 'word', 'dword', 'unk')
200
203
  if @dasm.get_section_at(addr) and @recurse > 0
201
204
  puts "found function pointer to #{name}" if $VERBOSE
202
205
  @dasm.disassemble(addr) if not @dasm.decoded[addr] # TODO disassemble_fast ?
203
206
  f = @dasm.function[addr] ||= DecodedFunction.new
204
207
  # TODO detect thunks (__noreturn)
205
- f.decompdata ||= { :stackoff_type => {}, :stackoff_name => {} }
206
- if not s = @c_parser.toplevel.symbol[name] or not s.initializer or not s.type.untypedef.kind_of? C::Function
208
+ f.decompdata ||= { :unalias_type => {}, :unalias_name => {} }
209
+ if not s = @c_parser.toplevel.symbol[name] or not s.initializer or not s.type.untypedef.kind_of?(C::Function)
207
210
  os = @c_parser.toplevel.symbol.delete name
208
- @c_parser.toplevel.statements.delete_if { |ts| ts.kind_of? C::Declaration and ts.var.name == name }
209
- aoff = 1
210
- ptype.args.to_a.each { |a|
211
- aoff = (aoff + @c_parser.typesize[:ptr] - 1) / @c_parser.typesize[:ptr] * @c_parser.typesize[:ptr]
212
- f.decompdata[:stackoff_type][aoff] ||= a.type
213
- f.decompdata[:stackoff_name][aoff] ||= a.name if a.name
214
- aoff += sizeof(a) # ary ?
215
- }
211
+ @c_parser.toplevel.statements.delete_if { |ts| ts.kind_of?(C::Declaration) and ts.var.name == name }
212
+ #aoff = 1
213
+ #ptype.args.to_a.each { |a|
214
+ # TODO
215
+ #aoff = (aoff + @c_parser.typesize[:ptr] - 1) / @c_parser.typesize[:ptr] * @c_parser.typesize[:ptr]
216
+ #f.decompdata[:unalias_type][aoff] ||= a.type
217
+ #f.decompdata[:unalias_name][aoff] ||= a.name if a.name
218
+ #aoff += sizeof(a) # ary ?
219
+ #}
216
220
  decompile_func_rec(addr)
217
221
  s = @c_parser.toplevel.symbol[name]
218
222
  walk_ce([@c_parser.toplevel, scope]) { |ce|
@@ -230,7 +234,7 @@ class Decompiler
230
234
  when 4; 'dword'
231
235
  else 'unk'
232
236
  end
233
- name = 'stru' if ptype.kind_of? C::Union
237
+ name = 'stru' if ptype.kind_of?(C::Union)
234
238
  name = @dasm.auto_label_at(addr, name, 'xref', 'byte', 'word', 'dword', 'unk', 'stru')
235
239
 
236
240
  if not var = @c_parser.toplevel.symbol[name]
@@ -240,28 +244,28 @@ class Decompiler
240
244
  @c_parser.toplevel.symbol[var.name] = var
241
245
  @c_parser.toplevel.statements << C::Declaration.new(var)
242
246
  end
243
- if ptype.kind_of? C::Union and type.pointer? and s = @dasm.get_section_at(name) and s[0].ptr < s[0].length
247
+ if ptype.kind_of?(C::Union) and type.pointer? and s = @dasm.get_section_at(name) and s[0].ptr < s[0].length
244
248
  # TODO struct init, array, fptrs..
245
- elsif type.pointer? and not type.pointed.untypedef.kind_of? C::Function and s = @dasm.get_section_at(name) and s[0].ptr < s[0].length and
246
- [1, 2, 4].include? tsz and (not var.type.pointer? or sizeof(var.type.pointed) != sizeof(type.pointed) or not var.initializer)
249
+ elsif type.pointer? and not type.pointed.untypedef.kind_of?(C::Function) and s = @dasm.get_section_at(name) and s[0].ptr < s[0].length and
250
+ [1, 2, 4].include?(tsz) and (not var.type.pointer? or sizeof(var.type.pointed) != sizeof(type.pointed) or not var.initializer)
247
251
  # TODO do not overlap other statics (but labels may refer to elements of the array...)
248
252
  data = (0..256).map {
249
253
  v = s[0].decode_imm("u#{tsz*8}".to_sym, @dasm.cpu.endianness)
250
- v = decompile_cexpr(v, @c_parser.toplevel) if v.kind_of? Expression # relocation
254
+ v = decompile_cexpr(v, @c_parser.toplevel) if v.kind_of?(Expression) # relocation
251
255
  v
252
256
  }
253
257
  var.initializer = data.map { |v| C::CExpression[v, C::BaseType.new(:int)] } unless (data - [0]).empty?
254
- if (tsz == 1 or tsz == 2) and eos = data.index(0) and (0..3).all? { |i| data[i] >= 0x20 and data[i] < 0x7f } # printable str
258
+ if (tsz == 1 or tsz == 2) and eos = data.index(0) and ((0..3).all? { |i| data[i] >= 0x20 and data[i] < 0x7f } or ptype.to_s == '(char)') # printable str
255
259
  # XXX 0x80 with ruby1.9...
256
260
  var.initializer = C::CExpression[data[0, eos].pack('C*'), C::Pointer.new(ptype)] rescue nil
257
261
  end
258
- if var.initializer.kind_of? ::Array and i = var.initializer.first and i.kind_of? C::CExpression and not i.op and i.rexpr.kind_of? C::Variable and
259
- i.rexpr.type.kind_of? C::Function and not @dasm.get_section_at(@dasm.normalize(i.rexpr.name)) # iat_ExternalFunc
262
+ if var.initializer.kind_of?(::Array) and i = var.initializer.first and i.kind_of?(C::CExpression) and not i.op and i.rexpr.kind_of?(C::Variable) and
263
+ i.rexpr.type.kind_of?(C::Function) and not @dasm.get_section_at(@dasm.normalize(i.rexpr.name)) # iat_ExternalFunc
260
264
  i.type = i.rexpr.type
261
265
  type = var.type = C::Array.new(C::Pointer.new(i.type))
262
266
  var.initializer = [i]
263
267
  end
264
- var.initializer = nil if var.initializer.kind_of? ::Array and not type.untypedef.kind_of? C::Array
268
+ var.initializer = nil if var.initializer.kind_of?(::Array) and not type.untypedef.kind_of?(C::Array)
265
269
  end
266
270
 
267
271
  # TODO patch existing references to addr ? (or would they have already triggered new_global_var?)
@@ -285,7 +289,7 @@ class Decompiler
285
289
  next if type == :indirect
286
290
  ta = dasm.normalize ta
287
291
  if type != :subfuncret and not @dasm.function[ta] and
288
- (not @dasm.function[entry] or @autofuncs.include? entry) and
292
+ (not @dasm.function[entry] or @autofuncs.include?(entry)) and
289
293
  di.block.list.last.opcode.props[:saveip]
290
294
  # possible noreturn function
291
295
  # XXX call $+5; pop eax
@@ -317,7 +321,7 @@ class Decompiler
317
321
  return expr if n == Expression::Unknown
318
322
  n = Expression[n].reduce_rec
319
323
  n = @dasm.get_label_at(n) || n
320
- n = $1 if n.kind_of? ::String and n =~ /^thunk_(.*)/
324
+ n = $1 if n.kind_of?(::String) and n =~ /^thunk_(.*)/
321
325
  n
322
326
  else
323
327
  expr
@@ -329,27 +333,29 @@ class Decompiler
329
333
  blockstart = nil
330
334
  cache_di = nil
331
335
  cache = {} # [i_s, e, type] => backtrace
332
- tovar = lambda { |di, e, i_s|
336
+ @decomp_mkstackvars_terminals ||= [:frameptr]
337
+ tovar = lambda { |di, e, i_s_c|
338
+ i_s = (i_s_c > 0)
333
339
  case e
334
- when Expression; Expression[tovar[di, e.lexpr, i_s], e.op, tovar[di, e.rexpr, i_s]].reduce
335
- when Indirection; Indirection[tovar[di, e.target, i_s], e.len, e.origin]
340
+ when Expression; Expression[tovar[di, e.lexpr, i_s_c], e.op, tovar[di, e.rexpr, i_s_c]].reduce
341
+ when Indirection; Indirection[tovar[di, e.target, i_s_c-1], e.len, e.origin]
336
342
  when :frameptr; e
337
343
  when ::Symbol
338
344
  cache.clear if cache_di != di ; cache_di = di
339
345
  vals = cache[[e, i_s, 0]] ||= @dasm.backtrace(e, di.address, :snapshot_addr => blockstart,
340
- :include_start => i_s, :no_check => true, :terminals => [:frameptr])
346
+ :include_start => i_s, :no_check => true, :terminals => @decomp_mkstackvars_terminals)
341
347
  # backtrace only to blockstart first
342
- if vals.length == 1 and ee = vals.first and ee.kind_of? Expression and (ee == Expression[:frameptr] or
343
- (ee.lexpr == :frameptr and ee.op == :+ and ee.rexpr.kind_of? ::Integer) or
344
- (not ee.lexpr and ee.op == :+ and ee.rexpr.kind_of? Indirection and eep = ee.rexpr.pointer and
345
- (eep == Expression[:frameptr] or (eep.lexpr == :frameptr and eep.op == :+ and eep.rexpr.kind_of? ::Integer))))
348
+ if vals.length == 1 and ee = vals.first and ee.kind_of?(Expression) and (ee == Expression[:frameptr] or
349
+ (ee.lexpr == :frameptr and ee.op == :+ and ee.rexpr.kind_of?(::Integer)) or
350
+ (not ee.lexpr and ee.op == :+ and ee.rexpr.kind_of?(Indirection) and eep = ee.rexpr.pointer and
351
+ (eep == Expression[:frameptr] or (eep.lexpr == :frameptr and eep.op == :+ and eep.rexpr.kind_of?(::Integer)))))
346
352
  ee
347
353
  else
348
354
  # fallback on full run (could restart from blockstart with ee, but may reevaluate addr_binding..
349
355
  vals = cache[[e, i_s, 1]] ||= @dasm.backtrace(e, di.address, :snapshot_addr => funcstart,
350
- :include_start => i_s, :no_check => true, :terminals => [:frameptr])
351
- if vals.length == 1 and ee = vals.first and (ee.kind_of? Expression and (ee == Expression[:frameptr] or
352
- (ee.lexpr == :frameptr and ee.op == :+ and ee.rexpr.kind_of? ::Integer)))
356
+ :include_start => i_s, :no_check => true, :terminals => @decomp_mkstackvars_terminals)
357
+ if vals.length == 1 and ee = vals.first and (ee.kind_of?(Expression) and (ee == Expression[:frameptr] or
358
+ (ee.lexpr == :frameptr and ee.op == :+ and ee.rexpr.kind_of?(::Integer))))
353
359
  ee
354
360
  else e
355
361
  end
@@ -366,9 +372,9 @@ class Decompiler
366
372
  bd = di.backtrace_binding ||= @dasm.cpu.get_backtrace_binding(di)
367
373
  newbd = repl_bind[di] = {}
368
374
  bd.each { |k, v|
369
- k = tovar[di, k, true] if k.kind_of? Indirection
370
- next if k == Expression[:frameptr] or (k.kind_of? Expression and k.lexpr == :frameptr and k.op == :+ and k.rexpr.kind_of? ::Integer)
371
- newbd[k] = tovar[di, v, false]
375
+ k = tovar[di, k, 2] if k.kind_of?(Indirection)
376
+ next if k == Expression[:frameptr] or (k.kind_of?(Expression) and k.lexpr == :frameptr and k.op == :+ and k.rexpr.kind_of?( ::Integer))
377
+ newbd[k] = tovar[di, v, 0]
372
378
  }
373
379
  }
374
380
  }
@@ -391,9 +397,9 @@ class Decompiler
391
397
  def decompile_cexpr(e, scope, itype=nil)
392
398
  case e
393
399
  when Expression
394
- if e.op == :'=' and e.lexpr.kind_of? ::String and e.lexpr =~ /^dummy_metasm_/
400
+ if e.op == :'=' and e.lexpr.kind_of?(::String) and e.lexpr =~ /^dummy_metasm_/
395
401
  decompile_cexpr(e.rexpr, scope, itype)
396
- elsif e.op == :+ and e.rexpr.kind_of? ::Integer and e.rexpr < 0
402
+ elsif e.op == :+ and e.rexpr.kind_of?(::Integer) and e.rexpr < 0
397
403
  decompile_cexpr(Expression[e.lexpr, :-, -e.rexpr], scope, itype)
398
404
  elsif e.lexpr
399
405
  a = decompile_cexpr(e.lexpr, scope, itype)
@@ -414,7 +420,7 @@ class Decompiler
414
420
  end
415
421
  itype = C::Pointer.new(bt)
416
422
  p = decompile_cexpr(e.target, scope, itype)
417
- p = C::CExpression[[p], itype] if not p.type.kind_of? C::Pointer
423
+ p = C::CExpression[[p], itype]
418
424
  C::CExpression[:*, p]
419
425
  when ::Integer
420
426
  C::CExpression[e]
@@ -442,17 +448,17 @@ class Decompiler
442
448
 
443
449
  # simplify goto -> goto / goto -> return
444
450
  def simplify_goto(scope, keepret = false)
445
- if not keepret and scope.statements[-1].kind_of? C::Return and not scope.statements[-2].kind_of? C::Label
451
+ if not keepret and scope.statements[-1].kind_of?(C::Return) and not scope.statements[-2].kind_of?(C::Label)
446
452
  scope.statements.insert(-2, C::Label.new("ret_label"))
447
453
  end
448
454
 
449
455
  jumpto = {}
450
456
  walk(scope) { |s|
451
- next if not s.kind_of? C::Block
457
+ next if not s.kind_of?(C::Block)
452
458
  s.statements.each_with_index { |ss, i|
453
459
  case ss
454
460
  when C::Goto, C::Return
455
- while l = s.statements[i -= 1] and l.kind_of? C::Label
461
+ while l = s.statements[i -= 1] and l.kind_of?(C::Label)
456
462
  jumpto[l.name] = ss
457
463
  end
458
464
  end
@@ -464,11 +470,11 @@ class Decompiler
464
470
  when C::Goto
465
471
  if jumpto[s.target]
466
472
  r = jumpto[s.target].dup
467
- r.value = r.value.deep_dup if r.kind_of? C::Return and r.value.kind_of? C::CExpression
473
+ r.value = r.value.deep_dup if r.kind_of?(C::Return) and r.value.kind_of?(C::CExpression)
468
474
  r
469
475
  end
470
476
  when C::Return
471
- if not keepret and scope.statements[-1].kind_of? C::Return and s.value == scope.statements[-1].value and s != scope.statements[-1]
477
+ if not keepret and scope.statements[-1].kind_of?(C::Return) and s.value == scope.statements[-1].value and s != scope.statements[-1]
472
478
  C::Goto.new(scope.statements[-2].name)
473
479
  end
474
480
  end
@@ -493,7 +499,7 @@ class Decompiler
493
499
  remove_labels(scope)
494
500
 
495
501
  walk(scope) { |s|
496
- next if not s.kind_of? C::Block
502
+ next if not s.kind_of?(C::Block)
497
503
  del = false
498
504
  # remove dead code goto a; goto b; if (0) { z: bla; } => rm goto b
499
505
  s.statements.delete_if { |st|
@@ -508,10 +514,10 @@ class Decompiler
508
514
  }
509
515
  # if () { goto x; } x:
510
516
  s.statements.each_with_index { |ss, i|
511
- if ss.kind_of? C::If
517
+ if ss.kind_of?(C::If)
512
518
  t = ss.bthen
513
- t = t.statements.first if t.kind_of? C::Block
514
- if t.kind_of? C::Goto and s.statements[i+1].kind_of? C::Label and s.statements[i+1].name == t.target
519
+ t = t.statements.first if t.kind_of?(C::Block)
520
+ if t.kind_of?(C::Goto) and s.statements[i+1].kind_of?(C::Label) and s.statements[i+1].name == t.target
515
521
  ss.bthen = C::Block.new(scope)
516
522
  end
517
523
  end
@@ -548,8 +554,8 @@ class Decompiler
548
554
  e.each_with_index { |st, i|
549
555
  case st
550
556
  when C::While, C::DoWhile
551
- l1 = (e[i+1].name if e[i+1].kind_of? C::Label)
552
- l2 = (e[i-1].name if e[i-1].kind_of? C::Label)
557
+ l1 = (e[i+1].name if e[i+1].kind_of?(C::Label))
558
+ l2 = (e[i-1].name if e[i-1].kind_of?(C::Label))
553
559
  e[i].body = walk[st.body, l1, l2]
554
560
  else
555
561
  e[i] = walk[st, brk, cnt]
@@ -578,20 +584,20 @@ class Decompiler
578
584
  remove_labels(scope)
579
585
 
580
586
  # while (1) { a; if(b) { c; return; }; d; } => while (1) { a; if (b) break; d; } c;
581
- while st = scope.statements.last and st.kind_of? C::While and st.test.kind_of? C::CExpression and
582
- not st.test.op and st.test.rexpr == 1 and st.body.kind_of? C::Block
587
+ while st = scope.statements.last and st.kind_of?(C::While) and st.test.kind_of?(C::CExpression) and
588
+ not st.test.op and st.test.rexpr == 1 and st.body.kind_of?(C::Block)
583
589
  break if not i = st.body.statements.find { |ist|
584
- ist.kind_of? C::If and not ist.belse and ist.bthen.kind_of? C::Block and ist.bthen.statements.last.kind_of? C::Return
590
+ ist.kind_of?(C::If) and not ist.belse and ist.bthen.kind_of?(C::Block) and ist.bthen.statements.last.kind_of?(C::Return)
585
591
  }
586
- walk(i.bthen.statements) { |sst| sst.outer = i.bthen.outer if sst.kind_of? C::Block and sst.outer == i.bthen }
592
+ walk(i.bthen.statements) { |sst| sst.outer = i.bthen.outer if sst.kind_of?(C::Block) and sst.outer == i.bthen }
587
593
  scope.statements.concat i.bthen.statements
588
594
  i.bthen = C::Break.new
589
595
  end
590
596
 
591
597
  patch_test = lambda { |ce|
592
- ce = ce.rexpr if ce.kind_of? C::CExpression and ce.op == :'!'
598
+ ce = ce.rexpr if ce.kind_of?(C::CExpression) and ce.op == :'!'
593
599
  # if (a+1) => if (a != -1)
594
- if ce.kind_of? C::CExpression and (ce.op == :+ or ce.op == :-) and ce.rexpr.kind_of? C::CExpression and not ce.rexpr.op and ce.rexpr.rexpr.kind_of? ::Integer and ce.lexpr
600
+ if ce.kind_of?(C::CExpression) and (ce.op == :+ or ce.op == :-) and ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and ce.rexpr.rexpr.kind_of?(::Integer) and ce.lexpr
595
601
  ce.rexpr.rexpr = -ce.rexpr.rexpr if ce.op == :+
596
602
  ce.op = :'!='
597
603
  end
@@ -601,10 +607,10 @@ class Decompiler
601
607
  case ce
602
608
  when C::If
603
609
  patch_test[ce.test]
604
- if ce.bthen.kind_of? C::Block
610
+ if ce.bthen.kind_of?(C::Block)
605
611
  case ce.bthen.statements.length
606
612
  when 1
607
- walk(ce.bthen.statements) { |sst| sst.outer = ce.bthen.outer if sst.kind_of? C::Block and sst.outer == ce.bthen }
613
+ walk(ce.bthen.statements) { |sst| sst.outer = ce.bthen.outer if sst.kind_of?(C::Block) and sst.outer == ce.bthen }
608
614
  ce.bthen = ce.bthen.statements.first
609
615
  when 0
610
616
  if not ce.belse and i = ce.bthen.outer.statements.index(ce)
@@ -612,19 +618,19 @@ class Decompiler
612
618
  end
613
619
  end
614
620
  end
615
- if ce.belse.kind_of? C::Block and ce.belse.statements.length == 1
616
- walk(ce.belse.statements) { |sst| sst.outer = ce.belse.outer if sst.kind_of? C::Block and sst.outer == ce.belse }
621
+ if ce.belse.kind_of?(C::Block) and ce.belse.statements.length == 1
622
+ walk(ce.belse.statements) { |sst| sst.outer = ce.belse.outer if sst.kind_of?(C::Block) and sst.outer == ce.belse }
617
623
  ce.belse = ce.belse.statements.first
618
624
  end
619
625
  when C::While, C::DoWhile
620
626
  patch_test[ce.test]
621
- if ce.body.kind_of? C::Block
627
+ if ce.body.kind_of?(C::Block)
622
628
  case ce.body.statements.length
623
629
  when 1
624
- walk(ce.body.statements) { |sst| sst.outer = ce.body.outer if sst.kind_of? C::Block and sst.outer == ce.body }
630
+ walk(ce.body.statements) { |sst| sst.outer = ce.body.outer if sst.kind_of?(C::Block) and sst.outer == ce.body }
625
631
  ce.body = ce.body.statements.first
626
632
  when 0
627
- if ce.kind_of? C::DoWhile and i = ce.body.outer.statements.index(ce)
633
+ if ce.kind_of?(C::DoWhile) and i = ce.body.outer.statements.index(ce)
628
634
  ce = ce.body.outer.statements[i] = C::While.new(ce.test, ce.body)
629
635
  end
630
636
  ce.body = nil
@@ -632,14 +638,33 @@ class Decompiler
632
638
  end
633
639
  end
634
640
  }
641
+
642
+ walk(scope, false, true) { |ce|
643
+ # while (1) { a; if (b) break; } => do { a } while (!b);
644
+ if ce.kind_of?(C::While) and ce.test.kind_of?(C::CExpression) and not ce.test.op and ce.test.rexpr == 1 and ce.body.kind_of?(C::Block)
645
+ i = ce.body.statements.last
646
+ if i.kind_of?(C::If) and not i.belse and i.bthen.kind_of?(C::Break)
647
+ ce.body.statements.pop
648
+ next C::DoWhile.new(i.test.negate, ce.body)
649
+ end
650
+ end
651
+
652
+ # if (a) b = 1; else b = 2; => b = a ? 1 : 2
653
+ if ce.kind_of?(C::If) and ce.belse.kind_of?(C::CExpression) and ce.belse.op == :'=' and ce.belse.lexpr.kind_of?(C::Variable) and ce.bthen.kind_of?(C::CExpression) and ce.bthen.op == :'=' and ce.bthen.lexpr == ce.belse.lexpr
654
+ next C::CExpression[ce.bthen.lexpr, :'=', [ce.test, :'?:', [ce.bthen.rexpr, ce.belse.rexpr]]]
655
+ end
656
+ }
657
+
658
+ # TODO for (;;) {}
659
+
635
660
  walk(scope) { |ce|
636
- next if not ce.kind_of? C::Block
661
+ next if not ce.kind_of?(C::Block)
637
662
  st = ce.statements
638
663
  st.length.times { |n|
639
- while st[n].kind_of? C::If and st[n+1].kind_of? C::If and not st[n].belse and not st[n+1].belse and (
640
- (st[n].bthen.kind_of? C::Return and st[n+1].bthen.kind_of? C::Return and st[n].bthen.value == st[n+1].bthen.value) or
641
- (st[n].bthen.kind_of? C::Break and st[n+1].bthen.kind_of? C::Break) or
642
- (st[n].bthen.kind_of? C::Continue and st[n+1].bthen.kind_of? C::Continue))
664
+ while st[n].kind_of?(C::If) and st[n+1].kind_of?(C::If) and not st[n].belse and not st[n+1].belse and (
665
+ (st[n].bthen.kind_of?(C::Return) and st[n+1].bthen.kind_of?(C::Return) and st[n].bthen.value == st[n+1].bthen.value) or
666
+ (st[n].bthen.kind_of?(C::Break) and st[n+1].bthen.kind_of?(C::Break)) or
667
+ (st[n].bthen.kind_of?(C::Continue) and st[n+1].bthen.kind_of?(C::Continue)))
643
668
  # if (a) return x; if (b) return x; => if (a || b) return x;
644
669
  st[n].test = C::CExpression[st[n].test, :'||', st[n+1].test]
645
670
  st.delete_at(n+1)
@@ -659,19 +684,19 @@ class Decompiler
659
684
  inner_labels = ary.grep(C::Label).map { |l| l.name }
660
685
  while s = ary.shift
661
686
  # recurse if it's not the first run
662
- if s.kind_of? C::If
663
- s.bthen.statements = decompile_cseq_if(s.bthen.statements, s.bthen) if s.bthen.kind_of? C::Block
664
- s.belse.statements = decompile_cseq_if(s.belse.statements, s.belse) if s.belse.kind_of? C::Block
687
+ if s.kind_of?(C::If)
688
+ s.bthen.statements = decompile_cseq_if(s.bthen.statements, s.bthen) if s.bthen.kind_of?(C::Block)
689
+ s.belse.statements = decompile_cseq_if(s.belse.statements, s.belse) if s.belse.kind_of?(C::Block)
665
690
  end
666
691
 
667
692
  # if (a) goto x; if (b) goto x; => if (a || b) goto x;
668
- while s.kind_of? C::If and s.bthen.kind_of? C::Goto and not s.belse and ary.first.kind_of? C::If and ary.first.bthen.kind_of? C::Goto and
693
+ while s.kind_of?(C::If) and s.bthen.kind_of?(C::Goto) and not s.belse and ary.first.kind_of?(C::If) and ary.first.bthen.kind_of?(C::Goto) and
669
694
  not ary.first.belse and s.bthen.target == ary.first.bthen.target
670
695
  s.test = C::CExpression[s.test, :'||', ary.shift.test]
671
696
  end
672
697
 
673
698
  # if (a) goto x; b; x: => if (!a) { b; }
674
- if s.kind_of? C::If and s.bthen.kind_of? C::Goto and l = ary.grep(C::Label).find { |l_| l_.name == s.bthen.target }
699
+ if s.kind_of?(C::If) and s.bthen.kind_of?(C::Goto) and l = ary.grep(C::Label).find { |l_| l_.name == s.bthen.target }
675
700
  # if {goto l;} a; l: => if (!) {a;}
676
701
  s.test = C::CExpression.negate s.test
677
702
  s.bthen = C::Block.new(scope)
@@ -680,20 +705,20 @@ class Decompiler
680
705
  ary[0...ary.index(l)] = []
681
706
  end
682
707
 
683
- if s.kind_of? C::If and (s.bthen.kind_of? C::Block or s.bthen.kind_of? C::Goto)
684
- s.bthen = C::Block.new(scope, [s.bthen]) if s.bthen.kind_of? C::Goto
708
+ if s.kind_of?(C::If) and (s.bthen.kind_of?(C::Block) or s.bthen.kind_of?(C::Goto))
709
+ s.bthen = C::Block.new(scope, [s.bthen]) if s.bthen.kind_of?(C::Goto)
685
710
 
686
711
  bts = s.bthen.statements
687
712
 
688
713
  # if (a) if (b) { c; } => if (a && b) { c; }
689
- if bts.length == 1 and bts.first.kind_of? C::If and not bts.first.belse
714
+ if bts.length == 1 and bts.first.kind_of?(C::If) and not bts.first.belse
690
715
  s.test = C::CExpression[s.test, :'&&', bts.first.test]
691
716
  bts = bts.first.bthen
692
717
  bts = s.bthen.statements = bts.kind_of?(C::Block) ? bts.statements : [bts]
693
718
  end
694
719
 
695
720
  # if (a) { if (b) goto c; d; } c: => if (a && !b) { d; }
696
- if bts.first.kind_of? C::If and l = bts.first.bthen and (l = l.kind_of?(C::Block) ? l.statements.first : l) and l.kind_of? C::Goto and ary[0].kind_of? C::Label and l.target == ary[0].name
721
+ if bts.first.kind_of?(C::If) and l = bts.first.bthen and (l = l.kind_of?(C::Block) ? l.statements.first : l) and l.kind_of?(C::Goto) and ary[0].kind_of?(C::Label) and l.target == ary[0].name
697
722
  s.test = C::CExpression[s.test, :'&&', C::CExpression.negate(bts.first.test)]
698
723
  if e = bts.shift.belse
699
724
  bts.unshift e
@@ -701,18 +726,18 @@ class Decompiler
701
726
  end
702
727
 
703
728
  # if () { goto a; } a:
704
- if bts.last.kind_of? C::Goto and ary[0].kind_of? C::Label and bts.last.target == ary[0].name
729
+ if bts.last.kind_of?(C::Goto) and ary[0].kind_of?(C::Label) and bts.last.target == ary[0].name
705
730
  bts.pop
706
731
  end
707
732
 
708
733
  # if { a; goto outer; } b; return; => if (!) { b; return; } a; goto outer;
709
- if bts.last.kind_of? C::Goto and not inner_labels.include? bts.last.target and g = ary.find { |ss| ss.kind_of? C::Goto or ss.kind_of? C::Return } and g.kind_of? C::Return
734
+ if bts.last.kind_of?(C::Goto) and not inner_labels.include?(bts.last.target) and g = ary.find { |ss| ss.kind_of?(C::Goto) or ss.kind_of?(C::Return) } and g.kind_of?(C::Return)
710
735
  s.test = C::CExpression.negate s.test
711
736
  ary[0..ary.index(g)], bts[0..-1] = bts, ary[0..ary.index(g)]
712
737
  end
713
738
 
714
739
  # if { a; goto l; } b; l: => if {a;} else {b;}
715
- if bts.last.kind_of? C::Goto and l = ary.grep(C::Label).find { |l_| l_.name == bts.last.target }
740
+ if bts.last.kind_of?(C::Goto) and l = ary.grep(C::Label).find { |l_| l_.name == bts.last.target }
716
741
  s.belse = C::Block.new(scope)
717
742
  s.belse.statements = decompile_cseq_if(ary[0...ary.index(l)], s.belse)
718
743
  ary[0...ary.index(l)] = []
@@ -720,7 +745,7 @@ class Decompiler
720
745
  end
721
746
 
722
747
  # if { a; l: b; goto any;} c; goto l; => if { a; } else { c; } b; goto any;
723
- if not s.belse and (bts.last.kind_of? C::Goto or bts.last.kind_of? C::Return) and g = ary.grep(C::Goto).first and l = bts.grep(C::Label).find { |l_| l_.name == g.target }
748
+ if not s.belse and (bts.last.kind_of?(C::Goto) or bts.last.kind_of?(C::Return)) and g = ary.grep(C::Goto).first and l = bts.grep(C::Label).find { |l_| l_.name == g.target }
724
749
  s.belse = C::Block.new(scope)
725
750
  s.belse.statements = decompile_cseq_if(ary[0...ary.index(g)], s.belse)
726
751
  ary[0..ary.index(g)], bts[bts.index(l)..-1] = bts[bts.index(l)..-1], []
@@ -730,8 +755,8 @@ class Decompiler
730
755
  if s.belse
731
756
  bes = s.belse.statements
732
757
  while not bts.empty?
733
- if bts.last.kind_of? C::Label; ary.unshift bts.pop
734
- elsif bes.last.kind_of? C::Label; ary.unshift bes.pop
758
+ if bts.last.kind_of?(C::Label); ary.unshift bts.pop
759
+ elsif bes.last.kind_of?(C::Label); ary.unshift bes.pop
735
760
  elsif bts.last.to_s == bes.last.to_s; ary.unshift bes.pop ; bts.pop
736
761
  else break
737
762
  end
@@ -754,24 +779,24 @@ class Decompiler
754
779
  end
755
780
 
756
781
  # l1: l2: if () goto l1; goto l2; => if(!) goto l2; goto l1;
757
- if s.kind_of? C::If
782
+ if s.kind_of?(C::If)
758
783
  ls = s.bthen
759
- ls = ls.statements.last if ls.kind_of? C::Block
760
- if ls.kind_of? C::Goto
784
+ ls = ls.statements.last if ls.kind_of?(C::Block)
785
+ if ls.kind_of?(C::Goto)
761
786
  if li = inner_labels.index(ls.target)
762
787
  table = inner_labels
763
788
  else
764
- table = ary.map { |st| st.name if st.kind_of? C::Label }.compact.reverse
789
+ table = ary.map { |st| st.name if st.kind_of?(C::Label) }.compact.reverse
765
790
  li = table.index(ls.target) || table.length
766
791
  end
767
792
  g = ary.find { |ss|
768
- break if ss.kind_of? C::Return
769
- next if not ss.kind_of? C::Goto
793
+ break if ss.kind_of?(C::Return)
794
+ next if not ss.kind_of?(C::Goto)
770
795
  table.index(ss.target).to_i > li
771
796
  }
772
797
  if g
773
798
  s.test = C::CExpression.negate s.test
774
- if not s.bthen.kind_of? C::Block
799
+ if not s.bthen.kind_of?(C::Block)
775
800
  ls = C::Block.new(scope)
776
801
  ls.statements << s.bthen
777
802
  s.bthen = ls
@@ -790,81 +815,96 @@ class Decompiler
790
815
  return if forbid_decompile_ifwhile
791
816
 
792
817
  # find the next instruction that is not a label
793
- ni = lambda { |l| ary[ary.index(l)..-1].find { |s| not s.kind_of? C::Label } }
794
-
795
- # TODO XXX get rid of #index
796
- finished = false ; while not finished ; finished = true # 1.9 does not support 'retry'
797
- ary.each { |s|
818
+ ni = lambda { |li| (li..ary.length).find { |ni_| not ary[ni_].kind_of?(C::Label) } }
819
+
820
+ finished = false; while not finished; finished = true # ruby1.9 does not support 'retry'
821
+ i = 0
822
+ while i < ary.length
823
+ si = i
824
+ s = ary[si]
825
+ i += 1
798
826
  case s
799
827
  when C::Label
800
- if ss = ni[s] and ss.kind_of? C::If and not ss.belse and ss.bthen.kind_of? C::Block
801
- if ss.bthen.statements.last.kind_of? C::Goto and ss.bthen.statements.last.target == s.name
828
+ if ssi = ni[si] and ss = ary[ssi] and ss.kind_of?(C::If) and not ss.belse and ss.bthen.kind_of?(C::Block)
829
+ if ss.bthen.statements.last.kind_of?(C::Goto) and ss.bthen.statements.last.target == s.name
830
+ # l: if (a) { b; goto l; } => while(a) { b; }
802
831
  ss.bthen.statements.pop
803
- if l = ary[ary.index(ss)+1] and l.kind_of? C::Label
804
- ss.bthen.statements.grep(C::If).each { |i|
805
- i.bthen = C::Break.new if i.bthen.kind_of? C::Goto and i.bthen.target == l.name
832
+ if l = ary[ssi+1] and l.kind_of?(C::Label)
833
+ ss.bthen.statements.grep(C::If).each { |it|
834
+ it.bthen = C::Break.new if it.bthen.kind_of?(C::Goto) and it.bthen.target == l.name
806
835
  }
807
836
  end
808
- ary[ary.index(ss)] = C::While.new(ss.test, ss.bthen)
809
- elsif ss.bthen.statements.last.kind_of? C::Return and g = ary[ary.index(s)+1..-1].reverse.find { |_s| _s.kind_of? C::Goto and _s.target == s.name }
837
+ ary[ssi] = C::While.new(ss.test, ss.bthen)
838
+ elsif ss.bthen.statements.last.kind_of?(C::Return) and gi = ((si+1)..ary.length).to_a.reverse.find { |_si| ary[_si].kind_of?(C::Goto) and ary[_si].target == s.name }
839
+ # l: if (a) { b; return; } c; goto l; => while (!a) { c; } b; return;
810
840
  wb = C::Block.new(scope)
811
- wb.statements = decompile_cseq_while(ary[ary.index(ss)+1...ary.index(g)], wb)
841
+ wb.statements = decompile_cseq_while(ary[ssi+1...gi], wb)
812
842
  w = C::While.new(C::CExpression.negate(ss.test), wb)
813
- ary[ary.index(ss)..ary.index(g)] = [w, *ss.bthen.statements]
843
+ ary[ssi..gi] = [w, *ss.bthen.statements]
814
844
  finished = false ; break #retry
815
845
  end
816
846
  end
817
- if g = ary[ary.index(s)..-1].reverse.find { |_s| _s.kind_of? C::Goto and _s.target == s.name }
847
+ if gi = (si..ary.length).to_a.reverse.find { |_si| ary[_si].kind_of?(C::Goto) and ary[_si].target == s.name }
848
+ # l: a; goto l; => while(1) { a; }
818
849
  wb = C::Block.new(scope)
819
- wb.statements = decompile_cseq_while(ary[ary.index(s)...ary.index(g)], wb)
850
+ wb.statements = decompile_cseq_while(ary[si...gi], wb)
820
851
  w = C::While.new(C::CExpression[1], wb)
821
- ary[ary.index(s)..ary.index(g)] = [w]
852
+ ary[si..gi] = [w]
822
853
  finished = false ; break #retry
823
854
  end
824
- if g = ary[ary.index(s)..-1].reverse.find { |_s| _s.kind_of? C::If and not _s.belse and gt = _s.bthen and
825
- (gt = gt.kind_of?(C::Block) && gt.statements.length == 1 ? gt.statements.first : gt) and gt.kind_of? C::Goto and gt.target == s.name }
855
+ if gi = (si..ary.length).to_a.reverse.find { |_si| ary[_si].kind_of?(C::If) and not ary[_si].belse and gt = ary[_si].bthen and
856
+ (gt = gt.kind_of?(C::Block) ? gt.statements.last : gt) and gt.kind_of?(C::Goto) and gt.target == s.name }
857
+ # l: a; if (b) goto l; => do { a; } while (b);
858
+ # l: a; if (b) { c; goto l; } => do { a; if (!b) break; c; } while(1);
826
859
  wb = C::Block.new(scope)
827
- wb.statements = decompile_cseq_while(ary[ary.index(s)...ary.index(g)], wb)
828
- w = C::DoWhile.new(g.test, wb)
829
- ary[ary.index(s)..ary.index(g)] = [w]
860
+ g = ary[gi]
861
+ if g.bthen.kind_of?(C::Block) and g.bthen.statements.length > 1
862
+ nary = ary[si...gi] + [C::If.new(C::CExpression.negate(g.test), C::Break.new)] + g.bthen.statements[0...-1]
863
+ wb.statements = decompile_cseq_while(nary, wb)
864
+ w = C::DoWhile.new(C::CExpression[1], wb)
865
+ else
866
+ wb.statements = decompile_cseq_while(ary[si...gi], wb)
867
+ w = C::DoWhile.new(g.test, wb)
868
+ end
869
+ ary[si..gi] = [w]
830
870
  finished = false ; break #retry
831
871
  end
832
872
  when C::If
833
- decompile_cseq_while(s.bthen.statements, s.bthen) if s.bthen.kind_of? C::Block
834
- decompile_cseq_while(s.belse.statements, s.belse) if s.belse.kind_of? C::Block
873
+ decompile_cseq_while(s.bthen.statements, s.bthen) if s.bthen.kind_of?(C::Block)
874
+ decompile_cseq_while(s.belse.statements, s.belse) if s.belse.kind_of?(C::Block)
835
875
  when C::While, C::DoWhile
836
- decompile_cseq_while(s.body.statements, s.body) if s.body.kind_of? C::Block
876
+ decompile_cseq_while(s.body.statements, s.body) if s.body.kind_of?(C::Block)
837
877
  end
838
- }
839
878
  end
879
+ end # while finished
840
880
  ary
841
881
  end
842
882
 
843
883
  # TODO
844
884
  def decompile_cseq_switch(scope)
845
- uncast = lambda { |e| e = e.rexpr while e.kind_of? C::CExpression and not e.op ; e }
885
+ uncast = lambda { |e| e = e.rexpr while e.kind_of?(C::CExpression) and not e.op ; e }
846
886
  walk(scope) { |s|
847
887
  # XXX pfff...
848
- next if not s.kind_of? C::If
888
+ next if not s.kind_of?(C::If)
849
889
  # if (v < 12) return ((void(*)())(tableaddr+4*v))();
850
890
  t = s.bthen
851
- t = t.statements.first if t.kind_of? C::Block and t.statements.length == 1
852
- next if not t.kind_of? C::Return or not t.respond_to? :from_instr
853
- next if t.from_instr.comment.to_a.include? 'switch'
854
- next if not t.value.kind_of? C::CExpression or t.value.op != :funcall or t.value.rexpr != [] or not t.value.lexpr.kind_of? C::CExpression or t.value.lexpr.op
891
+ t = t.statements.first if t.kind_of?(C::Block) and t.statements.length == 1
892
+ next if not t.kind_of?(C::Return) or not t.respond_to?(:from_instr)
893
+ next if t.from_instr.comment.to_a.include?('switch')
894
+ next if not t.value.kind_of?(C::CExpression) or t.value.op != :funcall or t.value.rexpr != [] or not t.value.lexpr.kind_of?(C::CExpression) or t.value.lexpr.op
855
895
  p = uncast[t.value.lexpr.rexpr]
856
- next if not p.kind_of? C::CExpression or p.op != :* or p.lexpr
896
+ next if not p.kind_of?(C::CExpression) or p.op != :* or p.lexpr
857
897
  p = uncast[p.rexpr]
858
- next if not p.kind_of? C::CExpression or p.op != :+
898
+ next if not p.kind_of?(C::CExpression) or p.op != :+
859
899
  r, l = uncast[p.rexpr], uncast[p.lexpr]
860
- r, l = l, r if r.kind_of? C::CExpression
861
- next if not r.kind_of? ::Integer or not l.kind_of? C::CExpression or l.op != :* or not l.lexpr
900
+ r, l = l, r if r.kind_of?(C::CExpression)
901
+ next if not r.kind_of?(::Integer) or not l.kind_of?(C::CExpression) or l.op != :* or not l.lexpr
862
902
  lr, ll = uncast[l.rexpr], uncast[l.lexpr]
863
- lr, ll = ll, lr if not ll.kind_of? ::Integer
903
+ lr, ll = ll, lr if not ll.kind_of?(::Integer)
864
904
  next if ll != sizeof(nil, C::Pointer.new(C::BaseType.new(:void)))
865
905
  base, index = r, lr
866
- if s.test.kind_of? C::CExpression and (s.test.op == :<= or s.test.op == :<) and s.test.lexpr == index and
867
- s.test.rexpr.kind_of? C::CExpression and not s.test.rexpr.op and s.test.rexpr.rexpr.kind_of? ::Integer
906
+ if s.test.kind_of?(C::CExpression) and (s.test.op == :<= or s.test.op == :<) and s.test.lexpr == index and
907
+ s.test.rexpr.kind_of?(C::CExpression) and not s.test.rexpr.op and s.test.rexpr.rexpr.kind_of?(::Integer)
868
908
  t.from_instr.add_comment 'switch'
869
909
  sup = s.test.rexpr.rexpr
870
910
  rng = ((s.test.op == :<) ? (0...sup) : (0..sup))
@@ -883,19 +923,19 @@ class Decompiler
883
923
 
884
924
  used = []
885
925
  walk(scope) { |ss|
886
- used |= [ss.target] if ss.kind_of? C::Goto
926
+ used |= [ss.target] if ss.kind_of?(C::Goto)
887
927
  }
888
928
  walk(scope) { |s|
889
- next if not s.kind_of? C::Block
929
+ next if not s.kind_of?(C::Block)
890
930
  s.statements.delete_if { |l|
891
- l.kind_of? C::Label and not used.include? l.name
931
+ l.kind_of?(C::Label) and not used.include?(l.name)
892
932
  }
893
933
  }
894
934
 
895
935
  # remove implicit continue; at end of loop
896
936
  walk(scope) { |s|
897
- next if not s.kind_of? C::While
898
- if s.body.kind_of? C::Block and s.body.statements.last.kind_of? C::Continue
937
+ next if not s.kind_of?(C::While)
938
+ if s.body.kind_of?(C::Block) and s.body.statements.last.kind_of?(C::Continue)
899
939
  s.body.statements.pop
900
940
  end
901
941
  }
@@ -903,11 +943,11 @@ class Decompiler
903
943
 
904
944
  # checks if expr is a var (var or *&var)
905
945
  def isvar(ce, var)
906
- if var.stackoff and ce.kind_of? C::CExpression
946
+ if var.stackoff and ce.kind_of?(C::CExpression)
907
947
  return unless ce.op == :* and not ce.lexpr
908
948
  ce = ce.rexpr
909
- ce = ce.rexpr while ce.kind_of? C::CExpression and not ce.op
910
- return unless ce.kind_of? C::CExpression and ce.op == :& and not ce.lexpr
949
+ ce = ce.rexpr while ce.kind_of?(C::CExpression) and not ce.op
950
+ return unless ce.kind_of?(C::CExpression) and ce.op == :& and not ce.lexpr
911
951
  ce = ce.rexpr
912
952
  end
913
953
  ce == var
@@ -929,7 +969,7 @@ class Decompiler
929
969
  # checks if expr writes var
930
970
  def ce_write(ce_, var)
931
971
  walk_ce(ce_) { |ce|
932
- break true if AssignOp.include?(ce.op) and (isvar(ce.lexpr, var) or
972
+ break true if C::CExpression::AssignOp.include?(ce.op) and (isvar(ce.lexpr, var) or
933
973
  (((ce.op == :'++' or ce.op == :'--') and isvar(ce.rexpr, var))))
934
974
  }
935
975
  end
@@ -971,6 +1011,8 @@ class Decompiler
971
1011
  write = {}
972
1012
  ro = {}
973
1013
  wo = {}
1014
+ g_exprs = {}
1015
+ g.exprs_var[var.name].to_h.each { |k, v| g_exprs[k] = v.map { |i| g.exprs[k][i] } }
974
1016
 
975
1017
  # list of [l, i] for which domain is not known
976
1018
  unchecked = []
@@ -978,7 +1020,7 @@ class Decompiler
978
1020
  # mark all exprs of the graph
979
1021
  # TODO handle var_14 __attribute__((out)) = &curvar <=> curvar write
980
1022
  r = var.has_attribute_var('register')
981
- g.exprs.each { |label, exprs|
1023
+ g_exprs.each { |label, exprs|
982
1024
  exprs.each_with_index { |ce, i|
983
1025
  if ce_read(ce, var)
984
1026
  if (ce.op == :'=' and isvar(ce.lexpr, var) and not ce_write(ce.rexpr, var)) or
@@ -1006,28 +1048,29 @@ class Decompiler
1006
1048
  todo_w = [[l, i-1]]
1007
1049
  done_w = []
1008
1050
  while o = todo_w.pop
1009
- next if done_w.include? o
1051
+ next if done_w.include?(o)
1010
1052
  done_w << o
1011
1053
  l, i = o
1012
1054
  loop do
1013
- if read[l].to_a.include? i
1055
+ if read[l].to_a.include?(i)
1014
1056
  # XXX not optimal (should mark only the uppest read)
1015
- todo_down |= [[l, i]] if not dom.include? [l, i]
1057
+ todo_down |= [[l, i]] if not dom.include?([l, i])
1016
1058
  dom |= [[l, i]]
1017
- elsif write[l].to_a.include? i
1018
- todo_down |= [[l, i]] if not dom.include? [l, i]
1059
+ elsif write[l].to_a.include?(i)
1060
+ todo_down |= [[l, i]] if not dom.include?([l, i])
1019
1061
  dom |= [[l, i]]
1020
1062
  break
1021
- elsif wo[l].to_a.include? i
1022
- todo_down |= [[l, i]] if not dom_wo.include? [l, i, :down]
1063
+ elsif wo[l].to_a.include?(i)
1064
+ todo_down |= [[l, i]] if not dom_wo.include?([l, i, :down])
1023
1065
  dom_wo |= [[l, i, :down]]
1024
1066
  break
1025
1067
  end
1026
1068
  i -= 1
1027
1069
  if i < 0
1028
1070
  g.from_optim[l].to_a.each { |ll|
1029
- todo_w << [ll, g.exprs[ll].to_a.length-1]
1071
+ todo_w << [ll, g_exprs[ll].to_a.length-1]
1030
1072
  }
1073
+ # read unitialized
1031
1074
  func_top = true if g.from_optim[l].to_a.empty?
1032
1075
  break
1033
1076
  end
@@ -1036,27 +1079,27 @@ class Decompiler
1036
1079
  }
1037
1080
 
1038
1081
  # flood by walking the graph down from [l, i] (excluded)
1039
- # malks stuff to walk up
1082
+ # marks stuff to walk up
1040
1083
  walk_down = lambda { |l, i|
1041
1084
  todo_w = [[l, i+1]]
1042
1085
  done_w = []
1043
1086
  while o = todo_w.pop
1044
- next if done_w.include? o
1087
+ next if done_w.include?(o)
1045
1088
  done_w << o
1046
1089
  l, i = o
1047
1090
  loop do
1048
- if read[l].to_a.include? i
1049
- todo_up |= [[l, i]] if not dom.include? [l, i]
1091
+ if read[l].to_a.include?(i)
1092
+ todo_up |= [[l, i]] if not dom.include?([l, i])
1050
1093
  dom |= [[l, i]]
1051
- elsif write[l].to_a.include? i
1094
+ elsif write[l].to_a.include?(i)
1052
1095
  break
1053
- elsif ro[l].to_a.include? i
1054
- todo_up |= [[l, i]] if not dom_ro.include? [l, i, :up]
1096
+ elsif ro[l].to_a.include?(i)
1097
+ todo_up |= [[l, i]] if not dom_ro.include?([l, i, :up])
1055
1098
  dom_ro |= [[l, i, :up]]
1056
1099
  break
1057
1100
  end
1058
1101
  i += 1
1059
- if i >= g.exprs[l].to_a.length
1102
+ if i >= g_exprs[l].to_a.length
1060
1103
  g.to_optim[l].to_a.each { |ll|
1061
1104
  todo_w << [ll, 0]
1062
1105
  }
@@ -1077,11 +1120,11 @@ class Decompiler
1077
1120
  todo_down = []
1078
1121
 
1079
1122
  # init
1080
- if read[o[0]].to_a.include? o[1]
1123
+ if read[o[0]].to_a.include?(o[1])
1081
1124
  todo_up << o
1082
1125
  todo_down << o
1083
1126
  dom << o
1084
- elsif write[o[0]].to_a.include? o[1]
1127
+ elsif write[o[0]].to_a.include?(o[1])
1085
1128
  todo_down << o
1086
1129
  dom << o
1087
1130
  elsif o[2] == :up
@@ -1111,25 +1154,29 @@ class Decompiler
1111
1154
  n_i += 1 while scope.symbol_ancestors[newvarname = "#{var.name}_a#{n_i}"]
1112
1155
 
1113
1156
  nv = var.dup
1157
+ nv.misc = var.misc ? var.misc.dup : {}
1114
1158
  nv.storage = :register if nv.has_attribute_var('register')
1115
1159
  nv.attributes = nv.attributes.dup if nv.attributes
1116
1160
  nv.name = newvarname
1161
+ nv.misc[:unalias_name] = newvarname
1117
1162
  scope.statements << C::Declaration.new(nv)
1118
1163
  scope.symbol[nv.name] = nv
1119
1164
 
1120
- dom.each { |oo| ce_patch(g.exprs[oo[0]][oo[1]], var, nv) }
1165
+ dom.each { |oo| ce_patch(g_exprs[oo[0]][oo[1]], var, nv) }
1121
1166
  dom_ro.each { |oo|
1122
- ce = g.exprs[oo[0]][oo[1]]
1123
- if ce.op == :funcall or ce.rexpr.kind_of? C::CExpression
1167
+ ce = g_exprs[oo[0]][oo[1]]
1168
+ if ce.op == :funcall
1169
+ ce_patch(ce, var, nv)
1170
+ elsif ce.rexpr.kind_of?(C::CExpression)
1124
1171
  ce_patch(ce.rexpr, var, nv)
1125
1172
  else
1126
1173
  ce.rexpr = nv
1127
1174
  end
1128
1175
  }
1129
1176
  dom_wo.each { |oo|
1130
- ce = g.exprs[oo[0]][oo[1]]
1177
+ ce = g_exprs[oo[0]][oo[1]]
1131
1178
  if ce.op == :funcall
1132
- elsif ce.lexpr.kind_of? C::CExpression
1179
+ elsif ce.lexpr.kind_of?(C::CExpression)
1133
1180
  ce_patch(ce.lexpr, var, nv)
1134
1181
  else
1135
1182
  ce.lexpr = nv
@@ -1174,13 +1221,10 @@ class Decompiler
1174
1221
  v
1175
1222
  }
1176
1223
 
1177
- scope.decompdata[:stackoff_name].each { |o, n| newvar[o, n] }
1178
- scope.decompdata[:stackoff_type].each { |o, t| newvar[o, stackoff_to_varname(o)] }
1179
-
1180
1224
  walk_ce(scope) { |e|
1181
1225
  next if e.op != :+ and e.op != :-
1182
- next if not e.lexpr.kind_of? C::Variable or e.lexpr.name != 'frameptr'
1183
- next if not e.rexpr.kind_of? C::CExpression or e.rexpr.op or not e.rexpr.rexpr.kind_of? ::Integer
1226
+ next if not e.lexpr.kind_of?(C::Variable) or e.lexpr.name != 'frameptr'
1227
+ next if not e.rexpr.kind_of?(C::CExpression) or e.rexpr.op or not e.rexpr.rexpr.kind_of?(::Integer)
1184
1228
  off = e.rexpr.rexpr
1185
1229
  off = -off if e.op == :-
1186
1230
  v = newvar[off, stackoff_to_varname(off)]
@@ -1200,24 +1244,24 @@ class Decompiler
1200
1244
  types = {}
1201
1245
 
1202
1246
  pscopevar = lambda { |e|
1203
- e = e.rexpr while e.kind_of? C::CExpression and not e.op and e.rexpr.kind_of? C::CExpression
1204
- if e.kind_of? C::CExpression and e.op == :& and not e.lexpr and e.rexpr.kind_of? C::Variable
1247
+ e = e.rexpr while e.kind_of?(C::CExpression) and not e.op and e.rexpr.kind_of?(C::CExpression)
1248
+ if e.kind_of?(C::CExpression) and e.op == :& and not e.lexpr and e.rexpr.kind_of?(C::Variable)
1205
1249
  e.rexpr.name if scope.symbol[e.rexpr.name]
1206
1250
  end
1207
1251
  }
1208
1252
  scopevar = lambda { |e|
1209
- e = e.rexpr if e.kind_of? C::CExpression and not e.op
1210
- if e.kind_of? C::Variable and scope.symbol[e.name]
1253
+ e = e.rexpr if e.kind_of?(C::CExpression) and not e.op
1254
+ if e.kind_of?(C::Variable) and scope.symbol[e.name]
1211
1255
  e.name
1212
- elsif e.kind_of? C::CExpression and e.op == :* and not e.lexpr
1256
+ elsif e.kind_of?(C::CExpression) and e.op == :* and not e.lexpr
1213
1257
  pscopevar[e.rexpr]
1214
1258
  end
1215
1259
  }
1216
1260
  globalvar = lambda { |e|
1217
- e = e.rexpr if e.kind_of? C::CExpression and not e.op
1218
- if e.kind_of? ::Integer and @dasm.get_section_at(e)
1261
+ e = e.rexpr if e.kind_of?(C::CExpression) and not e.op
1262
+ if e.kind_of?(::Integer) and e > 0x10000 and @dasm.get_section_at(e)
1219
1263
  e
1220
- elsif e.kind_of? C::Variable and not scope.symbol[e.name] and @c_parser.toplevel.symbol[e.name] and @dasm.get_section_at(e.name)
1264
+ elsif e.kind_of?(C::Variable) and not scope.symbol[e.name] and @c_parser.toplevel.symbol[e.name] and @dasm.get_section_at(e.name)
1221
1265
  e.name
1222
1266
  end
1223
1267
  }
@@ -1225,8 +1269,8 @@ class Decompiler
1225
1269
  # check if a newly found type for o is better than current type
1226
1270
  # order: foo* > void* > foo
1227
1271
  better_type = lambda { |t0, t1|
1228
- t1 == C::BaseType.new(:void) or (t0.pointer? and t1.kind_of? C::BaseType) or t0.untypedef.kind_of? C::Union or
1229
- (t0.kind_of? C::BaseType and t1.kind_of? C::BaseType and (@c_parser.typesize[t0.name] > @c_parser.typesize[t1.name] or (t0.name == t1.name and t0.qualifier))) or
1272
+ t1 == C::BaseType.new(:void) or (t0.pointer? and t1.kind_of?(C::BaseType)) or t0.untypedef.kind_of?(C::Union) or
1273
+ (t0.kind_of?(C::BaseType) and t1.kind_of?(C::BaseType) and (@c_parser.typesize[t0.name] > @c_parser.typesize[t1.name] or (t0.name == t1.name and t0.qualifier))) or
1230
1274
  (t0.pointer? and t1.pointer? and better_type[t0.pointed, t1.pointed])
1231
1275
  }
1232
1276
 
@@ -1234,11 +1278,11 @@ class Decompiler
1234
1278
  if ne = new_global_var(e, t, scope)
1235
1279
  ne.type = t if better_type[t, ne.type] # TODO patch existing scopes using ne
1236
1280
  # TODO rename (dword_xx -> byte_xx etc)
1237
- e = scope.symbol_ancestors[e] || e if e.kind_of? String # exe reloc
1281
+ e = scope.symbol_ancestors[e] || e if e.kind_of?(String) # exe reloc
1238
1282
  walk_ce(scope) { |ce|
1239
1283
  ce.lexpr = ne if ce.lexpr == e
1240
1284
  ce.rexpr = ne if ce.rexpr == e
1241
- if ce.op == :* and not ce.lexpr and ce.rexpr == ne and ne.type.pointer? and ne.type.pointed.untypedef.kind_of? C::Union
1285
+ if ce.op == :* and not ce.lexpr and ce.rexpr == ne and ne.type.pointer? and ne.type.pointed.untypedef.kind_of?(C::Union)
1242
1286
  # *struct -> struct->bla
1243
1287
  ce.rexpr = structoffset(ne.type.pointed.untypedef, ce.rexpr, 0, sizeof(ce.type))
1244
1288
  elsif ce.lexpr == ne or ce.rexpr == ne
@@ -1255,10 +1299,10 @@ class Decompiler
1255
1299
  # check if need to change the type of a var
1256
1300
  # propagate_type if type is updated
1257
1301
  update_type = lambda { |n, t|
1258
- next if propagating.include? n
1302
+ next if propagating.include?(n)
1259
1303
  o = scope.symbol[n].stackoff
1260
- next if not o and t.untypedef.kind_of? C::Union
1261
- next if o and scope.decompdata[:stackoff_type][o] and t != scope.decompdata[:stackoff_type][o]
1304
+ next if not o and t.untypedef.kind_of?(C::Union)
1305
+ next if scope.decompdata[:unalias_type][n] and t != scope.decompdata[:unalias_type][n]
1262
1306
  next if t0 = types[n] and not better_type[t, t0]
1263
1307
  next if o and (t.integral? or t.pointer?) and o % sizeof(t) != 0 # keep vars aligned
1264
1308
  types[n] = t
@@ -1268,7 +1312,7 @@ class Decompiler
1268
1312
  propagating.delete n
1269
1313
  next if not o
1270
1314
  t = t.untypedef
1271
- if t.kind_of? C::Struct
1315
+ if t.kind_of?(C::Struct)
1272
1316
  t.members.to_a.each { |m|
1273
1317
  mo = t.offsetof(@c_parser, m.name)
1274
1318
  next if mo == 0
@@ -1282,23 +1326,23 @@ class Decompiler
1282
1326
  # try to update the type of a var from knowing the type of an expr (through dereferences etc)
1283
1327
  known_type = lambda { |e, t|
1284
1328
  loop do
1285
- e = e.rexpr while e.kind_of? C::CExpression and not e.op and e.type == t
1329
+ e = e.rexpr while e.kind_of?(C::CExpression) and not e.op and e.type == t
1286
1330
  if o = scopevar[e]
1287
1331
  update_type[o, t]
1288
1332
  elsif o = globalvar[e]
1289
1333
  update_global_type[o, t]
1290
- elsif not e.kind_of? C::CExpression
1334
+ elsif not e.kind_of?(C::CExpression)
1291
1335
  elsif o = pscopevar[e] and t.pointer?
1292
1336
  update_type[o, t.pointed]
1293
1337
  elsif e.op == :* and not e.lexpr
1294
1338
  e = e.rexpr
1295
1339
  t = C::Pointer.new(t)
1296
1340
  next
1297
- elsif t.pointer? and e.op == :+ and e.lexpr.kind_of? C::CExpression and e.lexpr.type.integral? and e.rexpr.kind_of? C::Variable
1341
+ elsif t.pointer? and e.op == :+ and e.lexpr.kind_of?(C::CExpression) and e.lexpr.type.integral? and e.rexpr.kind_of?(C::Variable)
1298
1342
  e.lexpr, e.rexpr = e.rexpr, e.lexpr
1299
1343
  next
1300
- elsif e.op == :+ and e.lexpr and e.rexpr.kind_of? C::CExpression
1301
- if not e.rexpr.op and e.rexpr.rexpr.kind_of? ::Integer
1344
+ elsif e.op == :+ and e.lexpr and e.rexpr.kind_of?(C::CExpression)
1345
+ if not e.rexpr.op and e.rexpr.rexpr.kind_of?(::Integer)
1302
1346
  if t.pointer? and e.rexpr.rexpr < 0x1000 and (e.rexpr.rexpr % sizeof(t.pointed)) == 0 # XXX relocatable + base=0..
1303
1347
  e = e.lexpr # (int)*(x+2) === (int) *x
1304
1348
  next
@@ -1307,13 +1351,13 @@ class Decompiler
1307
1351
  e = e.rexpr
1308
1352
  next
1309
1353
  end
1310
- elsif t.pointer? and (e.lexpr.kind_of? C::CExpression and e.lexpr.lexpr and [:<<, :>>, :*, :&].include? e.lexpr.op) or
1354
+ elsif t.pointer? and (e.lexpr.kind_of?(C::CExpression) and e.lexpr.lexpr and [:<<, :>>, :*, :&].include?(e.lexpr.op)) or
1311
1355
  (o = scopevar[e.lexpr] and types[o] and types[o].integral? and
1312
1356
  !(o = scopevar[e.rexpr] and types[o] and types[o].integral?))
1313
1357
  e.lexpr, e.rexpr = e.rexpr, e.lexpr # swap
1314
1358
  e = e.lexpr
1315
1359
  next
1316
- elsif t.pointer? and ((e.rexpr.kind_of? C::CExpression and e.rexpr.lexpr and [:<<, :>>, :*, :&].include? e.rexpr.op) or
1360
+ elsif t.pointer? and ((e.rexpr.kind_of?(C::CExpression) and e.rexpr.lexpr and [:<<, :>>, :*, :&].include?(e.rexpr.op)) or
1317
1361
  (o = scopevar[e.rexpr] and types[o] and types[o].integral? and
1318
1362
  !(o = scopevar[e.lexpr] and types[o] and types[o].integral?)))
1319
1363
  e = e.lexpr
@@ -1329,11 +1373,11 @@ class Decompiler
1329
1373
  walk_ce(scope) { |ce|
1330
1374
  next if ce.op != :'='
1331
1375
 
1332
- if ce.lexpr.kind_of? C::Variable and ce.lexpr.name == var
1376
+ if ce.lexpr.kind_of?(C::Variable) and ce.lexpr.name == var
1333
1377
  known_type[ce.rexpr, type]
1334
1378
  next
1335
1379
  end
1336
- if ce.rexpr.kind_of? C::Variable and ce.rexpr.name == var
1380
+ if ce.rexpr.kind_of?(C::Variable) and ce.rexpr.name == var
1337
1381
  known_type[ce.lexpr, type]
1338
1382
  next
1339
1383
  end
@@ -1341,7 +1385,7 @@ class Decompiler
1341
1385
  # int **x; y = **x => int y
1342
1386
  t = type
1343
1387
  l = ce.lexpr
1344
- while l.kind_of? C::CExpression and l.op == :* and not l.lexpr
1388
+ while l.kind_of?(C::CExpression) and l.op == :* and not l.lexpr
1345
1389
  if var == pscopevar[l.rexpr]
1346
1390
  known_type[ce.rexpr, t]
1347
1391
  break
@@ -1355,7 +1399,7 @@ class Decompiler
1355
1399
  # int **x; **x = y => int y
1356
1400
  t = type
1357
1401
  r = ce.rexpr
1358
- while r.kind_of? C::CExpression and r.op == :* and not r.lexpr
1402
+ while r.kind_of?(C::CExpression) and r.op == :* and not r.lexpr
1359
1403
  if var == pscopevar[r.rexpr]
1360
1404
  known_type[ce.lexpr, t]
1361
1405
  break
@@ -1373,32 +1417,32 @@ class Decompiler
1373
1417
  # put all those macros in use
1374
1418
  # use user-defined types first
1375
1419
  scope.symbol.each_value { |v|
1376
- next if not v.kind_of? C::Variable or not v.stackoff or not t = scope.decompdata[:stackoff_type][v.stackoff]
1420
+ next if not v.kind_of?(C::Variable) or not t = scope.decompdata[:unalias_type][v.name]
1377
1421
  known_type[v, t]
1378
1422
  }
1379
1423
 
1380
1424
  # try to infer types from C semantics
1381
1425
  later = []
1382
1426
  walk_ce(scope) { |ce|
1383
- if ce.op == :'=' and ce.rexpr.kind_of? C::CExpression and (ce.rexpr.op == :funcall or (ce.rexpr.op == nil and ce.rexpr.rexpr.kind_of? ::Integer and
1384
- ce.rexpr.rexpr.abs < 0x10000 and (not ce.lexpr.kind_of? C::CExpression or ce.lexpr.op != :'*' or ce.lexpr.lexpr)))
1427
+ if ce.op == :'=' and ce.rexpr.kind_of?(C::CExpression) and (ce.rexpr.op == :funcall or (ce.rexpr.op == nil and ce.rexpr.rexpr.kind_of?(::Integer) and
1428
+ ce.rexpr.rexpr.abs < 0x10000 and (not ce.lexpr.kind_of?(C::CExpression) or ce.lexpr.op != :'*' or ce.lexpr.lexpr)))
1385
1429
  # var = int
1386
1430
  known_type[ce.lexpr, ce.rexpr.type]
1387
1431
  elsif ce.op == :funcall
1388
1432
  f = ce.lexpr.type
1389
1433
  f = f.pointed if f.pointer?
1390
- next if not f.kind_of? C::Function
1434
+ next if not f.kind_of?(C::Function)
1391
1435
  # cast func args to arg prototypes
1392
1436
  f.args.to_a.zip(ce.rexpr).each_with_index { |(proto, arg), i| ce.rexpr[i] = C::CExpression[arg, proto.type] ; known_type[arg, proto.type] }
1393
1437
  elsif ce.op == :* and not ce.lexpr
1394
- if e = ce.rexpr and e.kind_of? C::CExpression and not e.op and e = e.rexpr and e.kind_of? C::CExpression and
1395
- e.op == :& and not e.lexpr and e.rexpr.kind_of? C::Variable and e.rexpr.stackoff
1438
+ if e = ce.rexpr and e.kind_of?(C::CExpression) and not e.op and e = e.rexpr and e.kind_of?(C::CExpression) and
1439
+ e.op == :& and not e.lexpr and e.rexpr.kind_of?(C::Variable) and e.rexpr.stackoff
1396
1440
  # skip *(__int32*)&var_12 for now, avoid saying var12 is an int if it may be a ptr or anything
1397
1441
  later << [ce.rexpr, C::Pointer.new(ce.type)]
1398
1442
  next
1399
1443
  end
1400
1444
  known_type[ce.rexpr, C::Pointer.new(ce.type)]
1401
- elsif not ce.op and ce.type.pointer? and ce.type.pointed.kind_of? C::Function
1445
+ elsif not ce.op and ce.type.pointer? and ce.type.pointed.kind_of?(C::Function)
1402
1446
  # cast to fptr: must be a fptr
1403
1447
  known_type[ce.rexpr, ce.type]
1404
1448
  end
@@ -1423,7 +1467,7 @@ class Decompiler
1423
1467
  v = scope.symbol[n]
1424
1468
  next if not o = v.stackoff
1425
1469
  t = t.untypedef
1426
- if t.kind_of? C::Struct
1470
+ if t.kind_of?(C::Struct)
1427
1471
  t.members.to_a.each { |tm|
1428
1472
  moff = t.offsetof(@c_parser, tm.name)
1429
1473
  next if moff == 0
@@ -1469,7 +1513,7 @@ class Decompiler
1469
1513
  }
1470
1514
  when o = scopevar[ce.lexpr]; ce.lexpr = maycast[varat[o], ce.lexpr]
1471
1515
  when o = scopevar[ce.rexpr]; ce.rexpr = maycast[varat[o], ce.rexpr]
1472
- ce.rexpr = C::CExpression[ce.rexpr] if not ce.op and ce.rexpr.kind_of? C::Variable
1516
+ ce.rexpr = C::CExpression[ce.rexpr] if not ce.op and ce.rexpr.kind_of?(C::Variable)
1473
1517
  when o = pscopevar[ce.lexpr]; ce.lexpr = maycast_p[varat[o], ce.lexpr]
1474
1518
  when o = pscopevar[ce.rexpr]; ce.rexpr = maycast_p[varat[o], ce.rexpr]
1475
1519
  when o = scopevar[ce]; ce.replace C::CExpression[maycast[varat[o], ce]]
@@ -1485,14 +1529,14 @@ class Decompiler
1485
1529
  varandff = Hash.new(0)
1486
1530
  varandffff = Hash.new(0)
1487
1531
  walk_ce(scope) { |ce|
1488
- if ce.op == :& and ce.lexpr.kind_of? C::Variable and ce.lexpr.type.integral? and ce.rexpr.kind_of? C::CExpression and not ce.rexpr.op and ce.rexpr.rexpr.kind_of? ::Integer
1532
+ if ce.op == :& and ce.lexpr.kind_of?(C::Variable) and ce.lexpr.type.integral? and ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and ce.rexpr.rexpr.kind_of?(::Integer)
1489
1533
  case ce.rexpr.rexpr
1490
1534
  when 0xff; varandff[ce.lexpr.name] += 1
1491
1535
  when 0xffff; varandffff[ce.lexpr.name] += 1
1492
1536
  end
1493
1537
  end
1494
- varuse[ce.lexpr.name] += 1 if ce.lexpr.kind_of? C::Variable
1495
- varuse[ce.rexpr.name] += 1 if ce.rexpr.kind_of? C::Variable
1538
+ varuse[ce.lexpr.name] += 1 if ce.lexpr.kind_of?(C::Variable)
1539
+ varuse[ce.rexpr.name] += 1 if ce.rexpr.kind_of?(C::Variable)
1496
1540
  }
1497
1541
  varandff.each { |k, v|
1498
1542
  scope.symbol[k].type = C::BaseType.new(:__int8, :unsigned) if varuse[k] == v
@@ -1505,28 +1549,96 @@ class Decompiler
1505
1549
  walk_ce(scope, true) { |ce|
1506
1550
  if ce.op
1507
1551
  ce.type = C::CExpression[ce.lexpr, ce.op, ce.rexpr].type rescue next
1508
- if ce.op == :'=' and ce.rexpr.kind_of? C::Typed and ce.rexpr.type != ce.type and (not ce.rexpr.type.integral? or not ce.type.integral?)
1509
- known_type[ce.rexpr, ce.type] if ce.type.pointer? and ce.type.pointed.untypedef.kind_of? C::Function # localvar = &struct with fptr
1552
+ if ce.op == :'=' and ce.rexpr.kind_of?(C::Typed) and ce.rexpr.type != ce.type and (not ce.rexpr.type.integral? or not ce.type.integral?)
1553
+ known_type[ce.rexpr, ce.type] if ce.type.pointer? and ce.type.pointed.untypedef.kind_of?(C::Function) # localvar = &struct with fptr
1510
1554
  ce.rexpr = C::CExpression[[ce.rexpr], ce.type]
1511
1555
  end
1512
- elsif ce.type.pointer? and ce.rexpr.kind_of? C::CExpression and ce.rexpr.op == :& and not ce.rexpr.lexpr and sizeof(ce.rexpr.rexpr.type) == sizeof(ce.type.pointed)
1556
+ elsif ce.type.pointer? and ce.rexpr.kind_of?(C::CExpression) and ce.rexpr.op == :& and not ce.rexpr.lexpr and sizeof(ce.rexpr.rexpr.type) == sizeof(ce.type.pointed)
1513
1557
  ce.type = ce.rexpr.type
1514
1558
  end
1515
1559
  }
1516
1560
  end
1517
1561
 
1562
+ # use casts to determine variable types after code optimization
1563
+ # if all uses of var_42 are through *(int*)(&var_42), set type to int
1564
+ def decompile_c_types_again(scope)
1565
+ return if forbid_decompile_types
1566
+
1567
+ update_type = lambda { |n, t|
1568
+ o = scope.symbol[n].stackoff
1569
+ next if not o and t.untypedef.kind_of?(C::Union)
1570
+ next if scope.decompdata[:unalias_type][n] and t != scope.decompdata[:unalias_type][n]
1571
+ scope.symbol[n].type = t
1572
+ }
1573
+
1574
+ # true if e is a cast of a var address
1575
+ is_cast = lambda { |ce|
1576
+ true if not ce.op and not ce.lexpr and ce.rexpr and ce.rexpr.kind_of?(C::CExpression) and ce.rexpr.op == :& and not ce.rexpr.lexpr
1577
+ }
1578
+
1579
+ # scan code for casts
1580
+ uses = {}
1581
+ count_refs = Hash.new(0)
1582
+ walk_ce(scope) { |ce|
1583
+ count_refs[ce.lexpr.name] += 1 if ce.lexpr.kind_of?(C::Variable)
1584
+ count_refs[ce.rexpr.name] += 1 if ce.rexpr.kind_of?(C::Variable)
1585
+ if is_cast[ce] and ce.rexpr.rexpr.kind_of?(C::Variable)
1586
+ (uses[ce.rexpr.rexpr.name] ||= []) << ce.type.pointed
1587
+ end
1588
+ }
1589
+
1590
+ # given a list of types, return a type compatible with all
1591
+ summary_type = lambda { |type_list|
1592
+ t = type_list.first
1593
+ type_list.each { |tt|
1594
+ if sizeof(t) != sizeof(tt) or t.integral? != tt.integral? or t.pointer? != tt.pointer?
1595
+ t = nil
1596
+ break
1597
+ elsif t != tt
1598
+ t = tt if t.to_s =~ /__/
1599
+ end
1600
+ }
1601
+ t
1602
+ }
1603
+
1604
+ updated = {}
1605
+ uses.each { |n, tl|
1606
+ if tl.length == count_refs[n] and t = summary_type[tl] and update_type[n, t]
1607
+ updated[n] = true
1608
+ end
1609
+ }
1610
+ return if updated.empty?
1611
+
1612
+ walk_ce(scope, true) { |ce|
1613
+ if is_cast[ce] and updated[ce.rexpr.rexpr.name]
1614
+ ce.op = :&
1615
+ ce.rexpr = ce.rexpr.rexpr
1616
+ elsif ce.op == :* and not ce.lexpr and ce.rexpr.kind_of?(C::CExpression) and ce.rexpr.op == :& and not ce.rexpr.lexpr and ce.rexpr.rexpr.kind_of?(C::Variable) and updated[ce.rexpr.rexpr.name]
1617
+ ce.op = nil
1618
+ ce.rexpr = ce.rexpr.rexpr
1619
+ elsif ce.op
1620
+ if ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and ce.rexpr.rexpr.kind_of?(C::Variable) and updated[ce.rexpr.rexpr.name]
1621
+ ce.rexpr = ce.rexpr.rexpr
1622
+ end
1623
+ if ce.lexpr.kind_of?(C::CExpression) and not ce.lexpr.op and ce.lexpr.rexpr.kind_of?(C::Variable) and updated[ce.lexpr.rexpr.name]
1624
+ ce.lexpr = ce.lexpr.rexpr
1625
+ end
1626
+ end
1627
+ }
1628
+ end
1629
+
1518
1630
  # struct foo { int i; int j; struct { int k; int l; } m; }; bla+12 => &bla->m.l
1519
1631
  # st is a struct, ptr is an expr pointing to a struct, off is a numeric offset from ptr, msz is the size of the pointed member (nil ignored)
1520
1632
  def structoffset(st, ptr, off, msz)
1521
1633
  tabidx = off / sizeof(st)
1522
1634
  off -= tabidx * sizeof(st)
1523
- ptr = C::CExpression[:&, [ptr, :'[]', [tabidx]]] if tabidx != 0 or ptr.type.untypedef.kind_of? C::Array
1635
+ ptr = C::CExpression[:&, [ptr, :'[]', [tabidx]]] if tabidx != 0 or ptr.type.untypedef.kind_of?(C::Array)
1524
1636
  return ptr if off == 0 and (not msz or # avoid infinite recursion with eg chained list
1525
- (ptr.kind_of? C::CExpression and ((ptr.op == :& and not ptr.lexpr and s=ptr.rexpr) or (ptr.op == :'.' and s=ptr)) and
1526
- not s.type.untypedef.kind_of? C::Union))
1637
+ (ptr.kind_of?(C::CExpression) and ((ptr.op == :& and not ptr.lexpr and s=ptr.rexpr) or (ptr.op == :'.' and s=ptr)) and
1638
+ not s.type.untypedef.kind_of?(C::Union)))
1527
1639
 
1528
1640
  m_ptr = lambda { |m|
1529
- if ptr.kind_of? C::CExpression and ptr.op == :& and not ptr.lexpr
1641
+ if ptr.kind_of?(C::CExpression) and ptr.op == :& and not ptr.lexpr
1530
1642
  C::CExpression[ptr.rexpr, :'.', m.name]
1531
1643
  else
1532
1644
  C::CExpression[ptr, :'->', m.name]
@@ -1544,7 +1656,7 @@ class Decompiler
1544
1656
  sst = sm.type.untypedef
1545
1657
  #return ptr if mo[sm] == 0 and sst.pointer? and sst.type.untypedef == st # TODO fix infinite recursion on mutually recursive ptrs
1546
1658
  ptr = C::CExpression[:&, m_ptr[sm]]
1547
- if sst.kind_of? C::Union
1659
+ if sst.kind_of?(C::Union)
1548
1660
  return structoffset(sst, ptr, off, msz)
1549
1661
  end
1550
1662
  end
@@ -1561,15 +1673,15 @@ class Decompiler
1561
1673
  # must be run only once, right after type setting
1562
1674
  def fix_pointer_arithmetic(scope)
1563
1675
  walk_ce(scope, true) { |ce|
1564
- if ce.lexpr and ce.lexpr.type.pointer? and [:&, :>>, :<<].include? ce.op
1676
+ if ce.lexpr and ce.lexpr.type.pointer? and [:&, :>>, :<<].include?(ce.op)
1565
1677
  ce.lexpr = C::CExpression[[ce.lexpr], C::BaseType.new(:int)]
1566
1678
  end
1567
1679
 
1568
- if ce.op == :+ and ce.lexpr and ((ce.lexpr.type.integral? and ce.rexpr.type.pointer?) or (ce.rexpr.type.pointer? and ce.rexpr.type.pointed.untypedef.kind_of? C::Union))
1680
+ if ce.op == :+ and ce.lexpr and ((ce.lexpr.type.integral? and ce.rexpr.type.pointer?) or (ce.rexpr.type.pointer? and ce.rexpr.type.pointed.untypedef.kind_of?(C::Union)))
1569
1681
  ce.rexpr, ce.lexpr = ce.lexpr, ce.rexpr
1570
1682
  end
1571
1683
 
1572
- if ce.op == :* and not ce.lexpr and ce.rexpr.type.pointer? and ce.rexpr.type.pointed.untypedef.kind_of? C::Struct
1684
+ if ce.op == :* and not ce.lexpr and ce.rexpr.type.pointer? and ce.rexpr.type.pointed.untypedef.kind_of?(C::Struct)
1573
1685
  s = ce.rexpr.type.pointed.untypedef
1574
1686
  m = s.members.to_a.find { |m_| s.offsetof(@c_parser, m_.name) == 0 }
1575
1687
  if sizeof(m) != sizeof(ce)
@@ -1582,7 +1694,7 @@ class Decompiler
1582
1694
  ce.rexpr = m.name
1583
1695
  ce.type = m.type
1584
1696
  next
1585
- elsif ce.op == :'=' and ce.lexpr.type.untypedef.kind_of? C::Struct
1697
+ elsif ce.op == :'=' and ce.lexpr.type.untypedef.kind_of?(C::Struct)
1586
1698
  s = ce.lexpr.type.untypedef
1587
1699
  m = s.members.to_a.find { |m_| s.offsetof(@c_parser, m_.name) == 0 }
1588
1700
  ce.lexpr = C::CExpression.new(ce.lexpr, :'.', m.name, m.type)
@@ -1594,18 +1706,18 @@ class Decompiler
1594
1706
  ce.type = ce.lexpr.type
1595
1707
  end
1596
1708
 
1597
- if ce.op == :& and not ce.lexpr and ce.rexpr.kind_of? C::CExpression and ce.rexpr.op == :* and not ce.rexpr.lexpr
1709
+ if ce.op == :& and not ce.lexpr and ce.rexpr.kind_of?(C::CExpression) and ce.rexpr.op == :* and not ce.rexpr.lexpr
1598
1710
  ce.replace C::CExpression[ce.rexpr.rexpr]
1599
1711
  end
1600
1712
 
1601
1713
  next if not ce.lexpr or not ce.lexpr.type.pointer?
1602
- if ce.op == :+ and (s = ce.lexpr.type.pointed.untypedef).kind_of? C::Union and ce.rexpr.kind_of? C::CExpression and not ce.rexpr.op and
1603
- ce.rexpr.rexpr.kind_of? ::Integer and o = ce.rexpr.rexpr
1714
+ if ce.op == :+ and (s = ce.lexpr.type.pointed.untypedef).kind_of?(C::Union) and ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and
1715
+ ce.rexpr.rexpr.kind_of?(::Integer) and o = ce.rexpr.rexpr
1604
1716
  # structptr + 4 => &structptr->member
1605
1717
  ce.replace structoffset(s, ce.lexpr, o, nil)
1606
- elsif [:+, :-, :'+=', :'-='].include? ce.op and ce.rexpr.kind_of? C::CExpression and ((not ce.rexpr.op and i = ce.rexpr.rexpr) or
1607
- (ce.rexpr.op == :* and i = ce.rexpr.lexpr and ((i.kind_of? C::CExpression and not i.op and i = i.rexpr) or true))) and
1608
- i.kind_of? ::Integer and psz = sizeof(nil, ce.lexpr.type.pointed) and i % psz == 0
1718
+ elsif [:+, :-, :'+=', :'-='].include?(ce.op) and ce.rexpr.kind_of?(C::CExpression) and ((not ce.rexpr.op and i = ce.rexpr.rexpr) or
1719
+ (ce.rexpr.op == :* and i = ce.rexpr.lexpr and ((i.kind_of?(C::CExpression) and not i.op and i = i.rexpr) or true))) and
1720
+ i.kind_of?(::Integer) and psz = sizeof(nil, ce.lexpr.type.pointed) and i % psz == 0
1609
1721
  # ptr += 4 => ptr += 1
1610
1722
  if not ce.rexpr.op
1611
1723
  ce.rexpr.rexpr /= psz
@@ -1646,9 +1758,10 @@ class Decompiler
1646
1758
  # XXX o1 may overlap o2 AND another (int32 v_10; int32 v_E; int32 v_C;)
1647
1759
  # TODO should check stuff with aliasing domains
1648
1760
  next if v1.name == v2.name or o1 >= o2+l2 or o1+l1 <= o2 or l1 > l2 or (l2 == l1 and o2 >= o1)
1761
+ next if o1 == o2 and l1 != l2
1649
1762
  # v1 => *(&v2+delta)
1650
1763
  p = C::CExpression[:&, v2]
1651
- p = C::CExpression[p, :+, [o1-o2]]
1764
+ p = C::CExpression[p, :+, [o1-o2]] if o1 != o2
1652
1765
  p = C::CExpression[p, C::Pointer.new(v1.type)] if v1.type != p.type.type
1653
1766
  p = C::CExpression[:*, p]
1654
1767
  walk_ce(scope) { |ce|
@@ -1659,16 +1772,6 @@ class Decompiler
1659
1772
  }
1660
1773
  end
1661
1774
 
1662
- # to be run with scope = function body with only CExpr/Decl/Label/Goto/IfGoto/Return, with correct variables types
1663
- # will transform += 1 to ++, inline them to prev/next statement ('++x; if (x)..' => 'if (++x)..')
1664
- # remove useless variables ('int i;', i never used or 'i = 1; j = i;', i never read after => 'j = 1;')
1665
- # remove useless casts ('(int)i' with 'int i;' => 'i')
1666
- def optimize(scope)
1667
- optimize_code(scope)
1668
- optimize_vars(scope)
1669
- optimize_vars(scope) # 1st run may transform i = i+1 into i++ which second run may coalesce into if(i)
1670
- end
1671
-
1672
1775
  # simplify cexpressions (char & 255, redundant casts, etc)
1673
1776
  def optimize_code(scope)
1674
1777
  return if forbid_optimize_code
@@ -1676,12 +1779,12 @@ class Decompiler
1676
1779
  sametype = lambda { |t1, t2|
1677
1780
  t1 = t1.untypedef
1678
1781
  t2 = t2.untypedef
1679
- t1 = t1.pointed.untypedef if t1.pointer? and t1.pointed.untypedef.kind_of? C::Function
1680
- t2 = t2.pointed.untypedef if t2.pointer? and t2.pointed.untypedef.kind_of? C::Function
1782
+ t1 = t1.pointed.untypedef if t1.pointer? and t1.pointed.untypedef.kind_of?(C::Function)
1783
+ t2 = t2.pointed.untypedef if t2.pointer? and t2.pointed.untypedef.kind_of?(C::Function)
1681
1784
  t1 == t2 or
1682
- (t1.kind_of? C::Function and t2.kind_of? C::Function and sametype[t1.type, t2.type] and t1.args.to_a.length == t2.args.to_a.length and
1785
+ (t1.kind_of?(C::Function) and t2.kind_of?(C::Function) and sametype[t1.type, t2.type] and t1.args.to_a.length == t2.args.to_a.length and
1683
1786
  t1.args.to_a.zip(t2.args.to_a).all? { |st1, st2| sametype[st1.type, st2.type] }) or
1684
- (t1.kind_of? C::BaseType and t1.integral? and t2.kind_of? C::BaseType and t2.integral? and sizeof(nil, t1) == sizeof(nil, t2)) or
1787
+ (t1.kind_of?(C::BaseType) and t1.integral? and t2.kind_of?(C::BaseType) and t2.integral? and sizeof(nil, t1) == sizeof(nil, t2)) or
1685
1788
  (t1.pointer? and t2.pointer? and sametype[t1.type, t2.type])
1686
1789
  }
1687
1790
 
@@ -1689,56 +1792,92 @@ class Decompiler
1689
1792
  future_array = []
1690
1793
  walk_ce(scope, true) { |ce|
1691
1794
  # (whatever)0 => 0
1692
- if not ce.op and ce.rexpr.kind_of? C::CExpression and not ce.rexpr.op and ce.rexpr.rexpr == 0
1795
+ if not ce.op and ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and ce.rexpr.rexpr == 0
1693
1796
  ce.replace ce.rexpr
1694
1797
  end
1695
1798
 
1696
1799
  # *&bla => bla if types ok
1697
- if ce.op == :* and not ce.lexpr and ce.rexpr.kind_of? C::CExpression and ce.rexpr.op == :& and not ce.rexpr.lexpr and sametype[ce.rexpr.type.pointed, ce.rexpr.rexpr.type]
1800
+ if ce.op == :* and not ce.lexpr and ce.rexpr.kind_of?(C::CExpression) and ce.rexpr.op == :& and not ce.rexpr.lexpr and sametype[ce.rexpr.type.pointed, ce.rexpr.rexpr.type]
1698
1801
  ce.replace C::CExpression[ce.rexpr.rexpr]
1699
1802
  end
1700
1803
 
1701
- # int x + 0xffffffff -> x-1
1702
- if ce.lexpr and ce.rexpr.kind_of? C::CExpression and not ce.rexpr.op and [:+, :-, :'+=', :'-=', :'!=', :==, :>, :<, :>=, :<=].include? ce.op and
1804
+ # int x + 0xffffffff => x-1
1805
+ if ce.lexpr and ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and [:+, :-, :'+=', :'-=', :'!=', :==, :>, :<, :>=, :<=].include?(ce.op) and
1703
1806
  ce.rexpr.rexpr == (1 << (8*sizeof(ce.lexpr)))-1
1704
1807
  ce.op = {:+ => :-, :- => :+, :'+=' => :'-=', :'-=' => :'+='}[ce.op]
1705
1808
  ce.rexpr.rexpr = 1
1706
1809
  end
1707
1810
 
1811
+ # i + ptr => ptr + i
1812
+ if ce.op == :+ and ce.lexpr and ce.rexpr.type.pointer? and ce.lexpr.type.integral?
1813
+ ce.rexpr, ce.lexpr = ce.lexpr, ce.rexpr
1814
+ end
1815
+
1816
+ # i + v => v + i
1817
+ if ce.op == :+ and ce.lexpr.kind_of?(C::CExpression) and not ce.lexpr.op and ce.lexpr.rexpr.kind_of?(::Integer)
1818
+ # avoid infinite swapping
1819
+ if not ce.rexpr.kind_of?(C::CExpression) or ce.rexpr.op or not ce.rexpr.rexpr.kind_of?(::Integer)
1820
+ ce.rexpr, ce.lexpr = ce.lexpr, ce.rexpr
1821
+ end
1822
+ end
1823
+
1824
+ # (a + b) + c => a + (b + c)
1825
+ if ce.op == :+ and ce.lexpr.kind_of?(C::CExpression) and ce.lexpr.op == :+ and ce.lexpr.lexpr
1826
+ ce.lexpr, ce.rexpr = ce.lexpr.lexpr, C::CExpression[ce.lexpr.rexpr, :+, ce.rexpr]
1827
+ optimize_code(ce)
1828
+ end
1829
+
1830
+ # 1 + 2 => 3
1831
+ if (ce.op == :+ or ce.op == :- or ce.op == :*) and ce.lexpr.kind_of?(C::CExpression) and ce.type.integral? and not ce.lexpr.op and ce.lexpr.rexpr.kind_of?(::Integer) and ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and ce.rexpr.rexpr.kind_of?(::Integer)
1832
+ ce.lexpr, ce.op, ce.rexpr = nil, nil, ce.lexpr.rexpr.send(ce.op, ce.rexpr.rexpr)
1833
+ end
1834
+
1835
+ # 4 * (a + 1) => 4*a + 4
1836
+ if ce.op == :* and ce.lexpr.kind_of?(C::CExpression) and ce.type.integral? and not ce.lexpr.op and ce.lexpr.rexpr.kind_of?(::Integer) and ce.rexpr.kind_of?(C::CExpression) and (ce.rexpr.op == :+ or ce.rexpr.op == :-) and ce.rexpr.lexpr and ce.rexpr.rexpr.kind_of?(C::CExpression) and not ce.rexpr.rexpr.op and ce.rexpr.rexpr.rexpr.kind_of?(::Integer)
1837
+ ce.replace C::CExpression[[ce.lexpr, ce.op, ce.rexpr.lexpr], ce.rexpr.op, [ce.lexpr.rexpr * ce.rexpr.rexpr.rexpr]]
1838
+ optimize_code(ce)
1839
+ end
1840
+
1708
1841
  # int *ptr; *(ptr + 4) => ptr[4]
1709
- if ce.op == :* and not ce.lexpr and ce.rexpr.kind_of? C::CExpression and ce.rexpr.op == :+ and var = ce.rexpr.lexpr and var.kind_of? C::Variable and var.type.pointer?
1842
+ if ce.op == :* and not ce.lexpr and ce.rexpr.kind_of?(C::CExpression) and ce.rexpr.op == :+ and var = ce.rexpr.lexpr and var.kind_of?(C::Variable) and var.type.pointer?
1710
1843
  ce.lexpr, ce.op, ce.rexpr = ce.rexpr.lexpr, :'[]', ce.rexpr.rexpr
1711
1844
  future_array << var.name
1712
1845
  end
1713
1846
 
1847
+ # ptr + (i << 3) => ptr + 8*i
1848
+ if (ce.op == :+ or ce.op == :[]) and ce.rexpr.kind_of?(C::CExpression) and ce.rexpr.op == :<< and ce.rexpr.rexpr.kind_of?(C::CExpression) and not ce.rexpr.rexpr.op and ce.rexpr.rexpr.rexpr.kind_of?(::Integer)
1849
+ ce.rexpr.rexpr.rexpr = 1 << ce.rexpr.rexpr.rexpr
1850
+ ce.rexpr.lexpr, ce.rexpr.op, ce.rexpr.rexpr = ce.rexpr.rexpr, :*, ce.rexpr.lexpr
1851
+ end
1852
+
1714
1853
  # char x; x & 255 => x
1715
- if ce.op == :& and ce.lexpr and (ce.lexpr.type.integral? or ce.lexpr.type.pointer?) and ce.rexpr.kind_of? C::CExpression and
1716
- not ce.rexpr.op and ce.rexpr.rexpr.kind_of? ::Integer and m = (1 << (8*sizeof(ce.lexpr))) - 1 and
1854
+ if ce.op == :& and ce.lexpr and (ce.lexpr.type.integral? or ce.lexpr.type.pointer?) and ce.rexpr.kind_of?(C::CExpression) and
1855
+ not ce.rexpr.op and ce.rexpr.rexpr.kind_of?(::Integer) and m = (1 << (8*sizeof(ce.lexpr))) - 1 and
1717
1856
  ce.rexpr.rexpr & m == m
1718
1857
  ce.replace C::CExpression[ce.lexpr]
1719
1858
  end
1720
1859
 
1721
1860
  # a + -b => a - b
1722
- if ce.op == :+ and ce.lexpr and ce.rexpr.kind_of? C::CExpression and ce.rexpr.op == :- and not ce.rexpr.lexpr
1861
+ if ce.op == :+ and ce.lexpr and ce.rexpr.kind_of?(C::CExpression) and ce.rexpr.op == :- and not ce.rexpr.lexpr
1723
1862
  ce.op, ce.rexpr = :-, ce.rexpr.rexpr
1724
1863
  end
1725
1864
 
1726
1865
  # (((int) i >> 31) & 1) => i < 0
1727
- if ce.op == :& and ce.rexpr.kind_of? C::CExpression and not ce.rexpr.op and ce.rexpr.rexpr == 1 and
1728
- ce.lexpr.kind_of? C::CExpression and ce.lexpr.op == :>> and ce.lexpr.rexpr.kind_of? C::CExpression and
1866
+ if ce.op == :& and ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and ce.rexpr.rexpr == 1 and
1867
+ ce.lexpr.kind_of?(C::CExpression) and ce.lexpr.op == :>> and ce.lexpr.rexpr.kind_of?(C::CExpression) and
1729
1868
  not ce.lexpr.rexpr.op and ce.lexpr.rexpr.rexpr == sizeof(ce.lexpr.lexpr) * 8 - 1
1730
1869
  ce.replace C::CExpression[ce.lexpr.lexpr, :<, [0]]
1731
1870
  end
1732
1871
 
1733
1872
  # a-b == 0 => a == b
1734
- if ce.rexpr.kind_of? C::CExpression and not ce.rexpr.op and ce.rexpr.rexpr == 0 and [:==, :'!=', :<, :>, :<=, :>=].include? ce.op and
1735
- ce.lexpr.kind_of? C::CExpression and ce.lexpr.op == :- and ce.lexpr.lexpr
1873
+ if ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and ce.rexpr.rexpr == 0 and [:==, :'!=', :<, :>, :<=, :>=].include?(ce.op) and
1874
+ ce.lexpr.kind_of?(C::CExpression) and ce.lexpr.op == :- and ce.lexpr.lexpr
1736
1875
  ce.lexpr, ce.rexpr = ce.lexpr.lexpr, ce.lexpr.rexpr
1737
1876
  end
1738
1877
 
1739
1878
  # (a > 0) != 0
1740
- if ce.op == :'!=' and ce.rexpr.kind_of? C::CExpression and not ce.rexpr.op and ce.rexpr.rexpr == 0 and ce.lexpr.kind_of? C::CExpression and
1741
- [:<, :<=, :>, :>=, :'==', :'!=', :'!'].include? ce.lexpr.op
1879
+ if ce.op == :'!=' and ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and ce.rexpr.rexpr == 0 and ce.lexpr.kind_of?(C::CExpression) and
1880
+ [:<, :<=, :>, :>=, :'==', :'!=', :'!'].include?(ce.lexpr.op)
1742
1881
  ce.replace ce.lexpr
1743
1882
  end
1744
1883
 
@@ -1747,21 +1886,21 @@ class Decompiler
1747
1886
  # a>=b => true if r => a<0 == b>=0 and a<0 => a<0 and b>=0
1748
1887
 
1749
1888
  # x != (a && (b != x)) => [x && (!a || b)] || [!x && !(!a || b)]
1750
- if ce.op == :'!=' and ce.lexpr.kind_of? C::CExpression and ce.lexpr.op == :< and ce.rexpr.kind_of? C::CExpression and
1751
- ce.rexpr.op == :'&&' and ce.rexpr.rexpr.kind_of? C::CExpression and ce.rexpr.rexpr.op == :'!=' and
1889
+ if ce.op == :'!=' and ce.lexpr.kind_of?(C::CExpression) and ce.lexpr.op == :< and ce.rexpr.kind_of?(C::CExpression) and
1890
+ ce.rexpr.op == :'&&' and ce.rexpr.rexpr.kind_of?(C::CExpression) and ce.rexpr.rexpr.op == :'!=' and
1752
1891
  ce.rexpr.rexpr.rexpr == ce.lexpr and not walk_ce(ce) { |ce_| break true if ce_.op == :funcall }
1753
1892
  x, a, b = ce.lexpr, ce.rexpr.lexpr, ce.rexpr.rexpr.lexpr
1754
1893
  ce.replace C::CExpression[ [x, :'&&', [[:'!',a],:'||',b]] , :'||', [[:'!', x], :'&&', [:'!', [[:'!',a],:'||',b]]] ]
1755
1894
  optimize_code(ce)
1756
1895
  end
1757
1896
  # (a != b) || a => a || b
1758
- if ce.op == :'||' and ce.lexpr.kind_of? C::CExpression and ce.lexpr.op == :'!=' and ce.lexpr.lexpr == ce.rexpr and not walk_ce(ce) { |ce_| break true if ce_.op == :funcall }
1897
+ if ce.op == :'||' and ce.lexpr.kind_of?(C::CExpression) and ce.lexpr.op == :'!=' and ce.lexpr.lexpr == ce.rexpr and not walk_ce(ce) { |ce_| break true if ce_.op == :funcall }
1759
1898
  ce.lexpr, ce.rexpr = ce.rexpr, ce.lexpr.rexpr
1760
1899
  optimize_code(ce)
1761
1900
  end
1762
1901
  # (a<b) && !(a>=0 && b<0) || (a>=b) && (a>=0 && b<0) => (signed)a < (signed)b
1763
- if ce.op == :'||' and ce.lexpr.kind_of? C::CExpression and ce.rexpr.kind_of? C::CExpression and ce.lexpr.op == :'&&' and ce.rexpr.op == :'&&' and
1764
- ce.lexpr.lexpr.kind_of? C::CExpression and ce.lexpr.lexpr.op == :<
1902
+ if ce.op == :'||' and ce.lexpr.kind_of?(C::CExpression) and ce.rexpr.kind_of?(C::CExpression) and ce.lexpr.op == :'&&' and ce.rexpr.op == :'&&' and
1903
+ ce.lexpr.lexpr.kind_of?(C::CExpression) and ce.lexpr.lexpr.op == :<
1765
1904
  a, b = ce.lexpr.lexpr.lexpr, ce.lexpr.lexpr.rexpr
1766
1905
  if ce.lexpr.rexpr === C::CExpression[[a, :'>=', [0]], :'&&', [b, :'<', [0]]].negate and
1767
1906
  ce.rexpr.lexpr === ce.lexpr.lexpr.negate and ce.rexpr.rexpr === ce.lexpr.rexpr.negate
@@ -1769,7 +1908,7 @@ class Decompiler
1769
1908
  end
1770
1909
  end
1771
1910
  # a && 1
1772
- if (ce.op == :'||' or ce.op == :'&&') and ce.rexpr.kind_of? C::CExpression and not ce.rexpr.op and ce.rexpr.rexpr.kind_of? ::Integer
1911
+ if (ce.op == :'||' or ce.op == :'&&') and ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and ce.rexpr.rexpr.kind_of?(::Integer)
1773
1912
  if ((ce.op == :'||' and ce.rexpr.rexpr == 0) or (ce.op == :'&&' and ce.rexpr.rexpr != 0))
1774
1913
  ce.replace C::CExpression[ce.lexpr]
1775
1914
  elsif not walk_ce(ce) { |ce_| break true if ce.op == :funcall } # cannot wipe if sideeffect
@@ -1782,82 +1921,76 @@ class Decompiler
1782
1921
  end
1783
1922
 
1784
1923
  # (a < b) | (a == b) => a <= b
1785
- if ce.op == :| and ce.rexpr.kind_of? C::CExpression and ce.rexpr.op == :== and ce.lexpr.kind_of? C::CExpression and
1924
+ if ce.op == :| and ce.rexpr.kind_of?(C::CExpression) and ce.rexpr.op == :== and ce.lexpr.kind_of?(C::CExpression) and
1786
1925
  (ce.lexpr.op == :< or ce.lexpr.op == :>) and ce.lexpr.lexpr == ce.rexpr.lexpr and ce.lexpr.rexpr == ce.rexpr.rexpr
1787
1926
  ce.op = {:< => :<=, :> => :>=}[ce.lexpr.op]
1788
1927
  ce.lexpr, ce.rexpr = ce.lexpr.lexpr, ce.lexpr.rexpr
1789
1928
  end
1790
1929
 
1791
1930
  # a == 0 => !a
1792
- if ce.op == :== and ce.rexpr.kind_of? C::CExpression and not ce.rexpr.op and ce.rexpr.rexpr == 0
1931
+ if ce.op == :== and ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and ce.rexpr.rexpr == 0
1793
1932
  ce.lexpr, ce.op, ce.rexpr = nil, :'!', ce.lexpr
1794
1933
  end
1795
1934
 
1796
- if ce.op == :'!' and ce.rexpr.kind_of? C::CExpression and not ce.rexpr.op and ce.rexpr.rexpr.kind_of? ::Integer
1935
+ if ce.op == :'!' and ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and ce.rexpr.rexpr.kind_of?(::Integer)
1797
1936
  ce.replace C::CExpression[[ce.rexpr.rexpr == 0 ? 1 : 0]]
1798
1937
  end
1799
1938
 
1800
1939
  # !(bool) => bool
1801
- if ce.op == :'!' and ce.rexpr.kind_of? C::CExpression and [:'==', :'!=', :<, :>, :<=, :>=, :'||', :'&&', :'!'].include? ce.rexpr.op
1940
+ if ce.op == :'!' and ce.rexpr.kind_of?(C::CExpression) and [:'==', :'!=', :<, :>, :<=, :>=, :'||', :'&&', :'!'].include?(ce.rexpr.op)
1802
1941
  ce.replace ce.rexpr.negate
1803
1942
  end
1804
1943
 
1805
1944
  # (foo)(bar)x => (foo)x
1806
- if not ce.op and ce.rexpr.kind_of? C::CExpression and not ce.rexpr.op and ce.rexpr.rexpr.kind_of? C::CExpression
1945
+ if not ce.op and ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and ce.rexpr.rexpr.kind_of?(C::CExpression)
1807
1946
  ce.rexpr = ce.rexpr.rexpr
1808
1947
  end
1809
1948
 
1810
1949
  # &struct.1stmember => &struct
1811
- if ce.op == :& and not ce.lexpr and ce.rexpr.kind_of? C::CExpression and ce.rexpr.op == :'.' and s = ce.rexpr.lexpr.type and
1812
- s.kind_of? C::Union and s.offsetof(@c_parser, ce.rexpr.rexpr) == 0
1950
+ if ce.op == :& and not ce.lexpr and ce.rexpr.kind_of?(C::CExpression) and ce.rexpr.op == :'.' and s = ce.rexpr.lexpr.type and
1951
+ s.kind_of?(C::Union) and s.offsetof(@c_parser, ce.rexpr.rexpr) == 0
1813
1952
  ce.rexpr = ce.rexpr.lexpr
1814
1953
  ce.type = C::Pointer.new(ce.rexpr.type)
1815
1954
  end
1816
1955
 
1817
1956
  # (1stmember*)structptr => &structptr->1stmember
1818
- if not ce.op and ce.type.pointer? and not ce.type.pointed.void? and ce.rexpr.kind_of? C::Typed and ce.rexpr.type.pointer? and
1819
- s = ce.rexpr.type.pointed.untypedef and s.kind_of? C::Union and ce.type.pointed.untypedef != s
1957
+ if not ce.op and ce.type.pointer? and not ce.type.pointed.void? and ce.rexpr.kind_of?(C::Typed) and ce.rexpr.type.pointer? and
1958
+ s = ce.rexpr.type.pointed.untypedef and s.kind_of?(C::Union) and ce.type.pointed.untypedef != s
1820
1959
  ce.rexpr = C::CExpression[structoffset(s, ce.rexpr, 0, sizeof(ce.type.pointed))]
1821
- #ce.replace ce.rexpr if not ce.type.pointed.untypedef.kind_of? C::Function or (ce.rexpr.type.pointer? and
1822
- #ce.rexpr.type.pointed.untypedef.kind_of? C::Function) # XXX ugly
1960
+ #ce.replace ce.rexpr if not ce.type.pointed.untypedef.kind_of?(C::Function) or (ce.rexpr.type.pointer? and
1961
+ #ce.rexpr.type.pointed.untypedef.kind_of?(C::Function)) # XXX ugly
1823
1962
  # int32* v1 = (int32*)pstruct;
1824
1963
  # z = v1+4 if v1 is not cast, the + is invalid (sizeof pointed changes)
1825
1964
  # TODO when finding type of pstruct, set type of v1 accordingly
1826
1965
  end
1827
1966
 
1828
1967
  # (&foo)->bar => foo.bar
1829
- if ce.op == :'->' and ce.lexpr.kind_of? C::CExpression and ce.lexpr.op == :& and not ce.lexpr.lexpr
1968
+ if ce.op == :'->' and ce.lexpr.kind_of?(C::CExpression) and ce.lexpr.op == :& and not ce.lexpr.lexpr
1830
1969
  ce.lexpr = ce.lexpr.rexpr
1831
1970
  ce.op = :'.'
1832
1971
  end
1833
1972
 
1834
1973
  # (foo)bla => bla if bla of type foo
1835
- if not ce.op and ce.rexpr.kind_of? C::Typed and sametype[ce.type, ce.rexpr.type]
1974
+ if not ce.op and ce.rexpr.kind_of?(C::Typed) and sametype[ce.type, ce.rexpr.type]
1836
1975
  ce.replace C::CExpression[ce.rexpr]
1837
1976
  end
1838
- if ce.lexpr.kind_of? C::CExpression and not ce.lexpr.op and ce.lexpr.rexpr.kind_of? C::Variable and ce.lexpr.type == ce.lexpr.rexpr.type
1977
+ if ce.lexpr.kind_of?(C::CExpression) and not ce.lexpr.op and ce.lexpr.rexpr.kind_of?(C::Variable) and ce.lexpr.type == ce.lexpr.rexpr.type
1839
1978
  ce.lexpr = ce.lexpr.rexpr
1840
1979
  end
1841
-
1842
- if ce.op == :'=' and ce.lexpr.kind_of? C::CExpression and ce.lexpr.op == :* and not ce.lexpr.lexpr and ce.lexpr.rexpr.kind_of? C::CExpression and
1843
- not ce.lexpr.rexpr.op and ce.lexpr.rexpr.type.pointer? and ce.lexpr.rexpr.type.pointed != ce.rexpr.type
1844
- ce.lexpr.rexpr.type = C::Pointer.new(ce.rexpr.type)
1845
- optimize_code(ce.lexpr)
1846
- end
1847
1980
  }
1848
1981
 
1849
1982
  # if there is a ptr[4], change all *ptr to ptr[0] for consistency
1850
1983
  # do this after the first pass, which may change &*ptr to ptr
1851
1984
  walk_ce(scope) { |ce|
1852
- if ce.op == :* and not ce.lexpr and ce.rexpr.kind_of? C::Variable and future_array.include? ce.rexpr.name
1985
+ if ce.op == :* and not ce.lexpr and ce.rexpr.kind_of?(C::Variable) and future_array.include?(ce.rexpr.name)
1853
1986
  ce.lexpr, ce.op, ce.rexpr = ce.rexpr, :'[]', C::CExpression[0]
1854
1987
  end
1855
1988
  } if not future_array.empty?
1856
1989
 
1857
1990
  # if (x != 0) => if (x)
1858
1991
  walk(scope) { |st|
1859
- if st.kind_of? C::If and st.test.kind_of? C::CExpression and st.test.op == :'!=' and
1860
- st.test.rexpr.kind_of? C::CExpression and not st.test.rexpr.op and st.test.rexpr.rexpr == 0
1992
+ if st.kind_of?(C::If) and st.test.kind_of?(C::CExpression) and st.test.op == :'!=' and
1993
+ st.test.rexpr.kind_of?(C::CExpression) and not st.test.rexpr.op and st.test.rexpr.rexpr == 0
1861
1994
  st.test = C::CExpression[st.test.lexpr]
1862
1995
  end
1863
1996
  }
@@ -1868,8 +2001,8 @@ class Decompiler
1868
2001
  case exp
1869
2002
  when nil, ::Numeric, ::String; false
1870
2003
  when ::Array; exp.any? { |_e| sideeffect _e, scope }
1871
- when C::Variable; (scope and not scope.symbol[exp.name]) or exp.type.qualifier.to_a.include? :volatile
1872
- when C::CExpression; (exp.op == :* and not exp.lexpr) or exp.op == :funcall or AssignOp.include?(exp.op) or
2004
+ when C::Variable; (scope and not scope.symbol[exp.name]) or exp.type.qualifier.to_a.include?(:volatile)
2005
+ when C::CExpression; (exp.op == :* and not exp.lexpr) or exp.op == :funcall or C::CExpression::AssignOp.include?(exp.op) or
1873
2006
  sideeffect(exp.lexpr, scope) or sideeffect(exp.rexpr, scope)
1874
2007
  else true # failsafe
1875
2008
  end
@@ -1878,97 +2011,153 @@ class Decompiler
1878
2011
  # converts C code to a graph of cexprs (nodes = cexprs, edges = codepaths)
1879
2012
  # returns a CGraph
1880
2013
  class CGraph
1881
- # exprs: label => [exprs], to: label => [labels], block: label => are exprs standalone (vs If#test), start: 1st label
2014
+ # exprs: label => [exprs], to: label => [labels], block: label => are exprs in a block (vs If#test), start: 1st label
1882
2015
  attr_accessor :exprs, :to, :block, :start, :to_optim, :from_optim
1883
- end
1884
- def c_to_graph(st)
1885
- g = CGraph.new
1886
- g.exprs = {} # label => [exprs]
1887
- g.to = {} # label => [labels]
1888
- g.block = {} # label => is label in a block? (vs If#test)
1889
- anon_label = 0 # when no label is there, use anon_label++
2016
+
2017
+ def initialize
2018
+ @exprs = {} # label => [exprs]
2019
+ @to = {} # label => [labels]
2020
+ @block = {} # label => is label in a block? (vs If#test)
2021
+ @anon_label = 0 # when no label is there, use anon_label++
2022
+ @exprs_var = nil # similar to @exprs, indexed by var name, lazy initialization
2023
+ end
2024
+
2025
+ def build(stmt)
2026
+ @start = @anon_label
2027
+ to_graph(stmt, @start, nil, nil, nil)
2028
+ optimize
2029
+ self
2030
+ end
2031
+
1890
2032
  # converts C code to a graph of codepath of cexprs
1891
- to_graph = lambda { |stmt, l_cur, l_after, l_cont, l_break|
2033
+ def to_graph(stmt, l_cur, l_after, l_cont, l_break)
1892
2034
  case stmt
1893
- when C::Label; g.to[l_cur] = [stmt.name] ; g.to[stmt.name] = [l_after]
1894
- when C::Goto; g.to[l_cur] = [stmt.target]
1895
- when C::Continue; g.to[l_cur] = [l_cont]
1896
- when C::Break; g.to[l_cur] = [l_break]
2035
+ when C::Label; @to[l_cur] = [stmt.name] ; @to[stmt.name] = [l_after]
2036
+ when C::Goto; @to[l_cur] = [stmt.target]
2037
+ when C::Continue; @to[l_cur] = [l_cont]
2038
+ when C::Break; @to[l_cur] = [l_break]
1897
2039
  when C::CExpression
1898
- g.exprs[l_cur] = [stmt]
1899
- g.to[l_cur] = [l_after]
2040
+ @exprs[l_cur] = [stmt]
2041
+ @to[l_cur] = [l_after]
1900
2042
  when C::Return
1901
- g.exprs[l_cur] = [stmt.value] if stmt.value
1902
- g.to[l_cur] = []
2043
+ @exprs[l_cur] = [stmt.value] if stmt.value
2044
+ @to[l_cur] = []
1903
2045
  when C::Block
1904
- to_graph[stmt.statements, l_cur, l_after, l_cont, l_break]
2046
+ to_graph(stmt.statements, l_cur, l_after, l_cont, l_break)
1905
2047
  when ::Array
1906
- g.exprs[l_cur] = []
1907
- g.block[l_cur] = true
2048
+ @exprs[l_cur] = []
2049
+ @block[l_cur] = true
1908
2050
  stmt.each_with_index { |s, i|
1909
2051
  case s
1910
2052
  when C::Declaration
1911
2053
  when C::CExpression
1912
- g.exprs[l_cur] << s
2054
+ @exprs[l_cur] << s
1913
2055
  else
1914
- l = anon_label += 1
1915
- ll = anon_label += 1
1916
- g.to[l_cur] = [l]
1917
- g.block[l_cur] = true
1918
- to_graph[stmt[i], l, ll, l_cont, l_break]
2056
+ l = @anon_label += 1
2057
+ ll = @anon_label += 1
2058
+ @to[l_cur] = [l]
2059
+ @block[l_cur] = true
2060
+ to_graph(stmt[i], l, ll, l_cont, l_break)
1919
2061
  l_cur = ll
1920
- g.exprs[l_cur] = []
2062
+ @exprs[l_cur] = []
1921
2063
  end
1922
2064
  }
1923
- g.to[l_cur] = [l_after].compact
2065
+ @to[l_cur] = [l_after].compact
1924
2066
  when C::If
1925
- g.exprs[l_cur] = [stmt.test]
1926
- lt = anon_label += 1
1927
- to_graph[stmt.bthen, lt, l_after, l_cont, l_break]
1928
- le = anon_label += 1
1929
- to_graph[stmt.belse, le, l_after, l_cont, l_break]
1930
- g.to[l_cur] = [lt, le]
2067
+ @exprs[l_cur] = [stmt.test]
2068
+ lt = @anon_label += 1
2069
+ to_graph(stmt.bthen, lt, l_after, l_cont, l_break)
2070
+ le = @anon_label += 1
2071
+ to_graph(stmt.belse, le, l_after, l_cont, l_break)
2072
+ @to[l_cur] = [lt, le]
1931
2073
  when C::While, C::DoWhile
1932
- la = anon_label += 1
1933
- if stmt.kind_of? C::DoWhile
2074
+ la = @anon_label += 1
2075
+ if stmt.kind_of?(C::DoWhile)
1934
2076
  lt, lb = la, l_cur
1935
2077
  else
1936
2078
  lt, lb = l_cur, la
1937
2079
  end
1938
- g.exprs[lt] = [stmt.test]
1939
- g.to[lt] = [lb, l_after]
1940
- to_graph[stmt.body, lb, lt, lt, l_after]
1941
- when C::Asm, nil; g.to[l_cur] = [l_after]
2080
+ @exprs[lt] = [stmt.test]
2081
+ @to[lt] = [lb, l_after]
2082
+ to_graph(stmt.body, lb, lt, lt, l_after)
2083
+ when C::Asm, nil; @to[l_cur] = [l_after]
1942
2084
  else puts "to_graph unhandled #{stmt.class}: #{stmt}" if $VERBOSE
1943
2085
  end
1944
- }
1945
-
1946
- g.start = anon_label
1947
- to_graph[st, g.start, nil, nil, nil]
2086
+ end
1948
2087
 
1949
2088
  # optimize graph
1950
- g.to_optim = {}
1951
- g.to.each { |k, v| g.to_optim[k] = v.uniq }
1952
- g.exprs.delete_if { |k, v| v == [] }
1953
- g.to_optim.delete_if { |k, v|
1954
- if v.length == 1 and not g.exprs[k] and v != [k]
1955
- g.to_optim.each_value { |t| if i = t.index(k) ; t[i] = v.first ; end }
1956
- true
1957
- elsif v.length == 0 and not g.exprs[k]
1958
- g.to_optim.each_value { |t| t.delete k }
1959
- true
2089
+ def optimize
2090
+ @to_optim = {}
2091
+ @to.each { |k, v| @to_optim[k] = v.uniq }
2092
+ @exprs.delete_if { |k, v| v == [] }
2093
+ @to_optim.delete_if { |k, v|
2094
+ if v.length == 1 and not @exprs[k] and v != [k]
2095
+ @to_optim.each_value { |t| if i = t.index(k) ; t[i] = v.first ; end }
2096
+ true
2097
+ elsif v.length == 0 and not @exprs[k]
2098
+ @to_optim.each_value { |t| t.delete k }
2099
+ true
2100
+ end
2101
+ }
2102
+
2103
+ @from_optim = {}
2104
+ @to_optim.each { |k, v| v.each { |t| (@from_optim[t] ||= []) << k } }
2105
+ end
2106
+
2107
+ # varname => { label => [list of indices of @exprs[label] referencing varname] }
2108
+ def exprs_var
2109
+ @exprs_var ||= init_exprs_var
2110
+ end
2111
+
2112
+ # returns the list of variable names referenced by a CExpr
2113
+ def get_expr_vars(e)
2114
+ case e
2115
+ when C::CExpression; get_expr_vars(e.lexpr) + get_expr_vars(e.rexpr)
2116
+ when ::Array; e.inject([]) { |a, ee| a.concat get_expr_vars(ee) }
2117
+ when C::Variable; [e.name]
2118
+ else; []
1960
2119
  end
1961
- }
2120
+ end
1962
2121
 
1963
- g.from_optim = {}
1964
- g.to_optim.each { |k, v| v.each { |t| (g.from_optim[t] ||= []) << k } }
2122
+ # initialize @exprs_var
2123
+ def init_exprs_var
2124
+ @exprs_var = {}
2125
+ @exprs.each_key { |label| update_exprs_var(label) }
2126
+ @exprs_var
2127
+ end
1965
2128
 
1966
- g
2129
+ # populate one label of @exprs_var
2130
+ def update_exprs_var(label)
2131
+ @exprs[label].each_with_index { |e, idx|
2132
+ get_expr_vars(e).uniq.each { |varname|
2133
+ @exprs_var[varname] ||= {}
2134
+ @exprs_var[varname][label] ||= []
2135
+ @exprs_var[varname][label] << idx
2136
+ }
2137
+ }
2138
+ end
2139
+
2140
+ # invalidates one label (eg exprs were deleted)
2141
+ # rebuilds @exprs_var if necessary
2142
+ def invalidate(label=nil)
2143
+ if @exprs_var
2144
+ if label
2145
+ @exprs_var.each { |v, h| h.delete(label) }
2146
+ update_exprs_var(label)
2147
+ else
2148
+ @exprs_var = nil
2149
+ end
2150
+ end
2151
+ end
2152
+ end
2153
+ def c_to_graph(stmt)
2154
+ CGraph.new.build(stmt)
1967
2155
  end
1968
2156
 
1969
2157
  # dataflow optimization
1970
2158
  # condenses expressions (++x; if (x) => if (++x))
1971
2159
  # remove local var assignment (x = 1; f(x); x = 2; g(x); => f(1); g(2); etc)
2160
+ # XXX omg
1972
2161
  def optimize_vars(scope)
1973
2162
  return if forbid_optimize_dataflow
1974
2163
 
@@ -1996,36 +2185,40 @@ class Decompiler
1996
2185
 
1997
2186
  # badlabels is a list of labels that may be reached without passing through the first invocation block
1998
2187
  find_next_read_rec = lambda { |label, idx, var, done, badlabels|
1999
- next if done.include? label
2188
+ next if done.include?(label)
2000
2189
  done << label if idx == 0
2190
+ list = g.exprs_var[var.name][label].to_a.find_all { |i| i >= idx }
2191
+ idx = list.shift
2001
2192
 
2002
- idx += 1 while ce = g.exprs[label].to_a[idx] and not ret = find_next_read_ce[ce, var]
2193
+ idx = list.shift while idx and not ret = find_next_read_ce[g.exprs[label][idx], var]
2003
2194
  next ret if ret
2004
2195
 
2005
2196
  to = g.to_optim[label].to_a.map { |t|
2006
- break [:split] if badlabels.include? t
2197
+ break [:split] if badlabels.include?(t)
2007
2198
  find_next_read_rec[t, 0, var, done, badlabels]
2008
2199
  }.compact
2009
2200
 
2010
2201
  tw = to - [:write]
2011
- if to.include? :split or tw.length > 1
2202
+ if to.include?(:split) or tw.length > 1
2012
2203
  :split
2013
2204
  elsif tw.length == 1
2014
2205
  tw.first
2015
- elsif to.include? :write
2206
+ elsif to.include?(:write)
2016
2207
  :write
2017
2208
  end
2018
2209
  }
2019
2210
  # return the previous subexpr reading var with no fwd path to another reading (otherwise split), see loop comment for reason
2020
2211
  find_next_read = nil
2021
2212
  find_prev_read_rec = lambda { |label, idx, var, done|
2022
- next if done.include? label
2213
+ next if done.include?(label)
2023
2214
  done << label if idx == g.exprs[label].length-1
2215
+ list = g.exprs_var[var.name][label].to_a.find_all { |i| i <= idx }
2216
+ idx = list.pop
2024
2217
 
2025
- idx -= 1 while idx >= 0 and ce = g.exprs[label].to_a[idx] and not ret = find_next_read_ce[ce, var]
2026
- if ret.kind_of? C::CExpression
2218
+ idx = list.pop while idx and not ret = find_next_read_ce[g.exprs[label][idx], var]
2219
+ if ret.kind_of?(C::CExpression)
2027
2220
  fwchk = find_next_read[label, idx+1, var]
2028
- ret = fwchk if not fwchk.kind_of? C::CExpression
2221
+ ret = fwchk if not fwchk.kind_of?(C::CExpression)
2029
2222
  end
2030
2223
  next ret if ret
2031
2224
 
@@ -2033,25 +2226,25 @@ class Decompiler
2033
2226
  find_prev_read_rec[f, g.exprs[f].to_a.length-1, var, done]
2034
2227
  }.compact
2035
2228
 
2036
- next :split if from.include? :split
2229
+ next :split if from.include?(:split)
2037
2230
  fw = from - [:write]
2038
2231
  if fw.length == 1
2039
2232
  fw.first
2040
2233
  elsif fw.length > 1
2041
2234
  :split
2042
- elsif from.include? :write
2235
+ elsif from.include?(:write)
2043
2236
  :write
2044
2237
  end
2045
2238
  }
2046
2239
 
2047
- # list of labels reachable without using a label
2240
+ # list of labels reachable without passing through label
2048
2241
  badlab = {}
2049
2242
  build_badlabel = lambda { |label|
2050
2243
  next if badlab[label]
2051
2244
  badlab[label] = []
2052
2245
  todo = [g.start]
2053
2246
  while l = todo.pop
2054
- next if l == label or badlab[label].include? l
2247
+ next if l == label or badlab[label].include?(l)
2055
2248
  badlab[label] << l
2056
2249
  todo.concat g.to_optim[l].to_a
2057
2250
  end
@@ -2085,10 +2278,10 @@ class Decompiler
2085
2278
 
2086
2279
  # TODO x = x + 1 => x += 1 => ++x here, move all other optimizations after (in optim_code)
2087
2280
  # needs also int & 0xffffffff -> int, *&var etc (decomp_type? optim_type?)
2088
- if (e.op == :'++' or e.op == :'--') and v = (e.lexpr || e.rexpr) and v.kind_of? C::Variable and
2089
- scope.symbol[v.name] and not v.type.qualifier.to_a.include? :volatile
2090
- next if !((pos = :post.to_sym) and (oe = find_next_read_bl[label, i, v]) and oe.kind_of? C::CExpression) and
2091
- !((pos = :prev.to_sym) and (oe = find_prev_read[label, i-2, v]) and oe.kind_of? C::CExpression)
2281
+ if (e.op == :'++' or e.op == :'--') and v = (e.lexpr || e.rexpr) and v.kind_of?(C::Variable) and
2282
+ scope.symbol[v.name] and not v.type.qualifier.to_a.include?(:volatile)
2283
+ next if !((pos = :post.to_sym) and (oe = find_next_read_bl[label, i, v]) and oe.kind_of?(C::CExpression)) and
2284
+ !((pos = :prev.to_sym) and (oe = find_prev_read[label, i-2, v]) and oe.kind_of?(C::CExpression))
2092
2285
  next if oe.op == :& and not oe.lexpr # no &(++eax)
2093
2286
 
2094
2287
  # merge pre/postincrement into next/prev var usage
@@ -2121,7 +2314,7 @@ class Decompiler
2121
2314
  when :'+=', :'-='
2122
2315
  # TODO i++; i += 4 => i += 5
2123
2316
  next
2124
- when *AssignOp
2317
+ when *C::CExpression::AssignOp
2125
2318
  next # ++i; i |= 4 => ignore
2126
2319
  else
2127
2320
  if pos == :post and v == oe.lexpr; oe.lexpr = C::CExpression[e.op, v]
@@ -2134,16 +2327,27 @@ class Decompiler
2134
2327
 
2135
2328
  i -= 1
2136
2329
  exprs.delete_at(i)
2330
+ g.invalidate(label)
2137
2331
  e.lexpr = e.op = e.rexpr = nil
2138
2332
 
2139
2333
 
2140
- elsif e.op == :'=' and v = e.lexpr and v.kind_of? C::Variable and scope.symbol[v.name] and
2141
- not v.type.qualifier.to_a.include? :volatile and not find_next_read_ce[e.rexpr, v]
2334
+ elsif e.op == :'=' and v = e.lexpr and v.kind_of?(C::Variable) and scope.symbol[v.name] and
2335
+ not v.type.qualifier.to_a.include?(:volatile) and not find_next_read_ce[e.rexpr, v]
2142
2336
 
2143
2337
  # reduce trivial static assignments
2144
- if (e.rexpr.kind_of? C::CExpression and iv = e.rexpr.reduce(@c_parser) and iv.kind_of? ::Integer) or
2145
- (e.rexpr.kind_of? C::CExpression and e.rexpr.op == :& and not e.rexpr.lexpr and e.rexpr.lexpr.kind_of? C::Variable) or
2146
- (e.rexpr.kind_of? C::Variable and e.rexpr.type.kind_of? C::Array)
2338
+ # b = a + 1 ; a = b => a = a + 1 ; b = a
2339
+ if ne = g.exprs[label][i] and ne.op == :'=' and ne.rexpr == e.lexpr and ne.lexpr.kind_of?(C::Variable) and find_next_read_ce[e.rexpr, ne.lexpr]
2340
+ e.lexpr, ne.lexpr, ne.rexpr = ne.lexpr, ne.rexpr, ne.lexpr
2341
+ optimize_code(e)
2342
+ i -= 1
2343
+ g.invalidate(label)
2344
+ next
2345
+ end
2346
+
2347
+ # i = 4 ; f(i) => f(4)
2348
+ if (e.rexpr.kind_of?(C::CExpression) and iv = e.rexpr.reduce(@c_parser) and iv.kind_of?(::Integer)) or
2349
+ (e.rexpr.kind_of?(C::CExpression) and e.rexpr.op == :& and not e.rexpr.lexpr and e.rexpr.lexpr.kind_of?(C::Variable)) or
2350
+ (e.rexpr.kind_of?(C::Variable) and e.rexpr.type.kind_of?(C::Array))
2147
2351
  rewritten = false
2148
2352
  readers = []
2149
2353
  discard = [e]
@@ -2173,7 +2377,7 @@ class Decompiler
2173
2377
  end
2174
2378
  end
2175
2379
 
2176
- case nr = find_next_read[label, i, v]
2380
+ case find_next_read[label, i, v]
2177
2381
  when C::CExpression
2178
2382
  # read in one place only, try to patch rexpr in there
2179
2383
  r = e.rexpr
@@ -2183,12 +2387,12 @@ class Decompiler
2183
2387
  isfunc = false
2184
2388
  depend_vars = []
2185
2389
  walk_ce(C::CExpression[r]) { |ce|
2186
- isfunc = true if ce.op == :func and (not ce.lexpr.kind_of? C::Variable or
2390
+ isfunc = true if ce.op == :func and (not ce.lexpr.kind_of?(C::Variable) or
2187
2391
  not ce.lexpr.has_attribute('pure')) # XXX is there a C attr for func depending only on staticvars+param ?
2188
- depend_vars << ce.lexpr if ce.lexpr.kind_of? C::Variable
2189
- depend_vars << ce.rexpr if ce.rexpr.kind_of? C::Variable and (ce.lexpr or ce.op != :&) # a = &v; v = 12; func(a) => func(&v)
2392
+ depend_vars << ce.lexpr if ce.lexpr.kind_of?(C::Variable)
2393
+ depend_vars << ce.rexpr if ce.rexpr.kind_of?(C::Variable) and (ce.lexpr or ce.op != :&) # a = &v; v = 12; func(a) => func(&v)
2190
2394
  depend_vars << ce if ce.lvalue?
2191
- depend_vars.concat(ce.rexpr.grep(C::Variable)) if ce.rexpr.kind_of? ::Array
2395
+ depend_vars.concat(ce.rexpr.grep(C::Variable)) if ce.rexpr.kind_of?(::Array)
2192
2396
  }
2193
2397
  depend_vars.uniq!
2194
2398
 
@@ -2209,11 +2413,11 @@ class Decompiler
2209
2413
  ce.rexpr.each { |a| cnt += 1 if a == v }
2210
2414
  cnt += 1 if ce.lexpr == v
2211
2415
  when :'='
2212
- bad = true if depend_vars.include? ce.lexpr
2416
+ bad = true if depend_vars.include?(ce.lexpr)
2213
2417
  cnt += 1 if ce.rexpr == v
2214
2418
  else
2215
- bad = true if (ce.op == :'++' or ce.op == :'--') and depend_vars.include? ce.rexpr
2216
- bad = true if AssignOp.include? ce.op and depend_vars.include? ce.lexpr
2419
+ bad = true if (ce.op == :'++' or ce.op == :'--') and depend_vars.include?(ce.rexpr)
2420
+ bad = true if C::CExpression::AssignOp.include?(ce.op) and depend_vars.include?(ce.lexpr)
2217
2421
  cnt += 1 if ce.lexpr == v
2218
2422
  cnt += 1 if ce.rexpr == v
2219
2423
  end
@@ -2226,7 +2430,7 @@ class Decompiler
2226
2430
  break if e.complexity > 10 and ce_.complexity > 3 # try to keep the C readable
2227
2431
  # x = 1; y = x; z = x; => cannot suppress x
2228
2432
  nr = find_next_read[l_l, n_i+1, v]
2229
- break if (nr.kind_of? C::CExpression or nr == :split) and not walk_ce(ce_) { |ce| break true if ce.op == :'=' and ce.lexpr == v }
2433
+ break if (nr.kind_of?(C::CExpression) or nr == :split) and not walk_ce(ce_) { |ce| break true if ce.op == :'=' and ce.lexpr == v }
2230
2434
  else break # a = 1; b = a + a => fail
2231
2435
  end
2232
2436
 
@@ -2246,12 +2450,12 @@ class Decompiler
2246
2450
  elsif isfunc
2247
2451
  break :fail
2248
2452
  end
2249
- when *AssignOp
2250
- break :fail if not ce.lexpr and depend_vars.include? ce.rexpr # ++depend
2453
+ when *C::CExpression::AssignOp
2454
+ break :fail if not ce.lexpr and depend_vars.include?(ce.rexpr) # ++depend
2251
2455
  if ce.rexpr == v
2252
2456
  ce.rexpr = r
2253
2457
  break :done
2254
- elsif ce.lexpr == v or depend_vars.include? ce.lexpr
2458
+ elsif ce.lexpr == v or depend_vars.include?(ce.lexpr)
2255
2459
  break :fail
2256
2460
  end
2257
2461
  else
@@ -2270,6 +2474,8 @@ class Decompiler
2270
2474
  when :done
2271
2475
  i -= 1
2272
2476
  exprs.delete_at(i)
2477
+ g.invalidate(label)
2478
+ g.invalidate(l_l) if l_l != label
2273
2479
  e.lexpr = e.op = e.rexpr = nil
2274
2480
  break
2275
2481
  when :fail
@@ -2277,8 +2483,9 @@ class Decompiler
2277
2483
  end
2278
2484
  }
2279
2485
  # ignore branches that will never reuse v
2280
- may_to = g.to_optim[l_l].find_all { |to| find_next_read[to, 0, v].kind_of? C::CExpression }
2281
- if may_to.length == 1 and to = may_to.first and to != l_l and g.from_optim[to] == [l_l]
2486
+ may_to = g.to_optim[l_l].find_all { |to| find_next_read[to, 0, v].kind_of?(C::CExpression) }
2487
+ if may_to.length == 1 and to = may_to.first and to != l_l and g.from_optim[to] == [l_l] and
2488
+ not sideeffect(e.rexpr) # dont do cross-block var optimization, eg 'a = f() ; if() return a' =!> 'if () return f()'
2282
2489
  l_i = 0
2283
2490
  l_l = to
2284
2491
  else break
@@ -2292,10 +2499,10 @@ class Decompiler
2292
2499
  # remove sideeffectless subexprs
2293
2500
  loop do
2294
2501
  case e.op
2295
- when :funcall, *AssignOp
2502
+ when :funcall, *C::CExpression::AssignOp
2296
2503
  else
2297
- l = (e.lexpr.kind_of? C::CExpression and sideeffect(e.lexpr))
2298
- r = (e.rexpr.kind_of? C::CExpression and sideeffect(e.rexpr))
2504
+ l = (e.lexpr.kind_of?(C::CExpression) and sideeffect(e.lexpr))
2505
+ r = (e.rexpr.kind_of?(C::CExpression) and sideeffect(e.rexpr))
2299
2506
  if l and r # could split...
2300
2507
  elsif l
2301
2508
  e.replace(e.lexpr)
@@ -2311,87 +2518,183 @@ class Decompiler
2311
2518
  end
2312
2519
  break
2313
2520
  end
2521
+ g.invalidate(label)
2314
2522
  end
2315
2523
  end
2316
2524
  end
2317
2525
  }
2318
2526
 
2527
+
2528
+ # var propagation
2529
+ # find vars who are written only once, and replace all their use by their assignment value
2530
+ # XXX this may supercede some of the ugly stuff just before
2531
+ loop do
2532
+ g.invalidate
2533
+ writtenonce = {} # var => [label, offset] of assignment
2534
+ neverwritten = {} # var => true (eg args)
2535
+ g.exprs_var.each { |varname, h1|
2536
+ next if not var = scope.symbol[varname]
2537
+ neverwritten[varname] = true
2538
+ h1.each { |label, idx_list|
2539
+ idx_list.each { |expr_idx|
2540
+ e = g.exprs[label][expr_idx]
2541
+ if ce_write(e, var)
2542
+ neverwritten.delete varname
2543
+ if writtenonce[varname]
2544
+ # written twice, abort
2545
+ writtenonce.delete varname
2546
+ break
2547
+ elsif e.op == :'=' and e.lexpr == var and not ce_write(e.rexpr, var) and not ce_read(e.rexpr, var)
2548
+ # good !
2549
+ writtenonce[varname] = [label, expr_idx]
2550
+ else
2551
+ # unhandled write, abort
2552
+ break
2553
+ end
2554
+ end
2555
+ }
2556
+ }
2557
+ }
2558
+ # XXX check cycles ?
2559
+
2560
+ is_trivial_assign = lambda { |e, rec_max|
2561
+ case e
2562
+ when C::Variable; writtenonce[e.name] or neverwritten[e.name]
2563
+ when ::Integer, nil; true
2564
+ when C::CExpression
2565
+ rec_max > 0 and
2566
+ not sideeffect(e) and
2567
+ (e.op == :+ or e.op == :- or e.op == nil) and
2568
+ is_trivial_assign[e.lexpr, rec_max-1] and
2569
+ is_trivial_assign[e.rexpr, rec_max-1]
2570
+ end
2571
+ }
2572
+ break if not trivial_var = writtenonce.keys.find { |var|
2573
+ l, i = writtenonce[var]
2574
+ e = g.exprs[l][i].rexpr
2575
+ is_trivial_assign[e, 3]
2576
+ }
2577
+ label, idx = writtenonce[trivial_var]
2578
+ assign_expr = g.exprs[label][idx]
2579
+ var = assign_expr.lexpr
2580
+ value = assign_expr.rexpr
2581
+ g.exprs_var[trivial_var].each { |l, list|
2582
+ list.each { |i|
2583
+ e = g.exprs[l][i]
2584
+ if l == label and i == idx
2585
+ e.lexpr = e.op = e.rexpr = nil
2586
+ else
2587
+ ce_patch(e, var, value)
2588
+ optimize_code(e)
2589
+ end
2590
+ }
2591
+ }
2592
+ end
2593
+
2594
+
2319
2595
  # wipe cexprs marked in the previous step
2320
2596
  walk(scope) { |st|
2321
- next if not st.kind_of? C::Block
2322
- st.statements.delete_if { |e| e.kind_of? C::CExpression and not e.lexpr and not e.op and not e.rexpr }
2597
+ next if not st.kind_of?(C::Block)
2598
+ st.statements.delete_if { |e| e.kind_of?(C::CExpression) and not e.lexpr and not e.op and not e.rexpr }
2323
2599
  }
2600
+ g.invalidate
2324
2601
 
2325
2602
  # reoptimize cexprs
2326
2603
  walk_ce(scope, true) { |ce|
2327
2604
  # redo some simplification that may become available after variable propagation
2328
2605
  # int8 & 255 => int8
2329
- if ce.op == :& and ce.lexpr and ce.lexpr.type.integral? and ce.rexpr.kind_of? C::CExpression and not ce.rexpr.op and ce.rexpr.rexpr == (1 << (8*sizeof(ce.lexpr))) - 1
2606
+ if ce.op == :& and ce.lexpr and ce.lexpr.type.integral? and ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and ce.rexpr.rexpr == (1 << (8*sizeof(ce.lexpr))) - 1
2330
2607
  ce.replace C::CExpression[ce.lexpr]
2331
2608
  end
2332
2609
 
2333
2610
  # int *ptr; *(ptr + 4) => ptr[4]
2334
- if ce.op == :* and not ce.lexpr and ce.rexpr.kind_of? C::CExpression and ce.rexpr.op == :+ and var = ce.rexpr.lexpr and var.kind_of? C::Variable and var.type.pointer?
2611
+ if ce.op == :* and not ce.lexpr and ce.rexpr.kind_of?(C::CExpression) and ce.rexpr.op == :+ and var = ce.rexpr.lexpr and var.kind_of?(C::Variable) and var.type.pointer?
2335
2612
  ce.lexpr, ce.op, ce.rexpr = ce.rexpr.lexpr, :'[]', ce.rexpr.rexpr
2336
2613
  end
2337
2614
 
2338
2615
  # useless casts
2339
- if not ce.op and ce.rexpr.kind_of? C::CExpression and not ce.rexpr.op and (ce.rexpr.rexpr.kind_of? C::CExpression or
2340
- (ce.type.pointer? and ce.rexpr.rexpr == 0 and not ce.type.pointed.untypedef.kind_of? C::Union)) # keep ((struct*)0)->memb
2616
+ if not ce.op and ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and (ce.rexpr.rexpr.kind_of?(C::CExpression) or
2617
+ (ce.type.pointer? and ce.rexpr.rexpr == 0 and not ce.type.pointed.untypedef.kind_of?(C::Union))) # keep ((struct*)0)->memb
2341
2618
  ce.rexpr = ce.rexpr.rexpr
2342
2619
  end
2343
- if not ce.op and ce.rexpr.kind_of? C::CExpression and (ce.type == ce.rexpr.type or (ce.type.integral? and ce.rexpr.type.integral?))
2620
+ if not ce.op and ce.rexpr.kind_of?(C::CExpression) and (ce.type == ce.rexpr.type or (ce.type.integral? and ce.rexpr.type.integral?))
2344
2621
  ce.replace ce.rexpr
2345
2622
  end
2346
2623
  # useless casts (type)*((oeua)Ptype)
2347
- if not ce.op and ce.rexpr.kind_of? C::CExpression and ce.rexpr.op == :* and not ce.rexpr.lexpr and ce.rexpr.rexpr.kind_of? C::CExpression and not ce.rexpr.rexpr.op and
2348
- p = ce.rexpr.rexpr.rexpr and p.kind_of? C::Typed and p.type.pointer? and ce.type == p.type.pointed
2624
+ if not ce.op and ce.rexpr.kind_of?(C::CExpression) and ce.rexpr.op == :* and not ce.rexpr.lexpr and ce.rexpr.rexpr.kind_of?(C::CExpression) and not ce.rexpr.rexpr.op and
2625
+ p = ce.rexpr.rexpr.rexpr and p.kind_of?(C::Typed) and p.type.pointer? and ce.type == p.type.pointed
2349
2626
  ce.op = ce.rexpr.op
2350
2627
  ce.rexpr = ce.rexpr.rexpr.rexpr
2351
2628
  end
2629
+
2630
+ # (char *)42 => new global var
2631
+ if not ce.op and ce.type.pointer? and ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and ce.rexpr.rexpr.kind_of?(::Integer)
2632
+ ce.rexpr = new_global_var(ce.rexpr.rexpr, ce.type, scope) || ce.rexpr
2633
+ end
2634
+
2352
2635
  # (a > 0) != 0
2353
- if ce.op == :'!=' and ce.rexpr.kind_of? C::CExpression and not ce.rexpr.op and ce.rexpr.rexpr == 0 and ce.lexpr.kind_of? C::CExpression and
2354
- [:<, :<=, :>, :>=, :'==', :'!=', :'!'].include? ce.lexpr.op
2636
+ if ce.op == :'!=' and ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and ce.rexpr.rexpr == 0 and ce.lexpr.kind_of?(C::CExpression) and
2637
+ [:<, :<=, :>, :>=, :'==', :'!=', :'!'].include?(ce.lexpr.op)
2355
2638
  ce.replace ce.lexpr
2356
2639
  end
2357
2640
  # a == 0 => !a
2358
- if ce.op == :== and ce.rexpr.kind_of? C::CExpression and not ce.rexpr.op and ce.rexpr.rexpr == 0
2641
+ if ce.op == :== and ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and ce.rexpr.rexpr == 0
2359
2642
  ce.replace C::CExpression[:'!', ce.lexpr]
2360
2643
  end
2361
2644
  # !(int)a => !a
2362
- if ce.op == :'!' and ce.rexpr.kind_of? C::CExpression and not ce.rexpr.op and ce.rexpr.rexpr.kind_of? C::CExpression
2645
+ if ce.op == :'!' and ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and ce.rexpr.rexpr.kind_of?(C::CExpression)
2363
2646
  ce.rexpr = ce.rexpr.rexpr
2364
2647
  end
2365
2648
  # (int)a < (int)b => a < b TODO uint <-> int
2366
- if [:<, :<=, :>, :>=].include? ce.op and ce.rexpr.kind_of? C::CExpression and ce.lexpr.kind_of? C::CExpression and not ce.rexpr.op and not ce.lexpr.op and
2367
- ce.rexpr.rexpr.kind_of? C::CExpression and ce.rexpr.rexpr.type.pointer? and ce.lexpr.rexpr.kind_of? C::CExpression and ce.lexpr.rexpr.type.pointer?
2649
+ if [:<, :<=, :>, :>=].include?(ce.op) and ce.rexpr.kind_of?(C::CExpression) and ce.lexpr.kind_of?(C::CExpression) and not ce.rexpr.op and not ce.lexpr.op and
2650
+ ce.rexpr.rexpr.kind_of?(C::CExpression) and ce.rexpr.rexpr.type.pointer? and ce.lexpr.rexpr.kind_of?(C::CExpression) and ce.lexpr.rexpr.type.pointer?
2368
2651
  ce.rexpr = ce.rexpr.rexpr
2369
2652
  ce.lexpr = ce.lexpr.rexpr
2370
2653
  end
2371
2654
 
2372
2655
  # a & 3 & 1
2373
- while (ce.op == :& or ce.op == :|) and ce.rexpr.kind_of? C::CExpression and not ce.rexpr.op and ce.rexpr.rexpr.kind_of? ::Integer and
2374
- ce.lexpr.kind_of? C::CExpression and ce.lexpr.op == ce.op and ce.lexpr.lexpr and
2375
- ce.lexpr.rexpr.kind_of? C::CExpression and ce.lexpr.rexpr.rexpr.kind_of? ::Integer
2656
+ while (ce.op == :& or ce.op == :|) and ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and ce.rexpr.rexpr.kind_of?(::Integer) and
2657
+ ce.lexpr.kind_of?(C::CExpression) and ce.lexpr.op == ce.op and ce.lexpr.lexpr and
2658
+ ce.lexpr.rexpr.kind_of?(C::CExpression) and ce.lexpr.rexpr.rexpr.kind_of?(::Integer)
2376
2659
  ce.lexpr, ce.rexpr.rexpr = ce.lexpr.lexpr, ce.lexpr.rexpr.rexpr.send(ce.op, ce.rexpr.rexpr)
2377
2660
  end
2378
2661
 
2379
2662
  # x = x | 4 => x |= 4
2380
- if ce.op == :'=' and ce.rexpr.kind_of? C::CExpression and [:+, :-, :*, :/, :|, :&, :^, :>>, :<<].include? ce.rexpr.op and ce.rexpr.lexpr == ce.lexpr
2663
+ if ce.op == :'=' and ce.rexpr.kind_of?(C::CExpression) and [:+, :-, :*, :/, :|, :&, :^, :>>, :<<].include?(ce.rexpr.op) and ce.rexpr.lexpr == ce.lexpr
2381
2664
  ce.op = (ce.rexpr.op.to_s + '=').to_sym
2382
2665
  ce.rexpr = ce.rexpr.rexpr
2383
2666
  end
2384
2667
 
2668
+ # x = 4 | x => x |= 4
2669
+ if ce.op == :'=' and ce.rexpr.kind_of?(C::CExpression) and [:+, :*, :|, :&, :^].include?(ce.rexpr.op) and ce.rexpr.rexpr == ce.lexpr
2670
+ ce.op = (ce.rexpr.op.to_s + '=').to_sym
2671
+ ce.rexpr = ce.rexpr.lexpr
2672
+ end
2673
+
2385
2674
  # x += 1 => ++x
2386
- if (ce.op == :'+=' or ce.op == :'-=') and ce.rexpr.kind_of? C::CExpression and not ce.rexpr.op and ce.rexpr.rexpr == 1
2387
- ce.lexpr, ce.op, ce.rexpr = nil, {:'+=' => :'++', :'-=' => :'--'}[ce.op], ce.lexpr
2675
+ if (ce.op == :'+=' or ce.op == :'-=') and ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and (ce.rexpr.rexpr == 1 or ce.rexpr.rexpr == -1)
2676
+ if ce.rexpr.rexpr == 1
2677
+ ce.op = {:'+=' => :'++', :'-=' => :'--'}[ce.op]
2678
+ else
2679
+ ce.op = {:'+=' => :'--', :'-=' => :'++'}[ce.op]
2680
+ end
2681
+ ce.rexpr = ce.lexpr
2682
+ ce.lexpr = nil
2388
2683
  end
2389
2684
 
2390
2685
  # --x+1 => x--
2391
- if (ce.op == :+ or ce.op == :-) and ce.lexpr.kind_of? C::CExpression and ce.lexpr.op == {:+ => :'--', :- => :'++'}[ce.op] and
2392
- ce.lexpr.rexpr and ce.rexpr.kind_of? C::CExpression and not ce.rexpr.op and ce.rexpr.rexpr == 1
2686
+ if (ce.op == :+ or ce.op == :-) and ce.lexpr.kind_of?(C::CExpression) and ce.lexpr.op == {:+ => :'--', :- => :'++'}[ce.op] and
2687
+ ce.lexpr.rexpr and ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and ce.rexpr.rexpr == 1
2393
2688
  ce.lexpr, ce.op, ce.rexpr = ce.lexpr.rexpr, ce.lexpr.op, nil
2394
2689
  end
2690
+
2691
+ # 1+2 => 3
2692
+ if ce.lexpr.kind_of?(C::CExpression) and not ce.lexpr.op and ce.lexpr.rexpr.kind_of?(::Integer) and
2693
+ ce.rexpr.kind_of?(C::CExpression) and not ce.rexpr.op and ce.rexpr.rexpr.kind_of?(::Integer) and
2694
+ [:+, :-, :*, :/, :|, :&, :^, :>, :'==', :'!=', :<, :>=, :<=].include?(ce.op)
2695
+ ce.rexpr = ce.reduce(@c_parser)
2696
+ ce.lexpr = ce.op = nil
2697
+ end
2395
2698
  }
2396
2699
  end
2397
2700
 
@@ -2399,14 +2702,14 @@ class Decompiler
2399
2702
  used = {}
2400
2703
  walk_ce(scope) { |ce|
2401
2704
  # remove unreferenced local vars
2402
- used[ce.rexpr.name] = true if ce.rexpr.kind_of? C::Variable
2403
- used[ce.lexpr.name] = true if ce.lexpr.kind_of? C::Variable
2404
- ce.rexpr.each { |v| used[v.name] = true if v.kind_of? C::Variable } if ce.rexpr.kind_of?(::Array)
2705
+ used[ce.rexpr.name] = true if ce.rexpr.kind_of?(C::Variable)
2706
+ used[ce.lexpr.name] = true if ce.lexpr.kind_of?(C::Variable)
2707
+ ce.rexpr.each { |v| used[v.name] = true if v.kind_of?(C::Variable) } if ce.rexpr.kind_of?(::Array)
2405
2708
  }
2406
2709
  unused = scope.symbol.keys.find_all { |n| not used[n] }
2407
2710
  unused.each { |v| scope.symbol[v].add_attribute 'unused' } # fastcall args need it
2408
- scope.statements.delete_if { |sm| sm.kind_of? C::Declaration and unused.include? sm.var.name }
2409
- scope.symbol.delete_if { |n, v| unused.include? n }
2711
+ scope.statements.delete_if { |sm| sm.kind_of?(C::Declaration) and unused.include?(sm.var.name) }
2712
+ scope.symbol.delete_if { |n, v| unused.include?(n) }
2410
2713
  end
2411
2714
 
2412
2715
  def finalize
@@ -2417,17 +2720,17 @@ class Decompiler
2417
2720
  def optimize_global
2418
2721
  # check all global vars (pointers to global data)
2419
2722
  tl = @c_parser.toplevel
2420
- vars = tl.symbol.keys.find_all { |k| tl.symbol[k].kind_of? C::Variable and not tl.symbol[k].type.kind_of? C::Function }
2723
+ vars = tl.symbol.keys.find_all { |k| tl.symbol[k].kind_of?(C::Variable) and not tl.symbol[k].type.kind_of?(C::Function) and not tl.symbol[k].storage == :extern and not tl.symbol[k].storage == :static }
2421
2724
  countref = Hash.new(0)
2422
2725
 
2423
2726
  walk_ce(tl) { |ce|
2424
2727
  # XXX int foo; void bar() { int foo; } => false negative
2425
- countref[ce.rexpr.name] += 1 if ce.rexpr.kind_of? C::Variable
2426
- countref[ce.lexpr.name] += 1 if ce.lexpr.kind_of? C::Variable
2728
+ countref[ce.rexpr.name] += 1 if ce.rexpr.kind_of?(C::Variable)
2729
+ countref[ce.lexpr.name] += 1 if ce.lexpr.kind_of?(C::Variable)
2427
2730
  }
2428
2731
 
2429
2732
  vars.delete_if { |v| countref[v] == 0 }
2430
- countref.delete_if { |k, v| not vars.include? k }
2733
+ countref.delete_if { |k, v| not vars.include?(k) }
2431
2734
 
2432
2735
  # by default globals are C::Arrays
2433
2736
  # if all references are *foo, dereference the var type
@@ -2441,7 +2744,7 @@ class Decompiler
2441
2744
  else next
2442
2745
  end
2443
2746
  # compare type.type cause var is an Array and the cast is a Pointer
2444
- countderef[r.rexpr.name] += 1 if r.kind_of? C::CExpression and not r.op and r.rexpr.kind_of? C::Variable and
2747
+ countderef[r.rexpr.name] += 1 if r.kind_of?(C::CExpression) and not r.op and r.rexpr.kind_of?(C::Variable) and
2445
2748
  sizeof(nil, r.type.type) == sizeof(nil, r.rexpr.type.type) rescue nil
2446
2749
  }
2447
2750
  vars.each { |n|
@@ -2449,7 +2752,7 @@ class Decompiler
2449
2752
  v = tl.symbol[n]
2450
2753
  target = C::CExpression[:*, [v]]
2451
2754
  v.type = v.type.type
2452
- v.initializer = v.initializer.first if v.initializer.kind_of? ::Array
2755
+ v.initializer = v.initializer.first if v.initializer.kind_of?(::Array)
2453
2756
  walk_ce(tl) { |ce|
2454
2757
  if ce.op == :'->' and C::CExpression[ce.lexpr] == C::CExpression[v]
2455
2758
  ce.op = :'.'
@@ -2464,28 +2767,28 @@ class Decompiler
2464
2767
 
2465
2768
  # if a global var appears only in one function, make it a static variable
2466
2769
  tl.statements.each { |st|
2467
- next if not st.kind_of? C::Declaration or not st.var.type.kind_of? C::Function or not scope = st.var.initializer
2770
+ next if not st.kind_of?(C::Declaration) or not st.var.type.kind_of?(C::Function) or not scope = st.var.initializer
2468
2771
  localcountref = Hash.new(0)
2469
2772
  walk_ce(scope) { |ce|
2470
- localcountref[ce.rexpr.name] += 1 if ce.rexpr.kind_of? C::Variable
2471
- localcountref[ce.lexpr.name] += 1 if ce.lexpr.kind_of? C::Variable
2773
+ localcountref[ce.rexpr.name] += 1 if ce.rexpr.kind_of?(C::Variable)
2774
+ localcountref[ce.lexpr.name] += 1 if ce.lexpr.kind_of?(C::Variable)
2472
2775
  }
2473
2776
 
2474
2777
  vars.delete_if { |n|
2475
2778
  next if scope.symbol[n]
2476
2779
  next if localcountref[n] != countref[n]
2477
2780
  v = tl.symbol.delete(n)
2478
- tl.statements.delete_if { |d| d.kind_of? C::Declaration and d.var.name == n }
2781
+ tl.statements.delete_if { |d| d.kind_of?(C::Declaration) and d.var.name == n }
2479
2782
 
2480
- if countref[n] == 1 and v.initializer.kind_of? C::CExpression and v.initializer.rexpr.kind_of? String
2783
+ if countref[n] == 1 and v.initializer.kind_of?(C::CExpression) and v.initializer.rexpr.kind_of?(String)
2481
2784
  walk_ce(scope) { |ce|
2482
- if ce.rexpr.kind_of? C::Variable and ce.rexpr.name == n
2785
+ if ce.rexpr.kind_of?(C::Variable) and ce.rexpr.name == n
2483
2786
  if not ce.op
2484
2787
  ce.replace v.initializer
2485
2788
  else
2486
2789
  ce.rexpr = v.initializer
2487
2790
  end
2488
- elsif ce.lexpr.kind_of? C::Variable and ce.lexpr.name == n
2791
+ elsif ce.lexpr.kind_of?(C::Variable) and ce.lexpr.name == n
2489
2792
  ce.lexpr = v.initializer
2490
2793
  end
2491
2794
  }
@@ -2507,7 +2810,7 @@ class Decompiler
2507
2810
  args = func.type.args
2508
2811
  decl = []
2509
2812
  scope.statements.delete_if { |sm|
2510
- next if not sm.kind_of? C::Declaration
2813
+ next if not sm.kind_of?(C::Declaration)
2511
2814
  if sm.var.stackoff.to_i > 0 and sm.var.name !~ /_a(\d+)$/ # aliased vars: use 1st domain only
2512
2815
  args << sm.var
2513
2816
  else
@@ -2520,8 +2823,8 @@ class Decompiler
2520
2823
  # XXX a = 1 ; b = a ; a = 2
2521
2824
  go = true # break from delete_if does not delete..
2522
2825
  scope.statements.delete_if { |st|
2523
- if go and st.kind_of? C::CExpression and st.op == :'=' and st.rexpr.kind_of? C::CExpression and not st.rexpr.op and
2524
- st.rexpr.rexpr.kind_of? ::Integer and st.lexpr.kind_of? C::Variable and scope.symbol[st.lexpr.name]
2826
+ if go and st.kind_of?(C::CExpression) and st.op == :'=' and st.rexpr.kind_of?(C::CExpression) and not st.rexpr.op and
2827
+ st.rexpr.rexpr.kind_of?(::Integer) and st.lexpr.kind_of?(C::Variable) and scope.symbol[st.lexpr.name]
2525
2828
  st.lexpr.initializer = st.rexpr
2526
2829
  else
2527
2830
  go = false
@@ -2542,7 +2845,7 @@ class Decompiler
2542
2845
  end
2543
2846
  while curoff > argoff
2544
2847
  wantarg = C::Variable.new
2545
- wantarg.name = scope.decompdata[:stackoff_name][argoff] || stackoff_to_varname(argoff)
2848
+ wantarg.name = stackoff_to_varname(argoff)
2546
2849
  wantarg.type = C::BaseType.new(:int)
2547
2850
  wantarg.attributes = ['unused']
2548
2851
  func.type.args << wantarg
@@ -2552,6 +2855,18 @@ class Decompiler
2552
2855
  func.type.args << a
2553
2856
  argoff += @c_parser.typesize[:ptr]
2554
2857
  }
2858
+
2859
+ # use user-supplied names
2860
+ scope.symbol.keys.each { |s|
2861
+ v = scope.symbol[s]
2862
+ next if not v.kind_of?(C::Variable)
2863
+ v.misc ||= {}
2864
+ uan = v.misc[:unalias_name] ||= s
2865
+ if newname = scope.decompdata[:unalias_name][uan] and newname != s
2866
+ v.name = newname
2867
+ scope.symbol[newname] = scope.symbol.delete(s)
2868
+ end
2869
+ }
2555
2870
  end
2556
2871
 
2557
2872
  # rename local variables from subfunc arg names
@@ -2563,12 +2878,12 @@ class Decompiler
2563
2878
  walk_ce(scope) { |ce|
2564
2879
  funcs << ce if ce.op == :funcall
2565
2880
  cntrs << (ce.lexpr || ce.rexpr) if ce.op == :'++'
2566
- cmpi << ce.lexpr if [:<, :>, :<=, :>=, :==, :'!='].include? ce.op and ce.rexpr.kind_of? C::CExpression and ce.rexpr.rexpr.kind_of? ::Integer
2881
+ cmpi << ce.lexpr if [:<, :>, :<=, :>=, :==, :'!='].include?(ce.op) and ce.rexpr.kind_of?(C::CExpression) and ce.rexpr.rexpr.kind_of?(::Integer)
2567
2882
  }
2568
2883
 
2569
2884
  rename = lambda { |var, name|
2570
- var = var.rexpr if var.kind_of? C::CExpression and not var.op
2571
- next if not var.kind_of? C::Variable or not scope.symbol[var.name] or not name
2885
+ var = var.rexpr if var.kind_of?(C::CExpression) and not var.op
2886
+ next if not var.kind_of?(C::Variable) or not scope.symbol[var.name] or not name
2572
2887
  next if (var.name !~ /^(var|arg)_/ and not var.storage == :register) or not scope.symbol[var.name] or name =~ /^(var|arg)_/
2573
2888
  s = scope.symbol_ancestors
2574
2889
  n = name
@@ -2579,13 +2894,13 @@ class Decompiler
2579
2894
  }
2580
2895
 
2581
2896
  funcs.each { |ce|
2582
- next if not ce.lexpr.kind_of? C::Variable or not ce.lexpr.type.kind_of? C::Function
2897
+ next if not ce.lexpr.kind_of?(C::Variable) or not ce.lexpr.type.kind_of?(C::Function)
2583
2898
  ce.rexpr.to_a.zip(ce.lexpr.type.args.to_a).each { |a, fa| rename[a, fa.name] if fa }
2584
2899
  }
2585
2900
  funcs.each { |ce|
2586
- next if not ce.lexpr.kind_of? C::Variable or not ce.lexpr.type.kind_of? C::Function
2901
+ next if not ce.lexpr.kind_of?(C::Variable) or not ce.lexpr.type.kind_of?(C::Function)
2587
2902
  ce.rexpr.to_a.zip(ce.lexpr.type.args.to_a).each { |a, fa|
2588
- next if not a.kind_of? C::CExpression or a.op != :& or a.lexpr
2903
+ next if not a.kind_of?(C::CExpression) or a.op != :& or a.lexpr
2589
2904
  next if not fa or not fa.name
2590
2905
  rename[a.rexpr, fa.name.sub(/^l?p/, '')]
2591
2906
  }
@@ -2624,34 +2939,46 @@ class Decompiler
2624
2939
  end
2625
2940
 
2626
2941
  # yields each statement (recursive)
2627
- def walk(scope, post=false, &b)
2942
+ # replace the element by the block return value if patch is true
2943
+ def walk(scope, post=false, patch=false, &b)
2628
2944
  case scope
2629
- when ::Array; scope.each { |s| walk(s, post, &b) }
2945
+ when ::Array
2946
+ scope.each_with_index { |s, i|
2947
+ v = walk(s, post, patch, &b)
2948
+ scope[i] = v if patch and v
2949
+ }
2950
+ nil
2630
2951
  when C::Statement
2631
- yield scope if not post
2952
+ v = yield scope if not post
2632
2953
  case scope
2633
- when C::Block; walk(scope.statements, post, &b)
2954
+ when C::Block
2955
+ walk(scope.statements, post, patch, &b)
2634
2956
  when C::If
2635
- yield scope.test
2636
- walk(scope.bthen, post, &b)
2637
- walk(scope.belse, post, &b) if scope.belse
2957
+ vv = yield scope.test
2958
+ scope.test = vv if patch and vv
2959
+ walk(scope.bthen, post, patch, &b)
2960
+ walk(scope.belse, post, patch, &b) if scope.belse
2638
2961
  when C::While, C::DoWhile
2639
- yield scope.test
2640
- walk(scope.body, post, &b)
2962
+ vv = yield scope.test
2963
+ scope.test = vv if patch and vv
2964
+ walk(scope.body, post, patch, &b)
2641
2965
  when C::Return
2642
- yield scope.value
2966
+ vv = yield scope.value
2967
+ scope.value = vv if patch and vv
2643
2968
  end
2644
- yield scope if post
2969
+ v = yield scope if post
2970
+ v
2645
2971
  when C::Declaration
2646
- walk(scope.var.initializer, post, &b) if scope.var.initializer
2972
+ walk(scope.var.initializer, post, patch, &b) if scope.var.initializer
2973
+ nil
2647
2974
  end
2648
2975
  end
2649
2976
 
2650
2977
  # forwards to @c_parser, handles cast to Array (these should not happen btw...)
2651
2978
  def sizeof(var, type=nil)
2652
- var, type = nil, var if var.kind_of? C::Type and not type
2979
+ var, type = nil, var if var.kind_of?(C::Type) and not type
2653
2980
  type ||= var.type
2654
- return @c_parser.typesize[:ptr] if type.kind_of? C::Array and not var.kind_of? C::Variable
2981
+ return @c_parser.typesize[:ptr] if type.kind_of?(C::Array) and not var.kind_of?(C::Variable)
2655
2982
  @c_parser.sizeof(var, type) rescue -1
2656
2983
  end
2657
2984
  end