1 //===-- DWARFExpressionList.h -----------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_EXPRESSION_DWARFEXPRESSIONLIST_H
10 #define LLDB_EXPRESSION_DWARFEXPRESSIONLIST_H
11 
12 #include "lldb/Expression/DWARFExpression.h"
13 #include "lldb/Utility/RangeMap.h"
14 #include "lldb/lldb-private.h"
15 
16 class DWARFUnit;
17 
18 namespace lldb_private {
19 
20 /// \class DWARFExpressionList DWARFExpressionList.h
21 /// "lldb/Expression/DWARFExpressionList.h" Encapsulates a range map from file
22 /// address range to a single DWARF location expression.
23 class DWARFExpressionList {
24 public:
25   DWARFExpressionList() = default;
26 
27   DWARFExpressionList(lldb::ModuleSP module_sp, const DWARFUnit *dwarf_cu,
28                       lldb::addr_t func_file_addr)
29       : m_module_wp(module_sp), m_dwarf_cu(dwarf_cu),
30         m_func_file_addr(func_file_addr) {}
31 
32   DWARFExpressionList(lldb::ModuleSP module_sp, DWARFExpression expr,
33                       const DWARFUnit *dwarf_cu)
34       : m_module_wp(module_sp), m_dwarf_cu(dwarf_cu) {
35     AddExpression(0, LLDB_INVALID_ADDRESS, expr);
36   }
37 
38   /// Return true if the location expression contains data
39   bool IsValid() const { return !m_exprs.IsEmpty(); }
40 
41   void Clear() { m_exprs.Clear(); }
42 
43   // Return true if the location expression is always valid.
44   bool IsAlwaysValidSingleExpr() const;
45 
46   bool AddExpression(lldb::addr_t base, lldb::addr_t end, DWARFExpression expr);
47 
48   /// Get the expression data at the file address.
49   bool GetExpressionData(DataExtractor &data,
50                          lldb::addr_t func_load_addr = LLDB_INVALID_ADDRESS,
51                          lldb::addr_t file_addr = 0) const;
52 
53   /// Sort m_expressions.
54   void Sort() { m_exprs.Sort(); }
55 
56   void SetFuncFileAddress(lldb::addr_t func_file_addr) {
57     m_func_file_addr = func_file_addr;
58   }
59 
60   lldb::addr_t GetFuncFileAddress() { return m_func_file_addr; }
61 
62   const DWARFExpression *GetExpressionAtAddress(lldb::addr_t func_load_addr,
63                                                 lldb::addr_t load_addr) const;
64 
65   const DWARFExpression *GetAlwaysValidExpr() const;
66 
67   DWARFExpression *GetMutableExpressionAtAddress(
68       lldb::addr_t func_load_addr = LLDB_INVALID_ADDRESS,
69       lldb::addr_t load_addr = 0);
70 
71   size_t GetSize() const { return m_exprs.GetSize(); }
72 
73   bool ContainsThreadLocalStorage() const;
74 
75   bool LinkThreadLocalStorage(
76       lldb::ModuleSP new_module_sp,
77       std::function<lldb::addr_t(lldb::addr_t file_addr)> const
78           &link_address_callback);
79 
80   bool MatchesOperand(StackFrame &frame,
81                       const Instruction::Operand &operand) const;
82 
83   /// Dump locations that contains file_addr if it's valid. Otherwise. dump all
84   /// locations.
85   bool DumpLocations(Stream *s, lldb::DescriptionLevel level,
86                      lldb::addr_t func_load_addr, lldb::addr_t file_addr,
87                      ABI *abi) const;
88 
89   /// Dump all locaitons with each seperated by new line.
90   void GetDescription(Stream *s, lldb::DescriptionLevel level, ABI *abi) const;
91 
92   /// Search for a load address in the dwarf location list
93   ///
94   /// \param[in] func_load_addr
95   ///     The actual address of the function containing this location list.
96   ///
97   /// \param[in] addr
98   ///     The address to resolve.
99   ///
100   /// \return
101   ///     True if IsLocationList() is true and the address was found;
102   ///     false otherwise.
103   //    bool
104   //    LocationListContainsLoadAddress (Process* process, const Address &addr)
105   //    const;
106   //
107   bool ContainsAddress(lldb::addr_t func_load_addr, lldb::addr_t addr) const;
108 
109   void SetModule(const lldb::ModuleSP &module) { m_module_wp = module; }
110 
111   bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
112                 lldb::addr_t func_load_addr, const Value *initial_value_ptr,
113                 const Value *object_address_ptr, Value &result,
114                 Status *error_ptr) const;
115 
116 private:
117   // RangeDataVector requires a comparator for DWARFExpression, but it doesn't
118   // make sense to do so.
119   struct DWARFExpressionCompare {
120   public:
121     bool operator()(const DWARFExpression &lhs,
122                     const DWARFExpression &rhs) const {
123       return false;
124     }
125   };
126   using ExprVec = RangeDataVector<lldb::addr_t, lldb::addr_t, DWARFExpression,
127                                   0, DWARFExpressionCompare>;
128   using Entry = ExprVec::Entry;
129 
130   // File address range mapping to single dwarf expression.
131   ExprVec m_exprs;
132 
133   /// Module which defined this expression.
134   lldb::ModuleWP m_module_wp;
135 
136   /// The DWARF compile unit this expression belongs to. It is used to evaluate
137   /// values indexing into the .debug_addr section (e.g. DW_OP_GNU_addr_index,
138   /// DW_OP_GNU_const_index)
139   const DWARFUnit *m_dwarf_cu = nullptr;
140 
141   // Function base file address.
142   lldb::addr_t m_func_file_addr = LLDB_INVALID_ADDRESS;
143 
144   using const_iterator = ExprVec::Collection::const_iterator;
145   const_iterator begin() const { return m_exprs.begin(); }
146   const_iterator end() const { return m_exprs.end(); }
147 };
148 } // namespace lldb_private
149 
150 #endif // LLDB_EXPRESSION_DWARFEXPRESSIONLIST_H
151