Author: Zequan Wu Date: 2022-07-12T10:54:24-07:00 New Revision: b74a01a80b72f581c68d336b0de5ed9757efbaa8
URL: https://github.com/llvm/llvm-project/commit/b74a01a80b72f581c68d336b0de5ed9757efbaa8 DIFF: https://github.com/llvm/llvm-project/commit/b74a01a80b72f581c68d336b0de5ed9757efbaa8.diff LOG: Reland "[LLDB][NFC] Decouple dwarf location table from DWARFExpression." This reland 227dffd0b6d78154516ace45f6ed28259c7baa48 and 562c3467a6738aa89203f72fc1d1343e5baadf3c with failed api tests fixed by keeping function base file addres in DWARFExpressionList. Added: lldb/include/lldb/Expression/DWARFExpressionList.h lldb/source/Expression/DWARFExpressionList.cpp Modified: lldb/include/lldb/Expression/DWARFExpression.h lldb/include/lldb/Symbol/Function.h lldb/include/lldb/Symbol/Variable.h lldb/include/lldb/Target/StackFrame.h lldb/include/lldb/Utility/RangeMap.h lldb/include/lldb/lldb-forward.h lldb/source/Core/ValueObjectVariable.cpp lldb/source/Expression/CMakeLists.txt lldb/source/Expression/DWARFExpression.cpp lldb/source/Expression/Materializer.cpp lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp lldb/source/Symbol/Function.cpp lldb/source/Symbol/Variable.cpp lldb/source/Target/RegisterContextUnwind.cpp lldb/source/Target/StackFrame.cpp lldb/test/Shell/SymbolFile/DWARF/x86/debug_loc.s lldb/test/Shell/SymbolFile/DWARF/x86/dwp.s llvm/utils/gn/secondary/lldb/source/Expression/BUILD.gn Removed: ################################################################################ diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h index 96a0e8e02da1..49e51d51f211 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<lldb::addr_t(lldb::addr_t file_addr)> 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<bool(llvm::DWARFLocationExpression)> callback) const; + void DumpLocation(Stream *s, lldb::DescriptionLevel level, ABI *abi) const; - bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op); - - llvm::Optional<DataExtractor> - 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<LoclistAddresses> 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 000000000000..a8f2a7126e3c --- /dev/null +++ b/lldb/include/lldb/Expression/DWARFExpressionList.h @@ -0,0 +1,151 @@ +//===-- 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, + lldb::addr_t func_file_addr) + : m_module_wp(module_sp), m_dwarf_cu(dwarf_cu), + m_func_file_addr(func_file_addr) {} + + DWARFExpressionList(lldb::ModuleSP module_sp, DWARFExpression expr, + const DWARFUnit *dwarf_cu) + : m_module_wp(module_sp), m_dwarf_cu(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 func_load_addr = LLDB_INVALID_ADDRESS, + lldb::addr_t file_addr = 0) const; + + /// Sort m_expressions. + void Sort() { m_exprs.Sort(); } + + void SetFuncFileAddress(lldb::addr_t func_file_addr) { + m_func_file_addr = func_file_addr; + } + + lldb::addr_t GetFuncFileAddress() { return m_func_file_addr; } + + const DWARFExpression *GetExpressionAtAddress(lldb::addr_t func_load_addr, + lldb::addr_t load_addr) const; + + const DWARFExpression *GetAlwaysValidExpr() const; + + DWARFExpression *GetMutableExpressionAtAddress( + lldb::addr_t func_load_addr = LLDB_INVALID_ADDRESS, + lldb::addr_t load_addr = 0); + + size_t GetSize() const { return m_exprs.GetSize(); } + + bool ContainsThreadLocalStorage() const; + + bool LinkThreadLocalStorage( + lldb::ModuleSP new_module_sp, + std::function<lldb::addr_t(lldb::addr_t file_addr)> 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 func_load_addr, 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 dwarf 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 ContainsAddress(lldb::addr_t func_load_addr, lldb::addr_t addr) const; + + void SetModule(const lldb::ModuleSP &module) { m_module_wp = module; } + + bool 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; + +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<lldb::addr_t, lldb::addr_t, DWARFExpression, + 0, DWARFExpressionCompare>; + 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; + + // Function base file address. + lldb::addr_t m_func_file_addr = LLDB_INVALID_ADDRESS; + + 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 83f9979c3c52..3eb4f5d7dedf 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 88a975df3992..c437624d1ea6 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> { 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<Variable> { 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<Variable> { 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 1b0485b22cac..7c4340de4de0 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 7eb0cab8084c..257b177c7092 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 487b2f20792b..c51e1850338f 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 8e89503a8a76..4e2bd12c1053 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,17 +127,16 @@ 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); @@ -151,7 +150,7 @@ bool ValueObjectVariable::UpdateValue() { m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); } - if (expr.IsLocationList()) { + if (!expr_list.IsAlwaysValidSingleExpr()) { SymbolContext sc; variable->CalculateSymbolContext(&sc); if (sc.function) @@ -160,8 +159,8 @@ bool ValueObjectVariable::UpdateValue() { 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, loclist_base_load_addr, nullptr, + nullptr, m_value, &m_error)) { m_resolved_value = m_value; m_value.SetContext(Value::ContextType::Variable, variable); @@ -246,7 +245,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 c935e1b1c04b..54414fb2a7c4 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 1f11907dc64c..9e6b21fc25ea 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<llvm::RelocAddrEntry> 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<llvm::DWARFLocationTable> 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<lldb::addr_t(lldb::addr_t file_addr)> 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<DataExtractor> expr = - GetLocationExpression(func_load_addr, address)) { - DumpLocation(s, *expr, level, abi); - return true; - } - return false; -} - static bool Evaluate_DW_OP_entry_value(std::vector<Value> &stack, ExecutionContext *exe_ctx, RegisterContext *reg_ctx, @@ -824,10 +703,10 @@ static bool Evaluate_DW_OP_entry_value(std::vector<Value> &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, + LLDB_INVALID_ADDRESS, /*initial_value_ptr=*/nullptr, /*object_address_ptr=*/nullptr, result, error_ptr)) { LLDB_LOG(log, @@ -839,63 +718,6 @@ static bool Evaluate_DW_OP_entry_value(std::vector<Value> &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<DataExtractor> 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 +2492,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 +2512,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 +2565,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<DataBufferHeap>(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<bool(llvm::DWARFLocationExpression)> 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<llvm::DWARFLocationTable> 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<llvm::object::SectionedAddress> { - 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 +2584,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 diff erence 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<DataBufferHeap>(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 +2602,8 @@ bool DWARFExpression::GetLocationExpressions( return true; } -llvm::Optional<DataExtractor> -DWARFExpression::GetLocationExpression(addr_t load_function_start, - addr_t addr) const { - llvm::Optional<DataExtractor> 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 +2611,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<DataExtractor> 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 +2619,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 000000000000..5cf722c42fa9 --- /dev/null +++ b/lldb/source/Expression/DWARFExpressionList.cpp @@ -0,0 +1,248 @@ +//===-- 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 { + return GetAlwaysValidExpr() != nullptr; +} + +const DWARFExpression * DWARFExpressionList::GetAlwaysValidExpr() const { + if (m_exprs.GetSize() != 1) + return nullptr; + const auto *expr = m_exprs.GetEntryAtIndex(0); + if (expr->base == 0 && expr->size == LLDB_INVALID_ADDRESS) + return &expr->data; + return nullptr; +} + +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 func_load_addr, + lldb::addr_t file_addr) const { + if (const DWARFExpression *expr = + GetExpressionAtAddress(func_load_addr, file_addr)) + return expr->GetExpressionData(data); + return false; +} + +bool DWARFExpressionList::ContainsAddress(lldb::addr_t func_load_addr, + lldb::addr_t addr) const { + if (IsAlwaysValidSingleExpr()) + return true; + return GetExpressionAtAddress(func_load_addr, addr) != nullptr; +} + +const DWARFExpression * +DWARFExpressionList::GetExpressionAtAddress(lldb::addr_t func_load_addr, + lldb::addr_t load_addr) const { + if (const DWARFExpression *expr = GetAlwaysValidExpr()) + return expr; + if (func_load_addr == LLDB_INVALID_ADDRESS) + func_load_addr = m_func_file_addr; + addr_t addr = load_addr - func_load_addr + m_func_file_addr; + uint32_t index = m_exprs.FindEntryIndexThatContains(addr); + if (index == UINT32_MAX) + return nullptr; + return &m_exprs.GetEntryAtIndex(index)->data; +} + +DWARFExpression * +DWARFExpressionList::GetMutableExpressionAtAddress(lldb::addr_t func_load_addr, + lldb::addr_t load_addr) { + if (IsAlwaysValidSingleExpr()) + return &m_exprs.GetMutableEntryAtIndex(0)->data; + if (func_load_addr == LLDB_INVALID_ADDRESS) + func_load_addr = m_func_file_addr; + addr_t addr = load_addr - func_load_addr + m_func_file_addr; + uint32_t index = m_exprs.FindEntryIndexThatContains(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<lldb::addr_t(lldb::addr_t file_addr)> 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(LLDB_INVALID_ADDRESS, pc); + } + if (!expr) + return false; + return expr->MatchesOperand(frame, operand); +} + +bool DWARFExpressionList::DumpLocations(Stream *s, lldb::DescriptionLevel level, + lldb::addr_t func_load_addr, + lldb::addr_t file_addr, + ABI *abi) const { + llvm::raw_ostream &os = s->AsRawOstream(); + llvm::ListSeparator separator; + if (const DWARFExpression *expr = GetAlwaysValidExpr()) { + expr->DumpLocation(s, level, abi); + return true; + } + for (const Entry &entry : *this) { + addr_t load_base = entry.GetRangeBase() + func_load_addr - m_func_file_addr; + addr_t load_end = entry.GetRangeEnd() + func_load_addr - m_func_file_addr; + if (file_addr != LLDB_INVALID_ADDRESS && + (file_addr < load_base || file_addr >= load_end)) + continue; + const auto &expr = entry.data; + DataExtractor data; + expr.GetExpressionData(data); + uint32_t addr_size = data.GetAddressByteSize(); + + os << separator; + os << "["; + os << llvm::format_hex(load_base, 2 + 2 * addr_size); + os << ", "; + os << llvm::format_hex(load_end, 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, + 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(); + 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 pc_load_addr = pc.GetLoadAddress(exe_ctx->GetTargetPtr()); + const DWARFExpression *entry = + GetExpressionAtAddress(func_load_addr, pc_load_addr); + if (!entry) { + if (error_ptr) { + error_ptr->SetErrorString("variable not available"); + } + return false; + } + expr = *entry; + } + 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 9ee2d983ddfc..965a96b7f909 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 0bef688e1cf5..4305a9982343 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -1437,15 +1437,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 2aacac3692be..4b9354371bda 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 ec074be581b5..06cdd877f7dc 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 5ee44a763204..7ce9550a081e 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<child_iterator> children() const; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index 95c0cb6472c5..c98953640a58 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -231,7 +231,7 @@ 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<DWARFDIE> dies; @@ -345,21 +345,22 @@ 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 { + DWARFExpression::ParseDWARFLocationList(cu, data, frame_base); + frame_base->SetFuncFileAddress(lo_pc); + } else set_frame_base_loclist_addr = true; - } } } } @@ -384,7 +385,7 @@ 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); + frame_base->SetFuncFileAddress(lowest_range_pc); } if (ranges.IsEmpty() || name == nullptr || mangled == nullptr) { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h index 64e86c71ac09..32f653e99a70 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 903cd2e38f76..7b4a5d8eca3e 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 265e28b51c99..40a1943b847a 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 c0bf13e0281d..cbc24b1550c7 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,14 @@ 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, LLDB_INVALID_ADDRESS, + nullptr, nullptr, location_result, + &error)) { if (location_result.GetValueType() == Value::ValueType::FileAddress) { lldb::addr_t file_addr = @@ -3163,7 +3167,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 +3233,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 +3250,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); - 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(); + if (DWARFExpression::ParseDWARFLocationList(dwarf_cu, data, + &location_list)) + location_list.SetFuncFileAddress(func_low_pc); } } } else if (const_value_form.IsValid()) { @@ -3263,7 +3266,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 +3276,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 +3326,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 +3351,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 +3392,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 +3412,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 +3429,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 +3473,17 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, auto type_sp = std::make_shared<SymbolFileType>( *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<Variable>( 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 +3768,8 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) { child.Tag() != DW_TAG_GNU_call_site_parameter) continue; - llvm::Optional<DWARFExpression> LocationInCallee; - llvm::Optional<DWARFExpression> LocationInCaller; + llvm::Optional<DWARFExpressionList> LocationInCallee; + llvm::Optional<DWARFExpressionList> LocationInCaller; DWARFAttributes attributes; const size_t num_attributes = child.GetAttributes(attributes); @@ -3764,7 +3777,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<DWARFExpression> { + [&](int attr_index) -> llvm::Optional<DWARFExpressionList> { DWARFFormValue form_value; if (!attributes.ExtractFormValueAtIndex(attr_index, form_value)) return {}; @@ -3773,9 +3786,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 +3833,7 @@ SymbolFileDWARF::CollectCallEdges(ModuleSP module, DWARFDIE function_die) { continue; llvm::Optional<DWARFDIE> call_origin; - llvm::Optional<DWARFExpression> call_target; + llvm::Optional<DWARFExpressionList> 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 +3894,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 2403ee2624ea..cfd18f02053b 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 3ba0079c96e6..3166c8ae65c6 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<DataBufferHeap>(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/PdbUtil.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp index 7bb7c69eece7..6317b140f7e8 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp @@ -602,7 +602,7 @@ static RegisterId GetBaseFrameRegister(PdbIndex &index, } VariableInfo lldb_private::npdb::GetVariableLocationInfo( - PdbIndex &index, PdbCompilandSymId var_id, Block &block, + PdbIndex &index, PdbCompilandSymId var_id, Block &func_block, lldb::ModuleSP module) { CVSymbol sym = index.ReadSymbolRecord(var_id); @@ -642,14 +642,8 @@ VariableInfo lldb_private::npdb::GetVariableLocationInfo( Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps); - // TODO: may be better to pass function scope and not lookup it every - // time? find nearest parent function block - Block *cur = █ - while (cur->GetParent()) { - cur = cur->GetParent(); - } PdbCompilandSymId func_scope_id = - PdbSymUid(cur->GetID()).asCompilandSym(); + PdbSymUid(func_block.GetID()).asCompilandSym(); CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id); lldbassert(func_block_cvs.kind() == S_GPROC32 || func_block_cvs.kind() == S_LPROC32); diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h index 138c11aaeb43..066bcc89fd3b 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h @@ -142,8 +142,8 @@ LookThroughModifierRecord(llvm::codeview::CVType modifier); llvm::StringRef DropNameScope(llvm::StringRef name); VariableInfo GetVariableNameInfo(llvm::codeview::CVSymbol symbol); -VariableInfo GetVariableLocationInfo(PdbIndex &index, PdbCompilandSymId var_id, Block& block, - lldb::ModuleSP module); +VariableInfo GetVariableLocationInfo(PdbIndex &index, PdbCompilandSymId var_id, + Block &func_block, lldb::ModuleSP module); size_t GetTypeSizeForSimpleKind(llvm::codeview::SimpleTypeKind kind); lldb::BasicType diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index 7dc99818c244..7e10e315be20 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; @@ -1689,8 +1693,15 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id, bool is_param) { ModuleSP module = GetObjectFile()->GetModule(); Block &block = GetOrCreateBlock(scope_id); + // Get function block. + Block *func_block = █ + while (func_block->GetParent()) { + func_block = func_block->GetParent(); + } + Address addr; + func_block->GetStartAddress(addr); VariableInfo var_info = - GetVariableLocationInfo(*m_index, var_id, block, module); + GetVariableLocationInfo(*m_index, var_id, *func_block, module); if (!var_info.location || !var_info.ranges) return nullptr; @@ -1709,11 +1720,12 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id, bool artificial = false; bool location_is_constant_data = false; bool static_member = false; + DWARFExpressionList locaiton_list = DWARFExpressionList( + module, *var_info.location, nullptr); VariableSP var_sp = std::make_shared<Variable>( toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope, - &block, *var_info.ranges, &decl, *var_info.location, external, - artificial, location_is_constant_data, static_member); - + &block, *var_info.ranges, &decl, locaiton_list, external, artificial, + location_is_constant_data, static_member); if (!is_param) m_ast->GetOrCreateVariableDecl(scope_id, var_id); diff --git a/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp b/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp index 96e9de704e41..94023737b2a2 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<DataBufferHeap>(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 bd3d16aad6c2..baa48532864b 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<Variable>( 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 648a12524aed..bc9f7461323a 100644 --- a/lldb/source/Symbol/Function.cpp +++ b/lldb/source/Symbol/Function.cpp @@ -196,11 +196,10 @@ Function *IndirectCallEdge::GetCallee(ModuleList &images, Log *log = GetLog(LLDBLog::Step); 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)) { + if (!call_target.Evaluate( + &exe_ctx, exe_ctx.GetRegisterContext(), LLDB_INVALID_ADDRESS, + /*initial_value_ptr=*/nullptr, + /*object_address_ptr=*/nullptr, callee_addr_val, &error)) { LLDB_LOGF(log, "IndirectCallEdge: Could not evaluate expression: %s", error.AsCString()); return nullptr; diff --git a/lldb/source/Symbol/Variable.cpp b/lldb/source/Symbol/Variable.cpp index b92c86654496..f65e73e5d049 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,12 +212,6 @@ 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; @@ -231,7 +225,7 @@ bool Variable::LocationIsValidForFrame(StackFrame *frame) { 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( + return m_location_list.ContainsAddress( loclist_base_load_addr, frame->GetFrameCodeAddress().GetLoadAddress(target_sp.get())); } @@ -244,7 +238,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( @@ -255,7 +249,7 @@ bool Variable::LocationIsValidForAddress(const Address &address) { CalculateSymbolContext(&sc); if (sc.module_sp == address.GetModule()) { // Is the variable is described by a single location? - if (!m_location.IsLocationList()) { + if (m_location_list.IsAlwaysValidSingleExpr()) { // Yes it is, the location is valid. return true; } @@ -267,8 +261,8 @@ bool Variable::LocationIsValidForAddress(const Address &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 m_location_list.ContainsAddress(loclist_base_file_addr, + address.GetFileAddress()); } } } @@ -459,9 +453,9 @@ bool Variable::DumpLocations(Stream *s, const Address &address) { 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 m_location_list.DumpLocations(s, eDescriptionLevelBrief, + loclist_base_file_addr, file_addr, + abi.get()); } return false; } diff --git a/lldb/source/Target/RegisterContextUnwind.cpp b/lldb/source/Target/RegisterContextUnwind.cpp index e98aed7e1555..a0f97d7e7cff 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,8 +1642,9 @@ 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; @@ -2006,8 +2007,9 @@ 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, diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 1e3dbc73a04e..e87cf5af3e39 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -1087,7 +1087,7 @@ bool StackFrame::GetFrameBaseValue(Scalar &frame_base, Status *error_ptr) { ExecutionContext exe_ctx(shared_from_this()); Value expr_value; addr_t loclist_base_addr = LLDB_INVALID_ADDRESS; - if (m_sc.function->GetFrameBaseExpression().IsLocationList()) + if (!m_sc.function->GetFrameBaseExpression().IsAlwaysValidSingleExpr()) loclist_base_addr = m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress( exe_ctx.GetTargetPtr()); @@ -1116,7 +1116,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 +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(); @@ -1417,7 +1417,7 @@ ValueObjectSP GetValueForDereferincingOffset(StackFrame &frame, Status error; ValueObjectSP pointee = base->Dereference(error); - + if (!pointee) { return ValueObjectSP(); } @@ -1505,7 +1505,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 2daf816d300c..f8e8bfba970f 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 a921641bcec5..c8eead3d28d2 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 = "<not loaded>", 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 = "<not loaded>", 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 = "<not loaded>", 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 = "<not loaded>", 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 f58874f794ee..62d733538421 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", _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits