1 //===-- DataDumpExtractorTest.cpp -----------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Core/DumpDataExtractor.h"
10 #include "lldb/Host/FileSystem.h"
11 #include "lldb/Host/HostInfo.h"
12 #include "lldb/Utility/DataBufferHeap.h"
13 #include "lldb/Utility/DataExtractor.h"
14 #include "lldb/Utility/Endian.h"
15 #include "lldb/Utility/StreamString.h"
16 #include "gtest/gtest.h"
21 using namespace lldb_private
;
23 // This is needed for the tests because they rely on the Target global
25 class DumpDataExtractorTest
: public ::testing::Test
{
27 void SetUp() override
{
28 FileSystem::Initialize();
29 HostInfo::Initialize();
31 void TearDown() override
{
32 HostInfo::Terminate();
33 FileSystem::Terminate();
37 static void TestDumpWithAddress(uint64_t base_addr
, size_t item_count
,
38 llvm::StringRef expected
) {
39 std::vector
<uint8_t> data
{0x11, 0x22};
41 DataBufferHeap
dumpbuffer(&data
[0], data
.size());
42 DataExtractor
extractor(dumpbuffer
.GetBytes(), dumpbuffer
.GetByteSize(),
43 endian::InlHostByteOrder(), /*addr_size=*/4);
45 DumpDataExtractor(extractor
, &result
, 0, lldb::Format::eFormatHex
,
46 /*item_byte_size=*/1, item_count
,
47 /*num_per_line=*/1, base_addr
, 0, 0);
48 ASSERT_EQ(expected
, result
.GetString());
51 TEST_F(DumpDataExtractorTest
, BaseAddress
) {
52 TestDumpWithAddress(0x12341234, 1, "0x12341234: 0x11");
53 TestDumpWithAddress(LLDB_INVALID_ADDRESS
, 1, "0x11");
54 TestDumpWithAddress(0x12341234, 2, "0x12341234: 0x11\n0x12341235: 0x22");
55 TestDumpWithAddress(LLDB_INVALID_ADDRESS
, 2, "0x11\n0x22");
58 static void TestDumpWithOffset(offset_t start_offset
,
59 llvm::StringRef expected
) {
60 std::vector
<uint8_t> data
{0x11, 0x22, 0x33};
62 DataBufferHeap
dumpbuffer(&data
[0], data
.size());
63 DataExtractor
extractor(dumpbuffer
.GetBytes(), dumpbuffer
.GetByteSize(),
64 endian::InlHostByteOrder(), /*addr_size=*/4);
66 DumpDataExtractor(extractor
, &result
, start_offset
, lldb::Format::eFormatHex
,
67 /*item_byte_size=*/1, /*item_count=*/data
.size(),
68 /*num_per_line=*/data
.size(), /*base_addr=*/0, 0, 0);
69 ASSERT_EQ(expected
, result
.GetString());
72 TEST_F(DumpDataExtractorTest
, StartOffset
) {
73 TestDumpWithOffset(0, "0x00000000: 0x11 0x22 0x33");
74 // The offset applies to the DataExtractor, not the address used when
76 TestDumpWithOffset(1, "0x00000000: 0x22 0x33");
77 // If the offset is outside the DataExtractor's range we do nothing.
78 TestDumpWithOffset(3, "");
81 TEST_F(DumpDataExtractorTest
, NullStream
) {
82 // We don't do any work if there is no output stream.
85 DataBufferHeap
dumpbuffer(&c
, 0);
86 DataExtractor
extractor(dumpbuffer
.GetBytes(), dumpbuffer
.GetByteSize(),
87 endian::InlHostByteOrder(), /*addr_size=*/4);
89 DumpDataExtractor(extractor
, nullptr, 0, lldb::Format::eFormatHex
,
90 /*item_byte_size=*/1, /*item_count=*/1,
91 /*num_per_line=*/1, /*base_addr=*/0, 0, 0);
92 ASSERT_EQ("", result
.GetString());
95 static void TestDumpImpl(const void *data
, size_t data_size
,
96 size_t item_byte_size
, size_t item_count
,
97 size_t num_per_line
, uint64_t base_addr
,
98 lldb::Format format
, llvm::StringRef expected
) {
100 DataBufferHeap
dumpbuffer(data
, data_size
);
101 DataExtractor
extractor(dumpbuffer
.GetBytes(), dumpbuffer
.GetByteSize(),
102 endian::InlHostByteOrder(),
104 DumpDataExtractor(extractor
, &result
, 0, format
, item_byte_size
, item_count
,
105 num_per_line
, base_addr
, 0, 0);
106 ASSERT_EQ(expected
, result
.GetString());
109 template <typename T
>
110 static void TestDump(T data
, lldb::Format format
, llvm::StringRef expected
) {
111 TestDumpImpl(&data
, sizeof(T
), sizeof(T
), 1, 1, LLDB_INVALID_ADDRESS
, format
,
115 static void TestDump(llvm::StringRef str
, lldb::Format format
,
116 llvm::StringRef expected
) {
117 TestDumpImpl(str
.bytes_begin(),
118 // +1 to include the NULL char as the last byte
119 str
.size() + 1, str
.size() + 1, 1, 1, LLDB_INVALID_ADDRESS
,
123 template <typename T
>
124 static void TestDump(const std::vector
<T
> data
, lldb::Format format
,
125 llvm::StringRef expected
) {
126 size_t sz_bytes
= data
.size() * sizeof(T
);
127 TestDumpImpl(&data
[0], sz_bytes
, sz_bytes
, data
.size(), 1,
128 LLDB_INVALID_ADDRESS
, format
, expected
);
131 TEST_F(DumpDataExtractorTest
, Formats
) {
132 TestDump
<uint8_t>(1, lldb::eFormatDefault
, "0x01");
133 TestDump
<uint8_t>(1, lldb::eFormatBoolean
, "true");
134 TestDump
<uint8_t>(0xAA, lldb::eFormatBinary
, "0b10101010");
135 TestDump
<uint8_t>(1, lldb::eFormatBytes
, "01");
136 TestDump
<uint8_t>(1, lldb::eFormatBytesWithASCII
, "01 .");
137 TestDump('?', lldb::eFormatChar
, "'?'");
138 TestDump('\x1A', lldb::eFormatCharPrintable
, ".");
139 TestDump('#', lldb::eFormatCharPrintable
, "#");
140 TestDump(std::complex<float>(1.2, 3.4), lldb::eFormatComplex
, "1.2 + 3.4i");
141 TestDump(std::complex<double>(4.5, 6.7), lldb::eFormatComplex
, "4.5 + 6.7i");
143 // long double is not tested here because for some platforms we treat it as 10
144 // bytes when the compiler allocates 16 bytes of space for it. (see
145 // DataExtractor::GetLongDouble) Meaning that when we extract the second one,
146 // it gets the wrong value (it's 6 bytes off). You could manually construct a
147 // set of bytes to match the 10 byte format but then if the test runs on a
148 // machine where we don't use 10 it'll break.
150 // Test printable characters.
151 TestDump(llvm::StringRef("aardvark"), lldb::Format::eFormatCString
,
153 // Test unprintable characters.
154 TestDump(llvm::StringRef("\xcf\xfa\xed\xfe\f"), lldb::Format::eFormatCString
,
155 "\"\\xcf\\xfa\\xed\\xfe\\f\"");
156 // Test a mix of printable and unprintable characters.
157 TestDump(llvm::StringRef("\xcf\xfa\ffoo"), lldb::Format::eFormatCString
,
158 "\"\\xcf\\xfa\\ffoo\"");
160 TestDump
<uint16_t>(99, lldb::Format::eFormatDecimal
, "99");
161 // Just prints as a signed integer.
162 TestDump(-1, lldb::Format::eFormatEnum
, "-1");
163 TestDump(0xcafef00d, lldb::Format::eFormatHex
, "0xcafef00d");
164 TestDump(0xcafef00d, lldb::Format::eFormatHexUppercase
, "0xCAFEF00D");
165 TestDump(0.456, lldb::Format::eFormatFloat
, "0.45600000000000002");
166 TestDump(9, lldb::Format::eFormatOctal
, "011");
167 // Chars packed into an integer.
168 TestDump
<uint32_t>(0x4C4C4442, lldb::Format::eFormatOSType
, "'LLDB'");
169 // Unicode8 doesn't have a specific formatter.
170 TestDump
<uint8_t>(0x34, lldb::Format::eFormatUnicode8
, "0x34");
171 TestDump
<uint16_t>(0x1122, lldb::Format::eFormatUnicode16
, "U+1122");
172 TestDump
<uint32_t>(0x12345678, lldb::Format::eFormatUnicode32
,
174 TestDump
<unsigned int>(654321, lldb::Format::eFormatUnsigned
, "654321");
175 // This pointer is printed based on the size of uint64_t, so the test is the
176 // same for 32/64 bit host.
177 TestDump
<uint64_t>(0x4444555566667777, lldb::Format::eFormatPointer
,
178 "0x4444555566667777");
180 TestDump(std::vector
<char>{'A', '\x01', 'C'},
181 lldb::Format::eFormatVectorOfChar
, "{A\\x01C}");
182 TestDump(std::vector
<int8_t>{0, -1, std::numeric_limits
<int8_t>::max()},
183 lldb::Format::eFormatVectorOfSInt8
, "{0 -1 127}");
184 TestDump(std::vector
<uint8_t>{12, 0xFF, 34},
185 lldb::Format::eFormatVectorOfUInt8
, "{0x0c 0xff 0x22}");
186 TestDump(std::vector
<int16_t>{-1, 1234, std::numeric_limits
<int16_t>::max()},
187 lldb::Format::eFormatVectorOfSInt16
, "{-1 1234 32767}");
188 TestDump(std::vector
<uint16_t>{0xffff, 0xabcd, 0x1234},
189 lldb::Format::eFormatVectorOfUInt16
, "{0xffff 0xabcd 0x1234}");
190 TestDump(std::vector
<int32_t>{0, -1, std::numeric_limits
<int32_t>::max()},
191 lldb::Format::eFormatVectorOfSInt32
, "{0 -1 2147483647}");
192 TestDump(std::vector
<uint32_t>{0, 0xffffffff, 0x1234abcd},
193 lldb::Format::eFormatVectorOfUInt32
,
194 "{0x00000000 0xffffffff 0x1234abcd}");
195 TestDump(std::vector
<int64_t>{0, -1, std::numeric_limits
<int64_t>::max()},
196 lldb::Format::eFormatVectorOfSInt64
, "{0 -1 9223372036854775807}");
197 TestDump(std::vector
<uint64_t>{0, 0xaaaabbbbccccdddd},
198 lldb::Format::eFormatVectorOfUInt64
,
199 "{0x0000000000000000 0xaaaabbbbccccdddd}");
201 // See half2float for format details.
203 TestDump(std::vector
<uint16_t>{0x0000, 0x8000},
204 lldb::Format::eFormatVectorOfFloat16
, "{0 -0}");
205 // Some subnormal numbers.
206 TestDump(std::vector
<uint16_t>{0x0001, 0x8001},
207 lldb::Format::eFormatVectorOfFloat16
, "{5.9605E-8 -5.9605E-8}");
208 // A full mantisse and empty expontent.
209 TestDump(std::vector
<uint16_t>{0x83ff, 0x03ff},
210 lldb::Format::eFormatVectorOfFloat16
, "{-6.0976E-5 6.0976E-5}");
211 // Some normal numbers.
212 TestDump(std::vector
<uint16_t>{0b0100001001001000},
213 lldb::Format::eFormatVectorOfFloat16
, "{3.1406}");
214 // Largest and smallest normal number.
215 TestDump(std::vector
<uint16_t>{0x0400, 0x7bff},
216 lldb::Format::eFormatVectorOfFloat16
, "{6.1035E-5 65504}");
217 TestDump(std::vector
<uint16_t>{0xabcd, 0x1234},
218 lldb::Format::eFormatVectorOfFloat16
, "{-0.060944 7.5722E-4}");
220 // quiet/signaling NaNs.
221 TestDump(std::vector
<uint16_t>{0xffff, 0xffc0, 0x7fff, 0x7fc0},
222 lldb::Format::eFormatVectorOfFloat16
, "{NaN NaN NaN NaN}");
224 TestDump(std::vector
<uint16_t>{0xfc00, 0x7c00},
225 lldb::Format::eFormatVectorOfFloat16
, "{-Inf +Inf}");
227 TestDump(std::vector
<float>{std::numeric_limits
<float>::min(),
228 std::numeric_limits
<float>::max()},
229 lldb::Format::eFormatVectorOfFloat32
,
230 "{1.17549435E-38 3.40282347E+38}");
231 TestDump(std::vector
<float>{std::numeric_limits
<float>::quiet_NaN(),
232 std::numeric_limits
<float>::signaling_NaN(),
233 -std::numeric_limits
<float>::quiet_NaN(),
234 -std::numeric_limits
<float>::signaling_NaN()},
235 lldb::Format::eFormatVectorOfFloat32
, "{NaN NaN NaN NaN}");
236 TestDump(std::vector
<double>{std::numeric_limits
<double>::min(),
237 std::numeric_limits
<double>::max()},
238 lldb::Format::eFormatVectorOfFloat64
,
239 "{2.2250738585072014E-308 1.7976931348623157E+308}");
242 std::numeric_limits
<double>::quiet_NaN(),
243 std::numeric_limits
<double>::signaling_NaN(),
244 -std::numeric_limits
<double>::quiet_NaN(),
245 -std::numeric_limits
<double>::signaling_NaN(),
247 lldb::Format::eFormatVectorOfFloat64
, "{NaN NaN NaN NaN}");
249 // Not sure we can rely on having uint128_t everywhere so emulate with
252 std::vector
<uint64_t>{0x1, 0x1111222233334444, 0xaaaabbbbccccdddd, 0x0},
253 lldb::Format::eFormatVectorOfUInt128
,
254 "{0x11112222333344440000000000000001 "
255 "0x0000000000000000aaaabbbbccccdddd}");
257 TestDump(std::vector
<int>{2, 4}, lldb::Format::eFormatComplexInteger
,
260 // Without an execution context this just prints the pointer on its own.
261 TestDump
<uint32_t>(0x11223344, lldb::Format::eFormatAddressInfo
,
264 // Input not written in hex form because that requires C++17.
265 TestDump
<float>(10, lldb::Format::eFormatHexFloat
, "0x1.4p3");
266 TestDump
<double>(10, lldb::Format::eFormatHexFloat
, "0x1.4p3");
267 // long double not supported, see ItemByteSizeErrors.
269 // Can't disassemble without an execution context.
270 TestDump
<uint32_t>(0xcafef00d, lldb::Format::eFormatInstruction
,
273 // Has no special handling, intended for use elsewhere.
274 TestDump
<int>(99, lldb::Format::eFormatVoid
, "0x00000063");
277 TEST_F(DumpDataExtractorTest
, FormatCharArray
) {
278 // Unlike the other formats, charArray isn't 1 array of N chars.
279 // It must be passed as N chars of 1 byte each.
280 // (eFormatVectorOfChar does this swap for you)
281 std::vector
<char> data
{'A', '\x01', '#'};
283 DataBufferHeap
dumpbuffer(&data
[0], data
.size());
284 DataExtractor
extractor(dumpbuffer
.GetBytes(), dumpbuffer
.GetByteSize(),
285 endian::InlHostByteOrder(), /*addr_size=*/4);
287 DumpDataExtractor(extractor
, &result
, 0, lldb::Format::eFormatCharArray
,
288 /*item_byte_size=*/1,
289 /*item_count=*/data
.size(),
290 /*num_per_line=*/data
.size(), 0, 0, 0);
291 ASSERT_EQ("0x00000000: A\\x01#", result
.GetString());
294 DumpDataExtractor(extractor
, &result
, 0, lldb::Format::eFormatCharArray
, 1,
295 data
.size(), 1, 0, 0, 0);
296 // ASSERT macro thinks the split strings are multiple arguments so make a var.
297 const char *expected
= "0x00000000: A\n"
298 "0x00000001: \\x01\n"
300 ASSERT_EQ(expected
, result
.GetString());
303 template <typename T
>
304 void TestDumpMultiLine(std::vector
<T
> data
, lldb::Format format
,
305 size_t num_per_line
, llvm::StringRef expected
) {
306 size_t sz_bytes
= data
.size() * sizeof(T
);
307 TestDumpImpl(&data
[0], sz_bytes
, data
.size(), sz_bytes
, num_per_line
,
308 0x80000000, format
, expected
);
311 template <typename T
>
312 void TestDumpMultiLine(const T
*data
, size_t num_items
, lldb::Format format
,
313 size_t num_per_line
, llvm::StringRef expected
) {
314 TestDumpImpl(data
, sizeof(T
) * num_items
, sizeof(T
), num_items
, num_per_line
,
315 0x80000000, format
, expected
);
318 TEST_F(DumpDataExtractorTest
, MultiLine
) {
319 // A vector counts as 1 item regardless of size.
320 TestDumpMultiLine(std::vector
<uint8_t>{0x11},
321 lldb::Format::eFormatVectorOfUInt8
, 1,
322 "0x80000000: {0x11}");
323 TestDumpMultiLine(std::vector
<uint8_t>{0x11, 0x22},
324 lldb::Format::eFormatVectorOfUInt8
, 1,
325 "0x80000000: {0x11 0x22}");
327 // If you have multiple vectors then that's multiple items.
328 // Here we say that these 2 bytes are actually 2 1 byte vectors.
329 const std::vector
<uint8_t> vector_data
{0x11, 0x22};
330 TestDumpMultiLine(vector_data
.data(), 2, lldb::Format::eFormatVectorOfUInt8
,
331 1, "0x80000000: {0x11}\n0x80000001: {0x22}");
333 // Single value formats can span multiple lines.
334 const std::vector
<uint8_t> bytes
{0x11, 0x22, 0x33};
335 const char *expected_bytes_3_line
= "0x80000000: 0x11\n"
338 TestDumpMultiLine(bytes
.data(), bytes
.size(), lldb::Format::eFormatHex
, 1,
339 expected_bytes_3_line
);
341 // Lines may not have the full number of items.
342 TestDumpMultiLine(bytes
.data(), bytes
.size(), lldb::Format::eFormatHex
, 4,
343 "0x80000000: 0x11 0x22 0x33");
344 const char *expected_bytes_2_line
= "0x80000000: 0x11 0x22\n"
346 TestDumpMultiLine(bytes
.data(), bytes
.size(), lldb::Format::eFormatHex
, 2,
347 expected_bytes_2_line
);
349 // The line address accounts for item sizes other than 1 byte.
350 const std::vector
<uint16_t> shorts
{0x1111, 0x2222, 0x3333};
351 const char *expected_shorts_2_line
= "0x80000000: 0x1111 0x2222\n"
352 "0x80000004: 0x3333";
353 TestDumpMultiLine(shorts
.data(), shorts
.size(), lldb::Format::eFormatHex
, 2,
354 expected_shorts_2_line
);
356 // The ascii column is positioned using the maximum line length.
357 const std::vector
<char> chars
{'L', 'L', 'D', 'B'};
358 const char *expected_chars_2_lines
= "0x80000000: 4c 4c 44 LLD\n"
360 TestDumpMultiLine(chars
.data(), chars
.size(),
361 lldb::Format::eFormatBytesWithASCII
, 3,
362 expected_chars_2_lines
);
365 void TestDumpWithItemByteSize(size_t item_byte_size
, lldb::Format format
,
366 llvm::StringRef expected
) {
367 // We won't be reading this data so anything will do.
369 TestDumpImpl(&dummy
, 1, item_byte_size
, 1, 1, LLDB_INVALID_ADDRESS
, format
,
373 TEST_F(DumpDataExtractorTest
, ItemByteSizeErrors
) {
374 TestDumpWithItemByteSize(
375 16, lldb::Format::eFormatBoolean
,
376 "error: unsupported byte size (16) for boolean format");
377 TestDumpWithItemByteSize(21, lldb::Format::eFormatChar
,
378 "error: unsupported byte size (21) for char format");
379 TestDumpWithItemByteSize(
380 18, lldb::Format::eFormatComplexInteger
,
381 "error: unsupported byte size (18) for complex integer format");
383 // The code uses sizeof(long double) for these checks. This changes by host
384 // but we know it won't be >16.
385 TestDumpWithItemByteSize(
386 34, lldb::Format::eFormatComplex
,
387 "error: unsupported byte size (34) for complex float format");
388 TestDumpWithItemByteSize(
389 18, lldb::Format::eFormatFloat
,
390 "error: unsupported byte size (18) for float format");
392 // We want sizes to exactly match one of float/double.
393 TestDumpWithItemByteSize(
394 14, lldb::Format::eFormatComplex
,
395 "error: unsupported byte size (14) for complex float format");
396 TestDumpWithItemByteSize(3, lldb::Format::eFormatFloat
,
397 "error: unsupported byte size (3) for float format");
399 // We only allow float and double size.
400 TestDumpWithItemByteSize(
401 1, lldb::Format::eFormatHexFloat
,
402 "error: unsupported byte size (1) for hex float format");
403 TestDumpWithItemByteSize(
404 17, lldb::Format::eFormatHexFloat
,
405 "error: unsupported byte size (17) for hex float format");