LCOV - code coverage report
Current view: directory - src/trusted/gdb_rsp - packet.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 186 125 67.2 %
Date: 2012-02-16 Functions: 0 0 -

       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                 : 
       8                 : #include <assert.h>
       9                 : #include <string.h>
      10                 : #include <stdlib.h>
      11                 : 
      12                 : #include <string>
      13                 : 
      14                 : #include "native_client/src/trusted/gdb_rsp/packet.h"
      15                 : #include "native_client/src/trusted/gdb_rsp/util.h"
      16                 : #include "native_client/src/trusted/port/platform.h"
      17                 : 
      18                 : using std::string;
      19                 : using port::IPlatform;
      20                 : 
      21                 : 
      22                 : namespace gdb_rsp {
      23                 : 
      24                 : #define MIN_PAD 1
      25                 : #define GROW_SIZE  64
      26                 : 
      27              32 : Packet::Packet() {
      28              32 :   seq_ = -1;
      29              32 :   Clear();
      30              32 : }
      31                 : 
      32              72 : void Packet::Clear() {
      33              72 :   data_.clear();
      34              72 :   data_.resize(GROW_SIZE);
      35              72 :   data_[0] = 0;
      36                 : 
      37              72 :   read_index_  = 0;
      38              72 :   write_index_ = 0;
      39              72 : }
      40                 : 
      41               1 : void Packet::Rewind() {
      42               1 :   read_index_ = 0;
      43               1 : }
      44                 : 
      45              15 : bool Packet::EndOfPacket() const {
      46              15 :   return (read_index_ >= write_index_);
      47                 : }
      48                 : 
      49            1071 : void Packet::AddRawChar(char ch) {
      50                 :   // Grow by a fixed amount whenever we are within the pad boundry.
      51                 :   // The pad boundry allows for the addition of NUL termination.
      52            1071 :   if (data_.size() <= (write_index_ + MIN_PAD)) {
      53               8 :     data_.resize(data_.size() + GROW_SIZE);
      54                 :   }
      55                 : 
      56                 :   // Add character and always null terminate.
      57            1071 :   data_[write_index_++] = ch;
      58            1071 :   data_[write_index_] = 0;
      59            1071 : }
      60                 : 
      61              72 : void Packet::AddWord8(uint8_t ch) {
      62                 :   char seq1, seq2;
      63                 : 
      64              72 :   IntToNibble(ch >> 4, &seq1);
      65              72 :   IntToNibble(ch & 0xF, &seq2);
      66                 : 
      67              72 :   AddRawChar(seq1);
      68              72 :   AddRawChar(seq2);
      69              72 : }
      70                 : 
      71               3 : void Packet::AddBlock(const void *ptr, uint32_t len) {
      72               3 :   assert(ptr);
      73                 : 
      74               3 :   const char *p = (const char *) ptr;
      75                 : 
      76              73 :   for (uint32_t offs = 0; offs < len; offs++) {
      77              70 :     AddWord8(p[offs]);
      78                 :   }
      79               3 : }
      80                 : 
      81               1 : void Packet::AddWord16(uint16_t val) {
      82               1 :   AddBlock(&val, sizeof(val));
      83               1 : }
      84                 : 
      85               1 : void Packet::AddWord32(uint32_t val) {
      86               1 :   AddBlock(&val, sizeof(val));
      87               1 : }
      88                 : 
      89               0 : void Packet::AddWord64(uint64_t val) {
      90               0 :   AddBlock(&val, sizeof(val));
      91               0 : }
      92                 : 
      93              39 : void Packet::AddString(const char *str) {
      94              39 :   assert(str);
      95                 : 
      96             914 :   while (*str) {
      97             836 :     AddRawChar(*str);
      98             836 :     str++;
      99                 :   }
     100              39 : }
     101                 : 
     102               0 : void Packet::AddHexString(const char *str) {
     103               0 :   assert(str);
     104                 : 
     105               0 :   while (*str) {
     106               0 :     AddWord8(*str);
     107               0 :     str++;
     108                 :   }
     109               0 : }
     110                 : 
     111               6 : void Packet::AddNumberSep(uint64_t val, char sep) {
     112                 :   char out[sizeof(val) * 2];
     113               6 :   int nibbles = 0;
     114                 :   size_t a;
     115                 : 
     116                 :   // Check for -1 optimization
     117               6 :   if (val == static_cast<uint64_t>(-1)) {
     118               1 :     AddRawChar('-');
     119               1 :     AddRawChar('1');
     120                 :   } else {
     121                 :     // Assume we have the valuse 0x00001234
     122              14 :     for (a = 0; a < sizeof(val); a++) {
     123              14 :       uint8_t byte = static_cast<uint8_t>(val & 0xFF);
     124                 : 
     125                 :       // Stream in with bytes reverse, starting at least significant
     126                 :       // So we store 4, then 3, 2, 1
     127              14 :       IntToNibble(byte & 0xF, &out[nibbles++]);
     128              14 :       IntToNibble(byte >> 4, &out[nibbles++]);
     129                 : 
     130                 :       // Get the next 8 bits;
     131              14 :       val >>= 8;
     132                 : 
     133                 :       // Supress leading zeros, so we are done when val hits zero
     134              14 :       if (val == 0) break;
     135                 :     }
     136                 : 
     137                 :     // Strip the high zero for this byte if needed
     138               5 :     if ((nibbles > 1) && (out[nibbles-1] == '0')) nibbles--;
     139                 : 
     140                 :     // Now write it out reverse to correct the order
     141              35 :     while (nibbles) {
     142              25 :       nibbles--;
     143              25 :       AddRawChar(out[nibbles]);
     144                 :     }
     145                 :   }
     146                 : 
     147                 :   // If we asked for a sperator, insert it
     148               6 :   if (sep) AddRawChar(sep);
     149               6 : }
     150                 : 
     151               1 : bool Packet::GetNumberSep(uint64_t *val, char *sep) {
     152               1 :   uint64_t out = 0;
     153                 :   char ch;
     154                 : 
     155               1 :   if (!GetRawChar(&ch)) return false;
     156                 : 
     157                 :   // Check for -1
     158               1 :   if (ch == '-') {
     159               0 :     if (!GetRawChar(&ch)) return false;
     160                 : 
     161               0 :     if (ch == '1') {
     162               0 :       *val = -1;
     163                 : 
     164               0 :       ch = 0;
     165               0 :       GetRawChar(&ch);
     166               0 :       if (sep) *sep = ch;
     167               0 :       return true;
     168                 :     }
     169               0 :     return false;
     170                 :   }
     171                 : 
     172               3 :   do {
     173                 :     int nib;
     174                 : 
     175                 :     // Check for separator
     176               4 :     if (!NibbleToInt(ch, &nib)) break;
     177                 : 
     178                 :     // Add this nibble.
     179               4 :     out = (out << 4) + nib;
     180                 : 
     181                 :     // Get the next character (if availible)
     182               4 :     ch = 0;
     183               4 :     if (!GetRawChar(&ch)) break;
     184                 :   } while (1);
     185                 : 
     186                 :   // Set the value;
     187               1 :   *val = out;
     188                 : 
     189                 :   // Add the separator if the user wants it...
     190               1 :   if (sep != NULL) *sep = ch;
     191                 : 
     192               1 :   return true;
     193                 : }
     194                 : 
     195             413 : bool Packet::GetRawChar(char *ch) {
     196             413 :   assert(ch != NULL);
     197                 : 
     198             413 :   if (read_index_ >= write_index_)
     199               2 :     return false;
     200                 : 
     201             411 :   *ch = data_[read_index_++];
     202                 : 
     203                 :   // Check for RLE X*N, where X is the value, N is the reps.
     204             411 :   if (*ch == '*') {
     205               9 :     if (read_index_ < 2) {
     206               0 :       IPlatform::LogError("Unexpected RLE at start of packet.\n");
     207               0 :       return false;
     208                 :     }
     209                 : 
     210               9 :     if (read_index_ >= write_index_) {
     211               0 :       IPlatform::LogError("Unexpected EoP during RLE.\n");
     212               0 :       return false;
     213                 :     }
     214                 : 
     215                 :     // GDB does not use "CTRL" characters in the stream, so the
     216                 :     // number of reps is encoded as the ASCII value beyond 28
     217                 :     // (which when you add a min rep size of 4, forces the rep
     218                 :     // character to be ' ' (32) or greater).
     219               9 :     int32_t cnt = (data_[read_index_] - 28);
     220               9 :     if (cnt < 3) {
     221               0 :       IPlatform::LogError("Unexpected RLE length.\n");
     222               0 :       return false;
     223                 :     }
     224                 : 
     225                 :     // We have just read '*' and incremented the read pointer,
     226                 :     // so here is the old state, and expected new state.
     227                 :     //
     228                 :     //   Assume N = 5, we grow by N - size of encoding (3).
     229                 :     //
     230                 :     // OldP:       R  W
     231                 :     // OldD:  012X*N89 = 8 chars
     232                 :     // Size:  012X*N89__ = 10 chars
     233                 :     // Move:  012X*__N89 = 10 chars
     234                 :     // Fill:  012XXXXX89 = 10 chars
     235                 :     // NewP:       R    W  (shifted 5 - 3)
     236                 :     //
     237                 :     // To accomplish this we must first, resize the vector then move
     238                 :     // all remaining characters to the right, by the delta between
     239                 :     // the run length, and encoding size. This moves one more char
     240                 :     // than needed (the 'N'), but is easier to understand.
     241                 :     // NOTE: We add one to the resize to allow for zero termination.
     242               9 :     data_.resize(write_index_ + cnt - 3 + 1);
     243                 :     memmove(&data_[read_index_ + cnt - 3], &data_[read_index_],
     244               9 :             write_index_ - read_index_);
     245                 : 
     246                 :     // Now me must go back and fill over the previous '*' with the
     247                 :     // repeated character for the length of the run minus the original
     248                 :     // character which is already correct
     249               9 :     *ch = data_[read_index_ - 2];
     250               9 :     memset(&data_[read_index_ - 1], *ch, cnt - 1);
     251                 : 
     252                 :     // Now we update the write_index_, and reterminate the string.
     253               9 :     write_index_ = data_.size() - 1;
     254               9 :     data_[write_index_] = 0;
     255                 :   }
     256             411 :   return true;
     257                 : }
     258                 : 
     259             199 : bool Packet::GetWord8(uint8_t *ch) {
     260             199 :   assert(ch);
     261                 : 
     262                 :   char seq1, seq2;
     263                 :   int  val1, val2;
     264                 : 
     265                 :   // Get two ASCII hex values
     266             199 :   if (!GetRawChar(&seq1)) return false;
     267             199 :   if (!GetRawChar(&seq2)) return false;
     268                 : 
     269                 :   // Convert them to ints
     270             199 :   if (!NibbleToInt(seq1, &val1)) return false;
     271             199 :   if (!NibbleToInt(seq2, &val2)) return false;
     272                 : 
     273             199 :   *ch = (val1 << 4) + val2;
     274             199 :   return true;
     275                 : }
     276                 : 
     277               5 : bool Packet::GetBlock(void *ptr, uint32_t len) {
     278               5 :   assert(ptr);
     279                 : 
     280               5 :   uint8_t *p = reinterpret_cast<uint8_t *>(ptr);
     281               5 :   bool res = true;
     282                 : 
     283             203 :   for (uint32_t offs = 0; offs < len; offs++) {
     284             198 :     res = GetWord8(&p[offs]);
     285             198 :     if (false == res) break;
     286                 :   }
     287                 : 
     288               5 :   return res;
     289                 : }
     290                 : 
     291               1 : bool Packet::GetWord16(uint16_t *ptr) {
     292               1 :   assert(ptr);
     293               1 :   return GetBlock(ptr, sizeof(*ptr));
     294                 : }
     295                 : 
     296               1 : bool Packet::GetWord32(uint32_t *ptr) {
     297               1 :   assert(ptr);
     298               1 :   return GetBlock(ptr, sizeof(*ptr));
     299                 : }
     300                 : 
     301               0 : bool Packet::GetWord64(uint64_t *ptr) {
     302               0 :   assert(ptr);
     303               0 :   return GetBlock(ptr, sizeof(*ptr));
     304                 : }
     305                 : 
     306                 : 
     307              15 : bool Packet::GetString(string* str) {
     308              15 :   if (EndOfPacket()) return false;
     309                 : 
     310              15 :   *str = &data_[read_index_];
     311              15 :   read_index_ = write_index_;
     312              15 :   return true;
     313                 : }
     314                 : 
     315               0 : bool Packet::GetHexString(string* str) {
     316                 :   char ch;
     317               0 :   if (EndOfPacket()) return false;
     318                 : 
     319                 :   // Pull values until we hit a seperator
     320               0 :   str->clear();
     321               0 :   while (GetRawChar(&ch)) {
     322               0 :     if (NibbleToInt(ch, NULL)) {
     323               0 :       *str += ch;
     324                 :     } else {
     325               0 :       read_index_--;
     326               0 :       break;
     327                 :     }
     328                 :   }
     329               0 :   return true;
     330                 : }
     331                 : 
     332               0 : bool Packet::GetStringCB(void *ctx, StrFunc_t cb) {
     333               0 :   assert(NULL != ctx);
     334                 : 
     335               0 :   if (EndOfPacket()) {
     336               0 :     cb(ctx, NULL);
     337               0 :     return false;
     338                 :   }
     339                 : 
     340               0 :   cb(ctx, &data_[read_index_]);
     341               0 :   read_index_ = write_index_;
     342               0 :   return true;
     343                 : }
     344                 : 
     345               0 : bool Packet::GetHexStringCB(void *ctx, StrFunc_t cb) {
     346               0 :   assert(NULL != ctx);
     347                 : 
     348               0 :   std::string out;
     349                 :   char ch;
     350                 : 
     351               0 :   if (EndOfPacket()) {
     352               0 :     cb(ctx, NULL);
     353               0 :     return false;
     354                 :   }
     355                 : 
     356                 :   // Pull values until we hit a seperator
     357               0 :   while (GetRawChar(&ch)) {
     358               0 :     if (NibbleToInt(ch, NULL)) {
     359               0 :       out += ch;
     360                 :     } else {
     361               0 :       read_index_--;
     362               0 :       break;
     363                 :     }
     364                 :   }
     365                 : 
     366                 :   // Call the CB with the availible string
     367               0 :   cb(ctx, out.data());
     368               0 :   return true;
     369                 : }
     370                 : 
     371                 : 
     372              26 : const char *Packet::GetPayload() const {
     373              26 :   return &data_[0];
     374                 : }
     375                 : 
     376              13 : bool Packet::GetSequence(int32_t *ch) const {
     377              13 :   assert(ch);
     378                 : 
     379              13 :   if (seq_ != -1) {
     380               0 :     *ch = seq_;
     381               0 :     return true;
     382                 :   }
     383                 : 
     384              13 :   return false;
     385                 : }
     386                 : 
     387               0 : void Packet::SetSequence(int32_t val) {
     388               0 :   seq_ = val;
     389               0 : }
     390                 : 
     391                 : }  // namespace gdb_rsp
     392                 : 

Generated by: LCOV version 1.7