EmulateInstruction.h revision 60299ec172c9bbeab4e1bbffad513d75cd1741de
1//===-- EmulateInstruction.h ------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef lldb_EmulateInstruction_h_ 11#define lldb_EmulateInstruction_h_ 12 13#include "lldb/lldb-include.h" 14#include "lldb/Core/PluginInterface.h" 15 16//---------------------------------------------------------------------- 17/// @class EmulateInstruction EmulateInstruction.h "lldb/Core/EmulateInstruction.h" 18/// @brief A class that allows emulation of CPU opcodes. 19/// 20/// This class is a plug-in interface that is accessed through the 21/// standard static FindPlugin function call in the EmulateInstruction 22/// class. The FindPlugin takes a target triple and returns a new object 23/// if there is a plug-in that supports the architecture and OS. Four 24/// callbacks and a baton are provided. The four callbacks are read 25/// register, write register, read memory and write memory. 26/// 27/// This class is currently designed for these main use cases: 28/// - Auto generation of Call Frame Information (CFI) from assembly code 29/// - Predicting single step breakpoint locations 30/// - Emulating instructions for breakpoint traps 31/// 32/// Objects can be asked to read an instruction which will cause a call 33/// to the read register callback to get the PC, followed by a read 34/// memory call to read the opcode. If ReadInstruction () returns true, 35/// then a call to EmulateInstruction::EvaluateInstruction () can be 36/// made. At this point the EmulateInstruction subclass will use all of 37/// the callbacks to emulate an instruction. 38/// 39/// Clients that provide the callbacks can either do the read/write 40/// registers/memory to actually emulate the instruction on a real or 41/// virtual CPU, or watch for the EmulateInstruction::Context which 42/// is context for the read/write register/memory which explains why 43/// the callback is being called. Examples of a context are: 44/// "pushing register 3 onto the stack at offset -12", or "adjusting 45/// stack pointer by -16". This extra context allows the generation of 46/// CFI information from assembly code without having to actually do 47/// the read/write register/memory. 48/// 49/// Clients must be prepared that not all instructions for an 50/// Instruction Set Architecture (ISA) will be emulated. 51/// 52/// Subclasses at the very least should implement the instructions that 53/// save and restore regiters onto the stack and adjustment to the stack 54/// pointer. By just implementing a few instructions for an ISA that are 55/// the typical prologue opcodes, you can then generate CFI using a 56/// class that will soon be available. 57/// 58/// Implmenting all of the instructions that affect the PC can then 59/// allow single step prediction support. 60/// 61/// Implmenting all of the instructions allows for emulation of opcodes 62/// for breakpoint traps and will pave the way for "thread centric" 63/// debugging. The current debugging model is "process centric" where 64/// all threads must be stopped when any thread is stopped since when 65/// hitting software breakpoints once must disable the breakpoint by 66/// restoring the original breakpoint opcde, single stepping and 67/// restoring the breakpoint trap. If all threads were allowed to run 68/// then other threads could miss the breakpoint. 69/// 70/// This class centralizes the code that usually is done in separate 71/// code paths in a debugger (single step prediction, finding save 72/// restore locations of registers for unwinding stack frame variables, 73/// and emulating the intruction is just a bonus. 74//---------------------------------------------------------------------- 75 76namespace lldb_private { 77 78class EmulateInstruction : 79 public PluginInterface 80{ 81public: 82 83 static EmulateInstruction* 84 FindPlugin (const ArchSpec &arch, const char *plugin_name); 85 86 enum ContextType 87 { 88 eContextInvalid = 0, 89 // Read an instruciton opcode from memory 90 eContextReadOpcode, 91 92 // Usually used for writing a register value whose source value in an 93 // immediate 94 eContextImmediate, 95 96 // Exclusively used when saving a register to the stack as part of the 97 // prologue 98 // arg0 = register kind 99 // arg1 = register number 100 // arg2 = signed offset from current SP value where register is being 101 // stored 102 eContextPushRegisterOnStack, 103 104 // Exclusively used when restoring a register off the stack as part of 105 // the epilogue 106 // arg0 = register kind 107 // arg1 = register number 108 // arg2 = signed offset from current SP value where register is being 109 // restored 110 eContextPopRegisterOffStack, 111 112 // Add or subtract a value from the stack 113 // arg0 = register kind for SP 114 // arg1 = register number for SP 115 // arg2 = signed offset being applied to the SP value 116 eContextAdjustStackPointer, 117 118 // Add or subtract a value from a base address register (other than SP) 119 // arg0 = register kind for base register 120 // arg1 = register number of base register 121 // arg2 = signed offset being applied to base register 122 eContextAdjustBaseRegister, 123 124 // Used in WriteRegister callbacks to indicate where the 125 // arg0 = source register kind 126 // arg1 = source register number 127 // arg2 = source signed offset 128 eContextRegisterPlusOffset, 129 130 // Used in WriteMemory callback to indicate where the data came from 131 // arg0 = register kind 132 // arg1 = register number (register being stored) 133 // arg2 = address of store 134 eContextRegisterStore, 135 136 eContextRegisterLoad, 137 138 // Used when performing a PC-relative branch where the 139 // arg0 = don't care 140 // arg1 = imm32 (signed offset) 141 // arg2 = target instruction set or don't care 142 eContextRelativeBranchImmediate, 143 144 // Used when performing an absolute branch where the 145 // arg0 = target register kind 146 // arg1 = target register number 147 // arg2 = target instruction set or don't care 148 eContextAbsoluteBranchRegister, 149 150 // Used when performing a supervisor call to an operating system to 151 // provide a service: 152 // arg0 = current instruction set or don't care 153 // arg1 = immediate data or don't care 154 // arg2 = don't care 155 eContextSupervisorCall, 156 157 // Used when performing a MemU operation to read the PC-relative offset 158 // from an address. 159 eContextTableBranchReadMemory, 160 161 // Used when random bits are written into a register 162 // arg0 = target register kind 163 // arg1 = target register number 164 // arg2 = don't care 165 eContextWriteRegisterRandomBits, 166 167 // Used when random bits are written to memory 168 // arg0 = target memory address 169 // arg1 = don't care 170 // arg2 = don't care 171 eContextWriteMemoryRandomBits 172 }; 173 174 enum InfoType { 175 eInfoTypeRegisterPlusOffset, 176 eInfoTypeRegisterPlusIndirectOffset, 177 eInfoTypeRegisterToRegisterPlusOffset, 178 eInfoTypeOffset, 179 eInfoTypeRegister, 180 eInfoTypeImmediate, 181 eInfoTypeImmediateSigned, 182 eInfoTypeAddress, 183 eInfoTypeModeAndImmediate, 184 eInfoTypeModeAndImmediateSigned, 185 eInfoTypeMode, 186 eInfoTypeNoArgs 187 } InfoType; 188 189 struct Register 190 { 191 uint32_t kind; 192 uint32_t num; 193 194 195 void 196 SetRegister (uint32_t reg_kind, uint32_t reg_num) 197 { 198 kind = reg_kind; 199 num = reg_num; 200 } 201 }; 202 203 struct Context 204 { 205 ContextType type; 206 enum InfoType info_type; 207 union 208 { 209 struct RegisterPlusOffset 210 { 211 Register reg; // base register 212 int64_t signed_offset; // signed offset added to base register 213 } RegisterPlusOffset; 214 215 struct RegisterPlusIndirectOffset 216 { 217 Register base_reg; // base register number 218 Register offset_reg; // offset register kind 219 } RegisterPlusIndirectOffset; 220 221 struct RegisterToRegisterPlusOffset 222 { 223 Register data_reg; // source/target register for data 224 Register base_reg; // base register for address calculation 225 int64_t offset; // offset for address calculation 226 } RegisterToRegisterPlusOffset; 227 228 int64_t signed_offset; // signed offset by which to adjust self (for registers only) 229 230 Register reg; // plain register 231 232 uint64_t immediate; // immediate value 233 234 int64_t signed_immediate; // signed immediate value 235 236 lldb::addr_t address; // direct address 237 238 struct ModeAndImmediate 239 { 240 uint32_t mode; // eModeARM or eModeThumb 241 uint32_t data_value; // immdiate data 242 } ModeAndImmediate; 243 244 struct ModeAndImmediateSigned 245 { 246 uint32_t mode; // eModeARM or eModeThumb 247 int32_t signed_data_value; // signed immdiate data 248 } ModeAndImmediateSigned; 249 250 uint32_t mode; // eModeARM or eModeThumb 251 252 } info; 253 254 void 255 SetRegisterPlusOffset (Register base_reg, 256 int64_t signed_offset) 257 { 258 info_type = eInfoTypeRegisterPlusOffset; 259 info.RegisterPlusOffset.reg = base_reg; 260 info.RegisterPlusOffset.signed_offset = signed_offset; 261 } 262 263 void 264 SetRegisterPlusIndirectOffset (Register base_reg, 265 Register offset_reg) 266 { 267 info_type = eInfoTypeRegisterPlusIndirectOffset; 268 info.RegisterPlusIndirectOffset.base_reg = base_reg; 269 info.RegisterPlusIndirectOffset.offset_reg = offset_reg; 270 } 271 272 void 273 SetRegisterToRegisterPlusOffset (Register data_reg, 274 Register base_reg, 275 int64_t offset) 276 { 277 info_type = eInfoTypeRegisterToRegisterPlusOffset; 278 info.RegisterToRegisterPlusOffset.data_reg = data_reg; 279 info.RegisterToRegisterPlusOffset.base_reg = base_reg; 280 info.RegisterToRegisterPlusOffset.offset = offset; 281 } 282 283 void 284 SetOffset (int64_t signed_offset) 285 { 286 info_type = eInfoTypeOffset; 287 info.signed_offset = signed_offset; 288 } 289 290 void 291 SetRegister (Register reg) 292 { 293 info_type = eInfoTypeRegister; 294 info.reg = reg; 295 } 296 297 void 298 SetImmediate (uint64_t immediate) 299 { 300 info_type = eInfoTypeImmediate; 301 info.immediate = immediate; 302 } 303 304 void 305 SetImmediateSigned (int64_t signed_immediate) 306 { 307 info_type = eInfoTypeImmediateSigned; 308 info.signed_immediate = signed_immediate; 309 } 310 311 void 312 SetAddress (lldb::addr_t address) 313 { 314 info_type = eInfoTypeAddress; 315 info.address = address; 316 } 317 void 318 SetModeAndImmediate (uint32_t mode, uint32_t data_value) 319 { 320 info_type = eInfoTypeModeAndImmediate; 321 info.ModeAndImmediate.mode = mode; 322 info.ModeAndImmediate.data_value = data_value; 323 } 324 325 void 326 SetModeAndImmediateSigned (uint32_t mode, int32_t signed_data_value) 327 { 328 info_type = eInfoTypeModeAndImmediateSigned; 329 info.ModeAndImmediateSigned.mode = mode; 330 info.ModeAndImmediateSigned.signed_data_value = signed_data_value; 331 } 332 333 void 334 SetMode (uint32_t mode) 335 { 336 info_type = eInfoTypeMode; 337 info.mode = mode; 338 } 339 340 void 341 SetNoArgs () 342 { 343 info_type = eInfoTypeNoArgs; 344 } 345 346 }; 347 348 union Opcode 349 { 350 uint8_t inst8; 351 uint16_t inst16; 352 uint32_t inst32; 353 uint64_t inst64; 354 union inst 355 { 356 uint8_t bytes[16]; 357 uint8_t length; 358 }; 359 }; 360 361 enum OpcodeType 362 { 363 eOpcode8, 364 eOpcode16, 365 eOpcode32, 366 eOpcode64, 367 eOpcodeBytes 368 }; 369 370 struct Instruction 371 { 372 OpcodeType opcode_type; 373 Opcode opcode; 374 }; 375 376 typedef size_t (*ReadMemory) (void *baton, 377 const Context &context, 378 lldb::addr_t addr, 379 void *dst, 380 size_t length); 381 382 typedef size_t (*WriteMemory) (void *baton, 383 const Context &context, 384 lldb::addr_t addr, 385 const void *dst, 386 size_t length); 387 388 typedef bool (*ReadRegister) (void *baton, 389 uint32_t reg_kind, 390 uint32_t reg_num, 391 uint64_t ®_value); 392 393 typedef bool (*WriteRegister) (void *baton, 394 const Context &context, 395 uint32_t reg_kind, 396 uint32_t reg_num, 397 uint64_t reg_value); 398 399 EmulateInstruction (lldb::ByteOrder byte_order, 400 uint32_t addr_byte_size, 401 void *baton, 402 ReadMemory read_mem_callback, 403 WriteMemory write_mem_callback, 404 ReadRegister read_reg_callback, 405 WriteRegister write_reg_callback); 406 407 virtual ~EmulateInstruction() 408 { 409 } 410 411 virtual bool 412 SetTargetTriple (const ArchSpec &arch) = 0; 413 414 virtual bool 415 ReadInstruction () = 0; 416 417 virtual bool 418 EvaluateInstruction () = 0; 419 420 uint64_t 421 ReadRegisterUnsigned (uint32_t reg_kind, 422 uint32_t reg_num, 423 uint64_t fail_value, 424 bool *success_ptr); 425 426 bool 427 WriteRegisterUnsigned (const Context &context, 428 uint32_t reg_kind, 429 uint32_t reg_num, 430 uint64_t reg_value); 431 432 uint64_t 433 ReadMemoryUnsigned (const Context &context, 434 lldb::addr_t addr, 435 size_t byte_size, 436 uint64_t fail_value, 437 bool *success_ptr); 438 439 bool 440 WriteMemoryUnsigned (const Context &context, 441 lldb::addr_t addr, 442 uint64_t uval, 443 size_t uval_byte_size); 444 445 uint32_t 446 GetAddressByteSize () const 447 { 448 return m_addr_byte_size; 449 } 450 451 lldb::ByteOrder 452 GetByteOrder () const 453 { 454 return m_byte_order; 455 } 456 457 uint64_t 458 OpcodeAsUnsigned (bool *success_ptr) 459 { 460 if (success_ptr) 461 *success_ptr = true; 462 switch (m_inst.opcode_type) 463 { 464 eOpcode8: return m_inst.opcode.inst8; 465 eOpcode16: return m_inst.opcode.inst16; 466 eOpcode32: return m_inst.opcode.inst32; 467 eOpcode64: return m_inst.opcode.inst64; 468 eOpcodeBytes: 469 break; 470 } 471 if (success_ptr) 472 *success_ptr = false; 473 return 0; 474 } 475 476protected: 477 lldb::ByteOrder m_byte_order; 478 uint32_t m_addr_byte_size; 479 void * m_baton; 480 ReadMemory m_read_mem_callback; 481 WriteMemory m_write_mem_callback; 482 ReadRegister m_read_reg_callback; 483 WriteRegister m_write_reg_callback; 484 485 lldb::addr_t m_inst_pc; 486 Instruction m_inst; 487 //------------------------------------------------------------------ 488 // For EmulateInstruction only 489 //------------------------------------------------------------------ 490 DISALLOW_COPY_AND_ASSIGN (EmulateInstruction); 491}; 492 493} // namespace lldb_private 494 495#endif // lldb_EmulateInstruction_h_ 496