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