diff options
7 files changed, 112 insertions, 12 deletions
diff --git a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp index a08adc866c9..9e45bc4b0a0 100644 --- a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp +++ b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp @@ -42,9 +42,10 @@ using namespace lldb_private; // A8.6.50 // Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition. -static unsigned short CountITSize(unsigned ITMask) { +static uint32_t +CountITSize (uint32_t ITMask) { // First count the trailing zeros of the IT mask. - unsigned TZ = llvm::CountTrailingZeros_32(ITMask); + uint32_t TZ = llvm::CountTrailingZeros_32(ITMask); if (TZ > 3) { printf("Encoding error: IT Mask '0000'\n"); @@ -54,7 +55,7 @@ static unsigned short CountITSize(unsigned ITMask) { } // Init ITState. Note that at least one bit is always 1 in mask. -bool ITSession::InitIT(unsigned short bits7_0) +bool ITSession::InitIT(uint32_t bits7_0) { ITCounter = CountITSize(Bits32(bits7_0, 3, 0)); if (ITCounter == 0) @@ -138,6 +139,7 @@ uint32_t ITSession::GetCond() #define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8) #define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8) #define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8) +#define ARMV7_ABOVE (ARMv7|ARMv8) #define No_VFP 0 #define VFPv1 (1u << 1) @@ -274,6 +276,24 @@ EmulateInstructionARM::GetRegisterInfo (uint32_t reg_kind, uint32_t reg_num, Reg return false; } +uint32_t +EmulateInstructionARM::GetFramePointerRegisterNumber () const +{ + if (m_opcode_mode == eModeThumb || m_arch.GetTriple().getOS() == llvm::Triple::Darwin) + return 7; + else + return 11; +} + +uint32_t +EmulateInstructionARM::GetFramePointerDWARFRegisterNumber () const +{ + if (m_opcode_mode == eModeThumb || m_arch.GetTriple().getOS() == llvm::Triple::Darwin) + return dwarf_r7; + else + return dwarf_r11; +} + // Push Multiple Registers stores multiple registers to the stack, storing to // consecutive memory locations ending just below the address in SP, and updates // SP to point to the start of the stored data. @@ -630,7 +650,10 @@ EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding } EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRegisterPlusOffset; + if (Rd == GetFramePointerRegisterNumber()) + context.type = EmulateInstruction::eContextSetFramePointer; + else + context.type = EmulateInstruction::eContextRegisterPlusOffset; RegisterInfo sp_reg; GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); context.SetRegisterPlusOffset (sp_reg, 0); @@ -2153,6 +2176,13 @@ EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encod return true; } +bool +EmulateInstructionARM::EmulateNop (const uint32_t opcode, const ARMEncoding encoding) +{ + // NOP, nothing to do... + return true; +} + // Branch causes a branch to a target address. bool EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding) @@ -12377,7 +12407,13 @@ EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode, uint //---------------------------------------------------------------------- // If Then makes up to four following instructions conditional. //---------------------------------------------------------------------- - { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"}, + // The next 5 opcode _must_ come before the if then instruction + { 0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop"}, + { 0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"}, + { 0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"}, + { 0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"}, + { 0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"}, + { 0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"}, //---------------------------------------------------------------------- // Branch instructions diff --git a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h index dbafe6924d8..d5ce73c5a98 100644 --- a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h +++ b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h @@ -25,7 +25,7 @@ public: ~ITSession() {} // InitIT - Initializes ITCounter/ITState. - bool InitIT(unsigned short bits7_0); + bool InitIT(uint32_t bits7_0); // ITAdvance - Updates ITCounter/ITState as IT Block progresses. void ITAdvance(); @@ -370,6 +370,11 @@ protected: const char *name; } ARMOpcode; + uint32_t + GetFramePointerRegisterNumber () const; + + uint32_t + GetFramePointerDWARFRegisterNumber () const; static ARMOpcode* GetARMOpcodeForInstruction (const uint32_t opcode, uint32_t isa_mask); @@ -461,6 +466,10 @@ protected: bool EmulateIT (const uint32_t opcode, const ARMEncoding encoding); + // NOP + bool + EmulateNop (const uint32_t opcode, const ARMEncoding encoding); + // A8.6.16 B bool EmulateB (const uint32_t opcode, const ARMEncoding encoding); diff --git a/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp index e8408dcd459..81c64de7c59 100644 --- a/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp +++ b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp @@ -177,6 +177,8 @@ StopInfoMachException::GetDescription () case llvm::Triple::arm: switch (m_exc_code) { + case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break; + case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break; case 1: code_desc = "EXC_ARM_BREAKPOINT"; break; } break; @@ -311,7 +313,13 @@ StopInfoMachException::CreateStopReasonWithMachException break; case llvm::Triple::arm: - is_software_breakpoint = exc_code == 1; // EXC_ARM_BREAKPOINT + if (exc_code == 0x102) + { + // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as EXC_BAD_ACCESS + return StopInfo::CreateStopReasonToTrace(thread); + } + else + is_software_breakpoint = exc_code == 1; // EXC_ARM_BREAKPOINT break; default: diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index 62472732d17..ee6bff6a5d2 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -425,14 +425,16 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data //ReadRegisterBytes (const RegisterInfo *reg_info, RegisterValue &value, DataExtractor &data) const RegisterInfo *reg_info; - for (uint32_t reg_idx=0; (reg_info = GetRegisterInfoAtIndex (reg_idx)) != NULL; ++reg_idx) + // We have to march the offset of each register along in the + // buffer to make sure we get the right offset. + uint32_t reg_byte_offset = 0; + for (uint32_t reg_idx=0; (reg_info = GetRegisterInfoAtIndex (reg_idx)) != NULL; ++reg_idx, reg_byte_offset += reg_info->byte_size) { const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; // Only write down the registers that need to be written // if we are going to be doing registers individually. bool write_reg = true; - const uint32_t reg_byte_offset = reg_info->byte_offset; const uint32_t reg_byte_size = reg_info->byte_size; const char *restore_src = (const char *)restore_data.PeekData(reg_byte_offset, reg_byte_size); diff --git a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp index 6ebcd60845b..c8eba035339 100644 --- a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp +++ b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp @@ -2572,7 +2572,7 @@ DNBArchMachARM::g_gpr_registers[] = DEFINE_GPR_IDX ( 4, r4, NULL, INVALID_NUB_REGNUM ), DEFINE_GPR_IDX ( 5, r5, NULL, INVALID_NUB_REGNUM ), DEFINE_GPR_IDX ( 6, r6, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX ( 7, r7, NULL, GENERIC_REGNUM_FP ), + DEFINE_GPR_IDX ( 7, r7, "fp", GENERIC_REGNUM_FP ), DEFINE_GPR_IDX ( 8, r8, NULL, INVALID_NUB_REGNUM ), DEFINE_GPR_IDX ( 9, r9, NULL, INVALID_NUB_REGNUM ), DEFINE_GPR_IDX (10, r10, NULL, INVALID_NUB_REGNUM ), diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp index 2548d3d04cc..cc3091da631 100644 --- a/lldb/tools/debugserver/source/RNBRemote.cpp +++ b/lldb/tools/debugserver/source/RNBRemote.cpp @@ -877,7 +877,23 @@ g_gdb_register_map_arm[] = { 55, 4, "s29", {0}, NULL, 0}, { 56, 4, "s30", {0}, NULL, 0}, { 57, 4, "s31", {0}, NULL, 0}, - { 58, 4, "fpscr", {0}, NULL, 0} + { 58, 4, "fpscr", {0}, NULL, 0}, + { 59, 8, "d16", {0}, NULL, 0}, + { 60, 8, "d17", {0}, NULL, 0}, + { 61, 8, "d18", {0}, NULL, 0}, + { 62, 8, "d19", {0}, NULL, 0}, + { 63, 8, "d20", {0}, NULL, 0}, + { 64, 8, "d21", {0}, NULL, 0}, + { 65, 8, "d22", {0}, NULL, 0}, + { 66, 8, "d23", {0}, NULL, 0}, + { 67, 8, "d24", {0}, NULL, 0}, + { 68, 8, "d25", {0}, NULL, 0}, + { 69, 8, "d26", {0}, NULL, 0}, + { 70, 8, "d27", {0}, NULL, 0}, + { 71, 8, "d28", {0}, NULL, 0}, + { 72, 8, "d29", {0}, NULL, 0}, + { 73, 8, "d30", {0}, NULL, 0}, + { 74, 8, "d31", {0}, NULL, 0} }; register_map_entry_t diff --git a/lldb/tools/debugserver/source/debugserver.cpp b/lldb/tools/debugserver/source/debugserver.cpp index 12a873ef8e3..24e33e72a0e 100644 --- a/lldb/tools/debugserver/source/debugserver.cpp +++ b/lldb/tools/debugserver/source/debugserver.cpp @@ -831,7 +831,36 @@ main (int argc, char *argv[]) RNBRunLoopMode start_mode = eRNBRunLoopModeExit; - while ((ch = getopt_long(argc, argv, "a:A:d:gi:vktl:f:w:x:rs:nu:", g_long_options, &long_option_index)) != -1) + char short_options[512]; + uint32_t short_options_idx = 0; + + // Handle the two case that don't have short options in g_long_options + short_options[short_options_idx++] = 'k'; + short_options[short_options_idx++] = 't'; + + for (i=0; g_long_options[i].name != NULL; ++i) + { + if (isalpha(g_long_options[i].val)) + { + short_options[short_options_idx++] = g_long_options[i].val; + switch (g_long_options[i].has_arg) + { + default: + case no_argument: + break; + + case optional_argument: + short_options[short_options_idx++] = ':'; + // Fall through to required_argument case below... + case required_argument: + short_options[short_options_idx++] = ':'; + break; + } + } + } + // NULL terminate the short option string. + short_options[short_options_idx++] = '\0'; + while ((ch = getopt_long(argc, argv, short_options, g_long_options, &long_option_index)) != -1) { DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n", ch, (uint8_t)ch, |