180814287SRaphael Isemann //===-- StackFrame.cpp ----------------------------------------------------===// 230fdc8d8SChris Lattner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 630fdc8d8SChris Lattner // 730fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 830fdc8d8SChris Lattner 9d70a6e71SEugene Zelenko #include "lldb/Target/StackFrame.h" 100603aa9dSGreg Clayton #include "lldb/Core/Debugger.h" 1130fdc8d8SChris Lattner #include "lldb/Core/Disassembler.h" 12554f68d3SGreg Clayton #include "lldb/Core/FormatEntity.h" 13592afe73SEnrico Granata #include "lldb/Core/Mangled.h" 14592afe73SEnrico Granata #include "lldb/Core/Module.h" 1530fdc8d8SChris Lattner #include "lldb/Core/Value.h" 1654979cddSGreg Clayton #include "lldb/Core/ValueObjectConstResult.h" 174740a734SSean Callanan #include "lldb/Core/ValueObjectMemory.h" 18b9c1b51eSKate Stone #include "lldb/Core/ValueObjectVariable.h" 191f746071SGreg Clayton #include "lldb/Symbol/CompileUnit.h" 2030fdc8d8SChris Lattner #include "lldb/Symbol/Function.h" 211f746071SGreg Clayton #include "lldb/Symbol/Symbol.h" 221f746071SGreg Clayton #include "lldb/Symbol/SymbolContextScope.h" 2346252398SEnrico Granata #include "lldb/Symbol/Type.h" 24288bdf9cSGreg Clayton #include "lldb/Symbol/VariableList.h" 254740a734SSean Callanan #include "lldb/Target/ABI.h" 2630fdc8d8SChris Lattner #include "lldb/Target/ExecutionContext.h" 2730fdc8d8SChris Lattner #include "lldb/Target/Process.h" 2830fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h" 2941ae8e74SKuba Mracek #include "lldb/Target/StackFrameRecognizer.h" 3030fdc8d8SChris Lattner #include "lldb/Target/Target.h" 3130fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 32c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h" 330e252e38SAlex Langford #include "lldb/Utility/Log.h" 34d821c997SPavel Labath #include "lldb/Utility/RegisterValue.h" 3530fdc8d8SChris Lattner 36991e4453SZachary Turner #include "lldb/lldb-enumerations.h" 37991e4453SZachary Turner 38796ac80bSJonas Devlieghere #include <memory> 39796ac80bSJonas Devlieghere 4030fdc8d8SChris Lattner using namespace lldb; 4130fdc8d8SChris Lattner using namespace lldb_private; 4230fdc8d8SChris Lattner 4330fdc8d8SChris Lattner // The first bits in the flags are reserved for the SymbolContext::Scope bits 4430fdc8d8SChris Lattner // so we know if we have tried to look up information in our internal symbol 4530fdc8d8SChris Lattner // context (m_sc) already. 4659e8fc1cSGreg Clayton #define RESOLVED_FRAME_CODE_ADDR (uint32_t(eSymbolContextEverything + 1)) 476dadd508SGreg Clayton #define RESOLVED_FRAME_ID_SYMBOL_SCOPE (RESOLVED_FRAME_CODE_ADDR << 1) 4859e8fc1cSGreg Clayton #define GOT_FRAME_BASE (RESOLVED_FRAME_ID_SYMBOL_SCOPE << 1) 4959e8fc1cSGreg Clayton #define RESOLVED_VARIABLES (GOT_FRAME_BASE << 1) 507c0962dcSSean Callanan #define RESOLVED_GLOBAL_VARIABLES (RESOLVED_VARIABLES << 1) 5130fdc8d8SChris Lattner 52b9c1b51eSKate Stone StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, 53b9c1b51eSKate Stone user_id_t unwind_frame_index, addr_t cfa, 544b36f791SVedant Kumar bool cfa_is_valid, addr_t pc, StackFrame::Kind kind, 5531e6dbe1SJoseph Tremoulet bool behaves_like_zeroth_frame, 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), 6131e6dbe1SJoseph Tremoulet m_stack_frame_kind(kind), 6231e6dbe1SJoseph Tremoulet m_behaves_like_zeroth_frame(behaves_like_zeroth_frame), 6331e6dbe1SJoseph Tremoulet m_variable_list_sp(), m_variable_list_value_objects(), 6431e6dbe1SJoseph Tremoulet m_recognized_frame_sp(), m_disassembly(), m_mutex() { 65b9c1b51eSKate Stone // If we don't have a CFA value, use the frame index for our StackID so that 6605097246SAdrian Prantl // recursive functions properly aren't confused with one another on a history 6705097246SAdrian Prantl // stack. 684b36f791SVedant Kumar if (IsHistorical() && !m_cfa_is_valid) { 6999618476SJason Molenda m_id.SetCFA(m_frame_index); 7099618476SJason Molenda } 7199618476SJason Molenda 72b9c1b51eSKate Stone if (sc_ptr != nullptr) { 7330fdc8d8SChris Lattner m_sc = *sc_ptr; 741b72fcb7SGreg Clayton m_flags.Set(m_sc.GetResolvedMask()); 751b72fcb7SGreg Clayton } 7630fdc8d8SChris Lattner } 7730fdc8d8SChris Lattner 78b9c1b51eSKate Stone StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, 79b9c1b51eSKate Stone user_id_t unwind_frame_index, 80b9c1b51eSKate Stone const RegisterContextSP ®_context_sp, addr_t cfa, 8131e6dbe1SJoseph Tremoulet addr_t pc, bool behaves_like_zeroth_frame, 8231e6dbe1SJoseph Tremoulet const SymbolContext *sc_ptr) 83b9c1b51eSKate Stone : m_thread_wp(thread_sp), m_frame_index(frame_idx), 845ccbd294SGreg Clayton m_concrete_frame_index(unwind_frame_index), 85b9c1b51eSKate Stone m_reg_context_sp(reg_context_sp), m_id(pc, cfa, nullptr), 86b9c1b51eSKate Stone m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(), 874b36f791SVedant Kumar m_frame_base_error(), m_cfa_is_valid(true), 8831e6dbe1SJoseph Tremoulet m_stack_frame_kind(StackFrame::Kind::Regular), 8931e6dbe1SJoseph Tremoulet m_behaves_like_zeroth_frame(behaves_like_zeroth_frame), 9031e6dbe1SJoseph Tremoulet m_variable_list_sp(), m_variable_list_value_objects(), 9131e6dbe1SJoseph Tremoulet m_recognized_frame_sp(), m_disassembly(), m_mutex() { 92b9c1b51eSKate Stone if (sc_ptr != nullptr) { 9330fdc8d8SChris Lattner m_sc = *sc_ptr; 941b72fcb7SGreg Clayton m_flags.Set(m_sc.GetResolvedMask()); 951b72fcb7SGreg Clayton } 961b72fcb7SGreg Clayton 97b9c1b51eSKate Stone if (reg_context_sp && !m_sc.target_sp) { 98d9e416c0SGreg Clayton m_sc.target_sp = reg_context_sp->CalculateTarget(); 99d9e416c0SGreg Clayton if (m_sc.target_sp) 1001b72fcb7SGreg Clayton m_flags.Set(eSymbolContextTarget); 1011b72fcb7SGreg Clayton } 1021b72fcb7SGreg Clayton } 1031b72fcb7SGreg Clayton 104b9c1b51eSKate Stone StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, 105b9c1b51eSKate Stone user_id_t unwind_frame_index, 106b9c1b51eSKate Stone const RegisterContextSP ®_context_sp, addr_t cfa, 10731e6dbe1SJoseph Tremoulet const Address &pc_addr, bool behaves_like_zeroth_frame, 10831e6dbe1SJoseph Tremoulet const SymbolContext *sc_ptr) 109b9c1b51eSKate Stone : m_thread_wp(thread_sp), m_frame_index(frame_idx), 1105ccbd294SGreg Clayton m_concrete_frame_index(unwind_frame_index), 1111b72fcb7SGreg Clayton m_reg_context_sp(reg_context_sp), 112b9c1b51eSKate Stone m_id(pc_addr.GetLoadAddress(thread_sp->CalculateTarget().get()), cfa, 113b9c1b51eSKate Stone nullptr), 114b9c1b51eSKate Stone m_frame_code_addr(pc_addr), m_sc(), m_flags(), m_frame_base(), 1154b36f791SVedant Kumar m_frame_base_error(), m_cfa_is_valid(true), 11631e6dbe1SJoseph Tremoulet m_stack_frame_kind(StackFrame::Kind::Regular), 11731e6dbe1SJoseph Tremoulet m_behaves_like_zeroth_frame(behaves_like_zeroth_frame), 11831e6dbe1SJoseph Tremoulet m_variable_list_sp(), m_variable_list_value_objects(), 11931e6dbe1SJoseph Tremoulet m_recognized_frame_sp(), m_disassembly(), m_mutex() { 120b9c1b51eSKate Stone if (sc_ptr != nullptr) { 1211b72fcb7SGreg Clayton m_sc = *sc_ptr; 1221b72fcb7SGreg Clayton m_flags.Set(m_sc.GetResolvedMask()); 1231b72fcb7SGreg Clayton } 1241b72fcb7SGreg Clayton 125b9c1b51eSKate Stone if (!m_sc.target_sp && reg_context_sp) { 126d9e416c0SGreg Clayton m_sc.target_sp = reg_context_sp->CalculateTarget(); 127d9e416c0SGreg Clayton if (m_sc.target_sp) 1281b72fcb7SGreg Clayton m_flags.Set(eSymbolContextTarget); 1291b72fcb7SGreg Clayton } 1301b72fcb7SGreg Clayton 131e72dfb32SGreg Clayton ModuleSP pc_module_sp(pc_addr.GetModule()); 132b9c1b51eSKate Stone if (!m_sc.module_sp || m_sc.module_sp != pc_module_sp) { 133b9c1b51eSKate Stone if (pc_module_sp) { 134e72dfb32SGreg Clayton m_sc.module_sp = pc_module_sp; 1351b72fcb7SGreg Clayton m_flags.Set(eSymbolContextModule); 136b9c1b51eSKate Stone } else { 137ffc1d667SGreg Clayton m_sc.module_sp.reset(); 138ffc1d667SGreg Clayton } 1391b72fcb7SGreg Clayton } 14030fdc8d8SChris Lattner } 14130fdc8d8SChris Lattner 142d70a6e71SEugene Zelenko StackFrame::~StackFrame() = default; 14330fdc8d8SChris Lattner 144b9c1b51eSKate Stone StackID &StackFrame::GetStackID() { 145bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 14605097246SAdrian Prantl // Make sure we have resolved the StackID object's symbol context scope if we 14705097246SAdrian Prantl // already haven't looked it up. 14859e8fc1cSGreg Clayton 149b9c1b51eSKate Stone if (m_flags.IsClear(RESOLVED_FRAME_ID_SYMBOL_SCOPE)) { 150b9c1b51eSKate Stone if (m_id.GetSymbolContextScope()) { 15105097246SAdrian Prantl // We already have a symbol context scope, we just don't have our flag 15205097246SAdrian Prantl // bit set. 15359e8fc1cSGreg Clayton m_flags.Set(RESOLVED_FRAME_ID_SYMBOL_SCOPE); 154b9c1b51eSKate Stone } else { 15505097246SAdrian Prantl // Calculate the frame block and use this for the stack ID symbol context 15605097246SAdrian Prantl // scope if we have one. 15795897c6aSGreg Clayton SymbolContextScope *scope = GetFrameBlock(); 158b9c1b51eSKate Stone if (scope == nullptr) { 15995897c6aSGreg Clayton // We don't have a block, so use the symbol 16095897c6aSGreg Clayton if (m_flags.IsClear(eSymbolContextSymbol)) 16159e8fc1cSGreg Clayton GetSymbolContext(eSymbolContextSymbol); 16295897c6aSGreg Clayton 163d70a6e71SEugene Zelenko // It is ok if m_sc.symbol is nullptr here 16495897c6aSGreg Clayton scope = m_sc.symbol; 16559e8fc1cSGreg Clayton } 16695897c6aSGreg Clayton // Set the symbol context scope (the accessor will set the 16795897c6aSGreg Clayton // RESOLVED_FRAME_ID_SYMBOL_SCOPE bit in m_flags). 16895897c6aSGreg Clayton SetSymbolContextScope(scope); 16959e8fc1cSGreg Clayton } 17059e8fc1cSGreg Clayton } 17130fdc8d8SChris Lattner return m_id; 17230fdc8d8SChris Lattner } 17330fdc8d8SChris Lattner 174b9c1b51eSKate Stone uint32_t StackFrame::GetFrameIndex() const { 175513c6bb8SJim Ingham ThreadSP thread_sp = GetThread(); 176513c6bb8SJim Ingham if (thread_sp) 177b9c1b51eSKate Stone return thread_sp->GetStackFrameList()->GetVisibleStackFrameIndex( 178b9c1b51eSKate Stone m_frame_index); 179513c6bb8SJim Ingham else 180513c6bb8SJim Ingham return m_frame_index; 181513c6bb8SJim Ingham } 182513c6bb8SJim Ingham 183b9c1b51eSKate Stone void StackFrame::SetSymbolContextScope(SymbolContextScope *symbol_scope) { 184bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 18559e8fc1cSGreg Clayton m_flags.Set(RESOLVED_FRAME_ID_SYMBOL_SCOPE); 18659e8fc1cSGreg Clayton m_id.SetSymbolContextScope(symbol_scope); 18759e8fc1cSGreg Clayton } 18859e8fc1cSGreg Clayton 189b9c1b51eSKate Stone const Address &StackFrame::GetFrameCodeAddress() { 190bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 191b9c1b51eSKate Stone if (m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR) && 192b9c1b51eSKate Stone !m_frame_code_addr.IsSectionOffset()) { 19359e8fc1cSGreg Clayton m_flags.Set(RESOLVED_FRAME_CODE_ADDR); 19430fdc8d8SChris Lattner 19530fdc8d8SChris Lattner // Resolve the PC into a temporary address because if ResolveLoadAddress 19630fdc8d8SChris Lattner // fails to resolve the address, it will clear the address object... 197d9e416c0SGreg Clayton ThreadSP thread_sp(GetThread()); 198b9c1b51eSKate Stone if (thread_sp) { 199d9e416c0SGreg Clayton TargetSP target_sp(thread_sp->CalculateTarget()); 200b9c1b51eSKate Stone if (target_sp) { 201c3c72122SPavel Labath const bool allow_section_end = true; 202b9c1b51eSKate Stone if (m_frame_code_addr.SetOpcodeLoadAddress( 203b9c1b51eSKate Stone m_frame_code_addr.GetOffset(), target_sp.get(), 20404803b3eSTatyana Krasnukha AddressClass::eCode, allow_section_end)) { 205e72dfb32SGreg Clayton ModuleSP module_sp(m_frame_code_addr.GetModule()); 206b9c1b51eSKate Stone if (module_sp) { 207e72dfb32SGreg Clayton m_sc.module_sp = module_sp; 20830fdc8d8SChris Lattner m_flags.Set(eSymbolContextModule); 20930fdc8d8SChris Lattner } 21030fdc8d8SChris Lattner } 21130fdc8d8SChris Lattner } 21230fdc8d8SChris Lattner } 213d9e416c0SGreg Clayton } 21412fc3e0fSGreg Clayton return m_frame_code_addr; 21530fdc8d8SChris Lattner } 21630fdc8d8SChris Lattner 217266bb78fSJason Molenda // This can't be rewritten into a call to 218266bb78fSJason Molenda // RegisterContext::GetPCForSymbolication because this 219266bb78fSJason Molenda // StackFrame may have been constructed with a special pc, 220266bb78fSJason Molenda // e.g. tail-call artificial frames. 221266bb78fSJason Molenda Address StackFrame::GetFrameCodeAddressForSymbolication() { 222266bb78fSJason Molenda Address lookup_addr(GetFrameCodeAddress()); 223266bb78fSJason Molenda if (!lookup_addr.IsValid()) 224266bb78fSJason Molenda return lookup_addr; 225266bb78fSJason Molenda if (m_behaves_like_zeroth_frame) 226266bb78fSJason Molenda return lookup_addr; 227266bb78fSJason Molenda 228266bb78fSJason Molenda addr_t offset = lookup_addr.GetOffset(); 229266bb78fSJason Molenda if (offset > 0) { 230266bb78fSJason Molenda lookup_addr.SetOffset(offset - 1); 231266bb78fSJason Molenda } else { 232266bb78fSJason Molenda // lookup_addr is the start of a section. We need do the math on the 233266bb78fSJason Molenda // actual load address and re-compute the section. We're working with 234266bb78fSJason Molenda // a 'noreturn' function at the end of a section. 235266bb78fSJason Molenda TargetSP target_sp = CalculateTarget(); 236266bb78fSJason Molenda if (target_sp) { 237266bb78fSJason Molenda addr_t addr_minus_one = lookup_addr.GetOpcodeLoadAddress( 238266bb78fSJason Molenda target_sp.get(), AddressClass::eCode) - 239266bb78fSJason Molenda 1; 240266bb78fSJason Molenda lookup_addr.SetOpcodeLoadAddress(addr_minus_one, target_sp.get()); 241266bb78fSJason Molenda } 242266bb78fSJason Molenda } 243266bb78fSJason Molenda return lookup_addr; 244266bb78fSJason Molenda } 245266bb78fSJason Molenda 246b9c1b51eSKate Stone bool StackFrame::ChangePC(addr_t pc) { 247bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 24899618476SJason Molenda // We can't change the pc value of a history stack frame - it is immutable. 2494b36f791SVedant Kumar if (IsHistorical()) 25099618476SJason Molenda return false; 251e72dfb32SGreg Clayton m_frame_code_addr.SetRawAddress(pc); 25272310355SGreg Clayton m_sc.Clear(false); 25373b472d4SGreg Clayton m_flags.Reset(0); 254d9e416c0SGreg Clayton ThreadSP thread_sp(GetThread()); 255d9e416c0SGreg Clayton if (thread_sp) 256d9e416c0SGreg Clayton thread_sp->ClearStackFrames(); 25799618476SJason Molenda return true; 25830fdc8d8SChris Lattner } 25930fdc8d8SChris Lattner 260b9c1b51eSKate Stone const char *StackFrame::Disassemble() { 261bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 262826997c4SJonas Devlieghere if (!m_disassembly.Empty()) 263826997c4SJonas Devlieghere return m_disassembly.GetData(); 264826997c4SJonas Devlieghere 265d9e416c0SGreg Clayton ExecutionContext exe_ctx(shared_from_this()); 266826997c4SJonas Devlieghere if (Target *target = exe_ctx.GetTargetPtr()) { 267826997c4SJonas Devlieghere Disassembler::Disassemble(target->GetDebugger(), target->GetArchitecture(), 268826997c4SJonas Devlieghere *this, m_disassembly); 2698b3f2160SZachary Turner } 2708b3f2160SZachary Turner 271826997c4SJonas Devlieghere return m_disassembly.Empty() ? nullptr : m_disassembly.GetData(); 27230fdc8d8SChris Lattner } 27330fdc8d8SChris Lattner 274b9c1b51eSKate Stone Block *StackFrame::GetFrameBlock() { 275d70a6e71SEugene Zelenko if (m_sc.block == nullptr && m_flags.IsClear(eSymbolContextBlock)) 27695897c6aSGreg Clayton GetSymbolContext(eSymbolContextBlock); 27795897c6aSGreg Clayton 278b9c1b51eSKate Stone if (m_sc.block) { 27995897c6aSGreg Clayton Block *inline_block = m_sc.block->GetContainingInlinedBlock(); 280b9c1b51eSKate Stone if (inline_block) { 28105097246SAdrian Prantl // Use the block with the inlined function info as the frame block we 28205097246SAdrian Prantl // want this frame to have only the variables for the inlined function 28305097246SAdrian Prantl // and its non-inlined block child blocks. 28495897c6aSGreg Clayton return inline_block; 285b9c1b51eSKate Stone } else { 28605097246SAdrian Prantl // This block is not contained within any inlined function blocks with so 28705097246SAdrian Prantl // we want to use the top most function block. 28895897c6aSGreg Clayton return &m_sc.function->GetBlock(false); 28995897c6aSGreg Clayton } 29095897c6aSGreg Clayton } 291d70a6e71SEugene Zelenko return nullptr; 29295897c6aSGreg Clayton } 29395897c6aSGreg Clayton 29430fdc8d8SChris Lattner // Get the symbol context if we already haven't done so by resolving the 29530fdc8d8SChris Lattner // PC address as much as possible. This way when we pass around a 29605097246SAdrian Prantl // StackFrame object, everyone will have as much information as possible and no 29705097246SAdrian Prantl // one will ever have to look things up manually. 298991e4453SZachary Turner const SymbolContext & 299991e4453SZachary Turner StackFrame::GetSymbolContext(SymbolContextItem resolve_scope) { 300bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 30130fdc8d8SChris Lattner // Copy our internal symbol context into "sc". 302b9c1b51eSKate Stone if ((m_flags.Get() & resolve_scope) != resolve_scope) { 30375a0333bSGreg Clayton uint32_t resolved = 0; 30475a0333bSGreg Clayton 30575a0333bSGreg Clayton // If the target was requested add that: 306b9c1b51eSKate Stone if (!m_sc.target_sp) { 30775a0333bSGreg Clayton m_sc.target_sp = CalculateTarget(); 30875a0333bSGreg Clayton if (m_sc.target_sp) 30975a0333bSGreg Clayton resolved |= eSymbolContextTarget; 31075a0333bSGreg Clayton } 31175a0333bSGreg Clayton 31205097246SAdrian Prantl // Resolve our PC to section offset if we haven't already done so and if we 31305097246SAdrian Prantl // don't have a module. The resolved address section will contain the 31405097246SAdrian Prantl // module to which it belongs 31559e8fc1cSGreg Clayton if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR)) 3169da7bd07SGreg Clayton GetFrameCodeAddress(); 31730fdc8d8SChris Lattner 31805097246SAdrian Prantl // If this is not frame zero, then we need to subtract 1 from the PC value 31905097246SAdrian Prantl // when doing address lookups since the PC will be on the instruction 32005097246SAdrian Prantl // following the function call instruction... 321266bb78fSJason Molenda Address lookup_addr(GetFrameCodeAddressForSymbolication()); 32230fdc8d8SChris Lattner 323b9c1b51eSKate Stone if (m_sc.module_sp) { 32405097246SAdrian Prantl // We have something in our stack frame symbol context, lets check if we 32505097246SAdrian Prantl // haven't already tried to lookup one of those things. If we haven't 32605097246SAdrian Prantl // then we will do the query. 3271b72fcb7SGreg Clayton 328991e4453SZachary Turner SymbolContextItem actual_resolve_scope = SymbolContextItem(0); 3291b72fcb7SGreg Clayton 330b9c1b51eSKate Stone if (resolve_scope & eSymbolContextCompUnit) { 331b9c1b51eSKate Stone if (m_flags.IsClear(eSymbolContextCompUnit)) { 3321b72fcb7SGreg Clayton if (m_sc.comp_unit) 3339da7bd07SGreg Clayton resolved |= eSymbolContextCompUnit; 3341b72fcb7SGreg Clayton else 3351b72fcb7SGreg Clayton actual_resolve_scope |= eSymbolContextCompUnit; 3361b72fcb7SGreg Clayton } 3371b72fcb7SGreg Clayton } 3381b72fcb7SGreg Clayton 339b9c1b51eSKate Stone if (resolve_scope & eSymbolContextFunction) { 340b9c1b51eSKate Stone if (m_flags.IsClear(eSymbolContextFunction)) { 3411b72fcb7SGreg Clayton if (m_sc.function) 3429da7bd07SGreg Clayton resolved |= eSymbolContextFunction; 3431b72fcb7SGreg Clayton else 3441b72fcb7SGreg Clayton actual_resolve_scope |= eSymbolContextFunction; 3451b72fcb7SGreg Clayton } 3461b72fcb7SGreg Clayton } 3471b72fcb7SGreg Clayton 348b9c1b51eSKate Stone if (resolve_scope & eSymbolContextBlock) { 349b9c1b51eSKate Stone if (m_flags.IsClear(eSymbolContextBlock)) { 3501b72fcb7SGreg Clayton if (m_sc.block) 3519da7bd07SGreg Clayton resolved |= eSymbolContextBlock; 3521b72fcb7SGreg Clayton else 3531b72fcb7SGreg Clayton actual_resolve_scope |= eSymbolContextBlock; 3541b72fcb7SGreg Clayton } 3551b72fcb7SGreg Clayton } 3561b72fcb7SGreg Clayton 357b9c1b51eSKate Stone if (resolve_scope & eSymbolContextSymbol) { 358b9c1b51eSKate Stone if (m_flags.IsClear(eSymbolContextSymbol)) { 3591b72fcb7SGreg Clayton if (m_sc.symbol) 3609da7bd07SGreg Clayton resolved |= eSymbolContextSymbol; 3611b72fcb7SGreg Clayton else 3621b72fcb7SGreg Clayton actual_resolve_scope |= eSymbolContextSymbol; 3631b72fcb7SGreg Clayton } 3641b72fcb7SGreg Clayton } 3651b72fcb7SGreg Clayton 366b9c1b51eSKate Stone if (resolve_scope & eSymbolContextLineEntry) { 367b9c1b51eSKate Stone if (m_flags.IsClear(eSymbolContextLineEntry)) { 3681b72fcb7SGreg Clayton if (m_sc.line_entry.IsValid()) 3699da7bd07SGreg Clayton resolved |= eSymbolContextLineEntry; 3701b72fcb7SGreg Clayton else 3711b72fcb7SGreg Clayton actual_resolve_scope |= eSymbolContextLineEntry; 3721b72fcb7SGreg Clayton } 3731b72fcb7SGreg Clayton } 3741b72fcb7SGreg Clayton 375b9c1b51eSKate Stone if (actual_resolve_scope) { 37605097246SAdrian Prantl // We might be resolving less information than what is already in our 37705097246SAdrian Prantl // current symbol context so resolve into a temporary symbol context 37805097246SAdrian Prantl // "sc" so we don't clear out data we have already found in "m_sc" 37930fdc8d8SChris Lattner SymbolContext sc; 38030fdc8d8SChris Lattner // Set flags that indicate what we have tried to resolve 381b9c1b51eSKate Stone resolved |= m_sc.module_sp->ResolveSymbolContextForAddress( 382b9c1b51eSKate Stone lookup_addr, actual_resolve_scope, sc); 38305097246SAdrian Prantl // Only replace what we didn't already have as we may have information 38405097246SAdrian Prantl // for an inlined function scope that won't match what a standard 38505097246SAdrian Prantl // lookup by address would match 386d70a6e71SEugene Zelenko if ((resolved & eSymbolContextCompUnit) && m_sc.comp_unit == nullptr) 3879da7bd07SGreg Clayton m_sc.comp_unit = sc.comp_unit; 388d70a6e71SEugene Zelenko if ((resolved & eSymbolContextFunction) && m_sc.function == nullptr) 3899da7bd07SGreg Clayton m_sc.function = sc.function; 390d70a6e71SEugene Zelenko if ((resolved & eSymbolContextBlock) && m_sc.block == nullptr) 3919da7bd07SGreg Clayton m_sc.block = sc.block; 392d70a6e71SEugene Zelenko if ((resolved & eSymbolContextSymbol) && m_sc.symbol == nullptr) 3939da7bd07SGreg Clayton m_sc.symbol = sc.symbol; 394b9c1b51eSKate Stone if ((resolved & eSymbolContextLineEntry) && 395b9c1b51eSKate Stone !m_sc.line_entry.IsValid()) { 3969da7bd07SGreg Clayton m_sc.line_entry = sc.line_entry; 397911d5784STed Woodward m_sc.line_entry.ApplyFileMappings(m_sc.target_sp); 39875a0333bSGreg Clayton } 39930fdc8d8SChris Lattner } 400b9c1b51eSKate Stone } else { 40130fdc8d8SChris Lattner // If we don't have a module, then we can't have the compile unit, 40230fdc8d8SChris Lattner // function, block, line entry or symbol, so we can safely call 40330fdc8d8SChris Lattner // ResolveSymbolContextForAddress with our symbol context member m_sc. 404b9c1b51eSKate Stone if (m_sc.target_sp) { 405b9c1b51eSKate Stone resolved |= m_sc.target_sp->GetImages().ResolveSymbolContextForAddress( 406b9c1b51eSKate Stone lookup_addr, resolve_scope, m_sc); 407f4be227dSSean Callanan } 4089da7bd07SGreg Clayton } 40930fdc8d8SChris Lattner 41030fdc8d8SChris Lattner // Update our internal flags so we remember what we have tried to locate so 41130fdc8d8SChris Lattner // we don't have to keep trying when more calls to this function are made. 41205097246SAdrian Prantl // We might have dug up more information that was requested (for example if 41305097246SAdrian Prantl // we were asked to only get the block, we will have gotten the compile 41405097246SAdrian Prantl // unit, and function) so set any additional bits that we resolved 4159da7bd07SGreg Clayton m_flags.Set(resolve_scope | resolved); 41630fdc8d8SChris Lattner } 41730fdc8d8SChris Lattner 41830fdc8d8SChris Lattner // Return the symbol context with everything that was possible to resolve 41930fdc8d8SChris Lattner // resolved. 42030fdc8d8SChris Lattner return m_sc; 42130fdc8d8SChris Lattner } 42230fdc8d8SChris Lattner 423b9c1b51eSKate Stone VariableList *StackFrame::GetVariableList(bool get_file_globals) { 424bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 425b9c1b51eSKate Stone if (m_flags.IsClear(RESOLVED_VARIABLES)) { 42630fdc8d8SChris Lattner m_flags.Set(RESOLVED_VARIABLES); 42730fdc8d8SChris Lattner 42895897c6aSGreg Clayton Block *frame_block = GetFrameBlock(); 429288bdf9cSGreg Clayton 430b9c1b51eSKate Stone if (frame_block) { 43195897c6aSGreg Clayton const bool get_child_variables = true; 43295897c6aSGreg Clayton const bool can_create = true; 433c662ec8bSGreg Clayton const bool stop_if_child_block_is_inlined_function = true; 434796ac80bSJonas Devlieghere m_variable_list_sp = std::make_shared<VariableList>(); 435b9c1b51eSKate Stone frame_block->AppendBlockVariables(can_create, get_child_variables, 43672ac8a84STamas Berghammer stop_if_child_block_is_inlined_function, 4373bc714b2SZachary Turner [](Variable *v) { return true; }, 43872ac8a84STamas Berghammer m_variable_list_sp.get()); 43930fdc8d8SChris Lattner } 4407c0962dcSSean Callanan } 441288bdf9cSGreg Clayton 442b9c1b51eSKate Stone if (m_flags.IsClear(RESOLVED_GLOBAL_VARIABLES) && get_file_globals) { 4437c0962dcSSean Callanan m_flags.Set(RESOLVED_GLOBAL_VARIABLES); 4447c0962dcSSean Callanan 44595897c6aSGreg Clayton if (m_flags.IsClear(eSymbolContextCompUnit)) 44695897c6aSGreg Clayton GetSymbolContext(eSymbolContextCompUnit); 44795897c6aSGreg Clayton 448b9c1b51eSKate Stone if (m_sc.comp_unit) { 449b9c1b51eSKate Stone VariableListSP global_variable_list_sp( 450b9c1b51eSKate Stone m_sc.comp_unit->GetVariableList(true)); 451288bdf9cSGreg Clayton if (m_variable_list_sp) 452288bdf9cSGreg Clayton m_variable_list_sp->AddVariables(global_variable_list_sp.get()); 453288bdf9cSGreg Clayton else 454288bdf9cSGreg Clayton m_variable_list_sp = global_variable_list_sp; 455288bdf9cSGreg Clayton } 45630fdc8d8SChris Lattner } 4577c0962dcSSean Callanan 45830fdc8d8SChris Lattner return m_variable_list_sp.get(); 45930fdc8d8SChris Lattner } 46030fdc8d8SChris Lattner 461d41f032aSGreg Clayton VariableListSP 462b9c1b51eSKate Stone StackFrame::GetInScopeVariableList(bool get_file_globals, 463b9c1b51eSKate Stone bool must_have_valid_location) { 464bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 46599618476SJason Molenda // We can't fetch variable information for a history stack frame. 4664b36f791SVedant Kumar if (IsHistorical()) 46799618476SJason Molenda return VariableListSP(); 46899618476SJason Molenda 469d41f032aSGreg Clayton VariableListSP var_list_sp(new VariableList); 470d41f032aSGreg Clayton GetSymbolContext(eSymbolContextCompUnit | eSymbolContextBlock); 471d41f032aSGreg Clayton 472b9c1b51eSKate Stone if (m_sc.block) { 473d41f032aSGreg Clayton const bool can_create = true; 474d41f032aSGreg Clayton const bool get_parent_variables = true; 475d41f032aSGreg Clayton const bool stop_if_block_is_inlined_function = true; 476b9c1b51eSKate Stone m_sc.block->AppendVariables( 477b9c1b51eSKate Stone can_create, get_parent_variables, stop_if_block_is_inlined_function, 478b9c1b51eSKate Stone [this, must_have_valid_location](Variable *v) { 479b9c1b51eSKate Stone return v->IsInScope(this) && (!must_have_valid_location || 480b9c1b51eSKate Stone v->LocationIsValidForFrame(this)); 481cef46177SJim Ingham }, 482d41f032aSGreg Clayton var_list_sp.get()); 483d41f032aSGreg Clayton } 484d41f032aSGreg Clayton 485b9c1b51eSKate Stone if (m_sc.comp_unit && get_file_globals) { 486b9c1b51eSKate Stone VariableListSP global_variable_list_sp( 487b9c1b51eSKate Stone m_sc.comp_unit->GetVariableList(true)); 488d41f032aSGreg Clayton if (global_variable_list_sp) 489d41f032aSGreg Clayton var_list_sp->AddVariables(global_variable_list_sp.get()); 490d41f032aSGreg Clayton } 491d41f032aSGreg Clayton 492d41f032aSGreg Clayton return var_list_sp; 493d41f032aSGreg Clayton } 494d41f032aSGreg Clayton 495b9c1b51eSKate Stone ValueObjectSP StackFrame::GetValueForVariableExpressionPath( 4960eb31a1dSZachary Turner llvm::StringRef var_expr, DynamicValueType use_dynamic, uint32_t options, 49797206d57SZachary Turner VariableSP &var_sp, Status &error) { 4980eb31a1dSZachary Turner llvm::StringRef original_var_expr = var_expr; 49999618476SJason Molenda // We can't fetch variable information for a history stack frame. 5004b36f791SVedant Kumar if (IsHistorical()) 50199618476SJason Molenda return ValueObjectSP(); 50254979cddSGreg Clayton 5030eb31a1dSZachary Turner if (var_expr.empty()) { 5040eb31a1dSZachary Turner error.SetErrorStringWithFormat("invalid variable path '%s'", 5050eb31a1dSZachary Turner var_expr.str().c_str()); 50624bd3178SZachary Turner return ValueObjectSP(); 50724bd3178SZachary Turner } 50824bd3178SZachary Turner 509b9c1b51eSKate Stone const bool check_ptr_vs_member = 510b9c1b51eSKate Stone (options & eExpressionPathOptionCheckPtrVsMember) != 0; 511b9c1b51eSKate Stone const bool no_fragile_ivar = 512b9c1b51eSKate Stone (options & eExpressionPathOptionsNoFragileObjcIvar) != 0; 513b9c1b51eSKate Stone const bool no_synth_child = 514b9c1b51eSKate Stone (options & eExpressionPathOptionsNoSyntheticChildren) != 0; 515b9c1b51eSKate Stone // const bool no_synth_array = (options & 516b9c1b51eSKate Stone // eExpressionPathOptionsNoSyntheticArrayRange) != 0; 51754979cddSGreg Clayton error.Clear(); 5188b2fe6dcSGreg Clayton bool deref = false; 5198b2fe6dcSGreg Clayton bool address_of = false; 5208b2fe6dcSGreg Clayton ValueObjectSP valobj_sp; 5218b2fe6dcSGreg Clayton const bool get_file_globals = true; 522d41f032aSGreg Clayton // When looking up a variable for an expression, we need only consider the 523d41f032aSGreg Clayton // variables that are in scope. 524d41f032aSGreg Clayton VariableListSP var_list_sp(GetInScopeVariableList(get_file_globals)); 525d41f032aSGreg Clayton VariableList *variable_list = var_list_sp.get(); 5268b2fe6dcSGreg Clayton 52724bd3178SZachary Turner if (!variable_list) 52824bd3178SZachary Turner return ValueObjectSP(); 52924bd3178SZachary Turner 5308b2fe6dcSGreg Clayton // If first character is a '*', then show pointer contents 53124bd3178SZachary Turner std::string var_expr_storage; 532b9c1b51eSKate Stone if (var_expr[0] == '*') { 5338b2fe6dcSGreg Clayton deref = true; 53424bd3178SZachary Turner var_expr = var_expr.drop_front(); // Skip the '*' 535b9c1b51eSKate Stone } else if (var_expr[0] == '&') { 5368b2fe6dcSGreg Clayton address_of = true; 53724bd3178SZachary Turner var_expr = var_expr.drop_front(); // Skip the '&' 5388b2fe6dcSGreg Clayton } 5398b2fe6dcSGreg Clayton 54024bd3178SZachary Turner size_t separator_idx = var_expr.find_first_of(".-[=+~|&^%#@!/?,<>{}"); 54154979cddSGreg Clayton StreamString var_expr_path_strm; 5428b2fe6dcSGreg Clayton 54324bd3178SZachary Turner ConstString name_const_string(var_expr.substr(0, separator_idx)); 5448b2fe6dcSGreg Clayton 54510bc1a4eSPaul Herman var_sp = variable_list->FindVariable(name_const_string, false); 546685c88c5SGreg Clayton 547685c88c5SGreg Clayton bool synthetically_added_instance_object = false; 548685c88c5SGreg Clayton 549b9c1b51eSKate Stone if (var_sp) { 55024bd3178SZachary Turner var_expr = var_expr.drop_front(name_const_string.GetLength()); 551685c88c5SGreg Clayton } 55246252398SEnrico Granata 553b9c1b51eSKate Stone if (!var_sp && (options & eExpressionPathOptionsAllowDirectIVarAccess)) { 55405097246SAdrian Prantl // Check for direct ivars access which helps us with implicit access to 555e30c4938SDave Lee // ivars using "this" or "self". 556685c88c5SGreg Clayton GetSymbolContext(eSymbolContextFunction | eSymbolContextBlock); 557685c88c5SGreg Clayton lldb::LanguageType method_language = eLanguageTypeUnknown; 558685c88c5SGreg Clayton bool is_instance_method = false; 559685c88c5SGreg Clayton ConstString method_object_name; 560b9c1b51eSKate Stone if (m_sc.GetFunctionMethodInfo(method_language, is_instance_method, 561b9c1b51eSKate Stone method_object_name)) { 562b9c1b51eSKate Stone if (is_instance_method && method_object_name) { 563685c88c5SGreg Clayton var_sp = variable_list->FindVariable(method_object_name); 564b9c1b51eSKate Stone if (var_sp) { 565685c88c5SGreg Clayton separator_idx = 0; 566e30c4938SDave Lee if (Type *var_type = var_sp->GetType()) 567e30c4938SDave Lee if (auto compiler_type = var_type->GetForwardCompilerType()) 568e30c4938SDave Lee if (!compiler_type.IsPointerType()) 569e30c4938SDave Lee var_expr_storage = "."; 570e30c4938SDave Lee 571e30c4938SDave Lee if (var_expr_storage.empty()) 57224bd3178SZachary Turner var_expr_storage = "->"; 57324bd3178SZachary Turner var_expr_storage += var_expr; 57424bd3178SZachary Turner var_expr = var_expr_storage; 575685c88c5SGreg Clayton synthetically_added_instance_object = true; 576685c88c5SGreg Clayton } 577685c88c5SGreg Clayton } 578685c88c5SGreg Clayton } 579685c88c5SGreg Clayton } 580685c88c5SGreg Clayton 581b9c1b51eSKate Stone if (!var_sp && (options & eExpressionPathOptionsInspectAnonymousUnions)) { 582b9c1b51eSKate Stone // Check if any anonymous unions are there which contain a variable with 583b9c1b51eSKate Stone // the name we need 584d1782133SRaphael Isemann for (const VariableSP &variable_sp : *variable_list) { 58524bd3178SZachary Turner if (!variable_sp) 58624bd3178SZachary Turner continue; 58724bd3178SZachary Turner if (!variable_sp->GetName().IsEmpty()) 58824bd3178SZachary Turner continue; 58924bd3178SZachary Turner 59024bd3178SZachary Turner Type *var_type = variable_sp->GetType(); 59124bd3178SZachary Turner if (!var_type) 59224bd3178SZachary Turner continue; 59324bd3178SZachary Turner 59424bd3178SZachary Turner if (!var_type->GetForwardCompilerType().IsAnonymousType()) 59524bd3178SZachary Turner continue; 59624bd3178SZachary Turner valobj_sp = GetValueObjectForFrameVariable(variable_sp, use_dynamic); 59746252398SEnrico Granata if (!valobj_sp) 59846252398SEnrico Granata return valobj_sp; 59924bd3178SZachary Turner valobj_sp = valobj_sp->GetChildMemberWithName(name_const_string, true); 60046252398SEnrico Granata if (valobj_sp) 60146252398SEnrico Granata break; 60246252398SEnrico Granata } 60346252398SEnrico Granata } 60446252398SEnrico Granata 605b9c1b51eSKate Stone if (var_sp && !valobj_sp) { 6062837b766SJim Ingham valobj_sp = GetValueObjectForFrameVariable(var_sp, use_dynamic); 60778a685aaSJim Ingham if (!valobj_sp) 60878a685aaSJim Ingham return valobj_sp; 60946252398SEnrico Granata } 61024bd3178SZachary Turner if (!valobj_sp) { 61124bd3178SZachary Turner error.SetErrorStringWithFormat("no variable named '%s' found in this frame", 61224bd3178SZachary Turner name_const_string.GetCString()); 61324bd3178SZachary Turner return ValueObjectSP(); 61424bd3178SZachary Turner } 61524bd3178SZachary Turner 6168b2fe6dcSGreg Clayton // We are dumping at least one child 617cf5ed6dcSJaroslav Sevcik while (!var_expr.empty()) { 6188b2fe6dcSGreg Clayton // Calculate the next separator index ahead of time 6198b2fe6dcSGreg Clayton ValueObjectSP child_valobj_sp; 62024bd3178SZachary Turner const char separator_type = var_expr[0]; 6214c08fe28STamas Berghammer bool expr_is_ptr = false; 622b9c1b51eSKate Stone switch (separator_type) { 6238b2fe6dcSGreg Clayton case '-': 6244c08fe28STamas Berghammer expr_is_ptr = true; 62524bd3178SZachary Turner if (var_expr.size() >= 2 && var_expr[1] != '>') 6268b2fe6dcSGreg Clayton return ValueObjectSP(); 6278b2fe6dcSGreg Clayton 628b9c1b51eSKate Stone if (no_fragile_ivar) { 6296d5e68eaSGreg Clayton // Make sure we aren't trying to deref an objective 6306d5e68eaSGreg Clayton // C ivar if this is not allowed 631b9c1b51eSKate Stone const uint32_t pointer_type_flags = 632b9c1b51eSKate Stone valobj_sp->GetCompilerType().GetTypeInfo(nullptr); 633622be238SEnrico Granata if ((pointer_type_flags & eTypeIsObjC) && 634b9c1b51eSKate Stone (pointer_type_flags & eTypeIsPointer)) { 63505097246SAdrian Prantl // This was an objective C object pointer and it was requested we 63605097246SAdrian Prantl // skip any fragile ivars so return nothing here 6376d5e68eaSGreg Clayton return ValueObjectSP(); 6386d5e68eaSGreg Clayton } 6396d5e68eaSGreg Clayton } 6404c08fe28STamas Berghammer 6414c08fe28STamas Berghammer // If we have a non pointer type with a sythetic value then lets check if 6424c08fe28STamas Berghammer // we have an sythetic dereference specified. 6434c08fe28STamas Berghammer if (!valobj_sp->IsPointerType() && valobj_sp->HasSyntheticValue()) { 64497206d57SZachary Turner Status deref_error; 6454c08fe28STamas Berghammer if (valobj_sp->GetCompilerType().IsReferenceType()) { 6464c08fe28STamas Berghammer valobj_sp = valobj_sp->GetSyntheticValue()->Dereference(deref_error); 6474c08fe28STamas Berghammer if (error.Fail()) { 6484c08fe28STamas Berghammer error.SetErrorStringWithFormatv( 6494c08fe28STamas Berghammer "Failed to dereference reference type: %s", deref_error); 6504c08fe28STamas Berghammer return ValueObjectSP(); 6514c08fe28STamas Berghammer } 6524c08fe28STamas Berghammer } 6534c08fe28STamas Berghammer 6544c08fe28STamas Berghammer valobj_sp = valobj_sp->Dereference(deref_error); 6554c08fe28STamas Berghammer if (error.Fail()) { 6564c08fe28STamas Berghammer error.SetErrorStringWithFormatv( 6570d6f6812SGreg Clayton "Failed to dereference sythetic value: {0}", deref_error); 6580d6f6812SGreg Clayton return ValueObjectSP(); 6590d6f6812SGreg Clayton } 6600d6f6812SGreg Clayton // Some synthetic plug-ins fail to set the error in Dereference 6610d6f6812SGreg Clayton if (!valobj_sp) { 6620d6f6812SGreg Clayton error.SetErrorString("Failed to dereference sythetic value"); 6634c08fe28STamas Berghammer return ValueObjectSP(); 6644c08fe28STamas Berghammer } 6654c08fe28STamas Berghammer expr_is_ptr = false; 6664c08fe28STamas Berghammer } 6674c08fe28STamas Berghammer 66824bd3178SZachary Turner var_expr = var_expr.drop_front(); // Remove the '-' 66962e0681aSJason Molenda LLVM_FALLTHROUGH; 670b9c1b51eSKate Stone case '.': { 67124bd3178SZachary Turner var_expr = var_expr.drop_front(); // Remove the '.' or '>' 67224bd3178SZachary Turner separator_idx = var_expr.find_first_of(".-["); 67324bd3178SZachary Turner ConstString child_name(var_expr.substr(0, var_expr.find_first_of(".-["))); 6748b2fe6dcSGreg Clayton 675b9c1b51eSKate Stone if (check_ptr_vs_member) { 67605097246SAdrian Prantl // We either have a pointer type and need to verify valobj_sp is a 67705097246SAdrian Prantl // pointer, or we have a member of a class/union/struct being accessed 67805097246SAdrian Prantl // with the . syntax and need to verify we don't have a pointer. 67954979cddSGreg Clayton const bool actual_is_ptr = valobj_sp->IsPointerType(); 68054979cddSGreg Clayton 681b9c1b51eSKate Stone if (actual_is_ptr != expr_is_ptr) { 68205097246SAdrian Prantl // Incorrect use of "." with a pointer, or "->" with a 68305097246SAdrian Prantl // class/union/struct instance or reference. 6843014efe0SAlex Langford valobj_sp->GetExpressionPath(var_expr_path_strm); 68554979cddSGreg Clayton if (actual_is_ptr) 686b9c1b51eSKate Stone error.SetErrorStringWithFormat( 687b9c1b51eSKate Stone "\"%s\" is a pointer and . was used to attempt to access " 688b9c1b51eSKate Stone "\"%s\". Did you mean \"%s->%s\"?", 689c156427dSZachary Turner var_expr_path_strm.GetData(), child_name.GetCString(), 69024bd3178SZachary Turner var_expr_path_strm.GetData(), var_expr.str().c_str()); 69154979cddSGreg Clayton else 692b9c1b51eSKate Stone error.SetErrorStringWithFormat( 693b9c1b51eSKate Stone "\"%s\" is not a pointer and -> was used to attempt to " 694b9c1b51eSKate Stone "access \"%s\". Did you mean \"%s.%s\"?", 695c156427dSZachary Turner var_expr_path_strm.GetData(), child_name.GetCString(), 69624bd3178SZachary Turner var_expr_path_strm.GetData(), var_expr.str().c_str()); 69754979cddSGreg Clayton return ValueObjectSP(); 69854979cddSGreg Clayton } 69954979cddSGreg Clayton } 70024bd3178SZachary Turner child_valobj_sp = valobj_sp->GetChildMemberWithName(child_name, true); 701b9c1b51eSKate Stone if (!child_valobj_sp) { 702b9c1b51eSKate Stone if (!no_synth_child) { 70386cc9829SEnrico Granata child_valobj_sp = valobj_sp->GetSyntheticValue(); 70486cc9829SEnrico Granata if (child_valobj_sp) 705b9c1b51eSKate Stone child_valobj_sp = 706b9c1b51eSKate Stone child_valobj_sp->GetChildMemberWithName(child_name, true); 70786cc9829SEnrico Granata } 7088c9d3560SEnrico Granata 709b9c1b51eSKate Stone if (no_synth_child || !child_valobj_sp) { 7108b2fe6dcSGreg Clayton // No child member with name "child_name" 711b9c1b51eSKate Stone if (synthetically_added_instance_object) { 712b9c1b51eSKate Stone // We added a "this->" or "self->" to the beginning of the 71305097246SAdrian Prantl // expression and this is the first pointer ivar access, so just 71405097246SAdrian Prantl // return the normal error 715b9c1b51eSKate Stone error.SetErrorStringWithFormat( 716b9c1b51eSKate Stone "no variable or instance variable named '%s' found in " 717b9c1b51eSKate Stone "this frame", 718685c88c5SGreg Clayton name_const_string.GetCString()); 719b9c1b51eSKate Stone } else { 7203014efe0SAlex Langford valobj_sp->GetExpressionPath(var_expr_path_strm); 721b9c1b51eSKate Stone if (child_name) { 722b9c1b51eSKate Stone error.SetErrorStringWithFormat( 723b9c1b51eSKate Stone "\"%s\" is not a member of \"(%s) %s\"", 72454979cddSGreg Clayton child_name.GetCString(), 72554979cddSGreg Clayton valobj_sp->GetTypeName().AsCString("<invalid type>"), 726c156427dSZachary Turner var_expr_path_strm.GetData()); 727b9c1b51eSKate Stone } else { 728b9c1b51eSKate Stone error.SetErrorStringWithFormat( 729b9c1b51eSKate Stone "incomplete expression path after \"%s\" in \"%s\"", 7300eb31a1dSZachary Turner var_expr_path_strm.GetData(), 7310eb31a1dSZachary Turner original_var_expr.str().c_str()); 73254979cddSGreg Clayton } 733685c88c5SGreg Clayton } 7348b2fe6dcSGreg Clayton return ValueObjectSP(); 7358b2fe6dcSGreg Clayton } 7368c9d3560SEnrico Granata } 737685c88c5SGreg Clayton synthetically_added_instance_object = false; 7388b2fe6dcSGreg Clayton // Remove the child name from the path 73924bd3178SZachary Turner var_expr = var_expr.drop_front(child_name.GetLength()); 740b9c1b51eSKate Stone if (use_dynamic != eNoDynamicValues) { 741b9c1b51eSKate Stone ValueObjectSP dynamic_value_sp( 742b9c1b51eSKate Stone child_valobj_sp->GetDynamicValue(use_dynamic)); 74378a685aaSJim Ingham if (dynamic_value_sp) 74478a685aaSJim Ingham child_valobj_sp = dynamic_value_sp; 74578a685aaSJim Ingham } 746b9c1b51eSKate Stone } break; 7478b2fe6dcSGreg Clayton 74824bd3178SZachary Turner case '[': { 74905097246SAdrian Prantl // Array member access, or treating pointer as an array Need at least two 75005097246SAdrian Prantl // brackets and a number 75124bd3178SZachary Turner if (var_expr.size() <= 2) { 75224bd3178SZachary Turner error.SetErrorStringWithFormat( 75324bd3178SZachary Turner "invalid square bracket encountered after \"%s\" in \"%s\"", 75424bd3178SZachary Turner var_expr_path_strm.GetData(), var_expr.str().c_str()); 75524bd3178SZachary Turner return ValueObjectSP(); 75624bd3178SZachary Turner } 75724bd3178SZachary Turner 75824bd3178SZachary Turner // Drop the open brace. 75924bd3178SZachary Turner var_expr = var_expr.drop_front(); 76024bd3178SZachary Turner long child_index = 0; 76124bd3178SZachary Turner 76224bd3178SZachary Turner // If there's no closing brace, this is an invalid expression. 76324bd3178SZachary Turner size_t end_pos = var_expr.find_first_of(']'); 76424bd3178SZachary Turner if (end_pos == llvm::StringRef::npos) { 76524bd3178SZachary Turner error.SetErrorStringWithFormat( 76624bd3178SZachary Turner "missing closing square bracket in expression \"%s\"", 76724bd3178SZachary Turner var_expr_path_strm.GetData()); 76824bd3178SZachary Turner return ValueObjectSP(); 76924bd3178SZachary Turner } 77024bd3178SZachary Turner llvm::StringRef index_expr = var_expr.take_front(end_pos); 77124bd3178SZachary Turner llvm::StringRef original_index_expr = index_expr; 77224bd3178SZachary Turner // Drop all of "[index_expr]" 77324bd3178SZachary Turner var_expr = var_expr.drop_front(end_pos + 1); 77424bd3178SZachary Turner 77524bd3178SZachary Turner if (index_expr.consumeInteger(0, child_index)) { 77624bd3178SZachary Turner // If there was no integer anywhere in the index expression, this is 77724bd3178SZachary Turner // erroneous expression. 77824bd3178SZachary Turner error.SetErrorStringWithFormat("invalid index expression \"%s\"", 77924bd3178SZachary Turner index_expr.str().c_str()); 78024bd3178SZachary Turner return ValueObjectSP(); 78124bd3178SZachary Turner } 78224bd3178SZachary Turner 78324bd3178SZachary Turner if (index_expr.empty()) { 78424bd3178SZachary Turner // The entire index expression was a single integer. 78524bd3178SZachary Turner 78624bd3178SZachary Turner if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) { 78724bd3178SZachary Turner // what we have is *ptr[low]. the most similar C++ syntax is to deref 78824bd3178SZachary Turner // ptr and extract bit low out of it. reading array item low would be 78924bd3178SZachary Turner // done by saying ptr[low], without a deref * sign 79097206d57SZachary Turner Status error; 7919fc1944eSEnrico Granata ValueObjectSP temp(valobj_sp->Dereference(error)); 792b9c1b51eSKate Stone if (error.Fail()) { 7933014efe0SAlex Langford valobj_sp->GetExpressionPath(var_expr_path_strm); 794b9c1b51eSKate Stone error.SetErrorStringWithFormat( 795b9c1b51eSKate Stone "could not dereference \"(%s) %s\"", 7969fc1944eSEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 797c156427dSZachary Turner var_expr_path_strm.GetData()); 7989fc1944eSEnrico Granata return ValueObjectSP(); 7999fc1944eSEnrico Granata } 8009fc1944eSEnrico Granata valobj_sp = temp; 8019fc1944eSEnrico Granata deref = false; 802b9c1b51eSKate Stone } else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() && 803b9c1b51eSKate Stone deref) { 80405097246SAdrian Prantl // what we have is *arr[low]. the most similar C++ syntax is to get 80505097246SAdrian Prantl // arr[0] (an operation that is equivalent to deref-ing arr) and 80605097246SAdrian Prantl // extract bit low out of it. reading array item low would be done by 80705097246SAdrian Prantl // saying arr[low], without a deref * sign 80897206d57SZachary Turner Status error; 8099fc1944eSEnrico Granata ValueObjectSP temp(valobj_sp->GetChildAtIndex(0, true)); 810b9c1b51eSKate Stone if (error.Fail()) { 8113014efe0SAlex Langford valobj_sp->GetExpressionPath(var_expr_path_strm); 812b9c1b51eSKate Stone error.SetErrorStringWithFormat( 813b9c1b51eSKate Stone "could not get item 0 for \"(%s) %s\"", 8149fc1944eSEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 815c156427dSZachary Turner var_expr_path_strm.GetData()); 8169fc1944eSEnrico Granata return ValueObjectSP(); 8179fc1944eSEnrico Granata } 8189fc1944eSEnrico Granata valobj_sp = temp; 8199fc1944eSEnrico Granata deref = false; 8209fc1944eSEnrico Granata } 8218b2fe6dcSGreg Clayton 8224ef877f5SGreg Clayton bool is_incomplete_array = false; 823b9c1b51eSKate Stone if (valobj_sp->IsPointerType()) { 824226b70c1SSean Callanan bool is_objc_pointer = true; 825226b70c1SSean Callanan 826b9c1b51eSKate Stone if (valobj_sp->GetCompilerType().GetMinimumLanguage() != 827b9c1b51eSKate Stone eLanguageTypeObjC) 828226b70c1SSean Callanan is_objc_pointer = false; 82999558cc4SGreg Clayton else if (!valobj_sp->GetCompilerType().IsPointerType()) 830226b70c1SSean Callanan is_objc_pointer = false; 831226b70c1SSean Callanan 832b9c1b51eSKate Stone if (no_synth_child && is_objc_pointer) { 833b9c1b51eSKate Stone error.SetErrorStringWithFormat( 834b9c1b51eSKate Stone "\"(%s) %s\" is an Objective-C pointer, and cannot be " 835b9c1b51eSKate Stone "subscripted", 836226b70c1SSean Callanan valobj_sp->GetTypeName().AsCString("<invalid type>"), 837c156427dSZachary Turner var_expr_path_strm.GetData()); 838226b70c1SSean Callanan 839226b70c1SSean Callanan return ValueObjectSP(); 840b9c1b51eSKate Stone } else if (is_objc_pointer) { 84105097246SAdrian Prantl // dereferencing ObjC variables is not valid.. so let's try and 84205097246SAdrian Prantl // recur to synthetic children 84386cc9829SEnrico Granata ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(); 844d70a6e71SEugene Zelenko if (!synthetic /* no synthetic */ 845b9c1b51eSKate Stone || synthetic == valobj_sp) /* synthetic is the same as 846b9c1b51eSKate Stone the original object */ 84727b625e1SEnrico Granata { 8483014efe0SAlex Langford valobj_sp->GetExpressionPath(var_expr_path_strm); 849b9c1b51eSKate Stone error.SetErrorStringWithFormat( 850b9c1b51eSKate Stone "\"(%s) %s\" is not an array type", 85127b625e1SEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 852c156427dSZachary Turner var_expr_path_strm.GetData()); 853b9c1b51eSKate Stone } else if ( 854b9c1b51eSKate Stone static_cast<uint32_t>(child_index) >= 855b9c1b51eSKate Stone synthetic 856b9c1b51eSKate Stone ->GetNumChildren() /* synthetic does not have that many values */) { 8573014efe0SAlex Langford valobj_sp->GetExpressionPath(var_expr_path_strm); 858b9c1b51eSKate Stone error.SetErrorStringWithFormat( 85924bd3178SZachary Turner "array index %ld is not valid for \"(%s) %s\"", child_index, 86027b625e1SEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 861c156427dSZachary Turner var_expr_path_strm.GetData()); 862b9c1b51eSKate Stone } else { 86324bd3178SZachary Turner child_valobj_sp = synthetic->GetChildAtIndex(child_index, true); 864b9c1b51eSKate Stone if (!child_valobj_sp) { 8653014efe0SAlex Langford valobj_sp->GetExpressionPath(var_expr_path_strm); 866b9c1b51eSKate Stone error.SetErrorStringWithFormat( 86724bd3178SZachary Turner "array index %ld is not valid for \"(%s) %s\"", child_index, 86824bd3178SZachary Turner valobj_sp->GetTypeName().AsCString("<invalid type>"), 869c156427dSZachary Turner var_expr_path_strm.GetData()); 870b9c1b51eSKate Stone } 871b9c1b51eSKate Stone } 872b9c1b51eSKate Stone } else { 873b9c1b51eSKate Stone child_valobj_sp = 874b9c1b51eSKate Stone valobj_sp->GetSyntheticArrayMember(child_index, true); 875b9c1b51eSKate Stone if (!child_valobj_sp) { 8763014efe0SAlex Langford valobj_sp->GetExpressionPath(var_expr_path_strm); 877b9c1b51eSKate Stone error.SetErrorStringWithFormat( 878b9c1b51eSKate Stone "failed to use pointer as array for index %ld for " 879b9c1b51eSKate Stone "\"(%s) %s\"", 88027b625e1SEnrico Granata child_index, 88127b625e1SEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 882c156427dSZachary Turner var_expr_path_strm.GetData()); 88327b625e1SEnrico Granata } 88427b625e1SEnrico Granata } 885b9c1b51eSKate Stone } else if (valobj_sp->GetCompilerType().IsArrayType( 886b9c1b51eSKate Stone nullptr, nullptr, &is_incomplete_array)) { 88705097246SAdrian Prantl // Pass false to dynamic_value here so we can tell the difference 88805097246SAdrian Prantl // between no dynamic value and no member of this type... 88924bd3178SZachary Turner child_valobj_sp = valobj_sp->GetChildAtIndex(child_index, true); 89024bd3178SZachary Turner if (!child_valobj_sp && (is_incomplete_array || !no_synth_child)) 891b9c1b51eSKate Stone child_valobj_sp = 892b9c1b51eSKate Stone valobj_sp->GetSyntheticArrayMember(child_index, true); 8934ef877f5SGreg Clayton 894b9c1b51eSKate Stone if (!child_valobj_sp) { 8953014efe0SAlex Langford valobj_sp->GetExpressionPath(var_expr_path_strm); 896b9c1b51eSKate Stone error.SetErrorStringWithFormat( 89724bd3178SZachary Turner "array index %ld is not valid for \"(%s) %s\"", child_index, 89854979cddSGreg Clayton valobj_sp->GetTypeName().AsCString("<invalid type>"), 899c156427dSZachary Turner var_expr_path_strm.GetData()); 90054979cddSGreg Clayton } 901b9c1b51eSKate Stone } else if (valobj_sp->GetCompilerType().IsScalarType()) { 9029fc1944eSEnrico Granata // this is a bitfield asking to display just one bit 903b9c1b51eSKate Stone child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild( 904b9c1b51eSKate Stone child_index, child_index, true); 905b9c1b51eSKate Stone if (!child_valobj_sp) { 9063014efe0SAlex Langford valobj_sp->GetExpressionPath(var_expr_path_strm); 907b9c1b51eSKate Stone error.SetErrorStringWithFormat( 908b9c1b51eSKate Stone "bitfield range %ld-%ld is not valid for \"(%s) %s\"", 9099fc1944eSEnrico Granata child_index, child_index, 9109fc1944eSEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 911c156427dSZachary Turner var_expr_path_strm.GetData()); 9129fc1944eSEnrico Granata } 913b9c1b51eSKate Stone } else { 91486cc9829SEnrico Granata ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(); 91527b625e1SEnrico Granata if (no_synth_child /* synthetic is forbidden */ || 916d70a6e71SEugene Zelenko !synthetic /* no synthetic */ 9170b4c26b2SJason Molenda || synthetic == valobj_sp) /* synthetic is the same as the 918b9c1b51eSKate Stone original object */ 91927b625e1SEnrico Granata { 9203014efe0SAlex Langford valobj_sp->GetExpressionPath(var_expr_path_strm); 921b9c1b51eSKate Stone error.SetErrorStringWithFormat( 922b9c1b51eSKate Stone "\"(%s) %s\" is not an array type", 92354979cddSGreg Clayton valobj_sp->GetTypeName().AsCString("<invalid type>"), 924c156427dSZachary Turner var_expr_path_strm.GetData()); 925b9c1b51eSKate Stone } else if ( 926b9c1b51eSKate Stone static_cast<uint32_t>(child_index) >= 927b9c1b51eSKate Stone synthetic 928b9c1b51eSKate Stone ->GetNumChildren() /* synthetic does not have that many values */) { 9293014efe0SAlex Langford valobj_sp->GetExpressionPath(var_expr_path_strm); 930b9c1b51eSKate Stone error.SetErrorStringWithFormat( 93124bd3178SZachary Turner "array index %ld is not valid for \"(%s) %s\"", child_index, 93227b625e1SEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 933c156427dSZachary Turner var_expr_path_strm.GetData()); 934b9c1b51eSKate Stone } else { 93524bd3178SZachary Turner child_valobj_sp = synthetic->GetChildAtIndex(child_index, true); 936b9c1b51eSKate Stone if (!child_valobj_sp) { 9373014efe0SAlex Langford valobj_sp->GetExpressionPath(var_expr_path_strm); 938b9c1b51eSKate Stone error.SetErrorStringWithFormat( 93924bd3178SZachary Turner "array index %ld is not valid for \"(%s) %s\"", child_index, 94027b625e1SEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 941c156427dSZachary Turner var_expr_path_strm.GetData()); 94227b625e1SEnrico Granata } 94327b625e1SEnrico Granata } 94427b625e1SEnrico Granata } 9458b2fe6dcSGreg Clayton 946b9c1b51eSKate Stone if (!child_valobj_sp) { 9478b2fe6dcSGreg Clayton // Invalid array index... 9488b2fe6dcSGreg Clayton return ValueObjectSP(); 9498b2fe6dcSGreg Clayton } 9508b2fe6dcSGreg Clayton 951b9c1b51eSKate Stone if (use_dynamic != eNoDynamicValues) { 952b9c1b51eSKate Stone ValueObjectSP dynamic_value_sp( 953b9c1b51eSKate Stone child_valobj_sp->GetDynamicValue(use_dynamic)); 95478a685aaSJim Ingham if (dynamic_value_sp) 95578a685aaSJim Ingham child_valobj_sp = dynamic_value_sp; 95678a685aaSJim Ingham } 95724bd3178SZachary Turner // Break out early from the switch since we were able to find the child 95824bd3178SZachary Turner // member 9598b2fe6dcSGreg Clayton break; 96024bd3178SZachary Turner } 96124bd3178SZachary Turner 9629fc1944eSEnrico Granata // this is most probably a BitField, let's take a look 96324bd3178SZachary Turner if (index_expr.front() != '-') { 96424bd3178SZachary Turner error.SetErrorStringWithFormat("invalid range expression \"'%s'\"", 96524bd3178SZachary Turner original_index_expr.str().c_str()); 96624bd3178SZachary Turner return ValueObjectSP(); 96724bd3178SZachary Turner } 96824bd3178SZachary Turner 9697edc3a6eSZachary Turner index_expr = index_expr.drop_front(); 97024bd3178SZachary Turner long final_index = 0; 97124bd3178SZachary Turner if (index_expr.getAsInteger(0, final_index)) { 97224bd3178SZachary Turner error.SetErrorStringWithFormat("invalid range expression \"'%s'\"", 97324bd3178SZachary Turner original_index_expr.str().c_str()); 97424bd3178SZachary Turner return ValueObjectSP(); 97524bd3178SZachary Turner } 97624bd3178SZachary Turner 9779fc1944eSEnrico Granata // if the format given is [high-low], swap range 978b9c1b51eSKate Stone if (child_index > final_index) { 9799fc1944eSEnrico Granata long temp = child_index; 9809fc1944eSEnrico Granata child_index = final_index; 9819fc1944eSEnrico Granata final_index = temp; 9829fc1944eSEnrico Granata } 9839fc1944eSEnrico Granata 98424bd3178SZachary Turner if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) { 98524bd3178SZachary Turner // what we have is *ptr[low-high]. the most similar C++ syntax is to 98624bd3178SZachary Turner // deref ptr and extract bits low thru high out of it. reading array 98705097246SAdrian Prantl // items low thru high would be done by saying ptr[low-high], without a 98805097246SAdrian Prantl // deref * sign 98997206d57SZachary Turner Status error; 9909fc1944eSEnrico Granata ValueObjectSP temp(valobj_sp->Dereference(error)); 991b9c1b51eSKate Stone if (error.Fail()) { 9923014efe0SAlex Langford valobj_sp->GetExpressionPath(var_expr_path_strm); 993b9c1b51eSKate Stone error.SetErrorStringWithFormat( 994b9c1b51eSKate Stone "could not dereference \"(%s) %s\"", 9959fc1944eSEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 996c156427dSZachary Turner var_expr_path_strm.GetData()); 9979fc1944eSEnrico Granata return ValueObjectSP(); 9989fc1944eSEnrico Granata } 9999fc1944eSEnrico Granata valobj_sp = temp; 10009fc1944eSEnrico Granata deref = false; 100124bd3178SZachary Turner } else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() && deref) { 100205097246SAdrian Prantl // what we have is *arr[low-high]. the most similar C++ syntax is to 100305097246SAdrian Prantl // get arr[0] (an operation that is equivalent to deref-ing arr) and 100405097246SAdrian Prantl // extract bits low thru high out of it. reading array items low thru 100505097246SAdrian Prantl // high would be done by saying arr[low-high], without a deref * sign 100697206d57SZachary Turner Status error; 10079fc1944eSEnrico Granata ValueObjectSP temp(valobj_sp->GetChildAtIndex(0, true)); 1008b9c1b51eSKate Stone if (error.Fail()) { 10093014efe0SAlex Langford valobj_sp->GetExpressionPath(var_expr_path_strm); 1010b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1011b9c1b51eSKate Stone "could not get item 0 for \"(%s) %s\"", 10129fc1944eSEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 1013c156427dSZachary Turner var_expr_path_strm.GetData()); 10149fc1944eSEnrico Granata return ValueObjectSP(); 10159fc1944eSEnrico Granata } 10169fc1944eSEnrico Granata valobj_sp = temp; 10179fc1944eSEnrico Granata deref = false; 10189fc1944eSEnrico Granata } 10199fc1944eSEnrico Granata 102024bd3178SZachary Turner child_valobj_sp = 102124bd3178SZachary Turner valobj_sp->GetSyntheticBitFieldChild(child_index, final_index, true); 1022b9c1b51eSKate Stone if (!child_valobj_sp) { 10233014efe0SAlex Langford valobj_sp->GetExpressionPath(var_expr_path_strm); 1024b9c1b51eSKate Stone error.SetErrorStringWithFormat( 102524bd3178SZachary Turner "bitfield range %ld-%ld is not valid for \"(%s) %s\"", child_index, 102624bd3178SZachary Turner final_index, valobj_sp->GetTypeName().AsCString("<invalid type>"), 1027c156427dSZachary Turner var_expr_path_strm.GetData()); 10289fc1944eSEnrico Granata } 10299fc1944eSEnrico Granata 1030b9c1b51eSKate Stone if (!child_valobj_sp) { 10319fc1944eSEnrico Granata // Invalid bitfield range... 10329fc1944eSEnrico Granata return ValueObjectSP(); 10339fc1944eSEnrico Granata } 10349fc1944eSEnrico Granata 1035b9c1b51eSKate Stone if (use_dynamic != eNoDynamicValues) { 1036b9c1b51eSKate Stone ValueObjectSP dynamic_value_sp( 1037b9c1b51eSKate Stone child_valobj_sp->GetDynamicValue(use_dynamic)); 10389fc1944eSEnrico Granata if (dynamic_value_sp) 10399fc1944eSEnrico Granata child_valobj_sp = dynamic_value_sp; 10409fc1944eSEnrico Granata } 104124bd3178SZachary Turner // Break out early from the switch since we were able to find the child 104224bd3178SZachary Turner // member 10439fc1944eSEnrico Granata break; 10449fc1944eSEnrico Granata } 10458b2fe6dcSGreg Clayton default: 10468b2fe6dcSGreg Clayton // Failure... 104754979cddSGreg Clayton { 10483014efe0SAlex Langford valobj_sp->GetExpressionPath(var_expr_path_strm); 1049b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1050b9c1b51eSKate Stone "unexpected char '%c' encountered after \"%s\" in \"%s\"", 1051c156427dSZachary Turner separator_type, var_expr_path_strm.GetData(), 105224bd3178SZachary Turner var_expr.str().c_str()); 105354979cddSGreg Clayton 10548b2fe6dcSGreg Clayton return ValueObjectSP(); 10558b2fe6dcSGreg Clayton } 105654979cddSGreg Clayton } 10578b2fe6dcSGreg Clayton 10588b2fe6dcSGreg Clayton if (child_valobj_sp) 10598b2fe6dcSGreg Clayton valobj_sp = child_valobj_sp; 10608b2fe6dcSGreg Clayton } 1061b9c1b51eSKate Stone if (valobj_sp) { 1062b9c1b51eSKate Stone if (deref) { 1063af67cecdSGreg Clayton ValueObjectSP deref_valobj_sp(valobj_sp->Dereference(error)); 10648b2fe6dcSGreg Clayton valobj_sp = deref_valobj_sp; 1065b9c1b51eSKate Stone } else if (address_of) { 106654979cddSGreg Clayton ValueObjectSP address_of_valobj_sp(valobj_sp->AddressOf(error)); 10678b2fe6dcSGreg Clayton valobj_sp = address_of_valobj_sp; 10688b2fe6dcSGreg Clayton } 10698b2fe6dcSGreg Clayton } 10708b2fe6dcSGreg Clayton return valobj_sp; 10718b2fe6dcSGreg Clayton } 107230fdc8d8SChris Lattner 107397206d57SZachary Turner bool StackFrame::GetFrameBaseValue(Scalar &frame_base, Status *error_ptr) { 1074bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 1075b9c1b51eSKate Stone if (!m_cfa_is_valid) { 1076b9c1b51eSKate Stone m_frame_base_error.SetErrorString( 1077b9c1b51eSKate Stone "No frame base available for this historical stack frame."); 107899618476SJason Molenda return false; 107999618476SJason Molenda } 108099618476SJason Molenda 1081b9c1b51eSKate Stone if (m_flags.IsClear(GOT_FRAME_BASE)) { 1082b9c1b51eSKate Stone if (m_sc.function) { 108330fdc8d8SChris Lattner m_frame_base.Clear(); 108430fdc8d8SChris Lattner m_frame_base_error.Clear(); 108530fdc8d8SChris Lattner 108630fdc8d8SChris Lattner m_flags.Set(GOT_FRAME_BASE); 1087d9e416c0SGreg Clayton ExecutionContext exe_ctx(shared_from_this()); 108830fdc8d8SChris Lattner Value expr_value; 1089*e4c5bca5SJonas Devlieghere addr_t loclist_base_addr = LLDB_INVALID_ADDRESS; 1090*e4c5bca5SJonas Devlieghere if (m_sc.function->GetFrameBaseExpression().IsLocationList()) 1091*e4c5bca5SJonas Devlieghere loclist_base_addr = 1092*e4c5bca5SJonas Devlieghere m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress( 1093*e4c5bca5SJonas Devlieghere exe_ctx.GetTargetPtr()); 1094*e4c5bca5SJonas Devlieghere 1095a6682a41SJonas Devlieghere if (!m_sc.function->GetFrameBaseExpression().Evaluate( 1096*e4c5bca5SJonas Devlieghere &exe_ctx, nullptr, loclist_base_addr, nullptr, nullptr, 1097*e4c5bca5SJonas Devlieghere expr_value, &m_frame_base_error)) { 109805097246SAdrian Prantl // We should really have an error if evaluate returns, but in case we 109905097246SAdrian Prantl // don't, lets set the error to something at least. 110030fdc8d8SChris Lattner if (m_frame_base_error.Success()) 1101b9c1b51eSKate Stone m_frame_base_error.SetErrorString( 1102b9c1b51eSKate Stone "Evaluation of the frame base expression failed."); 1103b9c1b51eSKate Stone } else { 110457ee3067SGreg Clayton m_frame_base = expr_value.ResolveValue(&exe_ctx); 110530fdc8d8SChris Lattner } 1106b9c1b51eSKate Stone } else { 110730fdc8d8SChris Lattner m_frame_base_error.SetErrorString("No function in symbol context."); 110830fdc8d8SChris Lattner } 110930fdc8d8SChris Lattner } 111030fdc8d8SChris Lattner 111130fdc8d8SChris Lattner if (m_frame_base_error.Success()) 111230fdc8d8SChris Lattner frame_base = m_frame_base; 111330fdc8d8SChris Lattner 111430fdc8d8SChris Lattner if (error_ptr) 111530fdc8d8SChris Lattner *error_ptr = m_frame_base_error; 111630fdc8d8SChris Lattner return m_frame_base_error.Success(); 111730fdc8d8SChris Lattner } 111830fdc8d8SChris Lattner 1119*e4c5bca5SJonas Devlieghere DWARFExpression *StackFrame::GetFrameBaseExpression(Status *error_ptr) { 1120b9c1b51eSKate Stone if (!m_sc.function) { 1121b9c1b51eSKate Stone if (error_ptr) { 11224740a734SSean Callanan error_ptr->SetErrorString("No function in symbol context."); 11234740a734SSean Callanan } 11244740a734SSean Callanan return nullptr; 11254740a734SSean Callanan } 11264740a734SSean Callanan 11274740a734SSean Callanan return &m_sc.function->GetFrameBaseExpression(); 11284740a734SSean Callanan } 11294740a734SSean Callanan 1130b9c1b51eSKate Stone RegisterContextSP StackFrame::GetRegisterContext() { 1131bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 1132b9c1b51eSKate Stone if (!m_reg_context_sp) { 1133d9e416c0SGreg Clayton ThreadSP thread_sp(GetThread()); 1134d9e416c0SGreg Clayton if (thread_sp) 1135d9e416c0SGreg Clayton m_reg_context_sp = thread_sp->CreateRegisterContextForFrame(this); 1136d9e416c0SGreg Clayton } 11375ccbd294SGreg Clayton return m_reg_context_sp; 113830fdc8d8SChris Lattner } 113930fdc8d8SChris Lattner 1140b9c1b51eSKate Stone bool StackFrame::HasDebugInformation() { 114130fdc8d8SChris Lattner GetSymbolContext(eSymbolContextLineEntry); 114230fdc8d8SChris Lattner return m_sc.line_entry.IsValid(); 114330fdc8d8SChris Lattner } 114430fdc8d8SChris Lattner 1145288bdf9cSGreg Clayton ValueObjectSP 1146b9c1b51eSKate Stone StackFrame::GetValueObjectForFrameVariable(const VariableSP &variable_sp, 1147b9c1b51eSKate Stone DynamicValueType use_dynamic) { 1148bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 1149288bdf9cSGreg Clayton ValueObjectSP valobj_sp; 11504b36f791SVedant Kumar if (IsHistorical()) { 115199618476SJason Molenda return valobj_sp; 115299618476SJason Molenda } 1153288bdf9cSGreg Clayton VariableList *var_list = GetVariableList(true); 1154b9c1b51eSKate Stone if (var_list) { 1155288bdf9cSGreg Clayton // Make sure the variable is a frame variable 1156288bdf9cSGreg Clayton const uint32_t var_idx = var_list->FindIndexForVariable(variable_sp.get()); 1157288bdf9cSGreg Clayton const uint32_t num_variables = var_list->GetSize(); 1158b9c1b51eSKate Stone if (var_idx < num_variables) { 1159288bdf9cSGreg Clayton valobj_sp = m_variable_list_value_objects.GetValueObjectAtIndex(var_idx); 1160b9c1b51eSKate Stone if (!valobj_sp) { 1161288bdf9cSGreg Clayton if (m_variable_list_value_objects.GetSize() < num_variables) 1162288bdf9cSGreg Clayton m_variable_list_value_objects.Resize(num_variables); 116358b59f95SJim Ingham valobj_sp = ValueObjectVariable::Create(this, variable_sp); 1164288bdf9cSGreg Clayton m_variable_list_value_objects.SetValueObjectAtIndex(var_idx, valobj_sp); 1165288bdf9cSGreg Clayton } 1166288bdf9cSGreg Clayton } 1167288bdf9cSGreg Clayton } 1168b9c1b51eSKate Stone if (use_dynamic != eNoDynamicValues && valobj_sp) { 11692837b766SJim Ingham ValueObjectSP dynamic_sp = valobj_sp->GetDynamicValue(use_dynamic); 117078a685aaSJim Ingham if (dynamic_sp) 117178a685aaSJim Ingham return dynamic_sp; 117278a685aaSJim Ingham } 1173288bdf9cSGreg Clayton return valobj_sp; 1174288bdf9cSGreg Clayton } 1175288bdf9cSGreg Clayton 1176b9c1b51eSKate Stone bool StackFrame::IsInlined() { 1177d70a6e71SEugene Zelenko if (m_sc.block == nullptr) 117859e8fc1cSGreg Clayton GetSymbolContext(eSymbolContextBlock); 117959e8fc1cSGreg Clayton if (m_sc.block) 1180d70a6e71SEugene Zelenko return m_sc.block->GetContainingInlinedBlock() != nullptr; 118159e8fc1cSGreg Clayton return false; 11826b8379c4SJim Ingham } 11836b8379c4SJim Ingham 11844b36f791SVedant Kumar bool StackFrame::IsHistorical() const { 11854b36f791SVedant Kumar return m_stack_frame_kind == StackFrame::Kind::History; 11864b36f791SVedant Kumar } 11874b36f791SVedant Kumar 11884b36f791SVedant Kumar bool StackFrame::IsArtificial() const { 11894b36f791SVedant Kumar return m_stack_frame_kind == StackFrame::Kind::Artificial; 11904b36f791SVedant Kumar } 11914b36f791SVedant Kumar 1192b9c1b51eSKate Stone lldb::LanguageType StackFrame::GetLanguage() { 1193009d110dSDawn Perchik CompileUnit *cu = GetSymbolContext(eSymbolContextCompUnit).comp_unit; 1194009d110dSDawn Perchik if (cu) 1195009d110dSDawn Perchik return cu->GetLanguage(); 1196009d110dSDawn Perchik return lldb::eLanguageTypeUnknown; 1197009d110dSDawn Perchik } 1198009d110dSDawn Perchik 1199b9c1b51eSKate Stone lldb::LanguageType StackFrame::GuessLanguage() { 1200592afe73SEnrico Granata LanguageType lang_type = GetLanguage(); 1201592afe73SEnrico Granata 1202b9c1b51eSKate Stone if (lang_type == eLanguageTypeUnknown) { 1203bdbdd229SJim Ingham SymbolContext sc = GetSymbolContext(eSymbolContextFunction 1204bdbdd229SJim Ingham | eSymbolContextSymbol); 1205bdbdd229SJim Ingham if (sc.function) { 1206bdbdd229SJim Ingham lang_type = sc.function->GetMangled().GuessLanguage(); 1207bdbdd229SJim Ingham } 1208bdbdd229SJim Ingham else if (sc.symbol) 1209bdbdd229SJim Ingham { 1210bdbdd229SJim Ingham lang_type = sc.symbol->GetMangled().GuessLanguage(); 1211592afe73SEnrico Granata } 1212592afe73SEnrico Granata } 1213592afe73SEnrico Granata 1214592afe73SEnrico Granata return lang_type; 1215592afe73SEnrico Granata } 1216592afe73SEnrico Granata 1217b9c1b51eSKate Stone namespace { 12184740a734SSean Callanan std::pair<const Instruction::Operand *, int64_t> 12194740a734SSean Callanan GetBaseExplainingValue(const Instruction::Operand &operand, 1220b9c1b51eSKate Stone RegisterContext ®ister_context, lldb::addr_t value) { 1221b9c1b51eSKate Stone switch (operand.m_type) { 12224740a734SSean Callanan case Instruction::Operand::Type::Dereference: 12234740a734SSean Callanan case Instruction::Operand::Type::Immediate: 12244740a734SSean Callanan case Instruction::Operand::Type::Invalid: 12254740a734SSean Callanan case Instruction::Operand::Type::Product: 12264740a734SSean Callanan // These are not currently interesting 12274740a734SSean Callanan return std::make_pair(nullptr, 0); 1228b9c1b51eSKate Stone case Instruction::Operand::Type::Sum: { 12294740a734SSean Callanan const Instruction::Operand *immediate_child = nullptr; 12304740a734SSean Callanan const Instruction::Operand *variable_child = nullptr; 1231b9c1b51eSKate Stone if (operand.m_children[0].m_type == Instruction::Operand::Type::Immediate) { 12324740a734SSean Callanan immediate_child = &operand.m_children[0]; 12334740a734SSean Callanan variable_child = &operand.m_children[1]; 1234b9c1b51eSKate Stone } else if (operand.m_children[1].m_type == 1235b9c1b51eSKate Stone Instruction::Operand::Type::Immediate) { 12364740a734SSean Callanan immediate_child = &operand.m_children[1]; 12374740a734SSean Callanan variable_child = &operand.m_children[0]; 12384740a734SSean Callanan } 1239b9c1b51eSKate Stone if (!immediate_child) { 12404740a734SSean Callanan return std::make_pair(nullptr, 0); 12414740a734SSean Callanan } 12424740a734SSean Callanan lldb::addr_t adjusted_value = value; 1243b9c1b51eSKate Stone if (immediate_child->m_negative) { 12444740a734SSean Callanan adjusted_value += immediate_child->m_immediate; 1245b9c1b51eSKate Stone } else { 12464740a734SSean Callanan adjusted_value -= immediate_child->m_immediate; 12474740a734SSean Callanan } 1248b9c1b51eSKate Stone std::pair<const Instruction::Operand *, int64_t> base_and_offset = 1249b9c1b51eSKate Stone GetBaseExplainingValue(*variable_child, register_context, 1250b9c1b51eSKate Stone adjusted_value); 1251b9c1b51eSKate Stone if (!base_and_offset.first) { 12524740a734SSean Callanan return std::make_pair(nullptr, 0); 12534740a734SSean Callanan } 1254b9c1b51eSKate Stone if (immediate_child->m_negative) { 12554740a734SSean Callanan base_and_offset.second -= immediate_child->m_immediate; 1256b9c1b51eSKate Stone } else { 12574740a734SSean Callanan base_and_offset.second += immediate_child->m_immediate; 12584740a734SSean Callanan } 12594740a734SSean Callanan return base_and_offset; 12604740a734SSean Callanan } 1261b9c1b51eSKate Stone case Instruction::Operand::Type::Register: { 1262b9c1b51eSKate Stone const RegisterInfo *info = 1263b9c1b51eSKate Stone register_context.GetRegisterInfoByName(operand.m_register.AsCString()); 1264b9c1b51eSKate Stone if (!info) { 12654740a734SSean Callanan return std::make_pair(nullptr, 0); 12664740a734SSean Callanan } 12674740a734SSean Callanan RegisterValue reg_value; 1268b9c1b51eSKate Stone if (!register_context.ReadRegister(info, reg_value)) { 12694740a734SSean Callanan return std::make_pair(nullptr, 0); 12704740a734SSean Callanan } 1271b9c1b51eSKate Stone if (reg_value.GetAsUInt64() == value) { 12724740a734SSean Callanan return std::make_pair(&operand, 0); 1273b9c1b51eSKate Stone } else { 12744740a734SSean Callanan return std::make_pair(nullptr, 0); 12754740a734SSean Callanan } 12764740a734SSean Callanan } 12774740a734SSean Callanan } 12785a8ad459SZachary Turner return std::make_pair(nullptr, 0); 12794740a734SSean Callanan } 12804740a734SSean Callanan 12814740a734SSean Callanan std::pair<const Instruction::Operand *, int64_t> 12824740a734SSean Callanan GetBaseExplainingDereference(const Instruction::Operand &operand, 12834740a734SSean Callanan RegisterContext ®ister_context, 1284b9c1b51eSKate Stone lldb::addr_t addr) { 1285b9c1b51eSKate Stone if (operand.m_type == Instruction::Operand::Type::Dereference) { 1286b9c1b51eSKate Stone return GetBaseExplainingValue(operand.m_children[0], register_context, 12874740a734SSean Callanan addr); 12884740a734SSean Callanan } 12894740a734SSean Callanan return std::make_pair(nullptr, 0); 12904740a734SSean Callanan } 12914f730dc7SIlia K } 12924740a734SSean Callanan 1293b9c1b51eSKate Stone lldb::ValueObjectSP StackFrame::GuessValueForAddress(lldb::addr_t addr) { 12944740a734SSean Callanan TargetSP target_sp = CalculateTarget(); 12954740a734SSean Callanan 12964740a734SSean Callanan const ArchSpec &target_arch = target_sp->GetArchitecture(); 12974740a734SSean Callanan 12984740a734SSean Callanan AddressRange pc_range; 12994740a734SSean Callanan pc_range.GetBaseAddress() = GetFrameCodeAddress(); 13004740a734SSean Callanan pc_range.SetByteSize(target_arch.GetMaximumOpcodeByteSize()); 13014740a734SSean Callanan 13024740a734SSean Callanan const char *plugin_name = nullptr; 13034740a734SSean Callanan const char *flavor = nullptr; 1304e9fe788dSJason Molenda const bool force_live_memory = true; 13054740a734SSean Callanan 130604592d5bSPavel Labath DisassemblerSP disassembler_sp = 130704592d5bSPavel Labath Disassembler::DisassembleRange(target_arch, plugin_name, flavor, 1308e9fe788dSJason Molenda *target_sp, pc_range, force_live_memory); 13094740a734SSean Callanan 131099d1e28aSJim Ingham if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) { 13114740a734SSean Callanan return ValueObjectSP(); 13124740a734SSean Callanan } 13134740a734SSean Callanan 1314b9c1b51eSKate Stone InstructionSP instruction_sp = 1315b9c1b51eSKate Stone disassembler_sp->GetInstructionList().GetInstructionAtIndex(0); 13164740a734SSean Callanan 13174740a734SSean Callanan llvm::SmallVector<Instruction::Operand, 3> operands; 13184740a734SSean Callanan 1319b9c1b51eSKate Stone if (!instruction_sp->ParseOperands(operands)) { 13204740a734SSean Callanan return ValueObjectSP(); 13214740a734SSean Callanan } 13224740a734SSean Callanan 13234740a734SSean Callanan RegisterContextSP register_context_sp = GetRegisterContext(); 13244740a734SSean Callanan 1325b9c1b51eSKate Stone if (!register_context_sp) { 13264740a734SSean Callanan return ValueObjectSP(); 13274740a734SSean Callanan } 13284740a734SSean Callanan 1329b9c1b51eSKate Stone for (const Instruction::Operand &operand : operands) { 1330b9c1b51eSKate Stone std::pair<const Instruction::Operand *, int64_t> base_and_offset = 1331b9c1b51eSKate Stone GetBaseExplainingDereference(operand, *register_context_sp, addr); 13324740a734SSean Callanan 1333b9c1b51eSKate Stone if (!base_and_offset.first) { 13344740a734SSean Callanan continue; 13354740a734SSean Callanan } 13364740a734SSean Callanan 1337b9c1b51eSKate Stone switch (base_and_offset.first->m_type) { 1338b9c1b51eSKate Stone case Instruction::Operand::Type::Immediate: { 13394740a734SSean Callanan lldb_private::Address addr; 1340b9c1b51eSKate Stone if (target_sp->ResolveLoadAddress(base_and_offset.first->m_immediate + 1341b9c1b51eSKate Stone base_and_offset.second, 1342b9c1b51eSKate Stone addr)) { 13430e252e38SAlex Langford auto c_type_system_or_err = 13440e252e38SAlex Langford target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeC); 13450e252e38SAlex Langford if (auto err = c_type_system_or_err.takeError()) { 1346a007a6d8SPavel Labath LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), std::move(err), 1347a007a6d8SPavel Labath "Unable to guess value for given address"); 13484740a734SSean Callanan return ValueObjectSP(); 1349b9c1b51eSKate Stone } else { 1350b9c1b51eSKate Stone CompilerType void_ptr_type = 13510e252e38SAlex Langford c_type_system_or_err 1352b9c1b51eSKate Stone ->GetBasicTypeFromAST(lldb::BasicType::eBasicTypeChar) 1353b9c1b51eSKate Stone .GetPointerType(); 13544740a734SSean Callanan return ValueObjectMemory::Create(this, "", addr, void_ptr_type); 13554740a734SSean Callanan } 1356b9c1b51eSKate Stone } else { 13574740a734SSean Callanan return ValueObjectSP(); 13584740a734SSean Callanan } 13594740a734SSean Callanan break; 13604740a734SSean Callanan } 1361b9c1b51eSKate Stone case Instruction::Operand::Type::Register: { 1362b9c1b51eSKate Stone return GuessValueForRegisterAndOffset(base_and_offset.first->m_register, 1363b9c1b51eSKate Stone base_and_offset.second); 13644740a734SSean Callanan } 13654740a734SSean Callanan default: 13664740a734SSean Callanan return ValueObjectSP(); 13674740a734SSean Callanan } 13684740a734SSean Callanan } 13694740a734SSean Callanan 13704740a734SSean Callanan return ValueObjectSP(); 13714740a734SSean Callanan } 13724740a734SSean Callanan 1373b9c1b51eSKate Stone namespace { 1374b9c1b51eSKate Stone ValueObjectSP GetValueForOffset(StackFrame &frame, ValueObjectSP &parent, 1375b9c1b51eSKate Stone int64_t offset) { 1376b9c1b51eSKate Stone if (offset < 0 || uint64_t(offset) >= parent->GetByteSize()) { 13774740a734SSean Callanan return ValueObjectSP(); 13784740a734SSean Callanan } 13794740a734SSean Callanan 1380b9c1b51eSKate Stone if (parent->IsPointerOrReferenceType()) { 13814740a734SSean Callanan return parent; 13824740a734SSean Callanan } 13834740a734SSean Callanan 1384b9c1b51eSKate Stone for (int ci = 0, ce = parent->GetNumChildren(); ci != ce; ++ci) { 13854740a734SSean Callanan const bool can_create = true; 13864740a734SSean Callanan ValueObjectSP child_sp = parent->GetChildAtIndex(ci, can_create); 13874740a734SSean Callanan 1388b9c1b51eSKate Stone if (!child_sp) { 13894740a734SSean Callanan return ValueObjectSP(); 13904740a734SSean Callanan } 13914740a734SSean Callanan 13924740a734SSean Callanan int64_t child_offset = child_sp->GetByteOffset(); 1393aa88161bSKazu Hirata int64_t child_size = child_sp->GetByteSize().value_or(0); 13944740a734SSean Callanan 1395b9c1b51eSKate Stone if (offset >= child_offset && offset < (child_offset + child_size)) { 13964740a734SSean Callanan return GetValueForOffset(frame, child_sp, offset - child_offset); 13974740a734SSean Callanan } 13984740a734SSean Callanan } 13994740a734SSean Callanan 1400b9c1b51eSKate Stone if (offset == 0) { 14014740a734SSean Callanan return parent; 1402b9c1b51eSKate Stone } else { 14034740a734SSean Callanan return ValueObjectSP(); 14044740a734SSean Callanan } 14054740a734SSean Callanan } 14064740a734SSean Callanan 1407b9c1b51eSKate Stone ValueObjectSP GetValueForDereferincingOffset(StackFrame &frame, 1408b9c1b51eSKate Stone ValueObjectSP &base, 1409b9c1b51eSKate Stone int64_t offset) { 14104740a734SSean Callanan // base is a pointer to something 141105097246SAdrian Prantl // offset is the thing to add to the pointer We return the most sensible 141205097246SAdrian Prantl // ValueObject for the result of *(base+offset) 14134740a734SSean Callanan 1414b9c1b51eSKate Stone if (!base->IsPointerOrReferenceType()) { 14154740a734SSean Callanan return ValueObjectSP(); 14164740a734SSean Callanan } 14174740a734SSean Callanan 141897206d57SZachary Turner Status error; 14194740a734SSean Callanan ValueObjectSP pointee = base->Dereference(error); 1420a0a1d2dbSSean Callanan 1421a0a1d2dbSSean Callanan if (!pointee) { 1422a0a1d2dbSSean Callanan return ValueObjectSP(); 1423a0a1d2dbSSean Callanan } 14244740a734SSean Callanan 14254f730dc7SIlia K if (offset >= 0 && uint64_t(offset) >= pointee->GetByteSize()) { 1426aa88161bSKazu Hirata int64_t index = offset / pointee->GetByteSize().value_or(1); 1427aa88161bSKazu Hirata offset = offset % pointee->GetByteSize().value_or(1); 14284740a734SSean Callanan const bool can_create = true; 14294740a734SSean Callanan pointee = base->GetSyntheticArrayMember(index, can_create); 14304740a734SSean Callanan } 14314740a734SSean Callanan 1432b9c1b51eSKate Stone if (!pointee || error.Fail()) { 14334740a734SSean Callanan return ValueObjectSP(); 14344740a734SSean Callanan } 14354740a734SSean Callanan 14364740a734SSean Callanan return GetValueForOffset(frame, pointee, offset); 14374740a734SSean Callanan } 14384740a734SSean Callanan 14394740a734SSean Callanan /// Attempt to reconstruct the ValueObject for the address contained in a 14404740a734SSean Callanan /// given register plus an offset. 14414740a734SSean Callanan /// 14428d714e4aSDavid Spickett /// \param [in] frame 14434740a734SSean Callanan /// The current stack frame. 14444740a734SSean Callanan /// 14458d714e4aSDavid Spickett /// \param [in] reg 14464740a734SSean Callanan /// The register. 14474740a734SSean Callanan /// 14488d714e4aSDavid Spickett /// \param [in] offset 14494740a734SSean Callanan /// The offset from the register. 14504740a734SSean Callanan /// 1451f05b42e9SAdrian Prantl /// \param [in] disassembler 14524740a734SSean Callanan /// A disassembler containing instructions valid up to the current PC. 14534740a734SSean Callanan /// 1454f05b42e9SAdrian Prantl /// \param [in] variables 14554740a734SSean Callanan /// The variable list from the current frame, 14564740a734SSean Callanan /// 1457f05b42e9SAdrian Prantl /// \param [in] pc 14584740a734SSean Callanan /// The program counter for the instruction considered the 'user'. 14594740a734SSean Callanan /// 1460f05b42e9SAdrian Prantl /// \return 14614740a734SSean Callanan /// A string describing the base for the ExpressionPath. This could be a 14624740a734SSean Callanan /// variable, a register value, an argument, or a function return value. 14634740a734SSean Callanan /// The ValueObject if found. If valid, it has a valid ExpressionPath. 1464b9c1b51eSKate Stone lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg, 1465b9c1b51eSKate Stone int64_t offset, Disassembler &disassembler, 1466b9c1b51eSKate Stone VariableList &variables, const Address &pc) { 14674740a734SSean Callanan // Example of operation for Intel: 14684740a734SSean Callanan // 14694740a734SSean Callanan // +14: movq -0x8(%rbp), %rdi 14704740a734SSean Callanan // +18: movq 0x8(%rdi), %rdi 14714740a734SSean Callanan // +22: addl 0x4(%rdi), %eax 14724740a734SSean Callanan // 14734740a734SSean Callanan // f, a pointer to a struct, is known to be at -0x8(%rbp). 14744740a734SSean Callanan // 147505097246SAdrian Prantl // DoGuessValueAt(frame, rdi, 4, dis, vars, 0x22) finds the instruction at 147605097246SAdrian Prantl // +18 that assigns to rdi, and calls itself recursively for that dereference 1477b9c1b51eSKate Stone // DoGuessValueAt(frame, rdi, 8, dis, vars, 0x18) finds the instruction at 1478b9c1b51eSKate Stone // +14 that assigns to rdi, and calls itself recursively for that 1479e9264b74SKazuaki Ishizaki // dereference 1480b9c1b51eSKate Stone // DoGuessValueAt(frame, rbp, -8, dis, vars, 0x14) finds "f" in the 1481b9c1b51eSKate Stone // variable list. 14824740a734SSean Callanan // Returns a ValueObject for f. (That's what was stored at rbp-8 at +14) 1483b9c1b51eSKate Stone // Returns a ValueObject for *(f+8) or f->b (That's what was stored at rdi+8 1484b9c1b51eSKate Stone // at +18) 1485b9c1b51eSKate Stone // Returns a ValueObject for *(f->b+4) or f->b->a (That's what was stored at 1486b9c1b51eSKate Stone // rdi+4 at +22) 14874740a734SSean Callanan 1488b9c1b51eSKate Stone // First, check the variable list to see if anything is at the specified 1489b9c1b51eSKate Stone // location. 1490807ee2ffSSean Callanan 149150857108SSean Callanan using namespace OperandMatchers; 149250857108SSean Callanan 14930ac172d8SSean Callanan const RegisterInfo *reg_info = 14940ac172d8SSean Callanan frame.GetRegisterContext()->GetRegisterInfoByName(reg.AsCString()); 14950ac172d8SSean Callanan if (!reg_info) { 14960ac172d8SSean Callanan return ValueObjectSP(); 14970ac172d8SSean Callanan } 14980ac172d8SSean Callanan 1499807ee2ffSSean Callanan Instruction::Operand op = 1500807ee2ffSSean Callanan offset ? Instruction::Operand::BuildDereference( 1501807ee2ffSSean Callanan Instruction::Operand::BuildSum( 1502807ee2ffSSean Callanan Instruction::Operand::BuildRegister(reg), 1503807ee2ffSSean Callanan Instruction::Operand::BuildImmediate(offset))) 1504807ee2ffSSean Callanan : Instruction::Operand::BuildDereference( 1505807ee2ffSSean Callanan Instruction::Operand::BuildRegister(reg)); 1506807ee2ffSSean Callanan 1507d1782133SRaphael Isemann for (VariableSP var_sp : variables) { 1508*e4c5bca5SJonas Devlieghere if (var_sp->LocationExpression().MatchesOperand(frame, op)) 15094740a734SSean Callanan return frame.GetValueObjectForFrameVariable(var_sp, eNoDynamicValues); 15104740a734SSean Callanan } 15114740a734SSean Callanan 1512b9c1b51eSKate Stone const uint32_t current_inst = 1513b9c1b51eSKate Stone disassembler.GetInstructionList().GetIndexOfInstructionAtAddress(pc); 1514b9c1b51eSKate Stone if (current_inst == UINT32_MAX) { 15154740a734SSean Callanan return ValueObjectSP(); 15164740a734SSean Callanan } 15174740a734SSean Callanan 1518b9c1b51eSKate Stone for (uint32_t ii = current_inst - 1; ii != (uint32_t)-1; --ii) { 1519b9c1b51eSKate Stone // This is not an exact algorithm, and it sacrifices accuracy for 152005097246SAdrian Prantl // generality. Recognizing "mov" and "ld" instructions –– and which 152105097246SAdrian Prantl // are their source and destination operands -- is something the 152205097246SAdrian Prantl // disassembler should do for us. 1523b9c1b51eSKate Stone InstructionSP instruction_sp = 1524b9c1b51eSKate Stone disassembler.GetInstructionList().GetInstructionAtIndex(ii); 15254740a734SSean Callanan 152650857108SSean Callanan if (instruction_sp->IsCall()) { 152750857108SSean Callanan ABISP abi_sp = frame.CalculateProcess()->GetABI(); 152850857108SSean Callanan if (!abi_sp) { 152950857108SSean Callanan continue; 153050857108SSean Callanan } 153150857108SSean Callanan 153250857108SSean Callanan const char *return_register_name; 153350857108SSean Callanan if (!abi_sp->GetPointerReturnRegister(return_register_name)) { 153450857108SSean Callanan continue; 153550857108SSean Callanan } 153650857108SSean Callanan 153750857108SSean Callanan const RegisterInfo *return_register_info = 153850857108SSean Callanan frame.GetRegisterContext()->GetRegisterInfoByName( 153950857108SSean Callanan return_register_name); 154050857108SSean Callanan if (!return_register_info) { 154150857108SSean Callanan continue; 154250857108SSean Callanan } 154350857108SSean Callanan 154450857108SSean Callanan int64_t offset = 0; 154550857108SSean Callanan 154650857108SSean Callanan if (!MatchUnaryOp(MatchOpType(Instruction::Operand::Type::Dereference), 154750857108SSean Callanan MatchRegOp(*return_register_info))(op) && 154850857108SSean Callanan !MatchUnaryOp( 154950857108SSean Callanan MatchOpType(Instruction::Operand::Type::Dereference), 155050857108SSean Callanan MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum), 155150857108SSean Callanan MatchRegOp(*return_register_info), 155250857108SSean Callanan FetchImmOp(offset)))(op)) { 155350857108SSean Callanan continue; 155450857108SSean Callanan } 155550857108SSean Callanan 15564740a734SSean Callanan llvm::SmallVector<Instruction::Operand, 1> operands; 1557b9c1b51eSKate Stone if (!instruction_sp->ParseOperands(operands) || operands.size() != 1) { 15584740a734SSean Callanan continue; 15594740a734SSean Callanan } 15604740a734SSean Callanan 1561b9c1b51eSKate Stone switch (operands[0].m_type) { 15624740a734SSean Callanan default: 15634740a734SSean Callanan break; 1564b9c1b51eSKate Stone case Instruction::Operand::Type::Immediate: { 15654740a734SSean Callanan SymbolContext sc; 15664740a734SSean Callanan Address load_address; 1567b9c1b51eSKate Stone if (!frame.CalculateTarget()->ResolveLoadAddress( 1568b9c1b51eSKate Stone operands[0].m_immediate, load_address)) { 15694740a734SSean Callanan break; 15704740a734SSean Callanan } 1571b9c1b51eSKate Stone frame.CalculateTarget()->GetImages().ResolveSymbolContextForAddress( 1572b9c1b51eSKate Stone load_address, eSymbolContextFunction, sc); 1573b9c1b51eSKate Stone if (!sc.function) { 15744740a734SSean Callanan break; 15754740a734SSean Callanan } 15764740a734SSean Callanan CompilerType function_type = sc.function->GetCompilerType(); 1577b9c1b51eSKate Stone if (!function_type.IsFunctionType()) { 15784740a734SSean Callanan break; 15794740a734SSean Callanan } 15804740a734SSean Callanan CompilerType return_type = function_type.GetFunctionReturnType(); 15814740a734SSean Callanan RegisterValue return_value; 158250857108SSean Callanan if (!frame.GetRegisterContext()->ReadRegister(return_register_info, 1583b9c1b51eSKate Stone return_value)) { 15844740a734SSean Callanan break; 15854740a734SSean Callanan } 1586b9c1b51eSKate Stone std::string name_str( 1587b9c1b51eSKate Stone sc.function->GetName().AsCString("<unknown function>")); 15884740a734SSean Callanan name_str.append("()"); 15894740a734SSean Callanan Address return_value_address(return_value.GetAsUInt64()); 1590b9c1b51eSKate Stone ValueObjectSP return_value_sp = ValueObjectMemory::Create( 159122a2628fSZachary Turner &frame, name_str, return_value_address, return_type); 15924740a734SSean Callanan return GetValueForDereferincingOffset(frame, return_value_sp, offset); 15934740a734SSean Callanan } 15944740a734SSean Callanan } 15954740a734SSean Callanan 15964740a734SSean Callanan continue; 15974740a734SSean Callanan } 15984740a734SSean Callanan 15994740a734SSean Callanan llvm::SmallVector<Instruction::Operand, 2> operands; 1600b9c1b51eSKate Stone if (!instruction_sp->ParseOperands(operands) || operands.size() != 2) { 16014740a734SSean Callanan continue; 16024740a734SSean Callanan } 16034740a734SSean Callanan 16044740a734SSean Callanan Instruction::Operand *origin_operand = nullptr; 1605aa4b44c6SSean Callanan auto clobbered_reg_matcher = [reg_info](const Instruction::Operand &op) { 16060ac172d8SSean Callanan return MatchRegOp(*reg_info)(op) && op.m_clobbered; 16070ac172d8SSean Callanan }; 16080ac172d8SSean Callanan 16090ac172d8SSean Callanan if (clobbered_reg_matcher(operands[0])) { 16104740a734SSean Callanan origin_operand = &operands[1]; 16110ac172d8SSean Callanan } 16120ac172d8SSean Callanan else if (clobbered_reg_matcher(operands[1])) { 16134740a734SSean Callanan origin_operand = &operands[0]; 16140ac172d8SSean Callanan } 16150ac172d8SSean Callanan else { 16164740a734SSean Callanan continue; 16174740a734SSean Callanan } 16184740a734SSean Callanan 16194740a734SSean Callanan // We have an origin operand. Can we track its value down? 1620561a9bbfSSean Callanan ValueObjectSP source_path; 1621561a9bbfSSean Callanan ConstString origin_register; 1622561a9bbfSSean Callanan int64_t origin_offset = 0; 1623561a9bbfSSean Callanan 1624561a9bbfSSean Callanan if (FetchRegOp(origin_register)(*origin_operand)) { 1625561a9bbfSSean Callanan source_path = DoGuessValueAt(frame, origin_register, 0, disassembler, 1626561a9bbfSSean Callanan variables, instruction_sp->GetAddress()); 1627561a9bbfSSean Callanan } else if (MatchUnaryOp( 1628561a9bbfSSean Callanan MatchOpType(Instruction::Operand::Type::Dereference), 1629561a9bbfSSean Callanan FetchRegOp(origin_register))(*origin_operand) || 1630561a9bbfSSean Callanan MatchUnaryOp( 1631561a9bbfSSean Callanan MatchOpType(Instruction::Operand::Type::Dereference), 1632561a9bbfSSean Callanan MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum), 1633561a9bbfSSean Callanan FetchRegOp(origin_register), 1634561a9bbfSSean Callanan FetchImmOp(origin_offset)))(*origin_operand)) { 1635b9c1b51eSKate Stone source_path = 1636561a9bbfSSean Callanan DoGuessValueAt(frame, origin_register, origin_offset, disassembler, 1637b9c1b51eSKate Stone variables, instruction_sp->GetAddress()); 1638b9c1b51eSKate Stone if (!source_path) { 1639561a9bbfSSean Callanan continue; 16404740a734SSean Callanan } 1641b9c1b51eSKate Stone source_path = 1642b9c1b51eSKate Stone GetValueForDereferincingOffset(frame, source_path, offset); 16434740a734SSean Callanan } 16444740a734SSean Callanan 1645b9c1b51eSKate Stone if (source_path) { 16464740a734SSean Callanan return source_path; 16474740a734SSean Callanan } 16484740a734SSean Callanan } 16494740a734SSean Callanan 16504740a734SSean Callanan return ValueObjectSP(); 16514740a734SSean Callanan } 16524740a734SSean Callanan } 16534740a734SSean Callanan 1654b9c1b51eSKate Stone lldb::ValueObjectSP StackFrame::GuessValueForRegisterAndOffset(ConstString reg, 1655b9c1b51eSKate Stone int64_t offset) { 16564740a734SSean Callanan TargetSP target_sp = CalculateTarget(); 16574740a734SSean Callanan 16584740a734SSean Callanan const ArchSpec &target_arch = target_sp->GetArchitecture(); 16594740a734SSean Callanan 16604740a734SSean Callanan Block *frame_block = GetFrameBlock(); 16614740a734SSean Callanan 1662b9c1b51eSKate Stone if (!frame_block) { 16634740a734SSean Callanan return ValueObjectSP(); 16644740a734SSean Callanan } 16654740a734SSean Callanan 16664740a734SSean Callanan Function *function = frame_block->CalculateSymbolContextFunction(); 1667b9c1b51eSKate Stone if (!function) { 16684740a734SSean Callanan return ValueObjectSP(); 16694740a734SSean Callanan } 16704740a734SSean Callanan 16714740a734SSean Callanan AddressRange pc_range = function->GetAddressRange(); 16724740a734SSean Callanan 1673b9c1b51eSKate Stone if (GetFrameCodeAddress().GetFileAddress() < 1674b9c1b51eSKate Stone pc_range.GetBaseAddress().GetFileAddress() || 1675b9c1b51eSKate Stone GetFrameCodeAddress().GetFileAddress() - 1676b9c1b51eSKate Stone pc_range.GetBaseAddress().GetFileAddress() >= 1677b9c1b51eSKate Stone pc_range.GetByteSize()) { 16784740a734SSean Callanan return ValueObjectSP(); 16794740a734SSean Callanan } 16804740a734SSean Callanan 16814740a734SSean Callanan const char *plugin_name = nullptr; 16824740a734SSean Callanan const char *flavor = nullptr; 1683e9fe788dSJason Molenda const bool force_live_memory = true; 168404592d5bSPavel Labath DisassemblerSP disassembler_sp = 168504592d5bSPavel Labath Disassembler::DisassembleRange(target_arch, plugin_name, flavor, 1686e9fe788dSJason Molenda *target_sp, pc_range, force_live_memory); 16874740a734SSean Callanan 1688b9c1b51eSKate Stone if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) { 16894740a734SSean Callanan return ValueObjectSP(); 16904740a734SSean Callanan } 16914740a734SSean Callanan 16924740a734SSean Callanan const bool get_file_globals = false; 16934740a734SSean Callanan VariableList *variables = GetVariableList(get_file_globals); 16944740a734SSean Callanan 1695b9c1b51eSKate Stone if (!variables) { 16964740a734SSean Callanan return ValueObjectSP(); 16974740a734SSean Callanan } 16984740a734SSean Callanan 1699b9c1b51eSKate Stone return DoGuessValueAt(*this, reg, offset, *disassembler_sp, *variables, 1700b9c1b51eSKate Stone GetFrameCodeAddress()); 17014740a734SSean Callanan } 17024740a734SSean Callanan 1703e23d0b63SShafik Yaghmour lldb::ValueObjectSP StackFrame::FindVariable(ConstString name) { 1704e23d0b63SShafik Yaghmour ValueObjectSP value_sp; 1705e23d0b63SShafik Yaghmour 1706e23d0b63SShafik Yaghmour if (!name) 1707e23d0b63SShafik Yaghmour return value_sp; 1708e23d0b63SShafik Yaghmour 1709e23d0b63SShafik Yaghmour TargetSP target_sp = CalculateTarget(); 1710e23d0b63SShafik Yaghmour ProcessSP process_sp = CalculateProcess(); 1711e23d0b63SShafik Yaghmour 1712e23d0b63SShafik Yaghmour if (!target_sp && !process_sp) 1713e23d0b63SShafik Yaghmour return value_sp; 1714e23d0b63SShafik Yaghmour 1715e23d0b63SShafik Yaghmour VariableList variable_list; 1716e23d0b63SShafik Yaghmour VariableSP var_sp; 1717e23d0b63SShafik Yaghmour SymbolContext sc(GetSymbolContext(eSymbolContextBlock)); 1718e23d0b63SShafik Yaghmour 1719e23d0b63SShafik Yaghmour if (sc.block) { 1720e23d0b63SShafik Yaghmour const bool can_create = true; 1721e23d0b63SShafik Yaghmour const bool get_parent_variables = true; 1722e23d0b63SShafik Yaghmour const bool stop_if_block_is_inlined_function = true; 1723e23d0b63SShafik Yaghmour 1724e23d0b63SShafik Yaghmour if (sc.block->AppendVariables( 1725e23d0b63SShafik Yaghmour can_create, get_parent_variables, stop_if_block_is_inlined_function, 1726e23d0b63SShafik Yaghmour [this](Variable *v) { return v->IsInScope(this); }, 1727e23d0b63SShafik Yaghmour &variable_list)) { 1728e23d0b63SShafik Yaghmour var_sp = variable_list.FindVariable(name); 1729e23d0b63SShafik Yaghmour } 1730e23d0b63SShafik Yaghmour 1731e23d0b63SShafik Yaghmour if (var_sp) 1732e23d0b63SShafik Yaghmour value_sp = GetValueObjectForFrameVariable(var_sp, eNoDynamicValues); 1733e23d0b63SShafik Yaghmour } 1734e23d0b63SShafik Yaghmour 1735e23d0b63SShafik Yaghmour return value_sp; 1736e23d0b63SShafik Yaghmour } 1737e23d0b63SShafik Yaghmour 1738b9c1b51eSKate Stone TargetSP StackFrame::CalculateTarget() { 1739d9e416c0SGreg Clayton TargetSP target_sp; 1740d9e416c0SGreg Clayton ThreadSP thread_sp(GetThread()); 1741b9c1b51eSKate Stone if (thread_sp) { 1742d9e416c0SGreg Clayton ProcessSP process_sp(thread_sp->CalculateProcess()); 1743d9e416c0SGreg Clayton if (process_sp) 1744d9e416c0SGreg Clayton target_sp = process_sp->CalculateTarget(); 1745d9e416c0SGreg Clayton } 1746d9e416c0SGreg Clayton return target_sp; 174730fdc8d8SChris Lattner } 174830fdc8d8SChris Lattner 1749b9c1b51eSKate Stone ProcessSP StackFrame::CalculateProcess() { 1750d9e416c0SGreg Clayton ProcessSP process_sp; 1751d9e416c0SGreg Clayton ThreadSP thread_sp(GetThread()); 1752d9e416c0SGreg Clayton if (thread_sp) 1753d9e416c0SGreg Clayton process_sp = thread_sp->CalculateProcess(); 1754d9e416c0SGreg Clayton return process_sp; 175530fdc8d8SChris Lattner } 175630fdc8d8SChris Lattner 1757b9c1b51eSKate Stone ThreadSP StackFrame::CalculateThread() { return GetThread(); } 175830fdc8d8SChris Lattner 1759b9c1b51eSKate Stone StackFrameSP StackFrame::CalculateStackFrame() { return shared_from_this(); } 176030fdc8d8SChris Lattner 1761b9c1b51eSKate Stone void StackFrame::CalculateExecutionContext(ExecutionContext &exe_ctx) { 1762d9e416c0SGreg Clayton exe_ctx.SetContext(shared_from_this()); 176330fdc8d8SChris Lattner } 176430fdc8d8SChris Lattner 17657f1c1211SPavel Labath void StackFrame::DumpUsingSettingsFormat(Stream *strm, bool show_unique, 1766b9c1b51eSKate Stone const char *frame_marker) { 1767d70a6e71SEugene Zelenko if (strm == nullptr) 17680603aa9dSGreg Clayton return; 17690603aa9dSGreg Clayton 17700603aa9dSGreg Clayton GetSymbolContext(eSymbolContextEverything); 1771d9e416c0SGreg Clayton ExecutionContext exe_ctx(shared_from_this()); 17720603aa9dSGreg Clayton StreamString s; 17738ec10efcSJim Ingham 17748ec10efcSJim Ingham if (frame_marker) 17758ec10efcSJim Ingham s.PutCString(frame_marker); 17768ec10efcSJim Ingham 1777d70a6e71SEugene Zelenko const FormatEntity::Entry *frame_format = nullptr; 1778d9e416c0SGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 17797f1c1211SPavel Labath if (target) { 17807f1c1211SPavel Labath if (show_unique) { 17817f1c1211SPavel Labath frame_format = target->GetDebugger().GetFrameFormatUnique(); 17827f1c1211SPavel Labath } else { 1783d9e416c0SGreg Clayton frame_format = target->GetDebugger().GetFrameFormat(); 17847f1c1211SPavel Labath } 17857f1c1211SPavel Labath } 1786b9c1b51eSKate Stone if (frame_format && FormatEntity::Format(*frame_format, s, &m_sc, &exe_ctx, 1787b9c1b51eSKate Stone nullptr, nullptr, false, false)) { 1788c156427dSZachary Turner strm->PutCString(s.GetString()); 1789b9c1b51eSKate Stone } else { 17900603aa9dSGreg Clayton Dump(strm, true, false); 17910603aa9dSGreg Clayton strm->EOL(); 17920603aa9dSGreg Clayton } 17930603aa9dSGreg Clayton } 17940603aa9dSGreg Clayton 1795b9c1b51eSKate Stone void StackFrame::Dump(Stream *strm, bool show_frame_index, 1796b9c1b51eSKate Stone bool show_fullpaths) { 1797d70a6e71SEugene Zelenko if (strm == nullptr) 179830fdc8d8SChris Lattner return; 179930fdc8d8SChris Lattner 180030fdc8d8SChris Lattner if (show_frame_index) 18011b72fcb7SGreg Clayton strm->Printf("frame #%u: ", m_frame_index); 1802d9e416c0SGreg Clayton ExecutionContext exe_ctx(shared_from_this()); 1803d9e416c0SGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 1804d01b2953SDaniel Malea strm->Printf("0x%0*" PRIx64 " ", 1805b9c1b51eSKate Stone target ? (target->GetArchitecture().GetAddressByteSize() * 2) 1806b9c1b51eSKate Stone : 16, 1807d9e416c0SGreg Clayton GetFrameCodeAddress().GetLoadAddress(target)); 18089da7bd07SGreg Clayton GetSymbolContext(eSymbolContextEverything); 18091b72fcb7SGreg Clayton const bool show_module = true; 18101b72fcb7SGreg Clayton const bool show_inline = true; 1811aff1b357SJason Molenda const bool show_function_arguments = true; 1812c980fa92SJason Molenda const bool show_function_name = true; 1813b9c1b51eSKate Stone m_sc.DumpStopContext(strm, exe_ctx.GetBestExecutionContextScope(), 1814b9c1b51eSKate Stone GetFrameCodeAddress(), show_fullpaths, show_module, 1815b9c1b51eSKate Stone show_inline, show_function_arguments, 1816c980fa92SJason Molenda show_function_name); 181730fdc8d8SChris Lattner } 181830fdc8d8SChris Lattner 1819b9c1b51eSKate Stone void StackFrame::UpdateCurrentFrameFromPreviousFrame(StackFrame &prev_frame) { 1820bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 1821b9c1b51eSKate Stone assert(GetStackID() == 1822b9c1b51eSKate Stone prev_frame.GetStackID()); // TODO: remove this after some testing 1823b57e4a1bSJason Molenda m_variable_list_sp = prev_frame.m_variable_list_sp; 1824b57e4a1bSJason Molenda m_variable_list_value_objects.Swap(prev_frame.m_variable_list_value_objects); 1825c156427dSZachary Turner if (!m_disassembly.GetString().empty()) { 1826c156427dSZachary Turner m_disassembly.Clear(); 1827c156427dSZachary Turner m_disassembly.PutCString(prev_frame.m_disassembly.GetString()); 1828c156427dSZachary Turner } 18295082c5fdSGreg Clayton } 183068275d5eSGreg Clayton 1831b9c1b51eSKate Stone void StackFrame::UpdatePreviousFrameFromCurrentFrame(StackFrame &curr_frame) { 1832bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 1833b9c1b51eSKate Stone assert(GetStackID() == 1834b9c1b51eSKate Stone curr_frame.GetStackID()); // TODO: remove this after some testing 1835b57e4a1bSJason Molenda m_id.SetPC(curr_frame.m_id.GetPC()); // Update the Stack ID PC value 1836b57e4a1bSJason Molenda assert(GetThread() == curr_frame.GetThread()); 1837b57e4a1bSJason Molenda m_frame_index = curr_frame.m_frame_index; 1838b57e4a1bSJason Molenda m_concrete_frame_index = curr_frame.m_concrete_frame_index; 1839b57e4a1bSJason Molenda m_reg_context_sp = curr_frame.m_reg_context_sp; 1840b57e4a1bSJason Molenda m_frame_code_addr = curr_frame.m_frame_code_addr; 18410a840ef8STatyana Krasnukha m_behaves_like_zeroth_frame = curr_frame.m_behaves_like_zeroth_frame; 1842b9c1b51eSKate Stone assert(!m_sc.target_sp || !curr_frame.m_sc.target_sp || 1843b9c1b51eSKate Stone m_sc.target_sp.get() == curr_frame.m_sc.target_sp.get()); 1844b9c1b51eSKate Stone assert(!m_sc.module_sp || !curr_frame.m_sc.module_sp || 1845b9c1b51eSKate Stone m_sc.module_sp.get() == curr_frame.m_sc.module_sp.get()); 1846b9c1b51eSKate Stone assert(m_sc.comp_unit == nullptr || curr_frame.m_sc.comp_unit == nullptr || 1847b9c1b51eSKate Stone m_sc.comp_unit == curr_frame.m_sc.comp_unit); 1848b9c1b51eSKate Stone assert(m_sc.function == nullptr || curr_frame.m_sc.function == nullptr || 1849b9c1b51eSKate Stone m_sc.function == curr_frame.m_sc.function); 1850b57e4a1bSJason Molenda m_sc = curr_frame.m_sc; 185159e8fc1cSGreg Clayton m_flags.Clear(GOT_FRAME_BASE | eSymbolContextEverything); 185259e8fc1cSGreg Clayton m_flags.Set(m_sc.GetResolvedMask()); 185359e8fc1cSGreg Clayton m_frame_base.Clear(); 185459e8fc1cSGreg Clayton m_frame_base_error.Clear(); 185559e8fc1cSGreg Clayton } 1856e4284b71SJim Ingham 1857b9c1b51eSKate Stone bool StackFrame::HasCachedData() const { 1858d70a6e71SEugene Zelenko if (m_variable_list_sp) 1859b57e4a1bSJason Molenda return true; 1860b57e4a1bSJason Molenda if (m_variable_list_value_objects.GetSize() > 0) 1861b57e4a1bSJason Molenda return true; 1862b57e4a1bSJason Molenda if (!m_disassembly.GetString().empty()) 1863b57e4a1bSJason Molenda return true; 1864b57e4a1bSJason Molenda return false; 1865b57e4a1bSJason Molenda } 1866b57e4a1bSJason Molenda 1867b9c1b51eSKate Stone bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source, 18687f1c1211SPavel Labath bool show_unique, const char *frame_marker) { 1869b9c1b51eSKate Stone if (show_frame_info) { 18707260f620SGreg Clayton strm.Indent(); 18717f1c1211SPavel Labath DumpUsingSettingsFormat(&strm, show_unique, frame_marker); 18727260f620SGreg Clayton } 18737260f620SGreg Clayton 1874b9c1b51eSKate Stone if (show_source) { 1875d9e416c0SGreg Clayton ExecutionContext exe_ctx(shared_from_this()); 18768be74995SMohit K. Bhakkad bool have_source = false, have_debuginfo = false; 1877b9c1b51eSKate Stone Debugger::StopDisassemblyType disasm_display = 1878b9c1b51eSKate Stone Debugger::eStopDisassemblyTypeNever; 1879d9e416c0SGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 1880b9c1b51eSKate Stone if (target) { 188153eb7ad2SGreg Clayton Debugger &debugger = target->GetDebugger(); 1882b9c1b51eSKate Stone const uint32_t source_lines_before = 1883b9c1b51eSKate Stone debugger.GetStopSourceLineCount(true); 1884b9c1b51eSKate Stone const uint32_t source_lines_after = 1885b9c1b51eSKate Stone debugger.GetStopSourceLineCount(false); 188653eb7ad2SGreg Clayton disasm_display = debugger.GetStopDisassemblyDisplay(); 188753eb7ad2SGreg Clayton 18887260f620SGreg Clayton GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry); 1889b9c1b51eSKate Stone if (m_sc.comp_unit && m_sc.line_entry.IsValid()) { 18908be74995SMohit K. Bhakkad have_debuginfo = true; 1891b9c1b51eSKate Stone if (source_lines_before > 0 || source_lines_after > 0) { 1892edf410e4SMed Ismail Bennani uint32_t start_line = m_sc.line_entry.line; 1893edf410e4SMed Ismail Bennani if (!start_line && m_sc.function) { 1894edf410e4SMed Ismail Bennani FileSpec source_file; 1895edf410e4SMed Ismail Bennani m_sc.function->GetStartLineSourceInfo(source_file, start_line); 1896edf410e4SMed Ismail Bennani } 1897edf410e4SMed Ismail Bennani 1898b9c1b51eSKate Stone size_t num_lines = 1899b9c1b51eSKate Stone target->GetSourceManager().DisplaySourceLinesWithLineNumbers( 1900edf410e4SMed Ismail Bennani m_sc.line_entry.file, start_line, m_sc.line_entry.column, 1901edf410e4SMed Ismail Bennani source_lines_before, source_lines_after, "->", &strm); 19028be74995SMohit K. Bhakkad if (num_lines != 0) 19038be74995SMohit K. Bhakkad have_source = true; 19048be74995SMohit K. Bhakkad // TODO: Give here a one time warning if source file is missing. 1905edf410e4SMed Ismail Bennani if (!m_sc.line_entry.line) { 1906edf410e4SMed Ismail Bennani ConstString fn_name = m_sc.GetFunctionName(); 1907edf410e4SMed Ismail Bennani 1908edf410e4SMed Ismail Bennani if (!fn_name.IsEmpty()) 190920db8e07SMed Ismail Bennani strm.Printf( 191020db8e07SMed Ismail Bennani "Note: this address is compiler-generated code in function " 191120db8e07SMed Ismail Bennani "%s that has no source code associated with it.", 1912edf410e4SMed Ismail Bennani fn_name.AsCString()); 1913edf410e4SMed Ismail Bennani else 191420db8e07SMed Ismail Bennani strm.Printf("Note: this address is compiler-generated code that " 191520db8e07SMed Ismail Bennani "has no source code associated with it."); 1916edf410e4SMed Ismail Bennani strm.EOL(); 1917edf410e4SMed Ismail Bennani } 1918e372b98dSGreg Clayton } 1919e372b98dSGreg Clayton } 1920b9c1b51eSKate Stone switch (disasm_display) { 192167cc0636SGreg Clayton case Debugger::eStopDisassemblyTypeNever: 1922e372b98dSGreg Clayton break; 1923e372b98dSGreg Clayton 19248be74995SMohit K. Bhakkad case Debugger::eStopDisassemblyTypeNoDebugInfo: 19258be74995SMohit K. Bhakkad if (have_debuginfo) 19268be74995SMohit K. Bhakkad break; 192762e0681aSJason Molenda LLVM_FALLTHROUGH; 19288be74995SMohit K. Bhakkad 192967cc0636SGreg Clayton case Debugger::eStopDisassemblyTypeNoSource: 1930e372b98dSGreg Clayton if (have_source) 1931e372b98dSGreg Clayton break; 193262e0681aSJason Molenda LLVM_FALLTHROUGH; 19338be74995SMohit K. Bhakkad 193467cc0636SGreg Clayton case Debugger::eStopDisassemblyTypeAlways: 1935b9c1b51eSKate Stone if (target) { 193653eb7ad2SGreg Clayton const uint32_t disasm_lines = debugger.GetDisassemblyLineCount(); 1937b9c1b51eSKate Stone if (disasm_lines > 0) { 1938d9e416c0SGreg Clayton const ArchSpec &target_arch = target->GetArchitecture(); 1939d70a6e71SEugene Zelenko const char *plugin_name = nullptr; 1940d70a6e71SEugene Zelenko const char *flavor = nullptr; 19410b4c26b2SJason Molenda const bool mixed_source_and_assembly = false; 19420b4c26b2SJason Molenda Disassembler::Disassemble( 19430b4c26b2SJason Molenda target->GetDebugger(), target_arch, plugin_name, flavor, 1944af3db4e9SPavel Labath exe_ctx, GetFrameCodeAddress(), 1945af3db4e9SPavel Labath {Disassembler::Limit::Instructions, disasm_lines}, 1946af3db4e9SPavel Labath mixed_source_and_assembly, 0, 1947b9c1b51eSKate Stone Disassembler::eOptionMarkPCAddress, strm); 1948e372b98dSGreg Clayton } 1949e372b98dSGreg Clayton } 1950e372b98dSGreg Clayton break; 19517260f620SGreg Clayton } 19527260f620SGreg Clayton } 195353eb7ad2SGreg Clayton } 19547260f620SGreg Clayton return true; 19557260f620SGreg Clayton } 195641ae8e74SKuba Mracek 195741ae8e74SKuba Mracek RecognizedStackFrameSP StackFrame::GetRecognizedFrame() { 195841ae8e74SKuba Mracek if (!m_recognized_frame_sp) { 19591b7c9eaeSRaphael Isemann m_recognized_frame_sp = GetThread() 19601b7c9eaeSRaphael Isemann ->GetProcess() 19611b7c9eaeSRaphael Isemann ->GetTarget() 19621b7c9eaeSRaphael Isemann .GetFrameRecognizerManager() 19631b7c9eaeSRaphael Isemann .RecognizeFrame(CalculateStackFrame()); 196441ae8e74SKuba Mracek } 196541ae8e74SKuba Mracek return m_recognized_frame_sp; 196641ae8e74SKuba Mracek } 1967