diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h index 49e51d51f211c..96a0e8e02da13 100644 --- a/lldb/include/lldb/Expression/DWARFExpression.h +++ b/lldb/include/lldb/Expression/DWARFExpression.h @@ -42,14 +42,49 @@ class DWARFExpression { /// \param[in] data /// A data extractor configured to read the DWARF location expression's /// bytecode. - DWARFExpression(const DataExtractor &data); + DWARFExpression(lldb::ModuleSP module, const DataExtractor &data, + const DWARFUnit *dwarf_cu); /// 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 @@ -58,9 +93,6 @@ 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. @@ -72,22 +104,36 @@ 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(const DWARFUnit *dwarf_cu, - uint32_t op_addr_idx, bool &error) const; + lldb::addr_t GetLocation_DW_OP_addr(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 - lldb::RegisterKind GetRegisterKind() const; + int GetRegisterKind(); /// Set the call-frame-info style register kind /// @@ -95,6 +141,20 @@ 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 @@ -134,32 +194,72 @@ 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 module_sp, const DataExtractor &opcodes, + lldb::ModuleSP opcode_ctx, 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; } - void DumpLocation(Stream *s, lldb::DescriptionLevel level, ABI *abi) const; + 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; - bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op) const; + bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op); + + llvm::Optional + GetLocationExpression(lldb::addr_t load_function_start, + lldb::addr_t addr) 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 deleted file mode 100644 index 34cd217b8fe4a..0000000000000 --- a/lldb/include/lldb/Expression/DWARFExpressionList.h +++ /dev/null @@ -1,132 +0,0 @@ -//===-- 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 3eb4f5d7dedf4..83f9979c3c529 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/DWARFExpressionList.h" +#include "lldb/Expression/DWARFExpression.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 { - DWARFExpressionList LocationInCallee; - DWARFExpressionList LocationInCaller; + DWARFExpression LocationInCallee; + DWARFExpression 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(DWARFExpressionList call_target, AddrType caller_address_type, + IndirectCallEdge(DWARFExpression 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. - DWARFExpressionList call_target; + DWARFExpression 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. - DWARFExpressionList &GetFrameBaseExpression() { return m_frame_base; } + DWARFExpression &GetFrameBaseExpression() { return m_frame_base; } /// Get const accessor for the frame base location. /// /// \return /// A const compile unit object pointer. - const DWARFExpressionList &GetFrameBaseExpression() const { return m_frame_base; } + const DWARFExpression &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. - DWARFExpressionList m_frame_base; + DWARFExpression m_frame_base; Flags m_flags; diff --git a/lldb/include/lldb/Symbol/Variable.h b/lldb/include/lldb/Symbol/Variable.h index c437624d1ea6d..88a975df39928 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/DWARFExpressionList.h" +#include "lldb/Expression/DWARFExpression.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 DWARFExpressionList &location, - bool external, bool artificial, bool location_is_constant_data, + Declaration *decl, const DWARFExpression &location, bool external, + bool artificial, bool location_is_constant_data, bool static_member = false); virtual ~Variable(); @@ -73,11 +73,9 @@ class Variable : public UserID, public std::enable_shared_from_this { bool IsStaticMember() const { return m_static_member; } - DWARFExpressionList &LocationExpressionList() { return m_location_list; } + DWARFExpression &LocationExpression() { return m_location; } - const DWARFExpressionList &LocationExpressionList() const { - return m_location_list; - } + const DWARFExpression &LocationExpression() const { return m_location; } // When given invalid address, it dumps all locations. Otherwise it only dumps // the location that contains this address. @@ -130,7 +128,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(). - DWARFExpressionList m_location_list; + DWARFExpression m_location; /// 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 7c4340de4de06..1b0485b22cacb 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 DWARFExpressionList corresponding to the Canonical Frame Address. + /// Get the DWARFExpression 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. - DWARFExpressionList *GetFrameBaseExpression(Status *error_ptr); + DWARFExpression *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 257b177c70927..7eb0cab8084c7 100644 --- a/lldb/include/lldb/Utility/RangeMap.h +++ b/lldb/include/lldb/Utility/RangeMap.h @@ -627,10 +627,6 @@ 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 c51e1850338ff..487b2f20792b9 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -66,7 +66,6 @@ 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 7f0e86b9294da..8e89503a8a76b 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/DWARFExpressionList.h" +#include "lldb/Expression/DWARFExpression.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" @@ -127,20 +127,22 @@ bool ValueObjectVariable::UpdateValue() { m_error.Clear(); Variable *variable = m_variable_sp.get(); - DWARFExpressionList &expr_list = variable->LocationExpressionList(); + DWARFExpression &expr = variable->LocationExpression(); if (variable->GetLocationIsConstantValueData()) { // expr doesn't contain DWARF bytes, it contains the constant variable // value bytes themselves... - if (expr_list.GetExpressionData(m_data)) { - if (m_data.GetDataStart() && m_data.GetByteSize()) + if (expr.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(); @@ -149,8 +151,17 @@ 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_list.Evaluate(&exe_ctx, nullptr, nullptr, nullptr, m_value, &m_error)) { + if (expr.Evaluate(&exe_ctx, nullptr, loclist_base_load_addr, nullptr, + nullptr, m_value, &m_error)) { m_resolved_value = m_value; m_value.SetContext(Value::ContextType::Variable, variable); @@ -235,7 +246,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 54414fb2a7c4f..c935e1b1c04b9 100644 --- a/lldb/source/Expression/CMakeLists.txt +++ b/lldb/source/Expression/CMakeLists.txt @@ -1,7 +1,6 @@ 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 fff5f60bc3abf..1f11907dc64c4 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -45,10 +45,29 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::dwarf; -// DWARFExpression constructor -DWARFExpression::DWARFExpression() : m_data() {} +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::DWARFExpression(const DataExtractor &data) : m_data(data) {} +// 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; +} // Destructor DWARFExpression::~DWARFExpression() = default; @@ -67,19 +86,71 @@ void DWARFExpression::UpdateValue(uint64_t const_value, m_data.SetAddressByteSize(addr_byte_size); } -void DWARFExpression::DumpLocation(Stream *s, lldb::DescriptionLevel level, +void DWARFExpression::DumpLocation(Stream *s, const DataExtractor &data, + lldb::DescriptionLevel level, ABI *abi) const { - llvm::DWARFExpression(m_data.GetAsLLVM(), m_data.GetAddressByteSize()) + llvm::DWARFExpression(data.GetAsLLVM(), data.GetAddressByteSize()) .print(s->AsRawOstream(), llvm::DIDumpOptions(), abi ? &abi->GetMCRegisterInfo() : nullptr, nullptr); } -RegisterKind DWARFExpression::GetRegisterKind() const { return m_reg_kind; } +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; } 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, @@ -338,10 +409,11 @@ static offset_t GetOpcodeDataSize(const DataExtractor &data, return LLDB_INVALID_OFFSET; } -lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu, - uint32_t op_addr_idx, +lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(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)) { @@ -351,18 +423,19 @@ lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu, const lldb::addr_t op_file_addr = m_data.GetAddress(&offset); if (curr_op_addr_idx == op_addr_idx) return op_file_addr; - ++curr_op_addr_idx; + else + ++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 (!dwarf_cu) { + if (!m_dwarf_cu) { error = true; break; } - return dwarf_cu->ReadAddressFromDebugAddrSection(index); - } - ++curr_op_addr_idx; + return ReadAddressFromDebugAddrSection(m_dwarf_cu, index); + } else + ++curr_op_addr_idx; } else { const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); if (op_arg_size == LLDB_INVALID_OFFSET) { @@ -376,6 +449,8 @@ lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu, } 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); @@ -412,6 +487,11 @@ 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); @@ -421,18 +501,27 @@ bool DWARFExpression::ContainsThreadLocalStorage() const { const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); if (op_arg_size == LLDB_INVALID_OFFSET) return false; - offset += op_arg_size; + else + 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(), @@ -504,10 +593,42 @@ 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, @@ -703,9 +824,10 @@ 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 DWARFExpressionList ¶m_expr = matched_param->LocationInCaller; + const DWARFExpression ¶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, @@ -717,6 +839,63 @@ 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 @@ -2491,7 +2670,7 @@ bool DWARFExpression::Evaluate( return false; } uint64_t index = opcodes.GetULEB128(&offset); - lldb::addr_t value = dwarf_cu->ReadAddressFromDebugAddrSection(index); + lldb::addr_t value = ReadAddressFromDebugAddrSection(dwarf_cu, index); stack.push_back(Scalar(value)); stack.back().SetValueType(Value::ValueType::FileAddress); } break; @@ -2511,7 +2690,7 @@ bool DWARFExpression::Evaluate( return false; } uint64_t index = opcodes.GetULEB128(&offset); - lldb::addr_t value = dwarf_cu->ReadAddressFromDebugAddrSection(index); + lldb::addr_t value = ReadAddressFromDebugAddrSection(dwarf_cu, index); stack.push_back(Scalar(value)); } break; @@ -2564,16 +2743,61 @@ bool DWARFExpression::Evaluate( return true; // Return true on success } -bool DWARFExpression::ParseDWARFLocationList( - const DWARFUnit *dwarf_cu, const DataExtractor &data, - DWARFExpressionList *location_list) { - location_list->Clear(); - std::unique_ptr loctable_up = - dwarf_cu->GetLocationTable(data); +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); + + std::unique_ptr loctable_up = + m_dwarf_cu->GetLocationTable(m_data); + + uint64_t offset = 0; auto lookup_addr = [&](uint32_t index) -> llvm::Optional { - addr_t address = dwarf_cu->ReadAddressFromDebugAddrSection(index); + addr_t address = ReadAddressFromDebugAddrSection(m_dwarf_cu, index); if (address == LLDB_INVALID_ADDRESS) return llvm::None; return llvm::object::SectionedAddress{address}; @@ -2583,17 +2807,18 @@ bool DWARFExpression::ParseDWARFLocationList( LLDB_LOG_ERROR(log, loc.takeError(), "{0}"); return true; } - 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; + 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); }; llvm::Error error = loctable_up->visitAbsoluteLocationList( - 0, llvm::object::SectionedAddress{dwarf_cu->GetBaseAddress()}, + offset, llvm::object::SectionedAddress{m_loclist_addresses->cu_file_addr}, lookup_addr, process_list); - location_list->Sort(); if (error) { LLDB_LOG_ERROR(log, std::move(error), "{0}"); return false; @@ -2601,8 +2826,23 @@ bool DWARFExpression::ParseDWARFLocationList( return true; } -bool DWARFExpression::MatchesOperand( - StackFrame &frame, const Instruction::Operand &operand) const { +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) { using namespace OperandMatchers; RegisterContextSP reg_ctx_sp = frame.GetRegisterContext(); @@ -2610,7 +2850,28 @@ bool DWARFExpression::MatchesOperand( return false; } - DataExtractor opcodes(m_data); + 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; + lldb::offset_t op_offset = 0; uint8_t opcode = opcodes.GetU8(&op_offset); @@ -2618,7 +2879,7 @@ bool DWARFExpression::MatchesOperand( if (opcode == DW_OP_fbreg) { int64_t offset = opcodes.GetSLEB128(&op_offset); - DWARFExpressionList *fb_expr = frame.GetFrameBaseExpression(nullptr); + DWARFExpression *fb_expr = frame.GetFrameBaseExpression(nullptr); if (!fb_expr) { return false; } diff --git a/lldb/source/Expression/DWARFExpressionList.cpp b/lldb/source/Expression/DWARFExpressionList.cpp deleted file mode 100644 index 68e3e8c611b9f..0000000000000 --- a/lldb/source/Expression/DWARFExpressionList.cpp +++ /dev/null @@ -1,219 +0,0 @@ -//===-- 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) { - if (error_ptr) - error_ptr->SetErrorString("variable not available"); - 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 965a96b7f909d..9ee2d983ddfc6 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->LocationExpressionList().IsValid()) { + !m_variable_sp->LocationExpression().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 6fb7d92244f90..cc45871bcd71a 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -1485,14 +1485,15 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var, return false; } - DWARFExpressionList &var_location_list = var->LocationExpressionList(); + DWARFExpression &var_location_expr = var->LocationExpression(); Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); Status err; if (var->GetLocationIsConstantValueData()) { DataExtractor const_value_extractor; - if (var_location_list.GetExpressionData(const_value_extractor)) { + + if (var_location_expr.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 4b9354371bda3..2aacac3692be5 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; - DWARFExpressionList frame_base; + DWARFExpression 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 06cdd877f7dcd..ec074be581b54 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::DWARFExpressionList *frame_base) const { + lldb_private::DWARFExpression *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 7ce9550a081e9..5ee44a7632049 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -85,12 +85,11 @@ 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::DWARFExpressionList *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::DWARFExpression *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 c1d49c5f23d7c..95c0cb6472c59 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -231,10 +231,11 @@ 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, - DWARFExpressionList *frame_base) const { + DWARFExpression *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); @@ -344,17 +345,21 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges( uint32_t block_offset = form_value.BlockData() - data.GetDataStart(); uint32_t block_length = form_value.Unsigned(); - *frame_base = - DWARFExpressionList(module, - DWARFExpression(DataExtractor( - data, block_offset, block_length)), - cu); + *frame_base = DWARFExpression( + module, 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); - DWARFExpression::ParseDWARFLocationList(cu, data, frame_base); + *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; + } } } } @@ -376,6 +381,12 @@ 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 32f653e99a705..64e86c71ac09e 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::DWARFExpressionList *frame_base = nullptr) const; + lldb_private::DWARFExpression *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 7b4a5d8eca3ed..903cd2e38f769 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -579,17 +579,6 @@ 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 40a1943b847a0..265e28b51c991 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -166,8 +166,6 @@ 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 ab61a699c3edf..c0bf13e0281d3 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -9,7 +9,6 @@ #include "SymbolFileDWARF.h" #include "llvm/ADT/Optional.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Threading.h" @@ -1886,13 +1885,11 @@ 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 DWARFExpressionList &location = - var_sp->LocationExpressionList(); + const DWARFExpression &location = var_sp->LocationExpression(); Value location_result; Status error; - ExecutionContext exe_ctx; - if (location.Evaluate(&exe_ctx, nullptr, nullptr, nullptr, - location_result, &error)) { + if (location.Evaluate(nullptr, LLDB_INVALID_ADDRESS, nullptr, + nullptr, location_result, &error)) { if (location_result.GetValueType() == Value::ValueType::FileAddress) { lldb::addr_t file_addr = @@ -3166,7 +3163,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, const char *mangled = nullptr; Declaration decl; DWARFFormValue type_die_form; - DWARFExpressionList location_list(module, DWARFExpression(), die.GetCU()); + DWARFExpression location; bool is_external = false; bool is_artificial = false; DWARFFormValue const_value_form, location_form; @@ -3232,15 +3229,16 @@ 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 = location_form.IsValid(); + bool has_explicit_location = false; 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_list = DWARFExpressionList( + location = DWARFExpression( module, DataExtractor(data, block_offset, block_length), die.GetCU()); } else { DataExtractor data = die.GetCU()->GetLocationData(); @@ -3249,8 +3247,10 @@ 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); - const DWARFUnit *dwarf_cu = location_form.GetUnit(); - DWARFExpression::ParseDWARFLocationList(dwarf_cu, data, &location_list); + location = DWARFExpression(module, data, die.GetCU()); + assert(func_low_pc != LLDB_INVALID_ADDRESS); + location.SetLocationListAddresses( + location_form.GetUnit()->GetBaseAddress(), func_low_pc); } } } 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_list = DWARFExpressionList( + location = DWARFExpression( 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_list = DWARFExpressionList( + location = DWARFExpression( module, DataExtractor(str, string_length, die.GetCU()->GetByteOrder(), die.GetCU()->GetAddressByteSize()), @@ -3323,19 +3323,16 @@ 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_list.IsValid()); + has_explicit_mangled || (has_explicit_location && !location.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; - const DWARFExpression* location = location_list.GetAlwaysValidExpr(); - if (location) - location_DW_OP_addr = location->GetLocation_DW_OP_addr( - location_form.GetUnit(), 0, op_error); + location_DW_OP_addr = location.GetLocation_DW_OP_addr(0, op_error); if (op_error) { StreamString strm; - location->DumpLocation(&strm, eDescriptionLevelFull, nullptr); + location.DumpLocationForAddress(&strm, eDescriptionLevelFull, 0, 0, + nullptr); GetObjectFile()->GetModule()->ReportError( "0x%8.8x: %s has an invalid location: %s", die.GetOffset(), die.GetTagAsCString(), strm.GetData()); @@ -3348,7 +3345,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_list.SetModule(debug_map_symfile->GetObjectFile()->GetModule()); + location.SetModule(debug_map_symfile->GetObjectFile()->GetModule()); if (is_static_lifetime) { if (is_external) @@ -3389,9 +3386,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, const addr_t exe_file_addr = exe_symbol->GetAddressRef().GetFileAddress(); if (exe_file_addr != LLDB_INVALID_ADDRESS) { - DWARFExpression *location = - location_list.GetMutableExpressionAtAddress(); - if (location->Update_DW_OP_addr(exe_file_addr)) { + if (location.Update_DW_OP_addr(exe_file_addr)) { linked_oso_file_addr = true; symbol_context_scope = exe_symbol; } @@ -3409,9 +3404,7 @@ 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 - DWARFExpression *location = - location_list.GetMutableExpressionAtAddress(); - location->Update_DW_OP_addr(exe_file_addr); + location.Update_DW_OP_addr(exe_file_addr); } else { // Variable didn't make it into the final executable return nullptr; @@ -3426,8 +3419,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_list.ContainsThreadLocalStorage()) { - location_list.LinkThreadLocalStorage( + if (location.ContainsThreadLocalStorage()) { + location.LinkThreadLocalStorage( debug_map_symfile->GetObjectFile()->GetModule(), [this, debug_map_symfile]( lldb::addr_t unlinked_file_addr) -> lldb::addr_t { @@ -3470,17 +3463,14 @@ 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()) { - DWARFExpression *location = location_list.GetMutableExpressionAtAddress(); - location->UpdateValue( - const_value_form.Unsigned(), - type_sp->GetType()->GetByteSize(nullptr).getValueOr(0), - die.GetCU()->GetAddressByteSize()); - } + 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()); return std::make_shared( die.GetID(), name, mangled, type_sp, scope, symbol_context_scope, - scope_ranges, &decl, location_list, is_external, is_artificial, + scope_ranges, &decl, location, is_external, is_artificial, location_is_const_value_data, is_static_member); } @@ -3765,8 +3755,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); @@ -3774,7 +3764,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 {}; @@ -3783,9 +3773,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 DWARFExpressionList( - module, DataExtractor(data, block_offset, block_length), - child.GetCU()); + return DWARFExpression(module, + DataExtractor(data, block_offset, block_length), + child.GetCU()); }; for (size_t i = 0; i < num_attributes; ++i) { @@ -3830,7 +3820,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; @@ -3891,7 +3881,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 = DWARFExpressionList( + call_target = DWARFExpression( 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 cfd18f02053b4..2403ee2624ea1 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -21,7 +21,6 @@ #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 3166c8ae65c6c..3ba0079c96e6a 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(extractor); + DWARFExpression result(module, extractor, nullptr); 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(extractor); + DWARFExpression result(nullptr, extractor, nullptr); return result; } diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index d94ba6b3531a6..7dc99818c2443 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -823,10 +823,8 @@ VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) { m_ast->GetOrCreateVariableDecl(var_id); - ModuleSP module_sp = GetObjectFile()->GetModule(); - DWARFExpressionList location( - module_sp, MakeGlobalLocationExpression(section, offset, module_sp), - nullptr); + DWARFExpression location = MakeGlobalLocationExpression( + section, offset, GetObjectFile()->GetModule()); std::string global_name("::"); global_name += name; @@ -857,10 +855,8 @@ SymbolFileNativePDB::CreateConstantSymbol(PdbGlobalSymId var_id, Declaration decl; Variable::RangeList ranges; ModuleSP module = GetObjectFile()->GetModule(); - DWARFExpressionList location(module, - MakeConstantLocationExpression( - constant.Type, tpi, constant.Value, module), - nullptr); + DWARFExpression location = MakeConstantLocationExpression( + constant.Type, tpi, constant.Value, module); bool external = false; bool artificial = false; @@ -1715,8 +1711,7 @@ 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, - DWARFExpressionList(module, *var_info.location, nullptr), external, + &block, *var_info.ranges, &decl, *var_info.location, 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 94023737b2a2e..96e9de704e414 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(extractor); + DWARFExpression result(module, extractor, nullptr); 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 baa48532864bb..bd3d16aad6c2e 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -1023,11 +1023,8 @@ VariableSP SymbolFilePDB::ParseVariableForPDBData( auto mangled_cstr = mangled.empty() ? nullptr : mangled.c_str(); bool is_constant; - ModuleSP module_sp = GetObjectFile()->GetModule(); - DWARFExpressionList location(module_sp, - ConvertPDBLocationToDWARFExpression( - module_sp, pdb_data, ranges, is_constant), - nullptr); + DWARFExpression location = ConvertPDBLocationToDWARFExpression( + GetObjectFile()->GetModule(), pdb_data, ranges, is_constant); 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 54c562eb1bdd9..648a12524aed1 100644 --- a/lldb/source/Symbol/Function.cpp +++ b/lldb/source/Symbol/Function.cpp @@ -197,6 +197,7 @@ 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 285e32d21ce23..b92c866544969 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 DWARFExpressionList &location_list, bool external, + const DWARFExpression &location, 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_list(location_list), m_external(external), + m_declaration(decl_ptr), m_location(location), 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_list.IsValid()) { + if (m_location.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_list.GetDescription(s, lldb::eDescriptionLevelBrief, abi.get()); + m_location.GetDescription(s, lldb::eDescriptionLevelBrief, abi.get()); } if (m_external) @@ -212,8 +212,31 @@ void Variable::CalculateSymbolContext(SymbolContext *sc) { } bool Variable::LocationIsValidForFrame(StackFrame *frame) { - return m_location_list.ContainsAddress( - frame->GetFrameCodeAddress().GetFileAddress()); + // 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; } bool Variable::LocationIsValidForAddress(const Address &address) { @@ -221,7 +244,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( @@ -231,10 +254,22 @@ bool Variable::LocationIsValidForAddress(const Address &address) { SymbolContext sc; CalculateSymbolContext(&sc); if (sc.module_sp == address.GetModule()) { - // 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()); + // 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()); + } } } return false; @@ -419,8 +454,16 @@ bool Variable::DumpLocations(Stream *s, const Address &address) { } const addr_t file_addr = address.GetFileAddress(); - return m_location_list.DumpLocations(s, eDescriptionLevelBrief, file_addr, - abi.get()); + 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; } static void PrivateAutoComplete( diff --git a/lldb/source/Target/RegisterContextUnwind.cpp b/lldb/source/Target/RegisterContextUnwind.cpp index bca7eec5e939e..e98aed7e15552 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/DWARFExpressionList.h" +#include "lldb/Expression/DWARFExpression.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; - DWARFExpressionList dwarfexpr(opcode_ctx, dwarfdata, nullptr); - dwarfexpr.GetMutableExpressionAtAddress()->SetRegisterKind( - unwindplan_registerkind); + DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr); + dwarfexpr.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, &cfa_val, nullptr, result, &error)) { + if (dwarfexpr.Evaluate(&exe_ctx, this, 0, &cfa_val, nullptr, result, + &error)) { addr_t val; val = result.GetScalar().ULongLong(); if (unwindplan_regloc.IsDWARFExpression()) { @@ -2006,12 +2006,11 @@ bool RegisterContextUnwind::ReadFrameAddress( process->GetByteOrder(), process->GetAddressByteSize()); ModuleSP opcode_ctx; - DWARFExpressionList dwarfexpr(opcode_ctx, dwarfdata, nullptr); - dwarfexpr.GetMutableExpressionAtAddress()->SetRegisterKind( - row_register_kind); + DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr); + dwarfexpr.SetRegisterKind(row_register_kind); Value result; Status error; - if (dwarfexpr.Evaluate(&exe_ctx, this, nullptr, nullptr, result, + if (dwarfexpr.Evaluate(&exe_ctx, this, 0, 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 28c8dfde72a8d..1e3dbc73a04ed 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -1086,9 +1086,15 @@ 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, nullptr, nullptr, expr_value, - &m_frame_base_error)) { + &exe_ctx, nullptr, loclist_base_addr, 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()) @@ -1110,7 +1116,7 @@ bool StackFrame::GetFrameBaseValue(Scalar &frame_base, Status *error_ptr) { return m_frame_base_error.Success(); } -DWARFExpressionList *StackFrame::GetFrameBaseExpression(Status *error_ptr) { +DWARFExpression *StackFrame::GetFrameBaseExpression(Status *error_ptr) { if (!m_sc.function) { if (error_ptr) { error_ptr->SetErrorString("No function in symbol context."); @@ -1194,7 +1200,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(); @@ -1411,7 +1417,7 @@ ValueObjectSP GetValueForDereferincingOffset(StackFrame &frame, Status error; ValueObjectSP pointee = base->Dereference(error); - + if (!pointee) { return ValueObjectSP(); } @@ -1499,7 +1505,7 @@ lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg, Instruction::Operand::BuildRegister(reg)); for (VariableSP var_sp : variables) { - if (var_sp->LocationExpressionList().MatchesOperand(frame, op)) + if (var_sp->LocationExpression().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 f8e8bfba970f0..2daf816d300c8 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 +# CHECK: Variable{{.*}}, name = "x2", {{.*}}, scope = parameter, location = 0x00000000: error: unexpected end of data # CHECK: Variable{{.*}}, name = "x3", {{.*}}, scope = parameter, location = # CHECK-NEXT: [0x0000000000000002, 0x0000000000000003): DW_OP_reg1 RDX -# LOCLISTS: Variable{{.*}}, name = "x4", {{.*}}, scope = parameter -# LOCLISTS-EMPTY: +# LOCLISTS: Variable{{.*}}, name = "x4", {{.*}}, scope = parameter, location = +# LOCLISTS-NEXT: DW_LLE_startx_length (0x000000000000dead, 0x0000000000000001): DW_OP_reg2 RCX .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 c8eead3d28d29..a921641bcec54 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: [0x0000000000000000, 0x0000000000000001): DW_OP_reg0 RAX +# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location = +# SYMBOLS-NEXT: DW_LLE_startx_length (0x0000000000000001, 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: [0x0000000000000001, 0x0000000000000002): DW_OP_reg1 RDX +# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location = +# SYMBOLS-NEXT: DW_LLE_startx_length (0x0000000000000003, 0x0000000000000001): 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: [0x0000000000000002, 0x0000000000000003): DW_OP_reg2 RCX +# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location = +# SYMBOLS-NEXT: DW_LLE_startx_length (0x0000000000000005, 0x0000000000000001): 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: [0x0000000000000003, 0x0000000000000004): DW_OP_reg3 RBX +# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location = +# SYMBOLS-NEXT: DW_LLE_startx_length (0x0000000000000007, 0x0000000000000001): 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 62d7335384216..f58874f794eec 100644 --- a/llvm/utils/gn/secondary/lldb/source/Expression/BUILD.gn +++ b/llvm/utils/gn/secondary/lldb/source/Expression/BUILD.gn @@ -23,7 +23,6 @@ static_library("Expression") { include_dirs = [ ".." ] sources = [ "DWARFExpression.cpp", - "DWARFExpressionList.cpp", "DiagnosticManager.cpp", "Expression.cpp", "ExpressionVariable.cpp",