metasm 1.0.3 → 1.0.4

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