forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			1372 lines
		
	
	
		
			46 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			1372 lines
		
	
	
		
			46 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- SBFrame.cpp ---------------------------------------------*- C++ -*-===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include <algorithm>
 | |
| #include <set>
 | |
| #include <string>
 | |
| 
 | |
| #include "lldb/API/SBFrame.h"
 | |
| 
 | |
| #include "lldb/lldb-types.h"
 | |
| 
 | |
| #include "SBReproducerPrivate.h"
 | |
| #include "Utils.h"
 | |
| #include "lldb/Core/Address.h"
 | |
| #include "lldb/Core/StreamFile.h"
 | |
| #include "lldb/Core/ValueObjectRegister.h"
 | |
| #include "lldb/Core/ValueObjectVariable.h"
 | |
| #include "lldb/Expression/ExpressionVariable.h"
 | |
| #include "lldb/Expression/UserExpression.h"
 | |
| #include "lldb/Host/Host.h"
 | |
| #include "lldb/Symbol/Block.h"
 | |
| #include "lldb/Symbol/Function.h"
 | |
| #include "lldb/Symbol/Symbol.h"
 | |
| #include "lldb/Symbol/SymbolContext.h"
 | |
| #include "lldb/Symbol/Variable.h"
 | |
| #include "lldb/Symbol/VariableList.h"
 | |
| #include "lldb/Target/ExecutionContext.h"
 | |
| #include "lldb/Target/Process.h"
 | |
| #include "lldb/Target/RegisterContext.h"
 | |
| #include "lldb/Target/StackFrame.h"
 | |
| #include "lldb/Target/StackFrameRecognizer.h"
 | |
| #include "lldb/Target/StackID.h"
 | |
| #include "lldb/Target/Target.h"
 | |
| #include "lldb/Target/Thread.h"
 | |
| #include "lldb/Utility/ConstString.h"
 | |
| #include "lldb/Utility/Stream.h"
 | |
| 
 | |
| #include "lldb/API/SBAddress.h"
 | |
| #include "lldb/API/SBDebugger.h"
 | |
| #include "lldb/API/SBExpressionOptions.h"
 | |
| #include "lldb/API/SBStream.h"
 | |
| #include "lldb/API/SBSymbolContext.h"
 | |
| #include "lldb/API/SBThread.h"
 | |
| #include "lldb/API/SBValue.h"
 | |
| #include "lldb/API/SBVariablesOptions.h"
 | |
| 
 | |
| #include "llvm/Support/PrettyStackTrace.h"
 | |
| 
 | |
| using namespace lldb;
 | |
| using namespace lldb_private;
 | |
| 
 | |
| SBFrame::SBFrame() : m_opaque_sp(new ExecutionContextRef()) {
 | |
|   LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBFrame);
 | |
| }
 | |
| 
 | |
| SBFrame::SBFrame(const StackFrameSP &lldb_object_sp)
 | |
|     : m_opaque_sp(new ExecutionContextRef(lldb_object_sp)) {
 | |
|   LLDB_RECORD_CONSTRUCTOR(SBFrame, (const lldb::StackFrameSP &),
 | |
|                           lldb_object_sp);
 | |
| }
 | |
| 
 | |
| SBFrame::SBFrame(const SBFrame &rhs) : m_opaque_sp() {
 | |
|   LLDB_RECORD_CONSTRUCTOR(SBFrame, (const lldb::SBFrame &), rhs);
 | |
| 
 | |
|   m_opaque_sp = clone(rhs.m_opaque_sp);
 | |
| }
 | |
| 
 | |
| SBFrame::~SBFrame() = default;
 | |
| 
 | |
| const SBFrame &SBFrame::operator=(const SBFrame &rhs) {
 | |
|   LLDB_RECORD_METHOD(const lldb::SBFrame &,
 | |
|                      SBFrame, operator=,(const lldb::SBFrame &), rhs);
 | |
| 
 | |
|   if (this != &rhs)
 | |
|     m_opaque_sp = clone(rhs.m_opaque_sp);
 | |
|   return LLDB_RECORD_RESULT(*this);
 | |
| }
 | |
| 
 | |
| StackFrameSP SBFrame::GetFrameSP() const {
 | |
|   return (m_opaque_sp ? m_opaque_sp->GetFrameSP() : StackFrameSP());
 | |
| }
 | |
| 
 | |
| void SBFrame::SetFrameSP(const StackFrameSP &lldb_object_sp) {
 | |
|   return m_opaque_sp->SetFrameSP(lldb_object_sp);
 | |
| }
 | |
| 
 | |
| bool SBFrame::IsValid() const {
 | |
|   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBFrame, IsValid);
 | |
|   return this->operator bool();
 | |
| }
 | |
| SBFrame::operator bool() const {
 | |
|   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBFrame, operator bool);
 | |
| 
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock()))
 | |
|       return GetFrameSP().get() != nullptr;
 | |
|   }
 | |
| 
 | |
|   // Without a target & process we can't have a valid stack frame.
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| SBSymbolContext SBFrame::GetSymbolContext(uint32_t resolve_scope) const {
 | |
|   LLDB_RECORD_METHOD_CONST(lldb::SBSymbolContext, SBFrame, GetSymbolContext,
 | |
|                            (uint32_t), resolve_scope);
 | |
| 
 | |
|   SBSymbolContext sb_sym_ctx;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
|   SymbolContextItem scope = static_cast<SymbolContextItem>(resolve_scope);
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame)
 | |
|         sb_sym_ctx.SetSymbolContext(&frame->GetSymbolContext(scope));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return LLDB_RECORD_RESULT(sb_sym_ctx);
 | |
| }
 | |
| 
 | |
| SBModule SBFrame::GetModule() const {
 | |
|   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::SBModule, SBFrame, GetModule);
 | |
| 
 | |
|   SBModule sb_module;
 | |
|   ModuleSP module_sp;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame) {
 | |
|         module_sp = frame->GetSymbolContext(eSymbolContextModule).module_sp;
 | |
|         sb_module.SetSP(module_sp);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return LLDB_RECORD_RESULT(sb_module);
 | |
| }
 | |
| 
 | |
