blob: 4b4ca0e4a30c40a9539ccf59f1b120abfd91d2f7 [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 Hughes872d4ec2011-10-21 17:07:15 -070021#include "jdwp/jdwp_expand_buf.h"
Elliott Hughes872d4ec2011-10-21 17:07:15 -070022
23#include <stdlib.h>
24#include <string.h>
25
Andreas Gampe57943812017-12-06 21:39:13 -080026#include <android-base/logging.h>
27
Elliott Hughes07ed66b2012-12-12 18:34:25 -080028#include "jdwp/jdwp.h"
29#include "jdwp/jdwp_bits.h"
30
Elliott Hughes872d4ec2011-10-21 17:07:15 -070031namespace art {
32
33namespace JDWP {
34
35/*
36 * Data structure used to track buffer use.
37 */
38struct ExpandBuf {
39 uint8_t* storage;
40 int curLen;
41 int maxLen;
42};
43
44#define kInitialStorage 64
45
46/*
47 * Allocate a JdwpBuf and some initial storage.
48 */
49ExpandBuf* expandBufAlloc() {
Elliott Hughesa21039c2012-06-21 12:09:25 -070050 ExpandBuf* newBuf = new ExpandBuf;
51 newBuf->storage = reinterpret_cast<uint8_t*>(malloc(kInitialStorage));
Elliott Hughes872d4ec2011-10-21 17:07:15 -070052 newBuf->curLen = 0;
53 newBuf->maxLen = kInitialStorage;
Elliott Hughes872d4ec2011-10-21 17:07:15 -070054 return newBuf;
55}
56
57/*
58 * Free a JdwpBuf and associated storage.
59 */
60void expandBufFree(ExpandBuf* pBuf) {
Sebastien Hertz7d955652014-10-22 10:57:10 +020061 if (pBuf == nullptr) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -070062 return;
63 }
64
65 free(pBuf->storage);
Elliott Hughesa21039c2012-06-21 12:09:25 -070066 delete pBuf;
Elliott Hughes872d4ec2011-10-21 17:07:15 -070067}
68
69/*
70 * Get a pointer to the start of the buffer.
71 */
72uint8_t* expandBufGetBuffer(ExpandBuf* pBuf) {
73 return pBuf->storage;
74}
75
76/*
77 * Get the amount of data currently in the buffer.
78 */
79size_t expandBufGetLength(ExpandBuf* pBuf) {
80 return pBuf->curLen;
81}
82
Elliott Hughes872d4ec2011-10-21 17:07:15 -070083/*
84 * Ensure that the buffer has enough space to hold incoming data. If it
85 * doesn't, resize the buffer.
86 */
87static void ensureSpace(ExpandBuf* pBuf, int newCount) {
88 if (pBuf->curLen + newCount <= pBuf->maxLen) {
89 return;
90 }
91
92 while (pBuf->curLen + newCount > pBuf->maxLen) {
93 pBuf->maxLen *= 2;
94 }
95
Elliott Hughesa21039c2012-06-21 12:09:25 -070096 uint8_t* newPtr = reinterpret_cast<uint8_t*>(realloc(pBuf->storage, pBuf->maxLen));
Sebastien Hertz7d955652014-10-22 10:57:10 +020097 if (newPtr == nullptr) {
Elliott Hughes6c1c69e2012-04-23 16:12:51 -070098 LOG(FATAL) << "realloc(" << pBuf->maxLen << ") failed";
Elliott Hughes872d4ec2011-10-21 17:07:15 -070099 }
100
101 pBuf->storage = newPtr;
102}
103
104/*
105 * Allocate some space in the buffer.
106 */
107uint8_t* expandBufAddSpace(ExpandBuf* pBuf, int gapSize) {
108 uint8_t* gapStart;
109
110 ensureSpace(pBuf, gapSize);
111 gapStart = pBuf->storage + pBuf->curLen;
112 /* do we want to garbage-fill the gap for debugging? */
113 pBuf->curLen += gapSize;
114
115 return gapStart;
116}
117
118/*
119 * Append a byte.
120 */
121void expandBufAdd1(ExpandBuf* pBuf, uint8_t val) {
122 ensureSpace(pBuf, sizeof(val));
123 *(pBuf->storage + pBuf->curLen) = val;
124 pBuf->curLen++;
125}
126
127/*
128 * Append two big-endian bytes.
129 */
130void expandBufAdd2BE(ExpandBuf* pBuf, uint16_t val) {
131 ensureSpace(pBuf, sizeof(val));
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700132 Set2BE(pBuf->storage + pBuf->curLen, val);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700133 pBuf->curLen += sizeof(val);
134}
135
136/*
137 * Append four big-endian bytes.
138 */
139void expandBufAdd4BE(ExpandBuf* pBuf, uint32_t val) {
140 ensureSpace(pBuf, sizeof(val));
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700141 Set4BE(pBuf->storage + pBuf->curLen, val);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700142 pBuf->curLen += sizeof(val);
143}
144
145/*
146 * Append eight big-endian bytes.
147 */
148void expandBufAdd8BE(ExpandBuf* pBuf, uint64_t val) {
149 ensureSpace(pBuf, sizeof(val));
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700150 Set8BE(pBuf->storage + pBuf->curLen, val);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700151 pBuf->curLen += sizeof(val);
152}
153
Elliott Hughesa2155262011-11-16 16:26:58 -0800154static void SetUtf8String(uint8_t* buf, const char* str, size_t strLen) {
Elliott Hughes21f32d72011-11-09 17:44:13 -0800155 Set4BE(buf, strLen);
Andreas Gampef45d61c2017-06-07 10:29:33 -0700156 if (str != nullptr) {
157 memcpy(buf + sizeof(uint32_t), str, strLen);
158 }
Elliott Hughes21f32d72011-11-09 17:44:13 -0800159}
160
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700161/*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700162 * Add a UTF8 string as a 4-byte length followed by a non-nullptr-terminated
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700163 * string.
164 *
165 * Because these strings are coming out of the VM, it's safe to assume that
166 * they can be null-terminated (either they don't have null bytes or they
167 * have stored null bytes in a multi-byte encoding).
168 */
Elliott Hughes4740cdf2011-12-07 14:07:12 -0800169void expandBufAddUtf8String(ExpandBuf* pBuf, const char* s) {
David Srbeckyb06e28e2015-12-10 13:15:00 +0000170 int strLen = (s != nullptr ? strlen(s) : 0);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700171 ensureSpace(pBuf, sizeof(uint32_t) + strLen);
Elliott Hughes4740cdf2011-12-07 14:07:12 -0800172 SetUtf8String(pBuf->storage + pBuf->curLen, s, strLen);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700173 pBuf->curLen += sizeof(uint32_t) + strLen;
174}
175
Elliott Hughes4740cdf2011-12-07 14:07:12 -0800176void expandBufAddUtf8String(ExpandBuf* pBuf, const std::string& s) {
177 ensureSpace(pBuf, sizeof(uint32_t) + s.size());
178 SetUtf8String(pBuf->storage + pBuf->curLen, s.data(), s.size());
179 pBuf->curLen += sizeof(uint32_t) + s.size();
180}
181
Elliott Hughes6e9d22c2012-06-22 15:02:37 -0700182void expandBufAddLocation(ExpandBuf* buf, const JdwpLocation& location) {
183 expandBufAdd1(buf, location.type_tag);
184 expandBufAddObjectId(buf, location.class_id);
185 expandBufAddMethodId(buf, location.method_id);
186 expandBufAdd8BE(buf, location.dex_pc);
187}
188
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700189} // namespace JDWP
190
191} // namespace art