jdwp_expand_buf.cc revision 6e9d22c78c1016e70f8c2a9e6bc66c94ec36f728
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 216e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes#include "jdwp/jdwp.h" 22872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "jdwp/jdwp_bits.h" 23872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "jdwp/jdwp_expand_buf.h" 24872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "logging.h" 25872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 26872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include <stdlib.h> 27872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include <string.h> 28872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 29872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesnamespace art { 30872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 31872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesnamespace JDWP { 32872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 33872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 34872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Data structure used to track buffer use. 35872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 36872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstruct ExpandBuf { 37872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes uint8_t* storage; 38872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes int curLen; 39872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes int maxLen; 40872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}; 41872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 42872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#define kInitialStorage 64 43872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 44872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 45872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Allocate a JdwpBuf and some initial storage. 46872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 47872d4ec7225444d9400d30f9027247deb91012fdElliott HughesExpandBuf* expandBufAlloc() { 48a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes ExpandBuf* newBuf = new ExpandBuf; 49a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes newBuf->storage = reinterpret_cast<uint8_t*>(malloc(kInitialStorage)); 50872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes newBuf->curLen = 0; 51872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes newBuf->maxLen = kInitialStorage; 52872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return newBuf; 53872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 54872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 55872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 56872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Free a JdwpBuf and associated storage. 57872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 58872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid expandBufFree(ExpandBuf* pBuf) { 59872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes if (pBuf == NULL) { 60872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return; 61872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 62872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 63872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes free(pBuf->storage); 64a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes delete pBuf; 65872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 66872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 67872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 68872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Get a pointer to the start of the buffer. 69872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 70872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesuint8_t* expandBufGetBuffer(ExpandBuf* pBuf) { 71872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return pBuf->storage; 72872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 73872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 74872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 75872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Get the amount of data currently in the buffer. 76872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 77872d4ec7225444d9400d30f9027247deb91012fdElliott Hughessize_t expandBufGetLength(ExpandBuf* pBuf) { 78872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return pBuf->curLen; 79872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 80872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 81872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 82872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Ensure that the buffer has enough space to hold incoming data. If it 83872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * doesn't, resize the buffer. 84872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 85872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstatic void ensureSpace(ExpandBuf* pBuf, int newCount) { 86872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes if (pBuf->curLen + newCount <= pBuf->maxLen) { 87872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return; 88872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 89872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 90872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes while (pBuf->curLen + newCount > pBuf->maxLen) { 91872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes pBuf->maxLen *= 2; 92872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 93872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 94a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes uint8_t* newPtr = reinterpret_cast<uint8_t*>(realloc(pBuf->storage, pBuf->maxLen)); 95872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes if (newPtr == NULL) { 966c1c69eea21cce39dd043d89368a684d250c9abeElliott Hughes LOG(FATAL) << "realloc(" << pBuf->maxLen << ") failed"; 97872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 98872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 99872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes pBuf->storage = newPtr; 100872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 101872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 102872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 103872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Allocate some space in the buffer. 104872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 105872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesuint8_t* expandBufAddSpace(ExpandBuf* pBuf, int gapSize) { 106872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes uint8_t* gapStart; 107872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 108872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes ensureSpace(pBuf, gapSize); 109872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes gapStart = pBuf->storage + pBuf->curLen; 110872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* do we want to garbage-fill the gap for debugging? */ 111872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes pBuf->curLen += gapSize; 112872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 113872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return gapStart; 114872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 115872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 116872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 117872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Append a byte. 118872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 119872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid expandBufAdd1(ExpandBuf* pBuf, uint8_t val) { 120872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes ensureSpace(pBuf, sizeof(val)); 121872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *(pBuf->storage + pBuf->curLen) = val; 122872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes pBuf->curLen++; 123872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 124872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 125872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 126872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Append two big-endian bytes. 127872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 128872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid expandBufAdd2BE(ExpandBuf* pBuf, uint16_t val) { 129872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes ensureSpace(pBuf, sizeof(val)); 130f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes Set2BE(pBuf->storage + pBuf->curLen, val); 131872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes pBuf->curLen += sizeof(val); 132872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 133872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 134872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 135872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Append four big-endian bytes. 136872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 137872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid expandBufAdd4BE(ExpandBuf* pBuf, uint32_t val) { 138872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes ensureSpace(pBuf, sizeof(val)); 139f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes Set4BE(pBuf->storage + pBuf->curLen, val); 140872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes pBuf->curLen += sizeof(val); 141872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 142872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 143872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 144872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Append eight big-endian bytes. 145872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 146872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid expandBufAdd8BE(ExpandBuf* pBuf, uint64_t val) { 147872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes ensureSpace(pBuf, sizeof(val)); 148f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes Set8BE(pBuf->storage + pBuf->curLen, val); 149872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes pBuf->curLen += sizeof(val); 150872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 151872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 152a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughesstatic void SetUtf8String(uint8_t* buf, const char* str, size_t strLen) { 15321f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes Set4BE(buf, strLen); 15421f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes memcpy(buf + sizeof(uint32_t), str, strLen); 15521f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes} 15621f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes 157872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 158872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Add a UTF8 string as a 4-byte length followed by a non-NULL-terminated 159872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * string. 160872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 161872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Because these strings are coming out of the VM, it's safe to assume that 162872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * they can be null-terminated (either they don't have null bytes or they 163872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * have stored null bytes in a multi-byte encoding). 164872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 1654740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughesvoid expandBufAddUtf8String(ExpandBuf* pBuf, const char* s) { 1664740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes int strLen = strlen(s); 167872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes ensureSpace(pBuf, sizeof(uint32_t) + strLen); 1684740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes SetUtf8String(pBuf->storage + pBuf->curLen, s, strLen); 169872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes pBuf->curLen += sizeof(uint32_t) + strLen; 170872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 171872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1724740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughesvoid expandBufAddUtf8String(ExpandBuf* pBuf, const std::string& s) { 1734740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes ensureSpace(pBuf, sizeof(uint32_t) + s.size()); 1744740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes SetUtf8String(pBuf->storage + pBuf->curLen, s.data(), s.size()); 1754740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes pBuf->curLen += sizeof(uint32_t) + s.size(); 1764740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes} 1774740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes 1786e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughesvoid expandBufAddLocation(ExpandBuf* buf, const JdwpLocation& location) { 1796e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes expandBufAdd1(buf, location.type_tag); 1806e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes expandBufAddObjectId(buf, location.class_id); 1816e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes expandBufAddMethodId(buf, location.method_id); 1826e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes expandBufAdd8BE(buf, location.dex_pc); 1836e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes} 1846e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes 185872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} // namespace JDWP 186872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 187872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} // namespace art 188