diff options
| -rw-r--r-- | lldb/include/lldb/Core/Disassembler.h | 28 | ||||
| -rw-r--r-- | lldb/include/lldb/Expression/DWARFExpression.h | 7 | ||||
| -rw-r--r-- | lldb/source/Core/Disassembler.cpp | 113 | ||||
| -rw-r--r-- | lldb/source/Expression/DWARFExpression.cpp | 118 | ||||
| -rw-r--r-- | lldb/source/Target/StackFrame.cpp | 24 |
5 files changed, 210 insertions, 80 deletions
diff --git a/lldb/include/lldb/Core/Disassembler.h b/lldb/include/lldb/Core/Disassembler.h index c90e3ea8180..0bb5fb3ab08 100644 --- a/lldb/include/lldb/Core/Disassembler.h +++ b/lldb/include/lldb/Core/Disassembler.h @@ -169,6 +169,13 @@ public: bool m_clobbered = false; bool IsValid() { return m_type != Type::Invalid; } + + static Operand BuildRegister(ConstString &r); + static Operand BuildImmediate(lldb::addr_t imm, bool neg); + static Operand BuildImmediate(int64_t imm); + static Operand BuildDereference(const Operand &ref); + static Operand BuildSum(const Operand &lhs, const Operand &rhs); + static Operand BuildProduct(const Operand &lhs, const Operand &rhs); }; virtual bool ParseOperands(llvm::SmallVectorImpl<Operand> &operands) { @@ -204,6 +211,27 @@ protected: } }; +namespace OperandMatchers { +std::function<bool(const Instruction::Operand &)> +MatchBinaryOp(std::function<bool(const Instruction::Operand &)> base, + std::function<bool(const Instruction::Operand &)> left, + std::function<bool(const Instruction::Operand &)> right); + +std::function<bool(const Instruction::Operand &)> +MatchUnaryOp(std::function<bool(const Instruction::Operand &)> base, + std::function<bool(const Instruction::Operand &)> child); + +std::function<bool(const Instruction::Operand &)> +MatchRegOp(const RegisterInfo &info); + +std::function<bool(const Instruction::Operand &)> MatchImmOp(int64_t imm); + +std::function<bool(const Instruction::Operand &)> FetchImmOp(int64_t &imm); + +std::function<bool(const Instruction::Operand &)> +MatchOpType(Instruction::Operand::Type type); +} + class InstructionList { public: InstructionList(); diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h index 10363bce572..ea3f5cc03db 100644 --- a/lldb/include/lldb/Expression/DWARFExpression.h +++ b/lldb/include/lldb/Expression/DWARFExpression.h @@ -12,6 +12,7 @@ #include "lldb/Core/Address.h" #include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Disassembler.h" #include "lldb/Core/Error.h" #include "lldb/Core/Scalar.h" #include "lldb/lldb-private.h" @@ -385,11 +386,7 @@ public: const DataExtractor &debug_loc_data, lldb::offset_t offset); - bool IsRegister(StackFrame &frame, const RegisterInfo *®ister_info); - - bool IsDereferenceOfRegister(StackFrame &frame, - const RegisterInfo *®ister_info, - int64_t &offset); + bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op); protected: //------------------------------------------------------------------ diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp index 84665c0ebb8..fa55c8a64fd 100644 --- a/lldb/source/Core/Disassembler.cpp +++ b/lldb/source/Core/Disassembler.cpp @@ -1320,3 +1320,116 @@ void PseudoInstruction::SetDescription(const char *description) { if (description && strlen(description) > 0) m_description = description; } + +Instruction::Operand Instruction::Operand::BuildRegister(ConstString &r) { + Operand ret; + ret.m_type = Type::Register; + ret.m_register = r; + return ret; +} + +Instruction::Operand Instruction::Operand::BuildImmediate(lldb::addr_t imm, + bool neg) { + Operand ret; + ret.m_type = Type::Immediate; + ret.m_immediate = imm; + ret.m_negative = neg; + return ret; +} + +Instruction::Operand Instruction::Operand::BuildImmediate(int64_t imm) { + Operand ret; + ret.m_type = Type::Immediate; + if (imm < 0) { + ret.m_immediate = -imm; + ret.m_negative = true; + } else { + ret.m_immediate = imm; + ret.m_negative = false; + } + return ret; +} + +Instruction::Operand +Instruction::Operand::BuildDereference(const Operand &ref) { + Operand ret; + ret.m_type = Type::Dereference; + ret.m_children = {ref}; + return ret; +} + +Instruction::Operand Instruction::Operand::BuildSum(const Operand &lhs, + const Operand &rhs) { + Operand ret; + ret.m_type = Type::Sum; + ret.m_children = {lhs, rhs}; + return ret; +} + +Instruction::Operand Instruction::Operand::BuildProduct(const Operand &lhs, + const Operand &rhs) { + Operand ret; + ret.m_type = Type::Product; + ret.m_children = {lhs, rhs}; + return ret; +} + +std::function<bool(const Instruction::Operand &)> +lldb_private::OperandMatchers::MatchBinaryOp( + std::function<bool(const Instruction::Operand &)> base, + std::function<bool(const Instruction::Operand &)> left, + std::function<bool(const Instruction::Operand &)> right) { + return [base, left, right](const Instruction::Operand &op) -> bool { + return (base(op) && op.m_children.size() == 2 && + ((left(op.m_children[0]) && right(op.m_children[1])) || + (left(op.m_children[1]) && right(op.m_children[0])))); + }; +} + +std::function<bool(const Instruction::Operand &)> +lldb_private::OperandMatchers::MatchUnaryOp( + std::function<bool(const Instruction::Operand &)> base, + std::function<bool(const Instruction::Operand &)> child) { + return [base, child](const Instruction::Operand &op) -> bool { + return (base(op) && op.m_children.size() == 1 && child(op.m_children[0])); + }; +} + +std::function<bool(const Instruction::Operand &)> +lldb_private::OperandMatchers::MatchRegOp(const RegisterInfo &info) { + return [&info](const Instruction::Operand &op) { + return (op.m_type == Instruction::Operand::Type::Register && + (op.m_register == ConstString(info.name) || + op.m_register == ConstString(info.alt_name))); + }; +} + +std::function<bool(const Instruction::Operand &)> +lldb_private::OperandMatchers::MatchImmOp(int64_t imm) { + return [imm](const Instruction::Operand &op) { + return (op.m_type == Instruction::Operand::Type::Immediate && + ((op.m_negative && op.m_immediate == (uint64_t)-imm) || + (!op.m_negative && op.m_immediate == (uint64_t)imm))); + }; +} + +std::function<bool(const Instruction::Operand &)> +lldb_private::OperandMatchers::FetchImmOp(int64_t &imm) { + return [&imm](const Instruction::Operand &op) { + if (op.m_type != Instruction::Operand::Type::Immediate) { + return false; + } + if (op.m_negative) { + imm = -((int64_t)op.m_immediate); + } else { + imm = ((int64_t)op.m_immediate); + } + return true; + }; +} + +std::function<bool(const Instruction::Operand &)> +lldb_private::OperandMatchers::MatchOpType(Instruction::Operand::Type type) { + return [type](const Instruction::Operand &op) { return op.m_type == type; }; +} + diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 446377e3b10..07bdca4ecc3 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -3305,44 +3305,10 @@ bool DWARFExpression::GetOpAndEndOffsets(StackFrame &frame, return true; } -bool DWARFExpression::IsRegister(StackFrame &frame, - const RegisterInfo *®ister_info) { - lldb::offset_t op_offset; - lldb::offset_t end_offset; - if (!GetOpAndEndOffsets(frame, op_offset, end_offset)) { - return false; - } - - if (!m_data.ValidOffset(op_offset) || op_offset >= end_offset) { - return false; - } - - RegisterContextSP reg_ctx_sp = frame.GetRegisterContext(); - if (!reg_ctx_sp) { - return false; - } - - DataExtractor opcodes = m_data; - uint8_t opcode = opcodes.GetU8(&op_offset); - - if (opcode >= DW_OP_reg0 && opcode <= DW_OP_breg31) { - register_info = - reg_ctx_sp->GetRegisterInfo(m_reg_kind, opcode - DW_OP_reg0); - return register_info != nullptr; - } - switch (opcode) { - default: - return false; - case DW_OP_regx: { - uint32_t reg_num = m_data.GetULEB128(&op_offset); - register_info = reg_ctx_sp->GetRegisterInfo(m_reg_kind, reg_num); - return register_info != nullptr; - } - } -} +bool DWARFExpression::MatchesOperand(StackFrame &frame, + const Instruction::Operand &operand) { + using namespace OperandMatchers; -bool DWARFExpression::IsDereferenceOfRegister( - StackFrame &frame, const RegisterInfo *®ister_info, int64_t &offset) { lldb::offset_t op_offset; lldb::offset_t end_offset; if (!GetOpAndEndOffsets(frame, op_offset, end_offset)) { @@ -3361,41 +3327,69 @@ bool DWARFExpression::IsDereferenceOfRegister( DataExtractor opcodes = m_data; uint8_t opcode = opcodes.GetU8(&op_offset); - switch (opcode) { - default: - return false; - case DW_OP_bregx: { - uint32_t reg_num = static_cast<uint32_t>(opcodes.GetULEB128(&op_offset)); - int64_t breg_offset = opcodes.GetSLEB128(&op_offset); + if (opcode == DW_OP_fbreg) { + int64_t offset = opcodes.GetSLEB128(&op_offset); - const RegisterInfo *reg_info = - reg_ctx_sp->GetRegisterInfo(m_reg_kind, reg_num); - if (!reg_info) { + DWARFExpression *fb_expr = frame.GetFrameBaseExpression(nullptr); + if (!fb_expr) { return false; } - register_info = reg_info; - offset = breg_offset; - return true; + std::function<bool(const Instruction::Operand &)> recurse = + [&frame, fb_expr](const Instruction::Operand &child) { + return fb_expr->MatchesOperand(frame, child); + }; + + if (!offset && + MatchUnaryOp(MatchOpType(Instruction::Operand::Type::Dereference), + recurse)(operand)) { + return true; + } + + return MatchUnaryOp( + MatchOpType(Instruction::Operand::Type::Dereference), + MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum), + MatchImmOp(offset), recurse))(operand); } - case DW_OP_fbreg: { - int64_t fbreg_offset = opcodes.GetSLEB128(&op_offset); - DWARFExpression *dwarf_expression = frame.GetFrameBaseExpression(nullptr); + bool dereference = false; + const RegisterInfo *reg = nullptr; + int64_t offset = 0; - if (!dwarf_expression) { - return false; - } + if (opcode >= DW_OP_reg0 && opcode <= DW_OP_reg31) { + reg = reg_ctx_sp->GetRegisterInfo(m_reg_kind, opcode - DW_OP_reg0); + } else if (opcode >= DW_OP_breg0 && opcode <= DW_OP_breg31) { + offset = opcodes.GetSLEB128(&op_offset); + reg = reg_ctx_sp->GetRegisterInfo(m_reg_kind, opcode - DW_OP_breg0); + } else if (opcode == DW_OP_regx) { + uint32_t reg_num = static_cast<uint32_t>(opcodes.GetULEB128(&op_offset)); + reg = reg_ctx_sp->GetRegisterInfo(m_reg_kind, reg_num); + } else if (opcode == DW_OP_bregx) { + uint32_t reg_num = static_cast<uint32_t>(opcodes.GetULEB128(&op_offset)); + offset = opcodes.GetSLEB128(&op_offset); + reg = reg_ctx_sp->GetRegisterInfo(m_reg_kind, reg_num); + } else { + return false; + } - const RegisterInfo *fbr_info; + if (!reg) { + return false; + } - if (!dwarf_expression->IsRegister(frame, fbr_info)) { - return false; + if (dereference) { + if (!offset && + MatchUnaryOp(MatchOpType(Instruction::Operand::Type::Dereference), + MatchRegOp(*reg))(operand)) { + return true; } - register_info = fbr_info; - offset = fbreg_offset; - return true; - } + return MatchUnaryOp( + MatchOpType(Instruction::Operand::Type::Dereference), + MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum), + MatchRegOp(*reg), + MatchImmOp(offset)))(operand); + } else { + return MatchRegOp(*reg)(operand); } } + diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 0b28c1ea20e..0e32cb4676a 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -1489,21 +1489,19 @@ lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg, // First, check the variable list to see if anything is at the specified // location. + + Instruction::Operand op = + offset ? Instruction::Operand::BuildDereference( + Instruction::Operand::BuildSum( + Instruction::Operand::BuildRegister(reg), + Instruction::Operand::BuildImmediate(offset))) + : Instruction::Operand::BuildDereference( + Instruction::Operand::BuildRegister(reg)); + for (size_t vi = 0, ve = variables.GetSize(); vi != ve; ++vi) { VariableSP var_sp = variables.GetVariableAtIndex(vi); - DWARFExpression &dwarf_expression = var_sp->LocationExpression(); - - const RegisterInfo *expression_reg; - int64_t expression_offset; - ExecutionContext exe_ctx; - - if (dwarf_expression.IsDereferenceOfRegister(frame, expression_reg, - expression_offset)) { - if ((reg == ConstString(expression_reg->name) || - reg == ConstString(expression_reg->alt_name)) && - expression_offset == offset) { - return frame.GetValueObjectForFrameVariable(var_sp, eNoDynamicValues); - } + if (var_sp->LocationExpression().MatchesOperand(frame, op)) { + return frame.GetValueObjectForFrameVariable(var_sp, eNoDynamicValues); } } |

