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