1 //===-- SBFrame.cpp -------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include <algorithm> 10 #include <set> 11 #include <string> 12 13 #include "lldb/API/SBFrame.h" 14 15 #include "lldb/lldb-types.h" 16 17 #include "Utils.h" 18 #include "lldb/Core/Address.h" 19 #include "lldb/Core/Debugger.h" 20 #include "lldb/Core/ValueObjectRegister.h" 21 #include "lldb/Core/ValueObjectVariable.h" 22 #include "lldb/Core/ValueObjectConstResult.h" 23 #include "lldb/Expression/ExpressionVariable.h" 24 #include "lldb/Expression/UserExpression.h" 25 #include "lldb/Host/Host.h" 26 #include "lldb/Symbol/Block.h" 27 #include "lldb/Symbol/Function.h" 28 #include "lldb/Symbol/Symbol.h" 29 #include "lldb/Symbol/SymbolContext.h" 30 #include "lldb/Symbol/Variable.h" 31 #include "lldb/Symbol/VariableList.h" 32 #include "lldb/Target/ExecutionContext.h" 33 #include "lldb/Target/Process.h" 34 #include "lldb/Target/RegisterContext.h" 35 #include "lldb/Target/StackFrame.h" 36 #include "lldb/Target/StackFrameRecognizer.h" 37 #include "lldb/Target/StackID.h" 38 #include "lldb/Target/Target.h" 39 #include "lldb/Target/Thread.h" 40 #include "lldb/Utility/ConstString.h" 41 #include "lldb/Utility/Instrumentation.h" 42 #include "lldb/Utility/LLDBLog.h" 43 #include "lldb/Utility/Stream.h" 44 45 #include "lldb/API/SBAddress.h" 46 #include "lldb/API/SBDebugger.h" 47 #include "lldb/API/SBExpressionOptions.h" 48 #include "lldb/API/SBFormat.h" 49 #include "lldb/API/SBStream.h" 50 #include "lldb/API/SBSymbolContext.h" 51 #include "lldb/API/SBThread.h" 52 #include "lldb/API/SBValue.h" 53 #include "lldb/API/SBVariablesOptions.h" 54 55 #include "llvm/Support/PrettyStackTrace.h" 56 57 using namespace lldb; 58 using namespace lldb_private; 59 60 SBFrame::SBFrame() : m_opaque_sp(new ExecutionContextRef()) { 61 LLDB_INSTRUMENT_VA(this); 62 } 63 64 SBFrame::SBFrame(const StackFrameSP &lldb_object_sp) 65 : m_opaque_sp(new ExecutionContextRef(lldb_object_sp)) { 66 LLDB_INSTRUMENT_VA(this, lldb_object_sp); 67 } 68 69 SBFrame::SBFrame(const SBFrame &rhs) { 70 LLDB_INSTRUMENT_VA(this, rhs); 71 72 m_opaque_sp = clone(rhs.m_opaque_sp); 73 } 74 75 SBFrame::~SBFrame() = default; 76 77 const SBFrame &SBFrame::operator=(const SBFrame &rhs) { 78 LLDB_INSTRUMENT_VA(this, rhs); 79 80 if (this != &rhs) 81 m_opaque_sp = clone(rhs.m_opaque_sp); 82 return *this; 83 } 84 85 StackFrameSP SBFrame::GetFrameSP() const { 86 return (m_opaque_sp ? m_opaque_sp->GetFrameSP() : StackFrameSP()); 87 } 88 89 void SBFrame::SetFrameSP(const StackFrameSP &lldb_object_sp) { 90 return m_opaque_sp->SetFrameSP(lldb_object_sp); 91 } 92 93 bool SBFrame::IsValid() const { 94 LLDB_INSTRUMENT_VA(this); 95 return this->operator bool(); 96 } 97 SBFrame::operator bool() const { 98 LLDB_INSTRUMENT_VA(this); 99 100 std::unique_lock<std::recursive_mutex> lock; 101 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 102 103 Target *target = exe_ctx.GetTargetPtr(); 104 Process *process = exe_ctx.GetProcessPtr(); 105 if (target && process) { 106 Process::StopLocker stop_locker; 107 if (stop_locker.TryLock(&process->GetRunLock())) 108 return GetFrameSP().get() != nullptr; 109 } 110 111 // Without a target & process we can't have a valid stack frame. 112 return false; 113 } 114 115 SBSymbolContext SBFrame::GetSymbolContext(uint32_t resolve_scope) const { 116 LLDB_INSTRUMENT_VA(this, resolve_scope); 117 118 SBSymbolContext sb_sym_ctx; 119 std::unique_lock<std::recursive_mutex> lock; 120 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 121 SymbolContextItem scope = static_cast<SymbolContextItem>(resolve_scope); 122 Target *target = exe_ctx.GetTargetPtr(); 123 Process *process = exe_ctx.GetProcessPtr(); 124 if (target && process) { 125 Process::StopLocker stop_locker; 126 if (stop_locker.TryLock(&process->GetRunLock())) { 127 if (StackFrame *frame = exe_ctx.GetFramePtr()) 128 sb_sym_ctx = frame->GetSymbolContext(scope); 129 } 130 } 131 132 return sb_sym_ctx; 133 } 134 135 SBModule SBFrame::GetModule() const { 136 LLDB_INSTRUMENT_VA(this); 137 138 SBModule sb_module; 139 ModuleSP module_sp; 140 std::unique_lock<std::recursive_mutex> lock; 141 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 142 143 StackFrame *frame = nullptr; 144 Target *target = exe_ctx.GetTargetPtr(); 145 Process *process = exe_ctx.GetProcessPtr(); 146 if (target && process) { 147 Process::StopLocker stop_locker; 148 if (stop_locker.TryLock(&process->GetRunLock())) { 149 frame = exe_ctx.GetFramePtr(); 150 if (frame) { 151 module_sp = frame->GetSymbolContext(eSymbolContextModule).module_sp; 152 sb_module.SetSP(module_sp); 153 } 154 } 155 } 156 157 return sb_module; 158 } 159 160 SBCompileUnit SBFrame::GetCompileUnit() const { 161 LLDB_INSTRUMENT_VA(this); 162 163 SBCompileUnit sb_comp_unit; 164 std::unique_lock<std::recursive_mutex> lock; 165 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 166 167 StackFrame *frame = nullptr; 168 Target *target = exe_ctx.GetTargetPtr(); 169 Process *process = exe_ctx.GetProcessPtr(); 170 if (target && process) { 171 Process::StopLocker stop_locker; 172 if (stop_locker.TryLock(&process->GetRunLock())) { 173 frame = exe_ctx.GetFramePtr(); 174 if (frame) { 175 sb_comp_unit.reset( 176 frame->GetSymbolContext(eSymbolContextCompUnit).comp_unit); 177 } 178 } 179 } 180 181 return sb_comp_unit; 182 } 183 184 SBFunction SBFrame::GetFunction() const { 185 LLDB_INSTRUMENT_VA(this); 186 187 SBFunction sb_function; 188 std::unique_lock<std::recursive_mutex> lock; 189 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 190 191 StackFrame *frame = nullptr; 192 Target *target = exe_ctx.GetTargetPtr(); 193 Process *process = exe_ctx.GetProcessPtr(); 194 if (target && process) { 195 Process::StopLocker stop_locker; 196 if (stop_locker.TryLock(&process->GetRunLock())) { 197 frame = exe_ctx.GetFramePtr(); 198 if (frame) { 199 sb_function.reset( 200 frame->GetSymbolContext(eSymbolContextFunction).function); 201 } 202 } 203 } 204 205 return sb_function; 206 } 207 208 SBSymbol SBFrame::GetSymbol() const { 209 LLDB_INSTRUMENT_VA(this); 210 211 SBSymbol sb_symbol; 212 std::unique_lock<std::recursive_mutex> lock; 213 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 214 215 StackFrame *frame = nullptr; 216 Target *target = exe_ctx.GetTargetPtr(); 217 Process *process = exe_ctx.GetProcessPtr(); 218 if (target && process) { 219 Process::StopLocker stop_locker; 220 if (stop_locker.TryLock(&process->GetRunLock())) { 221 frame = exe_ctx.GetFramePtr(); 222 if (frame) { 223 sb_symbol.reset(frame->GetSymbolContext(eSymbolContextSymbol).symbol); 224 } 225 } 226 } 227 228 return sb_symbol; 229 } 230 231 SBBlock SBFrame::GetBlock() const { 232 LLDB_INSTRUMENT_VA(this); 233 234 SBBlock sb_block; 235 std::unique_lock<std::recursive_mutex> lock; 236 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 237 238 StackFrame *frame = nullptr; 239 Target *target = exe_ctx.GetTargetPtr(); 240 Process *process = exe_ctx.GetProcessPtr(); 241 if (target && process) { 242 Process::StopLocker stop_locker; 243 if (stop_locker.TryLock(&process->GetRunLock())) { 244 frame = exe_ctx.GetFramePtr(); 245 if (frame) 246 sb_block.SetPtr(frame->GetSymbolContext(eSymbolContextBlock).block); 247 } 248 } 249 return sb_block; 250 } 251 252 SBBlock SBFrame::GetFrameBlock() const { 253 LLDB_INSTRUMENT_VA(this); 254 255 SBBlock sb_block; 256 std::unique_lock<std::recursive_mutex> lock; 257 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 258 259 StackFrame *frame = nullptr; 260 Target *target = exe_ctx.GetTargetPtr(); 261 Process *process = exe_ctx.GetProcessPtr(); 262 if (target && process) { 263 Process::StopLocker stop_locker; 264 if (stop_locker.TryLock(&process->GetRunLock())) { 265 frame = exe_ctx.GetFramePtr(); 266 if (frame) 267 sb_block.SetPtr(frame->GetFrameBlock()); 268 } 269 } 270 return sb_block; 271 } 272 273 SBLineEntry SBFrame::GetLineEntry() const { 274 LLDB_INSTRUMENT_VA(this); 275 276 SBLineEntry sb_line_entry; 277 std::unique_lock<std::recursive_mutex> lock; 278 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 279 280 StackFrame *frame = nullptr; 281 Target *target = exe_ctx.GetTargetPtr(); 282 Process *process = exe_ctx.GetProcessPtr(); 283 if (target && process) { 284 Process::StopLocker stop_locker; 285 if (stop_locker.TryLock(&process->GetRunLock())) { 286 frame = exe_ctx.GetFramePtr(); 287 if (frame) { 288 sb_line_entry.SetLineEntry( 289 frame->GetSymbolContext(eSymbolContextLineEntry).line_entry); 290 } 291 } 292 } 293 return sb_line_entry; 294 } 295 296 uint32_t SBFrame::GetFrameID() const { 297 LLDB_INSTRUMENT_VA(this); 298 299 uint32_t frame_idx = UINT32_MAX; 300 301 std::unique_lock<std::recursive_mutex> lock; 302 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 303 304 StackFrame *frame = exe_ctx.GetFramePtr(); 305 if (frame) 306 frame_idx = frame->GetFrameIndex(); 307 308 return frame_idx; 309 } 310 311 lldb::addr_t SBFrame::GetCFA() const { 312 LLDB_INSTRUMENT_VA(this); 313 314 std::unique_lock<std::recursive_mutex> lock; 315 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 316 317 StackFrame *frame = exe_ctx.GetFramePtr(); 318 if (frame) 319 return frame->GetStackID().GetCallFrameAddress(); 320 return LLDB_INVALID_ADDRESS; 321 } 322 323 addr_t SBFrame::GetPC() const { 324 LLDB_INSTRUMENT_VA(this); 325 326 addr_t addr = LLDB_INVALID_ADDRESS; 327 std::unique_lock<std::recursive_mutex> lock; 328 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 329 330 StackFrame *frame = nullptr; 331 Target *target = exe_ctx.GetTargetPtr(); 332 Process *process = exe_ctx.GetProcessPtr(); 333 if (target && process) { 334 Process::StopLocker stop_locker; 335 if (stop_locker.TryLock(&process->GetRunLock())) { 336 frame = exe_ctx.GetFramePtr(); 337 if (frame) { 338 addr = frame->GetFrameCodeAddress().GetOpcodeLoadAddress( 339 target, AddressClass::eCode); 340 } 341 } 342 } 343 344 return addr; 345 } 346 347 bool SBFrame::SetPC(addr_t new_pc) { 348 LLDB_INSTRUMENT_VA(this, new_pc); 349 350 bool ret_val = false; 351 std::unique_lock<std::recursive_mutex> lock; 352 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 353 354 Target *target = exe_ctx.GetTargetPtr(); 355 Process *process = exe_ctx.GetProcessPtr(); 356 if (target && process) { 357 Process::StopLocker stop_locker; 358 if (stop_locker.TryLock(&process->GetRunLock())) { 359 if (StackFrame *frame = exe_ctx.GetFramePtr()) { 360 if (RegisterContextSP reg_ctx_sp = frame->GetRegisterContext()) { 361 ret_val = reg_ctx_sp->SetPC(new_pc); 362 } 363 } 364 } 365 } 366 367 return ret_val; 368 } 369 370 addr_t SBFrame::GetSP() const { 371 LLDB_INSTRUMENT_VA(this); 372 373 addr_t addr = LLDB_INVALID_ADDRESS; 374 std::unique_lock<std::recursive_mutex> lock; 375 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 376 377 Target *target = exe_ctx.GetTargetPtr(); 378 Process *process = exe_ctx.GetProcessPtr(); 379 if (target && process) { 380 Process::StopLocker stop_locker; 381 if (stop_locker.TryLock(&process->GetRunLock())) { 382 if (StackFrame *frame = exe_ctx.GetFramePtr()) { 383 if (RegisterContextSP reg_ctx_sp = frame->GetRegisterContext()) { 384 addr = reg_ctx_sp->GetSP(); 385 } 386 } 387 } 388 } 389 390 return addr; 391 } 392 393 addr_t SBFrame::GetFP() const { 394 LLDB_INSTRUMENT_VA(this); 395 396 addr_t addr = LLDB_INVALID_ADDRESS; 397 std::unique_lock<std::recursive_mutex> lock; 398 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 399 400 Target *target = exe_ctx.GetTargetPtr(); 401 Process *process = exe_ctx.GetProcessPtr(); 402 if (target && process) { 403 Process::StopLocker stop_locker; 404 if (stop_locker.TryLock(&process->GetRunLock())) { 405 if (StackFrame *frame = exe_ctx.GetFramePtr()) { 406 if (RegisterContextSP reg_ctx_sp = frame->GetRegisterContext()) { 407 addr = reg_ctx_sp->GetFP(); 408 } 409 } 410 } 411 } 412 413 return addr; 414 } 415 416 SBAddress SBFrame::GetPCAddress() const { 417 LLDB_INSTRUMENT_VA(this); 418 419 SBAddress sb_addr; 420 std::unique_lock<std::recursive_mutex> lock; 421 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 422 423 StackFrame *frame = exe_ctx.GetFramePtr(); 424 Target *target = exe_ctx.GetTargetPtr(); 425 Process *process = exe_ctx.GetProcessPtr(); 426 if (target && process) { 427 Process::StopLocker stop_locker; 428 if (stop_locker.TryLock(&process->GetRunLock())) { 429 frame = exe_ctx.GetFramePtr(); 430 if (frame) 431 sb_addr.SetAddress(frame->GetFrameCodeAddress()); 432 } 433 } 434 return sb_addr; 435 } 436 437 void SBFrame::Clear() { 438 LLDB_INSTRUMENT_VA(this); 439 440 m_opaque_sp->Clear(); 441 } 442 443 lldb::SBValue SBFrame::GetValueForVariablePath(const char *var_path) { 444 LLDB_INSTRUMENT_VA(this, var_path); 445 446 SBValue sb_value; 447 std::unique_lock<std::recursive_mutex> lock; 448 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 449 450 StackFrame *frame = exe_ctx.GetFramePtr(); 451 Target *target = exe_ctx.GetTargetPtr(); 452 if (frame && target) { 453 lldb::DynamicValueType use_dynamic = 454 frame->CalculateTarget()->GetPreferDynamicValue(); 455 sb_value = GetValueForVariablePath(var_path, use_dynamic); 456 } 457 return sb_value; 458 } 459 460 lldb::SBValue SBFrame::GetValueForVariablePath(const char *var_path, 461 DynamicValueType use_dynamic) { 462 LLDB_INSTRUMENT_VA(this, var_path, use_dynamic); 463 464 SBValue sb_value; 465 if (var_path == nullptr || var_path[0] == '\0') { 466 return sb_value; 467 } 468 469 std::unique_lock<std::recursive_mutex> lock; 470 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 471 472 StackFrame *frame = nullptr; 473 Target *target = exe_ctx.GetTargetPtr(); 474 Process *process = exe_ctx.GetProcessPtr(); 475 if (target && process) { 476 Process::StopLocker stop_locker; 477 if (stop_locker.TryLock(&process->GetRunLock())) { 478 frame = exe_ctx.GetFramePtr(); 479 if (frame) { 480 VariableSP var_sp; 481 Status error; 482 ValueObjectSP value_sp(frame->GetValueForVariableExpressionPath( 483 var_path, eNoDynamicValues, 484 StackFrame::eExpressionPathOptionCheckPtrVsMember | 485 StackFrame::eExpressionPathOptionsAllowDirectIVarAccess, 486 var_sp, error)); 487 sb_value.SetSP(value_sp, use_dynamic); 488 } 489 } 490 } 491 return sb_value; 492 } 493 494 SBValue SBFrame::FindVariable(const char *name) { 495 LLDB_INSTRUMENT_VA(this, name); 496 497 SBValue value; 498 std::unique_lock<std::recursive_mutex> lock; 499 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 500 501 StackFrame *frame = exe_ctx.GetFramePtr(); 502 Target *target = exe_ctx.GetTargetPtr(); 503 if (frame && target) { 504 lldb::DynamicValueType use_dynamic = 505 frame->CalculateTarget()->GetPreferDynamicValue(); 506 value = FindVariable(name, use_dynamic); 507 } 508 return value; 509 } 510 511 SBValue SBFrame::FindVariable(const char *name, 512 lldb::DynamicValueType use_dynamic) { 513 LLDB_INSTRUMENT_VA(this, name, use_dynamic); 514 515 VariableSP var_sp; 516 SBValue sb_value; 517 518 if (name == nullptr || name[0] == '\0') { 519 return sb_value; 520 } 521 522 ValueObjectSP value_sp; 523 std::unique_lock<std::recursive_mutex> lock; 524 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 525 526 StackFrame *frame = nullptr; 527 Target *target = exe_ctx.GetTargetPtr(); 528 Process *process = exe_ctx.GetProcessPtr(); 529 if (target && process) { 530 Process::StopLocker stop_locker; 531 if (stop_locker.TryLock(&process->GetRunLock())) { 532 frame = exe_ctx.GetFramePtr(); 533 if (frame) { 534 value_sp = frame->FindVariable(ConstString(name)); 535 536 if (value_sp) 537 sb_value.SetSP(value_sp, use_dynamic); 538 } 539 } 540 } 541 542 return sb_value; 543 } 544 545 SBValue SBFrame::FindValue(const char *name, ValueType value_type) { 546 LLDB_INSTRUMENT_VA(this, name, value_type); 547 548 SBValue value; 549 std::unique_lock<std::recursive_mutex> lock; 550 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 551 552 StackFrame *frame = exe_ctx.GetFramePtr(); 553 Target *target = exe_ctx.GetTargetPtr(); 554 if (frame && target) { 555 lldb::DynamicValueType use_dynamic = 556 frame->CalculateTarget()->GetPreferDynamicValue(); 557 value = FindValue(name, value_type, use_dynamic); 558 } 559 return value; 560 } 561 562 SBValue SBFrame::FindValue(const char *name, ValueType value_type, 563 lldb::DynamicValueType use_dynamic) { 564 LLDB_INSTRUMENT_VA(this, name, value_type, use_dynamic); 565 566 SBValue sb_value; 567 568 if (name == nullptr || name[0] == '\0') { 569 return sb_value; 570 } 571 572 ValueObjectSP value_sp; 573 std::unique_lock<std::recursive_mutex> lock; 574 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 575 576 StackFrame *frame = nullptr; 577 Target *target = exe_ctx.GetTargetPtr(); 578 Process *process = exe_ctx.GetProcessPtr(); 579 if (target && process) { 580 Process::StopLocker stop_locker; 581 if (stop_locker.TryLock(&process->GetRunLock())) { 582 frame = exe_ctx.GetFramePtr(); 583 if (frame) { 584 VariableList variable_list; 585 586 switch (value_type) { 587 case eValueTypeVariableGlobal: // global variable 588 case eValueTypeVariableStatic: // static variable 589 case eValueTypeVariableArgument: // function argument variables 590 case eValueTypeVariableLocal: // function local variables 591 case eValueTypeVariableThreadLocal: // thread local variables 592 { 593 SymbolContext sc(frame->GetSymbolContext(eSymbolContextBlock)); 594 595 const bool can_create = true; 596 const bool get_parent_variables = true; 597 const bool stop_if_block_is_inlined_function = true; 598 599 if (sc.block) 600 sc.block->AppendVariables( 601 can_create, get_parent_variables, 602 stop_if_block_is_inlined_function, 603 [frame](Variable *v) { return v->IsInScope(frame); }, 604 &variable_list); 605 if (value_type == eValueTypeVariableGlobal 606 || value_type == eValueTypeVariableStatic) { 607 const bool get_file_globals = true; 608 VariableList *frame_vars = frame->GetVariableList(get_file_globals, 609 nullptr); 610 if (frame_vars) 611 frame_vars->AppendVariablesIfUnique(variable_list); 612 } 613 ConstString const_name(name); 614 VariableSP variable_sp( 615 variable_list.FindVariable(const_name, value_type)); 616 if (variable_sp) { 617 value_sp = frame->GetValueObjectForFrameVariable(variable_sp, 618 eNoDynamicValues); 619 sb_value.SetSP(value_sp, use_dynamic); 620 } 621 } break; 622 623 case eValueTypeRegister: // stack frame register value 624 { 625 RegisterContextSP reg_ctx(frame->GetRegisterContext()); 626 if (reg_ctx) { 627 if (const RegisterInfo *reg_info = 628 reg_ctx->GetRegisterInfoByName(name)) { 629 value_sp = ValueObjectRegister::Create(frame, reg_ctx, reg_info); 630 sb_value.SetSP(value_sp); 631 } 632 } 633 } break; 634 635 case eValueTypeRegisterSet: // A collection of stack frame register 636 // values 637 { 638 RegisterContextSP reg_ctx(frame->GetRegisterContext()); 639 if (reg_ctx) { 640 const uint32_t num_sets = reg_ctx->GetRegisterSetCount(); 641 for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx) { 642 const RegisterSet *reg_set = reg_ctx->GetRegisterSet(set_idx); 643 if (reg_set && 644 (llvm::StringRef(reg_set->name).equals_insensitive(name) || 645 llvm::StringRef(reg_set->short_name) 646 .equals_insensitive(name))) { 647 value_sp = 648 ValueObjectRegisterSet::Create(frame, reg_ctx, set_idx); 649 sb_value.SetSP(value_sp); 650 break; 651 } 652 } 653 } 654 } break; 655 656 case eValueTypeConstResult: // constant result variables 657 { 658 ConstString const_name(name); 659 ExpressionVariableSP expr_var_sp( 660 target->GetPersistentVariable(const_name)); 661 if (expr_var_sp) { 662 value_sp = expr_var_sp->GetValueObject(); 663 sb_value.SetSP(value_sp, use_dynamic); 664 } 665 } break; 666 667 default: 668 break; 669 } 670 } 671 } 672 } 673 674 return sb_value; 675 } 676 677 bool SBFrame::IsEqual(const SBFrame &that) const { 678 LLDB_INSTRUMENT_VA(this, that); 679 680 lldb::StackFrameSP this_sp = GetFrameSP(); 681 lldb::StackFrameSP that_sp = that.GetFrameSP(); 682 return (this_sp && that_sp && this_sp->GetStackID() == that_sp->GetStackID()); 683 } 684 685 bool SBFrame::operator==(const SBFrame &rhs) const { 686 LLDB_INSTRUMENT_VA(this, rhs); 687 688 return IsEqual(rhs); 689 } 690 691 bool SBFrame::operator!=(const SBFrame &rhs) const { 692 LLDB_INSTRUMENT_VA(this, rhs); 693 694 return !IsEqual(rhs); 695 } 696 697 SBThread SBFrame::GetThread() const { 698 LLDB_INSTRUMENT_VA(this); 699 700 std::unique_lock<std::recursive_mutex> lock; 701 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 702 703 ThreadSP thread_sp(exe_ctx.GetThreadSP()); 704 SBThread sb_thread(thread_sp); 705 706 return sb_thread; 707 } 708 709 const char *SBFrame::Disassemble() const { 710 LLDB_INSTRUMENT_VA(this); 711 712 std::unique_lock<std::recursive_mutex> lock; 713 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 714 Target *target = exe_ctx.GetTargetPtr(); 715 Process *process = exe_ctx.GetProcessPtr(); 716 if (!target || !process) 717 return nullptr; 718 719 Process::StopLocker stop_locker; 720 if (stop_locker.TryLock(&process->GetRunLock())) { 721 if (auto *frame = exe_ctx.GetFramePtr()) 722 return ConstString(frame->Disassemble()).GetCString(); 723 } 724 725 return nullptr; 726 } 727 728 SBValueList SBFrame::GetVariables(bool arguments, bool locals, bool statics, 729 bool in_scope_only) { 730 LLDB_INSTRUMENT_VA(this, arguments, locals, statics, in_scope_only); 731 732 SBValueList value_list; 733 std::unique_lock<std::recursive_mutex> lock; 734 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 735 736 StackFrame *frame = exe_ctx.GetFramePtr(); 737 Target *target = exe_ctx.GetTargetPtr(); 738 if (frame && target) { 739 lldb::DynamicValueType use_dynamic = 740 frame->CalculateTarget()->GetPreferDynamicValue(); 741 const bool include_runtime_support_values = 742 target->GetDisplayRuntimeSupportValues(); 743 744 SBVariablesOptions options; 745 options.SetIncludeArguments(arguments); 746 options.SetIncludeLocals(locals); 747 options.SetIncludeStatics(statics); 748 options.SetInScopeOnly(in_scope_only); 749 options.SetIncludeRuntimeSupportValues(include_runtime_support_values); 750 options.SetUseDynamic(use_dynamic); 751 752 value_list = GetVariables(options); 753 } 754 return value_list; 755 } 756 757 lldb::SBValueList SBFrame::GetVariables(bool arguments, bool locals, 758 bool statics, bool in_scope_only, 759 lldb::DynamicValueType use_dynamic) { 760 LLDB_INSTRUMENT_VA(this, arguments, locals, statics, in_scope_only, 761 use_dynamic); 762 763 std::unique_lock<std::recursive_mutex> lock; 764 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 765 766 Target *target = exe_ctx.GetTargetPtr(); 767 const bool include_runtime_support_values = 768 target ? target->GetDisplayRuntimeSupportValues() : false; 769 SBVariablesOptions options; 770 options.SetIncludeArguments(arguments); 771 options.SetIncludeLocals(locals); 772 options.SetIncludeStatics(statics); 773 options.SetInScopeOnly(in_scope_only); 774 options.SetIncludeRuntimeSupportValues(include_runtime_support_values); 775 options.SetUseDynamic(use_dynamic); 776 return GetVariables(options); 777 } 778 779 SBValueList SBFrame::GetVariables(const lldb::SBVariablesOptions &options) { 780 LLDB_INSTRUMENT_VA(this, options); 781 782 SBValueList value_list; 783 std::unique_lock<std::recursive_mutex> lock; 784 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 785 786 StackFrame *frame = nullptr; 787 Target *target = exe_ctx.GetTargetPtr(); 788 789 const bool statics = options.GetIncludeStatics(); 790 const bool arguments = options.GetIncludeArguments(); 791 const bool recognized_arguments = 792 options.GetIncludeRecognizedArguments(SBTarget(exe_ctx.GetTargetSP())); 793 const bool locals = options.GetIncludeLocals(); 794 const bool in_scope_only = options.GetInScopeOnly(); 795 const bool include_runtime_support_values = 796 options.GetIncludeRuntimeSupportValues(); 797 const lldb::DynamicValueType use_dynamic = options.GetUseDynamic(); 798 799 800 std::set<VariableSP> variable_set; 801 Process *process = exe_ctx.GetProcessPtr(); 802 if (target && process) { 803 Process::StopLocker stop_locker; 804 if (stop_locker.TryLock(&process->GetRunLock())) { 805 frame = exe_ctx.GetFramePtr(); 806 if (frame) { 807 Debugger &dbg = process->GetTarget().GetDebugger(); 808 VariableList *variable_list = nullptr; 809 Status var_error; 810 variable_list = frame->GetVariableList(true, &var_error); 811 if (var_error.Fail()) 812 value_list.SetError(var_error); 813 if (variable_list) { 814 const size_t num_variables = variable_list->GetSize(); 815 if (num_variables) { 816 size_t num_produced = 0; 817 for (const VariableSP &variable_sp : *variable_list) { 818 if (INTERRUPT_REQUESTED(dbg, 819 "Interrupted getting frame variables with {0} of {1} " 820 "produced.", num_produced, num_variables)) 821 return {}; 822 823 if (variable_sp) { 824 bool add_variable = false; 825 switch (variable_sp->GetScope()) { 826 case eValueTypeVariableGlobal: 827 case eValueTypeVariableStatic: 828 case eValueTypeVariableThreadLocal: 829 add_variable = statics; 830 break; 831 832 case eValueTypeVariableArgument: 833 add_variable = arguments; 834 break; 835 836 case eValueTypeVariableLocal: 837 add_variable = locals; 838 break; 839 840 default: 841 break; 842 } 843 if (add_variable) { 844 // Only add variables once so we don't end up with duplicates 845 if (variable_set.find(variable_sp) == variable_set.end()) 846 variable_set.insert(variable_sp); 847 else 848 continue; 849 850 if (in_scope_only && !variable_sp->IsInScope(frame)) 851 continue; 852 853 ValueObjectSP valobj_sp(frame->GetValueObjectForFrameVariable( 854 variable_sp, eNoDynamicValues)); 855 856 if (!include_runtime_support_values && valobj_sp != nullptr && 857 valobj_sp->IsRuntimeSupportValue()) 858 continue; 859 860 SBValue value_sb; 861 value_sb.SetSP(valobj_sp, use_dynamic); 862 value_list.Append(value_sb); 863 } 864 } 865 } 866 num_produced++; 867 } 868 } 869 if (recognized_arguments) { 870 auto recognized_frame = frame->GetRecognizedFrame(); 871 if (recognized_frame) { 872 ValueObjectListSP recognized_arg_list = 873 recognized_frame->GetRecognizedArguments(); 874 if (recognized_arg_list) { 875 for (auto &rec_value_sp : recognized_arg_list->GetObjects()) { 876 SBValue value_sb; 877 value_sb.SetSP(rec_value_sp, use_dynamic); 878 value_list.Append(value_sb); 879 } 880 } 881 } 882 } 883 } 884 } 885 } 886 887 return value_list; 888 } 889 890 SBValueList SBFrame::GetRegisters() { 891 LLDB_INSTRUMENT_VA(this); 892 893 SBValueList value_list; 894 std::unique_lock<std::recursive_mutex> lock; 895 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 896 897 StackFrame *frame = nullptr; 898 Target *target = exe_ctx.GetTargetPtr(); 899 Process *process = exe_ctx.GetProcessPtr(); 900 if (target && process) { 901 Process::StopLocker stop_locker; 902 if (stop_locker.TryLock(&process->GetRunLock())) { 903 frame = exe_ctx.GetFramePtr(); 904 if (frame) { 905 RegisterContextSP reg_ctx(frame->GetRegisterContext()); 906 if (reg_ctx) { 907 const uint32_t num_sets = reg_ctx->GetRegisterSetCount(); 908 for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx) { 909 value_list.Append( 910 ValueObjectRegisterSet::Create(frame, reg_ctx, set_idx)); 911 } 912 } 913 } 914 } 915 } 916 917 return value_list; 918 } 919 920 SBValue SBFrame::FindRegister(const char *name) { 921 LLDB_INSTRUMENT_VA(this, name); 922 923 SBValue result; 924 ValueObjectSP value_sp; 925 std::unique_lock<std::recursive_mutex> lock; 926 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 927 928 StackFrame *frame = nullptr; 929 Target *target = exe_ctx.GetTargetPtr(); 930 Process *process = exe_ctx.GetProcessPtr(); 931 if (target && process) { 932 Process::StopLocker stop_locker; 933 if (stop_locker.TryLock(&process->GetRunLock())) { 934 frame = exe_ctx.GetFramePtr(); 935 if (frame) { 936 RegisterContextSP reg_ctx(frame->GetRegisterContext()); 937 if (reg_ctx) { 938 if (const RegisterInfo *reg_info = 939 reg_ctx->GetRegisterInfoByName(name)) { 940 value_sp = ValueObjectRegister::Create(frame, reg_ctx, reg_info); 941 result.SetSP(value_sp); 942 } 943 } 944 } 945 } 946 } 947 948 return result; 949 } 950 951 SBError SBFrame::GetDescriptionWithFormat(const SBFormat &format, 952 SBStream &output) { 953 Stream &strm = output.ref(); 954 955 std::unique_lock<std::recursive_mutex> lock; 956 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 957 958 StackFrame *frame = nullptr; 959 Target *target = exe_ctx.GetTargetPtr(); 960 Process *process = exe_ctx.GetProcessPtr(); 961 SBError error; 962 963 if (!format) { 964 error.SetErrorString("The provided SBFormat object is invalid"); 965 return error; 966 } 967 968 if (target && process) { 969 Process::StopLocker stop_locker; 970 if (stop_locker.TryLock(&process->GetRunLock())) { 971 frame = exe_ctx.GetFramePtr(); 972 if (frame && 973 frame->DumpUsingFormat(strm, format.GetFormatEntrySP().get())) { 974 return error; 975 } 976 } 977 } 978 error.SetErrorStringWithFormat( 979 "It was not possible to generate a frame " 980 "description with the given format string '%s'", 981 format.GetFormatEntrySP()->string.c_str()); 982 return error; 983 } 984 985 bool SBFrame::GetDescription(SBStream &description) { 986 LLDB_INSTRUMENT_VA(this, description); 987 988 Stream &strm = description.ref(); 989 990 std::unique_lock<std::recursive_mutex> lock; 991 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 992 993 StackFrame *frame; 994 Target *target = exe_ctx.GetTargetPtr(); 995 Process *process = exe_ctx.GetProcessPtr(); 996 if (target && process) { 997 Process::StopLocker stop_locker; 998 if (stop_locker.TryLock(&process->GetRunLock())) { 999 frame = exe_ctx.GetFramePtr(); 1000 if (frame) { 1001 frame->DumpUsingSettingsFormat(&strm); 1002 } 1003 } 1004 1005 } else 1006 strm.PutCString("No value"); 1007 1008 return true; 1009 } 1010 1011 SBValue SBFrame::EvaluateExpression(const char *expr) { 1012 LLDB_INSTRUMENT_VA(this, expr); 1013 1014 SBValue result; 1015 std::unique_lock<std::recursive_mutex> lock; 1016 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 1017 1018 StackFrame *frame = exe_ctx.GetFramePtr(); 1019 Target *target = exe_ctx.GetTargetPtr(); 1020 if (frame && target) { 1021 SBExpressionOptions options; 1022 lldb::DynamicValueType fetch_dynamic_value = 1023 frame->CalculateTarget()->GetPreferDynamicValue(); 1024 options.SetFetchDynamicValue(fetch_dynamic_value); 1025 options.SetUnwindOnError(true); 1026 options.SetIgnoreBreakpoints(true); 1027 if (target->GetLanguage() != eLanguageTypeUnknown) 1028 options.SetLanguage(target->GetLanguage()); 1029 else 1030 options.SetLanguage(frame->GetLanguage()); 1031 return EvaluateExpression(expr, options); 1032 } else { 1033 Status error; 1034 error.SetErrorString("can't evaluate expressions when the " 1035 "process is running."); 1036 ValueObjectSP error_val_sp = ValueObjectConstResult::Create(nullptr, error); 1037 result.SetSP(error_val_sp, false); 1038 } 1039 return result; 1040 } 1041 1042 SBValue 1043 SBFrame::EvaluateExpression(const char *expr, 1044 lldb::DynamicValueType fetch_dynamic_value) { 1045 LLDB_INSTRUMENT_VA(this, expr, fetch_dynamic_value); 1046 1047 SBExpressionOptions options; 1048 options.SetFetchDynamicValue(fetch_dynamic_value); 1049 options.SetUnwindOnError(true); 1050 options.SetIgnoreBreakpoints(true); 1051 std::unique_lock<std::recursive_mutex> lock; 1052 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 1053 1054 StackFrame *frame = exe_ctx.GetFramePtr(); 1055 Target *target = exe_ctx.GetTargetPtr(); 1056 if (target && target->GetLanguage() != eLanguageTypeUnknown) 1057 options.SetLanguage(target->GetLanguage()); 1058 else if (frame) 1059 options.SetLanguage(frame->GetLanguage()); 1060 return EvaluateExpression(expr, options); 1061 } 1062 1063 SBValue SBFrame::EvaluateExpression(const char *expr, 1064 lldb::DynamicValueType fetch_dynamic_value, 1065 bool unwind_on_error) { 1066 LLDB_INSTRUMENT_VA(this, expr, fetch_dynamic_value, unwind_on_error); 1067 1068 SBExpressionOptions options; 1069 std::unique_lock<std::recursive_mutex> lock; 1070 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 1071 1072 options.SetFetchDynamicValue(fetch_dynamic_value); 1073 options.SetUnwindOnError(unwind_on_error); 1074 options.SetIgnoreBreakpoints(true); 1075 StackFrame *frame = exe_ctx.GetFramePtr(); 1076 Target *target = exe_ctx.GetTargetPtr(); 1077 if (target && target->GetLanguage() != eLanguageTypeUnknown) 1078 options.SetLanguage(target->GetLanguage()); 1079 else if (frame) 1080 options.SetLanguage(frame->GetLanguage()); 1081 return EvaluateExpression(expr, options); 1082 } 1083 1084 lldb::SBValue SBFrame::EvaluateExpression(const char *expr, 1085 const SBExpressionOptions &options) { 1086 LLDB_INSTRUMENT_VA(this, expr, options); 1087 1088 Log *expr_log = GetLog(LLDBLog::Expressions); 1089 1090 SBValue expr_result; 1091 1092 if (expr == nullptr || expr[0] == '\0') { 1093 return expr_result; 1094 } 1095 1096 ValueObjectSP expr_value_sp; 1097 1098 std::unique_lock<std::recursive_mutex> lock; 1099 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 1100 1101 StackFrame *frame = nullptr; 1102 Target *target = exe_ctx.GetTargetPtr(); 1103 Process *process = exe_ctx.GetProcessPtr(); 1104 1105 if (target && process) { 1106 Process::StopLocker stop_locker; 1107 if (stop_locker.TryLock(&process->GetRunLock())) { 1108 frame = exe_ctx.GetFramePtr(); 1109 if (frame) { 1110 std::unique_ptr<llvm::PrettyStackTraceFormat> stack_trace; 1111 if (target->GetDisplayExpressionsInCrashlogs()) { 1112 StreamString frame_description; 1113 frame->DumpUsingSettingsFormat(&frame_description); 1114 stack_trace = std::make_unique<llvm::PrettyStackTraceFormat>( 1115 "SBFrame::EvaluateExpression (expr = \"%s\", fetch_dynamic_value " 1116 "= %u) %s", 1117 expr, options.GetFetchDynamicValue(), 1118 frame_description.GetData()); 1119 } 1120 1121 target->EvaluateExpression(expr, frame, expr_value_sp, options.ref()); 1122 expr_result.SetSP(expr_value_sp, options.GetFetchDynamicValue()); 1123 } 1124 } else { 1125 Status error; 1126 error.SetErrorString("can't evaluate expressions when the " 1127 "process is running."); 1128 expr_value_sp = ValueObjectConstResult::Create(nullptr, error); 1129 expr_result.SetSP(expr_value_sp, false); 1130 } 1131 } else { 1132 Status error; 1133 error.SetErrorString("sbframe object is not valid."); 1134 expr_value_sp = ValueObjectConstResult::Create(nullptr, error); 1135 expr_result.SetSP(expr_value_sp, false); 1136 } 1137 1138 if (expr_result.GetError().Success()) 1139 LLDB_LOGF(expr_log, 1140 "** [SBFrame::EvaluateExpression] Expression result is " 1141 "%s, summary %s **", 1142 expr_result.GetValue(), expr_result.GetSummary()); 1143 else 1144 LLDB_LOGF(expr_log, 1145 "** [SBFrame::EvaluateExpression] Expression evaluation failed: " 1146 "%s **", 1147 expr_result.GetError().GetCString()); 1148 1149 return expr_result; 1150 } 1151 1152 bool SBFrame::IsInlined() { 1153 LLDB_INSTRUMENT_VA(this); 1154 1155 return static_cast<const SBFrame *>(this)->IsInlined(); 1156 } 1157 1158 bool SBFrame::IsInlined() const { 1159 LLDB_INSTRUMENT_VA(this); 1160 1161 std::unique_lock<std::recursive_mutex> lock; 1162 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 1163 1164 StackFrame *frame = nullptr; 1165 Target *target = exe_ctx.GetTargetPtr(); 1166 Process *process = exe_ctx.GetProcessPtr(); 1167 if (target && process) { 1168 Process::StopLocker stop_locker; 1169 if (stop_locker.TryLock(&process->GetRunLock())) { 1170 frame = exe_ctx.GetFramePtr(); 1171 if (frame) { 1172 1173 Block *block = frame->GetSymbolContext(eSymbolContextBlock).block; 1174 if (block) 1175 return block->GetContainingInlinedBlock() != nullptr; 1176 } 1177 } 1178 } 1179 return false; 1180 } 1181 1182 bool SBFrame::IsArtificial() { 1183 LLDB_INSTRUMENT_VA(this); 1184 1185 return static_cast<const SBFrame *>(this)->IsArtificial(); 1186 } 1187 1188 bool SBFrame::IsArtificial() const { 1189 LLDB_INSTRUMENT_VA(this); 1190 1191 std::unique_lock<std::recursive_mutex> lock; 1192 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 1193 1194 StackFrame *frame = exe_ctx.GetFramePtr(); 1195 if (frame) 1196 return frame->IsArtificial(); 1197 1198 return false; 1199 } 1200 1201 const char *SBFrame::GetFunctionName() { 1202 LLDB_INSTRUMENT_VA(this); 1203 1204 return static_cast<const SBFrame *>(this)->GetFunctionName(); 1205 } 1206 1207 lldb::LanguageType SBFrame::GuessLanguage() const { 1208 LLDB_INSTRUMENT_VA(this); 1209 1210 std::unique_lock<std::recursive_mutex> lock; 1211 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 1212 1213 StackFrame *frame = nullptr; 1214 Target *target = exe_ctx.GetTargetPtr(); 1215 Process *process = exe_ctx.GetProcessPtr(); 1216 if (target && process) { 1217 Process::StopLocker stop_locker; 1218 if (stop_locker.TryLock(&process->GetRunLock())) { 1219 frame = exe_ctx.GetFramePtr(); 1220 if (frame) { 1221 return frame->GuessLanguage(); 1222 } 1223 } 1224 } 1225 return eLanguageTypeUnknown; 1226 } 1227 1228 const char *SBFrame::GetFunctionName() const { 1229 LLDB_INSTRUMENT_VA(this); 1230 1231 const char *name = nullptr; 1232 std::unique_lock<std::recursive_mutex> lock; 1233 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 1234 1235 StackFrame *frame = nullptr; 1236 Target *target = exe_ctx.GetTargetPtr(); 1237 Process *process = exe_ctx.GetProcessPtr(); 1238 if (target && process) { 1239 Process::StopLocker stop_locker; 1240 if (stop_locker.TryLock(&process->GetRunLock())) { 1241 frame = exe_ctx.GetFramePtr(); 1242 if (frame) { 1243 SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | 1244 eSymbolContextBlock | 1245 eSymbolContextSymbol)); 1246 if (sc.block) { 1247 Block *inlined_block = sc.block->GetContainingInlinedBlock(); 1248 if (inlined_block) { 1249 const InlineFunctionInfo *inlined_info = 1250 inlined_block->GetInlinedFunctionInfo(); 1251 name = inlined_info->GetName().AsCString(); 1252 } 1253 } 1254 1255 if (name == nullptr) { 1256 if (sc.function) 1257 name = sc.function->GetName().GetCString(); 1258 } 1259 1260 if (name == nullptr) { 1261 if (sc.symbol) 1262 name = sc.symbol->GetName().GetCString(); 1263 } 1264 } 1265 } 1266 } 1267 return name; 1268 } 1269 1270 const char *SBFrame::GetDisplayFunctionName() { 1271 LLDB_INSTRUMENT_VA(this); 1272 1273 const char *name = nullptr; 1274 1275 std::unique_lock<std::recursive_mutex> lock; 1276 ExecutionContext exe_ctx(m_opaque_sp.get(), lock); 1277 1278 StackFrame *frame = nullptr; 1279 Target *target = exe_ctx.GetTargetPtr(); 1280 Process *process = exe_ctx.GetProcessPtr(); 1281 if (target && process) { 1282 Process::StopLocker stop_locker; 1283 if (stop_locker.TryLock(&process->GetRunLock())) { 1284 frame = exe_ctx.GetFramePtr(); 1285 if (frame) { 1286 SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | 1287 eSymbolContextBlock | 1288 eSymbolContextSymbol)); 1289 if (sc.block) { 1290 Block *inlined_block = sc.block->GetContainingInlinedBlock(); 1291 if (inlined_block) { 1292 const InlineFunctionInfo *inlined_info = 1293 inlined_block->GetInlinedFunctionInfo(); 1294 name = inlined_info->GetDisplayName().AsCString(); 1295 } 1296 } 1297 1298 if (name == nullptr) { 1299 if (sc.function) 1300 name = sc.function->GetDisplayName().GetCString(); 1301 } 1302 1303 if (name == nullptr) { 1304 if (sc.symbol) 1305 name = sc.symbol->GetDisplayName().GetCString(); 1306 } 1307 } 1308 } 1309 } 1310 return name; 1311 } 1312