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/Core/ValueObject.h" 15 #include "lldb/Core/ValueObjectVariable.h" 16 #include "lldb/Symbol/Block.h" 17 #include "lldb/Symbol/Function.h" 18 #include "lldb/Symbol/SymbolContext.h" 19 #include "lldb/Symbol/Type.h" 20 #include "lldb/Symbol/VariableList.h" 21 #include "lldb/Target/Process.h" 22 #include "lldb/Target/RegisterContext.h" 23 #include "lldb/Target/StackFrame.h" 24 #include "lldb/Target/Thread.h" 25 #include "lldb/Target/Target.h" 26 27 using namespace lldb; 28 using namespace lldb_private; 29 30 //---------------------------------------------------------------------- 31 // Variable constructor 32 //---------------------------------------------------------------------- 33 Variable::Variable 34 ( 35 lldb::user_id_t uid, 36 const char *name, 37 const char *mangled, // The mangled variable name for variables in namespaces 38 Type *type, 39 ValueType scope, 40 SymbolContextScope *context, 41 Declaration* decl_ptr, 42 const DWARFExpression& location, 43 bool external, 44 bool artificial 45 ) : 46 UserID(uid), 47 m_name(name), 48 m_mangled (mangled, true), 49 m_type(type), 50 m_scope(scope), 51 m_owner_scope(context), 52 m_declaration(decl_ptr), 53 m_location(location), 54 m_external(external), 55 m_artificial(artificial) 56 { 57 } 58 59 //---------------------------------------------------------------------- 60 // Destructor 61 //---------------------------------------------------------------------- 62 Variable::~Variable() 63 { 64 } 65 66 67 const ConstString& 68 Variable::GetName() const 69 { 70 if (m_mangled) 71 return m_mangled.GetName(); 72 return m_name; 73 } 74 75 bool 76 Variable::NameMatches (const RegularExpression& regex) const 77 { 78 if (regex.Execute (m_name.AsCString())) 79 return true; 80 return m_mangled.NameMatches (regex); 81 } 82 83 void 84 Variable::Dump(Stream *s, bool show_context) const 85 { 86 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 87 s->Indent(); 88 *s << "Variable" << (const UserID&)*this; 89 90 if (m_name) 91 *s << ", name = \"" << m_name << "\""; 92 93 if (m_type != NULL) 94 { 95 *s << ", type = {" << m_type->GetID() << "} " << (void*)m_type << " ("; 96 m_type->DumpTypeName(s); 97 s->PutChar(')'); 98 } 99 100 if (m_scope != eValueTypeInvalid) 101 { 102 s->PutCString(", scope = "); 103 switch (m_scope) 104 { 105 case eValueTypeVariableGlobal: s->PutCString(m_external ? "global" : "static"); break; 106 case eValueTypeVariableArgument: s->PutCString("parameter"); break; 107 case eValueTypeVariableLocal: s->PutCString("local"); break; 108 default: *s << "??? (" << m_scope << ')'; 109 } 110 } 111 112 if (show_context && m_owner_scope != NULL) 113 { 114 s->PutCString(", context = ( "); 115 m_owner_scope->DumpSymbolContext(s); 116 s->PutCString(" )"); 117 } 118 119 bool show_fullpaths = false; 120 m_declaration.Dump(s, show_fullpaths); 121 122 if (m_location.IsValid()) 123 { 124 s->PutCString(", location = "); 125 lldb::addr_t loclist_base_addr = LLDB_INVALID_ADDRESS; 126 if (m_location.IsLocationList()) 127 { 128 SymbolContext variable_sc; 129 m_owner_scope->CalculateSymbolContext(&variable_sc); 130 if (variable_sc.function) 131 loclist_base_addr = variable_sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); 132 } 133 m_location.GetDescription(s, lldb::eDescriptionLevelBrief, loclist_base_addr); 134 } 135 136 if (m_external) 137 s->PutCString(", external"); 138 139 if (m_artificial) 140 s->PutCString(", artificial"); 141 142 s->EOL(); 143 } 144 145 bool 146 Variable::DumpDeclaration (Stream *s, bool show_fullpaths, bool show_module) 147 { 148 bool dumped_declaration_info = false; 149 if (m_owner_scope) 150 { 151 SymbolContext sc; 152 m_owner_scope->CalculateSymbolContext(&sc); 153 sc.block = NULL; 154 sc.line_entry.Clear(); 155 bool show_inlined_frames = false; 156 157 dumped_declaration_info = sc.DumpStopContext (s, 158 NULL, 159 Address(), 160 show_fullpaths, 161 show_module, 162 show_inlined_frames); 163 164 if (sc.function) 165 s->PutChar(':'); 166 } 167 if (m_declaration.DumpStopContext (s, false)) 168 dumped_declaration_info = true; 169 return dumped_declaration_info; 170 } 171 172 size_t 173 Variable::MemorySize() const 174 { 175 return sizeof(Variable); 176 } 177 178 179 void 180 Variable::CalculateSymbolContext (SymbolContext *sc) 181 { 182 if (m_owner_scope) 183 m_owner_scope->CalculateSymbolContext(sc); 184 else 185 sc->Clear(); 186 } 187 188 bool 189 Variable::LocationIsValidForFrame (StackFrame *frame) 190 { 191 // Is the variable is described by a single location? 192 if (!m_location.IsLocationList()) 193 { 194 // Yes it is, the location is valid. 195 return true; 196 } 197 198 if (frame) 199 { 200 Target *target = &frame->GetThread().GetProcess().GetTarget(); 201 202 Function *function = frame->GetSymbolContext(eSymbolContextFunction).function; 203 if (function) 204 { 205 addr_t loclist_base_load_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress (target); 206 if (loclist_base_load_addr == LLDB_INVALID_ADDRESS) 207 return false; 208 // It is a location list. We just need to tell if the location 209 // list contains the current address when converted to a load 210 // address 211 return m_location.LocationListContainsAddress (loclist_base_load_addr, 212 frame->GetFrameCodeAddress().GetLoadAddress (target)); 213 } 214 } 215 return false; 216 } 217 218 bool 219 Variable::LocationIsValidForAddress (const Address &address) 220 { 221 // Be sure to resolve the address to section offset prior to 222 // calling this function. 223 if (address.IsSectionOffset()) 224 { 225 SymbolContext sc; 226 CalculateSymbolContext(&sc); 227 if (sc.module_sp.get() == address.GetModule()) 228 { 229 // Is the variable is described by a single location? 230 if (!m_location.IsLocationList()) 231 { 232 // Yes it is, the location is valid. 233 return true; 234 } 235 236 if (sc.function) 237 { 238 addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); 239 if (loclist_base_file_addr == LLDB_INVALID_ADDRESS) 240 return false; 241 // It is a location list. We just need to tell if the location 242 // list contains the current address when converted to a load 243 // address 244 return m_location.LocationListContainsAddress (loclist_base_file_addr, 245 address.GetFileAddress()); 246 } 247 } 248 } 249 return false; 250 } 251 252 bool 253 Variable::IsInScope (StackFrame *frame) 254 { 255 switch (m_scope) 256 { 257 case eValueTypeRegister: 258 case eValueTypeRegisterSet: 259 return frame != NULL; 260 261 case eValueTypeConstResult: 262 case eValueTypeVariableGlobal: 263 case eValueTypeVariableStatic: 264 return true; 265 266 case eValueTypeVariableArgument: 267 case eValueTypeVariableLocal: 268 if (frame) 269 { 270 // We don't have a location list, we just need to see if the block 271 // that this variable was defined in is currently 272 Block *deepest_frame_block = frame->GetSymbolContext(eSymbolContextBlock).block; 273 if (deepest_frame_block) 274 { 275 SymbolContext variable_sc; 276 CalculateSymbolContext (&variable_sc); 277 // Check for static or global variable defined at the compile unit 278 // level that wasn't defined in a block 279 if (variable_sc.block == NULL) 280 return true; 281 282 if (variable_sc.block == deepest_frame_block) 283 return true; 284 return variable_sc.block->Contains (deepest_frame_block); 285 } 286 } 287 break; 288 289 default: 290 break; 291 } 292 return false; 293 } 294 295 Error 296 Variable::GetValuesForVariableExpressionPath (const char *variable_expr_path, 297 ExecutionContextScope *scope, 298 GetVariableCallback callback, 299 void *baton, 300 VariableList &variable_list, 301 ValueObjectList &valobj_list) 302 { 303 Error error; 304 if (variable_expr_path && callback) 305 { 306 switch (variable_expr_path[0]) 307 { 308 case '*': 309 { 310 error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1, 311 scope, 312 callback, 313 baton, 314 variable_list, 315 valobj_list); 316 if (error.Success()) 317 { 318 for (uint32_t i=0; i<valobj_list.GetSize(); ) 319 { 320 Error tmp_error; 321 ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->Dereference(tmp_error)); 322 if (tmp_error.Fail()) 323 { 324 variable_list.RemoveVariableAtIndex (i); 325 valobj_list.RemoveValueObjectAtIndex (i); 326 } 327 else 328 { 329 valobj_list.SetValueObjectAtIndex (i, valobj_sp); 330 ++i; 331 } 332 } 333 } 334 else 335 { 336 error.SetErrorString ("unknown error"); 337 } 338 return error; 339 } 340 break; 341 342 case '&': 343 { 344 error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1, 345 scope, 346 callback, 347 baton, 348 variable_list, 349 valobj_list); 350 if (error.Success()) 351 { 352 for (uint32_t i=0; i<valobj_list.GetSize(); ) 353 { 354 Error tmp_error; 355 ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->AddressOf(tmp_error)); 356 if (tmp_error.Fail()) 357 { 358 variable_list.RemoveVariableAtIndex (i); 359 valobj_list.RemoveValueObjectAtIndex (i); 360 } 361 else 362 { 363 valobj_list.SetValueObjectAtIndex (i, valobj_sp); 364 ++i; 365 } 366 } 367 } 368 else 369 { 370 error.SetErrorString ("unknown error"); 371 } 372 return error; 373 } 374 break; 375 376 default: 377 { 378 RegularExpression regex ("^([A-Za-z_:][A-Za-z_0-9:]*)(.*)"); 379 if (regex.Execute(variable_expr_path, 1)) 380 { 381 std::string variable_name; 382 if (regex.GetMatchAtIndex(variable_expr_path, 1, variable_name)) 383 { 384 variable_list.Clear(); 385 if (callback (baton, variable_name.c_str(), variable_list)) 386 { 387 uint32_t i=0; 388 while (i < variable_list.GetSize()) 389 { 390 VariableSP var_sp (variable_list.GetVariableAtIndex (i)); 391 ValueObjectSP valobj_sp; 392 if (var_sp) 393 { 394 ValueObjectSP variable_valobj_sp(ValueObjectVariable::Create (scope, var_sp)); 395 if (variable_valobj_sp) 396 { 397 variable_expr_path += variable_name.size(); 398 if (*variable_expr_path) 399 { 400 const char* first_unparsed = NULL; 401 ValueObject::ExpressionPathScanEndReason reason_to_stop; 402 ValueObject::ExpressionPathEndResultType final_value_type; 403 ValueObject::GetValueForExpressionPathOptions options; 404 ValueObject::ExpressionPathAftermath final_task_on_target; 405 406 valobj_sp = variable_valobj_sp->GetValueForExpressionPath (variable_expr_path, 407 &first_unparsed, 408 &reason_to_stop, 409 &final_value_type, 410 options, 411 &final_task_on_target); 412 if (!valobj_sp) 413 { 414 error.SetErrorStringWithFormat ("invalid expression path '%s' for variable '%s'", 415 variable_expr_path, 416 var_sp->GetName().GetCString()); 417 } 418 } 419 else 420 { 421 // Just the name of a variable with no extras 422 valobj_sp = variable_valobj_sp; 423 } 424 } 425 } 426 427 if (!var_sp || !valobj_sp) 428 { 429 variable_list.RemoveVariableAtIndex (i); 430 } 431 else 432 { 433 valobj_list.Append(valobj_sp); 434 ++i; 435 } 436 } 437 438 if (variable_list.GetSize() > 0) 439 { 440 error.Clear(); 441 return error; 442 } 443 } 444 } 445 } 446 error.SetErrorStringWithFormat ("unable to extracta variable name from '%s'", variable_expr_path); 447 } 448 break; 449 } 450 } 451 error.SetErrorString ("unknown error"); 452 return error; 453 } 454 455 bool 456 Variable::DumpLocationForAddress (Stream *s, const Address &address) 457 { 458 // Be sure to resolve the address to section offset prior to 459 // calling this function. 460 if (address.IsSectionOffset()) 461 { 462 SymbolContext sc; 463 CalculateSymbolContext(&sc); 464 if (sc.module_sp.get() == address.GetModule()) 465 { 466 const addr_t file_addr = address.GetFileAddress(); 467 if (sc.function) 468 { 469 if (sc.function->GetAddressRange().ContainsFileAddress(address)) 470 { 471 addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); 472 if (loclist_base_file_addr == LLDB_INVALID_ADDRESS) 473 return false; 474 return m_location.DumpLocationForAddress (s, 475 eDescriptionLevelBrief, 476 loclist_base_file_addr, 477 file_addr); 478 } 479 } 480 return m_location.DumpLocationForAddress (s, 481 eDescriptionLevelBrief, 482 LLDB_INVALID_ADDRESS, 483 file_addr); 484 485 } 486 } 487 return false; 488 489 } 490 491