130fdc8d8SChris Lattner //===-- StackFrame.cpp ------------------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1030fdc8d8SChris Lattner // C Includes 1130fdc8d8SChris Lattner // C++ Includes 1230fdc8d8SChris Lattner // Other libraries and framework includes 1330fdc8d8SChris Lattner // Project includes 14d70a6e71SEugene Zelenko #include "lldb/Target/StackFrame.h" 150603aa9dSGreg Clayton #include "lldb/Core/Debugger.h" 1630fdc8d8SChris Lattner #include "lldb/Core/Disassembler.h" 17554f68d3SGreg Clayton #include "lldb/Core/FormatEntity.h" 18592afe73SEnrico Granata #include "lldb/Core/Mangled.h" 19592afe73SEnrico Granata #include "lldb/Core/Module.h" 2030fdc8d8SChris Lattner #include "lldb/Core/Value.h" 2154979cddSGreg Clayton #include "lldb/Core/ValueObjectConstResult.h" 224740a734SSean Callanan #include "lldb/Core/ValueObjectMemory.h" 23b9c1b51eSKate Stone #include "lldb/Core/ValueObjectVariable.h" 241f746071SGreg Clayton #include "lldb/Symbol/CompileUnit.h" 2530fdc8d8SChris Lattner #include "lldb/Symbol/Function.h" 261f746071SGreg Clayton #include "lldb/Symbol/Symbol.h" 271f746071SGreg Clayton #include "lldb/Symbol/SymbolContextScope.h" 2846252398SEnrico Granata #include "lldb/Symbol/Type.h" 29288bdf9cSGreg Clayton #include "lldb/Symbol/VariableList.h" 304740a734SSean Callanan #include "lldb/Target/ABI.h" 3130fdc8d8SChris Lattner #include "lldb/Target/ExecutionContext.h" 3230fdc8d8SChris Lattner #include "lldb/Target/Process.h" 3330fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h" 3430fdc8d8SChris Lattner #include "lldb/Target/Target.h" 3530fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 3630fdc8d8SChris Lattner 3730fdc8d8SChris Lattner using namespace lldb; 3830fdc8d8SChris Lattner using namespace lldb_private; 3930fdc8d8SChris Lattner 4030fdc8d8SChris Lattner // The first bits in the flags are reserved for the SymbolContext::Scope bits 4130fdc8d8SChris Lattner // so we know if we have tried to look up information in our internal symbol 4230fdc8d8SChris Lattner // context (m_sc) already. 4359e8fc1cSGreg Clayton #define RESOLVED_FRAME_CODE_ADDR (uint32_t(eSymbolContextEverything + 1)) 446dadd508SGreg Clayton #define RESOLVED_FRAME_ID_SYMBOL_SCOPE (RESOLVED_FRAME_CODE_ADDR << 1) 4559e8fc1cSGreg Clayton #define GOT_FRAME_BASE (RESOLVED_FRAME_ID_SYMBOL_SCOPE << 1) 4659e8fc1cSGreg Clayton #define RESOLVED_VARIABLES (GOT_FRAME_BASE << 1) 477c0962dcSSean Callanan #define RESOLVED_GLOBAL_VARIABLES (RESOLVED_VARIABLES << 1) 4830fdc8d8SChris Lattner 49b9c1b51eSKate Stone StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, 50b9c1b51eSKate Stone user_id_t unwind_frame_index, addr_t cfa, 51b9c1b51eSKate Stone bool cfa_is_valid, addr_t pc, uint32_t stop_id, 52b9c1b51eSKate Stone bool stop_id_is_valid, bool is_history_frame, 53bb19a13cSSaleem Abdulrasool const SymbolContext *sc_ptr) 54b9c1b51eSKate Stone : m_thread_wp(thread_sp), m_frame_index(frame_idx), 55b9c1b51eSKate Stone m_concrete_frame_index(unwind_frame_index), m_reg_context_sp(), 56b9c1b51eSKate Stone m_id(pc, cfa, nullptr), m_frame_code_addr(pc), m_sc(), m_flags(), 57b9c1b51eSKate Stone m_frame_base(), m_frame_base_error(), m_cfa_is_valid(cfa_is_valid), 58b9c1b51eSKate Stone m_stop_id(stop_id), m_stop_id_is_valid(stop_id_is_valid), 59b9c1b51eSKate Stone m_is_history_frame(is_history_frame), m_variable_list_sp(), 60b9c1b51eSKate Stone m_variable_list_value_objects(), m_disassembly(), m_mutex() { 61b9c1b51eSKate Stone // If we don't have a CFA value, use the frame index for our StackID so that 62b9c1b51eSKate Stone // recursive 6399618476SJason Molenda // functions properly aren't confused with one another on a history stack. 64b9c1b51eSKate Stone if (m_is_history_frame && !m_cfa_is_valid) { 6599618476SJason Molenda m_id.SetCFA(m_frame_index); 6699618476SJason Molenda } 6799618476SJason Molenda 68b9c1b51eSKate Stone if (sc_ptr != nullptr) { 6930fdc8d8SChris Lattner m_sc = *sc_ptr; 701b72fcb7SGreg Clayton m_flags.Set(m_sc.GetResolvedMask()); 711b72fcb7SGreg Clayton } 7230fdc8d8SChris Lattner } 7330fdc8d8SChris Lattner 74b9c1b51eSKate Stone StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, 75b9c1b51eSKate Stone user_id_t unwind_frame_index, 76b9c1b51eSKate Stone const RegisterContextSP ®_context_sp, addr_t cfa, 77b9c1b51eSKate Stone addr_t pc, const SymbolContext *sc_ptr) 78b9c1b51eSKate Stone : m_thread_wp(thread_sp), m_frame_index(frame_idx), 795ccbd294SGreg Clayton m_concrete_frame_index(unwind_frame_index), 80b9c1b51eSKate Stone m_reg_context_sp(reg_context_sp), m_id(pc, cfa, nullptr), 81b9c1b51eSKate Stone m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(), 82b9c1b51eSKate Stone m_frame_base_error(), m_cfa_is_valid(true), m_stop_id(0), 83b9c1b51eSKate Stone m_stop_id_is_valid(false), m_is_history_frame(false), 84b9c1b51eSKate Stone m_variable_list_sp(), m_variable_list_value_objects(), m_disassembly(), 85b9c1b51eSKate Stone m_mutex() { 86b9c1b51eSKate Stone if (sc_ptr != nullptr) { 8730fdc8d8SChris Lattner m_sc = *sc_ptr; 881b72fcb7SGreg Clayton m_flags.Set(m_sc.GetResolvedMask()); 891b72fcb7SGreg Clayton } 901b72fcb7SGreg Clayton 91b9c1b51eSKate Stone if (reg_context_sp && !m_sc.target_sp) { 92d9e416c0SGreg Clayton m_sc.target_sp = reg_context_sp->CalculateTarget(); 93d9e416c0SGreg Clayton if (m_sc.target_sp) 941b72fcb7SGreg Clayton m_flags.Set(eSymbolContextTarget); 951b72fcb7SGreg Clayton } 961b72fcb7SGreg Clayton } 971b72fcb7SGreg Clayton 98b9c1b51eSKate Stone StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, 99b9c1b51eSKate Stone user_id_t unwind_frame_index, 100b9c1b51eSKate Stone const RegisterContextSP ®_context_sp, addr_t cfa, 101b9c1b51eSKate Stone const Address &pc_addr, const SymbolContext *sc_ptr) 102b9c1b51eSKate Stone : m_thread_wp(thread_sp), m_frame_index(frame_idx), 1035ccbd294SGreg Clayton m_concrete_frame_index(unwind_frame_index), 1041b72fcb7SGreg Clayton m_reg_context_sp(reg_context_sp), 105b9c1b51eSKate Stone m_id(pc_addr.GetLoadAddress(thread_sp->CalculateTarget().get()), cfa, 106b9c1b51eSKate Stone nullptr), 107b9c1b51eSKate Stone m_frame_code_addr(pc_addr), m_sc(), m_flags(), m_frame_base(), 108b9c1b51eSKate Stone m_frame_base_error(), m_cfa_is_valid(true), m_stop_id(0), 109b9c1b51eSKate Stone m_stop_id_is_valid(false), m_is_history_frame(false), 110b9c1b51eSKate Stone m_variable_list_sp(), m_variable_list_value_objects(), m_disassembly(), 111b9c1b51eSKate Stone m_mutex() { 112b9c1b51eSKate Stone if (sc_ptr != nullptr) { 1131b72fcb7SGreg Clayton m_sc = *sc_ptr; 1141b72fcb7SGreg Clayton m_flags.Set(m_sc.GetResolvedMask()); 1151b72fcb7SGreg Clayton } 1161b72fcb7SGreg Clayton 117b9c1b51eSKate Stone if (!m_sc.target_sp && reg_context_sp) { 118d9e416c0SGreg Clayton m_sc.target_sp = reg_context_sp->CalculateTarget(); 119d9e416c0SGreg Clayton if (m_sc.target_sp) 1201b72fcb7SGreg Clayton m_flags.Set(eSymbolContextTarget); 1211b72fcb7SGreg Clayton } 1221b72fcb7SGreg Clayton 123e72dfb32SGreg Clayton ModuleSP pc_module_sp(pc_addr.GetModule()); 124b9c1b51eSKate Stone if (!m_sc.module_sp || m_sc.module_sp != pc_module_sp) { 125b9c1b51eSKate Stone if (pc_module_sp) { 126e72dfb32SGreg Clayton m_sc.module_sp = pc_module_sp; 1271b72fcb7SGreg Clayton m_flags.Set(eSymbolContextModule); 128b9c1b51eSKate Stone } else { 129ffc1d667SGreg Clayton m_sc.module_sp.reset(); 130ffc1d667SGreg Clayton } 1311b72fcb7SGreg Clayton } 13230fdc8d8SChris Lattner } 13330fdc8d8SChris Lattner 134d70a6e71SEugene Zelenko StackFrame::~StackFrame() = default; 13530fdc8d8SChris Lattner 136b9c1b51eSKate Stone StackID &StackFrame::GetStackID() { 137bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 1386dadd508SGreg Clayton // Make sure we have resolved the StackID object's symbol context scope if 1396dadd508SGreg Clayton // we already haven't looked it up. 14059e8fc1cSGreg Clayton 141b9c1b51eSKate Stone if (m_flags.IsClear(RESOLVED_FRAME_ID_SYMBOL_SCOPE)) { 142b9c1b51eSKate Stone if (m_id.GetSymbolContextScope()) { 14395897c6aSGreg Clayton // We already have a symbol context scope, we just don't have our 14495897c6aSGreg Clayton // flag bit set. 14559e8fc1cSGreg Clayton m_flags.Set(RESOLVED_FRAME_ID_SYMBOL_SCOPE); 146b9c1b51eSKate Stone } else { 14795897c6aSGreg Clayton // Calculate the frame block and use this for the stack ID symbol 14895897c6aSGreg Clayton // context scope if we have one. 14995897c6aSGreg Clayton SymbolContextScope *scope = GetFrameBlock(); 150b9c1b51eSKate Stone if (scope == nullptr) { 15195897c6aSGreg Clayton // We don't have a block, so use the symbol 15295897c6aSGreg Clayton if (m_flags.IsClear(eSymbolContextSymbol)) 15359e8fc1cSGreg Clayton GetSymbolContext(eSymbolContextSymbol); 15495897c6aSGreg Clayton 155d70a6e71SEugene Zelenko // It is ok if m_sc.symbol is nullptr here 15695897c6aSGreg Clayton scope = m_sc.symbol; 15759e8fc1cSGreg Clayton } 15895897c6aSGreg Clayton // Set the symbol context scope (the accessor will set the 15995897c6aSGreg Clayton // RESOLVED_FRAME_ID_SYMBOL_SCOPE bit in m_flags). 16095897c6aSGreg Clayton SetSymbolContextScope(scope); 16159e8fc1cSGreg Clayton } 16259e8fc1cSGreg Clayton } 16330fdc8d8SChris Lattner return m_id; 16430fdc8d8SChris Lattner } 16530fdc8d8SChris Lattner 166b9c1b51eSKate Stone uint32_t StackFrame::GetFrameIndex() const { 167513c6bb8SJim Ingham ThreadSP thread_sp = GetThread(); 168513c6bb8SJim Ingham if (thread_sp) 169b9c1b51eSKate Stone return thread_sp->GetStackFrameList()->GetVisibleStackFrameIndex( 170b9c1b51eSKate Stone m_frame_index); 171513c6bb8SJim Ingham else 172513c6bb8SJim Ingham return m_frame_index; 173513c6bb8SJim Ingham } 174513c6bb8SJim Ingham 175b9c1b51eSKate Stone void StackFrame::SetSymbolContextScope(SymbolContextScope *symbol_scope) { 176bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 17759e8fc1cSGreg Clayton m_flags.Set(RESOLVED_FRAME_ID_SYMBOL_SCOPE); 17859e8fc1cSGreg Clayton m_id.SetSymbolContextScope(symbol_scope); 17959e8fc1cSGreg Clayton } 18059e8fc1cSGreg Clayton 181b9c1b51eSKate Stone const Address &StackFrame::GetFrameCodeAddress() { 182bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 183b9c1b51eSKate Stone if (m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR) && 184b9c1b51eSKate Stone !m_frame_code_addr.IsSectionOffset()) { 18559e8fc1cSGreg Clayton m_flags.Set(RESOLVED_FRAME_CODE_ADDR); 18630fdc8d8SChris Lattner 18730fdc8d8SChris Lattner // Resolve the PC into a temporary address because if ResolveLoadAddress 18830fdc8d8SChris Lattner // fails to resolve the address, it will clear the address object... 189d9e416c0SGreg Clayton ThreadSP thread_sp(GetThread()); 190b9c1b51eSKate Stone if (thread_sp) { 191d9e416c0SGreg Clayton TargetSP target_sp(thread_sp->CalculateTarget()); 192b9c1b51eSKate Stone if (target_sp) { 193b9c1b51eSKate Stone if (m_frame_code_addr.SetOpcodeLoadAddress( 194b9c1b51eSKate Stone m_frame_code_addr.GetOffset(), target_sp.get(), 195b9c1b51eSKate Stone eAddressClassCode)) { 196e72dfb32SGreg Clayton ModuleSP module_sp(m_frame_code_addr.GetModule()); 197b9c1b51eSKate Stone if (module_sp) { 198e72dfb32SGreg Clayton m_sc.module_sp = module_sp; 19930fdc8d8SChris Lattner m_flags.Set(eSymbolContextModule); 20030fdc8d8SChris Lattner } 20130fdc8d8SChris Lattner } 20230fdc8d8SChris Lattner } 20330fdc8d8SChris Lattner } 204d9e416c0SGreg Clayton } 20512fc3e0fSGreg Clayton return m_frame_code_addr; 20630fdc8d8SChris Lattner } 20730fdc8d8SChris Lattner 208b9c1b51eSKate Stone bool StackFrame::ChangePC(addr_t pc) { 209bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 21099618476SJason Molenda // We can't change the pc value of a history stack frame - it is immutable. 21199618476SJason Molenda if (m_is_history_frame) 21299618476SJason Molenda return false; 213e72dfb32SGreg Clayton m_frame_code_addr.SetRawAddress(pc); 21472310355SGreg Clayton m_sc.Clear(false); 21573b472d4SGreg Clayton m_flags.Reset(0); 216d9e416c0SGreg Clayton ThreadSP thread_sp(GetThread()); 217d9e416c0SGreg Clayton if (thread_sp) 218d9e416c0SGreg Clayton thread_sp->ClearStackFrames(); 21999618476SJason Molenda return true; 22030fdc8d8SChris Lattner } 22130fdc8d8SChris Lattner 222b9c1b51eSKate Stone const char *StackFrame::Disassemble() { 223bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 224*24bd3178SZachary Turner if (m_disassembly.Empty()) 225*24bd3178SZachary Turner return nullptr; 226*24bd3178SZachary Turner 227d9e416c0SGreg Clayton ExecutionContext exe_ctx(shared_from_this()); 228d9e416c0SGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 229b9c1b51eSKate Stone if (target) { 230d70a6e71SEugene Zelenko const char *plugin_name = nullptr; 231d70a6e71SEugene Zelenko const char *flavor = nullptr; 232*24bd3178SZachary Turner Disassembler::Disassemble(target->GetDebugger(), target->GetArchitecture(), 233*24bd3178SZachary Turner plugin_name, flavor, exe_ctx, 0, false, 0, 0, 234*24bd3178SZachary Turner m_disassembly); 23530fdc8d8SChris Lattner } 23630fdc8d8SChris Lattner return m_disassembly.GetData(); 23730fdc8d8SChris Lattner } 23830fdc8d8SChris Lattner 239b9c1b51eSKate Stone Block *StackFrame::GetFrameBlock() { 240d70a6e71SEugene Zelenko if (m_sc.block == nullptr && m_flags.IsClear(eSymbolContextBlock)) 24195897c6aSGreg Clayton GetSymbolContext(eSymbolContextBlock); 24295897c6aSGreg Clayton 243b9c1b51eSKate Stone if (m_sc.block) { 24495897c6aSGreg Clayton Block *inline_block = m_sc.block->GetContainingInlinedBlock(); 245b9c1b51eSKate Stone if (inline_block) { 24695897c6aSGreg Clayton // Use the block with the inlined function info 24795897c6aSGreg Clayton // as the frame block we want this frame to have only the variables 24895897c6aSGreg Clayton // for the inlined function and its non-inlined block child blocks. 24995897c6aSGreg Clayton return inline_block; 250b9c1b51eSKate Stone } else { 25175500e72SEd Maste // This block is not contained within any inlined function blocks 25295897c6aSGreg Clayton // with so we want to use the top most function block. 25395897c6aSGreg Clayton return &m_sc.function->GetBlock(false); 25495897c6aSGreg Clayton } 25595897c6aSGreg Clayton } 256d70a6e71SEugene Zelenko return nullptr; 25795897c6aSGreg Clayton } 25895897c6aSGreg Clayton 25930fdc8d8SChris Lattner //---------------------------------------------------------------------- 26030fdc8d8SChris Lattner // Get the symbol context if we already haven't done so by resolving the 26130fdc8d8SChris Lattner // PC address as much as possible. This way when we pass around a 26230fdc8d8SChris Lattner // StackFrame object, everyone will have as much information as 26330fdc8d8SChris Lattner // possible and no one will ever have to look things up manually. 26430fdc8d8SChris Lattner //---------------------------------------------------------------------- 265b9c1b51eSKate Stone const SymbolContext &StackFrame::GetSymbolContext(uint32_t resolve_scope) { 266bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 26730fdc8d8SChris Lattner // Copy our internal symbol context into "sc". 268b9c1b51eSKate Stone if ((m_flags.Get() & resolve_scope) != resolve_scope) { 26975a0333bSGreg Clayton uint32_t resolved = 0; 27075a0333bSGreg Clayton 27175a0333bSGreg Clayton // If the target was requested add that: 272b9c1b51eSKate Stone if (!m_sc.target_sp) { 27375a0333bSGreg Clayton m_sc.target_sp = CalculateTarget(); 27475a0333bSGreg Clayton if (m_sc.target_sp) 27575a0333bSGreg Clayton resolved |= eSymbolContextTarget; 27675a0333bSGreg Clayton } 27775a0333bSGreg Clayton 278aaa0ba31SBruce Mitchener // Resolve our PC to section offset if we haven't already done so 27930fdc8d8SChris Lattner // and if we don't have a module. The resolved address section will 28030fdc8d8SChris Lattner // contain the module to which it belongs 28159e8fc1cSGreg Clayton if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR)) 2829da7bd07SGreg Clayton GetFrameCodeAddress(); 28330fdc8d8SChris Lattner 28430fdc8d8SChris Lattner // If this is not frame zero, then we need to subtract 1 from the PC 28530fdc8d8SChris Lattner // value when doing address lookups since the PC will be on the 28630fdc8d8SChris Lattner // instruction following the function call instruction... 28730fdc8d8SChris Lattner 2889da7bd07SGreg Clayton Address lookup_addr(GetFrameCodeAddress()); 289b9c1b51eSKate Stone if (m_frame_index > 0 && lookup_addr.IsValid()) { 29030fdc8d8SChris Lattner addr_t offset = lookup_addr.GetOffset(); 291b9c1b51eSKate Stone if (offset > 0) { 29230fdc8d8SChris Lattner lookup_addr.SetOffset(offset - 1); 293cf29675dSJason Molenda 294b9c1b51eSKate Stone } else { 295cf29675dSJason Molenda // lookup_addr is the start of a section. We need 296cf29675dSJason Molenda // do the math on the actual load address and re-compute 297cf29675dSJason Molenda // the section. We're working with a 'noreturn' function 298cf29675dSJason Molenda // at the end of a section. 299cf29675dSJason Molenda ThreadSP thread_sp(GetThread()); 300b9c1b51eSKate Stone if (thread_sp) { 301cf29675dSJason Molenda TargetSP target_sp(thread_sp->CalculateTarget()); 302b9c1b51eSKate Stone if (target_sp) { 303b9c1b51eSKate Stone addr_t addr_minus_one = 304b9c1b51eSKate Stone lookup_addr.GetLoadAddress(target_sp.get()) - 1; 305cf29675dSJason Molenda lookup_addr.SetLoadAddress(addr_minus_one, target_sp.get()); 306b9c1b51eSKate Stone } else { 307cf29675dSJason Molenda lookup_addr.SetOffset(offset - 1); 308cf29675dSJason Molenda } 309cf29675dSJason Molenda } 310cf29675dSJason Molenda } 31130fdc8d8SChris Lattner } 31230fdc8d8SChris Lattner 313b9c1b51eSKate Stone if (m_sc.module_sp) { 31430fdc8d8SChris Lattner // We have something in our stack frame symbol context, lets check 31530fdc8d8SChris Lattner // if we haven't already tried to lookup one of those things. If we 31630fdc8d8SChris Lattner // haven't then we will do the query. 3171b72fcb7SGreg Clayton 3181b72fcb7SGreg Clayton uint32_t actual_resolve_scope = 0; 3191b72fcb7SGreg Clayton 320b9c1b51eSKate Stone if (resolve_scope & eSymbolContextCompUnit) { 321b9c1b51eSKate Stone if (m_flags.IsClear(eSymbolContextCompUnit)) { 3221b72fcb7SGreg Clayton if (m_sc.comp_unit) 3239da7bd07SGreg Clayton resolved |= eSymbolContextCompUnit; 3241b72fcb7SGreg Clayton else 3251b72fcb7SGreg Clayton actual_resolve_scope |= eSymbolContextCompUnit; 3261b72fcb7SGreg Clayton } 3271b72fcb7SGreg Clayton } 3281b72fcb7SGreg Clayton 329b9c1b51eSKate Stone if (resolve_scope & eSymbolContextFunction) { 330b9c1b51eSKate Stone if (m_flags.IsClear(eSymbolContextFunction)) { 3311b72fcb7SGreg Clayton if (m_sc.function) 3329da7bd07SGreg Clayton resolved |= eSymbolContextFunction; 3331b72fcb7SGreg Clayton else 3341b72fcb7SGreg Clayton actual_resolve_scope |= eSymbolContextFunction; 3351b72fcb7SGreg Clayton } 3361b72fcb7SGreg Clayton } 3371b72fcb7SGreg Clayton 338b9c1b51eSKate Stone if (resolve_scope & eSymbolContextBlock) { 339b9c1b51eSKate Stone if (m_flags.IsClear(eSymbolContextBlock)) { 3401b72fcb7SGreg Clayton if (m_sc.block) 3419da7bd07SGreg Clayton resolved |= eSymbolContextBlock; 3421b72fcb7SGreg Clayton else 3431b72fcb7SGreg Clayton actual_resolve_scope |= eSymbolContextBlock; 3441b72fcb7SGreg Clayton } 3451b72fcb7SGreg Clayton } 3461b72fcb7SGreg Clayton 347b9c1b51eSKate Stone if (resolve_scope & eSymbolContextSymbol) { 348b9c1b51eSKate Stone if (m_flags.IsClear(eSymbolContextSymbol)) { 3491b72fcb7SGreg Clayton if (m_sc.symbol) 3509da7bd07SGreg Clayton resolved |= eSymbolContextSymbol; 3511b72fcb7SGreg Clayton else 3521b72fcb7SGreg Clayton actual_resolve_scope |= eSymbolContextSymbol; 3531b72fcb7SGreg Clayton } 3541b72fcb7SGreg Clayton } 3551b72fcb7SGreg Clayton 356b9c1b51eSKate Stone if (resolve_scope & eSymbolContextLineEntry) { 357b9c1b51eSKate Stone if (m_flags.IsClear(eSymbolContextLineEntry)) { 3581b72fcb7SGreg Clayton if (m_sc.line_entry.IsValid()) 3599da7bd07SGreg Clayton resolved |= eSymbolContextLineEntry; 3601b72fcb7SGreg Clayton else 3611b72fcb7SGreg Clayton actual_resolve_scope |= eSymbolContextLineEntry; 3621b72fcb7SGreg Clayton } 3631b72fcb7SGreg Clayton } 3641b72fcb7SGreg Clayton 365b9c1b51eSKate Stone if (actual_resolve_scope) { 36630fdc8d8SChris Lattner // We might be resolving less information than what is already 36730fdc8d8SChris Lattner // in our current symbol context so resolve into a temporary 36830fdc8d8SChris Lattner // symbol context "sc" so we don't clear out data we have 36930fdc8d8SChris Lattner // already found in "m_sc" 37030fdc8d8SChris Lattner SymbolContext sc; 37130fdc8d8SChris Lattner // Set flags that indicate what we have tried to resolve 372b9c1b51eSKate Stone resolved |= m_sc.module_sp->ResolveSymbolContextForAddress( 373b9c1b51eSKate Stone lookup_addr, actual_resolve_scope, sc); 3741b72fcb7SGreg Clayton // Only replace what we didn't already have as we may have 3751b72fcb7SGreg Clayton // information for an inlined function scope that won't match 3761b72fcb7SGreg Clayton // what a standard lookup by address would match 377d70a6e71SEugene Zelenko if ((resolved & eSymbolContextCompUnit) && m_sc.comp_unit == nullptr) 3789da7bd07SGreg Clayton m_sc.comp_unit = sc.comp_unit; 379d70a6e71SEugene Zelenko if ((resolved & eSymbolContextFunction) && m_sc.function == nullptr) 3809da7bd07SGreg Clayton m_sc.function = sc.function; 381d70a6e71SEugene Zelenko if ((resolved & eSymbolContextBlock) && m_sc.block == nullptr) 3829da7bd07SGreg Clayton m_sc.block = sc.block; 383d70a6e71SEugene Zelenko if ((resolved & eSymbolContextSymbol) && m_sc.symbol == nullptr) 3849da7bd07SGreg Clayton m_sc.symbol = sc.symbol; 385b9c1b51eSKate Stone if ((resolved & eSymbolContextLineEntry) && 386b9c1b51eSKate Stone !m_sc.line_entry.IsValid()) { 3879da7bd07SGreg Clayton m_sc.line_entry = sc.line_entry; 388911d5784STed Woodward m_sc.line_entry.ApplyFileMappings(m_sc.target_sp); 38975a0333bSGreg Clayton } 39030fdc8d8SChris Lattner } 391b9c1b51eSKate Stone } else { 39230fdc8d8SChris Lattner // If we don't have a module, then we can't have the compile unit, 39330fdc8d8SChris Lattner // function, block, line entry or symbol, so we can safely call 39430fdc8d8SChris Lattner // ResolveSymbolContextForAddress with our symbol context member m_sc. 395b9c1b51eSKate Stone if (m_sc.target_sp) { 396b9c1b51eSKate Stone resolved |= m_sc.target_sp->GetImages().ResolveSymbolContextForAddress( 397b9c1b51eSKate Stone lookup_addr, resolve_scope, m_sc); 398f4be227dSSean Callanan } 3999da7bd07SGreg Clayton } 40030fdc8d8SChris Lattner 40130fdc8d8SChris Lattner // Update our internal flags so we remember what we have tried to locate so 40230fdc8d8SChris Lattner // we don't have to keep trying when more calls to this function are made. 4039da7bd07SGreg Clayton // We might have dug up more information that was requested (for example 4049da7bd07SGreg Clayton // if we were asked to only get the block, we will have gotten the 4059da7bd07SGreg Clayton // compile unit, and function) so set any additional bits that we resolved 4069da7bd07SGreg Clayton m_flags.Set(resolve_scope | resolved); 40730fdc8d8SChris Lattner } 40830fdc8d8SChris Lattner 40930fdc8d8SChris Lattner // Return the symbol context with everything that was possible to resolve 41030fdc8d8SChris Lattner // resolved. 41130fdc8d8SChris Lattner return m_sc; 41230fdc8d8SChris Lattner } 41330fdc8d8SChris Lattner 414b9c1b51eSKate Stone VariableList *StackFrame::GetVariableList(bool get_file_globals) { 415bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 416b9c1b51eSKate Stone if (m_flags.IsClear(RESOLVED_VARIABLES)) { 41730fdc8d8SChris Lattner m_flags.Set(RESOLVED_VARIABLES); 41830fdc8d8SChris Lattner 41995897c6aSGreg Clayton Block *frame_block = GetFrameBlock(); 420288bdf9cSGreg Clayton 421b9c1b51eSKate Stone if (frame_block) { 42295897c6aSGreg Clayton const bool get_child_variables = true; 42395897c6aSGreg Clayton const bool can_create = true; 424c662ec8bSGreg Clayton const bool stop_if_child_block_is_inlined_function = true; 425c662ec8bSGreg Clayton m_variable_list_sp.reset(new VariableList()); 426b9c1b51eSKate Stone frame_block->AppendBlockVariables(can_create, get_child_variables, 42772ac8a84STamas Berghammer stop_if_child_block_is_inlined_function, 428a32532bfSGreg Clayton [this](Variable *v) { return true; }, 42972ac8a84STamas Berghammer m_variable_list_sp.get()); 43030fdc8d8SChris Lattner } 4317c0962dcSSean Callanan } 432288bdf9cSGreg Clayton 433b9c1b51eSKate Stone if (m_flags.IsClear(RESOLVED_GLOBAL_VARIABLES) && get_file_globals) { 4347c0962dcSSean Callanan m_flags.Set(RESOLVED_GLOBAL_VARIABLES); 4357c0962dcSSean Callanan 43695897c6aSGreg Clayton if (m_flags.IsClear(eSymbolContextCompUnit)) 43795897c6aSGreg Clayton GetSymbolContext(eSymbolContextCompUnit); 43895897c6aSGreg Clayton 439b9c1b51eSKate Stone if (m_sc.comp_unit) { 440b9c1b51eSKate Stone VariableListSP global_variable_list_sp( 441b9c1b51eSKate Stone m_sc.comp_unit->GetVariableList(true)); 442288bdf9cSGreg Clayton if (m_variable_list_sp) 443288bdf9cSGreg Clayton m_variable_list_sp->AddVariables(global_variable_list_sp.get()); 444288bdf9cSGreg Clayton else 445288bdf9cSGreg Clayton m_variable_list_sp = global_variable_list_sp; 446288bdf9cSGreg Clayton } 44730fdc8d8SChris Lattner } 4487c0962dcSSean Callanan 44930fdc8d8SChris Lattner return m_variable_list_sp.get(); 45030fdc8d8SChris Lattner } 45130fdc8d8SChris Lattner 452d41f032aSGreg Clayton VariableListSP 453b9c1b51eSKate Stone StackFrame::GetInScopeVariableList(bool get_file_globals, 454b9c1b51eSKate Stone bool must_have_valid_location) { 455bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 45699618476SJason Molenda // We can't fetch variable information for a history stack frame. 45799618476SJason Molenda if (m_is_history_frame) 45899618476SJason Molenda return VariableListSP(); 45999618476SJason Molenda 460d41f032aSGreg Clayton VariableListSP var_list_sp(new VariableList); 461d41f032aSGreg Clayton GetSymbolContext(eSymbolContextCompUnit | eSymbolContextBlock); 462d41f032aSGreg Clayton 463b9c1b51eSKate Stone if (m_sc.block) { 464d41f032aSGreg Clayton const bool can_create = true; 465d41f032aSGreg Clayton const bool get_parent_variables = true; 466d41f032aSGreg Clayton const bool stop_if_block_is_inlined_function = true; 467b9c1b51eSKate Stone m_sc.block->AppendVariables( 468b9c1b51eSKate Stone can_create, get_parent_variables, stop_if_block_is_inlined_function, 469b9c1b51eSKate Stone [this, must_have_valid_location](Variable *v) { 470b9c1b51eSKate Stone return v->IsInScope(this) && (!must_have_valid_location || 471b9c1b51eSKate Stone v->LocationIsValidForFrame(this)); 472cef46177SJim Ingham }, 473d41f032aSGreg Clayton var_list_sp.get()); 474d41f032aSGreg Clayton } 475d41f032aSGreg Clayton 476b9c1b51eSKate Stone if (m_sc.comp_unit && get_file_globals) { 477b9c1b51eSKate Stone VariableListSP global_variable_list_sp( 478b9c1b51eSKate Stone m_sc.comp_unit->GetVariableList(true)); 479d41f032aSGreg Clayton if (global_variable_list_sp) 480d41f032aSGreg Clayton var_list_sp->AddVariables(global_variable_list_sp.get()); 481d41f032aSGreg Clayton } 482d41f032aSGreg Clayton 483d41f032aSGreg Clayton return var_list_sp; 484d41f032aSGreg Clayton } 485d41f032aSGreg Clayton 486b9c1b51eSKate Stone ValueObjectSP StackFrame::GetValueForVariableExpressionPath( 487*24bd3178SZachary Turner llvm::StringRef var_expr_cstr, DynamicValueType use_dynamic, 488*24bd3178SZachary Turner uint32_t options, VariableSP &var_sp, Error &error) { 48999618476SJason Molenda // We can't fetch variable information for a history stack frame. 49099618476SJason Molenda if (m_is_history_frame) 49199618476SJason Molenda return ValueObjectSP(); 49254979cddSGreg Clayton 493*24bd3178SZachary Turner if (var_expr_cstr.empty()) { 494*24bd3178SZachary Turner error.SetErrorStringWithFormat("invalid variable path '%s'", var_expr_cstr); 495*24bd3178SZachary Turner return ValueObjectSP(); 496*24bd3178SZachary Turner } 497*24bd3178SZachary Turner 498b9c1b51eSKate Stone const bool check_ptr_vs_member = 499b9c1b51eSKate Stone (options & eExpressionPathOptionCheckPtrVsMember) != 0; 500b9c1b51eSKate Stone const bool no_fragile_ivar = 501b9c1b51eSKate Stone (options & eExpressionPathOptionsNoFragileObjcIvar) != 0; 502b9c1b51eSKate Stone const bool no_synth_child = 503b9c1b51eSKate Stone (options & eExpressionPathOptionsNoSyntheticChildren) != 0; 504b9c1b51eSKate Stone // const bool no_synth_array = (options & 505b9c1b51eSKate Stone // eExpressionPathOptionsNoSyntheticArrayRange) != 0; 50654979cddSGreg Clayton error.Clear(); 5078b2fe6dcSGreg Clayton bool deref = false; 5088b2fe6dcSGreg Clayton bool address_of = false; 5098b2fe6dcSGreg Clayton ValueObjectSP valobj_sp; 5108b2fe6dcSGreg Clayton const bool get_file_globals = true; 511d41f032aSGreg Clayton // When looking up a variable for an expression, we need only consider the 512d41f032aSGreg Clayton // variables that are in scope. 513d41f032aSGreg Clayton VariableListSP var_list_sp(GetInScopeVariableList(get_file_globals)); 514d41f032aSGreg Clayton VariableList *variable_list = var_list_sp.get(); 5158b2fe6dcSGreg Clayton 516*24bd3178SZachary Turner if (!variable_list) 517*24bd3178SZachary Turner return ValueObjectSP(); 518*24bd3178SZachary Turner 5198b2fe6dcSGreg Clayton // If first character is a '*', then show pointer contents 520*24bd3178SZachary Turner llvm::StringRef var_expr = var_expr_cstr; 521*24bd3178SZachary Turner std::string var_expr_storage; 522b9c1b51eSKate Stone if (var_expr[0] == '*') { 5238b2fe6dcSGreg Clayton deref = true; 524*24bd3178SZachary Turner var_expr = var_expr.drop_front(); // Skip the '*' 525b9c1b51eSKate Stone } else if (var_expr[0] == '&') { 5268b2fe6dcSGreg Clayton address_of = true; 527*24bd3178SZachary Turner var_expr = var_expr.drop_front(); // Skip the '&' 5288b2fe6dcSGreg Clayton } 5298b2fe6dcSGreg Clayton 530*24bd3178SZachary Turner size_t separator_idx = var_expr.find_first_of(".-[=+~|&^%#@!/?,<>{}"); 53154979cddSGreg Clayton StreamString var_expr_path_strm; 5328b2fe6dcSGreg Clayton 533*24bd3178SZachary Turner ConstString name_const_string(var_expr.substr(0, separator_idx)); 5348b2fe6dcSGreg Clayton 53510bc1a4eSPaul Herman var_sp = variable_list->FindVariable(name_const_string, false); 536685c88c5SGreg Clayton 537685c88c5SGreg Clayton bool synthetically_added_instance_object = false; 538685c88c5SGreg Clayton 539b9c1b51eSKate Stone if (var_sp) { 540*24bd3178SZachary Turner var_expr = var_expr.drop_front(name_const_string.GetLength()); 541685c88c5SGreg Clayton } 54246252398SEnrico Granata 543b9c1b51eSKate Stone if (!var_sp && (options & eExpressionPathOptionsAllowDirectIVarAccess)) { 544685c88c5SGreg Clayton // Check for direct ivars access which helps us with implicit 545685c88c5SGreg Clayton // access to ivars with the "this->" or "self->" 546685c88c5SGreg Clayton GetSymbolContext(eSymbolContextFunction | eSymbolContextBlock); 547685c88c5SGreg Clayton lldb::LanguageType method_language = eLanguageTypeUnknown; 548685c88c5SGreg Clayton bool is_instance_method = false; 549685c88c5SGreg Clayton ConstString method_object_name; 550b9c1b51eSKate Stone if (m_sc.GetFunctionMethodInfo(method_language, is_instance_method, 551b9c1b51eSKate Stone method_object_name)) { 552b9c1b51eSKate Stone if (is_instance_method && method_object_name) { 553685c88c5SGreg Clayton var_sp = variable_list->FindVariable(method_object_name); 554b9c1b51eSKate Stone if (var_sp) { 555685c88c5SGreg Clayton separator_idx = 0; 556*24bd3178SZachary Turner var_expr_storage = "->"; 557*24bd3178SZachary Turner var_expr_storage += var_expr; 558*24bd3178SZachary Turner var_expr = var_expr_storage; 559685c88c5SGreg Clayton synthetically_added_instance_object = true; 560685c88c5SGreg Clayton } 561685c88c5SGreg Clayton } 562685c88c5SGreg Clayton } 563685c88c5SGreg Clayton } 564685c88c5SGreg Clayton 565b9c1b51eSKate Stone if (!var_sp && (options & eExpressionPathOptionsInspectAnonymousUnions)) { 566b9c1b51eSKate Stone // Check if any anonymous unions are there which contain a variable with 567b9c1b51eSKate Stone // the name we need 568b9c1b51eSKate Stone for (size_t i = 0; i < variable_list->GetSize(); i++) { 569*24bd3178SZachary Turner VariableSP variable_sp = variable_list->GetVariableAtIndex(i); 570*24bd3178SZachary Turner if (!variable_sp) 571*24bd3178SZachary Turner continue; 572*24bd3178SZachary Turner if (!variable_sp->GetName().IsEmpty()) 573*24bd3178SZachary Turner continue; 574*24bd3178SZachary Turner 575*24bd3178SZachary Turner Type *var_type = variable_sp->GetType(); 576*24bd3178SZachary Turner if (!var_type) 577*24bd3178SZachary Turner continue; 578*24bd3178SZachary Turner 579*24bd3178SZachary Turner if (!var_type->GetForwardCompilerType().IsAnonymousType()) 580*24bd3178SZachary Turner continue; 581*24bd3178SZachary Turner valobj_sp = GetValueObjectForFrameVariable(variable_sp, use_dynamic); 58246252398SEnrico Granata if (!valobj_sp) 58346252398SEnrico Granata return valobj_sp; 584*24bd3178SZachary Turner valobj_sp = valobj_sp->GetChildMemberWithName(name_const_string, true); 58546252398SEnrico Granata if (valobj_sp) 58646252398SEnrico Granata break; 58746252398SEnrico Granata } 58846252398SEnrico Granata } 58946252398SEnrico Granata 590b9c1b51eSKate Stone if (var_sp && !valobj_sp) { 5912837b766SJim Ingham valobj_sp = GetValueObjectForFrameVariable(var_sp, use_dynamic); 59278a685aaSJim Ingham if (!valobj_sp) 59378a685aaSJim Ingham return valobj_sp; 59446252398SEnrico Granata } 595*24bd3178SZachary Turner if (!valobj_sp) { 596*24bd3178SZachary Turner error.SetErrorStringWithFormat("no variable named '%s' found in this frame", 597*24bd3178SZachary Turner name_const_string.GetCString()); 598*24bd3178SZachary Turner return ValueObjectSP(); 599*24bd3178SZachary Turner } 600*24bd3178SZachary Turner 6018b2fe6dcSGreg Clayton // We are dumping at least one child 602b9c1b51eSKate Stone while (separator_idx != std::string::npos) { 6038b2fe6dcSGreg Clayton // Calculate the next separator index ahead of time 6048b2fe6dcSGreg Clayton ValueObjectSP child_valobj_sp; 605*24bd3178SZachary Turner const char separator_type = var_expr[0]; 606b9c1b51eSKate Stone switch (separator_type) { 6078b2fe6dcSGreg Clayton case '-': 608*24bd3178SZachary Turner if (var_expr.size() >= 2 && var_expr[1] != '>') 6098b2fe6dcSGreg Clayton return ValueObjectSP(); 6108b2fe6dcSGreg Clayton 611b9c1b51eSKate Stone if (no_fragile_ivar) { 6126d5e68eaSGreg Clayton // Make sure we aren't trying to deref an objective 6136d5e68eaSGreg Clayton // C ivar if this is not allowed 614b9c1b51eSKate Stone const uint32_t pointer_type_flags = 615b9c1b51eSKate Stone valobj_sp->GetCompilerType().GetTypeInfo(nullptr); 616622be238SEnrico Granata if ((pointer_type_flags & eTypeIsObjC) && 617b9c1b51eSKate Stone (pointer_type_flags & eTypeIsPointer)) { 6186d5e68eaSGreg Clayton // This was an objective C object pointer and 6196d5e68eaSGreg Clayton // it was requested we skip any fragile ivars 6206d5e68eaSGreg Clayton // so return nothing here 6216d5e68eaSGreg Clayton return ValueObjectSP(); 6226d5e68eaSGreg Clayton } 6236d5e68eaSGreg Clayton } 624*24bd3178SZachary Turner var_expr = var_expr.drop_front(); // Remove the '-' 62562e0681aSJason Molenda LLVM_FALLTHROUGH; 626b9c1b51eSKate Stone case '.': { 627*24bd3178SZachary Turner const bool expr_is_ptr = var_expr[0] == '>'; 6288b2fe6dcSGreg Clayton 629*24bd3178SZachary Turner var_expr = var_expr.drop_front(); // Remove the '.' or '>' 630*24bd3178SZachary Turner separator_idx = var_expr.find_first_of(".-["); 631*24bd3178SZachary Turner ConstString child_name(var_expr.substr(0, var_expr.find_first_of(".-["))); 6328b2fe6dcSGreg Clayton 633b9c1b51eSKate Stone if (check_ptr_vs_member) { 63454979cddSGreg Clayton // We either have a pointer type and need to verify 63554979cddSGreg Clayton // valobj_sp is a pointer, or we have a member of a 63654979cddSGreg Clayton // class/union/struct being accessed with the . syntax 63754979cddSGreg Clayton // and need to verify we don't have a pointer. 63854979cddSGreg Clayton const bool actual_is_ptr = valobj_sp->IsPointerType(); 63954979cddSGreg Clayton 640b9c1b51eSKate Stone if (actual_is_ptr != expr_is_ptr) { 64154979cddSGreg Clayton // Incorrect use of "." with a pointer, or "->" with 64254979cddSGreg Clayton // a class/union/struct instance or reference. 6436beaaa68SGreg Clayton valobj_sp->GetExpressionPath(var_expr_path_strm, false); 64454979cddSGreg Clayton if (actual_is_ptr) 645b9c1b51eSKate Stone error.SetErrorStringWithFormat( 646b9c1b51eSKate Stone "\"%s\" is a pointer and . was used to attempt to access " 647b9c1b51eSKate Stone "\"%s\". Did you mean \"%s->%s\"?", 648c156427dSZachary Turner var_expr_path_strm.GetData(), child_name.GetCString(), 649*24bd3178SZachary Turner var_expr_path_strm.GetData(), var_expr.str().c_str()); 65054979cddSGreg Clayton else 651b9c1b51eSKate Stone error.SetErrorStringWithFormat( 652b9c1b51eSKate Stone "\"%s\" is not a pointer and -> was used to attempt to " 653b9c1b51eSKate Stone "access \"%s\". Did you mean \"%s.%s\"?", 654c156427dSZachary Turner var_expr_path_strm.GetData(), child_name.GetCString(), 655*24bd3178SZachary Turner var_expr_path_strm.GetData(), var_expr.str().c_str()); 65654979cddSGreg Clayton return ValueObjectSP(); 65754979cddSGreg Clayton } 65854979cddSGreg Clayton } 659*24bd3178SZachary Turner child_valobj_sp = valobj_sp->GetChildMemberWithName(child_name, true); 660b9c1b51eSKate Stone if (!child_valobj_sp) { 661b9c1b51eSKate Stone if (!no_synth_child) { 66286cc9829SEnrico Granata child_valobj_sp = valobj_sp->GetSyntheticValue(); 66386cc9829SEnrico Granata if (child_valobj_sp) 664b9c1b51eSKate Stone child_valobj_sp = 665b9c1b51eSKate Stone child_valobj_sp->GetChildMemberWithName(child_name, true); 66686cc9829SEnrico Granata } 6678c9d3560SEnrico Granata 668b9c1b51eSKate Stone if (no_synth_child || !child_valobj_sp) { 6698b2fe6dcSGreg Clayton // No child member with name "child_name" 670b9c1b51eSKate Stone if (synthetically_added_instance_object) { 671b9c1b51eSKate Stone // We added a "this->" or "self->" to the beginning of the 672b9c1b51eSKate Stone // expression 673b9c1b51eSKate Stone // and this is the first pointer ivar access, so just return 674b9c1b51eSKate Stone // the normal 675685c88c5SGreg Clayton // error 676b9c1b51eSKate Stone error.SetErrorStringWithFormat( 677b9c1b51eSKate Stone "no variable or instance variable named '%s' found in " 678b9c1b51eSKate Stone "this frame", 679685c88c5SGreg Clayton name_const_string.GetCString()); 680b9c1b51eSKate Stone } else { 6816beaaa68SGreg Clayton valobj_sp->GetExpressionPath(var_expr_path_strm, false); 682b9c1b51eSKate Stone if (child_name) { 683b9c1b51eSKate Stone error.SetErrorStringWithFormat( 684b9c1b51eSKate Stone "\"%s\" is not a member of \"(%s) %s\"", 68554979cddSGreg Clayton child_name.GetCString(), 68654979cddSGreg Clayton valobj_sp->GetTypeName().AsCString("<invalid type>"), 687c156427dSZachary Turner var_expr_path_strm.GetData()); 688b9c1b51eSKate Stone } else { 689b9c1b51eSKate Stone error.SetErrorStringWithFormat( 690b9c1b51eSKate Stone "incomplete expression path after \"%s\" in \"%s\"", 691c156427dSZachary Turner var_expr_path_strm.GetData(), var_expr_cstr); 69254979cddSGreg Clayton } 693685c88c5SGreg Clayton } 6948b2fe6dcSGreg Clayton return ValueObjectSP(); 6958b2fe6dcSGreg Clayton } 6968c9d3560SEnrico Granata } 697685c88c5SGreg Clayton synthetically_added_instance_object = false; 6988b2fe6dcSGreg Clayton // Remove the child name from the path 699*24bd3178SZachary Turner var_expr = var_expr.drop_front(child_name.GetLength()); 700b9c1b51eSKate Stone if (use_dynamic != eNoDynamicValues) { 701b9c1b51eSKate Stone ValueObjectSP dynamic_value_sp( 702b9c1b51eSKate Stone child_valobj_sp->GetDynamicValue(use_dynamic)); 70378a685aaSJim Ingham if (dynamic_value_sp) 70478a685aaSJim Ingham child_valobj_sp = dynamic_value_sp; 70578a685aaSJim Ingham } 706b9c1b51eSKate Stone } break; 7078b2fe6dcSGreg Clayton 708*24bd3178SZachary Turner case '[': { 7098b2fe6dcSGreg Clayton // Array member access, or treating pointer as an array 710*24bd3178SZachary Turner // Need at least two brackets and a number 711*24bd3178SZachary Turner if (var_expr.size() <= 2) { 712*24bd3178SZachary Turner error.SetErrorStringWithFormat( 713*24bd3178SZachary Turner "invalid square bracket encountered after \"%s\" in \"%s\"", 714*24bd3178SZachary Turner var_expr_path_strm.GetData(), var_expr.str().c_str()); 715*24bd3178SZachary Turner return ValueObjectSP(); 716*24bd3178SZachary Turner } 717*24bd3178SZachary Turner 718*24bd3178SZachary Turner // Drop the open brace. 719*24bd3178SZachary Turner var_expr = var_expr.drop_front(); 720*24bd3178SZachary Turner long child_index = 0; 721*24bd3178SZachary Turner 722*24bd3178SZachary Turner // If there's no closing brace, this is an invalid expression. 723*24bd3178SZachary Turner size_t end_pos = var_expr.find_first_of(']'); 724*24bd3178SZachary Turner if (end_pos == llvm::StringRef::npos) { 725*24bd3178SZachary Turner error.SetErrorStringWithFormat( 726*24bd3178SZachary Turner "missing closing square bracket in expression \"%s\"", 727*24bd3178SZachary Turner var_expr_path_strm.GetData()); 728*24bd3178SZachary Turner return ValueObjectSP(); 729*24bd3178SZachary Turner } 730*24bd3178SZachary Turner llvm::StringRef index_expr = var_expr.take_front(end_pos); 731*24bd3178SZachary Turner llvm::StringRef original_index_expr = index_expr; 732*24bd3178SZachary Turner // Drop all of "[index_expr]" 733*24bd3178SZachary Turner var_expr = var_expr.drop_front(end_pos + 1); 734*24bd3178SZachary Turner 735*24bd3178SZachary Turner if (index_expr.consumeInteger(0, child_index)) { 736*24bd3178SZachary Turner // If there was no integer anywhere in the index expression, this is 737*24bd3178SZachary Turner // erroneous expression. 738*24bd3178SZachary Turner error.SetErrorStringWithFormat("invalid index expression \"%s\"", 739*24bd3178SZachary Turner index_expr.str().c_str()); 740*24bd3178SZachary Turner return ValueObjectSP(); 741*24bd3178SZachary Turner } 742*24bd3178SZachary Turner 743*24bd3178SZachary Turner if (index_expr.empty()) { 744*24bd3178SZachary Turner // The entire index expression was a single integer. 745*24bd3178SZachary Turner 746*24bd3178SZachary Turner if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) { 747*24bd3178SZachary Turner // what we have is *ptr[low]. the most similar C++ syntax is to deref 748*24bd3178SZachary Turner // ptr and extract bit low out of it. reading array item low would be 749*24bd3178SZachary Turner // done by saying ptr[low], without a deref * sign 7509fc1944eSEnrico Granata Error error; 7519fc1944eSEnrico Granata ValueObjectSP temp(valobj_sp->Dereference(error)); 752b9c1b51eSKate Stone if (error.Fail()) { 7539fc1944eSEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 754b9c1b51eSKate Stone error.SetErrorStringWithFormat( 755b9c1b51eSKate Stone "could not dereference \"(%s) %s\"", 7569fc1944eSEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 757c156427dSZachary Turner var_expr_path_strm.GetData()); 7589fc1944eSEnrico Granata return ValueObjectSP(); 7599fc1944eSEnrico Granata } 7609fc1944eSEnrico Granata valobj_sp = temp; 7619fc1944eSEnrico Granata deref = false; 762b9c1b51eSKate Stone } else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() && 763b9c1b51eSKate Stone deref) { 764b9c1b51eSKate Stone // what we have is *arr[low]. the most similar C++ syntax is 765b9c1b51eSKate Stone // to get arr[0] 7669fc1944eSEnrico Granata // (an operation that is equivalent to deref-ing arr) 7679fc1944eSEnrico Granata // and extract bit low out of it. reading array item low 7689fc1944eSEnrico Granata // would be done by saying arr[low], without a deref * sign 7699fc1944eSEnrico Granata Error error; 7709fc1944eSEnrico Granata ValueObjectSP temp(valobj_sp->GetChildAtIndex(0, true)); 771b9c1b51eSKate Stone if (error.Fail()) { 7729fc1944eSEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 773b9c1b51eSKate Stone error.SetErrorStringWithFormat( 774b9c1b51eSKate Stone "could not get item 0 for \"(%s) %s\"", 7759fc1944eSEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 776c156427dSZachary Turner var_expr_path_strm.GetData()); 7779fc1944eSEnrico Granata return ValueObjectSP(); 7789fc1944eSEnrico Granata } 7799fc1944eSEnrico Granata valobj_sp = temp; 7809fc1944eSEnrico Granata deref = false; 7819fc1944eSEnrico Granata } 7828b2fe6dcSGreg Clayton 7834ef877f5SGreg Clayton bool is_incomplete_array = false; 784b9c1b51eSKate Stone if (valobj_sp->IsPointerType()) { 785226b70c1SSean Callanan bool is_objc_pointer = true; 786226b70c1SSean Callanan 787b9c1b51eSKate Stone if (valobj_sp->GetCompilerType().GetMinimumLanguage() != 788b9c1b51eSKate Stone eLanguageTypeObjC) 789226b70c1SSean Callanan is_objc_pointer = false; 79099558cc4SGreg Clayton else if (!valobj_sp->GetCompilerType().IsPointerType()) 791226b70c1SSean Callanan is_objc_pointer = false; 792226b70c1SSean Callanan 793b9c1b51eSKate Stone if (no_synth_child && is_objc_pointer) { 794b9c1b51eSKate Stone error.SetErrorStringWithFormat( 795b9c1b51eSKate Stone "\"(%s) %s\" is an Objective-C pointer, and cannot be " 796b9c1b51eSKate Stone "subscripted", 797226b70c1SSean Callanan valobj_sp->GetTypeName().AsCString("<invalid type>"), 798c156427dSZachary Turner var_expr_path_strm.GetData()); 799226b70c1SSean Callanan 800226b70c1SSean Callanan return ValueObjectSP(); 801b9c1b51eSKate Stone } else if (is_objc_pointer) { 802b9c1b51eSKate Stone // dereferencing ObjC variables is not valid.. so let's try 803b9c1b51eSKate Stone // and recur to synthetic children 80486cc9829SEnrico Granata ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(); 805d70a6e71SEugene Zelenko if (!synthetic /* no synthetic */ 806b9c1b51eSKate Stone || synthetic == valobj_sp) /* synthetic is the same as 807b9c1b51eSKate Stone the original object */ 80827b625e1SEnrico Granata { 80927b625e1SEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 810b9c1b51eSKate Stone error.SetErrorStringWithFormat( 811b9c1b51eSKate Stone "\"(%s) %s\" is not an array type", 81227b625e1SEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 813c156427dSZachary Turner var_expr_path_strm.GetData()); 814b9c1b51eSKate Stone } else if ( 815b9c1b51eSKate Stone static_cast<uint32_t>(child_index) >= 816b9c1b51eSKate Stone synthetic 817b9c1b51eSKate Stone ->GetNumChildren() /* synthetic does not have that many values */) { 81827b625e1SEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 819b9c1b51eSKate Stone error.SetErrorStringWithFormat( 820*24bd3178SZachary Turner "array index %ld is not valid for \"(%s) %s\"", child_index, 82127b625e1SEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 822c156427dSZachary Turner var_expr_path_strm.GetData()); 823b9c1b51eSKate Stone } else { 824*24bd3178SZachary Turner child_valobj_sp = synthetic->GetChildAtIndex(child_index, true); 825b9c1b51eSKate Stone if (!child_valobj_sp) { 82627b625e1SEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 827b9c1b51eSKate Stone error.SetErrorStringWithFormat( 828*24bd3178SZachary Turner "array index %ld is not valid for \"(%s) %s\"", child_index, 829*24bd3178SZachary Turner valobj_sp->GetTypeName().AsCString("<invalid type>"), 830c156427dSZachary Turner var_expr_path_strm.GetData()); 831b9c1b51eSKate Stone } 832b9c1b51eSKate Stone } 833b9c1b51eSKate Stone } else { 834b9c1b51eSKate Stone child_valobj_sp = 835b9c1b51eSKate Stone valobj_sp->GetSyntheticArrayMember(child_index, true); 836b9c1b51eSKate Stone if (!child_valobj_sp) { 837b9c1b51eSKate Stone valobj_sp->GetExpressionPath(var_expr_path_strm, false); 838b9c1b51eSKate Stone error.SetErrorStringWithFormat( 839b9c1b51eSKate Stone "failed to use pointer as array for index %ld for " 840b9c1b51eSKate Stone "\"(%s) %s\"", 84127b625e1SEnrico Granata child_index, 84227b625e1SEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 843c156427dSZachary Turner var_expr_path_strm.GetData()); 84427b625e1SEnrico Granata } 84527b625e1SEnrico Granata } 846b9c1b51eSKate Stone } else if (valobj_sp->GetCompilerType().IsArrayType( 847b9c1b51eSKate Stone nullptr, nullptr, &is_incomplete_array)) { 848b9c1b51eSKate Stone // Pass false to dynamic_value here so we can tell the 849b9c1b51eSKate Stone // difference between 85078a685aaSJim Ingham // no dynamic value and no member of this type... 851*24bd3178SZachary Turner child_valobj_sp = valobj_sp->GetChildAtIndex(child_index, true); 852*24bd3178SZachary Turner if (!child_valobj_sp && (is_incomplete_array || !no_synth_child)) 853b9c1b51eSKate Stone child_valobj_sp = 854b9c1b51eSKate Stone valobj_sp->GetSyntheticArrayMember(child_index, true); 8554ef877f5SGreg Clayton 856b9c1b51eSKate Stone if (!child_valobj_sp) { 8576beaaa68SGreg Clayton valobj_sp->GetExpressionPath(var_expr_path_strm, false); 858b9c1b51eSKate Stone error.SetErrorStringWithFormat( 859*24bd3178SZachary Turner "array index %ld is not valid for \"(%s) %s\"", child_index, 86054979cddSGreg Clayton valobj_sp->GetTypeName().AsCString("<invalid type>"), 861c156427dSZachary Turner var_expr_path_strm.GetData()); 86254979cddSGreg Clayton } 863b9c1b51eSKate Stone } else if (valobj_sp->GetCompilerType().IsScalarType()) { 8649fc1944eSEnrico Granata // this is a bitfield asking to display just one bit 865b9c1b51eSKate Stone child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild( 866b9c1b51eSKate Stone child_index, child_index, true); 867b9c1b51eSKate Stone if (!child_valobj_sp) { 8689fc1944eSEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 869b9c1b51eSKate Stone error.SetErrorStringWithFormat( 870b9c1b51eSKate Stone "bitfield range %ld-%ld is not valid for \"(%s) %s\"", 8719fc1944eSEnrico Granata child_index, child_index, 8729fc1944eSEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 873c156427dSZachary Turner var_expr_path_strm.GetData()); 8749fc1944eSEnrico Granata } 875b9c1b51eSKate Stone } else { 87686cc9829SEnrico Granata ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(); 87727b625e1SEnrico Granata if (no_synth_child /* synthetic is forbidden */ || 878d70a6e71SEugene Zelenko !synthetic /* no synthetic */ 8790b4c26b2SJason Molenda || synthetic == valobj_sp) /* synthetic is the same as the 880b9c1b51eSKate Stone original object */ 88127b625e1SEnrico Granata { 8826beaaa68SGreg Clayton valobj_sp->GetExpressionPath(var_expr_path_strm, false); 883b9c1b51eSKate Stone error.SetErrorStringWithFormat( 884b9c1b51eSKate Stone "\"(%s) %s\" is not an array type", 88554979cddSGreg Clayton valobj_sp->GetTypeName().AsCString("<invalid type>"), 886c156427dSZachary Turner var_expr_path_strm.GetData()); 887b9c1b51eSKate Stone } else if ( 888b9c1b51eSKate Stone static_cast<uint32_t>(child_index) >= 889b9c1b51eSKate Stone synthetic 890b9c1b51eSKate Stone ->GetNumChildren() /* synthetic does not have that many values */) { 89127b625e1SEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 892b9c1b51eSKate Stone error.SetErrorStringWithFormat( 893*24bd3178SZachary Turner "array index %ld is not valid for \"(%s) %s\"", child_index, 89427b625e1SEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 895c156427dSZachary Turner var_expr_path_strm.GetData()); 896b9c1b51eSKate Stone } else { 897*24bd3178SZachary Turner child_valobj_sp = synthetic->GetChildAtIndex(child_index, true); 898b9c1b51eSKate Stone if (!child_valobj_sp) { 89927b625e1SEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 900b9c1b51eSKate Stone error.SetErrorStringWithFormat( 901*24bd3178SZachary Turner "array index %ld is not valid for \"(%s) %s\"", child_index, 90227b625e1SEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 903c156427dSZachary Turner var_expr_path_strm.GetData()); 90427b625e1SEnrico Granata } 90527b625e1SEnrico Granata } 90627b625e1SEnrico Granata } 9078b2fe6dcSGreg Clayton 908b9c1b51eSKate Stone if (!child_valobj_sp) { 9098b2fe6dcSGreg Clayton // Invalid array index... 9108b2fe6dcSGreg Clayton return ValueObjectSP(); 9118b2fe6dcSGreg Clayton } 9128b2fe6dcSGreg Clayton 913*24bd3178SZachary Turner separator_idx = var_expr.find_first_of(".-["); 914b9c1b51eSKate Stone if (use_dynamic != eNoDynamicValues) { 915b9c1b51eSKate Stone ValueObjectSP dynamic_value_sp( 916b9c1b51eSKate Stone child_valobj_sp->GetDynamicValue(use_dynamic)); 91778a685aaSJim Ingham if (dynamic_value_sp) 91878a685aaSJim Ingham child_valobj_sp = dynamic_value_sp; 91978a685aaSJim Ingham } 920*24bd3178SZachary Turner // Break out early from the switch since we were able to find the child 921*24bd3178SZachary Turner // member 9228b2fe6dcSGreg Clayton break; 923*24bd3178SZachary Turner } 924*24bd3178SZachary Turner 9259fc1944eSEnrico Granata // this is most probably a BitField, let's take a look 926*24bd3178SZachary Turner if (index_expr.front() != '-') { 927*24bd3178SZachary Turner error.SetErrorStringWithFormat("invalid range expression \"'%s'\"", 928*24bd3178SZachary Turner original_index_expr.str().c_str()); 929*24bd3178SZachary Turner return ValueObjectSP(); 930*24bd3178SZachary Turner } 931*24bd3178SZachary Turner 932*24bd3178SZachary Turner index_expr.drop_front(); 933*24bd3178SZachary Turner long final_index = 0; 934*24bd3178SZachary Turner if (index_expr.getAsInteger(0, final_index)) { 935*24bd3178SZachary Turner error.SetErrorStringWithFormat("invalid range expression \"'%s'\"", 936*24bd3178SZachary Turner original_index_expr.str().c_str()); 937*24bd3178SZachary Turner return ValueObjectSP(); 938*24bd3178SZachary Turner } 939*24bd3178SZachary Turner 9409fc1944eSEnrico Granata // if the format given is [high-low], swap range 941b9c1b51eSKate Stone if (child_index > final_index) { 9429fc1944eSEnrico Granata long temp = child_index; 9439fc1944eSEnrico Granata child_index = final_index; 9449fc1944eSEnrico Granata final_index = temp; 9459fc1944eSEnrico Granata } 9469fc1944eSEnrico Granata 947*24bd3178SZachary Turner if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) { 948*24bd3178SZachary Turner // what we have is *ptr[low-high]. the most similar C++ syntax is to 949*24bd3178SZachary Turner // deref ptr and extract bits low thru high out of it. reading array 950*24bd3178SZachary Turner // items low thru high would be done by saying ptr[low-high], without 951*24bd3178SZachary Turner // a deref * sign 9529fc1944eSEnrico Granata Error error; 9539fc1944eSEnrico Granata ValueObjectSP temp(valobj_sp->Dereference(error)); 954b9c1b51eSKate Stone if (error.Fail()) { 9559fc1944eSEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 956b9c1b51eSKate Stone error.SetErrorStringWithFormat( 957b9c1b51eSKate Stone "could not dereference \"(%s) %s\"", 9589fc1944eSEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 959c156427dSZachary Turner var_expr_path_strm.GetData()); 9609fc1944eSEnrico Granata return ValueObjectSP(); 9619fc1944eSEnrico Granata } 9629fc1944eSEnrico Granata valobj_sp = temp; 9639fc1944eSEnrico Granata deref = false; 964*24bd3178SZachary Turner } else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() && deref) { 965*24bd3178SZachary Turner // what we have is *arr[low-high]. the most similar C++ syntax is to get 966*24bd3178SZachary Turner // arr[0] (an operation that is equivalent to deref-ing arr) and extract 967*24bd3178SZachary Turner // bits low thru high out of it. reading array items low thru high would 968*24bd3178SZachary Turner // be done by saying arr[low-high], without a deref * sign 9699fc1944eSEnrico Granata Error error; 9709fc1944eSEnrico Granata ValueObjectSP temp(valobj_sp->GetChildAtIndex(0, true)); 971b9c1b51eSKate Stone if (error.Fail()) { 9729fc1944eSEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 973b9c1b51eSKate Stone error.SetErrorStringWithFormat( 974b9c1b51eSKate Stone "could not get item 0 for \"(%s) %s\"", 9759fc1944eSEnrico Granata valobj_sp->GetTypeName().AsCString("<invalid type>"), 976c156427dSZachary Turner var_expr_path_strm.GetData()); 9779fc1944eSEnrico Granata return ValueObjectSP(); 9789fc1944eSEnrico Granata } 9799fc1944eSEnrico Granata valobj_sp = temp; 9809fc1944eSEnrico Granata deref = false; 9819fc1944eSEnrico Granata } 9829fc1944eSEnrico Granata 983*24bd3178SZachary Turner child_valobj_sp = 984*24bd3178SZachary Turner valobj_sp->GetSyntheticBitFieldChild(child_index, final_index, true); 985b9c1b51eSKate Stone if (!child_valobj_sp) { 9869fc1944eSEnrico Granata valobj_sp->GetExpressionPath(var_expr_path_strm, false); 987b9c1b51eSKate Stone error.SetErrorStringWithFormat( 988*24bd3178SZachary Turner "bitfield range %ld-%ld is not valid for \"(%s) %s\"", child_index, 989*24bd3178SZachary Turner final_index, valobj_sp->GetTypeName().AsCString("<invalid type>"), 990c156427dSZachary Turner var_expr_path_strm.GetData()); 9919fc1944eSEnrico Granata } 9929fc1944eSEnrico Granata 993b9c1b51eSKate Stone if (!child_valobj_sp) { 9949fc1944eSEnrico Granata // Invalid bitfield range... 9959fc1944eSEnrico Granata return ValueObjectSP(); 9969fc1944eSEnrico Granata } 9979fc1944eSEnrico Granata 998*24bd3178SZachary Turner separator_idx = var_expr.find_first_of(".-["); 999b9c1b51eSKate Stone if (use_dynamic != eNoDynamicValues) { 1000b9c1b51eSKate Stone ValueObjectSP dynamic_value_sp( 1001b9c1b51eSKate Stone child_valobj_sp->GetDynamicValue(use_dynamic)); 10029fc1944eSEnrico Granata if (dynamic_value_sp) 10039fc1944eSEnrico Granata child_valobj_sp = dynamic_value_sp; 10049fc1944eSEnrico Granata } 1005*24bd3178SZachary Turner // Break out early from the switch since we were able to find the child 1006*24bd3178SZachary Turner // member 10079fc1944eSEnrico Granata break; 10089fc1944eSEnrico Granata } 10098b2fe6dcSGreg Clayton default: 10108b2fe6dcSGreg Clayton // Failure... 101154979cddSGreg Clayton { 10126beaaa68SGreg Clayton valobj_sp->GetExpressionPath(var_expr_path_strm, false); 1013b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1014b9c1b51eSKate Stone "unexpected char '%c' encountered after \"%s\" in \"%s\"", 1015c156427dSZachary Turner separator_type, var_expr_path_strm.GetData(), 1016*24bd3178SZachary Turner var_expr.str().c_str()); 101754979cddSGreg Clayton 10188b2fe6dcSGreg Clayton return ValueObjectSP(); 10198b2fe6dcSGreg Clayton } 102054979cddSGreg Clayton } 10218b2fe6dcSGreg Clayton 10228b2fe6dcSGreg Clayton if (child_valobj_sp) 10238b2fe6dcSGreg Clayton valobj_sp = child_valobj_sp; 10248b2fe6dcSGreg Clayton 1025*24bd3178SZachary Turner if (var_expr.empty()) 10268b2fe6dcSGreg Clayton break; 10278b2fe6dcSGreg Clayton } 1028b9c1b51eSKate Stone if (valobj_sp) { 1029b9c1b51eSKate Stone if (deref) { 1030af67cecdSGreg Clayton ValueObjectSP deref_valobj_sp(valobj_sp->Dereference(error)); 10318b2fe6dcSGreg Clayton valobj_sp = deref_valobj_sp; 1032b9c1b51eSKate Stone } else if (address_of) { 103354979cddSGreg Clayton ValueObjectSP address_of_valobj_sp(valobj_sp->AddressOf(error)); 10348b2fe6dcSGreg Clayton valobj_sp = address_of_valobj_sp; 10358b2fe6dcSGreg Clayton } 10368b2fe6dcSGreg Clayton } 10378b2fe6dcSGreg Clayton return valobj_sp; 10388b2fe6dcSGreg Clayton } 103930fdc8d8SChris Lattner 1040b9c1b51eSKate Stone bool StackFrame::GetFrameBaseValue(Scalar &frame_base, Error *error_ptr) { 1041bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 1042b9c1b51eSKate Stone if (!m_cfa_is_valid) { 1043b9c1b51eSKate Stone m_frame_base_error.SetErrorString( 1044b9c1b51eSKate Stone "No frame base available for this historical stack frame."); 104599618476SJason Molenda return false; 104699618476SJason Molenda } 104799618476SJason Molenda 1048b9c1b51eSKate Stone if (m_flags.IsClear(GOT_FRAME_BASE)) { 1049b9c1b51eSKate Stone if (m_sc.function) { 105030fdc8d8SChris Lattner m_frame_base.Clear(); 105130fdc8d8SChris Lattner m_frame_base_error.Clear(); 105230fdc8d8SChris Lattner 105330fdc8d8SChris Lattner m_flags.Set(GOT_FRAME_BASE); 1054d9e416c0SGreg Clayton ExecutionContext exe_ctx(shared_from_this()); 105530fdc8d8SChris Lattner Value expr_value; 1056016a95ebSGreg Clayton addr_t loclist_base_addr = LLDB_INVALID_ADDRESS; 1057016a95ebSGreg Clayton if (m_sc.function->GetFrameBaseExpression().IsLocationList()) 1058b9c1b51eSKate Stone loclist_base_addr = 1059b9c1b51eSKate Stone m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress( 1060b9c1b51eSKate Stone exe_ctx.GetTargetPtr()); 1061016a95ebSGreg Clayton 1062b9c1b51eSKate Stone if (m_sc.function->GetFrameBaseExpression().Evaluate( 1063b9c1b51eSKate Stone &exe_ctx, nullptr, nullptr, nullptr, loclist_base_addr, nullptr, 1064b9c1b51eSKate Stone nullptr, expr_value, &m_frame_base_error) == false) { 106530fdc8d8SChris Lattner // We should really have an error if evaluate returns, but in case 106630fdc8d8SChris Lattner // we don't, lets set the error to something at least. 106730fdc8d8SChris Lattner if (m_frame_base_error.Success()) 1068b9c1b51eSKate Stone m_frame_base_error.SetErrorString( 1069b9c1b51eSKate Stone "Evaluation of the frame base expression failed."); 1070b9c1b51eSKate Stone } else { 107157ee3067SGreg Clayton m_frame_base = expr_value.ResolveValue(&exe_ctx); 107230fdc8d8SChris Lattner } 1073b9c1b51eSKate Stone } else { 107430fdc8d8SChris Lattner m_frame_base_error.SetErrorString("No function in symbol context."); 107530fdc8d8SChris Lattner } 107630fdc8d8SChris Lattner } 107730fdc8d8SChris Lattner 107830fdc8d8SChris Lattner if (m_frame_base_error.Success()) 107930fdc8d8SChris Lattner frame_base = m_frame_base; 108030fdc8d8SChris Lattner 108130fdc8d8SChris Lattner if (error_ptr) 108230fdc8d8SChris Lattner *error_ptr = m_frame_base_error; 108330fdc8d8SChris Lattner return m_frame_base_error.Success(); 108430fdc8d8SChris Lattner } 108530fdc8d8SChris Lattner 1086b9c1b51eSKate Stone DWARFExpression *StackFrame::GetFrameBaseExpression(Error *error_ptr) { 1087b9c1b51eSKate Stone if (!m_sc.function) { 1088b9c1b51eSKate Stone if (error_ptr) { 10894740a734SSean Callanan error_ptr->SetErrorString("No function in symbol context."); 10904740a734SSean Callanan } 10914740a734SSean Callanan return nullptr; 10924740a734SSean Callanan } 10934740a734SSean Callanan 10944740a734SSean Callanan return &m_sc.function->GetFrameBaseExpression(); 10954740a734SSean Callanan } 10964740a734SSean Callanan 1097b9c1b51eSKate Stone RegisterContextSP StackFrame::GetRegisterContext() { 1098bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 1099b9c1b51eSKate Stone if (!m_reg_context_sp) { 1100d9e416c0SGreg Clayton ThreadSP thread_sp(GetThread()); 1101d9e416c0SGreg Clayton if (thread_sp) 1102d9e416c0SGreg Clayton m_reg_context_sp = thread_sp->CreateRegisterContextForFrame(this); 1103d9e416c0SGreg Clayton } 11045ccbd294SGreg Clayton return m_reg_context_sp; 110530fdc8d8SChris Lattner } 110630fdc8d8SChris Lattner 1107b9c1b51eSKate Stone bool StackFrame::HasDebugInformation() { 110830fdc8d8SChris Lattner GetSymbolContext(eSymbolContextLineEntry); 110930fdc8d8SChris Lattner return m_sc.line_entry.IsValid(); 111030fdc8d8SChris Lattner } 111130fdc8d8SChris Lattner 1112288bdf9cSGreg Clayton ValueObjectSP 1113b9c1b51eSKate Stone StackFrame::GetValueObjectForFrameVariable(const VariableSP &variable_sp, 1114b9c1b51eSKate Stone DynamicValueType use_dynamic) { 1115bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 1116288bdf9cSGreg Clayton ValueObjectSP valobj_sp; 1117b9c1b51eSKate Stone if (m_is_history_frame) { 111899618476SJason Molenda return valobj_sp; 111999618476SJason Molenda } 1120288bdf9cSGreg Clayton VariableList *var_list = GetVariableList(true); 1121b9c1b51eSKate Stone if (var_list) { 1122288bdf9cSGreg Clayton // Make sure the variable is a frame variable 1123288bdf9cSGreg Clayton const uint32_t var_idx = var_list->FindIndexForVariable(variable_sp.get()); 1124288bdf9cSGreg Clayton const uint32_t num_variables = var_list->GetSize(); 1125b9c1b51eSKate Stone if (var_idx < num_variables) { 1126288bdf9cSGreg Clayton valobj_sp = m_variable_list_value_objects.GetValueObjectAtIndex(var_idx); 1127b9c1b51eSKate Stone if (!valobj_sp) { 1128288bdf9cSGreg Clayton if (m_variable_list_value_objects.GetSize() < num_variables) 1129288bdf9cSGreg Clayton m_variable_list_value_objects.Resize(num_variables); 113058b59f95SJim Ingham valobj_sp = ValueObjectVariable::Create(this, variable_sp); 1131288bdf9cSGreg Clayton m_variable_list_value_objects.SetValueObjectAtIndex(var_idx, valobj_sp); 1132288bdf9cSGreg Clayton } 1133288bdf9cSGreg Clayton } 1134288bdf9cSGreg Clayton } 1135b9c1b51eSKate Stone if (use_dynamic != eNoDynamicValues && valobj_sp) { 11362837b766SJim Ingham ValueObjectSP dynamic_sp = valobj_sp->GetDynamicValue(use_dynamic); 113778a685aaSJim Ingham if (dynamic_sp) 113878a685aaSJim Ingham return dynamic_sp; 113978a685aaSJim Ingham } 1140288bdf9cSGreg Clayton return valobj_sp; 1141288bdf9cSGreg Clayton } 1142288bdf9cSGreg Clayton 1143b9c1b51eSKate Stone ValueObjectSP StackFrame::TrackGlobalVariable(const VariableSP &variable_sp, 1144b9c1b51eSKate Stone DynamicValueType use_dynamic) { 1145bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 114699618476SJason Molenda if (m_is_history_frame) 114799618476SJason Molenda return ValueObjectSP(); 114899618476SJason Molenda 1149288bdf9cSGreg Clayton // Check to make sure we aren't already tracking this variable? 1150b9c1b51eSKate Stone ValueObjectSP valobj_sp( 1151b9c1b51eSKate Stone GetValueObjectForFrameVariable(variable_sp, use_dynamic)); 1152b9c1b51eSKate Stone if (!valobj_sp) { 1153288bdf9cSGreg Clayton // We aren't already tracking this global 1154288bdf9cSGreg Clayton VariableList *var_list = GetVariableList(true); 1155288bdf9cSGreg Clayton // If this frame has no variables, create a new list 1156d70a6e71SEugene Zelenko if (var_list == nullptr) 1157288bdf9cSGreg Clayton m_variable_list_sp.reset(new VariableList()); 1158288bdf9cSGreg Clayton 1159288bdf9cSGreg Clayton // Add the global/static variable to this frame 1160288bdf9cSGreg Clayton m_variable_list_sp->AddVariable(variable_sp); 1161288bdf9cSGreg Clayton 1162288bdf9cSGreg Clayton // Now make a value object for it so we can track its changes 116378a685aaSJim Ingham valobj_sp = GetValueObjectForFrameVariable(variable_sp, use_dynamic); 1164288bdf9cSGreg Clayton } 1165288bdf9cSGreg Clayton return valobj_sp; 116630fdc8d8SChris Lattner } 116730fdc8d8SChris Lattner 1168b9c1b51eSKate Stone bool StackFrame::IsInlined() { 1169d70a6e71SEugene Zelenko if (m_sc.block == nullptr) 117059e8fc1cSGreg Clayton GetSymbolContext(eSymbolContextBlock); 117159e8fc1cSGreg Clayton if (m_sc.block) 1172d70a6e71SEugene Zelenko return m_sc.block->GetContainingInlinedBlock() != nullptr; 117359e8fc1cSGreg Clayton return false; 11746b8379c4SJim Ingham } 11756b8379c4SJim Ingham 1176b9c1b51eSKate Stone lldb::LanguageType StackFrame::GetLanguage() { 1177009d110dSDawn Perchik CompileUnit *cu = GetSymbolContext(eSymbolContextCompUnit).comp_unit; 1178009d110dSDawn Perchik if (cu) 1179009d110dSDawn Perchik return cu->GetLanguage(); 1180009d110dSDawn Perchik return lldb::eLanguageTypeUnknown; 1181009d110dSDawn Perchik } 1182009d110dSDawn Perchik 1183b9c1b51eSKate Stone lldb::LanguageType StackFrame::GuessLanguage() { 1184592afe73SEnrico Granata LanguageType lang_type = GetLanguage(); 1185592afe73SEnrico Granata 1186b9c1b51eSKate Stone if (lang_type == eLanguageTypeUnknown) { 1187592afe73SEnrico Granata Function *f = GetSymbolContext(eSymbolContextFunction).function; 1188b9c1b51eSKate Stone if (f) { 1189592afe73SEnrico Granata lang_type = f->GetMangled().GuessLanguage(); 1190592afe73SEnrico Granata } 1191592afe73SEnrico Granata } 1192592afe73SEnrico Granata 1193592afe73SEnrico Granata return lang_type; 1194592afe73SEnrico Granata } 1195592afe73SEnrico Granata 1196b9c1b51eSKate Stone namespace { 11974740a734SSean Callanan std::pair<const Instruction::Operand *, int64_t> 11984740a734SSean Callanan GetBaseExplainingValue(const Instruction::Operand &operand, 1199b9c1b51eSKate Stone RegisterContext ®ister_context, lldb::addr_t value) { 1200b9c1b51eSKate Stone switch (operand.m_type) { 12014740a734SSean Callanan case Instruction::Operand::Type::Dereference: 12024740a734SSean Callanan case Instruction::Operand::Type::Immediate: 12034740a734SSean Callanan case Instruction::Operand::Type::Invalid: 12044740a734SSean Callanan case Instruction::Operand::Type::Product: 12054740a734SSean Callanan // These are not currently interesting 12064740a734SSean Callanan return std::make_pair(nullptr, 0); 1207b9c1b51eSKate Stone case Instruction::Operand::Type::Sum: { 12084740a734SSean Callanan const Instruction::Operand *immediate_child = nullptr; 12094740a734SSean Callanan const Instruction::Operand *variable_child = nullptr; 1210b9c1b51eSKate Stone if (operand.m_children[0].m_type == Instruction::Operand::Type::Immediate) { 12114740a734SSean Callanan immediate_child = &operand.m_children[0]; 12124740a734SSean Callanan variable_child = &operand.m_children[1]; 1213b9c1b51eSKate Stone } else if (operand.m_children[1].m_type == 1214b9c1b51eSKate Stone Instruction::Operand::Type::Immediate) { 12154740a734SSean Callanan immediate_child = &operand.m_children[1]; 12164740a734SSean Callanan variable_child = &operand.m_children[0]; 12174740a734SSean Callanan } 1218b9c1b51eSKate Stone if (!immediate_child) { 12194740a734SSean Callanan return std::make_pair(nullptr, 0); 12204740a734SSean Callanan } 12214740a734SSean Callanan lldb::addr_t adjusted_value = value; 1222b9c1b51eSKate Stone if (immediate_child->m_negative) { 12234740a734SSean Callanan adjusted_value += immediate_child->m_immediate; 1224b9c1b51eSKate Stone } else { 12254740a734SSean Callanan adjusted_value -= immediate_child->m_immediate; 12264740a734SSean Callanan } 1227b9c1b51eSKate Stone std::pair<const Instruction::Operand *, int64_t> base_and_offset = 1228b9c1b51eSKate Stone GetBaseExplainingValue(*variable_child, register_context, 1229b9c1b51eSKate Stone adjusted_value); 1230b9c1b51eSKate Stone if (!base_and_offset.first) { 12314740a734SSean Callanan return std::make_pair(nullptr, 0); 12324740a734SSean Callanan } 1233b9c1b51eSKate Stone if (immediate_child->m_negative) { 12344740a734SSean Callanan base_and_offset.second -= immediate_child->m_immediate; 1235b9c1b51eSKate Stone } else { 12364740a734SSean Callanan base_and_offset.second += immediate_child->m_immediate; 12374740a734SSean Callanan } 12384740a734SSean Callanan return base_and_offset; 12394740a734SSean Callanan } 1240b9c1b51eSKate Stone case Instruction::Operand::Type::Register: { 1241b9c1b51eSKate Stone const RegisterInfo *info = 1242b9c1b51eSKate Stone register_context.GetRegisterInfoByName(operand.m_register.AsCString()); 1243b9c1b51eSKate Stone if (!info) { 12444740a734SSean Callanan return std::make_pair(nullptr, 0); 12454740a734SSean Callanan } 12464740a734SSean Callanan RegisterValue reg_value; 1247b9c1b51eSKate Stone if (!register_context.ReadRegister(info, reg_value)) { 12484740a734SSean Callanan return std::make_pair(nullptr, 0); 12494740a734SSean Callanan } 1250b9c1b51eSKate Stone if (reg_value.GetAsUInt64() == value) { 12514740a734SSean Callanan return std::make_pair(&operand, 0); 1252b9c1b51eSKate Stone } else { 12534740a734SSean Callanan return std::make_pair(nullptr, 0); 12544740a734SSean Callanan } 12554740a734SSean Callanan } 12564740a734SSean Callanan } 12575a8ad459SZachary Turner return std::make_pair(nullptr, 0); 12584740a734SSean Callanan } 12594740a734SSean Callanan 12604740a734SSean Callanan std::pair<const Instruction::Operand *, int64_t> 12614740a734SSean Callanan GetBaseExplainingDereference(const Instruction::Operand &operand, 12624740a734SSean Callanan RegisterContext ®ister_context, 1263b9c1b51eSKate Stone lldb::addr_t addr) { 1264b9c1b51eSKate Stone if (operand.m_type == Instruction::Operand::Type::Dereference) { 1265b9c1b51eSKate Stone return GetBaseExplainingValue(operand.m_children[0], register_context, 12664740a734SSean Callanan addr); 12674740a734SSean Callanan } 12684740a734SSean Callanan return std::make_pair(nullptr, 0); 12694740a734SSean Callanan } 12704f730dc7SIlia K } 12714740a734SSean Callanan 1272b9c1b51eSKate Stone lldb::ValueObjectSP StackFrame::GuessValueForAddress(lldb::addr_t addr) { 12734740a734SSean Callanan TargetSP target_sp = CalculateTarget(); 12744740a734SSean Callanan 12754740a734SSean Callanan const ArchSpec &target_arch = target_sp->GetArchitecture(); 12764740a734SSean Callanan 12774740a734SSean Callanan AddressRange pc_range; 12784740a734SSean Callanan pc_range.GetBaseAddress() = GetFrameCodeAddress(); 12794740a734SSean Callanan pc_range.SetByteSize(target_arch.GetMaximumOpcodeByteSize()); 12804740a734SSean Callanan 12814740a734SSean Callanan ExecutionContext exe_ctx(shared_from_this()); 12824740a734SSean Callanan 12834740a734SSean Callanan const char *plugin_name = nullptr; 12844740a734SSean Callanan const char *flavor = nullptr; 12854740a734SSean Callanan const bool prefer_file_cache = false; 12864740a734SSean Callanan 1287b9c1b51eSKate Stone DisassemblerSP disassembler_sp = Disassembler::DisassembleRange( 1288b9c1b51eSKate Stone target_arch, plugin_name, flavor, exe_ctx, pc_range, prefer_file_cache); 12894740a734SSean Callanan 1290b9c1b51eSKate Stone if (!disassembler_sp->GetInstructionList().GetSize()) { 12914740a734SSean Callanan return ValueObjectSP(); 12924740a734SSean Callanan } 12934740a734SSean Callanan 1294b9c1b51eSKate Stone InstructionSP instruction_sp = 1295b9c1b51eSKate Stone disassembler_sp->GetInstructionList().GetInstructionAtIndex(0); 12964740a734SSean Callanan 12974740a734SSean Callanan llvm::SmallVector<Instruction::Operand, 3> operands; 12984740a734SSean Callanan 1299b9c1b51eSKate Stone if (!instruction_sp->ParseOperands(operands)) { 13004740a734SSean Callanan return ValueObjectSP(); 13014740a734SSean Callanan } 13024740a734SSean Callanan 13034740a734SSean Callanan RegisterContextSP register_context_sp = GetRegisterContext(); 13044740a734SSean Callanan 1305b9c1b51eSKate Stone if (!register_context_sp) { 13064740a734SSean Callanan return ValueObjectSP(); 13074740a734SSean Callanan } 13084740a734SSean Callanan 1309b9c1b51eSKate Stone for (const Instruction::Operand &operand : operands) { 1310b9c1b51eSKate Stone std::pair<const Instruction::Operand *, int64_t> base_and_offset = 1311b9c1b51eSKate Stone GetBaseExplainingDereference(operand, *register_context_sp, addr); 13124740a734SSean Callanan 1313b9c1b51eSKate Stone if (!base_and_offset.first) { 13144740a734SSean Callanan continue; 13154740a734SSean Callanan } 13164740a734SSean Callanan 1317b9c1b51eSKate Stone switch (base_and_offset.first->m_type) { 1318b9c1b51eSKate Stone case Instruction::Operand::Type::Immediate: { 13194740a734SSean Callanan lldb_private::Address addr; 1320b9c1b51eSKate Stone if (target_sp->ResolveLoadAddress(base_and_offset.first->m_immediate + 1321b9c1b51eSKate Stone base_and_offset.second, 1322b9c1b51eSKate Stone addr)) { 1323b9c1b51eSKate Stone TypeSystem *c_type_system = 1324b9c1b51eSKate Stone target_sp->GetScratchTypeSystemForLanguage(nullptr, eLanguageTypeC); 1325b9c1b51eSKate Stone if (!c_type_system) { 13264740a734SSean Callanan return ValueObjectSP(); 1327b9c1b51eSKate Stone } else { 1328b9c1b51eSKate Stone CompilerType void_ptr_type = 1329b9c1b51eSKate Stone c_type_system 1330b9c1b51eSKate Stone ->GetBasicTypeFromAST(lldb::BasicType::eBasicTypeChar) 1331b9c1b51eSKate Stone .GetPointerType(); 13324740a734SSean Callanan return ValueObjectMemory::Create(this, "", addr, void_ptr_type); 13334740a734SSean Callanan } 1334b9c1b51eSKate Stone } else { 13354740a734SSean Callanan return ValueObjectSP(); 13364740a734SSean Callanan } 13374740a734SSean Callanan break; 13384740a734SSean Callanan } 1339b9c1b51eSKate Stone case Instruction::Operand::Type::Register: { 1340b9c1b51eSKate Stone return GuessValueForRegisterAndOffset(base_and_offset.first->m_register, 1341b9c1b51eSKate Stone base_and_offset.second); 13424740a734SSean Callanan } 13434740a734SSean Callanan default: 13444740a734SSean Callanan return ValueObjectSP(); 13454740a734SSean Callanan } 13464740a734SSean Callanan } 13474740a734SSean Callanan 13484740a734SSean Callanan return ValueObjectSP(); 13494740a734SSean Callanan } 13504740a734SSean Callanan 1351b9c1b51eSKate Stone namespace { 1352b9c1b51eSKate Stone ValueObjectSP GetValueForOffset(StackFrame &frame, ValueObjectSP &parent, 1353b9c1b51eSKate Stone int64_t offset) { 1354b9c1b51eSKate Stone if (offset < 0 || uint64_t(offset) >= parent->GetByteSize()) { 13554740a734SSean Callanan return ValueObjectSP(); 13564740a734SSean Callanan } 13574740a734SSean Callanan 1358b9c1b51eSKate Stone if (parent->IsPointerOrReferenceType()) { 13594740a734SSean Callanan return parent; 13604740a734SSean Callanan } 13614740a734SSean Callanan 1362b9c1b51eSKate Stone for (int ci = 0, ce = parent->GetNumChildren(); ci != ce; ++ci) { 13634740a734SSean Callanan const bool can_create = true; 13644740a734SSean Callanan ValueObjectSP child_sp = parent->GetChildAtIndex(ci, can_create); 13654740a734SSean Callanan 1366b9c1b51eSKate Stone if (!child_sp) { 13674740a734SSean Callanan return ValueObjectSP(); 13684740a734SSean Callanan } 13694740a734SSean Callanan 13704740a734SSean Callanan int64_t child_offset = child_sp->GetByteOffset(); 13714740a734SSean Callanan int64_t child_size = child_sp->GetByteSize(); 13724740a734SSean Callanan 1373b9c1b51eSKate Stone if (offset >= child_offset && offset < (child_offset + child_size)) { 13744740a734SSean Callanan return GetValueForOffset(frame, child_sp, offset - child_offset); 13754740a734SSean Callanan } 13764740a734SSean Callanan } 13774740a734SSean Callanan 1378b9c1b51eSKate Stone if (offset == 0) { 13794740a734SSean Callanan return parent; 1380b9c1b51eSKate Stone } else { 13814740a734SSean Callanan return ValueObjectSP(); 13824740a734SSean Callanan } 13834740a734SSean Callanan } 13844740a734SSean Callanan 1385b9c1b51eSKate Stone ValueObjectSP GetValueForDereferincingOffset(StackFrame &frame, 1386b9c1b51eSKate Stone ValueObjectSP &base, 1387b9c1b51eSKate Stone int64_t offset) { 13884740a734SSean Callanan // base is a pointer to something 13894740a734SSean Callanan // offset is the thing to add to the pointer 13904740a734SSean Callanan // We return the most sensible ValueObject for the result of *(base+offset) 13914740a734SSean Callanan 1392b9c1b51eSKate Stone if (!base->IsPointerOrReferenceType()) { 13934740a734SSean Callanan return ValueObjectSP(); 13944740a734SSean Callanan } 13954740a734SSean Callanan 13964740a734SSean Callanan Error error; 13974740a734SSean Callanan ValueObjectSP pointee = base->Dereference(error); 1398a0a1d2dbSSean Callanan 1399a0a1d2dbSSean Callanan if (!pointee) { 1400a0a1d2dbSSean Callanan return ValueObjectSP(); 1401a0a1d2dbSSean Callanan } 14024740a734SSean Callanan 14034f730dc7SIlia K if (offset >= 0 && uint64_t(offset) >= pointee->GetByteSize()) { 14044740a734SSean Callanan int64_t index = offset / pointee->GetByteSize(); 14054740a734SSean Callanan offset = offset % pointee->GetByteSize(); 14064740a734SSean Callanan const bool can_create = true; 14074740a734SSean Callanan pointee = base->GetSyntheticArrayMember(index, can_create); 14084740a734SSean Callanan } 14094740a734SSean Callanan 1410b9c1b51eSKate Stone if (!pointee || error.Fail()) { 14114740a734SSean Callanan return ValueObjectSP(); 14124740a734SSean Callanan } 14134740a734SSean Callanan 14144740a734SSean Callanan return GetValueForOffset(frame, pointee, offset); 14154740a734SSean Callanan } 14164740a734SSean Callanan 14174740a734SSean Callanan //------------------------------------------------------------------ 14184740a734SSean Callanan /// Attempt to reconstruct the ValueObject for the address contained in a 14194740a734SSean Callanan /// given register plus an offset. 14204740a734SSean Callanan /// 14214740a734SSean Callanan /// @params [in] frame 14224740a734SSean Callanan /// The current stack frame. 14234740a734SSean Callanan /// 14244740a734SSean Callanan /// @params [in] reg 14254740a734SSean Callanan /// The register. 14264740a734SSean Callanan /// 14274740a734SSean Callanan /// @params [in] offset 14284740a734SSean Callanan /// The offset from the register. 14294740a734SSean Callanan /// 14304740a734SSean Callanan /// @param [in] disassembler 14314740a734SSean Callanan /// A disassembler containing instructions valid up to the current PC. 14324740a734SSean Callanan /// 14334740a734SSean Callanan /// @param [in] variables 14344740a734SSean Callanan /// The variable list from the current frame, 14354740a734SSean Callanan /// 14364740a734SSean Callanan /// @param [in] pc 14374740a734SSean Callanan /// The program counter for the instruction considered the 'user'. 14384740a734SSean Callanan /// 14394740a734SSean Callanan /// @return 14404740a734SSean Callanan /// A string describing the base for the ExpressionPath. This could be a 14414740a734SSean Callanan /// variable, a register value, an argument, or a function return value. 14424740a734SSean Callanan /// The ValueObject if found. If valid, it has a valid ExpressionPath. 14434740a734SSean Callanan //------------------------------------------------------------------ 1444b9c1b51eSKate Stone lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg, 1445b9c1b51eSKate Stone int64_t offset, Disassembler &disassembler, 1446b9c1b51eSKate Stone VariableList &variables, const Address &pc) { 14474740a734SSean Callanan // Example of operation for Intel: 14484740a734SSean Callanan // 14494740a734SSean Callanan // +14: movq -0x8(%rbp), %rdi 14504740a734SSean Callanan // +18: movq 0x8(%rdi), %rdi 14514740a734SSean Callanan // +22: addl 0x4(%rdi), %eax 14524740a734SSean Callanan // 14534740a734SSean Callanan // f, a pointer to a struct, is known to be at -0x8(%rbp). 14544740a734SSean Callanan // 1455b9c1b51eSKate Stone // DoGuessValueAt(frame, rdi, 4, dis, vars, 0x22) finds the instruction at +18 1456b9c1b51eSKate Stone // that assigns to rdi, and calls itself recursively for that dereference 1457b9c1b51eSKate Stone // DoGuessValueAt(frame, rdi, 8, dis, vars, 0x18) finds the instruction at 1458b9c1b51eSKate Stone // +14 that assigns to rdi, and calls itself recursively for that 1459b9c1b51eSKate Stone // derefernece 1460b9c1b51eSKate Stone // DoGuessValueAt(frame, rbp, -8, dis, vars, 0x14) finds "f" in the 1461b9c1b51eSKate Stone // variable list. 14624740a734SSean Callanan // Returns a ValueObject for f. (That's what was stored at rbp-8 at +14) 1463b9c1b51eSKate Stone // Returns a ValueObject for *(f+8) or f->b (That's what was stored at rdi+8 1464b9c1b51eSKate Stone // at +18) 1465b9c1b51eSKate Stone // Returns a ValueObject for *(f->b+4) or f->b->a (That's what was stored at 1466b9c1b51eSKate Stone // rdi+4 at +22) 14674740a734SSean Callanan 1468b9c1b51eSKate Stone // First, check the variable list to see if anything is at the specified 1469b9c1b51eSKate Stone // location. 1470807ee2ffSSean Callanan 147150857108SSean Callanan using namespace OperandMatchers; 147250857108SSean Callanan 14730ac172d8SSean Callanan const RegisterInfo *reg_info = 14740ac172d8SSean Callanan frame.GetRegisterContext()->GetRegisterInfoByName(reg.AsCString()); 14750ac172d8SSean Callanan if (!reg_info) { 14760ac172d8SSean Callanan return ValueObjectSP(); 14770ac172d8SSean Callanan } 14780ac172d8SSean Callanan 1479807ee2ffSSean Callanan Instruction::Operand op = 1480807ee2ffSSean Callanan offset ? Instruction::Operand::BuildDereference( 1481807ee2ffSSean Callanan Instruction::Operand::BuildSum( 1482807ee2ffSSean Callanan Instruction::Operand::BuildRegister(reg), 1483807ee2ffSSean Callanan Instruction::Operand::BuildImmediate(offset))) 1484807ee2ffSSean Callanan : Instruction::Operand::BuildDereference( 1485807ee2ffSSean Callanan Instruction::Operand::BuildRegister(reg)); 1486807ee2ffSSean Callanan 1487b9c1b51eSKate Stone for (size_t vi = 0, ve = variables.GetSize(); vi != ve; ++vi) { 14884740a734SSean Callanan VariableSP var_sp = variables.GetVariableAtIndex(vi); 1489807ee2ffSSean Callanan if (var_sp->LocationExpression().MatchesOperand(frame, op)) { 14904740a734SSean Callanan return frame.GetValueObjectForFrameVariable(var_sp, eNoDynamicValues); 14914740a734SSean Callanan } 14924740a734SSean Callanan } 14934740a734SSean Callanan 1494b9c1b51eSKate Stone const uint32_t current_inst = 1495b9c1b51eSKate Stone disassembler.GetInstructionList().GetIndexOfInstructionAtAddress(pc); 1496b9c1b51eSKate Stone if (current_inst == UINT32_MAX) { 14974740a734SSean Callanan return ValueObjectSP(); 14984740a734SSean Callanan } 14994740a734SSean Callanan 1500b9c1b51eSKate Stone for (uint32_t ii = current_inst - 1; ii != (uint32_t)-1; --ii) { 1501b9c1b51eSKate Stone // This is not an exact algorithm, and it sacrifices accuracy for 15020ac172d8SSean Callanan // generality. Recognizing "mov" and "ld" instructions –– and which are 15030ac172d8SSean Callanan // their source and destination operands -- is something the disassembler 15040ac172d8SSean Callanan // should do for us. 1505b9c1b51eSKate Stone InstructionSP instruction_sp = 1506b9c1b51eSKate Stone disassembler.GetInstructionList().GetInstructionAtIndex(ii); 15074740a734SSean Callanan 150850857108SSean Callanan if (instruction_sp->IsCall()) { 150950857108SSean Callanan ABISP abi_sp = frame.CalculateProcess()->GetABI(); 151050857108SSean Callanan if (!abi_sp) { 151150857108SSean Callanan continue; 151250857108SSean Callanan } 151350857108SSean Callanan 151450857108SSean Callanan const char *return_register_name; 151550857108SSean Callanan if (!abi_sp->GetPointerReturnRegister(return_register_name)) { 151650857108SSean Callanan continue; 151750857108SSean Callanan } 151850857108SSean Callanan 151950857108SSean Callanan const RegisterInfo *return_register_info = 152050857108SSean Callanan frame.GetRegisterContext()->GetRegisterInfoByName( 152150857108SSean Callanan return_register_name); 152250857108SSean Callanan if (!return_register_info) { 152350857108SSean Callanan continue; 152450857108SSean Callanan } 152550857108SSean Callanan 152650857108SSean Callanan int64_t offset = 0; 152750857108SSean Callanan 152850857108SSean Callanan if (!MatchUnaryOp(MatchOpType(Instruction::Operand::Type::Dereference), 152950857108SSean Callanan MatchRegOp(*return_register_info))(op) && 153050857108SSean Callanan !MatchUnaryOp( 153150857108SSean Callanan MatchOpType(Instruction::Operand::Type::Dereference), 153250857108SSean Callanan MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum), 153350857108SSean Callanan MatchRegOp(*return_register_info), 153450857108SSean Callanan FetchImmOp(offset)))(op)) { 153550857108SSean Callanan continue; 153650857108SSean Callanan } 153750857108SSean Callanan 15384740a734SSean Callanan llvm::SmallVector<Instruction::Operand, 1> operands; 1539b9c1b51eSKate Stone if (!instruction_sp->ParseOperands(operands) || operands.size() != 1) { 15404740a734SSean Callanan continue; 15414740a734SSean Callanan } 15424740a734SSean Callanan 1543b9c1b51eSKate Stone switch (operands[0].m_type) { 15444740a734SSean Callanan default: 15454740a734SSean Callanan break; 1546b9c1b51eSKate Stone case Instruction::Operand::Type::Immediate: { 15474740a734SSean Callanan SymbolContext sc; 15484740a734SSean Callanan Address load_address; 1549b9c1b51eSKate Stone if (!frame.CalculateTarget()->ResolveLoadAddress( 1550b9c1b51eSKate Stone operands[0].m_immediate, load_address)) { 15514740a734SSean Callanan break; 15524740a734SSean Callanan } 1553b9c1b51eSKate Stone frame.CalculateTarget()->GetImages().ResolveSymbolContextForAddress( 1554b9c1b51eSKate Stone load_address, eSymbolContextFunction, sc); 1555b9c1b51eSKate Stone if (!sc.function) { 15564740a734SSean Callanan break; 15574740a734SSean Callanan } 15584740a734SSean Callanan CompilerType function_type = sc.function->GetCompilerType(); 1559b9c1b51eSKate Stone if (!function_type.IsFunctionType()) { 15604740a734SSean Callanan break; 15614740a734SSean Callanan } 15624740a734SSean Callanan CompilerType return_type = function_type.GetFunctionReturnType(); 15634740a734SSean Callanan RegisterValue return_value; 156450857108SSean Callanan if (!frame.GetRegisterContext()->ReadRegister(return_register_info, 1565b9c1b51eSKate Stone return_value)) { 15664740a734SSean Callanan break; 15674740a734SSean Callanan } 1568b9c1b51eSKate Stone std::string name_str( 1569b9c1b51eSKate Stone sc.function->GetName().AsCString("<unknown function>")); 15704740a734SSean Callanan name_str.append("()"); 15714740a734SSean Callanan Address return_value_address(return_value.GetAsUInt64()); 1572b9c1b51eSKate Stone ValueObjectSP return_value_sp = ValueObjectMemory::Create( 157322a2628fSZachary Turner &frame, name_str, return_value_address, return_type); 15744740a734SSean Callanan return GetValueForDereferincingOffset(frame, return_value_sp, offset); 15754740a734SSean Callanan } 15764740a734SSean Callanan } 15774740a734SSean Callanan 15784740a734SSean Callanan continue; 15794740a734SSean Callanan } 15804740a734SSean Callanan 15814740a734SSean Callanan llvm::SmallVector<Instruction::Operand, 2> operands; 1582b9c1b51eSKate Stone if (!instruction_sp->ParseOperands(operands) || operands.size() != 2) { 15834740a734SSean Callanan continue; 15844740a734SSean Callanan } 15854740a734SSean Callanan 15864740a734SSean Callanan Instruction::Operand *origin_operand = nullptr; 1587aa4b44c6SSean Callanan auto clobbered_reg_matcher = [reg_info](const Instruction::Operand &op) { 15880ac172d8SSean Callanan return MatchRegOp(*reg_info)(op) && op.m_clobbered; 15890ac172d8SSean Callanan }; 15900ac172d8SSean Callanan 15910ac172d8SSean Callanan if (clobbered_reg_matcher(operands[0])) { 15924740a734SSean Callanan origin_operand = &operands[1]; 15930ac172d8SSean Callanan } 15940ac172d8SSean Callanan else if (clobbered_reg_matcher(operands[1])) { 15954740a734SSean Callanan origin_operand = &operands[0]; 15960ac172d8SSean Callanan } 15970ac172d8SSean Callanan else { 15984740a734SSean Callanan continue; 15994740a734SSean Callanan } 16004740a734SSean Callanan 16014740a734SSean Callanan // We have an origin operand. Can we track its value down? 1602561a9bbfSSean Callanan ValueObjectSP source_path; 1603561a9bbfSSean Callanan ConstString origin_register; 1604561a9bbfSSean Callanan int64_t origin_offset = 0; 1605561a9bbfSSean Callanan 1606561a9bbfSSean Callanan if (FetchRegOp(origin_register)(*origin_operand)) { 1607561a9bbfSSean Callanan source_path = DoGuessValueAt(frame, origin_register, 0, disassembler, 1608561a9bbfSSean Callanan variables, instruction_sp->GetAddress()); 1609561a9bbfSSean Callanan } else if (MatchUnaryOp( 1610561a9bbfSSean Callanan MatchOpType(Instruction::Operand::Type::Dereference), 1611561a9bbfSSean Callanan FetchRegOp(origin_register))(*origin_operand) || 1612561a9bbfSSean Callanan MatchUnaryOp( 1613561a9bbfSSean Callanan MatchOpType(Instruction::Operand::Type::Dereference), 1614561a9bbfSSean Callanan MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum), 1615561a9bbfSSean Callanan FetchRegOp(origin_register), 1616561a9bbfSSean Callanan FetchImmOp(origin_offset)))(*origin_operand)) { 1617b9c1b51eSKate Stone source_path = 1618561a9bbfSSean Callanan DoGuessValueAt(frame, origin_register, origin_offset, disassembler, 1619b9c1b51eSKate Stone variables, instruction_sp->GetAddress()); 1620b9c1b51eSKate Stone if (!source_path) { 1621561a9bbfSSean Callanan continue; 16224740a734SSean Callanan } 1623b9c1b51eSKate Stone source_path = 1624b9c1b51eSKate Stone GetValueForDereferincingOffset(frame, source_path, offset); 16254740a734SSean Callanan } 16264740a734SSean Callanan 1627b9c1b51eSKate Stone if (source_path) { 16284740a734SSean Callanan return source_path; 16294740a734SSean Callanan } 16304740a734SSean Callanan } 16314740a734SSean Callanan 16324740a734SSean Callanan return ValueObjectSP(); 16334740a734SSean Callanan } 16344740a734SSean Callanan } 16354740a734SSean Callanan 1636b9c1b51eSKate Stone lldb::ValueObjectSP StackFrame::GuessValueForRegisterAndOffset(ConstString reg, 1637b9c1b51eSKate Stone int64_t offset) { 16384740a734SSean Callanan TargetSP target_sp = CalculateTarget(); 16394740a734SSean Callanan 16404740a734SSean Callanan const ArchSpec &target_arch = target_sp->GetArchitecture(); 16414740a734SSean Callanan 16424740a734SSean Callanan Block *frame_block = GetFrameBlock(); 16434740a734SSean Callanan 1644b9c1b51eSKate Stone if (!frame_block) { 16454740a734SSean Callanan return ValueObjectSP(); 16464740a734SSean Callanan } 16474740a734SSean Callanan 16484740a734SSean Callanan Function *function = frame_block->CalculateSymbolContextFunction(); 1649b9c1b51eSKate Stone if (!function) { 16504740a734SSean Callanan return ValueObjectSP(); 16514740a734SSean Callanan } 16524740a734SSean Callanan 16534740a734SSean Callanan AddressRange pc_range = function->GetAddressRange(); 16544740a734SSean Callanan 1655b9c1b51eSKate Stone if (GetFrameCodeAddress().GetFileAddress() < 1656b9c1b51eSKate Stone pc_range.GetBaseAddress().GetFileAddress() || 1657b9c1b51eSKate Stone GetFrameCodeAddress().GetFileAddress() - 1658b9c1b51eSKate Stone pc_range.GetBaseAddress().GetFileAddress() >= 1659b9c1b51eSKate Stone pc_range.GetByteSize()) { 16604740a734SSean Callanan return ValueObjectSP(); 16614740a734SSean Callanan } 16624740a734SSean Callanan 16634740a734SSean Callanan ExecutionContext exe_ctx(shared_from_this()); 16644740a734SSean Callanan 16654740a734SSean Callanan const char *plugin_name = nullptr; 16664740a734SSean Callanan const char *flavor = nullptr; 16674740a734SSean Callanan const bool prefer_file_cache = false; 1668b9c1b51eSKate Stone DisassemblerSP disassembler_sp = Disassembler::DisassembleRange( 1669b9c1b51eSKate Stone target_arch, plugin_name, flavor, exe_ctx, pc_range, prefer_file_cache); 16704740a734SSean Callanan 1671b9c1b51eSKate Stone if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) { 16724740a734SSean Callanan return ValueObjectSP(); 16734740a734SSean Callanan } 16744740a734SSean Callanan 16754740a734SSean Callanan const bool get_file_globals = false; 16764740a734SSean Callanan VariableList *variables = GetVariableList(get_file_globals); 16774740a734SSean Callanan 1678b9c1b51eSKate Stone if (!variables) { 16794740a734SSean Callanan return ValueObjectSP(); 16804740a734SSean Callanan } 16814740a734SSean Callanan 1682b9c1b51eSKate Stone return DoGuessValueAt(*this, reg, offset, *disassembler_sp, *variables, 1683b9c1b51eSKate Stone GetFrameCodeAddress()); 16844740a734SSean Callanan } 16854740a734SSean Callanan 1686b9c1b51eSKate Stone TargetSP StackFrame::CalculateTarget() { 1687d9e416c0SGreg Clayton TargetSP target_sp; 1688d9e416c0SGreg Clayton ThreadSP thread_sp(GetThread()); 1689b9c1b51eSKate Stone if (thread_sp) { 1690d9e416c0SGreg Clayton ProcessSP process_sp(thread_sp->CalculateProcess()); 1691d9e416c0SGreg Clayton if (process_sp) 1692d9e416c0SGreg Clayton target_sp = process_sp->CalculateTarget(); 1693d9e416c0SGreg Clayton } 1694d9e416c0SGreg Clayton return target_sp; 169530fdc8d8SChris Lattner } 169630fdc8d8SChris Lattner 1697b9c1b51eSKate Stone ProcessSP StackFrame::CalculateProcess() { 1698d9e416c0SGreg Clayton ProcessSP process_sp; 1699d9e416c0SGreg Clayton ThreadSP thread_sp(GetThread()); 1700d9e416c0SGreg Clayton if (thread_sp) 1701d9e416c0SGreg Clayton process_sp = thread_sp->CalculateProcess(); 1702d9e416c0SGreg Clayton return process_sp; 170330fdc8d8SChris Lattner } 170430fdc8d8SChris Lattner 1705b9c1b51eSKate Stone ThreadSP StackFrame::CalculateThread() { return GetThread(); } 170630fdc8d8SChris Lattner 1707b9c1b51eSKate Stone StackFrameSP StackFrame::CalculateStackFrame() { return shared_from_this(); } 170830fdc8d8SChris Lattner 1709b9c1b51eSKate Stone void StackFrame::CalculateExecutionContext(ExecutionContext &exe_ctx) { 1710d9e416c0SGreg Clayton exe_ctx.SetContext(shared_from_this()); 171130fdc8d8SChris Lattner } 171230fdc8d8SChris Lattner 1713b9c1b51eSKate Stone void StackFrame::DumpUsingSettingsFormat(Stream *strm, 1714b9c1b51eSKate Stone const char *frame_marker) { 1715d70a6e71SEugene Zelenko if (strm == nullptr) 17160603aa9dSGreg Clayton return; 17170603aa9dSGreg Clayton 17180603aa9dSGreg Clayton GetSymbolContext(eSymbolContextEverything); 1719d9e416c0SGreg Clayton ExecutionContext exe_ctx(shared_from_this()); 17200603aa9dSGreg Clayton StreamString s; 17218ec10efcSJim Ingham 17228ec10efcSJim Ingham if (frame_marker) 17238ec10efcSJim Ingham s.PutCString(frame_marker); 17248ec10efcSJim Ingham 1725d70a6e71SEugene Zelenko const FormatEntity::Entry *frame_format = nullptr; 1726d9e416c0SGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 1727d9e416c0SGreg Clayton if (target) 1728d9e416c0SGreg Clayton frame_format = target->GetDebugger().GetFrameFormat(); 1729b9c1b51eSKate Stone if (frame_format && FormatEntity::Format(*frame_format, s, &m_sc, &exe_ctx, 1730b9c1b51eSKate Stone nullptr, nullptr, false, false)) { 1731c156427dSZachary Turner strm->PutCString(s.GetString()); 1732b9c1b51eSKate Stone } else { 17330603aa9dSGreg Clayton Dump(strm, true, false); 17340603aa9dSGreg Clayton strm->EOL(); 17350603aa9dSGreg Clayton } 17360603aa9dSGreg Clayton } 17370603aa9dSGreg Clayton 1738b9c1b51eSKate Stone void StackFrame::Dump(Stream *strm, bool show_frame_index, 1739b9c1b51eSKate Stone bool show_fullpaths) { 1740d70a6e71SEugene Zelenko if (strm == nullptr) 174130fdc8d8SChris Lattner return; 174230fdc8d8SChris Lattner 174330fdc8d8SChris Lattner if (show_frame_index) 17441b72fcb7SGreg Clayton strm->Printf("frame #%u: ", m_frame_index); 1745d9e416c0SGreg Clayton ExecutionContext exe_ctx(shared_from_this()); 1746d9e416c0SGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 1747d01b2953SDaniel Malea strm->Printf("0x%0*" PRIx64 " ", 1748b9c1b51eSKate Stone target ? (target->GetArchitecture().GetAddressByteSize() * 2) 1749b9c1b51eSKate Stone : 16, 1750d9e416c0SGreg Clayton GetFrameCodeAddress().GetLoadAddress(target)); 17519da7bd07SGreg Clayton GetSymbolContext(eSymbolContextEverything); 17521b72fcb7SGreg Clayton const bool show_module = true; 17531b72fcb7SGreg Clayton const bool show_inline = true; 1754aff1b357SJason Molenda const bool show_function_arguments = true; 1755c980fa92SJason Molenda const bool show_function_name = true; 1756b9c1b51eSKate Stone m_sc.DumpStopContext(strm, exe_ctx.GetBestExecutionContextScope(), 1757b9c1b51eSKate Stone GetFrameCodeAddress(), show_fullpaths, show_module, 1758b9c1b51eSKate Stone show_inline, show_function_arguments, 1759c980fa92SJason Molenda show_function_name); 176030fdc8d8SChris Lattner } 176130fdc8d8SChris Lattner 1762b9c1b51eSKate Stone void StackFrame::UpdateCurrentFrameFromPreviousFrame(StackFrame &prev_frame) { 1763bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 1764b9c1b51eSKate Stone assert(GetStackID() == 1765b9c1b51eSKate Stone prev_frame.GetStackID()); // TODO: remove this after some testing 1766b57e4a1bSJason Molenda m_variable_list_sp = prev_frame.m_variable_list_sp; 1767b57e4a1bSJason Molenda m_variable_list_value_objects.Swap(prev_frame.m_variable_list_value_objects); 1768c156427dSZachary Turner if (!m_disassembly.GetString().empty()) { 1769c156427dSZachary Turner m_disassembly.Clear(); 1770c156427dSZachary Turner m_disassembly.PutCString(prev_frame.m_disassembly.GetString()); 1771c156427dSZachary Turner } 17725082c5fdSGreg Clayton } 177368275d5eSGreg Clayton 1774b9c1b51eSKate Stone void StackFrame::UpdatePreviousFrameFromCurrentFrame(StackFrame &curr_frame) { 1775bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 1776b9c1b51eSKate Stone assert(GetStackID() == 1777b9c1b51eSKate Stone curr_frame.GetStackID()); // TODO: remove this after some testing 1778b57e4a1bSJason Molenda m_id.SetPC(curr_frame.m_id.GetPC()); // Update the Stack ID PC value 1779b57e4a1bSJason Molenda assert(GetThread() == curr_frame.GetThread()); 1780b57e4a1bSJason Molenda m_frame_index = curr_frame.m_frame_index; 1781b57e4a1bSJason Molenda m_concrete_frame_index = curr_frame.m_concrete_frame_index; 1782b57e4a1bSJason Molenda m_reg_context_sp = curr_frame.m_reg_context_sp; 1783b57e4a1bSJason Molenda m_frame_code_addr = curr_frame.m_frame_code_addr; 1784b9c1b51eSKate Stone assert(!m_sc.target_sp || !curr_frame.m_sc.target_sp || 1785b9c1b51eSKate Stone m_sc.target_sp.get() == curr_frame.m_sc.target_sp.get()); 1786b9c1b51eSKate Stone assert(!m_sc.module_sp || !curr_frame.m_sc.module_sp || 1787b9c1b51eSKate Stone m_sc.module_sp.get() == curr_frame.m_sc.module_sp.get()); 1788b9c1b51eSKate Stone assert(m_sc.comp_unit == nullptr || curr_frame.m_sc.comp_unit == nullptr || 1789b9c1b51eSKate Stone m_sc.comp_unit == curr_frame.m_sc.comp_unit); 1790b9c1b51eSKate Stone assert(m_sc.function == nullptr || curr_frame.m_sc.function == nullptr || 1791b9c1b51eSKate Stone m_sc.function == curr_frame.m_sc.function); 1792b57e4a1bSJason Molenda m_sc = curr_frame.m_sc; 179359e8fc1cSGreg Clayton m_flags.Clear(GOT_FRAME_BASE | eSymbolContextEverything); 179459e8fc1cSGreg Clayton m_flags.Set(m_sc.GetResolvedMask()); 179559e8fc1cSGreg Clayton m_frame_base.Clear(); 179659e8fc1cSGreg Clayton m_frame_base_error.Clear(); 179759e8fc1cSGreg Clayton } 1798e4284b71SJim Ingham 1799b9c1b51eSKate Stone bool StackFrame::HasCachedData() const { 1800d70a6e71SEugene Zelenko if (m_variable_list_sp) 1801b57e4a1bSJason Molenda return true; 1802b57e4a1bSJason Molenda if (m_variable_list_value_objects.GetSize() > 0) 1803b57e4a1bSJason Molenda return true; 1804b57e4a1bSJason Molenda if (!m_disassembly.GetString().empty()) 1805b57e4a1bSJason Molenda return true; 1806b57e4a1bSJason Molenda return false; 1807b57e4a1bSJason Molenda } 1808b57e4a1bSJason Molenda 1809b9c1b51eSKate Stone bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source, 1810b9c1b51eSKate Stone const char *frame_marker) { 181153eb7ad2SGreg Clayton 1812b9c1b51eSKate Stone if (show_frame_info) { 18137260f620SGreg Clayton strm.Indent(); 18148ec10efcSJim Ingham DumpUsingSettingsFormat(&strm, frame_marker); 18157260f620SGreg Clayton } 18167260f620SGreg Clayton 1817b9c1b51eSKate Stone if (show_source) { 1818d9e416c0SGreg Clayton ExecutionContext exe_ctx(shared_from_this()); 18198be74995SMohit K. Bhakkad bool have_source = false, have_debuginfo = false; 1820b9c1b51eSKate Stone Debugger::StopDisassemblyType disasm_display = 1821b9c1b51eSKate Stone Debugger::eStopDisassemblyTypeNever; 1822d9e416c0SGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 1823b9c1b51eSKate Stone if (target) { 182453eb7ad2SGreg Clayton Debugger &debugger = target->GetDebugger(); 1825b9c1b51eSKate Stone const uint32_t source_lines_before = 1826b9c1b51eSKate Stone debugger.GetStopSourceLineCount(true); 1827b9c1b51eSKate Stone const uint32_t source_lines_after = 1828b9c1b51eSKate Stone debugger.GetStopSourceLineCount(false); 182953eb7ad2SGreg Clayton disasm_display = debugger.GetStopDisassemblyDisplay(); 183053eb7ad2SGreg Clayton 18317260f620SGreg Clayton GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry); 1832b9c1b51eSKate Stone if (m_sc.comp_unit && m_sc.line_entry.IsValid()) { 18338be74995SMohit K. Bhakkad have_debuginfo = true; 1834b9c1b51eSKate Stone if (source_lines_before > 0 || source_lines_after > 0) { 1835b9c1b51eSKate Stone size_t num_lines = 1836b9c1b51eSKate Stone target->GetSourceManager().DisplaySourceLinesWithLineNumbers( 1837b9c1b51eSKate Stone m_sc.line_entry.file, m_sc.line_entry.line, 18389666ba75STodd Fiala m_sc.line_entry.column, source_lines_before, 18399666ba75STodd Fiala source_lines_after, "->", &strm); 18408be74995SMohit K. Bhakkad if (num_lines != 0) 18418be74995SMohit K. Bhakkad have_source = true; 18428be74995SMohit K. Bhakkad // TODO: Give here a one time warning if source file is missing. 1843e372b98dSGreg Clayton } 1844e372b98dSGreg Clayton } 1845b9c1b51eSKate Stone switch (disasm_display) { 184667cc0636SGreg Clayton case Debugger::eStopDisassemblyTypeNever: 1847e372b98dSGreg Clayton break; 1848e372b98dSGreg Clayton 18498be74995SMohit K. Bhakkad case Debugger::eStopDisassemblyTypeNoDebugInfo: 18508be74995SMohit K. Bhakkad if (have_debuginfo) 18518be74995SMohit K. Bhakkad break; 185262e0681aSJason Molenda LLVM_FALLTHROUGH; 18538be74995SMohit K. Bhakkad 185467cc0636SGreg Clayton case Debugger::eStopDisassemblyTypeNoSource: 1855e372b98dSGreg Clayton if (have_source) 1856e372b98dSGreg Clayton break; 185762e0681aSJason Molenda LLVM_FALLTHROUGH; 18588be74995SMohit K. Bhakkad 185967cc0636SGreg Clayton case Debugger::eStopDisassemblyTypeAlways: 1860b9c1b51eSKate Stone if (target) { 186153eb7ad2SGreg Clayton const uint32_t disasm_lines = debugger.GetDisassemblyLineCount(); 1862b9c1b51eSKate Stone if (disasm_lines > 0) { 1863d9e416c0SGreg Clayton const ArchSpec &target_arch = target->GetArchitecture(); 1864e372b98dSGreg Clayton AddressRange pc_range; 1865e372b98dSGreg Clayton pc_range.GetBaseAddress() = GetFrameCodeAddress(); 1866b9c1b51eSKate Stone pc_range.SetByteSize(disasm_lines * 1867b9c1b51eSKate Stone target_arch.GetMaximumOpcodeByteSize()); 1868d70a6e71SEugene Zelenko const char *plugin_name = nullptr; 1869d70a6e71SEugene Zelenko const char *flavor = nullptr; 18700b4c26b2SJason Molenda const bool mixed_source_and_assembly = false; 18710b4c26b2SJason Molenda Disassembler::Disassemble( 18720b4c26b2SJason Molenda target->GetDebugger(), target_arch, plugin_name, flavor, 18730b4c26b2SJason Molenda exe_ctx, pc_range, disasm_lines, mixed_source_and_assembly, 0, 1874b9c1b51eSKate Stone Disassembler::eOptionMarkPCAddress, strm); 1875e372b98dSGreg Clayton } 1876e372b98dSGreg Clayton } 1877e372b98dSGreg Clayton break; 18787260f620SGreg Clayton } 18797260f620SGreg Clayton } 188053eb7ad2SGreg Clayton } 18817260f620SGreg Clayton return true; 18827260f620SGreg Clayton } 1883