brintos

brintos / llvm-project-archived public Read only

0
0
Text · 21.2 KiB · 09f3edb Raw
584 lines · cpp
1//===----------------------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Utility/VirtualDataExtractor.h"10#include "lldb/Utility/DataBufferHeap.h"11#include "gtest/gtest.h"12 13using namespace lldb_private;14using namespace lldb;15 16using Table = VirtualDataExtractor::LookupTable;17using Entry = Table::Entry;18 19TEST(VirtualDataExtractorTest, BasicConstruction) {20  uint8_t buffer[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};21 22  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(23      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 8, 0)});24 25  EXPECT_EQ(extractor->GetByteSize(), 8U);26}27 28TEST(VirtualDataExtractorTest, GetDataAtVirtualOffset) {29  uint8_t buffer[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};30 31  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(32      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 8, 0)});33 34  offset_t virtual_offset = 0x1000;35  const void *data = extractor->GetData(&virtual_offset, 4);36 37  ASSERT_NE(data, nullptr);38  EXPECT_EQ(virtual_offset, 0x1004U);39  EXPECT_EQ(memcmp(data, buffer, 4), 0);40}41 42TEST(VirtualDataExtractorTest, GetDataAtVirtualOffsetInvalid) {43  uint8_t buffer[] = {0x01, 0x02, 0x03, 0x04};44 45  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(46      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 4, 0)});47 48  // Try to read from an invalid virtual address.49  offset_t virtual_offset = 0x2000;50  const void *data = extractor->GetData(&virtual_offset, 4);51 52  EXPECT_EQ(data, nullptr);53}54 55TEST(VirtualDataExtractorTest, GetU8AtVirtualOffset) {56  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78};57 58  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(59      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 4, 0)});60 61  offset_t virtual_offset = 0x1000;62  EXPECT_EQ(extractor->GetU8(&virtual_offset), 0x12U);63  EXPECT_EQ(virtual_offset, 0x1001U);64 65  EXPECT_EQ(extractor->GetU8(&virtual_offset), 0x34U);66  EXPECT_EQ(virtual_offset, 0x1002U);67}68 69TEST(VirtualDataExtractorTest, GetU16AtVirtualOffset) {70  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78};71 72  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(73      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 4, 0)});74 75  offset_t virtual_offset = 0x1000;76  EXPECT_EQ(extractor->GetU16(&virtual_offset), 0x3412U);77  EXPECT_EQ(virtual_offset, 0x1002U);78 79  EXPECT_EQ(extractor->GetU16(&virtual_offset), 0x7856U);80  EXPECT_EQ(virtual_offset, 0x1004U);81}82 83TEST(VirtualDataExtractorTest, GetU32AtVirtualOffset) {84  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};85 86  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(87      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 8, 0)});88 89  offset_t virtual_offset = 0x1000;90  EXPECT_EQ(extractor->GetU32(&virtual_offset), 0x78563412U);91  EXPECT_EQ(virtual_offset, 0x1004U);92 93  EXPECT_EQ(extractor->GetU32(&virtual_offset), 0xF0DEBC9AU);94  EXPECT_EQ(virtual_offset, 0x1008U);95}96 97TEST(VirtualDataExtractorTest, GetU64AtVirtualOffset) {98  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};99 100  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(101      buffer, sizeof(buffer), eByteOrderLittle, 8, Table{Entry(0x1000, 8, 0)});102 103  offset_t virtual_offset = 0x1000;104  EXPECT_EQ(extractor->GetU64(&virtual_offset), 0xF0DEBC9A78563412ULL);105  EXPECT_EQ(virtual_offset, 0x1008U);106}107 108TEST(VirtualDataExtractorTest, GetAddressAtVirtualOffset) {109  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78};110 111  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(112      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 4, 0)});113 114  offset_t virtual_offset = 0x1000;115  EXPECT_EQ(extractor->GetAddress(&virtual_offset), 0x78563412U);116  EXPECT_EQ(virtual_offset, 0x1004U);117}118 119TEST(VirtualDataExtractorTest, BigEndian) {120  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78};121 122  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(123      buffer, sizeof(buffer), eByteOrderBig, 4, Table{Entry(0x1000, 4, 0)});124 125  offset_t virtual_offset = 0x1000;126  EXPECT_EQ(extractor->GetU16(&virtual_offset), 0x1234U);127  EXPECT_EQ(virtual_offset, 0x1002U);128 129  EXPECT_EQ(extractor->GetU16(&virtual_offset), 0x5678U);130  EXPECT_EQ(virtual_offset, 0x1004U);131}132 133TEST(VirtualDataExtractorTest, MultipleEntries) {134  // Create a buffer with distinct patterns for each section.135  uint8_t buffer[] = {136      0x01, 0x02, 0x03, 0x04, // Physical offset 0-3.137      0x11, 0x12, 0x13, 0x14, // Physical offset 4-7.138      0x21, 0x22, 0x23, 0x24  // Physical offset 8-11.139  };140 141  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(142      buffer, sizeof(buffer), eByteOrderLittle, 4,143      Table{Entry(0x1000, 4, 0),   // Virt 0x1000-0x1004144            Entry(0x2000, 4, 4),   // Virt 0x2000-0x2004145            Entry(0x3000, 4, 8)}); // Virt 0x3000-0x3004146 147  // Test reading from first virtual range.148  offset_t virtual_offset = 0x1000;149  EXPECT_EQ(extractor->GetU8(&virtual_offset), 0x01U);150 151  // Test reading from second virtual range.152  virtual_offset = 0x2000;153  EXPECT_EQ(extractor->GetU8(&virtual_offset), 0x11U);154 155  // Test reading from third virtual range.156  virtual_offset = 0x3000;157  EXPECT_EQ(extractor->GetU8(&virtual_offset), 0x21U);158}159 160TEST(VirtualDataExtractorTest, NonContiguousVirtualAddresses) {161  uint8_t buffer[] = {0xAA, 0xBB, 0xCC, 0xDD};162 163  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(164      buffer, sizeof(buffer), eByteOrderLittle, 4,165      Table{Entry(0x1000, 2, 0),   // Virt 0x1000-0x1002166            Entry(0x5000, 2, 2)}); // Virt 0x5000-0x5002167 168  // Test reading from first virtual range.169  offset_t virtual_offset = 0x1000;170  EXPECT_EQ(extractor->GetU16(&virtual_offset), 0xBBAAU);171 172  // Test reading from second virtual range (non-contiguous).173  virtual_offset = 0x5000;174  EXPECT_EQ(extractor->GetU16(&virtual_offset), 0xDDCCU);175 176  // Test that gap between ranges is invalid.177  virtual_offset = 0x3000;178  EXPECT_EQ(extractor->GetU8(&virtual_offset), 0U);179}180 181TEST(VirtualDataExtractorTest, SharedDataBuffer) {182  // Test with shared_ptr to DataBuffer.183  uint8_t buffer[] = {0x01, 0x02, 0x03, 0x04};184  auto data_sp = std::make_shared<DataBufferHeap>(buffer, sizeof(buffer));185 186  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(187      data_sp, eByteOrderLittle, 4, Table{Entry(0x1000, 4, 0)});188 189  offset_t virtual_offset = 0x1000;190  EXPECT_EQ(extractor->GetU32(&virtual_offset), 0x04030201U);191}192 193TEST(VirtualDataExtractorTest, NullPointerHandling) {194  uint8_t buffer[] = {0x01, 0x02, 0x03, 0x04};195 196  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(197      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 4, 0)});198 199  // Test that passing nullptr returns default values.200  EXPECT_EQ(extractor->GetU8(nullptr), 0U);201  EXPECT_EQ(extractor->GetU16(nullptr), 0U);202  EXPECT_EQ(extractor->GetU32(nullptr), 0U);203  EXPECT_EQ(extractor->GetU64(nullptr), 0U);204  EXPECT_EQ(extractor->GetAddress(nullptr), 0U);205  EXPECT_EQ(extractor->GetData(nullptr, 4), nullptr);206}207 208TEST(VirtualDataExtractorTest, OffsetMapping) {209  // Test that virtual to physical offset mapping works correctly.210  uint8_t buffer[] = {0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD};211 212  // Map virtual address 0x1000 to physical offset 4 (skipping first 4 bytes).213  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(214      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 4, 4)});215 216  offset_t virtual_offset = 0x1000;217  // Should read from physical offset 4, not 0.218  EXPECT_EQ(extractor->GetU32(&virtual_offset), 0xDDCCBBAAU);219}220 221TEST(VirtualDataExtractorTest, GetU8Unchecked) {222  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78};223 224  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(225      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 4, 0)});226 227  offset_t virtual_offset = 0x1000;228  EXPECT_EQ(extractor->GetU8_unchecked(&virtual_offset), 0x12U);229  EXPECT_EQ(virtual_offset, 0x1001U);230 231  EXPECT_EQ(extractor->GetU8_unchecked(&virtual_offset), 0x34U);232  EXPECT_EQ(virtual_offset, 0x1002U);233}234 235TEST(VirtualDataExtractorTest, GetU16Unchecked) {236  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78};237 238  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(239      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 4, 0)});240 241  offset_t virtual_offset = 0x1000;242  EXPECT_EQ(extractor->GetU16_unchecked(&virtual_offset), 0x3412U);243  EXPECT_EQ(virtual_offset, 0x1002U);244 245  EXPECT_EQ(extractor->GetU16_unchecked(&virtual_offset), 0x7856U);246  EXPECT_EQ(virtual_offset, 0x1004U);247}248 249TEST(VirtualDataExtractorTest, GetU32Unchecked) {250  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};251 252  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(253      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 8, 0)});254 255  offset_t virtual_offset = 0x1000;256  EXPECT_EQ(extractor->GetU32_unchecked(&virtual_offset), 0x78563412U);257  EXPECT_EQ(virtual_offset, 0x1004U);258 259  EXPECT_EQ(extractor->GetU32_unchecked(&virtual_offset), 0xF0DEBC9AU);260  EXPECT_EQ(virtual_offset, 0x1008U);261}262 263TEST(VirtualDataExtractorTest, GetU64Unchecked) {264  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};265 266  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(267      buffer, sizeof(buffer), eByteOrderLittle, 8, Table{Entry(0x1000, 8, 0)});268 269  offset_t virtual_offset = 0x1000;270  EXPECT_EQ(extractor->GetU64_unchecked(&virtual_offset),271            0xF0DEBC9A78563412ULL);272  EXPECT_EQ(virtual_offset, 0x1008U);273}274 275TEST(VirtualDataExtractorTest, GetMaxU64Unchecked) {276  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};277 278  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(279      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 8, 0)});280 281  // Test various byte sizes.282  offset_t virtual_offset = 0x1000;283  EXPECT_EQ(extractor->GetMaxU64_unchecked(&virtual_offset, 1), 0x12U);284  EXPECT_EQ(virtual_offset, 0x1001U);285 286  virtual_offset = 0x1000;287  EXPECT_EQ(extractor->GetMaxU64_unchecked(&virtual_offset, 2), 0x3412U);288  EXPECT_EQ(virtual_offset, 0x1002U);289 290  virtual_offset = 0x1000;291  EXPECT_EQ(extractor->GetMaxU64_unchecked(&virtual_offset, 4), 0x78563412U);292  EXPECT_EQ(virtual_offset, 0x1004U);293 294  virtual_offset = 0x1000;295  EXPECT_EQ(extractor->GetMaxU64_unchecked(&virtual_offset, 8),296            0xF0DEBC9A78563412ULL);297  EXPECT_EQ(virtual_offset, 0x1008U);298}299 300TEST(VirtualDataExtractorTest, GetAddressUnchecked) {301  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78};302 303  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(304      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 4, 0)});305 306  offset_t virtual_offset = 0x1000;307  EXPECT_EQ(extractor->GetAddress_unchecked(&virtual_offset), 0x78563412U);308  EXPECT_EQ(virtual_offset, 0x1004U);309}310 311TEST(VirtualDataExtractorTest, UncheckedWithBigEndian) {312  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78};313 314  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(315      buffer, sizeof(buffer), eByteOrderBig, 4, Table{Entry(0x1000, 4, 0)});316 317  offset_t virtual_offset = 0x1000;318  EXPECT_EQ(extractor->GetU16_unchecked(&virtual_offset), 0x1234U);319  EXPECT_EQ(virtual_offset, 0x1002U);320 321  EXPECT_EQ(extractor->GetU16_unchecked(&virtual_offset), 0x5678U);322  EXPECT_EQ(virtual_offset, 0x1004U);323}324 325TEST(VirtualDataExtractorTest, GetCStr) {326  // Create buffer with null-terminated strings.327  uint8_t buffer[] = {'H', 'e', 'l', 'l',  'o', '\0', 'W', 'o',328                      'r', 'l', 'd', '\0', 'F', 'o',  'o', '\0'};329 330  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(331      buffer, sizeof(buffer), eByteOrderLittle, 4,332      Table{Entry(0x1000, 6, 0), Entry(0x2000, 12, 6)});333 334  // Test reading first string.335  offset_t virtual_offset = 0x1000;336  const char *str1 = extractor->GetCStr(&virtual_offset);337  ASSERT_NE(str1, nullptr);338  EXPECT_STREQ(str1, "Hello");339  EXPECT_EQ(virtual_offset, 0x1006U); // After "Hello\0"340 341  // Test reading second string.342  virtual_offset = 0x2000;343  const char *str2 = extractor->GetCStr(&virtual_offset);344  ASSERT_NE(str2, nullptr);345  EXPECT_STREQ(str2, "World");346  EXPECT_EQ(virtual_offset, 0x2006U); // After "World\0"347}348 349TEST(VirtualDataExtractorTest, GetFloat) {350  // Create buffer with float value (IEEE 754 single precision).351  // 3.14159f in little endian: 0xDB 0x0F 0x49 0x40352  uint8_t buffer[] = {0xDB, 0x0F, 0x49, 0x40};353 354  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(355      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 4, 0)});356 357  offset_t virtual_offset = 0x1000;358  float value = extractor->GetFloat(&virtual_offset);359  EXPECT_NEAR(value, 3.14159f, 0.00001f);360  EXPECT_EQ(virtual_offset, 0x1004U);361}362 363TEST(VirtualDataExtractorTest, GetDouble) {364  // Create buffer with double value (IEEE 754 double precision).365  // 3.14159265358979 in little endian366  uint8_t buffer[] = {0x18, 0x2D, 0x44, 0x54, 0xFB, 0x21, 0x09, 0x40};367 368  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(369      buffer, sizeof(buffer), eByteOrderLittle, 8, Table{Entry(0x1000, 8, 0)});370 371  offset_t virtual_offset = 0x1000;372  double value = extractor->GetDouble(&virtual_offset);373  EXPECT_NEAR(value, 3.14159265358979, 0.00000000000001);374  EXPECT_EQ(virtual_offset, 0x1008U);375}376 377TEST(VirtualDataExtractorTest, GetULEB128) {378  // ULEB128 encoding: 0x624 (1572 decimal) = 0xA4 0x0C379  uint8_t buffer[] = {0xA4, 0x0C, 0xFF, 0x00, 0x7F, 0x80, 0x01};380 381  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(382      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 7, 0)});383 384  // Test reading first ULEB128 value (1572).385  offset_t virtual_offset = 0x1000;386  EXPECT_EQ(extractor->GetULEB128(&virtual_offset), 1572U);387  EXPECT_EQ(virtual_offset, 0x1002U);388 389  // Test reading second ULEB128 value (127).390  virtual_offset = 0x1004;391  EXPECT_EQ(extractor->GetULEB128(&virtual_offset), 127U);392  EXPECT_EQ(virtual_offset, 0x1005U);393 394  // Test reading third ULEB128 value (128).395  EXPECT_EQ(extractor->GetULEB128(&virtual_offset), 128U);396  EXPECT_EQ(virtual_offset, 0x1007U);397}398 399TEST(VirtualDataExtractorTest, GetSLEB128) {400  // SLEB128 encoding: -123 = 0x85 0x7F, 123 = 0xFB 0x00401  uint8_t buffer[] = {0x85, 0x7F, 0xFB, 0x00};402 403  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(404      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 4, 0)});405 406  // Test reading negative SLEB128 value (-123).407  offset_t virtual_offset = 0x1000;408  EXPECT_EQ(extractor->GetSLEB128(&virtual_offset), -123);409  EXPECT_EQ(virtual_offset, 0x1002U);410 411  // Test reading positive SLEB128 value (123).412  EXPECT_EQ(extractor->GetSLEB128(&virtual_offset), 123);413  EXPECT_EQ(virtual_offset, 0x1004U);414}415 416TEST(VirtualDataExtractorTest, GetU8Array) {417  uint8_t buffer[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};418 419  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(420      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 8, 0)});421 422  // Test reading array of 4 bytes.423  offset_t virtual_offset = 0x1000;424  uint8_t dst[4] = {0};425  void *result = extractor->GetU8(&virtual_offset, dst, 4);426  ASSERT_NE(result, nullptr);427  EXPECT_EQ(dst[0], 0x01U);428  EXPECT_EQ(dst[1], 0x02U);429  EXPECT_EQ(dst[2], 0x03U);430  EXPECT_EQ(dst[3], 0x04U);431  EXPECT_EQ(virtual_offset, 0x1004U);432}433 434TEST(VirtualDataExtractorTest, GetU16Array) {435  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};436 437  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(438      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 8, 0)});439 440  // Test reading array of 3 uint16_t values.441  offset_t virtual_offset = 0x1000;442  uint16_t dst[3] = {0};443  void *result = extractor->GetU16(&virtual_offset, dst, 3);444  ASSERT_NE(result, nullptr);445  EXPECT_EQ(dst[0], 0x3412U);446  EXPECT_EQ(dst[1], 0x7856U);447  EXPECT_EQ(dst[2], 0xBC9AU);448  EXPECT_EQ(virtual_offset, 0x1006U);449}450 451TEST(VirtualDataExtractorTest, GetU32Array) {452  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};453 454  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(455      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 8, 0)});456 457  // Test reading array of 2 uint32_t values.458  offset_t virtual_offset = 0x1000;459  uint32_t dst[2] = {0};460  void *result = extractor->GetU32(&virtual_offset, dst, 2);461  ASSERT_NE(result, nullptr);462  EXPECT_EQ(dst[0], 0x78563412U);463  EXPECT_EQ(dst[1], 0xF0DEBC9AU);464  EXPECT_EQ(virtual_offset, 0x1008U);465}466 467TEST(VirtualDataExtractorTest, GetU64Array) {468  uint8_t buffer[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,469                      0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18};470 471  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(472      buffer, sizeof(buffer), eByteOrderLittle, 8, Table{Entry(0x1000, 16, 0)});473 474  // Test reading array of 2 uint64_t values.475  offset_t virtual_offset = 0x1000;476  uint64_t dst[2] = {0};477  void *result = extractor->GetU64(&virtual_offset, dst, 2);478  ASSERT_NE(result, nullptr);479  EXPECT_EQ(dst[0], 0x0807060504030201ULL);480  EXPECT_EQ(dst[1], 0x1817161514131211ULL);481  EXPECT_EQ(virtual_offset, 0x1010U);482}483 484TEST(VirtualDataExtractorTest, GetMaxU64WithVariableSizes) {485  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};486 487  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(488      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 8, 0)});489 490  // Test reading 3-byte value.491  offset_t virtual_offset = 0x1000;492  EXPECT_EQ(extractor->GetMaxU64(&virtual_offset, 3), 0x563412U);493  EXPECT_EQ(virtual_offset, 0x1003U);494 495  // Test reading 5-byte value.496  virtual_offset = 0x1000;497  EXPECT_EQ(extractor->GetMaxU64(&virtual_offset, 5), 0x9A78563412ULL);498  EXPECT_EQ(virtual_offset, 0x1005U);499}500 501TEST(VirtualDataExtractorTest, GetMaxS64) {502  // Test with negative number (sign extension).503  uint8_t buffer[] = {0xFF, 0xFF, 0xFF, 0xFF};504 505  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(506      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 4, 0)});507 508  // Test reading 1-byte signed value (-1).509  offset_t virtual_offset = 0x1000;510  EXPECT_EQ(extractor->GetMaxS64(&virtual_offset, 1), -1);511  EXPECT_EQ(virtual_offset, 0x1001U);512 513  // Test reading 2-byte signed value (-1).514  virtual_offset = 0x1000;515  EXPECT_EQ(extractor->GetMaxS64(&virtual_offset, 2), -1);516  EXPECT_EQ(virtual_offset, 0x1002U);517}518 519TEST(VirtualDataExtractorTest, CannotReadAcrossEntryBoundaries) {520  // Create buffer with two separate regions.521  uint8_t buffer[] = {0x01, 0x02, 0x03, 0x04, 0x11, 0x12, 0x13, 0x14};522 523  // First entry: virtual 0x1000-0x1004 maps to physical 0-4.524  // Second entry: virtual 0x2000-0x2004 maps to physical 4-8.525  // Note: there's a gap in virtual addresses (0x1004-0x2000).526  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(527      buffer, sizeof(buffer), eByteOrderLittle, 4,528      Table{Entry(0x1000, 4, 0), Entry(0x2000, 4, 4)});529 530  // Verify we can read within the first entry.531  offset_t virtual_offset = 0x1000;532  EXPECT_EQ(extractor->GetU32(&virtual_offset), 0x04030201U);533  EXPECT_EQ(virtual_offset, 0x1004U);534 535  // Verify we can read within the second entry.536  virtual_offset = 0x2000;537  EXPECT_EQ(extractor->GetU32(&virtual_offset), 0x14131211U);538  EXPECT_EQ(virtual_offset, 0x2004U);539 540  // Verify we CANNOT read in the gap between entries.541  // This address is not in any lookup table entry.542  virtual_offset = 0x1500;543  EXPECT_EQ(extractor->GetU8(&virtual_offset), 0U);544  EXPECT_EQ(virtual_offset, 0x1500U);545 546  // Verify we CANNOT read data pointer from the gap.547  virtual_offset = 0x1800;548  const void *data = extractor->GetData(&virtual_offset, 1);549  EXPECT_EQ(data, nullptr);550  EXPECT_EQ(virtual_offset, 0x1800U); // Offset unchanged.551 552  // Verify we can read individual bytes within each entry.553  virtual_offset = 0x1003;554  EXPECT_EQ(extractor->GetU8(&virtual_offset), 0x04U);555  EXPECT_EQ(virtual_offset, 0x1004U);556 557  // Verify we CANNOT read past the end of an entry.558  virtual_offset = 0x1004;559  EXPECT_EQ(extractor->GetU8(&virtual_offset), 0U);560  EXPECT_EQ(virtual_offset, 0x1004U);561}562 563TEST(VirtualDataExtractorTest, ReadExactlyAtEntryEnd) {564  uint8_t buffer[] = {0x01, 0x02, 0x03, 0x04};565 566  lldb::DataExtractorSP extractor = std::make_shared<VirtualDataExtractor>(567      buffer, sizeof(buffer), eByteOrderLittle, 4, Table{Entry(0x1000, 4, 0)});568 569  // Reading exactly to the end of an entry should work.570  offset_t virtual_offset = 0x1000;571  EXPECT_EQ(extractor->GetU32(&virtual_offset), 0x04030201U);572  EXPECT_EQ(virtual_offset, 0x1004U);573 574  // But reading one byte past the end should fail.575  virtual_offset = 0x1004;576  EXPECT_EQ(extractor->GetU8(&virtual_offset), 0U);577  EXPECT_EQ(virtual_offset, 0x1004U);578 579  // Reading from just before the end should work for smaller sizes.580  virtual_offset = 0x1003;581  EXPECT_EQ(extractor->GetU8(&virtual_offset), 0x04U);582  EXPECT_EQ(virtual_offset, 0x1004U);583}584