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 <android-base/logging.h> 27 28 #include "jdwp/jdwp.h" 29 #include "jdwp/jdwp_bits.h" 30 31 namespace art { 32 33 namespace JDWP { 34 35 /* 36 * Data structure used to track buffer use. 37 */ 38 struct ExpandBuf { 39 uint8_t* storage; 40 int curLen; 41 int maxLen; 42 }; 43 44 #define kInitialStorage 64 45 46 /* 47 * Allocate a JdwpBuf and some initial storage. 48 */ 49 ExpandBuf* expandBufAlloc() { 50 ExpandBuf* newBuf = new ExpandBuf; 51 newBuf->storage = reinterpret_cast<uint8_t*>(malloc(kInitialStorage)); 52 newBuf->curLen = 0; 53 newBuf->maxLen = kInitialStorage; 54 return newBuf; 55 } 56 57 /* 58 * Free a JdwpBuf and associated storage. 59 */ 60 void expandBufFree(ExpandBuf* pBuf) { 61 if (pBuf == nullptr) { 62 return; 63 } 64 65 free(pBuf->storage); 66 delete pBuf; 67 } 68 69 /* 70 * Get a pointer to the start of the buffer. 71 */ 72 uint8_t* expandBufGetBuffer(ExpandBuf* pBuf) { 73 return pBuf->storage; 74 } 75 76 /* 77 * Get the amount of data currently in the buffer. 78 */ 79 size_t expandBufGetLength(ExpandBuf* pBuf) { 80 return pBuf->curLen; 81 } 82 83 /* 84 * Ensure that the buffer has enough space to hold incoming data. If it 85 * doesn't, resize the buffer. 86 */ 87 static void ensureSpace(ExpandBuf* pBuf, int newCount) { 88 if (pBuf->curLen + newCount <= pBuf->maxLen) { 89 return; 90 } 91 92 while (pBuf->curLen + newCount > pBuf->maxLen) { 93 pBuf->maxLen *= 2; 94 } 95 96 uint8_t* newPtr = reinterpret_cast<uint8_t*>(realloc(pBuf->storage, pBuf->maxLen)); 97 if (newPtr == nullptr) { 98 LOG(FATAL) << "realloc(" << pBuf->maxLen << ") failed"; 99 } 100 101 pBuf->storage = newPtr; 102 } 103 104 /* 105 * Allocate some space in the buffer. 106 */ 107 uint8_t* expandBufAddSpace(ExpandBuf* pBuf, int gapSize) { 108 uint8_t* gapStart; 109 110 ensureSpace(pBuf, gapSize); 111 gapStart = pBuf->storage + pBuf->curLen; 112 /* do we want to garbage-fill the gap for debugging? */ 113 pBuf->curLen += gapSize; 114 115 return gapStart; 116 } 117 118 /* 119 * Append a byte. 120 */ 121 void expandBufAdd1(ExpandBuf* pBuf, uint8_t val) { 122 ensureSpace(pBuf, sizeof(val)); 123 *(pBuf->storage + pBuf->curLen) = val; 124 pBuf->curLen++; 125 } 126 127 /* 128 * Append two big-endian bytes. 129 */ 130 void expandBufAdd2BE(ExpandBuf* pBuf, uint16_t val) { 131 ensureSpace(pBuf, sizeof(val)); 132 Set2BE(pBuf->storage + pBuf->curLen, val); 133 pBuf->curLen += sizeof(val); 134 } 135 136 /* 137 * Append four big-endian bytes. 138 */ 139 void expandBufAdd4BE(ExpandBuf* pBuf, uint32_t val) { 140 ensureSpace(pBuf, sizeof(val)); 141 Set4BE(pBuf->storage + pBuf->curLen, val); 142 pBuf->curLen += sizeof(val); 143 } 144 145 /* 146 * Append eight big-endian bytes. 147 */ 148 void expandBufAdd8BE(ExpandBuf* pBuf, uint64_t val) { 149 ensureSpace(pBuf, sizeof(val)); 150 Set8BE(pBuf->storage + pBuf->curLen, val); 151 pBuf->curLen += sizeof(val); 152 } 153 154 static void SetUtf8String(uint8_t* buf, const char* str, size_t strLen) { 155 Set4BE(buf, strLen); 156 if (str != nullptr) { 157 memcpy(buf + sizeof(uint32_t), str, strLen); 158 } 159 } 160 161 /* 162 * Add a UTF8 string as a 4-byte length followed by a non-nullptr-terminated 163 * string. 164 * 165 * Because these strings are coming out of the VM, it's safe to assume that 166 * they can be null-terminated (either they don't have null bytes or they 167 * have stored null bytes in a multi-byte encoding). 168 */ 169 void expandBufAddUtf8String(ExpandBuf* pBuf, const char* s) { 170 int strLen = (s != nullptr ? strlen(s) : 0); 171 ensureSpace(pBuf, sizeof(uint32_t) + strLen); 172 SetUtf8String(pBuf->storage + pBuf->curLen, s, strLen); 173 pBuf->curLen += sizeof(uint32_t) + strLen; 174 } 175 176 void expandBufAddUtf8String(ExpandBuf* pBuf, const std::string& s) { 177 ensureSpace(pBuf, sizeof(uint32_t) + s.size()); 178 SetUtf8String(pBuf->storage + pBuf->curLen, s.data(), s.size()); 179 pBuf->curLen += sizeof(uint32_t) + s.size(); 180 } 181 182 void expandBufAddLocation(ExpandBuf* buf, const JdwpLocation& location) { 183 expandBufAdd1(buf, location.type_tag); 184 expandBufAddObjectId(buf, location.class_id); 185 expandBufAddMethodId(buf, location.method_id); 186 expandBufAdd8BE(buf, location.dex_pc); 187 } 188 189 } // namespace JDWP 190 191 } // namespace art 192