LCOV - code coverage report
Current view: directory - src/trusted/debug_stub - packet.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 244 137 56.1 %
Date: 2014-09-25 Functions: 0 0 -

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

Generated by: LCOV version 1.7