diff options
-rw-r--r-- | lldb/include/lldb/API/SBInstruction.h | 2 | ||||
-rw-r--r-- | lldb/include/lldb/Core/Disassembler.h | 1 | ||||
-rw-r--r-- | lldb/include/lldb/Core/EmulateInstruction.h | 9 | ||||
-rw-r--r-- | lldb/source/API/SBInstruction.cpp | 11 | ||||
-rw-r--r-- | lldb/source/Core/Disassembler.cpp | 2 | ||||
-rw-r--r-- | lldb/source/Core/EmulateInstruction.cpp | 6 | ||||
-rw-r--r-- | lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp | 55 |
7 files changed, 69 insertions, 17 deletions
diff --git a/lldb/include/lldb/API/SBInstruction.h b/lldb/include/lldb/API/SBInstruction.h index d12c8ce8b09..6e6926cd728 100644 --- a/lldb/include/lldb/API/SBInstruction.h +++ b/lldb/include/lldb/API/SBInstruction.h @@ -53,7 +53,7 @@ public: GetDescription (lldb::SBStream &description); bool - EmulateWithFrame (lldb::SBFrame &frame); + EmulateWithFrame (lldb::SBFrame &frame, bool auto_advance_pc); bool DumpEmulation (const char * triple); // triple is to specify the architecture, e.g. 'armv6' or 'arm-apple-darwin' diff --git a/lldb/include/lldb/Core/Disassembler.h b/lldb/include/lldb/Core/Disassembler.h index 705d9bb7198..fda05bcb4ef 100644 --- a/lldb/include/lldb/Core/Disassembler.h +++ b/lldb/include/lldb/Core/Disassembler.h @@ -73,6 +73,7 @@ public: bool Emulate (const ArchSpec &arch, + bool auto_advance_pc, void *baton, EmulateInstruction::ReadMemory read_mem_callback, EmulateInstruction::WriteMemory write_mem_calback, diff --git a/lldb/include/lldb/Core/EmulateInstruction.h b/lldb/include/lldb/Core/EmulateInstruction.h index 2e8bccb2ef4..9a088c8cbeb 100644 --- a/lldb/include/lldb/Core/EmulateInstruction.h +++ b/lldb/include/lldb/Core/EmulateInstruction.h @@ -144,6 +144,8 @@ public: eContextAddition, eContextSubtraction, + + eContextAdvancePC, eContextReturnFromException }; @@ -412,6 +414,12 @@ public: virtual bool EvaluateInstruction () = 0; + bool + GetAdvancePC () { return m_advance_pc; } + + void + SetAdvancePC (bool value) { m_advance_pc = value; } + static void TranslateRegister (uint32_t reg_kind, uint32_t reg_num, std::string ®_name); @@ -548,6 +556,7 @@ protected: WriteRegister m_write_reg_callback; lldb::addr_t m_opcode_pc; Opcode m_opcode; + bool m_advance_pc; //------------------------------------------------------------------ // For EmulateInstruction only //------------------------------------------------------------------ diff --git a/lldb/source/API/SBInstruction.cpp b/lldb/source/API/SBInstruction.cpp index e46e8696ed0..a4ab1558fd0 100644 --- a/lldb/source/API/SBInstruction.cpp +++ b/lldb/source/API/SBInstruction.cpp @@ -116,7 +116,7 @@ SBInstruction::Print (FILE *out) } bool -SBInstruction::EmulateWithFrame (lldb::SBFrame &frame) +SBInstruction::EmulateWithFrame (lldb::SBFrame &frame, bool auto_advance_pc) { if (m_opaque_sp && frame.get()) { @@ -126,6 +126,7 @@ SBInstruction::EmulateWithFrame (lldb::SBFrame &frame) lldb_private::ArchSpec arch = target->GetArchitecture(); return m_opaque_sp->Emulate (arch, + auto_advance_pc, (void *) frame.get(), &lldb_private::EmulateInstruction::ReadMemoryFrame, &lldb_private::EmulateInstruction::WriteMemoryFrame, @@ -142,12 +143,8 @@ SBInstruction::DumpEmulation (const char *triple) { lldb_private::ArchSpec arch (triple, NULL); - return m_opaque_sp->Emulate (arch, - NULL, - &lldb_private::EmulateInstruction::ReadMemoryDefault, - &lldb_private::EmulateInstruction::WriteMemoryDefault, - &lldb_private::EmulateInstruction::ReadRegisterDefault, - &lldb_private::EmulateInstruction::WriteRegisterDefault); + return m_opaque_sp->DumpEmulation (arch); + } return false; } diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp index 2318cf5783d..c422113b688 100644 --- a/lldb/source/Core/Disassembler.cpp +++ b/lldb/source/Core/Disassembler.cpp @@ -504,6 +504,7 @@ Instruction::DumpEmulation (const ArchSpec &arch) bool Instruction::Emulate (const ArchSpec &arch, + bool auto_advance_pc, void *baton, EmulateInstruction::ReadMemory read_mem_callback, EmulateInstruction::WriteMemory write_mem_callback, @@ -516,6 +517,7 @@ Instruction::Emulate (const ArchSpec &arch, insn_emulator_ap->SetBaton (baton); insn_emulator_ap->SetCallbacks (read_mem_callback, write_mem_callback, read_reg_callback, write_reg_callback); insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress()); + insn_emulator_ap->SetAdvancePC (auto_advance_pc); return insn_emulator_ap->EvaluateInstruction (); } diff --git a/lldb/source/Core/EmulateInstruction.cpp b/lldb/source/Core/EmulateInstruction.cpp index 7130360fb34..e828dbc7ca1 100644 --- a/lldb/source/Core/EmulateInstruction.cpp +++ b/lldb/source/Core/EmulateInstruction.cpp @@ -70,7 +70,8 @@ EmulateInstruction::EmulateInstruction m_read_reg_callback (read_reg_callback), m_write_reg_callback (write_reg_callback), m_opcode (), - m_opcode_pc (LLDB_INVALID_ADDRESS) + m_opcode_pc (LLDB_INVALID_ADDRESS), + m_advance_pc (false) { } @@ -88,7 +89,8 @@ EmulateInstruction::EmulateInstruction m_write_mem_callback (&WriteMemoryDefault), m_read_reg_callback (&ReadRegisterDefault), m_write_reg_callback (&WriteRegisterDefault), - m_opcode_pc (LLDB_INVALID_ADDRESS) + m_opcode_pc (LLDB_INVALID_ADDRESS), + m_advance_pc (false) { ::memset (&m_opcode, 0, sizeof (m_opcode)); } diff --git a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp index 04abfbdb0de..1cd8440c191 100644 --- a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp +++ b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp @@ -11937,7 +11937,7 @@ EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode) // add (register) { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, // add (register-shifted register) - { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>m, <Rm>, <type> <RS>"}, + { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"}, // adr { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"}, @@ -12063,7 +12063,7 @@ EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode) { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"}, { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"}, { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"}, - { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strc<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"}, + { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"}, { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"}, { 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"}, { 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"}, @@ -12331,7 +12331,7 @@ EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode) { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" }, { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" }, { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" }, - { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" }, + { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" }, { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" }, { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" }, { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" }, @@ -12351,7 +12351,7 @@ EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode) { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" }, { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" }, { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" }, - { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt?, <Rt2>, [<Rn>,#+/-<imm>]!"}, + { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"}, { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" }, { 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, @@ -12832,8 +12832,13 @@ EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in) int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in; result = UnsignedBits(unsigned_sum, 31, 0); - carry_out = (result == unsigned_sum ? 0 : 1); +// carry_out = (result == unsigned_sum ? 0 : 1); overflow = ((int32_t)result == signed_sum ? 0 : 1); + + if (carry_in) + carry_out = ((int32_t) x >= (int32_t) y) ? 1 : 0; + else + carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0; AddWithCarryResult res = { result, carry_out, overflow }; return res; @@ -13057,7 +13062,43 @@ EmulateInstructionARM::EvaluateInstruction () // Just for now, for testing purposes. if (m_baton == NULL) - fprintf (stdout, "\nEvaluateInstruction, opcode (0x%x), found = '%s'\n", m_opcode.GetOpcode32(), opcode_data->name); + fprintf (stdout, "\nEvaluateInstruction, opcode (0x%x), found = '%s'\n", m_opcode.GetOpcode32(), + opcode_data->name); + + bool success; + if (m_baton) + { + uint32_t cpsr_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success); + if (success) + m_opcode_cpsr = cpsr_value; + } + + uint32_t orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success); + if (!success) + return false; - return (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding); // Call the Emulate... function. + success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding); // Call the Emulate... function. + if (!success) + return false; + + uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success); + if (!success) + return false; + + if (m_advance_pc && (after_pc_value == orig_pc_value)) + { + if (opcode_data->size == eSize32) + after_pc_value += 4; + else if (opcode_data->size == eSize16) + after_pc_value += 2; + + EmulateInstruction::Context context; + context.type = eContextAdvancePC; + context.SetNoArgs(); + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value)) + return false; + + } + + return true; } |