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