18fdfc1d6SDavid Spickett //===-- DataDumpExtractorTest.cpp -----------------------------------------===//
28fdfc1d6SDavid Spickett //
38fdfc1d6SDavid Spickett // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
48fdfc1d6SDavid Spickett // See https://llvm.org/LICENSE.txt for license information.
58fdfc1d6SDavid Spickett // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68fdfc1d6SDavid Spickett //
78fdfc1d6SDavid Spickett //===----------------------------------------------------------------------===//
88fdfc1d6SDavid Spickett
98fdfc1d6SDavid Spickett #include "lldb/Core/DumpDataExtractor.h"
108fdfc1d6SDavid Spickett #include "lldb/Utility/DataBufferHeap.h"
118fdfc1d6SDavid Spickett #include "lldb/Utility/DataExtractor.h"
128fdfc1d6SDavid Spickett #include "lldb/Utility/Endian.h"
138fdfc1d6SDavid Spickett #include "lldb/Utility/StreamString.h"
148fdfc1d6SDavid Spickett #include "gtest/gtest.h"
158fdfc1d6SDavid Spickett #include <complex>
16ae58cf5fSRaphael Isemann #include <limits>
178fdfc1d6SDavid Spickett
188fdfc1d6SDavid Spickett using namespace lldb;
198fdfc1d6SDavid Spickett using namespace lldb_private;
208fdfc1d6SDavid Spickett
TestDumpWithAddress(uint64_t base_addr,size_t item_count,llvm::StringRef expected)2144d0ad53SDavid Spickett static void TestDumpWithAddress(uint64_t base_addr, size_t item_count,
228fdfc1d6SDavid Spickett llvm::StringRef expected) {
23a86cbd47SDavid Spickett std::vector<uint8_t> data{0x11, 0x22};
24a86cbd47SDavid Spickett StreamString result;
25a86cbd47SDavid Spickett DataBufferHeap dumpbuffer(&data[0], data.size());
26a86cbd47SDavid Spickett DataExtractor extractor(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(),
27a86cbd47SDavid Spickett endian::InlHostByteOrder(), /*addr_size=*/4);
28a86cbd47SDavid Spickett
29a86cbd47SDavid Spickett DumpDataExtractor(extractor, &result, 0, lldb::Format::eFormatHex,
30a86cbd47SDavid Spickett /*item_byte_size=*/1, item_count,
31a86cbd47SDavid Spickett /*num_per_line=*/1, base_addr, 0, 0);
32a86cbd47SDavid Spickett ASSERT_EQ(expected, result.GetString());
33a86cbd47SDavid Spickett }
34a86cbd47SDavid Spickett
TEST(DumpDataExtractorTest,BaseAddress)35a86cbd47SDavid Spickett TEST(DumpDataExtractorTest, BaseAddress) {
3644d0ad53SDavid Spickett TestDumpWithAddress(0x12341234, 1, "0x12341234: 0x11");
3744d0ad53SDavid Spickett TestDumpWithAddress(LLDB_INVALID_ADDRESS, 1, "0x11");
3844d0ad53SDavid Spickett TestDumpWithAddress(0x12341234, 2, "0x12341234: 0x11\n0x12341235: 0x22");
3944d0ad53SDavid Spickett TestDumpWithAddress(LLDB_INVALID_ADDRESS, 2, "0x11\n0x22");
40a86cbd47SDavid Spickett }
41a86cbd47SDavid Spickett
TestDumpWithOffset(offset_t start_offset,llvm::StringRef expected)4244d0ad53SDavid Spickett static void TestDumpWithOffset(offset_t start_offset,
43a86cbd47SDavid Spickett llvm::StringRef expected) {
44a86cbd47SDavid Spickett std::vector<uint8_t> data{0x11, 0x22, 0x33};
45a86cbd47SDavid Spickett StreamString result;
46a86cbd47SDavid Spickett DataBufferHeap dumpbuffer(&data[0], data.size());
47a86cbd47SDavid Spickett DataExtractor extractor(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(),
48a86cbd47SDavid Spickett endian::InlHostByteOrder(), /*addr_size=*/4);
49a86cbd47SDavid Spickett
50a86cbd47SDavid Spickett DumpDataExtractor(extractor, &result, start_offset, lldb::Format::eFormatHex,
51a86cbd47SDavid Spickett /*item_byte_size=*/1, /*item_count=*/data.size(),
52a86cbd47SDavid Spickett /*num_per_line=*/data.size(), /*base_addr=*/0, 0, 0);
53a86cbd47SDavid Spickett ASSERT_EQ(expected, result.GetString());
54a86cbd47SDavid Spickett }
55a86cbd47SDavid Spickett
TEST(DumpDataExtractorTest,StartOffset)56a86cbd47SDavid Spickett TEST(DumpDataExtractorTest, StartOffset) {
5744d0ad53SDavid Spickett TestDumpWithOffset(0, "0x00000000: 0x11 0x22 0x33");
58a86cbd47SDavid Spickett // The offset applies to the DataExtractor, not the address used when
59a86cbd47SDavid Spickett // formatting.
6044d0ad53SDavid Spickett TestDumpWithOffset(1, "0x00000000: 0x22 0x33");
61a86cbd47SDavid Spickett // If the offset is outside the DataExtractor's range we do nothing.
6244d0ad53SDavid Spickett TestDumpWithOffset(3, "");
63a86cbd47SDavid Spickett }
64a86cbd47SDavid Spickett
TEST(DumpDataExtractorTest,NullStream)65a86cbd47SDavid Spickett TEST(DumpDataExtractorTest, NullStream) {
66a86cbd47SDavid Spickett // We don't do any work if there is no output stream.
67a86cbd47SDavid Spickett uint8_t c = 0x11;
68a86cbd47SDavid Spickett StreamString result;
69a86cbd47SDavid Spickett DataBufferHeap dumpbuffer(&c, 0);
70a86cbd47SDavid Spickett DataExtractor extractor(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(),
71a86cbd47SDavid Spickett endian::InlHostByteOrder(), /*addr_size=*/4);
72a86cbd47SDavid Spickett
73a86cbd47SDavid Spickett DumpDataExtractor(extractor, nullptr, 0, lldb::Format::eFormatHex,
74a86cbd47SDavid Spickett /*item_byte_size=*/1, /*item_count=*/1,
75a86cbd47SDavid Spickett /*num_per_line=*/1, /*base_addr=*/0, 0, 0);
76a86cbd47SDavid Spickett ASSERT_EQ("", result.GetString());
77a86cbd47SDavid Spickett }
78a86cbd47SDavid Spickett
TestDumpImpl(const void * data,size_t data_size,size_t item_byte_size,size_t item_count,size_t num_per_line,uint64_t base_addr,lldb::Format format,llvm::StringRef expected)79a86cbd47SDavid Spickett static void TestDumpImpl(const void *data, size_t data_size,
80a86cbd47SDavid Spickett size_t item_byte_size, size_t item_count,
81a86cbd47SDavid Spickett size_t num_per_line, uint64_t base_addr,
82a86cbd47SDavid Spickett lldb::Format format, llvm::StringRef expected) {
838fdfc1d6SDavid Spickett StreamString result;
848fdfc1d6SDavid Spickett DataBufferHeap dumpbuffer(data, data_size);
858fdfc1d6SDavid Spickett DataExtractor extractor(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(),
868fdfc1d6SDavid Spickett endian::InlHostByteOrder(),
878fdfc1d6SDavid Spickett /*addr_size=*/4);
88a86cbd47SDavid Spickett DumpDataExtractor(extractor, &result, 0, format, item_byte_size, item_count,
89a86cbd47SDavid Spickett num_per_line, base_addr, 0, 0);
908fdfc1d6SDavid Spickett ASSERT_EQ(expected, result.GetString());
918fdfc1d6SDavid Spickett }
928fdfc1d6SDavid Spickett
938fdfc1d6SDavid Spickett template <typename T>
TestDump(T data,lldb::Format format,llvm::StringRef expected)94a86cbd47SDavid Spickett static void TestDump(T data, lldb::Format format, llvm::StringRef expected) {
95a86cbd47SDavid Spickett TestDumpImpl(&data, sizeof(T), sizeof(T), 1, 1, LLDB_INVALID_ADDRESS, format,
968fdfc1d6SDavid Spickett expected);
978fdfc1d6SDavid Spickett }
988fdfc1d6SDavid Spickett
TestDump(llvm::StringRef str,lldb::Format format,llvm::StringRef expected)99a86cbd47SDavid Spickett static void TestDump(llvm::StringRef str, lldb::Format format,
100a86cbd47SDavid Spickett llvm::StringRef expected) {
101a86cbd47SDavid Spickett TestDumpImpl(str.bytes_begin(),
102a86cbd47SDavid Spickett // +1 to include the NULL char as the last byte
103a86cbd47SDavid Spickett str.size() + 1, str.size() + 1, 1, 1, LLDB_INVALID_ADDRESS,
104a86cbd47SDavid Spickett format, expected);
105a86cbd47SDavid Spickett }
106a86cbd47SDavid Spickett
107a86cbd47SDavid Spickett template <typename T>
TestDump(const std::vector<T> data,lldb::Format format,llvm::StringRef expected)108a86cbd47SDavid Spickett static void TestDump(const std::vector<T> data, lldb::Format format,
109a86cbd47SDavid Spickett llvm::StringRef expected) {
110a86cbd47SDavid Spickett size_t sz_bytes = data.size() * sizeof(T);
111a86cbd47SDavid Spickett TestDumpImpl(&data[0], sz_bytes, sz_bytes, data.size(), 1,
112a86cbd47SDavid Spickett LLDB_INVALID_ADDRESS, format, expected);
113a86cbd47SDavid Spickett }
114a86cbd47SDavid Spickett
TEST(DumpDataExtractorTest,Formats)1158fdfc1d6SDavid Spickett TEST(DumpDataExtractorTest, Formats) {
116a86cbd47SDavid Spickett TestDump<uint8_t>(1, lldb::eFormatDefault, "0x01");
117a86cbd47SDavid Spickett TestDump<uint8_t>(1, lldb::eFormatBoolean, "true");
118a86cbd47SDavid Spickett TestDump<uint8_t>(0xAA, lldb::eFormatBinary, "0b10101010");
119a86cbd47SDavid Spickett TestDump<uint8_t>(1, lldb::eFormatBytes, "01");
120a86cbd47SDavid Spickett TestDump<uint8_t>(1, lldb::eFormatBytesWithASCII, "01 .");
121a86cbd47SDavid Spickett TestDump('?', lldb::eFormatChar, "'?'");
122a86cbd47SDavid Spickett TestDump('\x1A', lldb::eFormatCharPrintable, ".");
123a86cbd47SDavid Spickett TestDump('#', lldb::eFormatCharPrintable, "#");
124a86cbd47SDavid Spickett TestDump(std::complex<float>(1.2, 3.4), lldb::eFormatComplex, "1.2 + 3.4i");
125a86cbd47SDavid Spickett TestDump(std::complex<double>(4.5, 6.7), lldb::eFormatComplex, "4.5 + 6.7i");
1268fdfc1d6SDavid Spickett
1278fdfc1d6SDavid Spickett // long double is not tested here because for some platforms we treat it as 10
1288fdfc1d6SDavid Spickett // bytes when the compiler allocates 16 bytes of space for it. (see
1298fdfc1d6SDavid Spickett // DataExtractor::GetLongDouble) Meaning that when we extract the second one,
1308fdfc1d6SDavid Spickett // it gets the wrong value (it's 6 bytes off). You could manually construct a
1318fdfc1d6SDavid Spickett // set of bytes to match the 10 byte format but then if the test runs on a
1328fdfc1d6SDavid Spickett // machine where we don't use 10 it'll break.
1338fdfc1d6SDavid Spickett
134a86cbd47SDavid Spickett TestDump(llvm::StringRef("aardvark"), lldb::Format::eFormatCString,
135a86cbd47SDavid Spickett "\"aardvark\"");
136a86cbd47SDavid Spickett TestDump<uint16_t>(99, lldb::Format::eFormatDecimal, "99");
1378fdfc1d6SDavid Spickett // Just prints as a signed integer.
138a86cbd47SDavid Spickett TestDump(-1, lldb::Format::eFormatEnum, "-1");
139a86cbd47SDavid Spickett TestDump(0xcafef00d, lldb::Format::eFormatHex, "0xcafef00d");
140a86cbd47SDavid Spickett TestDump(0xcafef00d, lldb::Format::eFormatHexUppercase, "0xCAFEF00D");
141a86cbd47SDavid Spickett TestDump(0.456, lldb::Format::eFormatFloat, "0.456");
142a86cbd47SDavid Spickett TestDump(9, lldb::Format::eFormatOctal, "011");
1438fdfc1d6SDavid Spickett // Chars packed into an integer.
144a86cbd47SDavid Spickett TestDump<uint32_t>(0x4C4C4442, lldb::Format::eFormatOSType, "'LLDB'");
1458fdfc1d6SDavid Spickett // Unicode8 doesn't have a specific formatter.
146a86cbd47SDavid Spickett TestDump<uint8_t>(0x34, lldb::Format::eFormatUnicode8, "0x34");
147a86cbd47SDavid Spickett TestDump<uint16_t>(0x1122, lldb::Format::eFormatUnicode16, "U+1122");
148a86cbd47SDavid Spickett TestDump<uint32_t>(0x12345678, lldb::Format::eFormatUnicode32,
149a86cbd47SDavid Spickett "U+0x12345678");
150a86cbd47SDavid Spickett TestDump<unsigned int>(654321, lldb::Format::eFormatUnsigned, "654321");
1518fdfc1d6SDavid Spickett // This pointer is printed based on the size of uint64_t, so the test is the
1528fdfc1d6SDavid Spickett // same for 32/64 bit host.
153a86cbd47SDavid Spickett TestDump<uint64_t>(0x4444555566667777, lldb::Format::eFormatPointer,
154a86cbd47SDavid Spickett "0x4444555566667777");
1558fdfc1d6SDavid Spickett
156a86cbd47SDavid Spickett TestDump(std::vector<char>{'A', '\x01', 'C'},
157a86cbd47SDavid Spickett lldb::Format::eFormatVectorOfChar, "{A\\x01C}");
158a86cbd47SDavid Spickett TestDump(std::vector<int8_t>{0, -1, std::numeric_limits<int8_t>::max()},
159a86cbd47SDavid Spickett lldb::Format::eFormatVectorOfSInt8, "{0 -1 127}");
160a86cbd47SDavid Spickett TestDump(std::vector<uint8_t>{12, 0xFF, 34},
161a86cbd47SDavid Spickett lldb::Format::eFormatVectorOfUInt8, "{0x0c 0xff 0x22}");
162a86cbd47SDavid Spickett TestDump(std::vector<int16_t>{-1, 1234, std::numeric_limits<int16_t>::max()},
163a86cbd47SDavid Spickett lldb::Format::eFormatVectorOfSInt16, "{-1 1234 32767}");
164a86cbd47SDavid Spickett TestDump(std::vector<uint16_t>{0xffff, 0xabcd, 0x1234},
165a86cbd47SDavid Spickett lldb::Format::eFormatVectorOfUInt16, "{0xffff 0xabcd 0x1234}");
166a86cbd47SDavid Spickett TestDump(std::vector<int32_t>{0, -1, std::numeric_limits<int32_t>::max()},
167a86cbd47SDavid Spickett lldb::Format::eFormatVectorOfSInt32, "{0 -1 2147483647}");
168a86cbd47SDavid Spickett TestDump(std::vector<uint32_t>{0, 0xffffffff, 0x1234abcd},
1698fdfc1d6SDavid Spickett lldb::Format::eFormatVectorOfUInt32,
170a86cbd47SDavid Spickett "{0x00000000 0xffffffff 0x1234abcd}");
171a86cbd47SDavid Spickett TestDump(std::vector<int64_t>{0, -1, std::numeric_limits<int64_t>::max()},
172a86cbd47SDavid Spickett lldb::Format::eFormatVectorOfSInt64, "{0 -1 9223372036854775807}");
173a86cbd47SDavid Spickett TestDump(std::vector<uint64_t>{0, 0xaaaabbbbccccdddd},
1748fdfc1d6SDavid Spickett lldb::Format::eFormatVectorOfUInt64,
175a86cbd47SDavid Spickett "{0x0000000000000000 0xaaaabbbbccccdddd}");
1768fdfc1d6SDavid Spickett
1778fdfc1d6SDavid Spickett // See half2float for format details.
17848780527SRaphael Isemann // Test zeroes.
17948780527SRaphael Isemann TestDump(std::vector<uint16_t>{0x0000, 0x8000},
18048780527SRaphael Isemann lldb::Format::eFormatVectorOfFloat16, "{0 -0}");
18148780527SRaphael Isemann // Some subnormal numbers.
18248780527SRaphael Isemann TestDump(std::vector<uint16_t>{0x0001, 0x8001},
18348780527SRaphael Isemann lldb::Format::eFormatVectorOfFloat16, "{5.96046e-08 -5.96046e-08}");
18448780527SRaphael Isemann // A full mantisse and empty expontent.
18548780527SRaphael Isemann TestDump(std::vector<uint16_t>{0x83ff, 0x03ff},
18648780527SRaphael Isemann lldb::Format::eFormatVectorOfFloat16, "{-6.09756e-05 6.09756e-05}");
18748780527SRaphael Isemann // Some normal numbers.
18848780527SRaphael Isemann TestDump(std::vector<uint16_t>{0b0100001001001000},
1898ebaa195SRaphael Isemann lldb::Format::eFormatVectorOfFloat16,
190*553a8724SMuhammad Omair Javaid #if defined(_MSC_VER) && _MSC_VER < 1920
1918ebaa195SRaphael Isemann // FIXME: This should print the same on all platforms.
1928ebaa195SRaphael Isemann "{3.14063}");
1938ebaa195SRaphael Isemann #else
1948ebaa195SRaphael Isemann "{3.14062}");
1958ebaa195SRaphael Isemann #endif
19648780527SRaphael Isemann // Largest and smallest normal number.
19748780527SRaphael Isemann TestDump(std::vector<uint16_t>{0x0400, 0x7bff},
19848780527SRaphael Isemann lldb::Format::eFormatVectorOfFloat16, "{6.10352e-05 65504}");
199a86cbd47SDavid Spickett TestDump(std::vector<uint16_t>{0xabcd, 0x1234},
200a86cbd47SDavid Spickett lldb::Format::eFormatVectorOfFloat16, "{-0.0609436 0.000757217}");
201ae58cf5fSRaphael Isemann
202ae58cf5fSRaphael Isemann // quiet/signaling NaNs.
203ae58cf5fSRaphael Isemann TestDump(std::vector<uint16_t>{0xffff, 0xffc0, 0x7fff, 0x7fc0},
204ae58cf5fSRaphael Isemann lldb::Format::eFormatVectorOfFloat16, "{-nan -nan nan nan}");
205ae58cf5fSRaphael Isemann // +/-Inf.
206ae58cf5fSRaphael Isemann TestDump(std::vector<uint16_t>{0xfc00, 0x7c00},
207ae58cf5fSRaphael Isemann lldb::Format::eFormatVectorOfFloat16, "{-inf inf}");
208ae58cf5fSRaphael Isemann
209a86cbd47SDavid Spickett TestDump(std::vector<float>{std::numeric_limits<float>::min(),
2108fdfc1d6SDavid Spickett std::numeric_limits<float>::max()},
211a86cbd47SDavid Spickett lldb::Format::eFormatVectorOfFloat32, "{1.17549e-38 3.40282e+38}");
212ae58cf5fSRaphael Isemann TestDump(std::vector<float>{std::numeric_limits<float>::quiet_NaN(),
213ae58cf5fSRaphael Isemann std::numeric_limits<float>::signaling_NaN(),
214ae58cf5fSRaphael Isemann -std::numeric_limits<float>::quiet_NaN(),
215ae58cf5fSRaphael Isemann -std::numeric_limits<float>::signaling_NaN()},
216ae58cf5fSRaphael Isemann lldb::Format::eFormatVectorOfFloat32, "{nan nan -nan -nan}");
217a86cbd47SDavid Spickett TestDump(std::vector<double>{std::numeric_limits<double>::min(),
2188fdfc1d6SDavid Spickett std::numeric_limits<double>::max()},
2198fdfc1d6SDavid Spickett lldb::Format::eFormatVectorOfFloat64,
220a86cbd47SDavid Spickett "{2.2250738585072e-308 1.79769313486232e+308}");
221ae58cf5fSRaphael Isemann TestDump(
222ae58cf5fSRaphael Isemann std::vector<double>{
223ae58cf5fSRaphael Isemann std::numeric_limits<double>::quiet_NaN(),
224ae58cf5fSRaphael Isemann std::numeric_limits<double>::signaling_NaN(),
225ae58cf5fSRaphael Isemann -std::numeric_limits<double>::quiet_NaN(),
226ae58cf5fSRaphael Isemann -std::numeric_limits<double>::signaling_NaN(),
227ae58cf5fSRaphael Isemann },
228ae58cf5fSRaphael Isemann lldb::Format::eFormatVectorOfFloat64, "{nan nan -nan -nan}");
2298fdfc1d6SDavid Spickett
2308fdfc1d6SDavid Spickett // Not sure we can rely on having uint128_t everywhere so emulate with
2318fdfc1d6SDavid Spickett // uint64_t.
232a86cbd47SDavid Spickett TestDump(
2338fdfc1d6SDavid Spickett std::vector<uint64_t>{0x1, 0x1111222233334444, 0xaaaabbbbccccdddd, 0x0},
2348fdfc1d6SDavid Spickett lldb::Format::eFormatVectorOfUInt128,
235a86cbd47SDavid Spickett "{0x11112222333344440000000000000001 "
2368fdfc1d6SDavid Spickett "0x0000000000000000aaaabbbbccccdddd}");
2378fdfc1d6SDavid Spickett
238a86cbd47SDavid Spickett TestDump(std::vector<int>{2, 4}, lldb::Format::eFormatComplexInteger,
239a86cbd47SDavid Spickett "2 + 4i");
2408fdfc1d6SDavid Spickett
2418fdfc1d6SDavid Spickett // Without an execution context this just prints the pointer on its own.
242a86cbd47SDavid Spickett TestDump<uint32_t>(0x11223344, lldb::Format::eFormatAddressInfo,
243a86cbd47SDavid Spickett "0x11223344");
2448fdfc1d6SDavid Spickett
2458fdfc1d6SDavid Spickett // Input not written in hex form because that requires C++17.
246a86cbd47SDavid Spickett TestDump<float>(10, lldb::Format::eFormatHexFloat, "0x1.4p3");
247a86cbd47SDavid Spickett TestDump<double>(10, lldb::Format::eFormatHexFloat, "0x1.4p3");
2488da5d111SDavid Spickett // long double not supported, see ItemByteSizeErrors.
2498fdfc1d6SDavid Spickett
2508fdfc1d6SDavid Spickett // Can't disassemble without an execution context.
251a86cbd47SDavid Spickett TestDump<uint32_t>(0xcafef00d, lldb::Format::eFormatInstruction,
2528fdfc1d6SDavid Spickett "invalid target");
2538fdfc1d6SDavid Spickett
2548fdfc1d6SDavid Spickett // Has no special handling, intended for use elsewhere.
255a86cbd47SDavid Spickett TestDump<int>(99, lldb::Format::eFormatVoid, "0x00000063");
2568fdfc1d6SDavid Spickett }
2578fdfc1d6SDavid Spickett
TEST(DumpDataExtractorTest,FormatCharArray)2588fdfc1d6SDavid Spickett TEST(DumpDataExtractorTest, FormatCharArray) {
2598fdfc1d6SDavid Spickett // Unlike the other formats, charArray isn't 1 array of N chars.
2608fdfc1d6SDavid Spickett // It must be passed as N chars of 1 byte each.
2618fdfc1d6SDavid Spickett // (eFormatVectorOfChar does this swap for you)
2628fdfc1d6SDavid Spickett std::vector<char> data{'A', '\x01', '#'};
2638fdfc1d6SDavid Spickett StreamString result;
2648fdfc1d6SDavid Spickett DataBufferHeap dumpbuffer(&data[0], data.size());
2658fdfc1d6SDavid Spickett DataExtractor extractor(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(),
2668fdfc1d6SDavid Spickett endian::InlHostByteOrder(), /*addr_size=*/4);
2678fdfc1d6SDavid Spickett
2688fdfc1d6SDavid Spickett DumpDataExtractor(extractor, &result, 0, lldb::Format::eFormatCharArray,
2698fdfc1d6SDavid Spickett /*item_byte_size=*/1,
2708fdfc1d6SDavid Spickett /*item_count=*/data.size(),
2718fdfc1d6SDavid Spickett /*num_per_line=*/data.size(), 0, 0, 0);
2728fdfc1d6SDavid Spickett ASSERT_EQ("0x00000000: A\\x01#", result.GetString());
2738fdfc1d6SDavid Spickett
2748fdfc1d6SDavid Spickett result.Clear();
2758fdfc1d6SDavid Spickett DumpDataExtractor(extractor, &result, 0, lldb::Format::eFormatCharArray, 1,
2768fdfc1d6SDavid Spickett data.size(), 1, 0, 0, 0);
2778fdfc1d6SDavid Spickett // ASSERT macro thinks the split strings are multiple arguments so make a var.
2788fdfc1d6SDavid Spickett const char *expected = "0x00000000: A\n"
2798fdfc1d6SDavid Spickett "0x00000001: \\x01\n"
2808fdfc1d6SDavid Spickett "0x00000002: #";
2818fdfc1d6SDavid Spickett ASSERT_EQ(expected, result.GetString());
2828fdfc1d6SDavid Spickett }
283a86cbd47SDavid Spickett
284a86cbd47SDavid Spickett template <typename T>
TestDumpMultiLine(std::vector<T> data,lldb::Format format,size_t num_per_line,llvm::StringRef expected)28544d0ad53SDavid Spickett void TestDumpMultiLine(std::vector<T> data, lldb::Format format,
286a86cbd47SDavid Spickett size_t num_per_line, llvm::StringRef expected) {
287a86cbd47SDavid Spickett size_t sz_bytes = data.size() * sizeof(T);
288a86cbd47SDavid Spickett TestDumpImpl(&data[0], sz_bytes, data.size(), sz_bytes, num_per_line,
289a86cbd47SDavid Spickett 0x80000000, format, expected);
290a86cbd47SDavid Spickett }
291a86cbd47SDavid Spickett
292a86cbd47SDavid Spickett template <typename T>
TestDumpMultiLine(const T * data,size_t num_items,lldb::Format format,size_t num_per_line,llvm::StringRef expected)29344d0ad53SDavid Spickett void TestDumpMultiLine(const T *data, size_t num_items, lldb::Format format,
294a86cbd47SDavid Spickett size_t num_per_line, llvm::StringRef expected) {
295a86cbd47SDavid Spickett TestDumpImpl(data, sizeof(T) * num_items, sizeof(T), num_items, num_per_line,
296a86cbd47SDavid Spickett 0x80000000, format, expected);
297a86cbd47SDavid Spickett }
298a86cbd47SDavid Spickett
TEST(DumpDataExtractorTest,MultiLine)299a86cbd47SDavid Spickett TEST(DumpDataExtractorTest, MultiLine) {
300a86cbd47SDavid Spickett // A vector counts as 1 item regardless of size.
30144d0ad53SDavid Spickett TestDumpMultiLine(std::vector<uint8_t>{0x11},
302a86cbd47SDavid Spickett lldb::Format::eFormatVectorOfUInt8, 1,
303a86cbd47SDavid Spickett "0x80000000: {0x11}");
30444d0ad53SDavid Spickett TestDumpMultiLine(std::vector<uint8_t>{0x11, 0x22},
305a86cbd47SDavid Spickett lldb::Format::eFormatVectorOfUInt8, 1,
306a86cbd47SDavid Spickett "0x80000000: {0x11 0x22}");
307a86cbd47SDavid Spickett
308a86cbd47SDavid Spickett // If you have multiple vectors then that's multiple items.
309a86cbd47SDavid Spickett // Here we say that these 2 bytes are actually 2 1 byte vectors.
310a86cbd47SDavid Spickett const std::vector<uint8_t> vector_data{0x11, 0x22};
31144d0ad53SDavid Spickett TestDumpMultiLine(vector_data.data(), 2, lldb::Format::eFormatVectorOfUInt8,
312a86cbd47SDavid Spickett 1, "0x80000000: {0x11}\n0x80000001: {0x22}");
313a86cbd47SDavid Spickett
314a86cbd47SDavid Spickett // Single value formats can span multiple lines.
315a86cbd47SDavid Spickett const std::vector<uint8_t> bytes{0x11, 0x22, 0x33};
316a86cbd47SDavid Spickett const char *expected_bytes_3_line = "0x80000000: 0x11\n"
317a86cbd47SDavid Spickett "0x80000001: 0x22\n"
318a86cbd47SDavid Spickett "0x80000002: 0x33";
31944d0ad53SDavid Spickett TestDumpMultiLine(bytes.data(), bytes.size(), lldb::Format::eFormatHex, 1,
320a86cbd47SDavid Spickett expected_bytes_3_line);
321a86cbd47SDavid Spickett
322a86cbd47SDavid Spickett // Lines may not have the full number of items.
32344d0ad53SDavid Spickett TestDumpMultiLine(bytes.data(), bytes.size(), lldb::Format::eFormatHex, 4,
324a86cbd47SDavid Spickett "0x80000000: 0x11 0x22 0x33");
325a86cbd47SDavid Spickett const char *expected_bytes_2_line = "0x80000000: 0x11 0x22\n"
326a86cbd47SDavid Spickett "0x80000002: 0x33";
32744d0ad53SDavid Spickett TestDumpMultiLine(bytes.data(), bytes.size(), lldb::Format::eFormatHex, 2,
328a86cbd47SDavid Spickett expected_bytes_2_line);
329a86cbd47SDavid Spickett
330a86cbd47SDavid Spickett // The line address accounts for item sizes other than 1 byte.
331a86cbd47SDavid Spickett const std::vector<uint16_t> shorts{0x1111, 0x2222, 0x3333};
332a86cbd47SDavid Spickett const char *expected_shorts_2_line = "0x80000000: 0x1111 0x2222\n"
333a86cbd47SDavid Spickett "0x80000004: 0x3333";
33444d0ad53SDavid Spickett TestDumpMultiLine(shorts.data(), shorts.size(), lldb::Format::eFormatHex, 2,
335a86cbd47SDavid Spickett expected_shorts_2_line);
336a86cbd47SDavid Spickett
337a86cbd47SDavid Spickett // The ascii column is positioned using the maximum line length.
338a86cbd47SDavid Spickett const std::vector<char> chars{'L', 'L', 'D', 'B'};
339a86cbd47SDavid Spickett const char *expected_chars_2_lines = "0x80000000: 4c 4c 44 LLD\n"
340a86cbd47SDavid Spickett "0x80000003: 42 B";
34144d0ad53SDavid Spickett TestDumpMultiLine(chars.data(), chars.size(),
342a86cbd47SDavid Spickett lldb::Format::eFormatBytesWithASCII, 3,
343a86cbd47SDavid Spickett expected_chars_2_lines);
344a86cbd47SDavid Spickett }
3458da5d111SDavid Spickett
TestDumpWithItemByteSize(size_t item_byte_size,lldb::Format format,llvm::StringRef expected)3468da5d111SDavid Spickett void TestDumpWithItemByteSize(size_t item_byte_size, lldb::Format format,
3478da5d111SDavid Spickett llvm::StringRef expected) {
3488da5d111SDavid Spickett // We won't be reading this data so anything will do.
3498da5d111SDavid Spickett uint8_t dummy = 0;
3508da5d111SDavid Spickett TestDumpImpl(&dummy, 1, item_byte_size, 1, 1, LLDB_INVALID_ADDRESS, format,
3518da5d111SDavid Spickett expected);
3528da5d111SDavid Spickett }
3538da5d111SDavid Spickett
TEST(DumpDataExtractorTest,ItemByteSizeErrors)3548da5d111SDavid Spickett TEST(DumpDataExtractorTest, ItemByteSizeErrors) {
3558da5d111SDavid Spickett TestDumpWithItemByteSize(
3568da5d111SDavid Spickett 16, lldb::Format::eFormatBoolean,
3578da5d111SDavid Spickett "error: unsupported byte size (16) for boolean format");
3588da5d111SDavid Spickett TestDumpWithItemByteSize(21, lldb::Format::eFormatChar,
3598da5d111SDavid Spickett "error: unsupported byte size (21) for char format");
3608da5d111SDavid Spickett TestDumpWithItemByteSize(
3618da5d111SDavid Spickett 18, lldb::Format::eFormatComplexInteger,
3628da5d111SDavid Spickett "error: unsupported byte size (18) for complex integer format");
3638da5d111SDavid Spickett
3648da5d111SDavid Spickett // The code uses sizeof(long double) for these checks. This changes by host
3658da5d111SDavid Spickett // but we know it won't be >16.
3668da5d111SDavid Spickett TestDumpWithItemByteSize(
3678da5d111SDavid Spickett 34, lldb::Format::eFormatComplex,
3688da5d111SDavid Spickett "error: unsupported byte size (34) for complex float format");
3698da5d111SDavid Spickett TestDumpWithItemByteSize(
3708da5d111SDavid Spickett 18, lldb::Format::eFormatFloat,
3718da5d111SDavid Spickett "error: unsupported byte size (18) for float format");
3728da5d111SDavid Spickett
3738da5d111SDavid Spickett // We want sizes to exactly match one of float/double.
3748da5d111SDavid Spickett TestDumpWithItemByteSize(
3758da5d111SDavid Spickett 14, lldb::Format::eFormatComplex,
3768da5d111SDavid Spickett "error: unsupported byte size (14) for complex float format");
3778da5d111SDavid Spickett TestDumpWithItemByteSize(3, lldb::Format::eFormatFloat,
3788da5d111SDavid Spickett "error: unsupported byte size (3) for float format");
3798da5d111SDavid Spickett
3808da5d111SDavid Spickett // We only allow float and double size.
3818da5d111SDavid Spickett TestDumpWithItemByteSize(
3828da5d111SDavid Spickett 1, lldb::Format::eFormatHexFloat,
3838da5d111SDavid Spickett "error: unsupported byte size (1) for hex float format");
3848da5d111SDavid Spickett TestDumpWithItemByteSize(
3858da5d111SDavid Spickett 17, lldb::Format::eFormatHexFloat,
3868da5d111SDavid Spickett "error: unsupported byte size (17) for hex float format");
3878da5d111SDavid Spickett }
388