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 
Packet()28 Packet::Packet() {
29   seq_ = -1;
30   Clear();
31 }
32 
Clear()33 void Packet::Clear() {
34   data_.clear();
35   data_.resize(GROW_SIZE);
36   data_[0] = 0;
37 
38   read_index_  = 0;
39   write_index_ = 0;
40 }
41 
Rewind()42 void Packet::Rewind() {
43   read_index_ = 0;
44 }
45 
EndOfPacket() const46 bool Packet::EndOfPacket() const {
47   return (read_index_ >= write_index_);
48 }
49 
AddRawChar(char ch)50 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   if (data_.size() <= (write_index_ + MIN_PAD)) {
54     data_.resize(data_.size() + GROW_SIZE);
55   }
56 
57   // Add character and always null terminate.
58   data_[write_index_++] = ch;
59   data_[write_index_] = 0;
60 }
61 
AddWord8(uint8_t ch)62 void Packet::AddWord8(uint8_t ch) {
63   char seq1, seq2;
64 
65   IntToNibble(ch >> 4, &seq1);
66   IntToNibble(ch & 0xF, &seq2);
67 
68   AddRawChar(seq1);
69   AddRawChar(seq2);
70 }
71 
AddBlock(const void * ptr,uint32_t len)72 void Packet::AddBlock(const void *ptr, uint32_t len) {
73   assert(ptr);
74 
75   const char *p = (const char *) ptr;
76 
77   for (uint32_t offs = 0; offs < len; offs++) {
78     AddWord8(p[offs]);
79   }
80 }
81 
AddWord16(uint16_t val)82 void Packet::AddWord16(uint16_t val) {
83   AddBlock(&val, sizeof(val));
84 }
85 
AddWord32(uint32_t val)86 void Packet::AddWord32(uint32_t val) {
87   AddBlock(&val, sizeof(val));
88 }
89 
AddWord64(uint64_t val)90 void Packet::AddWord64(uint64_t val) {
91   AddBlock(&val, sizeof(val));
92 }
93 
AddString(const char * str)94 void Packet::AddString(const char *str) {
95   assert(str);
96 
97   while (*str) {
98     AddRawChar(*str);
99     str++;
100   }
101 }
102 
AddEscapedData(const char * data,size_t length)103 void Packet::AddEscapedData(const char *data, size_t length) {
104   while (length > 0) {
105     char ch = *data;
106     // Escape certain characters by sending 0x7d ('}') followed by the original
107     // character xor-ed with 0x20.
108     if (ch == '}' || ch == '#' || ch == '$' || ch == '*') {
109       AddRawChar('}');
110       AddRawChar(ch ^ 0x20);
111     } else {
112       AddRawChar(ch);
113     }
114     ++data;
115     --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     size_t count = 0;
120     while (count < 97 && length > count && data[count] == ch) {
121       count++;
122     }
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     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       if (count == 6 || count == 7) {
132         count = 5;
133       }
134       AddRawChar('*');
135       AddRawChar(static_cast<char>(count + 29));
136       data += count;
137       length -= count;
138     }
139   }
140 }
141 
AddHexString(const char * str)142 void Packet::AddHexString(const char *str) {
143   assert(str);
144 
145   while (*str) {
146     AddWord8(*str);
147     str++;
148   }
149 }
150 
AddNumberSep(uint64_t val,char sep)151 void Packet::AddNumberSep(uint64_t val, char sep) {
152   char out[sizeof(val) * 2];
153   int nibbles = 0;
154   size_t a;
155 
156   // Check for -1 optimization
157   if (val == static_cast<uint64_t>(-1)) {
158     AddRawChar('-');
159     AddRawChar('1');
160   } else {
161     // Assume we have the valuse 0x00001234
162     for (a = 0; a < sizeof(val); a++) {
163       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       IntToNibble(byte & 0xF, &out[nibbles++]);
168       IntToNibble(byte >> 4, &out[nibbles++]);
169 
170       // Get the next 8 bits;
171       val >>= 8;
172 
173       // Supress leading zeros, so we are done when val hits zero
174       if (val == 0) {
175         break;
176       }
177     }
178 
179     // Strip the high zero for this byte if needed
180     if ((nibbles > 1) && (out[nibbles-1] == '0')) nibbles--;
181 
182     // Now write it out reverse to correct the order
183     while (nibbles) {
184       nibbles--;
185       AddRawChar(out[nibbles]);
186     }
187   }
188 
189   // If we asked for a sperator, insert it
190   if (sep) AddRawChar(sep);
191 }
192 
GetNumberSep(uint64_t * val,char * sep)193 bool Packet::GetNumberSep(uint64_t *val, char *sep) {
194   uint64_t out = 0;
195   char ch;
196 
197   if (!GetRawChar(&ch)) {
198     return false;
199   }
200 
201   // Check for -1
202   if (ch == '-') {
203     if (!GetRawChar(&ch)) {
204       return false;
205     }
206 
207     if (ch == '1') {
208       *val = (uint64_t) -1;
209 
210       ch = 0;
211       GetRawChar(&ch);
212       if (sep) {
213         *sep = ch;
214       }
215       return true;
216     }
217     return false;
218   }
219 
220   do {
221     int nib;
222 
223     // Check for separator
224     if (!NibbleToInt(ch, &nib)) {
225       break;
226     }
227 
228     // Add this nibble.
229     out = (out << 4) + nib;
230 
231     // Get the next character (if availible)
232     ch = 0;
233     if (!GetRawChar(&ch)) {
234       break;
235     }
236   } while (1);
237 
238   // Set the value;
239   *val = out;
240 
241   // Add the separator if the user wants it...
242   if (sep != NULL) *sep = ch;
243 
244   return true;
245 }
246 
GetRawChar(char * ch)247 bool Packet::GetRawChar(char *ch) {
248   assert(ch != NULL);
249 
250   if (read_index_ >= write_index_)
251     return false;
252 
253   *ch = data_[read_index_++];
254 
255   // Check for RLE X*N, where X is the value, N is the reps.
256   if (*ch == '*') {
257     if (read_index_ < 2) {
258       NaClLog(LOG_ERROR, "Unexpected RLE at start of packet.\n");
259       return false;
260     }
261 
262     if (read_index_ >= write_index_) {
263       NaClLog(LOG_ERROR, "Unexpected EoP during RLE.\n");
264       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     int32_t cnt = (data_[read_index_] - 28);
272     if (cnt < 3) {
273       NaClLog(LOG_ERROR, "Unexpected RLE length.\n");
274       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     data_.resize(write_index_ + cnt - 3 + 1);
295     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     *ch = data_[read_index_ - 2];
302     memset(&data_[read_index_ - 1], *ch, cnt - 1);
303 
304     // Now we update the write_index_, and reterminate the string.
305     write_index_ = data_.size() - 1;
306     data_[write_index_] = 0;
307   }
308   return true;
309 }
310 
GetWord8(uint8_t * ch)311 bool Packet::GetWord8(uint8_t *ch) {
312   assert(ch);
313 
314   char seq1, seq2;
315   int  val1, val2;
316 
317   // Get two ASCII hex values
318   if (!GetRawChar(&seq1)) {
319     return false;
320   }
321   if (!GetRawChar(&seq2)) {
322     return false;
323   }
324 
325   // Convert them to ints
326   if (!NibbleToInt(seq1, &val1)) {
327     return false;
328   }
329   if (!NibbleToInt(seq2, &val2)) {
330     return false;
331   }
332 
333   *ch = (val1 << 4) + val2;
334   return true;
335 }
336 
GetBlock(void * ptr,uint32_t len)337 bool Packet::GetBlock(void *ptr, uint32_t len) {
338   assert(ptr);
339 
340   uint8_t *p = reinterpret_cast<uint8_t *>(ptr);
341   bool res = true;
342 
343   for (uint32_t offs = 0; offs < len; offs++) {
344     res = GetWord8(&p[offs]);
345     if (false == res) {
346       break;
347     }
348   }
349 
350   return res;
351 }
352 
GetWord16(uint16_t * ptr)353 bool Packet::GetWord16(uint16_t *ptr) {
354   assert(ptr);
355   return GetBlock(ptr, sizeof(*ptr));
356 }
357 
GetWord32(uint32_t * ptr)358 bool Packet::GetWord32(uint32_t *ptr) {
359   assert(ptr);
360   return GetBlock(ptr, sizeof(*ptr));
361 }
362 
GetWord64(uint64_t * ptr)363 bool Packet::GetWord64(uint64_t *ptr) {
364   assert(ptr);
365   return GetBlock(ptr, sizeof(*ptr));
366 }
367 
368 
GetString(string * str)369 bool Packet::GetString(string *str) {
370   if (EndOfPacket()) {
371     return false;
372   }
373 
374   *str = &data_[read_index_];
375   read_index_ = write_index_;
376   return true;
377 }
378 
GetHexString(string * str)379 bool Packet::GetHexString(string *str) {
380   // Decode a string encoded as a series of 2-hex digit pairs.
381 
382   char ch1;
383   char ch2;
384   int nib1;
385   int nib2;
386 
387   if (EndOfPacket()) {
388     return false;
389   }
390 
391   // Pull values until we hit a separator
392   str->clear();
393   while (GetRawChar(&ch1)) {
394     if (!NibbleToInt(ch1, &nib1)) {
395       read_index_--;
396       break;
397     }
398     if (!GetRawChar(&ch2) ||
399         !NibbleToInt(ch2, &nib2)) {
400       return false;
401     }
402     *str += static_cast<char>((nib1 << 4) + nib2);
403   }
404   return true;
405 }
406 
GetStringSep(std::string * str,char sep)407 bool Packet::GetStringSep(std::string *str, char sep) {
408   char ch;
409 
410   if (EndOfPacket()) {
411     return false;
412   }
413 
414   // Pull values until we hit a separator
415   str->clear();
416   while (GetRawChar(&ch)) {
417     if (ch == sep) {
418       return true;
419     } else {
420       *str += ch;
421     }
422   }
423   return false;
424 }
425 
GetPayload() const426 const char *Packet::GetPayload() const {
427   return &data_[0];
428 }
429 
GetPayloadSize() const430 size_t Packet::GetPayloadSize() const {
431   return write_index_;
432 }
433 
GetSequence(int32_t * ch) const434 bool Packet::GetSequence(int32_t *ch) const {
435   assert(ch);
436 
437   if (seq_ != -1) {
438     *ch = seq_;
439     return true;
440   }
441 
442   return false;
443 }
444 
ParseSequence()445 void Packet::ParseSequence() {
446   size_t saved_read_index = read_index_;
447   unsigned char seq;
448   char ch;
449   if (GetWord8(&seq) &&
450       GetRawChar(&ch)) {
451     if (ch == ':') {
452       SetSequence(seq);
453       return;
454     }
455   }
456   // No sequence number present, so reset to original position.
457   read_index_ = saved_read_index;
458 }
459 
SetSequence(int32_t val)460 void Packet::SetSequence(int32_t val) {
461   seq_ = val;
462 }
463 
464 }  // namespace gdb_rsp
465