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
|
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 (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 (TargetMemoryAccess target)
{
try {
mutex.Lock ();
this.target = target;
handle = mono_debugger_thread_db_init (
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, TargetMemoryAccess 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;
}
disposed = true;
}
}
public void Dispose ()
{
Dispose (true);
// Take yourself off the Finalization queue
GC.SuppressFinalize (this);
}
~ThreadDB ()
{
Dispose (false);
}
}
}
|