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
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # Demo of using the EmuDebugger to work on the SSTIC2017 challenge (EBPF program)
4
+
5
+ require 'metasm'
6
+ include Metasm
7
+ require 'zlib'
8
+
9
+ bpf_prog = "eNrlWk9sVEUYn7f7nq8lxS5QpDZEinSxIUEKASnEhNYGQYS0WGsBY8LBUA4YKq" <<
10
+ "Dl8UICQRLkQFbBSLiUFpH2BJ7KbTi2F7NHDx4w8cCRI6mQdWa+b/6+t/voAhdtsp2dN/PNfN/8" <<
11
+ "vvl+38xb+gYRfzMhlJ3s08Q+Q6TskwZCutj3FaL+u78E2wvsQxugP29/ndcbtXyH6D/rbwsIaf" <<
12
+ "UIeVKpVAj+NbdCOcL651g5zMr3WbnqOjyPbzwSfUP2nKs24+HztifieStTIk/0H52EMszBPBfZ" <<
13
+ "d0/MD4KBmIWQCMcZ8j637B1hdrSzcgzLoYbf/ALqJ55jOVDC+dDuaFrrucJoH2btFTHOlL+X1w" <<
14
+ "nWya/+kCFHf0C9mV5vCfsewnNch5CN08afX54Vz3vO4TosKif6vW21/yHaowkYr6dg68315RDs" <<
15
+ "Ltn2RxMg14/4cNzO9h7Zx7+f6Pty5xetV3wYF+Yf8XB9sBzyLvv7h7/9QNhb4fZe8uN9sM586e" <<
16
+ "MzgJ/G83Emno8ZnvQW1vOA74wPdY5zTugza9l5R8xfqYwQ1A/LeBHMH595WfM+XNC83O7cS7S7" <<
17
+ "NYT5pHxADvm1/fozvyhwGvK9Gv6t/XWn/zHX62d4vgtxHBhFfXEe0w+5XgPnkv6WTx1/mx9b+2" <<
18
+ "Wrf5DXQ6yHW/ydfJ3v4D5jz7cb8+txuvyzuL5eHXFiBvXUfgn7YLkTN+RzU582C9eFzbsc41OE" <<
19
+ "88eXYV+p+FB1f99PtK+z2h8k2jdZ7ei3ozZOEmdu11qjPV50r+K2v2u130y0v2e1z6o4yeNcj4" <<
20
+ "yj32OJ6zvsAZ7SL/uRT+iPUI6x9eOq0rzeF2W2nsN5kCvmc6QR4yl/HggWs/tTp3+A/edE/9dU" <<
21
+ "PJ5mde7e47w/+tkMk+M91uc9y1/oVdQvj7zYgfb4IEeLOH+A+gY4f5AX+o6wfnzjhvzfM67HYh" <<
22
+ "jXkKOOXODIlZ5q/WcC7W9C/xzK5VLk5lmc2Yk4HUK/u4b2+MATdAvag/PTTXr8sjO+sCcAnLje" <<
23
+ "vIOyx5CjaXqZcnOGPTmN37iFX4ocA45+ksSF+5O0U9nRg+MStANxjteVxDoUibanSY7PAFL2GP" <<
24
+ "LUkOdygSvHAErY46M96CdFP01uXtuD+5nHc55j0c2On21J97O47Trw3rpLYJfhdwXpd0xC6meO" <<
25
+ "Y/vdCuU/Wm6uItchmrTjxFgIuSG9gHoibvQ7bX/ZsD+agLjG10Hox/q3IO584QMCiaopT631aw" <<
26
+ "L9LLnS04A0w7qTdD+SehfzjypJ+6aVfQH5G3jc13FVjIP8VWzIp80/L3FS+RIzrpvbcTI9jsV7" <<
27
+ "plAfXIcQ9mEIfFsORLZty9O0fWHLzQUEvkj9TfnxbPlpegr696+291dSf7meEI95PF8p1q8pIW" <<
28
+ "fr7Yl5AxJYcczsn6onjh8CX5ToTyjnxuFWvX8Ej6ypov+h+5b+0k+V/msy+MR3+MRHPnHiseKT" <<
29
+ "NZ6Nywq9fwoGT/JzUsXYT0n+y6v19uV6mHxyIcNfDDmLT3IZ/m7KcT5BvjbXW/BI5NhxMtuOBm" <<
30
+ "mHySMns+1QciaP5HV+IuzAPLMYpshxHkG/i7ePVlxc2uvEpUn56bMF4aLkTB7JZ+Oi5eYNe45W" <<
31
+ "XHw668SnoOwpLwgfLTe3IHy03LRhz+EEPl114tOi48izheCj5TjfPD8+hty8tucAnAOmII9X5z" <<
32
+ "ivNm+8Mr5orJMv0J+iO3A+6D+N4yyrnb9zngS+KCT6p+qN/UMIo6WAgMJ0uX2uo4PZeeRKlecx" <<
33
+ "Htkvz30D4F9f2+cU6Rc8vxR88o3237Lhv/Gec5h/nYbyBuBaDKucV4b1ONTaBxnnlQDtwnyN3w" <<
34
+ "MIfhl2zisXiZVHjWG+Q7c5+6Vb+2/Z8N+4DfDkflyTbwx5msUbJt80ZPO9xTeYF9ODaA/eb9E+" <<
35
+ "J+/clY4Pjy8y32yQeZvJN7uq4aHzPSWXdm6pluebcpxv8Hwk8Vc8c9Wx41p6/mzmzU0q/zR45l" <<
36
+ "q1vFnro+RMnvH0PY6wA/2j2Jgmx3hmYxKPTiN+KDtOZdtRUHYY/HIq2w4tZ/CLn8EvlhzjF8zb" <<
37
+ "4z3dFReXrjpxsc8zz4+LfZ5x7KmBS9o5JN7TBfxyC+6BRvB8HG+H+lhQm2eiX2Zf7fnkBfkmbu" <<
38
+ "ux7Ovvk7yK9+uDVfL+G51ol6/O/SsN3KMJOEcr+wbT7ZP9EueZsE4ewvnjM+1oF9zTNC+TduG9" <<
39
+ "DcYp6dfRNOKJeS3t1e8bhN2evO/YDfp6YLeMjxTPX9HNS2g3nKPNcagxjuxf9MAOPg7nKS0fqv" <<
40
+ "0n+MqJizzOvGbMt77Xs9Ytmizhew20f7XE+5H1voPnSQXj3lCet6qdV5Uf55BXcg6PXc3wY0PO" <<
41
+ "4rF8xv405TiPrZF4wv6KJtFO5JF4Hdp5E/04p+9FW408ScWjlmrxKEjlO8n/8v2OwrslPT5F02" <<
42
+ "V1X1OTBxu1v4wb/iL9JMGDSg+0H/Mwmc/J+2L53kmum7K7o05+7KiTH/2M+1aXH1UcRjwn4b6n" <<
43
+ "Ge97TVw7F4RrBm+2vCBv1sAvnTencF/CfVBzCn5ddeKXyqMdL8ijNfBL49Fo8r6FG3/fJ3hzac" <<
44
+ "b9uIe85Tl8uTTjftyW03yJccaUH8+Wn5Z+Jd/73nXwSfDEDbxHxvs9yafcDxqNfI+//1xp8qSX" <<
45
+ "zhdFD84zUk7dP2Nd5s+mfKr/4XxIEyWq4iXgw/fQWuN9oRzvHVZGx46P3n1T/x7BfB861HibfP" <<
46
+ "Tp4GA0cQ73KZzfmpfKdRt16ked+mGnfsCpP3DqA04d4uvdpfoce+TE8a92oP6S/5Lv4a+Q3X3t" <<
47
+ "fdEEnNPk7y2iid1Ovcepdzv1Lqfe6dTbnTr6UWv6+2d6Hp5vWIK/L2A4rb/94WX1nhT9cQfGgw" <<
48
+ "1Yrtpoy2X1k+fyRHv3wsb5z/Q7/3z9hrxdpHfv3naZ3zefsvPe5haHl1V9yqnfc+oPnfp9p45+" <<
49
+ "jnX+/qUd7yXajXzT9Ju/Lh3786X7TV+V9s3/U7/pfb5+y73FZFPXxq0yT5e/83lZv7Oh+DsCfK" <<
50
+ "2T+L2FvJ8IyLV/ePkvDyQvEw=="
51
+
52
+ raw = Zlib::Inflate.inflate(bpf_prog.unpack('m*').first)
53
+ dasm = Shellcode.decode(raw, EBPF.new(:latest, :little)).disassembler
54
+ dasm.backtrace_maxblocks_data = -1
55
+
56
+ dasm.callback_newinstr = lambda { |di|
57
+ if di.opcode.name == 'call'
58
+ case di.instruction.args.first.reduce
59
+ when 1; di.instruction.args[0] = ExpressionString.new(Expression[1], "bpf_map_lookup_elem")
60
+ when 2; di.instruction.args[0] = ExpressionString.new(Expression[1], "bpf_map_update_elem")
61
+ end
62
+ end
63
+ di
64
+ }
65
+ # EmuDebugger needs an already disassembled binary
66
+ dasm.disassemble(0)
67
+
68
+ #Gui::DasmWindow.new.display(dasm)
69
+
70
+ # EmuDebugger has no memory except what is described in the binary
71
+ # We must manually add sections to the disassembler to 'map' the stack and working heap
72
+ stack = EncodedData.new("\x00" * 0x1000)
73
+ dasm.add_section(stack, 0x8000)
74
+
75
+ # ebpf works on network packets
76
+ eth = "\x11\x11\x11\x11\x11\x11\x22\x22\x22\x22\x22\x22\x08\x00"
77
+ ip = "\x45\x00\x00\x2c\x00\x00\x11\x11\x22\x11\x33\x33\x44\x44\x44\x44\x55\x55\x55\x55"
78
+ udp = "\x00\x00\x05\x39\x22\x22\x33\x33"
79
+ pld = "LUM{BvWQEdCrMfA}"
80
+ # forge the needed network headers
81
+ ip[2, 2] = [ip.length + udp.length + pld.length].pack('n')
82
+ udp[4, 2] = [udp.length + pld.length].pack('n')
83
+ pkt = EncodedData.new(eth + ip + udp + pld)
84
+ dasm.add_section(pkt, 0x9000)
85
+
86
+ # Initialize the emulator
87
+ dbg = Metasm::EmuDebugger.new(dasm)
88
+ # Set the initial state of the registers
89
+ dbg.set_reg_value(:r10, 0x8900)
90
+ # :packet is a special register used internally by some opcodes of the EBPF cpu (packet data store/load)
91
+ dbg.set_reg_value(:packet, 0x9000)
92
+
93
+ # This section emulates the kernel API for shared bpf maps
94
+ $bpf_map = { 0 => 0 }
95
+ dbg.callback_emulate_di = lambda { |di|
96
+ case di.opcode.name
97
+ when 'call'
98
+ case di.instruction.args.to_s
99
+ when /map_lookup/
100
+ key = dbg.resolve('dword ptr [r2]')
101
+ puts "bpf_map_lookup(#{dbg[:r1]}, #{key}) => #{$bpf_map[key].inspect}"
102
+ if $bpf_map[key]
103
+ dbg[:r0] = dbg[:r2]
104
+ dbg.memory_write_int(:r2, $bpf_map[key], 4)
105
+ else
106
+ dbg[:r0] = 0
107
+ end
108
+ when /map_update/
109
+ key = dbg.resolve('dword ptr [r2]')
110
+ val = dbg.resolve('dword ptr [r3]')
111
+ puts "bpf_map_update(#{dbg[:r1]}, #{key}, #{val})"
112
+ $bpf_map[key] = val
113
+ end
114
+ dbg.pc += di.bin_length
115
+ true
116
+ end
117
+ }
118
+
119
+ # Start the GUI
120
+ Gui::DbgWindow.new.display(dbg)
121
+ # some pretty settings for the initial view
122
+ dbg.gui.run_command('wd 6')
123
+ dbg.gui.run_command('wp 6')
124
+ dbg.gui.run_command('d :packet')
125
+ dbg.gui.parent.code.toggle_view(:graph)
126
+
127
+ Gui.main
@@ -35,7 +35,7 @@ module Ansi
35
35
  end
