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 (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 Module *module = m_owner_scope->CalculateSymbolContextModule(); 150 abi = ABI::FindPlugin (module->GetArchitecture()).get(); 151 } 152 m_location.GetDescription(s, lldb::eDescriptionLevelBrief, loclist_base_addr, abi); 153 } 154 155 if (m_external) 156 s->PutCString(", external"); 157 158 if (m_artificial) 159 s->PutCString(", artificial"); 160 161 s->EOL(); 162 } 163 164 bool 165 Variable::DumpDeclaration (Stream *s, bool show_fullpaths, bool show_module) 166 { 167 bool dumped_declaration_info = false; 168 if (m_owner_scope) 169 { 170 SymbolContext sc; 171 m_owner_scope->CalculateSymbolContext(&sc); 172 sc.block = NULL; 173 sc.line_entry.Clear(); 174 bool show_inlined_frames = false; 175 176 dumped_declaration_info = sc.DumpStopContext (s, 177 NULL, 178 Address(), 179 show_fullpaths, 180 show_module, 181 show_inlined_frames); 182 183 if (sc.function) 184 s->PutChar(':'); 185 } 186 if (m_declaration.DumpStopContext (s, false)) 187 dumped_declaration_info = true; 188 return dumped_declaration_info; 189 } 190 191 size_t 192 Variable::MemorySize() const 193 { 194 return sizeof(Variable); 195 } 196 197 198 void 199 Variable::CalculateSymbolContext (SymbolContext *sc) 200 { 201 if (m_owner_scope) 202 m_owner_scope->CalculateSymbolContext(sc); 203 else 204 sc->Clear(); 205 } 206 207 bool 208 Variable::LocationIsValidForFrame (StackFrame *frame) 209 { 210 // Is the variable is described by a single location? 211 if (!m_location.IsLocationList()) 212 { 213 // Yes it is, the location is valid. 214 return true; 215 } 216 217 if (frame) 218 { 219 Target *target = &frame->GetThread().GetProcess().GetTarget(); 220 221 Function *function = frame->GetSymbolContext(eSymbolContextFunction).function; 222 if (function) 223 { 224 addr_t loclist_base_load_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress (target); 225 if (loclist_base_load_addr == LLDB_INVALID_ADDRESS) 226 return false; 227 // It is a location list. We just need to tell if the location 228 // list contains the current address when converted to a load 229 // address 230 return m_location.LocationListContainsAddress (loclist_base_load_addr, 231 frame->GetFrameCodeAddress().GetLoadAddress (target)); 232 } 233 } 234 return false; 235 } 236 237 bool 238 Variable::LocationIsValidForAddress (const Address &address) 239 { 240 // Be sure to resolve the address to section offset prior to 241 // calling this function. 242 if (address.IsSectionOffset()) 243 { 244 SymbolContext sc; 245 CalculateSymbolContext(&sc); 246 if (sc.module_sp.get() == address.GetModulePtr()) 247 { 248 // Is the variable is described by a single location? 249 if (!m_location.IsLocationList()) 250 { 251 // Yes it is, the location is valid. 252 return true; 253 } 254 255 if (sc.function) 256 { 257 addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); 258 if (loclist_base_file_addr == LLDB_INVALID_ADDRESS) 259 return false; 260 // It is a location list. We just need to tell if the location 261 // list contains the current address when converted to a load 262 // address 263 return m_location.LocationListContainsAddress (loclist_base_file_addr, 264 address.GetFileAddress()); 265 } 266 } 267 } 268 return false; 269 } 270 271 bool 272 Variable::IsInScope (StackFrame *frame) 273 { 274 switch (m_scope) 275 { 276 case eValueTypeRegister: 277 case eValueTypeRegisterSet: 278 return frame != NULL; 279 280 case eValueTypeConstResult: 281 case eValueTypeVariableGlobal: 282 case eValueTypeVariableStatic: 283 return true; 284 285 case eValueTypeVariableArgument: 286 case eValueTypeVariableLocal: 287 if (frame) 288 { 289 // We don't have a location list, we just need to see if the block 290 // that this variable was defined in is currently 291 Block *deepest_frame_block = frame->GetSymbolContext(eSymbolContextBlock).block; 292 if (deepest_frame_block) 293 { 294 SymbolContext variable_sc; 295 CalculateSymbolContext (&variable_sc); 296 // Check for static or global variable defined at the compile unit 297 // level that wasn't defined in a block 298 if (variable_sc.block == NULL) 299 return true; 300 301 if (variable_sc.block == deepest_frame_block) 302 return true; 303 return variable_sc.block->Contains (deepest_frame_block); 304 } 305 } 306 break; 307 308 default: 309 break; 310 } 311 return false; 312 } 313 314 Error 315 Variable::GetValuesForVariableExpressionPath (const char *variable_expr_path, 316 ExecutionContextScope *scope, 317 GetVariableCallback callback, 318 void *baton, 319 VariableList &variable_list, 320 ValueObjectList &valobj_list) 321 { 322 Error error; 323 if (variable_expr_path && callback) 324 { 325 switch (variable_expr_path[0]) 326 { 327 case '*': 328 { 329 error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1, 330 scope, 331 callback, 332 baton, 333 variable_list, 334 valobj_list); 335 if (error.Success()) 336 { 337 for (uint32_t i=0; i<valobj_list.GetSize(); ) 338 { 339 Error tmp_error; 340 ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->Dereference(tmp_error)); 341 if (tmp_error.Fail()) 342 { 343 variable_list.RemoveVariableAtIndex (i); 344 valobj_list.RemoveValueObjectAtIndex (i); 345 } 346 else 347 { 348 valobj_list.SetValueObjectAtIndex (i, valobj_sp); 349 ++i; 350 } 351 } 352 } 353 else 354 { 355 error.SetErrorString ("unknown error"); 356 } 357 return error; 358 } 359 break; 360 361 case '&': 362 { 363 error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1, 364 scope, 365 callback, 366 baton, 367 variable_list, 368 valobj_list); 369 if (error.Success()) 370 { 371 for (uint32_t i=0; i<valobj_list.GetSize(); ) 372 { 373 Error tmp_error; 374 ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->AddressOf(tmp_error)); 375 if (tmp_error.Fail()) 376 { 377 variable_list.RemoveVariableAtIndex (i); 378 valobj_list.RemoveValueObjectAtIndex (i); 379 } 380 else 381 { 382 valobj_list.SetValueObjectAtIndex (i, valobj_sp); 383 ++i; 384 } 385 } 386 } 387 else 388 { 389 error.SetErrorString ("unknown error"); 390 } 391 return error; 392 } 393 break; 394 395 default: 396 { 397 RegularExpression regex ("^([A-Za-z_:][A-Za-z_0-9:]*)(.*)"); 398 if (regex.Execute(variable_expr_path, 1)) 399 { 400 std::string variable_name; 401 if (regex.GetMatchAtIndex(variable_expr_path, 1, variable_name)) 402 { 403 variable_list.Clear(); 404 if (callback (baton, variable_name.c_str(), variable_list)) 405 { 406 uint32_t i=0; 407 while (i < variable_list.GetSize()) 408 { 409 VariableSP var_sp (variable_list.GetVariableAtIndex (i)); 410 ValueObjectSP valobj_sp; 411 if (var_sp) 412 { 413 ValueObjectSP variable_valobj_sp(ValueObjectVariable::Create (scope, var_sp)); 414 if (variable_valobj_sp) 415 { 416 variable_expr_path += variable_name.size(); 417 if (*variable_expr_path) 418 { 419 const char* first_unparsed = NULL; 420 ValueObject::ExpressionPathScanEndReason reason_to_stop; 421 ValueObject::ExpressionPathEndResultType final_value_type; 422 ValueObject::GetValueForExpressionPathOptions options; 423 ValueObject::ExpressionPathAftermath final_task_on_target; 424 425 valobj_sp = variable_valobj_sp->GetValueForExpressionPath (variable_expr_path, 426 &first_unparsed, 427 &reason_to_stop, 428 &final_value_type, 429 options, 430 &final_task_on_target); 431 if (!valobj_sp) 432 { 433 error.SetErrorStringWithFormat ("invalid expression path '%s' for variable '%s'", 434 variable_expr_path, 435 var_sp->GetName().GetCString()); 436 } 437 } 438 else 439 { 440 // Just the name of a variable with no extras 441 valobj_sp = variable_valobj_sp; 442 } 443 } 444 } 445 446 if (!var_sp || !valobj_sp) 447 { 448 variable_list.RemoveVariableAtIndex (i); 449 } 450 else 451 { 452 valobj_list.Append(valobj_sp); 453 ++i; 454 } 455 } 456 457 if (variable_list.GetSize() > 0) 458 { 459 error.Clear(); 460 return error; 461 } 462 } 463 } 464 } 465 error.SetErrorStringWithFormat ("unable to extracta variable name from '%s'", variable_expr_path); 466 } 467 break; 468 } 469 } 470 error.SetErrorString ("unknown error"); 471 return error; 472 } 473 474 bool 475 Variable::DumpLocationForAddress (Stream *s, const Address &address) 476 { 477 // Be sure to resolve the address to section offset prior to 478 // calling this function. 479 if (address.IsSectionOffset()) 480 { 481 SymbolContext sc; 482 CalculateSymbolContext(&sc); 483 if (sc.module_sp.get() == address.GetModulePtr()) 484 { 485 ABI *abi = NULL; 486 if (m_owner_scope) 487 { 488 Module *module = m_owner_scope->CalculateSymbolContextModule(); 489 abi = ABI::FindPlugin (module->GetArchitecture()).get(); 490 } 491 492 const addr_t file_addr = address.GetFileAddress(); 493 if (sc.function) 494 { 495 if (sc.function->GetAddressRange().ContainsFileAddress(address)) 496 { 497 addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); 498 if (loclist_base_file_addr == LLDB_INVALID_ADDRESS) 499 return false; 500 return m_location.DumpLocationForAddress (s, 501 eDescriptionLevelBrief, 502 loclist_base_file_addr, 503 file_addr, 504 abi); 505 } 506 } 507 return m_location.DumpLocationForAddress (s, 508 eDescriptionLevelBrief, 509 LLDB_INVALID_ADDRESS, 510 file_addr, 511 abi); 512 } 513 } 514 return false; 515 516 } 517 518