blob: 663afac9d08e48815ccc9a4e3cfd987cecea395a [file] [log] [blame]
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16/*
17 * Implementation of an expandable byte buffer. Designed for serializing
18 * primitive values, e.g. JDWP replies.
19 */
20
Elliott Hughes6e9d22c2012-06-22 15:02:37 -070021#include "jdwp/jdwp.h"
Elliott Hughes872d4ec2011-10-21 17:07:15 -070022#include "jdwp/jdwp_bits.h"
23#include "jdwp/jdwp_expand_buf.h"
24#include "logging.h"
25
26#include <stdlib.h>
27#include <string.h>
28
29namespace art {
30
31namespace JDWP {
32
33/*
34 * Data structure used to track buffer use.
35 */
36struct ExpandBuf {
37 uint8_t* storage;
38 int curLen;
39 int maxLen;
40};
41
42#define kInitialStorage 64
43
44/*
45 * Allocate a JdwpBuf and some initial storage.
46 */
47ExpandBuf* expandBufAlloc() {
Elliott Hughesa21039c2012-06-21 12:09:25 -070048 ExpandBuf* newBuf = new ExpandBuf;
49 newBuf->storage = reinterpret_cast<uint8_t*>(malloc(kInitialStorage));
Elliott Hughes872d4ec2011-10-21 17:07:15 -070050 newBuf->curLen = 0;
51 newBuf->maxLen = kInitialStorage;
Elliott Hughes872d4ec2011-10-21 17:07:15 -070052 return newBuf;
53}
54
55/*
56 * Free a JdwpBuf and associated storage.
57 */
58void expandBufFree(ExpandBuf* pBuf) {
59 if (pBuf == NULL) {
60 return;
61 }
62
63 free(pBuf->storage);
Elliott Hughesa21039c2012-06-21 12:09:25 -070064 delete pBuf;
Elliott Hughes872d4ec2011-10-21 17:07:15 -070065}
66
67/*
68 * Get a pointer to the start of the buffer.
69 */
70uint8_t* expandBufGetBuffer(ExpandBuf* pBuf) {
71 return pBuf->storage;
72}
73
74/*
75 * Get the amount of data currently in the buffer.
76 */
77size_t expandBufGetLength(ExpandBuf* pBuf) {
78 return pBuf->curLen;
79}
80
Elliott Hughes872d4ec2011-10-21 17:07:15 -070081/*
82 * Ensure that the buffer has enough space to hold incoming data. If it
83 * doesn't, resize the buffer.
84 */
85static void ensureSpace(ExpandBuf* pBuf, int newCount) {
86 if (pBuf->curLen + newCount <= pBuf->maxLen) {
87 return;
88 }
89
90 while (pBuf->curLen + newCount > pBuf->maxLen) {
91 pBuf->maxLen *= 2;
92 }
93
Elliott Hughesa21039c2012-06-21 12:09:25 -070094 uint8_t* newPtr = reinterpret_cast<uint8_t*>(realloc(pBuf->storage, pBuf->maxLen));
Elliott Hughes872d4ec2011-10-21 17:07:15 -070095 if (newPtr == NULL) {
Elliott Hughes6c1c69e2012-04-23 16:12:51 -070096 LOG(FATAL) << "realloc(" << pBuf->maxLen << ") failed";
Elliott Hughes872d4ec2011-10-21 17:07:15 -070097 }
98
99 pBuf->storage = newPtr;
100}
101
102/*
103 * Allocate some space in the buffer.
104 */
105uint8_t* expandBufAddSpace(ExpandBuf* pBuf, int gapSize) {
106 uint8_t* gapStart;
107
108 ensureSpace(pBuf, gapSize);
109 gapStart = pBuf->storage + pBuf->curLen;
110 /* do we want to garbage-fill the gap for debugging? */
111 pBuf->curLen += gapSize;
112
113 return gapStart;
114}
115
116/*
117 * Append a byte.
118 */
119void expandBufAdd1(ExpandBuf* pBuf, uint8_t val) {
120 ensureSpace(pBuf, sizeof(val));
121 *(pBuf->storage + pBuf->curLen) = val;
122 pBuf->curLen++;
123}
124
125/*
126 * Append two big-endian bytes.
127 */
128void expandBufAdd2BE(ExpandBuf* pBuf, uint16_t val) {
129 ensureSpace(pBuf, sizeof(val));
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700130 Set2BE(pBuf->storage + pBuf->curLen, val);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700131 pBuf->curLen += sizeof(val);
132}
133
134/*
135 * Append four big-endian bytes.
136 */
137void expandBufAdd4BE(ExpandBuf* pBuf, uint32_t val) {
138 ensureSpace(pBuf, sizeof(val));
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700139 Set4BE(pBuf->storage + pBuf->curLen, val);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700140 pBuf->curLen += sizeof(val);
141}
142
143/*
144 * Append eight big-endian bytes.
145 */
146void expandBufAdd8BE(ExpandBuf* pBuf, uint64_t val) {
147 ensureSpace(pBuf, sizeof(val));
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700148 Set8BE(pBuf->storage + pBuf->curLen, val);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700149 pBuf->curLen += sizeof(val);
150}
151
Elliott Hughesa2155262011-11-16 16:26:58 -0800152static void SetUtf8String(uint8_t* buf, const char* str, size_t strLen) {
Elliott Hughes21f32d72011-11-09 17:44:13 -0800153 Set4BE(buf, strLen);
154 memcpy(buf + sizeof(uint32_t), str, strLen);
155}
156
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700157/*
158 * Add a UTF8 string as a 4-byte length followed by a non-NULL-terminated
159 * string.
160 *
161 * Because these strings are coming out of the VM, it's safe to assume that
162 * they can be null-terminated (either they don't have null bytes or they
163 * have stored null bytes in a multi-byte encoding).
164 */
Elliott Hughes4740cdf2011-12-07 14:07:12 -0800165void expandBufAddUtf8String(ExpandBuf* pBuf, const char* s) {
166 int strLen = strlen(s);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700167 ensureSpace(pBuf, sizeof(uint32_t) + strLen);
Elliott Hughes4740cdf2011-12-07 14:07:12 -0800168 SetUtf8String(pBuf->storage + pBuf->curLen, s, strLen);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700169 pBuf->curLen += sizeof(uint32_t) + strLen;
170}
171
Elliott Hughes4740cdf2011-12-07 14:07:12 -0800172void expandBufAddUtf8String(ExpandBuf* pBuf, const std::string& s) {
173 ensureSpace(pBuf, sizeof(uint32_t) + s.size());
174 SetUtf8String(pBuf->storage + pBuf->curLen, s.data(), s.size());
175 pBuf->curLen += sizeof(uint32_t) + s.size();
176}
177
Elliott Hughes6e9d22c2012-06-22 15:02:37 -0700178void expandBufAddLocation(ExpandBuf* buf, const JdwpLocation& location) {
179 expandBufAdd1(buf, location.type_tag);
180 expandBufAddObjectId(buf, location.class_id);
181 expandBufAddMethodId(buf, location.method_id);
182 expandBufAdd8BE(buf, location.dex_pc);
183}
184
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700185} // namespace JDWP
186
187} // namespace art