|
OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2010 The Native Client Authors. All rights reserved. | |
3 * Use of this source code is governed by a BSD-style license that can | |
4 * be found in the LICENSE file. | |
5 */ | |
6 | |
7 #include <assert.h> | |
8 #include <string.h> | |
9 #include <stdlib.h> | |
10 #include <stdio.h> | |
mmortensen
2010/12/07 22:53:58
Minor nit: we could use C++ style headers here, s
mlinck
2010/12/10 21:10:27
I'm leaning towards leaving these since they're wo
| |
11 | |
12 #include "native_client/src/trusted/gdb_rsp/abi.h" | |
13 #include "native_client/src/trusted/gdb_rsp/host.h" | |
14 #include "native_client/src/trusted/gdb_rsp/host_mock.h" | |
15 #include "native_client/src/trusted/gdb_rsp/packet.h" | |
16 #include "native_client/src/trusted/gdb_rsp/session.h" | |
17 #include "native_client/src/trusted/gdb_rsp/util.h" | |
18 | |
19 #include "native_client/src/trusted/port/std_types.h" | |
20 #include "native_client/src/trusted/port/platform.h" | |
21 | |
22 #ifdef WIN32 | |
23 #define snprintf sprintf_s | |
24 #endif | |
25 | |
26 | |
27 using std::string; | |
28 using port::IPlatform; | |
29 | |
30 namespace gdb_rsp { | |
31 | |
32 | |
33 // Construct unitialzied | |
34 HostMock::HostMock() : Host(0) { } | |
noelallen_use_chromium
2010/12/07 23:04:44
http://www.corp.google.com/eng/doc/cppguide.xml#0_
| |
35 | |
36 HostMock::~HostMock() { | |
37 while (!signals_.empty()) { | |
38 SignalMock* sig = signals_.front(); | |
39 signals_.pop_front(); | |
40 delete sig; | |
41 } | |
42 | |
43 while (!memory_.empty()) { | |
44 delete[] memory_.begin()->second; | |
45 memory_.erase(memory_.begin()); | |
46 } | |
47 } | |
48 | |
49 bool HostMock::Init() { | |
50 string reply; | |
51 | |
52 properties_.clear(); | |
53 properties_["PacketSize"] = "3fa"; | |
54 | |
55 SetRequest("qExecPath", "nullptr.nexe"); | |
56 SetRequest("qExecArgs", ""); | |
57 SetRequest("qExecEnvs", ""); | |
58 | |
59 abi_ = Abi::Find("i386:x86-64"); | |
60 | |
61 status_ = HS_STOPPED; | |
62 return true; | |
63 } | |
64 | |
65 bool HostMock::Step() { | |
66 // We can only step if we are stopped | |
67 if (HS_STOPPED != status_) return false; | |
68 | |
69 status_ = HS_RUNNING; | |
70 return true; | |
71 } | |
72 | |
73 bool HostMock::Continue() { | |
74 // We can only step if we are stopped | |
75 if (HS_STOPPED != status_) return false; | |
76 | |
77 status_ = HS_RUNNING; | |
78 return true; | |
79 } | |
80 | |
81 | |
82 bool HostMock::Break() { | |
83 char brk[2] = { 0x03, 0x00 }; | |
noelallen_use_chromium
2010/12/07 23:04:44
Where is this used? This should have generated a
| |
84 | |
85 // We can only break if running | |
86 if (HS_RUNNING != status_) return false; | |
87 | |
88 status_ = HS_STOPPING; | |
89 | |
90 SignalMock* sig = new SignalMock; | |
noelallen_use_chromium
2010/12/07 23:04:44
While this is not REALLY trusted code, since it wi
mlinck
2010/12/10 21:10:27
There's a separate target for these called gdb_rsp
| |
91 sig->sig = 5; | |
92 sig->thread = 0; | |
93 sig->rel = true; | |
94 sig->ip = 0; | |
95 | |
96 signals_.push_front(sig); | |
97 return true; | |
98 } | |
99 | |
100 bool HostMock::Detach() { | |
101 // We can only detach if stopped | |
102 if (HS_STOPPED != status_) return false; | |
103 return true; | |
104 } | |
105 | |
106 #define MEMBLOCKSIZE 65536 | |
107 bool HostMock::GetMemory(void *dst, uint64_t addr, uint32_t size) { | |
108 char *out = reinterpret_cast<char *>(dst); | |
109 | |
110 while (size) { | |
111 uint64_t key = addr & ~(MEMBLOCKSIZE - 1); | |
112 uint64_t offs = addr & (MEMBLOCKSIZE - 1); | |
113 uint32_t max = static_cast<uint32_t>(MEMBLOCKSIZE - offs); | |
114 char *data = memory_[key]; | |
115 | |
116 /* Truncate this iteration */ | |
117 if (max > size) max = size; | |
118 | |
119 /* Check if block is availible */ | |
noelallen_use_chromium
2010/12/07 23:04:44
Misleading:
Fail if block does not exist.
| |
120 if (NULL == data) return false; | |
121 | |
122 /* Copy it out. */ | |
123 memcpy(out, &data[addr - key], max); | |
124 size -= max; | |
125 out += max; | |
noelallen_use_chromium
2010/12/07 23:04:44
Does this actually work? Addr does not appear to
| |
126 } | |
127 | |
128 return true; | |
129 } | |
130 | |
131 bool HostMock::SetMemory(const void *src, uint64_t addr, uint32_t size) { | |
132 const char *in = reinterpret_cast<const char *>(src); | |
133 | |
134 while (size) { | |
noelallen_use_chromium
2010/12/07 23:04:44
Same as above.
| |
135 uint64_t key = addr & ~(MEMBLOCKSIZE - 1); | |
136 uint64_t offs = addr & (MEMBLOCKSIZE - 1); | |
137 uint32_t max = static_cast<uint32_t>(MEMBLOCKSIZE - offs); | |
138 char *data = memory_[key]; | |
139 | |
140 /* Truncate this iteration */ | |
141 if (max > size) max = size; | |
142 | |
143 /* Check if block is availible, if not allocate */ | |
144 if (NULL == data) { | |
145 data = new char[MEMBLOCKSIZE]; | |
146 memory_[key] = data; | |
147 } | |
148 | |
149 /* Copy it out. */ | |
150 memcpy(&data[addr - key], in, max); | |
151 size -= max; | |
152 in += max; | |
153 } | |
154 | |
155 return true; | |
156 } | |
157 | |
158 bool HostMock::Request(const std::string &req, std::string *resp) { | |
159 std::map<string, string>::const_iterator itr; | |
160 itr = requests_.find(req); | |
161 | |
162 if (requests_.end() == itr) return false; | |
163 | |
164 *resp = itr->second; | |
165 return true; | |
166 } | |
167 | |
168 void HostMock::SetRequest(const std::string &req, const std::string &resp) { | |
169 requests_[req] = resp; | |
170 } | |
171 | |
172 | |
noelallen_use_chromium
2010/12/07 23:04:44
Either the source or the header should describe th
| |
173 void HostMock::AddSignal(int32_t signal, uint32_t thread) { | |
174 SignalMock* sig = new SignalMock; | |
175 sig->sig = signal; | |
176 sig->thread = thread; | |
177 sig->rel = true; | |
178 sig->ip = 0; | |
179 | |
180 signals_.push_back(sig); | |
181 } | |
182 | |
183 void HostMock::AddSignalAbs(int32_t signal, uint32_t thread, uint64_t ip) { | |
184 SignalMock* sig = new SignalMock; | |
185 sig->sig = signal; | |
186 sig->thread = thread; | |
187 sig->rel = false; | |
188 sig->ip = ip; | |
189 | |
190 signals_.push_back(sig); | |
191 } | |
192 | |
193 void HostMock::AddSignalDelta(int32_t signal, uint32_t thread, int64_t delta) { | |
194 SignalMock* sig = new SignalMock; | |
195 sig->sig = signal; | |
196 sig->thread = thread; | |
197 sig->rel = true; | |
198 sig->ip = delta; | |
199 | |
200 signals_.push_back(sig); | |
201 } | |
202 | |
203 // Wait to see if we receive a break | |
204 bool HostMock::WaitForBreak() { | |
205 if (signals_.empty()) return false; | |
206 | |
207 SignalMock* sig = signals_.front(); | |
208 signals_.pop_front(); | |
209 | |
210 Thread* thread = GetThread(sig->thread); | |
211 if (thread) { | |
212 const Abi *abi = thread->GetAbi(); | |
213 const Abi::RegDef *def = abi->GetRegisterType(Abi::INST_PTR); | |
214 uint64_t ip; | |
215 | |
216 if (sig->rel) { | |
217 thread->GetRegister(def->index_, &ip); | |
218 sig->ip += ip; | |
noelallen_use_chromium
2010/12/07 23:04:44
Should this be
ip += sig->ip
| |
219 } else { | |
220 ip = sig->ip; | |
221 } | |
222 | |
223 /* Update the current thread's IP */ | |
224 thread->SetRegister(def->index_, &ip); | |
225 } | |
226 | |
227 /* Generate a "signal" packet */ | |
228 char tmp[64]; | |
229 snprintf(tmp, "S%02d", sig->sig, 63); | |
noelallen_use_chromium
2010/12/07 23:04:44
should use sizeof(tmp) instead of 63 in case the s
| |
230 ParseStopPacket(tmp); | |
231 | |
232 delete sig; | |
233 return true; | |
234 } | |
235 | |
236 | |
237 | |
238 } // namespace gdb_rsp | |
239 | |
240 | |
OLD | NEW |