Home | History | Annotate | Download | only in jdwp
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 /*
     17  * Implementation of an expandable byte buffer.  Designed for serializing
     18  * primitive values, e.g. JDWP replies.
     19  */
     20 
     21 #include "jdwp/jdwp_expand_buf.h"
     22 
     23 #include <stdlib.h>
     24 #include <string.h>
     25 
     26 #include "base/logging.h"
     27 #include "jdwp/jdwp.h"
     28 #include "jdwp/jdwp_bits.h"
     29 
     30 namespace art {
     31 
     32 namespace JDWP {
     33 
     34 /*
     35  * Data structure used to track buffer use.
     36  */
     37 struct ExpandBuf {
     38   uint8_t*     storage;
     39   int     curLen;
     40   int     maxLen;
     41 };
     42 
     43 #define kInitialStorage 64
     44 
     45 /*
     46  * Allocate a JdwpBuf and some initial storage.
     47  */
     48 ExpandBuf* expandBufAlloc() {
     49   ExpandBuf* newBuf = new ExpandBuf;
     50   newBuf->storage = reinterpret_cast<uint8_t*>(malloc(kInitialStorage));
     51   newBuf->curLen = 0;
     52   newBuf->maxLen = kInitialStorage;
     53   return newBuf;
     54 }
     55 
     56 /*
     57  * Free a JdwpBuf and associated storage.
     58  */
     59 void expandBufFree(ExpandBuf* pBuf) {
     60   if (pBuf == nullptr) {
     61     return;
     62   }
     63 
     64   free(pBuf->storage);
     65   delete pBuf;
     66 }
     67 
     68 /*
     69  * Get a pointer to the start of the buffer.
     70  */
     71 uint8_t* expandBufGetBuffer(ExpandBuf* pBuf) {
     72   return pBuf->storage;
     73 }
     74 
     75 /*
     76  * Get the amount of data currently in the buffer.
     77  */
     78 size_t expandBufGetLength(ExpandBuf* pBuf) {
     79   return pBuf->curLen;
     80 }
     81 
     82 /*
     83  * Ensure that the buffer has enough space to hold incoming data.  If it
     84  * doesn't, resize the buffer.
     85  */
     86 static void ensureSpace(ExpandBuf* pBuf, int newCount) {
     87   if (pBuf->curLen + newCount <= pBuf->maxLen) {
     88     return;
     89   }
     90 
     91   while (pBuf->curLen + newCount > pBuf->maxLen) {
     92     pBuf->maxLen *= 2;
     93   }
     94 
     95   uint8_t* newPtr = reinterpret_cast<uint8_t*>(realloc(pBuf->storage, pBuf->maxLen));
     96   if (newPtr == nullptr) {
     97     LOG(FATAL) << "realloc(" << pBuf->maxLen << ") failed";
     98   }
     99 
    100   pBuf->storage = newPtr;
    101 }
    102 
    103 /*
    104  * Allocate some space in the buffer.
    105  */
    106 uint8_t* expandBufAddSpace(ExpandBuf* pBuf, int gapSize) {
    107   uint8_t* gapStart;
    108 
    109   ensureSpace(pBuf, gapSize);
    110   gapStart = pBuf->storage + pBuf->curLen;
    111   /* do we want to garbage-fill the gap for debugging? */
    112   pBuf->curLen += gapSize;
    113 
    114   return gapStart;
    115 }
    116 
    117 /*
    118  * Append a byte.
    119  */
    120 void expandBufAdd1(ExpandBuf* pBuf, uint8_t val) {
    121   ensureSpace(pBuf, sizeof(val));
    122   *(pBuf->storage + pBuf->curLen) = val;
    123   pBuf->curLen++;
    124 }
    125 
    126 /*
    127  * Append two big-endian bytes.
    128  */
    129 void expandBufAdd2BE(ExpandBuf* pBuf, uint16_t val) {
    130   ensureSpace(pBuf, sizeof(val));
    131   Set2BE(pBuf->storage + pBuf->curLen, val);
    132   pBuf->curLen += sizeof(val);
    133 }
    134 
    135 /*
    136  * Append four big-endian bytes.
    137  */
    138 void expandBufAdd4BE(ExpandBuf* pBuf, uint32_t val) {
    139   ensureSpace(pBuf, sizeof(val));
    140   Set4BE(pBuf->storage + pBuf->curLen, val);
    141   pBuf->curLen += sizeof(val);
    142 }
    143 
    144 /*
    145  * Append eight big-endian bytes.
    146  */
    147 void expandBufAdd8BE(ExpandBuf* pBuf, uint64_t val) {
    148   ensureSpace(pBuf, sizeof(val));
    149   Set8BE(pBuf->storage + pBuf->curLen, val);
    150   pBuf->curLen += sizeof(val);
    151 }
    152 
    153 static void SetUtf8String(uint8_t* buf, const char* str, size_t strLen) {
    154   Set4BE(buf, strLen);
    155   memcpy(buf + sizeof(uint32_t), str, strLen);
    156 }
    157 
    158 /*
    159  * Add a UTF8 string as a 4-byte length followed by a non-nullptr-terminated
    160  * string.
    161  *
    162  * Because these strings are coming out of the VM, it's safe to assume that
    163  * they can be null-terminated (either they don't have null bytes or they
    164  * have stored null bytes in a multi-byte encoding).
    165  */
    166 void expandBufAddUtf8String(ExpandBuf* pBuf, const char* s) {
    167   int strLen = (s != nullptr ? strlen(s) : 0);
    168   ensureSpace(pBuf, sizeof(uint32_t) + strLen);
    169   SetUtf8String(pBuf->storage + pBuf->curLen, s, strLen);
    170   pBuf->curLen += sizeof(uint32_t) + strLen;
    171 }
    172 
    173 void expandBufAddUtf8String(ExpandBuf* pBuf, const std::string& s) {
    174   ensureSpace(pBuf, sizeof(uint32_t) + s.size());
    175   SetUtf8String(pBuf->storage + pBuf->curLen, s.data(), s.size());
    176   pBuf->curLen += sizeof(uint32_t) + s.size();
    177 }
    178 
    179 void expandBufAddLocation(ExpandBuf* buf, const JdwpLocation& location) {
    180   expandBufAdd1(buf, location.type_tag);
    181   expandBufAddObjectId(buf, location.class_id);
    182   expandBufAddMethodId(buf, location.method_id);
    183   expandBufAdd8BE(buf, location.dex_pc);
    184 }
    185 
    186 }  // namespace JDWP
    187 
    188 }  // namespace art
    189