https://github.com/JDevlieghere created 
https://github.com/llvm/llvm-project/pull/168802

None

>From a2258029c741f357d0f45c656839492c7411898c Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <[email protected]>
Date: Wed, 19 Nov 2025 17:07:47 -0800
Subject: [PATCH] [lldb] Add VirtualDataExtractor abstraction

---
 lldb/include/lldb/Utility/DataExtractor.h     |   6 +-
 .../lldb/Utility/VirtualDataExtractor.h       |  69 +++++
 lldb/source/Utility/CMakeLists.txt            |   1 +
 lldb/source/Utility/VirtualDataExtractor.cpp  |  95 ++++++
 lldb/unittests/Utility/CMakeLists.txt         |   1 +
 .../Utility/VirtualDataExtractorTest.cpp      | 285 ++++++++++++++++++
 6 files changed, 455 insertions(+), 2 deletions(-)
 create mode 100644 lldb/include/lldb/Utility/VirtualDataExtractor.h
 create mode 100644 lldb/source/Utility/VirtualDataExtractor.cpp
 create mode 100644 lldb/unittests/Utility/VirtualDataExtractorTest.cpp

diff --git a/lldb/include/lldb/Utility/DataExtractor.h 
b/lldb/include/lldb/Utility/DataExtractor.h
index b4960f5e87c85..fe217795ff3b1 100644
--- a/lldb/include/lldb/Utility/DataExtractor.h
+++ b/lldb/include/lldb/Utility/DataExtractor.h
@@ -334,7 +334,8 @@ class DataExtractor {
   /// \return
   ///     A pointer to the bytes in this object's data if the offset
   ///     and length are valid, or nullptr otherwise.
-  const void *GetData(lldb::offset_t *offset_ptr, lldb::offset_t length) const 
{
+  virtual const void *GetData(lldb::offset_t *offset_ptr,
+                              lldb::offset_t length) const {
     const uint8_t *ptr = PeekData(*offset_ptr, length);
     if (ptr)
       *offset_ptr += length;
@@ -829,7 +830,8 @@ class DataExtractor {
   ///     A non-nullptr data pointer if \a offset is a valid offset and
   ///     there are \a length bytes available at that offset, nullptr
   ///     otherwise.
-  const uint8_t *PeekData(lldb::offset_t offset, lldb::offset_t length) const {
+  virtual const uint8_t *PeekData(lldb::offset_t offset,
+                                  lldb::offset_t length) const {
     if (ValidOffsetForDataOfSize(offset, length))
       return m_start + offset;
     return nullptr;
diff --git a/lldb/include/lldb/Utility/VirtualDataExtractor.h 
b/lldb/include/lldb/Utility/VirtualDataExtractor.h
new file mode 100644
index 0000000000000..a940e58db7a12
--- /dev/null
+++ b/lldb/include/lldb/Utility/VirtualDataExtractor.h
@@ -0,0 +1,69 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_UTILITY_VIRTUALDATAEXTRACTOR_H
+#define LLDB_UTILITY_VIRTUALDATAEXTRACTOR_H
+
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/RangeMap.h"
+#include "lldb/lldb-types.h"
+
+namespace lldb_private {
+
+/// A DataExtractor subclass that allows reading data at virtual addresses
+/// using a lookup table that maps virtual address ranges to physical offsets.
+///
+/// This class maintains a lookup table where each entry contains:
+/// - base: starting virtual address for this entry
+/// - size: size of this entry in bytes
+/// - data: physical offset in the underlying data buffer
+///
+/// Reads are translated from virtual addresses to physical offsets using
+/// this lookup table. Reads cannot cross entry boundaries and this is
+/// enforced with assertions.
+class VirtualDataExtractor : public DataExtractor {
+public:
+  /// Type alias for the range map used internally.
+  /// Maps virtual addresses (base) to physical offsets (data).
+  using LookupTable =
+      RangeDataVector<lldb::offset_t, lldb::offset_t, lldb::offset_t>;
+
+  VirtualDataExtractor() = default;
+
+  VirtualDataExtractor(const void *data, lldb::offset_t data_length,
+                       lldb::ByteOrder byte_order, uint32_t addr_size,
+                       LookupTable lookup_table);
+
+  VirtualDataExtractor(const lldb::DataBufferSP &data_sp,
+                       lldb::ByteOrder byte_order, uint32_t addr_size,
+                       LookupTable lookup_table);
+
+  const void *GetData(lldb::offset_t *offset_ptr,
+                      lldb::offset_t length) const override;
+
+  const uint8_t *PeekData(lldb::offset_t offset,
+                          lldb::offset_t length) const override;
+
+  const LookupTable &GetLookupTable() const { return m_lookup_table; }
+
+protected:
+  /// Find the lookup entry that contains the given virtual address.
+  const LookupTable::Entry *FindEntry(lldb::offset_t virtual_addr) const;
+
+  /// Validate that a read at a virtual address is within bounds and
+  /// does not cross entry boundaries.
+  bool ValidateVirtualRead(lldb::offset_t virtual_addr,
+                           lldb::offset_t length) const;
+
+private:
+  LookupTable m_lookup_table;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_UTILITY_VIRTUALDATAEXTRACTOR_H
diff --git a/lldb/source/Utility/CMakeLists.txt 
b/lldb/source/Utility/CMakeLists.txt
index 1dd4d63f7016f..4696ed4690d37 100644
--- a/lldb/source/Utility/CMakeLists.txt
+++ b/lldb/source/Utility/CMakeLists.txt
@@ -78,6 +78,7 @@ add_lldb_library(lldbUtility NO_INTERNAL_DEPENDENCIES
   UserIDResolver.cpp
   VASprintf.cpp
   VMRange.cpp
+  VirtualDataExtractor.cpp
   XcodeSDK.cpp
   ZipFile.cpp
 
diff --git a/lldb/source/Utility/VirtualDataExtractor.cpp 
b/lldb/source/Utility/VirtualDataExtractor.cpp
new file mode 100644
index 0000000000000..f727cf1c8bc8a
--- /dev/null
+++ b/lldb/source/Utility/VirtualDataExtractor.cpp
@@ -0,0 +1,95 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/VirtualDataExtractor.h"
+#include <cassert>
+
+using namespace lldb;
+using namespace lldb_private;
+
+VirtualDataExtractor::VirtualDataExtractor(const void *data,
+                                           offset_t data_length,
+                                           ByteOrder byte_order,
+                                           uint32_t addr_size,
+                                           LookupTable lookup_table)
+    : DataExtractor(data, data_length, byte_order, addr_size),
+      m_lookup_table(std::move(lookup_table)) {
+  m_lookup_table.Sort();
+}
+
+VirtualDataExtractor::VirtualDataExtractor(const DataBufferSP &data_sp,
+                                           ByteOrder byte_order,
+                                           uint32_t addr_size,
+                                           LookupTable lookup_table)
+    : DataExtractor(data_sp, byte_order, addr_size),
+      m_lookup_table(std::move(lookup_table)) {
+  m_lookup_table.Sort();
+}
+
+const VirtualDataExtractor::LookupTable::Entry *
+VirtualDataExtractor::FindEntry(offset_t virtual_addr) const {
+  // Use RangeDataVector's binary search instead of linear search.
+  return m_lookup_table.FindEntryThatContains(virtual_addr);
+}
+
+bool VirtualDataExtractor::ValidateVirtualRead(offset_t virtual_addr,
+                                               offset_t length) const {
+  const LookupTable::Entry *entry = FindEntry(virtual_addr);
+  if (!entry)
+    return false;
+
+  // Assert that the read does not cross entry boundaries.
+  // RangeData.Contains() checks if a range is fully contained.
+  assert(entry->Contains(LookupTable::Range(virtual_addr, length)) &&
+         "Read crosses lookup table entry boundary");
+
+  // Also validate that the physical offset is within the data buffer.
+  // RangeData.data contains the physical offset.
+  offset_t physical_offset = entry->data + (virtual_addr - entry->base);
+  return ValidOffsetForDataOfSize(physical_offset, length);
+}
+
+const void *VirtualDataExtractor::GetData(offset_t *offset_ptr,
+                                          offset_t length) const {
+  // Override to treat offset as virtual address.
+  if (!offset_ptr)
+    return nullptr;
+
+  offset_t virtual_addr = *offset_ptr;
+
+  if (!ValidateVirtualRead(virtual_addr, length))
+    return nullptr;
+
+  const LookupTable::Entry *entry = FindEntry(virtual_addr);
+  assert(entry && "ValidateVirtualRead should have found an entry");
+
+  offset_t physical_offset = entry->data + (virtual_addr - entry->base);
+  // Use base class PeekData directly to avoid recursion.
+  const void *result = DataExtractor::PeekData(physical_offset, length);
+
+  if (result) {
+    // Advance the virtual offset pointer.
+    *offset_ptr += length;
+  }
+
+  return result;
+}
+
+const uint8_t *VirtualDataExtractor::PeekData(offset_t offset,
+                                              offset_t length) const {
+  // Override to treat offset as virtual address.
+  if (!ValidateVirtualRead(offset, length))
+    return nullptr;
+
+  const LookupTable::Entry *entry = FindEntry(offset);
+  assert(entry && "ValidateVirtualRead should have found an entry");
+
+  offset_t physical_offset = entry->data + (offset - entry->base);
+  // Use the base class PeekData with the physical offset.
+  return DataExtractor::PeekData(physical_offset, length);
+}
diff --git a/lldb/unittests/Utility/CMakeLists.txt 
b/lldb/unittests/Utility/CMakeLists.txt
index aed4177f5edee..77b52079cf32b 100644
--- a/lldb/unittests/Utility/CMakeLists.txt
+++ b/lldb/unittests/Utility/CMakeLists.txt
@@ -48,6 +48,7 @@ add_lldb_unittest(UtilityTests
   UserIDResolverTest.cpp
   UUIDTest.cpp
   VASprintfTest.cpp
+  VirtualDataExtractorTest.cpp
   VMRangeTest.cpp
   XcodeSDKTest.cpp
 
diff --git a/lldb/unittests/Utility/VirtualDataExtractorTest.cpp 
b/lldb/unittests/Utility/VirtualDataExtractorTest.cpp
new file mode 100644
index 0000000000000..2a321884bab84
--- /dev/null
+++ b/lldb/unittests/Utility/VirtualDataExtractorTest.cpp
@@ -0,0 +1,285 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/VirtualDataExtractor.h"
+#include "lldb/Utility/DataBufferHeap.h"
+#include "gtest/gtest.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+TEST(VirtualDataExtractorTest, BasicConstruction) {
+  // Create a simple data buffer.
+  uint8_t buffer[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
+
+  // Create a lookup table that maps virtual addresses to physical offsets.
+  VirtualDataExtractor::LookupTable lookup_table;
+  // Virtual address 0x1000-0x1008 maps to physical offset 0-8.
+  // Entry(base=virtual_offset, size, data=physical_offset).
+  lookup_table.Append(VirtualDataExtractor::LookupTable::Entry(0x1000, 8, 0));
+
+  VirtualDataExtractor extractor(buffer, sizeof(buffer), eByteOrderLittle, 4,
+                                 std::move(lookup_table));
+
+  EXPECT_EQ(extractor.GetByteSize(), 8U);
+}
+
+TEST(VirtualDataExtractorTest, GetDataAtVirtualOffset) {
+  uint8_t buffer[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
+
+  VirtualDataExtractor::LookupTable lookup_table;
+  lookup_table.Append(VirtualDataExtractor::LookupTable::Entry(0x1000, 8, 0));
+
+  VirtualDataExtractor extractor(buffer, sizeof(buffer), eByteOrderLittle, 4,
+                                 std::move(lookup_table));
+
+  offset_t virtual_offset = 0x1000;
+  const void *data = extractor.GetData(&virtual_offset, 4);
+
+  ASSERT_NE(data, nullptr);
+  EXPECT_EQ(virtual_offset, 0x1004U);
+  EXPECT_EQ(memcmp(data, buffer, 4), 0);
+}
+
+TEST(VirtualDataExtractorTest, GetDataAtVirtualOffsetInvalid) {
+  uint8_t buffer[] = {0x01, 0x02, 0x03, 0x04};
+
+  VirtualDataExtractor::LookupTable lookup_table;
+  lookup_table.Append(VirtualDataExtractor::LookupTable::Entry(0x1000, 4, 0));
+
+  VirtualDataExtractor extractor(buffer, sizeof(buffer), eByteOrderLittle, 4,
+                                 std::move(lookup_table));
+
+  // Try to read from an invalid virtual address.
+  offset_t virtual_offset = 0x2000;
+  const void *data = extractor.GetData(&virtual_offset, 4);
+
+  EXPECT_EQ(data, nullptr);
+}
+
+TEST(VirtualDataExtractorTest, GetU8AtVirtualOffset) {
+  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78};
+
+  VirtualDataExtractor::LookupTable lookup_table;
+  lookup_table.Append(VirtualDataExtractor::LookupTable::Entry(0x1000, 4, 0));
+
+  VirtualDataExtractor extractor(buffer, sizeof(buffer), eByteOrderLittle, 4,
+                                 std::move(lookup_table));
+
+  offset_t virtual_offset = 0x1000;
+  EXPECT_EQ(extractor.GetU8(&virtual_offset), 0x12U);
+  EXPECT_EQ(virtual_offset, 0x1001U);
+
+  EXPECT_EQ(extractor.GetU8(&virtual_offset), 0x34U);
+  EXPECT_EQ(virtual_offset, 0x1002U);
+}
+
+TEST(VirtualDataExtractorTest, GetU16AtVirtualOffset) {
+  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78};
+
+  VirtualDataExtractor::LookupTable lookup_table;
+  lookup_table.Append(VirtualDataExtractor::LookupTable::Entry(0x1000, 4, 0));
+
+  VirtualDataExtractor extractor(buffer, sizeof(buffer), eByteOrderLittle, 4,
+                                 std::move(lookup_table));
+
+  offset_t virtual_offset = 0x1000;
+  EXPECT_EQ(extractor.GetU16(&virtual_offset), 0x3412U);
+  EXPECT_EQ(virtual_offset, 0x1002U);
+
+  EXPECT_EQ(extractor.GetU16(&virtual_offset), 0x7856U);
+  EXPECT_EQ(virtual_offset, 0x1004U);
+}
+
+TEST(VirtualDataExtractorTest, GetU32AtVirtualOffset) {
+  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};
+
+  VirtualDataExtractor::LookupTable lookup_table;
+  lookup_table.Append(VirtualDataExtractor::LookupTable::Entry(0x1000, 8, 0));
+
+  VirtualDataExtractor extractor(buffer, sizeof(buffer), eByteOrderLittle, 4,
+                                 std::move(lookup_table));
+
+  offset_t virtual_offset = 0x1000;
+  EXPECT_EQ(extractor.GetU32(&virtual_offset), 0x78563412U);
+  EXPECT_EQ(virtual_offset, 0x1004U);
+
+  EXPECT_EQ(extractor.GetU32(&virtual_offset), 0xF0DEBC9AU);
+  EXPECT_EQ(virtual_offset, 0x1008U);
+}
+
+TEST(VirtualDataExtractorTest, GetU64AtVirtualOffset) {
+  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};
+
+  VirtualDataExtractor::LookupTable lookup_table;
+  lookup_table.Append(VirtualDataExtractor::LookupTable::Entry(0x1000, 8, 0));
+
+  VirtualDataExtractor extractor(buffer, sizeof(buffer), eByteOrderLittle, 8,
+                                 std::move(lookup_table));
+
+  offset_t virtual_offset = 0x1000;
+  EXPECT_EQ(extractor.GetU64(&virtual_offset), 0xF0DEBC9A78563412ULL);
+  EXPECT_EQ(virtual_offset, 0x1008U);
+}
+
+TEST(VirtualDataExtractorTest, GetAddressAtVirtualOffset) {
+  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78};
+
+  VirtualDataExtractor::LookupTable lookup_table;
+  lookup_table.Append(VirtualDataExtractor::LookupTable::Entry(0x1000, 4, 0));
+
+  VirtualDataExtractor extractor(buffer, sizeof(buffer), eByteOrderLittle, 4,
+                                 std::move(lookup_table));
+
+  offset_t virtual_offset = 0x1000;
+  EXPECT_EQ(extractor.GetAddress(&virtual_offset), 0x78563412U);
+  EXPECT_EQ(virtual_offset, 0x1004U);
+}
+
+TEST(VirtualDataExtractorTest, BigEndian) {
+  uint8_t buffer[] = {0x12, 0x34, 0x56, 0x78};
+
+  VirtualDataExtractor::LookupTable lookup_table;
+  lookup_table.Append(VirtualDataExtractor::LookupTable::Entry(0x1000, 4, 0));
+
+  VirtualDataExtractor extractor(buffer, sizeof(buffer), eByteOrderBig, 4,
+                                 std::move(lookup_table));
+
+  offset_t virtual_offset = 0x1000;
+  EXPECT_EQ(extractor.GetU16(&virtual_offset), 0x1234U);
+  EXPECT_EQ(virtual_offset, 0x1002U);
+
+  EXPECT_EQ(extractor.GetU16(&virtual_offset), 0x5678U);
+  EXPECT_EQ(virtual_offset, 0x1004U);
+}
+
+TEST(VirtualDataExtractorTest, MultipleEntries) {
+  // Create a buffer with distinct patterns for each section.
+  uint8_t buffer[] = {
+      0x01, 0x02, 0x03, 0x04, // Physical offset 0-3.
+      0x11, 0x12, 0x13, 0x14, // Physical offset 4-7.
+      0x21, 0x22, 0x23, 0x24  // Physical offset 8-11.
+  };
+
+  VirtualDataExtractor::LookupTable lookup_table;
+  // Map different virtual address ranges to different physical offsets.
+  // Entry(base=virtual_offset, size, data=physical_offset).
+  lookup_table.Append(VirtualDataExtractor::LookupTable::Entry(
+      0x1000, 4, 0)); // Virt 0x1000-0x1004 -> phys 0-4.
+  lookup_table.Append(VirtualDataExtractor::LookupTable::Entry(
+      0x2000, 4, 4)); // Virt 0x2000-0x2004 -> phys 4-8.
+  lookup_table.Append(VirtualDataExtractor::LookupTable::Entry(
+      0x3000, 4, 8)); // Virt 0x3000-0x3004 -> phys 8-12.
+
+  VirtualDataExtractor extractor(buffer, sizeof(buffer), eByteOrderLittle, 4,
+                                 std::move(lookup_table));
+
+  // Test reading from first virtual range.
+  offset_t virtual_offset = 0x1000;
+  EXPECT_EQ(extractor.GetU8(&virtual_offset), 0x01U);
+
+  // Test reading from second virtual range.
+  virtual_offset = 0x2000;
+  EXPECT_EQ(extractor.GetU8(&virtual_offset), 0x11U);
+
+  // Test reading from third virtual range.
+  virtual_offset = 0x3000;
+  EXPECT_EQ(extractor.GetU8(&virtual_offset), 0x21U);
+}
+
+TEST(VirtualDataExtractorTest, NonContiguousVirtualAddresses) {
+  uint8_t buffer[] = {0xAA, 0xBB, 0xCC, 0xDD};
+
+  VirtualDataExtractor::LookupTable lookup_table;
+  // Create non-contiguous virtual address mapping.
+  // Entry(base=virtual_offset, size, data=physical_offset).
+  lookup_table.Append(VirtualDataExtractor::LookupTable::Entry(
+      0x1000, 2, 0)); // Virt 0x1000-0x1002 -> phys 0-2.
+  lookup_table.Append(VirtualDataExtractor::LookupTable::Entry(
+      0x5000, 2, 2)); // Virt 0x5000-0x5002 -> phys 2-4.
+
+  VirtualDataExtractor extractor(buffer, sizeof(buffer), eByteOrderLittle, 4,
+                                 std::move(lookup_table));
+
+  // Test reading from first virtual range.
+  offset_t virtual_offset = 0x1000;
+  EXPECT_EQ(extractor.GetU16(&virtual_offset), 0xBBAAU);
+
+  // Test reading from second virtual range (non-contiguous).
+  virtual_offset = 0x5000;
+  EXPECT_EQ(extractor.GetU16(&virtual_offset), 0xDDCCU);
+
+  // Test that gap between ranges is invalid.
+  virtual_offset = 0x3000;
+  EXPECT_EQ(extractor.GetU8(&virtual_offset), 0U);
+}
+
+TEST(VirtualDataExtractorTest, SharedDataBuffer) {
+  // Test with shared_ptr to DataBuffer.
+  uint8_t buffer[] = {0x01, 0x02, 0x03, 0x04};
+  auto data_sp = std::make_shared<DataBufferHeap>(buffer, sizeof(buffer));
+
+  VirtualDataExtractor::LookupTable lookup_table;
+  lookup_table.Append(VirtualDataExtractor::LookupTable::Entry(0x1000, 4, 0));
+
+  VirtualDataExtractor extractor(data_sp, eByteOrderLittle, 4,
+                                 std::move(lookup_table));
+
+  offset_t virtual_offset = 0x1000;
+  EXPECT_EQ(extractor.GetU32(&virtual_offset), 0x04030201U);
+}
+
+TEST(VirtualDataExtractorTest, LookupTableAccess) {
+  uint8_t buffer[] = {0x01, 0x02, 0x03, 0x04};
+
+  VirtualDataExtractor::LookupTable lookup_table;
+  lookup_table.Append(VirtualDataExtractor::LookupTable::Entry(0x1000, 2, 0));
+  lookup_table.Append(VirtualDataExtractor::LookupTable::Entry(0x2000, 2, 2));
+
+  VirtualDataExtractor extractor(buffer, sizeof(buffer), eByteOrderLittle, 4,
+                                 std::move(lookup_table));
+
+  const auto &table = extractor.GetLookupTable();
+  EXPECT_EQ(table.GetSize(), 2U);
+  EXPECT_FALSE(table.IsEmpty());
+}
+
+TEST(VirtualDataExtractorTest, NullPointerHandling) {
+  uint8_t buffer[] = {0x01, 0x02, 0x03, 0x04};
+
+  VirtualDataExtractor::LookupTable lookup_table;
+  lookup_table.Append(VirtualDataExtractor::LookupTable::Entry(0x1000, 4, 0));
+
+  VirtualDataExtractor extractor(buffer, sizeof(buffer), eByteOrderLittle, 4,
+                                 std::move(lookup_table));
+
+  // Test that passing nullptr returns default values.
+  EXPECT_EQ(extractor.GetU8(nullptr), 0U);
+  EXPECT_EQ(extractor.GetU16(nullptr), 0U);
+  EXPECT_EQ(extractor.GetU32(nullptr), 0U);
+  EXPECT_EQ(extractor.GetU64(nullptr), 0U);
+  EXPECT_EQ(extractor.GetAddress(nullptr), 0U);
+  EXPECT_EQ(extractor.GetData(nullptr, 4), nullptr);
+}
+
+TEST(VirtualDataExtractorTest, OffsetMapping) {
+  // Test that virtual to physical offset mapping works correctly.
+  uint8_t buffer[] = {0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD};
+
+  VirtualDataExtractor::LookupTable lookup_table;
+  // Map virtual address 0x1000 to physical offset 4 (skipping first 4 bytes).
+  // Entry(base=virtual_offset, size, data=physical_offset).
+  lookup_table.Append(VirtualDataExtractor::LookupTable::Entry(0x1000, 4, 4));
+
+  VirtualDataExtractor extractor(buffer, sizeof(buffer), eByteOrderLittle, 4,
+                                 std::move(lookup_table));
+
+  offset_t virtual_offset = 0x1000;
+  // Should read from physical offset 4, not 0.
+  EXPECT_EQ(extractor.GetU32(&virtual_offset), 0xDDCCBBAAU);
+}

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to