| SBCompileUnit SBFrame::GetCompileUnit() const {
 | |
|   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::SBCompileUnit, SBFrame,
 | |
|                                    GetCompileUnit);
 | |
| 
 | |
|   SBCompileUnit sb_comp_unit;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame) {
 | |
|         sb_comp_unit.reset(
 | |
|             frame->GetSymbolContext(eSymbolContextCompUnit).comp_unit);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return LLDB_RECORD_RESULT(sb_comp_unit);
 | |
| }
 | |
| 
 | |
| SBFunction SBFrame::GetFunction() const {
 | |
|   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::SBFunction, SBFrame, GetFunction);
 | |
| 
 | |
|   SBFunction sb_function;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame) {
 | |
|         sb_function.reset(
 | |
|             frame->GetSymbolContext(eSymbolContextFunction).function);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return LLDB_RECORD_RESULT(sb_function);
 | |
| }
 | |
| 
 | |
| SBSymbol SBFrame::GetSymbol() const {
 | |
|   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::SBSymbol, SBFrame, GetSymbol);
 | |
| 
 | |
|   SBSymbol sb_symbol;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame) {
 | |
|         sb_symbol.reset(frame->GetSymbolContext(eSymbolContextSymbol).symbol);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return LLDB_RECORD_RESULT(sb_symbol);
 | |
| }
 | |
| 
 | |
| SBBlock SBFrame::GetBlock() const {
 | |
|   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::SBBlock, SBFrame, GetBlock);
 | |
| 
 | |
|   SBBlock sb_block;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame)
 | |
|         sb_block.SetPtr(frame->GetSymbolContext(eSymbolContextBlock).block);
 | |
|     }
 | |
|   }
 | |
|   return LLDB_RECORD_RESULT(sb_block);
 | |
| }
 | |
| 
 | |
| SBBlock SBFrame::GetFrameBlock() const {
 | |
|   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::SBBlock, SBFrame, GetFrameBlock);
 | |
| 
 | |
|   SBBlock sb_block;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame)
 | |
|         sb_block.SetPtr(frame->GetFrameBlock());
 | |
|     }
 | |
|   }
 | |
|   return LLDB_RECORD_RESULT(sb_block);
 | |
| }
 | |
| 
 | |
| SBLineEntry SBFrame::GetLineEntry() const {
 | |
|   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::SBLineEntry, SBFrame, GetLineEntry);
 | |
| 
 | |
|   SBLineEntry sb_line_entry;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame) {
 | |
|         sb_line_entry.SetLineEntry(
 | |
|             frame->GetSymbolContext(eSymbolContextLineEntry).line_entry);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return LLDB_RECORD_RESULT(sb_line_entry);
 | |
| }
 | |
| 
 | |
| uint32_t SBFrame::GetFrameID() const {
 | |
|   LLDB_RECORD_METHOD_CONST_NO_ARGS(uint32_t, SBFrame, GetFrameID);
 | |
| 
 | |
|   uint32_t frame_idx = UINT32_MAX;
 | |
| 
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = exe_ctx.GetFramePtr();
 | |
|   if (frame)
 | |
|     frame_idx = frame->GetFrameIndex();
 | |
| 
 | |
|   return frame_idx;
 | |
| }
 | |
| 
 | |
| lldb::addr_t SBFrame::GetCFA() const {
 | |
|   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::addr_t, SBFrame, GetCFA);
 | |
| 
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = exe_ctx.GetFramePtr();
 | |
|   if (frame)
 | |
|     return frame->GetStackID().GetCallFrameAddress();
 | |
|   return LLDB_INVALID_ADDRESS;
 | |
| }
 | |
| 
 | |
| addr_t SBFrame::GetPC() const {
 | |
|   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::addr_t, SBFrame, GetPC);
 | |
| 
 | |
|   addr_t addr = LLDB_INVALID_ADDRESS;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame) {
 | |
|         addr = frame->GetFrameCodeAddress().GetOpcodeLoadAddress(
 | |
|             target, AddressClass::eCode);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return addr;
 | |
| }
 | |
| 
 | |
| bool SBFrame::SetPC(addr_t new_pc) {
 | |
|   LLDB_RECORD_METHOD(bool, SBFrame, SetPC, (lldb::addr_t), new_pc);
 | |
| 
 | |
|   bool ret_val = false;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame) {
 | |
|         ret_val = frame->GetRegisterContext()->SetPC(new_pc);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return ret_val;
 | |
| }
 | |
| 
 | |
| addr_t SBFrame::GetSP() const {
 | |
|   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::addr_t, SBFrame, GetSP);
 | |
| 
 | |
|   addr_t addr = LLDB_INVALID_ADDRESS;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame) {
 | |
|         addr = frame->GetRegisterContext()->GetSP();
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return addr;
 | |
| }
 | |
| 
 | |
| addr_t SBFrame::GetFP() const {
 | |
|   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::addr_t, SBFrame, GetFP);
 | |
| 
 | |
|   addr_t addr = LLDB_INVALID_ADDRESS;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame)
 | |
|         addr = frame->GetRegisterContext()->GetFP();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return addr;
 | |
| }
 | |
| 
 | |
| SBAddress SBFrame::GetPCAddress() const {
 | |
|   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::SBAddress, SBFrame, GetPCAddress);
 | |
| 
 | |
|   SBAddress sb_addr;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = exe_ctx.GetFramePtr();
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame)
 | |
|         sb_addr.SetAddress(&frame->GetFrameCodeAddress());
 | |
|     }
 | |
|   }
 | |
|   return LLDB_RECORD_RESULT(sb_addr);
 | |
| }
 | |
| 
 | |
| void SBFrame::Clear() {
 | |
|   LLDB_RECORD_METHOD_NO_ARGS(void, SBFrame, Clear);
 | |
| 
 | |
|   m_opaque_sp->Clear();
 | |
| }
 | |
| 
 | |
