/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Core/EmulateInstruction.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- EmulateInstruction.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/Core/EmulateInstruction.h" |
10 | | |
11 | | #include "lldb/Core/Address.h" |
12 | | #include "lldb/Core/DumpRegisterValue.h" |
13 | | #include "lldb/Core/PluginManager.h" |
14 | | #include "lldb/Host/StreamFile.h" |
15 | | #include "lldb/Symbol/UnwindPlan.h" |
16 | | #include "lldb/Target/Process.h" |
17 | | #include "lldb/Target/RegisterContext.h" |
18 | | #include "lldb/Target/StackFrame.h" |
19 | | #include "lldb/Utility/ConstString.h" |
20 | | #include "lldb/Utility/DataExtractor.h" |
21 | | #include "lldb/Utility/RegisterValue.h" |
22 | | #include "lldb/Utility/Status.h" |
23 | | #include "lldb/Utility/Stream.h" |
24 | | #include "lldb/Utility/StreamString.h" |
25 | | #include "lldb/lldb-forward.h" |
26 | | #include "lldb/lldb-private-interfaces.h" |
27 | | |
28 | | #include "llvm/ADT/StringRef.h" |
29 | | |
30 | | #include <cstring> |
31 | | #include <memory> |
32 | | #include <optional> |
33 | | |
34 | | #include <cinttypes> |
35 | | #include <cstdio> |
36 | | |
37 | | namespace lldb_private { |
38 | | class Target; |
39 | | } |
40 | | |
41 | | using namespace lldb; |
42 | | using namespace lldb_private; |
43 | | |
44 | | EmulateInstruction * |
45 | | EmulateInstruction::FindPlugin(const ArchSpec &arch, |
46 | | InstructionType supported_inst_type, |
47 | 16.9k | const char *plugin_name) { |
48 | 16.9k | EmulateInstructionCreateInstance create_callback = nullptr; |
49 | 16.9k | if (plugin_name) { |
50 | 0 | create_callback = |
51 | 0 | PluginManager::GetEmulateInstructionCreateCallbackForPluginName( |
52 | 0 | plugin_name); |
53 | 0 | if (create_callback) { |
54 | 0 | EmulateInstruction *emulate_insn_ptr = |
55 | 0 | create_callback(arch, supported_inst_type); |
56 | 0 | if (emulate_insn_ptr) |
57 | 0 | return emulate_insn_ptr; |
58 | 0 | } |
59 | 16.9k | } else { |
60 | 16.9k | for (uint32_t idx = 0; |
61 | 134k | (create_callback = |
62 | 134k | PluginManager::GetEmulateInstructionCreateCallbackAtIndex(idx)) != |
63 | 134k | nullptr; |
64 | 117k | ++idx117k ) { |
65 | 117k | EmulateInstruction *emulate_insn_ptr = |
66 | 117k | create_callback(arch, supported_inst_type); |
67 | 117k | if (emulate_insn_ptr) |
68 | 191 | return emulate_insn_ptr; |
69 | 117k | } |
70 | 16.9k | } |
71 | 16.7k | return nullptr; |
72 | 16.9k | } |
73 | | |
74 | 252 | EmulateInstruction::EmulateInstruction(const ArchSpec &arch) : m_arch(arch) {} |
75 | | |
76 | | std::optional<RegisterValue> |
77 | 1.22k | EmulateInstruction::ReadRegister(const RegisterInfo ®_info) { |
78 | 1.22k | if (m_read_reg_callback == nullptr) |
79 | 0 | return {}; |
80 | | |
81 | 1.22k | RegisterValue reg_value; |
82 | 1.22k | bool success = m_read_reg_callback(this, m_baton, ®_info, reg_value); |
83 | 1.22k | if (success) |
84 | 1.22k | return reg_value; |
85 | 0 | return {}; |
86 | 1.22k | } |
87 | | |
88 | | bool EmulateInstruction::ReadRegister(lldb::RegisterKind reg_kind, |
89 | | uint32_t reg_num, |
90 | 1.16k | RegisterValue ®_value) { |
91 | 1.16k | std::optional<RegisterInfo> reg_info = GetRegisterInfo(reg_kind, reg_num); |
92 | 1.16k | if (!reg_info) |
93 | 0 | return false; |
94 | | |
95 | 1.16k | std::optional<RegisterValue> value = ReadRegister(*reg_info); |
96 | 1.16k | if (value) |
97 | 1.16k | reg_value = *value; |
98 | 1.16k | return value.has_value(); |
99 | 1.16k | } |
100 | | |
101 | | uint64_t EmulateInstruction::ReadRegisterUnsigned(lldb::RegisterKind reg_kind, |
102 | | uint32_t reg_num, |
103 | | uint64_t fail_value, |
104 | 920 | bool *success_ptr) { |
105 | 920 | RegisterValue reg_value; |
106 | 920 | if (ReadRegister(reg_kind, reg_num, reg_value)) |
107 | 920 | return reg_value.GetAsUInt64(fail_value, success_ptr); |
108 | 0 | if (success_ptr) |
109 | 0 | *success_ptr = false; |
110 | 0 | return fail_value; |
111 | 920 | } |
112 | | |
113 | | uint64_t EmulateInstruction::ReadRegisterUnsigned(const RegisterInfo ®_info, |
114 | | uint64_t fail_value, |
115 | 17 | bool *success_ptr) { |
116 | 17 | std::optional<RegisterValue> reg_value = ReadRegister(reg_info); |
117 | 17 | if (!reg_value) { |
118 | 0 | if (success_ptr) |
119 | 0 | *success_ptr = false; |
120 | 0 | return fail_value; |
121 | 0 | } |
122 | | |
123 | 17 | return reg_value->GetAsUInt64(fail_value, success_ptr); |
124 | 17 | } |
125 | | |
126 | | bool EmulateInstruction::WriteRegister(const Context &context, |
127 | | const RegisterInfo ®_info, |
128 | 709 | const RegisterValue ®_value) { |
129 | 709 | if (m_write_reg_callback != nullptr) |
130 | 709 | return m_write_reg_callback(this, m_baton, context, ®_info, reg_value); |
131 | 0 | return false; |
132 | 709 | } |
133 | | |
134 | | bool EmulateInstruction::WriteRegister(const Context &context, |
135 | | lldb::RegisterKind reg_kind, |
136 | | uint32_t reg_num, |
137 | 121 | const RegisterValue ®_value) { |
138 | 121 | std::optional<RegisterInfo> reg_info = GetRegisterInfo(reg_kind, reg_num); |
139 | 121 | if (reg_info) |
140 | 121 | return WriteRegister(context, *reg_info, reg_value); |
141 | 0 | return false; |
142 | 121 | } |
143 | | |
144 | | bool EmulateInstruction::WriteRegisterUnsigned(const Context &context, |
145 | | lldb::RegisterKind reg_kind, |
146 | | uint32_t reg_num, |
147 | 516 | uint64_t uint_value) { |
148 | 516 | std::optional<RegisterInfo> reg_info = GetRegisterInfo(reg_kind, reg_num); |
149 | 516 | if (reg_info) { |
150 | 516 | RegisterValue reg_value; |
151 | 516 | if (reg_value.SetUInt(uint_value, reg_info->byte_size)) |
152 | 516 | return WriteRegister(context, *reg_info, reg_value); |
153 | 516 | } |
154 | 0 | return false; |
155 | 516 | } |
156 | | |
157 | | bool EmulateInstruction::WriteRegisterUnsigned(const Context &context, |
158 | | const RegisterInfo ®_info, |
159 | 24 | uint64_t uint_value) { |
160 | 24 | RegisterValue reg_value; |
161 | 24 | if (reg_value.SetUInt(uint_value, reg_info.byte_size)) |
162 | 24 | return WriteRegister(context, reg_info, reg_value); |
163 | 0 | return false; |
164 | 24 | } |
165 | | |
166 | | size_t EmulateInstruction::ReadMemory(const Context &context, lldb::addr_t addr, |
167 | 48 | void *dst, size_t dst_len) { |
168 | 48 | if (m_read_mem_callback != nullptr) |
169 | 48 | return m_read_mem_callback(this, m_baton, context, addr, dst, dst_len) == |
170 | 48 | dst_len; |
171 | 0 | return false; |
172 | 48 | } |
173 | | |
174 | | uint64_t EmulateInstruction::ReadMemoryUnsigned(const Context &context, |
175 | | lldb::addr_t addr, |
176 | | size_t byte_size, |
177 | | uint64_t fail_value, |
178 | 135 | bool *success_ptr) { |
179 | 135 | uint64_t uval64 = 0; |
180 | 135 | bool success = false; |
181 | 135 | if (byte_size <= 8) { |
182 | 135 | uint8_t buf[sizeof(uint64_t)]; |
183 | 135 | size_t bytes_read = |
184 | 135 | m_read_mem_callback(this, m_baton, context, addr, buf, byte_size); |
185 | 135 | if (bytes_read == byte_size) { |
186 | 135 | lldb::offset_t offset = 0; |
187 | 135 | DataExtractor data(buf, byte_size, GetByteOrder(), GetAddressByteSize()); |
188 | 135 | uval64 = data.GetMaxU64(&offset, byte_size); |
189 | 135 | success = true; |
190 | 135 | } |
191 | 135 | } |
192 | | |
193 | 135 | if (success_ptr) |
194 | 135 | *success_ptr = success; |
195 | | |
196 | 135 | if (!success) |
197 | 0 | uval64 = fail_value; |
198 | 135 | return uval64; |
199 | 135 | } |
200 | | |
201 | | bool EmulateInstruction::WriteMemoryUnsigned(const Context &context, |
202 | | lldb::addr_t addr, uint64_t uval, |
203 | 90 | size_t uval_byte_size) { |
204 | 90 | StreamString strm(Stream::eBinary, GetAddressByteSize(), GetByteOrder()); |
205 | 90 | strm.PutMaxHex64(uval, uval_byte_size); |
206 | | |
207 | 90 | size_t bytes_written = m_write_mem_callback( |
208 | 90 | this, m_baton, context, addr, strm.GetString().data(), uval_byte_size); |
209 | 90 | return (bytes_written == uval_byte_size); |
210 | 90 | } |
211 | | |
212 | | bool EmulateInstruction::WriteMemory(const Context &context, lldb::addr_t addr, |
213 | 47 | const void *src, size_t src_len) { |
214 | 47 | if (m_write_mem_callback != nullptr) |
215 | 47 | return m_write_mem_callback(this, m_baton, context, addr, src, src_len) == |
216 | 47 | src_len; |
217 | 0 | return false; |
218 | 47 | } |
219 | | |
220 | 191 | void EmulateInstruction::SetBaton(void *baton) { m_baton = baton; } |
221 | | |
222 | | void EmulateInstruction::SetCallbacks( |
223 | | ReadMemoryCallback read_mem_callback, |
224 | | WriteMemoryCallback write_mem_callback, |
225 | | ReadRegisterCallback read_reg_callback, |
226 | 191 | WriteRegisterCallback write_reg_callback) { |
227 | 191 | m_read_mem_callback = read_mem_callback; |
228 | 191 | m_write_mem_callback = write_mem_callback; |
229 | 191 | m_read_reg_callback = read_reg_callback; |
230 | 191 | m_write_reg_callback = write_reg_callback; |
231 | 191 | } |
232 | | |
233 | | void EmulateInstruction::SetReadMemCallback( |
234 | 37 | ReadMemoryCallback read_mem_callback) { |
235 | 37 | m_read_mem_callback = read_mem_callback; |
236 | 37 | } |
237 | | |
238 | | void EmulateInstruction::SetWriteMemCallback( |
239 | 37 | WriteMemoryCallback write_mem_callback) { |
240 | 37 | m_write_mem_callback = write_mem_callback; |
241 | 37 | } |
242 | | |
243 | | void EmulateInstruction::SetReadRegCallback( |
244 | 60 | ReadRegisterCallback read_reg_callback) { |
245 | 60 | m_read_reg_callback = read_reg_callback; |
246 | 60 | } |
247 | | |
248 | | void EmulateInstruction::SetWriteRegCallback( |
249 | 60 | WriteRegisterCallback write_reg_callback) { |
250 | 60 | m_write_reg_callback = write_reg_callback; |
251 | 60 | } |
252 | | |
253 | | // |
254 | | // Read & Write Memory and Registers callback functions. |
255 | | // |
256 | | |
257 | | size_t EmulateInstruction::ReadMemoryFrame(EmulateInstruction *instruction, |
258 | | void *baton, const Context &context, |
259 | | lldb::addr_t addr, void *dst, |
260 | 0 | size_t dst_len) { |
261 | 0 | if (baton == nullptr || dst == nullptr || dst_len == 0) |
262 | 0 | return 0; |
263 | | |
264 | 0 | StackFrame *frame = (StackFrame *)baton; |
265 | |
|
266 | 0 | ProcessSP process_sp(frame->CalculateProcess()); |
267 | 0 | if (process_sp) { |
268 | 0 | Status error; |
269 | 0 | return process_sp->ReadMemory(addr, dst, dst_len, error); |
270 | 0 | } |
271 | 0 | return 0; |
272 | 0 | } |
273 | | |
274 | | size_t EmulateInstruction::WriteMemoryFrame(EmulateInstruction *instruction, |
275 | | void *baton, const Context &context, |
276 | | lldb::addr_t addr, const void *src, |
277 | 0 | size_t src_len) { |
278 | 0 | if (baton == nullptr || src == nullptr || src_len == 0) |
279 | 0 | return 0; |
280 | | |
281 | 0 | StackFrame *frame = (StackFrame *)baton; |
282 | |
|
283 | 0 | ProcessSP process_sp(frame->CalculateProcess()); |
284 | 0 | if (process_sp) { |
285 | 0 | Status error; |
286 | 0 | return process_sp->WriteMemory(addr, src, src_len, error); |
287 | 0 | } |
288 | | |
289 | 0 | return 0; |
290 | 0 | } |
291 | | |
292 | | bool EmulateInstruction::ReadRegisterFrame(EmulateInstruction *instruction, |
293 | | void *baton, |
294 | | const RegisterInfo *reg_info, |
295 | 0 | RegisterValue ®_value) { |
296 | 0 | if (baton == nullptr) |
297 | 0 | return false; |
298 | | |
299 | 0 | StackFrame *frame = (StackFrame *)baton; |
300 | 0 | return frame->GetRegisterContext()->ReadRegister(reg_info, reg_value); |
301 | 0 | } |
302 | | |
303 | | bool EmulateInstruction::WriteRegisterFrame(EmulateInstruction *instruction, |
304 | | void *baton, const Context &context, |
305 | | const RegisterInfo *reg_info, |
306 | 0 | const RegisterValue ®_value) { |
307 | 0 | if (baton == nullptr) |
308 | 0 | return false; |
309 | | |
310 | 0 | StackFrame *frame = (StackFrame *)baton; |
311 | 0 | return frame->GetRegisterContext()->WriteRegister(reg_info, reg_value); |
312 | 0 | } |
313 | | |
314 | | size_t EmulateInstruction::ReadMemoryDefault(EmulateInstruction *instruction, |
315 | | void *baton, |
316 | | const Context &context, |
317 | | lldb::addr_t addr, void *dst, |
318 | 0 | size_t length) { |
319 | 0 | StreamFile strm(stdout, false); |
320 | 0 | strm.Printf(" Read from Memory (address = 0x%" PRIx64 ", length = %" PRIu64 |
321 | 0 | ", context = ", |
322 | 0 | addr, (uint64_t)length); |
323 | 0 | context.Dump(strm, instruction); |
324 | 0 | strm.EOL(); |
325 | 0 | *((uint64_t *)dst) = 0xdeadbeef; |
326 | 0 | return length; |
327 | 0 | } |
328 | | |
329 | | size_t EmulateInstruction::WriteMemoryDefault(EmulateInstruction *instruction, |
330 | | void *baton, |
331 | | const Context &context, |
332 | | lldb::addr_t addr, |
333 | 0 | const void *dst, size_t length) { |
334 | 0 | StreamFile strm(stdout, false); |
335 | 0 | strm.Printf(" Write to Memory (address = 0x%" PRIx64 ", length = %" PRIu64 |
336 | 0 | ", context = ", |
337 | 0 | addr, (uint64_t)length); |
338 | 0 | context.Dump(strm, instruction); |
339 | 0 | strm.EOL(); |
340 | 0 | return length; |
341 | 0 | } |
342 | | |
343 | | bool EmulateInstruction::ReadRegisterDefault(EmulateInstruction *instruction, |
344 | | void *baton, |
345 | | const RegisterInfo *reg_info, |
346 | 0 | RegisterValue ®_value) { |
347 | 0 | StreamFile strm(stdout, false); |
348 | 0 | strm.Printf(" Read Register (%s)\n", reg_info->name); |
349 | 0 | lldb::RegisterKind reg_kind; |
350 | 0 | uint32_t reg_num; |
351 | 0 | if (GetBestRegisterKindAndNumber(reg_info, reg_kind, reg_num)) |
352 | 0 | reg_value.SetUInt64((uint64_t)reg_kind << 24 | reg_num); |
353 | 0 | else |
354 | 0 | reg_value.SetUInt64(0); |
355 | |
|
356 | 0 | return true; |
357 | 0 | } |
358 | | |
359 | | bool EmulateInstruction::WriteRegisterDefault(EmulateInstruction *instruction, |
360 | | void *baton, |
361 | | const Context &context, |
362 | | const RegisterInfo *reg_info, |
363 | 0 | const RegisterValue ®_value) { |
364 | 0 | StreamFile strm(stdout, false); |
365 | 0 | strm.Printf(" Write to Register (name = %s, value = ", reg_info->name); |
366 | 0 | DumpRegisterValue(reg_value, strm, *reg_info, false, false, eFormatDefault); |
367 | 0 | strm.PutCString(", context = "); |
368 | 0 | context.Dump(strm, instruction); |
369 | 0 | strm.EOL(); |
370 | 0 | return true; |
371 | 0 | } |
372 | | |
373 | | void EmulateInstruction::Context::Dump(Stream &strm, |
374 | 0 | EmulateInstruction *instruction) const { |
375 | 0 | switch (type) { |
376 | 0 | case eContextReadOpcode: |
377 | 0 | strm.PutCString("reading opcode"); |
378 | 0 | break; |
379 | | |
380 | 0 | case eContextImmediate: |
381 | 0 | strm.PutCString("immediate"); |
382 | 0 | break; |
383 | | |
384 | 0 | case eContextPushRegisterOnStack: |
385 | 0 | strm.PutCString("push register"); |
386 | 0 | break; |
387 | | |
388 | 0 | case eContextPopRegisterOffStack: |
389 | 0 | strm.PutCString("pop register"); |
390 | 0 | break; |
391 | | |
392 | 0 | case eContextAdjustStackPointer: |
393 | 0 | strm.PutCString("adjust sp"); |
394 | 0 | break; |
395 | | |
396 | 0 | case eContextSetFramePointer: |
397 | 0 | strm.PutCString("set frame pointer"); |
398 | 0 | break; |
399 | | |
400 | 0 | case eContextAdjustBaseRegister: |
401 | 0 | strm.PutCString("adjusting (writing value back to) a base register"); |
402 | 0 | break; |
403 | | |
404 | 0 | case eContextRegisterPlusOffset: |
405 | 0 | strm.PutCString("register + offset"); |
406 | 0 | break; |
407 | | |
408 | 0 | case eContextRegisterStore: |
409 | 0 | strm.PutCString("store register"); |
410 | 0 | break; |
411 | | |
412 | 0 | case eContextRegisterLoad: |
413 | 0 | strm.PutCString("load register"); |
414 | 0 | break; |
415 | | |
416 | 0 | case eContextRelativeBranchImmediate: |
417 | 0 | strm.PutCString("relative branch immediate"); |
418 | 0 | break; |
419 | | |
420 | 0 | case eContextAbsoluteBranchRegister: |
421 | 0 | strm.PutCString("absolute branch register"); |
422 | 0 | break; |
423 | | |
424 | 0 | case eContextSupervisorCall: |
425 | 0 | strm.PutCString("supervisor call"); |
426 | 0 | break; |
427 | | |
428 | 0 | case eContextTableBranchReadMemory: |
429 | 0 | strm.PutCString("table branch read memory"); |
430 | 0 | break; |
431 | | |
432 | 0 | case eContextWriteRegisterRandomBits: |
433 | 0 | strm.PutCString("write random bits to a register"); |
434 | 0 | break; |
435 | | |
436 | 0 | case eContextWriteMemoryRandomBits: |
437 | 0 | strm.PutCString("write random bits to a memory address"); |
438 | 0 | break; |
439 | | |
440 | 0 | case eContextArithmetic: |
441 | 0 | strm.PutCString("arithmetic"); |
442 | 0 | break; |
443 | | |
444 | 0 | case eContextReturnFromException: |
445 | 0 | strm.PutCString("return from exception"); |
446 | 0 | break; |
447 | | |
448 | 0 | default: |
449 | 0 | strm.PutCString("unrecognized context."); |
450 | 0 | break; |
451 | 0 | } |
452 | | |
453 | 0 | switch (GetInfoType()) { |
454 | 0 | case eInfoTypeRegisterPlusOffset: |
455 | 0 | strm.Printf(" (reg_plus_offset = %s%+" PRId64 ")", |
456 | 0 | info.RegisterPlusOffset.reg.name, |
457 | 0 | info.RegisterPlusOffset.signed_offset); |
458 | 0 | break; |
459 | | |
460 | 0 | case eInfoTypeRegisterPlusIndirectOffset: |
461 | 0 | strm.Printf(" (reg_plus_reg = %s + %s)", |
462 | 0 | info.RegisterPlusIndirectOffset.base_reg.name, |
463 | 0 | info.RegisterPlusIndirectOffset.offset_reg.name); |
464 | 0 | break; |
465 | | |
466 | 0 | case eInfoTypeRegisterToRegisterPlusOffset: |
467 | 0 | strm.Printf(" (base_and_imm_offset = %s%+" PRId64 ", data_reg = %s)", |
468 | 0 | info.RegisterToRegisterPlusOffset.base_reg.name, |
469 | 0 | info.RegisterToRegisterPlusOffset.offset, |
470 | 0 | info.RegisterToRegisterPlusOffset.data_reg.name); |
471 | 0 | break; |
472 | | |
473 | 0 | case eInfoTypeRegisterToRegisterPlusIndirectOffset: |
474 | 0 | strm.Printf(" (base_and_reg_offset = %s + %s, data_reg = %s)", |
475 | 0 | info.RegisterToRegisterPlusIndirectOffset.base_reg.name, |
476 | 0 | info.RegisterToRegisterPlusIndirectOffset.offset_reg.name, |
477 | 0 | info.RegisterToRegisterPlusIndirectOffset.data_reg.name); |
478 | 0 | break; |
479 | | |
480 | 0 | case eInfoTypeRegisterRegisterOperands: |
481 | 0 | strm.Printf(" (register to register binary op: %s and %s)", |
482 | 0 | info.RegisterRegisterOperands.operand1.name, |
483 | 0 | info.RegisterRegisterOperands.operand2.name); |
484 | 0 | break; |
485 | | |
486 | 0 | case eInfoTypeOffset: |
487 | 0 | strm.Printf(" (signed_offset = %+" PRId64 ")", info.signed_offset); |
488 | 0 | break; |
489 | | |
490 | 0 | case eInfoTypeRegister: |
491 | 0 | strm.Printf(" (reg = %s)", info.reg.name); |
492 | 0 | break; |
493 | | |
494 | 0 | case eInfoTypeImmediate: |
495 | 0 | strm.Printf(" (unsigned_immediate = %" PRIu64 " (0x%16.16" PRIx64 "))", |
496 | 0 | info.unsigned_immediate, info.unsigned_immediate); |
497 | 0 | break; |
498 | | |
499 | 0 | case eInfoTypeImmediateSigned: |
500 | 0 | strm.Printf(" (signed_immediate = %+" PRId64 " (0x%16.16" PRIx64 "))", |
501 | 0 | info.signed_immediate, info.signed_immediate); |
502 | 0 | break; |
503 | | |
504 | 0 | case eInfoTypeAddress: |
505 | 0 | strm.Printf(" (address = 0x%" PRIx64 ")", info.address); |
506 | 0 | break; |
507 | | |
508 | 0 | case eInfoTypeISAAndImmediate: |
509 | 0 | strm.Printf(" (isa = %u, unsigned_immediate = %u (0x%8.8x))", |
510 | 0 | info.ISAAndImmediate.isa, info.ISAAndImmediate.unsigned_data32, |
511 | 0 | info.ISAAndImmediate.unsigned_data32); |
512 | 0 | break; |
513 | | |
514 | 0 | case eInfoTypeISAAndImmediateSigned: |
515 | 0 | strm.Printf(" (isa = %u, signed_immediate = %i (0x%8.8x))", |
516 | 0 | info.ISAAndImmediateSigned.isa, |
517 | 0 | info.ISAAndImmediateSigned.signed_data32, |
518 | 0 | info.ISAAndImmediateSigned.signed_data32); |
519 | 0 | break; |
520 | | |
521 | 0 | case eInfoTypeISA: |
522 | 0 | strm.Printf(" (isa = %u)", info.isa); |
523 | 0 | break; |
524 | | |
525 | 0 | case eInfoTypeNoArgs: |
526 | 0 | break; |
527 | 0 | } |
528 | 0 | } |
529 | | |
530 | | bool EmulateInstruction::SetInstruction(const Opcode &opcode, |
531 | | const Address &inst_addr, |
532 | 149 | Target *target) { |
533 | 149 | m_opcode = opcode; |
534 | 149 | m_addr = LLDB_INVALID_ADDRESS; |
535 | 149 | if (inst_addr.IsValid()) { |
536 | 149 | if (target != nullptr) |
537 | 0 | m_addr = inst_addr.GetLoadAddress(target); |
538 | 149 | if (m_addr == LLDB_INVALID_ADDRESS) |
539 | 149 | m_addr = inst_addr.GetFileAddress(); |
540 | 149 | } |
541 | 149 | return true; |
542 | 149 | } |
543 | | |
544 | | bool EmulateInstruction::GetBestRegisterKindAndNumber( |
545 | | const RegisterInfo *reg_info, lldb::RegisterKind ®_kind, |
546 | 265 | uint32_t ®_num) { |
547 | | // Generic and DWARF should be the two most popular register kinds when |
548 | | // emulating instructions since they are the most platform agnostic... |
549 | 265 | reg_num = reg_info->kinds[eRegisterKindGeneric]; |
550 | 265 | if (reg_num != LLDB_INVALID_REGNUM) { |
551 | 199 | reg_kind = eRegisterKindGeneric; |
552 | 199 | return true; |
553 | 199 | } |
554 | | |
555 | 66 | reg_num = reg_info->kinds[eRegisterKindDWARF]; |
556 | 66 | if (reg_num != LLDB_INVALID_REGNUM) { |
557 | 50 | reg_kind = eRegisterKindDWARF; |
558 | 50 | return true; |
559 | 50 | } |
560 | | |
561 | 16 | reg_num = reg_info->kinds[eRegisterKindLLDB]; |
562 | 16 | if (reg_num != LLDB_INVALID_REGNUM) { |
563 | 16 | reg_kind = eRegisterKindLLDB; |
564 | 16 | return true; |
565 | 16 | } |
566 | | |
567 | 0 | reg_num = reg_info->kinds[eRegisterKindEHFrame]; |
568 | 0 | if (reg_num != LLDB_INVALID_REGNUM) { |
569 | 0 | reg_kind = eRegisterKindEHFrame; |
570 | 0 | return true; |
571 | 0 | } |
572 | | |
573 | 0 | reg_num = reg_info->kinds[eRegisterKindProcessPlugin]; |
574 | 0 | if (reg_num != LLDB_INVALID_REGNUM) { |
575 | 0 | reg_kind = eRegisterKindProcessPlugin; |
576 | 0 | return true; |
577 | 0 | } |
578 | 0 | return false; |
579 | 0 | } |
580 | | |
581 | | uint32_t |
582 | | EmulateInstruction::GetInternalRegisterNumber(RegisterContext *reg_ctx, |
583 | 0 | const RegisterInfo ®_info) { |
584 | 0 | lldb::RegisterKind reg_kind; |
585 | 0 | uint32_t reg_num; |
586 | 0 | if (reg_ctx && GetBestRegisterKindAndNumber(®_info, reg_kind, reg_num)) |
587 | 0 | return reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); |
588 | 0 | return LLDB_INVALID_REGNUM; |
589 | 0 | } |
590 | | |
591 | 0 | bool EmulateInstruction::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) { |
592 | 0 | unwind_plan.Clear(); |
593 | 0 | return false; |
594 | 0 | } |