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