diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h index 96a0e8e02da133..49e51d51f211cc 100644 --- a/lldb/include/lldb/Expression/DWARFExpression.h +++ b/lldb/include/lldb/Expression/DWARFExpression.h @@ -42,49 +42,14 @@ class DWARFExpression { /// \param[in] data /// A data extractor configured to read the DWARF location expression's /// bytecode. - DWARFExpression(lldb::ModuleSP module, const DataExtractor &data, - const DWARFUnit *dwarf_cu); + DWARFExpression(const DataExtractor &data); /// Destructor virtual ~DWARFExpression(); - /// Print the description of the expression to a stream - /// - /// \param[in] s - /// The stream to print to. - /// - /// \param[in] level - /// The level of verbosity to use. - /// - /// \param[in] abi - /// An optional ABI plug-in that can be used to resolve register - /// names. - void GetDescription(Stream *s, lldb::DescriptionLevel level, ABI *abi) const; - /// Return true if the location expression contains data bool IsValid() const; - /// Return true if a location list was provided - bool IsLocationList() const; - - /// Search for a load address in the location list - /// - /// \param[in] func_load_addr - /// The actual address of the function containing this location list. - /// - /// \param[in] addr - /// The address to resolve - /// - /// \return - /// True if IsLocationList() is true and the address was found; - /// false otherwise. - // bool - // LocationListContainsLoadAddress (Process* process, const Address &addr) - // const; - // - bool LocationListContainsAddress(lldb::addr_t func_load_addr, - lldb::addr_t addr) const; - /// If a location is not a location list, return true if the location /// contains a DW_OP_addr () opcode in the stream that matches \a file_addr. /// If file_addr is LLDB_INVALID_ADDRESS, the this function will return true @@ -93,6 +58,9 @@ class DWARFExpression { /// static variable since there is no other indication from DWARF debug /// info. /// + /// \param[in] dwarf_cu + /// The dwarf unit this expression belongs to. + /// /// \param[in] op_addr_idx /// The DW_OP_addr index to retrieve in case there is more than /// one DW_OP_addr opcode in the location byte stream. @@ -104,36 +72,22 @@ class DWARFExpression { /// \return /// LLDB_INVALID_ADDRESS if the location doesn't contain a /// DW_OP_addr for \a op_addr_idx, otherwise a valid file address - lldb::addr_t GetLocation_DW_OP_addr(uint32_t op_addr_idx, bool &error) const; + lldb::addr_t GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu, + uint32_t op_addr_idx, bool &error) const; bool Update_DW_OP_addr(lldb::addr_t file_addr); void UpdateValue(uint64_t const_value, lldb::offset_t const_value_byte_size, uint8_t addr_byte_size); - void SetModule(const lldb::ModuleSP &module) { m_module_wp = module; } - bool ContainsThreadLocalStorage() const; bool LinkThreadLocalStorage( - lldb::ModuleSP new_module_sp, std::function const &link_address_callback); - /// Tells the expression that it refers to a location list. - /// - /// \param[in] cu_file_addr - /// The base address to use for interpreting relative location list - /// entries. - /// \param[in] func_file_addr - /// The file address of the function containing this location list. This - /// address will be used to relocate the location list on the fly (in - /// conjuction with the func_load_addr arguments). - void SetLocationListAddresses(lldb::addr_t cu_file_addr, - lldb::addr_t func_file_addr); - /// Return the call-frame-info style register kind - int GetRegisterKind(); + lldb::RegisterKind GetRegisterKind() const; /// Set the call-frame-info style register kind /// @@ -141,20 +95,6 @@ class DWARFExpression { /// The register kind. void SetRegisterKind(lldb::RegisterKind reg_kind); - /// Wrapper for the static evaluate function that accepts an - /// ExecutionContextScope instead of an ExecutionContext and uses member - /// variables to populate many operands - bool Evaluate(ExecutionContextScope *exe_scope, lldb::addr_t func_load_addr, - const Value *initial_value_ptr, const Value *object_address_ptr, - Value &result, Status *error_ptr) const; - - /// Wrapper for the static evaluate function that uses member variables to - /// populate many operands - bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx, - lldb::addr_t loclist_base_load_addr, - const Value *initial_value_ptr, const Value *object_address_ptr, - Value &result, Status *error_ptr) const; - /// Evaluate a DWARF location expression in a particular context /// /// \param[in] exe_ctx @@ -194,72 +134,32 @@ class DWARFExpression { /// True on success; false otherwise. If error_ptr is non-NULL, /// details of the failure are provided through it. static bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx, - lldb::ModuleSP opcode_ctx, const DataExtractor &opcodes, + lldb::ModuleSP module_sp, const DataExtractor &opcodes, const DWARFUnit *dwarf_cu, const lldb::RegisterKind reg_set, const Value *initial_value_ptr, const Value *object_address_ptr, Value &result, Status *error_ptr); + static bool ParseDWARFLocationList(const DWARFUnit *dwarf_cu, + const DataExtractor &data, + DWARFExpressionList *loc_list); + bool GetExpressionData(DataExtractor &data) const { data = m_data; return data.GetByteSize() > 0; } - bool DumpLocationForAddress(Stream *s, lldb::DescriptionLevel level, - lldb::addr_t func_load_addr, lldb::addr_t address, - ABI *abi); - - bool DumpLocations(Stream *s, lldb::DescriptionLevel level, - lldb::addr_t func_load_addr, lldb::addr_t addr, ABI *abi); - - bool GetLocationExpressions( - lldb::addr_t load_function_start, - llvm::function_ref callback) const; + void DumpLocation(Stream *s, lldb::DescriptionLevel level, ABI *abi) const; - bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op); - - llvm::Optional - GetLocationExpression(lldb::addr_t load_function_start, - lldb::addr_t addr) const; + bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op) const; private: - /// Pretty-prints the location expression to a stream - /// - /// \param[in] s - /// The stream to use for pretty-printing. - /// - /// \param[in] data - /// The data extractor. - /// - /// \param[in] level - /// The level of detail to use in pretty-printing. - /// - /// \param[in] abi - /// An optional ABI plug-in that can be used to resolve register - /// names. - void DumpLocation(Stream *s, const DataExtractor &data, - lldb::DescriptionLevel level, ABI *abi) const; - - /// Module which defined this expression. - lldb::ModuleWP m_module_wp; - /// A data extractor capable of reading opcode bytes DataExtractor m_data; - /// The DWARF compile unit this expression belongs to. It is used to evaluate - /// values indexing into the .debug_addr section (e.g. DW_OP_GNU_addr_index, - /// DW_OP_GNU_const_index) - const DWARFUnit *m_dwarf_cu = nullptr; - /// One of the defines that starts with LLDB_REGKIND_ lldb::RegisterKind m_reg_kind = lldb::eRegisterKindDWARF; - - struct LoclistAddresses { - lldb::addr_t cu_file_addr; - lldb::addr_t func_file_addr; - }; - llvm::Optional m_loclist_addresses; }; } // namespace lldb_private diff --git a/lldb/include/lldb/Expression/DWARFExpressionList.h b/lldb/include/lldb/Expression/DWARFExpressionList.h new file mode 100644 index 00000000000000..34cd217b8fe4a9 --- /dev/null +++ b/lldb/include/lldb/Expression/DWARFExpressionList.h @@ -0,0 +1,132 @@ +//===-- DWARFExpressionList.h -----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_EXPRESSION_DWARFEXPRESSIONLIST_H +#define LLDB_EXPRESSION_DWARFEXPRESSIONLIST_H + +#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Utility/RangeMap.h" +#include "lldb/lldb-private.h" +#include "llvm/ADT/Optional.h" + +class DWARFUnit; + +namespace lldb_private { + +/// \class DWARFExpressionList DWARFExpressionList.h +/// "lldb/Expression/DWARFExpressionList.h" Encapsulates a range map from file +/// address range to a single DWARF location expression. +class DWARFExpressionList { +public: + DWARFExpressionList() = default; + + DWARFExpressionList(lldb::ModuleSP module_sp, const DWARFUnit *dwarf_cu) + : m_module_wp(module_sp), m_dwarf_cu(dwarf_cu) {} + + DWARFExpressionList(lldb::ModuleSP module_sp, DWARFExpression expr, + const DWARFUnit *dwarf_cu) + : DWARFExpressionList(module_sp, dwarf_cu) { + AddExpression(0, LLDB_INVALID_ADDRESS, expr); + } + + /// Return true if the location expression contains data + bool IsValid() const { return !m_exprs.IsEmpty(); } + + void Clear() { m_exprs.Clear(); } + + // Return true if the location expression is always valid. + bool IsAlwaysValidSingleExpr() const; + + bool AddExpression(lldb::addr_t base, lldb::addr_t end, DWARFExpression expr); + + /// Get the expression data at the file address. + bool GetExpressionData(DataExtractor &data, lldb::addr_t file_addr = 0) const; + + /// Sort m_expressions. + void Sort() { m_exprs.Sort(); } + + const DWARFExpression *GetExpressionAtAddress(lldb::addr_t file_addr) const; + + const DWARFExpression *GetAlwaysValidExpr() const { + return GetExpressionAtAddress(0); + } + + DWARFExpression *GetMutableExpressionAtAddress(lldb::addr_t file_addr = 0); + + size_t GetSize() const { return m_exprs.GetSize(); } + + bool ContainsThreadLocalStorage() const; + + bool LinkThreadLocalStorage( + lldb::ModuleSP new_module_sp, + std::function const + &link_address_callback); + + bool MatchesOperand(StackFrame &frame, + const Instruction::Operand &operand) const; + + /// Dump locations that contains file_addr if it's valid. Otherwise. dump all + /// locations. + bool DumpLocations(Stream *s, lldb::DescriptionLevel level, + lldb::addr_t file_addr, ABI *abi) const; + + /// Dump all locaitons with each seperated by new line. + void GetDescription(Stream *s, lldb::DescriptionLevel level, ABI *abi) const; + + /// Search for a load address in the location list + /// + /// \param[in] file_addr + /// The file address to resolve + /// + /// \return + /// True if IsLocationList() is true and the address was found; + /// false otherwise. + // bool + // LocationListContainsLoadAddress (Process* process, const Address &addr) + // const; + // + bool ContainsAddress(lldb::addr_t file_addr) const; + + void SetModule(const lldb::ModuleSP &module) { m_module_wp = module; } + + bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx, + const Value *initial_value_ptr, const Value *object_address_ptr, + Value &result, Status *error_ptr) const; + +private: + // RangeDataVector requires a comparator for DWARFExpression, but it doesn't + // make sense to do so. + struct DWARFExpressionCompare { + public: + bool operator()(const DWARFExpression &lhs, + const DWARFExpression &rhs) const { + return false; + } + }; + using ExprVec = RangeDataVector; + using Entry = ExprVec::Entry; + + // File address range mapping to single dwarf expression. + ExprVec m_exprs; + + /// Module which defined this expression. + lldb::ModuleWP m_module_wp; + + /// The DWARF compile unit this expression belongs to. It is used to evaluate + /// values indexing into the .debug_addr section (e.g. DW_OP_GNU_addr_index, + /// DW_OP_GNU_const_index) + const DWARFUnit *m_dwarf_cu = nullptr; + + using const_iterator = ExprVec::Collection::const_iterator; + const_iterator begin() const { return m_exprs.begin(); } + const_iterator end() const { return m_exprs.end(); } +}; +} // namespace lldb_private + +#endif // LLDB_EXPRESSION_DWARFEXPRESSIONLIST_H diff --git a/lldb/include/lldb/Symbol/Function.h b/lldb/include/lldb/Symbol/Function.h index 83f9979c3c529b..3eb4f5d7dedf4d 100644 --- a/lldb/include/lldb/Symbol/Function.h +++ b/lldb/include/lldb/Symbol/Function.h @@ -12,7 +12,7 @@ #include "lldb/Core/AddressRange.h" #include "lldb/Core/Declaration.h" #include "lldb/Core/Mangled.h" -#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Expression/DWARFExpressionList.h" #include "lldb/Symbol/Block.h" #include "lldb/Utility/UserID.h" #include "llvm/ADT/ArrayRef.h" @@ -253,8 +253,8 @@ class Function; /// Represent the locations of a parameter at a call site, both in the caller /// and in the callee. struct CallSiteParameter { - DWARFExpression LocationInCallee; - DWARFExpression LocationInCaller; + DWARFExpressionList LocationInCallee; + DWARFExpressionList LocationInCaller; }; /// A vector of \c CallSiteParameter. @@ -370,7 +370,7 @@ class IndirectCallEdge : public CallEdge { public: /// Construct a call edge using a DWARFExpression to identify the callee, and /// a return PC within the calling function to identify a specific call site. - IndirectCallEdge(DWARFExpression call_target, AddrType caller_address_type, + IndirectCallEdge(DWARFExpressionList call_target, AddrType caller_address_type, lldb::addr_t caller_address, bool is_tail_call, CallSiteParameterArray &¶meters) : CallEdge(caller_address_type, caller_address, is_tail_call, @@ -383,7 +383,7 @@ class IndirectCallEdge : public CallEdge { // Used to describe an indirect call. // // Specifies the location of the callee address in the calling frame. - DWARFExpression call_target; + DWARFExpressionList call_target; }; /// \class Function Function.h "lldb/Symbol/Function.h" @@ -521,13 +521,13 @@ class Function : public UserID, public SymbolContextScope { /// \return /// A location expression that describes the function frame /// base. - DWARFExpression &GetFrameBaseExpression() { return m_frame_base; } + DWARFExpressionList &GetFrameBaseExpression() { return m_frame_base; } /// Get const accessor for the frame base location. /// /// \return /// A const compile unit object pointer. - const DWARFExpression &GetFrameBaseExpression() const { return m_frame_base; } + const DWARFExpressionList &GetFrameBaseExpression() const { return m_frame_base; } ConstString GetName() const; @@ -659,7 +659,7 @@ class Function : public UserID, public SymbolContextScope { /// The frame base expression for variables that are relative to the frame /// pointer. - DWARFExpression m_frame_base; + DWARFExpressionList m_frame_base; Flags m_flags; diff --git a/lldb/include/lldb/Symbol/Variable.h b/lldb/include/lldb/Symbol/Variable.h index 88a975df399288..c437624d1ea6d7 100644 --- a/lldb/include/lldb/Symbol/Variable.h +++ b/lldb/include/lldb/Symbol/Variable.h @@ -11,7 +11,7 @@ #include "lldb/Core/Declaration.h" #include "lldb/Core/Mangled.h" -#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Expression/DWARFExpressionList.h" #include "lldb/Utility/CompletionRequest.h" #include "lldb/Utility/RangeMap.h" #include "lldb/Utility/UserID.h" @@ -32,8 +32,8 @@ class Variable : public UserID, public std::enable_shared_from_this { Variable(lldb::user_id_t uid, const char *name, const char *mangled, const lldb::SymbolFileTypeSP &symfile_type_sp, lldb::ValueType scope, SymbolContextScope *owner_scope, const RangeList &scope_range, - Declaration *decl, const DWARFExpression &location, bool external, - bool artificial, bool location_is_constant_data, + Declaration *decl, const DWARFExpressionList &location, + bool external, bool artificial, bool location_is_constant_data, bool static_member = false); virtual ~Variable(); @@ -73,9 +73,11 @@ class Variable : public UserID, public std::enable_shared_from_this { bool IsStaticMember() const { return m_static_member; } - DWARFExpression &LocationExpression() { return m_location; } + DWARFExpressionList &LocationExpressionList() { return m_location_list; } - const DWARFExpression &LocationExpression() const { return m_location; } + const DWARFExpressionList &LocationExpressionList() const { + return m_location_list; + } // When given invalid address, it dumps all locations. Otherwise it only dumps // the location that contains this address. @@ -128,7 +130,7 @@ class Variable : public UserID, public std::enable_shared_from_this { Declaration m_declaration; /// The location of this variable that can be fed to /// DWARFExpression::Evaluate(). - DWARFExpression m_location; + DWARFExpressionList m_location_list; /// Visible outside the containing compile unit? unsigned m_external : 1; /// Non-zero if the variable is not explicitly declared in source. diff --git a/lldb/include/lldb/Target/StackFrame.h b/lldb/include/lldb/Target/StackFrame.h index 1b0485b22cacba..7c4340de4de062 100644 --- a/lldb/include/lldb/Target/StackFrame.h +++ b/lldb/include/lldb/Target/StackFrame.h @@ -202,7 +202,7 @@ class StackFrame : public ExecutionContextScope, /// frames may be unable to provide this value; they will return false. bool GetFrameBaseValue(Scalar &value, Status *error_ptr); - /// Get the DWARFExpression corresponding to the Canonical Frame Address. + /// Get the DWARFExpressionList corresponding to the Canonical Frame Address. /// /// Often a register (bp), but sometimes a register + offset. /// @@ -212,7 +212,7 @@ class StackFrame : public ExecutionContextScope, /// /// \return /// Returns the corresponding DWARF expression, or NULL. - DWARFExpression *GetFrameBaseExpression(Status *error_ptr); + DWARFExpressionList *GetFrameBaseExpression(Status *error_ptr); /// Get the current lexical scope block for this StackFrame, if possible. /// diff --git a/lldb/include/lldb/Utility/RangeMap.h b/lldb/include/lldb/Utility/RangeMap.h index 7eb0cab8084c7a..257b177c709277 100644 --- a/lldb/include/lldb/Utility/RangeMap.h +++ b/lldb/include/lldb/Utility/RangeMap.h @@ -627,6 +627,10 @@ class RangeDataVector { return (m_entries.empty() ? nullptr : &m_entries.back()); } + using const_iterator = typename Collection::const_iterator; + const_iterator begin() const { return m_entries.begin(); } + const_iterator end() const { return m_entries.end(); } + protected: Collection m_entries; Compare m_compare; diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index 487b2f20792b9f..c51e1850338fff 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -66,6 +66,7 @@ class ConstStringTable; class DWARFCallFrameInfo; class DWARFDataExtractor; class DWARFExpression; +class DWARFExpressionList; class DataBuffer; class WritableDataBuffer; class DataBufferHeap; diff --git a/lldb/source/Core/ValueObjectVariable.cpp b/lldb/source/Core/ValueObjectVariable.cpp index 8e89503a8a76b9..7f0e86b9294dac 100644 --- a/lldb/source/Core/ValueObjectVariable.cpp +++ b/lldb/source/Core/ValueObjectVariable.cpp @@ -13,7 +13,7 @@ #include "lldb/Core/Declaration.h" #include "lldb/Core/Module.h" #include "lldb/Core/Value.h" -#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Expression/DWARFExpressionList.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" @@ -127,22 +127,20 @@ bool ValueObjectVariable::UpdateValue() { m_error.Clear(); Variable *variable = m_variable_sp.get(); - DWARFExpression &expr = variable->LocationExpression(); + DWARFExpressionList &expr_list = variable->LocationExpressionList(); if (variable->GetLocationIsConstantValueData()) { // expr doesn't contain DWARF bytes, it contains the constant variable // value bytes themselves... - if (expr.GetExpressionData(m_data)) { - if (m_data.GetDataStart() && m_data.GetByteSize()) + if (expr_list.GetExpressionData(m_data)) { + if (m_data.GetDataStart() && m_data.GetByteSize()) m_value.SetBytes(m_data.GetDataStart(), m_data.GetByteSize()); m_value.SetContext(Value::ContextType::Variable, variable); - } - else + } else m_error.SetErrorString("empty constant data"); // constant bytes can't be edited - sorry m_resolved_value.SetContext(Value::ContextType::Invalid, nullptr); } else { - lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS; ExecutionContext exe_ctx(GetExecutionContextRef()); Target *target = exe_ctx.GetTargetPtr(); @@ -151,17 +149,8 @@ bool ValueObjectVariable::UpdateValue() { m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); } - if (expr.IsLocationList()) { - SymbolContext sc; - variable->CalculateSymbolContext(&sc); - if (sc.function) - loclist_base_load_addr = - sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress( - target); - } Value old_value(m_value); - if (expr.Evaluate(&exe_ctx, nullptr, loclist_base_load_addr, nullptr, - nullptr, m_value, &m_error)) { + if (expr_list.Evaluate(&exe_ctx, nullptr, nullptr, nullptr, m_value, &m_error)) { m_resolved_value = m_value; m_value.SetContext(Value::ContextType::Variable, variable); @@ -246,7 +235,7 @@ bool ValueObjectVariable::UpdateValue() { m_resolved_value.SetContext(Value::ContextType::Invalid, nullptr); } } - + return m_error.Success(); } diff --git a/lldb/source/Expression/CMakeLists.txt b/lldb/source/Expression/CMakeLists.txt index c935e1b1c04b9e..54414fb2a7c4f6 100644 --- a/lldb/source/Expression/CMakeLists.txt +++ b/lldb/source/Expression/CMakeLists.txt @@ -1,6 +1,7 @@ add_lldb_library(lldbExpression DiagnosticManager.cpp DWARFExpression.cpp + DWARFExpressionList.cpp Expression.cpp ExpressionVariable.cpp FunctionCaller.cpp diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 1f11907dc64c44..fff5f60bc3abf7 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -45,29 +45,10 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::dwarf; -static lldb::addr_t -ReadAddressFromDebugAddrSection(const DWARFUnit *dwarf_cu, - uint32_t index) { - uint32_t index_size = dwarf_cu->GetAddressByteSize(); - dw_offset_t addr_base = dwarf_cu->GetAddrBase(); - lldb::offset_t offset = addr_base + index * index_size; - const DWARFDataExtractor &data = - dwarf_cu->GetSymbolFileDWARF().GetDWARFContext().getOrLoadAddrData(); - if (data.ValidOffsetForDataOfSize(offset, index_size)) - return data.GetMaxU64_unchecked(&offset, index_size); - return LLDB_INVALID_ADDRESS; -} - // DWARFExpression constructor -DWARFExpression::DWARFExpression() : m_module_wp(), m_data() {} - -DWARFExpression::DWARFExpression(lldb::ModuleSP module_sp, - const DataExtractor &data, - const DWARFUnit *dwarf_cu) - : m_module_wp(), m_data(data), m_dwarf_cu(dwarf_cu) { - if (module_sp) - m_module_wp = module_sp; -} +DWARFExpression::DWARFExpression() : m_data() {} + +DWARFExpression::DWARFExpression(const DataExtractor &data) : m_data(data) {} // Destructor DWARFExpression::~DWARFExpression() = default; @@ -86,71 +67,19 @@ void DWARFExpression::UpdateValue(uint64_t const_value, m_data.SetAddressByteSize(addr_byte_size); } -void DWARFExpression::DumpLocation(Stream *s, const DataExtractor &data, - lldb::DescriptionLevel level, +void DWARFExpression::DumpLocation(Stream *s, lldb::DescriptionLevel level, ABI *abi) const { - llvm::DWARFExpression(data.GetAsLLVM(), data.GetAddressByteSize()) + llvm::DWARFExpression(m_data.GetAsLLVM(), m_data.GetAddressByteSize()) .print(s->AsRawOstream(), llvm::DIDumpOptions(), abi ? &abi->GetMCRegisterInfo() : nullptr, nullptr); } -void DWARFExpression::SetLocationListAddresses(addr_t cu_file_addr, - addr_t func_file_addr) { - m_loclist_addresses = LoclistAddresses{cu_file_addr, func_file_addr}; -} - -int DWARFExpression::GetRegisterKind() { return m_reg_kind; } +RegisterKind DWARFExpression::GetRegisterKind() const { return m_reg_kind; } void DWARFExpression::SetRegisterKind(RegisterKind reg_kind) { m_reg_kind = reg_kind; } -bool DWARFExpression::IsLocationList() const { - return bool(m_loclist_addresses); -} - -namespace { -/// Implement enough of the DWARFObject interface in order to be able to call -/// DWARFLocationTable::dumpLocationList. We don't have access to a real -/// DWARFObject here because DWARFExpression is used in non-DWARF scenarios too. -class DummyDWARFObject final: public llvm::DWARFObject { -public: - DummyDWARFObject(bool IsLittleEndian) : IsLittleEndian(IsLittleEndian) {} - - bool isLittleEndian() const override { return IsLittleEndian; } - - llvm::Optional find(const llvm::DWARFSection &Sec, - uint64_t Pos) const override { - return llvm::None; - } -private: - bool IsLittleEndian; -}; -} - -void DWARFExpression::GetDescription(Stream *s, lldb::DescriptionLevel level, - ABI *abi) const { - if (IsLocationList()) { - // We have a location list - lldb::offset_t offset = 0; - std::unique_ptr loctable_up = - m_dwarf_cu->GetLocationTable(m_data); - - llvm::MCRegisterInfo *MRI = abi ? &abi->GetMCRegisterInfo() : nullptr; - llvm::DIDumpOptions DumpOpts; - DumpOpts.RecoverableErrorHandler = [&](llvm::Error E) { - s->AsRawOstream() << "error: " << toString(std::move(E)); - }; - loctable_up->dumpLocationList( - &offset, s->AsRawOstream(), - llvm::object::SectionedAddress{m_loclist_addresses->cu_file_addr}, MRI, - DummyDWARFObject(m_data.GetByteOrder() == eByteOrderLittle), nullptr, - DumpOpts, s->GetIndentLevel() + 2); - } else { - // We have a normal location that contains DW_OP location opcodes - DumpLocation(s, m_data, level, abi); - } -} static bool ReadRegisterValueAsScalar(RegisterContext *reg_ctx, lldb::RegisterKind reg_kind, @@ -409,11 +338,10 @@ static offset_t GetOpcodeDataSize(const DataExtractor &data, return LLDB_INVALID_OFFSET; } -lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(uint32_t op_addr_idx, +lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu, + uint32_t op_addr_idx, bool &error) const { error = false; - if (IsLocationList()) - return LLDB_INVALID_ADDRESS; lldb::offset_t offset = 0; uint32_t curr_op_addr_idx = 0; while (m_data.ValidOffset(offset)) { @@ -423,19 +351,18 @@ lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(uint32_t op_addr_idx, const lldb::addr_t op_file_addr = m_data.GetAddress(&offset); if (curr_op_addr_idx == op_addr_idx) return op_file_addr; - else - ++curr_op_addr_idx; + ++curr_op_addr_idx; } else if (op == DW_OP_GNU_addr_index || op == DW_OP_addrx) { uint64_t index = m_data.GetULEB128(&offset); if (curr_op_addr_idx == op_addr_idx) { - if (!m_dwarf_cu) { + if (!dwarf_cu) { error = true; break; } - return ReadAddressFromDebugAddrSection(m_dwarf_cu, index); - } else - ++curr_op_addr_idx; + return dwarf_cu->ReadAddressFromDebugAddrSection(index); + } + ++curr_op_addr_idx; } else { const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); if (op_arg_size == LLDB_INVALID_OFFSET) { @@ -449,8 +376,6 @@ lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(uint32_t op_addr_idx, } bool DWARFExpression::Update_DW_OP_addr(lldb::addr_t file_addr) { - if (IsLocationList()) - return false; lldb::offset_t offset = 0; while (m_data.ValidOffset(offset)) { const uint8_t op = m_data.GetU8(&offset); @@ -487,11 +412,6 @@ bool DWARFExpression::Update_DW_OP_addr(lldb::addr_t file_addr) { } bool DWARFExpression::ContainsThreadLocalStorage() const { - // We are assuming for now that any thread local variable will not have a - // location list. This has been true for all thread local variables we have - // seen so far produced by any compiler. - if (IsLocationList()) - return false; lldb::offset_t offset = 0; while (m_data.ValidOffset(offset)) { const uint8_t op = m_data.GetU8(&offset); @@ -501,27 +421,18 @@ bool DWARFExpression::ContainsThreadLocalStorage() const { const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); if (op_arg_size == LLDB_INVALID_OFFSET) return false; - else - offset += op_arg_size; + offset += op_arg_size; } return false; } bool DWARFExpression::LinkThreadLocalStorage( - lldb::ModuleSP new_module_sp, std::function const &link_address_callback) { - // We are assuming for now that any thread local variable will not have a - // location list. This has been true for all thread local variables we have - // seen so far produced by any compiler. - if (IsLocationList()) - return false; - const uint32_t addr_byte_size = m_data.GetAddressByteSize(); // We have to make a copy of the data as we don't know if this data is from a // read only memory mapped buffer, so we duplicate all of the data first, // then modify it, and if all goes well, we then replace the data for this // expression. - // Make en encoder that contains a copy of the location expression data so we // can write the address into the buffer using the correct byte order. DataEncoder encoder(m_data.GetDataStart(), m_data.GetByteSize(), @@ -593,42 +504,10 @@ bool DWARFExpression::LinkThreadLocalStorage( } } - // If we linked the TLS address correctly, update the module so that when the - // expression is evaluated it can resolve the file address to a load address - // and read the - // TLS data - m_module_wp = new_module_sp; m_data.SetData(encoder.GetDataBuffer()); return true; } -bool DWARFExpression::LocationListContainsAddress(addr_t func_load_addr, - lldb::addr_t addr) const { - if (func_load_addr == LLDB_INVALID_ADDRESS || addr == LLDB_INVALID_ADDRESS) - return false; - - if (!IsLocationList()) - return false; - - return GetLocationExpression(func_load_addr, addr) != llvm::None; -} - -bool DWARFExpression::DumpLocationForAddress(Stream *s, - lldb::DescriptionLevel level, - addr_t func_load_addr, - addr_t address, ABI *abi) { - if (!IsLocationList()) { - DumpLocation(s, m_data, level, abi); - return true; - } - if (llvm::Optional expr = - GetLocationExpression(func_load_addr, address)) { - DumpLocation(s, *expr, level, abi); - return true; - } - return false; -} - static bool Evaluate_DW_OP_entry_value(std::vector &stack, ExecutionContext *exe_ctx, RegisterContext *reg_ctx, @@ -824,10 +703,9 @@ static bool Evaluate_DW_OP_entry_value(std::vector &stack, // TODO: Add support for DW_OP_push_object_address within a DW_OP_entry_value // subexpresion whenever llvm does. Value result; - const DWARFExpression ¶m_expr = matched_param->LocationInCaller; + const DWARFExpressionList ¶m_expr = matched_param->LocationInCaller; if (!param_expr.Evaluate(&parent_exe_ctx, parent_frame->GetRegisterContext().get(), - /*loclist_base_load_addr=*/LLDB_INVALID_ADDRESS, /*initial_value_ptr=*/nullptr, /*object_address_ptr=*/nullptr, result, error_ptr)) { LLDB_LOG(log, @@ -839,63 +717,6 @@ static bool Evaluate_DW_OP_entry_value(std::vector &stack, return true; } -bool DWARFExpression::Evaluate(ExecutionContextScope *exe_scope, - lldb::addr_t loclist_base_load_addr, - const Value *initial_value_ptr, - const Value *object_address_ptr, Value &result, - Status *error_ptr) const { - ExecutionContext exe_ctx(exe_scope); - return Evaluate(&exe_ctx, nullptr, loclist_base_load_addr, initial_value_ptr, - object_address_ptr, result, error_ptr); -} - -bool DWARFExpression::Evaluate(ExecutionContext *exe_ctx, - RegisterContext *reg_ctx, - lldb::addr_t func_load_addr, - const Value *initial_value_ptr, - const Value *object_address_ptr, Value &result, - Status *error_ptr) const { - ModuleSP module_sp = m_module_wp.lock(); - - if (IsLocationList()) { - Address pc; - StackFrame *frame = nullptr; - if (!reg_ctx || !reg_ctx->GetPCForSymbolication(pc)) { - frame = exe_ctx->GetFramePtr(); - if (!frame) - return false; - RegisterContextSP reg_ctx_sp = frame->GetRegisterContext(); - if (!reg_ctx_sp) - return false; - reg_ctx_sp->GetPCForSymbolication(pc); - } - - if (func_load_addr != LLDB_INVALID_ADDRESS) { - if (!pc.IsValid()) { - if (error_ptr) - error_ptr->SetErrorString("Invalid PC in frame."); - return false; - } - - Target *target = exe_ctx->GetTargetPtr(); - if (llvm::Optional expr = GetLocationExpression( - func_load_addr, pc.GetLoadAddress(target))) { - return DWARFExpression::Evaluate( - exe_ctx, reg_ctx, module_sp, *expr, m_dwarf_cu, m_reg_kind, - initial_value_ptr, object_address_ptr, result, error_ptr); - } - } - if (error_ptr) - error_ptr->SetErrorString("variable not available"); - return false; - } - - // Not a location list, just a single expression. - return DWARFExpression::Evaluate(exe_ctx, reg_ctx, module_sp, m_data, - m_dwarf_cu, m_reg_kind, initial_value_ptr, - object_address_ptr, result, error_ptr); -} - namespace { /// The location description kinds described by the DWARF v5 /// specification. Composite locations are handled out-of-band and @@ -2670,7 +2491,7 @@ bool DWARFExpression::Evaluate( return false; } uint64_t index = opcodes.GetULEB128(&offset); - lldb::addr_t value = ReadAddressFromDebugAddrSection(dwarf_cu, index); + lldb::addr_t value = dwarf_cu->ReadAddressFromDebugAddrSection(index); stack.push_back(Scalar(value)); stack.back().SetValueType(Value::ValueType::FileAddress); } break; @@ -2690,7 +2511,7 @@ bool DWARFExpression::Evaluate( return false; } uint64_t index = opcodes.GetULEB128(&offset); - lldb::addr_t value = ReadAddressFromDebugAddrSection(dwarf_cu, index); + lldb::addr_t value = dwarf_cu->ReadAddressFromDebugAddrSection(index); stack.push_back(Scalar(value)); } break; @@ -2743,61 +2564,16 @@ bool DWARFExpression::Evaluate( return true; // Return true on success } -static DataExtractor ToDataExtractor(const llvm::DWARFLocationExpression &loc, - ByteOrder byte_order, uint32_t addr_size) { - auto buffer_sp = - std::make_shared(loc.Expr.data(), loc.Expr.size()); - return DataExtractor(buffer_sp, byte_order, addr_size); -} - -bool DWARFExpression::DumpLocations(Stream *s, lldb::DescriptionLevel level, - addr_t load_function_start, addr_t addr, - ABI *abi) { - if (!IsLocationList()) { - DumpLocation(s, m_data, level, abi); - return true; - } - bool dump_all = addr == LLDB_INVALID_ADDRESS; - llvm::ListSeparator separator; - auto callback = [&](llvm::DWARFLocationExpression loc) -> bool { - if (loc.Range && - (dump_all || (loc.Range->LowPC <= addr && addr < loc.Range->HighPC))) { - uint32_t addr_size = m_data.GetAddressByteSize(); - DataExtractor data = ToDataExtractor(loc, m_data.GetByteOrder(), - m_data.GetAddressByteSize()); - s->AsRawOstream() << separator; - s->PutCString("["); - s->AsRawOstream() << llvm::format_hex(loc.Range->LowPC, - 2 + 2 * addr_size); - s->PutCString(", "); - s->AsRawOstream() << llvm::format_hex(loc.Range->HighPC, - 2 + 2 * addr_size); - s->PutCString(") -> "); - DumpLocation(s, data, level, abi); - return dump_all; - } - return true; - }; - if (!GetLocationExpressions(load_function_start, callback)) - return false; - return true; -} - -bool DWARFExpression::GetLocationExpressions( - addr_t load_function_start, - llvm::function_ref callback) const { - if (load_function_start == LLDB_INVALID_ADDRESS) - return false; - - Log *log = GetLog(LLDBLog::Expressions); - +bool DWARFExpression::ParseDWARFLocationList( + const DWARFUnit *dwarf_cu, const DataExtractor &data, + DWARFExpressionList *location_list) { + location_list->Clear(); std::unique_ptr loctable_up = - m_dwarf_cu->GetLocationTable(m_data); - - uint64_t offset = 0; + dwarf_cu->GetLocationTable(data); + Log *log = GetLog(LLDBLog::Expressions); auto lookup_addr = [&](uint32_t index) -> llvm::Optional { - addr_t address = ReadAddressFromDebugAddrSection(m_dwarf_cu, index); + addr_t address = dwarf_cu->ReadAddressFromDebugAddrSection(index); if (address == LLDB_INVALID_ADDRESS) return llvm::None; return llvm::object::SectionedAddress{address}; @@ -2807,18 +2583,17 @@ bool DWARFExpression::GetLocationExpressions( LLDB_LOG_ERROR(log, loc.takeError(), "{0}"); return true; } - if (loc->Range) { - // This relocates low_pc and high_pc by adding the difference between the - // function file address, and the actual address it is loaded in memory. - addr_t slide = load_function_start - m_loclist_addresses->func_file_addr; - loc->Range->LowPC += slide; - loc->Range->HighPC += slide; - } - return callback(*loc); + auto buffer_sp = + std::make_shared(loc->Expr.data(), loc->Expr.size()); + DWARFExpression expr = DWARFExpression(DataExtractor( + buffer_sp, data.GetByteOrder(), data.GetAddressByteSize())); + location_list->AddExpression(loc->Range->LowPC, loc->Range->HighPC, expr); + return true; }; llvm::Error error = loctable_up->visitAbsoluteLocationList( - offset, llvm::object::SectionedAddress{m_loclist_addresses->cu_file_addr}, + 0, llvm::object::SectionedAddress{dwarf_cu->GetBaseAddress()}, lookup_addr, process_list); + location_list->Sort(); if (error) { LLDB_LOG_ERROR(log, std::move(error), "{0}"); return false; @@ -2826,23 +2601,8 @@ bool DWARFExpression::GetLocationExpressions( return true; } -llvm::Optional -DWARFExpression::GetLocationExpression(addr_t load_function_start, - addr_t addr) const { - llvm::Optional data; - auto callback = [&](llvm::DWARFLocationExpression loc) { - if (loc.Range && loc.Range->LowPC <= addr && addr < loc.Range->HighPC) { - data = ToDataExtractor(loc, m_data.GetByteOrder(), - m_data.GetAddressByteSize()); - } - return !data; - }; - GetLocationExpressions(load_function_start, callback); - return data; -} - -bool DWARFExpression::MatchesOperand(StackFrame &frame, - const Instruction::Operand &operand) { +bool DWARFExpression::MatchesOperand( + StackFrame &frame, const Instruction::Operand &operand) const { using namespace OperandMatchers; RegisterContextSP reg_ctx_sp = frame.GetRegisterContext(); @@ -2850,28 +2610,7 @@ bool DWARFExpression::MatchesOperand(StackFrame &frame, return false; } - DataExtractor opcodes; - if (IsLocationList()) { - SymbolContext sc = frame.GetSymbolContext(eSymbolContextFunction); - if (!sc.function) - return false; - - addr_t load_function_start = - sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); - if (load_function_start == LLDB_INVALID_ADDRESS) - return false; - - addr_t pc = frame.GetFrameCodeAddressForSymbolication().GetLoadAddress( - frame.CalculateTarget().get()); - - if (llvm::Optional expr = - GetLocationExpression(load_function_start, pc)) - opcodes = std::move(*expr); - else - return false; - } else - opcodes = m_data; - + DataExtractor opcodes(m_data); lldb::offset_t op_offset = 0; uint8_t opcode = opcodes.GetU8(&op_offset); @@ -2879,7 +2618,7 @@ bool DWARFExpression::MatchesOperand(StackFrame &frame, if (opcode == DW_OP_fbreg) { int64_t offset = opcodes.GetSLEB128(&op_offset); - DWARFExpression *fb_expr = frame.GetFrameBaseExpression(nullptr); + DWARFExpressionList *fb_expr = frame.GetFrameBaseExpression(nullptr); if (!fb_expr) { return false; } diff --git a/lldb/source/Expression/DWARFExpressionList.cpp b/lldb/source/Expression/DWARFExpressionList.cpp new file mode 100644 index 00000000000000..e13a2931644be9 --- /dev/null +++ b/lldb/source/Expression/DWARFExpressionList.cpp @@ -0,0 +1,216 @@ +//===-- DWARFExpressionList.cpp -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Expression/DWARFExpressionList.h" +#include "Plugins/SymbolFile/DWARF/DWARFUnit.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StackFrame.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" + +using namespace lldb; +using namespace lldb_private; + +bool DWARFExpressionList::IsAlwaysValidSingleExpr() const { + if (m_exprs.GetSize() != 1) + return false; + const Entry expr = m_exprs.GetEntryRef(0); + return expr.base == 0 && expr.size == LLDB_INVALID_ADDRESS; +} + +bool DWARFExpressionList::AddExpression(addr_t base, addr_t end, + DWARFExpression expr) { + if (IsAlwaysValidSingleExpr() || base >= end) + return false; + m_exprs.Append({base, end - base, expr}); + return true; +} + +bool DWARFExpressionList::GetExpressionData(DataExtractor &data, + lldb::addr_t file_addr) const { + if (const DWARFExpression *expr = GetExpressionAtAddress(file_addr)) + return expr->GetExpressionData(data); + return false; +} + +bool DWARFExpressionList::ContainsAddress(lldb::addr_t file_addr) const { + return m_exprs.FindEntryThatContains(file_addr) != nullptr; +} + +const DWARFExpression * +DWARFExpressionList::GetExpressionAtAddress(lldb::addr_t file_addr) const { + uint32_t index = m_exprs.FindEntryIndexThatContains(file_addr); + if (index == UINT32_MAX) + return nullptr; + return &m_exprs.GetEntryAtIndex(index)->data; +} + +DWARFExpression * +DWARFExpressionList::GetMutableExpressionAtAddress(lldb::addr_t file_addr) { + uint32_t index = m_exprs.FindEntryIndexThatContains(file_addr); + if (index == UINT32_MAX) + return nullptr; + return &m_exprs.GetMutableEntryAtIndex(index)->data; +} + +bool DWARFExpressionList::ContainsThreadLocalStorage() const { + // We are assuming for now that any thread local variable will not have a + // location list. This has been true for all thread local variables we have + // seen so far produced by any compiler. + if (!IsAlwaysValidSingleExpr()) + return false; + + const DWARFExpression &expr = m_exprs.GetEntryRef(0).data; + return expr.ContainsThreadLocalStorage(); +} + +bool DWARFExpressionList::LinkThreadLocalStorage( + lldb::ModuleSP new_module_sp, + std::function const + &link_address_callback) { + // We are assuming for now that any thread local variable will not have a + // location list. This has been true for all thread local variables we have + // seen so far produced by any compiler. + if (!IsAlwaysValidSingleExpr()) + return false; + + DWARFExpression &expr = m_exprs.GetEntryRef(0).data; + // If we linked the TLS address correctly, update the module so that when the + // expression is evaluated it can resolve the file address to a load address + // and read the TLS data + if (expr.LinkThreadLocalStorage(link_address_callback)) + m_module_wp = new_module_sp; + return true; +} + +bool DWARFExpressionList::MatchesOperand( + StackFrame &frame, const Instruction::Operand &operand) const { + RegisterContextSP reg_ctx_sp = frame.GetRegisterContext(); + if (!reg_ctx_sp) { + return false; + } + const DWARFExpression *expr = nullptr; + if (IsAlwaysValidSingleExpr()) + expr = &m_exprs.GetEntryAtIndex(0)->data; + else { + SymbolContext sc = frame.GetSymbolContext(eSymbolContextFunction); + if (!sc.function) + return false; + + addr_t load_function_start = + sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); + if (load_function_start == LLDB_INVALID_ADDRESS) + return false; + + addr_t pc = frame.GetFrameCodeAddressForSymbolication().GetFileAddress(); + expr = GetExpressionAtAddress(pc); + } + if (!expr) + return false; + return expr->MatchesOperand(frame, operand); +} + +bool DWARFExpressionList::DumpLocations(Stream *s, lldb::DescriptionLevel level, + lldb::addr_t file_addr, + ABI *abi) const { + llvm::raw_ostream &os = s->AsRawOstream(); + llvm::ListSeparator separator; + for (const Entry &entry : *this) { + if (file_addr != LLDB_INVALID_ADDRESS && + (file_addr < entry.GetRangeBase() || file_addr >= entry.GetRangeEnd())) + continue; + const auto &expr = entry.data; + DataExtractor data; + expr.GetExpressionData(data); + uint32_t addr_size = data.GetAddressByteSize(); + if (entry.GetRangeEnd() == LLDB_INVALID_ADDRESS) { + expr.DumpLocation(s, level, abi); + break; + } + + os << separator; + os << "["; + os << llvm::format_hex(entry.GetRangeBase(), 2 + 2 * addr_size); + os << ", "; + os << llvm::format_hex(entry.GetRangeEnd(), 2 + 2 * addr_size); + os << ") -> "; + expr.DumpLocation(s, level, abi); + if (file_addr != LLDB_INVALID_ADDRESS) + break; + } + return true; +} + +void DWARFExpressionList::GetDescription(Stream *s, + lldb::DescriptionLevel level, + ABI *abi) const { + llvm::raw_ostream &os = s->AsRawOstream(); + if (IsAlwaysValidSingleExpr()) { + m_exprs.Back()->data.DumpLocation(s, level, abi); + return; + } + os << llvm::format("0x%8.8" PRIx64 ": ", 0); + for (const Entry &entry : *this) { + const auto &expr = entry.data; + DataExtractor data; + expr.GetExpressionData(data); + uint32_t addr_size = data.GetAddressByteSize(); + os << "\n"; + os.indent(s->GetIndentLevel() + 2); + os << "["; + llvm::DWARFFormValue::dumpAddress(os, addr_size, entry.GetRangeBase()); + os << ", "; + llvm::DWARFFormValue::dumpAddress(os, addr_size, entry.GetRangeEnd()); + os << "): "; + expr.DumpLocation(s, level, abi); + } +} + +bool DWARFExpressionList::Evaluate(ExecutionContext *exe_ctx, + RegisterContext *reg_ctx, + const Value *initial_value_ptr, + const Value *object_address_ptr, + Value &result, Status *error_ptr) const { + ModuleSP module_sp = m_module_wp.lock(); + DataExtractor data; + RegisterKind reg_kind; + DWARFExpression expr; + if (IsAlwaysValidSingleExpr()) { + expr = m_exprs.Back()->data; + } else { + Address pc; + StackFrame *frame = nullptr; + if (!reg_ctx || !reg_ctx->GetPCForSymbolication(pc)) { + if (exe_ctx) + frame = exe_ctx->GetFramePtr(); + if (!frame) + return false; + RegisterContextSP reg_ctx_sp = frame->GetRegisterContext(); + if (!reg_ctx_sp) + return false; + reg_ctx_sp->GetPCForSymbolication(pc); + } + + if (!pc.IsValid()) { + if (error_ptr) + error_ptr->SetErrorString("Invalid PC in frame."); + return false; + } + addr_t addr = pc.GetFileAddress(); + const auto *entry = m_exprs.FindEntryThatContains(addr); + if (!entry) + return false; + expr = entry->data; + } + expr.GetExpressionData(data); + reg_kind = expr.GetRegisterKind(); + return DWARFExpression::Evaluate(exe_ctx, reg_ctx, module_sp, data, + m_dwarf_cu, reg_kind, initial_value_ptr, + object_address_ptr, result, error_ptr); +} diff --git a/lldb/source/Expression/Materializer.cpp b/lldb/source/Expression/Materializer.cpp index 9ee2d983ddfc64..965a96b7f909d6 100644 --- a/lldb/source/Expression/Materializer.cpp +++ b/lldb/source/Expression/Materializer.cpp @@ -520,7 +520,7 @@ class EntityVariable : public Materializer::Entity { if (data.GetByteSize() < m_variable_sp->GetType()->GetByteSize(scope)) { if (data.GetByteSize() == 0 && - !m_variable_sp->LocationExpression().IsValid()) { + !m_variable_sp->LocationExpressionList().IsValid()) { err.SetErrorStringWithFormat("the variable '%s' has no location, " "it may have been optimized out", m_variable_sp->GetName().AsCString()); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index cc45871bcd71a5..6fb7d92244f90c 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -1485,15 +1485,14 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var, return false; } - DWARFExpression &var_location_expr = var->LocationExpression(); + DWARFExpressionList &var_location_list = var->LocationExpressionList(); Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); Status err; if (var->GetLocationIsConstantValueData()) { DataExtractor const_value_extractor; - - if (var_location_expr.GetExpressionData(const_value_extractor)) { + if (var_location_list.GetExpressionData(const_value_extractor)) { var_location = Value(const_value_extractor.GetDataStart(), const_value_extractor.GetByteSize()); var_location.SetValueType(Value::ValueType::HostAddress); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 2aacac3692be5a..4b9354371bda38 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -2292,7 +2292,7 @@ DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit, int call_file = 0; int call_line = 0; int call_column = 0; - DWARFExpression frame_base; + DWARFExpressionList frame_base; const dw_tag_t tag = die.Tag(); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp index ec074be581b54f..06cdd877f7dcd4 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -441,7 +441,7 @@ bool DWARFDIE::GetDIENamesAndRanges( const char *&name, const char *&mangled, DWARFRangeList &ranges, int &decl_file, int &decl_line, int &decl_column, int &call_file, int &call_line, int &call_column, - lldb_private::DWARFExpression *frame_base) const { + lldb_private::DWARFExpressionList *frame_base) const { if (IsValid()) { return m_die->GetDIENamesAndRanges( GetCU(), name, mangled, ranges, decl_file, decl_line, decl_column, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h index 5ee44a7632049f..7ce9550a081e93 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -85,11 +85,12 @@ class DWARFDIE : public DWARFBaseDIE { DWARFDIE GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const; - bool GetDIENamesAndRanges(const char *&name, const char *&mangled, - DWARFRangeList &ranges, int &decl_file, - int &decl_line, int &decl_column, int &call_file, - int &call_line, int &call_column, - lldb_private::DWARFExpression *frame_base) const; + bool + GetDIENamesAndRanges(const char *&name, const char *&mangled, + DWARFRangeList &ranges, int &decl_file, int &decl_line, + int &decl_column, int &call_file, int &call_line, + int &call_column, + lldb_private::DWARFExpressionList *frame_base) const; /// The range of all the children of this DIE. llvm::iterator_range children() const; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index 95c0cb6472c594..c1d49c5f23d7c8 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -231,11 +231,10 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges( DWARFUnit *cu, const char *&name, const char *&mangled, DWARFRangeList &ranges, int &decl_file, int &decl_line, int &decl_column, int &call_file, int &call_line, int &call_column, - DWARFExpression *frame_base) const { + DWARFExpressionList *frame_base) const { dw_addr_t lo_pc = LLDB_INVALID_ADDRESS; dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; std::vector dies; - bool set_frame_base_loclist_addr = false; const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu); @@ -345,21 +344,17 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges( uint32_t block_offset = form_value.BlockData() - data.GetDataStart(); uint32_t block_length = form_value.Unsigned(); - *frame_base = DWARFExpression( - module, DataExtractor(data, block_offset, block_length), cu); + *frame_base = + DWARFExpressionList(module, + DWARFExpression(DataExtractor( + data, block_offset, block_length)), + cu); } else { DataExtractor data = cu->GetLocationData(); const dw_offset_t offset = form_value.Unsigned(); if (data.ValidOffset(offset)) { data = DataExtractor(data, offset, data.GetByteSize() - offset); - *frame_base = DWARFExpression(module, data, cu); - if (lo_pc != LLDB_INVALID_ADDRESS) { - assert(lo_pc >= cu->GetBaseAddress()); - frame_base->SetLocationListAddresses(cu->GetBaseAddress(), - lo_pc); - } else { - set_frame_base_loclist_addr = true; - } + DWARFExpression::ParseDWARFLocationList(cu, data, frame_base); } } } @@ -381,12 +376,6 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges( } } - if (set_frame_base_loclist_addr) { - dw_addr_t lowest_range_pc = ranges.GetMinRangeBase(0); - assert(lowest_range_pc >= cu->GetBaseAddress()); - frame_base->SetLocationListAddresses(cu->GetBaseAddress(), lowest_range_pc); - } - if (ranges.IsEmpty() || name == nullptr || mangled == nullptr) { for (const DWARFDIE &die : dies) { if (die) { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h index 64e86c71ac09e0..32f653e99a7054 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -104,7 +104,7 @@ class DWARFDebugInfoEntry { DWARFUnit *cu, const char *&name, const char *&mangled, DWARFRangeList &rangeList, int &decl_file, int &decl_line, int &decl_column, int &call_file, int &call_line, int &call_column, - lldb_private::DWARFExpression *frame_base = nullptr) const; + lldb_private::DWARFExpressionList *frame_base = nullptr) const; const DWARFAbbreviationDeclaration * GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index 903cd2e38f769c..7b4a5d8eca3ed4 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -579,6 +579,17 @@ void DWARFUnit::SetStrOffsetsBase(dw_offset_t str_offsets_base) { m_str_offsets_base = str_offsets_base; } +dw_addr_t DWARFUnit::ReadAddressFromDebugAddrSection(uint32_t index) const { + uint32_t index_size = GetAddressByteSize(); + dw_offset_t addr_base = GetAddrBase(); + dw_addr_t offset = addr_base + index * index_size; + const DWARFDataExtractor &data = + m_dwarf.GetDWARFContext().getOrLoadAddrData(); + if (data.ValidOffsetForDataOfSize(offset, index_size)) + return data.GetMaxU64_unchecked(&offset, index_size); + return LLDB_INVALID_ADDRESS; +} + // It may be called only with m_die_array_mutex held R/W. void DWARFUnit::ClearDIEsRWLocked() { m_die_array.clear(); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h index 265e28b51c9911..40a1943b847a0f 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -166,6 +166,8 @@ class DWARFUnit : public lldb_private::UserID { void SetStrOffsetsBase(dw_offset_t str_offsets_base); virtual void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) = 0; + dw_addr_t ReadAddressFromDebugAddrSection(uint32_t index) const; + lldb::ByteOrder GetByteOrder() const; const DWARFDebugAranges &GetFunctionAranges(); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index c0bf13e0281d39..ab61a699c3edf0 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -9,6 +9,7 @@ #include "SymbolFileDWARF.h" #include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Threading.h" @@ -1885,11 +1886,13 @@ SymbolFileDWARF::GlobalVariableMap &SymbolFileDWARF::GetGlobalAranges() { for (size_t g = 0; g < num_globals; ++g) { VariableSP var_sp = globals_sp->GetVariableAtIndex(g); if (var_sp && !var_sp->GetLocationIsConstantValueData()) { - const DWARFExpression &location = var_sp->LocationExpression(); + const DWARFExpressionList &location = + var_sp->LocationExpressionList(); Value location_result; Status error; - if (location.Evaluate(nullptr, LLDB_INVALID_ADDRESS, nullptr, - nullptr, location_result, &error)) { + ExecutionContext exe_ctx; + if (location.Evaluate(&exe_ctx, nullptr, nullptr, nullptr, + location_result, &error)) { if (location_result.GetValueType() == Value::ValueType::FileAddress) { lldb::addr_t file_addr = @@ -3163,7 +3166,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, const char *mangled = nullptr; Declaration decl; DWARFFormValue type_die_form; - DWARFExpression location; + DWARFExpressionList location_list(module, DWARFExpression(), die.GetCU()); bool is_external = false; bool is_artificial = false; DWARFFormValue const_value_form, location_form; @@ -3229,16 +3232,15 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, // present in the class declaration and DW_AT_location in the DIE defining // the member. bool location_is_const_value_data = false; - bool has_explicit_location = false; + bool has_explicit_location = location_form.IsValid(); bool use_type_size_for_value = false; if (location_form.IsValid()) { - has_explicit_location = true; if (DWARFFormValue::IsBlockForm(location_form.Form())) { const DWARFDataExtractor &data = die.GetData(); uint32_t block_offset = location_form.BlockData() - data.GetDataStart(); uint32_t block_length = location_form.Unsigned(); - location = DWARFExpression( + location_list = DWARFExpressionList( module, DataExtractor(data, block_offset, block_length), die.GetCU()); } else { DataExtractor data = die.GetCU()->GetLocationData(); @@ -3247,10 +3249,8 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, offset = die.GetCU()->GetLoclistOffset(offset).value_or(-1); if (data.ValidOffset(offset)) { data = DataExtractor(data, offset, data.GetByteSize() - offset); - location = DWARFExpression(module, data, die.GetCU()); - assert(func_low_pc != LLDB_INVALID_ADDRESS); - location.SetLocationListAddresses( - location_form.GetUnit()->GetBaseAddress(), func_low_pc); + const DWARFUnit *dwarf_cu = location_form.GetUnit(); + DWARFExpression::ParseDWARFLocationList(dwarf_cu, data, &location_list); } } } else if (const_value_form.IsValid()) { @@ -3263,7 +3263,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, uint32_t block_offset = const_value_form.BlockData() - debug_info_data.GetDataStart(); uint32_t block_length = const_value_form.Unsigned(); - location = DWARFExpression( + location_list = DWARFExpressionList( module, DataExtractor(debug_info_data, block_offset, block_length), die.GetCU()); } else if (DWARFFormValue::IsDataForm(const_value_form.Form())) { @@ -3273,7 +3273,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, use_type_size_for_value = true; } else if (const char *str = const_value_form.AsCString()) { uint32_t string_length = strlen(str) + 1; - location = DWARFExpression( + location_list = DWARFExpressionList( module, DataExtractor(str, string_length, die.GetCU()->GetByteOrder(), die.GetCU()->GetAddressByteSize()), @@ -3323,16 +3323,19 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, // with locations like: DW_OP_addr(0x1000), DW_OP_constu(2), DW_OP_plus // so we need to look through the whole expression. bool is_static_lifetime = - has_explicit_mangled || (has_explicit_location && !location.IsValid()); + has_explicit_mangled || + (has_explicit_location && !location_list.IsValid()); // Check if the location has a DW_OP_addr with any address value... lldb::addr_t location_DW_OP_addr = LLDB_INVALID_ADDRESS; if (!location_is_const_value_data) { bool op_error = false; - location_DW_OP_addr = location.GetLocation_DW_OP_addr(0, op_error); + const DWARFExpression* location = location_list.GetAlwaysValidExpr(); + if (location) + location_DW_OP_addr = location->GetLocation_DW_OP_addr( + location_form.GetUnit(), 0, op_error); if (op_error) { StreamString strm; - location.DumpLocationForAddress(&strm, eDescriptionLevelFull, 0, 0, - nullptr); + location->DumpLocation(&strm, eDescriptionLevelFull, nullptr); GetObjectFile()->GetModule()->ReportError( "0x%8.8x: %s has an invalid location: %s", die.GetOffset(), die.GetTagAsCString(), strm.GetData()); @@ -3345,7 +3348,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, // Set the module of the expression to the linked module // instead of the object file so the relocated address can be // found there. - location.SetModule(debug_map_symfile->GetObjectFile()->GetModule()); + location_list.SetModule(debug_map_symfile->GetObjectFile()->GetModule()); if (is_static_lifetime) { if (is_external) @@ -3386,7 +3389,9 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, const addr_t exe_file_addr = exe_symbol->GetAddressRef().GetFileAddress(); if (exe_file_addr != LLDB_INVALID_ADDRESS) { - if (location.Update_DW_OP_addr(exe_file_addr)) { + DWARFExpression *location = + location_list.GetMutableExpressionAtAddress(); + if (location->Update_DW_OP_addr(exe_file_addr)) { linked_oso_file_addr = true; symbol_context_scope = exe_symbol; } @@ -3404,7 +3409,9 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, debug_map_symfile->LinkOSOFileAddress(this, location_DW_OP_addr); if (exe_file_addr != LLDB_INVALID_ADDRESS) { // Update the file address for this variable - location.Update_DW_OP_addr(exe_file_addr); + DWARFExpression *location = + location_list.GetMutableExpressionAtAddress(); + location->Update_DW_OP_addr(exe_file_addr); } else { // Variable didn't make it into the final executable return nullptr; @@ -3419,8 +3426,8 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, scope = eValueTypeVariableLocal; if (debug_map_symfile) { // We need to check for TLS addresses that we need to fixup - if (location.ContainsThreadLocalStorage()) { - location.LinkThreadLocalStorage( + if (location_list.ContainsThreadLocalStorage()) { + location_list.LinkThreadLocalStorage( debug_map_symfile->GetObjectFile()->GetModule(), [this, debug_map_symfile]( lldb::addr_t unlinked_file_addr) -> lldb::addr_t { @@ -3463,14 +3470,17 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, auto type_sp = std::make_shared( *this, GetUID(type_die_form.Reference())); - if (use_type_size_for_value && type_sp->GetType()) - location.UpdateValue(const_value_form.Unsigned(), - type_sp->GetType()->GetByteSize(nullptr).value_or(0), - die.GetCU()->GetAddressByteSize()); + if (use_type_size_for_value && type_sp->GetType()) { + DWARFExpression *location = location_list.GetMutableExpressionAtAddress(); + location->UpdateValue( + const_value_form.Unsigned(), + type_sp->GetType()->GetByteSize(nullptr).getValueOr(0), + die.GetCU()->GetAddressByteSize()); + } return std::make_shared( die.GetID(), name, mangled, type_sp, scope, symbol_context_scope, - scope_ranges, &decl, location, is_external, is_artificial, + scope_ranges, &decl, location_list, is_external, is_artificial, location_is_const_value_data, is_static_member); } @@ -3755,8 +3765,8 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) { child.Tag() != DW_TAG_GNU_call_site_parameter) continue; - llvm::Optional LocationInCallee; - llvm::Optional LocationInCaller; + llvm::Optional LocationInCallee; + llvm::Optional LocationInCaller; DWARFAttributes attributes; const size_t num_attributes = child.GetAttributes(attributes); @@ -3764,7 +3774,7 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) { // Parse the location at index \p attr_index within this call site parameter // DIE, or return None on failure. auto parse_simple_location = - [&](int attr_index) -> llvm::Optional { + [&](int attr_index) -> llvm::Optional { DWARFFormValue form_value; if (!attributes.ExtractFormValueAtIndex(attr_index, form_value)) return {}; @@ -3773,9 +3783,9 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) { auto data = child.GetData(); uint32_t block_offset = form_value.BlockData() - data.GetDataStart(); uint32_t block_length = form_value.Unsigned(); - return DWARFExpression(module, - DataExtractor(data, block_offset, block_length), - child.GetCU()); + return DWARFExpressionList( + module, DataExtractor(data, block_offset, block_length), + child.GetCU()); }; for (size_t i = 0; i < num_attributes; ++i) { @@ -3820,7 +3830,7 @@ SymbolFileDWARF::CollectCallEdges(ModuleSP module, DWARFDIE function_die) { continue; llvm::Optional call_origin; - llvm::Optional call_target; + llvm::Optional call_target; addr_t return_pc = LLDB_INVALID_ADDRESS; addr_t call_inst_pc = LLDB_INVALID_ADDRESS; addr_t low_pc = LLDB_INVALID_ADDRESS; @@ -3881,7 +3891,7 @@ SymbolFileDWARF::CollectCallEdges(ModuleSP module, DWARFDIE function_die) { auto data = child.GetData(); uint32_t block_offset = form_value.BlockData() - data.GetDataStart(); uint32_t block_length = form_value.Unsigned(); - call_target = DWARFExpression( + call_target = DWARFExpressionList( module, DataExtractor(data, block_offset, block_length), child.GetCU()); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 2403ee2624ea19..cfd18f02053b40 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -21,6 +21,7 @@ #include "lldb/Core/UniqueCStringMap.h" #include "lldb/Core/dwarf.h" +#include "lldb/Expression/DWARFExpressionList.h" #include "lldb/Symbol/DebugMacros.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/SymbolFile.h" diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp index 3ba0079c96e6ac..3166c8ae65c6c7 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp @@ -122,7 +122,7 @@ static DWARFExpression MakeLocationExpressionInternal(lldb::ModuleSP module, DataBufferSP buffer = std::make_shared(stream.GetData(), stream.GetSize()); DataExtractor extractor(buffer, byte_order, address_size, byte_size); - DWARFExpression result(module, extractor, nullptr); + DWARFExpression result(extractor); result.SetRegisterKind(register_kind); return result; @@ -247,7 +247,7 @@ DWARFExpression lldb_private::npdb::MakeConstantLocationExpression( .take_front(size); buffer->CopyData(bytes.data(), size); DataExtractor extractor(buffer, lldb::eByteOrderLittle, address_size); - DWARFExpression result(nullptr, extractor, nullptr); + DWARFExpression result(extractor); return result; } diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index 7dc99818c24432..d94ba6b3531a6f 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -823,8 +823,10 @@ VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) { m_ast->GetOrCreateVariableDecl(var_id); - DWARFExpression location = MakeGlobalLocationExpression( - section, offset, GetObjectFile()->GetModule()); + ModuleSP module_sp = GetObjectFile()->GetModule(); + DWARFExpressionList location( + module_sp, MakeGlobalLocationExpression(section, offset, module_sp), + nullptr); std::string global_name("::"); global_name += name; @@ -855,8 +857,10 @@ SymbolFileNativePDB::CreateConstantSymbol(PdbGlobalSymId var_id, Declaration decl; Variable::RangeList ranges; ModuleSP module = GetObjectFile()->GetModule(); - DWARFExpression location = MakeConstantLocationExpression( - constant.Type, tpi, constant.Value, module); + DWARFExpressionList location(module, + MakeConstantLocationExpression( + constant.Type, tpi, constant.Value, module), + nullptr); bool external = false; bool artificial = false; @@ -1711,7 +1715,8 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id, bool static_member = false; VariableSP var_sp = std::make_shared( toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope, - &block, *var_info.ranges, &decl, *var_info.location, external, + &block, *var_info.ranges, &decl, + DWARFExpressionList(module, *var_info.location, nullptr), external, artificial, location_is_constant_data, static_member); if (!is_param) diff --git a/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp b/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp index 96e9de704e414e..94023737b2a2ef 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp +++ b/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp @@ -175,7 +175,7 @@ DWARFExpression ConvertPDBLocationToDWARFExpression( DataBufferSP buffer = std::make_shared(stream.GetData(), stream.GetSize()); DataExtractor extractor(buffer, byte_order, address_size, byte_size); - DWARFExpression result(module, extractor, nullptr); + DWARFExpression result(extractor); result.SetRegisterKind(register_kind); return result; diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp index bd3d16aad6c2e4..baa48532864bbe 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -1023,8 +1023,11 @@ VariableSP SymbolFilePDB::ParseVariableForPDBData( auto mangled_cstr = mangled.empty() ? nullptr : mangled.c_str(); bool is_constant; - DWARFExpression location = ConvertPDBLocationToDWARFExpression( - GetObjectFile()->GetModule(), pdb_data, ranges, is_constant); + ModuleSP module_sp = GetObjectFile()->GetModule(); + DWARFExpressionList location(module_sp, + ConvertPDBLocationToDWARFExpression( + module_sp, pdb_data, ranges, is_constant), + nullptr); var_sp = std::make_shared( var_uid, var_name.c_str(), mangled_cstr, type_sp, scope, context_scope, diff --git a/lldb/source/Symbol/Function.cpp b/lldb/source/Symbol/Function.cpp index 648a12524aed1e..54c562eb1bdd92 100644 --- a/lldb/source/Symbol/Function.cpp +++ b/lldb/source/Symbol/Function.cpp @@ -197,7 +197,6 @@ Function *IndirectCallEdge::GetCallee(ModuleList &images, Status error; Value callee_addr_val; if (!call_target.Evaluate(&exe_ctx, exe_ctx.GetRegisterContext(), - /*loclist_base_load_addr=*/LLDB_INVALID_ADDRESS, /*initial_value_ptr=*/nullptr, /*object_address_ptr=*/nullptr, callee_addr_val, &error)) { diff --git a/lldb/source/Symbol/Variable.cpp b/lldb/source/Symbol/Variable.cpp index b92c8665449694..285e32d21ce232 100644 --- a/lldb/source/Symbol/Variable.cpp +++ b/lldb/source/Symbol/Variable.cpp @@ -39,13 +39,13 @@ Variable::Variable(lldb::user_id_t uid, const char *name, const char *mangled, const lldb::SymbolFileTypeSP &symfile_type_sp, ValueType scope, SymbolContextScope *context, const RangeList &scope_range, Declaration *decl_ptr, - const DWARFExpression &location, bool external, + const DWARFExpressionList &location_list, bool external, bool artificial, bool location_is_constant_data, bool static_member) : UserID(uid), m_name(name), m_mangled(ConstString(mangled)), m_symfile_type_sp(symfile_type_sp), m_scope(scope), m_owner_scope(context), m_scope_range(scope_range), - m_declaration(decl_ptr), m_location(location), m_external(external), + m_declaration(decl_ptr), m_location_list(location_list), m_external(external), m_artificial(artificial), m_loc_is_const_data(location_is_constant_data), m_static_member(static_member) {} @@ -145,7 +145,7 @@ void Variable::Dump(Stream *s, bool show_context) const { bool show_fullpaths = false; m_declaration.Dump(s, show_fullpaths); - if (m_location.IsValid()) { + if (m_location_list.IsValid()) { s->PutCString(", location = "); ABISP abi; if (m_owner_scope) { @@ -153,7 +153,7 @@ void Variable::Dump(Stream *s, bool show_context) const { if (module_sp) abi = ABI::FindPlugin(ProcessSP(), module_sp->GetArchitecture()); } - m_location.GetDescription(s, lldb::eDescriptionLevelBrief, abi.get()); + m_location_list.GetDescription(s, lldb::eDescriptionLevelBrief, abi.get()); } if (m_external) @@ -212,31 +212,8 @@ void Variable::CalculateSymbolContext(SymbolContext *sc) { } bool Variable::LocationIsValidForFrame(StackFrame *frame) { - // Is the variable is described by a single location? - if (!m_location.IsLocationList()) { - // Yes it is, the location is valid. - return true; - } - - if (frame) { - Function *function = - frame->GetSymbolContext(eSymbolContextFunction).function; - if (function) { - TargetSP target_sp(frame->CalculateTarget()); - - addr_t loclist_base_load_addr = - function->GetAddressRange().GetBaseAddress().GetLoadAddress( - target_sp.get()); - if (loclist_base_load_addr == LLDB_INVALID_ADDRESS) - return false; - // It is a location list. We just need to tell if the location list - // contains the current address when converted to a load address - return m_location.LocationListContainsAddress( - loclist_base_load_addr, - frame->GetFrameCodeAddress().GetLoadAddress(target_sp.get())); - } - } - return false; + return m_location_list.ContainsAddress( + frame->GetFrameCodeAddress().GetFileAddress()); } bool Variable::LocationIsValidForAddress(const Address &address) { @@ -244,7 +221,7 @@ bool Variable::LocationIsValidForAddress(const Address &address) { // function. if (address.IsSectionOffset()) { // We need to check if the address is valid for both scope range and value - // range. + // range. // Empty scope range means block range. bool valid_in_scope_range = GetScopeRange().IsEmpty() || GetScopeRange().FindEntryThatContains( @@ -254,22 +231,10 @@ bool Variable::LocationIsValidForAddress(const Address &address) { SymbolContext sc; CalculateSymbolContext(&sc); if (sc.module_sp == address.GetModule()) { - // Is the variable is described by a single location? - if (!m_location.IsLocationList()) { - // Yes it is, the location is valid. - return true; - } - - if (sc.function) { - addr_t loclist_base_file_addr = - sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); - if (loclist_base_file_addr == LLDB_INVALID_ADDRESS) - return false; - // It is a location list. We just need to tell if the location list - // contains the current address when converted to a load address - return m_location.LocationListContainsAddress(loclist_base_file_addr, - address.GetFileAddress()); - } + // Empty location list means we have missing value range info, but it's in + // the scope. + return m_location_list.GetSize() == 0 || + m_location_list.ContainsAddress(address.GetFileAddress()); } } return false; @@ -454,16 +419,8 @@ bool Variable::DumpLocations(Stream *s, const Address &address) { } const addr_t file_addr = address.GetFileAddress(); - if (sc.function) { - addr_t loclist_base_file_addr = - sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); - if (loclist_base_file_addr == LLDB_INVALID_ADDRESS) - return false; - return m_location.DumpLocations(s, eDescriptionLevelBrief, - loclist_base_file_addr, file_addr, - abi.get()); - } - return false; + return m_location_list.DumpLocations(s, eDescriptionLevelBrief, file_addr, + abi.get()); } static void PrivateAutoComplete( diff --git a/lldb/source/Target/RegisterContextUnwind.cpp b/lldb/source/Target/RegisterContextUnwind.cpp index e98aed7e15552e..bca7eec5e939e4 100644 --- a/lldb/source/Target/RegisterContextUnwind.cpp +++ b/lldb/source/Target/RegisterContextUnwind.cpp @@ -11,7 +11,7 @@ #include "lldb/Core/AddressRange.h" #include "lldb/Core/Module.h" #include "lldb/Core/Value.h" -#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Expression/DWARFExpressionList.h" #include "lldb/Symbol/ArmUnwindInfo.h" #include "lldb/Symbol/CallFrameInfo.h" #include "lldb/Symbol/DWARFCallFrameInfo.h" @@ -381,7 +381,7 @@ void RegisterContextUnwind::InitializeNonZerothFrame() { // symbol/function information - just stick in some reasonable defaults and // hope we can unwind past this frame. If we're above a trap handler, // we may be at a bogus address because we jumped through a bogus function - // pointer and trapped, so don't force the arch default unwind plan in that + // pointer and trapped, so don't force the arch default unwind plan in that // case. ModuleSP pc_module_sp(m_current_pc.GetModule()); if ((!m_current_pc.IsValid() || !pc_module_sp) && @@ -1286,7 +1286,7 @@ RegisterContextUnwind::SavedLocationForRegister( // arch default unwind plan is used as the Fast Unwind Plan, we // need to recognize this & switch over to the Full Unwind Plan // to see what unwind rule that (more knoweldgeable, probably) - // UnwindPlan has. If the full UnwindPlan says the register + // UnwindPlan has. If the full UnwindPlan says the register // location is Undefined, then it really is. if (active_row->GetRegisterInfo(regnum.GetAsKind(unwindplan_registerkind), unwindplan_regloc) && @@ -1335,13 +1335,13 @@ RegisterContextUnwind::SavedLocationForRegister( m_full_unwind_plan_sp->GetReturnAddressRegister() != LLDB_INVALID_REGNUM) { // If this is a trap handler frame, we should have access to - // the complete register context when the interrupt/async + // the complete register context when the interrupt/async // signal was received, we should fetch the actual saved $pc // value instead of the Return Address register. // If $pc is not available, fall back to the RA reg. UnwindPlan::Row::RegisterLocation scratch; if (m_frame_type == eTrapHandlerFrame && - active_row->GetRegisterInfo + active_row->GetRegisterInfo (pc_regnum.GetAsKind (unwindplan_registerkind), scratch)) { UnwindLogMsg("Providing pc register instead of rewriting to " "RA reg because this is a trap handler and there is " @@ -1642,14 +1642,14 @@ RegisterContextUnwind::SavedLocationForRegister( process->GetByteOrder(), process->GetAddressByteSize()); ModuleSP opcode_ctx; - DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr); - dwarfexpr.SetRegisterKind(unwindplan_registerkind); + DWARFExpressionList dwarfexpr(opcode_ctx, dwarfdata, nullptr); + dwarfexpr.GetMutableExpressionAtAddress()->SetRegisterKind( + unwindplan_registerkind); Value cfa_val = Scalar(m_cfa); cfa_val.SetValueType(Value::ValueType::LoadAddress); Value result; Status error; - if (dwarfexpr.Evaluate(&exe_ctx, this, 0, &cfa_val, nullptr, result, - &error)) { + if (dwarfexpr.Evaluate(&exe_ctx, this, &cfa_val, nullptr, result, &error)) { addr_t val; val = result.GetScalar().ULongLong(); if (unwindplan_regloc.IsDWARFExpression()) { @@ -2006,11 +2006,12 @@ bool RegisterContextUnwind::ReadFrameAddress( process->GetByteOrder(), process->GetAddressByteSize()); ModuleSP opcode_ctx; - DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr); - dwarfexpr.SetRegisterKind(row_register_kind); + DWARFExpressionList dwarfexpr(opcode_ctx, dwarfdata, nullptr); + dwarfexpr.GetMutableExpressionAtAddress()->SetRegisterKind( + row_register_kind); Value result; Status error; - if (dwarfexpr.Evaluate(&exe_ctx, this, 0, nullptr, nullptr, result, + if (dwarfexpr.Evaluate(&exe_ctx, this, nullptr, nullptr, result, &error)) { address = result.GetScalar().ULongLong(); if (ABISP abi_sp = m_thread.GetProcess()->GetABI()) diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 1e3dbc73a04ed5..28c8dfde72a8dc 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -1086,15 +1086,9 @@ bool StackFrame::GetFrameBaseValue(Scalar &frame_base, Status *error_ptr) { m_flags.Set(GOT_FRAME_BASE); ExecutionContext exe_ctx(shared_from_this()); Value expr_value; - addr_t loclist_base_addr = LLDB_INVALID_ADDRESS; - if (m_sc.function->GetFrameBaseExpression().IsLocationList()) - loclist_base_addr = - m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress( - exe_ctx.GetTargetPtr()); - if (!m_sc.function->GetFrameBaseExpression().Evaluate( - &exe_ctx, nullptr, loclist_base_addr, nullptr, nullptr, - expr_value, &m_frame_base_error)) { + &exe_ctx, nullptr, nullptr, nullptr, expr_value, + &m_frame_base_error)) { // We should really have an error if evaluate returns, but in case we // don't, lets set the error to something at least. if (m_frame_base_error.Success()) @@ -1116,7 +1110,7 @@ bool StackFrame::GetFrameBaseValue(Scalar &frame_base, Status *error_ptr) { return m_frame_base_error.Success(); } -DWARFExpression *StackFrame::GetFrameBaseExpression(Status *error_ptr) { +DWARFExpressionList *StackFrame::GetFrameBaseExpression(Status *error_ptr) { if (!m_sc.function) { if (error_ptr) { error_ptr->SetErrorString("No function in symbol context."); @@ -1200,7 +1194,7 @@ lldb::LanguageType StackFrame::GuessLanguage() { LanguageType lang_type = GetLanguage(); if (lang_type == eLanguageTypeUnknown) { - SymbolContext sc = GetSymbolContext(eSymbolContextFunction + SymbolContext sc = GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol); if (sc.function) { lang_type = sc.function->GetMangled().GuessLanguage(); @@ -1417,7 +1411,7 @@ ValueObjectSP GetValueForDereferincingOffset(StackFrame &frame, Status error; ValueObjectSP pointee = base->Dereference(error); - + if (!pointee) { return ValueObjectSP(); } @@ -1505,7 +1499,7 @@ lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg, Instruction::Operand::BuildRegister(reg)); for (VariableSP var_sp : variables) { - if (var_sp->LocationExpression().MatchesOperand(frame, op)) + if (var_sp->LocationExpressionList().MatchesOperand(frame, op)) return frame.GetValueObjectForFrameVariable(var_sp, eNoDynamicValues); } diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/debug_loc.s b/lldb/test/Shell/SymbolFile/DWARF/x86/debug_loc.s index 2daf816d300c8d..f8e8bfba970f0d 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/x86/debug_loc.s +++ b/lldb/test/Shell/SymbolFile/DWARF/x86/debug_loc.s @@ -40,11 +40,11 @@ # CHECK-NEXT: [0x0000000000000000, 0x0000000000000001): DW_OP_reg5 RDI # CHECK-NEXT: [0x0000000000000001, 0x0000000000000006): DW_OP_reg0 RAX # CHECK: Variable{{.*}}, name = "x1", {{.*}}, scope = parameter -# CHECK: Variable{{.*}}, name = "x2", {{.*}}, scope = parameter, location = 0x00000000: error: unexpected end of data +# CHECK: Variable{{.*}}, name = "x2", {{.*}}, scope = parameter # CHECK: Variable{{.*}}, name = "x3", {{.*}}, scope = parameter, location = # CHECK-NEXT: [0x0000000000000002, 0x0000000000000003): DW_OP_reg1 RDX -# LOCLISTS: Variable{{.*}}, name = "x4", {{.*}}, scope = parameter, location = -# LOCLISTS-NEXT: DW_LLE_startx_length (0x000000000000dead, 0x0000000000000001): DW_OP_reg2 RCX +# LOCLISTS: Variable{{.*}}, name = "x4", {{.*}}, scope = parameter +# LOCLISTS-EMPTY: .ifdef LOC .macro OFFSET_PAIR lo hi diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/dwp.s b/lldb/test/Shell/SymbolFile/DWARF/x86/dwp.s index a921641bcec545..c8eead3d28d292 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/x86/dwp.s +++ b/lldb/test/Shell/SymbolFile/DWARF/x86/dwp.s @@ -19,29 +19,29 @@ # SYMBOLS-NEXT: Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x0 # SYMBOLS-NEXT: Function{{.*}}, demangled = F0 # SYMBOLS-NEXT: Block{{.*}}, ranges = [0x00000000-0x00000001) -# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location = -# SYMBOLS-NEXT: DW_LLE_startx_length (0x0000000000000001, 0x0000000000000001): DW_OP_reg0 RAX +# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location = +# SYMBOLS-NEXT: [0x0000000000000000, 0x0000000000000001): DW_OP_reg0 RAX # SYMBOLS-EMPTY: # SYMBOLS-NEXT: CompileUnit{0x00000001}, language = "", file = '1.c' # SYMBOLS-NEXT: Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x2 # SYMBOLS-NEXT: Function{{.*}}, demangled = F1 # SYMBOLS-NEXT: Block{{.*}}, ranges = [0x00000001-0x00000002) -# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location = -# SYMBOLS-NEXT: DW_LLE_startx_length (0x0000000000000003, 0x0000000000000001): DW_OP_reg1 RDX +# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location = +# SYMBOLS-NEXT: [0x0000000000000001, 0x0000000000000002): DW_OP_reg1 RDX # SYMBOLS-EMPTY: # SYMBOLS-NEXT: CompileUnit{0x00000002}, language = "", file = '2.c' # SYMBOLS-NEXT: Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x4 # SYMBOLS-NEXT: Function{{.*}}, demangled = F2 # SYMBOLS-NEXT: Block{{.*}}, ranges = [0x00000002-0x00000003) -# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location = -# SYMBOLS-NEXT: DW_LLE_startx_length (0x0000000000000005, 0x0000000000000001): DW_OP_reg2 RCX +# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location = +# SYMBOLS-NEXT: [0x0000000000000002, 0x0000000000000003): DW_OP_reg2 RCX # SYMBOLS-EMPTY: # SYMBOLS-NEXT: CompileUnit{0x00000003}, language = "", file = '3.c' # SYMBOLS-NEXT: Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x6 # SYMBOLS-NEXT: Function{{.*}}, demangled = F3 # SYMBOLS-NEXT: Block{{.*}}, ranges = [0x00000003-0x00000004) -# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location = -# SYMBOLS-NEXT: DW_LLE_startx_length (0x0000000000000007, 0x0000000000000001): DW_OP_reg3 RBX +# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location = +# SYMBOLS-NEXT: [0x0000000000000003, 0x0000000000000004): DW_OP_reg3 RBX # SYMBOLS-EMPTY: # SYMBOLS-NEXT: CompileUnit{0x00000004}, language = "", file = '' # SYMBOLS-EMPTY: @@ -116,7 +116,7 @@ F\I: .Lloc\I: .byte 3 # DW_LLE_startx_length .uleb128 \I*2+1 - .long 1 + .long 1 .short 1 # Expression size .byte 80+\I # super-register DW_OP_reg0+\I .byte 0 # DW_LLE_end_of_list diff --git a/llvm/utils/gn/secondary/lldb/source/Expression/BUILD.gn b/llvm/utils/gn/secondary/lldb/source/Expression/BUILD.gn index f58874f794eecc..62d73353842169 100644 --- a/llvm/utils/gn/secondary/lldb/source/Expression/BUILD.gn +++ b/llvm/utils/gn/secondary/lldb/source/Expression/BUILD.gn @@ -23,6 +23,7 @@ static_library("Expression") { include_dirs = [ ".." ] sources = [ "DWARFExpression.cpp", + "DWARFExpressionList.cpp", "DiagnosticManager.cpp", "Expression.cpp", "ExpressionVariable.cpp",