[lld][WebAssembly] Perform data relocations during start function
[llvm-project.git] / lldb / source / Utility / StringExtractor.cpp
blobd082c86f84639b73f9d877203d6f81e441a270e6
1 //===-- StringExtractor.cpp -----------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Utility/StringExtractor.h"
10 #include "llvm/ADT/StringExtras.h"
12 #include <tuple>
14 #include <cctype>
15 #include <cstdlib>
16 #include <cstring>
18 static inline int xdigit_to_sint(char ch) {
19 if (ch >= 'a' && ch <= 'f')
20 return 10 + ch - 'a';
21 if (ch >= 'A' && ch <= 'F')
22 return 10 + ch - 'A';
23 if (ch >= '0' && ch <= '9')
24 return ch - '0';
25 return -1;
28 // StringExtractor constructor
29 StringExtractor::StringExtractor() : m_packet() {}
31 StringExtractor::StringExtractor(llvm::StringRef packet_str)
32 : m_packet(), m_index(0) {
33 m_packet.assign(packet_str.begin(), packet_str.end());
36 StringExtractor::StringExtractor(const char *packet_cstr)
37 : m_packet(), m_index(0) {
38 if (packet_cstr)
39 m_packet.assign(packet_cstr);
42 // Destructor
43 StringExtractor::~StringExtractor() = default;
45 char StringExtractor::GetChar(char fail_value) {
46 if (m_index < m_packet.size()) {
47 char ch = m_packet[m_index];
48 ++m_index;
49 return ch;
51 m_index = UINT64_MAX;
52 return fail_value;
55 // If a pair of valid hex digits exist at the head of the StringExtractor they
56 // are decoded into an unsigned byte and returned by this function
58 // If there is not a pair of valid hex digits at the head of the
59 // StringExtractor, it is left unchanged and -1 is returned
60 int StringExtractor::DecodeHexU8() {
61 SkipSpaces();
62 if (GetBytesLeft() < 2) {
63 return -1;
65 const int hi_nibble = xdigit_to_sint(m_packet[m_index]);
66 const int lo_nibble = xdigit_to_sint(m_packet[m_index + 1]);
67 if (hi_nibble == -1 || lo_nibble == -1) {
68 return -1;
70 m_index += 2;
71 return static_cast<uint8_t>((hi_nibble << 4) + lo_nibble);
74 // Extract an unsigned character from two hex ASCII chars in the packet string,
75 // or return fail_value on failure
76 uint8_t StringExtractor::GetHexU8(uint8_t fail_value, bool set_eof_on_fail) {
77 // On success, fail_value will be overwritten with the next character in the
78 // stream
79 GetHexU8Ex(fail_value, set_eof_on_fail);
80 return fail_value;
83 bool StringExtractor::GetHexU8Ex(uint8_t &ch, bool set_eof_on_fail) {
84 int byte = DecodeHexU8();
85 if (byte == -1) {
86 if (set_eof_on_fail || m_index >= m_packet.size())
87 m_index = UINT64_MAX;
88 // ch should not be changed in case of failure
89 return false;
91 ch = static_cast<uint8_t>(byte);
92 return true;
95 uint32_t StringExtractor::GetU32(uint32_t fail_value, int base) {
96 if (m_index < m_packet.size()) {
97 char *end = nullptr;
98 const char *start = m_packet.c_str();
99 const char *cstr = start + m_index;
100 uint32_t result = static_cast<uint32_t>(::strtoul(cstr, &end, base));
102 if (end && end != cstr) {
103 m_index = end - start;
104 return result;
107 return fail_value;
110 int32_t StringExtractor::GetS32(int32_t fail_value, int base) {
111 if (m_index < m_packet.size()) {
112 char *end = nullptr;
113 const char *start = m_packet.c_str();
114 const char *cstr = start + m_index;
115 int32_t result = static_cast<int32_t>(::strtol(cstr, &end, base));
117 if (end && end != cstr) {
118 m_index = end - start;
119 return result;
122 return fail_value;
125 uint64_t StringExtractor::GetU64(uint64_t fail_value, int base) {
126 if (m_index < m_packet.size()) {
127 char *end = nullptr;
128 const char *start = m_packet.c_str();
129 const char *cstr = start + m_index;
130 uint64_t result = ::strtoull(cstr, &end, base);
132 if (end && end != cstr) {
133 m_index = end - start;
134 return result;
137 return fail_value;
140 int64_t StringExtractor::GetS64(int64_t fail_value, int base) {
141 if (m_index < m_packet.size()) {
142 char *end = nullptr;
143 const char *start = m_packet.c_str();
144 const char *cstr = start + m_index;
145 int64_t result = ::strtoll(cstr, &end, base);
147 if (end && end != cstr) {
148 m_index = end - start;
149 return result;
152 return fail_value;
155 uint32_t StringExtractor::GetHexMaxU32(bool little_endian,
156 uint32_t fail_value) {
157 uint32_t result = 0;
158 uint32_t nibble_count = 0;
160 SkipSpaces();
161 if (little_endian) {
162 uint32_t shift_amount = 0;
163 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
164 // Make sure we don't exceed the size of a uint32_t...
165 if (nibble_count >= (sizeof(uint32_t) * 2)) {
166 m_index = UINT64_MAX;
167 return fail_value;
170 uint8_t nibble_lo;
171 uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
172 ++m_index;
173 if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
174 nibble_lo = xdigit_to_sint(m_packet[m_index]);
175 ++m_index;
176 result |= (static_cast<uint32_t>(nibble_hi) << (shift_amount + 4));
177 result |= (static_cast<uint32_t>(nibble_lo) << shift_amount);
178 nibble_count += 2;
179 shift_amount += 8;
180 } else {
181 result |= (static_cast<uint32_t>(nibble_hi) << shift_amount);
182 nibble_count += 1;
183 shift_amount += 4;
186 } else {
187 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
188 // Make sure we don't exceed the size of a uint32_t...
189 if (nibble_count >= (sizeof(uint32_t) * 2)) {
190 m_index = UINT64_MAX;
191 return fail_value;
194 uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
195 // Big Endian
196 result <<= 4;
197 result |= nibble;
199 ++m_index;
200 ++nibble_count;
203 return result;
206 uint64_t StringExtractor::GetHexMaxU64(bool little_endian,
207 uint64_t fail_value) {
208 uint64_t result = 0;
209 uint32_t nibble_count = 0;
211 SkipSpaces();
212 if (little_endian) {
213 uint32_t shift_amount = 0;
214 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
215 // Make sure we don't exceed the size of a uint64_t...
216 if (nibble_count >= (sizeof(uint64_t) * 2)) {
217 m_index = UINT64_MAX;
218 return fail_value;
221 uint8_t nibble_lo;
222 uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
223 ++m_index;
224 if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
225 nibble_lo = xdigit_to_sint(m_packet[m_index]);
226 ++m_index;
227 result |= (static_cast<uint64_t>(nibble_hi) << (shift_amount + 4));
228 result |= (static_cast<uint64_t>(nibble_lo) << shift_amount);
229 nibble_count += 2;
230 shift_amount += 8;
231 } else {
232 result |= (static_cast<uint64_t>(nibble_hi) << shift_amount);
233 nibble_count += 1;
234 shift_amount += 4;
237 } else {
238 while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
239 // Make sure we don't exceed the size of a uint64_t...
240 if (nibble_count >= (sizeof(uint64_t) * 2)) {
241 m_index = UINT64_MAX;
242 return fail_value;
245 uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
246 // Big Endian
247 result <<= 4;
248 result |= nibble;
250 ++m_index;
251 ++nibble_count;
254 return result;
257 bool StringExtractor::ConsumeFront(const llvm::StringRef &str) {
258 llvm::StringRef S = GetStringRef();
259 if (!S.startswith(str))
260 return false;
261 else
262 m_index += str.size();
263 return true;
266 size_t StringExtractor::GetHexBytes(llvm::MutableArrayRef<uint8_t> dest,
267 uint8_t fail_fill_value) {
268 size_t bytes_extracted = 0;
269 while (!dest.empty() && GetBytesLeft() > 0) {
270 dest[0] = GetHexU8(fail_fill_value);
271 if (!IsGood())
272 break;
273 ++bytes_extracted;
274 dest = dest.drop_front();
277 if (!dest.empty())
278 ::memset(dest.data(), fail_fill_value, dest.size());
280 return bytes_extracted;
283 // Decodes all valid hex encoded bytes at the head of the StringExtractor,
284 // limited by dst_len.
286 // Returns the number of bytes successfully decoded
287 size_t StringExtractor::GetHexBytesAvail(llvm::MutableArrayRef<uint8_t> dest) {
288 size_t bytes_extracted = 0;
289 while (!dest.empty()) {
290 int decode = DecodeHexU8();
291 if (decode == -1)
292 break;
293 dest[0] = static_cast<uint8_t>(decode);
294 dest = dest.drop_front();
295 ++bytes_extracted;
297 return bytes_extracted;
300 size_t StringExtractor::GetHexByteString(std::string &str) {
301 str.clear();
302 str.reserve(GetBytesLeft() / 2);
303 char ch;
304 while ((ch = GetHexU8()) != '\0')
305 str.append(1, ch);
306 return str.size();
309 size_t StringExtractor::GetHexByteStringFixedLength(std::string &str,
310 uint32_t nibble_length) {
311 str.clear();
313 uint32_t nibble_count = 0;
314 for (const char *pch = Peek();
315 (nibble_count < nibble_length) && (pch != nullptr);
316 str.append(1, GetHexU8(0, false)), pch = Peek(), nibble_count += 2) {
319 return str.size();
322 size_t StringExtractor::GetHexByteStringTerminatedBy(std::string &str,
323 char terminator) {
324 str.clear();
325 char ch;
326 while ((ch = GetHexU8(0, false)) != '\0')
327 str.append(1, ch);
328 if (Peek() && *Peek() == terminator)
329 return str.size();
331 str.clear();
332 return str.size();
335 bool StringExtractor::GetNameColonValue(llvm::StringRef &name,
336 llvm::StringRef &value) {
337 // Read something in the form of NNNN:VVVV; where NNNN is any character that
338 // is not a colon, followed by a ':' character, then a value (one or more ';'
339 // chars), followed by a ';'
340 if (m_index >= m_packet.size())
341 return fail();
343 llvm::StringRef view(m_packet);
344 if (view.empty())
345 return fail();
347 llvm::StringRef a, b, c, d;
348 view = view.substr(m_index);
349 std::tie(a, b) = view.split(':');
350 if (a.empty() || b.empty())
351 return fail();
352 std::tie(c, d) = b.split(';');
353 if (b == c && d.empty())
354 return fail();
356 name = a;
357 value = c;
358 if (d.empty())
359 m_index = m_packet.size();
360 else {
361 size_t bytes_consumed = d.data() - view.data();
362 m_index += bytes_consumed;
364 return true;
367 void StringExtractor::SkipSpaces() {
368 const size_t n = m_packet.size();
369 while (m_index < n && llvm::isSpace(m_packet[m_index]))
370 ++m_index;