140 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 <cassert>11 12using namespace lldb;13using namespace lldb_private;14 15VirtualDataExtractor::VirtualDataExtractor(const void *data,16 offset_t data_length,17 ByteOrder byte_order,18 uint32_t addr_size,19 LookupTable lookup_table)20 : DataExtractor(data, data_length, byte_order, addr_size),21 m_lookup_table(std::move(lookup_table)) {22 m_lookup_table.Sort();23}24 25VirtualDataExtractor::VirtualDataExtractor(const DataBufferSP &data_sp,26 ByteOrder byte_order,27 uint32_t addr_size,28 LookupTable lookup_table)29 : DataExtractor(data_sp, byte_order, addr_size),30 m_lookup_table(std::move(lookup_table)) {31 m_lookup_table.Sort();32}33 34const VirtualDataExtractor::LookupTable::Entry *35VirtualDataExtractor::FindEntry(offset_t virtual_addr) const {36 // Use RangeDataVector's binary search instead of linear search.37 return m_lookup_table.FindEntryThatContains(virtual_addr);38}39 40bool VirtualDataExtractor::ValidateVirtualRead(offset_t virtual_addr,41 offset_t length) const {42 const LookupTable::Entry *entry = FindEntry(virtual_addr);43 if (!entry)44 return false;45 46 // Assert that the read does not cross entry boundaries.47 // RangeData.Contains() checks if a range is fully contained.48 assert(entry->Contains(LookupTable::Range(virtual_addr, length)) &&49 "Read crosses lookup table entry boundary");50 51 // Also validate that the physical offset is within the data buffer.52 // RangeData.data contains the physical offset.53 offset_t physical_offset = entry->data + (virtual_addr - entry->base);54 return ValidOffsetForDataOfSize(physical_offset, length);55}56 57const void *VirtualDataExtractor::GetData(offset_t *offset_ptr,58 offset_t length) const {59 // Override to treat offset as virtual address.60 if (!offset_ptr)61 return nullptr;62 63 offset_t virtual_addr = *offset_ptr;64 65 if (!ValidateVirtualRead(virtual_addr, length))66 return nullptr;67 68 const LookupTable::Entry *entry = FindEntry(virtual_addr);69 assert(entry && "ValidateVirtualRead should have found an entry");70 71 offset_t physical_offset = entry->data + (virtual_addr - entry->base);72 // Use base class PeekData directly to avoid recursion.73 const void *result = DataExtractor::PeekData(physical_offset, length);74 75 if (result) {76 // Advance the virtual offset pointer.77 *offset_ptr += length;78 }79 80 return result;81}82 83const uint8_t *VirtualDataExtractor::PeekData(offset_t offset,84 offset_t length) const {85 // Override to treat offset as virtual address.86 if (!ValidateVirtualRead(offset, length))87 return nullptr;88 89 const LookupTable::Entry *entry = FindEntry(offset);90 assert(entry && "ValidateVirtualRead should have found an entry");91 92 offset_t physical_offset = entry->data + (offset - entry->base);93 // Use the base class PeekData with the physical offset.94 return DataExtractor::PeekData(physical_offset, length);95}96 97uint8_t VirtualDataExtractor::GetU8_unchecked(offset_t *offset_ptr) const {98 offset_t virtual_addr = *offset_ptr;99 const LookupTable::Entry *entry = FindEntry(virtual_addr);100 assert(entry && "Unchecked methods require valid virtual address");101 102 offset_t physical_offset = entry->data + (virtual_addr - entry->base);103 uint8_t result = DataExtractor::GetU8_unchecked(&physical_offset);104 *offset_ptr += 1;105 return result;106}107 108uint16_t VirtualDataExtractor::GetU16_unchecked(offset_t *offset_ptr) const {109 offset_t virtual_addr = *offset_ptr;110 const LookupTable::Entry *entry = FindEntry(virtual_addr);111 assert(entry && "Unchecked methods require valid virtual address");112 113 offset_t physical_offset = entry->data + (virtual_addr - entry->base);114 uint16_t result = DataExtractor::GetU16_unchecked(&physical_offset);115 *offset_ptr += 2;116 return result;117}118 119uint32_t VirtualDataExtractor::GetU32_unchecked(offset_t *offset_ptr) const {120 offset_t virtual_addr = *offset_ptr;121 const LookupTable::Entry *entry = FindEntry(virtual_addr);122 assert(entry && "Unchecked methods require valid virtual address");123 124 offset_t physical_offset = entry->data + (virtual_addr - entry->base);125 uint32_t result = DataExtractor::GetU32_unchecked(&physical_offset);126 *offset_ptr += 4;127 return result;128}129 130uint64_t VirtualDataExtractor::GetU64_unchecked(offset_t *offset_ptr) const {131 offset_t virtual_addr = *offset_ptr;132 const LookupTable::Entry *entry = FindEntry(virtual_addr);133 assert(entry && "Unchecked methods require valid virtual address");134 135 offset_t physical_offset = entry->data + (virtual_addr - entry->base);136 uint64_t result = DataExtractor::GetU64_unchecked(&physical_offset);137 *offset_ptr += 8;138 return result;139}140