LLDB mainline
VirtualDataExtractor.cpp
Go to the documentation of this file.
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-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include <cassert>
11
12using namespace lldb;
13using namespace lldb_private;
14
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
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
35 LookupTable lookup_table)
36 : DataExtractor(data_sp), m_lookup_table(std::move(lookup_table)) {
37 m_lookup_table.Sort();
38}
39
42 // Use RangeDataVector's binary search instead of linear search.
43 return m_lookup_table.FindEntryThatContains(virtual_addr);
44}
45
47 offset_t length) const {
48 const LookupTable::Entry *entry = FindEntry(virtual_addr);
49 if (!entry)
50 return false;
51
52 // Assert that the read does not cross entry boundaries.
53 // RangeData.Contains() checks if a range is fully contained.
54 assert(entry->Contains(LookupTable::Range(virtual_addr, length)) &&
55 "Read crosses lookup table entry boundary");
56
57 // Also validate that the physical offset is within the data buffer.
58 // RangeData.data contains the physical offset.
59 offset_t physical_offset = entry->data + (virtual_addr - entry->base);
60 return ValidOffsetForDataOfSize(physical_offset, length);
61}
62
64 offset_t length) const {
65 // Override to treat offset as virtual address.
66 if (!offset_ptr)
67 return nullptr;
68
69 offset_t virtual_addr = *offset_ptr;
70
71 if (!ValidateVirtualRead(virtual_addr, length))
72 return nullptr;
73
74 const LookupTable::Entry *entry = FindEntry(virtual_addr);
75 assert(entry && "ValidateVirtualRead should have found an entry");
76
77 offset_t physical_offset = entry->data + (virtual_addr - entry->base);
78 // Use base class PeekData directly to avoid recursion.
79 const void *result = DataExtractor::PeekData(physical_offset, length);
80
81 if (result) {
82 // Advance the virtual offset pointer.
83 *offset_ptr += length;
84 }
85
86 return result;
87}
88
90 offset_t length) const {
91 // Override to treat offset as virtual address.
92 if (!ValidateVirtualRead(offset, length))
93 return nullptr;
94
95 const LookupTable::Entry *entry = FindEntry(offset);
96 assert(entry && "ValidateVirtualRead should have found an entry");
97
98 offset_t physical_offset = entry->data + (offset - entry->base);
99 // Use the base class PeekData with the physical offset.
100 return DataExtractor::PeekData(physical_offset, length);
101}
102
104 offset_t virtual_addr = *offset_ptr;
105 const LookupTable::Entry *entry = FindEntry(virtual_addr);
106 assert(entry && "Unchecked methods require valid virtual address");
107
108 offset_t physical_offset = entry->data + (virtual_addr - entry->base);
109 uint8_t result = DataExtractor::GetU8_unchecked(&physical_offset);
110 *offset_ptr += 1;
111 return result;
112}
113
115 offset_t virtual_addr = *offset_ptr;
116 const LookupTable::Entry *entry = FindEntry(virtual_addr);
117 assert(entry && "Unchecked methods require valid virtual address");
118
119 offset_t physical_offset = entry->data + (virtual_addr - entry->base);
120 uint16_t result = DataExtractor::GetU16_unchecked(&physical_offset);
121 *offset_ptr += 2;
122 return result;
123}
124
126 offset_t virtual_addr = *offset_ptr;
127 const LookupTable::Entry *entry = FindEntry(virtual_addr);
128 assert(entry && "Unchecked methods require valid virtual address");
129
130 offset_t physical_offset = entry->data + (virtual_addr - entry->base);
131 uint32_t result = DataExtractor::GetU32_unchecked(&physical_offset);
132 *offset_ptr += 4;
133 return result;
134}
135
137 offset_t virtual_addr = *offset_ptr;
138 const LookupTable::Entry *entry = FindEntry(virtual_addr);
139 assert(entry && "Unchecked methods require valid virtual address");
140
141 offset_t physical_offset = entry->data + (virtual_addr - entry->base);
142 uint64_t result = DataExtractor::GetU64_unchecked(&physical_offset);
143 *offset_ptr += 8;
144 return result;
145}
146
149 offset_t virtual_length) {
150 const LookupTable::Entry *entry = FindEntry(virtual_offset);
151 assert(
152 entry &&
153 "VirtualDataExtractor subset extractor requires valid virtual address");
154 if (!entry)
155 return {};
156
157 // Entry::data is the offset into the DataBuffer's actual start/end range
158 // Entry::base is the virtual address at the start of this region of data
159 offset_t offset_into_entry_range = virtual_offset - entry->base;
160 assert(
161 offset_into_entry_range + virtual_length <= entry->size &&
162 "VirtualDataExtractor subset may not span multiple LookupTable entries");
163 if (offset_into_entry_range + virtual_length > entry->size)
164 return {};
165
166 // We could support a Subset VirtualDataExtractor which covered
167 // multiple LookupTable virtual entries, but we'd need to mutate
168 // all of the LookupTable entries that were properly included in
169 // the Subset, a bit tricky. So we won't implement that until it's
170 // needed.
171
172 offset_t physical_start = entry->data + offset_into_entry_range;
173 std::shared_ptr<DataExtractor> new_sp = std::make_shared<DataExtractor>(
175 new_sp->SetData(GetSharedDataBuffer(), physical_start, virtual_length);
176 return new_sp;
177}
178
179// Return a DataExtractorSP that contains a single LookupTable's entry; all
180// bytes are guaranteed to be readable.
183 const LookupTable::Entry *entry = FindEntry(virtual_offset);
184 assert(
185 entry &&
186 "VirtualDataExtractor subset extractor requires valid virtual address");
187 if (!entry)
188 return {};
189
190 // Entry::data is the offset into the DataBuffer's actual start/end range
191 // Entry::base is the virtual address at the start of this region of data
192 offset_t offset_into_entry_range = virtual_offset - entry->base;
193
194 offset_t physical_start = entry->data + offset_into_entry_range;
195 std::shared_ptr<DataExtractor> new_sp = std::make_shared<DataExtractor>(
197 new_sp->SetData(GetSharedDataBuffer(), physical_start,
198 entry->size - offset_into_entry_range);
199 return new_sp;
200}
201
202// Return an ArrayRef to the first contiguous region of the LookupTable
203// only. The LookupTable entries may have gaps of unmapped data, and we
204// can't include those in the ArrayRef or something may touch those pages.
205llvm::ArrayRef<uint8_t> VirtualDataExtractor::GetData() const {
206 const LookupTable::Entry *entry = FindEntry(0);
207 assert(entry &&
208 "VirtualDataExtractor GetData requires valid virtual address");
209 if (!entry)
210 return {};
211 return {m_start + static_cast<size_t>(entry->data), static_cast<size_t>(entry->size)};
212}
virtual uint32_t GetU32_unchecked(lldb::offset_t *offset_ptr) const
bool ValidOffsetForDataOfSize(lldb::offset_t offset, lldb::offset_t length) const
Test the availability of length bytes of data from offset.
const uint8_t * m_start
A pointer to the first byte of data.
virtual const uint8_t * PeekData(lldb::offset_t offset, lldb::offset_t length) const
Peek at a bytes at offset.
lldb::DataBufferSP & GetSharedDataBuffer()
DataExtractor()
Default constructor.
uint32_t GetAddressByteSize() const
Get the current address size.
virtual uint8_t GetU8_unchecked(lldb::offset_t *offset_ptr) const
virtual uint64_t GetU64_unchecked(lldb::offset_t *offset_ptr) const
lldb::ByteOrder GetByteOrder() const
Get the current byte order value.
virtual uint16_t GetU16_unchecked(lldb::offset_t *offset_ptr) const
RangeData< lldb::offset_t, lldb::offset_t, lldb::offset_t > Entry
Definition RangeMap.h:462
lldb_private::Range< lldb::offset_t, lldb::offset_t > Range
Definition RangeMap.h:461
lldb::DataExtractorSP GetSubsetExtractorSP(lldb::offset_t offset, lldb::offset_t length) override
Return a new DataExtractor which represents a subset of an existing data extractor's bytes,...
uint32_t GetU32_unchecked(lldb::offset_t *offset_ptr) const override
const LookupTable::Entry * FindEntry(lldb::offset_t virtual_addr) const
Find the lookup entry that contains the given virtual address.
llvm::ArrayRef< uint8_t > GetData() const override
bool ValidateVirtualRead(lldb::offset_t virtual_addr, lldb::offset_t length) const
Validate that a read at a virtual address is within bounds and does not cross entry boundaries.
const uint8_t * PeekData(lldb::offset_t offset, lldb::offset_t length) const override
Peek at a bytes at offset.
uint8_t GetU8_unchecked(lldb::offset_t *offset_ptr) const override
Unchecked overrides.
uint64_t GetU64_unchecked(lldb::offset_t *offset_ptr) const override
RangeDataVector< lldb::offset_t, lldb::offset_t, lldb::offset_t > LookupTable
Type alias for the range map used internally.
uint16_t GetU16_unchecked(lldb::offset_t *offset_ptr) const override
A class that represents a running process on the host machine.
uint64_t offset_t
Definition lldb-types.h:85
ByteOrder
Byte ordering definitions.
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP
std::shared_ptr< lldb_private::DataExtractor > DataExtractorSP
bool Contains(BaseType r) const
Definition RangeMap.h:93