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