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