blob: f67e3505981f0de875fd56c42bbf3563d1c4e924 [file] [log] [blame]
Greg Clayton64c84432011-01-21 22:02:52 +00001//===-- 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
Greg Clayton17f5afe2011-02-05 02:56:16 +000010#include "lldb/Core/EmulateInstruction.h"
Greg Clayton64c84432011-01-21 22:02:52 +000011
Caroline Tice080bf612011-04-05 18:46:00 +000012#include "lldb/Core/DataBufferHeap.h"
Greg Clayton64c84432011-01-21 22:02:52 +000013#include "lldb/Core/DataExtractor.h"
Caroline Tice080bf612011-04-05 18:46:00 +000014#include "lldb/Core/Error.h"
Greg Clayton52fd9842011-02-02 02:24:04 +000015#include "lldb/Core/PluginManager.h"
Greg Clayton64c84432011-01-21 22:02:52 +000016#include "lldb/Core/StreamString.h"
Greg Claytoncd548032011-02-01 01:31:41 +000017#include "lldb/Host/Endian.h"
Caroline Tice080bf612011-04-05 18:46:00 +000018#include "lldb/Target/Process.h"
19#include "lldb/Target/RegisterContext.h"
20#include "lldb/Target/Thread.h"
21
22#include "Plugins/Instruction/ARM/EmulateInstructionARM.h"
23
Greg Clayton64c84432011-01-21 22:02:52 +000024using namespace lldb;
25using namespace lldb_private;
26
Greg Clayton52fd9842011-02-02 02:24:04 +000027EmulateInstruction*
Greg Clayton395fc332011-02-15 21:59:32 +000028EmulateInstruction::FindPlugin (const ArchSpec &arch, const char *plugin_name)
Greg Clayton52fd9842011-02-02 02:24:04 +000029{
30 EmulateInstructionCreateInstance create_callback = NULL;
31 if (plugin_name)
32 {
33 create_callback = PluginManager::GetEmulateInstructionCreateCallbackForPluginName (plugin_name);
34 if (create_callback)
35 {
Caroline Tice080bf612011-04-05 18:46:00 +000036 EmulateInstruction *emulate_insn_ptr = create_callback(arch);
37 if (emulate_insn_ptr)
38 return emulate_insn_ptr;
Greg Clayton52fd9842011-02-02 02:24:04 +000039 }
40 }
41 else
42 {
43 for (uint32_t idx = 0; (create_callback = PluginManager::GetEmulateInstructionCreateCallbackAtIndex(idx)) != NULL; ++idx)
44 {
Caroline Tice080bf612011-04-05 18:46:00 +000045 EmulateInstruction *emulate_insn_ptr = create_callback(arch);
46 if (emulate_insn_ptr)
47 return emulate_insn_ptr;
Greg Clayton52fd9842011-02-02 02:24:04 +000048 }
49 }
50 return NULL;
51}
Greg Clayton64c84432011-01-21 22:02:52 +000052
53EmulateInstruction::EmulateInstruction
54(
55 lldb::ByteOrder byte_order,
56 uint32_t addr_byte_size,
Caroline Tice080bf612011-04-05 18:46:00 +000057 const ArchSpec &arch,
Greg Clayton64c84432011-01-21 22:02:52 +000058 void *baton,
59 ReadMemory read_mem_callback,
60 WriteMemory write_mem_callback,
61 ReadRegister read_reg_callback,
62 WriteRegister write_reg_callback
63) :
Greg Claytoncd548032011-02-01 01:31:41 +000064 m_byte_order (endian::InlHostByteOrder()),
Caroline Tice080bf612011-04-05 18:46:00 +000065 m_addr_byte_size (addr_byte_size),
66 m_arch (arch),
Greg Clayton64c84432011-01-21 22:02:52 +000067 m_baton (baton),
68 m_read_mem_callback (read_mem_callback),
69 m_write_mem_callback (write_mem_callback),
70 m_read_reg_callback (read_reg_callback),
71 m_write_reg_callback (write_reg_callback),
Greg Clayton7bc39082011-03-24 23:53:38 +000072 m_opcode (),
Greg Claytonb3448432011-03-24 21:19:54 +000073 m_opcode_pc (LLDB_INVALID_ADDRESS)
Greg Clayton64c84432011-01-21 22:02:52 +000074{
Greg Clayton64c84432011-01-21 22:02:52 +000075}
76
Caroline Tice080bf612011-04-05 18:46:00 +000077EmulateInstruction::EmulateInstruction
78(
79 lldb::ByteOrder byte_order,
80 uint32_t addr_byte_size,
81 const ArchSpec &arch
82) :
83 m_byte_order (endian::InlHostByteOrder()),
84 m_addr_byte_size (addr_byte_size),
85 m_arch (arch),
86 m_baton (NULL),
87 m_read_mem_callback (&ReadMemoryDefault),
88 m_write_mem_callback (&WriteMemoryDefault),
89 m_read_reg_callback (&ReadRegisterDefault),
90 m_write_reg_callback (&WriteRegisterDefault),
91 m_opcode_pc (LLDB_INVALID_ADDRESS)
92{
93 ::memset (&m_opcode, 0, sizeof (m_opcode));
94}
95
Greg Clayton64c84432011-01-21 22:02:52 +000096uint64_t
97EmulateInstruction::ReadRegisterUnsigned (uint32_t reg_kind, uint32_t reg_num, uint64_t fail_value, bool *success_ptr)
98{
99 uint64_t uval64 = 0;
100 bool success = m_read_reg_callback (m_baton, reg_kind, reg_num, uval64);
101 if (success_ptr)
102 *success_ptr = success;
103 if (!success)
104 uval64 = fail_value;
105 return uval64;
106}
107
108bool
109EmulateInstruction::WriteRegisterUnsigned (const Context &context, uint32_t reg_kind, uint32_t reg_num, uint64_t reg_value)
110{
111 return m_write_reg_callback (m_baton, context, reg_kind, reg_num, reg_value);
112}
113
114uint64_t
115EmulateInstruction::ReadMemoryUnsigned (const Context &context, lldb::addr_t addr, size_t byte_size, uint64_t fail_value, bool *success_ptr)
116{
117 uint64_t uval64 = 0;
118 bool success = false;
119 if (byte_size <= 8)
120 {
121 uint8_t buf[sizeof(uint64_t)];
122 size_t bytes_read = m_read_mem_callback (m_baton, context, addr, buf, byte_size);
123 if (bytes_read == byte_size)
124 {
125 uint32_t offset = 0;
126 DataExtractor data (buf, byte_size, m_byte_order, m_addr_byte_size);
127 uval64 = data.GetMaxU64 (&offset, byte_size);
128 success = true;
129 }
130 }
131
132 if (success_ptr)
133 *success_ptr = success;
134
135 if (!success)
136 uval64 = fail_value;
137 return uval64;
138}
139
140
141bool
142EmulateInstruction::WriteMemoryUnsigned (const Context &context,
143 lldb::addr_t addr,
144 uint64_t uval,
145 size_t uval_byte_size)
146{
147 StreamString strm(Stream::eBinary, GetAddressByteSize(), GetByteOrder());
148 strm.PutMaxHex64 (uval, uval_byte_size);
149
150 size_t bytes_written = m_write_mem_callback (m_baton, context, addr, strm.GetData(), uval_byte_size);
151 if (bytes_written == uval_byte_size)
152 return true;
153 return false;
154}
Caroline Tice080bf612011-04-05 18:46:00 +0000155
156
157void
158EmulateInstruction::SetBaton (void *baton)
159{
160 m_baton = baton;
161}
162
163void
164EmulateInstruction::SetCallbacks (ReadMemory read_mem_callback,
165 WriteMemory write_mem_callback,
166 ReadRegister read_reg_callback,
167 WriteRegister write_reg_callback)
168{
169 m_read_mem_callback = read_mem_callback;
170 m_write_mem_callback = write_mem_callback;
171 m_read_reg_callback = read_reg_callback;
172 m_write_reg_callback = write_reg_callback;
173}
174
175void
176EmulateInstruction::SetReadMemCallback (ReadMemory read_mem_callback)
177{
178 m_read_mem_callback = read_mem_callback;
179}
180
181
182void
183EmulateInstruction::SetWriteMemCallback (WriteMemory write_mem_callback)
184{
185 m_write_mem_callback = write_mem_callback;
186}
187
188
189void
190EmulateInstruction::SetReadRegCallback (ReadRegister read_reg_callback)
191{
192 m_read_reg_callback = read_reg_callback;
193}
194
195
196void
197EmulateInstruction::SetWriteRegCallback (WriteRegister write_reg_callback)
198{
199 m_write_reg_callback = write_reg_callback;
200}
201
202
203
204//
205// Read & Write Memory and Registers callback functions.
206//
207
208size_t
209EmulateInstruction::ReadMemoryProcess (void *baton,
210 const Context &context,
211 lldb::addr_t addr,
212 void *dst,
213 size_t length)
214{
215 Process *process = (Process *) baton;
216
217 if (!process)
218 return 0;
219
220 DataBufferSP data_sp (new DataBufferHeap (length, '\0'));
221 Error error;
222
223 size_t bytes_read = process->ReadMemory (addr, data_sp->GetBytes(), data_sp->GetByteSize(), error);
224
225 if (bytes_read > 0)
226 ((DataBufferHeap *) data_sp.get())->CopyData (dst, length);
227
228 return bytes_read;
229}
230
231size_t
232EmulateInstruction::WriteMemoryProcess (void *baton,
233 const Context &context,
234 lldb::addr_t addr,
235 const void *dst,
236 size_t length)
237{
238 Process *process = (Process *) baton;
239
240 if (!process)
241 return 0;
242
243 lldb::DataBufferSP data_sp (new DataBufferHeap (dst, length));
244 if (data_sp)
245 {
246 length = data_sp->GetByteSize();
247 if (length > 0)
248 {
249 Error error;
250 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
251
252 return bytes_written;
253 }
254 }
255
256 return 0;
257}
258
259bool
260EmulateInstruction::ReadRegisterProcess (void *baton,
261 uint32_t reg_kind,
262 uint32_t reg_num,
263 uint64_t &reg_value)
264{
265 Process *process = (Process *) baton;
266 if (!process)
267 return false;
268
269 Thread *thread = process->CalculateThread ();
270 RegisterContext *reg_context = thread->GetRegisterContext().get();
271 Scalar value;
272
273
274 if (reg_context->ReadRegisterValue (reg_num, value))
275 {
276 reg_value = value.GetRawBits64 (0);
277 return true;
278 }
279
280 return false;
281}
282
283bool
284EmulateInstruction::WriteRegisterProcess (void *baton,
285 const Context &context,
286 uint32_t reg_kind,
287 uint32_t reg_num,
288 uint64_t reg_value)
289{
290 Process *process = (Process *) baton;
291 Thread *thread = process->CalculateThread ();
292 RegisterContext *reg_context = thread->GetRegisterContext().get();
293 Scalar value (reg_value);
294
295 return reg_context->WriteRegisterValue (reg_num, value);
296}
297
298size_t
299EmulateInstruction::ReadMemoryDefault (void *baton,
300 const Context &context,
301 lldb::addr_t addr,
302 void *dst,
303 size_t length)
304{
305 PrintContext ("Read from memory", context);
306 fprintf (stdout, " Read from Memory (address = %p, length = %d)\n",(void *) addr, (uint) length);
307
308 *((uint64_t *) dst) = 0xdeadbeef;
309 return length;
310}
311
312size_t
313EmulateInstruction::WriteMemoryDefault (void *baton,
314 const Context &context,
315 lldb::addr_t addr,
316 const void *dst,
317 size_t length)
318{
319 PrintContext ("Write to memory", context);
320 fprintf (stdout, " Write to Memory (address = %p, length = %d)\n", (void *) addr, (uint) length);
321 return length;
322}
323
324bool
325EmulateInstruction::ReadRegisterDefault (void *baton,
326 uint32_t reg_kind,
327 uint32_t reg_num,
328 uint64_t &reg_value)
329{
330 std::string reg_name;
331 TranslateRegister (reg_kind, reg_num, reg_name);
332 fprintf (stdout, " Read Register (%s)\n", reg_name.c_str());
333
334 reg_value = 24;
335 return true;
336}
337
338bool
339EmulateInstruction::WriteRegisterDefault (void *baton,
340 const Context &context,
341 uint32_t reg_kind,
342 uint32_t reg_num,
343 uint64_t reg_value)
344{
345 PrintContext ("Write to register", context);
346 std::string reg_name;
347 TranslateRegister (reg_kind, reg_num, reg_name);
348 fprintf (stdout, " Write to Register (%s), value = 0x%llx\n", reg_name.c_str(), reg_value);
349 return true;
350}
351
352void
353EmulateInstruction::PrintContext (const char *context_type, const Context &context)
354{
355 switch (context.type)
356 {
357 case eContextReadOpcode:
358 fprintf (stdout, " %s context: Reading an Opcode\n", context_type);
359 break;
360
361 case eContextImmediate:
362 fprintf (stdout, " %s context: Immediate\n", context_type);
363 break;
364
365 case eContextPushRegisterOnStack:
366 fprintf (stdout, " %s context: Pushing a register onto the stack.\n", context_type);
367 break;
368
369 case eContextPopRegisterOffStack:
370 fprintf (stdout, " %s context: Popping a register off the stack.\n", context_type);
371 break;
372
373 case eContextAdjustStackPointer:
374 fprintf (stdout, " %s context: Adjusting the stack pointer.\n", context_type);
375 break;
376
377 case eContextAdjustBaseRegister:
378 fprintf (stdout, " %s context: Adjusting (writing value back to) a base register.\n", context_type);
379 break;
380
381 case eContextRegisterPlusOffset:
382 fprintf (stdout, " %s context: Register plus offset\n", context_type);
383 break;
384
385 case eContextRegisterStore:
386 fprintf (stdout, " %s context: Storing a register.\n", context_type);
387 break;
388
389 case eContextRegisterLoad:
390 fprintf (stdout, " %s context: Loading a register.\n", context_type);
391 break;
392
393 case eContextRelativeBranchImmediate:
394 fprintf (stdout, " %s context: Relative branch immediate\n", context_type);
395 break;
396
397 case eContextAbsoluteBranchRegister:
398 fprintf (stdout, " %s context: Absolute branch register\n", context_type);
399 break;
400
401 case eContextSupervisorCall:
402 fprintf (stdout, " %s context: Performing a supervisor call.\n", context_type);
403 break;
404
405 case eContextTableBranchReadMemory:
406 fprintf (stdout, " %s context: Table branch read memory\n", context_type);
407 break;
408
409 case eContextWriteRegisterRandomBits:
410 fprintf (stdout, " %s context: Write random bits to a register\n", context_type);
411 break;
412
413 case eContextWriteMemoryRandomBits:
414 fprintf (stdout, " %s context: Write random bits to a memory address\n", context_type);
415 break;
416
417 case eContextMultiplication:
418 fprintf (stdout, " %s context: Performing a multiplication\n", context_type);
419 break;
420
421 case eContextAddition:
422 fprintf (stdout, " %s context: Performing an addition\n", context_type);
423 break;
424
425 case eContextReturnFromException:
426 fprintf (stdout, " %s context: Returning from an exception\n", context_type);
427 break;
428
429 default:
430 fprintf (stdout, " %s context: Unrecognized context.\n", context_type);
431 break;
432 }
433
434 switch (context.info_type)
435 {
436 case eInfoTypeRegisterPlusOffset:
437 {
438 std::string reg_name;
439 TranslateRegister (context.info.RegisterPlusOffset.reg.kind,
440 context.info.RegisterPlusOffset.reg.num,
441 reg_name);
442 fprintf (stdout, " Info type: Register plus offset (%s +/- %lld)\n", reg_name.c_str(),
443 context.info.RegisterPlusOffset.signed_offset);
444 }
445 break;
446 case eInfoTypeRegisterPlusIndirectOffset:
447 {
448 std::string base_reg_name;
449 std::string offset_reg_name;
450 TranslateRegister (context.info.RegisterPlusIndirectOffset.base_reg.kind,
451 context.info.RegisterPlusIndirectOffset.base_reg.num,
452 base_reg_name);
453 TranslateRegister (context.info.RegisterPlusIndirectOffset.offset_reg.kind,
454 context.info.RegisterPlusIndirectOffset.offset_reg.num,
455 offset_reg_name);
456 fprintf (stdout, " Info type: Register plus indirect offset (%s +/- %s)\n",
457 base_reg_name.c_str(),
458 offset_reg_name.c_str());
459 }
460 break;
461 case eInfoTypeRegisterToRegisterPlusOffset:
462 {
463 std::string base_reg_name;
464 std::string data_reg_name;
465 TranslateRegister (context.info.RegisterToRegisterPlusOffset.base_reg.kind,
466 context.info.RegisterToRegisterPlusOffset.base_reg.num,
467 base_reg_name);
468 TranslateRegister (context.info.RegisterToRegisterPlusOffset.data_reg.kind,
469 context.info.RegisterToRegisterPlusOffset.data_reg.num,
470 data_reg_name);
471 fprintf (stdout, " Info type: Register plus offset (%s +/- %lld) and data register (%s)\n",
472 base_reg_name.c_str(), context.info.RegisterToRegisterPlusOffset.offset,
473 data_reg_name.c_str());
474 }
475 break;
476 case eInfoTypeRegisterToRegisterPlusIndirectOffset:
477 {
478 std::string base_reg_name;
479 std::string offset_reg_name;
480 std::string data_reg_name;
481 TranslateRegister (context.info.RegisterToRegisterPlusIndirectOffset.base_reg.kind,
482 context.info.RegisterToRegisterPlusIndirectOffset.base_reg.num,
483 base_reg_name);
484 TranslateRegister (context.info.RegisterToRegisterPlusIndirectOffset.offset_reg.kind,
485 context.info.RegisterToRegisterPlusIndirectOffset.offset_reg.num,
486 offset_reg_name);
487 TranslateRegister (context.info.RegisterToRegisterPlusIndirectOffset.data_reg.kind,
488 context.info.RegisterToRegisterPlusIndirectOffset.data_reg.num,
489 data_reg_name);
490 fprintf (stdout, " Info type: Register plus indirect offset (%s +/- %s) and data register (%s)\n",
491 base_reg_name.c_str(), offset_reg_name.c_str(), data_reg_name.c_str());
492 }
493 break;
494
495 case eInfoTypeRegisterRegisterOperands:
496 {
497 std::string op1_reg_name;
498 std::string op2_reg_name;
499 TranslateRegister (context.info.RegisterRegisterOperands.operand1.kind,
500 context.info.RegisterRegisterOperands.operand1.num,
501 op1_reg_name);
502 TranslateRegister (context.info.RegisterRegisterOperands.operand2.kind,
503 context.info.RegisterRegisterOperands.operand2.num,
504 op2_reg_name);
505 fprintf (stdout, " Info type: Register operands for binary op (%s, %s)\n",
506 op1_reg_name.c_str(),
507 op2_reg_name.c_str());
508 }
509 break;
510 case eInfoTypeOffset:
511 fprintf (stdout, " Info type: signed offset (%lld)\n", context.info.signed_offset);
512 break;
513
514 case eInfoTypeRegister:
515 {
516 std::string reg_name;
517 TranslateRegister (context.info.reg.kind, context.info.reg.num, reg_name);
518 fprintf (stdout, " Info type: Register (%s)\n", reg_name.c_str());
519 }
520 break;
521
522 case eInfoTypeImmediate:
523 fprintf (stdout, " Info type: Immediate (%lld)\n", context.info.immediate);
524 break;
525
526 case eInfoTypeImmediateSigned:
527 fprintf (stdout, " Info type: Signed immediate (%lld)\n", context.info.signed_immediate);
528 break;
529
530 case eInfoTypeAddress:
531 fprintf (stdout, " Info type: Address (%p)\n", (void *) context.info.address);
532 break;
533
534 case eInfoTypeModeAndImmediate:
535 {
536 std::string mode_name;
537
538 if (context.info.ModeAndImmediate.mode == EmulateInstructionARM::eModeARM)
539 mode_name = "ARM";
540 else if (context.info.ModeAndImmediate.mode == EmulateInstructionARM::eModeThumb)
541 mode_name = "Thumb";
542 else
543 mode_name = "Unknown mode";
544
545 fprintf (stdout, " Info type: Mode (%s) and immediate (%d)\n", mode_name.c_str(),
546 context.info.ModeAndImmediate.data_value);
547 }
548 break;
549
550 case eInfoTypeModeAndImmediateSigned:
551 {
552 std::string mode_name;
553
554 if (context.info.ModeAndImmediateSigned.mode == EmulateInstructionARM::eModeARM)
555 mode_name = "ARM";
556 else if (context.info.ModeAndImmediateSigned.mode == EmulateInstructionARM::eModeThumb)
557 mode_name = "Thumb";
558 else
559 mode_name = "Unknown mode";
560
561 fprintf (stdout, " Info type: Mode (%s) and signed immediate (%d)\n", mode_name.c_str(),
562 context.info.ModeAndImmediateSigned.signed_data_value);
563 }
564 break;
565
566 case eInfoTypeMode:
567 {
568 std::string mode_name;
569
570 if (context.info.mode == EmulateInstructionARM::eModeARM)
571 mode_name = "ARM";
572 else if (context.info.mode == EmulateInstructionARM::eModeThumb)
573 mode_name = "Thumb";
574 else
575 mode_name = "Unknown mode";
576
577 fprintf (stdout, " Info type: Mode (%s)\n", mode_name.c_str());
578 }
579 break;
580
581 case eInfoTypeNoArgs:
582 fprintf (stdout, " Info type: no arguments\n");
583 break;
584
585 default:
586 break;
587 }
588}
589
590void
591EmulateInstruction::TranslateRegister (uint32_t kind, uint32_t num, std::string &name)
592{
593 if (kind == eRegisterKindDWARF)
594 {
595 if (num == 13) //dwarf_sp NOTE: This is ARM-SPECIFIC
596 name = "sp";
597 else if (num == 14) //dwarf_lr NOTE: This is ARM-SPECIFIC
598 name = "lr";
599 else if (num == 15) //dwarf_pc NOTE: This is ARM-SPECIFIC
600 name = "pc";
601 else if (num == 16) //dwarf_cpsr NOTE: This is ARM-SPECIFIC
602 name = "cpsr";
603 else
604 {
605 StreamString sstr;
606
607 sstr.Printf ("r%d", num);
608 name = sstr.GetData();
609 }
610
611 }
612 else if (kind == eRegisterKindGeneric)
613 {
614 if (num == LLDB_REGNUM_GENERIC_SP)
615 name = "sp";
616 else if (num == LLDB_REGNUM_GENERIC_FLAGS)
617 name = "cpsr";
618 else if (num == LLDB_REGNUM_GENERIC_PC)
619 name = "pc";
620 else if (num == LLDB_REGNUM_GENERIC_RA)
621 name = "lr";
622 else
623 {
624 StreamString sstr;
625
626 sstr.Printf ("r%d", num);
627 name = sstr.GetData();
628 }
629 }
630 else
631 {
632 StreamString sstr;
633
634 sstr.Printf ("r%d", num);
635 name = sstr.GetData();
636 }
637}
638
639
640