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