15ffd83dbSDimitry Andric //===-- StackFrame.cpp ----------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "lldb/Target/StackFrame.h" 100b57cec5SDimitry Andric #include "lldb/Core/Debugger.h" 110b57cec5SDimitry Andric #include "lldb/Core/Disassembler.h" 120b57cec5SDimitry Andric #include "lldb/Core/FormatEntity.h" 130b57cec5SDimitry Andric #include "lldb/Core/Mangled.h" 140b57cec5SDimitry Andric #include "lldb/Core/Module.h" 150b57cec5SDimitry Andric #include "lldb/Core/Value.h" 160b57cec5SDimitry Andric #include "lldb/Core/ValueObjectConstResult.h" 170b57cec5SDimitry Andric #include "lldb/Core/ValueObjectMemory.h" 180b57cec5SDimitry Andric #include "lldb/Core/ValueObjectVariable.h" 190b57cec5SDimitry Andric #include "lldb/Symbol/CompileUnit.h" 200b57cec5SDimitry Andric #include "lldb/Symbol/Function.h" 210b57cec5SDimitry Andric #include "lldb/Symbol/Symbol.h" 220b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContextScope.h" 23bdd1243dSDimitry Andric #include "lldb/Symbol/SymbolFile.h" 240b57cec5SDimitry Andric #include "lldb/Symbol/Type.h" 250b57cec5SDimitry Andric #include "lldb/Symbol/VariableList.h" 260b57cec5SDimitry Andric #include "lldb/Target/ABI.h" 270b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h" 280b57cec5SDimitry Andric #include "lldb/Target/Process.h" 290b57cec5SDimitry Andric #include "lldb/Target/RegisterContext.h" 300b57cec5SDimitry Andric #include "lldb/Target/StackFrameRecognizer.h" 310b57cec5SDimitry Andric #include "lldb/Target/Target.h" 320b57cec5SDimitry Andric #include "lldb/Target/Thread.h" 3381ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h" 349dba64beSDimitry Andric #include "lldb/Utility/Log.h" 350b57cec5SDimitry Andric #include "lldb/Utility/RegisterValue.h" 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric #include "lldb/lldb-enumerations.h" 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric #include <memory> 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric using namespace lldb; 420b57cec5SDimitry Andric using namespace lldb_private; 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric // The first bits in the flags are reserved for the SymbolContext::Scope bits 450b57cec5SDimitry Andric // so we know if we have tried to look up information in our internal symbol 460b57cec5SDimitry Andric // context (m_sc) already. 47bdd1243dSDimitry Andric #define RESOLVED_FRAME_CODE_ADDR (uint32_t(eSymbolContextLastItem) << 1) 480b57cec5SDimitry Andric #define RESOLVED_FRAME_ID_SYMBOL_SCOPE (RESOLVED_FRAME_CODE_ADDR << 1) 490b57cec5SDimitry Andric #define GOT_FRAME_BASE (RESOLVED_FRAME_ID_SYMBOL_SCOPE << 1) 500b57cec5SDimitry Andric #define RESOLVED_VARIABLES (GOT_FRAME_BASE << 1) 510b57cec5SDimitry Andric #define RESOLVED_GLOBAL_VARIABLES (RESOLVED_VARIABLES << 1) 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, 540b57cec5SDimitry Andric user_id_t unwind_frame_index, addr_t cfa, 550b57cec5SDimitry Andric bool cfa_is_valid, addr_t pc, StackFrame::Kind kind, 569dba64beSDimitry Andric bool behaves_like_zeroth_frame, 570b57cec5SDimitry Andric const SymbolContext *sc_ptr) 580b57cec5SDimitry Andric : m_thread_wp(thread_sp), m_frame_index(frame_idx), 590b57cec5SDimitry Andric m_concrete_frame_index(unwind_frame_index), m_reg_context_sp(), 600b57cec5SDimitry Andric m_id(pc, cfa, nullptr), m_frame_code_addr(pc), m_sc(), m_flags(), 610b57cec5SDimitry Andric m_frame_base(), m_frame_base_error(), m_cfa_is_valid(cfa_is_valid), 629dba64beSDimitry Andric m_stack_frame_kind(kind), 639dba64beSDimitry Andric m_behaves_like_zeroth_frame(behaves_like_zeroth_frame), 649dba64beSDimitry Andric m_variable_list_sp(), m_variable_list_value_objects(), 659dba64beSDimitry Andric m_recognized_frame_sp(), m_disassembly(), m_mutex() { 660b57cec5SDimitry Andric // If we don't have a CFA value, use the frame index for our StackID so that 670b57cec5SDimitry Andric // recursive functions properly aren't confused with one another on a history 680b57cec5SDimitry Andric // stack. 690b57cec5SDimitry Andric if (IsHistorical() && !m_cfa_is_valid) { 700b57cec5SDimitry Andric m_id.SetCFA(m_frame_index); 710b57cec5SDimitry Andric } 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric if (sc_ptr != nullptr) { 740b57cec5SDimitry Andric m_sc = *sc_ptr; 750b57cec5SDimitry Andric m_flags.Set(m_sc.GetResolvedMask()); 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, 800b57cec5SDimitry Andric user_id_t unwind_frame_index, 810b57cec5SDimitry Andric const RegisterContextSP ®_context_sp, addr_t cfa, 829dba64beSDimitry Andric addr_t pc, bool behaves_like_zeroth_frame, 839dba64beSDimitry Andric const SymbolContext *sc_ptr) 840b57cec5SDimitry Andric : m_thread_wp(thread_sp), m_frame_index(frame_idx), 850b57cec5SDimitry Andric m_concrete_frame_index(unwind_frame_index), 860b57cec5SDimitry Andric m_reg_context_sp(reg_context_sp), m_id(pc, cfa, nullptr), 870b57cec5SDimitry Andric m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(), 880b57cec5SDimitry Andric m_frame_base_error(), m_cfa_is_valid(true), 899dba64beSDimitry Andric m_stack_frame_kind(StackFrame::Kind::Regular), 909dba64beSDimitry Andric m_behaves_like_zeroth_frame(behaves_like_zeroth_frame), 919dba64beSDimitry Andric m_variable_list_sp(), m_variable_list_value_objects(), 929dba64beSDimitry Andric m_recognized_frame_sp(), m_disassembly(), m_mutex() { 930b57cec5SDimitry Andric if (sc_ptr != nullptr) { 940b57cec5SDimitry Andric m_sc = *sc_ptr; 950b57cec5SDimitry Andric m_flags.Set(m_sc.GetResolvedMask()); 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric if (reg_context_sp && !m_sc.target_sp) { 990b57cec5SDimitry Andric m_sc.target_sp = reg_context_sp->CalculateTarget(); 1000b57cec5SDimitry Andric if (m_sc.target_sp) 1010b57cec5SDimitry Andric m_flags.Set(eSymbolContextTarget); 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, 1060b57cec5SDimitry Andric user_id_t unwind_frame_index, 1070b57cec5SDimitry Andric const RegisterContextSP ®_context_sp, addr_t cfa, 1089dba64beSDimitry Andric const Address &pc_addr, bool behaves_like_zeroth_frame, 1099dba64beSDimitry Andric const SymbolContext *sc_ptr) 1100b57cec5SDimitry Andric : m_thread_wp(thread_sp), m_frame_index(frame_idx), 1110b57cec5SDimitry Andric m_concrete_frame_index(unwind_frame_index), 1120b57cec5SDimitry Andric m_reg_context_sp(reg_context_sp), 1130b57cec5SDimitry Andric m_id(pc_addr.GetLoadAddress(thread_sp->CalculateTarget().get()), cfa, 1140b57cec5SDimitry Andric nullptr), 1150b57cec5SDimitry Andric m_frame_code_addr(pc_addr), m_sc(), m_flags(), m_frame_base(), 1160b57cec5SDimitry Andric m_frame_base_error(), m_cfa_is_valid(true), 1179dba64beSDimitry Andric m_stack_frame_kind(StackFrame::Kind::Regular), 1189dba64beSDimitry Andric m_behaves_like_zeroth_frame(behaves_like_zeroth_frame), 1199dba64beSDimitry Andric m_variable_list_sp(), m_variable_list_value_objects(), 1209dba64beSDimitry Andric m_recognized_frame_sp(), m_disassembly(), m_mutex() { 1210b57cec5SDimitry Andric if (sc_ptr != nullptr) { 1220b57cec5SDimitry Andric m_sc = *sc_ptr; 1230b57cec5SDimitry Andric m_flags.Set(m_sc.GetResolvedMask()); 1240b57cec5SDimitry Andric } 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric if (!m_sc.target_sp && reg_context_sp) { 1270b57cec5SDimitry Andric m_sc.target_sp = reg_context_sp->CalculateTarget(); 1280b57cec5SDimitry Andric if (m_sc.target_sp) 1290b57cec5SDimitry Andric m_flags.Set(eSymbolContextTarget); 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric ModuleSP pc_module_sp(pc_addr.GetModule()); 1330b57cec5SDimitry Andric if (!m_sc.module_sp || m_sc.module_sp != pc_module_sp) { 1340b57cec5SDimitry Andric if (pc_module_sp) { 1350b57cec5SDimitry Andric m_sc.module_sp = pc_module_sp; 1360b57cec5SDimitry Andric m_flags.Set(eSymbolContextModule); 1370b57cec5SDimitry Andric } else { 1380b57cec5SDimitry Andric m_sc.module_sp.reset(); 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric StackFrame::~StackFrame() = default; 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric StackID &StackFrame::GetStackID() { 1460b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 1470b57cec5SDimitry Andric // Make sure we have resolved the StackID object's symbol context scope if we 1480b57cec5SDimitry Andric // already haven't looked it up. 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric if (m_flags.IsClear(RESOLVED_FRAME_ID_SYMBOL_SCOPE)) { 1510b57cec5SDimitry Andric if (m_id.GetSymbolContextScope()) { 1520b57cec5SDimitry Andric // We already have a symbol context scope, we just don't have our flag 1530b57cec5SDimitry Andric // bit set. 1540b57cec5SDimitry Andric m_flags.Set(RESOLVED_FRAME_ID_SYMBOL_SCOPE); 1550b57cec5SDimitry Andric } else { 1560b57cec5SDimitry Andric // Calculate the frame block and use this for the stack ID symbol context 1570b57cec5SDimitry Andric // scope if we have one. 1580b57cec5SDimitry Andric SymbolContextScope *scope = GetFrameBlock(); 1590b57cec5SDimitry Andric if (scope == nullptr) { 1600b57cec5SDimitry Andric // We don't have a block, so use the symbol 1610b57cec5SDimitry Andric if (m_flags.IsClear(eSymbolContextSymbol)) 1620b57cec5SDimitry Andric GetSymbolContext(eSymbolContextSymbol); 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric // It is ok if m_sc.symbol is nullptr here 1650b57cec5SDimitry Andric scope = m_sc.symbol; 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric // Set the symbol context scope (the accessor will set the 1680b57cec5SDimitry Andric // RESOLVED_FRAME_ID_SYMBOL_SCOPE bit in m_flags). 1690b57cec5SDimitry Andric SetSymbolContextScope(scope); 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric } 1720b57cec5SDimitry Andric return m_id; 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric uint32_t StackFrame::GetFrameIndex() const { 1760b57cec5SDimitry Andric ThreadSP thread_sp = GetThread(); 1770b57cec5SDimitry Andric if (thread_sp) 1780b57cec5SDimitry Andric return thread_sp->GetStackFrameList()->GetVisibleStackFrameIndex( 1790b57cec5SDimitry Andric m_frame_index); 1800b57cec5SDimitry Andric else 1810b57cec5SDimitry Andric return m_frame_index; 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric void StackFrame::SetSymbolContextScope(SymbolContextScope *symbol_scope) { 1850b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 1860b57cec5SDimitry Andric m_flags.Set(RESOLVED_FRAME_ID_SYMBOL_SCOPE); 1870b57cec5SDimitry Andric m_id.SetSymbolContextScope(symbol_scope); 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric const Address &StackFrame::GetFrameCodeAddress() { 1910b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 1920b57cec5SDimitry Andric if (m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR) && 1930b57cec5SDimitry Andric !m_frame_code_addr.IsSectionOffset()) { 1940b57cec5SDimitry Andric m_flags.Set(RESOLVED_FRAME_CODE_ADDR); 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric // Resolve the PC into a temporary address because if ResolveLoadAddress 1970b57cec5SDimitry Andric // fails to resolve the address, it will clear the address object... 1980b57cec5SDimitry Andric ThreadSP thread_sp(GetThread()); 1990b57cec5SDimitry Andric if (thread_sp) { 2000b57cec5SDimitry Andric TargetSP target_sp(thread_sp->CalculateTarget()); 2010b57cec5SDimitry Andric if (target_sp) { 2020b57cec5SDimitry Andric const bool allow_section_end = true; 2030b57cec5SDimitry Andric if (m_frame_code_addr.SetOpcodeLoadAddress( 2040b57cec5SDimitry Andric m_frame_code_addr.GetOffset(), target_sp.get(), 2050b57cec5SDimitry Andric AddressClass::eCode, allow_section_end)) { 2060b57cec5SDimitry Andric ModuleSP module_sp(m_frame_code_addr.GetModule()); 2070b57cec5SDimitry Andric if (module_sp) { 2080b57cec5SDimitry Andric m_sc.module_sp = module_sp; 2090b57cec5SDimitry Andric m_flags.Set(eSymbolContextModule); 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric } 2130b57cec5SDimitry Andric } 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric return m_frame_code_addr; 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric 218fe6060f1SDimitry Andric // This can't be rewritten into a call to 219fe6060f1SDimitry Andric // RegisterContext::GetPCForSymbolication because this 220fe6060f1SDimitry Andric // StackFrame may have been constructed with a special pc, 221fe6060f1SDimitry Andric // e.g. tail-call artificial frames. 222fe6060f1SDimitry Andric Address StackFrame::GetFrameCodeAddressForSymbolication() { 223fe6060f1SDimitry Andric Address lookup_addr(GetFrameCodeAddress()); 224fe6060f1SDimitry Andric if (!lookup_addr.IsValid()) 225fe6060f1SDimitry Andric return lookup_addr; 226fe6060f1SDimitry Andric if (m_behaves_like_zeroth_frame) 227fe6060f1SDimitry Andric return lookup_addr; 228fe6060f1SDimitry Andric 229fe6060f1SDimitry Andric addr_t offset = lookup_addr.GetOffset(); 230fe6060f1SDimitry Andric if (offset > 0) { 231fe6060f1SDimitry Andric lookup_addr.SetOffset(offset - 1); 232fe6060f1SDimitry Andric } else { 233fe6060f1SDimitry Andric // lookup_addr is the start of a section. We need do the math on the 234fe6060f1SDimitry Andric // actual load address and re-compute the section. We're working with 235fe6060f1SDimitry Andric // a 'noreturn' function at the end of a section. 236fe6060f1SDimitry Andric TargetSP target_sp = CalculateTarget(); 237fe6060f1SDimitry Andric if (target_sp) { 238fe6060f1SDimitry Andric addr_t addr_minus_one = lookup_addr.GetOpcodeLoadAddress( 239fe6060f1SDimitry Andric target_sp.get(), AddressClass::eCode) - 240fe6060f1SDimitry Andric 1; 241fe6060f1SDimitry Andric lookup_addr.SetOpcodeLoadAddress(addr_minus_one, target_sp.get()); 242fe6060f1SDimitry Andric } 243fe6060f1SDimitry Andric } 244fe6060f1SDimitry Andric return lookup_addr; 245fe6060f1SDimitry Andric } 246fe6060f1SDimitry Andric 2470b57cec5SDimitry Andric bool StackFrame::ChangePC(addr_t pc) { 2480b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 2490b57cec5SDimitry Andric // We can't change the pc value of a history stack frame - it is immutable. 2500b57cec5SDimitry Andric if (IsHistorical()) 2510b57cec5SDimitry Andric return false; 2520b57cec5SDimitry Andric m_frame_code_addr.SetRawAddress(pc); 2530b57cec5SDimitry Andric m_sc.Clear(false); 2540b57cec5SDimitry Andric m_flags.Reset(0); 2550b57cec5SDimitry Andric ThreadSP thread_sp(GetThread()); 2560b57cec5SDimitry Andric if (thread_sp) 2570b57cec5SDimitry Andric thread_sp->ClearStackFrames(); 2580b57cec5SDimitry Andric return true; 2590b57cec5SDimitry Andric } 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric const char *StackFrame::Disassemble() { 2620b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 263e8d8bef9SDimitry Andric if (!m_disassembly.Empty()) 264e8d8bef9SDimitry Andric return m_disassembly.GetData(); 265e8d8bef9SDimitry Andric 2660b57cec5SDimitry Andric ExecutionContext exe_ctx(shared_from_this()); 267e8d8bef9SDimitry Andric if (Target *target = exe_ctx.GetTargetPtr()) { 268e8d8bef9SDimitry Andric Disassembler::Disassemble(target->GetDebugger(), target->GetArchitecture(), 269e8d8bef9SDimitry Andric *this, m_disassembly); 2700b57cec5SDimitry Andric } 2710b57cec5SDimitry Andric 272e8d8bef9SDimitry Andric return m_disassembly.Empty() ? nullptr : m_disassembly.GetData(); 2730b57cec5SDimitry Andric } 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric Block *StackFrame::GetFrameBlock() { 2760b57cec5SDimitry Andric if (m_sc.block == nullptr && m_flags.IsClear(eSymbolContextBlock)) 2770b57cec5SDimitry Andric GetSymbolContext(eSymbolContextBlock); 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric if (m_sc.block) { 2800b57cec5SDimitry Andric Block *inline_block = m_sc.block->GetContainingInlinedBlock(); 2810b57cec5SDimitry Andric if (inline_block) { 2820b57cec5SDimitry Andric // Use the block with the inlined function info as the frame block we 2830b57cec5SDimitry Andric // want this frame to have only the variables for the inlined function 2840b57cec5SDimitry Andric // and its non-inlined block child blocks. 2850b57cec5SDimitry Andric return inline_block; 2860b57cec5SDimitry Andric } else { 2870b57cec5SDimitry Andric // This block is not contained within any inlined function blocks with so 2880b57cec5SDimitry Andric // we want to use the top most function block. 2890b57cec5SDimitry Andric return &m_sc.function->GetBlock(false); 2900b57cec5SDimitry Andric } 2910b57cec5SDimitry Andric } 2920b57cec5SDimitry Andric return nullptr; 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric // Get the symbol context if we already haven't done so by resolving the 2960b57cec5SDimitry Andric // PC address as much as possible. This way when we pass around a 2970b57cec5SDimitry Andric // StackFrame object, everyone will have as much information as possible and no 2980b57cec5SDimitry Andric // one will ever have to look things up manually. 2990b57cec5SDimitry Andric const SymbolContext & 3000b57cec5SDimitry Andric StackFrame::GetSymbolContext(SymbolContextItem resolve_scope) { 3010b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 3020b57cec5SDimitry Andric // Copy our internal symbol context into "sc". 3030b57cec5SDimitry Andric if ((m_flags.Get() & resolve_scope) != resolve_scope) { 3040b57cec5SDimitry Andric uint32_t resolved = 0; 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andric // If the target was requested add that: 3070b57cec5SDimitry Andric if (!m_sc.target_sp) { 3080b57cec5SDimitry Andric m_sc.target_sp = CalculateTarget(); 3090b57cec5SDimitry Andric if (m_sc.target_sp) 3100b57cec5SDimitry Andric resolved |= eSymbolContextTarget; 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric // Resolve our PC to section offset if we haven't already done so and if we 3140b57cec5SDimitry Andric // don't have a module. The resolved address section will contain the 3150b57cec5SDimitry Andric // module to which it belongs 3160b57cec5SDimitry Andric if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR)) 3170b57cec5SDimitry Andric GetFrameCodeAddress(); 3180b57cec5SDimitry Andric 3190b57cec5SDimitry Andric // If this is not frame zero, then we need to subtract 1 from the PC value 3200b57cec5SDimitry Andric // when doing address lookups since the PC will be on the instruction 3210b57cec5SDimitry Andric // following the function call instruction... 322fe6060f1SDimitry Andric Address lookup_addr(GetFrameCodeAddressForSymbolication()); 3230b57cec5SDimitry Andric 3240b57cec5SDimitry Andric if (m_sc.module_sp) { 3250b57cec5SDimitry Andric // We have something in our stack frame symbol context, lets check if we 3260b57cec5SDimitry Andric // haven't already tried to lookup one of those things. If we haven't 3270b57cec5SDimitry Andric // then we will do the query. 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric SymbolContextItem actual_resolve_scope = SymbolContextItem(0); 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric if (resolve_scope & eSymbolContextCompUnit) { 3320b57cec5SDimitry Andric if (m_flags.IsClear(eSymbolContextCompUnit)) { 3330b57cec5SDimitry Andric if (m_sc.comp_unit) 3340b57cec5SDimitry Andric resolved |= eSymbolContextCompUnit; 3350b57cec5SDimitry Andric else 3360b57cec5SDimitry Andric actual_resolve_scope |= eSymbolContextCompUnit; 3370b57cec5SDimitry Andric } 3380b57cec5SDimitry Andric } 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric if (resolve_scope & eSymbolContextFunction) { 3410b57cec5SDimitry Andric if (m_flags.IsClear(eSymbolContextFunction)) { 3420b57cec5SDimitry Andric if (m_sc.function) 3430b57cec5SDimitry Andric resolved |= eSymbolContextFunction; 3440b57cec5SDimitry Andric else 3450b57cec5SDimitry Andric actual_resolve_scope |= eSymbolContextFunction; 3460b57cec5SDimitry Andric } 3470b57cec5SDimitry Andric } 3480b57cec5SDimitry Andric 3490b57cec5SDimitry Andric if (resolve_scope & eSymbolContextBlock) { 3500b57cec5SDimitry Andric if (m_flags.IsClear(eSymbolContextBlock)) { 3510b57cec5SDimitry Andric if (m_sc.block) 3520b57cec5SDimitry Andric resolved |= eSymbolContextBlock; 3530b57cec5SDimitry Andric else 3540b57cec5SDimitry Andric actual_resolve_scope |= eSymbolContextBlock; 3550b57cec5SDimitry Andric } 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric if (resolve_scope & eSymbolContextSymbol) { 3590b57cec5SDimitry Andric if (m_flags.IsClear(eSymbolContextSymbol)) { 3600b57cec5SDimitry Andric if (m_sc.symbol) 3610b57cec5SDimitry Andric resolved |= eSymbolContextSymbol; 3620b57cec5SDimitry Andric else 3630b57cec5SDimitry Andric actual_resolve_scope |= eSymbolContextSymbol; 3640b57cec5SDimitry Andric } 3650b57cec5SDimitry Andric } 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andric if (resolve_scope & eSymbolContextLineEntry) { 3680b57cec5SDimitry Andric if (m_flags.IsClear(eSymbolContextLineEntry)) { 3690b57cec5SDimitry Andric if (m_sc.line_entry.IsValid()) 3700b57cec5SDimitry Andric resolved |= eSymbolContextLineEntry; 3710b57cec5SDimitry Andric else 3720b57cec5SDimitry Andric actual_resolve_scope |= eSymbolContextLineEntry; 3730b57cec5SDimitry Andric } 3740b57cec5SDimitry Andric } 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric if (actual_resolve_scope) { 3770b57cec5SDimitry Andric // We might be resolving less information than what is already in our 3780b57cec5SDimitry Andric // current symbol context so resolve into a temporary symbol context 3790b57cec5SDimitry Andric // "sc" so we don't clear out data we have already found in "m_sc" 3800b57cec5SDimitry Andric SymbolContext sc; 3810b57cec5SDimitry Andric // Set flags that indicate what we have tried to resolve 3820b57cec5SDimitry Andric resolved |= m_sc.module_sp->ResolveSymbolContextForAddress( 3830b57cec5SDimitry Andric lookup_addr, actual_resolve_scope, sc); 3840b57cec5SDimitry Andric // Only replace what we didn't already have as we may have information 3850b57cec5SDimitry Andric // for an inlined function scope that won't match what a standard 3860b57cec5SDimitry Andric // lookup by address would match 3870b57cec5SDimitry Andric if ((resolved & eSymbolContextCompUnit) && m_sc.comp_unit == nullptr) 3880b57cec5SDimitry Andric m_sc.comp_unit = sc.comp_unit; 3890b57cec5SDimitry Andric if ((resolved & eSymbolContextFunction) && m_sc.function == nullptr) 3900b57cec5SDimitry Andric m_sc.function = sc.function; 3910b57cec5SDimitry Andric if ((resolved & eSymbolContextBlock) && m_sc.block == nullptr) 3920b57cec5SDimitry Andric m_sc.block = sc.block; 3930b57cec5SDimitry Andric if ((resolved & eSymbolContextSymbol) && m_sc.symbol == nullptr) 3940b57cec5SDimitry Andric m_sc.symbol = sc.symbol; 3950b57cec5SDimitry Andric if ((resolved & eSymbolContextLineEntry) && 3960b57cec5SDimitry Andric !m_sc.line_entry.IsValid()) { 3970b57cec5SDimitry Andric m_sc.line_entry = sc.line_entry; 3980b57cec5SDimitry Andric m_sc.line_entry.ApplyFileMappings(m_sc.target_sp); 3990b57cec5SDimitry Andric } 4000b57cec5SDimitry Andric } 4010b57cec5SDimitry Andric } else { 4020b57cec5SDimitry Andric // If we don't have a module, then we can't have the compile unit, 4030b57cec5SDimitry Andric // function, block, line entry or symbol, so we can safely call 4040b57cec5SDimitry Andric // ResolveSymbolContextForAddress with our symbol context member m_sc. 4050b57cec5SDimitry Andric if (m_sc.target_sp) { 4060b57cec5SDimitry Andric resolved |= m_sc.target_sp->GetImages().ResolveSymbolContextForAddress( 4070b57cec5SDimitry Andric lookup_addr, resolve_scope, m_sc); 4080b57cec5SDimitry Andric } 4090b57cec5SDimitry Andric } 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric // Update our internal flags so we remember what we have tried to locate so 4120b57cec5SDimitry Andric // we don't have to keep trying when more calls to this function are made. 4130b57cec5SDimitry Andric // We might have dug up more information that was requested (for example if 4140b57cec5SDimitry Andric // we were asked to only get the block, we will have gotten the compile 4150b57cec5SDimitry Andric // unit, and function) so set any additional bits that we resolved 4160b57cec5SDimitry Andric m_flags.Set(resolve_scope | resolved); 4170b57cec5SDimitry Andric } 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric // Return the symbol context with everything that was possible to resolve 4200b57cec5SDimitry Andric // resolved. 4210b57cec5SDimitry Andric return m_sc; 4220b57cec5SDimitry Andric } 4230b57cec5SDimitry Andric 424bdd1243dSDimitry Andric VariableList *StackFrame::GetVariableList(bool get_file_globals, 425bdd1243dSDimitry Andric Status *error_ptr) { 4260b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 4270b57cec5SDimitry Andric if (m_flags.IsClear(RESOLVED_VARIABLES)) { 4280b57cec5SDimitry Andric m_flags.Set(RESOLVED_VARIABLES); 429bdd1243dSDimitry Andric m_variable_list_sp = std::make_shared<VariableList>(); 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric Block *frame_block = GetFrameBlock(); 4320b57cec5SDimitry Andric 4330b57cec5SDimitry Andric if (frame_block) { 4340b57cec5SDimitry Andric const bool get_child_variables = true; 4350b57cec5SDimitry Andric const bool can_create = true; 4360b57cec5SDimitry Andric const bool stop_if_child_block_is_inlined_function = true; 4370b57cec5SDimitry Andric frame_block->AppendBlockVariables(can_create, get_child_variables, 4380b57cec5SDimitry Andric stop_if_child_block_is_inlined_function, 4390b57cec5SDimitry Andric [](Variable *v) { return true; }, 4400b57cec5SDimitry Andric m_variable_list_sp.get()); 4410b57cec5SDimitry Andric } 4420b57cec5SDimitry Andric } 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric if (m_flags.IsClear(RESOLVED_GLOBAL_VARIABLES) && get_file_globals) { 4450b57cec5SDimitry Andric m_flags.Set(RESOLVED_GLOBAL_VARIABLES); 4460b57cec5SDimitry Andric 4470b57cec5SDimitry Andric if (m_flags.IsClear(eSymbolContextCompUnit)) 4480b57cec5SDimitry Andric GetSymbolContext(eSymbolContextCompUnit); 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andric if (m_sc.comp_unit) { 4510b57cec5SDimitry Andric VariableListSP global_variable_list_sp( 4520b57cec5SDimitry Andric m_sc.comp_unit->GetVariableList(true)); 4530b57cec5SDimitry Andric if (m_variable_list_sp) 4540b57cec5SDimitry Andric m_variable_list_sp->AddVariables(global_variable_list_sp.get()); 4550b57cec5SDimitry Andric else 4560b57cec5SDimitry Andric m_variable_list_sp = global_variable_list_sp; 4570b57cec5SDimitry Andric } 4580b57cec5SDimitry Andric } 4590b57cec5SDimitry Andric 460bdd1243dSDimitry Andric if (error_ptr && m_variable_list_sp->GetSize() == 0) { 461bdd1243dSDimitry Andric // Check with the symbol file to check if there is an error for why we 462bdd1243dSDimitry Andric // don't have variables that the user might need to know about. 463bdd1243dSDimitry Andric GetSymbolContext(eSymbolContextEverything); 464bdd1243dSDimitry Andric if (m_sc.module_sp) { 465bdd1243dSDimitry Andric SymbolFile *sym_file = m_sc.module_sp->GetSymbolFile(); 466bdd1243dSDimitry Andric if (sym_file) 467bdd1243dSDimitry Andric *error_ptr = sym_file->GetFrameVariableError(*this); 468bdd1243dSDimitry Andric } 469bdd1243dSDimitry Andric } 470bdd1243dSDimitry Andric 4710b57cec5SDimitry Andric return m_variable_list_sp.get(); 4720b57cec5SDimitry Andric } 4730b57cec5SDimitry Andric 4740b57cec5SDimitry Andric VariableListSP 4750b57cec5SDimitry Andric StackFrame::GetInScopeVariableList(bool get_file_globals, 4760b57cec5SDimitry Andric bool must_have_valid_location) { 4770b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 4780b57cec5SDimitry Andric // We can't fetch variable information for a history stack frame. 4790b57cec5SDimitry Andric if (IsHistorical()) 4800b57cec5SDimitry Andric return VariableListSP(); 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric VariableListSP var_list_sp(new VariableList); 4830b57cec5SDimitry Andric GetSymbolContext(eSymbolContextCompUnit | eSymbolContextBlock); 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric if (m_sc.block) { 4860b57cec5SDimitry Andric const bool can_create = true; 4870b57cec5SDimitry Andric const bool get_parent_variables = true; 4880b57cec5SDimitry Andric const bool stop_if_block_is_inlined_function = true; 4890b57cec5SDimitry Andric m_sc.block->AppendVariables( 4900b57cec5SDimitry Andric can_create, get_parent_variables, stop_if_block_is_inlined_function, 4910b57cec5SDimitry Andric [this, must_have_valid_location](Variable *v) { 4920b57cec5SDimitry Andric return v->IsInScope(this) && (!must_have_valid_location || 4930b57cec5SDimitry Andric v->LocationIsValidForFrame(this)); 4940b57cec5SDimitry Andric }, 4950b57cec5SDimitry Andric var_list_sp.get()); 4960b57cec5SDimitry Andric } 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric if (m_sc.comp_unit && get_file_globals) { 4990b57cec5SDimitry Andric VariableListSP global_variable_list_sp( 5000b57cec5SDimitry Andric m_sc.comp_unit->GetVariableList(true)); 5010b57cec5SDimitry Andric if (global_variable_list_sp) 5020b57cec5SDimitry Andric var_list_sp->AddVariables(global_variable_list_sp.get()); 5030b57cec5SDimitry Andric } 5040b57cec5SDimitry Andric 5050b57cec5SDimitry Andric return var_list_sp; 5060b57cec5SDimitry Andric } 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andric ValueObjectSP StackFrame::GetValueForVariableExpressionPath( 5090b57cec5SDimitry Andric llvm::StringRef var_expr, DynamicValueType use_dynamic, uint32_t options, 5100b57cec5SDimitry Andric VariableSP &var_sp, Status &error) { 5110b57cec5SDimitry Andric llvm::StringRef original_var_expr = var_expr; 5120b57cec5SDimitry Andric // We can't fetch variable information for a history stack frame. 5130b57cec5SDimitry Andric if (IsHistorical()) 5140b57cec5SDimitry Andric return ValueObjectSP(); 5150b57cec5SDimitry Andric 5160b57cec5SDimitry Andric if (var_expr.empty()) { 5170b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid variable path '%s'", 5180b57cec5SDimitry Andric var_expr.str().c_str()); 5190b57cec5SDimitry Andric return ValueObjectSP(); 5200b57cec5SDimitry Andric } 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric const bool check_ptr_vs_member = 5230b57cec5SDimitry Andric (options & eExpressionPathOptionCheckPtrVsMember) != 0; 5240b57cec5SDimitry Andric const bool no_fragile_ivar = 5250b57cec5SDimitry Andric (options & eExpressionPathOptionsNoFragileObjcIvar) != 0; 5260b57cec5SDimitry Andric const bool no_synth_child = 5270b57cec5SDimitry Andric (options & eExpressionPathOptionsNoSyntheticChildren) != 0; 5280b57cec5SDimitry Andric // const bool no_synth_array = (options & 5290b57cec5SDimitry Andric // eExpressionPathOptionsNoSyntheticArrayRange) != 0; 5300b57cec5SDimitry Andric error.Clear(); 5310b57cec5SDimitry Andric bool deref = false; 5320b57cec5SDimitry Andric bool address_of = false; 5330b57cec5SDimitry Andric ValueObjectSP valobj_sp; 5340b57cec5SDimitry Andric const bool get_file_globals = true; 5350b57cec5SDimitry Andric // When looking up a variable for an expression, we need only consider the 5360b57cec5SDimitry Andric // variables that are in scope. 5370b57cec5SDimitry Andric VariableListSP var_list_sp(GetInScopeVariableList(get_file_globals)); 5380b57cec5SDimitry Andric VariableList *variable_list = var_list_sp.get(); 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric if (!variable_list) 5410b57cec5SDimitry Andric return ValueObjectSP(); 5420b57cec5SDimitry Andric 5430b57cec5SDimitry Andric // If first character is a '*', then show pointer contents 5440b57cec5SDimitry Andric std::string var_expr_storage; 5450b57cec5SDimitry Andric if (var_expr[0] == '*') { 5460b57cec5SDimitry Andric deref = true; 5470b57cec5SDimitry Andric var_expr = var_expr.drop_front(); // Skip the '*' 5480b57cec5SDimitry Andric } else if (var_expr[0] == '&') { 5490b57cec5SDimitry Andric address_of = true; 5500b57cec5SDimitry Andric var_expr = var_expr.drop_front(); // Skip the '&' 5510b57cec5SDimitry Andric } 5520b57cec5SDimitry Andric 5530b57cec5SDimitry Andric size_t separator_idx = var_expr.find_first_of(".-[=+~|&^%#@!/?,<>{}"); 5540b57cec5SDimitry Andric StreamString var_expr_path_strm; 5550b57cec5SDimitry Andric 5560b57cec5SDimitry Andric ConstString name_const_string(var_expr.substr(0, separator_idx)); 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andric var_sp = variable_list->FindVariable(name_const_string, false); 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andric bool synthetically_added_instance_object = false; 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric if (var_sp) { 5630b57cec5SDimitry Andric var_expr = var_expr.drop_front(name_const_string.GetLength()); 5640b57cec5SDimitry Andric } 5650b57cec5SDimitry Andric 5660b57cec5SDimitry Andric if (!var_sp && (options & eExpressionPathOptionsAllowDirectIVarAccess)) { 5670b57cec5SDimitry Andric // Check for direct ivars access which helps us with implicit access to 56881ad6265SDimitry Andric // ivars using "this" or "self". 5690b57cec5SDimitry Andric GetSymbolContext(eSymbolContextFunction | eSymbolContextBlock); 57006c3fb27SDimitry Andric llvm::StringRef instance_var_name = m_sc.GetInstanceVariableName(); 57106c3fb27SDimitry Andric if (!instance_var_name.empty()) { 57206c3fb27SDimitry Andric var_sp = variable_list->FindVariable(ConstString(instance_var_name)); 5730b57cec5SDimitry Andric if (var_sp) { 5740b57cec5SDimitry Andric separator_idx = 0; 57581ad6265SDimitry Andric if (Type *var_type = var_sp->GetType()) 57681ad6265SDimitry Andric if (auto compiler_type = var_type->GetForwardCompilerType()) 57781ad6265SDimitry Andric if (!compiler_type.IsPointerType()) 57881ad6265SDimitry Andric var_expr_storage = "."; 57981ad6265SDimitry Andric 58081ad6265SDimitry Andric if (var_expr_storage.empty()) 5810b57cec5SDimitry Andric var_expr_storage = "->"; 5820b57cec5SDimitry Andric var_expr_storage += var_expr; 5830b57cec5SDimitry Andric var_expr = var_expr_storage; 5840b57cec5SDimitry Andric synthetically_added_instance_object = true; 5850b57cec5SDimitry Andric } 5860b57cec5SDimitry Andric } 5870b57cec5SDimitry Andric } 5880b57cec5SDimitry Andric 5890b57cec5SDimitry Andric if (!var_sp && (options & eExpressionPathOptionsInspectAnonymousUnions)) { 5900b57cec5SDimitry Andric // Check if any anonymous unions are there which contain a variable with 5910b57cec5SDimitry Andric // the name we need 592480093f4SDimitry Andric for (const VariableSP &variable_sp : *variable_list) { 5930b57cec5SDimitry Andric if (!variable_sp) 5940b57cec5SDimitry Andric continue; 5950b57cec5SDimitry Andric if (!variable_sp->GetName().IsEmpty()) 5960b57cec5SDimitry Andric continue; 5970b57cec5SDimitry Andric 5980b57cec5SDimitry Andric Type *var_type = variable_sp->GetType(); 5990b57cec5SDimitry Andric if (!var_type) 6000b57cec5SDimitry Andric continue; 6010b57cec5SDimitry Andric 6020b57cec5SDimitry Andric if (!var_type->GetForwardCompilerType().IsAnonymousType()) 6030b57cec5SDimitry Andric continue; 6040b57cec5SDimitry Andric valobj_sp = GetValueObjectForFrameVariable(variable_sp, use_dynamic); 6050b57cec5SDimitry Andric if (!valobj_sp) 6060b57cec5SDimitry Andric return valobj_sp; 60706c3fb27SDimitry Andric valobj_sp = valobj_sp->GetChildMemberWithName(name_const_string); 6080b57cec5SDimitry Andric if (valobj_sp) 6090b57cec5SDimitry Andric break; 6100b57cec5SDimitry Andric } 6110b57cec5SDimitry Andric } 6120b57cec5SDimitry Andric 6130b57cec5SDimitry Andric if (var_sp && !valobj_sp) { 6140b57cec5SDimitry Andric valobj_sp = GetValueObjectForFrameVariable(var_sp, use_dynamic); 6150b57cec5SDimitry Andric if (!valobj_sp) 6160b57cec5SDimitry Andric return valobj_sp; 6170b57cec5SDimitry Andric } 6180b57cec5SDimitry Andric if (!valobj_sp) { 6190b57cec5SDimitry Andric error.SetErrorStringWithFormat("no variable named '%s' found in this frame", 6200b57cec5SDimitry Andric name_const_string.GetCString()); 6210b57cec5SDimitry Andric return ValueObjectSP(); 6220b57cec5SDimitry Andric } 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andric // We are dumping at least one child 6255ffd83dbSDimitry Andric while (!var_expr.empty()) { 6260b57cec5SDimitry Andric // Calculate the next separator index ahead of time 6270b57cec5SDimitry Andric ValueObjectSP child_valobj_sp; 6280b57cec5SDimitry Andric const char separator_type = var_expr[0]; 6290b57cec5SDimitry Andric bool expr_is_ptr = false; 6300b57cec5SDimitry Andric switch (separator_type) { 6310b57cec5SDimitry Andric case '-': 6320b57cec5SDimitry Andric expr_is_ptr = true; 6330b57cec5SDimitry Andric if (var_expr.size() >= 2 && var_expr[1] != '>') 6340b57cec5SDimitry Andric return ValueObjectSP(); 6350b57cec5SDimitry Andric 6360b57cec5SDimitry Andric if (no_fragile_ivar) { 6370b57cec5SDimitry Andric // Make sure we aren't trying to deref an objective 6380b57cec5SDimitry Andric // C ivar if this is not allowed 6390b57cec5SDimitry Andric const uint32_t pointer_type_flags = 6400b57cec5SDimitry Andric valobj_sp->GetCompilerType().GetTypeInfo(nullptr); 6410b57cec5SDimitry Andric if ((pointer_type_flags & eTypeIsObjC) && 6420b57cec5SDimitry Andric (pointer_type_flags & eTypeIsPointer)) { 6430b57cec5SDimitry Andric // This was an objective C object pointer and it was requested we 6440b57cec5SDimitry Andric // skip any fragile ivars so return nothing here 6450b57cec5SDimitry Andric return ValueObjectSP(); 6460b57cec5SDimitry Andric } 6470b57cec5SDimitry Andric } 6480b57cec5SDimitry Andric 6490b57cec5SDimitry Andric // If we have a non pointer type with a sythetic value then lets check if 6500b57cec5SDimitry Andric // we have an sythetic dereference specified. 6510b57cec5SDimitry Andric if (!valobj_sp->IsPointerType() && valobj_sp->HasSyntheticValue()) { 6520b57cec5SDimitry Andric Status deref_error; 6530b57cec5SDimitry Andric if (valobj_sp->GetCompilerType().IsReferenceType()) { 6540b57cec5SDimitry Andric valobj_sp = valobj_sp->GetSyntheticValue()->Dereference(deref_error); 6555f757f3fSDimitry Andric if (!valobj_sp || deref_error.Fail()) { 6560b57cec5SDimitry Andric error.SetErrorStringWithFormatv( 6570b57cec5SDimitry Andric "Failed to dereference reference type: %s", deref_error); 6580b57cec5SDimitry Andric return ValueObjectSP(); 6590b57cec5SDimitry Andric } 6600b57cec5SDimitry Andric } 6610b57cec5SDimitry Andric 6620b57cec5SDimitry Andric valobj_sp = valobj_sp->Dereference(deref_error); 6635f757f3fSDimitry Andric if (!valobj_sp || deref_error.Fail()) { 6640b57cec5SDimitry Andric error.SetErrorStringWithFormatv( 6650b57cec5SDimitry Andric "Failed to dereference sythetic value: {0}", deref_error); 6660b57cec5SDimitry Andric return ValueObjectSP(); 6670b57cec5SDimitry Andric } 6680b57cec5SDimitry Andric // Some synthetic plug-ins fail to set the error in Dereference 6690b57cec5SDimitry Andric if (!valobj_sp) { 6700b57cec5SDimitry Andric error.SetErrorString("Failed to dereference sythetic value"); 6710b57cec5SDimitry Andric return ValueObjectSP(); 6720b57cec5SDimitry Andric } 6730b57cec5SDimitry Andric expr_is_ptr = false; 6740b57cec5SDimitry Andric } 6750b57cec5SDimitry Andric 6760b57cec5SDimitry Andric var_expr = var_expr.drop_front(); // Remove the '-' 677bdd1243dSDimitry Andric [[fallthrough]]; 6780b57cec5SDimitry Andric case '.': { 6790b57cec5SDimitry Andric var_expr = var_expr.drop_front(); // Remove the '.' or '>' 6800b57cec5SDimitry Andric separator_idx = var_expr.find_first_of(".-["); 6810b57cec5SDimitry Andric ConstString child_name(var_expr.substr(0, var_expr.find_first_of(".-["))); 6820b57cec5SDimitry Andric 6830b57cec5SDimitry Andric if (check_ptr_vs_member) { 6840b57cec5SDimitry Andric // We either have a pointer type and need to verify valobj_sp is a 6850b57cec5SDimitry Andric // pointer, or we have a member of a class/union/struct being accessed 6860b57cec5SDimitry Andric // with the . syntax and need to verify we don't have a pointer. 6870b57cec5SDimitry Andric const bool actual_is_ptr = valobj_sp->IsPointerType(); 6880b57cec5SDimitry Andric 6890b57cec5SDimitry Andric if (actual_is_ptr != expr_is_ptr) { 6900b57cec5SDimitry Andric // Incorrect use of "." with a pointer, or "->" with a 6910b57cec5SDimitry Andric // class/union/struct instance or reference. 6925ffd83dbSDimitry Andric valobj_sp->GetExpressionPath(var_expr_path_strm); 6930b57cec5SDimitry Andric if (actual_is_ptr) 6940b57cec5SDimitry Andric error.SetErrorStringWithFormat( 6950b57cec5SDimitry Andric "\"%s\" is a pointer and . was used to attempt to access " 6960b57cec5SDimitry Andric "\"%s\". Did you mean \"%s->%s\"?", 6970b57cec5SDimitry Andric var_expr_path_strm.GetData(), child_name.GetCString(), 6980b57cec5SDimitry Andric var_expr_path_strm.GetData(), var_expr.str().c_str()); 6990b57cec5SDimitry Andric else 7000b57cec5SDimitry Andric error.SetErrorStringWithFormat( 7010b57cec5SDimitry Andric "\"%s\" is not a pointer and -> was used to attempt to " 7020b57cec5SDimitry Andric "access \"%s\". Did you mean \"%s.%s\"?", 7030b57cec5SDimitry Andric var_expr_path_strm.GetData(), child_name.GetCString(), 7040b57cec5SDimitry Andric var_expr_path_strm.GetData(), var_expr.str().c_str()); 7050b57cec5SDimitry Andric return ValueObjectSP(); 7060b57cec5SDimitry Andric } 7070b57cec5SDimitry Andric } 70806c3fb27SDimitry Andric child_valobj_sp = valobj_sp->GetChildMemberWithName(child_name); 7090b57cec5SDimitry Andric if (!child_valobj_sp) { 7100b57cec5SDimitry Andric if (!no_synth_child) { 7110b57cec5SDimitry Andric child_valobj_sp = valobj_sp->GetSyntheticValue(); 7120b57cec5SDimitry Andric if (child_valobj_sp) 7130b57cec5SDimitry Andric child_valobj_sp = 71406c3fb27SDimitry Andric child_valobj_sp->GetChildMemberWithName(child_name); 7150b57cec5SDimitry Andric } 7160b57cec5SDimitry Andric 7170b57cec5SDimitry Andric if (no_synth_child || !child_valobj_sp) { 7180b57cec5SDimitry Andric // No child member with name "child_name" 7190b57cec5SDimitry Andric if (synthetically_added_instance_object) { 7200b57cec5SDimitry Andric // We added a "this->" or "self->" to the beginning of the 7210b57cec5SDimitry Andric // expression and this is the first pointer ivar access, so just 7220b57cec5SDimitry Andric // return the normal error 7230b57cec5SDimitry Andric error.SetErrorStringWithFormat( 7240b57cec5SDimitry Andric "no variable or instance variable named '%s' found in " 7250b57cec5SDimitry Andric "this frame", 7260b57cec5SDimitry Andric name_const_string.GetCString()); 7270b57cec5SDimitry Andric } else { 7285ffd83dbSDimitry Andric valobj_sp->GetExpressionPath(var_expr_path_strm); 7290b57cec5SDimitry Andric if (child_name) { 7300b57cec5SDimitry Andric error.SetErrorStringWithFormat( 7310b57cec5SDimitry Andric "\"%s\" is not a member of \"(%s) %s\"", 7320b57cec5SDimitry Andric child_name.GetCString(), 7330b57cec5SDimitry Andric valobj_sp->GetTypeName().AsCString("<invalid type>"), 7340b57cec5SDimitry Andric var_expr_path_strm.GetData()); 7350b57cec5SDimitry Andric } else { 7360b57cec5SDimitry Andric error.SetErrorStringWithFormat( 7370b57cec5SDimitry Andric "incomplete expression path after \"%s\" in \"%s\"", 7380b57cec5SDimitry Andric var_expr_path_strm.GetData(), 7390b57cec5SDimitry Andric original_var_expr.str().c_str()); 7400b57cec5SDimitry Andric } 7410b57cec5SDimitry Andric } 7420b57cec5SDimitry Andric return ValueObjectSP(); 7430b57cec5SDimitry Andric } 7440b57cec5SDimitry Andric } 7450b57cec5SDimitry Andric synthetically_added_instance_object = false; 7460b57cec5SDimitry Andric // Remove the child name from the path 7470b57cec5SDimitry Andric var_expr = var_expr.drop_front(child_name.GetLength()); 7480b57cec5SDimitry Andric if (use_dynamic != eNoDynamicValues) { 7490b57cec5SDimitry Andric ValueObjectSP dynamic_value_sp( 7500b57cec5SDimitry Andric child_valobj_sp->GetDynamicValue(use_dynamic)); 7510b57cec5SDimitry Andric if (dynamic_value_sp) 7520b57cec5SDimitry Andric child_valobj_sp = dynamic_value_sp; 7530b57cec5SDimitry Andric } 7540b57cec5SDimitry Andric } break; 7550b57cec5SDimitry Andric 7560b57cec5SDimitry Andric case '[': { 7570b57cec5SDimitry Andric // Array member access, or treating pointer as an array Need at least two 7580b57cec5SDimitry Andric // brackets and a number 7590b57cec5SDimitry Andric if (var_expr.size() <= 2) { 7600b57cec5SDimitry Andric error.SetErrorStringWithFormat( 7610b57cec5SDimitry Andric "invalid square bracket encountered after \"%s\" in \"%s\"", 7620b57cec5SDimitry Andric var_expr_path_strm.GetData(), var_expr.str().c_str()); 7630b57cec5SDimitry Andric return ValueObjectSP(); 7640b57cec5SDimitry Andric } 7650b57cec5SDimitry Andric 7660b57cec5SDimitry Andric // Drop the open brace. 7670b57cec5SDimitry Andric var_expr = var_expr.drop_front(); 7680b57cec5SDimitry Andric long child_index = 0; 7690b57cec5SDimitry Andric 7700b57cec5SDimitry Andric // If there's no closing brace, this is an invalid expression. 7710b57cec5SDimitry Andric size_t end_pos = var_expr.find_first_of(']'); 7720b57cec5SDimitry Andric if (end_pos == llvm::StringRef::npos) { 7730b57cec5SDimitry Andric error.SetErrorStringWithFormat( 7740b57cec5SDimitry Andric "missing closing square bracket in expression \"%s\"", 7750b57cec5SDimitry Andric var_expr_path_strm.GetData()); 7760b57cec5SDimitry Andric return ValueObjectSP(); 7770b57cec5SDimitry Andric } 7780b57cec5SDimitry Andric llvm::StringRef index_expr = var_expr.take_front(end_pos); 7790b57cec5SDimitry Andric llvm::StringRef original_index_expr = index_expr; 7800b57cec5SDimitry Andric // Drop all of "[index_expr]" 7810b57cec5SDimitry Andric var_expr = var_expr.drop_front(end_pos + 1); 7820b57cec5SDimitry Andric 7830b57cec5SDimitry Andric if (index_expr.consumeInteger(0, child_index)) { 7840b57cec5SDimitry Andric // If there was no integer anywhere in the index expression, this is 7850b57cec5SDimitry Andric // erroneous expression. 7860b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid index expression \"%s\"", 7870b57cec5SDimitry Andric index_expr.str().c_str()); 7880b57cec5SDimitry Andric return ValueObjectSP(); 7890b57cec5SDimitry Andric } 7900b57cec5SDimitry Andric 7910b57cec5SDimitry Andric if (index_expr.empty()) { 7920b57cec5SDimitry Andric // The entire index expression was a single integer. 7930b57cec5SDimitry Andric 7940b57cec5SDimitry Andric if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) { 7950b57cec5SDimitry Andric // what we have is *ptr[low]. the most similar C++ syntax is to deref 7960b57cec5SDimitry Andric // ptr and extract bit low out of it. reading array item low would be 7970b57cec5SDimitry Andric // done by saying ptr[low], without a deref * sign 7985f757f3fSDimitry Andric Status deref_error; 7995f757f3fSDimitry Andric ValueObjectSP temp(valobj_sp->Dereference(deref_error)); 8005f757f3fSDimitry Andric if (!temp || deref_error.Fail()) { 8015ffd83dbSDimitry Andric valobj_sp->GetExpressionPath(var_expr_path_strm); 8020b57cec5SDimitry Andric error.SetErrorStringWithFormat( 8030b57cec5SDimitry Andric "could not dereference \"(%s) %s\"", 8040b57cec5SDimitry Andric valobj_sp->GetTypeName().AsCString("<invalid type>"), 8050b57cec5SDimitry Andric var_expr_path_strm.GetData()); 8060b57cec5SDimitry Andric return ValueObjectSP(); 8070b57cec5SDimitry Andric } 8080b57cec5SDimitry Andric valobj_sp = temp; 8090b57cec5SDimitry Andric deref = false; 8100b57cec5SDimitry Andric } else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() && 8110b57cec5SDimitry Andric deref) { 8120b57cec5SDimitry Andric // what we have is *arr[low]. the most similar C++ syntax is to get 8130b57cec5SDimitry Andric // arr[0] (an operation that is equivalent to deref-ing arr) and 8140b57cec5SDimitry Andric // extract bit low out of it. reading array item low would be done by 8150b57cec5SDimitry Andric // saying arr[low], without a deref * sign 81606c3fb27SDimitry Andric ValueObjectSP temp(valobj_sp->GetChildAtIndex(0)); 8175f757f3fSDimitry Andric if (!temp) { 8185ffd83dbSDimitry Andric valobj_sp->GetExpressionPath(var_expr_path_strm); 8190b57cec5SDimitry Andric error.SetErrorStringWithFormat( 8200b57cec5SDimitry Andric "could not get item 0 for \"(%s) %s\"", 8210b57cec5SDimitry Andric valobj_sp->GetTypeName().AsCString("<invalid type>"), 8220b57cec5SDimitry Andric var_expr_path_strm.GetData()); 8230b57cec5SDimitry Andric return ValueObjectSP(); 8240b57cec5SDimitry Andric } 8250b57cec5SDimitry Andric valobj_sp = temp; 8260b57cec5SDimitry Andric deref = false; 8270b57cec5SDimitry Andric } 8280b57cec5SDimitry Andric 8290b57cec5SDimitry Andric bool is_incomplete_array = false; 8300b57cec5SDimitry Andric if (valobj_sp->IsPointerType()) { 8310b57cec5SDimitry Andric bool is_objc_pointer = true; 8320b57cec5SDimitry Andric 8330b57cec5SDimitry Andric if (valobj_sp->GetCompilerType().GetMinimumLanguage() != 8340b57cec5SDimitry Andric eLanguageTypeObjC) 8350b57cec5SDimitry Andric is_objc_pointer = false; 8360b57cec5SDimitry Andric else if (!valobj_sp->GetCompilerType().IsPointerType()) 8370b57cec5SDimitry Andric is_objc_pointer = false; 8380b57cec5SDimitry Andric 8390b57cec5SDimitry Andric if (no_synth_child && is_objc_pointer) { 8400b57cec5SDimitry Andric error.SetErrorStringWithFormat( 8410b57cec5SDimitry Andric "\"(%s) %s\" is an Objective-C pointer, and cannot be " 8420b57cec5SDimitry Andric "subscripted", 8430b57cec5SDimitry Andric valobj_sp->GetTypeName().AsCString("<invalid type>"), 8440b57cec5SDimitry Andric var_expr_path_strm.GetData()); 8450b57cec5SDimitry Andric 8460b57cec5SDimitry Andric return ValueObjectSP(); 8470b57cec5SDimitry Andric } else if (is_objc_pointer) { 8480b57cec5SDimitry Andric // dereferencing ObjC variables is not valid.. so let's try and 8490b57cec5SDimitry Andric // recur to synthetic children 8500b57cec5SDimitry Andric ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(); 8510b57cec5SDimitry Andric if (!synthetic /* no synthetic */ 8520b57cec5SDimitry Andric || synthetic == valobj_sp) /* synthetic is the same as 8530b57cec5SDimitry Andric the original object */ 8540b57cec5SDimitry Andric { 8555ffd83dbSDimitry Andric valobj_sp->GetExpressionPath(var_expr_path_strm); 8560b57cec5SDimitry Andric error.SetErrorStringWithFormat( 8570b57cec5SDimitry Andric "\"(%s) %s\" is not an array type", 8580b57cec5SDimitry Andric valobj_sp->GetTypeName().AsCString("<invalid type>"), 8590b57cec5SDimitry Andric var_expr_path_strm.GetData()); 860*0fca6ea1SDimitry Andric } else if (static_cast<uint32_t>(child_index) >= 8610b57cec5SDimitry Andric synthetic 862*0fca6ea1SDimitry Andric ->GetNumChildrenIgnoringErrors() /* synthetic does 863*0fca6ea1SDimitry Andric not have that 864*0fca6ea1SDimitry Andric many values */) { 8655ffd83dbSDimitry Andric valobj_sp->GetExpressionPath(var_expr_path_strm); 8660b57cec5SDimitry Andric error.SetErrorStringWithFormat( 8670b57cec5SDimitry Andric "array index %ld is not valid for \"(%s) %s\"", child_index, 8680b57cec5SDimitry Andric valobj_sp->GetTypeName().AsCString("<invalid type>"), 8690b57cec5SDimitry Andric var_expr_path_strm.GetData()); 8700b57cec5SDimitry Andric } else { 87106c3fb27SDimitry Andric child_valobj_sp = synthetic->GetChildAtIndex(child_index); 8720b57cec5SDimitry Andric if (!child_valobj_sp) { 8735ffd83dbSDimitry Andric valobj_sp->GetExpressionPath(var_expr_path_strm); 8740b57cec5SDimitry Andric error.SetErrorStringWithFormat( 8750b57cec5SDimitry Andric "array index %ld is not valid for \"(%s) %s\"", child_index, 8760b57cec5SDimitry Andric valobj_sp->GetTypeName().AsCString("<invalid type>"), 8770b57cec5SDimitry Andric var_expr_path_strm.GetData()); 8780b57cec5SDimitry Andric } 8790b57cec5SDimitry Andric } 8800b57cec5SDimitry Andric } else { 8810b57cec5SDimitry Andric child_valobj_sp = 8820b57cec5SDimitry Andric valobj_sp->GetSyntheticArrayMember(child_index, true); 8830b57cec5SDimitry Andric if (!child_valobj_sp) { 8845ffd83dbSDimitry Andric valobj_sp->GetExpressionPath(var_expr_path_strm); 8850b57cec5SDimitry Andric error.SetErrorStringWithFormat( 8860b57cec5SDimitry Andric "failed to use pointer as array for index %ld for " 8870b57cec5SDimitry Andric "\"(%s) %s\"", 8880b57cec5SDimitry Andric child_index, 8890b57cec5SDimitry Andric valobj_sp->GetTypeName().AsCString("<invalid type>"), 8900b57cec5SDimitry Andric var_expr_path_strm.GetData()); 8910b57cec5SDimitry Andric } 8920b57cec5SDimitry Andric } 8930b57cec5SDimitry Andric } else if (valobj_sp->GetCompilerType().IsArrayType( 8940b57cec5SDimitry Andric nullptr, nullptr, &is_incomplete_array)) { 8950b57cec5SDimitry Andric // Pass false to dynamic_value here so we can tell the difference 8960b57cec5SDimitry Andric // between no dynamic value and no member of this type... 89706c3fb27SDimitry Andric child_valobj_sp = valobj_sp->GetChildAtIndex(child_index); 8980b57cec5SDimitry Andric if (!child_valobj_sp && (is_incomplete_array || !no_synth_child)) 8990b57cec5SDimitry Andric child_valobj_sp = 9000b57cec5SDimitry Andric valobj_sp->GetSyntheticArrayMember(child_index, true); 9010b57cec5SDimitry Andric 9020b57cec5SDimitry Andric if (!child_valobj_sp) { 9035ffd83dbSDimitry Andric valobj_sp->GetExpressionPath(var_expr_path_strm); 9040b57cec5SDimitry Andric error.SetErrorStringWithFormat( 9050b57cec5SDimitry Andric "array index %ld is not valid for \"(%s) %s\"", child_index, 9060b57cec5SDimitry Andric valobj_sp->GetTypeName().AsCString("<invalid type>"), 9070b57cec5SDimitry Andric var_expr_path_strm.GetData()); 9080b57cec5SDimitry Andric } 9090b57cec5SDimitry Andric } else if (valobj_sp->GetCompilerType().IsScalarType()) { 9100b57cec5SDimitry Andric // this is a bitfield asking to display just one bit 9110b57cec5SDimitry Andric child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild( 9120b57cec5SDimitry Andric child_index, child_index, true); 9130b57cec5SDimitry Andric if (!child_valobj_sp) { 9145ffd83dbSDimitry Andric valobj_sp->GetExpressionPath(var_expr_path_strm); 9150b57cec5SDimitry Andric error.SetErrorStringWithFormat( 9160b57cec5SDimitry Andric "bitfield range %ld-%ld is not valid for \"(%s) %s\"", 9170b57cec5SDimitry Andric child_index, child_index, 9180b57cec5SDimitry Andric valobj_sp->GetTypeName().AsCString("<invalid type>"), 9190b57cec5SDimitry Andric var_expr_path_strm.GetData()); 9200b57cec5SDimitry Andric } 9210b57cec5SDimitry Andric } else { 9220b57cec5SDimitry Andric ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(); 9230b57cec5SDimitry Andric if (no_synth_child /* synthetic is forbidden */ || 9240b57cec5SDimitry Andric !synthetic /* no synthetic */ 9250b57cec5SDimitry Andric || synthetic == valobj_sp) /* synthetic is the same as the 9260b57cec5SDimitry Andric original object */ 9270b57cec5SDimitry Andric { 9285ffd83dbSDimitry Andric valobj_sp->GetExpressionPath(var_expr_path_strm); 9290b57cec5SDimitry Andric error.SetErrorStringWithFormat( 9300b57cec5SDimitry Andric "\"(%s) %s\" is not an array type", 9310b57cec5SDimitry Andric valobj_sp->GetTypeName().AsCString("<invalid type>"), 9320b57cec5SDimitry Andric var_expr_path_strm.GetData()); 933*0fca6ea1SDimitry Andric } else if (static_cast<uint32_t>(child_index) >= 934*0fca6ea1SDimitry Andric synthetic->GetNumChildrenIgnoringErrors() /* synthetic 935*0fca6ea1SDimitry Andric does not have that many values */) { 9365ffd83dbSDimitry Andric valobj_sp->GetExpressionPath(var_expr_path_strm); 9370b57cec5SDimitry Andric error.SetErrorStringWithFormat( 9380b57cec5SDimitry Andric "array index %ld is not valid for \"(%s) %s\"", child_index, 9390b57cec5SDimitry Andric valobj_sp->GetTypeName().AsCString("<invalid type>"), 9400b57cec5SDimitry Andric var_expr_path_strm.GetData()); 9410b57cec5SDimitry Andric } else { 94206c3fb27SDimitry Andric child_valobj_sp = synthetic->GetChildAtIndex(child_index); 9430b57cec5SDimitry Andric if (!child_valobj_sp) { 9445ffd83dbSDimitry Andric valobj_sp->GetExpressionPath(var_expr_path_strm); 9450b57cec5SDimitry Andric error.SetErrorStringWithFormat( 9460b57cec5SDimitry Andric "array index %ld is not valid for \"(%s) %s\"", child_index, 9470b57cec5SDimitry Andric valobj_sp->GetTypeName().AsCString("<invalid type>"), 9480b57cec5SDimitry Andric var_expr_path_strm.GetData()); 9490b57cec5SDimitry Andric } 9500b57cec5SDimitry Andric } 9510b57cec5SDimitry Andric } 9520b57cec5SDimitry Andric 9530b57cec5SDimitry Andric if (!child_valobj_sp) { 9540b57cec5SDimitry Andric // Invalid array index... 9550b57cec5SDimitry Andric return ValueObjectSP(); 9560b57cec5SDimitry Andric } 9570b57cec5SDimitry Andric 9580b57cec5SDimitry Andric if (use_dynamic != eNoDynamicValues) { 9590b57cec5SDimitry Andric ValueObjectSP dynamic_value_sp( 9600b57cec5SDimitry Andric child_valobj_sp->GetDynamicValue(use_dynamic)); 9610b57cec5SDimitry Andric if (dynamic_value_sp) 9620b57cec5SDimitry Andric child_valobj_sp = dynamic_value_sp; 9630b57cec5SDimitry Andric } 9640b57cec5SDimitry Andric // Break out early from the switch since we were able to find the child 9650b57cec5SDimitry Andric // member 9660b57cec5SDimitry Andric break; 9670b57cec5SDimitry Andric } 9680b57cec5SDimitry Andric 9690b57cec5SDimitry Andric // this is most probably a BitField, let's take a look 9700b57cec5SDimitry Andric if (index_expr.front() != '-') { 9710b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid range expression \"'%s'\"", 9720b57cec5SDimitry Andric original_index_expr.str().c_str()); 9730b57cec5SDimitry Andric return ValueObjectSP(); 9740b57cec5SDimitry Andric } 9750b57cec5SDimitry Andric 9760b57cec5SDimitry Andric index_expr = index_expr.drop_front(); 9770b57cec5SDimitry Andric long final_index = 0; 9780b57cec5SDimitry Andric if (index_expr.getAsInteger(0, final_index)) { 9790b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid range expression \"'%s'\"", 9800b57cec5SDimitry Andric original_index_expr.str().c_str()); 9810b57cec5SDimitry Andric return ValueObjectSP(); 9820b57cec5SDimitry Andric } 9830b57cec5SDimitry Andric 9840b57cec5SDimitry Andric // if the format given is [high-low], swap range 9850b57cec5SDimitry Andric if (child_index > final_index) { 9860b57cec5SDimitry Andric long temp = child_index; 9870b57cec5SDimitry Andric child_index = final_index; 9880b57cec5SDimitry Andric final_index = temp; 9890b57cec5SDimitry Andric } 9900b57cec5SDimitry Andric 9910b57cec5SDimitry Andric if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) { 9920b57cec5SDimitry Andric // what we have is *ptr[low-high]. the most similar C++ syntax is to 9930b57cec5SDimitry Andric // deref ptr and extract bits low thru high out of it. reading array 9940b57cec5SDimitry Andric // items low thru high would be done by saying ptr[low-high], without a 9950b57cec5SDimitry Andric // deref * sign 9965f757f3fSDimitry Andric Status deref_error; 9975f757f3fSDimitry Andric ValueObjectSP temp(valobj_sp->Dereference(deref_error)); 9985f757f3fSDimitry Andric if (!temp || deref_error.Fail()) { 9995ffd83dbSDimitry Andric valobj_sp->GetExpressionPath(var_expr_path_strm); 10000b57cec5SDimitry Andric error.SetErrorStringWithFormat( 10010b57cec5SDimitry Andric "could not dereference \"(%s) %s\"", 10020b57cec5SDimitry Andric valobj_sp->GetTypeName().AsCString("<invalid type>"), 10030b57cec5SDimitry Andric var_expr_path_strm.GetData()); 10040b57cec5SDimitry Andric return ValueObjectSP(); 10050b57cec5SDimitry Andric } 10060b57cec5SDimitry Andric valobj_sp = temp; 10070b57cec5SDimitry Andric deref = false; 10080b57cec5SDimitry Andric } else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() && deref) { 10090b57cec5SDimitry Andric // what we have is *arr[low-high]. the most similar C++ syntax is to 10100b57cec5SDimitry Andric // get arr[0] (an operation that is equivalent to deref-ing arr) and 10110b57cec5SDimitry Andric // extract bits low thru high out of it. reading array items low thru 10120b57cec5SDimitry Andric // high would be done by saying arr[low-high], without a deref * sign 101306c3fb27SDimitry Andric ValueObjectSP temp(valobj_sp->GetChildAtIndex(0)); 10145f757f3fSDimitry Andric if (!temp) { 10155ffd83dbSDimitry Andric valobj_sp->GetExpressionPath(var_expr_path_strm); 10160b57cec5SDimitry Andric error.SetErrorStringWithFormat( 10170b57cec5SDimitry Andric "could not get item 0 for \"(%s) %s\"", 10180b57cec5SDimitry Andric valobj_sp->GetTypeName().AsCString("<invalid type>"), 10190b57cec5SDimitry Andric var_expr_path_strm.GetData()); 10200b57cec5SDimitry Andric return ValueObjectSP(); 10210b57cec5SDimitry Andric } 10220b57cec5SDimitry Andric valobj_sp = temp; 10230b57cec5SDimitry Andric deref = false; 10240b57cec5SDimitry Andric } 10250b57cec5SDimitry Andric 10260b57cec5SDimitry Andric child_valobj_sp = 10270b57cec5SDimitry Andric valobj_sp->GetSyntheticBitFieldChild(child_index, final_index, true); 10280b57cec5SDimitry Andric if (!child_valobj_sp) { 10295ffd83dbSDimitry Andric valobj_sp->GetExpressionPath(var_expr_path_strm); 10300b57cec5SDimitry Andric error.SetErrorStringWithFormat( 10310b57cec5SDimitry Andric "bitfield range %ld-%ld is not valid for \"(%s) %s\"", child_index, 10320b57cec5SDimitry Andric final_index, valobj_sp->GetTypeName().AsCString("<invalid type>"), 10330b57cec5SDimitry Andric var_expr_path_strm.GetData()); 10340b57cec5SDimitry Andric } 10350b57cec5SDimitry Andric 10360b57cec5SDimitry Andric if (!child_valobj_sp) { 10370b57cec5SDimitry Andric // Invalid bitfield range... 10380b57cec5SDimitry Andric return ValueObjectSP(); 10390b57cec5SDimitry Andric } 10400b57cec5SDimitry Andric 10410b57cec5SDimitry Andric if (use_dynamic != eNoDynamicValues) { 10420b57cec5SDimitry Andric ValueObjectSP dynamic_value_sp( 10430b57cec5SDimitry Andric child_valobj_sp->GetDynamicValue(use_dynamic)); 10440b57cec5SDimitry Andric if (dynamic_value_sp) 10450b57cec5SDimitry Andric child_valobj_sp = dynamic_value_sp; 10460b57cec5SDimitry Andric } 10470b57cec5SDimitry Andric // Break out early from the switch since we were able to find the child 10480b57cec5SDimitry Andric // member 10490b57cec5SDimitry Andric break; 10500b57cec5SDimitry Andric } 10510b57cec5SDimitry Andric default: 10520b57cec5SDimitry Andric // Failure... 10530b57cec5SDimitry Andric { 10545ffd83dbSDimitry Andric valobj_sp->GetExpressionPath(var_expr_path_strm); 10550b57cec5SDimitry Andric error.SetErrorStringWithFormat( 10560b57cec5SDimitry Andric "unexpected char '%c' encountered after \"%s\" in \"%s\"", 10570b57cec5SDimitry Andric separator_type, var_expr_path_strm.GetData(), 10580b57cec5SDimitry Andric var_expr.str().c_str()); 10590b57cec5SDimitry Andric 10600b57cec5SDimitry Andric return ValueObjectSP(); 10610b57cec5SDimitry Andric } 10620b57cec5SDimitry Andric } 10630b57cec5SDimitry Andric 10640b57cec5SDimitry Andric if (child_valobj_sp) 10650b57cec5SDimitry Andric valobj_sp = child_valobj_sp; 10660b57cec5SDimitry Andric } 10670b57cec5SDimitry Andric if (valobj_sp) { 10680b57cec5SDimitry Andric if (deref) { 10690b57cec5SDimitry Andric ValueObjectSP deref_valobj_sp(valobj_sp->Dereference(error)); 10700b57cec5SDimitry Andric valobj_sp = deref_valobj_sp; 10710b57cec5SDimitry Andric } else if (address_of) { 10720b57cec5SDimitry Andric ValueObjectSP address_of_valobj_sp(valobj_sp->AddressOf(error)); 10730b57cec5SDimitry Andric valobj_sp = address_of_valobj_sp; 10740b57cec5SDimitry Andric } 10750b57cec5SDimitry Andric } 10760b57cec5SDimitry Andric return valobj_sp; 10770b57cec5SDimitry Andric } 10780b57cec5SDimitry Andric 10790b57cec5SDimitry Andric bool StackFrame::GetFrameBaseValue(Scalar &frame_base, Status *error_ptr) { 10800b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 10810b57cec5SDimitry Andric if (!m_cfa_is_valid) { 10820b57cec5SDimitry Andric m_frame_base_error.SetErrorString( 10830b57cec5SDimitry Andric "No frame base available for this historical stack frame."); 10840b57cec5SDimitry Andric return false; 10850b57cec5SDimitry Andric } 10860b57cec5SDimitry Andric 10870b57cec5SDimitry Andric if (m_flags.IsClear(GOT_FRAME_BASE)) { 10880b57cec5SDimitry Andric if (m_sc.function) { 10890b57cec5SDimitry Andric m_frame_base.Clear(); 10900b57cec5SDimitry Andric m_frame_base_error.Clear(); 10910b57cec5SDimitry Andric 10920b57cec5SDimitry Andric m_flags.Set(GOT_FRAME_BASE); 10930b57cec5SDimitry Andric ExecutionContext exe_ctx(shared_from_this()); 10940b57cec5SDimitry Andric addr_t loclist_base_addr = LLDB_INVALID_ADDRESS; 1095753f127fSDimitry Andric if (!m_sc.function->GetFrameBaseExpression().IsAlwaysValidSingleExpr()) 10960b57cec5SDimitry Andric loclist_base_addr = 10970b57cec5SDimitry Andric m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress( 10980b57cec5SDimitry Andric exe_ctx.GetTargetPtr()); 10990b57cec5SDimitry Andric 1100*0fca6ea1SDimitry Andric llvm::Expected<Value> expr_value = 1101*0fca6ea1SDimitry Andric m_sc.function->GetFrameBaseExpression().Evaluate( 1102*0fca6ea1SDimitry Andric &exe_ctx, nullptr, loclist_base_addr, nullptr, nullptr); 1103*0fca6ea1SDimitry Andric if (!expr_value) 1104*0fca6ea1SDimitry Andric m_frame_base_error = expr_value.takeError(); 1105*0fca6ea1SDimitry Andric else 1106*0fca6ea1SDimitry Andric m_frame_base = expr_value->ResolveValue(&exe_ctx); 11070b57cec5SDimitry Andric } else { 11080b57cec5SDimitry Andric m_frame_base_error.SetErrorString("No function in symbol context."); 11090b57cec5SDimitry Andric } 11100b57cec5SDimitry Andric } 11110b57cec5SDimitry Andric 11120b57cec5SDimitry Andric if (m_frame_base_error.Success()) 11130b57cec5SDimitry Andric frame_base = m_frame_base; 11140b57cec5SDimitry Andric 11150b57cec5SDimitry Andric if (error_ptr) 11160b57cec5SDimitry Andric *error_ptr = m_frame_base_error; 11170b57cec5SDimitry Andric return m_frame_base_error.Success(); 11180b57cec5SDimitry Andric } 11190b57cec5SDimitry Andric 1120753f127fSDimitry Andric DWARFExpressionList *StackFrame::GetFrameBaseExpression(Status *error_ptr) { 11210b57cec5SDimitry Andric if (!m_sc.function) { 11220b57cec5SDimitry Andric if (error_ptr) { 11230b57cec5SDimitry Andric error_ptr->SetErrorString("No function in symbol context."); 11240b57cec5SDimitry Andric } 11250b57cec5SDimitry Andric return nullptr; 11260b57cec5SDimitry Andric } 11270b57cec5SDimitry Andric 11280b57cec5SDimitry Andric return &m_sc.function->GetFrameBaseExpression(); 11290b57cec5SDimitry Andric } 11300b57cec5SDimitry Andric 11310b57cec5SDimitry Andric RegisterContextSP StackFrame::GetRegisterContext() { 11320b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 11330b57cec5SDimitry Andric if (!m_reg_context_sp) { 11340b57cec5SDimitry Andric ThreadSP thread_sp(GetThread()); 11350b57cec5SDimitry Andric if (thread_sp) 11360b57cec5SDimitry Andric m_reg_context_sp = thread_sp->CreateRegisterContextForFrame(this); 11370b57cec5SDimitry Andric } 11380b57cec5SDimitry Andric return m_reg_context_sp; 11390b57cec5SDimitry Andric } 11400b57cec5SDimitry Andric 11410b57cec5SDimitry Andric bool StackFrame::HasDebugInformation() { 11420b57cec5SDimitry Andric GetSymbolContext(eSymbolContextLineEntry); 11430b57cec5SDimitry Andric return m_sc.line_entry.IsValid(); 11440b57cec5SDimitry Andric } 11450b57cec5SDimitry Andric 11460b57cec5SDimitry Andric ValueObjectSP 11470b57cec5SDimitry Andric StackFrame::GetValueObjectForFrameVariable(const VariableSP &variable_sp, 11480b57cec5SDimitry Andric DynamicValueType use_dynamic) { 11490b57cec5SDimitry Andric ValueObjectSP valobj_sp; 1150972a253aSDimitry Andric { // Scope for stack frame mutex. We need to drop this mutex before we figure 1151972a253aSDimitry Andric // out the dynamic value. That will require converting the StackID in the 1152972a253aSDimitry Andric // VO back to a StackFrame, which will in turn require locking the 1153972a253aSDimitry Andric // StackFrameList. If we still hold the StackFrame mutex, we could suffer 1154972a253aSDimitry Andric // lock inversion against the pattern of getting the StackFrameList and 1155972a253aSDimitry Andric // then the stack frame, which is fairly common. 1156972a253aSDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 11570b57cec5SDimitry Andric if (IsHistorical()) { 11580b57cec5SDimitry Andric return valobj_sp; 11590b57cec5SDimitry Andric } 1160bdd1243dSDimitry Andric VariableList *var_list = GetVariableList(true, nullptr); 11610b57cec5SDimitry Andric if (var_list) { 11620b57cec5SDimitry Andric // Make sure the variable is a frame variable 11630b57cec5SDimitry Andric const uint32_t var_idx = var_list->FindIndexForVariable(variable_sp.get()); 11640b57cec5SDimitry Andric const uint32_t num_variables = var_list->GetSize(); 11650b57cec5SDimitry Andric if (var_idx < num_variables) { 11660b57cec5SDimitry Andric valobj_sp = m_variable_list_value_objects.GetValueObjectAtIndex(var_idx); 11670b57cec5SDimitry Andric if (!valobj_sp) { 11680b57cec5SDimitry Andric if (m_variable_list_value_objects.GetSize() < num_variables) 11690b57cec5SDimitry Andric m_variable_list_value_objects.Resize(num_variables); 11700b57cec5SDimitry Andric valobj_sp = ValueObjectVariable::Create(this, variable_sp); 1171972a253aSDimitry Andric m_variable_list_value_objects.SetValueObjectAtIndex(var_idx, 1172972a253aSDimitry Andric valobj_sp); 11730b57cec5SDimitry Andric } 11740b57cec5SDimitry Andric } 11750b57cec5SDimitry Andric } 1176972a253aSDimitry Andric } // End of StackFrame mutex scope. 11770b57cec5SDimitry Andric if (use_dynamic != eNoDynamicValues && valobj_sp) { 11780b57cec5SDimitry Andric ValueObjectSP dynamic_sp = valobj_sp->GetDynamicValue(use_dynamic); 11790b57cec5SDimitry Andric if (dynamic_sp) 11800b57cec5SDimitry Andric return dynamic_sp; 11810b57cec5SDimitry Andric } 11820b57cec5SDimitry Andric return valobj_sp; 11830b57cec5SDimitry Andric } 11840b57cec5SDimitry Andric 11850b57cec5SDimitry Andric bool StackFrame::IsInlined() { 11860b57cec5SDimitry Andric if (m_sc.block == nullptr) 11870b57cec5SDimitry Andric GetSymbolContext(eSymbolContextBlock); 11880b57cec5SDimitry Andric if (m_sc.block) 11890b57cec5SDimitry Andric return m_sc.block->GetContainingInlinedBlock() != nullptr; 11900b57cec5SDimitry Andric return false; 11910b57cec5SDimitry Andric } 11920b57cec5SDimitry Andric 11930b57cec5SDimitry Andric bool StackFrame::IsHistorical() const { 11940b57cec5SDimitry Andric return m_stack_frame_kind == StackFrame::Kind::History; 11950b57cec5SDimitry Andric } 11960b57cec5SDimitry Andric 11970b57cec5SDimitry Andric bool StackFrame::IsArtificial() const { 11980b57cec5SDimitry Andric return m_stack_frame_kind == StackFrame::Kind::Artificial; 11990b57cec5SDimitry Andric } 12000b57cec5SDimitry Andric 1201*0fca6ea1SDimitry Andric SourceLanguage StackFrame::GetLanguage() { 12020b57cec5SDimitry Andric CompileUnit *cu = GetSymbolContext(eSymbolContextCompUnit).comp_unit; 12030b57cec5SDimitry Andric if (cu) 12040b57cec5SDimitry Andric return cu->GetLanguage(); 1205*0fca6ea1SDimitry Andric return {}; 12060b57cec5SDimitry Andric } 12070b57cec5SDimitry Andric 1208*0fca6ea1SDimitry Andric SourceLanguage StackFrame::GuessLanguage() { 1209*0fca6ea1SDimitry Andric SourceLanguage lang_type = GetLanguage(); 12100b57cec5SDimitry Andric 12110b57cec5SDimitry Andric if (lang_type == eLanguageTypeUnknown) { 1212*0fca6ea1SDimitry Andric SymbolContext sc = 1213*0fca6ea1SDimitry Andric GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol); 1214*0fca6ea1SDimitry Andric if (sc.function) 1215*0fca6ea1SDimitry Andric lang_type = LanguageType(sc.function->GetMangled().GuessLanguage()); 12160b57cec5SDimitry Andric else if (sc.symbol) 1217*0fca6ea1SDimitry Andric lang_type = SourceLanguage(sc.symbol->GetMangled().GuessLanguage()); 12180b57cec5SDimitry Andric } 12190b57cec5SDimitry Andric 12200b57cec5SDimitry Andric return lang_type; 12210b57cec5SDimitry Andric } 12220b57cec5SDimitry Andric 12230b57cec5SDimitry Andric namespace { 12240b57cec5SDimitry Andric std::pair<const Instruction::Operand *, int64_t> 12250b57cec5SDimitry Andric GetBaseExplainingValue(const Instruction::Operand &operand, 12260b57cec5SDimitry Andric RegisterContext ®ister_context, lldb::addr_t value) { 12270b57cec5SDimitry Andric switch (operand.m_type) { 12280b57cec5SDimitry Andric case Instruction::Operand::Type::Dereference: 12290b57cec5SDimitry Andric case Instruction::Operand::Type::Immediate: 12300b57cec5SDimitry Andric case Instruction::Operand::Type::Invalid: 12310b57cec5SDimitry Andric case Instruction::Operand::Type::Product: 12320b57cec5SDimitry Andric // These are not currently interesting 12330b57cec5SDimitry Andric return std::make_pair(nullptr, 0); 12340b57cec5SDimitry Andric case Instruction::Operand::Type::Sum: { 12350b57cec5SDimitry Andric const Instruction::Operand *immediate_child = nullptr; 12360b57cec5SDimitry Andric const Instruction::Operand *variable_child = nullptr; 12370b57cec5SDimitry Andric if (operand.m_children[0].m_type == Instruction::Operand::Type::Immediate) { 12380b57cec5SDimitry Andric immediate_child = &operand.m_children[0]; 12390b57cec5SDimitry Andric variable_child = &operand.m_children[1]; 12400b57cec5SDimitry Andric } else if (operand.m_children[1].m_type == 12410b57cec5SDimitry Andric Instruction::Operand::Type::Immediate) { 12420b57cec5SDimitry Andric immediate_child = &operand.m_children[1]; 12430b57cec5SDimitry Andric variable_child = &operand.m_children[0]; 12440b57cec5SDimitry Andric } 12450b57cec5SDimitry Andric if (!immediate_child) { 12460b57cec5SDimitry Andric return std::make_pair(nullptr, 0); 12470b57cec5SDimitry Andric } 12480b57cec5SDimitry Andric lldb::addr_t adjusted_value = value; 12490b57cec5SDimitry Andric if (immediate_child->m_negative) { 12500b57cec5SDimitry Andric adjusted_value += immediate_child->m_immediate; 12510b57cec5SDimitry Andric } else { 12520b57cec5SDimitry Andric adjusted_value -= immediate_child->m_immediate; 12530b57cec5SDimitry Andric } 12540b57cec5SDimitry Andric std::pair<const Instruction::Operand *, int64_t> base_and_offset = 12550b57cec5SDimitry Andric GetBaseExplainingValue(*variable_child, register_context, 12560b57cec5SDimitry Andric adjusted_value); 12570b57cec5SDimitry Andric if (!base_and_offset.first) { 12580b57cec5SDimitry Andric return std::make_pair(nullptr, 0); 12590b57cec5SDimitry Andric } 12600b57cec5SDimitry Andric if (immediate_child->m_negative) { 12610b57cec5SDimitry Andric base_and_offset.second -= immediate_child->m_immediate; 12620b57cec5SDimitry Andric } else { 12630b57cec5SDimitry Andric base_and_offset.second += immediate_child->m_immediate; 12640b57cec5SDimitry Andric } 12650b57cec5SDimitry Andric return base_and_offset; 12660b57cec5SDimitry Andric } 12670b57cec5SDimitry Andric case Instruction::Operand::Type::Register: { 12680b57cec5SDimitry Andric const RegisterInfo *info = 12690b57cec5SDimitry Andric register_context.GetRegisterInfoByName(operand.m_register.AsCString()); 12700b57cec5SDimitry Andric if (!info) { 12710b57cec5SDimitry Andric return std::make_pair(nullptr, 0); 12720b57cec5SDimitry Andric } 12730b57cec5SDimitry Andric RegisterValue reg_value; 12740b57cec5SDimitry Andric if (!register_context.ReadRegister(info, reg_value)) { 12750b57cec5SDimitry Andric return std::make_pair(nullptr, 0); 12760b57cec5SDimitry Andric } 12770b57cec5SDimitry Andric if (reg_value.GetAsUInt64() == value) { 12780b57cec5SDimitry Andric return std::make_pair(&operand, 0); 12790b57cec5SDimitry Andric } else { 12800b57cec5SDimitry Andric return std::make_pair(nullptr, 0); 12810b57cec5SDimitry Andric } 12820b57cec5SDimitry Andric } 12830b57cec5SDimitry Andric } 12840b57cec5SDimitry Andric return std::make_pair(nullptr, 0); 12850b57cec5SDimitry Andric } 12860b57cec5SDimitry Andric 12870b57cec5SDimitry Andric std::pair<const Instruction::Operand *, int64_t> 12880b57cec5SDimitry Andric GetBaseExplainingDereference(const Instruction::Operand &operand, 12890b57cec5SDimitry Andric RegisterContext ®ister_context, 12900b57cec5SDimitry Andric lldb::addr_t addr) { 12910b57cec5SDimitry Andric if (operand.m_type == Instruction::Operand::Type::Dereference) { 12920b57cec5SDimitry Andric return GetBaseExplainingValue(operand.m_children[0], register_context, 12930b57cec5SDimitry Andric addr); 12940b57cec5SDimitry Andric } 12950b57cec5SDimitry Andric return std::make_pair(nullptr, 0); 12960b57cec5SDimitry Andric } 1297*0fca6ea1SDimitry Andric } // namespace 12980b57cec5SDimitry Andric 12990b57cec5SDimitry Andric lldb::ValueObjectSP StackFrame::GuessValueForAddress(lldb::addr_t addr) { 13000b57cec5SDimitry Andric TargetSP target_sp = CalculateTarget(); 13010b57cec5SDimitry Andric 13020b57cec5SDimitry Andric const ArchSpec &target_arch = target_sp->GetArchitecture(); 13030b57cec5SDimitry Andric 13040b57cec5SDimitry Andric AddressRange pc_range; 13050b57cec5SDimitry Andric pc_range.GetBaseAddress() = GetFrameCodeAddress(); 13060b57cec5SDimitry Andric pc_range.SetByteSize(target_arch.GetMaximumOpcodeByteSize()); 13070b57cec5SDimitry Andric 13080b57cec5SDimitry Andric const char *plugin_name = nullptr; 13090b57cec5SDimitry Andric const char *flavor = nullptr; 1310fe6060f1SDimitry Andric const bool force_live_memory = true; 13110b57cec5SDimitry Andric 13125ffd83dbSDimitry Andric DisassemblerSP disassembler_sp = 13135ffd83dbSDimitry Andric Disassembler::DisassembleRange(target_arch, plugin_name, flavor, 1314fe6060f1SDimitry Andric *target_sp, pc_range, force_live_memory); 13150b57cec5SDimitry Andric 13160b57cec5SDimitry Andric if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) { 13170b57cec5SDimitry Andric return ValueObjectSP(); 13180b57cec5SDimitry Andric } 13190b57cec5SDimitry Andric 13200b57cec5SDimitry Andric InstructionSP instruction_sp = 13210b57cec5SDimitry Andric disassembler_sp->GetInstructionList().GetInstructionAtIndex(0); 13220b57cec5SDimitry Andric 13230b57cec5SDimitry Andric llvm::SmallVector<Instruction::Operand, 3> operands; 13240b57cec5SDimitry Andric 13250b57cec5SDimitry Andric if (!instruction_sp->ParseOperands(operands)) { 13260b57cec5SDimitry Andric return ValueObjectSP(); 13270b57cec5SDimitry Andric } 13280b57cec5SDimitry Andric 13290b57cec5SDimitry Andric RegisterContextSP register_context_sp = GetRegisterContext(); 13300b57cec5SDimitry Andric 13310b57cec5SDimitry Andric if (!register_context_sp) { 13320b57cec5SDimitry Andric return ValueObjectSP(); 13330b57cec5SDimitry Andric } 13340b57cec5SDimitry Andric 13350b57cec5SDimitry Andric for (const Instruction::Operand &operand : operands) { 13360b57cec5SDimitry Andric std::pair<const Instruction::Operand *, int64_t> base_and_offset = 13370b57cec5SDimitry Andric GetBaseExplainingDereference(operand, *register_context_sp, addr); 13380b57cec5SDimitry Andric 13390b57cec5SDimitry Andric if (!base_and_offset.first) { 13400b57cec5SDimitry Andric continue; 13410b57cec5SDimitry Andric } 13420b57cec5SDimitry Andric 13430b57cec5SDimitry Andric switch (base_and_offset.first->m_type) { 13440b57cec5SDimitry Andric case Instruction::Operand::Type::Immediate: { 13450b57cec5SDimitry Andric lldb_private::Address addr; 13460b57cec5SDimitry Andric if (target_sp->ResolveLoadAddress(base_and_offset.first->m_immediate + 13470b57cec5SDimitry Andric base_and_offset.second, 13480b57cec5SDimitry Andric addr)) { 13499dba64beSDimitry Andric auto c_type_system_or_err = 13509dba64beSDimitry Andric target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeC); 13519dba64beSDimitry Andric if (auto err = c_type_system_or_err.takeError()) { 135281ad6265SDimitry Andric LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), std::move(err), 135306c3fb27SDimitry Andric "Unable to guess value for given address: {0}"); 13540b57cec5SDimitry Andric return ValueObjectSP(); 13550b57cec5SDimitry Andric } else { 1356bdd1243dSDimitry Andric auto ts = *c_type_system_or_err; 1357bdd1243dSDimitry Andric if (!ts) 1358bdd1243dSDimitry Andric return {}; 13590b57cec5SDimitry Andric CompilerType void_ptr_type = 1360bdd1243dSDimitry Andric ts->GetBasicTypeFromAST(lldb::BasicType::eBasicTypeChar) 13610b57cec5SDimitry Andric .GetPointerType(); 13620b57cec5SDimitry Andric return ValueObjectMemory::Create(this, "", addr, void_ptr_type); 13630b57cec5SDimitry Andric } 13640b57cec5SDimitry Andric } else { 13650b57cec5SDimitry Andric return ValueObjectSP(); 13660b57cec5SDimitry Andric } 13670b57cec5SDimitry Andric break; 13680b57cec5SDimitry Andric } 13690b57cec5SDimitry Andric case Instruction::Operand::Type::Register: { 13700b57cec5SDimitry Andric return GuessValueForRegisterAndOffset(base_and_offset.first->m_register, 13710b57cec5SDimitry Andric base_and_offset.second); 13720b57cec5SDimitry Andric } 13730b57cec5SDimitry Andric default: 13740b57cec5SDimitry Andric return ValueObjectSP(); 13750b57cec5SDimitry Andric } 13760b57cec5SDimitry Andric } 13770b57cec5SDimitry Andric 13780b57cec5SDimitry Andric return ValueObjectSP(); 13790b57cec5SDimitry Andric } 13800b57cec5SDimitry Andric 13810b57cec5SDimitry Andric namespace { 13820b57cec5SDimitry Andric ValueObjectSP GetValueForOffset(StackFrame &frame, ValueObjectSP &parent, 13830b57cec5SDimitry Andric int64_t offset) { 13840b57cec5SDimitry Andric if (offset < 0 || uint64_t(offset) >= parent->GetByteSize()) { 13850b57cec5SDimitry Andric return ValueObjectSP(); 13860b57cec5SDimitry Andric } 13870b57cec5SDimitry Andric 13880b57cec5SDimitry Andric if (parent->IsPointerOrReferenceType()) { 13890b57cec5SDimitry Andric return parent; 13900b57cec5SDimitry Andric } 13910b57cec5SDimitry Andric 1392*0fca6ea1SDimitry Andric for (int ci = 0, ce = parent->GetNumChildrenIgnoringErrors(); ci != ce; 1393*0fca6ea1SDimitry Andric ++ci) { 139406c3fb27SDimitry Andric ValueObjectSP child_sp = parent->GetChildAtIndex(ci); 13950b57cec5SDimitry Andric 13960b57cec5SDimitry Andric if (!child_sp) { 13970b57cec5SDimitry Andric return ValueObjectSP(); 13980b57cec5SDimitry Andric } 13990b57cec5SDimitry Andric 14000b57cec5SDimitry Andric int64_t child_offset = child_sp->GetByteOffset(); 140181ad6265SDimitry Andric int64_t child_size = child_sp->GetByteSize().value_or(0); 14020b57cec5SDimitry Andric 14030b57cec5SDimitry Andric if (offset >= child_offset && offset < (child_offset + child_size)) { 14040b57cec5SDimitry Andric return GetValueForOffset(frame, child_sp, offset - child_offset); 14050b57cec5SDimitry Andric } 14060b57cec5SDimitry Andric } 14070b57cec5SDimitry Andric 14080b57cec5SDimitry Andric if (offset == 0) { 14090b57cec5SDimitry Andric return parent; 14100b57cec5SDimitry Andric } else { 14110b57cec5SDimitry Andric return ValueObjectSP(); 14120b57cec5SDimitry Andric } 14130b57cec5SDimitry Andric } 14140b57cec5SDimitry Andric 14150b57cec5SDimitry Andric ValueObjectSP GetValueForDereferincingOffset(StackFrame &frame, 14160b57cec5SDimitry Andric ValueObjectSP &base, 14170b57cec5SDimitry Andric int64_t offset) { 14180b57cec5SDimitry Andric // base is a pointer to something 14190b57cec5SDimitry Andric // offset is the thing to add to the pointer We return the most sensible 14200b57cec5SDimitry Andric // ValueObject for the result of *(base+offset) 14210b57cec5SDimitry Andric 14220b57cec5SDimitry Andric if (!base->IsPointerOrReferenceType()) { 14230b57cec5SDimitry Andric return ValueObjectSP(); 14240b57cec5SDimitry Andric } 14250b57cec5SDimitry Andric 14260b57cec5SDimitry Andric Status error; 14270b57cec5SDimitry Andric ValueObjectSP pointee = base->Dereference(error); 14280b57cec5SDimitry Andric 14290b57cec5SDimitry Andric if (!pointee) { 14300b57cec5SDimitry Andric return ValueObjectSP(); 14310b57cec5SDimitry Andric } 14320b57cec5SDimitry Andric 14330b57cec5SDimitry Andric if (offset >= 0 && uint64_t(offset) >= pointee->GetByteSize()) { 143481ad6265SDimitry Andric int64_t index = offset / pointee->GetByteSize().value_or(1); 143581ad6265SDimitry Andric offset = offset % pointee->GetByteSize().value_or(1); 14360b57cec5SDimitry Andric const bool can_create = true; 14370b57cec5SDimitry Andric pointee = base->GetSyntheticArrayMember(index, can_create); 14380b57cec5SDimitry Andric } 14390b57cec5SDimitry Andric 14400b57cec5SDimitry Andric if (!pointee || error.Fail()) { 14410b57cec5SDimitry Andric return ValueObjectSP(); 14420b57cec5SDimitry Andric } 14430b57cec5SDimitry Andric 14440b57cec5SDimitry Andric return GetValueForOffset(frame, pointee, offset); 14450b57cec5SDimitry Andric } 14460b57cec5SDimitry Andric 14470b57cec5SDimitry Andric /// Attempt to reconstruct the ValueObject for the address contained in a 14480b57cec5SDimitry Andric /// given register plus an offset. 14490b57cec5SDimitry Andric /// 145004eeddc0SDimitry Andric /// \param [in] frame 14510b57cec5SDimitry Andric /// The current stack frame. 14520b57cec5SDimitry Andric /// 145304eeddc0SDimitry Andric /// \param [in] reg 14540b57cec5SDimitry Andric /// The register. 14550b57cec5SDimitry Andric /// 145604eeddc0SDimitry Andric /// \param [in] offset 14570b57cec5SDimitry Andric /// The offset from the register. 14580b57cec5SDimitry Andric /// 14590b57cec5SDimitry Andric /// \param [in] disassembler 14600b57cec5SDimitry Andric /// A disassembler containing instructions valid up to the current PC. 14610b57cec5SDimitry Andric /// 14620b57cec5SDimitry Andric /// \param [in] variables 14630b57cec5SDimitry Andric /// The variable list from the current frame, 14640b57cec5SDimitry Andric /// 14650b57cec5SDimitry Andric /// \param [in] pc 14660b57cec5SDimitry Andric /// The program counter for the instruction considered the 'user'. 14670b57cec5SDimitry Andric /// 14680b57cec5SDimitry Andric /// \return 14690b57cec5SDimitry Andric /// A string describing the base for the ExpressionPath. This could be a 14700b57cec5SDimitry Andric /// variable, a register value, an argument, or a function return value. 14710b57cec5SDimitry Andric /// The ValueObject if found. If valid, it has a valid ExpressionPath. 14720b57cec5SDimitry Andric lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg, 14730b57cec5SDimitry Andric int64_t offset, Disassembler &disassembler, 14740b57cec5SDimitry Andric VariableList &variables, const Address &pc) { 14750b57cec5SDimitry Andric // Example of operation for Intel: 14760b57cec5SDimitry Andric // 14770b57cec5SDimitry Andric // +14: movq -0x8(%rbp), %rdi 14780b57cec5SDimitry Andric // +18: movq 0x8(%rdi), %rdi 14790b57cec5SDimitry Andric // +22: addl 0x4(%rdi), %eax 14800b57cec5SDimitry Andric // 14810b57cec5SDimitry Andric // f, a pointer to a struct, is known to be at -0x8(%rbp). 14820b57cec5SDimitry Andric // 14830b57cec5SDimitry Andric // DoGuessValueAt(frame, rdi, 4, dis, vars, 0x22) finds the instruction at 14840b57cec5SDimitry Andric // +18 that assigns to rdi, and calls itself recursively for that dereference 14850b57cec5SDimitry Andric // DoGuessValueAt(frame, rdi, 8, dis, vars, 0x18) finds the instruction at 14860b57cec5SDimitry Andric // +14 that assigns to rdi, and calls itself recursively for that 14875ffd83dbSDimitry Andric // dereference 14880b57cec5SDimitry Andric // DoGuessValueAt(frame, rbp, -8, dis, vars, 0x14) finds "f" in the 14890b57cec5SDimitry Andric // variable list. 14900b57cec5SDimitry Andric // Returns a ValueObject for f. (That's what was stored at rbp-8 at +14) 14910b57cec5SDimitry Andric // Returns a ValueObject for *(f+8) or f->b (That's what was stored at rdi+8 14920b57cec5SDimitry Andric // at +18) 14930b57cec5SDimitry Andric // Returns a ValueObject for *(f->b+4) or f->b->a (That's what was stored at 14940b57cec5SDimitry Andric // rdi+4 at +22) 14950b57cec5SDimitry Andric 14960b57cec5SDimitry Andric // First, check the variable list to see if anything is at the specified 14970b57cec5SDimitry Andric // location. 14980b57cec5SDimitry Andric 14990b57cec5SDimitry Andric using namespace OperandMatchers; 15000b57cec5SDimitry Andric 15010b57cec5SDimitry Andric const RegisterInfo *reg_info = 15020b57cec5SDimitry Andric frame.GetRegisterContext()->GetRegisterInfoByName(reg.AsCString()); 15030b57cec5SDimitry Andric if (!reg_info) { 15040b57cec5SDimitry Andric return ValueObjectSP(); 15050b57cec5SDimitry Andric } 15060b57cec5SDimitry Andric 15070b57cec5SDimitry Andric Instruction::Operand op = 15080b57cec5SDimitry Andric offset ? Instruction::Operand::BuildDereference( 15090b57cec5SDimitry Andric Instruction::Operand::BuildSum( 15100b57cec5SDimitry Andric Instruction::Operand::BuildRegister(reg), 15110b57cec5SDimitry Andric Instruction::Operand::BuildImmediate(offset))) 15120b57cec5SDimitry Andric : Instruction::Operand::BuildDereference( 15130b57cec5SDimitry Andric Instruction::Operand::BuildRegister(reg)); 15140b57cec5SDimitry Andric 1515480093f4SDimitry Andric for (VariableSP var_sp : variables) { 1516753f127fSDimitry Andric if (var_sp->LocationExpressionList().MatchesOperand(frame, op)) 15170b57cec5SDimitry Andric return frame.GetValueObjectForFrameVariable(var_sp, eNoDynamicValues); 15180b57cec5SDimitry Andric } 15190b57cec5SDimitry Andric 15200b57cec5SDimitry Andric const uint32_t current_inst = 15210b57cec5SDimitry Andric disassembler.GetInstructionList().GetIndexOfInstructionAtAddress(pc); 15220b57cec5SDimitry Andric if (current_inst == UINT32_MAX) { 15230b57cec5SDimitry Andric return ValueObjectSP(); 15240b57cec5SDimitry Andric } 15250b57cec5SDimitry Andric 15260b57cec5SDimitry Andric for (uint32_t ii = current_inst - 1; ii != (uint32_t)-1; --ii) { 15270b57cec5SDimitry Andric // This is not an exact algorithm, and it sacrifices accuracy for 15280b57cec5SDimitry Andric // generality. Recognizing "mov" and "ld" instructions –– and which 15290b57cec5SDimitry Andric // are their source and destination operands -- is something the 15300b57cec5SDimitry Andric // disassembler should do for us. 15310b57cec5SDimitry Andric InstructionSP instruction_sp = 15320b57cec5SDimitry Andric disassembler.GetInstructionList().GetInstructionAtIndex(ii); 15330b57cec5SDimitry Andric 15340b57cec5SDimitry Andric if (instruction_sp->IsCall()) { 15350b57cec5SDimitry Andric ABISP abi_sp = frame.CalculateProcess()->GetABI(); 15360b57cec5SDimitry Andric if (!abi_sp) { 15370b57cec5SDimitry Andric continue; 15380b57cec5SDimitry Andric } 15390b57cec5SDimitry Andric 15400b57cec5SDimitry Andric const char *return_register_name; 15410b57cec5SDimitry Andric if (!abi_sp->GetPointerReturnRegister(return_register_name)) { 15420b57cec5SDimitry Andric continue; 15430b57cec5SDimitry Andric } 15440b57cec5SDimitry Andric 15450b57cec5SDimitry Andric const RegisterInfo *return_register_info = 15460b57cec5SDimitry Andric frame.GetRegisterContext()->GetRegisterInfoByName( 15470b57cec5SDimitry Andric return_register_name); 15480b57cec5SDimitry Andric if (!return_register_info) { 15490b57cec5SDimitry Andric continue; 15500b57cec5SDimitry Andric } 15510b57cec5SDimitry Andric 15520b57cec5SDimitry Andric int64_t offset = 0; 15530b57cec5SDimitry Andric 15540b57cec5SDimitry Andric if (!MatchUnaryOp(MatchOpType(Instruction::Operand::Type::Dereference), 15550b57cec5SDimitry Andric MatchRegOp(*return_register_info))(op) && 15560b57cec5SDimitry Andric !MatchUnaryOp( 15570b57cec5SDimitry Andric MatchOpType(Instruction::Operand::Type::Dereference), 15580b57cec5SDimitry Andric MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum), 15590b57cec5SDimitry Andric MatchRegOp(*return_register_info), 15600b57cec5SDimitry Andric FetchImmOp(offset)))(op)) { 15610b57cec5SDimitry Andric continue; 15620b57cec5SDimitry Andric } 15630b57cec5SDimitry Andric 15640b57cec5SDimitry Andric llvm::SmallVector<Instruction::Operand, 1> operands; 15650b57cec5SDimitry Andric if (!instruction_sp->ParseOperands(operands) || operands.size() != 1) { 15660b57cec5SDimitry Andric continue; 15670b57cec5SDimitry Andric } 15680b57cec5SDimitry Andric 15690b57cec5SDimitry Andric switch (operands[0].m_type) { 15700b57cec5SDimitry Andric default: 15710b57cec5SDimitry Andric break; 15720b57cec5SDimitry Andric case Instruction::Operand::Type::Immediate: { 15730b57cec5SDimitry Andric SymbolContext sc; 15740b57cec5SDimitry Andric Address load_address; 15750b57cec5SDimitry Andric if (!frame.CalculateTarget()->ResolveLoadAddress( 15760b57cec5SDimitry Andric operands[0].m_immediate, load_address)) { 15770b57cec5SDimitry Andric break; 15780b57cec5SDimitry Andric } 15790b57cec5SDimitry Andric frame.CalculateTarget()->GetImages().ResolveSymbolContextForAddress( 15800b57cec5SDimitry Andric load_address, eSymbolContextFunction, sc); 15810b57cec5SDimitry Andric if (!sc.function) { 15820b57cec5SDimitry Andric break; 15830b57cec5SDimitry Andric } 15840b57cec5SDimitry Andric CompilerType function_type = sc.function->GetCompilerType(); 15850b57cec5SDimitry Andric if (!function_type.IsFunctionType()) { 15860b57cec5SDimitry Andric break; 15870b57cec5SDimitry Andric } 15880b57cec5SDimitry Andric CompilerType return_type = function_type.GetFunctionReturnType(); 15890b57cec5SDimitry Andric RegisterValue return_value; 15900b57cec5SDimitry Andric if (!frame.GetRegisterContext()->ReadRegister(return_register_info, 15910b57cec5SDimitry Andric return_value)) { 15920b57cec5SDimitry Andric break; 15930b57cec5SDimitry Andric } 15940b57cec5SDimitry Andric std::string name_str( 15950b57cec5SDimitry Andric sc.function->GetName().AsCString("<unknown function>")); 15960b57cec5SDimitry Andric name_str.append("()"); 15970b57cec5SDimitry Andric Address return_value_address(return_value.GetAsUInt64()); 15980b57cec5SDimitry Andric ValueObjectSP return_value_sp = ValueObjectMemory::Create( 15990b57cec5SDimitry Andric &frame, name_str, return_value_address, return_type); 16000b57cec5SDimitry Andric return GetValueForDereferincingOffset(frame, return_value_sp, offset); 16010b57cec5SDimitry Andric } 16020b57cec5SDimitry Andric } 16030b57cec5SDimitry Andric 16040b57cec5SDimitry Andric continue; 16050b57cec5SDimitry Andric } 16060b57cec5SDimitry Andric 16070b57cec5SDimitry Andric llvm::SmallVector<Instruction::Operand, 2> operands; 16080b57cec5SDimitry Andric if (!instruction_sp->ParseOperands(operands) || operands.size() != 2) { 16090b57cec5SDimitry Andric continue; 16100b57cec5SDimitry Andric } 16110b57cec5SDimitry Andric 16120b57cec5SDimitry Andric Instruction::Operand *origin_operand = nullptr; 16130b57cec5SDimitry Andric auto clobbered_reg_matcher = [reg_info](const Instruction::Operand &op) { 16140b57cec5SDimitry Andric return MatchRegOp(*reg_info)(op) && op.m_clobbered; 16150b57cec5SDimitry Andric }; 16160b57cec5SDimitry Andric 16170b57cec5SDimitry Andric if (clobbered_reg_matcher(operands[0])) { 16180b57cec5SDimitry Andric origin_operand = &operands[1]; 16190b57cec5SDimitry Andric } 16200b57cec5SDimitry Andric else if (clobbered_reg_matcher(operands[1])) { 16210b57cec5SDimitry Andric origin_operand = &operands[0]; 16220b57cec5SDimitry Andric } 16230b57cec5SDimitry Andric else { 16240b57cec5SDimitry Andric continue; 16250b57cec5SDimitry Andric } 16260b57cec5SDimitry Andric 16270b57cec5SDimitry Andric // We have an origin operand. Can we track its value down? 16280b57cec5SDimitry Andric ValueObjectSP source_path; 16290b57cec5SDimitry Andric ConstString origin_register; 16300b57cec5SDimitry Andric int64_t origin_offset = 0; 16310b57cec5SDimitry Andric 16320b57cec5SDimitry Andric if (FetchRegOp(origin_register)(*origin_operand)) { 16330b57cec5SDimitry Andric source_path = DoGuessValueAt(frame, origin_register, 0, disassembler, 16340b57cec5SDimitry Andric variables, instruction_sp->GetAddress()); 16350b57cec5SDimitry Andric } else if (MatchUnaryOp( 16360b57cec5SDimitry Andric MatchOpType(Instruction::Operand::Type::Dereference), 16370b57cec5SDimitry Andric FetchRegOp(origin_register))(*origin_operand) || 16380b57cec5SDimitry Andric MatchUnaryOp( 16390b57cec5SDimitry Andric MatchOpType(Instruction::Operand::Type::Dereference), 16400b57cec5SDimitry Andric MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum), 16410b57cec5SDimitry Andric FetchRegOp(origin_register), 16420b57cec5SDimitry Andric FetchImmOp(origin_offset)))(*origin_operand)) { 16430b57cec5SDimitry Andric source_path = 16440b57cec5SDimitry Andric DoGuessValueAt(frame, origin_register, origin_offset, disassembler, 16450b57cec5SDimitry Andric variables, instruction_sp->GetAddress()); 16460b57cec5SDimitry Andric if (!source_path) { 16470b57cec5SDimitry Andric continue; 16480b57cec5SDimitry Andric } 16490b57cec5SDimitry Andric source_path = 16500b57cec5SDimitry Andric GetValueForDereferincingOffset(frame, source_path, offset); 16510b57cec5SDimitry Andric } 16520b57cec5SDimitry Andric 16530b57cec5SDimitry Andric if (source_path) { 16540b57cec5SDimitry Andric return source_path; 16550b57cec5SDimitry Andric } 16560b57cec5SDimitry Andric } 16570b57cec5SDimitry Andric 16580b57cec5SDimitry Andric return ValueObjectSP(); 16590b57cec5SDimitry Andric } 16600b57cec5SDimitry Andric } 16610b57cec5SDimitry Andric 16620b57cec5SDimitry Andric lldb::ValueObjectSP StackFrame::GuessValueForRegisterAndOffset(ConstString reg, 16630b57cec5SDimitry Andric int64_t offset) { 16640b57cec5SDimitry Andric TargetSP target_sp = CalculateTarget(); 16650b57cec5SDimitry Andric 16660b57cec5SDimitry Andric const ArchSpec &target_arch = target_sp->GetArchitecture(); 16670b57cec5SDimitry Andric 16680b57cec5SDimitry Andric Block *frame_block = GetFrameBlock(); 16690b57cec5SDimitry Andric 16700b57cec5SDimitry Andric if (!frame_block) { 16710b57cec5SDimitry Andric return ValueObjectSP(); 16720b57cec5SDimitry Andric } 16730b57cec5SDimitry Andric 16740b57cec5SDimitry Andric Function *function = frame_block->CalculateSymbolContextFunction(); 16750b57cec5SDimitry Andric if (!function) { 16760b57cec5SDimitry Andric return ValueObjectSP(); 16770b57cec5SDimitry Andric } 16780b57cec5SDimitry Andric 16790b57cec5SDimitry Andric AddressRange pc_range = function->GetAddressRange(); 16800b57cec5SDimitry Andric 16810b57cec5SDimitry Andric if (GetFrameCodeAddress().GetFileAddress() < 16820b57cec5SDimitry Andric pc_range.GetBaseAddress().GetFileAddress() || 16830b57cec5SDimitry Andric GetFrameCodeAddress().GetFileAddress() - 16840b57cec5SDimitry Andric pc_range.GetBaseAddress().GetFileAddress() >= 16850b57cec5SDimitry Andric pc_range.GetByteSize()) { 16860b57cec5SDimitry Andric return ValueObjectSP(); 16870b57cec5SDimitry Andric } 16880b57cec5SDimitry Andric 16890b57cec5SDimitry Andric const char *plugin_name = nullptr; 16900b57cec5SDimitry Andric const char *flavor = nullptr; 1691fe6060f1SDimitry Andric const bool force_live_memory = true; 16925ffd83dbSDimitry Andric DisassemblerSP disassembler_sp = 16935ffd83dbSDimitry Andric Disassembler::DisassembleRange(target_arch, plugin_name, flavor, 1694fe6060f1SDimitry Andric *target_sp, pc_range, force_live_memory); 16950b57cec5SDimitry Andric 16960b57cec5SDimitry Andric if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) { 16970b57cec5SDimitry Andric return ValueObjectSP(); 16980b57cec5SDimitry Andric } 16990b57cec5SDimitry Andric 17000b57cec5SDimitry Andric const bool get_file_globals = false; 1701bdd1243dSDimitry Andric VariableList *variables = GetVariableList(get_file_globals, nullptr); 17020b57cec5SDimitry Andric 17030b57cec5SDimitry Andric if (!variables) { 17040b57cec5SDimitry Andric return ValueObjectSP(); 17050b57cec5SDimitry Andric } 17060b57cec5SDimitry Andric 17070b57cec5SDimitry Andric return DoGuessValueAt(*this, reg, offset, *disassembler_sp, *variables, 17080b57cec5SDimitry Andric GetFrameCodeAddress()); 17090b57cec5SDimitry Andric } 17100b57cec5SDimitry Andric 17110b57cec5SDimitry Andric lldb::ValueObjectSP StackFrame::FindVariable(ConstString name) { 17120b57cec5SDimitry Andric ValueObjectSP value_sp; 17130b57cec5SDimitry Andric 17140b57cec5SDimitry Andric if (!name) 17150b57cec5SDimitry Andric return value_sp; 17160b57cec5SDimitry Andric 17170b57cec5SDimitry Andric TargetSP target_sp = CalculateTarget(); 17180b57cec5SDimitry Andric ProcessSP process_sp = CalculateProcess(); 17190b57cec5SDimitry Andric 17200b57cec5SDimitry Andric if (!target_sp && !process_sp) 17210b57cec5SDimitry Andric return value_sp; 17220b57cec5SDimitry Andric 17230b57cec5SDimitry Andric VariableList variable_list; 17240b57cec5SDimitry Andric VariableSP var_sp; 17250b57cec5SDimitry Andric SymbolContext sc(GetSymbolContext(eSymbolContextBlock)); 17260b57cec5SDimitry Andric 17270b57cec5SDimitry Andric if (sc.block) { 17280b57cec5SDimitry Andric const bool can_create = true; 17290b57cec5SDimitry Andric const bool get_parent_variables = true; 17300b57cec5SDimitry Andric const bool stop_if_block_is_inlined_function = true; 17310b57cec5SDimitry Andric 17320b57cec5SDimitry Andric if (sc.block->AppendVariables( 17330b57cec5SDimitry Andric can_create, get_parent_variables, stop_if_block_is_inlined_function, 17340b57cec5SDimitry Andric [this](Variable *v) { return v->IsInScope(this); }, 17350b57cec5SDimitry Andric &variable_list)) { 17360b57cec5SDimitry Andric var_sp = variable_list.FindVariable(name); 17370b57cec5SDimitry Andric } 17380b57cec5SDimitry Andric 17390b57cec5SDimitry Andric if (var_sp) 17400b57cec5SDimitry Andric value_sp = GetValueObjectForFrameVariable(var_sp, eNoDynamicValues); 17410b57cec5SDimitry Andric } 17420b57cec5SDimitry Andric 17430b57cec5SDimitry Andric return value_sp; 17440b57cec5SDimitry Andric } 17450b57cec5SDimitry Andric 17460b57cec5SDimitry Andric TargetSP StackFrame::CalculateTarget() { 17470b57cec5SDimitry Andric TargetSP target_sp; 17480b57cec5SDimitry Andric ThreadSP thread_sp(GetThread()); 17490b57cec5SDimitry Andric if (thread_sp) { 17500b57cec5SDimitry Andric ProcessSP process_sp(thread_sp->CalculateProcess()); 17510b57cec5SDimitry Andric if (process_sp) 17520b57cec5SDimitry Andric target_sp = process_sp->CalculateTarget(); 17530b57cec5SDimitry Andric } 17540b57cec5SDimitry Andric return target_sp; 17550b57cec5SDimitry Andric } 17560b57cec5SDimitry Andric 17570b57cec5SDimitry Andric ProcessSP StackFrame::CalculateProcess() { 17580b57cec5SDimitry Andric ProcessSP process_sp; 17590b57cec5SDimitry Andric ThreadSP thread_sp(GetThread()); 17600b57cec5SDimitry Andric if (thread_sp) 17610b57cec5SDimitry Andric process_sp = thread_sp->CalculateProcess(); 17620b57cec5SDimitry Andric return process_sp; 17630b57cec5SDimitry Andric } 17640b57cec5SDimitry Andric 17650b57cec5SDimitry Andric ThreadSP StackFrame::CalculateThread() { return GetThread(); } 17660b57cec5SDimitry Andric 17670b57cec5SDimitry Andric StackFrameSP StackFrame::CalculateStackFrame() { return shared_from_this(); } 17680b57cec5SDimitry Andric 17690b57cec5SDimitry Andric void StackFrame::CalculateExecutionContext(ExecutionContext &exe_ctx) { 17700b57cec5SDimitry Andric exe_ctx.SetContext(shared_from_this()); 17710b57cec5SDimitry Andric } 17720b57cec5SDimitry Andric 17735f757f3fSDimitry Andric bool StackFrame::DumpUsingFormat(Stream &strm, 17745f757f3fSDimitry Andric const FormatEntity::Entry *format, 17755f757f3fSDimitry Andric llvm::StringRef frame_marker) { 17765f757f3fSDimitry Andric GetSymbolContext(eSymbolContextEverything); 17775f757f3fSDimitry Andric ExecutionContext exe_ctx(shared_from_this()); 17785f757f3fSDimitry Andric StreamString s; 17795f757f3fSDimitry Andric s.PutCString(frame_marker); 17805f757f3fSDimitry Andric 17815f757f3fSDimitry Andric if (format && FormatEntity::Format(*format, s, &m_sc, &exe_ctx, nullptr, 17825f757f3fSDimitry Andric nullptr, false, false)) { 17835f757f3fSDimitry Andric strm.PutCString(s.GetString()); 17845f757f3fSDimitry Andric return true; 17855f757f3fSDimitry Andric } 17865f757f3fSDimitry Andric return false; 17875f757f3fSDimitry Andric } 17885f757f3fSDimitry Andric 17890b57cec5SDimitry Andric void StackFrame::DumpUsingSettingsFormat(Stream *strm, bool show_unique, 17900b57cec5SDimitry Andric const char *frame_marker) { 17910b57cec5SDimitry Andric if (strm == nullptr) 17920b57cec5SDimitry Andric return; 17930b57cec5SDimitry Andric 17940b57cec5SDimitry Andric ExecutionContext exe_ctx(shared_from_this()); 17950b57cec5SDimitry Andric 17960b57cec5SDimitry Andric const FormatEntity::Entry *frame_format = nullptr; 17970b57cec5SDimitry Andric Target *target = exe_ctx.GetTargetPtr(); 17980b57cec5SDimitry Andric if (target) { 17990b57cec5SDimitry Andric if (show_unique) { 18000b57cec5SDimitry Andric frame_format = target->GetDebugger().GetFrameFormatUnique(); 18010b57cec5SDimitry Andric } else { 18020b57cec5SDimitry Andric frame_format = target->GetDebugger().GetFrameFormat(); 18030b57cec5SDimitry Andric } 18040b57cec5SDimitry Andric } 18055f757f3fSDimitry Andric if (!DumpUsingFormat(*strm, frame_format, frame_marker)) { 18060b57cec5SDimitry Andric Dump(strm, true, false); 18070b57cec5SDimitry Andric strm->EOL(); 18080b57cec5SDimitry Andric } 18090b57cec5SDimitry Andric } 18100b57cec5SDimitry Andric 18110b57cec5SDimitry Andric void StackFrame::Dump(Stream *strm, bool show_frame_index, 18120b57cec5SDimitry Andric bool show_fullpaths) { 18130b57cec5SDimitry Andric if (strm == nullptr) 18140b57cec5SDimitry Andric return; 18150b57cec5SDimitry Andric 18160b57cec5SDimitry Andric if (show_frame_index) 18170b57cec5SDimitry Andric strm->Printf("frame #%u: ", m_frame_index); 18180b57cec5SDimitry Andric ExecutionContext exe_ctx(shared_from_this()); 18190b57cec5SDimitry Andric Target *target = exe_ctx.GetTargetPtr(); 18200b57cec5SDimitry Andric strm->Printf("0x%0*" PRIx64 " ", 18210b57cec5SDimitry Andric target ? (target->GetArchitecture().GetAddressByteSize() * 2) 18220b57cec5SDimitry Andric : 16, 18230b57cec5SDimitry Andric GetFrameCodeAddress().GetLoadAddress(target)); 18240b57cec5SDimitry Andric GetSymbolContext(eSymbolContextEverything); 18250b57cec5SDimitry Andric const bool show_module = true; 18260b57cec5SDimitry Andric const bool show_inline = true; 18270b57cec5SDimitry Andric const bool show_function_arguments = true; 18280b57cec5SDimitry Andric const bool show_function_name = true; 18290b57cec5SDimitry Andric m_sc.DumpStopContext(strm, exe_ctx.GetBestExecutionContextScope(), 18300b57cec5SDimitry Andric GetFrameCodeAddress(), show_fullpaths, show_module, 18310b57cec5SDimitry Andric show_inline, show_function_arguments, 18320b57cec5SDimitry Andric show_function_name); 18330b57cec5SDimitry Andric } 18340b57cec5SDimitry Andric 18350b57cec5SDimitry Andric void StackFrame::UpdateCurrentFrameFromPreviousFrame(StackFrame &prev_frame) { 18360b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 18370b57cec5SDimitry Andric assert(GetStackID() == 18380b57cec5SDimitry Andric prev_frame.GetStackID()); // TODO: remove this after some testing 18390b57cec5SDimitry Andric m_variable_list_sp = prev_frame.m_variable_list_sp; 18400b57cec5SDimitry Andric m_variable_list_value_objects.Swap(prev_frame.m_variable_list_value_objects); 18410b57cec5SDimitry Andric if (!m_disassembly.GetString().empty()) { 18420b57cec5SDimitry Andric m_disassembly.Clear(); 18430b57cec5SDimitry Andric m_disassembly.PutCString(prev_frame.m_disassembly.GetString()); 18440b57cec5SDimitry Andric } 18450b57cec5SDimitry Andric } 18460b57cec5SDimitry Andric 18470b57cec5SDimitry Andric void StackFrame::UpdatePreviousFrameFromCurrentFrame(StackFrame &curr_frame) { 18480b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_mutex); 18490b57cec5SDimitry Andric assert(GetStackID() == 18500b57cec5SDimitry Andric curr_frame.GetStackID()); // TODO: remove this after some testing 18510b57cec5SDimitry Andric m_id.SetPC(curr_frame.m_id.GetPC()); // Update the Stack ID PC value 18520b57cec5SDimitry Andric assert(GetThread() == curr_frame.GetThread()); 18530b57cec5SDimitry Andric m_frame_index = curr_frame.m_frame_index; 18540b57cec5SDimitry Andric m_concrete_frame_index = curr_frame.m_concrete_frame_index; 18550b57cec5SDimitry Andric m_reg_context_sp = curr_frame.m_reg_context_sp; 18560b57cec5SDimitry Andric m_frame_code_addr = curr_frame.m_frame_code_addr; 18575ffd83dbSDimitry Andric m_behaves_like_zeroth_frame = curr_frame.m_behaves_like_zeroth_frame; 18580b57cec5SDimitry Andric assert(!m_sc.target_sp || !curr_frame.m_sc.target_sp || 18590b57cec5SDimitry Andric m_sc.target_sp.get() == curr_frame.m_sc.target_sp.get()); 18600b57cec5SDimitry Andric assert(!m_sc.module_sp || !curr_frame.m_sc.module_sp || 18610b57cec5SDimitry Andric m_sc.module_sp.get() == curr_frame.m_sc.module_sp.get()); 18620b57cec5SDimitry Andric assert(m_sc.comp_unit == nullptr || curr_frame.m_sc.comp_unit == nullptr || 18630b57cec5SDimitry Andric m_sc.comp_unit == curr_frame.m_sc.comp_unit); 18640b57cec5SDimitry Andric assert(m_sc.function == nullptr || curr_frame.m_sc.function == nullptr || 18650b57cec5SDimitry Andric m_sc.function == curr_frame.m_sc.function); 18660b57cec5SDimitry Andric m_sc = curr_frame.m_sc; 18670b57cec5SDimitry Andric m_flags.Clear(GOT_FRAME_BASE | eSymbolContextEverything); 18680b57cec5SDimitry Andric m_flags.Set(m_sc.GetResolvedMask()); 18690b57cec5SDimitry Andric m_frame_base.Clear(); 18700b57cec5SDimitry Andric m_frame_base_error.Clear(); 18710b57cec5SDimitry Andric } 18720b57cec5SDimitry Andric 18730b57cec5SDimitry Andric bool StackFrame::HasCachedData() const { 18740b57cec5SDimitry Andric if (m_variable_list_sp) 18750b57cec5SDimitry Andric return true; 18760b57cec5SDimitry Andric if (m_variable_list_value_objects.GetSize() > 0) 18770b57cec5SDimitry Andric return true; 18780b57cec5SDimitry Andric if (!m_disassembly.GetString().empty()) 18790b57cec5SDimitry Andric return true; 18800b57cec5SDimitry Andric return false; 18810b57cec5SDimitry Andric } 18820b57cec5SDimitry Andric 18830b57cec5SDimitry Andric bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source, 18840b57cec5SDimitry Andric bool show_unique, const char *frame_marker) { 18850b57cec5SDimitry Andric if (show_frame_info) { 18860b57cec5SDimitry Andric strm.Indent(); 18870b57cec5SDimitry Andric DumpUsingSettingsFormat(&strm, show_unique, frame_marker); 18880b57cec5SDimitry Andric } 18890b57cec5SDimitry Andric 18900b57cec5SDimitry Andric if (show_source) { 18910b57cec5SDimitry Andric ExecutionContext exe_ctx(shared_from_this()); 18920b57cec5SDimitry Andric bool have_source = false, have_debuginfo = false; 18930b57cec5SDimitry Andric Debugger::StopDisassemblyType disasm_display = 18940b57cec5SDimitry Andric Debugger::eStopDisassemblyTypeNever; 18950b57cec5SDimitry Andric Target *target = exe_ctx.GetTargetPtr(); 18960b57cec5SDimitry Andric if (target) { 18970b57cec5SDimitry Andric Debugger &debugger = target->GetDebugger(); 18980b57cec5SDimitry Andric const uint32_t source_lines_before = 18990b57cec5SDimitry Andric debugger.GetStopSourceLineCount(true); 19000b57cec5SDimitry Andric const uint32_t source_lines_after = 19010b57cec5SDimitry Andric debugger.GetStopSourceLineCount(false); 19020b57cec5SDimitry Andric disasm_display = debugger.GetStopDisassemblyDisplay(); 19030b57cec5SDimitry Andric 19040b57cec5SDimitry Andric GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry); 19050b57cec5SDimitry Andric if (m_sc.comp_unit && m_sc.line_entry.IsValid()) { 19060b57cec5SDimitry Andric have_debuginfo = true; 19070b57cec5SDimitry Andric if (source_lines_before > 0 || source_lines_after > 0) { 19080eae32dcSDimitry Andric uint32_t start_line = m_sc.line_entry.line; 19090eae32dcSDimitry Andric if (!start_line && m_sc.function) { 19100eae32dcSDimitry Andric FileSpec source_file; 19110eae32dcSDimitry Andric m_sc.function->GetStartLineSourceInfo(source_file, start_line); 19120eae32dcSDimitry Andric } 19130eae32dcSDimitry Andric 19140b57cec5SDimitry Andric size_t num_lines = 19150b57cec5SDimitry Andric target->GetSourceManager().DisplaySourceLinesWithLineNumbers( 1916*0fca6ea1SDimitry Andric m_sc.line_entry.GetFile(), start_line, m_sc.line_entry.column, 19170eae32dcSDimitry Andric source_lines_before, source_lines_after, "->", &strm); 19180b57cec5SDimitry Andric if (num_lines != 0) 19190b57cec5SDimitry Andric have_source = true; 19200b57cec5SDimitry Andric // TODO: Give here a one time warning if source file is missing. 19210eae32dcSDimitry Andric if (!m_sc.line_entry.line) { 19220eae32dcSDimitry Andric ConstString fn_name = m_sc.GetFunctionName(); 19230eae32dcSDimitry Andric 19240eae32dcSDimitry Andric if (!fn_name.IsEmpty()) 19250eae32dcSDimitry Andric strm.Printf( 19260eae32dcSDimitry Andric "Note: this address is compiler-generated code in function " 19270eae32dcSDimitry Andric "%s that has no source code associated with it.", 19280eae32dcSDimitry Andric fn_name.AsCString()); 19290eae32dcSDimitry Andric else 19300eae32dcSDimitry Andric strm.Printf("Note: this address is compiler-generated code that " 19310eae32dcSDimitry Andric "has no source code associated with it."); 19320eae32dcSDimitry Andric strm.EOL(); 19330eae32dcSDimitry Andric } 19340b57cec5SDimitry Andric } 19350b57cec5SDimitry Andric } 19360b57cec5SDimitry Andric switch (disasm_display) { 19370b57cec5SDimitry Andric case Debugger::eStopDisassemblyTypeNever: 19380b57cec5SDimitry Andric break; 19390b57cec5SDimitry Andric 19400b57cec5SDimitry Andric case Debugger::eStopDisassemblyTypeNoDebugInfo: 19410b57cec5SDimitry Andric if (have_debuginfo) 19420b57cec5SDimitry Andric break; 1943bdd1243dSDimitry Andric [[fallthrough]]; 19440b57cec5SDimitry Andric 19450b57cec5SDimitry Andric case Debugger::eStopDisassemblyTypeNoSource: 19460b57cec5SDimitry Andric if (have_source) 19470b57cec5SDimitry Andric break; 1948bdd1243dSDimitry Andric [[fallthrough]]; 19490b57cec5SDimitry Andric 19500b57cec5SDimitry Andric case Debugger::eStopDisassemblyTypeAlways: 19510b57cec5SDimitry Andric if (target) { 19520b57cec5SDimitry Andric const uint32_t disasm_lines = debugger.GetDisassemblyLineCount(); 19530b57cec5SDimitry Andric if (disasm_lines > 0) { 19540b57cec5SDimitry Andric const ArchSpec &target_arch = target->GetArchitecture(); 19550b57cec5SDimitry Andric const char *plugin_name = nullptr; 19560b57cec5SDimitry Andric const char *flavor = nullptr; 19570b57cec5SDimitry Andric const bool mixed_source_and_assembly = false; 19580b57cec5SDimitry Andric Disassembler::Disassemble( 19590b57cec5SDimitry Andric target->GetDebugger(), target_arch, plugin_name, flavor, 19605ffd83dbSDimitry Andric exe_ctx, GetFrameCodeAddress(), 19615ffd83dbSDimitry Andric {Disassembler::Limit::Instructions, disasm_lines}, 19625ffd83dbSDimitry Andric mixed_source_and_assembly, 0, 19630b57cec5SDimitry Andric Disassembler::eOptionMarkPCAddress, strm); 19640b57cec5SDimitry Andric } 19650b57cec5SDimitry Andric } 19660b57cec5SDimitry Andric break; 19670b57cec5SDimitry Andric } 19680b57cec5SDimitry Andric } 19690b57cec5SDimitry Andric } 19700b57cec5SDimitry Andric return true; 19710b57cec5SDimitry Andric } 19720b57cec5SDimitry Andric 19730b57cec5SDimitry Andric RecognizedStackFrameSP StackFrame::GetRecognizedFrame() { 19740b57cec5SDimitry Andric if (!m_recognized_frame_sp) { 1975e8d8bef9SDimitry Andric m_recognized_frame_sp = GetThread() 1976e8d8bef9SDimitry Andric ->GetProcess() 1977e8d8bef9SDimitry Andric ->GetTarget() 1978e8d8bef9SDimitry Andric .GetFrameRecognizerManager() 1979e8d8bef9SDimitry Andric .RecognizeFrame(CalculateStackFrame()); 19800b57cec5SDimitry Andric } 19810b57cec5SDimitry Andric return m_recognized_frame_sp; 19820b57cec5SDimitry Andric } 1983