1 //===-- Variable.cpp --------------------------------------------*- 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 #include "lldb/Symbol/Variable.h"
11 
12 #include "lldb/Core/Stream.h"
13 #include "lldb/Symbol/Block.h"
14 #include "lldb/Symbol/Function.h"
15 #include "lldb/Symbol/SymbolContext.h"
16 #include "lldb/Symbol/Type.h"
17 #include "lldb/Target/Process.h"
18 #include "lldb/Target/RegisterContext.h"
19 #include "lldb/Target/StackFrame.h"
20 #include "lldb/Target/Thread.h"
21 #include "lldb/Target/Target.h"
22 
23 using namespace lldb;
24 using namespace lldb_private;
25 
26 //----------------------------------------------------------------------
27 // Variable constructor
28 //----------------------------------------------------------------------
29 Variable::Variable(lldb::user_id_t uid,
30                        const ConstString& name,
31                        Type *type,
32                        ValueType scope,
33                        SymbolContextScope *context,
34                        Declaration* decl_ptr,
35                        const DWARFExpression& location,
36                        bool external,
37                        bool artificial) :
38     UserID(uid),
39     m_name(name),
40     m_type(type),
41     m_scope(scope),
42     m_owner_scope(context),
43     m_declaration(decl_ptr),
44     m_location(location),
45     m_external(external),
46     m_artificial(artificial)
47 {
48 }
49 
50 //----------------------------------------------------------------------
51 // Destructor
52 //----------------------------------------------------------------------
53 Variable::~Variable()
54 {
55 }
56 
57 
58 void
59 Variable::Dump(Stream *s, bool show_context) const
60 {
61     s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
62     s->Indent();
63     *s << "Variable" << (const UserID&)*this;
64 
65     if (m_name)
66         *s << ", name = \"" << m_name << "\"";
67 
68     if (m_type != NULL)
69     {
70         *s << ", type = {" << m_type->GetID() << "} " << (void*)m_type << " (";
71         m_type->DumpTypeName(s);
72         s->PutChar(')');
73     }
74 
75     if (m_scope != eValueTypeInvalid)
76     {
77         s->PutCString(", scope = ");
78         switch (m_scope)
79         {
80         case eValueTypeVariableGlobal:       s->PutCString(m_external ? "global" : "static"); break;
81         case eValueTypeVariableArgument:    s->PutCString("parameter"); break;
82         case eValueTypeVariableLocal:        s->PutCString("local"); break;
83         default:            *s << "??? (" << m_scope << ')';
84         }
85     }
86 
87     if (show_context && m_owner_scope != NULL)
88     {
89         s->PutCString(", context = ( ");
90         m_owner_scope->DumpSymbolContext(s);
91         s->PutCString(" )");
92     }
93 
94     bool show_fullpaths = false;
95     m_declaration.Dump(s, show_fullpaths);
96 
97     if (m_location.IsValid())
98     {
99         s->PutCString(", location = ");
100         lldb::addr_t loclist_base_addr = LLDB_INVALID_ADDRESS;
101         if (m_location.IsLocationList())
102         {
103             SymbolContext variable_sc;
104             m_owner_scope->CalculateSymbolContext(&variable_sc);
105             if (variable_sc.function)
106                 loclist_base_addr = variable_sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
107         }
108         m_location.GetDescription(s, lldb::eDescriptionLevelBrief, loclist_base_addr);
109     }
110 
111     if (m_external)
112         s->PutCString(", external");
113 
114     if (m_artificial)
115         s->PutCString(", artificial");
116 
117     s->EOL();
118 }
119 
120 
121 size_t
122 Variable::MemorySize() const
123 {
124     return sizeof(Variable);
125 }
126 
127 
128 void
129 Variable::CalculateSymbolContext (SymbolContext *sc)
130 {
131     if (m_owner_scope)
132         m_owner_scope->CalculateSymbolContext(sc);
133     else
134         sc->Clear();
135 }
136 
137 
138 bool
139 Variable::IsInScope (StackFrame *frame)
140 {
141     switch (m_scope)
142     {
143     case eValueTypeVariableGlobal:
144     case eValueTypeVariableStatic:
145         // Globals and statics are always in scope.
146         return true;
147 
148     case eValueTypeVariableArgument:
149     case eValueTypeVariableLocal:
150         // Check if the location has a location list that describes the value
151         // of the variable with address ranges and different locations for each
152         // address range?
153         if (m_location.IsLocationList())
154         {
155             SymbolContext sc;
156             CalculateSymbolContext(&sc);
157 
158             // Currently we only support functions that have things with
159             // locations lists. If this expands, we will need to add support
160             assert (sc.function);
161             Target *target = &frame->GetThread().GetProcess().GetTarget();
162             addr_t loclist_base_load_addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (target);
163             if (loclist_base_load_addr == LLDB_INVALID_ADDRESS)
164                 return false;
165             // It is a location list. We just need to tell if the location
166             // list contains the current address when converted to a load
167             // address
168             return m_location.LocationListContainsAddress (loclist_base_load_addr, frame->GetFrameCodeAddress().GetLoadAddress (target));
169         }
170         else
171         {
172             // We don't have a location list, we just need to see if the block
173             // that this variable was defined in is currently
174             Block *deepest_frame_block = frame->GetSymbolContext(eSymbolContextBlock).block;
175             if (deepest_frame_block)
176             {
177                 SymbolContext variable_sc;
178                 CalculateSymbolContext (&variable_sc);
179                 if (variable_sc.block == deepest_frame_block)
180                     return true;
181 
182                 return variable_sc.block->Contains (deepest_frame_block);
183             }
184         }
185         break;
186 
187     default:
188         assert (!"Unhandled case");
189         break;
190     }
191     return false;
192 }
193 
194