| lldb::SBValue SBFrame::GetValueForVariablePath(const char *var_path) {
 | |
|   LLDB_RECORD_METHOD(lldb::SBValue, SBFrame, GetValueForVariablePath,
 | |
|                      (const char *), var_path);
 | |
| 
 | |
|   SBValue sb_value;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = exe_ctx.GetFramePtr();
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   if (frame && target) {
 | |
|     lldb::DynamicValueType use_dynamic =
 | |
|         frame->CalculateTarget()->GetPreferDynamicValue();
 | |
|     sb_value = GetValueForVariablePath(var_path, use_dynamic);
 | |
|   }
 | |
|   return LLDB_RECORD_RESULT(sb_value);
 | |
| }
 | |
| 
 | |
| lldb::SBValue SBFrame::GetValueForVariablePath(const char *var_path,
 | |
|                                                DynamicValueType use_dynamic) {
 | |
|   LLDB_RECORD_METHOD(lldb::SBValue, SBFrame, GetValueForVariablePath,
 | |
|                      (const char *, lldb::DynamicValueType), var_path,
 | |
|                      use_dynamic);
 | |
| 
 | |
|   SBValue sb_value;
 | |
|   if (var_path == nullptr || var_path[0] == '\0') {
 | |
|     return LLDB_RECORD_RESULT(sb_value);
 | |
|   }
 | |
| 
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame) {
 | |
|         VariableSP var_sp;
 | |
|         Status error;
 | |
|         ValueObjectSP value_sp(frame->GetValueForVariableExpressionPath(
 | |
|             var_path, eNoDynamicValues,
 | |
|             StackFrame::eExpressionPathOptionCheckPtrVsMember |
 | |
|                 StackFrame::eExpressionPathOptionsAllowDirectIVarAccess,
 | |
|             var_sp, error));
 | |
|         sb_value.SetSP(value_sp, use_dynamic);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return LLDB_RECORD_RESULT(sb_value);
 | |
| }
 | |
| 
 | |
| SBValue SBFrame::FindVariable(const char *name) {
 | |
|   LLDB_RECORD_METHOD(lldb::SBValue, SBFrame, FindVariable, (const char *),
 | |
|                      name);
 | |
| 
 | |
|   SBValue value;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = exe_ctx.GetFramePtr();
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   if (frame && target) {
 | |
|     lldb::DynamicValueType use_dynamic =
 | |
|         frame->CalculateTarget()->GetPreferDynamicValue();
 | |
|     value = FindVariable(name, use_dynamic);
 | |
|   }
 | |
|   return LLDB_RECORD_RESULT(value);
 | |
| }
 | |
| 
 | |
| SBValue SBFrame::FindVariable(const char *name,
 | |
|                               lldb::DynamicValueType use_dynamic) {
 | |
|   LLDB_RECORD_METHOD(lldb::SBValue, SBFrame, FindVariable,
 | |
|                      (const char *, lldb::DynamicValueType), name, use_dynamic);
 | |
| 
 | |
|   VariableSP var_sp;
 | |
|   SBValue sb_value;
 | |
| 
 | |
|   if (name == nullptr || name[0] == '\0') {
 | |
|     return LLDB_RECORD_RESULT(sb_value);
 | |
|   }
 | |
| 
 | |
|   ValueObjectSP value_sp;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame) {
 | |
|         value_sp = frame->FindVariable(ConstString(name));
 | |
| 
 | |
|         if (value_sp)
 | |
|           sb_value.SetSP(value_sp, use_dynamic);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return LLDB_RECORD_RESULT(sb_value);
 | |
| }
 | |
| 
 | |
| SBValue SBFrame::FindValue(const char *name, ValueType value_type) {
 | |
|   LLDB_RECORD_METHOD(lldb::SBValue, SBFrame, FindValue,
 | |
|                      (const char *, lldb::ValueType), name, value_type);
 | |
| 
 | |
|   SBValue value;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = exe_ctx.GetFramePtr();
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   if (frame && target) {
 | |
|     lldb::DynamicValueType use_dynamic =
 | |
|         frame->CalculateTarget()->GetPreferDynamicValue();
 | |
|     value = FindValue(name, value_type, use_dynamic);
 | |
|   }
 | |
|   return LLDB_RECORD_RESULT(value);
 | |
| }
 | |
| 
 | |