36
36
  }.compact.join(';') << 'm'
37
37
  end
38
- def self.hline(len) "\e(0"<<'q'*len<<"\e(B" end
38
+ def self.hline(len) "\e(0" << 'q'*len << "\e(B" end
39
39
 
40
40
  TIOCGWINSZ = 0x5413
41
41
  TCGETS = 0x5401
@@ -124,10 +124,10 @@ class LinDebug
124
124
  defretval
125
125
  end
126
126
 
127
- attr_accessor :dataptr, :codeptr, :rs, :promptlog, :command
128
- def initialize(rs)
129
- @rs = rs
130
- @rs.set_log_proc { |l| add_log l }
127
+ attr_accessor :dataptr, :codeptr, :dbg, :promptlog, :command
128
+ def initialize(dbg)
129
+ @dbg = dbg
130
+ @dbg.set_log_proc { |l| add_log l }
131
131
  @datafmt = 'db'
132
132
 
133
133
  @prompthistlen = 20
@@ -148,7 +148,7 @@ class LinDebug
148
148
  end
149
149
 
150
150
  def init_rs
151
- @codeptr = @dataptr = @rs.pc # avoid initial faults
151
+ @codeptr = @dataptr = @dbg.pc # avoid initial faults
152
152
  end
153
153
 
