LLDB mainline
RegisterContextUnifiedCore.cpp
Go to the documentation of this file.
1//===-- RegisterContextUnifiedCore.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
11#include "lldb/Target/Process.h"
15
16using namespace lldb;
17using namespace lldb_private;
18
20 Thread &thread, uint32_t concrete_frame_idx,
21 RegisterContextSP core_thread_regctx_sp,
22 StructuredData::ObjectSP metadata_thread_registers)
23 : RegisterContext(thread, concrete_frame_idx) {
24
25 ProcessSP process_sp(thread.GetProcess());
26 Target &target = process_sp->GetTarget();
27 StructuredData::Dictionary *metadata_registers_dict = nullptr;
28
29 // If we have thread metadata, check if the keys for register
30 // definitions are present; if not, clear the ObjectSP.
31 if (metadata_thread_registers &&
32 metadata_thread_registers->GetAsDictionary() &&
33 metadata_thread_registers->GetAsDictionary()->HasKey("register_info")) {
34 metadata_registers_dict = metadata_thread_registers->GetAsDictionary()
35 ->GetValueForKey("register_info")
36 ->GetAsDictionary();
37 if (metadata_registers_dict)
38 if (!metadata_registers_dict->HasKey("sets") ||
39 !metadata_registers_dict->HasKey("registers"))
40 metadata_registers_dict = nullptr;
41 }
42
43 // When creating a register set list from the two sources,
44 // the LC_THREAD aka core_thread_regctx_sp register sets
45 // will be used at the same indexes.
46 // Any additional sets named by the thread metadata registers
47 // will be added after them. If the thread metadata
48 // specify a set with the same name as LC_THREAD, the already-used
49 // index from the core register context will be used in
50 // the RegisterInfo.
51 std::map<size_t, size_t> metadata_regset_to_combined_regset;
52
53 // Calculate the total size of the register store buffer we need
54 // for all registers. The corefile register definitions may include
55 // RegisterInfo descriptions of registers that aren't actually
56 // available. For simplicity, calculate the size of all registers
57 // as if they are available, so we can maintain the same offsets into
58 // the buffer.
59 uint32_t core_buffer_end = 0;
60 for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) {
61 const RegisterInfo *reginfo =
62 core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);
63 core_buffer_end =
64 std::max(reginfo->byte_offset + reginfo->byte_size, core_buffer_end);
65 }
66
67 // Add metadata register sizes to the total buffer size.
68 uint32_t combined_buffer_end = core_buffer_end;
69 if (metadata_registers_dict) {
70 StructuredData::Array *registers = nullptr;
71 if (metadata_registers_dict->GetValueForKeyAsArray("registers", registers))
72 registers->ForEach(
73 [&combined_buffer_end](StructuredData::Object *ent) -> bool {
74 uint32_t bitsize;
75 if (!ent->GetAsDictionary()->GetValueForKeyAsInteger("bitsize",
76 bitsize))
77 return false;
78 combined_buffer_end += (bitsize / 8);
79 return true;
80 });
81 }
82 m_register_data.resize(combined_buffer_end, 0);
83
84 // Copy the core register values into our combined data buffer,
85 // skip registers that are contained within another (e.g. w0 vs. x0)
86 // and registers that return as "unavailable".
87 for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) {
88 const RegisterInfo *reginfo =
89 core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);
90 RegisterValue val;
91 if (!reginfo->value_regs &&
92 core_thread_regctx_sp->ReadRegister(reginfo, val))
93 memcpy(m_register_data.data() + reginfo->byte_offset, val.GetBytes(),
94 val.GetByteSize());
95 }
96
97 // Set 'offset' fields for each register definition into our combined
98 // register data buffer. DynamicRegisterInfo needs this field set to
99 // parse the JSON.
100 // Also copy the values of the registers into our register data buffer.
101 if (metadata_registers_dict) {
102 size_t offset = core_buffer_end;
103 ByteOrder byte_order = core_thread_regctx_sp->GetByteOrder();
104 StructuredData::Array *registers;
105 if (metadata_registers_dict->GetValueForKeyAsArray("registers", registers))
106 registers->ForEach([this, &offset,
107 byte_order](StructuredData::Object *ent) -> bool {
108 uint64_t bitsize;
109 uint64_t value;
110 if (!ent->GetAsDictionary()->GetValueForKeyAsInteger("bitsize",
111 bitsize))
112 return false;
113 if (!ent->GetAsDictionary()->GetValueForKeyAsInteger("value", value)) {
114 // We had a bitsize but no value, so move the offset forward I guess.
115 offset += (bitsize / 8);
116 return false;
117 }
118 ent->GetAsDictionary()->AddIntegerItem("offset", offset);
120 const int bytesize = bitsize / 8;
121 switch (bytesize) {
122 case 2: {
123 Scalar value_scalar((uint16_t)value);
124 value_scalar.GetAsMemoryData(m_register_data.data() + offset,
125 bytesize, byte_order, error);
126 offset += bytesize;
127 } break;
128 case 4: {
129 Scalar value_scalar((uint32_t)value);
130 value_scalar.GetAsMemoryData(m_register_data.data() + offset,
131 bytesize, byte_order, error);
132 offset += bytesize;
133 } break;
134 case 8: {
135 Scalar value_scalar((uint64_t)value);
136 value_scalar.GetAsMemoryData(m_register_data.data() + offset,
137 bytesize, byte_order, error);
138 offset += bytesize;
139 } break;
140 }
141 return true;
142 });
143 }
144
145 // Create a DynamicRegisterInfo from the metadata JSON.
146 std::unique_ptr<DynamicRegisterInfo> additional_reginfo_up;
147 if (metadata_registers_dict)
148 additional_reginfo_up = DynamicRegisterInfo::Create(
149 *metadata_registers_dict, target.GetArchitecture());
150
151 // Put the RegisterSet names in the constant string pool,
152 // to sidestep lifetime issues of char*'s.
153 auto copy_regset_name = [](RegisterSet &dst, const RegisterSet &src) {
154 dst.name = ConstString(src.name).AsCString();
155 if (src.short_name)
156 dst.short_name = ConstString(src.short_name).AsCString();
157 else
158 dst.short_name = nullptr;
159 };
160
161 // Copy the core thread register sets into our combined register set list.
162 // RegisterSet indexes will be identical for the LC_THREAD RegisterContext.
163 for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterSetCount();
164 idx++) {
165 RegisterSet new_set;
166 const RegisterSet *old_set = core_thread_regctx_sp->GetRegisterSet(idx);
167 copy_regset_name(new_set, *old_set);
168 m_register_sets.push_back(new_set);
169 }
170
171 // Add any additional metadata RegisterSets to our combined RegisterSet array.
172 if (additional_reginfo_up) {
173 for (size_t idx = 0; idx < additional_reginfo_up->GetNumRegisterSets();
174 idx++) {
175 // See if this metadata RegisterSet name matches one already present
176 // from the LC_THREAD RegisterContext.
177 bool found_match = false;
178 const RegisterSet *old_set = additional_reginfo_up->GetRegisterSet(idx);
179 for (size_t jdx = 0; jdx < m_register_sets.size(); jdx++) {
180 if (strcmp(m_register_sets[jdx].name, old_set->name) == 0) {
181 metadata_regset_to_combined_regset[idx] = jdx;
182 found_match = true;
183 break;
184 }
185 }
186 // This metadata RegisterSet is a new one.
187 // Add it to the combined RegisterSet array.
188 if (!found_match) {
189 RegisterSet new_set;
190 copy_regset_name(new_set, *old_set);
191 metadata_regset_to_combined_regset[idx] = m_register_sets.size();
192 m_register_sets.push_back(new_set);
193 }
194 }
195 }
196
197 // Set up our combined RegisterInfo array, one RegisterSet at a time.
198 for (size_t combined_regset_idx = 0;
199 combined_regset_idx < m_register_sets.size(); combined_regset_idx++) {
200 uint32_t registers_this_regset = 0;
201
202 // Copy all LC_THREAD RegisterInfos that have a value into our
203 // combined RegisterInfo array. (the LC_THREAD RegisterContext
204 // may describe registers that were not provided in this thread)
205 //
206 // LC_THREAD register set indexes are identical to the combined
207 // register set indexes. The combined register set array may have
208 // additional entries.
209 if (combined_regset_idx < core_thread_regctx_sp->GetRegisterSetCount()) {
210 const RegisterSet *regset =
211 core_thread_regctx_sp->GetRegisterSet(combined_regset_idx);
212 // Copy all the registers that have values in.
213 for (size_t j = 0; j < regset->num_registers; j++) {
214 uint32_t reg_idx = regset->registers[j];
215 const RegisterInfo *reginfo =
216 core_thread_regctx_sp->GetRegisterInfoAtIndex(reg_idx);
217 RegisterValue val;
218 if (!reginfo->value_regs &&
219 core_thread_regctx_sp->ReadRegister(reginfo, val)) {
220 m_regset_regnum_collection[combined_regset_idx].push_back(
221 m_register_infos.size());
222 m_register_infos.push_back(*reginfo);
223 registers_this_regset++;
224 }
225 }
226 }
227
228 // Copy all the metadata RegisterInfos into our combined combined
229 // RegisterInfo array.
230 // The metadata may add registers to one of the LC_THREAD register sets,
231 // or its own newly added register sets. metadata_regset_to_combined_regset
232 // has the association of the RegisterSet indexes between the two.
233 if (additional_reginfo_up) {
234 // Find the register set in the metadata that matches this register
235 // set, then copy all its RegisterInfos.
236 for (size_t setidx = 0;
237 setidx < additional_reginfo_up->GetNumRegisterSets(); setidx++) {
238 if (metadata_regset_to_combined_regset[setidx] == combined_regset_idx) {
239 const RegisterSet *regset =
240 additional_reginfo_up->GetRegisterSet(setidx);
241 for (size_t j = 0; j < regset->num_registers; j++) {
242 uint32_t reg_idx = regset->registers[j];
243 const RegisterInfo *reginfo =
244 additional_reginfo_up->GetRegisterInfoAtIndex(reg_idx);
245 m_regset_regnum_collection[combined_regset_idx].push_back(
246 m_register_infos.size());
247 m_register_infos.push_back(*reginfo);
248 registers_this_regset++;
249 }
250 }
251 }
252 }
253 m_register_sets[combined_regset_idx].num_registers = registers_this_regset;
254 m_register_sets[combined_regset_idx].registers =
255 m_regset_regnum_collection[combined_regset_idx].data();
256 }
257}
258
262
263const RegisterInfo *
265 if (reg < m_register_infos.size())
266 return &m_register_infos[reg];
267 return nullptr;
268}
269
273
275 if (set < m_register_sets.size())
276 return &m_register_sets[set];
277 return nullptr;
278}
279
281 const lldb_private::RegisterInfo *reg_info,
283 if (!reg_info)
284 return false;
285 if (ProcessSP process_sp = m_thread.GetProcess()) {
286 DataExtractor regdata(m_register_data.data(), m_register_data.size(),
287 process_sp->GetByteOrder(),
288 process_sp->GetAddressByteSize());
289 offset_t offset = reg_info->byte_offset;
290 switch (reg_info->byte_size) {
291 case 2:
292 value.SetUInt16(regdata.GetU16(&offset));
293 break;
294 case 4:
295 value.SetUInt32(regdata.GetU32(&offset));
296 break;
297 case 8:
298 value.SetUInt64(regdata.GetU64(&offset));
299 break;
300 default:
301 return false;
302 }
303 return true;
304 }
305 return false;
306}
307
309 const lldb_private::RegisterInfo *reg_info,
310 const lldb_private::RegisterValue &value) {
311 return false;
312}
static llvm::raw_ostream & error(Stream &strm)
A uniqued constant string class.
Definition ConstString.h:40
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
An data extractor class.
uint64_t GetU64(lldb::offset_t *offset_ptr) const
Extract a uint64_t value from *offset_ptr.
uint32_t GetU32(lldb::offset_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
uint16_t GetU16(lldb::offset_t *offset_ptr) const
Extract a uint16_t value from *offset_ptr.
static std::unique_ptr< DynamicRegisterInfo > Create(const StructuredData::Dictionary &dict, const ArchSpec &arch)
const lldb_private::RegisterSet * GetRegisterSet(size_t set) override
bool ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value) override
std::vector< lldb_private::RegisterInfo > m_register_infos
std::vector< lldb_private::RegisterSet > m_register_sets
bool WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value) override
const lldb_private::RegisterInfo * GetRegisterInfoAtIndex(size_t reg) override
RegisterContextUnifiedCore(Thread &thread, uint32_t concrete_frame_idx, lldb::RegisterContextSP core_thread_regctx_sp, lldb_private::StructuredData::ObjectSP metadata_thread_registers)
std::vector< uint8_t > m_register_data
Bytes of the register contents.
std::map< size_t, std::vector< uint32_t > > m_regset_regnum_collection
For each register set, an array of register numbers included.
RegisterContext(Thread &thread, uint32_t concrete_frame_idx)
void SetUInt64(uint64_t uint, Type t=eTypeUInt64)
void SetUInt16(uint16_t uint)
const void * GetBytes() const
void SetUInt32(uint32_t uint, Type t=eTypeUInt32)
size_t GetAsMemoryData(void *dst, size_t dst_len, lldb::ByteOrder dst_byte_order, Status &error) const
Definition Scalar.cpp:788
An error handling class.
Definition Status.h:118
bool ForEach(std::function< bool(Object *object)> const &foreach_callback) const
bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result) const
void AddIntegerItem(llvm::StringRef key, T value)
ObjectSP GetValueForKey(llvm::StringRef key) const
bool HasKey(llvm::StringRef key) const
bool GetValueForKeyAsArray(llvm::StringRef key, Array *&result) const
std::shared_ptr< Object > ObjectSP
const ArchSpec & GetArchitecture() const
Definition Target.h:1056
A class that represents a running process on the host machine.
uint64_t offset_t
Definition lldb-types.h:85
std::shared_ptr< lldb_private::Process > ProcessSP
ByteOrder
Byte ordering definitions.
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
Every register is described in detail including its name, alternate name (optional),...
uint32_t * value_regs
List of registers (terminated with LLDB_INVALID_REGNUM).
uint32_t byte_offset
The byte offset in the register context data where this register's value is found.
uint32_t byte_size
Size in bytes of the register.
Registers are grouped into register sets.
size_t num_registers
The number of registers in REGISTERS array below.
const uint32_t * registers
An array of register indices in this set.
const char * name
Name of this register set.
const char * short_name
A short name for this register set.