1 | //===-- EmulateInstruction.h ------------------------------------*- C++ -*-===// |
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 | #ifndef LLDB_CORE_EMULATEINSTRUCTION_H |
10 | #define LLDB_CORE_EMULATEINSTRUCTION_H |
11 | |
12 | #include <string> |
13 | |
14 | #include "lldb/Core/Address.h" |
15 | #include "lldb/Core/Opcode.h" |
16 | #include "lldb/Core/PluginInterface.h" |
17 | #include "lldb/Utility/ArchSpec.h" |
18 | #include "lldb/lldb-defines.h" |
19 | #include "lldb/lldb-enumerations.h" |
20 | #include "lldb/lldb-private-enumerations.h" |
21 | #include "lldb/lldb-private-types.h" |
22 | #include "lldb/lldb-types.h" |
23 | |
24 | #include <stddef.h> |
25 | #include <stdint.h> |
26 | |
27 | namespace lldb_private { |
28 | class OptionValueDictionary; |
29 | class RegisterContext; |
30 | class RegisterValue; |
31 | class Stream; |
32 | class Target; |
33 | class UnwindPlan; |
34 | |
35 | /// \class EmulateInstruction EmulateInstruction.h |
36 | /// "lldb/Core/EmulateInstruction.h" |
37 | /// A class that allows emulation of CPU opcodes. |
38 | /// |
39 | /// This class is a plug-in interface that is accessed through the standard |
40 | /// static FindPlugin function call in the EmulateInstruction class. The |
41 | /// FindPlugin takes a target triple and returns a new object if there is a |
42 | /// plug-in that supports the architecture and OS. Four callbacks and a baton |
43 | /// are provided. The four callbacks are read register, write register, read |
44 | /// memory and write memory. |
45 | /// |
46 | /// This class is currently designed for these main use cases: - Auto |
47 | /// generation of Call Frame Information (CFI) from assembly code - Predicting |
48 | /// single step breakpoint locations - Emulating instructions for breakpoint |
49 | /// traps |
50 | /// |
51 | /// Objects can be asked to read an instruction which will cause a call to the |
52 | /// read register callback to get the PC, followed by a read memory call to |
53 | /// read the opcode. If ReadInstruction () returns true, then a call to |
54 | /// EmulateInstruction::EvaluateInstruction () can be made. At this point the |
55 | /// EmulateInstruction subclass will use all of the callbacks to emulate an |
56 | /// instruction. |
57 | /// |
58 | /// Clients that provide the callbacks can either do the read/write |
59 | /// registers/memory to actually emulate the instruction on a real or virtual |
60 | /// CPU, or watch for the EmulateInstruction::Context which is context for the |
61 | /// read/write register/memory which explains why the callback is being |
62 | /// called. Examples of a context are: "pushing register 3 onto the stack at |
63 | /// offset -12", or "adjusting stack pointer by -16". This extra context |
64 | /// allows the generation of |
65 | /// CFI information from assembly code without having to actually do |
66 | /// the read/write register/memory. |
67 | /// |
68 | /// Clients must be prepared that not all instructions for an Instruction Set |
69 | /// Architecture (ISA) will be emulated. |
70 | /// |
71 | /// Subclasses at the very least should implement the instructions that save |
72 | /// and restore registers onto the stack and adjustment to the stack pointer. |
73 | /// By just implementing a few instructions for an ISA that are the typical |
74 | /// prologue opcodes, you can then generate CFI using a class that will soon |
75 | /// be available. |
76 | /// |
77 | /// Implementing all of the instructions that affect the PC can then allow |
78 | /// single step prediction support. |
79 | /// |
80 | /// Implementing all of the instructions allows for emulation of opcodes for |
81 | /// breakpoint traps and will pave the way for "thread centric" debugging. The |
82 | /// current debugging model is "process centric" where all threads must be |
83 | /// stopped when any thread is stopped; when hitting software breakpoints we |
84 | /// must disable the breakpoint by restoring the original breakpoint opcode, |
85 | /// single stepping and restoring the breakpoint trap. If all threads were |
86 | /// allowed to run then other threads could miss the breakpoint. |
87 | /// |
88 | /// This class centralizes the code that usually is done in separate code |
89 | /// paths in a debugger (single step prediction, finding save restore |
90 | /// locations of registers for unwinding stack frame variables) and emulating |
91 | /// the instruction is just a bonus. |
92 | |
93 | class EmulateInstruction : public PluginInterface { |
94 | public: |
95 | static EmulateInstruction *FindPlugin(const ArchSpec &arch, |
96 | InstructionType supported_inst_type, |
97 | const char *plugin_name); |
98 | |
99 | enum ContextType { |
100 | eContextInvalid = 0, |
101 | // Read an instruction opcode from memory |
102 | eContextReadOpcode, |
103 | |
104 | // Usually used for writing a register value whose source value is an |
105 | // immediate |
106 | eContextImmediate, |
107 | |
108 | // Exclusively used when saving a register to the stack as part of the |
109 | // prologue |
110 | eContextPushRegisterOnStack, |
111 | |
112 | // Exclusively used when restoring a register off the stack as part of the |
113 | // epilogue |
114 | eContextPopRegisterOffStack, |
115 | |
116 | // Add or subtract a value from the stack |
117 | eContextAdjustStackPointer, |
118 | |
119 | // Adjust the frame pointer for the current frame |
120 | eContextSetFramePointer, |
121 | |
122 | // Typically in an epilogue sequence. Copy the frame pointer back into the |
123 | // stack pointer, use SP for CFA calculations again. |
124 | eContextRestoreStackPointer, |
125 | |
126 | // Add or subtract a value from a base address register (other than SP) |
127 | eContextAdjustBaseRegister, |
128 | |
129 | // Add or subtract a value from the PC or store a value to the PC. |
130 | eContextAdjustPC, |
131 | |
132 | // Used in WriteRegister callbacks to indicate where the |
133 | eContextRegisterPlusOffset, |
134 | |
135 | // Used in WriteMemory callback to indicate where the data came from |
136 | eContextRegisterStore, |
137 | |
138 | eContextRegisterLoad, |
139 | |
140 | // Used when performing a PC-relative branch where the |
141 | eContextRelativeBranchImmediate, |
142 | |
143 | // Used when performing an absolute branch where the |
144 | eContextAbsoluteBranchRegister, |
145 | |
146 | // Used when performing a supervisor call to an operating system to provide |
147 | // a service: |
148 | eContextSupervisorCall, |
149 | |
150 | // Used when performing a MemU operation to read the PC-relative offset |
151 | // from an address. |
152 | eContextTableBranchReadMemory, |
153 | |
154 | // Used when random bits are written into a register |
155 | eContextWriteRegisterRandomBits, |
156 | |
157 | // Used when random bits are written to memory |
158 | eContextWriteMemoryRandomBits, |
159 | |
160 | eContextArithmetic, |
161 | |
162 | eContextAdvancePC, |
163 | |
164 | eContextReturnFromException |
165 | }; |
166 | |
167 | enum InfoType { |
168 | eInfoTypeRegisterPlusOffset, |
169 | eInfoTypeRegisterPlusIndirectOffset, |
170 | eInfoTypeRegisterToRegisterPlusOffset, |
171 | eInfoTypeRegisterToRegisterPlusIndirectOffset, |
172 | eInfoTypeRegisterRegisterOperands, |
173 | eInfoTypeOffset, |
174 | eInfoTypeRegister, |
175 | eInfoTypeImmediate, |
176 | eInfoTypeImmediateSigned, |
177 | eInfoTypeAddress, |
178 | eInfoTypeISAAndImmediate, |
179 | eInfoTypeISAAndImmediateSigned, |
180 | eInfoTypeISA, |
181 | eInfoTypeNoArgs |
182 | } InfoType; |
183 | |
184 | struct Context { |
185 | ContextType type; |
186 | enum InfoType info_type; |
187 | union { |
188 | struct RegisterPlusOffset { |
189 | RegisterInfo reg; // base register |
190 | int64_t signed_offset; // signed offset added to base register |
191 | } RegisterPlusOffset; |
192 | |
193 | struct RegisterPlusIndirectOffset { |
194 | RegisterInfo base_reg; // base register number |
195 | RegisterInfo offset_reg; // offset register kind |
196 | } RegisterPlusIndirectOffset; |
197 | |
198 | struct RegisterToRegisterPlusOffset { |
199 | RegisterInfo data_reg; // source/target register for data |
200 | RegisterInfo base_reg; // base register for address calculation |
201 | int64_t offset; // offset for address calculation |
202 | } RegisterToRegisterPlusOffset; |
203 | |
204 | struct RegisterToRegisterPlusIndirectOffset { |
205 | RegisterInfo base_reg; // base register for address calculation |
206 | RegisterInfo offset_reg; // offset register for address calculation |
207 | RegisterInfo data_reg; // source/target register for data |
208 | } RegisterToRegisterPlusIndirectOffset; |
209 | |
210 | struct RegisterRegisterOperands { |
211 | RegisterInfo |
212 | operand1; // register containing first operand for binary op |
213 | RegisterInfo |
214 | operand2; // register containing second operand for binary op |
215 | } RegisterRegisterOperands; |
216 | |
217 | int64_t signed_offset; // signed offset by which to adjust self (for |
218 | // registers only) |
219 | |
220 | RegisterInfo reg; // plain register |
221 | |
222 | uint64_t unsigned_immediate; // unsigned immediate value |
223 | int64_t signed_immediate; // signed immediate value |
224 | |
225 | lldb::addr_t address; // direct address |
226 | |
227 | struct ISAAndImmediate { |
228 | uint32_t isa; |
229 | uint32_t unsigned_data32; // immediate data |
230 | } ISAAndImmediate; |
231 | |
232 | struct ISAAndImmediateSigned { |
233 | uint32_t isa; |
234 | int32_t signed_data32; // signed immediate data |
235 | } ISAAndImmediateSigned; |
236 | |
237 | uint32_t isa; |
238 | } info; |
239 | |
240 | Context() : type(eContextInvalid), info_type(eInfoTypeNoArgs) {} |
241 | |
242 | void SetRegisterPlusOffset(RegisterInfo base_reg, int64_t signed_offset) { |
243 | info_type = eInfoTypeRegisterPlusOffset; |
244 | info.RegisterPlusOffset.reg = base_reg; |
245 | info.RegisterPlusOffset.signed_offset = signed_offset; |
246 | } |
247 | |
248 | void SetRegisterPlusIndirectOffset(RegisterInfo base_reg, |
249 | RegisterInfo offset_reg) { |
250 | info_type = eInfoTypeRegisterPlusIndirectOffset; |
251 | info.RegisterPlusIndirectOffset.base_reg = base_reg; |
252 | info.RegisterPlusIndirectOffset.offset_reg = offset_reg; |
253 | } |
254 | |
255 | void SetRegisterToRegisterPlusOffset(RegisterInfo data_reg, |
256 | RegisterInfo base_reg, |
257 | int64_t offset) { |
258 | info_type = eInfoTypeRegisterToRegisterPlusOffset; |
259 | info.RegisterToRegisterPlusOffset.data_reg = data_reg; |
260 | info.RegisterToRegisterPlusOffset.base_reg = base_reg; |
261 | info.RegisterToRegisterPlusOffset.offset = offset; |
262 | } |
263 | |
264 | void SetRegisterToRegisterPlusIndirectOffset(RegisterInfo base_reg, |
265 | RegisterInfo offset_reg, |
266 | RegisterInfo data_reg) { |
267 | info_type = eInfoTypeRegisterToRegisterPlusIndirectOffset; |
268 | info.RegisterToRegisterPlusIndirectOffset.base_reg = base_reg; |
269 | info.RegisterToRegisterPlusIndirectOffset.offset_reg = offset_reg; |
270 | info.RegisterToRegisterPlusIndirectOffset.data_reg = data_reg; |
271 | } |
272 | |
273 | void SetRegisterRegisterOperands(RegisterInfo op1_reg, |
274 | RegisterInfo op2_reg) { |
275 | info_type = eInfoTypeRegisterRegisterOperands; |
276 | info.RegisterRegisterOperands.operand1 = op1_reg; |
277 | info.RegisterRegisterOperands.operand2 = op2_reg; |
278 | } |
279 | |
280 | void SetOffset(int64_t signed_offset) { |
281 | info_type = eInfoTypeOffset; |
282 | info.signed_offset = signed_offset; |
283 | } |
284 | |
285 | void SetRegister(RegisterInfo reg) { |
286 | info_type = eInfoTypeRegister; |
287 | info.reg = reg; |
288 | } |
289 | |
290 | void SetImmediate(uint64_t immediate) { |
291 | info_type = eInfoTypeImmediate; |
292 | info.unsigned_immediate = immediate; |
293 | } |
294 | |
295 | void SetImmediateSigned(int64_t signed_immediate) { |
296 | info_type = eInfoTypeImmediateSigned; |
297 | info.signed_immediate = signed_immediate; |
298 | } |
299 | |
300 | void SetAddress(lldb::addr_t address) { |
301 | info_type = eInfoTypeAddress; |
302 | info.address = address; |
303 | } |
304 | void SetISAAndImmediate(uint32_t isa, uint32_t data) { |
305 | info_type = eInfoTypeISAAndImmediate; |
306 | info.ISAAndImmediate.isa = isa; |
307 | info.ISAAndImmediate.unsigned_data32 = data; |
308 | } |
309 | |
310 | void SetISAAndImmediateSigned(uint32_t isa, int32_t data) { |
311 | info_type = eInfoTypeISAAndImmediateSigned; |
312 | info.ISAAndImmediateSigned.isa = isa; |
313 | info.ISAAndImmediateSigned.signed_data32 = data; |
314 | } |
315 | |
316 | void SetISA(uint32_t isa) { |
317 | info_type = eInfoTypeISA; |
318 | info.isa = isa; |
319 | } |
320 | |
321 | void SetNoArgs() { info_type = eInfoTypeNoArgs; } |
322 | |
323 | void Dump(Stream &s, EmulateInstruction *instruction) const; |
324 | }; |
325 | |
326 | typedef size_t (*ReadMemoryCallback)(EmulateInstruction *instruction, |
327 | void *baton, const Context &context, |
328 | lldb::addr_t addr, void *dst, |
329 | size_t length); |
330 | |
331 | typedef size_t (*WriteMemoryCallback)(EmulateInstruction *instruction, |
332 | void *baton, const Context &context, |
333 | lldb::addr_t addr, const void *dst, |
334 | size_t length); |
335 | |
336 | typedef bool (*ReadRegisterCallback)(EmulateInstruction *instruction, |
337 | void *baton, |
338 | const RegisterInfo *reg_info, |
339 | RegisterValue ®_value); |
340 | |
341 | typedef bool (*WriteRegisterCallback)(EmulateInstruction *instruction, |
342 | void *baton, const Context &context, |
343 | const RegisterInfo *reg_info, |
344 | const RegisterValue ®_value); |
345 | |
346 | // Type to represent the condition of an instruction. The UINT32 value is |
347 | // reserved for the unconditional case and all other value can be used in an |
348 | // architecture dependent way. |
349 | typedef uint32_t InstructionCondition; |
350 | static const InstructionCondition UnconditionalCondition = UINT32_MAX; |
351 | |
352 | EmulateInstruction(const ArchSpec &arch); |
353 | |
354 | ~EmulateInstruction() override = default; |
355 | |
356 | // Mandatory overrides |
357 | virtual bool |
358 | SupportsEmulatingInstructionsOfType(InstructionType inst_type) = 0; |
359 | |
360 | virtual bool SetTargetTriple(const ArchSpec &arch) = 0; |
361 | |
362 | virtual bool ReadInstruction() = 0; |
363 | |
364 | virtual bool EvaluateInstruction(uint32_t evaluate_options) = 0; |
365 | |
366 | virtual InstructionCondition GetInstructionCondition() { |
367 | return UnconditionalCondition; |
368 | } |
369 | |
370 | virtual bool TestEmulation(Stream *out_stream, ArchSpec &arch, |
371 | OptionValueDictionary *test_data) = 0; |
372 | |
373 | virtual bool GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num, |
374 | RegisterInfo ®_info) = 0; |
375 | |
376 | // Optional overrides |
377 | virtual bool SetInstruction(const Opcode &insn_opcode, |
378 | const Address &inst_addr, Target *target); |
379 | |
380 | virtual bool CreateFunctionEntryUnwind(UnwindPlan &unwind_plan); |
381 | |
382 | static const char *TranslateRegister(lldb::RegisterKind reg_kind, |
383 | uint32_t reg_num, std::string ®_name); |
384 | |
385 | // RegisterInfo variants |
386 | bool ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value); |
387 | |
388 | uint64_t ReadRegisterUnsigned(const RegisterInfo *reg_info, |
389 | uint64_t fail_value, bool *success_ptr); |
390 | |
391 | bool WriteRegister(const Context &context, const RegisterInfo *ref_info, |
392 | const RegisterValue ®_value); |
393 | |
394 | bool WriteRegisterUnsigned(const Context &context, |
395 | const RegisterInfo *reg_info, uint64_t reg_value); |
396 | |
397 | // Register kind and number variants |
398 | bool ReadRegister(lldb::RegisterKind reg_kind, uint32_t reg_num, |
399 | RegisterValue ®_value); |
400 | |
401 | bool WriteRegister(const Context &context, lldb::RegisterKind reg_kind, |
402 | uint32_t reg_num, const RegisterValue ®_value); |
403 | |
404 | uint64_t ReadRegisterUnsigned(lldb::RegisterKind reg_kind, uint32_t reg_num, |
405 | uint64_t fail_value, bool *success_ptr); |
406 | |
407 | bool WriteRegisterUnsigned(const Context &context, |
408 | lldb::RegisterKind reg_kind, uint32_t reg_num, |
409 | uint64_t reg_value); |
410 | |
411 | size_t ReadMemory(const Context &context, lldb::addr_t addr, void *dst, |
412 | size_t dst_len); |
413 | |
414 | uint64_t ReadMemoryUnsigned(const Context &context, lldb::addr_t addr, |
415 | size_t byte_size, uint64_t fail_value, |
416 | bool *success_ptr); |
417 | |
418 | bool WriteMemory(const Context &context, lldb::addr_t addr, const void *src, |
419 | size_t src_len); |
420 | |
421 | bool WriteMemoryUnsigned(const Context &context, lldb::addr_t addr, |
422 | uint64_t uval, size_t uval_byte_size); |
423 | |
424 | uint32_t GetAddressByteSize() const { return m_arch.GetAddressByteSize(); } |
425 | |
426 | lldb::ByteOrder GetByteOrder() const { return m_arch.GetByteOrder(); } |
427 | |
428 | const Opcode &GetOpcode() const { return m_opcode; } |
429 | |
430 | lldb::addr_t GetAddress() const { return m_addr; } |
431 | |
432 | const ArchSpec &GetArchitecture() const { return m_arch; } |
433 | |
434 | static size_t ReadMemoryFrame(EmulateInstruction *instruction, void *baton, |
435 | const Context &context, lldb::addr_t addr, |
436 | void *dst, size_t length); |
437 | |
438 | static size_t WriteMemoryFrame(EmulateInstruction *instruction, void *baton, |
439 | const Context &context, lldb::addr_t addr, |
440 | const void *dst, size_t length); |
441 | |
442 | static bool ReadRegisterFrame(EmulateInstruction *instruction, void *baton, |
443 | const RegisterInfo *reg_info, |
444 | RegisterValue ®_value); |
445 | |
446 | static bool WriteRegisterFrame(EmulateInstruction *instruction, void *baton, |
447 | const Context &context, |
448 | const RegisterInfo *reg_info, |
449 | const RegisterValue ®_value); |
450 | |
451 | static size_t ReadMemoryDefault(EmulateInstruction *instruction, void *baton, |
452 | const Context &context, lldb::addr_t addr, |
453 | void *dst, size_t length); |
454 | |
455 | static size_t WriteMemoryDefault(EmulateInstruction *instruction, void *baton, |
456 | const Context &context, lldb::addr_t addr, |
457 | const void *dst, size_t length); |
458 | |
459 | static bool ReadRegisterDefault(EmulateInstruction *instruction, void *baton, |
460 | const RegisterInfo *reg_info, |
461 | RegisterValue ®_value); |
462 | |
463 | static bool WriteRegisterDefault(EmulateInstruction *instruction, void *baton, |
464 | const Context &context, |
465 | const RegisterInfo *reg_info, |
466 | const RegisterValue ®_value); |
467 | |
468 | void SetBaton(void *baton); |
469 | |
470 | void SetCallbacks(ReadMemoryCallback read_mem_callback, |
471 | WriteMemoryCallback write_mem_callback, |
472 | ReadRegisterCallback read_reg_callback, |
473 | WriteRegisterCallback write_reg_callback); |
474 | |
475 | void SetReadMemCallback(ReadMemoryCallback read_mem_callback); |
476 | |
477 | void SetWriteMemCallback(WriteMemoryCallback write_mem_callback); |
478 | |
479 | void SetReadRegCallback(ReadRegisterCallback read_reg_callback); |
480 | |
481 | void SetWriteRegCallback(WriteRegisterCallback write_reg_callback); |
482 | |
483 | static bool GetBestRegisterKindAndNumber(const RegisterInfo *reg_info, |
484 | lldb::RegisterKind ®_kind, |
485 | uint32_t ®_num); |
486 | |
487 | static uint32_t GetInternalRegisterNumber(RegisterContext *reg_ctx, |
488 | const RegisterInfo ®_info); |
489 | |
490 | protected: |
491 | ArchSpec m_arch; |
492 | void *m_baton = nullptr; |
493 | ReadMemoryCallback m_read_mem_callback = &ReadMemoryDefault; |
494 | WriteMemoryCallback m_write_mem_callback = &WriteMemoryDefault; |
495 | ReadRegisterCallback m_read_reg_callback = &ReadRegisterDefault; |
496 | WriteRegisterCallback m_write_reg_callback = &WriteRegisterDefault; |
497 | lldb::addr_t m_addr = LLDB_INVALID_ADDRESS; |
498 | Opcode m_opcode; |
499 | |
500 | private: |
501 | // For EmulateInstruction only |
502 | EmulateInstruction(const EmulateInstruction &) = delete; |
503 | const EmulateInstruction &operator=(const EmulateInstruction &) = delete; |
504 | }; |
505 | |
506 | } // namespace lldb_private |
507 | |
508 | #endif // LLDB_CORE_EMULATEINSTRUCTION_H |
509 | |