This repository has been archived by the owner on Feb 8, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
/
ThreadDB.cs
210 lines (172 loc) · 4.6 KB
/
ThreadDB.cs
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
using System;
using System.Runtime.InteropServices;
namespace Mono.Debugger.Backend
{
internal class ThreadDB : DebuggerMarshalByRefObject
{
IntPtr handle;
ProcessServant process;
TargetMemoryAccess target;
DebuggerMutex mutex;
enum PsErr {
Ok = 0,
Err,
BadPid,
BadLid,
BadAddr,
NoSym,
NoFpRegs
};
internal delegate void GetThreadInfoFunc (int lwp, long tid);
delegate PsErr GlobalLookupFunc (string obj_name, string sym_name, out long addr);
delegate PsErr ReadMemoryFunc (long address, IntPtr buffer, int size);
delegate PsErr WriteMemoryFunc (long address, IntPtr buffer, int size);
delegate bool IterateOverThreadsFunc (IntPtr th);
[DllImport("monodebuggerserver")]
static extern IntPtr mono_debugger_thread_db_init (int pid, GlobalLookupFunc lookup_func, ReadMemoryFunc read_memory_func, WriteMemoryFunc write_memory_func);
[DllImport("monodebuggerserver")]
static extern void mono_debugger_thread_db_destroy (IntPtr handle);
[DllImport("monodebuggerserver")]
static extern bool mono_debugger_thread_db_iterate_over_threads (IntPtr handle, IterateOverThreadsFunc func);
[DllImport("monodebuggerserver")]
static extern bool mono_debugger_thread_db_get_thread_info (IntPtr th, out long tid, out long tls, out long lwp);
GlobalLookupFunc global_lookup_func;
ReadMemoryFunc read_memory_func;
WriteMemoryFunc write_memory_func;
protected ThreadDB (ProcessServant process)
{
this.process = process;
mutex = new DebuggerMutex ("thread_db_mutex");
global_lookup_func = new GlobalLookupFunc (global_lookup);
read_memory_func = new ReadMemoryFunc (read_memory);
write_memory_func = new WriteMemoryFunc (write_memory);
}
protected bool Initialize (Inferior target)
{
try {
mutex.Lock ();
this.target = target;
handle = mono_debugger_thread_db_init (
target.PID, global_lookup_func, read_memory_func,
write_memory_func);
return handle != IntPtr.Zero;
} finally {
this.target = null;
mutex.Unlock ();
}
}
public static ThreadDB Create (ProcessServant process, Inferior target)
{
ThreadDB db = new ThreadDB (process);
if (!db.Initialize (target))
return null;
return db;
}
bool get_thread_info (IntPtr th)
{
long tid, tls, lwp;
if (!mono_debugger_thread_db_get_thread_info (th, out tid, out tls, out lwp))
return false;
return true;
}
public void GetThreadInfo (TargetMemoryAccess target, GetThreadInfoFunc func)
{
try {
mutex.Lock ();
this.target = target;
mono_debugger_thread_db_iterate_over_threads (
handle, delegate (IntPtr th) {
long tid, tls, lwp;
if (!mono_debugger_thread_db_get_thread_info (
th, out tid, out tls, out lwp))
return false;
func ((int) lwp, tid);
return true;
});
} finally {
this.target = null;
mutex.Unlock ();
}
}
PsErr global_lookup (string obj_name, string sym_name, out long sym_addr)
{
Bfd bfd = process.BfdContainer.FindLibrary (obj_name);
if (bfd == null) {
sym_addr = 0;
return PsErr.NoSym;
}
TargetAddress addr = bfd.LookupLocalSymbol (sym_name);
if (addr.IsNull) {
sym_addr = 0;
return PsErr.NoSym;
}
sym_addr = addr.Address;
return PsErr.Ok;
}
TargetAddress create_address (long address)
{
return new TargetAddress (target.AddressDomain, address);
}
PsErr read_memory (long address, IntPtr ptr, int size)
{
try {
byte[] buffer = target.ReadBuffer (create_address (address), size);
Marshal.Copy (buffer, 0, ptr, size);
} catch {
return PsErr.BadAddr;
}
return PsErr.Ok;
}
PsErr write_memory (long address, IntPtr ptr, int size)
{
#if FIXME
byte[] buffer = new byte [size];
Marshal.Copy (ptr, buffer, 0, size);
try {
target.WriteBuffer (create_address (address), buffer);
} catch {
return PsErr.BadAddr;
}
return PsErr.Ok;
#else
return PsErr.Err;
#endif
}
//
// IDisposable
//
private bool disposed = false;
private void check_disposed ()
{
if (disposed)
throw new ObjectDisposedException ("ThreadDB");
}
private void Dispose (bool disposing)
{
// Check to see if Dispose has already been called.
lock (this) {
if (disposed)
return;
if (handle != IntPtr.Zero) {
mono_debugger_thread_db_destroy (handle);
handle = IntPtr.Zero;
}
if (mutex != null) {
mutex.Dispose ();
mutex = null;
}
disposed = true;
}
}
public void Dispose ()
{
Dispose (true);
// Take yourself off the Finalization queue
GC.SuppressFinalize (this);
}
~ThreadDB ()
{
Dispose (false);
}
}
}