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