summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/lldb/tools/debugserver/source/StdStringExtractor.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2020-08-03 14:33:06 +0000
committerpatrick <patrick@openbsd.org>2020-08-03 14:33:06 +0000
commit061da546b983eb767bad15e67af1174fb0bcf31c (patch)
tree83c78b820819d70aa40c36d90447978b300078c5 /gnu/llvm/lldb/tools/debugserver/source/StdStringExtractor.cpp
parentImport LLVM 10.0.0 release including clang, lld and lldb. (diff)
downloadwireguard-openbsd-061da546b983eb767bad15e67af1174fb0bcf31c.tar.xz
wireguard-openbsd-061da546b983eb767bad15e67af1174fb0bcf31c.zip
Import LLVM 10.0.0 release including clang, lld and lldb.
ok hackroom tested by plenty
Diffstat (limited to 'gnu/llvm/lldb/tools/debugserver/source/StdStringExtractor.cpp')
-rw-r--r--gnu/llvm/lldb/tools/debugserver/source/StdStringExtractor.cpp344
1 files changed, 344 insertions, 0 deletions
diff --git a/gnu/llvm/lldb/tools/debugserver/source/StdStringExtractor.cpp b/gnu/llvm/lldb/tools/debugserver/source/StdStringExtractor.cpp
new file mode 100644
index 00000000000..a4cad2d4bbf
--- /dev/null
+++ b/gnu/llvm/lldb/tools/debugserver/source/StdStringExtractor.cpp
@@ -0,0 +1,344 @@
+//===-- StdStringExtractor.cpp ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "StdStringExtractor.h"
+
+#include <stdlib.h>
+
+
+static inline int xdigit_to_sint(char ch) {
+ if (ch >= 'a' && ch <= 'f')
+ return 10 + ch - 'a';
+ if (ch >= 'A' && ch <= 'F')
+ return 10 + ch - 'A';
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ return -1;
+}
+
+// StdStringExtractor constructor
+StdStringExtractor::StdStringExtractor() : m_packet(), m_index(0) {}
+
+StdStringExtractor::StdStringExtractor(const char *packet_cstr)
+ : m_packet(), m_index(0) {
+ if (packet_cstr)
+ m_packet.assign(packet_cstr);
+}
+
+// Destructor
+StdStringExtractor::~StdStringExtractor() {}
+
+char StdStringExtractor::GetChar(char fail_value) {
+ if (m_index < m_packet.size()) {
+ char ch = m_packet[m_index];
+ ++m_index;
+ return ch;
+ }
+ m_index = UINT64_MAX;
+ return fail_value;
+}
+
+// If a pair of valid hex digits exist at the head of the
+// StdStringExtractor they are decoded into an unsigned byte and returned
+// by this function
+//
+// If there is not a pair of valid hex digits at the head of the
+// StdStringExtractor, it is left unchanged and -1 is returned
+int StdStringExtractor::DecodeHexU8() {
+ SkipSpaces();
+ if (GetBytesLeft() < 2) {
+ return -1;
+ }
+ const int hi_nibble = xdigit_to_sint(m_packet[m_index]);
+ const int lo_nibble = xdigit_to_sint(m_packet[m_index + 1]);
+ if (hi_nibble == -1 || lo_nibble == -1) {
+ return -1;
+ }
+ m_index += 2;
+ return (uint8_t)((hi_nibble << 4) + lo_nibble);
+}
+
+// Extract an unsigned character from two hex ASCII chars in the packet
+// string, or return fail_value on failure
+uint8_t StdStringExtractor::GetHexU8(uint8_t fail_value, bool set_eof_on_fail) {
+ // On success, fail_value will be overwritten with the next
+ // character in the stream
+ GetHexU8Ex(fail_value, set_eof_on_fail);
+ return fail_value;
+}
+
+bool StdStringExtractor::GetHexU8Ex(uint8_t &ch, bool set_eof_on_fail) {
+ int byte = DecodeHexU8();
+ if (byte == -1) {
+ if (set_eof_on_fail || m_index >= m_packet.size())
+ m_index = UINT64_MAX;
+ // ch should not be changed in case of failure
+ return false;
+ }
+ ch = (uint8_t)byte;
+ return true;
+}
+
+uint32_t StdStringExtractor::GetU32(uint32_t fail_value, int base) {
+ if (m_index < m_packet.size()) {
+ char *end = nullptr;
+ const char *start = m_packet.c_str();
+ const char *cstr = start + m_index;
+ uint32_t result = static_cast<uint32_t>(::strtoul(cstr, &end, base));
+
+ if (end && end != cstr) {
+ m_index = end - start;
+ return result;
+ }
+ }
+ return fail_value;
+}
+
+int32_t StdStringExtractor::GetS32(int32_t fail_value, int base) {
+ if (m_index < m_packet.size()) {
+ char *end = nullptr;
+ const char *start = m_packet.c_str();
+ const char *cstr = start + m_index;
+ int32_t result = static_cast<int32_t>(::strtol(cstr, &end, base));
+
+ if (end && end != cstr) {
+ m_index = end - start;
+ return result;
+ }
+ }
+ return fail_value;
+}
+
+uint64_t StdStringExtractor::GetU64(uint64_t fail_value, int base) {
+ if (m_index < m_packet.size()) {
+ char *end = nullptr;
+ const char *start = m_packet.c_str();
+ const char *cstr = start + m_index;
+ uint64_t result = ::strtoull(cstr, &end, base);
+
+ if (end && end != cstr) {
+ m_index = end - start;
+ return result;
+ }
+ }
+ return fail_value;
+}
+
+int64_t StdStringExtractor::GetS64(int64_t fail_value, int base) {
+ if (m_index < m_packet.size()) {
+ char *end = nullptr;
+ const char *start = m_packet.c_str();
+ const char *cstr = start + m_index;
+ int64_t result = ::strtoll(cstr, &end, base);
+
+ if (end && end != cstr) {
+ m_index = end - start;
+ return result;
+ }
+ }
+ return fail_value;
+}
+
+uint32_t StdStringExtractor::GetHexMaxU32(bool little_endian,
+ uint32_t fail_value) {
+ uint32_t result = 0;
+ uint32_t nibble_count = 0;
+
+ SkipSpaces();
+ if (little_endian) {
+ uint32_t shift_amount = 0;
+ while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
+ // Make sure we don't exceed the size of a uint32_t...
+ if (nibble_count >= (sizeof(uint32_t) * 2)) {
+ m_index = UINT64_MAX;
+ return fail_value;
+ }
+
+ uint8_t nibble_lo;
+ uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
+ ++m_index;
+ if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
+ nibble_lo = xdigit_to_sint(m_packet[m_index]);
+ ++m_index;
+ result |= ((uint32_t)nibble_hi << (shift_amount + 4));
+ result |= ((uint32_t)nibble_lo << shift_amount);
+ nibble_count += 2;
+ shift_amount += 8;
+ } else {
+ result |= ((uint32_t)nibble_hi << shift_amount);
+ nibble_count += 1;
+ shift_amount += 4;
+ }
+ }
+ } else {
+ while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
+ // Make sure we don't exceed the size of a uint32_t...
+ if (nibble_count >= (sizeof(uint32_t) * 2)) {
+ m_index = UINT64_MAX;
+ return fail_value;
+ }
+
+ uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
+ // Big Endian
+ result <<= 4;
+ result |= nibble;
+
+ ++m_index;
+ ++nibble_count;
+ }
+ }
+ return result;
+}
+
+uint64_t StdStringExtractor::GetHexMaxU64(bool little_endian,
+ uint64_t fail_value) {
+ uint64_t result = 0;
+ uint32_t nibble_count = 0;
+
+ SkipSpaces();
+ if (little_endian) {
+ uint32_t shift_amount = 0;
+ while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
+ // Make sure we don't exceed the size of a uint64_t...
+ if (nibble_count >= (sizeof(uint64_t) * 2)) {
+ m_index = UINT64_MAX;
+ return fail_value;
+ }
+
+ uint8_t nibble_lo;
+ uint8_t nibble_hi = xdigit_to_sint(m_packet[m_index]);
+ ++m_index;
+ if (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
+ nibble_lo = xdigit_to_sint(m_packet[m_index]);
+ ++m_index;
+ result |= ((uint64_t)nibble_hi << (shift_amount + 4));
+ result |= ((uint64_t)nibble_lo << shift_amount);
+ nibble_count += 2;
+ shift_amount += 8;
+ } else {
+ result |= ((uint64_t)nibble_hi << shift_amount);
+ nibble_count += 1;
+ shift_amount += 4;
+ }
+ }
+ } else {
+ while (m_index < m_packet.size() && ::isxdigit(m_packet[m_index])) {
+ // Make sure we don't exceed the size of a uint64_t...
+ if (nibble_count >= (sizeof(uint64_t) * 2)) {
+ m_index = UINT64_MAX;
+ return fail_value;
+ }
+
+ uint8_t nibble = xdigit_to_sint(m_packet[m_index]);
+ // Big Endian
+ result <<= 4;
+ result |= nibble;
+
+ ++m_index;
+ ++nibble_count;
+ }
+ }
+ return result;
+}
+
+size_t StdStringExtractor::GetHexBytes(void *dst_void, size_t dst_len,
+ uint8_t fail_fill_value) {
+ uint8_t *dst = (uint8_t *)dst_void;
+ size_t bytes_extracted = 0;
+ while (bytes_extracted < dst_len && GetBytesLeft()) {
+ dst[bytes_extracted] = GetHexU8(fail_fill_value);
+ if (IsGood())
+ ++bytes_extracted;
+ else
+ break;
+ }
+
+ for (size_t i = bytes_extracted; i < dst_len; ++i)
+ dst[i] = fail_fill_value;
+
+ return bytes_extracted;
+}
+
+// Decodes all valid hex encoded bytes at the head of the
+// StdStringExtractor, limited by dst_len.
+//
+// Returns the number of bytes successfully decoded
+size_t StdStringExtractor::GetHexBytesAvail(void *dst_void, size_t dst_len) {
+ uint8_t *dst = (uint8_t *)dst_void;
+ size_t bytes_extracted = 0;
+ while (bytes_extracted < dst_len) {
+ int decode = DecodeHexU8();
+ if (decode == -1) {
+ break;
+ }
+ dst[bytes_extracted++] = (uint8_t)decode;
+ }
+ return bytes_extracted;
+}
+
+size_t StdStringExtractor::GetHexByteString(std::string &str) {
+ str.clear();
+ str.reserve(GetBytesLeft() / 2);
+ char ch;
+ while ((ch = GetHexU8()) != '\0')
+ str.append(1, ch);
+ return str.size();
+}
+
+size_t StdStringExtractor::GetHexByteStringFixedLength(std::string &str,
+ uint32_t nibble_length) {
+ str.clear();
+
+ uint32_t nibble_count = 0;
+ for (const char *pch = Peek();
+ (nibble_count < nibble_length) && (pch != nullptr);
+ str.append(1, GetHexU8(0, false)), pch = Peek(), nibble_count += 2) {
+ }
+
+ return str.size();
+}
+
+size_t StdStringExtractor::GetHexByteStringTerminatedBy(std::string &str,
+ char terminator) {
+ str.clear();
+ char ch;
+ while ((ch = GetHexU8(0, false)) != '\0')
+ str.append(1, ch);
+ if (Peek() && *Peek() == terminator)
+ return str.size();
+
+ str.clear();
+ return str.size();
+}
+
+bool StdStringExtractor::GetNameColonValue(std::string &name,
+ std::string &value) {
+ // Read something in the form of NNNN:VVVV; where NNNN is any character
+ // that is not a colon, followed by a ':' character, then a value (one or
+ // more ';' chars), followed by a ';'
+ if (m_index < m_packet.size()) {
+ const size_t colon_idx = m_packet.find(':', m_index);
+ if (colon_idx != std::string::npos) {
+ const size_t semicolon_idx = m_packet.find(';', colon_idx);
+ if (semicolon_idx != std::string::npos) {
+ name.assign(m_packet, m_index, colon_idx - m_index);
+ value.assign(m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1));
+ m_index = semicolon_idx + 1;
+ return true;
+ }
+ }
+ }
+ m_index = UINT64_MAX;
+ return false;
+}
+
+void StdStringExtractor::SkipSpaces() {
+ const size_t n = m_packet.size();
+ while (m_index < n && isspace(m_packet[m_index]))
+ ++m_index;
+}