OLD | NEW |
| (Empty) |
1 // Copyright 2009 The Native Client Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can | |
3 // be found in the LICENSE file. | |
4 | |
5 #include "src/NaClVsx.DebugHelpers/GdbProxy.h" | |
6 | |
7 #include <string> | |
8 | |
9 #include "debug_conn/debug_host.h" | |
10 | |
11 using System::String; | |
12 using System::Byte; | |
13 using System::Int32; | |
14 using System::UInt32; | |
15 using System::UInt64; | |
16 using System::IntPtr; | |
17 using System::Collections::Generic::Dictionary; | |
18 using System::Diagnostics::Debug; | |
19 using System::Runtime::InteropServices::Marshal; | |
20 using System::Runtime::InteropServices::GCHandle; | |
21 using System::Runtime::InteropServices::GCHandleType; | |
22 using System::Runtime::InteropServices::OutAttribute; | |
23 | |
24 using nacl_debug_conn::DebugHost; | |
25 using std::string; | |
26 | |
27 namespace NaClVsx { namespace DebugHelpers { | |
28 | |
29 ref class ClosureMap { | |
30 public: | |
31 static int AddClosure(GdbProxy::AsyncResponse^ closure, bool remove) { | |
32 int id = nextId_++; | |
33 closureHandleMap_[id] = closure; | |
34 closureRemovalMap_[id] = remove; | |
35 return id; | |
36 } | |
37 | |
38 static GdbProxy::AsyncResponse^ GetClosure(int id) { | |
39 GdbProxy::AsyncResponse^ result = closureHandleMap_[id]; | |
40 if (closureRemovalMap_[id]) { | |
41 closureHandleMap_[id] = nullptr; | |
42 } | |
43 return result; | |
44 } | |
45 private: | |
46 static Dictionary<int, GdbProxy::AsyncResponse^> closureHandleMap_; | |
47 static Dictionary<int, bool> closureRemovalMap_; | |
48 static int nextId_ = 0; | |
49 }; | |
50 | |
51 struct GdbProxyImpl { | |
52 DebugHost *pHost; | |
53 | |
54 static void __stdcall DHAsync(DebugHost::DHResult res, void *obj); | |
55 static void __stdcall DHAsyncStr(DebugHost::DHResult res, | |
56 void *obj, | |
57 const char *str); | |
58 }; | |
59 | |
60 void __stdcall GdbProxyImpl::DHAsync(DebugHost::DHResult res, void *obj) { | |
61 GdbProxy::AsyncResponse^ closure = | |
62 ClosureMap::GetClosure(reinterpret_cast<int>(obj)); | |
63 if (closure != nullptr) { | |
64 closure((GdbProxy::ResultCode) res, nullptr, nullptr); | |
65 } | |
66 } | |
67 | |
68 void __stdcall GdbProxyImpl::DHAsyncStr( | |
69 DebugHost::DHResult res, | |
70 void *obj, const char *str) { | |
71 GdbProxy::AsyncResponse^ closure = | |
72 ClosureMap::GetClosure(reinterpret_cast<int>(obj)); | |
73 closure((GdbProxy::ResultCode) res, gcnew String(str), nullptr); | |
74 } | |
75 | |
76 GdbProxy::GdbProxy(void) | |
77 : pimpl_(new GdbProxyImpl) { | |
78 } | |
79 | |
80 GdbProxy::~GdbProxy() { | |
81 delete pimpl_; | |
82 } | |
83 | |
84 bool GdbProxy::CanConnect(String^ connectionString) { | |
85 Debug::WriteLine(String::Format("TransportImpl::CanConnect({0})", | |
86 connectionString)); | |
87 | |
88 return true; | |
89 } | |
90 | |
91 void GdbProxy::Open(String^ connectionString) { | |
92 Debug::WriteLine(String::Format("Transport::Open({0})", | |
93 connectionString)); | |
94 | |
95 IntPtr hString = Marshal::StringToHGlobalAnsi(connectionString); | |
96 pimpl_->pHost = DebugHost::SocketConnect( | |
97 static_cast<char*>(hString.ToPointer())); | |
98 Marshal::FreeHGlobal(hString); | |
99 | |
100 if (!pimpl_->pHost) { | |
101 throw gcnew System::IO::IOException( | |
102 String::Format("Failed to connect to {0}", connectionString)); | |
103 } | |
104 | |
105 connectionString_ = connectionString; | |
106 } | |
107 | |
108 void GdbProxy::Close() { | |
109 Debug::WriteLine(String::Format("Transport::Close")); | |
110 | |
111 | |
112 delete pimpl_->pHost; | |
113 pimpl_->pHost = NULL; | |
114 } | |
115 | |
116 bool GdbProxy::IsRunning() { | |
117 return pimpl_->pHost->IsRunning(); | |
118 } | |
119 | |
120 void GdbProxy::WaitForReply() { | |
121 pimpl_->pHost->WaitForReply(); | |
122 } | |
123 | |
124 void GdbProxy::SetOutputAsync(AsyncResponse^ reply) { | |
125 pimpl_->pHost->SetOutputAsync( | |
126 &GdbProxyImpl::DHAsyncStr, | |
127 reinterpret_cast<void*>(ClosureMap::AddClosure(reply, false))); | |
128 } | |
129 | |
130 void GdbProxy::SetStopAsync(AsyncResponse^ reply) { | |
131 pimpl_->pHost->SetStopAsync( | |
132 &GdbProxyImpl::DHAsync, | |
133 reinterpret_cast<void*>(ClosureMap::AddClosure(reply, false))); | |
134 } | |
135 | |
136 GdbProxy::ResultCode GdbProxy::GetArch(AsyncResponse^ reply) { | |
137 return static_cast<ResultCode>(pimpl_->pHost->GetArchAsync( | |
138 &GdbProxyImpl::DHAsyncStr, | |
139 reinterpret_cast<void*>(ClosureMap::AddClosure(reply, true)))); | |
140 } | |
141 | |
142 GdbProxy::ResultCode GdbProxy::GetThreads(AsyncResponse^ reply) { | |
143 return static_cast<ResultCode>(pimpl_->pHost->GetThreadsAsync( | |
144 &GdbProxyImpl::DHAsyncStr, | |
145 reinterpret_cast<void*>(ClosureMap::AddClosure(reply, true)))); | |
146 } | |
147 | |
148 GdbProxy::ResultCode GdbProxy::GetLastSig([Out]int% sig) { | |
149 int lastSig = 0; | |
150 ResultCode result = ResultCode::DHR_FAILED; | |
151 result = static_cast<ResultCode>(pimpl_->pHost->GetLastSig(&lastSig)); | |
152 sig = lastSig; | |
153 return result; | |
154 } | |
155 | |
156 GdbProxy::ResultCode GdbProxy::GetMemory( | |
157 System::UInt64 offs, | |
158 System::Array^ data, | |
159 System::UInt32 count ) { | |
160 Int32 size = | |
161 data->Length * Marshal::SizeOf(data->GetType()->GetElementType()); | |
162 Debug::Assert((UInt32)size >= count); | |
163 GCHandle^ hData = GCHandle::Alloc(data, GCHandleType::Pinned); | |
164 IntPtr pData = hData->AddrOfPinnedObject(); | |
165 ResultCode result = static_cast<ResultCode>( | |
166 pimpl_->pHost->GetMemory(offs, pData.ToPointer(), count)); | |
167 hData->Free(); | |
168 | |
169 return result; | |
170 } | |
171 | |
172 GdbProxy::ResultCode GdbProxy::SetMemory( | |
173 System::UInt64 offs, | |
174 System::Array^ data, | |
175 System::UInt32 count ) { | |
176 Int32 size = | |
177 data->Length * Marshal::SizeOf(data->GetType()->GetElementType()); | |
178 Debug::Assert((UInt32)size >= count); | |
179 GCHandle^ hData = GCHandle::Alloc(data, GCHandleType::Pinned); | |
180 IntPtr pData = hData->AddrOfPinnedObject(); | |
181 ResultCode result = static_cast<ResultCode>( | |
182 pimpl_->pHost->SetMemory(offs, pData.ToPointer(), count)); | |
183 hData->Free(); | |
184 | |
185 return result; | |
186 } | |
187 | |
188 GdbProxy::ResultCode GdbProxy::GetRegisters(RegsX86_64^% registers) { | |
189 Int32 size = Marshal::SizeOf(registers->GetType()); | |
190 GCHandle^ hRegisters = GCHandle::Alloc(registers, GCHandleType::Pinned); | |
191 IntPtr pRegisters = hRegisters->AddrOfPinnedObject(); | |
192 ResultCode result = static_cast<ResultCode>( | |
193 pimpl_->pHost->GetRegisters(pRegisters.ToPointer(), size)); | |
194 hRegisters->Free(); | |
195 | |
196 return result; | |
197 } | |
198 | |
199 GdbProxy::ResultCode GdbProxy::SetRegisters(void *, System::UInt32 ) { | |
200 return ResultCode::DHR_FAILED; | |
201 } | |
202 | |
203 GdbProxy::ResultCode GdbProxy::RequestBreak() { | |
204 return static_cast<ResultCode>(pimpl_->pHost->RequestBreak()); | |
205 } | |
206 | |
207 GdbProxy::ResultCode GdbProxy::RequestContinue() { | |
208 return static_cast<ResultCode>(pimpl_->pHost->RequestContinue()); | |
209 } | |
210 | |
211 GdbProxy::ResultCode GdbProxy::RequestStep() { | |
212 return static_cast<ResultCode>(pimpl_->pHost->RequestStep()); | |
213 } | |
214 | |
215 bool GdbProxy::HasBreakpoint(System::UInt64 offs ) { | |
216 return pimpl_->pHost->HasBreakpoint(offs); | |
217 } | |
218 | |
219 GdbProxy::ResultCode GdbProxy::AddBreakpoint(System::UInt64 offs ) { | |
220 return (GdbProxy::ResultCode)pimpl_->pHost->AddBreakpoint(offs); | |
221 } | |
222 | |
223 GdbProxy::ResultCode GdbProxy::RemoveBreakpoint(System::UInt64 offs ) { | |
224 return (GdbProxy::ResultCode)pimpl_->pHost->RemoveBreakpoint(offs); | |
225 } | |
226 | |
227 }} // namespace NaClVsx.DebugHelpers | |
228 | |
OLD | NEW |