metasm 1.0.0 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +3 -0
- data/.gitignore +3 -0
- data/.hgtags +3 -0
- data/Gemfile +3 -0
- data/INSTALL +61 -0
- data/LICENCE +458 -0
- data/README +29 -21
- data/Rakefile +10 -0
- data/TODO +10 -12
- data/doc/code_organisation.txt +3 -1
- data/doc/core/DynLdr.txt +247 -0
- data/doc/core/ExeFormat.txt +43 -0
- data/doc/core/Expression.txt +220 -0
- data/doc/core/GNUExports.txt +27 -0
- data/doc/core/Ia32.txt +236 -0
- data/doc/core/SerialStruct.txt +108 -0
- data/doc/core/VirtualString.txt +145 -0
- data/doc/core/WindowsExports.txt +61 -0
- data/doc/core/index.txt +1 -0
- data/doc/style.css +6 -3
- data/doc/usage/debugger.txt +327 -0
- data/doc/usage/index.txt +1 -0
- data/doc/use_cases.txt +2 -2
- data/metasm.gemspec +23 -0
- data/{lib/metasm.rb → metasm.rb} +15 -3
- data/{lib/metasm → metasm}/compile_c.rb +15 -9
- data/metasm/cpu/arc.rb +8 -0
- data/metasm/cpu/arc/decode.rb +404 -0
- data/metasm/cpu/arc/main.rb +191 -0
- data/metasm/cpu/arc/opcodes.rb +588 -0
- data/metasm/cpu/arm.rb +14 -0
- data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
- data/{lib/metasm → metasm/cpu}/arm/decode.rb +15 -18
- data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
- data/{lib/metasm → metasm/cpu}/arm/main.rb +3 -6
- data/metasm/cpu/arm/opcodes.rb +324 -0
- data/{lib/metasm → metasm/cpu}/arm/parse.rb +25 -13
- data/{lib/metasm → metasm/cpu}/arm/render.rb +2 -2
- data/metasm/cpu/arm64.rb +15 -0
- data/metasm/cpu/arm64/debug.rb +38 -0
- data/metasm/cpu/arm64/decode.rb +285 -0
- data/metasm/cpu/arm64/encode.rb +41 -0
- data/metasm/cpu/arm64/main.rb +105 -0
- data/metasm/cpu/arm64/opcodes.rb +232 -0
- data/metasm/cpu/arm64/parse.rb +20 -0
- data/metasm/cpu/arm64/render.rb +95 -0
- data/{lib/metasm/mips/compile_c.rb → metasm/cpu/bpf.rb} +4 -2
- data/metasm/cpu/bpf/decode.rb +110 -0
- data/metasm/cpu/bpf/main.rb +60 -0
- data/metasm/cpu/bpf/opcodes.rb +81 -0
- data/metasm/cpu/bpf/render.rb +30 -0
- data/{lib/metasm/ppc.rb → metasm/cpu/cy16.rb} +2 -4
- data/metasm/cpu/cy16/decode.rb +247 -0
- data/metasm/cpu/cy16/main.rb +63 -0
- data/metasm/cpu/cy16/opcodes.rb +78 -0
- data/metasm/cpu/cy16/render.rb +30 -0
- data/metasm/cpu/dalvik.rb +11 -0
- data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +34 -34
- data/{lib/metasm → metasm/cpu}/dalvik/main.rb +71 -4
- data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +21 -12
- data/{lib/metasm/mips.rb → metasm/cpu/ebpf.rb} +3 -4
- data/metasm/cpu/ebpf/debug.rb +61 -0
- data/metasm/cpu/ebpf/decode.rb +142 -0
- data/metasm/cpu/ebpf/main.rb +58 -0
- data/metasm/cpu/ebpf/opcodes.rb +97 -0
- data/metasm/cpu/ebpf/render.rb +36 -0
- data/metasm/cpu/ia32.rb +17 -0
- data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +23 -9
- data/{lib/metasm → metasm/cpu}/ia32/debug.rb +44 -6
- data/{lib/metasm → metasm/cpu}/ia32/decode.rb +342 -128
- data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +75 -53
- data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
- data/{lib/metasm → metasm/cpu}/ia32/main.rb +66 -8
- data/metasm/cpu/ia32/opcodes.rb +1424 -0
- data/{lib/metasm → metasm/cpu}/ia32/parse.rb +55 -17
- data/{lib/metasm → metasm/cpu}/ia32/render.rb +32 -5
- data/metasm/cpu/mcs51.rb +8 -0
- data/metasm/cpu/mcs51/decode.rb +99 -0
- data/metasm/cpu/mcs51/main.rb +87 -0
- data/metasm/cpu/mcs51/opcodes.rb +120 -0
- data/metasm/cpu/mips.rb +14 -0
- data/metasm/cpu/mips/debug.rb +42 -0
- data/{lib/metasm → metasm/cpu}/mips/decode.rb +59 -38
- data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
- data/{lib/metasm → metasm/cpu}/mips/main.rb +13 -6
- data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +87 -18
- data/{lib/metasm → metasm/cpu}/mips/parse.rb +1 -1
- data/{lib/metasm → metasm/cpu}/mips/render.rb +1 -1
- data/{lib/metasm/dalvik.rb → metasm/cpu/msp430.rb} +1 -1
- data/metasm/cpu/msp430/decode.rb +243 -0
- data/metasm/cpu/msp430/main.rb +62 -0
- data/metasm/cpu/msp430/opcodes.rb +101 -0
- data/metasm/cpu/openrisc.rb +11 -0
- data/metasm/cpu/openrisc/debug.rb +106 -0
- data/metasm/cpu/openrisc/decode.rb +182 -0
- data/metasm/cpu/openrisc/decompile.rb +350 -0
- data/metasm/cpu/openrisc/main.rb +70 -0
- data/metasm/cpu/openrisc/opcodes.rb +109 -0
- data/metasm/cpu/openrisc/render.rb +37 -0
- data/{lib/metasm → metasm/cpu}/pic16c/decode.rb +6 -7
- data/{lib/metasm → metasm/cpu}/pic16c/main.rb +0 -0
- data/{lib/metasm → metasm/cpu}/pic16c/opcodes.rb +1 -1
- data/metasm/cpu/ppc.rb +11 -0
- data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -37
- data/{lib/metasm → metasm/cpu}/ppc/decompile.rb +3 -3
- data/{lib/metasm → metasm/cpu}/ppc/encode.rb +2 -2
- data/{lib/metasm → metasm/cpu}/ppc/main.rb +23 -18
- data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -6
- data/metasm/cpu/ppc/parse.rb +55 -0
- data/metasm/cpu/python.rb +8 -0
- data/metasm/cpu/python/decode.rb +116 -0
- data/metasm/cpu/python/main.rb +36 -0
- data/metasm/cpu/python/opcodes.rb +180 -0
- data/{lib/metasm → metasm/cpu}/sh4.rb +1 -1
- data/{lib/metasm → metasm/cpu}/sh4/decode.rb +50 -23
- data/{lib/metasm → metasm/cpu}/sh4/main.rb +38 -27
- data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
- data/metasm/cpu/st20.rb +9 -0
- data/metasm/cpu/st20/decode.rb +173 -0
- data/metasm/cpu/st20/decompile.rb +283 -0
- data/metasm/cpu/st20/main.rb +37 -0
- data/metasm/cpu/st20/opcodes.rb +140 -0
- data/{lib/metasm/arm.rb → metasm/cpu/webasm.rb} +4 -5
- data/metasm/cpu/webasm/debug.rb +31 -0
- data/metasm/cpu/webasm/decode.rb +321 -0
- data/metasm/cpu/webasm/decompile.rb +386 -0
- data/metasm/cpu/webasm/encode.rb +104 -0
- data/metasm/cpu/webasm/main.rb +81 -0
- data/metasm/cpu/webasm/opcodes.rb +214 -0
- data/metasm/cpu/x86_64.rb +15 -0
- data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +40 -25
- data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
- data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +58 -15
- data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +59 -28
- data/{lib/metasm → metasm/cpu}/x86_64/main.rb +18 -6
- data/metasm/cpu/x86_64/opcodes.rb +138 -0
- data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +12 -4
- data/metasm/cpu/x86_64/render.rb +35 -0
- data/metasm/cpu/z80.rb +9 -0
- data/metasm/cpu/z80/decode.rb +286 -0
- data/metasm/cpu/z80/main.rb +67 -0
- data/metasm/cpu/z80/opcodes.rb +224 -0
- data/metasm/cpu/z80/render.rb +48 -0
- data/{lib/metasm/os/main.rb → metasm/debug.rb} +201 -407
- data/{lib/metasm → metasm}/decode.rb +104 -24
- data/{lib/metasm → metasm}/decompile.rb +804 -478
- data/{lib/metasm → metasm}/disassemble.rb +385 -170
- data/{lib/metasm → metasm}/disassemble_api.rb +684 -105
- data/{lib/metasm → metasm}/dynldr.rb +231 -138
- data/{lib/metasm → metasm}/encode.rb +20 -5
- data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
- data/{lib/metasm → metasm}/exe_format/autoexe.rb +3 -0
- data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
- data/{lib/metasm → metasm}/exe_format/coff.rb +35 -7
- data/{lib/metasm → metasm}/exe_format/coff_decode.rb +70 -23
- data/{lib/metasm → metasm}/exe_format/coff_encode.rb +24 -22
- data/{lib/metasm → metasm}/exe_format/dex.rb +26 -8
- data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/elf.rb +108 -58
- data/{lib/metasm → metasm}/exe_format/elf_decode.rb +202 -36
- data/{lib/metasm → metasm}/exe_format/elf_encode.rb +126 -32
- data/metasm/exe_format/gb.rb +65 -0
- data/metasm/exe_format/javaclass.rb +424 -0
- data/{lib/metasm → metasm}/exe_format/macho.rb +218 -16
- data/{lib/metasm → metasm}/exe_format/main.rb +28 -3
- data/{lib/metasm → metasm}/exe_format/mz.rb +2 -0
- data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
- data/{lib/metasm → metasm}/exe_format/pe.rb +96 -11
- data/metasm/exe_format/pyc.rb +167 -0
- data/{lib/metasm → metasm}/exe_format/serialstruct.rb +67 -14
- data/{lib/metasm → metasm}/exe_format/shellcode.rb +7 -3
- data/metasm/exe_format/shellcode_rwx.rb +114 -0
- data/metasm/exe_format/swf.rb +205 -0
- data/metasm/exe_format/wasm.rb +402 -0
- data/{lib/metasm → metasm}/exe_format/xcoff.rb +7 -7
- data/metasm/exe_format/zip.rb +335 -0
- data/metasm/gui.rb +13 -0
- data/{lib/metasm → metasm}/gui/cstruct.rb +35 -41
- data/{lib/metasm → metasm}/gui/dasm_coverage.rb +11 -11
- data/{lib/metasm → metasm}/gui/dasm_decomp.rb +177 -114
- data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
- data/metasm/gui/dasm_graph.rb +1754 -0
- data/{lib/metasm → metasm}/gui/dasm_hex.rb +16 -12
- data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
- data/{lib/metasm → metasm}/gui/dasm_main.rb +360 -77
- data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
- data/{lib/metasm → metasm}/gui/debug.rb +109 -34
- data/{lib/metasm → metasm}/gui/gtk.rb +174 -44
- data/{lib/metasm → metasm}/gui/qt.rb +14 -4
- data/{lib/metasm → metasm}/gui/win32.rb +180 -43
- data/{lib/metasm → metasm}/gui/x11.rb +59 -59
- data/{lib/metasm → metasm}/main.rb +421 -286
- data/metasm/os/emulator.rb +175 -0
- data/{lib/metasm/os/remote.rb → metasm/os/gdbremote.rb} +146 -54
- data/{lib/metasm → metasm}/os/gnu_exports.rb +1 -1
- data/{lib/metasm → metasm}/os/linux.rb +628 -151
- data/metasm/os/main.rb +335 -0
- data/{lib/metasm → metasm}/os/windows.rb +151 -58
- data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
- data/{lib/metasm → metasm}/parse.rb +49 -36
- data/{lib/metasm → metasm}/parse_c.rb +405 -246
- data/{lib/metasm → metasm}/preprocessor.rb +71 -41
- data/{lib/metasm → metasm}/render.rb +14 -38
- data/misc/hexdump.rb +4 -3
- data/misc/lint.rb +58 -0
- data/misc/objdiff.rb +4 -1
- data/misc/objscan.rb +1 -1
- data/misc/openrisc-parser.rb +79 -0
- data/misc/txt2html.rb +9 -7
- data/samples/bindiff.rb +3 -4
- data/samples/dasm-plugins/bindiff.rb +15 -0
- data/samples/dasm-plugins/bookmark.rb +133 -0
- data/samples/dasm-plugins/c_constants.rb +57 -0
- data/samples/dasm-plugins/colortheme_solarized.rb +125 -0
- data/samples/dasm-plugins/cppobj_funcall.rb +60 -0
- data/samples/dasm-plugins/dasm_all.rb +70 -0
- data/samples/dasm-plugins/demangle_cpp.rb +31 -0
- data/samples/dasm-plugins/deobfuscate.rb +251 -0
- data/samples/dasm-plugins/dump_text.rb +35 -0
- data/samples/dasm-plugins/export_graph_svg.rb +86 -0
- data/samples/dasm-plugins/findgadget.rb +75 -0
- data/samples/dasm-plugins/hl_opcode.rb +32 -0
- data/samples/dasm-plugins/hotfix_gtk_dbg.rb +19 -0
- data/samples/dasm-plugins/imm2off.rb +34 -0
- data/samples/dasm-plugins/match_libsigs.rb +93 -0
- data/samples/dasm-plugins/patch_file.rb +95 -0
- data/samples/dasm-plugins/scanfuncstart.rb +36 -0
- data/samples/dasm-plugins/scanxrefs.rb +29 -0
- data/samples/dasm-plugins/selfmodify.rb +197 -0
- data/samples/dasm-plugins/stringsxrefs.rb +28 -0
- data/samples/dasmnavig.rb +1 -1
- data/samples/dbg-apihook.rb +24 -9
- data/samples/dbg-plugins/heapscan.rb +283 -0
- data/samples/dbg-plugins/heapscan/compiled_heapscan_lin.c +155 -0
- data/samples/dbg-plugins/heapscan/compiled_heapscan_win.c +128 -0
- data/samples/dbg-plugins/heapscan/graphheap.rb +616 -0
- data/samples/dbg-plugins/heapscan/heapscan.rb +709 -0
- data/samples/dbg-plugins/heapscan/winheap.h +174 -0
- data/samples/dbg-plugins/heapscan/winheap7.h +307 -0
- data/samples/dbg-plugins/trace_func.rb +214 -0
- data/samples/disassemble-gui.rb +48 -7
- data/samples/disassemble.rb +31 -6
- data/samples/dump_upx.rb +24 -12
- data/samples/dynamic_ruby.rb +35 -27
- data/samples/elfencode.rb +15 -0
- data/samples/emubios.rb +251 -0
- data/samples/emudbg.rb +127 -0
- data/samples/exeencode.rb +6 -5
- data/samples/factorize-headers-peimports.rb +1 -1
- data/samples/lindebug.rb +186 -391
- data/samples/metasm-shell.rb +68 -57
- data/samples/peldr.rb +2 -2
- data/tests/all.rb +1 -1
- data/tests/arc.rb +26 -0
- data/tests/dynldr.rb +22 -4
- data/tests/expression.rb +57 -0
- data/tests/graph_layout.rb +285 -0
- data/tests/ia32.rb +80 -26
- data/tests/mcs51.rb +27 -0
- data/tests/mips.rb +10 -3
- data/tests/preprocessor.rb +18 -0
- data/tests/x86_64.rb +66 -18
- metadata +465 -219
- metadata.gz.sig +2 -0
- data/lib/metasm/arm/opcodes.rb +0 -177
- data/lib/metasm/gui.rb +0 -23
- data/lib/metasm/gui/dasm_graph.rb +0 -1354
- data/lib/metasm/ia32.rb +0 -14
- data/lib/metasm/ia32/opcodes.rb +0 -872
- data/lib/metasm/ppc/parse.rb +0 -52
- data/lib/metasm/x86_64.rb +0 -12
- data/lib/metasm/x86_64/opcodes.rb +0 -118
- data/samples/gdbclient.rb +0 -583
- data/samples/rubstop.rb +0 -399
@@ -0,0 +1,175 @@
|
|
1
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
2
|
+
# Copyright (C) 2006-2009 Yoann GUILLOT
|
3
|
+
#
|
4
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
5
|
+
|
6
|
+
|
7
|
+
require 'metasm/os/main'
|
8
|
+
require 'metasm/debug'
|
9
|
+
|
10
|
+
module Metasm
|
11
|
+
# a VirtualString mapping the segments from a disassembler
|
12
|
+
class VirtualMemoryDasm < VirtualString
|
13
|
+
attr_accessor :disassembler
|
14
|
+
|
15
|
+
def initialize(disassembler, addr_start = 0, length = nil)
|
16
|
+
@disassembler = disassembler
|
17
|
+
length ||= disassembler.sections.map { |k, v| k.kind_of?(Integer) ? k + v.length : 0 }.max
|
18
|
+
super(addr_start, length)
|
19
|
+
end
|
20
|
+
|
21
|
+
def dup(addr = @addr_start, len = @length)
|
22
|
+
self.class.new(@disassembler, addr, len)
|
23
|
+
end
|
24
|
+
|
25
|
+
# reads an aligned page from the file, at file offset addr
|
26
|
+
def read_range(addr, len=@pagelength)
|
27
|
+
@disassembler.read_raw_data(addr, len)
|
28
|
+
end
|
29
|
+
|
30
|
+
def page_invalid?(addr)
|
31
|
+
!@disassembler.get_section_at(addr)
|
32
|
+
end
|
33
|
+
|
34
|
+
# overwrite a section of the file
|
35
|
+
def rewrite_at(addr, data)
|
36
|
+
if e = @disassembler.get_section_at(addr)
|
37
|
+
e[0].data[addr - e[1], data.length] = data
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def decode_imm(addr, len, cpu)
|
42
|
+
@disassembler.decode_int(addr, len)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# this class implements a virtual debugger over an emulated cpu (based on cpu#get_backtrace_binding)
|
47
|
+
class EmuDebugger < Debugger
|
48
|
+
attr_accessor :ctx
|
49
|
+
# lambda called everytime we emulate a di
|
50
|
+
# receives the di as parameter
|
51
|
+
# if it returns nil, the di is emulated as usual, if it returns true no further processing is done for this di
|
52
|
+
# dont forget to handle reg_pc !
|
53
|
+
attr_accessor :callback_emulate_di
|
54
|
+
# lambda called everytime we cannot find an instruction at the current PC
|
55
|
+
# return true if the context was fixed
|
56
|
+
attr_accessor :callback_unknown_pc
|
57
|
+
|
58
|
+
def initialize(disassembler)
|
59
|
+
@pid = @tid = 0
|
60
|
+
attach(disassembler)
|
61
|
+
end
|
62
|
+
|
63
|
+
def shortname; 'emudbg'; end
|
64
|
+
|
65
|
+
def attach(disassembler)
|
66
|
+
@memory = VirtualMemoryDasm.new(disassembler)
|
67
|
+
@cpu = disassembler.cpu
|
68
|
+
@disassembler = disassembler
|
69
|
+
@ctx = {}
|
70
|
+
@state = :stopped
|
71
|
+
@symbols = disassembler.prog_binding.invert
|
72
|
+
@symbols_len = @symbols.keys.inject({}) { |h, s| h.update s => 1 }
|
73
|
+
@modulemap = {}
|
74
|
+
@breakpoint = {}
|
75
|
+
@breakpoint_memory = {}
|
76
|
+
@breakpoint_thread = {}
|
77
|
+
end
|
78
|
+
|
79
|
+
def detach
|
80
|
+
end
|
81
|
+
|
82
|
+
def initialize_disassembler
|
83
|
+
end
|
84
|
+
def initialize_cpu
|
85
|
+
end
|
86
|
+
def initialize_memory
|
87
|
+
end
|
88
|
+
def invalidate
|
89
|
+
end
|
90
|
+
|
91
|
+
def memory_get_page(addr, len)
|
92
|
+
@memory[addr, len]
|
93
|
+
end
|
94
|
+
|
95
|
+
def get_reg_value(r)
|
96
|
+
if r.to_s =~ /flags?_(.+)/i
|
97
|
+
f = $1.downcase.to_sym
|
98
|
+
get_flag_value(f)
|
99
|
+
else
|
100
|
+
@ctx[r] || 0
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def set_reg_value(r, v)
|
105
|
+
if r.to_s =~ /flags?_(.+)/i
|
106
|
+
f = $1.downcase.to_sym
|
107
|
+
set_flag_value(f, v)
|
108
|
+
else
|
109
|
+
@ctx[r] = v
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def do_check_target
|
114
|
+
true
|
115
|
+
end
|
116
|
+
|
117
|
+
def do_wait_target
|
118
|
+
true
|
119
|
+
end
|
120
|
+
|
121
|
+
def do_continue
|
122
|
+
while not @breakpoint[pc] and do_singlestep # TODO check bp#enabled
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def do_enable_bp(b) # no need to actually patch code in memory
|
127
|
+
end
|
128
|
+
|
129
|
+
def do_disable_bp(b)
|
130
|
+
end
|
131
|
+
|
132
|
+
def do_singlestep
|
133
|
+
di = @disassembler.di_at(pc)
|
134
|
+
if not di
|
135
|
+
@disassembler.disassemble_fast(pc)
|
136
|
+
di = @disassembler.di_at(pc)
|
137
|
+
end
|
138
|
+
if not di
|
139
|
+
if callback_unknown_pc and callback_unknown_pc.call()
|
140
|
+
return true
|
141
|
+
end
|
142
|
+
return
|
143
|
+
end
|
144
|
+
|
145
|
+
if callback_emulate_di
|
146
|
+
ret = callback_emulate_di.call(di)
|
147
|
+
return true if ret
|
148
|
+
end
|
149
|
+
|
150
|
+
return if di.opcode.props[:stopexec] and not di.opcode.props[:setip]
|
151
|
+
|
152
|
+
# 2-pass to respect binding atomicity
|
153
|
+
fbd = @disassembler.get_fwdemu_binding(di, register_pc, self)
|
154
|
+
|
155
|
+
fbd.map { |k, v|
|
156
|
+
if k.kind_of?(Indirection)
|
157
|
+
k = Indirection.new(resolve(k.pointer), k.len, k.origin)
|
158
|
+
end
|
159
|
+
[k, resolve(v)]
|
160
|
+
}.each { |k, v|
|
161
|
+
case k
|
162
|
+
when Indirection
|
163
|
+
v = v & ((1 << (k.len*8)) - 1)
|
164
|
+
memory_write_int(k.pointer, v, k.len)
|
165
|
+
when Symbol
|
166
|
+
set_reg_value(k, v)
|
167
|
+
when /^dummy_metasm_/
|
168
|
+
else
|
169
|
+
puts "singlestep: badkey #{k.inspect} = #{v}"
|
170
|
+
end
|
171
|
+
}
|
172
|
+
true
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
@@ -5,6 +5,7 @@
|
|
5
5
|
|
6
6
|
|
7
7
|
require 'metasm/os/main'
|
8
|
+
require 'metasm/debug'
|
8
9
|
require 'socket'
|
9
10
|
|
10
11
|
module Metasm
|
@@ -23,9 +24,11 @@ class GdbClient
|
|
23
24
|
def gdb_send(cmd, buf='')
|
24
25
|
buf = cmd + buf
|
25
26
|
buf = '$' << buf << '#' << gdb_csum(buf)
|
27
|
+
log "gdb_send #{buf.inspect}" if $DEBUG
|
26
28
|
|
27
29
|
5.times {
|
28
30
|
@io.write buf
|
31
|
+
out = ''
|
29
32
|
loop do
|
30
33
|
break if not IO.select([@io], nil, nil, 0.2)
|
31
34
|
raise Errno::EPIPE if not ack = @io.read(1)
|
@@ -33,12 +36,15 @@ class GdbClient
|
|
33
36
|
when '+'
|
34
37
|
return true
|
35
38
|
when '-'
|
36
|
-
|
39
|
+
log "gdb_send: ack neg" if $DEBUG
|
37
40
|
break
|
38
41
|
when nil
|
39
42
|
return
|
43
|
+
else
|
44
|
+
out << ack
|
40
45
|
end
|
41
46
|
end
|
47
|
+
log "no ack, got #{out.inspect}" if out != ''
|
42
48
|
}
|
43
49
|
|
44
50
|
log "send error #{cmd.inspect} (no ack)"
|
@@ -62,8 +68,18 @@ class GdbClient
|
|
62
68
|
buf = nil
|
63
69
|
|
64
70
|
while @recv_ctx
|
65
|
-
|
66
|
-
|
71
|
+
if !@recv_ctx[:rbuf]
|
72
|
+
return unless IO.select([@io], nil, nil, timeout)
|
73
|
+
if @io.kind_of?(UDPSocket)
|
74
|
+
raise Errno::EPIPE if not @recv_ctx[:rbuf] = @io.recvfrom(65536)[0]
|
75
|
+
else
|
76
|
+
raise Errno::EPIPE if not c = @io.read(1)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
if @recv_ctx[:rbuf]
|
80
|
+
c = @recv_ctx[:rbuf].slice!(0, 1)
|
81
|
+
@recv_ctx.delete :rbuf if @recv_ctx[:rbuf] == ''
|
82
|
+
end
|
67
83
|
|
68
84
|
case @recv_ctx[:state]
|
69
85
|
when :nosync
|
@@ -107,11 +123,11 @@ class GdbClient
|
|
107
123
|
end
|
108
124
|
outstr << unhex($1)
|
109
125
|
ret = gdb_readresp(timeout, outstr)
|
110
|
-
outstr.split("\n").each { |
|
126
|
+
outstr.split("\n").each { |o| log 'gdb: ' + o } if first
|
111
127
|
return ret
|
112
128
|
end
|
113
129
|
|
114
|
-
|
130
|
+
log "gdb_readresp: got #{buf[0, 64].inspect}#{'...' if buf.length > 64}" if $DEBUG
|
115
131
|
buf
|
116
132
|
end
|
117
133
|
|
@@ -169,7 +185,7 @@ class GdbClient
|
|
169
185
|
buf = gdb_msg('g')
|
170
186
|
regs = unhex(unrle(buf)) if buf
|
171
187
|
if not buf or regs.length < @regmsgsize
|
172
|
-
raise "regs buffer recv is too short !"
|
188
|
+
raise "regs buffer recv is too short ! (#{regs.length} < #{@regmsgsize})"
|
173
189
|
end
|
174
190
|
end
|
175
191
|
Hash[*@gdbregs.zip(@unpack_int[regs]).flatten]
|
@@ -232,9 +248,9 @@ class GdbClient
|
|
232
248
|
|
233
249
|
case io
|
234
250
|
when IO; @io = io
|
235
|
-
when /^
|
236
|
-
when /^
|
237
|
-
|
251
|
+
when /^ser:(.*)/i; @io = File.open($1, 'rb+')
|
252
|
+
when /^udp:\[?(.*)\]?:(.*?)$/i; @io = UDPSocket.new ; @io.connect($1, $2)
|
253
|
+
when /^(?:tcp:)?\[?(..+)\]?:(.*?)$/i; @io = TCPSocket.open($1, $2)
|
238
254
|
else raise "unknown target #{io.inspect}"
|
239
255
|
end
|
240
256
|
|
@@ -242,6 +258,10 @@ class GdbClient
|
|
242
258
|
end
|
243
259
|
|
244
260
|
def gdb_setup
|
261
|
+
pnd = ''
|
262
|
+
pnd << @io.read(1) while IO.select([@io], nil, nil, 0.2)
|
263
|
+
log "startpending: #{pnd.inspect}" if pnd != ''
|
264
|
+
|
245
265
|
gdb_msg('q', 'Supported')
|
246
266
|
#gdb_msg('Hc', '-1')
|
247
267
|
#gdb_msg('qC')
|
@@ -295,17 +315,22 @@ class GdbClient
|
|
295
315
|
|
296
316
|
attr_accessor :logger, :quiet
|
297
317
|
def log(s)
|
318
|
+
puts s if $DEBUG and logger
|
298
319
|
return if quiet
|
299
|
-
|
300
|
-
@logger.puts s
|
320
|
+
logger ? logger.log(s) : puts(s)
|
301
321
|
end
|
302
322
|
|
303
323
|
|
324
|
+
attr_accessor :ptrsz
|
325
|
+
|
304
326
|
# setup the various function used to pack ints & the reg list
|
305
327
|
# according to a target CPU
|
306
328
|
def setup_arch(cpu)
|
329
|
+
@ptrsz = cpu.size
|
330
|
+
|
307
331
|
case cpu.shortname
|
308
|
-
when
|
332
|
+
when /^ia32/
|
333
|
+
@ptrsz = 32
|
309
334
|
@gdbregs = GDBREGS_IA32
|
310
335
|
@regmsgsize = 4 * @gdbregs.length
|
311
336
|
when 'x64'
|
@@ -314,6 +339,12 @@ class GdbClient
|
|
314
339
|
when 'arm'
|
315
340
|
@gdbregs = cpu.dbg_register_list
|
316
341
|
@regmsgsize = 4 * @gdbregs.length
|
342
|
+
when 'arm64'
|
343
|
+
@gdbregs = cpu.dbg_register_list
|
344
|
+
@regmsgsize = 8 * @gdbregs.length
|
345
|
+
when 'mips'
|
346
|
+
@gdbregs = cpu.dbg_register_list
|
347
|
+
@regmsgsize = cpu.size/8 * @gdbregs.length
|
317
348
|
else
|
318
349
|
# we can still use readmem/kill and other generic commands
|
319
350
|
# XXX serverside setregs may fail if we give an incorrect regbuf size
|
@@ -324,7 +355,7 @@ class GdbClient
|
|
324
355
|
|
325
356
|
# yay life !
|
326
357
|
# do as if cpu is littleendian, fixup at the end
|
327
|
-
case
|
358
|
+
case @ptrsz
|
328
359
|
when 16
|
329
360
|
@pack_netint = lambda { |i| i.pack('n*') }
|
330
361
|
@unpack_netint = lambda { |s| s.unpack('n*') }
|
@@ -345,7 +376,7 @@ class GdbClient
|
|
345
376
|
@pack_netint, @pack_int = @pack_int, @pack_netint
|
346
377
|
@unpack_netint, @unpack_int = @unpack_int, @unpack_netint
|
347
378
|
end
|
348
|
-
else raise "GdbServer: unsupported cpu size #{
|
379
|
+
else raise "GdbServer: unsupported cpu size #{@ptrsz}"
|
349
380
|
end
|
350
381
|
|
351
382
|
# if target cpu is bigendian, use netint everywhere
|
@@ -362,7 +393,7 @@ class GdbRemoteString < VirtualString
|
|
362
393
|
|
363
394
|
def initialize(gdb, addr_start=0, length=nil)
|
364
395
|
@gdb = gdb
|
365
|
-
length ||= 1 << (@gdb.
|
396
|
+
length ||= 1 << (@gdb.ptrsz || 32)
|
366
397
|
@pagelength = 512
|
367
398
|
super(addr_start, length)
|
368
399
|
end
|
@@ -389,17 +420,55 @@ end
|
|
389
420
|
|
390
421
|
# this class implements a high-level API using the gdb-server network debugging protocol
|
391
422
|
class GdbRemoteDebugger < Debugger
|
392
|
-
attr_accessor :gdb, :check_target_timeout
|
423
|
+
attr_accessor :gdb, :check_target_timeout, :reg_val_cache
|
393
424
|
def initialize(url, cpu='Ia32')
|
425
|
+
super()
|
426
|
+
@tid_stuff_list << :reg_val_cache << :regs_dirty
|
394
427
|
@gdb = GdbClient.new(url, cpu)
|
395
428
|
@gdb.logger = self
|
396
|
-
@cpu = @gdb.cpu
|
397
|
-
@memory = GdbRemoteString.new(@gdb)
|
398
|
-
@reg_val_cache = {}
|
399
|
-
@regs_dirty = false
|
400
429
|
# when checking target, if no message seen since this much seconds, send a 'status' query
|
401
430
|
@check_target_timeout = 1
|
431
|
+
set_context(28, 28)
|
432
|
+
end
|
433
|
+
|
434
|
+
def check_pid(pid)
|
435
|
+
# return nil if pid == nil
|
436
|
+
pid
|
437
|
+
end
|
438
|
+
def check_tid(tid)
|
439
|
+
tid
|
440
|
+
end
|
441
|
+
|
442
|
+
def list_processes
|
443
|
+
[@pid].compact
|
444
|
+
end
|
445
|
+
def list_threads
|
446
|
+
[@tid].compact
|
447
|
+
end
|
448
|
+
|
449
|
+
def mappings
|
450
|
+
[]
|
451
|
+
end
|
452
|
+
|
453
|
+
def modules
|
454
|
+
[]
|
455
|
+
end
|
456
|
+
|
457
|
+
|
458
|
+
def initialize_newtid
|
402
459
|
super()
|
460
|
+
@reg_val_cache = {}
|
461
|
+
@regs_dirty = false
|
462
|
+
end
|
463
|
+
|
464
|
+
attr_accessor :realmode
|
465
|
+
def initialize_cpu
|
466
|
+
@cpu = @gdb.cpu
|
467
|
+
@realmode = true if @cpu and @cpu.shortname =~ /^ia32_16/
|
468
|
+
end
|
469
|
+
|
470
|
+
def initialize_memory
|
471
|
+
@memory = GdbRemoteString.new(@gdb)
|
403
472
|
end
|
404
473
|
|
405
474
|
def invalidate
|
@@ -409,12 +478,24 @@ class GdbRemoteDebugger < Debugger
|
|
409
478
|
end
|
410
479
|
|
411
480
|
def get_reg_value(r)
|
481
|
+
r = r.to_sym
|
412
482
|
return @reg_val_cache[r] || 0 if @state != :stopped
|
413
483
|
sync_regs
|
414
484
|
@reg_val_cache = @gdb.read_regs || {} if @reg_val_cache.empty?
|
485
|
+
if realmode
|
486
|
+
case r
|
487
|
+
when :eip; seg = :cs
|
488
|
+
when :esp; seg = :ss
|
489
|
+
else seg = :ds
|
490
|
+
end
|
491
|
+
# XXX seg override
|
492
|
+
return @reg_val_cache[seg].to_i*16 + @reg_val_cache[r].to_i
|
493
|
+
end
|
415
494
|
@reg_val_cache[r] || 0
|
416
495
|
end
|
417
496
|
def set_reg_value(r, v)
|
497
|
+
r = r.to_sym
|
498
|
+
# XXX realmode
|
418
499
|
@reg_val_cache[r] = v
|
419
500
|
@regs_dirty = true
|
420
501
|
end
|
@@ -426,37 +507,49 @@ class GdbRemoteDebugger < Debugger
|
|
426
507
|
|
427
508
|
def do_check_target
|
428
509
|
return if @state == :dead
|
510
|
+
|
511
|
+
# keep-alive on the connexion
|
429
512
|
t = Time.now
|
430
513
|
@last_check_target ||= t
|
431
514
|
if @state == :running and t - @last_check_target > @check_target_timeout
|
432
515
|
@gdb.io.write '$?#' << @gdb.gdb_csum('?')
|
433
516
|
@last_check_target = t
|
434
517
|
end
|
518
|
+
|
435
519
|
return unless i = @gdb.check_target(0.01)
|
436
|
-
|
437
|
-
|
438
|
-
@info = nil if @info =~ /TRAP/
|
520
|
+
update_state(i)
|
521
|
+
true
|
439
522
|
end
|
440
523
|
|
441
524
|
def do_wait_target
|
442
525
|
return unless i = @gdb.check_target(nil)
|
443
|
-
|
444
|
-
|
445
|
-
|
526
|
+
update_state(i)
|
527
|
+
end
|
528
|
+
|
529
|
+
def update_state(i)
|
530
|
+
@info = (i[:info] if i[:info] !~ /TRAP/)
|
531
|
+
if i[:state] == :stopped and @state != :stopped
|
532
|
+
invalidate
|
533
|
+
@state = i[:state]
|
534
|
+
case @run_method
|
535
|
+
when :singlestep
|
536
|
+
evt_singlestep
|
537
|
+
else
|
538
|
+
evt_bpx # XXX evt_hwbp?
|
539
|
+
end
|
540
|
+
else
|
541
|
+
@state = i[:state]
|
542
|
+
end
|
446
543
|
end
|
447
544
|
|
448
545
|
def do_continue(*a)
|
449
|
-
return if @state != :stopped
|
450
546
|
@state = :running
|
451
|
-
@info = 'continue'
|
452
547
|
@gdb.continue
|
453
548
|
@last_check_target = Time.now
|
454
549
|
end
|
455
550
|
|
456
551
|
def do_singlestep(*a)
|
457
|
-
return if @state != :stopped
|
458
552
|
@state = :running
|
459
|
-
@info = 'singlestep'
|
460
553
|
@gdb.singlestep
|
461
554
|
@last_check_target = Time.now
|
462
555
|
end
|
@@ -467,53 +560,52 @@ class GdbRemoteDebugger < Debugger
|
|
467
560
|
|
468
561
|
def kill(sig=nil)
|
469
562
|
# TODO signal nr
|
470
|
-
@gdb.kill
|
471
563
|
@state = :dead
|
472
|
-
@
|
564
|
+
@gdb.kill
|
473
565
|
end
|
474
566
|
|
475
567
|
def detach
|
476
|
-
|
477
|
-
|
478
|
-
@state = :dead
|
479
|
-
@info = 'detached'
|
568
|
+
del_all_breakpoints
|
569
|
+
del_pid
|
480
570
|
end
|
481
|
-
|
482
|
-
# set to true to use the gdb msg to handle bpx, false to set 0xcc ourself
|
571
|
+
|
572
|
+
# set to true to use the gdb msg to handle bpx, false to set 0xcc manually ourself
|
483
573
|
attr_accessor :gdb_bpx
|
484
|
-
def
|
485
|
-
return if not b = @breakpoint[addr]
|
486
|
-
b.state = :active
|
574
|
+
def do_enable_bp(b)
|
487
575
|
case b.type
|
576
|
+
when :bpm
|
577
|
+
do_enable_bpm(b)
|
488
578
|
when :bpx
|
489
579
|
if gdb_bpx
|
490
|
-
@gdb.set_hwbp('s',
|
580
|
+
@gdb.set_hwbp('s', b.address, 1)
|
491
581
|
else
|
492
|
-
@cpu.dbg_enable_bp(self,
|
582
|
+
@cpu.dbg_enable_bp(self, b)
|
493
583
|
end
|
494
|
-
when :
|
495
|
-
@gdb.set_hwbp(b.
|
584
|
+
when :hwbp
|
585
|
+
@gdb.set_hwbp(b.internal[:type], b.address, b.internal[:len])
|
496
586
|
end
|
497
587
|
end
|
498
588
|
|
499
|
-
def
|
500
|
-
return if not b = @breakpoint[addr]
|
501
|
-
b.state = :inactive
|
589
|
+
def do_disable_bp(b)
|
502
590
|
case b.type
|
591
|
+
when :bpm
|
592
|
+
do_disable_bpm(b)
|
503
593
|
when :bpx
|
504
594
|
if gdb_bpx
|
505
|
-
@gdb.unset_hwbp('s',
|
595
|
+
@gdb.unset_hwbp('s', b.address, 1)
|
506
596
|
else
|
507
|
-
@cpu.dbg_disable_bp(self,
|
597
|
+
@cpu.dbg_disable_bp(self, b)
|
508
598
|
end
|
509
|
-
when :
|
510
|
-
@gdb.unset_hwbp(b.
|
599
|
+
when :hwbp
|
600
|
+
@gdb.unset_hwbp(b.internal[:type], b.address, b.internal[:len])
|
511
601
|
end
|
512
602
|
end
|
513
603
|
|
514
604
|
def check_pre_run(*a)
|
515
|
-
|
516
|
-
|
605
|
+
if ret = super(*a)
|
606
|
+
sync_regs
|
607
|
+
ret
|
608
|
+
end
|
517
609
|
end
|
518
610
|
|
519
611
|
def loadallsyms
|