1 //===-- DataDumpExtractorTest.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 //===----------------------------------------------------------------------===// 8 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" 17 #include <complex> 18 #include <limits> 19 20 using namespace lldb; 21 using namespace lldb_private; 22 23 // This is needed for the tests because they rely on the Target global 24 // properties. 25 class DumpDataExtractorTest : public ::testing::Test { 26 public: 27 void SetUp() override { 28 FileSystem::Initialize(); 29 HostInfo::Initialize(); 30 } 31 void TearDown() override { 32 HostInfo::Terminate(); 33 FileSystem::Terminate(); 34 } 35 }; 36 37 static void TestDumpWithAddress(uint64_t base_addr, size_t item_count, 38 llvm::StringRef expected) { 39 std::vector<uint8_t> data{0x11, 0x22}; 40 StreamString result; 41 DataBufferHeap dumpbuffer(&data[0], data.size()); 42 DataExtractor extractor(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), 43 endian::InlHostByteOrder(), /*addr_size=*/4); 44 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()); 49 } 50 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"); 56 } 57 58 static void TestDumpWithOffset(offset_t start_offset, 59 llvm::StringRef expected) { 60 std::vector<uint8_t> data{0x11, 0x22, 0x33}; 61 StreamString result; 62 DataBufferHeap dumpbuffer(&data[0], data.size()); 63 DataExtractor extractor(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), 64 endian::InlHostByteOrder(), /*addr_size=*/4); 65 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()); 70 } 71 72 TEST_F(DumpDataExtractorTest, StartOffset) { 73 TestDumpWithOffset(0, "0x00000000: 0x11 0x22 0x33"); 74 // The offset applies to the DataExtractor, not the address used when 75 // formatting. 76 TestDumpWithOffset(1, "0x00000000: 0x22 0x33"); 77 // If the offset is outside the DataExtractor's range we do nothing. 78 TestDumpWithOffset(3, ""); 79 } 80 81 TEST_F(DumpDataExtractorTest, NullStream) { 82 // We don't do any work if there is no output stream. 83 uint8_t c = 0x11; 84 StreamString result; 85 DataBufferHeap dumpbuffer(&c, 0); 86 DataExtractor extractor(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), 87 endian::InlHostByteOrder(), /*addr_size=*/4); 88 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()); 93 } 94 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) { 99 StreamString result; 100 DataBufferHeap dumpbuffer(data, data_size); 101 DataExtractor extractor(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), 102 endian::InlHostByteOrder(), 103 /*addr_size=*/4); 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()); 107 } 108 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, 112 expected); 113 } 114 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, 120 format, expected); 121 } 122 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); 129 } 130 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"); 142 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. 149 150 // Test printable characters. 151 TestDump(llvm::StringRef("aardvark"), lldb::Format::eFormatCString, 152 "\"aardvark\""); 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\""); 159 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, 173 "U+0x12345678"); 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"); 179 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}"); 200 201 // See half2float for format details. 202 // Test zeroes. 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}"); 219 220 // quiet/signaling NaNs. 221 TestDump(std::vector<uint16_t>{0xffff, 0xffc0, 0x7fff, 0x7fc0}, 222 lldb::Format::eFormatVectorOfFloat16, "{NaN NaN NaN NaN}"); 223 // +/-Inf. 224 TestDump(std::vector<uint16_t>{0xfc00, 0x7c00}, 225 lldb::Format::eFormatVectorOfFloat16, "{-Inf +Inf}"); 226 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}"); 240 TestDump( 241 std::vector<double>{ 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(), 246 }, 247 lldb::Format::eFormatVectorOfFloat64, "{NaN NaN NaN NaN}"); 248 249 // Not sure we can rely on having uint128_t everywhere so emulate with 250 // uint64_t. 251 TestDump( 252 std::vector<uint64_t>{0x1, 0x1111222233334444, 0xaaaabbbbccccdddd, 0x0}, 253 lldb::Format::eFormatVectorOfUInt128, 254 "{0x11112222333344440000000000000001 " 255 "0x0000000000000000aaaabbbbccccdddd}"); 256 257 TestDump(std::vector<int>{2, 4}, lldb::Format::eFormatComplexInteger, 258 "2 + 4i"); 259 260 // Without an execution context this just prints the pointer on its own. 261 TestDump<uint32_t>(0x11223344, lldb::Format::eFormatAddressInfo, 262 "0x11223344"); 263 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. 268 269 // Can't disassemble without an execution context. 270 TestDump<uint32_t>(0xcafef00d, lldb::Format::eFormatInstruction, 271 "invalid target"); 272 273 // Has no special handling, intended for use elsewhere. 274 TestDump<int>(99, lldb::Format::eFormatVoid, "0x00000063"); 275 } 276 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', '#'}; 282 StreamString result; 283 DataBufferHeap dumpbuffer(&data[0], data.size()); 284 DataExtractor extractor(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), 285 endian::InlHostByteOrder(), /*addr_size=*/4); 286 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()); 292 293 result.Clear(); 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" 299 "0x00000002: #"; 300 ASSERT_EQ(expected, result.GetString()); 301 } 302 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); 309 } 310 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); 316 } 317 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}"); 326 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}"); 332 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" 336 "0x80000001: 0x22\n" 337 "0x80000002: 0x33"; 338 TestDumpMultiLine(bytes.data(), bytes.size(), lldb::Format::eFormatHex, 1, 339 expected_bytes_3_line); 340 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" 345 "0x80000002: 0x33"; 346 TestDumpMultiLine(bytes.data(), bytes.size(), lldb::Format::eFormatHex, 2, 347 expected_bytes_2_line); 348 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); 355 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" 359 "0x80000003: 42 B"; 360 TestDumpMultiLine(chars.data(), chars.size(), 361 lldb::Format::eFormatBytesWithASCII, 3, 362 expected_chars_2_lines); 363 } 364 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. 368 uint8_t dummy = 0; 369 TestDumpImpl(&dummy, 1, item_byte_size, 1, 1, LLDB_INVALID_ADDRESS, format, 370 expected); 371 } 372 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"); 382 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"); 391 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"); 398 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"); 406 } 407