130fdc8d8SChris Lattner //===-- StackFrame.cpp ------------------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1030fdc8d8SChris Lattner // C Includes 1130fdc8d8SChris Lattner // C++ Includes 1230fdc8d8SChris Lattner // Other libraries and framework includes 1330fdc8d8SChris Lattner // Project includes 14d70a6e71SEugene Zelenko #include "lldb/Target/StackFrame.h" 150603aa9dSGreg Clayton #include "lldb/Core/Debugger.h" 1630fdc8d8SChris Lattner #include "lldb/Core/Disassembler.h" 17554f68d3SGreg Clayton #include "lldb/Core/FormatEntity.h" 18592afe73SEnrico Granata #include "lldb/Core/Mangled.h" 19592afe73SEnrico Granata #include "lldb/Core/Module.h" 2030fdc8d8SChris Lattner #include "lldb/Core/Value.h" 2154979cddSGreg Clayton #include "lldb/Core/ValueObjectConstResult.h" 224740a734SSean Callanan #include "lldb/Core/ValueObjectMemory.h" 23b9c1b51eSKate Stone #include "lldb/Core/ValueObjectVariable.h" 241f746071SGreg Clayton #include "lldb/Symbol/CompileUnit.h" 2530fdc8d8SChris Lattner #include "lldb/Symbol/Function.h" 261f746071SGreg Clayton #include "lldb/Symbol/Symbol.h" 271f746071SGreg Clayton #include "lldb/Symbol/SymbolContextScope.h" 2846252398SEnrico Granata #include "lldb/Symbol/Type.h" 29288bdf9cSGreg Clayton #include "lldb/Symbol/VariableList.h" 304740a734SSean Callanan #include "lldb/Target/ABI.h" 3130fdc8d8SChris Lattner #include "lldb/Target/ExecutionContext.h" 3230fdc8d8SChris Lattner #include "lldb/Target/Process.h" 3330fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h" 34*41ae8e74SKuba Mracek #include "lldb/Target/StackFrameRecognizer.h" 3530fdc8d8SChris Lattner #include "lldb/Target/Target.h" 3630fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 37d821c997SPavel Labath #include "lldb/Utility/RegisterValue.h" 3830fdc8d8SChris Lattner 39991e4453SZachary Turner #include "lldb/lldb-enumerations.h" 40991e4453SZachary Turner 4130fdc8d8SChris Lattner using namespace lldb; 4230fdc8d8SChris Lattner using namespace lldb_private; 4330fdc8d8SChris Lattner 4430fdc8d8SChris Lattner // The first bits in the flags are reserved for the SymbolContext::Scope bits 4530fdc8d8SChris Lattner // so we know if we have tried to look up information in our internal symbol 4630fdc8d8SChris Lattner // context (m_sc) already. 4759e8fc1cSGreg Clayton #define RESOLVED_FRAME_CODE_ADDR (uint32_t(eSymbolContextEverything + 1)) 486dadd508SGreg Clayton #define RESOLVED_FRAME_ID_SYMBOL_SCOPE (RESOLVED_FRAME_CODE_ADDR << 1) 4959e8fc1cSGreg Clayton #define GOT_FRAME_BASE (RESOLVED_FRAME_ID_SYMBOL_SCOPE << 1) 5059e8fc1cSGreg Clayton #define RESOLVED_VARIABLES (GOT_FRAME_BASE << 1) 517c0962dcSSean Callanan #define RESOLVED_GLOBAL_VARIABLES (RESOLVED_VARIABLES << 1) 5230fdc8d8SChris Lattner 53b9c1b51eSKate Stone StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, 54b9c1b51eSKate Stone user_id_t unwind_frame_index, addr_t cfa, 554b36f791SVedant Kumar bool cfa_is_valid, addr_t pc, StackFrame::Kind kind, 56bb19a13cSSaleem Abdulrasool const SymbolContext *sc_ptr) 57b9c1b51eSKate Stone : m_thread_wp(thread_sp), m_frame_index(frame_idx), 58b9c1b51eSKate Stone m_concrete_frame_index(unwind_frame_index), m_reg_context_sp(), 59b9c1b51eSKate Stone m_id(pc, cfa, nullptr), m_frame_code_addr(pc), m_sc(), m_flags(), 60b9c1b51eSKate Stone m_frame_base(), m_frame_base_error(), m_cfa_is_valid(cfa_is_valid), 614b36f791SVedant Kumar m_stack_frame_kind(kind), m_variable_list_sp(), 62*41ae8e74SKuba Mracek m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(), 63*41ae8e74SKuba Mracek m_mutex() { 64b9c1b51eSKate Stone // If we don't have a CFA value, use the frame index for our StackID so that 6505097246SAdrian Prantl // recursive functions properly aren't confused with one another on a history 6605097246SAdrian Prantl // stack. 674b36f791SVedant Kumar if (IsHistorical() && !m_cfa_is_valid) { 6899618476SJason Molenda m_id.SetCFA(m_frame_index); 6999618476SJason Molenda } 7099618476SJason Molenda 71b9c1b51eSKate Stone if (sc_ptr != nullptr) { 7230fdc8d8SChris Lattner m_sc = *sc_ptr; 731b72fcb7SGreg Clayton m_flags.Set(m_sc.GetResolvedMask()); 741b72fcb7SGreg Clayton } 7530fdc8d8SChris Lattner } 7630fdc8d8SChris Lattner 77b9c1b51eSKate Stone StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, 78b9c1b51eSKate Stone user_id_t unwind_frame_index, 79b9c1b51eSKate Stone const RegisterContextSP ®_context_sp, addr_t cfa, 80b9c1b51eSKate Stone addr_t pc, const SymbolContext *sc_ptr) 81b9c1b51eSKate Stone : m_thread_wp(thread_sp), m_frame_index(frame_idx), 825ccbd294SGreg Clayton m_concrete_frame_index(unwind_frame_index), 83b9c1b51eSKate Stone m_reg_context_sp(reg_context_sp), m_id(pc, cfa, nullptr), 84b9c1b51eSKate Stone m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(), 854b36f791SVedant Kumar m_frame_base_error(), m_cfa_is_valid(true), 864b36f791SVedant Kumar m_stack_frame_kind(StackFrame::Kind::Regular), m_variable_list_sp(), 87*41ae8e74SKuba Mracek m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(), 88*41ae8e74SKuba Mracek m_mutex() { 89b9c1b51eSKate Stone if (sc_ptr != nullptr) { 9030fdc8d8SChris Lattner m_sc = *sc_ptr; 911b72fcb7SGreg Clayton m_flags.Set(m_sc.GetResolvedMask()); 921b72fcb7SGreg Clayton } 931b72fcb7SGreg Clayton 94b9c1b51eSKate Stone if (reg_context_sp && !m_sc.target_sp) { 95d9e416c0SGreg Clayton m_sc.target_sp = reg_context_sp->CalculateTarget(); 96d9e416c0SGreg Clayton if (m_sc.target_sp) 971b72fcb7SGreg Clayton m_flags.Set(eSymbolContextTarget); 981b72fcb7SGreg Clayton } 991b72fcb7SGreg Clayton } 1001b72fcb7SGreg Clayton 101b9c1b51eSKate Stone StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, 102b9c1b51eSKate Stone user_id_t unwind_frame_index, 103b9c1b51eSKate Stone const RegisterContextSP ®_context_sp, addr_t cfa, 104b9c1b51eSKate Stone const Address &pc_addr, const SymbolContext *sc_ptr) 105b9c1b51eSKate Stone : m_thread_wp(thread_sp), m_frame_index(frame_idx), 1065ccbd294SGreg Clayton m_concrete_frame_index(unwind_frame_index), 1071b72fcb7SGreg Clayton m_reg_context_sp(reg_context_sp), 108b9c1b51eSKate Stone m_id(pc_addr.GetLoadAddress(thread_sp->CalculateTarget().get()), cfa, 109b9c1b51eSKate Stone nullptr), 110b9c1b51eSKate Stone m_frame_code_addr(pc_addr), m_sc(), m_flags(), m_frame_base(), 1114b36f791SVedant Kumar m_frame_base_error(), m_cfa_is_valid(true), 1124b36f791SVedant Kumar m_stack_frame_kind(StackFrame::Kind::Regular), m_variable_list_sp(), 113*41ae8e74SKuba Mracek m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(), 114*41ae8e74SKuba Mracek m_mutex() { 115b9c1b51eSKate Stone if (sc_ptr != nullptr) { 1161b72fcb7SGreg Clayton m_sc = *sc_ptr; 1171b72fcb7SGreg Clayton m_flags.Set(m_sc.GetResolvedMask()); 1181b72fcb7SGreg Clayton } 1191b72fcb7SGreg Clayton 120b9c1b51eSKate Stone if (!m_sc.target_sp && reg_context_sp) { 121d9e416c0SGreg Clayton m_sc.target_sp = reg_context_sp->CalculateTarget(); 122d9e416c0SGreg Clayton if (m_sc.target_sp) 1231b72fcb7SGreg Clayton m_flags.Set(eSymbolContextTarget); 1241b72fcb7SGreg Clayton } 1251b72fcb7SGreg Clayton 126e72dfb32SGreg Clayton ModuleSP pc_module_sp(pc_addr.GetModule()); 127b9c1b51eSKate Stone if (!m_sc.module_sp || m_sc.module_sp != pc_module_sp) { 128b9c1b51eSKate Stone if (pc_module_sp) { 129e72dfb32SGreg Clayton m_sc.module_sp = pc_module_sp; 1301b72fcb7SGreg Clayton m_flags.Set(eSymbolContextModule); 131b9c1b51eSKate Stone } else { 132ffc1d667SGreg Clayton m_sc.module_sp.reset(); 133ffc1d667SGreg Clayton } 1341b72fcb7SGreg Clayton } 13530fdc8d8SChris Lattner } 13630fdc8d8SChris Lattner 137d70a6e71SEugene Zelenko StackFrame::~StackFrame() = default; 13830fdc8d8SChris Lattner 139b9c1b51eSKate Stone StackID &StackFrame::GetStackID() { 140bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 14105097246SAdrian Prantl // Make sure we have resolved the StackID object's symbol context scope if we 14205097246SAdrian Prantl // already haven't looked it up. 14359e8fc1cSGreg Clayton 144b9c1b51eSKate Stone if (m_flags.IsClear(RESOLVED_FRAME_ID_SYMBOL_SCOPE)) { 145b9c1b51eSKate Stone if (m_id.GetSymbolContextScope()) { 14605097246SAdrian Prantl // We already have a symbol context scope, we just don't have our flag 14705097246SAdrian Prantl // bit set. 14859e8fc1cSGreg Clayton m_flags.Set(RESOLVED_FRAME_ID_SYMBOL_SCOPE); 149b9c1b51eSKate Stone } else { 15005097246SAdrian Prantl // Calculate the frame block and use this for the stack ID symbol context 15105097246SAdrian Prantl // scope if we have one. 15295897c6aSGreg Clayton SymbolContextScope *scope = GetFrameBlock(); 153b9c1b51eSKate Stone if (scope == nullptr) { 15495897c6aSGreg Clayton // We don't have a block, so use the symbol 15595897c6aSGreg Clayton if (m_flags.IsClear(eSymbolContextSymbol)) 15659e8fc1cSGreg Clayton GetSymbolContext(eSymbolContextSymbol); 15795897c6aSGreg Clayton 158d70a6e71SEugene Zelenko // It is ok if m_sc.symbol is nullptr here 15995897c6aSGreg Clayton scope = m_sc.symbol; 16059e8fc1cSGreg Clayton } 16195897c6aSGreg Clayton // Set the symbol context scope (the accessor will set the 16295897c6aSGreg Clayton // RESOLVED_FRAME_ID_SYMBOL_SCOPE bit in m_flags). 16395897c6aSGreg Clayton SetSymbolContextScope(scope); 16459e8fc1cSGreg Clayton } 16559e8fc1cSGreg Clayton } 16630fdc8d8SChris Lattner return m_id; 16730fdc8d8SChris Lattner } 16830fdc8d8SChris Lattner 169b9c1b51eSKate Stone uint32_t StackFrame::GetFrameIndex() const { 170513c6bb8SJim Ingham ThreadSP thread_sp = GetThread(); 171513c6bb8SJim Ingham if (thread_sp) 172b9c1b51eSKate Stone return thread_sp->GetStackFrameList()->GetVisibleStackFrameIndex( 173b9c1b51eSKate Stone m_frame_index); 174513c6bb8SJim Ingham else 175513c6bb8SJim Ingham return m_frame_index; 176513c6bb8SJim Ingham } 177513c6bb8SJim Ingham 178b9c1b51eSKate Stone void StackFrame::SetSymbolContextScope(SymbolContextScope *symbol_scope) { 179bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 18059e8fc1cSGreg Clayton m_flags.Set(RESOLVED_FRAME_ID_SYMBOL_SCOPE); 18159e8fc1cSGreg Clayton m_id.SetSymbolContextScope(symbol_scope); 18259e8fc1cSGreg Clayton } 18359e8fc1cSGreg Clayton 184b9c1b51eSKate Stone const Address &StackFrame::GetFrameCodeAddress() { 185bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 186b9c1b51eSKate Stone if (m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR) && 187b9c1b51eSKate Stone !m_frame_code_addr.IsSectionOffset()) { 18859e8fc1cSGreg Clayton m_flags.Set(RESOLVED_FRAME_CODE_ADDR); 18930fdc8d8SChris Lattner 19030fdc8d8SChris Lattner // Resolve the PC into a temporary address because if ResolveLoadAddress 19130fdc8d8SChris Lattner // fails to resolve the address, it will clear the address object... 192d9e416c0SGreg Clayton ThreadSP thread_sp(GetThread()); 193b9c1b51eSKate Stone if (thread_sp) { 194d9e416c0SGreg Clayton TargetSP target_sp(thread_sp->CalculateTarget()); 195b9c1b51eSKate Stone if (target_sp) { 196c3c72122SPavel Labath const bool allow_section_end = true; 197b9c1b51eSKate Stone if (m_frame_code_addr.SetOpcodeLoadAddress( 198b9c1b51eSKate Stone m_frame_code_addr.GetOffset(), target_sp.get(), 19904803b3eSTatyana Krasnukha AddressClass::eCode, allow_section_end)) { 200e72dfb32SGreg Clayton ModuleSP module_sp(m_frame_code_addr.GetModule()); 201b9c1b51eSKate Stone if (module_sp) { 202e72dfb32SGreg Clayton m_sc.module_sp = module_sp; 20330fdc8d8SChris Lattner m_flags.Set(eSymbolContextModule); 20430fdc8d8SChris Lattner } 20530fdc8d8SChris Lattner } 20630fdc8d8SChris Lattner } 20730fdc8d8SChris Lattner } 208d9e416c0SGreg Clayton } 20912fc3e0fSGreg Clayton return m_frame_code_addr; 21030fdc8d8SChris Lattner } 21130fdc8d8SChris Lattner 212b9c1b51eSKate Stone bool StackFrame::ChangePC(addr_t pc) { 213bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 21499618476SJason Molenda // We can't change the pc value of a history stack frame - it is immutable. 2154b36f791SVedant Kumar if (IsHistorical()) 21699618476SJason Molenda return false; 217e72dfb32SGreg Clayton m_frame_code_addr.SetRawAddress(pc); 21872310355SGreg Clayton m_sc.Clear(false); 21973b472d4SGreg Clayton m_flags.Reset(0); 220d9e416c0SGreg Clayton ThreadSP thread_sp(GetThread()); 221d9e416c0SGreg Clayton if (thread_sp) 222d9e416c0SGreg Clayton thread_sp->ClearStackFrames(); 22399618476SJason Molenda return true; 22430fdc8d8SChris Lattner } 22530fdc8d8SChris Lattner 226b9c1b51eSKate Stone const char *StackFrame::Disassemble() { 227bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 2288b3f2160SZachary Turner if (m_disassembly.Empty()) { 229d9e416c0SGreg Clayton ExecutionContext exe_ctx(shared_from_this()); 230d9e416c0SGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 231b9c1b51eSKate Stone if (target) { 232d70a6e71SEugene Zelenko const char *plugin_name = nullptr; 233d70a6e71SEugene Zelenko const char *flavor = nullptr; 2348b3f2160SZachary Turner Disassembler::Disassemble(target->GetDebugger(), 2358b3f2160SZachary Turner target->GetArchitecture(), plugin_name, flavor, 2368b3f2160SZachary Turner exe_ctx, 0, false, 0, 0, m_disassembly); 23730fdc8d8SChris Lattner } 2388b3f2160SZachary Turner if (m_disassembly.Empty()) 2398b3f2160SZachary Turner return nullptr; 2408b3f2160SZachary Turner } 2418b3f2160SZachary Turner 24230fdc8d8SChris Lattner return m_disassembly.GetData(); 24330fdc8d8SChris Lattner } 24430fdc8d8SChris Lattner 245b9c1b51eSKate Stone Block *StackFrame::GetFrameBlock() { 246d70a6e71SEugene Zelenko if (m_sc.block == nullptr && m_flags.IsClear(eSymbolContextBlock)) 24795897c6aSGreg Clayton GetSymbolContext(eSymbolContextBlock); 24895897c6aSGreg Clayton 249b9c1b51eSKate Stone if (m_sc.block) { 25095897c6aSGreg Clayton Block *inline_block = m_sc.block->GetContainingInlinedBlock(); 251b9c1b51eSKate Stone if (inline_block) { 25205097246SAdrian Prantl // Use the block with the inlined function info as the frame block we 25305097246SAdrian Prantl // want this frame to have only the variables for the inlined function 25405097246SAdrian Prantl // and its non-inlined block child blocks. 25595897c6aSGreg Clayton return inline_block; 256b9c1b51eSKate Stone } else { 25705097246SAdrian Prantl // This block is not contained within any inlined function blocks with so 25805097246SAdrian Prantl // we want to use the top most function block. 25995897c6aSGreg Clayton return &m_sc.function->GetBlock(false); 26095897c6aSGreg Clayton } 26195897c6aSGreg Clayton } 262d70a6e71SEugene Zelenko return nullptr; 26395897c6aSGreg Clayton } 26495897c6aSGreg Clayton 26530fdc8d8SChris Lattner //---------------------------------------------------------------------- 26630fdc8d8SChris Lattner // Get the symbol context if we already haven't done so by resolving the 26730fdc8d8SChris Lattner // PC address as much as possible. This way when we pass around a 26805097246SAdrian Prantl // StackFrame object, everyone will have as much information as possible and no 26905097246SAdrian Prantl // one will ever have to look things up manually. 27030fdc8d8SChris Lattner //---------------------------------------------------------------------- 271991e4453SZachary Turner const SymbolContext & 272991e4453SZachary Turner StackFrame::GetSymbolContext(SymbolContextItem resolve_scope) { 273bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 27430fdc8d8SChris Lattner // Copy our internal symbol context into "sc". 275b9c1b51eSKate Stone if ((m_flags.Get() & resolve_scope) != resolve_scope) { 27675a0333bSGreg Clayton uint32_t resolved = 0; 27775a0333bSGreg Clayton 27875a0333bSGreg Clayton // If the target was requested add that: 279b9c1b51eSKate Stone if (!m_sc.target_sp) { 28075a0333bSGreg Clayton m_sc.target_sp = CalculateTarget(); 28175a0333bSGreg Clayton if (m_sc.target_sp) 28275a0333bSGreg Clayton resolved |= eSymbolContextTarget; 28375a0333bSGreg Clayton } 28475a0333bSGreg Clayton 28505097246SAdrian Prantl // Resolve our PC to section offset if we haven't already done so and if we 28605097246SAdrian Prantl // don't have a module. The resolved address section will contain the 28705097246SAdrian Prantl // module to which it belongs 28859e8fc1cSGreg Clayton if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR)) 2899da7bd07SGreg Clayton GetFrameCodeAddress(); 29030fdc8d8SChris Lattner 29105097246SAdrian Prantl // If this is not frame zero, then we need to subtract 1 from the PC value 29205097246SAdrian Prantl // when doing address lookups since the PC will be on the instruction 29305097246SAdrian Prantl // following the function call instruction... 29430fdc8d8SChris Lattner 2959da7bd07SGreg Clayton Address lookup_addr(GetFrameCodeAddress()); 296b9c1b51eSKate Stone if (m_frame_index > 0 && lookup_addr.IsValid()) { 29730fdc8d8SChris Lattner addr_t offset = lookup_addr.GetOffset(); 298b9c1b51eSKate Stone if (offset > 0) { 29930fdc8d8SChris Lattner lookup_addr.SetOffset(offset - 1); 300cf29675dSJason Molenda 301b9c1b51eSKate Stone } else { 30205097246SAdrian Prantl // lookup_addr is the start of a section. We need do the math on the 30305097246SAdrian Prantl // actual load address and re-compute the section. We're working with 30405097246SAdrian Prantl // a 'noreturn' function at the end of a section. 305cf29675dSJason Molenda ThreadSP thread_sp(GetThread()); 306b9c1b51eSKate Stone if (thread_sp) { 307cf29675dSJason Molenda TargetSP target_sp(thread_sp->CalculateTarget()); 308b9c1b51eSKate Stone if (target_sp) { 309b9c1b51eSKate Stone addr_t addr_minus_one = 310b9c1b51eSKate Stone lookup_addr.GetLoadAddress(target_sp.get()) - 1; 311cf29675dSJason Molenda lookup_addr.SetLoadAddress(addr_minus_one, target_sp.get()); 312b9c1b51eSKate Stone } else { 313cf29675dSJason Molenda lookup_addr.SetOffset(offset - 1); 314cf29675dSJason Molenda } 315cf29675dSJason Molenda } 316cf29675dSJason Molenda } 31730fdc8d8SChris Lattner } 31830fdc8d8SChris Lattner 319b9c1b51eSKate Stone if (m_sc.module_sp) { 32005097246SAdrian Prantl // We have something in our stack frame symbol context, lets check if we 32105097246SAdrian Prantl // haven't already tried to lookup one of those things. If we haven't 32205097246SAdrian Prantl // then we will do the query. 3231b72fcb7SGreg Clayton 324991e4453SZachary Turner SymbolContextItem actual_resolve_scope = SymbolContextItem(0); 3251b72fcb7SGreg Clayton 326b9c1b51eSKate Stone if (resolve_scope & eSymbolContextCompUnit) { 327b9c1b51eSKate Stone if (m_flags.IsClear(eSymbolContextCompUnit)) { 3281b72fcb7SGreg Clayton if (m_sc.comp_unit) 3299da7bd07SGreg Clayton resolved |= eSymbolContextCompUnit; 3301b72fcb7SGreg Clayton else 3311b72fcb7SGreg Clayton actual_resolve_scope |= eSymbolContextCompUnit; 3321b72fcb7SGreg Clayton } 3331b72fcb7SGreg Clayton } 3341b72fcb7SGreg Clayton 335b9c1b51eSKate Stone if (resolve_scope & eSymbolContextFunction) { 336b9c1b51eSKate Stone if (m_flags.IsClear(eSymbolContextFunction)) { 3371b72fcb7SGreg Clayton if (m_sc.function) 3389da7bd07SGreg Clayton resolved |= eSymbolContextFunction; 3391b72fcb7SGreg Clayton else 3401b72fcb7SGreg Clayton actual_resolve_scope |= eSymbolContextFunction; 3411b72fcb7SGreg Clayton } 3421b72fcb7SGreg Clayton } 3431b72fcb7SGreg Clayton 344b9c1b51eSKate Stone if (resolve_scope & eSymbolContextBlock) { 345b9c1b51eSKate Stone if (m_flags.IsClear(eSymbolContextBlock)) { 3461b72fcb7SGreg Clayton if (m_sc.block) 3479da7bd07SGreg Clayton resolved |= eSymbolContextBlock; 3481b72fcb7SGreg Clayton else 3491b72fcb7SGreg Clayton actual_resolve_scope |= eSymbolContextBlock; 3501b72fcb7SGreg Clayton } 3511b72fcb7SGreg Clayton } 3521b72fcb7SGreg Clayton 353b9c1b51eSKate Stone if (resolve_scope & eSymbolContextSymbol) { 354b9c1b51eSKate Stone if (m_flags.IsClear(eSymbolContextSymbol)) { 3551b72fcb7SGreg Clayton if (m_sc.symbol) 3569da7bd07SGreg Clayton resolved |= eSymbolContextSymbol; 3571b72fcb7SGreg Clayton else 3581b72fcb7SGreg Clayton actual_resolve_scope |= eSymbolContextSymbol; 3591b72fcb7SGreg Clayton } 3601b72fcb7SGreg Clayton } 3611b72fcb7SGreg Clayton 362b9c1b51eSKate Stone if (resolve_scope & eSymbolContextLineEntry) { 363b9c1b51eSKate Stone if (m_flags.IsClear(eSymbolContextLineEntry)) { 3641b72fcb7SGreg Clayton if (m_sc.line_entry.IsValid()) 3659da7bd07SGreg Clayton resolved |= eSymbolContextLineEntry; 3661b72fcb7SGreg Clayton else 3671b72fcb7SGreg Clayton actual_resolve_scope |= eSymbolContextLineEntry; 3681b72fcb7SGreg Clayton } 3691b72fcb7SGreg Clayton } 3701b72fcb7SGreg Clayton 371b9c1b51eSKate Stone if (actual_resolve_scope) { 37205097246SAdrian Prantl // We might be resolving less information than what is already in our 37305097246SAdrian Prantl // current symbol context so resolve into a temporary symbol context 37405097246SAdrian Prantl // "sc" so we don't clear out data we have already found in "m_sc" 37530fdc8d8SChris Lattner SymbolContext sc; 37630fdc8d8SChris Lattner // Set flags that indicate what we have tried to resolve 377b9c1b51eSKate Stone resolved |= m_sc.module_sp->ResolveSymbolContextForAddress( 378b9c1b51eSKate Stone lookup_addr, actual_resolve_scope, sc); 37905097246SAdrian Prantl // Only replace what we didn't already have as we may have information 38005097246SAdrian Prantl // for an inlined function scope that won't match what a standard 38105097246SAdrian Prantl // lookup by address would match 382d70a6e71SEugene Zelenko if ((resolved & eSymbolContextCompUnit) && m_sc.comp_unit == nullptr) 3839da7bd07SGreg Clayton m_sc.comp_unit = sc.comp_unit; 384d70a6e71SEugene Zelenko if ((resolved & eSymbolContextFunction) && m_sc.function == nullptr) 3859da7bd07SGreg Clayton m_sc.function = sc.function; 386d70a6e71SEugene Zelenko if ((resolved & eSymbolContextBlock) && m_sc.block == nullptr) 3879da7bd07SGreg Clayton m_sc.block = sc.block; 388d70a6e71SEugene Zelenko if ((resolved & eSymbolContextSymbol) && m_sc.symbol == nullptr) 3899da7bd07SGreg Clayton m_sc.symbol = sc.symbol; 390b9c1b51eSKate Stone if ((resolved & eSymbolContextLineEntry) && 391b9c1b51eSKate Stone !m_sc.line_entry.IsValid()) { 3929da7bd07SGreg Clayton m_sc.line_entry = sc.line_entry; 393911d5784STed Woodward m_sc.line_entry.ApplyFileMappings(m_sc.target_sp); 39475a0333bSGreg Clayton } 39530fdc8d8SChris Lattner } 396b9c1b51eSKate Stone } else { 39730fdc8d8SChris Lattner // If we don't have a module, then we can't have the compile unit, 39830fdc8d8SChris Lattner // function, block, line entry or symbol, so we can safely call 39930fdc8d8SChris Lattner // ResolveSymbolContextForAddress with our symbol context member m_sc. 400b9c1b51eSKate Stone if (m_sc.target_sp) { 401b9c1b51eSKate Stone resolved |= m_sc.target_sp->GetImages().ResolveSymbolContextForAddress( 402b9c1b51eSKate Stone lookup_addr, resolve_scope, m_sc); 403f4be227dSSean Callanan } 4049da7bd07SGreg Clayton } 40530fdc8d8SChris Lattner 40630fdc8d8SChris Lattner // Update our internal flags so we remember what we have tried to locate so 40730fdc8d8SChris Lattner // we don't have to keep trying when more calls to this function are made. 40805097246SAdrian Prantl // We might have dug up more information that was requested (for example if 40905097246SAdrian Prantl // we were asked to only get the block, we will have gotten the compile 41005097246SAdrian Prantl // unit, and function) so set any additional bits that we resolved 4119da7bd07SGreg Clayton m_flags.Set(resolve_scope | resolved); 41230fdc8d8SChris Lattner } 41330fdc8d8SChris Lattner 41430fdc8d8SChris Lattner // Return the symbol context with everything that was possible to resolve 41530fdc8d8SChris Lattner // resolved. 41630fdc8d8SChris Lattner return m_sc; 41730fdc8d8SChris Lattner } 41830fdc8d8SChris Lattner 419b9c1b51eSKate Stone VariableList *StackFrame::GetVariableList(bool get_file_globals) { 420bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 421b9c1b51eSKate Stone if (m_flags.IsClear(RESOLVED_VARIABLES)) { 42230fdc8d8SChris Lattner m_flags.Set(RESOLVED_VARIABLES); 42330fdc8d8SChris Lattner 42495897c6aSGreg Clayton Block *frame_block = GetFrameBlock(); 425288bdf9cSGreg Clayton 426b9c1b51eSKate Stone if (frame_block) { 42795897c6aSGreg Clayton const bool get_child_variables = true; 42895897c6aSGreg Clayton const bool can_create = true; 429c662ec8bSGreg Clayton const bool stop_if_child_block_is_inlined_function = true; 430c662ec8bSGreg Clayton m_variable_list_sp.reset(new VariableList()); 431b9c1b51eSKate Stone frame_block->AppendBlockVariables(can_create, get_child_variables, 43272ac8a84STamas Berghammer stop_if_child_block_is_inlined_function, 4333bc714b2SZachary Turner [](Variable *v) { return true; }, 43472ac8a84STamas Berghammer m_variable_list_sp.get()); 43530fdc8d8SChris Lattner } 4367c0962dcSSean Callanan } 437288bdf9cSGreg Clayton 438b9c1b51eSKate Stone if (m_flags.IsClear(RESOLVED_GLOBAL_VARIABLES) && get_file_globals) { 4397c0962dcSSean Callanan m_flags.Set(RESOLVED_GLOBAL_VARIABLES); 4407c0962dcSSean Callanan 44195897c6aSGreg Clayton if (m_flags.IsClear(eSymbolContextCompUnit)) 44295897c6aSGreg Clayton GetSymbolContext(eSymbolContextCompUnit); 44395897c6aSGreg Clayton 444b9c1b51eSKate Stone if (m_sc.comp_unit) { 445b9c1b51eSKate Stone VariableListSP global_variable_list_sp( 446b9c1b51eSKate Stone m_sc.comp_unit->GetVariableList(true)); 447288bdf9cSGreg Clayton if (m_variable_list_sp) 448288bdf9cSGreg Clayton m_variable_list_sp->AddVariables(global_variable_list_sp.get()); 449288bdf9cSGreg Clayton else 450288bdf9cSGreg Clayton m_variable_list_sp = global_variable_list_sp; 451288bdf9cSGreg Clayton } 45230fdc8d8SChris Lattner } 4537c0962dcSSean Callanan 45430fdc8d8SChris Lattner return m_variable_list_sp.get(); 45530fdc8d8SChris Lattner } 45630fdc8d8SChris Lattner 457d41f032aSGreg Clayton VariableListSP 458b9c1b51eSKate Stone StackFrame::GetInScopeVariableList(bool get_file_globals, 459b9c1b51eSKate Stone bool must_have_valid_location) { 460bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 46199618476SJason Molenda // We can't fetch variable information for a history stack frame. 4624b36f791SVedant Kumar if (IsHistorical()) 46399618476SJason Molenda return VariableListSP(); 46499618476SJason Molenda 465d41f032aSGreg Clayton VariableListSP var_list_sp(new VariableList); 466d41f032aSGreg Clayton GetSymbolContext(eSymbolContextCompUnit | eSymbolContextBlock); 467d41f032aSGreg Clayton 468b9c1b51eSKate Stone if (m_sc.block) { 469d41f032aSGreg Clayton const bool can_create = true; 470d41f032aSGreg Clayton const bool get_parent_variables = true; 471d41f032aSGreg Clayton const bool stop_if_block_is_inlined_function = true; 472b9c1b51eSKate Stone m_sc.block->AppendVariables( 473b9c1b51eSKate Stone can_create, get_parent_variables, stop_if_block_is_inlined_function, 474b9c1b51eSKate Stone [this, must_have_valid_location](Variable *v) { 475b9c1b51eSKate Stone return v->IsInScope(this) && (!must_have_valid_location || 476b9c1b51eSKate Stone v->LocationIsValidForFrame(this)); 477cef46177SJim Ingham }, 478d41f032aSGreg Clayton var_list_sp.get()); 479d41f032aSGreg Clayton } 480d41f032aSGreg Clayton 481b9c1b51eSKate Stone if (m_sc.comp_unit && get_file_globals) { 482b9c1b51eSKate Stone VariableListSP global_variable_list_sp( 483b9c1b51eSKate Stone m_sc.comp_unit->GetVariableList(true)); 484d41f032aSGreg Clayton if (global_variable_list_sp) 485d41f032aSGreg Clayton var_list_sp->AddVariables(global_variable_list_sp.get()); 486d41f032aSGreg Clayton } 487d41f032aSGreg Clayton 488d41f032aSGreg Clayton return var_list_sp; 489d41f032aSGreg Clayton } 490d41f032aSGreg Clayton 491b9c1b51eSKate Stone ValueObjectSP StackFrame::GetValueForVariableExpressionPath( 4920eb31a1dSZachary Turner llvm::StringRef var_expr, DynamicValueType use_dynamic, uint32_t options, 49397206d57SZachary Turner VariableSP &var_sp, Status &error) { 4940eb31a1dSZachary Turner llvm::StringRef original_var_expr = var_expr; 49599618476SJason Molenda // We can't fetch variable information for a history stack frame. 4964b36f791SVedant Kumar if (IsHistorical()) 49799618476SJason Molenda return ValueObjectSP(); 49854979cddSGreg Clayton 4990eb31a1dSZachary Turner if (var_expr.empty()) { 5000eb31a1dSZachary Turner error.SetErrorStringWithFormat("invalid variable path '%s'", 5010eb31a1dSZachary Turner var_expr.str().c_str()); 50224bd3178SZachary Turner return ValueObjectSP(); 50324bd3178SZachary Turner } 50424bd3178SZachary Turner 505b9c1b51eSKate Stone const bool check_ptr_vs_member = 506b9c1b51eSKate Stone (options & eExpressionPathOptionCheckPtrVsMember) != 0; 507b9c1b51eSKate Stone const bool no_fragile_ivar = 508b9c1b51eSKate Stone (options & eExpressionPathOptionsNoFragileObjcIvar) != 0; 509b9c1b51eSKate Stone const bool no_synth_child = 510b9c1b51eSKate Stone (options & eExpressionPathOptionsNoSyntheticChildren) != 0; 511b9c1b51eSKate Stone // const bool no_synth_array = (options & 512b9c1b51eSKate Stone // eExpressionPathOptionsNoSyntheticArrayRange) != 0; 51354979cddSGreg Clayton error.Clear(); 5148b2fe6dcSGreg Clayton bool deref = false; 5158b2fe6dcSGreg Clayton bool address_of = false; 5168b2fe6dcSGreg Clayton ValueObjectSP valobj_sp; 5178b2fe6dcSGreg Clayton const bool get_file_globals = true; 518d41f032aSGreg Clayton // When looking up a variable for an expression, we need only consider the 519d41f032aSGreg Clayton // variables that are in scope. 520d41f032aSGreg Clayton VariableListSP var_list_sp(GetInScopeVariableList(get_file_globals)); 521d41f032aSGreg Clayton VariableList *variable_list = var_list_sp.get(); 5228b2fe6dcSGreg Clayton 52324bd3178SZachary Turner if (!variable_list) 52424bd3178SZachary Turner return ValueObjectSP(); 52524bd3178SZachary Turner 5268b2fe6dcSGreg Clayton // If first character is a '*', then show pointer contents 52724bd3178SZachary Turner std::string var_expr_storage; 528b9c1b51eSKate Stone if (var_expr[0] == '*') { 5298b2fe6dcSGreg Clayton deref = true; 53024bd3178SZachary Turner var_expr = var_expr.drop_front(); // Skip the '*' 531b9c1b51eSKate Stone } else if (var_expr[0] == '&') { 5328b2fe6dcSGreg Clayton address_of = true; 53324bd3178SZachary Turner var_expr = var_expr.drop_front(); // Skip the '&' 5348b2fe6dcSGreg Clayton } 5358b2fe6dcSGreg Clayton 53624bd3178SZachary Turner size_t separator_idx = var_expr.find_first_of(".-[=+~|&^%#@!/?,<>{}"); 53754979cddSGreg Clayton StreamString var_expr_path_strm; 5388b2fe6dcSGreg Clayton 53924bd3178SZachary Turner ConstString name_const_string(var_expr.substr(0, separator_idx)); 5408b2fe6dcSGreg Clayton 54110bc1a4eSPaul Herman var_sp = variable_list->FindVariable(name_const_string, false); 542685c88c5SGreg Clayton 543685c88c5SGreg Clayton bool synthetically_added_instance_object = false; 544685c88c5SGreg Clayton 545b9c1b51eSKate Stone if (var_sp) { 54624bd3178SZachary Turner var_expr = var_expr.drop_front(name_const_string.GetLength()); 547685c88c5SGreg Clayton } 54846252398SEnrico Granata 549b9c1b51eSKate Stone if (!var_sp && (options & eExpressionPathOptionsAllowDirectIVarAccess)) { 55005097246SAdrian Prantl // Check for direct ivars access which helps us with implicit access to 55105097246SAdrian Prantl // ivars with the "this->" or "self->" 552685c88c5SGreg Clayton GetSymbolContext(eSymbolContextFunction | eSymbolContextBlock); 553685c88c5SGreg Clayton lldb::LanguageType method_language = eLanguageTypeUnknown; 554685c88c5SGreg Clayton bool is_instance_method = false; 555685c88c5SGreg Clayton ConstString method_object_name; 556b9c1b51eSKate Stone if (m_sc.GetFunctionMethodInfo(method_language, is_instance_method, 557b9c1b51eSKate Stone method_object_name)) { 558b9c1b51eSKate Stone if (is_instance_method && method_object_name) { 559685c88c5SGreg Clayton var_sp = variable_list->FindVariable(method_object_name); 560b9c1b51eSKate Stone if (var_sp) { 561685c88c5SGreg Clayton separator_idx = 0; 56224bd3178SZachary Turner var_expr_storage = "->"; 56324bd3178SZachary Turner var_expr_storage += var_expr; 56424bd3178SZachary Turner var_expr = var_expr_storage; 565685c88c5SGreg Clayton synthetically_added_instance_object = true; 566685c88c5SGreg Clayton } 567685c88c5SGreg Clayton } 568685c88c5SGreg Clayton } 569685c88c5SGreg Clayton } 570685c88c5SGreg Clayton 571b9c1b51eSKate Stone if (!var_sp && (options & eExpressionPathOptionsInspectAnonymousUnions)) { 572b9c1b51eSKate Stone // Check if any anonymous unions are there which contain a variable with 573b9c1b51eSKate Stone // the name we need 574b9c1b51eSKate Stone for (size_t i = 0; i < variable_list->GetSize(); i++) { 57524bd3178SZachary Turner VariableSP variable_sp = variable_list->GetVariableAtIndex(i); 57624bd3178SZachary Turner if (!variable_sp) 57724bd3178SZachary Turner continue; 57824bd3178SZachary Turner if (!variable_sp->GetName().IsEmpty()) 57924bd3178SZachary Turner continue; 58024bd3178SZachary Turner 58124bd3178SZachary Turner Type *var_type = variable_sp->GetType(); 58224bd3178SZachary Turner if (!var_type) 58324bd3178SZachary Turner continue; 58424bd3178SZachary Turner 58524bd3178SZachary Turner if (!var_type->GetForwardCompilerType().IsAnonymousType()) 58624bd3178SZachary Turner continue; 58724bd3178SZachary Turner valobj_sp = GetValueObjectForFrameVariable(variable_sp, use_dynamic); 58846252398SEnrico Granata if (!valobj_sp) 58946252398SEnrico Granata return valobj_sp; 59024bd3178SZachary Turner valobj_sp = valobj_sp->GetChildMemberWithName(name_const_string, true); 59146252398SEnrico Granata if (valobj_sp) 59246252398SEnrico Granata break; 59346252398SEnrico Granata } 59446252398SEnrico Granata } 59546252398SEnrico Granata 596b9c1b51eSKate Stone if (var_sp && !valobj_sp) { 5972837b766SJim Ingham valobj_sp = GetValueObjectForFrameVariable(var_sp, use_dynamic); 59878a685aaSJim Ingham if (!valobj_sp) 59978a685aaSJim Ingham return valobj_sp; 60046252398SEnrico Granata } 60124bd3178SZachary Turner if (!valobj_sp) { 60224bd3178SZachary Turner error.SetErrorStringWithFormat("no variable named '%s' found in this frame", 60324bd3178SZachary Turner name_const_string.GetCString()); 60424bd3178SZachary Turner return ValueObjectSP(); 60524bd3178SZachary Turner } 60624bd3178SZachary Turner 6078b2fe6dcSGreg Clayton // We are dumping at least one child 608b9c1b51eSKate Stone while (separator_idx != std::string::npos) { 6098b2fe6dcSGreg Clayton // Calculate the next separator index ahead of time 6108b2fe6dcSGreg Clayton ValueObjectSP child_valobj_sp; 61124bd3178SZachary Turner const char separator_type = var_expr[0]; 6124c08fe28STamas Berghammer bool expr_is_ptr = false; 613b9c1b51eSKate Stone switch (separator_type) { 6148b2fe6dcSGreg Clayton case '-': 6154c08fe28STamas Berghammer expr_is_ptr = true; 61624bd3178SZachary Turner if (var_expr.size() >= 2 && var_expr[1] != '>') 6178b2fe6dcSGreg Clayton return ValueObjectSP(); 6188b2fe6dcSGreg Clayton 619b9c1b51eSKate Stone if (no_fragile_ivar) { 6206d5e68eaSGreg Clayton // Make sure we aren't trying to deref an objective 6216d5e68eaSGreg Clayton // C ivar if this is not allowed 622b9c1b51eSKate Stone const uint32_t pointer_type_flags = 623b9c1b51eSKate Stone valobj_sp->GetCompilerType().GetTypeInfo(nullptr); 624622be238SEnrico Granata if ((pointer_type_flags & eTypeIsObjC) && 625b9c1b51eSKate Stone (pointer_type_flags & eTypeIsPointer)) { 62605097246SAdrian Prantl // This was an objective C object pointer and it was requested we 62705097246SAdrian Prantl // skip any fragile ivars so return nothing here 6286d5e68eaSGreg Clayton return ValueObjectSP(); 6296d5e68eaSGreg Clayton } 6306d5e68eaSGreg Clayton } 6314c08fe28STamas Berghammer 6324c08fe28STamas Berghammer // If we have a non pointer type with a sythetic value then lets check if 6334c08fe28STamas Berghammer // we have an sythetic dereference specified. 6344c08fe28STamas Berghammer if (!valobj_sp->IsPointerType() && valobj_sp->HasSyntheticValue()) { 63597206d57SZachary Turner Status deref_error; 6364c08fe28STamas Berghammer if (valobj_sp->GetCompilerType().IsReferenceType()) { 6374c08fe28STamas Berghammer valobj_sp = valobj_sp->GetSyntheticValue()->Dereference(deref_error); 6384c08fe28STamas Berghammer if (error.Fail()) { 6394c08fe28STamas Berghammer error.SetErrorStringWithFormatv( 6404c08fe28STamas Berghammer "Failed to dereference reference type: %s", deref_error); 6414c08fe28STamas Berghammer return ValueObjectSP(); 6424c08fe28STamas Berghammer } 6434c08fe28STamas Berghammer } 6444c08fe28STamas Berghammer 6454c08fe28STamas Berghammer valobj_sp = valobj_sp->Dereference(deref_error); 6464c08fe28STamas Berghammer if (error.Fail()) { 6474c08fe28STamas Berghammer error.SetErrorStringWithFormatv( 6484c08fe28STamas Berghammer "Failed to dereference sythetic value: %s", deref_error); 6494c08fe28STamas Berghammer return ValueObjectSP(); 6504c08fe28STamas Berghammer } 6514c08fe28STamas Berghammer expr_is_ptr = false; 6524c08fe28STamas Berghammer } 6534c08fe28STamas Berghammer 65424bd3178SZachary Turner var_expr = var_expr.drop_front(); // Remove the '-' 65562e0681aSJason Molenda LLVM_FALLTHROUGH; 656b9c1b51eSKate Stone case '.': { 65724bd3178SZachary Turner var_expr = var_expr.drop_front(); // Remove the '.' or '>' 65824bd3178SZachary Turner separator_idx = var_expr.find_first_of(".-["); 65924bd3178SZachary Turner ConstString child_name(var_expr.substr(0, var_expr.find_first_of(".-["))); 6608b2fe6dcSGreg Clayton 661b9c1b51eSKate Stone if (check_ptr_vs_member) { 66205097246SAdrian Prantl // We either have a pointer type and need to verify valobj_sp is a 66305097246SAdrian Prantl // pointer, or we have a member of a class/union/struct being accessed 66405097246SAdrian Prantl // with the . syntax and need to verify we don't have a pointer. 66554979cddSGreg Clayton const bool actual_is_ptr = valobj_sp->IsPointerType(); 66654979cddSGreg Clayton 667b9c1b51eSKate Stone if (actual_is_ptr != expr_is_ptr) { 66805097246SAdrian Prantl // Incorrect use of "." with a pointer, or "->" with a 66905097246SAdrian Prantl // class/union/struct instance or reference. 6706beaaa68SGreg Clayton valobj_sp->GetExpressionPath(var_expr_path_strm, false); 67154979cddSGreg Clayton if (actual_is_ptr) 672b9c1b51eSKate Stone error.SetErrorStringWithFormat( 673b9c1b51eSKate Stone "\"%s\" is a pointer and . was used to attempt to access " 674b9c1b51eSKate Stone "\"%s\". Did you mean \"%s->%s\"?", 675c156427dSZachary Turner var_expr_path_strm.GetData(), child_name.GetCString(), 67624bd3178SZachary Turner var_expr_path_strm.GetData(), var_expr.str().c_str()); 67754979cddSGreg Clayton else 678b9c1b51eSKate Stone error.SetErrorStringWithFormat( 679b9c1b51eSKate Stone "\"%s\" is not a pointer and -> was used to attempt to " 680b9c1b51eSKate Stone "access \"%s\". Did you mean \"%s.%s\"?", 681c156427dSZachary Turner var_expr_path_strm.GetData(), child_name.GetCString(), 68224bd3178SZachary Turner var_expr_path_strm.GetData(), var_expr.str().c_str()); 68354979cddSGreg Clayton return ValueObjectSP(); 68454979cddSGreg Clayton } 68554979cddSGreg Clayton } 68624bd3178SZachary Turner child_valobj_sp = valobj_sp->GetChildMemberWithName(child_name, true); 687b9c1b51eSKate Stone if (!child_valobj_sp) { 688b9c1b51eSKate Stone if (!no_synth_child) { 68986cc9829SEnrico Granata child_valobj_sp = valobj_sp->GetSyntheticValue(); 69086cc9829SEnrico Granata if (child_valobj_sp) 691b9c1b51eSKate Stone child_valobj_sp = 692b9c1b51eSKate Stone child_valobj_sp->GetChildMemberWithName(child_name, true); 69386cc9829SEnrico Granata } 6948c9d3560SEnrico Granata 695b9c1b51eSKate Stone if (no_synth_child || !child_valobj_sp) { 6968b2fe6dcSGreg Clayton // No child member with name "child_name" 697b9c1b51eSKate Stone if (synthetically_added_instance_object) { 698b9c1b51eSKate Stone // We added a "this->" or "self->" to the beginning of the 69905097246SAdrian Prantl // expression and this is the first pointer ivar access, so just 70005097246SAdrian Prantl // return the normal error 701b9c1b51eSKate Stone error.SetErrorStringWithFormat( 702b9c1b51eSKate Stone "no variable or instance variable named '%s' found in " 703b9c1b51eSKate Stone "this frame", 704685c88c5SGreg Clayton name_const_string.GetCString()); 705b9c1b51eSKate Stone } else { 7066beaaa68SGreg Clayton valobj_sp->GetExpressionPath(var_expr_path_strm, false); 707b9c1b51eSKate Stone if (child_name) { 708b9c1b51eSKate Stone error.SetErrorStringWithFormat( 709b9c1b51eSKate Stone "\"%s\" is not a member of \"(%s) %s\"", 71054979cddSGreg Clayton child_name.GetCString(), 71154979cddSGreg Clayton valobj_sp->GetTypeName().AsCString("<invalid type>"), 712c156427dSZachary Turner var_expr_path_strm.GetData()); 713b9c1b51eSKate Stone } else { 714b9c1b51eSKate Stone error.SetErrorStringWithFormat( 715b9c1b51eSKate Stone "incomplete expression path after \"%s\" in \"%s\"", 7160eb31a1dSZachary Turner var_expr_path_strm.GetData(), 7170eb31a1dSZachary Turner original_var_expr.str().c_str()); 71854979cddSGreg Clayton } 719685c88c5SGreg Clayton } 7208b2fe6dcSGreg Clayton return ValueObjectSP(); 7218b2fe6dcSGreg Clayton } 7228c9d3560SEnrico Granata } 723685c88c5SGreg Clayton synthetically_added_instance_object = false; 7248b2fe6dcSGreg Clayton // Remove the child name from the path 72524bd3178SZachary Turner var_expr = var_expr.drop_front(child_name.GetLength()); 726b9c1b51eSKate Stone if (use_dynamic != eNoDynamicValues) { 727b9c1b51eSKate Stone ValueObjectSP dynamic_value_sp( 728b9c1b51eSKate Stone child_valobj_sp->GetDynamicValue(use_dynamic)); 72978a685aaSJim Ingham if (dynamic_value_sp) 73078a685aaSJim Ingham child_valobj_sp = dynamic_value_sp; 73178a685aaSJim Ingham } 732b9c1b51eSKate Stone } break; 7338b2fe6dcSGreg Clayton 73424bd3178SZachary Turner case '[': { 73505097246SAdrian Prantl // Array member access, or treating pointer as an array Need at least two 73605097246SAdrian Prantl // brackets and a number 73724bd3178SZachary Turner if (var_expr.size() <= 2) { 73824bd3178SZachary Turner error.SetErrorStringWithFormat( 73924bd3178SZachary Turner "invalid square bracket encountered after \"%s\" in \"%s\"", 74024bd3178SZachary Turner var_expr_path_strm.GetData(), var_expr.str().c_str()); 74124bd3178SZachary Turner return ValueObjectSP(); 74224bd3178SZachary Turner } 74324bd3178SZachary Turner 74424bd3178SZachary Turner // Drop the open brace. 74524bd3178SZachary Turner var_expr = var_expr.drop_front(); 74624bd3178SZachary Turner long child_index = 0; 74724bd3178SZachary Turner 74824bd3178SZachary Turner // If there's no closing brace, this is an invalid expression. 74924bd3178SZachary Turner size_t end_pos = var_expr.find_first_of(']'); 75024bd3178SZachary Turner if (end_pos == llvm::StringRef::npos) { 75124bd3178SZachary Turner error.SetErrorStringWithFormat( 75224bd3178SZachary Turner "missing closing square bracket in expression \"%s\"", 75324bd3178SZachary Turner var_expr_path_strm.GetData()); 75424bd3178SZachary Turner return ValueObjectSP(); 75524bd3178SZachary Turner } 75624bd3178SZachary Turner llvm::StringRef index_expr = var_expr.take_front(end_pos); 75724bd3178SZachary Turner llvm::StringRef original_index_expr = index_expr; 75824bd3178SZachary Turner // Drop all of "[index_expr]" 75924bd3178SZachary Turner var_expr = var_expr.drop_front(end_pos + 1); 76024bd3178SZachary Turner 76124bd3178SZachary Turner if (index_expr.consumeInteger(0, child_index)) { 76224bd3178SZachary Turner // If there was no integer anywhere in the index expression, this is 76324bd3178SZachary Turner // erroneous expression. 76424bd3178SZachary Turner error.SetErrorStringWithFormat("invalid index expression \"%s\"", 76524bd3178SZachary Turner index_expr.str().c_str()); 76624bd3178SZachary Turner return ValueObjectSP(); 76724bd3178SZachary Turner } 76824bd3178SZachary Turner 76924bd3178SZachary Turner if (index_expr.empty()) { 77024bd3178SZachary Turner // The entire index expression was a single integer. 77124bd3178SZachary Turner 77224bd3178SZachary Turner if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) { 77324bd3178SZachary Turner // what we have is *ptr[low]. the most similar C++ syntax is to deref 77424bd3178SZachary Turner // ptr and extract bit low out of it. reading array item low would be 77524bd3178SZachary Turner // done by saying ptr[low], without a deref * sign 77697206d57SZachary Turner Status error; 7779fc1944eSEnrico Granata ValueObjectSP temp(valobj_sp->Dereference(error)); 778b9c1b51eSKate Stone if (error.Fail()) { 7799fc1944eSEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 780b9c1b51eSKate Stone error.SetErrorStringWithFormat( 781b9c1b51eSKate Stone "could not dereference \"(%s) %s\"", 7829fc1944eSEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 783c156427dSZachary Turner var_expr_path_strm.GetData()); 7849fc1944eSEnrico Granata return ValueObjectSP(); 7859fc1944eSEnrico Granata } 7869fc1944eSEnrico Granata valobj_sp = temp; 7879fc1944eSEnrico Granata deref = false; 788b9c1b51eSKate Stone } else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() && 789b9c1b51eSKate Stone deref) { 79005097246SAdrian Prantl // what we have is *arr[low]. the most similar C++ syntax is to get 79105097246SAdrian Prantl // arr[0] (an operation that is equivalent to deref-ing arr) and 79205097246SAdrian Prantl // extract bit low out of it. reading array item low would be done by 79305097246SAdrian Prantl // saying arr[low], without a deref * sign 79497206d57SZachary Turner Status error; 7959fc1944eSEnrico Granata ValueObjectSP temp(valobj_sp->GetChildAtIndex(0, true)); 796b9c1b51eSKate Stone if (error.Fail()) { 7979fc1944eSEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 798b9c1b51eSKate Stone error.SetErrorStringWithFormat( 799b9c1b51eSKate Stone "could not get item 0 for \"(%s) %s\"", 8009fc1944eSEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 801c156427dSZachary Turner var_expr_path_strm.GetData()); 8029fc1944eSEnrico Granata return ValueObjectSP(); 8039fc1944eSEnrico Granata } 8049fc1944eSEnrico Granata valobj_sp = temp; 8059fc1944eSEnrico Granata deref = false; 8069fc1944eSEnrico Granata } 8078b2fe6dcSGreg Clayton 8084ef877f5SGreg Clayton bool is_incomplete_array = false; 809b9c1b51eSKate Stone if (valobj_sp->IsPointerType()) { 810226b70c1SSean Callanan bool is_objc_pointer = true; 811226b70c1SSean Callanan 812b9c1b51eSKate Stone if (valobj_sp->GetCompilerType().GetMinimumLanguage() != 813b9c1b51eSKate Stone eLanguageTypeObjC) 814226b70c1SSean Callanan is_objc_pointer = false; 81599558cc4SGreg Clayton else if (!valobj_sp->GetCompilerType().IsPointerType()) 816226b70c1SSean Callanan is_objc_pointer = false; 817226b70c1SSean Callanan 818b9c1b51eSKate Stone if (no_synth_child && is_objc_pointer) { 819b9c1b51eSKate Stone error.SetErrorStringWithFormat( 820b9c1b51eSKate Stone "\"(%s) %s\" is an Objective-C pointer, and cannot be " 821b9c1b51eSKate Stone "subscripted", 822226b70c1SSean Callanan valobj_sp->GetTypeName().AsCString("<invalid type>"), 823c156427dSZachary Turner var_expr_path_strm.GetData()); 824226b70c1SSean Callanan 825226b70c1SSean Callanan return ValueObjectSP(); 826b9c1b51eSKate Stone } else if (is_objc_pointer) { 82705097246SAdrian Prantl // dereferencing ObjC variables is not valid.. so let's try and 82805097246SAdrian Prantl // recur to synthetic children 82986cc9829SEnrico Granata ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(); 830d70a6e71SEugene Zelenko if (!synthetic /* no synthetic */ 831b9c1b51eSKate Stone || synthetic == valobj_sp) /* synthetic is the same as 832b9c1b51eSKate Stone the original object */ 83327b625e1SEnrico Granata { 83427b625e1SEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 835b9c1b51eSKate Stone error.SetErrorStringWithFormat( 836b9c1b51eSKate Stone "\"(%s) %s\" is not an array type", 83727b625e1SEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 838c156427dSZachary Turner var_expr_path_strm.GetData()); 839b9c1b51eSKate Stone } else if ( 840b9c1b51eSKate Stone static_cast<uint32_t>(child_index) >= 841b9c1b51eSKate Stone synthetic 842b9c1b51eSKate Stone ->GetNumChildren() /* synthetic does not have that many values */) { 84327b625e1SEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 844b9c1b51eSKate Stone error.SetErrorStringWithFormat( 84524bd3178SZachary Turner "array index %ld is not valid for \"(%s) %s\"", child_index, 84627b625e1SEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 847c156427dSZachary Turner var_expr_path_strm.GetData()); 848b9c1b51eSKate Stone } else { 84924bd3178SZachary Turner child_valobj_sp = synthetic->GetChildAtIndex(child_index, true); 850b9c1b51eSKate Stone if (!child_valobj_sp) { 85127b625e1SEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 852b9c1b51eSKate Stone error.SetErrorStringWithFormat( 85324bd3178SZachary Turner "array index %ld is not valid for \"(%s) %s\"", child_index, 85424bd3178SZachary Turner valobj_sp->GetTypeName().AsCString("<invalid type>"), 855c156427dSZachary Turner var_expr_path_strm.GetData()); 856b9c1b51eSKate Stone } 857b9c1b51eSKate Stone } 858b9c1b51eSKate Stone } else { 859b9c1b51eSKate Stone child_valobj_sp = 860b9c1b51eSKate Stone valobj_sp->GetSyntheticArrayMember(child_index, true); 861b9c1b51eSKate Stone if (!child_valobj_sp) { 862b9c1b51eSKate Stone valobj_sp->GetExpressionPath(var_expr_path_strm, false); 863b9c1b51eSKate Stone error.SetErrorStringWithFormat( 864b9c1b51eSKate Stone "failed to use pointer as array for index %ld for " 865b9c1b51eSKate Stone "\"(%s) %s\"", 86627b625e1SEnrico Granata child_index, 86727b625e1SEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 868c156427dSZachary Turner var_expr_path_strm.GetData()); 86927b625e1SEnrico Granata } 87027b625e1SEnrico Granata } 871b9c1b51eSKate Stone } else if (valobj_sp->GetCompilerType().IsArrayType( 872b9c1b51eSKate Stone nullptr, nullptr, &is_incomplete_array)) { 87305097246SAdrian Prantl // Pass false to dynamic_value here so we can tell the difference 87405097246SAdrian Prantl // between no dynamic value and no member of this type... 87524bd3178SZachary Turner child_valobj_sp = valobj_sp->GetChildAtIndex(child_index, true); 87624bd3178SZachary Turner if (!child_valobj_sp && (is_incomplete_array || !no_synth_child)) 877b9c1b51eSKate Stone child_valobj_sp = 878b9c1b51eSKate Stone valobj_sp->GetSyntheticArrayMember(child_index, true); 8794ef877f5SGreg Clayton 880b9c1b51eSKate Stone if (!child_valobj_sp) { 8816beaaa68SGreg Clayton valobj_sp->GetExpressionPath(var_expr_path_strm, false); 882b9c1b51eSKate Stone error.SetErrorStringWithFormat( 88324bd3178SZachary Turner "array index %ld is not valid for \"(%s) %s\"", child_index, 88454979cddSGreg Clayton valobj_sp->GetTypeName().AsCString("<invalid type>"), 885c156427dSZachary Turner var_expr_path_strm.GetData()); 88654979cddSGreg Clayton } 887b9c1b51eSKate Stone } else if (valobj_sp->GetCompilerType().IsScalarType()) { 8889fc1944eSEnrico Granata // this is a bitfield asking to display just one bit 889b9c1b51eSKate Stone child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild( 890b9c1b51eSKate Stone child_index, child_index, true); 891b9c1b51eSKate Stone if (!child_valobj_sp) { 8929fc1944eSEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 893b9c1b51eSKate Stone error.SetErrorStringWithFormat( 894b9c1b51eSKate Stone "bitfield range %ld-%ld is not valid for \"(%s) %s\"", 8959fc1944eSEnrico Granata child_index, child_index, 8969fc1944eSEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 897c156427dSZachary Turner var_expr_path_strm.GetData()); 8989fc1944eSEnrico Granata } 899b9c1b51eSKate Stone } else { 90086cc9829SEnrico Granata ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(); 90127b625e1SEnrico Granata if (no_synth_child /* synthetic is forbidden */ || 902d70a6e71SEugene Zelenko !synthetic /* no synthetic */ 9030b4c26b2SJason Molenda || synthetic == valobj_sp) /* synthetic is the same as the 904b9c1b51eSKate Stone original object */ 90527b625e1SEnrico Granata { 9066beaaa68SGreg Clayton valobj_sp->GetExpressionPath(var_expr_path_strm, false); 907b9c1b51eSKate Stone error.SetErrorStringWithFormat( 908b9c1b51eSKate Stone "\"(%s) %s\" is not an array type", 90954979cddSGreg Clayton valobj_sp->GetTypeName().AsCString("<invalid type>"), 910c156427dSZachary Turner var_expr_path_strm.GetData()); 911b9c1b51eSKate Stone } else if ( 912b9c1b51eSKate Stone static_cast<uint32_t>(child_index) >= 913b9c1b51eSKate Stone synthetic 914b9c1b51eSKate Stone ->GetNumChildren() /* synthetic does not have that many values */) { 91527b625e1SEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 916b9c1b51eSKate Stone error.SetErrorStringWithFormat( 91724bd3178SZachary Turner "array index %ld is not valid for \"(%s) %s\"", child_index, 91827b625e1SEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 919c156427dSZachary Turner var_expr_path_strm.GetData()); 920b9c1b51eSKate Stone } else { 92124bd3178SZachary Turner child_valobj_sp = synthetic->GetChildAtIndex(child_index, true); 922b9c1b51eSKate Stone if (!child_valobj_sp) { 92327b625e1SEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 924b9c1b51eSKate Stone error.SetErrorStringWithFormat( 92524bd3178SZachary Turner "array index %ld is not valid for \"(%s) %s\"", child_index, 92627b625e1SEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 927c156427dSZachary Turner var_expr_path_strm.GetData()); 92827b625e1SEnrico Granata } 92927b625e1SEnrico Granata } 93027b625e1SEnrico Granata } 9318b2fe6dcSGreg Clayton 932b9c1b51eSKate Stone if (!child_valobj_sp) { 9338b2fe6dcSGreg Clayton // Invalid array index... 9348b2fe6dcSGreg Clayton return ValueObjectSP(); 9358b2fe6dcSGreg Clayton } 9368b2fe6dcSGreg Clayton 93724bd3178SZachary Turner separator_idx = var_expr.find_first_of(".-["); 938b9c1b51eSKate Stone if (use_dynamic != eNoDynamicValues) { 939b9c1b51eSKate Stone ValueObjectSP dynamic_value_sp( 940b9c1b51eSKate Stone child_valobj_sp->GetDynamicValue(use_dynamic)); 94178a685aaSJim Ingham if (dynamic_value_sp) 94278a685aaSJim Ingham child_valobj_sp = dynamic_value_sp; 94378a685aaSJim Ingham } 94424bd3178SZachary Turner // Break out early from the switch since we were able to find the child 94524bd3178SZachary Turner // member 9468b2fe6dcSGreg Clayton break; 94724bd3178SZachary Turner } 94824bd3178SZachary Turner 9499fc1944eSEnrico Granata // this is most probably a BitField, let's take a look 95024bd3178SZachary Turner if (index_expr.front() != '-') { 95124bd3178SZachary Turner error.SetErrorStringWithFormat("invalid range expression \"'%s'\"", 95224bd3178SZachary Turner original_index_expr.str().c_str()); 95324bd3178SZachary Turner return ValueObjectSP(); 95424bd3178SZachary Turner } 95524bd3178SZachary Turner 9567edc3a6eSZachary Turner index_expr = index_expr.drop_front(); 95724bd3178SZachary Turner long final_index = 0; 95824bd3178SZachary Turner if (index_expr.getAsInteger(0, final_index)) { 95924bd3178SZachary Turner error.SetErrorStringWithFormat("invalid range expression \"'%s'\"", 96024bd3178SZachary Turner original_index_expr.str().c_str()); 96124bd3178SZachary Turner return ValueObjectSP(); 96224bd3178SZachary Turner } 96324bd3178SZachary Turner 9649fc1944eSEnrico Granata // if the format given is [high-low], swap range 965b9c1b51eSKate Stone if (child_index > final_index) { 9669fc1944eSEnrico Granata long temp = child_index; 9679fc1944eSEnrico Granata child_index = final_index; 9689fc1944eSEnrico Granata final_index = temp; 9699fc1944eSEnrico Granata } 9709fc1944eSEnrico Granata 97124bd3178SZachary Turner if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) { 97224bd3178SZachary Turner // what we have is *ptr[low-high]. the most similar C++ syntax is to 97324bd3178SZachary Turner // deref ptr and extract bits low thru high out of it. reading array 97405097246SAdrian Prantl // items low thru high would be done by saying ptr[low-high], without a 97505097246SAdrian Prantl // deref * sign 97697206d57SZachary Turner Status error; 9779fc1944eSEnrico Granata ValueObjectSP temp(valobj_sp->Dereference(error)); 978b9c1b51eSKate Stone if (error.Fail()) { 9799fc1944eSEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 980b9c1b51eSKate Stone error.SetErrorStringWithFormat( 981b9c1b51eSKate Stone "could not dereference \"(%s) %s\"", 9829fc1944eSEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 983c156427dSZachary Turner var_expr_path_strm.GetData()); 9849fc1944eSEnrico Granata return ValueObjectSP(); 9859fc1944eSEnrico Granata } 9869fc1944eSEnrico Granata valobj_sp = temp; 9879fc1944eSEnrico Granata deref = false; 98824bd3178SZachary Turner } else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() && deref) { 98905097246SAdrian Prantl // what we have is *arr[low-high]. the most similar C++ syntax is to 99005097246SAdrian Prantl // get arr[0] (an operation that is equivalent to deref-ing arr) and 99105097246SAdrian Prantl // extract bits low thru high out of it. reading array items low thru 99205097246SAdrian Prantl // high would be done by saying arr[low-high], without a deref * sign 99397206d57SZachary Turner Status error; 9949fc1944eSEnrico Granata ValueObjectSP temp(valobj_sp->GetChildAtIndex(0, true)); 995b9c1b51eSKate Stone if (error.Fail()) { 9969fc1944eSEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 997b9c1b51eSKate Stone error.SetErrorStringWithFormat( 998b9c1b51eSKate Stone "could not get item 0 for \"(%s) %s\"", 9999fc1944eSEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 1000c156427dSZachary Turner var_expr_path_strm.GetData()); 10019fc1944eSEnrico Granata return ValueObjectSP(); 10029fc1944eSEnrico Granata } 10039fc1944eSEnrico Granata valobj_sp = temp; 10049fc1944eSEnrico Granata deref = false; 10059fc1944eSEnrico Granata } 10069fc1944eSEnrico Granata 100724bd3178SZachary Turner child_valobj_sp = 100824bd3178SZachary Turner valobj_sp->GetSyntheticBitFieldChild(child_index, final_index, true); 1009b9c1b51eSKate Stone if (!child_valobj_sp) { 10109fc1944eSEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 1011b9c1b51eSKate Stone error.SetErrorStringWithFormat( 101224bd3178SZachary Turner "bitfield range %ld-%ld is not valid for \"(%s) %s\"", child_index, 101324bd3178SZachary Turner final_index, valobj_sp->GetTypeName().AsCString("<invalid type>"), 1014c156427dSZachary Turner var_expr_path_strm.GetData()); 10159fc1944eSEnrico Granata } 10169fc1944eSEnrico Granata 1017b9c1b51eSKate Stone if (!child_valobj_sp) { 10189fc1944eSEnrico Granata // Invalid bitfield range... 10199fc1944eSEnrico Granata return ValueObjectSP(); 10209fc1944eSEnrico Granata } 10219fc1944eSEnrico Granata 102224bd3178SZachary Turner separator_idx = var_expr.find_first_of(".-["); 1023b9c1b51eSKate Stone if (use_dynamic != eNoDynamicValues) { 1024b9c1b51eSKate Stone ValueObjectSP dynamic_value_sp( 1025b9c1b51eSKate Stone child_valobj_sp->GetDynamicValue(use_dynamic)); 10269fc1944eSEnrico Granata if (dynamic_value_sp) 10279fc1944eSEnrico Granata child_valobj_sp = dynamic_value_sp; 10289fc1944eSEnrico Granata } 102924bd3178SZachary Turner // Break out early from the switch since we were able to find the child 103024bd3178SZachary Turner // member 10319fc1944eSEnrico Granata break; 10329fc1944eSEnrico Granata } 10338b2fe6dcSGreg Clayton default: 10348b2fe6dcSGreg Clayton // Failure... 103554979cddSGreg Clayton { 10366beaaa68SGreg Clayton valobj_sp->GetExpressionPath(var_expr_path_strm, false); 1037b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1038b9c1b51eSKate Stone "unexpected char '%c' encountered after \"%s\" in \"%s\"", 1039c156427dSZachary Turner separator_type, var_expr_path_strm.GetData(), 104024bd3178SZachary Turner var_expr.str().c_str()); 104154979cddSGreg Clayton 10428b2fe6dcSGreg Clayton return ValueObjectSP(); 10438b2fe6dcSGreg Clayton } 104454979cddSGreg Clayton } 10458b2fe6dcSGreg Clayton 10468b2fe6dcSGreg Clayton if (child_valobj_sp) 10478b2fe6dcSGreg Clayton valobj_sp = child_valobj_sp; 10488b2fe6dcSGreg Clayton 104924bd3178SZachary Turner if (var_expr.empty()) 10508b2fe6dcSGreg Clayton break; 10518b2fe6dcSGreg Clayton } 1052b9c1b51eSKate Stone if (valobj_sp) { 1053b9c1b51eSKate Stone if (deref) { 1054af67cecdSGreg Clayton ValueObjectSP deref_valobj_sp(valobj_sp->Dereference(error)); 10558b2fe6dcSGreg Clayton valobj_sp = deref_valobj_sp; 1056b9c1b51eSKate Stone } else if (address_of) { 105754979cddSGreg Clayton ValueObjectSP address_of_valobj_sp(valobj_sp->AddressOf(error)); 10588b2fe6dcSGreg Clayton valobj_sp = address_of_valobj_sp; 10598b2fe6dcSGreg Clayton } 10608b2fe6dcSGreg Clayton } 10618b2fe6dcSGreg Clayton return valobj_sp; 10628b2fe6dcSGreg Clayton } 106330fdc8d8SChris Lattner 106497206d57SZachary Turner bool StackFrame::GetFrameBaseValue(Scalar &frame_base, Status *error_ptr) { 1065bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 1066b9c1b51eSKate Stone if (!m_cfa_is_valid) { 1067b9c1b51eSKate Stone m_frame_base_error.SetErrorString( 1068b9c1b51eSKate Stone "No frame base available for this historical stack frame."); 106999618476SJason Molenda return false; 107099618476SJason Molenda } 107199618476SJason Molenda 1072b9c1b51eSKate Stone if (m_flags.IsClear(GOT_FRAME_BASE)) { 1073b9c1b51eSKate Stone if (m_sc.function) { 107430fdc8d8SChris Lattner m_frame_base.Clear(); 107530fdc8d8SChris Lattner m_frame_base_error.Clear(); 107630fdc8d8SChris Lattner 107730fdc8d8SChris Lattner m_flags.Set(GOT_FRAME_BASE); 1078d9e416c0SGreg Clayton ExecutionContext exe_ctx(shared_from_this()); 107930fdc8d8SChris Lattner Value expr_value; 1080016a95ebSGreg Clayton addr_t loclist_base_addr = LLDB_INVALID_ADDRESS; 1081016a95ebSGreg Clayton if (m_sc.function->GetFrameBaseExpression().IsLocationList()) 1082b9c1b51eSKate Stone loclist_base_addr = 1083b9c1b51eSKate Stone m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress( 1084b9c1b51eSKate Stone exe_ctx.GetTargetPtr()); 1085016a95ebSGreg Clayton 1086b9c1b51eSKate Stone if (m_sc.function->GetFrameBaseExpression().Evaluate( 1087bba2c834STamas Berghammer &exe_ctx, nullptr, loclist_base_addr, nullptr, nullptr, 1088bba2c834STamas Berghammer expr_value, &m_frame_base_error) == false) { 108905097246SAdrian Prantl // We should really have an error if evaluate returns, but in case we 109005097246SAdrian Prantl // don't, lets set the error to something at least. 109130fdc8d8SChris Lattner if (m_frame_base_error.Success()) 1092b9c1b51eSKate Stone m_frame_base_error.SetErrorString( 1093b9c1b51eSKate Stone "Evaluation of the frame base expression failed."); 1094b9c1b51eSKate Stone } else { 109557ee3067SGreg Clayton m_frame_base = expr_value.ResolveValue(&exe_ctx); 109630fdc8d8SChris Lattner } 1097b9c1b51eSKate Stone } else { 109830fdc8d8SChris Lattner m_frame_base_error.SetErrorString("No function in symbol context."); 109930fdc8d8SChris Lattner } 110030fdc8d8SChris Lattner } 110130fdc8d8SChris Lattner 110230fdc8d8SChris Lattner if (m_frame_base_error.Success()) 110330fdc8d8SChris Lattner frame_base = m_frame_base; 110430fdc8d8SChris Lattner 110530fdc8d8SChris Lattner if (error_ptr) 110630fdc8d8SChris Lattner *error_ptr = m_frame_base_error; 110730fdc8d8SChris Lattner return m_frame_base_error.Success(); 110830fdc8d8SChris Lattner } 110930fdc8d8SChris Lattner 111097206d57SZachary Turner DWARFExpression *StackFrame::GetFrameBaseExpression(Status *error_ptr) { 1111b9c1b51eSKate Stone if (!m_sc.function) { 1112b9c1b51eSKate Stone if (error_ptr) { 11134740a734SSean Callanan error_ptr->SetErrorString("No function in symbol context."); 11144740a734SSean Callanan } 11154740a734SSean Callanan return nullptr; 11164740a734SSean Callanan } 11174740a734SSean Callanan 11184740a734SSean Callanan return &m_sc.function->GetFrameBaseExpression(); 11194740a734SSean Callanan } 11204740a734SSean Callanan 1121b9c1b51eSKate Stone RegisterContextSP StackFrame::GetRegisterContext() { 1122bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 1123b9c1b51eSKate Stone if (!m_reg_context_sp) { 1124d9e416c0SGreg Clayton ThreadSP thread_sp(GetThread()); 1125d9e416c0SGreg Clayton if (thread_sp) 1126d9e416c0SGreg Clayton m_reg_context_sp = thread_sp->CreateRegisterContextForFrame(this); 1127d9e416c0SGreg Clayton } 11285ccbd294SGreg Clayton return m_reg_context_sp; 112930fdc8d8SChris Lattner } 113030fdc8d8SChris Lattner 1131b9c1b51eSKate Stone bool StackFrame::HasDebugInformation() { 113230fdc8d8SChris Lattner GetSymbolContext(eSymbolContextLineEntry); 113330fdc8d8SChris Lattner return m_sc.line_entry.IsValid(); 113430fdc8d8SChris Lattner } 113530fdc8d8SChris Lattner 1136288bdf9cSGreg Clayton ValueObjectSP 1137b9c1b51eSKate Stone StackFrame::GetValueObjectForFrameVariable(const VariableSP &variable_sp, 1138b9c1b51eSKate Stone DynamicValueType use_dynamic) { 1139bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 1140288bdf9cSGreg Clayton ValueObjectSP valobj_sp; 11414b36f791SVedant Kumar if (IsHistorical()) { 114299618476SJason Molenda return valobj_sp; 114399618476SJason Molenda } 1144288bdf9cSGreg Clayton VariableList *var_list = GetVariableList(true); 1145b9c1b51eSKate Stone if (var_list) { 1146288bdf9cSGreg Clayton // Make sure the variable is a frame variable 1147288bdf9cSGreg Clayton const uint32_t var_idx = var_list->FindIndexForVariable(variable_sp.get()); 1148288bdf9cSGreg Clayton const uint32_t num_variables = var_list->GetSize(); 1149b9c1b51eSKate Stone if (var_idx < num_variables) { 1150288bdf9cSGreg Clayton valobj_sp = m_variable_list_value_objects.GetValueObjectAtIndex(var_idx); 1151b9c1b51eSKate Stone if (!valobj_sp) { 1152288bdf9cSGreg Clayton if (m_variable_list_value_objects.GetSize() < num_variables) 1153288bdf9cSGreg Clayton m_variable_list_value_objects.Resize(num_variables); 115458b59f95SJim Ingham valobj_sp = ValueObjectVariable::Create(this, variable_sp); 1155288bdf9cSGreg Clayton m_variable_list_value_objects.SetValueObjectAtIndex(var_idx, valobj_sp); 1156288bdf9cSGreg Clayton } 1157288bdf9cSGreg Clayton } 1158288bdf9cSGreg Clayton } 1159b9c1b51eSKate Stone if (use_dynamic != eNoDynamicValues && valobj_sp) { 11602837b766SJim Ingham ValueObjectSP dynamic_sp = valobj_sp->GetDynamicValue(use_dynamic); 116178a685aaSJim Ingham if (dynamic_sp) 116278a685aaSJim Ingham return dynamic_sp; 116378a685aaSJim Ingham } 1164288bdf9cSGreg Clayton return valobj_sp; 1165288bdf9cSGreg Clayton } 1166288bdf9cSGreg Clayton 1167b9c1b51eSKate Stone ValueObjectSP StackFrame::TrackGlobalVariable(const VariableSP &variable_sp, 1168b9c1b51eSKate Stone DynamicValueType use_dynamic) { 1169bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 11704b36f791SVedant Kumar if (IsHistorical()) 117199618476SJason Molenda return ValueObjectSP(); 117299618476SJason Molenda 1173288bdf9cSGreg Clayton // Check to make sure we aren't already tracking this variable? 1174b9c1b51eSKate Stone ValueObjectSP valobj_sp( 1175b9c1b51eSKate Stone GetValueObjectForFrameVariable(variable_sp, use_dynamic)); 1176b9c1b51eSKate Stone if (!valobj_sp) { 1177288bdf9cSGreg Clayton // We aren't already tracking this global 1178288bdf9cSGreg Clayton VariableList *var_list = GetVariableList(true); 1179288bdf9cSGreg Clayton // If this frame has no variables, create a new list 1180d70a6e71SEugene Zelenko if (var_list == nullptr) 1181288bdf9cSGreg Clayton m_variable_list_sp.reset(new VariableList()); 1182288bdf9cSGreg Clayton 1183288bdf9cSGreg Clayton // Add the global/static variable to this frame 1184288bdf9cSGreg Clayton m_variable_list_sp->AddVariable(variable_sp); 1185288bdf9cSGreg Clayton 1186288bdf9cSGreg Clayton // Now make a value object for it so we can track its changes 118778a685aaSJim Ingham valobj_sp = GetValueObjectForFrameVariable(variable_sp, use_dynamic); 1188288bdf9cSGreg Clayton } 1189288bdf9cSGreg Clayton return valobj_sp; 119030fdc8d8SChris Lattner } 119130fdc8d8SChris Lattner 1192b9c1b51eSKate Stone bool StackFrame::IsInlined() { 1193d70a6e71SEugene Zelenko if (m_sc.block == nullptr) 119459e8fc1cSGreg Clayton GetSymbolContext(eSymbolContextBlock); 119559e8fc1cSGreg Clayton if (m_sc.block) 1196d70a6e71SEugene Zelenko return m_sc.block->GetContainingInlinedBlock() != nullptr; 119759e8fc1cSGreg Clayton return false; 11986b8379c4SJim Ingham } 11996b8379c4SJim Ingham 12004b36f791SVedant Kumar bool StackFrame::IsHistorical() const { 12014b36f791SVedant Kumar return m_stack_frame_kind == StackFrame::Kind::History; 12024b36f791SVedant Kumar } 12034b36f791SVedant Kumar 12044b36f791SVedant Kumar bool StackFrame::IsArtificial() const { 12054b36f791SVedant Kumar return m_stack_frame_kind == StackFrame::Kind::Artificial; 12064b36f791SVedant Kumar } 12074b36f791SVedant Kumar 1208b9c1b51eSKate Stone lldb::LanguageType StackFrame::GetLanguage() { 1209009d110dSDawn Perchik CompileUnit *cu = GetSymbolContext(eSymbolContextCompUnit).comp_unit; 1210009d110dSDawn Perchik if (cu) 1211009d110dSDawn Perchik return cu->GetLanguage(); 1212009d110dSDawn Perchik return lldb::eLanguageTypeUnknown; 1213009d110dSDawn Perchik } 1214009d110dSDawn Perchik 1215b9c1b51eSKate Stone lldb::LanguageType StackFrame::GuessLanguage() { 1216592afe73SEnrico Granata LanguageType lang_type = GetLanguage(); 1217592afe73SEnrico Granata 1218b9c1b51eSKate Stone if (lang_type == eLanguageTypeUnknown) { 1219bdbdd229SJim Ingham SymbolContext sc = GetSymbolContext(eSymbolContextFunction 1220bdbdd229SJim Ingham | eSymbolContextSymbol); 1221bdbdd229SJim Ingham if (sc.function) { 1222bdbdd229SJim Ingham lang_type = sc.function->GetMangled().GuessLanguage(); 1223bdbdd229SJim Ingham } 1224bdbdd229SJim Ingham else if (sc.symbol) 1225bdbdd229SJim Ingham { 1226bdbdd229SJim Ingham lang_type = sc.symbol->GetMangled().GuessLanguage(); 1227592afe73SEnrico Granata } 1228592afe73SEnrico Granata } 1229592afe73SEnrico Granata 1230592afe73SEnrico Granata return lang_type; 1231592afe73SEnrico Granata } 1232592afe73SEnrico Granata 1233b9c1b51eSKate Stone namespace { 12344740a734SSean Callanan std::pair<const Instruction::Operand *, int64_t> 12354740a734SSean Callanan GetBaseExplainingValue(const Instruction::Operand &operand, 1236b9c1b51eSKate Stone RegisterContext ®ister_context, lldb::addr_t value) { 1237b9c1b51eSKate Stone switch (operand.m_type) { 12384740a734SSean Callanan case Instruction::Operand::Type::Dereference: 12394740a734SSean Callanan case Instruction::Operand::Type::Immediate: 12404740a734SSean Callanan case Instruction::Operand::Type::Invalid: 12414740a734SSean Callanan case Instruction::Operand::Type::Product: 12424740a734SSean Callanan // These are not currently interesting 12434740a734SSean Callanan return std::make_pair(nullptr, 0); 1244b9c1b51eSKate Stone case Instruction::Operand::Type::Sum: { 12454740a734SSean Callanan const Instruction::Operand *immediate_child = nullptr; 12464740a734SSean Callanan const Instruction::Operand *variable_child = nullptr; 1247b9c1b51eSKate Stone if (operand.m_children[0].m_type == Instruction::Operand::Type::Immediate) { 12484740a734SSean Callanan immediate_child = &operand.m_children[0]; 12494740a734SSean Callanan variable_child = &operand.m_children[1]; 1250b9c1b51eSKate Stone } else if (operand.m_children[1].m_type == 1251b9c1b51eSKate Stone Instruction::Operand::Type::Immediate) { 12524740a734SSean Callanan immediate_child = &operand.m_children[1]; 12534740a734SSean Callanan variable_child = &operand.m_children[0]; 12544740a734SSean Callanan } 1255b9c1b51eSKate Stone if (!immediate_child) { 12564740a734SSean Callanan return std::make_pair(nullptr, 0); 12574740a734SSean Callanan } 12584740a734SSean Callanan lldb::addr_t adjusted_value = value; 1259b9c1b51eSKate Stone if (immediate_child->m_negative) { 12604740a734SSean Callanan adjusted_value += immediate_child->m_immediate; 1261b9c1b51eSKate Stone } else { 12624740a734SSean Callanan adjusted_value -= immediate_child->m_immediate; 12634740a734SSean Callanan } 1264b9c1b51eSKate Stone std::pair<const Instruction::Operand *, int64_t> base_and_offset = 1265b9c1b51eSKate Stone GetBaseExplainingValue(*variable_child, register_context, 1266b9c1b51eSKate Stone adjusted_value); 1267b9c1b51eSKate Stone if (!base_and_offset.first) { 12684740a734SSean Callanan return std::make_pair(nullptr, 0); 12694740a734SSean Callanan } 1270b9c1b51eSKate Stone if (immediate_child->m_negative) { 12714740a734SSean Callanan base_and_offset.second -= immediate_child->m_immediate; 1272b9c1b51eSKate Stone } else { 12734740a734SSean Callanan base_and_offset.second += immediate_child->m_immediate; 12744740a734SSean Callanan } 12754740a734SSean Callanan return base_and_offset; 12764740a734SSean Callanan } 1277b9c1b51eSKate Stone case Instruction::Operand::Type::Register: { 1278b9c1b51eSKate Stone const RegisterInfo *info = 1279b9c1b51eSKate Stone register_context.GetRegisterInfoByName(operand.m_register.AsCString()); 1280b9c1b51eSKate Stone if (!info) { 12814740a734SSean Callanan return std::make_pair(nullptr, 0); 12824740a734SSean Callanan } 12834740a734SSean Callanan RegisterValue reg_value; 1284b9c1b51eSKate Stone if (!register_context.ReadRegister(info, reg_value)) { 12854740a734SSean Callanan return std::make_pair(nullptr, 0); 12864740a734SSean Callanan } 1287b9c1b51eSKate Stone if (reg_value.GetAsUInt64() == value) { 12884740a734SSean Callanan return std::make_pair(&operand, 0); 1289b9c1b51eSKate Stone } else { 12904740a734SSean Callanan return std::make_pair(nullptr, 0); 12914740a734SSean Callanan } 12924740a734SSean Callanan } 12934740a734SSean Callanan } 12945a8ad459SZachary Turner return std::make_pair(nullptr, 0); 12954740a734SSean Callanan } 12964740a734SSean Callanan 12974740a734SSean Callanan std::pair<const Instruction::Operand *, int64_t> 12984740a734SSean Callanan GetBaseExplainingDereference(const Instruction::Operand &operand, 12994740a734SSean Callanan RegisterContext ®ister_context, 1300b9c1b51eSKate Stone lldb::addr_t addr) { 1301b9c1b51eSKate Stone if (operand.m_type == Instruction::Operand::Type::Dereference) { 1302b9c1b51eSKate Stone return GetBaseExplainingValue(operand.m_children[0], register_context, 13034740a734SSean Callanan addr); 13044740a734SSean Callanan } 13054740a734SSean Callanan return std::make_pair(nullptr, 0); 13064740a734SSean Callanan } 13074f730dc7SIlia K } 13084740a734SSean Callanan 1309b9c1b51eSKate Stone lldb::ValueObjectSP StackFrame::GuessValueForAddress(lldb::addr_t addr) { 13104740a734SSean Callanan TargetSP target_sp = CalculateTarget(); 13114740a734SSean Callanan 13124740a734SSean Callanan const ArchSpec &target_arch = target_sp->GetArchitecture(); 13134740a734SSean Callanan 13144740a734SSean Callanan AddressRange pc_range; 13154740a734SSean Callanan pc_range.GetBaseAddress() = GetFrameCodeAddress(); 13164740a734SSean Callanan pc_range.SetByteSize(target_arch.GetMaximumOpcodeByteSize()); 13174740a734SSean Callanan 13184740a734SSean Callanan ExecutionContext exe_ctx(shared_from_this()); 13194740a734SSean Callanan 13204740a734SSean Callanan const char *plugin_name = nullptr; 13214740a734SSean Callanan const char *flavor = nullptr; 13224740a734SSean Callanan const bool prefer_file_cache = false; 13234740a734SSean Callanan 1324b9c1b51eSKate Stone DisassemblerSP disassembler_sp = Disassembler::DisassembleRange( 1325b9c1b51eSKate Stone target_arch, plugin_name, flavor, exe_ctx, pc_range, prefer_file_cache); 13264740a734SSean Callanan 132799d1e28aSJim Ingham if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) { 13284740a734SSean Callanan return ValueObjectSP(); 13294740a734SSean Callanan } 13304740a734SSean Callanan 1331b9c1b51eSKate Stone InstructionSP instruction_sp = 1332b9c1b51eSKate Stone disassembler_sp->GetInstructionList().GetInstructionAtIndex(0); 13334740a734SSean Callanan 13344740a734SSean Callanan llvm::SmallVector<Instruction::Operand, 3> operands; 13354740a734SSean Callanan 1336b9c1b51eSKate Stone if (!instruction_sp->ParseOperands(operands)) { 13374740a734SSean Callanan return ValueObjectSP(); 13384740a734SSean Callanan } 13394740a734SSean Callanan 13404740a734SSean Callanan RegisterContextSP register_context_sp = GetRegisterContext(); 13414740a734SSean Callanan 1342b9c1b51eSKate Stone if (!register_context_sp) { 13434740a734SSean Callanan return ValueObjectSP(); 13444740a734SSean Callanan } 13454740a734SSean Callanan 1346b9c1b51eSKate Stone for (const Instruction::Operand &operand : operands) { 1347b9c1b51eSKate Stone std::pair<const Instruction::Operand *, int64_t> base_and_offset = 1348b9c1b51eSKate Stone GetBaseExplainingDereference(operand, *register_context_sp, addr); 13494740a734SSean Callanan 1350b9c1b51eSKate Stone if (!base_and_offset.first) { 13514740a734SSean Callanan continue; 13524740a734SSean Callanan } 13534740a734SSean Callanan 1354b9c1b51eSKate Stone switch (base_and_offset.first->m_type) { 1355b9c1b51eSKate Stone case Instruction::Operand::Type::Immediate: { 13564740a734SSean Callanan lldb_private::Address addr; 1357b9c1b51eSKate Stone if (target_sp->ResolveLoadAddress(base_and_offset.first->m_immediate + 1358b9c1b51eSKate Stone base_and_offset.second, 1359b9c1b51eSKate Stone addr)) { 1360b9c1b51eSKate Stone TypeSystem *c_type_system = 1361b9c1b51eSKate Stone target_sp->GetScratchTypeSystemForLanguage(nullptr, eLanguageTypeC); 1362b9c1b51eSKate Stone if (!c_type_system) { 13634740a734SSean Callanan return ValueObjectSP(); 1364b9c1b51eSKate Stone } else { 1365b9c1b51eSKate Stone CompilerType void_ptr_type = 1366b9c1b51eSKate Stone c_type_system 1367b9c1b51eSKate Stone ->GetBasicTypeFromAST(lldb::BasicType::eBasicTypeChar) 1368b9c1b51eSKate Stone .GetPointerType(); 13694740a734SSean Callanan return ValueObjectMemory::Create(this, "", addr, void_ptr_type); 13704740a734SSean Callanan } 1371b9c1b51eSKate Stone } else { 13724740a734SSean Callanan return ValueObjectSP(); 13734740a734SSean Callanan } 13744740a734SSean Callanan break; 13754740a734SSean Callanan } 1376b9c1b51eSKate Stone case Instruction::Operand::Type::Register: { 1377b9c1b51eSKate Stone return GuessValueForRegisterAndOffset(base_and_offset.first->m_register, 1378b9c1b51eSKate Stone base_and_offset.second); 13794740a734SSean Callanan } 13804740a734SSean Callanan default: 13814740a734SSean Callanan return ValueObjectSP(); 13824740a734SSean Callanan } 13834740a734SSean Callanan } 13844740a734SSean Callanan 13854740a734SSean Callanan return ValueObjectSP(); 13864740a734SSean Callanan } 13874740a734SSean Callanan 1388b9c1b51eSKate Stone namespace { 1389b9c1b51eSKate Stone ValueObjectSP GetValueForOffset(StackFrame &frame, ValueObjectSP &parent, 1390b9c1b51eSKate Stone int64_t offset) { 1391b9c1b51eSKate Stone if (offset < 0 || uint64_t(offset) >= parent->GetByteSize()) { 13924740a734SSean Callanan return ValueObjectSP(); 13934740a734SSean Callanan } 13944740a734SSean Callanan 1395b9c1b51eSKate Stone if (parent->IsPointerOrReferenceType()) { 13964740a734SSean Callanan return parent; 13974740a734SSean Callanan } 13984740a734SSean Callanan 1399b9c1b51eSKate Stone for (int ci = 0, ce = parent->GetNumChildren(); ci != ce; ++ci) { 14004740a734SSean Callanan const bool can_create = true; 14014740a734SSean Callanan ValueObjectSP child_sp = parent->GetChildAtIndex(ci, can_create); 14024740a734SSean Callanan 1403b9c1b51eSKate Stone if (!child_sp) { 14044740a734SSean Callanan return ValueObjectSP(); 14054740a734SSean Callanan } 14064740a734SSean Callanan 14074740a734SSean Callanan int64_t child_offset = child_sp->GetByteOffset(); 14084740a734SSean Callanan int64_t child_size = child_sp->GetByteSize(); 14094740a734SSean Callanan 1410b9c1b51eSKate Stone if (offset >= child_offset && offset < (child_offset + child_size)) { 14114740a734SSean Callanan return GetValueForOffset(frame, child_sp, offset - child_offset); 14124740a734SSean Callanan } 14134740a734SSean Callanan } 14144740a734SSean Callanan 1415b9c1b51eSKate Stone if (offset == 0) { 14164740a734SSean Callanan return parent; 1417b9c1b51eSKate Stone } else { 14184740a734SSean Callanan return ValueObjectSP(); 14194740a734SSean Callanan } 14204740a734SSean Callanan } 14214740a734SSean Callanan 1422b9c1b51eSKate Stone ValueObjectSP GetValueForDereferincingOffset(StackFrame &frame, 1423b9c1b51eSKate Stone ValueObjectSP &base, 1424b9c1b51eSKate Stone int64_t offset) { 14254740a734SSean Callanan // base is a pointer to something 142605097246SAdrian Prantl // offset is the thing to add to the pointer We return the most sensible 142705097246SAdrian Prantl // ValueObject for the result of *(base+offset) 14284740a734SSean Callanan 1429b9c1b51eSKate Stone if (!base->IsPointerOrReferenceType()) { 14304740a734SSean Callanan return ValueObjectSP(); 14314740a734SSean Callanan } 14324740a734SSean Callanan 143397206d57SZachary Turner Status error; 14344740a734SSean Callanan ValueObjectSP pointee = base->Dereference(error); 1435a0a1d2dbSSean Callanan 1436a0a1d2dbSSean Callanan if (!pointee) { 1437a0a1d2dbSSean Callanan return ValueObjectSP(); 1438a0a1d2dbSSean Callanan } 14394740a734SSean Callanan 14404f730dc7SIlia K if (offset >= 0 && uint64_t(offset) >= pointee->GetByteSize()) { 14414740a734SSean Callanan int64_t index = offset / pointee->GetByteSize(); 14424740a734SSean Callanan offset = offset % pointee->GetByteSize(); 14434740a734SSean Callanan const bool can_create = true; 14444740a734SSean Callanan pointee = base->GetSyntheticArrayMember(index, can_create); 14454740a734SSean Callanan } 14464740a734SSean Callanan 1447b9c1b51eSKate Stone if (!pointee || error.Fail()) { 14484740a734SSean Callanan return ValueObjectSP(); 14494740a734SSean Callanan } 14504740a734SSean Callanan 14514740a734SSean Callanan return GetValueForOffset(frame, pointee, offset); 14524740a734SSean Callanan } 14534740a734SSean Callanan 14544740a734SSean Callanan //------------------------------------------------------------------ 14554740a734SSean Callanan /// Attempt to reconstruct the ValueObject for the address contained in a 14564740a734SSean Callanan /// given register plus an offset. 14574740a734SSean Callanan /// 14584740a734SSean Callanan /// @params [in] frame 14594740a734SSean Callanan /// The current stack frame. 14604740a734SSean Callanan /// 14614740a734SSean Callanan /// @params [in] reg 14624740a734SSean Callanan /// The register. 14634740a734SSean Callanan /// 14644740a734SSean Callanan /// @params [in] offset 14654740a734SSean Callanan /// The offset from the register. 14664740a734SSean Callanan /// 14674740a734SSean Callanan /// @param [in] disassembler 14684740a734SSean Callanan /// A disassembler containing instructions valid up to the current PC. 14694740a734SSean Callanan /// 14704740a734SSean Callanan /// @param [in] variables 14714740a734SSean Callanan /// The variable list from the current frame, 14724740a734SSean Callanan /// 14734740a734SSean Callanan /// @param [in] pc 14744740a734SSean Callanan /// The program counter for the instruction considered the 'user'. 14754740a734SSean Callanan /// 14764740a734SSean Callanan /// @return 14774740a734SSean Callanan /// A string describing the base for the ExpressionPath. This could be a 14784740a734SSean Callanan /// variable, a register value, an argument, or a function return value. 14794740a734SSean Callanan /// The ValueObject if found. If valid, it has a valid ExpressionPath. 14804740a734SSean Callanan //------------------------------------------------------------------ 1481b9c1b51eSKate Stone lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg, 1482b9c1b51eSKate Stone int64_t offset, Disassembler &disassembler, 1483b9c1b51eSKate Stone VariableList &variables, const Address &pc) { 14844740a734SSean Callanan // Example of operation for Intel: 14854740a734SSean Callanan // 14864740a734SSean Callanan // +14: movq -0x8(%rbp), %rdi 14874740a734SSean Callanan // +18: movq 0x8(%rdi), %rdi 14884740a734SSean Callanan // +22: addl 0x4(%rdi), %eax 14894740a734SSean Callanan // 14904740a734SSean Callanan // f, a pointer to a struct, is known to be at -0x8(%rbp). 14914740a734SSean Callanan // 149205097246SAdrian Prantl // DoGuessValueAt(frame, rdi, 4, dis, vars, 0x22) finds the instruction at 149305097246SAdrian Prantl // +18 that assigns to rdi, and calls itself recursively for that dereference 1494b9c1b51eSKate Stone // DoGuessValueAt(frame, rdi, 8, dis, vars, 0x18) finds the instruction at 1495b9c1b51eSKate Stone // +14 that assigns to rdi, and calls itself recursively for that 1496b9c1b51eSKate Stone // derefernece 1497b9c1b51eSKate Stone // DoGuessValueAt(frame, rbp, -8, dis, vars, 0x14) finds "f" in the 1498b9c1b51eSKate Stone // variable list. 14994740a734SSean Callanan // Returns a ValueObject for f. (That's what was stored at rbp-8 at +14) 1500b9c1b51eSKate Stone // Returns a ValueObject for *(f+8) or f->b (That's what was stored at rdi+8 1501b9c1b51eSKate Stone // at +18) 1502b9c1b51eSKate Stone // Returns a ValueObject for *(f->b+4) or f->b->a (That's what was stored at 1503b9c1b51eSKate Stone // rdi+4 at +22) 15044740a734SSean Callanan 1505b9c1b51eSKate Stone // First, check the variable list to see if anything is at the specified 1506b9c1b51eSKate Stone // location. 1507807ee2ffSSean Callanan 150850857108SSean Callanan using namespace OperandMatchers; 150950857108SSean Callanan 15100ac172d8SSean Callanan const RegisterInfo *reg_info = 15110ac172d8SSean Callanan frame.GetRegisterContext()->GetRegisterInfoByName(reg.AsCString()); 15120ac172d8SSean Callanan if (!reg_info) { 15130ac172d8SSean Callanan return ValueObjectSP(); 15140ac172d8SSean Callanan } 15150ac172d8SSean Callanan 1516807ee2ffSSean Callanan Instruction::Operand op = 1517807ee2ffSSean Callanan offset ? Instruction::Operand::BuildDereference( 1518807ee2ffSSean Callanan Instruction::Operand::BuildSum( 1519807ee2ffSSean Callanan Instruction::Operand::BuildRegister(reg), 1520807ee2ffSSean Callanan Instruction::Operand::BuildImmediate(offset))) 1521807ee2ffSSean Callanan : Instruction::Operand::BuildDereference( 1522807ee2ffSSean Callanan Instruction::Operand::BuildRegister(reg)); 1523807ee2ffSSean Callanan 1524b9c1b51eSKate Stone for (size_t vi = 0, ve = variables.GetSize(); vi != ve; ++vi) { 15254740a734SSean Callanan VariableSP var_sp = variables.GetVariableAtIndex(vi); 1526807ee2ffSSean Callanan if (var_sp->LocationExpression().MatchesOperand(frame, op)) { 15274740a734SSean Callanan return frame.GetValueObjectForFrameVariable(var_sp, eNoDynamicValues); 15284740a734SSean Callanan } 15294740a734SSean Callanan } 15304740a734SSean Callanan 1531b9c1b51eSKate Stone const uint32_t current_inst = 1532b9c1b51eSKate Stone disassembler.GetInstructionList().GetIndexOfInstructionAtAddress(pc); 1533b9c1b51eSKate Stone if (current_inst == UINT32_MAX) { 15344740a734SSean Callanan return ValueObjectSP(); 15354740a734SSean Callanan } 15364740a734SSean Callanan 1537b9c1b51eSKate Stone for (uint32_t ii = current_inst - 1; ii != (uint32_t)-1; --ii) { 1538b9c1b51eSKate Stone // This is not an exact algorithm, and it sacrifices accuracy for 153905097246SAdrian Prantl // generality. Recognizing "mov" and "ld" instructions –– and which 154005097246SAdrian Prantl // are their source and destination operands -- is something the 154105097246SAdrian Prantl // disassembler should do for us. 1542b9c1b51eSKate Stone InstructionSP instruction_sp = 1543b9c1b51eSKate Stone disassembler.GetInstructionList().GetInstructionAtIndex(ii); 15444740a734SSean Callanan 154550857108SSean Callanan if (instruction_sp->IsCall()) { 154650857108SSean Callanan ABISP abi_sp = frame.CalculateProcess()->GetABI(); 154750857108SSean Callanan if (!abi_sp) { 154850857108SSean Callanan continue; 154950857108SSean Callanan } 155050857108SSean Callanan 155150857108SSean Callanan const char *return_register_name; 155250857108SSean Callanan if (!abi_sp->GetPointerReturnRegister(return_register_name)) { 155350857108SSean Callanan continue; 155450857108SSean Callanan } 155550857108SSean Callanan 155650857108SSean Callanan const RegisterInfo *return_register_info = 155750857108SSean Callanan frame.GetRegisterContext()->GetRegisterInfoByName( 155850857108SSean Callanan return_register_name); 155950857108SSean Callanan if (!return_register_info) { 156050857108SSean Callanan continue; 156150857108SSean Callanan } 156250857108SSean Callanan 156350857108SSean Callanan int64_t offset = 0; 156450857108SSean Callanan 156550857108SSean Callanan if (!MatchUnaryOp(MatchOpType(Instruction::Operand::Type::Dereference), 156650857108SSean Callanan MatchRegOp(*return_register_info))(op) && 156750857108SSean Callanan !MatchUnaryOp( 156850857108SSean Callanan MatchOpType(Instruction::Operand::Type::Dereference), 156950857108SSean Callanan MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum), 157050857108SSean Callanan MatchRegOp(*return_register_info), 157150857108SSean Callanan FetchImmOp(offset)))(op)) { 157250857108SSean Callanan continue; 157350857108SSean Callanan } 157450857108SSean Callanan 15754740a734SSean Callanan llvm::SmallVector<Instruction::Operand, 1> operands; 1576b9c1b51eSKate Stone if (!instruction_sp->ParseOperands(operands) || operands.size() != 1) { 15774740a734SSean Callanan continue; 15784740a734SSean Callanan } 15794740a734SSean Callanan 1580b9c1b51eSKate Stone switch (operands[0].m_type) { 15814740a734SSean Callanan default: 15824740a734SSean Callanan break; 1583b9c1b51eSKate Stone case Instruction::Operand::Type::Immediate: { 15844740a734SSean Callanan SymbolContext sc; 15854740a734SSean Callanan Address load_address; 1586b9c1b51eSKate Stone if (!frame.CalculateTarget()->ResolveLoadAddress( 1587b9c1b51eSKate Stone operands[0].m_immediate, load_address)) { 15884740a734SSean Callanan break; 15894740a734SSean Callanan } 1590b9c1b51eSKate Stone frame.CalculateTarget()->GetImages().ResolveSymbolContextForAddress( 1591b9c1b51eSKate Stone load_address, eSymbolContextFunction, sc); 1592b9c1b51eSKate Stone if (!sc.function) { 15934740a734SSean Callanan break; 15944740a734SSean Callanan } 15954740a734SSean Callanan CompilerType function_type = sc.function->GetCompilerType(); 1596b9c1b51eSKate Stone if (!function_type.IsFunctionType()) { 15974740a734SSean Callanan break; 15984740a734SSean Callanan } 15994740a734SSean Callanan CompilerType return_type = function_type.GetFunctionReturnType(); 16004740a734SSean Callanan RegisterValue return_value; 160150857108SSean Callanan if (!frame.GetRegisterContext()->ReadRegister(return_register_info, 1602b9c1b51eSKate Stone return_value)) { 16034740a734SSean Callanan break; 16044740a734SSean Callanan } 1605b9c1b51eSKate Stone std::string name_str( 1606b9c1b51eSKate Stone sc.function->GetName().AsCString("<unknown function>")); 16074740a734SSean Callanan name_str.append("()"); 16084740a734SSean Callanan Address return_value_address(return_value.GetAsUInt64()); 1609b9c1b51eSKate Stone ValueObjectSP return_value_sp = ValueObjectMemory::Create( 161022a2628fSZachary Turner &frame, name_str, return_value_address, return_type); 16114740a734SSean Callanan return GetValueForDereferincingOffset(frame, return_value_sp, offset); 16124740a734SSean Callanan } 16134740a734SSean Callanan } 16144740a734SSean Callanan 16154740a734SSean Callanan continue; 16164740a734SSean Callanan } 16174740a734SSean Callanan 16184740a734SSean Callanan llvm::SmallVector<Instruction::Operand, 2> operands; 1619b9c1b51eSKate Stone if (!instruction_sp->ParseOperands(operands) || operands.size() != 2) { 16204740a734SSean Callanan continue; 16214740a734SSean Callanan } 16224740a734SSean Callanan 16234740a734SSean Callanan Instruction::Operand *origin_operand = nullptr; 1624aa4b44c6SSean Callanan auto clobbered_reg_matcher = [reg_info](const Instruction::Operand &op) { 16250ac172d8SSean Callanan return MatchRegOp(*reg_info)(op) && op.m_clobbered; 16260ac172d8SSean Callanan }; 16270ac172d8SSean Callanan 16280ac172d8SSean Callanan if (clobbered_reg_matcher(operands[0])) { 16294740a734SSean Callanan origin_operand = &operands[1]; 16300ac172d8SSean Callanan } 16310ac172d8SSean Callanan else if (clobbered_reg_matcher(operands[1])) { 16324740a734SSean Callanan origin_operand = &operands[0]; 16330ac172d8SSean Callanan } 16340ac172d8SSean Callanan else { 16354740a734SSean Callanan continue; 16364740a734SSean Callanan } 16374740a734SSean Callanan 16384740a734SSean Callanan // We have an origin operand. Can we track its value down? 1639561a9bbfSSean Callanan ValueObjectSP source_path; 1640561a9bbfSSean Callanan ConstString origin_register; 1641561a9bbfSSean Callanan int64_t origin_offset = 0; 1642561a9bbfSSean Callanan 1643561a9bbfSSean Callanan if (FetchRegOp(origin_register)(*origin_operand)) { 1644561a9bbfSSean Callanan source_path = DoGuessValueAt(frame, origin_register, 0, disassembler, 1645561a9bbfSSean Callanan variables, instruction_sp->GetAddress()); 1646561a9bbfSSean Callanan } else if (MatchUnaryOp( 1647561a9bbfSSean Callanan MatchOpType(Instruction::Operand::Type::Dereference), 1648561a9bbfSSean Callanan FetchRegOp(origin_register))(*origin_operand) || 1649561a9bbfSSean Callanan MatchUnaryOp( 1650561a9bbfSSean Callanan MatchOpType(Instruction::Operand::Type::Dereference), 1651561a9bbfSSean Callanan MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum), 1652561a9bbfSSean Callanan FetchRegOp(origin_register), 1653561a9bbfSSean Callanan FetchImmOp(origin_offset)))(*origin_operand)) { 1654b9c1b51eSKate Stone source_path = 1655561a9bbfSSean Callanan DoGuessValueAt(frame, origin_register, origin_offset, disassembler, 1656b9c1b51eSKate Stone variables, instruction_sp->GetAddress()); 1657b9c1b51eSKate Stone if (!source_path) { 1658561a9bbfSSean Callanan continue; 16594740a734SSean Callanan } 1660b9c1b51eSKate Stone source_path = 1661b9c1b51eSKate Stone GetValueForDereferincingOffset(frame, source_path, offset); 16624740a734SSean Callanan } 16634740a734SSean Callanan 1664b9c1b51eSKate Stone if (source_path) { 16654740a734SSean Callanan return source_path; 16664740a734SSean Callanan } 16674740a734SSean Callanan } 16684740a734SSean Callanan 16694740a734SSean Callanan return ValueObjectSP(); 16704740a734SSean Callanan } 16714740a734SSean Callanan } 16724740a734SSean Callanan 1673b9c1b51eSKate Stone lldb::ValueObjectSP StackFrame::GuessValueForRegisterAndOffset(ConstString reg, 1674b9c1b51eSKate Stone int64_t offset) { 16754740a734SSean Callanan TargetSP target_sp = CalculateTarget(); 16764740a734SSean Callanan 16774740a734SSean Callanan const ArchSpec &target_arch = target_sp->GetArchitecture(); 16784740a734SSean Callanan 16794740a734SSean Callanan Block *frame_block = GetFrameBlock(); 16804740a734SSean Callanan 1681b9c1b51eSKate Stone if (!frame_block) { 16824740a734SSean Callanan return ValueObjectSP(); 16834740a734SSean Callanan } 16844740a734SSean Callanan 16854740a734SSean Callanan Function *function = frame_block->CalculateSymbolContextFunction(); 1686b9c1b51eSKate Stone if (!function) { 16874740a734SSean Callanan return ValueObjectSP(); 16884740a734SSean Callanan } 16894740a734SSean Callanan 16904740a734SSean Callanan AddressRange pc_range = function->GetAddressRange(); 16914740a734SSean Callanan 1692b9c1b51eSKate Stone if (GetFrameCodeAddress().GetFileAddress() < 1693b9c1b51eSKate Stone pc_range.GetBaseAddress().GetFileAddress() || 1694b9c1b51eSKate Stone GetFrameCodeAddress().GetFileAddress() - 1695b9c1b51eSKate Stone pc_range.GetBaseAddress().GetFileAddress() >= 1696b9c1b51eSKate Stone pc_range.GetByteSize()) { 16974740a734SSean Callanan return ValueObjectSP(); 16984740a734SSean Callanan } 16994740a734SSean Callanan 17004740a734SSean Callanan ExecutionContext exe_ctx(shared_from_this()); 17014740a734SSean Callanan 17024740a734SSean Callanan const char *plugin_name = nullptr; 17034740a734SSean Callanan const char *flavor = nullptr; 17044740a734SSean Callanan const bool prefer_file_cache = false; 1705b9c1b51eSKate Stone DisassemblerSP disassembler_sp = Disassembler::DisassembleRange( 1706b9c1b51eSKate Stone target_arch, plugin_name, flavor, exe_ctx, pc_range, prefer_file_cache); 17074740a734SSean Callanan 1708b9c1b51eSKate Stone if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) { 17094740a734SSean Callanan return ValueObjectSP(); 17104740a734SSean Callanan } 17114740a734SSean Callanan 17124740a734SSean Callanan const bool get_file_globals = false; 17134740a734SSean Callanan VariableList *variables = GetVariableList(get_file_globals); 17144740a734SSean Callanan 1715b9c1b51eSKate Stone if (!variables) { 17164740a734SSean Callanan return ValueObjectSP(); 17174740a734SSean Callanan } 17184740a734SSean Callanan 1719b9c1b51eSKate Stone return DoGuessValueAt(*this, reg, offset, *disassembler_sp, *variables, 1720b9c1b51eSKate Stone GetFrameCodeAddress()); 17214740a734SSean Callanan } 17224740a734SSean Callanan 1723e23d0b63SShafik Yaghmour lldb::ValueObjectSP StackFrame::FindVariable(ConstString name) { 1724e23d0b63SShafik Yaghmour ValueObjectSP value_sp; 1725e23d0b63SShafik Yaghmour 1726e23d0b63SShafik Yaghmour if (!name) 1727e23d0b63SShafik Yaghmour return value_sp; 1728e23d0b63SShafik Yaghmour 1729e23d0b63SShafik Yaghmour TargetSP target_sp = CalculateTarget(); 1730e23d0b63SShafik Yaghmour ProcessSP process_sp = CalculateProcess(); 1731e23d0b63SShafik Yaghmour 1732e23d0b63SShafik Yaghmour if (!target_sp && !process_sp) 1733e23d0b63SShafik Yaghmour return value_sp; 1734e23d0b63SShafik Yaghmour 1735e23d0b63SShafik Yaghmour VariableList variable_list; 1736e23d0b63SShafik Yaghmour VariableSP var_sp; 1737e23d0b63SShafik Yaghmour SymbolContext sc(GetSymbolContext(eSymbolContextBlock)); 1738e23d0b63SShafik Yaghmour 1739e23d0b63SShafik Yaghmour if (sc.block) { 1740e23d0b63SShafik Yaghmour const bool can_create = true; 1741e23d0b63SShafik Yaghmour const bool get_parent_variables = true; 1742e23d0b63SShafik Yaghmour const bool stop_if_block_is_inlined_function = true; 1743e23d0b63SShafik Yaghmour 1744e23d0b63SShafik Yaghmour if (sc.block->AppendVariables( 1745e23d0b63SShafik Yaghmour can_create, get_parent_variables, stop_if_block_is_inlined_function, 1746e23d0b63SShafik Yaghmour [this](Variable *v) { return v->IsInScope(this); }, 1747e23d0b63SShafik Yaghmour &variable_list)) { 1748e23d0b63SShafik Yaghmour var_sp = variable_list.FindVariable(name); 1749e23d0b63SShafik Yaghmour } 1750e23d0b63SShafik Yaghmour 1751e23d0b63SShafik Yaghmour if (var_sp) 1752e23d0b63SShafik Yaghmour value_sp = GetValueObjectForFrameVariable(var_sp, eNoDynamicValues); 1753e23d0b63SShafik Yaghmour } 1754e23d0b63SShafik Yaghmour 1755e23d0b63SShafik Yaghmour return value_sp; 1756e23d0b63SShafik Yaghmour } 1757e23d0b63SShafik Yaghmour 1758b9c1b51eSKate Stone TargetSP StackFrame::CalculateTarget() { 1759d9e416c0SGreg Clayton TargetSP target_sp; 1760d9e416c0SGreg Clayton ThreadSP thread_sp(GetThread()); 1761b9c1b51eSKate Stone if (thread_sp) { 1762d9e416c0SGreg Clayton ProcessSP process_sp(thread_sp->CalculateProcess()); 1763d9e416c0SGreg Clayton if (process_sp) 1764d9e416c0SGreg Clayton target_sp = process_sp->CalculateTarget(); 1765d9e416c0SGreg Clayton } 1766d9e416c0SGreg Clayton return target_sp; 176730fdc8d8SChris Lattner } 176830fdc8d8SChris Lattner 1769b9c1b51eSKate Stone ProcessSP StackFrame::CalculateProcess() { 1770d9e416c0SGreg Clayton ProcessSP process_sp; 1771d9e416c0SGreg Clayton ThreadSP thread_sp(GetThread()); 1772d9e416c0SGreg Clayton if (thread_sp) 1773d9e416c0SGreg Clayton process_sp = thread_sp->CalculateProcess(); 1774d9e416c0SGreg Clayton return process_sp; 177530fdc8d8SChris Lattner } 177630fdc8d8SChris Lattner 1777b9c1b51eSKate Stone ThreadSP StackFrame::CalculateThread() { return GetThread(); } 177830fdc8d8SChris Lattner 1779b9c1b51eSKate Stone StackFrameSP StackFrame::CalculateStackFrame() { return shared_from_this(); } 178030fdc8d8SChris Lattner 1781b9c1b51eSKate Stone void StackFrame::CalculateExecutionContext(ExecutionContext &exe_ctx) { 1782d9e416c0SGreg Clayton exe_ctx.SetContext(shared_from_this()); 178330fdc8d8SChris Lattner } 178430fdc8d8SChris Lattner 17857f1c1211SPavel Labath void StackFrame::DumpUsingSettingsFormat(Stream *strm, bool show_unique, 1786b9c1b51eSKate Stone const char *frame_marker) { 1787d70a6e71SEugene Zelenko if (strm == nullptr) 17880603aa9dSGreg Clayton return; 17890603aa9dSGreg Clayton 17900603aa9dSGreg Clayton GetSymbolContext(eSymbolContextEverything); 1791d9e416c0SGreg Clayton ExecutionContext exe_ctx(shared_from_this()); 17920603aa9dSGreg Clayton StreamString s; 17938ec10efcSJim Ingham 17948ec10efcSJim Ingham if (frame_marker) 17958ec10efcSJim Ingham s.PutCString(frame_marker); 17968ec10efcSJim Ingham 1797d70a6e71SEugene Zelenko const FormatEntity::Entry *frame_format = nullptr; 1798d9e416c0SGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 17997f1c1211SPavel Labath if (target) { 18007f1c1211SPavel Labath if (show_unique) { 18017f1c1211SPavel Labath frame_format = target->GetDebugger().GetFrameFormatUnique(); 18027f1c1211SPavel Labath } else { 1803d9e416c0SGreg Clayton frame_format = target->GetDebugger().GetFrameFormat(); 18047f1c1211SPavel Labath } 18057f1c1211SPavel Labath } 1806b9c1b51eSKate Stone if (frame_format && FormatEntity::Format(*frame_format, s, &m_sc, &exe_ctx, 1807b9c1b51eSKate Stone nullptr, nullptr, false, false)) { 1808c156427dSZachary Turner strm->PutCString(s.GetString()); 1809b9c1b51eSKate Stone } else { 18100603aa9dSGreg Clayton Dump(strm, true, false); 18110603aa9dSGreg Clayton strm->EOL(); 18120603aa9dSGreg Clayton } 18130603aa9dSGreg Clayton } 18140603aa9dSGreg Clayton 1815b9c1b51eSKate Stone void StackFrame::Dump(Stream *strm, bool show_frame_index, 1816b9c1b51eSKate Stone bool show_fullpaths) { 1817d70a6e71SEugene Zelenko if (strm == nullptr) 181830fdc8d8SChris Lattner return; 181930fdc8d8SChris Lattner 182030fdc8d8SChris Lattner if (show_frame_index) 18211b72fcb7SGreg Clayton strm->Printf("frame #%u: ", m_frame_index); 1822d9e416c0SGreg Clayton ExecutionContext exe_ctx(shared_from_this()); 1823d9e416c0SGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 1824d01b2953SDaniel Malea strm->Printf("0x%0*" PRIx64 " ", 1825b9c1b51eSKate Stone target ? (target->GetArchitecture().GetAddressByteSize() * 2) 1826b9c1b51eSKate Stone : 16, 1827d9e416c0SGreg Clayton GetFrameCodeAddress().GetLoadAddress(target)); 18289da7bd07SGreg Clayton GetSymbolContext(eSymbolContextEverything); 18291b72fcb7SGreg Clayton const bool show_module = true; 18301b72fcb7SGreg Clayton const bool show_inline = true; 1831aff1b357SJason Molenda const bool show_function_arguments = true; 1832c980fa92SJason Molenda const bool show_function_name = true; 1833b9c1b51eSKate Stone m_sc.DumpStopContext(strm, exe_ctx.GetBestExecutionContextScope(), 1834b9c1b51eSKate Stone GetFrameCodeAddress(), show_fullpaths, show_module, 1835b9c1b51eSKate Stone show_inline, show_function_arguments, 1836c980fa92SJason Molenda show_function_name); 183730fdc8d8SChris Lattner } 183830fdc8d8SChris Lattner 1839b9c1b51eSKate Stone void StackFrame::UpdateCurrentFrameFromPreviousFrame(StackFrame &prev_frame) { 1840bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 1841b9c1b51eSKate Stone assert(GetStackID() == 1842b9c1b51eSKate Stone prev_frame.GetStackID()); // TODO: remove this after some testing 1843b57e4a1bSJason Molenda m_variable_list_sp = prev_frame.m_variable_list_sp; 1844b57e4a1bSJason Molenda m_variable_list_value_objects.Swap(prev_frame.m_variable_list_value_objects); 1845c156427dSZachary Turner if (!m_disassembly.GetString().empty()) { 1846c156427dSZachary Turner m_disassembly.Clear(); 1847c156427dSZachary Turner m_disassembly.PutCString(prev_frame.m_disassembly.GetString()); 1848c156427dSZachary Turner } 18495082c5fdSGreg Clayton } 185068275d5eSGreg Clayton 1851b9c1b51eSKate Stone void StackFrame::UpdatePreviousFrameFromCurrentFrame(StackFrame &curr_frame) { 1852bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 1853b9c1b51eSKate Stone assert(GetStackID() == 1854b9c1b51eSKate Stone curr_frame.GetStackID()); // TODO: remove this after some testing 1855b57e4a1bSJason Molenda m_id.SetPC(curr_frame.m_id.GetPC()); // Update the Stack ID PC value 1856b57e4a1bSJason Molenda assert(GetThread() == curr_frame.GetThread()); 1857b57e4a1bSJason Molenda m_frame_index = curr_frame.m_frame_index; 1858b57e4a1bSJason Molenda m_concrete_frame_index = curr_frame.m_concrete_frame_index; 1859b57e4a1bSJason Molenda m_reg_context_sp = curr_frame.m_reg_context_sp; 1860b57e4a1bSJason Molenda m_frame_code_addr = curr_frame.m_frame_code_addr; 1861b9c1b51eSKate Stone assert(!m_sc.target_sp || !curr_frame.m_sc.target_sp || 1862b9c1b51eSKate Stone m_sc.target_sp.get() == curr_frame.m_sc.target_sp.get()); 1863b9c1b51eSKate Stone assert(!m_sc.module_sp || !curr_frame.m_sc.module_sp || 1864b9c1b51eSKate Stone m_sc.module_sp.get() == curr_frame.m_sc.module_sp.get()); 1865b9c1b51eSKate Stone assert(m_sc.comp_unit == nullptr || curr_frame.m_sc.comp_unit == nullptr || 1866b9c1b51eSKate Stone m_sc.comp_unit == curr_frame.m_sc.comp_unit); 1867b9c1b51eSKate Stone assert(m_sc.function == nullptr || curr_frame.m_sc.function == nullptr || 1868b9c1b51eSKate Stone m_sc.function == curr_frame.m_sc.function); 1869b57e4a1bSJason Molenda m_sc = curr_frame.m_sc; 187059e8fc1cSGreg Clayton m_flags.Clear(GOT_FRAME_BASE | eSymbolContextEverything); 187159e8fc1cSGreg Clayton m_flags.Set(m_sc.GetResolvedMask()); 187259e8fc1cSGreg Clayton m_frame_base.Clear(); 187359e8fc1cSGreg Clayton m_frame_base_error.Clear(); 187459e8fc1cSGreg Clayton } 1875e4284b71SJim Ingham 1876b9c1b51eSKate Stone bool StackFrame::HasCachedData() const { 1877d70a6e71SEugene Zelenko if (m_variable_list_sp) 1878b57e4a1bSJason Molenda return true; 1879b57e4a1bSJason Molenda if (m_variable_list_value_objects.GetSize() > 0) 1880b57e4a1bSJason Molenda return true; 1881b57e4a1bSJason Molenda if (!m_disassembly.GetString().empty()) 1882b57e4a1bSJason Molenda return true; 1883b57e4a1bSJason Molenda return false; 1884b57e4a1bSJason Molenda } 1885b57e4a1bSJason Molenda 1886b9c1b51eSKate Stone bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source, 18877f1c1211SPavel Labath bool show_unique, const char *frame_marker) { 1888b9c1b51eSKate Stone if (show_frame_info) { 18897260f620SGreg Clayton strm.Indent(); 18907f1c1211SPavel Labath DumpUsingSettingsFormat(&strm, show_unique, frame_marker); 18917260f620SGreg Clayton } 18927260f620SGreg Clayton 1893b9c1b51eSKate Stone if (show_source) { 1894d9e416c0SGreg Clayton ExecutionContext exe_ctx(shared_from_this()); 18958be74995SMohit K. Bhakkad bool have_source = false, have_debuginfo = false; 1896b9c1b51eSKate Stone Debugger::StopDisassemblyType disasm_display = 1897b9c1b51eSKate Stone Debugger::eStopDisassemblyTypeNever; 1898d9e416c0SGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 1899b9c1b51eSKate Stone if (target) { 190053eb7ad2SGreg Clayton Debugger &debugger = target->GetDebugger(); 1901b9c1b51eSKate Stone const uint32_t source_lines_before = 1902b9c1b51eSKate Stone debugger.GetStopSourceLineCount(true); 1903b9c1b51eSKate Stone const uint32_t source_lines_after = 1904b9c1b51eSKate Stone debugger.GetStopSourceLineCount(false); 190553eb7ad2SGreg Clayton disasm_display = debugger.GetStopDisassemblyDisplay(); 190653eb7ad2SGreg Clayton 19077260f620SGreg Clayton GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry); 1908b9c1b51eSKate Stone if (m_sc.comp_unit && m_sc.line_entry.IsValid()) { 19098be74995SMohit K. Bhakkad have_debuginfo = true; 1910b9c1b51eSKate Stone if (source_lines_before > 0 || source_lines_after > 0) { 1911b9c1b51eSKate Stone size_t num_lines = 1912b9c1b51eSKate Stone target->GetSourceManager().DisplaySourceLinesWithLineNumbers( 1913b9c1b51eSKate Stone m_sc.line_entry.file, m_sc.line_entry.line, 19149666ba75STodd Fiala m_sc.line_entry.column, source_lines_before, 19159666ba75STodd Fiala source_lines_after, "->", &strm); 19168be74995SMohit K. Bhakkad if (num_lines != 0) 19178be74995SMohit K. Bhakkad have_source = true; 19188be74995SMohit K. Bhakkad // TODO: Give here a one time warning if source file is missing. 1919e372b98dSGreg Clayton } 1920e372b98dSGreg Clayton } 1921b9c1b51eSKate Stone switch (disasm_display) { 192267cc0636SGreg Clayton case Debugger::eStopDisassemblyTypeNever: 1923e372b98dSGreg Clayton break; 1924e372b98dSGreg Clayton 19258be74995SMohit K. Bhakkad case Debugger::eStopDisassemblyTypeNoDebugInfo: 19268be74995SMohit K. Bhakkad if (have_debuginfo) 19278be74995SMohit K. Bhakkad break; 192862e0681aSJason Molenda LLVM_FALLTHROUGH; 19298be74995SMohit K. Bhakkad 193067cc0636SGreg Clayton case Debugger::eStopDisassemblyTypeNoSource: 1931e372b98dSGreg Clayton if (have_source) 1932e372b98dSGreg Clayton break; 193362e0681aSJason Molenda LLVM_FALLTHROUGH; 19348be74995SMohit K. Bhakkad 193567cc0636SGreg Clayton case Debugger::eStopDisassemblyTypeAlways: 1936b9c1b51eSKate Stone if (target) { 193753eb7ad2SGreg Clayton const uint32_t disasm_lines = debugger.GetDisassemblyLineCount(); 1938b9c1b51eSKate Stone if (disasm_lines > 0) { 1939d9e416c0SGreg Clayton const ArchSpec &target_arch = target->GetArchitecture(); 1940e372b98dSGreg Clayton AddressRange pc_range; 1941e372b98dSGreg Clayton pc_range.GetBaseAddress() = GetFrameCodeAddress(); 1942b9c1b51eSKate Stone pc_range.SetByteSize(disasm_lines * 1943b9c1b51eSKate Stone target_arch.GetMaximumOpcodeByteSize()); 1944d70a6e71SEugene Zelenko const char *plugin_name = nullptr; 1945d70a6e71SEugene Zelenko const char *flavor = nullptr; 19460b4c26b2SJason Molenda const bool mixed_source_and_assembly = false; 19470b4c26b2SJason Molenda Disassembler::Disassemble( 19480b4c26b2SJason Molenda target->GetDebugger(), target_arch, plugin_name, flavor, 19490b4c26b2SJason Molenda exe_ctx, pc_range, disasm_lines, mixed_source_and_assembly, 0, 1950b9c1b51eSKate Stone Disassembler::eOptionMarkPCAddress, strm); 1951e372b98dSGreg Clayton } 1952e372b98dSGreg Clayton } 1953e372b98dSGreg Clayton break; 19547260f620SGreg Clayton } 19557260f620SGreg Clayton } 195653eb7ad2SGreg Clayton } 19577260f620SGreg Clayton return true; 19587260f620SGreg Clayton } 1959*41ae8e74SKuba Mracek 1960*41ae8e74SKuba Mracek RecognizedStackFrameSP StackFrame::GetRecognizedFrame() { 1961*41ae8e74SKuba Mracek if (!m_recognized_frame_sp) { 1962*41ae8e74SKuba Mracek m_recognized_frame_sp = 1963*41ae8e74SKuba Mracek StackFrameRecognizerManager::RecognizeFrame(CalculateStackFrame()); 1964*41ae8e74SKuba Mracek } 1965*41ae8e74SKuba Mracek return m_recognized_frame_sp; 1966*41ae8e74SKuba Mracek } 1967