Home | History | Annotate | Download | only in Expression
      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 
     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
    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
    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 *
    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 {
    158         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
    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
    189     DisableJITVars(uint64_t parser_id)
    190     {
    191         m_jit_vars.erase(parser_id);
    192     }
    193 
    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
    288     GetSize()
    289     {
    290         return m_variables.size();
    291     }
    292 
    293     lldb::ClangExpressionVariableSP
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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