1 | //===-- NativeRegisterContext.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 | |
9 | #include "lldb/Host/common/NativeRegisterContext.h" |
10 | #include "lldb/Utility/LLDBLog.h" |
11 | #include "lldb/Utility/RegisterValue.h" |
12 | |
13 | #include "lldb/Host/PosixApi.h" |
14 | #include "lldb/Host/common/NativeProcessProtocol.h" |
15 | #include "lldb/Host/common/NativeThreadProtocol.h" |
16 | |
17 | using namespace lldb; |
18 | using namespace lldb_private; |
19 | |
20 | NativeRegisterContext::NativeRegisterContext(NativeThreadProtocol &thread) |
21 | : m_thread(thread) {} |
22 | |
23 | // Destructor |
24 | NativeRegisterContext::~NativeRegisterContext() = default; |
25 | |
26 | // FIXME revisit invalidation, process stop ids, etc. Right now we don't |
27 | // support caching in NativeRegisterContext. We can do this later by utilizing |
28 | // NativeProcessProtocol::GetStopID () and adding a stop id to |
29 | // NativeRegisterContext. |
30 | |
31 | // void |
32 | // NativeRegisterContext::InvalidateIfNeeded (bool force) { |
33 | // ProcessSP process_sp (m_thread.GetProcess()); |
34 | // bool invalidate = force; |
35 | // uint32_t process_stop_id = UINT32_MAX; |
36 | |
37 | // if (process_sp) |
38 | // process_stop_id = process_sp->GetStopID(); |
39 | // else |
40 | // invalidate = true; |
41 | |
42 | // if (!invalidate) |
43 | // invalidate = process_stop_id != GetStopID(); |
44 | |
45 | // if (invalidate) |
46 | // { |
47 | // InvalidateAllRegisters (); |
48 | // SetStopID (process_stop_id); |
49 | // } |
50 | // } |
51 | |
52 | const RegisterInfo * |
53 | NativeRegisterContext::GetRegisterInfoByName(llvm::StringRef reg_name, |
54 | uint32_t start_idx) { |
55 | if (reg_name.empty()) |
56 | return nullptr; |
57 | |
58 | // Generic register names take precedence over specific register names. |
59 | // For example, on x86 we want "sp" to refer to the complete RSP/ESP register |
60 | // rather than the 16-bit SP pseudo-register. |
61 | uint32_t generic_reg = Args::StringToGenericRegister(s: reg_name); |
62 | if (generic_reg != LLDB_INVALID_REGNUM) { |
63 | const RegisterInfo *reg_info = |
64 | GetRegisterInfo(reg_kind: eRegisterKindGeneric, reg_num: generic_reg); |
65 | if (reg_info) |
66 | return reg_info; |
67 | } |
68 | |
69 | const uint32_t num_registers = GetRegisterCount(); |
70 | for (uint32_t reg = start_idx; reg < num_registers; ++reg) { |
71 | const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); |
72 | |
73 | if (reg_name.equals_insensitive(RHS: reg_info->name) || |
74 | reg_name.equals_insensitive(RHS: reg_info->alt_name)) |
75 | return reg_info; |
76 | } |
77 | |
78 | return nullptr; |
79 | } |
80 | |
81 | const RegisterInfo *NativeRegisterContext::GetRegisterInfo(uint32_t kind, |
82 | uint32_t num) { |
83 | const uint32_t reg_num = ConvertRegisterKindToRegisterNumber(kind, num); |
84 | if (reg_num == LLDB_INVALID_REGNUM) |
85 | return nullptr; |
86 | return GetRegisterInfoAtIndex(reg: reg_num); |
87 | } |
88 | |
89 | const char *NativeRegisterContext::GetRegisterName(uint32_t reg) { |
90 | const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); |
91 | if (reg_info) |
92 | return reg_info->name; |
93 | return nullptr; |
94 | } |
95 | |
96 | const char *NativeRegisterContext::GetRegisterSetNameForRegisterAtIndex( |
97 | uint32_t reg_index) const { |
98 | const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg: reg_index); |
99 | if (!reg_info) |
100 | return nullptr; |
101 | |
102 | for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index) { |
103 | const RegisterSet *const reg_set = GetRegisterSet(set_index); |
104 | if (!reg_set) |
105 | continue; |
106 | |
107 | for (uint32_t reg_num_index = 0; reg_num_index < reg_set->num_registers; |
108 | ++reg_num_index) { |
109 | const uint32_t reg_num = reg_set->registers[reg_num_index]; |
110 | // FIXME double check we're checking the right register kind here. |
111 | if (reg_info->kinds[RegisterKind::eRegisterKindLLDB] == reg_num) { |
112 | // The given register is a member of this register set. Return the |
113 | // register set name. |
114 | return reg_set->name; |
115 | } |
116 | } |
117 | } |
118 | |
119 | // Didn't find it. |
120 | return nullptr; |
121 | } |
122 | |
123 | lldb::addr_t NativeRegisterContext::GetPC(lldb::addr_t fail_value) { |
124 | Log *log = GetLog(mask: LLDBLog::Thread); |
125 | |
126 | uint32_t reg = ConvertRegisterKindToRegisterNumber(kind: eRegisterKindGeneric, |
127 | LLDB_REGNUM_GENERIC_PC); |
128 | LLDB_LOGF(log, "Using reg index %" PRIu32 " (default %" PRIu64 ")" , reg, |
129 | fail_value); |
130 | |
131 | const uint64_t retval = ReadRegisterAsUnsigned(reg, fail_value); |
132 | |
133 | LLDB_LOGF(log, PRIu32 " retval %" PRIu64, retval); |
134 | |
135 | return retval; |
136 | } |
137 | |
138 | lldb::addr_t |
139 | NativeRegisterContext::GetPCfromBreakpointLocation(lldb::addr_t fail_value) { |
140 | return GetPC(fail_value); |
141 | } |
142 | |
143 | Status NativeRegisterContext::SetPC(lldb::addr_t pc) { |
144 | uint32_t reg = ConvertRegisterKindToRegisterNumber(kind: eRegisterKindGeneric, |
145 | LLDB_REGNUM_GENERIC_PC); |
146 | return WriteRegisterFromUnsigned(reg, uval: pc); |
147 | } |
148 | |
149 | lldb::addr_t NativeRegisterContext::GetSP(lldb::addr_t fail_value) { |
150 | uint32_t reg = ConvertRegisterKindToRegisterNumber(kind: eRegisterKindGeneric, |
151 | LLDB_REGNUM_GENERIC_SP); |
152 | return ReadRegisterAsUnsigned(reg, fail_value); |
153 | } |
154 | |
155 | Status NativeRegisterContext::SetSP(lldb::addr_t sp) { |
156 | uint32_t reg = ConvertRegisterKindToRegisterNumber(kind: eRegisterKindGeneric, |
157 | LLDB_REGNUM_GENERIC_SP); |
158 | return WriteRegisterFromUnsigned(reg, uval: sp); |
159 | } |
160 | |
161 | lldb::addr_t NativeRegisterContext::GetFP(lldb::addr_t fail_value) { |
162 | uint32_t reg = ConvertRegisterKindToRegisterNumber(kind: eRegisterKindGeneric, |
163 | LLDB_REGNUM_GENERIC_FP); |
164 | return ReadRegisterAsUnsigned(reg, fail_value); |
165 | } |
166 | |
167 | Status NativeRegisterContext::SetFP(lldb::addr_t fp) { |
168 | uint32_t reg = ConvertRegisterKindToRegisterNumber(kind: eRegisterKindGeneric, |
169 | LLDB_REGNUM_GENERIC_FP); |
170 | return WriteRegisterFromUnsigned(reg, uval: fp); |
171 | } |
172 | |
173 | lldb::addr_t NativeRegisterContext::GetReturnAddress(lldb::addr_t fail_value) { |
174 | uint32_t reg = ConvertRegisterKindToRegisterNumber(kind: eRegisterKindGeneric, |
175 | LLDB_REGNUM_GENERIC_RA); |
176 | return ReadRegisterAsUnsigned(reg, fail_value); |
177 | } |
178 | |
179 | lldb::addr_t NativeRegisterContext::GetFlags(lldb::addr_t fail_value) { |
180 | uint32_t reg = ConvertRegisterKindToRegisterNumber(kind: eRegisterKindGeneric, |
181 | LLDB_REGNUM_GENERIC_FLAGS); |
182 | return ReadRegisterAsUnsigned(reg, fail_value); |
183 | } |
184 | |
185 | lldb::addr_t |
186 | NativeRegisterContext::ReadRegisterAsUnsigned(uint32_t reg, |
187 | lldb::addr_t fail_value) { |
188 | if (reg != LLDB_INVALID_REGNUM) |
189 | return ReadRegisterAsUnsigned(reg_info: GetRegisterInfoAtIndex(reg), fail_value); |
190 | return fail_value; |
191 | } |
192 | |
193 | uint64_t |
194 | NativeRegisterContext::ReadRegisterAsUnsigned(const RegisterInfo *reg_info, |
195 | lldb::addr_t fail_value) { |
196 | Log *log = GetLog(mask: LLDBLog::Thread); |
197 | |
198 | if (reg_info) { |
199 | RegisterValue value; |
200 | Status error = ReadRegister(reg_info, reg_value&: value); |
201 | if (error.Success()) { |
202 | LLDB_LOGF(log, |
203 | "Read register succeeded: value " |
204 | "%" PRIu64, |
205 | value.GetAsUInt64()); |
206 | return value.GetAsUInt64(); |
207 | } else { |
208 | LLDB_LOGF(log, "Read register failed: error %s" , error.AsCString()); |
209 | } |
210 | } else { |
211 | LLDB_LOGF(log, "Read register failed: null reg_info" ); |
212 | } |
213 | return fail_value; |
214 | } |
215 | |
216 | Status NativeRegisterContext::WriteRegisterFromUnsigned(uint32_t reg, |
217 | uint64_t uval) { |
218 | if (reg == LLDB_INVALID_REGNUM) |
219 | return Status("Write register failed: reg is invalid" ); |
220 | return WriteRegisterFromUnsigned(reg_info: GetRegisterInfoAtIndex(reg), uval); |
221 | } |
222 | |
223 | Status |
224 | NativeRegisterContext::WriteRegisterFromUnsigned(const RegisterInfo *reg_info, |
225 | uint64_t uval) { |
226 | assert(reg_info); |
227 | if (!reg_info) |
228 | return Status("reg_info is nullptr" ); |
229 | |
230 | RegisterValue value; |
231 | if (!value.SetUInt(uint: uval, byte_size: reg_info->byte_size)) |
232 | return Status("RegisterValue::SetUInt () failed" ); |
233 | |
234 | return WriteRegister(reg_info, reg_value: value); |
235 | } |
236 | |
237 | lldb::tid_t NativeRegisterContext::GetThreadID() const { |
238 | return m_thread.GetID(); |
239 | } |
240 | |
241 | uint32_t NativeRegisterContext::NumSupportedHardwareBreakpoints() { return 0; } |
242 | |
243 | uint32_t NativeRegisterContext::SetHardwareBreakpoint(lldb::addr_t addr, |
244 | size_t size) { |
245 | return LLDB_INVALID_INDEX32; |
246 | } |
247 | |
248 | Status NativeRegisterContext::ClearAllHardwareBreakpoints() { |
249 | return Status("not implemented" ); |
250 | } |
251 | |
252 | bool NativeRegisterContext::ClearHardwareBreakpoint(uint32_t hw_idx) { |
253 | return false; |
254 | } |
255 | |
256 | Status NativeRegisterContext::GetHardwareBreakHitIndex(uint32_t &bp_index, |
257 | lldb::addr_t trap_addr) { |
258 | bp_index = LLDB_INVALID_INDEX32; |
259 | return Status("not implemented" ); |
260 | } |
261 | |
262 | uint32_t NativeRegisterContext::NumSupportedHardwareWatchpoints() { return 0; } |
263 | |
264 | uint32_t NativeRegisterContext::SetHardwareWatchpoint(lldb::addr_t addr, |
265 | size_t size, |
266 | uint32_t watch_flags) { |
267 | return LLDB_INVALID_INDEX32; |
268 | } |
269 | |
270 | bool NativeRegisterContext::ClearHardwareWatchpoint(uint32_t hw_index) { |
271 | return false; |
272 | } |
273 | |
274 | Status NativeRegisterContext::ClearWatchpointHit(uint32_t hw_index) { |
275 | return Status("not implemented" ); |
276 | } |
277 | |
278 | Status NativeRegisterContext::ClearAllHardwareWatchpoints() { |
279 | return Status("not implemented" ); |
280 | } |
281 | |
282 | Status NativeRegisterContext::IsWatchpointHit(uint32_t wp_index, bool &is_hit) { |
283 | is_hit = false; |
284 | return Status("not implemented" ); |
285 | } |
286 | |
287 | Status NativeRegisterContext::GetWatchpointHitIndex(uint32_t &wp_index, |
288 | lldb::addr_t trap_addr) { |
289 | wp_index = LLDB_INVALID_INDEX32; |
290 | return Status("not implemented" ); |
291 | } |
292 | |
293 | Status NativeRegisterContext::IsWatchpointVacant(uint32_t wp_index, |
294 | bool &is_vacant) { |
295 | is_vacant = false; |
296 | return Status("not implemented" ); |
297 | } |
298 | |
299 | lldb::addr_t NativeRegisterContext::GetWatchpointAddress(uint32_t wp_index) { |
300 | return LLDB_INVALID_ADDRESS; |
301 | } |
302 | |
303 | lldb::addr_t NativeRegisterContext::GetWatchpointHitAddress(uint32_t wp_index) { |
304 | return LLDB_INVALID_ADDRESS; |
305 | } |
306 | |
307 | bool NativeRegisterContext::HardwareSingleStep(bool enable) { return false; } |
308 | |
309 | Status NativeRegisterContext::ReadRegisterValueFromMemory( |
310 | const RegisterInfo *reg_info, lldb::addr_t src_addr, size_t src_len, |
311 | RegisterValue ®_value) { |
312 | Status error; |
313 | if (reg_info == nullptr) { |
314 | error.SetErrorString("invalid register info argument." ); |
315 | return error; |
316 | } |
317 | |
318 | // Moving from addr into a register |
319 | // |
320 | // Case 1: src_len == dst_len |
321 | // |
322 | // |AABBCCDD| Address contents |
323 | // |AABBCCDD| Register contents |
324 | // |
325 | // Case 2: src_len > dst_len |
326 | // |
327 | // Status! (The register should always be big enough to hold the data) |
328 | // |
329 | // Case 3: src_len < dst_len |
330 | // |
331 | // |AABB| Address contents |
332 | // |AABB0000| Register contents [on little-endian hardware] |
333 | // |0000AABB| Register contents [on big-endian hardware] |
334 | const size_t dst_len = reg_info->byte_size; |
335 | |
336 | if (src_len > dst_len) { |
337 | error.SetErrorStringWithFormat( |
338 | "%" PRIu64 " bytes is too big to store in register %s (%" PRIu64 |
339 | " bytes)" , |
340 | static_cast<uint64_t>(src_len), reg_info->name, |
341 | static_cast<uint64_t>(dst_len)); |
342 | return error; |
343 | } |
344 | |
345 | NativeProcessProtocol &process = m_thread.GetProcess(); |
346 | RegisterValue::BytesContainer src(src_len); |
347 | |
348 | // Read the memory |
349 | size_t bytes_read; |
350 | error = process.ReadMemory(addr: src_addr, buf: src.data(), size: src_len, bytes_read); |
351 | if (error.Fail()) |
352 | return error; |
353 | |
354 | // Make sure the memory read succeeded... |
355 | if (bytes_read != src_len) { |
356 | // This might happen if we read _some_ bytes but not all |
357 | error.SetErrorStringWithFormat("read %" PRIu64 " of %" PRIu64 " bytes" , |
358 | static_cast<uint64_t>(bytes_read), |
359 | static_cast<uint64_t>(src_len)); |
360 | return error; |
361 | } |
362 | |
363 | // We now have a memory buffer that contains the part or all of the register |
364 | // value. Set the register value using this memory data. |
365 | // TODO: we might need to add a parameter to this function in case the byte |
366 | // order of the memory data doesn't match the process. For now we are |
367 | // assuming they are the same. |
368 | reg_value.SetFromMemoryData(reg_info: *reg_info, src: src.data(), src_len, |
369 | src_byte_order: process.GetByteOrder(), error); |
370 | |
371 | return error; |
372 | } |
373 | |
374 | Status NativeRegisterContext::WriteRegisterValueToMemory( |
375 | const RegisterInfo *reg_info, lldb::addr_t dst_addr, size_t dst_len, |
376 | const RegisterValue ®_value) { |
377 | Status error; |
378 | if (reg_info == nullptr) { |
379 | error.SetErrorString("Invalid register info argument." ); |
380 | return error; |
381 | } |
382 | |
383 | RegisterValue::BytesContainer dst(dst_len); |
384 | NativeProcessProtocol &process = m_thread.GetProcess(); |
385 | |
386 | // TODO: we might need to add a parameter to this function in case the byte |
387 | // order of the memory data doesn't match the process. For now we are |
388 | // assuming they are the same. |
389 | const size_t bytes_copied = reg_value.GetAsMemoryData( |
390 | reg_info: *reg_info, dst: dst.data(), dst_len, dst_byte_order: process.GetByteOrder(), error); |
391 | |
392 | if (error.Success()) { |
393 | if (bytes_copied == 0) { |
394 | error.SetErrorString("byte copy failed." ); |
395 | } else { |
396 | size_t bytes_written; |
397 | error = process.WriteMemory(addr: dst_addr, buf: dst.data(), size: bytes_copied, |
398 | bytes_written); |
399 | if (error.Fail()) |
400 | return error; |
401 | |
402 | if (bytes_written != bytes_copied) { |
403 | // This might happen if we read _some_ bytes but not all |
404 | error.SetErrorStringWithFormat("only wrote %" PRIu64 " of %" PRIu64 |
405 | " bytes" , |
406 | static_cast<uint64_t>(bytes_written), |
407 | static_cast<uint64_t>(bytes_copied)); |
408 | } |
409 | } |
410 | } |
411 | |
412 | return error; |
413 | } |
414 | |
415 | uint32_t |
416 | NativeRegisterContext::ConvertRegisterKindToRegisterNumber(uint32_t kind, |
417 | uint32_t num) const { |
418 | const uint32_t num_regs = GetRegisterCount(); |
419 | |
420 | assert(kind < kNumRegisterKinds); |
421 | for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) { |
422 | const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg: reg_idx); |
423 | |
424 | if (reg_info->kinds[kind] == num) |
425 | return reg_idx; |
426 | } |
427 | |
428 | return LLDB_INVALID_REGNUM; |
429 | } |
430 | |
431 | std::vector<uint32_t> |
432 | NativeRegisterContext::GetExpeditedRegisters(ExpeditedRegs expType) const { |
433 | if (expType == ExpeditedRegs::Minimal) { |
434 | // Expedite only a minimum set of important generic registers. |
435 | static const uint32_t k_expedited_registers[] = { |
436 | LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_SP, LLDB_REGNUM_GENERIC_FP, |
437 | LLDB_REGNUM_GENERIC_RA}; |
438 | |
439 | std::vector<uint32_t> expedited_reg_nums; |
440 | for (uint32_t gen_reg : k_expedited_registers) { |
441 | uint32_t reg_num = |
442 | ConvertRegisterKindToRegisterNumber(kind: eRegisterKindGeneric, num: gen_reg); |
443 | if (reg_num == LLDB_INVALID_REGNUM) |
444 | continue; // Target does not support the given register. |
445 | else |
446 | expedited_reg_nums.push_back(x: reg_num); |
447 | } |
448 | |
449 | return expedited_reg_nums; |
450 | } |
451 | |
452 | if (GetRegisterSetCount() > 0 && expType == ExpeditedRegs::Full) |
453 | return std::vector<uint32_t>(GetRegisterSet(set_index: 0)->registers, |
454 | GetRegisterSet(set_index: 0)->registers + |
455 | GetRegisterSet(set_index: 0)->num_registers); |
456 | |
457 | return std::vector<uint32_t>(); |
458 | } |
459 | |