1 //===-- ClangExpressionVariable.h -------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef liblldb_ClangExpressionVariable_h_
11 #define liblldb_ClangExpressionVariable_h_
12 
13 // C Includes
14 #include <signal.h>
15 #include <stdint.h>
16 #include <string.h>
17 
18 // C++ Includes
19 #include <map>
20 #include <string>
21 #include <vector>
22 
23 // Other libraries and framework includes
24 // Project includes
25 #include "lldb/lldb-public.h"
26 #include "lldb/Core/ClangForward.h"
27 #include "lldb/Core/ConstString.h"
28 #include "lldb/Core/Value.h"
29 #include "lldb/Symbol/TaggedASTType.h"
30 
31 namespace llvm {
32     class Value;
33 }
34 
35 namespace lldb_private {
36 
37 class ClangExpressionVariableList;
38 class ValueObjectConstResult;
39 
40 //----------------------------------------------------------------------
41 /// @class ClangExpressionVariable ClangExpressionVariable.h "lldb/Expression/ClangExpressionVariable.h"
42 /// @brief Encapsulates one variable for the expression parser.
43 ///
44 /// The expression parser uses variables in three different contexts:
45 ///
46 /// First, it stores persistent variables along with the process for use
47 /// in expressions.  These persistent variables contain their own data
48 /// and are typed.
49 ///
50 /// Second, in an interpreted expression, it stores the local variables
51 /// for the expression along with the expression.  These variables
52 /// contain their own data and are typed.
53 ///
54 /// Third, in a JIT-compiled expression, it stores the variables that
55 /// the expression needs to have materialized and dematerialized at each
56 /// execution.  These do not contain their own data but are named and
57 /// typed.
58 ///
59 /// This class supports all of these use cases using simple type
60 /// polymorphism, and provides necessary support methods.  Its interface
61 /// is RTTI-neutral.
62 //----------------------------------------------------------------------
63 class ClangExpressionVariable
64 {
65 public:
66     ClangExpressionVariable(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size);
67 
68     ClangExpressionVariable(const lldb::ValueObjectSP &valobj_sp);
69 
70     //----------------------------------------------------------------------
71     /// If the variable contains its own data, make a Value point at it.
72     /// If \a exe_ctx in not NULL, the value will be resolved in with
73     /// that execution context.
74     ///
75     /// @param[in] value
76     ///     The value to point at the data.
77     ///
78     /// @param[in] exe_ctx
79     ///     The execution context to use to resolve \a value.
80     ///
81     /// @return
82     ///     True on success; false otherwise (in particular, if this variable
83     ///     does not contain its own data).
84     //----------------------------------------------------------------------
85     bool
86     PointValueAtData(Value &value, ExecutionContext *exe_ctx);
87 
88     lldb::ValueObjectSP
89     GetValueObject();
90 
91     //----------------------------------------------------------------------
92     /// The following values should not live beyond parsing
93     //----------------------------------------------------------------------
94     class ParserVars
95     {
96     public:
97 
ParserVars()98         ParserVars() :
99             m_parser_type(),
100             m_named_decl (NULL),
101             m_llvm_value (NULL),
102             m_lldb_value (),
103             m_lldb_var   (),
104             m_lldb_sym   (NULL)
105         {
106         }
107 
108         TypeFromParser          m_parser_type;  ///< The type of the variable according to the parser
109         const clang::NamedDecl *m_named_decl;   ///< The Decl corresponding to this variable
110         llvm::Value            *m_llvm_value;   ///< The IR value corresponding to this variable; usually a GlobalValue
111         lldb_private::Value     m_lldb_value;   ///< The value found in LLDB for this variable
112         lldb::VariableSP        m_lldb_var;     ///< The original variable for this variable
113         const lldb_private::Symbol *m_lldb_sym; ///< The original symbol for this variable, if it was a symbol
114     };
115 
116 private:
117     typedef std::map <uint64_t, ParserVars> ParserVarMap;
118     ParserVarMap m_parser_vars;
119 
120 public:
121     //----------------------------------------------------------------------
122     /// Make this variable usable by the parser by allocating space for
123     /// parser-specific variables
124     //----------------------------------------------------------------------
125     void
EnableParserVars(uint64_t parser_id)126     EnableParserVars(uint64_t parser_id)
127     {
128         m_parser_vars.insert(std::make_pair(parser_id, ParserVars()));
129     }
130 
131     //----------------------------------------------------------------------
132     /// Deallocate parser-specific variables
133     //----------------------------------------------------------------------
134     void
DisableParserVars(uint64_t parser_id)135     DisableParserVars(uint64_t parser_id)
136     {
137         m_parser_vars.erase(parser_id);
138     }
139 
140     //----------------------------------------------------------------------
141     /// Access parser-specific variables
142     //----------------------------------------------------------------------
143     ParserVars *
GetParserVars(uint64_t parser_id)144     GetParserVars(uint64_t parser_id)
145     {
146         ParserVarMap::iterator i = m_parser_vars.find(parser_id);
147 
148         if (i == m_parser_vars.end())
149             return NULL;
150         else
151             return &i->second;
152     }
153 
154     //----------------------------------------------------------------------
155     /// The following values are valid if the variable is used by JIT code
156     //----------------------------------------------------------------------
157     struct JITVars {
JITVarsJITVars158         JITVars () :
159             m_alignment (0),
160             m_size (0),
161             m_offset (0)
162         {
163         }
164 
165         off_t   m_alignment;    ///< The required alignment of the variable, in bytes
166         size_t  m_size;         ///< The space required for the variable, in bytes
167         off_t   m_offset;       ///< The offset of the variable in the struct, in bytes
168     };
169 
170 private:
171     typedef std::map <uint64_t, JITVars> JITVarMap;
172     JITVarMap m_jit_vars;
173 
174 public:
175     //----------------------------------------------------------------------
176     /// Make this variable usable for materializing for the JIT by allocating
177     /// space for JIT-specific variables
178     //----------------------------------------------------------------------
179     void
EnableJITVars(uint64_t parser_id)180     EnableJITVars(uint64_t parser_id)
181     {
182         m_jit_vars.insert(std::make_pair(parser_id, JITVars()));
183     }
184 
185     //----------------------------------------------------------------------
186     /// Deallocate JIT-specific variables
187     //----------------------------------------------------------------------
188     void
DisableJITVars(uint64_t parser_id)189     DisableJITVars(uint64_t parser_id)
190     {
191         m_jit_vars.erase(parser_id);
192     }
193 
GetJITVars(uint64_t parser_id)194     JITVars *GetJITVars(uint64_t parser_id)
195     {
196         JITVarMap::iterator i = m_jit_vars.find(parser_id);
197 
198         if (i == m_jit_vars.end())
199             return NULL;
200         else
201             return &i->second;
202     }
203 
204     //----------------------------------------------------------------------
205     /// Return the variable's size in bytes
206     //----------------------------------------------------------------------
207     size_t
208     GetByteSize ();
209 
210     const ConstString &
211     GetName();
212 
213     RegisterInfo *
214     GetRegisterInfo();
215 
216     void
217     SetRegisterInfo (const RegisterInfo *reg_info);
218 
219     ClangASTType
220     GetClangType ();
221 
222     void
223     SetClangType (const ClangASTType &clang_type);
224 
225     TypeFromUser
226     GetTypeFromUser ();
227 
228     uint8_t *
229     GetValueBytes ();
230 
231     void
232     SetName (const ConstString &name);
233 
234     void
235     ValueUpdated ();
236 
237     // this function is used to copy the address-of m_live_sp into m_frozen_sp
238     // this is necessary because the results of certain cast and pointer-arithmetic
239     // operations (such as those described in bugzilla issues 11588 and 11618) generate
240     // frozen objcts that do not have a valid address-of, which can be troublesome when
241     // using synthetic children providers. transferring the address-of the live object
242     // solves these issues and provides the expected user-level behavior
243     void
244     TransferAddress (bool force = false);
245 
246     typedef std::shared_ptr<ValueObjectConstResult> ValueObjectConstResultSP;
247 
248     //----------------------------------------------------------------------
249     /// Members
250     //----------------------------------------------------------------------
251     enum Flags
252     {
253         EVNone                  = 0,
254         EVIsLLDBAllocated       = 1 << 0,   ///< This variable is resident in a location specifically allocated for it by LLDB in the target process
255         EVIsProgramReference    = 1 << 1,   ///< This variable is a reference to a (possibly invalid) area managed by the target program
256         EVNeedsAllocation       = 1 << 2,   ///< Space for this variable has yet to be allocated in the target process
257         EVIsFreezeDried         = 1 << 3,   ///< This variable's authoritative version is in m_frozen_sp (for example, for statically-computed results)
258         EVNeedsFreezeDry        = 1 << 4,   ///< Copy from m_live_sp to m_frozen_sp during dematerialization
259         EVKeepInTarget          = 1 << 5,   ///< Keep the allocation after the expression is complete rather than freeze drying its contents and freeing it
260         EVTypeIsReference       = 1 << 6,   ///< The original type of this variable is a reference, so materialize the value rather than the location
261         EVUnknownType           = 1 << 7,   ///< This is a symbol of unknown type, and the type must be resolved after parsing is complete
262         EVBareRegister          = 1 << 8    ///< This variable is a direct reference to $pc or some other entity.
263     };
264 
265     typedef uint16_t FlagType;
266 
267     FlagType m_flags; // takes elements of Flags
268 
269     lldb::ValueObjectSP m_frozen_sp;
270     lldb::ValueObjectSP m_live_sp;
271 
272     DISALLOW_COPY_AND_ASSIGN (ClangExpressionVariable);
273 };
274 
275 //----------------------------------------------------------------------
276 /// @class ClangExpressionVariableListBase ClangExpressionVariable.h "lldb/Expression/ClangExpressionVariable.h"
277 /// @brief A list of variable references.
278 ///
279 /// This class stores variables internally, acting as the permanent store.
280 //----------------------------------------------------------------------
281 class ClangExpressionVariableList
282 {
283 public:
284     //----------------------------------------------------------------------
285     /// Implementation of methods in ClangExpressionVariableListBase
286     //----------------------------------------------------------------------
287     size_t
GetSize()288     GetSize()
289     {
290         return m_variables.size();
291     }
292 
293     lldb::ClangExpressionVariableSP
GetVariableAtIndex(size_t index)294     GetVariableAtIndex(size_t index)
295     {
296         lldb::ClangExpressionVariableSP var_sp;
297         if (index < m_variables.size())
298             var_sp = m_variables[index];
299         return var_sp;
300     }
301 
302     size_t
AddVariable(const lldb::ClangExpressionVariableSP & var_sp)303     AddVariable (const lldb::ClangExpressionVariableSP &var_sp)
304     {
305         m_variables.push_back(var_sp);
306         return m_variables.size() - 1;
307     }
308 
309     bool
ContainsVariable(const lldb::ClangExpressionVariableSP & var_sp)310     ContainsVariable (const lldb::ClangExpressionVariableSP &var_sp)
311     {
312         const size_t size = m_variables.size();
313         for (size_t index = 0; index < size; ++index)
314         {
315             if (m_variables[index].get() == var_sp.get())
316                 return true;
317         }
318         return false;
319     }
320 
321     //----------------------------------------------------------------------
322     /// Finds a variable by name in the list.
323     ///
324     /// @param[in] name
325     ///     The name of the requested variable.
326     ///
327     /// @return
328     ///     The variable requested, or NULL if that variable is not in the list.
329     //----------------------------------------------------------------------
330     lldb::ClangExpressionVariableSP
GetVariable(const ConstString & name)331     GetVariable (const ConstString &name)
332     {
333         lldb::ClangExpressionVariableSP var_sp;
334         for (size_t index = 0, size = GetSize(); index < size; ++index)
335         {
336             var_sp = GetVariableAtIndex(index);
337             if (var_sp->GetName() == name)
338                 return var_sp;
339         }
340         var_sp.reset();
341         return var_sp;
342     }
343 
344     lldb::ClangExpressionVariableSP
GetVariable(const char * name)345     GetVariable (const char *name)
346     {
347         lldb::ClangExpressionVariableSP var_sp;
348         if (name && name[0])
349         {
350             for (size_t index = 0, size = GetSize(); index < size; ++index)
351             {
352                 var_sp = GetVariableAtIndex(index);
353                 const char *var_name_cstr = var_sp->GetName().GetCString();
354                 if (!var_name_cstr || !name)
355                     continue;
356                 if (::strcmp (var_name_cstr, name) == 0)
357                     return var_sp;
358             }
359             var_sp.reset();
360         }
361         return var_sp;
362     }
363 
364     //----------------------------------------------------------------------
365     /// Finds a variable by NamedDecl in the list.
366     ///
367     /// @param[in] name
368     ///     The name of the requested variable.
369     ///
370     /// @return
371     ///     The variable requested, or NULL if that variable is not in the list.
372     //----------------------------------------------------------------------
373     lldb::ClangExpressionVariableSP
GetVariable(const clang::NamedDecl * decl,uint64_t parser_id)374     GetVariable (const clang::NamedDecl *decl, uint64_t parser_id)
375     {
376         lldb::ClangExpressionVariableSP var_sp;
377         for (size_t index = 0, size = GetSize(); index < size; ++index)
378         {
379             var_sp = GetVariableAtIndex(index);
380 
381             ClangExpressionVariable::ParserVars *parser_vars = var_sp->GetParserVars(parser_id);
382 
383             if (parser_vars && parser_vars->m_named_decl == decl)
384                 return var_sp;
385         }
386         var_sp.reset();
387         return var_sp;
388     }
389 
390     //----------------------------------------------------------------------
391     /// Create a new variable in the list and return its index
392     //----------------------------------------------------------------------
393     lldb::ClangExpressionVariableSP
CreateVariable(ExecutionContextScope * exe_scope,lldb::ByteOrder byte_order,uint32_t addr_byte_size)394     CreateVariable (ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size)
395     {
396         lldb::ClangExpressionVariableSP var_sp(new ClangExpressionVariable(exe_scope, byte_order, addr_byte_size));
397         m_variables.push_back(var_sp);
398         return var_sp;
399     }
400 
401     lldb::ClangExpressionVariableSP
CreateVariable(const lldb::ValueObjectSP & valobj_sp)402     CreateVariable(const lldb::ValueObjectSP &valobj_sp)
403     {
404         lldb::ClangExpressionVariableSP var_sp(new ClangExpressionVariable(valobj_sp));
405         m_variables.push_back(var_sp);
406         return var_sp;
407     }
408 
409     lldb::ClangExpressionVariableSP
CreateVariable(ExecutionContextScope * exe_scope,const ConstString & name,const TypeFromUser & user_type,lldb::ByteOrder byte_order,uint32_t addr_byte_size)410     CreateVariable (ExecutionContextScope *exe_scope,
411                     const ConstString &name,
412                     const TypeFromUser& user_type,
413                     lldb::ByteOrder byte_order,
414                     uint32_t addr_byte_size)
415     {
416         lldb::ClangExpressionVariableSP var_sp(new ClangExpressionVariable(exe_scope, byte_order, addr_byte_size));
417         var_sp->SetName (name);
418         var_sp->SetClangType (user_type);
419         m_variables.push_back(var_sp);
420         return var_sp;
421     }
422 
423     void
RemoveVariable(lldb::ClangExpressionVariableSP var_sp)424     RemoveVariable (lldb::ClangExpressionVariableSP var_sp)
425     {
426         for (std::vector<lldb::ClangExpressionVariableSP>::iterator vi = m_variables.begin(), ve = m_variables.end();
427              vi != ve;
428              ++vi)
429         {
430             if (vi->get() == var_sp.get())
431             {
432                 m_variables.erase(vi);
433                 return;
434             }
435         }
436     }
437 
438     void
Clear()439     Clear()
440     {
441         m_variables.clear();
442     }
443 
444 private:
445     std::vector <lldb::ClangExpressionVariableSP> m_variables;
446 };
447 
448 
449 } // namespace lldb_private
450 
451 #endif  // liblldb_ClangExpressionVariable_h_
452