/
ipydbg.py
155 lines (120 loc) · 4.59 KB
/
ipydbg.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import clr
clr.AddReference('CorDebug')
import sys
from System import Array, Console, ConsoleKey
from System.IO import Path
from System.Reflection import Assembly
from System.Threading import WaitHandle, AutoResetEvent
from System.Diagnostics.SymbolStore import ISymbolDocument, SymbolToken
from Microsoft.Samples.Debugging.CorDebug import CorDebugger
from Microsoft.Samples.Debugging.CorMetadata.NativeApi import IMetadataImport
from Microsoft.Samples.Debugging.CorSymbolStore import SymbolBinder
#use the current executing version of IPY to launch the debug process
ipy = Assembly.GetEntryAssembly().Location
py_file = sys.argv[1]
cmd_line = "\"%s\" -D \"%s\"" % (ipy, py_file)
terminate_event = AutoResetEvent(False)
break_event = AutoResetEvent(False)
sym_binder = SymbolBinder()
initial_breakpoint = None
symbol_readers = dict()
class sequence_point(object):
def __init__(self, offset, doc, start_line, start_col, end_line, end_col):
self.offset = offset
self.doc = doc
self.start_line = start_line
self.start_col = start_col
self.end_line = end_line
self.end_col = end_col
def get_sequence_points(method):
spOffsets = Array.CreateInstance(int, method.SequencePointCount)
spDocs = Array.CreateInstance(ISymbolDocument, method.SequencePointCount)
spStartLines = Array.CreateInstance(int, method.SequencePointCount)
spEndLines = Array.CreateInstance(int, method.SequencePointCount)
spStartCol = Array.CreateInstance(int, method.SequencePointCount)
spEndCol = Array.CreateInstance(int, method.SequencePointCount)
method.GetSequencePoints(spOffsets, spDocs, spStartLines, spStartCol, spEndLines, spEndCol)
for i in range(method.SequencePointCount):
yield sequence_point(spOffsets[i], spDocs[i], spStartLines[i], spStartCol[i], spEndLines[i], spEndCol[i])
def get_location(reader, thread):
frame = thread.ActiveFrame
function = frame.Function
offset, mapping_result = frame.GetIP()
method = reader.GetMethod(SymbolToken(frame.Function.Token))
real_sp = None
for sp in get_sequence_points(method):
if sp.offset > offset:
break
if sp.start_line != 0xfeefee:
real_sp = sp
if real_sp == None:
return "Location (offset %d)" % (offset)
return "Location %s:%d (offset %d)" % (
Path.GetFileName(real_sp.doc.URL), real_sp.start_line, offset)
def create_breakpoint(doc, line, module, reader):
line = doc.FindClosestLine(line)
method = reader.GetMethodFromDocumentPosition(doc, line, 0)
function = module.GetFunctionFromToken(method.Token.GetToken())
for sp in get_sequence_points(method):
if sp.doc.URL == doc.URL and sp.start_line == line:
bp = function.ILCode.CreateBreakpoint(sp.offset)
bp.Activate(True)
return bp
bp = function.CreateBreakpoint()
bp.Activate(True)
return bp
def OnCreateAppDomain(s,e):
print "OnCreateAppDomain", e.AppDomain.Name
e.AppDomain.Attach()
def OnProcessExit(s,e):
print "OnProcessExit"
terminate_event.Set()
def OnUpdateModuleSymbols(s,e):
print "OnUpdateModuleSymbols"
metadata_import = e.Module.GetMetaDataInterface[IMetadataImport]()
reader = sym_binder.GetReaderFromStream(metadata_import, e.Stream)
global symbol_readers
symbol_readers[e.Module] = reader
global initial_breakpoint
if initial_breakpoint != None:
return
full_path = Path.GetFullPath(py_file)
for doc in reader.GetDocuments():
if str.IsNullOrEmpty(doc.URL):
continue
if str.Compare(full_path, Path.GetFullPath(doc.URL), True) == 0:
initial_breakpoint = create_breakpoint(doc, 1, e.Module, reader)
def OnBreakpoint(s,e):
print "OnBreakpoint", get_location(
symbol_readers[e.Thread.ActiveFrame.Function.Module], e.Thread)
e.Continue = False
break_event.Set()
def input():
while True:
Console.Write("» ")
k = Console.ReadKey()
if k.Key == ConsoleKey.Spacebar:
Console.WriteLine("\nContinuing")
return
elif k.Key == ConsoleKey.Q:
Console.WriteLine("\nQuitting")
process.Stop(0)
process.Terminate(255)
return
else:
Console.WriteLine("\n Please enter a valid command")
debugger = CorDebugger(CorDebugger.GetDefaultDebuggerVersion())
process = debugger.CreateProcess(ipy, cmd_line)
process.OnCreateAppDomain += OnCreateAppDomain
process.OnProcessExit += OnProcessExit
process.OnUpdateModuleSymbols += OnUpdateModuleSymbols
process.OnBreakpoint += OnBreakpoint
handles = Array.CreateInstance(WaitHandle, 2)
handles[0] = terminate_event
handles[1] = break_event
while True:
process.Continue(False)
i = WaitHandle.WaitAny(handles)
if i == 0:
break
input()