metasm 1.0.3 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +3 -0
  3. data.tar.gz.sig +0 -0
  4. data/Gemfile +3 -2
  5. data/metasm.gemspec +3 -2
  6. data/metasm.rb +4 -1
  7. data/metasm/compile_c.rb +2 -2
  8. data/metasm/cpu/arc/decode.rb +0 -21
  9. data/metasm/cpu/arc/main.rb +4 -4
  10. data/metasm/cpu/arm/decode.rb +1 -5
  11. data/metasm/cpu/arm/main.rb +3 -3
  12. data/metasm/cpu/arm64/decode.rb +2 -6
  13. data/metasm/cpu/arm64/main.rb +5 -5
  14. data/metasm/cpu/bpf/decode.rb +3 -35
  15. data/metasm/cpu/bpf/main.rb +5 -5
  16. data/metasm/cpu/bpf/render.rb +1 -12
  17. data/metasm/cpu/cy16/decode.rb +0 -6
  18. data/metasm/cpu/cy16/main.rb +3 -3
  19. data/metasm/cpu/cy16/render.rb +0 -11
  20. data/metasm/cpu/dalvik/decode.rb +4 -26
  21. data/metasm/cpu/dalvik/main.rb +20 -2
  22. data/metasm/cpu/dalvik/opcodes.rb +3 -2
  23. data/metasm/cpu/{mips/compile_c.rb → ebpf.rb} +5 -2
  24. data/metasm/cpu/ebpf/debug.rb +61 -0
  25. data/metasm/cpu/ebpf/decode.rb +142 -0
  26. data/metasm/cpu/ebpf/main.rb +58 -0
  27. data/metasm/cpu/ebpf/opcodes.rb +97 -0
  28. data/metasm/cpu/ebpf/render.rb +36 -0
  29. data/metasm/cpu/ia32/debug.rb +39 -1
  30. data/metasm/cpu/ia32/decode.rb +111 -90
  31. data/metasm/cpu/ia32/decompile.rb +45 -37
  32. data/metasm/cpu/ia32/main.rb +10 -0
  33. data/metasm/cpu/ia32/parse.rb +6 -0
  34. data/metasm/cpu/mcs51/decode.rb +1 -1
  35. data/metasm/cpu/mcs51/main.rb +11 -0
  36. data/metasm/cpu/mips/decode.rb +8 -18
  37. data/metasm/cpu/mips/main.rb +3 -3
  38. data/metasm/cpu/mips/opcodes.rb +1 -1
  39. data/metasm/cpu/msp430/decode.rb +2 -6
  40. data/metasm/cpu/msp430/main.rb +3 -3
  41. data/metasm/cpu/openrisc.rb +11 -0
  42. data/metasm/cpu/openrisc/debug.rb +106 -0
  43. data/metasm/cpu/openrisc/decode.rb +182 -0
  44. data/metasm/cpu/openrisc/decompile.rb +350 -0
  45. data/metasm/cpu/openrisc/main.rb +70 -0
  46. data/metasm/cpu/openrisc/opcodes.rb +109 -0
  47. data/metasm/cpu/openrisc/render.rb +37 -0
  48. data/metasm/cpu/ppc/decode.rb +0 -25
  49. data/metasm/cpu/ppc/main.rb +6 -6
  50. data/metasm/cpu/ppc/opcodes.rb +3 -4
  51. data/metasm/cpu/python/decode.rb +0 -20
  52. data/metasm/cpu/python/main.rb +1 -1
  53. data/metasm/cpu/sh4/decode.rb +2 -6
  54. data/metasm/cpu/sh4/main.rb +25 -23
  55. data/metasm/cpu/st20/decode.rb +0 -7
  56. data/metasm/cpu/webasm.rb +11 -0
  57. data/metasm/cpu/webasm/debug.rb +31 -0
  58. data/metasm/cpu/webasm/decode.rb +321 -0
  59. data/metasm/cpu/webasm/decompile.rb +386 -0
  60. data/metasm/cpu/webasm/encode.rb +104 -0
  61. data/metasm/cpu/webasm/main.rb +81 -0
  62. data/metasm/cpu/webasm/opcodes.rb +214 -0
  63. data/metasm/cpu/x86_64/compile_c.rb +13 -9
  64. data/metasm/cpu/x86_64/parse.rb +1 -1
  65. data/metasm/cpu/z80/decode.rb +0 -27
  66. data/metasm/cpu/z80/main.rb +3 -3
  67. data/metasm/cpu/z80/render.rb +0 -11
  68. data/metasm/debug.rb +43 -8
  69. data/metasm/decode.rb +62 -14
  70. data/metasm/decompile.rb +793 -466
  71. data/metasm/disassemble.rb +188 -131
  72. data/metasm/disassemble_api.rb +30 -17
  73. data/metasm/dynldr.rb +2 -2
  74. data/metasm/encode.rb +8 -2
  75. data/metasm/exe_format/autoexe.rb +2 -0
  76. data/metasm/exe_format/coff.rb +21 -3
  77. data/metasm/exe_format/coff_decode.rb +12 -0
  78. data/metasm/exe_format/coff_encode.rb +6 -3
  79. data/metasm/exe_format/dex.rb +13 -3
  80. data/metasm/exe_format/elf.rb +12 -2
  81. data/metasm/exe_format/elf_decode.rb +59 -1
  82. data/metasm/exe_format/main.rb +2 -0
  83. data/metasm/exe_format/mz.rb +1 -0
  84. data/metasm/exe_format/pe.rb +25 -3
  85. data/metasm/exe_format/wasm.rb +402 -0
  86. data/metasm/gui/dasm_decomp.rb +171 -95
  87. data/metasm/gui/dasm_graph.rb +61 -2
  88. data/metasm/gui/dasm_hex.rb +2 -2
  89. data/metasm/gui/dasm_main.rb +45 -19
  90. data/metasm/gui/debug.rb +13 -4
  91. data/metasm/gui/gtk.rb +12 -4
  92. data/metasm/main.rb +108 -103
  93. data/metasm/os/emulator.rb +175 -0
  94. data/metasm/os/main.rb +11 -6
  95. data/metasm/parse.rb +23 -12
  96. data/metasm/parse_c.rb +189 -135
  97. data/metasm/preprocessor.rb +16 -1
  98. data/misc/openrisc-parser.rb +79 -0
  99. data/samples/dasm-plugins/scanxrefs.rb +6 -4
  100. data/samples/dasm-plugins/selfmodify.rb +8 -8
  101. data/samples/dbg-plugins/trace_func.rb +1 -1
  102. data/samples/disassemble-gui.rb +14 -3
  103. data/samples/emubios.rb +251 -0
  104. data/samples/emudbg.rb +127 -0
  105. data/samples/lindebug.rb +79 -78
  106. data/samples/metasm-shell.rb +8 -8
  107. data/tests/all.rb +1 -1
  108. data/tests/expression.rb +2 -0
  109. data/tests/graph_layout.rb +1 -1
  110. data/tests/ia32.rb +1 -0
  111. data/tests/mips.rb +1 -1
  112. data/tests/preprocessor.rb +18 -0
  113. metadata +124 -6
  114. metadata.gz.sig +0 -0
@@ -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