Index: include/lldb/lldb-private-types.h =================================================================== --- include/lldb/lldb-private-types.h +++ include/lldb/lldb-private-types.h @@ -54,6 +54,10 @@ // null, all registers in this list will be invalidated when the value of this // register changes. For example, the invalidate list for eax would be rax // ax, ah, and al. + const uint8_t *dynamic_size_dwarf_expr_bytes; // A DWARF expression that when evaluated gives + // the byte size of this register. + size_t dynamic_size_dwarf_len; // The length of the DWARF expression in bytes in the + // dynamic_size_dwarf_expr_bytes member }; //---------------------------------------------------------------------- Index: source/Plugins/Process/Utility/DynamicRegisterInfo.h =================================================================== --- source/Plugins/Process/Utility/DynamicRegisterInfo.h +++ source/Plugins/Process/Utility/DynamicRegisterInfo.h @@ -56,6 +56,9 @@ const lldb_private::RegisterInfo * GetRegisterInfoAtIndex (uint32_t i) const; + lldb_private::RegisterInfo * + GetRegisterInfoAtIndex (uint32_t i); + const lldb_private::RegisterSet * GetRegisterSet (uint32_t i) const; @@ -81,6 +84,8 @@ typedef std::vector set_reg_num_collection; typedef std::vector name_collection; typedef std::map reg_to_regs_map; + typedef std::vector dwarf_opcode; + typedef std::map dynamic_reg_size_map; lldb_private::RegisterInfo * GetRegisterInfo (const lldb_private::ConstString ®_name); @@ -91,6 +96,7 @@ name_collection m_set_names; reg_to_regs_map m_value_regs_map; reg_to_regs_map m_invalidate_regs_map; + dynamic_reg_size_map m_dynamic_reg_size_map; size_t m_reg_data_byte_size; // The number of bytes required to store all registers bool m_finalized; }; Index: source/Plugins/Process/Utility/DynamicRegisterInfo.cpp =================================================================== --- source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -19,7 +19,7 @@ #include "lldb/Core/StructuredData.h" #include "lldb/DataFormatters/FormatManager.h" #include "lldb/Host/StringConvert.h" - +#include "lldb/Utility/StringExtractor.h" using namespace lldb; using namespace lldb_private; @@ -30,6 +30,7 @@ m_set_names (), m_value_regs_map (), m_invalidate_regs_map (), + m_dynamic_reg_size_map (), m_reg_data_byte_size (0), m_finalized (false) { @@ -43,6 +44,7 @@ m_set_names (), m_value_regs_map (), m_invalidate_regs_map (), + m_dynamic_reg_size_map (), m_reg_data_byte_size (0), m_finalized (false) { @@ -292,6 +294,26 @@ reg_info.byte_size = bitsize / 8; + uint8_t dynamic_size = 0; + reg_info_dict->GetValueForKeyAsInteger("dynamic_size_dwarf_len", dynamic_size); + reg_info.dynamic_size_dwarf_len = dynamic_size; + + std::string dwarf_opcode_string; + if(reg_info_dict->GetValueForKeyAsString("dynamic_size_dwarf_expr_bytes", dwarf_opcode_string)) + { + uint8_t dwarf_opcode[8]; + uint32_t j; + assert(reg_info.dynamic_size_dwarf_len > 0); + StringExtractor name_extractor; + + // Swap "dwarf_opcode_string" over into "name_extractor" + name_extractor.GetStringRef().swap(dwarf_opcode_string); + uint32_t ret_val = name_extractor.GetHexBytesAvail (dwarf_opcode, reg_info.dynamic_size_dwarf_len); + assert(ret_val == reg_info.dynamic_size_dwarf_len); + for (j = 0; j < reg_info.dynamic_size_dwarf_len; ++j) + m_dynamic_reg_size_map[i].push_back(dwarf_opcode[j]); + } + std::string format_str; if (reg_info_dict->GetValueForKeyAsString("format", format_str, nullptr)) { @@ -417,6 +439,11 @@ for (i=0; reg_info.invalidate_regs[i] != LLDB_INVALID_REGNUM; ++i) m_invalidate_regs_map[reg_num].push_back(reg_info.invalidate_regs[i]); } + if (reg_info.dynamic_size_dwarf_expr_bytes) + { + for (i = 0; i < reg_info.dynamic_size_dwarf_len; ++i) + m_dynamic_reg_size_map[reg_num].push_back(reg_info.dynamic_size_dwarf_expr_bytes[i]); + } m_regs.push_back (reg_info); uint32_t set = GetRegisterSetIndexByName (set_name, true); assert (set < m_sets.size()); @@ -641,6 +668,14 @@ return NULL; } +RegisterInfo * +DynamicRegisterInfo::GetRegisterInfoAtIndex (uint32_t i) +{ + if (i < m_regs.size()) + return &m_regs[i]; + return NULL; +} + const RegisterSet * DynamicRegisterInfo::GetRegisterSet (uint32_t i) const { @@ -702,11 +737,12 @@ for (size_t i=0; ireg) / 2, GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_mips }, NULL, NULL } + eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_mips }, NULL, NULL, NULL, 0} + +const uint8_t dwarf_opcode_mips [] = { + llvm::dwarf::DW_OP_regx, dwarf_sr_mips, llvm::dwarf::DW_OP_lit1, + llvm::dwarf::DW_OP_lit26, llvm::dwarf::DW_OP_shl, llvm::dwarf::DW_OP_and, + llvm::dwarf::DW_OP_lit26, llvm::dwarf::DW_OP_shr + }; #define DEFINE_FPR(reg, alt, kind1, kind2, kind3, kind4) \ { #reg, alt, sizeof(((FPR_linux_mips*)NULL)->reg), FPR_OFFSET(reg), eEncodingIEEE754, \ - eFormatFloat, { kind1, kind2, kind3, kind4, fpr_##reg##_mips }, NULL, NULL } + eFormatFloat, { kind1, kind2, kind3, kind4, fpr_##reg##_mips }, NULL, NULL, dwarf_opcode_mips, sizeof(dwarf_opcode_mips)} #define DEFINE_FPR_INFO(reg, alt, kind1, kind2, kind3, kind4) \ { #reg, alt, sizeof(((FPR_linux_mips*)NULL)->reg), FPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, fpr_##reg##_mips }, NULL, NULL } + eFormatHex, { kind1, kind2, kind3, kind4, fpr_##reg##_mips }, NULL, NULL, NULL, 0 } #define DEFINE_MSA(reg, alt, kind1, kind2, kind3, kind4) \ { #reg, alt, sizeof(((MSA_linux_mips*)0)->reg), MSA_OFFSET(reg), eEncodingVector, \ - eFormatVectorOfUInt8, { kind1, kind2, kind3, kind4, msa_##reg##_mips }, NULL, NULL } + eFormatVectorOfUInt8, { kind1, kind2, kind3, kind4, msa_##reg##_mips }, NULL, NULL, NULL, 0 } #define DEFINE_MSA_INFO(reg, alt, kind1, kind2, kind3, kind4) \ { #reg, alt, sizeof(((MSA_linux_mips*)0)->reg), MSA_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, msa_##reg##_mips }, NULL, NULL } + eFormatHex, { kind1, kind2, kind3, kind4, msa_##reg##_mips }, NULL, NULL, NULL, 0 } // RegisterKind: EH_Frame, DWARF, Generic, Procss Plugin, LLDB Index: source/Plugins/Process/Utility/RegisterInfos_mips64.h =================================================================== --- source/Plugins/Process/Utility/RegisterInfos_mips64.h +++ source/Plugins/Process/Utility/RegisterInfos_mips64.h @@ -13,7 +13,7 @@ // C++ Includes // Other libraries and framework includes #include "llvm/Support/Compiler.h" - +#include "lldb/Core/dwarf.h" // Project includes #ifdef DECLARE_REGISTER_INFOS_MIPS64_STRUCT @@ -44,32 +44,39 @@ #ifdef LINUX_MIPS64 #define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ { #reg, alt, sizeof(((GPR_linux_mips*)0)->reg), GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_mips64 }, NULL, NULL } + eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_mips64 }, NULL, NULL, NULL, 0} #else #define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ { #reg, alt, sizeof(((GPR_freebsd_mips*)0)->reg), GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_mips64 }, NULL, NULL } + eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_mips64 }, NULL, NULL, NULL, 0} #endif #define DEFINE_GPR_INFO(reg, alt, kind1, kind2, kind3, kind4) \ { #reg, alt, sizeof(((GPR_linux_mips*)0)->reg) / 2, GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_mips64 }, NULL, NULL } + eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_mips64 }, NULL, NULL, NULL, 0} + +const uint8_t dwarf_opcode_mips64 [] = { + llvm::dwarf::DW_OP_regx, dwarf_sr_mips64, llvm::dwarf::DW_OP_lit1, + llvm::dwarf::DW_OP_lit26, llvm::dwarf::DW_OP_shl, llvm::dwarf::DW_OP_and, + llvm::dwarf::DW_OP_lit26, llvm::dwarf::DW_OP_shr + }; + #define DEFINE_FPR(reg, alt, kind1, kind2, kind3, kind4) \ { #reg, alt, sizeof(((FPR_linux_mips*)0)->reg), FPR_OFFSET(reg), eEncodingIEEE754, \ - eFormatFloat, { kind1, kind2, kind3, kind4, fpr_##reg##_mips64 }, NULL, NULL } + eFormatFloat, { kind1, kind2, kind3, kind4, fpr_##reg##_mips64 }, NULL, NULL, dwarf_opcode_mips64, sizeof(dwarf_opcode_mips64)} #define DEFINE_FPR_INFO(reg, alt, kind1, kind2, kind3, kind4) \ { #reg, alt, sizeof(((FPR_linux_mips*)0)->reg), FPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, fpr_##reg##_mips64 }, NULL, NULL } + eFormatHex, { kind1, kind2, kind3, kind4, fpr_##reg##_mips64 }, NULL, NULL, NULL, 0 } #define DEFINE_MSA(reg, alt, kind1, kind2, kind3, kind4) \ { #reg, alt, sizeof(((MSA_linux_mips*)0)->reg), MSA_OFFSET(reg), eEncodingVector, \ - eFormatVectorOfUInt8, { kind1, kind2, kind3, kind4, msa_##reg##_mips64 }, NULL, NULL } + eFormatVectorOfUInt8, { kind1, kind2, kind3, kind4, msa_##reg##_mips64 }, NULL, NULL, NULL, 0} #define DEFINE_MSA_INFO(reg, alt, kind1, kind2, kind3, kind4) \ { #reg, alt, sizeof(((MSA_linux_mips*)0)->reg), MSA_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, msa_##reg##_mips64 }, NULL, NULL } + eFormatHex, { kind1, kind2, kind3, kind4, msa_##reg##_mips64 }, NULL, NULL, NULL, 0} static RegisterInfo g_register_infos_mips64[] = Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -1634,6 +1634,14 @@ response.PutChar (';'); } + if (reg_info->dynamic_size_dwarf_len > 0) + { + response.Printf("dynamic_size_dwarf_len:%" PRIu64 ";",reg_info->dynamic_size_dwarf_len); + response.PutCString("dynamic_size_dwarf_expr_bytes:"); + for(uint32_t i = 0; i < reg_info->dynamic_size_dwarf_len; ++i) + response.PutHex8 (reg_info->dynamic_size_dwarf_expr_bytes[i]); + response.PutChar(';'); + } return SendPacketNoLock(response.GetData(), response.GetSize()); } @@ -1829,7 +1837,10 @@ return SendErrorResponse (0x47); } - if (reg_size != reg_info->byte_size) + // The dwarf expression are evaluate on LLDB side + // which may cause register size to change + // Hence the reg_size may not be same as reg_info->bytes_size + if ((reg_size != reg_info->byte_size) && (reg_info->dynamic_size_dwarf_len == 0)) { return SendIllFormedResponse (packet, "P packet register size is incorrect"); } Index: source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h +++ source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h @@ -46,6 +46,13 @@ void HardcodeARMRegisters(bool from_scratch); + + // Detect the register size dynamically. + uint32_t + UpdateDynamicRegisterSize (ExecutionContext *exe_ctx, + RegisterContext *reg_ctx, + const lldb_private::ArchSpec &arch, + RegisterInfo* reg_info, size_t reg); }; class GDBRemoteRegisterContext : public RegisterContext Index: source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -20,6 +20,10 @@ #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Target.h" #include "lldb/Utility/Utils.h" +#include "lldb/Core/Module.h" +#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Core/dwarf.h" +#include "lldb/Core/Value.h" // Project includes #include "Utility/StringExtractorGDBRemote.h" #include "ProcessGDBRemote.h" @@ -89,7 +93,15 @@ const RegisterInfo * GDBRemoteRegisterContext::GetRegisterInfoAtIndex (size_t reg) { - return m_reg_info.GetRegisterInfoAtIndex (reg); + ExecutionContext exe_ctx (CalculateThread()); + const ArchSpec &arch = m_thread.GetProcess()->GetTarget().GetArchitecture(); + RegisterInfo* reg_info = m_reg_info.GetRegisterInfoAtIndex (reg); + if(reg_info->dynamic_size_dwarf_len) + { + uint8_t reg_size = m_reg_info.UpdateDynamicRegisterSize (&exe_ctx, this, arch, reg_info, reg); + reg_info->byte_size = reg_size; + } + return reg_info; } size_t @@ -939,6 +951,47 @@ return m_reg_info.ConvertRegisterKindToRegisterNumber (kind, num); } +uint32_t +GDBRemoteDynamicRegisterInfo::UpdateDynamicRegisterSize (ExecutionContext *exe_ctx, + RegisterContext *reg_ctx, + const lldb_private::ArchSpec &arch, + RegisterInfo* reg_info, size_t reg) +{ + // In MIPS, the floating point registers size is depends on FR. + // if SR.26 == 1 then all floating point registers are 64 bits. + // else they are all 32 bits. + + int evaluate_result; + uint8_t opcode_len = reg_info->dynamic_size_dwarf_len; + uint32_t addr_size = arch.GetAddressByteSize (); + uint8_t* opcode_ptr = m_dynamic_reg_size_map[reg].data(); + DataExtractor dwarf_data (opcode_ptr, opcode_len, + arch.GetByteOrder (),addr_size); + ModuleSP opcode_ctx; + DWARFExpression dwarf_expr (opcode_ctx, dwarf_data, nullptr, 0, opcode_len); + Value result; + Error error; + const lldb::offset_t offset = 0; + if(dwarf_expr.Evaluate (exe_ctx, nullptr, nullptr, reg_ctx, opcode_ctx, dwarf_data, nullptr, + offset, opcode_len, eRegisterKindDWARF, nullptr, nullptr, result, &error)) + { + evaluate_result = result.GetScalar().SInt(-1); + switch (evaluate_result) + { + case 0: return 4;break; + case 1: return 8;break; + case -1: return reg_info->byte_size; break; + default: assert(false && "Incorrect Dwarf Opcode bytes"); + break; + } + return 0; + } + else + { + printf("Error executing DwarfExpression::Evaluate %s\n", error.AsCString()); + return reg_info->byte_size; + } +} void GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) Index: source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp =================================================================== --- source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -539,6 +539,7 @@ ConstString set_name; std::vector value_regs; std::vector invalidate_regs; + uint8_t dwarf_opcode[8]; RegisterInfo reg_info = { NULL, // Name NULL, // Alt name 0, // byte size @@ -553,7 +554,9 @@ reg_num // native register number }, NULL, - NULL + NULL, + NULL, + 0 // dynamic_size default value }; while (response.GetNameColonValue(name, value)) @@ -638,6 +641,22 @@ { SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 16); } + else if (name.compare("dynamic_size_dwarf_len") == 0) + { + reg_info.dynamic_size_dwarf_len = StringConvert::ToUInt32(value.c_str(), 0, 0); + } + else if (name.compare("dynamic_size_dwarf_expr_bytes") == 0) + { + uint32_t dwarf_len = reg_info.dynamic_size_dwarf_len; + assert(dwarf_len > 0); + StringExtractor name_extractor; + + // Swap "value" over into "name_extractor" + name_extractor.GetStringRef().swap(value); + uint32_t ret_val = name_extractor.GetHexBytesAvail (dwarf_opcode, dwarf_len); + assert(dwarf_len == ret_val); + reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode; + } } reg_info.byte_offset = reg_offset; @@ -4373,6 +4392,7 @@ ConstString set_name; std::vector value_regs; std::vector invalidate_regs; + uint8_t dwarf_opcode[8]; bool encoding_set = false; bool format_set = false; RegisterInfo reg_info = { NULL, // Name @@ -4389,10 +4409,12 @@ cur_reg_num // native register number }, NULL, - NULL + NULL, + NULL, + 0 }; - reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, ®_name, &alt_name, &set_name, &value_regs, &invalidate_regs, &encoding_set, &format_set, ®_info, &cur_reg_num, ®_offset](const llvm::StringRef &name, const llvm::StringRef &value) -> bool { + reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, ®_name, &alt_name, &set_name, &value_regs, &invalidate_regs, &encoding_set, &format_set, ®_info, &cur_reg_num, ®_offset, &dwarf_opcode](const llvm::StringRef &name, const llvm::StringRef &value) -> bool { if (name == "name") { reg_name.SetString(value); @@ -4480,6 +4502,21 @@ { SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 0); } + else if (name == "dynamic_size_dwarf_len") + { + reg_info.dynamic_size_dwarf_len = StringConvert::ToUInt32 (value.data(), 0, 0); + } + else if (name == "dynamic_size_dwarf_expr_bytes") + { + StringExtractor name_extractor; + uint32_t dwarf_len = reg_info.dynamic_size_dwarf_len; + assert(dwarf_len > 0); + std::string opcode_string = value.str(); + name_extractor.GetStringRef().swap(opcode_string); + uint32_t ret_val = name_extractor.GetHexBytesAvail (dwarf_opcode, dwarf_len); + assert(dwarf_len == ret_val); + reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode; + } else { printf("unhandled attribute %s = %s\n", name.data(), value.data());