154
154
  def main_loop
@@ -211,14 +211,14 @@ class LinDebug
211
211
 
212
212
  def _updateregs
213
213
  pvrsz = 0
214
- words = @rs.register_list.map { |r|
214
+ words = @dbg.register_list.map { |r|
215
215
  rs = r.to_s.rjust(pvrsz)
216
216
  pvrsz = rs.length
217
- rv = @rs[r]
218
- ["#{rs}=%0#{@rs.register_size[r]/4}X " % rv,
217
+ rv = @dbg[r]
218
+ ["#{rs}=%0#{@dbg.register_size[r]/4}X " % rv,
219
219
  (@oldregs[r] != rv)]
220
- } + @rs.flag_list.map { |fl|
221
- fv = @rs.get_flag(fl)
220
+ } + @dbg.flag_list.map { |fl|
221
+ fv = @dbg.get_flag(fl)
222
222
  [fv ? fl.to_s.upcase : fl.to_s.downcase,
223
223
  (@oldregs[fl] != fv)]
224
224
  }
@@ -253,24 +253,24 @@ class LinDebug
253
253
  def _updatecode
254
254
  if @codeptr
255
255
  addr = @codeptr
256
- elsif @oldregs[@rs.register_pc] and @oldregs[@rs.register_pc] < @rs.pc and @oldregs[@rs.register_pc] + 8 >= @rs.pc
257
- addr = @oldregs[@rs.register_pc]
256
+ elsif @oldregs[@dbg.register_pc] and @oldregs[@dbg.register_pc] < @dbg.pc and @oldregs[@dbg.register_pc] + 8 >= @dbg.pc
257
+ addr = @oldregs[@dbg.register_pc]
258
258
  else
259
- addr = @rs.pc
259
+ addr = @dbg.pc
260
260
  end
261
261
  @codeptr = addr
262
262
 
263
- addrsz = @rs.register_size[@rs.register_pc]
263
+ addrsz = @dbg.register_size[@dbg.register_pc]
264
264
  addrfmt = "%0#{addrsz/4}X"
265
- if not @rs.addr2module(addr) and @rs.shortname !~ /remote/
265
+ if not @dbg.addr2module(addr) and @dbg.shortname !~ /remote/
266
266
  base = addr & ((1 << addrsz) - 0x1000)
267
267
  @noelfsig ||= {} # cache elfmagic notfound
268
268
  if not @noelfsig[base] and base < ((1 << addrsz) - 0x1_0000)
269
269
  self.statusline = " scanning for elf header at #{addrfmt % base}"
270
270
  128.times {
271
271
  @statusline = " scanning for elf header at #{addrfmt % base}"
272
- if not @noelfsig[base] and @rs[base, Metasm::ELF::MAGIC.length] == Metasm::ELF::MAGIC
273
- @rs.loadsyms(base, base.to_s(16))
272
+ if not @noelfsig[base] and @dbg[base, Metasm::ELF::MAGIC.length] == Metasm::ELF::MAGIC
273
+ @dbg.loadsyms(base, base.to_s(16))
274
274
  break
275
275
  else
276
276
  @noelfsig[base] = true # XXX an elf may be mmaped here later..
@@ -284,35 +284,35 @@ class LinDebug
284
284
 
285
285
  text = ''
286
286
  text << Color[:border]
287
- title = @rs.addrname(addr)
287
+ title = @dbg.addrname(addr)
288
288
  pre = [@console_width-100, 6].max
289
289
  post = @console_width - (pre + title.length + 2)
290
290
  text << Ansi.hline(pre) << ' ' << title << ' ' << Ansi.hline(post) << Color[:normal] << "\n"
291
291
 
292
292
  seg = ''
293
- seg = ('%04X' % @rs['cs']) << ':' if @rs.cpu.shortname =~ /ia32|x64/
293
+ seg = ('%04X' % @dbg['cs']) << ':' if @dbg.cpu.shortname =~ /ia32|x64/
294
294
 
295
295
  cnt = @win_code_height
296
296
  while (cnt -= 1) > 0
297
- if @rs.symbols[addr]
298
- text << (' ' << @rs.symbols[addr] << ?:) << Ansi::ClearLineAfter << "\n"
297
+ if @dbg.symbols[addr]
298
+ text << (' ' << @dbg.symbols[addr] << ?:) << Ansi::ClearLineAfter << "\n"
299
299
  break if (cnt -= 1) <= 0
300
300
  end
301
- text << Color[:hilight] if addr == @rs.pc
301
+ text << Color[:hilight] if addr == @dbg.pc
302
302
  text << seg
303
- if @rs.shortname =~ /remote/ and @rs.realmode
304
- text << (addrfmt % (addr - 16*@rs['cs']))
303
+ if @dbg.shortname =~ /remote/ and @dbg.realmode
304
+ text << (addrfmt % (addr - 16*@dbg['cs']))
305
305
  else
306
306
  text << (addrfmt % addr)
307
307
  end
308
- di = @rs.di_at(addr)
309
- di = nil if di and addr < @rs.pc and addr+di.bin_length > @rs.pc
308
+ di = @dbg.di_at(addr)
309
+ di = nil if di and addr < @dbg.pc and addr+di.bin_length > @dbg.pc
310
310
  len = (di ? di.bin_length : 1)
311
311
  text << ' '
312
- text << @rs.memory[addr, [len, 10].min].to_s.unpack('C*').map { |c| '%02X' % c }.join.ljust(22)
312
+ text << @dbg.memory[addr, [len, 10].min].to_s.unpack('C*').map { |c| '%02X' % c }.join.ljust(22)
313
313
  if di
314
314
  text <<
315
- if addr == @rs.pc
315
+ if addr == @dbg.pc
316
316
  "*#{di.instruction}".ljust([@console_width-(addrsz/4+seg.length+24), 0].max)
317
317
  else
318
318
  " #{di.instruction}" << Ansi::ClearLineAfter
@@ -320,7 +320,7 @@ class LinDebug
320
320
  else
321
321
  text << ' <unk>' << Ansi::ClearLineAfter
322
322
  end
323
- text << Color[:normal] if addr == @rs.pc
323
+ text << Color[:normal] if addr == @dbg.pc
324
324
  addr += len
325
325
  text << "\n"
326
326
  end
@@ -332,7 +332,7 @@ class LinDebug
332
332
  end
333
333
 
334
334
  def _updatedata
335
- addrsz = @rs.register_size[@rs.register_pc]
335
+ addrsz = @dbg.register_size[@dbg.register_pc]
336
336
  addrfmt = "%0#{addrsz/4}X"
337
337
 
338
338
  @dataptr &= ((1 << addrsz) - 1)
@@ -340,17 +340,17 @@ class LinDebug
340
340
 
341
341
  text = ''
342
342
  text << Color[:border]
343
- title = @rs.addrname(addr)
343
+ title = @dbg.addrname(addr)
344
344
  pre = [@console_width-100, 6].max
345
345
  post = [@console_width - (pre + title.length + 2), 0].max
346
346
  text << Ansi.hline(pre) << ' ' << title << ' ' << Ansi.hline(post) << Color[:normal] << "\n"
347
347
 
348
348
  seg = ''
349
- seg = ('%04X' % @rs['ds']) << ':' if @rs.cpu.shortname =~ /^ia32/
349
+ seg = ('%04X' % @dbg['ds']) << ':' if @dbg.cpu.shortname =~ /^ia32/
350
350
 
351
351
  cnt = @win_data_height
352
352
  while (cnt -= 1) > 0
353
- raw = @rs.memory[addr, 16].to_s
353
+ raw = @dbg.memory[addr, 16].to_s
354
354
  text << seg << (addrfmt % addr) << ' '
355
355
  case @datafmt
356
356
  when 'db'; text << raw[0,8].unpack('C*').map { |c| '%02x ' % c }.join << ' ' <<
@@ -449,20 +449,21 @@ class LinDebug
449
449
  end
450
450
 
451
451
  def preupdate
452
- @rs.register_list.each { |r| @oldregs[r] = @rs[r] }
453
- @rs.flag_list.each { |fl| @oldregs[fl] = @rs.get_flag(fl) }
452
+ @dbg.register_list.each { |r| @oldregs[r] = @dbg[r] }
453
+ @dbg.flag_list.each { |fl| @oldregs[fl] = @dbg.get_flag(fl) }
454
454
  end
455
455
 
456
456
  def updatecodeptr
457
- @codeptr ||= @rs.pc
458
- if @codeptr > @rs.pc or @codeptr < @rs.pc - 6*@win_code_height
459
- @codeptr = @rs.pc
460
- elsif @codeptr != @rs.pc
457
+ @codeptr ||= @dbg.pc
458
+ if @codeptr > @dbg.pc or @codeptr < @dbg.pc - 6*@win_code_height
459
+ @codeptr = @dbg.pc
460
+ elsif @codeptr != @dbg.pc
461
461
  addr = @codeptr
462
462
  addrs = []
463
- while addr < @rs.pc
463
+ while addr <= @dbg.pc
464
464
  addrs << addr
465
- o = ((di = @rs.di_at(addr)) ? di.bin_length : 0)
465
+ addrs << addr if @dbg.symbols[addr]
466
+ o = ((di = @dbg.di_at(addr)) ? di.bin_length : 0)
466
467
  addr += ((o == 0) ? 1 : o)
467
468
  end
468
469
  if addrs.length > @win_code_height-4
@@ -478,35 +479,35 @@ class LinDebug
478
479
  def singlestep
479
480
  self.statusline = ' target singlestepping...'
480
481
  preupdate
481
- @rs.singlestep_wait
482
+ @dbg.singlestep_wait
482
483
  updatecodeptr
483
484
  @statusline = nil
484
485
  end
485
486
  def stepover
486
487
  self.statusline = ' target running...'
487
488
  preupdate
488
- @rs.stepover_wait
489
+ @dbg.stepover_wait
489
490
  updatecodeptr
490
491
  @statusline = nil
491
492
  end
492
493
  def cont(*a)
493
494
  self.statusline = ' target running...'
494
495
  preupdate
495
- @rs.continue_wait(*a)
496
+ @dbg.continue_wait(*a)
496
497
  updatecodeptr
497
498
  @statusline = nil
498
499
  end
499
500
  def stepout
500
501
  self.statusline = ' target running...'
501
502
  preupdate
502
- @rs.stepout_wait
503
+ @dbg.stepout_wait
503
504
  updatecodeptr
504
505
  @statusline = nil
505
506
  end
506
507
  def syscall
507
508
  self.statusline = ' target running to next syscall...'
508
509
  preupdate
509
- @rs.syscall_wait
510
+ @dbg.syscall_wait
510
511
  updatecodeptr
511
512
  @statusline = nil
512
513
  end
@@ -552,9 +553,9 @@ class LinDebug
552
553
  when :data
553
554
  @dataptr -= 16
554
555
  when :code
555
- @codeptr ||= @rs.pc
556
+ @codeptr ||= @dbg.pc
556
557
  @codeptr -= (1..10).find { |off|
557
- di = @rs.di_at(@codeptr-off)
558
+ di = @dbg.di_at(@codeptr-off)
558
559
  di.bin_length == off if di
559
560
  } || 10
560
561
  end
@@ -573,8 +574,8 @@ class LinDebug
573
574
  when :data
574
575
  @dataptr += 16
575
576
  when :code
576
- @codeptr ||= @rs.pc
577
- di = @rs.di_at(@codeptr)
577
+ @codeptr ||= @dbg.pc
578
+ di = @dbg.di_at(@codeptr)
578
579
  @codeptr += (di ? (di.bin_length || 1) : 1)
579
580
  end
580
581
  when :left; @promptpos -= 1 if @promptpos > 0
@@ -588,10 +589,10 @@ class LinDebug
588
589
  when :prompt; @log_off += @win_prpt_height-3
589
590
  when :data; @dataptr -= 16*(@win_data_height-1)
590
591
  when :code
591
- @codeptr ||= @rs.pc
592
+ @codeptr ||= @dbg.pc
592
593
  (@win_code_height-1).times {
593
594
  @codeptr -= (1..10).find { |off|
594
- di = @rs.di_at(@codeptr-off)
595
+ di = @dbg.di_at(@codeptr-off)
595
596
  di.bin_length == off if di
596
597
  } || 10
597
598
  }
@@ -601,8 +602,8 @@ class LinDebug
601
602
  when :prompt; @log_off -= @win_prpt_height-3
602
603
  when :data; @dataptr += 16*(@win_data_height-1)
603
604
  when :code
604
- @codeptr ||= @rs.pc
605
- (@win_code_height-1).times { @codeptr += ((o = @rs.di_at(@codeptr)) ? [o.bin_length, 1].max : 1) }
605
+ @codeptr ||= @dbg.pc
606
+ (@win_code_height-1).times { @codeptr += ((o = @dbg.di_at(@codeptr)) ? [o.bin_length, 1].max : 1) }
606
607
  end
607
608
  when ?\t
608
609
  if not @promptbuf[0, @promptpos].include? ' '
@@ -631,67 +632,67 @@ class LinDebug
631
632
 
632
633
  def load_commands
633
634
  @command['kill'] = lambda { |str|
634
- @rs.kill
635
+ @dbg.kill
635
636
  @running = false
636
637
  log 'killed'
637
638
  }
638
639
  @command['quit'] = @command['detach'] = @command['exit'] = lambda { |str|
639
- @rs.detach
640
+ @dbg.detach
640
641
  @running = false
641
642
  }
642
643
  @command['closeui'] = lambda { |str|
643
644
  @running = false
644
645
  }
645
646
  @command['bpx'] = lambda { |str|
646
- @rs.bpx @rs.resolve(str)
647
+ @dbg.bpx @dbg.resolve(str)
647
648
  }
648
649
  @command['bphw'] = @command['hwbp'] = lambda { |str|
649
650
  type, str = str.split(/\s+/, 2)
650
- @rs.hwbp @rs.resolve(str.to_s), type
651
+ @dbg.hwbp @dbg.resolve(str.to_s), type
651
652
  }
652
- @command['bt'] = lambda { |str| @rs.stacktrace { |a,t| add_log "#{'%x' % a} #{t}" } }
653
- @command['d'] = lambda { |str| @dataptr = @rs.resolve(str) if str.length > 0 }
654
- @command['db'] = lambda { |str| @datafmt = 'db' ; @dataptr = @rs.resolve(str) if str.length > 0 }
655
- @command['dw'] = lambda { |str| @datafmt = 'dw' ; @dataptr = @rs.resolve(str) if str.length > 0 }
656
- @command['dd'] = lambda { |str| @datafmt = 'dd' ; @dataptr = @rs.resolve(str) if str.length > 0 }
653
+ @command['bt'] = lambda { |str| @dbg.stacktrace { |a,t| add_log "#{'%x' % a} #{t}" } }
654
+ @command['d'] = lambda { |str| @dataptr = @dbg.resolve(str) if str.length > 0 }
655
+ @command['db'] = lambda { |str| @datafmt = 'db' ; @dataptr = @dbg.resolve(str) if str.length > 0 }
656
+ @command['dw'] = lambda { |str| @datafmt = 'dw' ; @dataptr = @dbg.resolve(str) if str.length > 0 }
657
+ @command['dd'] = lambda { |str| @datafmt = 'dd' ; @dataptr = @dbg.resolve(str) if str.length > 0 }
657
658
  @command['r'] = lambda { |str|
658
659
  r, str = str.split(/\s+/, 2)
659
660
  if r == 'fl'
660
- @rs.toggle_flag(str.to_sym)
661
- elsif not @rs[r]
661
+ @dbg.toggle_flag(str.to_sym)
662
+ elsif not @dbg[r]
662
663
  log "bad reg #{r}"
663
664
  elsif str and str.length > 0
664
- @rs[r] = @rs.resolve(str)
665
+ @dbg[r] = @dbg.resolve(str)
665
666
  else
666
- log "#{r} = #{@rs[r]}"
667
+ log "#{r} = #{@dbg[r]}"
667
668
  end
668
669
  }
669
670
  @command['g'] = lambda { |str|
670
- @rs.go @rs.resolve(str)
671
+ @dbg.go @dbg.resolve(str)
671
672
  }
672
- @command['u'] = lambda { |str| @codeptr = @rs.resolve(str) }
673
+ @command['u'] = lambda { |str| @codeptr = @dbg.resolve(str) }
673
674
  @command['ruby'] = lambda { |str| instance_eval str }
674
675
  @command['wd'] = lambda { |str|
675
676
  @focus = :data
676
677
  if str.length > 0
677
- @win_data_height = @rs.resolve(str)
678
+ @win_data_height = @dbg.resolve(str)
678
679
  resize
679
680
  end
680
681
  }
681
682
  @command['wc'] = lambda { |str|
682
683
  @focus = :code
683
684
  if str.length > 0
684
- @win_code_height = @rs.resolve(str)
685
+ @win_code_height = @dbg.resolve(str)
685
686
  resize
686
687
  end
687
688
  }
688
689
  @command['wp'] = lambda { |str| @focus = :prompt }
689
690
  @command['?'] = lambda { |str|
690
- val = @rs.resolve(str)
691
+ val = @dbg.resolve(str)
691
692
  log "#{val} 0x#{val.to_s(16)} #{[val].pack('L').inspect}"
692
693
  }
693
694
  @command['syscall'] = lambda { |str|
694
- @rs.syscall_wait(str)
695
+ @dbg.syscall_wait(str)
695
696
  }
696
697
  end
697
698
  end
@@ -709,10 +710,10 @@ if $0 == __FILE__
709
710
  when /^(tcp:|udp:)?..+:/, /^ser:/
710
711
  opts[:sc_cpu] = eval(opts[:sc_cpu]) if opts[:sc_cpu] =~ /[.(\s:]/
711
712
  opts[:sc_cpu] = opts[:sc_cpu].new if opts[:sc_cpu].kind_of?(::Class)
712
- rs = Metasm::GdbRemoteDebugger.new(ARGV.first, opts[:sc_cpu])
713
+ dbg = Metasm::GdbRemoteDebugger.new(ARGV.first, opts[:sc_cpu])
713
714
  else
714
- rs = Metasm::LinDebugger.new(ARGV.join(' '))
715
+ dbg = Metasm::LinDebugger.new(ARGV.join(' '))
715
716
  end
716
- rs.load_map(opts[:filemap]) if opts[:filemap]
717
- LinDebug.new(rs).main_loop
717
+ dbg.load_map(opts[:filemap]) if opts[:filemap]
718
+ LinDebug.new(dbg).main_loop
718
719
  end