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/Core/RegularExpression.h" 14 #include "lldb/Symbol/Block.h" 15 #include "lldb/Symbol/Function.h" 16 #include "lldb/Symbol/SymbolContext.h" 17 #include "lldb/Symbol/Type.h" 18 #include "lldb/Target/Process.h" 19 #include "lldb/Target/RegisterContext.h" 20 #include "lldb/Target/StackFrame.h" 21 #include "lldb/Target/Thread.h" 22 #include "lldb/Target/Target.h" 23 24 using namespace lldb; 25 using namespace lldb_private; 26 27 //---------------------------------------------------------------------- 28 // Variable constructor 29 //---------------------------------------------------------------------- 30 Variable::Variable 31 ( 32 lldb::user_id_t uid, 33 const char *name, 34 const char *mangled, // The mangled variable name for variables in namespaces 35 Type *type, 36 ValueType scope, 37 SymbolContextScope *context, 38 Declaration* decl_ptr, 39 const DWARFExpression& location, 40 bool external, 41 bool artificial 42 ) : 43 UserID(uid), 44 m_name(name), 45 m_mangled (mangled, true), 46 m_type(type), 47 m_scope(scope), 48 m_owner_scope(context), 49 m_declaration(decl_ptr), 50 m_location(location), 51 m_external(external), 52 m_artificial(artificial) 53 { 54 } 55 56 //---------------------------------------------------------------------- 57 // Destructor 58 //---------------------------------------------------------------------- 59 Variable::~Variable() 60 { 61 } 62 63 64 const ConstString& 65 Variable::GetName() const 66 { 67 if (m_mangled) 68 return m_mangled.GetName(); 69 return m_name; 70 } 71 72 bool 73 Variable::NameMatches (const RegularExpression& regex) const 74 { 75 if (regex.Execute (m_name.AsCString())) 76 return true; 77 return m_mangled.NameMatches (regex); 78 } 79 80 void 81 Variable::Dump(Stream *s, bool show_context) const 82 { 83 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 84 s->Indent(); 85 *s << "Variable" << (const UserID&)*this; 86 87 if (m_name) 88 *s << ", name = \"" << m_name << "\""; 89 90 if (m_type != NULL) 91 { 92 *s << ", type = {" << m_type->GetID() << "} " << (void*)m_type << " ("; 93 m_type->DumpTypeName(s); 94 s->PutChar(')'); 95 } 96 97 if (m_scope != eValueTypeInvalid) 98 { 99 s->PutCString(", scope = "); 100 switch (m_scope) 101 { 102 case eValueTypeVariableGlobal: s->PutCString(m_external ? "global" : "static"); break; 103 case eValueTypeVariableArgument: s->PutCString("parameter"); break; 104 case eValueTypeVariableLocal: s->PutCString("local"); break; 105 default: *s << "??? (" << m_scope << ')'; 106 } 107 } 108 109 if (show_context && m_owner_scope != NULL) 110 { 111 s->PutCString(", context = ( "); 112 m_owner_scope->DumpSymbolContext(s); 113 s->PutCString(" )"); 114 } 115 116 bool show_fullpaths = false; 117 m_declaration.Dump(s, show_fullpaths); 118 119 if (m_location.IsValid()) 120 { 121 s->PutCString(", location = "); 122 lldb::addr_t loclist_base_addr = LLDB_INVALID_ADDRESS; 123 if (m_location.IsLocationList()) 124 { 125 SymbolContext variable_sc; 126 m_owner_scope->CalculateSymbolContext(&variable_sc); 127 if (variable_sc.function) 128 loclist_base_addr = variable_sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); 129 } 130 m_location.GetDescription(s, lldb::eDescriptionLevelBrief, loclist_base_addr); 131 } 132 133 if (m_external) 134 s->PutCString(", external"); 135 136 if (m_artificial) 137 s->PutCString(", artificial"); 138 139 s->EOL(); 140 } 141 142 143 size_t 144 Variable::MemorySize() const 145 { 146 return sizeof(Variable); 147 } 148 149 150 void 151 Variable::CalculateSymbolContext (SymbolContext *sc) 152 { 153 if (m_owner_scope) 154 m_owner_scope->CalculateSymbolContext(sc); 155 else 156 sc->Clear(); 157 } 158 159 bool 160 Variable::LocationIsValidForFrame (StackFrame *frame) 161 { 162 // Is the variable is described by a single location? 163 if (!m_location.IsLocationList()) 164 { 165 // Yes it is, the location is valid. 166 return true; 167 } 168 169 if (frame) 170 { 171 Target *target = &frame->GetThread().GetProcess().GetTarget(); 172 173 Function *function = frame->GetSymbolContext(eSymbolContextFunction).function; 174 if (function) 175 { 176 addr_t loclist_base_load_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress (target); 177 if (loclist_base_load_addr == LLDB_INVALID_ADDRESS) 178 return false; 179 // It is a location list. We just need to tell if the location 180 // list contains the current address when converted to a load 181 // address 182 return m_location.LocationListContainsAddress (loclist_base_load_addr, 183 frame->GetFrameCodeAddress().GetLoadAddress (target)); 184 } 185 } 186 return false; 187 } 188 189 bool 190 Variable::IsInScope (StackFrame *frame) 191 { 192 switch (m_scope) 193 { 194 case eValueTypeRegister: 195 case eValueTypeRegisterSet: 196 return frame != NULL; 197 198 case eValueTypeConstResult: 199 return true; 200 201 case eValueTypeVariableGlobal: 202 case eValueTypeVariableStatic: 203 case eValueTypeVariableArgument: 204 case eValueTypeVariableLocal: 205 if (frame) 206 { 207 // We don't have a location list, we just need to see if the block 208 // that this variable was defined in is currently 209 Block *deepest_frame_block = frame->GetSymbolContext(eSymbolContextBlock).block; 210 if (deepest_frame_block) 211 { 212 SymbolContext variable_sc; 213 CalculateSymbolContext (&variable_sc); 214 // Check for static or global variable defined at the compile unit 215 // level that wasn't defined in a block 216 if (variable_sc.block == NULL) 217 return true; 218 219 if (variable_sc.block == deepest_frame_block) 220 return true; 221 return variable_sc.block->Contains (deepest_frame_block); 222 } 223 } 224 break; 225 226 default: 227 break; 228 } 229 return false; 230 } 231 232