1 : /*
2 : * Copyright (c) 2010 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 :
8 : #include <assert.h>
9 : #include <string.h>
10 : #include <stdlib.h>
11 :
12 : #include <string>
13 :
14 : #include "native_client/src/shared/platform/nacl_log.h"
15 : #include "native_client/src/trusted/debug_stub/packet.h"
16 : #include "native_client/src/trusted/debug_stub/util.h"
17 : #include "native_client/src/trusted/debug_stub/platform.h"
18 :
19 : using std::string;
20 : using port::IPlatform;
21 :
22 :
23 : namespace gdb_rsp {
24 :
25 : #define MIN_PAD 1
26 : #define GROW_SIZE 64
27 :
28 532 : Packet::Packet() {
29 266 : seq_ = -1;
30 266 : Clear();
31 532 : }
32 :
33 : void Packet::Clear() {
34 3856 : data_.clear();
35 3856 : data_.resize(GROW_SIZE);
36 3856 : data_[0] = 0;
37 :
38 3856 : read_index_ = 0;
39 3856 : write_index_ = 0;
40 3856 : }
41 :
42 : void Packet::Rewind() {
43 1 : read_index_ = 0;
44 1 : }
45 :
46 : bool Packet::EndOfPacket() const {
47 215 : return (read_index_ >= write_index_);
48 : }
49 :
50 326820 : void Packet::AddRawChar(char ch) {
51 : // Grow by a fixed amount whenever we are within the pad boundry.
52 : // The pad boundry allows for the addition of NUL termination.
53 326820 : if (data_.size() <= (write_index_ + MIN_PAD)) {
54 4760 : data_.resize(data_.size() + GROW_SIZE);
55 4760 : }
56 :
57 : // Add character and always null terminate.
58 326820 : data_[write_index_++] = ch;
59 326820 : data_[write_index_] = 0;
60 326820 : }
61 :
62 23968 : void Packet::AddWord8(uint8_t ch) {
63 23968 : char seq1, seq2;
64 :
65 23968 : IntToNibble(ch >> 4, &seq1);
66 23968 : IntToNibble(ch & 0xF, &seq2);
67 :
68 23968 : AddRawChar(seq1);
69 23968 : AddRawChar(seq2);
70 23968 : }
71 :
72 564 : void Packet::AddBlock(const void *ptr, uint32_t len) {
73 1128 : assert(ptr);
74 :
75 564 : const char *p = (const char *) ptr;
76 :
77 48742 : for (uint32_t offs = 0; offs < len; offs++) {
78 23807 : AddWord8(p[offs]);
79 23807 : }
80 564 : }
81 :
82 1 : void Packet::AddWord16(uint16_t val) {
83 1 : AddBlock(&val, sizeof(val));
84 1 : }
85 :
86 1 : void Packet::AddWord32(uint32_t val) {
87 1 : AddBlock(&val, sizeof(val));
88 1 : }
89 :
90 0 : void Packet::AddWord64(uint64_t val) {
91 0 : AddBlock(&val, sizeof(val));
92 0 : }
93 :
94 425 : void Packet::AddString(const char *str) {
95 850 : assert(str);
96 :
97 3452 : while (*str) {
98 2602 : AddRawChar(*str);
99 2602 : str++;
100 2602 : }
101 425 : }
102 :
103 99 : void Packet::AddEscapedData(const char *data, size_t length) {
104 219692 : while (length > 0) {
105 219494 : char ch = *data;
106 : // Escape certain characters by sending 0x7d ('}') followed by the original
107 : // character xor-ed with 0x20.
108 873553 : if (ch == '}' || ch == '#' || ch == '$' || ch == '*') {
109 4039 : AddRawChar('}');
110 4039 : AddRawChar(ch ^ 0x20);
111 4039 : } else {
112 215455 : AddRawChar(ch);
113 : }
114 219494 : ++data;
115 219494 : --length;
116 : // See if run length encoding can be used.
117 : // Limit runs to 97 copies, as character 126 is the highest that can be
118 : // used in the encoding.
119 219494 : size_t count = 0;
120 1480977 : while (count < 97 && length > count && data[count] == ch) {
121 201701 : count++;
122 201701 : }
123 : // We can only use run length encoding if there are 3 or more of the same
124 : // character (not including the initial character). This is the minimum run
125 : // length allowed by the protocol.
126 219494 : if (count >= 3) {
127 : // An odd quirk of the protocol is that because the characters
128 : // '#' and '$' cannot appear in a packet, they also are not valid as a
129 : // run length. Since these correspond to lengths 6 and 7, runs of this
130 : // size must be clipped down to length 5.
131 31134 : if (count == 6 || count == 7) {
132 661 : count = 5;
133 661 : }
134 15890 : AddRawChar('*');
135 15890 : AddRawChar(static_cast<char>(count + 29));
136 15890 : data += count;
137 15890 : length -= count;
138 15890 : }
139 219494 : }
140 99 : }
141 :
142 0 : void Packet::AddHexString(const char *str) {
143 0 : assert(str);
144 :
145 0 : while (*str) {
146 0 : AddWord8(*str);
147 0 : str++;
148 0 : }
149 0 : }
150 :
151 204 : void Packet::AddNumberSep(uint64_t val, char sep) {
152 204 : char out[sizeof(val) * 2];
153 204 : int nibbles = 0;
154 204 : size_t a;
155 :
156 : // Check for -1 optimization
157 204 : if (val == static_cast<uint64_t>(-1)) {
158 1 : AddRawChar('-');
159 1 : AddRawChar('1');
160 1 : } else {
161 : // Assume we have the valuse 0x00001234
162 618 : for (a = 0; a < sizeof(val); a++) {
163 309 : uint8_t byte = static_cast<uint8_t>(val & 0xFF);
164 :
165 : // Stream in with bytes reverse, starting at least significant
166 : // So we store 4, then 3, 2, 1
167 309 : IntToNibble(byte & 0xF, &out[nibbles++]);
168 309 : IntToNibble(byte >> 4, &out[nibbles++]);
169 :
170 : // Get the next 8 bits;
171 309 : val >>= 8;
172 :
173 : // Supress leading zeros, so we are done when val hits zero
174 309 : if (val == 0) {
175 203 : break;
176 : }
177 106 : }
178 :
179 : // Strip the high zero for this byte if needed
180 510 : if ((nibbles > 1) && (out[nibbles-1] == '0')) nibbles--;
181 :
182 : // Now write it out reverse to correct the order
183 920 : while (nibbles) {
184 514 : nibbles--;
185 514 : AddRawChar(out[nibbles]);
186 514 : }
187 : }
188 :
189 : // If we asked for a sperator, insert it
190 403 : if (sep) AddRawChar(sep);
191 204 : }
192 :
193 1613 : bool Packet::GetNumberSep(uint64_t *val, char *sep) {
194 1613 : uint64_t out = 0;
195 1613 : char ch;
196 :
197 1613 : if (!GetRawChar(&ch)) {
198 0 : return false;
199 : }
200 :
201 : // Check for -1
202 1613 : if (ch == '-') {
203 29 : if (!GetRawChar(&ch)) {
204 0 : return false;
205 : }
206 :
207 29 : if (ch == '1') {
208 29 : *val = -1;
209 :
210 29 : ch = 0;
211 29 : GetRawChar(&ch);
212 29 : if (sep) {
213 0 : *sep = ch;
214 0 : }
215 29 : return true;
216 : }
217 0 : return false;
218 : }
219 :
220 1584 : do {
221 5946 : int nib;
222 :
223 : // Check for separator
224 5946 : if (!NibbleToInt(ch, &nib)) {
225 878 : break;
226 : }
227 :
228 : // Add this nibble.
229 5068 : out = (out << 4) + nib;
230 :
231 : // Get the next character (if availible)
232 5068 : ch = 0;
233 5068 : if (!GetRawChar(&ch)) {
234 706 : break;
235 : }
236 8724 : } while (1);
237 :
238 : // Set the value;
239 1584 : *val = out;
240 :
241 : // Add the separator if the user wants it...
242 1584 : if (sep != NULL) *sep = ch;
243 :
244 1584 : return true;
245 1613 : }
246 :
247 16876 : bool Packet::GetRawChar(char *ch) {
248 33752 : assert(ch != NULL);
249 :
250 16876 : if (read_index_ >= write_index_)
251 881 : return false;
252 :
253 15995 : *ch = data_[read_index_++];
254 :
255 : // Check for RLE X*N, where X is the value, N is the reps.
256 15995 : if (*ch == '*') {
257 9 : if (read_index_ < 2) {
258 0 : NaClLog(LOG_ERROR, "Unexpected RLE at start of packet.\n");
259 0 : return false;
260 : }
261 :
262 9 : if (read_index_ >= write_index_) {
263 0 : NaClLog(LOG_ERROR, "Unexpected EoP during RLE.\n");
264 0 : return false;
265 : }
266 :
267 : // GDB does not use "CTRL" characters in the stream, so the
268 : // number of reps is encoded as the ASCII value beyond 28
269 : // (which when you add a min rep size of 4, forces the rep
270 : // character to be ' ' (32) or greater).
271 9 : int32_t cnt = (data_[read_index_] - 28);
272 9 : if (cnt < 3) {
273 0 : NaClLog(LOG_ERROR, "Unexpected RLE length.\n");
274 0 : return false;
275 : }
276 :
277 : // We have just read '*' and incremented the read pointer,
278 : // so here is the old state, and expected new state.
279 : //
280 : // Assume N = 5, we grow by N - size of encoding (3).
281 : //
282 : // OldP: R W
283 : // OldD: 012X*N89 = 8 chars
284 : // Size: 012X*N89__ = 10 chars
285 : // Move: 012X*__N89 = 10 chars
286 : // Fill: 012XXXXX89 = 10 chars
287 : // NewP: R W (shifted 5 - 3)
288 : //
289 : // To accomplish this we must first, resize the vector then move
290 : // all remaining characters to the right, by the delta between
291 : // the run length, and encoding size. This moves one more char
292 : // than needed (the 'N'), but is easier to understand.
293 : // NOTE: We add one to the resize to allow for zero termination.
294 9 : data_.resize(write_index_ + cnt - 3 + 1);
295 9 : memmove(&data_[read_index_ + cnt - 3], &data_[read_index_],
296 : write_index_ - read_index_);
297 :
298 : // Now me must go back and fill over the previous '*' with the
299 : // repeated character for the length of the run minus the original
300 : // character which is already correct
301 9 : *ch = data_[read_index_ - 2];
302 9 : memset(&data_[read_index_ - 1], *ch, cnt - 1);
303 :
304 : // Now we update the write_index_, and reterminate the string.
305 9 : write_index_ = data_.size() - 1;
306 9 : data_[write_index_] = 0;
307 9 : }
308 15995 : return true;
309 16876 : }
310 :
311 3890 : bool Packet::GetWord8(uint8_t *ch) {
312 7780 : assert(ch);
313 :
314 3890 : char seq1, seq2;
315 3890 : int val1, val2;
316 :
317 : // Get two ASCII hex values
318 3890 : if (!GetRawChar(&seq1)) {
319 0 : return false;
320 : }
321 3890 : if (!GetRawChar(&seq2)) {
322 145 : return false;
323 : }
324 :
325 : // Convert them to ints
326 3745 : if (!NibbleToInt(seq1, &val1)) {
327 1030 : return false;
328 : }
329 2715 : if (!NibbleToInt(seq2, &val2)) {
330 0 : return false;
331 : }
332 :
333 2715 : *ch = (val1 << 4) + val2;
334 2715 : return true;
335 3890 : }
336 :
337 23 : bool Packet::GetBlock(void *ptr, uint32_t len) {
338 46 : assert(ptr);
339 :
340 23 : uint8_t *p = reinterpret_cast<uint8_t *>(ptr);
341 23 : bool res = true;
342 :
343 5474 : for (uint32_t offs = 0; offs < len; offs++) {
344 2714 : res = GetWord8(&p[offs]);
345 2714 : if (false == res) {
346 0 : break;
347 : }
348 2714 : }
349 :
350 23 : return res;
351 : }
352 :
353 1 : bool Packet::GetWord16(uint16_t *ptr) {
354 2 : assert(ptr);
355 1 : return GetBlock(ptr, sizeof(*ptr));
356 : }
357 :
358 1 : bool Packet::GetWord32(uint32_t *ptr) {
359 2 : assert(ptr);
360 1 : return GetBlock(ptr, sizeof(*ptr));
361 : }
362 :
363 0 : bool Packet::GetWord64(uint64_t *ptr) {
364 0 : assert(ptr);
365 0 : return GetBlock(ptr, sizeof(*ptr));
366 : }
367 :
368 :
369 12 : bool Packet::GetString(string* str) {
370 12 : if (EndOfPacket()) {
371 0 : return false;
372 : }
373 :
374 12 : *str = &data_[read_index_];
375 12 : read_index_ = write_index_;
376 12 : return true;
377 12 : }
378 :
379 1 : bool Packet::GetHexString(string* str) {
380 : // Decode a string encoded as a series of 2-hex digit pairs.
381 :
382 1 : char ch1;
383 1 : char ch2;
384 1 : int nib1;
385 1 : int nib2;
386 :
387 1 : if (EndOfPacket()) {
388 0 : return false;
389 : }
390 :
391 : // Pull values until we hit a separator
392 1 : str->clear();
393 6 : while (GetRawChar(&ch1)) {
394 5 : if (!NibbleToInt(ch1, &nib1)) {
395 1 : read_index_--;
396 1 : break;
397 : }
398 4 : if (!GetRawChar(&ch2) ||
399 4 : !NibbleToInt(ch2, &nib2)) {
400 0 : return false;
401 : }
402 4 : *str += static_cast<char>((nib1 << 4) + nib2);
403 4 : }
404 1 : return true;
405 1 : }
406 :
407 202 : bool Packet::GetStringSep(std::string *str, char sep) {
408 202 : char ch;
409 :
410 202 : if (EndOfPacket()) {
411 0 : return false;
412 : }
413 :
414 : // Pull values until we hit a separator
415 202 : str->clear();
416 1312 : while (GetRawChar(&ch)) {
417 1110 : if (ch == sep) {
418 202 : return true;
419 : } else {
420 908 : *str += ch;
421 : }
422 908 : }
423 0 : return false;
424 202 : }
425 :
426 : const char *Packet::GetPayload() const {
427 1552 : return &data_[0];
428 : }
429 :
430 : size_t Packet::GetPayloadSize() const {
431 1177 : return write_index_;
432 : }
433 :
434 4703 : bool Packet::GetSequence(int32_t *ch) const {
435 9406 : assert(ch);
436 :
437 4703 : if (seq_ != -1) {
438 0 : *ch = seq_;
439 0 : return true;
440 : }
441 :
442 4703 : return false;
443 4703 : }
444 :
445 : void Packet::ParseSequence() {
446 1175 : size_t saved_read_index = read_index_;
447 1175 : unsigned char seq;
448 1175 : char ch;
449 1175 : if (GetWord8(&seq) &&
450 0 : GetRawChar(&ch)) {
451 0 : if (ch == ':') {
452 0 : SetSequence(seq);
453 0 : return;
454 : }
455 0 : }
456 : // No sequence number present, so reset to original position.
457 1175 : read_index_ = saved_read_index;
458 2350 : }
459 :
460 0 : void Packet::SetSequence(int32_t val) {
461 0 : seq_ = val;
462 0 : }
463 :
464 : } // namespace gdb_rsp
465 :
|