| SBValue SBFrame::FindValue(const char *name, ValueType value_type,
 | |
|                            lldb::DynamicValueType use_dynamic) {
 | |
|   LLDB_RECORD_METHOD(lldb::SBValue, SBFrame, FindValue,
 | |
|                      (const char *, lldb::ValueType, lldb::DynamicValueType),
 | |
|                      name, value_type, use_dynamic);
 | |
| 
 | |
|   SBValue sb_value;
 | |
| 
 | |
|   if (name == nullptr || name[0] == '\0') {
 | |
|     return LLDB_RECORD_RESULT(sb_value);
 | |
|   }
 | |
| 
 | |
|   ValueObjectSP value_sp;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame) {
 | |
|         VariableList variable_list;
 | |
| 
 | |
|         switch (value_type) {
 | |
|         case eValueTypeVariableGlobal:      // global variable
 | |
|         case eValueTypeVariableStatic:      // static variable
 | |
|         case eValueTypeVariableArgument:    // function argument variables
 | |
|         case eValueTypeVariableLocal:       // function local variables
 | |
|         case eValueTypeVariableThreadLocal: // thread local variables
 | |
|         {
 | |
|           SymbolContext sc(frame->GetSymbolContext(eSymbolContextBlock));
 | |
| 
 | |
|           const bool can_create = true;
 | |
|           const bool get_parent_variables = true;
 | |
|           const bool stop_if_block_is_inlined_function = true;
 | |
| 
 | |
|           if (sc.block)
 | |
|             sc.block->AppendVariables(
 | |
|                 can_create, get_parent_variables,
 | |
|                 stop_if_block_is_inlined_function,
 | |
|                 [frame](Variable *v) { return v->IsInScope(frame); },
 | |
|                 &variable_list);
 | |
|           if (value_type == eValueTypeVariableGlobal) {
 | |
|             const bool get_file_globals = true;
 | |
|             VariableList *frame_vars = frame->GetVariableList(get_file_globals);
 | |
|             if (frame_vars)
 | |
|               frame_vars->AppendVariablesIfUnique(variable_list);
 | |
|           }
 | |
|           ConstString const_name(name);
 | |
|           VariableSP variable_sp(
 | |
|               variable_list.FindVariable(const_name, value_type));
 | |
|           if (variable_sp) {
 | |
|             value_sp = frame->GetValueObjectForFrameVariable(variable_sp,
 | |
|                                                              eNoDynamicValues);
 | |
|             sb_value.SetSP(value_sp, use_dynamic);
 | |
|           }
 | |
|         } break;
 | |
| 
 | |
|         case eValueTypeRegister: // stack frame register value
 | |
|         {
 | |
|           RegisterContextSP reg_ctx(frame->GetRegisterContext());
 | |
|           if (reg_ctx) {
 | |
|             const uint32_t num_regs = reg_ctx->GetRegisterCount();
 | |
|             for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) {
 | |
|               const RegisterInfo *reg_info =
 | |
|                   reg_ctx->GetRegisterInfoAtIndex(reg_idx);
 | |
|               if (reg_info &&
 | |
|                   ((reg_info->name && strcasecmp(reg_info->name, name) == 0) ||
 | |
|                    (reg_info->alt_name &&
 | |
|                     strcasecmp(reg_info->alt_name, name) == 0))) {
 | |
|                 value_sp = ValueObjectRegister::Create(frame, reg_ctx, reg_idx);
 | |
|                 sb_value.SetSP(value_sp);
 | |
|                 break;
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|         } break;
 | |
| 
 | |
|         case eValueTypeRegisterSet: // A collection of stack frame register
 | |
|                                     // values
 | |
|         {
 | |
|           RegisterContextSP reg_ctx(frame->GetRegisterContext());
 | |
|           if (reg_ctx) {
 | |
|             const uint32_t num_sets = reg_ctx->GetRegisterSetCount();
 | |
|             for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx) {
 | |
|               const RegisterSet *reg_set = reg_ctx->GetRegisterSet(set_idx);
 | |
|               if (reg_set &&
 | |
|                   ((reg_set->name && strcasecmp(reg_set->name, name) == 0) ||
 | |
|                    (reg_set->short_name &&
 | |
|                     strcasecmp(reg_set->short_name, name) == 0))) {
 | |
|                 value_sp =
 | |
|                     ValueObjectRegisterSet::Create(frame, reg_ctx, set_idx);
 | |
|                 sb_value.SetSP(value_sp);
 | |
|                 break;
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|         } break;
 | |
| 
 | |
|         case eValueTypeConstResult: // constant result variables
 | |
|         {
 | |
|           ConstString const_name(name);
 | |
|           ExpressionVariableSP expr_var_sp(
 | |
|               target->GetPersistentVariable(const_name));
 | |
|           if (expr_var_sp) {
 | |
|             value_sp = expr_var_sp->GetValueObject();
 | |
|             sb_value.SetSP(value_sp, use_dynamic);
 | |
|           }
 | |
|         } break;
 | |
| 
 | |
|         default:
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return LLDB_RECORD_RESULT(sb_value);
 | |
| }
 | |
| 
 | |
| bool SBFrame::IsEqual(const SBFrame &that) const {
 | |
|   LLDB_RECORD_METHOD_CONST(bool, SBFrame, IsEqual, (const lldb::SBFrame &),
 | |
|                            that);
 | |
| 
 | |
|   lldb::StackFrameSP this_sp = GetFrameSP();
 | |
|   lldb::StackFrameSP that_sp = that.GetFrameSP();
 | |
|   return (this_sp && that_sp && this_sp->GetStackID() == that_sp->GetStackID());
 | |
| }
 | |
| 
 | |
| bool SBFrame::operator==(const SBFrame &rhs) const {
 | |
|   LLDB_RECORD_METHOD_CONST(bool, SBFrame, operator==,(const lldb::SBFrame &),
 | |
|                            rhs);
 | |
| 
 | |
|   return IsEqual(rhs);
 | |
| }
 | |
| 
 | |
| bool SBFrame::operator!=(const SBFrame &rhs) const {
 | |
|   LLDB_RECORD_METHOD_CONST(bool, SBFrame, operator!=,(const lldb::SBFrame &),
 | |
|                            rhs);
 | |
| 
 | |
|   return !IsEqual(rhs);
 | |
| }
 | |
| 
 | |
| SBThread SBFrame::GetThread() const {
 | |
|   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::SBThread, SBFrame, GetThread);
 | |
| 
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   ThreadSP thread_sp(exe_ctx.GetThreadSP());
 | |
|   SBThread sb_thread(thread_sp);
 | |
| 
 | |
|   return LLDB_RECORD_RESULT(sb_thread);
 | |
| }
 | |
| 
 | |
| const char *SBFrame::Disassemble() const {
 | |
|   LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBFrame, Disassemble);
 | |
| 
 | |
|   const char *disassembly = nullptr;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame) {
 | |
|         disassembly = frame->Disassemble();
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return disassembly;
 | |
| }
 | |
| 
 | |
| SBValueList SBFrame::GetVariables(bool arguments, bool locals, bool statics,
 | |
|                                   bool in_scope_only) {
 | |
|   LLDB_RECORD_METHOD(lldb::SBValueList, SBFrame, GetVariables,
 | |
|                      (bool, bool, bool, bool), arguments, locals, statics,
 | |
|                      in_scope_only);
 | |
| 
 | |
|   SBValueList value_list;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = exe_ctx.GetFramePtr();
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   if (frame && target) {
 | |
|     lldb::DynamicValueType use_dynamic =
 | |
|         frame->CalculateTarget()->GetPreferDynamicValue();
 | |
|     const bool include_runtime_support_values =
 | |
|         target ? target->GetDisplayRuntimeSupportValues() : false;
 | |
| 
 | |
|     SBVariablesOptions options;
 | |
|     options.SetIncludeArguments(arguments);
 | |
|     options.SetIncludeLocals(locals);
 | |
|     options.SetIncludeStatics(statics);
 | |
|     options.SetInScopeOnly(in_scope_only);
 | |
|     options.SetIncludeRuntimeSupportValues(include_runtime_support_values);
 | |
|     options.SetUseDynamic(use_dynamic);
 | |
| 
 | |
|     value_list = GetVariables(options);
 | |
|   }
 | |
|   return LLDB_RECORD_RESULT(value_list);
 | |
| }
 | |
| 
 | |
| lldb::SBValueList SBFrame::GetVariables(bool arguments, bool locals,
 | |
|                                         bool statics, bool in_scope_only,
 | |
|                                         lldb::DynamicValueType use_dynamic) {
 | |
|   LLDB_RECORD_METHOD(lldb::SBValueList, SBFrame, GetVariables,
 | |
|                      (bool, bool, bool, bool, lldb::DynamicValueType),
 | |
|                      arguments, locals, statics, in_scope_only, use_dynamic);
 | |
| 
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   const bool include_runtime_support_values =
 | |
|       target ? target->GetDisplayRuntimeSupportValues() : false;
 | |
|   SBVariablesOptions options;
 | |
|   options.SetIncludeArguments(arguments);
 | |
|   options.SetIncludeLocals(locals);
 | |
|   options.SetIncludeStatics(statics);
 | |
|   options.SetInScopeOnly(in_scope_only);
 | |
|   options.SetIncludeRuntimeSupportValues(include_runtime_support_values);
 | |
|   options.SetUseDynamic(use_dynamic);
 | |
|   return LLDB_RECORD_RESULT(GetVariables(options));
 | |
| }
 | |
| 
 | |
| SBValueList SBFrame::GetVariables(const lldb::SBVariablesOptions &options) {
 | |
|   LLDB_RECORD_METHOD(lldb::SBValueList, SBFrame, GetVariables,
 | |
|                      (const lldb::SBVariablesOptions &), options);
 | |
| 
 | |
|   SBValueList value_list;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
| 
 | |
|   const bool statics = options.GetIncludeStatics();
 | |
|   const bool arguments = options.GetIncludeArguments();
 | |
|   const bool recognized_arguments =
 | |
|         options.GetIncludeRecognizedArguments(SBTarget(exe_ctx.GetTargetSP()));
 | |
|   const bool locals = options.GetIncludeLocals();
 | |
|   const bool in_scope_only = options.GetInScopeOnly();
 | |
|   const bool include_runtime_support_values =
 | |
|       options.GetIncludeRuntimeSupportValues();
 | |
|   const lldb::DynamicValueType use_dynamic = options.GetUseDynamic();
 | |
| 
 | |
| 
 | |
|   std::set<VariableSP> variable_set;
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame) {
 | |
|         size_t i;
 | |
|         VariableList *variable_list = nullptr;
 | |
|         variable_list = frame->GetVariableList(true);
 | |
|         if (variable_list) {
 | |
|           const size_t num_variables = variable_list->GetSize();
 | |
|           if (num_variables) {
 | |
|             for (i = 0; i < num_variables; ++i) {
 | |
|               VariableSP variable_sp(variable_list->GetVariableAtIndex(i));
 | |
|               if (variable_sp) {
 | |
|                 bool add_variable = false;
 | |
|                 switch (variable_sp->GetScope()) {
 | |
|                 case eValueTypeVariableGlobal:
 | |
|                 case eValueTypeVariableStatic:
 | |
|                 case eValueTypeVariableThreadLocal:
 | |
|                   add_variable = statics;
 | |
|                   break;
 | |
| 
 | |
|                 case eValueTypeVariableArgument:
 | |
|                   add_variable = arguments;
 | |
|                   break;
 | |
| 
 | |
|                 case eValueTypeVariableLocal:
 | |
|                   add_variable = locals;
 | |
|                   break;
 | |
| 
 | |
|                 default:
 | |
|                   break;
 | |
|                 }
 | |
|                 if (add_variable) {
 | |
|                   // Only add variables once so we don't end up with duplicates
 | |
|                   if (variable_set.find(variable_sp) == variable_set.end())
 | |
|                     variable_set.insert(variable_sp);
 | |
|                   else
 | |
|                     continue;
 | |
| 
 | |
|                   if (in_scope_only && !variable_sp->IsInScope(frame))
 | |
|                     continue;
 | |
| 
 | |
|                   ValueObjectSP valobj_sp(frame->GetValueObjectForFrameVariable(
 | |
|                       variable_sp, eNoDynamicValues));
 | |
| 
 | |
|                   if (!include_runtime_support_values && valobj_sp != nullptr &&
 | |
|                       valobj_sp->IsRuntimeSupportValue())
 | |
|                     continue;
 | |
| 
 | |
|                   SBValue value_sb;
 | |
|                   value_sb.SetSP(valobj_sp, use_dynamic);
 | |
|                   value_list.Append(value_sb);
 | |
|                 }
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|         if (recognized_arguments) {
 | |
|           auto recognized_frame = frame->GetRecognizedFrame();
 | |
|           if (recognized_frame) {
 | |
|             ValueObjectListSP recognized_arg_list =
 | |
|                 recognized_frame->GetRecognizedArguments();
 | |
|             if (recognized_arg_list) {
 | |
|               for (auto &rec_value_sp : recognized_arg_list->GetObjects()) {
 | |
|                 SBValue value_sb;
 | |
|                 value_sb.SetSP(rec_value_sp, use_dynamic);
 | |
|                 value_list.Append(value_sb);
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return LLDB_RECORD_RESULT(value_list);
 | |
| }
 | |
| 
 | |
| SBValueList SBFrame::GetRegisters() {
 | |
|   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBValueList, SBFrame, GetRegisters);
 | |
| 
 | |
|   SBValueList value_list;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame) {
 | |
|         RegisterContextSP reg_ctx(frame->GetRegisterContext());
 | |
|         if (reg_ctx) {
 | |
|           const uint32_t num_sets = reg_ctx->GetRegisterSetCount();
 | |
|           for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx) {
 | |
|             value_list.Append(
 | |
|                 ValueObjectRegisterSet::Create(frame, reg_ctx, set_idx));
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return LLDB_RECORD_RESULT(value_list);
 | |
| }
 | |
| 
 | |
| SBValue SBFrame::FindRegister(const char *name) {
 | |
|   LLDB_RECORD_METHOD(lldb::SBValue, SBFrame, FindRegister, (const char *),
 | |
|                      name);
 | |
| 
 | |
|   SBValue result;
 | |
|   ValueObjectSP value_sp;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame) {
 | |
|         RegisterContextSP reg_ctx(frame->GetRegisterContext());
 | |
|         if (reg_ctx) {
 | |
|           const uint32_t num_regs = reg_ctx->GetRegisterCount();
 | |
|           for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) {
 | |
|             const RegisterInfo *reg_info =
 | |
|                 reg_ctx->GetRegisterInfoAtIndex(reg_idx);
 | |
|             if (reg_info &&
 | |
|                 ((reg_info->name && strcasecmp(reg_info->name, name) == 0) ||
 | |
|                  (reg_info->alt_name &&
 | |
|                   strcasecmp(reg_info->alt_name, name) == 0))) {
 | |
|               value_sp = ValueObjectRegister::Create(frame, reg_ctx, reg_idx);
 | |
|               result.SetSP(value_sp);
 | |
|               break;
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return LLDB_RECORD_RESULT(result);
 | |
| }
 | |
| 
 | |
| bool SBFrame::GetDescription(SBStream &description) {
 | |
|   LLDB_RECORD_METHOD(bool, SBFrame, GetDescription, (lldb::SBStream &),
 | |
|                      description);
 | |
| 
 | |
|   Stream &strm = description.ref();
 | |
| 
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame) {
 | |
|         frame->DumpUsingSettingsFormat(&strm);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|   } else
 | |
|     strm.PutCString("No value");
 | |
| 
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| SBValue SBFrame::EvaluateExpression(const char *expr) {
 | |
|   LLDB_RECORD_METHOD(lldb::SBValue, SBFrame, EvaluateExpression, (const char *),
 | |
|                      expr);
 | |
| 
 | |
|   SBValue result;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = exe_ctx.GetFramePtr();
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   if (frame && target) {
 | |
|     SBExpressionOptions options;
 | |
|     lldb::DynamicValueType fetch_dynamic_value =
 | |
|         frame->CalculateTarget()->GetPreferDynamicValue();
 | |
|     options.SetFetchDynamicValue(fetch_dynamic_value);
 | |
|     options.SetUnwindOnError(true);
 | |
|     options.SetIgnoreBreakpoints(true);
 | |
|     if (target->GetLanguage() != eLanguageTypeUnknown)
 | |
|       options.SetLanguage(target->GetLanguage());
 | |
|     else
 | |
|       options.SetLanguage(frame->GetLanguage());
 | |
|     return LLDB_RECORD_RESULT(EvaluateExpression(expr, options));
 | |
|   }
 | |
|   return LLDB_RECORD_RESULT(result);
 | |
| }
 | |
| 
 | |
| SBValue
 | |
| SBFrame::EvaluateExpression(const char *expr,
 | |
|                             lldb::DynamicValueType fetch_dynamic_value) {
 | |
|   LLDB_RECORD_METHOD(lldb::SBValue, SBFrame, EvaluateExpression,
 | |
|                      (const char *, lldb::DynamicValueType), expr,
 | |
|                      fetch_dynamic_value);
 | |
| 
 | |
|   SBExpressionOptions options;
 | |
|   options.SetFetchDynamicValue(fetch_dynamic_value);
 | |
|   options.SetUnwindOnError(true);
 | |
|   options.SetIgnoreBreakpoints(true);
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = exe_ctx.GetFramePtr();
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   if (target && target->GetLanguage() != eLanguageTypeUnknown)
 | |
|     options.SetLanguage(target->GetLanguage());
 | |
|   else if (frame)
 | |
|     options.SetLanguage(frame->GetLanguage());
 | |
|   return LLDB_RECORD_RESULT(EvaluateExpression(expr, options));
 | |
| }
 | |
| 
 | |
| SBValue SBFrame::EvaluateExpression(const char *expr,
 | |
|                                     lldb::DynamicValueType fetch_dynamic_value,
 | |
|                                     bool unwind_on_error) {
 | |
|   LLDB_RECORD_METHOD(lldb::SBValue, SBFrame, EvaluateExpression,
 | |
|                      (const char *, lldb::DynamicValueType, bool), expr,
 | |
|                      fetch_dynamic_value, unwind_on_error);
 | |
| 
 | |
|   SBExpressionOptions options;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   options.SetFetchDynamicValue(fetch_dynamic_value);
 | |
|   options.SetUnwindOnError(unwind_on_error);
 | |
|   options.SetIgnoreBreakpoints(true);
 | |
|   StackFrame *frame = exe_ctx.GetFramePtr();
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   if (target && target->GetLanguage() != eLanguageTypeUnknown)
 | |
|     options.SetLanguage(target->GetLanguage());
 | |
|   else if (frame)
 | |
|     options.SetLanguage(frame->GetLanguage());
 | |
|   return LLDB_RECORD_RESULT(EvaluateExpression(expr, options));
 | |
| }
 | |
| 
 | |
| lldb::SBValue SBFrame::EvaluateExpression(const char *expr,
 | |
|                                           const SBExpressionOptions &options) {
 | |
|   LLDB_RECORD_METHOD(lldb::SBValue, SBFrame, EvaluateExpression,
 | |
|                      (const char *, const lldb::SBExpressionOptions &), expr,
 | |
|                      options);
 | |
| 
 | |
|   Log *expr_log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
 | |
| 
 | |
|   SBValue expr_result;
 | |
| 
 | |
|   if (expr == nullptr || expr[0] == '\0') {
 | |
|     return LLDB_RECORD_RESULT(expr_result);
 | |
|   }
 | |
| 
 | |
|   ValueObjectSP expr_value_sp;
 | |
| 
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
| 
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame) {
 | |
|         std::unique_ptr<llvm::PrettyStackTraceFormat> stack_trace;
 | |
|         if (target->GetDisplayExpressionsInCrashlogs()) {
 | |
|           StreamString frame_description;
 | |
|           frame->DumpUsingSettingsFormat(&frame_description);
 | |
|           stack_trace = std::make_unique<llvm::PrettyStackTraceFormat>(
 | |
|               "SBFrame::EvaluateExpression (expr = \"%s\", fetch_dynamic_value "
 | |
|               "= %u) %s",
 | |
|               expr, options.GetFetchDynamicValue(),
 | |
|               frame_description.GetData());
 | |
|         }
 | |
| 
 | |
|         target->EvaluateExpression(expr, frame, expr_value_sp, options.ref());
 | |
|         expr_result.SetSP(expr_value_sp, options.GetFetchDynamicValue());
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   LLDB_LOGF(expr_log,
 | |
|             "** [SBFrame::EvaluateExpression] Expression result is "
 | |
|             "%s, summary %s **",
 | |
|             expr_result.GetValue(), expr_result.GetSummary());
 | |
| 
 | |
|   return LLDB_RECORD_RESULT(expr_result);
 | |
| }
 | |
| 
 | |
| bool SBFrame::IsInlined() {
 | |
|   LLDB_RECORD_METHOD_NO_ARGS(bool, SBFrame, IsInlined);
 | |
| 
 | |
|   return static_cast<const SBFrame *>(this)->IsInlined();
 | |
| }
 | |
| 
 | |
| bool SBFrame::IsInlined() const {
 | |
|   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBFrame, IsInlined);
 | |
| 
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame) {
 | |
| 
 | |
|         Block *block = frame->GetSymbolContext(eSymbolContextBlock).block;
 | |
|         if (block)
 | |
|           return block->GetContainingInlinedBlock() != nullptr;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool SBFrame::IsArtificial() {
 | |
|   LLDB_RECORD_METHOD_NO_ARGS(bool, SBFrame, IsArtificial);
 | |
| 
 | |
|   return static_cast<const SBFrame *>(this)->IsArtificial();
 | |
| }
 | |
| 
 | |
| bool SBFrame::IsArtificial() const {
 | |
|   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBFrame, IsArtificial);
 | |
| 
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = exe_ctx.GetFramePtr();
 | |
|   if (frame)
 | |
|     return frame->IsArtificial();
 | |
| 
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| const char *SBFrame::GetFunctionName() {
 | |
|   LLDB_RECORD_METHOD_NO_ARGS(const char *, SBFrame, GetFunctionName);
 | |
| 
 | |
|   return static_cast<const SBFrame *>(this)->GetFunctionName();
 | |
| }
 | |
| 
 | |
| lldb::LanguageType SBFrame::GuessLanguage() const {
 | |
|   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::LanguageType, SBFrame, GuessLanguage);
 | |
| 
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame) {
 | |
|         return frame->GuessLanguage();
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return eLanguageTypeUnknown;
 | |
| }
 | |
| 
 | |
| const char *SBFrame::GetFunctionName() const {
 | |
|   LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBFrame, GetFunctionName);
 | |
| 
 | |
|   const char *name = nullptr;
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame) {
 | |
|         SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction |
 | |
|                                                  eSymbolContextBlock |
 | |
|                                                  eSymbolContextSymbol));
 | |
|         if (sc.block) {
 | |
|           Block *inlined_block = sc.block->GetContainingInlinedBlock();
 | |
|           if (inlined_block) {
 | |
|             const InlineFunctionInfo *inlined_info =
 | |
|                 inlined_block->GetInlinedFunctionInfo();
 | |
|             name =
 | |
|                 inlined_info->GetName(sc.function->GetLanguage()).AsCString();
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         if (name == nullptr) {
 | |
|           if (sc.function)
 | |
|             name = sc.function->GetName().GetCString();
 | |
|         }
 | |
| 
 | |
|         if (name == nullptr) {
 | |
|           if (sc.symbol)
 | |
|             name = sc.symbol->GetName().GetCString();
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return name;
 | |
| }
 | |
| 
 | |
| const char *SBFrame::GetDisplayFunctionName() {
 | |
|   LLDB_RECORD_METHOD_NO_ARGS(const char *, SBFrame, GetDisplayFunctionName);
 | |
| 
 | |
|   const char *name = nullptr;
 | |
| 
 | |
|   std::unique_lock<std::recursive_mutex> lock;
 | |
|   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
 | |
| 
 | |
|   StackFrame *frame = nullptr;
 | |
|   Target *target = exe_ctx.GetTargetPtr();
 | |
|   Process *process = exe_ctx.GetProcessPtr();
 | |
|   if (target && process) {
 | |
|     Process::StopLocker stop_locker;
 | |
|     if (stop_locker.TryLock(&process->GetRunLock())) {
 | |
|       frame = exe_ctx.GetFramePtr();
 | |
|       if (frame) {
 | |
|         SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction |
 | |
|                                                  eSymbolContextBlock |
 | |
|                                                  eSymbolContextSymbol));
 | |
|         if (sc.block) {
 | |
|           Block *inlined_block = sc.block->GetContainingInlinedBlock();
 | |
|           if (inlined_block) {
 | |
|             const InlineFunctionInfo *inlined_info =
 | |
|                 inlined_block->GetInlinedFunctionInfo();
 | |
|             name = inlined_info->GetDisplayName(sc.function->GetLanguage())
 | |
|                        .AsCString();
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         if (name == nullptr) {
 | |
|           if (sc.function)
 | |
|             name = sc.function->GetDisplayName().GetCString();
 | |
|         }
 | |
| 
 | |
|         if (name == nullptr) {
 | |
|           if (sc.symbol)
 | |
|             name = sc.symbol->GetDisplayName().GetCString();
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return name;
 | |
| }
 | |
| 
 | |
| namespace lldb_private {
 | |
| namespace repro {
 | |
| 
 | |
| template <>
 | |
| void RegisterMethods<SBFrame>(Registry &R) {
 | |
|   LLDB_REGISTER_CONSTRUCTOR(SBFrame, ());
 | |
|   LLDB_REGISTER_CONSTRUCTOR(SBFrame, (const lldb::StackFrameSP &));
 | |
|   LLDB_REGISTER_CONSTRUCTOR(SBFrame, (const lldb::SBFrame &));
 | |
|   LLDB_REGISTER_METHOD(const lldb::SBFrame &,
 | |
|                        SBFrame, operator=,(const lldb::SBFrame &));
 | |
|   LLDB_REGISTER_METHOD_CONST(bool, SBFrame, IsValid, ());
 | |
|   LLDB_REGISTER_METHOD_CONST(bool, SBFrame, operator bool, ());
 | |
|   LLDB_REGISTER_METHOD_CONST(lldb::SBSymbolContext, SBFrame, GetSymbolContext,
 | |
|                              (uint32_t));
 | |
|   LLDB_REGISTER_METHOD_CONST(lldb::SBModule, SBFrame, GetModule, ());
 | |
|   LLDB_REGISTER_METHOD_CONST(lldb::SBCompileUnit, SBFrame, GetCompileUnit,
 | |
|                              ());
 | |
|   LLDB_REGISTER_METHOD_CONST(lldb::SBFunction, SBFrame, GetFunction, ());
 | |
|   LLDB_REGISTER_METHOD_CONST(lldb::SBSymbol, SBFrame, GetSymbol, ());
 | |
|   LLDB_REGISTER_METHOD_CONST(lldb::SBBlock, SBFrame, GetBlock, ());
 | |
|   LLDB_REGISTER_METHOD_CONST(lldb::SBBlock, SBFrame, GetFrameBlock, ());
 | |
|   LLDB_REGISTER_METHOD_CONST(lldb::SBLineEntry, SBFrame, GetLineEntry, ());
 | |
|   LLDB_REGISTER_METHOD_CONST(uint32_t, SBFrame, GetFrameID, ());
 | |
|   LLDB_REGISTER_METHOD_CONST(lldb::addr_t, SBFrame, GetCFA, ());
 | |
|   LLDB_REGISTER_METHOD_CONST(lldb::addr_t, SBFrame, GetPC, ());
 | |
|   LLDB_REGISTER_METHOD(bool, SBFrame, SetPC, (lldb::addr_t));
 | |
|   LLDB_REGISTER_METHOD_CONST(lldb::addr_t, SBFrame, GetSP, ());
 | |
|   LLDB_REGISTER_METHOD_CONST(lldb::addr_t, SBFrame, GetFP, ());
 | |
|   LLDB_REGISTER_METHOD_CONST(lldb::SBAddress, SBFrame, GetPCAddress, ());
 | |
|   LLDB_REGISTER_METHOD(void, SBFrame, Clear, ());
 | |
|   LLDB_REGISTER_METHOD(lldb::SBValue, SBFrame, GetValueForVariablePath,
 | |
|                        (const char *));
 | |
|   LLDB_REGISTER_METHOD(lldb::SBValue, SBFrame, GetValueForVariablePath,
 | |
|                        (const char *, lldb::DynamicValueType));
 | |
|   LLDB_REGISTER_METHOD(lldb::SBValue, SBFrame, FindVariable, (const char *));
 | |
|   LLDB_REGISTER_METHOD(lldb::SBValue, SBFrame, FindVariable,
 | |
|                        (const char *, lldb::DynamicValueType));
 | |
|   LLDB_REGISTER_METHOD(lldb::SBValue, SBFrame, FindValue,
 | |
|                        (const char *, lldb::ValueType));
 | |
|   LLDB_REGISTER_METHOD(
 | |
|       lldb::SBValue, SBFrame, FindValue,
 | |
|       (const char *, lldb::ValueType, lldb::DynamicValueType));
 | |
|   LLDB_REGISTER_METHOD_CONST(bool, SBFrame, IsEqual, (const lldb::SBFrame &));
 | |
|   LLDB_REGISTER_METHOD_CONST(bool,
 | |
|                              SBFrame, operator==,(const lldb::SBFrame &));
 | |
|   LLDB_REGISTER_METHOD_CONST(bool,
 | |
|                              SBFrame, operator!=,(const lldb::SBFrame &));
 | |
|   LLDB_REGISTER_METHOD_CONST(lldb::SBThread, SBFrame, GetThread, ());
 | |
|   LLDB_REGISTER_METHOD_CONST(const char *, SBFrame, Disassemble, ());
 | |
|   LLDB_REGISTER_METHOD(lldb::SBValueList, SBFrame, GetVariables,
 | |
|                        (bool, bool, bool, bool));
 | |
|   LLDB_REGISTER_METHOD(lldb::SBValueList, SBFrame, GetVariables,
 | |
|                        (bool, bool, bool, bool, lldb::DynamicValueType));
 | |
|   LLDB_REGISTER_METHOD(lldb::SBValueList, SBFrame, GetVariables,
 | |
|                        (const lldb::SBVariablesOptions &));
 | |
|   LLDB_REGISTER_METHOD(lldb::SBValueList, SBFrame, GetRegisters, ());
 | |
|   LLDB_REGISTER_METHOD(lldb::SBValue, SBFrame, FindRegister, (const char *));
 | |
|   LLDB_REGISTER_METHOD(bool, SBFrame, GetDescription, (lldb::SBStream &));
 | |
|   LLDB_REGISTER_METHOD(lldb::SBValue, SBFrame, EvaluateExpression,
 | |
|                        (const char *));
 | |
|   LLDB_REGISTER_METHOD(lldb::SBValue, SBFrame, EvaluateExpression,
 | |
|                        (const char *, lldb::DynamicValueType));
 | |
|   LLDB_REGISTER_METHOD(lldb::SBValue, SBFrame, EvaluateExpression,
 | |
|                        (const char *, lldb::DynamicValueType, bool));
 | |
|   LLDB_REGISTER_METHOD(lldb::SBValue, SBFrame, EvaluateExpression,
 | |
|                        (const char *, const lldb::SBExpressionOptions &));
 | |
|   LLDB_REGISTER_METHOD(bool, SBFrame, IsInlined, ());
 | |
|   LLDB_REGISTER_METHOD_CONST(bool, SBFrame, IsInlined, ());
 | |
|   LLDB_REGISTER_METHOD(bool, SBFrame, IsArtificial, ());
 | |
|   LLDB_REGISTER_METHOD_CONST(bool, SBFrame, IsArtificial, ());
 | |
|   LLDB_REGISTER_METHOD(const char *, SBFrame, GetFunctionName, ());
 | |
|   LLDB_REGISTER_METHOD_CONST(lldb::LanguageType, SBFrame, GuessLanguage, ());
 | |
|   LLDB_REGISTER_METHOD_CONST(const char *, SBFrame, GetFunctionName, ());
 | |
|   LLDB_REGISTER_METHOD(const char *, SBFrame, GetDisplayFunctionName, ());
 | |
| }
 | |
| 
 | |
| }
 | |
| }
 |