jdwp_expand_buf.cc revision a21039c3ae2b20e44ceb2735251c04d0aac89afd
1872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 2872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Copyright (C) 2008 The Android Open Source Project 3872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 4872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 5872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * you may not use this file except in compliance with the License. 6872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * You may obtain a copy of the License at 7872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 8872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 9872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 10872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Unless required by applicable law or agreed to in writing, software 11872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 12872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * See the License for the specific language governing permissions and 14872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * limitations under the License. 15872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 16872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 17872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Implementation of an expandable byte buffer. Designed for serializing 18872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * primitive values, e.g. JDWP replies. 19872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 20872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 21872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "jdwp/jdwp_bits.h" 22872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "jdwp/jdwp_expand_buf.h" 23872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "logging.h" 24872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 25872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include <stdlib.h> 26872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include <string.h> 27872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 28872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesnamespace art { 29872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 30872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesnamespace JDWP { 31872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 32872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 33872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Data structure used to track buffer use. 34872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 35872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstruct ExpandBuf { 36872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes uint8_t* storage; 37872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes int curLen; 38872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes int maxLen; 39872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}; 40872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 41872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#define kInitialStorage 64 42872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 43872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 44872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Allocate a JdwpBuf and some initial storage. 45872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 46872d4ec7225444d9400d30f9027247deb91012fdElliott HughesExpandBuf* expandBufAlloc() { 47a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes ExpandBuf* newBuf = new ExpandBuf; 48a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes newBuf->storage = reinterpret_cast<uint8_t*>(malloc(kInitialStorage)); 49872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes newBuf->curLen = 0; 50872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes newBuf->maxLen = kInitialStorage; 51872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return newBuf; 52872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 53872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 54872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 55872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Free a JdwpBuf and associated storage. 56872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 57872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid expandBufFree(ExpandBuf* pBuf) { 58872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes if (pBuf == NULL) { 59872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return; 60872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 61872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 62872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes free(pBuf->storage); 63a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes delete pBuf; 64872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 65872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 66872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 67872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Get a pointer to the start of the buffer. 68872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 69872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesuint8_t* expandBufGetBuffer(ExpandBuf* pBuf) { 70872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return pBuf->storage; 71872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 72872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 73872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 74872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Get the amount of data currently in the buffer. 75872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 76872d4ec7225444d9400d30f9027247deb91012fdElliott Hughessize_t expandBufGetLength(ExpandBuf* pBuf) { 77872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return pBuf->curLen; 78872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 79872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 80872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 81872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Ensure that the buffer has enough space to hold incoming data. If it 82872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * doesn't, resize the buffer. 83872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 84872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstatic void ensureSpace(ExpandBuf* pBuf, int newCount) { 85872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes if (pBuf->curLen + newCount <= pBuf->maxLen) { 86872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return; 87872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 88872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 89872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes while (pBuf->curLen + newCount > pBuf->maxLen) { 90872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes pBuf->maxLen *= 2; 91872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 92872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 93a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes uint8_t* newPtr = reinterpret_cast<uint8_t*>(realloc(pBuf->storage, pBuf->maxLen)); 94872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes if (newPtr == NULL) { 956c1c69eea21cce39dd043d89368a684d250c9abeElliott Hughes LOG(FATAL) << "realloc(" << pBuf->maxLen << ") failed"; 96872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 97872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 98872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes pBuf->storage = newPtr; 99872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 100872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 101872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 102872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Allocate some space in the buffer. 103872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 104872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesuint8_t* expandBufAddSpace(ExpandBuf* pBuf, int gapSize) { 105872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes uint8_t* gapStart; 106872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 107872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes ensureSpace(pBuf, gapSize); 108872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes gapStart = pBuf->storage + pBuf->curLen; 109872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* do we want to garbage-fill the gap for debugging? */ 110872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes pBuf->curLen += gapSize; 111872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 112872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return gapStart; 113872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 114872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 115872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 116872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Append a byte. 117872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 118872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid expandBufAdd1(ExpandBuf* pBuf, uint8_t val) { 119872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes ensureSpace(pBuf, sizeof(val)); 120872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *(pBuf->storage + pBuf->curLen) = val; 121872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes pBuf->curLen++; 122872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 123872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 124872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 125872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Append two big-endian bytes. 126872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 127872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid expandBufAdd2BE(ExpandBuf* pBuf, uint16_t val) { 128872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes ensureSpace(pBuf, sizeof(val)); 129f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes Set2BE(pBuf->storage + pBuf->curLen, val); 130872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes pBuf->curLen += sizeof(val); 131872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 132872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 133872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 134872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Append four big-endian bytes. 135872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 136872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid expandBufAdd4BE(ExpandBuf* pBuf, uint32_t val) { 137872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes ensureSpace(pBuf, sizeof(val)); 138f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes Set4BE(pBuf->storage + pBuf->curLen, val); 139872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes pBuf->curLen += sizeof(val); 140872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 141872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 142872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 143872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Append eight big-endian bytes. 144872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 145872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid expandBufAdd8BE(ExpandBuf* pBuf, uint64_t val) { 146872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes ensureSpace(pBuf, sizeof(val)); 147f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes Set8BE(pBuf->storage + pBuf->curLen, val); 148872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes pBuf->curLen += sizeof(val); 149872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 150872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 151a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughesstatic void SetUtf8String(uint8_t* buf, const char* str, size_t strLen) { 15221f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes Set4BE(buf, strLen); 15321f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes memcpy(buf + sizeof(uint32_t), str, strLen); 15421f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes} 15521f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes 156872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 157872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Add a UTF8 string as a 4-byte length followed by a non-NULL-terminated 158872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * string. 159872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 160872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Because these strings are coming out of the VM, it's safe to assume that 161872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * they can be null-terminated (either they don't have null bytes or they 162872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * have stored null bytes in a multi-byte encoding). 163872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 1644740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughesvoid expandBufAddUtf8String(ExpandBuf* pBuf, const char* s) { 1654740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes int strLen = strlen(s); 166872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes ensureSpace(pBuf, sizeof(uint32_t) + strLen); 1674740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes SetUtf8String(pBuf->storage + pBuf->curLen, s, strLen); 168872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes pBuf->curLen += sizeof(uint32_t) + strLen; 169872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 170872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1714740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughesvoid expandBufAddUtf8String(ExpandBuf* pBuf, const std::string& s) { 1724740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes ensureSpace(pBuf, sizeof(uint32_t) + s.size()); 1734740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes SetUtf8String(pBuf->storage + pBuf->curLen, s.data(), s.size()); 1744740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes pBuf->curLen += sizeof(uint32_t) + s.size(); 1754740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes} 1764740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes 177872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} // namespace JDWP 178872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 179872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} // namespace art 180