1ac7ddfbfSEd Maste //===-- StackFrame.cpp ------------------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
104bb0738eSEd Maste #include "lldb/Target/StackFrame.h"
11ac7ddfbfSEd Maste #include "lldb/Core/Debugger.h"
12ac7ddfbfSEd Maste #include "lldb/Core/Disassembler.h"
131c3bbb01SEd Maste #include "lldb/Core/FormatEntity.h"
144bb0738eSEd Maste #include "lldb/Core/Mangled.h"
154bb0738eSEd Maste #include "lldb/Core/Module.h"
16ac7ddfbfSEd Maste #include "lldb/Core/Value.h"
17ac7ddfbfSEd Maste #include "lldb/Core/ValueObjectConstResult.h"
18435933ddSDimitry Andric #include "lldb/Core/ValueObjectMemory.h"
19435933ddSDimitry Andric #include "lldb/Core/ValueObjectVariable.h"
20ac7ddfbfSEd Maste #include "lldb/Symbol/CompileUnit.h"
21ac7ddfbfSEd Maste #include "lldb/Symbol/Function.h"
22ac7ddfbfSEd Maste #include "lldb/Symbol/Symbol.h"
23ac7ddfbfSEd Maste #include "lldb/Symbol/SymbolContextScope.h"
249f2f44ceSEd Maste #include "lldb/Symbol/Type.h"
25ac7ddfbfSEd Maste #include "lldb/Symbol/VariableList.h"
26435933ddSDimitry Andric #include "lldb/Target/ABI.h"
27ac7ddfbfSEd Maste #include "lldb/Target/ExecutionContext.h"
28ac7ddfbfSEd Maste #include "lldb/Target/Process.h"
29ac7ddfbfSEd Maste #include "lldb/Target/RegisterContext.h"
30*b5893f02SDimitry Andric #include "lldb/Target/StackFrameRecognizer.h"
31ac7ddfbfSEd Maste #include "lldb/Target/Target.h"
32ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
33*b5893f02SDimitry Andric #include "lldb/Utility/RegisterValue.h"
34*b5893f02SDimitry Andric 
35*b5893f02SDimitry Andric #include "lldb/lldb-enumerations.h"
36ac7ddfbfSEd Maste 
37ac7ddfbfSEd Maste using namespace lldb;
38ac7ddfbfSEd Maste using namespace lldb_private;
39ac7ddfbfSEd Maste 
40ac7ddfbfSEd Maste // The first bits in the flags are reserved for the SymbolContext::Scope bits
41ac7ddfbfSEd Maste // so we know if we have tried to look up information in our internal symbol
42ac7ddfbfSEd Maste // context (m_sc) already.
43ac7ddfbfSEd Maste #define RESOLVED_FRAME_CODE_ADDR (uint32_t(eSymbolContextEverything + 1))
44ac7ddfbfSEd Maste #define RESOLVED_FRAME_ID_SYMBOL_SCOPE (RESOLVED_FRAME_CODE_ADDR << 1)
45ac7ddfbfSEd Maste #define GOT_FRAME_BASE (RESOLVED_FRAME_ID_SYMBOL_SCOPE << 1)
46ac7ddfbfSEd Maste #define RESOLVED_VARIABLES (GOT_FRAME_BASE << 1)
47ac7ddfbfSEd Maste #define RESOLVED_GLOBAL_VARIABLES (RESOLVED_VARIABLES << 1)
48ac7ddfbfSEd Maste 
StackFrame(const ThreadSP & thread_sp,user_id_t frame_idx,user_id_t unwind_frame_index,addr_t cfa,bool cfa_is_valid,addr_t pc,StackFrame::Kind kind,const SymbolContext * sc_ptr)49435933ddSDimitry Andric StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,
50435933ddSDimitry Andric                        user_id_t unwind_frame_index, addr_t cfa,
51*b5893f02SDimitry Andric                        bool cfa_is_valid, addr_t pc, StackFrame::Kind kind,
524bb0738eSEd Maste                        const SymbolContext *sc_ptr)
53435933ddSDimitry Andric     : m_thread_wp(thread_sp), m_frame_index(frame_idx),
54435933ddSDimitry Andric       m_concrete_frame_index(unwind_frame_index), m_reg_context_sp(),
55435933ddSDimitry Andric       m_id(pc, cfa, nullptr), m_frame_code_addr(pc), m_sc(), m_flags(),
56435933ddSDimitry Andric       m_frame_base(), m_frame_base_error(), m_cfa_is_valid(cfa_is_valid),
57*b5893f02SDimitry Andric       m_stack_frame_kind(kind), m_variable_list_sp(),
58*b5893f02SDimitry Andric       m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(),
59*b5893f02SDimitry Andric       m_mutex() {
60435933ddSDimitry Andric   // If we don't have a CFA value, use the frame index for our StackID so that
614ba319b5SDimitry Andric   // recursive functions properly aren't confused with one another on a history
624ba319b5SDimitry Andric   // stack.
63*b5893f02SDimitry Andric   if (IsHistorical() && !m_cfa_is_valid) {
6435617911SEd Maste     m_id.SetCFA(m_frame_index);
6535617911SEd Maste   }
6635617911SEd Maste 
67435933ddSDimitry Andric   if (sc_ptr != nullptr) {
68ac7ddfbfSEd Maste     m_sc = *sc_ptr;
69ac7ddfbfSEd Maste     m_flags.Set(m_sc.GetResolvedMask());
70ac7ddfbfSEd Maste   }
71ac7ddfbfSEd Maste }
72ac7ddfbfSEd Maste 
StackFrame(const ThreadSP & thread_sp,user_id_t frame_idx,user_id_t unwind_frame_index,const RegisterContextSP & reg_context_sp,addr_t cfa,addr_t pc,const SymbolContext * sc_ptr)73435933ddSDimitry Andric StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,
74435933ddSDimitry Andric                        user_id_t unwind_frame_index,
75435933ddSDimitry Andric                        const RegisterContextSP &reg_context_sp, addr_t cfa,
76435933ddSDimitry Andric                        addr_t pc, const SymbolContext *sc_ptr)
77435933ddSDimitry Andric     : m_thread_wp(thread_sp), m_frame_index(frame_idx),
78ac7ddfbfSEd Maste       m_concrete_frame_index(unwind_frame_index),
79435933ddSDimitry Andric       m_reg_context_sp(reg_context_sp), m_id(pc, cfa, nullptr),
80435933ddSDimitry Andric       m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(),
81*b5893f02SDimitry Andric       m_frame_base_error(), m_cfa_is_valid(true),
82*b5893f02SDimitry Andric       m_stack_frame_kind(StackFrame::Kind::Regular), m_variable_list_sp(),
83*b5893f02SDimitry Andric       m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(),
84435933ddSDimitry Andric       m_mutex() {
85435933ddSDimitry Andric   if (sc_ptr != nullptr) {
86ac7ddfbfSEd Maste     m_sc = *sc_ptr;
87ac7ddfbfSEd Maste     m_flags.Set(m_sc.GetResolvedMask());
88ac7ddfbfSEd Maste   }
89ac7ddfbfSEd Maste 
90435933ddSDimitry Andric   if (reg_context_sp && !m_sc.target_sp) {
91ac7ddfbfSEd Maste     m_sc.target_sp = reg_context_sp->CalculateTarget();
92ac7ddfbfSEd Maste     if (m_sc.target_sp)
93ac7ddfbfSEd Maste       m_flags.Set(eSymbolContextTarget);
94ac7ddfbfSEd Maste   }
95ac7ddfbfSEd Maste }
96ac7ddfbfSEd Maste 
StackFrame(const ThreadSP & thread_sp,user_id_t frame_idx,user_id_t unwind_frame_index,const RegisterContextSP & reg_context_sp,addr_t cfa,const Address & pc_addr,const SymbolContext * sc_ptr)97435933ddSDimitry Andric StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,
98435933ddSDimitry Andric                        user_id_t unwind_frame_index,
99435933ddSDimitry Andric                        const RegisterContextSP &reg_context_sp, addr_t cfa,
100435933ddSDimitry Andric                        const Address &pc_addr, const SymbolContext *sc_ptr)
101435933ddSDimitry Andric     : m_thread_wp(thread_sp), m_frame_index(frame_idx),
102ac7ddfbfSEd Maste       m_concrete_frame_index(unwind_frame_index),
103ac7ddfbfSEd Maste       m_reg_context_sp(reg_context_sp),
104435933ddSDimitry Andric       m_id(pc_addr.GetLoadAddress(thread_sp->CalculateTarget().get()), cfa,
105435933ddSDimitry Andric            nullptr),
106435933ddSDimitry Andric       m_frame_code_addr(pc_addr), m_sc(), m_flags(), m_frame_base(),
107*b5893f02SDimitry Andric       m_frame_base_error(), m_cfa_is_valid(true),
108*b5893f02SDimitry Andric       m_stack_frame_kind(StackFrame::Kind::Regular), m_variable_list_sp(),
109*b5893f02SDimitry Andric       m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(),
110435933ddSDimitry Andric       m_mutex() {
111435933ddSDimitry Andric   if (sc_ptr != nullptr) {
112ac7ddfbfSEd Maste     m_sc = *sc_ptr;
113ac7ddfbfSEd Maste     m_flags.Set(m_sc.GetResolvedMask());
114ac7ddfbfSEd Maste   }
115ac7ddfbfSEd Maste 
116435933ddSDimitry Andric   if (!m_sc.target_sp && reg_context_sp) {
117ac7ddfbfSEd Maste     m_sc.target_sp = reg_context_sp->CalculateTarget();
118ac7ddfbfSEd Maste     if (m_sc.target_sp)
119ac7ddfbfSEd Maste       m_flags.Set(eSymbolContextTarget);
120ac7ddfbfSEd Maste   }
121ac7ddfbfSEd Maste 
122ac7ddfbfSEd Maste   ModuleSP pc_module_sp(pc_addr.GetModule());
123435933ddSDimitry Andric   if (!m_sc.module_sp || m_sc.module_sp != pc_module_sp) {
124435933ddSDimitry Andric     if (pc_module_sp) {
125ac7ddfbfSEd Maste       m_sc.module_sp = pc_module_sp;
126ac7ddfbfSEd Maste       m_flags.Set(eSymbolContextModule);
127435933ddSDimitry Andric     } else {
128ac7ddfbfSEd Maste       m_sc.module_sp.reset();
129ac7ddfbfSEd Maste     }
130ac7ddfbfSEd Maste   }
131ac7ddfbfSEd Maste }
132ac7ddfbfSEd Maste 
1334bb0738eSEd Maste StackFrame::~StackFrame() = default;
134ac7ddfbfSEd Maste 
GetStackID()135435933ddSDimitry Andric StackID &StackFrame::GetStackID() {
1364bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
1374ba319b5SDimitry Andric   // Make sure we have resolved the StackID object's symbol context scope if we
1384ba319b5SDimitry Andric   // already haven't looked it up.
139ac7ddfbfSEd Maste 
140435933ddSDimitry Andric   if (m_flags.IsClear(RESOLVED_FRAME_ID_SYMBOL_SCOPE)) {
141435933ddSDimitry Andric     if (m_id.GetSymbolContextScope()) {
1424ba319b5SDimitry Andric       // We already have a symbol context scope, we just don't have our flag
1434ba319b5SDimitry Andric       // bit set.
144ac7ddfbfSEd Maste       m_flags.Set(RESOLVED_FRAME_ID_SYMBOL_SCOPE);
145435933ddSDimitry Andric     } else {
1464ba319b5SDimitry Andric       // Calculate the frame block and use this for the stack ID symbol context
1474ba319b5SDimitry Andric       // scope if we have one.
148ac7ddfbfSEd Maste       SymbolContextScope *scope = GetFrameBlock();
149435933ddSDimitry Andric       if (scope == nullptr) {
150ac7ddfbfSEd Maste         // We don't have a block, so use the symbol
151ac7ddfbfSEd Maste         if (m_flags.IsClear(eSymbolContextSymbol))
152ac7ddfbfSEd Maste           GetSymbolContext(eSymbolContextSymbol);
153ac7ddfbfSEd Maste 
1544bb0738eSEd Maste         // It is ok if m_sc.symbol is nullptr here
155ac7ddfbfSEd Maste         scope = m_sc.symbol;
156ac7ddfbfSEd Maste       }
157ac7ddfbfSEd Maste       // Set the symbol context scope (the accessor will set the
158ac7ddfbfSEd Maste       // RESOLVED_FRAME_ID_SYMBOL_SCOPE bit in m_flags).
159ac7ddfbfSEd Maste       SetSymbolContextScope(scope);
160ac7ddfbfSEd Maste     }
161ac7ddfbfSEd Maste   }
162ac7ddfbfSEd Maste   return m_id;
163ac7ddfbfSEd Maste }
164ac7ddfbfSEd Maste 
GetFrameIndex() const165435933ddSDimitry Andric uint32_t StackFrame::GetFrameIndex() const {
166ac7ddfbfSEd Maste   ThreadSP thread_sp = GetThread();
167ac7ddfbfSEd Maste   if (thread_sp)
168435933ddSDimitry Andric     return thread_sp->GetStackFrameList()->GetVisibleStackFrameIndex(
169435933ddSDimitry Andric         m_frame_index);
170ac7ddfbfSEd Maste   else
171ac7ddfbfSEd Maste     return m_frame_index;
172ac7ddfbfSEd Maste }
173ac7ddfbfSEd Maste 
SetSymbolContextScope(SymbolContextScope * symbol_scope)174435933ddSDimitry Andric void StackFrame::SetSymbolContextScope(SymbolContextScope *symbol_scope) {
1754bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
176ac7ddfbfSEd Maste   m_flags.Set(RESOLVED_FRAME_ID_SYMBOL_SCOPE);
177ac7ddfbfSEd Maste   m_id.SetSymbolContextScope(symbol_scope);
178ac7ddfbfSEd Maste }
179ac7ddfbfSEd Maste 
GetFrameCodeAddress()180435933ddSDimitry Andric const Address &StackFrame::GetFrameCodeAddress() {
1814bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
182435933ddSDimitry Andric   if (m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR) &&
183435933ddSDimitry Andric       !m_frame_code_addr.IsSectionOffset()) {
184ac7ddfbfSEd Maste     m_flags.Set(RESOLVED_FRAME_CODE_ADDR);
185ac7ddfbfSEd Maste 
186ac7ddfbfSEd Maste     // Resolve the PC into a temporary address because if ResolveLoadAddress
187ac7ddfbfSEd Maste     // fails to resolve the address, it will clear the address object...
188ac7ddfbfSEd Maste     ThreadSP thread_sp(GetThread());
189435933ddSDimitry Andric     if (thread_sp) {
190ac7ddfbfSEd Maste       TargetSP target_sp(thread_sp->CalculateTarget());
191435933ddSDimitry Andric       if (target_sp) {
192db17bf38SDimitry Andric         const bool allow_section_end = true;
193435933ddSDimitry Andric         if (m_frame_code_addr.SetOpcodeLoadAddress(
194435933ddSDimitry Andric                 m_frame_code_addr.GetOffset(), target_sp.get(),
1954ba319b5SDimitry Andric                 AddressClass::eCode, allow_section_end)) {
196ac7ddfbfSEd Maste           ModuleSP module_sp(m_frame_code_addr.GetModule());
197435933ddSDimitry Andric           if (module_sp) {
198ac7ddfbfSEd Maste             m_sc.module_sp = module_sp;
199ac7ddfbfSEd Maste             m_flags.Set(eSymbolContextModule);
200ac7ddfbfSEd Maste           }
201ac7ddfbfSEd Maste         }
202ac7ddfbfSEd Maste       }
203ac7ddfbfSEd Maste     }
204ac7ddfbfSEd Maste   }
205ac7ddfbfSEd Maste   return m_frame_code_addr;
206ac7ddfbfSEd Maste }
207ac7ddfbfSEd Maste 
ChangePC(addr_t pc)208435933ddSDimitry Andric bool StackFrame::ChangePC(addr_t pc) {
2094bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
21035617911SEd Maste   // We can't change the pc value of a history stack frame - it is immutable.
211*b5893f02SDimitry Andric   if (IsHistorical())
21235617911SEd Maste     return false;
213ac7ddfbfSEd Maste   m_frame_code_addr.SetRawAddress(pc);
214ac7ddfbfSEd Maste   m_sc.Clear(false);
215ac7ddfbfSEd Maste   m_flags.Reset(0);
216ac7ddfbfSEd Maste   ThreadSP thread_sp(GetThread());
217ac7ddfbfSEd Maste   if (thread_sp)
218ac7ddfbfSEd Maste     thread_sp->ClearStackFrames();
21935617911SEd Maste   return true;
220ac7ddfbfSEd Maste }
221ac7ddfbfSEd Maste 
Disassemble()222435933ddSDimitry Andric const char *StackFrame::Disassemble() {
2234bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
224f678e45dSDimitry Andric   if (m_disassembly.Empty()) {
225ac7ddfbfSEd Maste     ExecutionContext exe_ctx(shared_from_this());
226ac7ddfbfSEd Maste     Target *target = exe_ctx.GetTargetPtr();
227435933ddSDimitry Andric     if (target) {
2284bb0738eSEd Maste       const char *plugin_name = nullptr;
2294bb0738eSEd Maste       const char *flavor = nullptr;
230f678e45dSDimitry Andric       Disassembler::Disassemble(target->GetDebugger(),
231f678e45dSDimitry Andric                                 target->GetArchitecture(), plugin_name, flavor,
232f678e45dSDimitry Andric                                 exe_ctx, 0, false, 0, 0, m_disassembly);
233ac7ddfbfSEd Maste     }
234f678e45dSDimitry Andric     if (m_disassembly.Empty())
235f678e45dSDimitry Andric       return nullptr;
236f678e45dSDimitry Andric   }
237f678e45dSDimitry Andric 
238ac7ddfbfSEd Maste   return m_disassembly.GetData();
239ac7ddfbfSEd Maste }
240ac7ddfbfSEd Maste 
GetFrameBlock()241435933ddSDimitry Andric Block *StackFrame::GetFrameBlock() {
2424bb0738eSEd Maste   if (m_sc.block == nullptr && m_flags.IsClear(eSymbolContextBlock))
243ac7ddfbfSEd Maste     GetSymbolContext(eSymbolContextBlock);
244ac7ddfbfSEd Maste 
245435933ddSDimitry Andric   if (m_sc.block) {
246ac7ddfbfSEd Maste     Block *inline_block = m_sc.block->GetContainingInlinedBlock();
247435933ddSDimitry Andric     if (inline_block) {
2484ba319b5SDimitry Andric       // Use the block with the inlined function info as the frame block we
2494ba319b5SDimitry Andric       // want this frame to have only the variables for the inlined function
2504ba319b5SDimitry Andric       // and its non-inlined block child blocks.
251ac7ddfbfSEd Maste       return inline_block;
252435933ddSDimitry Andric     } else {
2534ba319b5SDimitry Andric       // This block is not contained within any inlined function blocks with so
2544ba319b5SDimitry Andric       // we want to use the top most function block.
255ac7ddfbfSEd Maste       return &m_sc.function->GetBlock(false);
256ac7ddfbfSEd Maste     }
257ac7ddfbfSEd Maste   }
2584bb0738eSEd Maste   return nullptr;
259ac7ddfbfSEd Maste }
260ac7ddfbfSEd Maste 
261ac7ddfbfSEd Maste //----------------------------------------------------------------------
262ac7ddfbfSEd Maste // Get the symbol context if we already haven't done so by resolving the
263ac7ddfbfSEd Maste // PC address as much as possible. This way when we pass around a
2644ba319b5SDimitry Andric // StackFrame object, everyone will have as much information as possible and no
2654ba319b5SDimitry Andric // one will ever have to look things up manually.
266ac7ddfbfSEd Maste //----------------------------------------------------------------------
267*b5893f02SDimitry Andric const SymbolContext &
GetSymbolContext(SymbolContextItem resolve_scope)268*b5893f02SDimitry Andric StackFrame::GetSymbolContext(SymbolContextItem resolve_scope) {
2694bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
270ac7ddfbfSEd Maste   // Copy our internal symbol context into "sc".
271435933ddSDimitry Andric   if ((m_flags.Get() & resolve_scope) != resolve_scope) {
272ac7ddfbfSEd Maste     uint32_t resolved = 0;
273ac7ddfbfSEd Maste 
274ac7ddfbfSEd Maste     // If the target was requested add that:
275435933ddSDimitry Andric     if (!m_sc.target_sp) {
276ac7ddfbfSEd Maste       m_sc.target_sp = CalculateTarget();
277ac7ddfbfSEd Maste       if (m_sc.target_sp)
278ac7ddfbfSEd Maste         resolved |= eSymbolContextTarget;
279ac7ddfbfSEd Maste     }
280ac7ddfbfSEd Maste 
2814ba319b5SDimitry Andric     // Resolve our PC to section offset if we haven't already done so and if we
2824ba319b5SDimitry Andric     // don't have a module. The resolved address section will contain the
2834ba319b5SDimitry Andric     // module to which it belongs
284ac7ddfbfSEd Maste     if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR))
285ac7ddfbfSEd Maste       GetFrameCodeAddress();
286ac7ddfbfSEd Maste 
2874ba319b5SDimitry Andric     // If this is not frame zero, then we need to subtract 1 from the PC value
2884ba319b5SDimitry Andric     // when doing address lookups since the PC will be on the instruction
2894ba319b5SDimitry Andric     // following the function call instruction...
290ac7ddfbfSEd Maste 
291ac7ddfbfSEd Maste     Address lookup_addr(GetFrameCodeAddress());
292435933ddSDimitry Andric     if (m_frame_index > 0 && lookup_addr.IsValid()) {
293ac7ddfbfSEd Maste       addr_t offset = lookup_addr.GetOffset();
294435933ddSDimitry Andric       if (offset > 0) {
295ac7ddfbfSEd Maste         lookup_addr.SetOffset(offset - 1);
2967aa51b79SEd Maste 
297435933ddSDimitry Andric       } else {
2984ba319b5SDimitry Andric         // lookup_addr is the start of a section.  We need do the math on the
2994ba319b5SDimitry Andric         // actual load address and re-compute the section.  We're working with
3004ba319b5SDimitry Andric         // a 'noreturn' function at the end of a section.
3017aa51b79SEd Maste         ThreadSP thread_sp(GetThread());
302435933ddSDimitry Andric         if (thread_sp) {
3037aa51b79SEd Maste           TargetSP target_sp(thread_sp->CalculateTarget());
304435933ddSDimitry Andric           if (target_sp) {
305435933ddSDimitry Andric             addr_t addr_minus_one =
306435933ddSDimitry Andric                 lookup_addr.GetLoadAddress(target_sp.get()) - 1;
3077aa51b79SEd Maste             lookup_addr.SetLoadAddress(addr_minus_one, target_sp.get());
308435933ddSDimitry Andric           } else {
3097aa51b79SEd Maste             lookup_addr.SetOffset(offset - 1);
3107aa51b79SEd Maste           }
3117aa51b79SEd Maste         }
3127aa51b79SEd Maste       }
313ac7ddfbfSEd Maste     }
314ac7ddfbfSEd Maste 
315435933ddSDimitry Andric     if (m_sc.module_sp) {
3164ba319b5SDimitry Andric       // We have something in our stack frame symbol context, lets check if we
3174ba319b5SDimitry Andric       // haven't already tried to lookup one of those things. If we haven't
3184ba319b5SDimitry Andric       // then we will do the query.
319ac7ddfbfSEd Maste 
320*b5893f02SDimitry Andric       SymbolContextItem actual_resolve_scope = SymbolContextItem(0);
321ac7ddfbfSEd Maste 
322435933ddSDimitry Andric       if (resolve_scope & eSymbolContextCompUnit) {
323435933ddSDimitry Andric         if (m_flags.IsClear(eSymbolContextCompUnit)) {
324ac7ddfbfSEd Maste           if (m_sc.comp_unit)
325ac7ddfbfSEd Maste             resolved |= eSymbolContextCompUnit;
326ac7ddfbfSEd Maste           else
327ac7ddfbfSEd Maste             actual_resolve_scope |= eSymbolContextCompUnit;
328ac7ddfbfSEd Maste         }
329ac7ddfbfSEd Maste       }
330ac7ddfbfSEd Maste 
331435933ddSDimitry Andric       if (resolve_scope & eSymbolContextFunction) {
332435933ddSDimitry Andric         if (m_flags.IsClear(eSymbolContextFunction)) {
333ac7ddfbfSEd Maste           if (m_sc.function)
334ac7ddfbfSEd Maste             resolved |= eSymbolContextFunction;
335ac7ddfbfSEd Maste           else
336ac7ddfbfSEd Maste             actual_resolve_scope |= eSymbolContextFunction;
337ac7ddfbfSEd Maste         }
338ac7ddfbfSEd Maste       }
339ac7ddfbfSEd Maste 
340435933ddSDimitry Andric       if (resolve_scope & eSymbolContextBlock) {
341435933ddSDimitry Andric         if (m_flags.IsClear(eSymbolContextBlock)) {
342ac7ddfbfSEd Maste           if (m_sc.block)
343ac7ddfbfSEd Maste             resolved |= eSymbolContextBlock;
344ac7ddfbfSEd Maste           else
345ac7ddfbfSEd Maste             actual_resolve_scope |= eSymbolContextBlock;
346ac7ddfbfSEd Maste         }
347ac7ddfbfSEd Maste       }
348ac7ddfbfSEd Maste 
349435933ddSDimitry Andric       if (resolve_scope & eSymbolContextSymbol) {
350435933ddSDimitry Andric         if (m_flags.IsClear(eSymbolContextSymbol)) {
351ac7ddfbfSEd Maste           if (m_sc.symbol)
352ac7ddfbfSEd Maste             resolved |= eSymbolContextSymbol;
353ac7ddfbfSEd Maste           else
354ac7ddfbfSEd Maste             actual_resolve_scope |= eSymbolContextSymbol;
355ac7ddfbfSEd Maste         }
356ac7ddfbfSEd Maste       }
357ac7ddfbfSEd Maste 
358435933ddSDimitry Andric       if (resolve_scope & eSymbolContextLineEntry) {
359435933ddSDimitry Andric         if (m_flags.IsClear(eSymbolContextLineEntry)) {
360ac7ddfbfSEd Maste           if (m_sc.line_entry.IsValid())
361ac7ddfbfSEd Maste             resolved |= eSymbolContextLineEntry;
362ac7ddfbfSEd Maste           else
363ac7ddfbfSEd Maste             actual_resolve_scope |= eSymbolContextLineEntry;
364ac7ddfbfSEd Maste         }
365ac7ddfbfSEd Maste       }
366ac7ddfbfSEd Maste 
367435933ddSDimitry Andric       if (actual_resolve_scope) {
3684ba319b5SDimitry Andric         // We might be resolving less information than what is already in our
3694ba319b5SDimitry Andric         // current symbol context so resolve into a temporary symbol context
3704ba319b5SDimitry Andric         // "sc" so we don't clear out data we have already found in "m_sc"
371ac7ddfbfSEd Maste         SymbolContext sc;
372ac7ddfbfSEd Maste         // Set flags that indicate what we have tried to resolve
373435933ddSDimitry Andric         resolved |= m_sc.module_sp->ResolveSymbolContextForAddress(
374435933ddSDimitry Andric             lookup_addr, actual_resolve_scope, sc);
3754ba319b5SDimitry Andric         // Only replace what we didn't already have as we may have information
3764ba319b5SDimitry Andric         // for an inlined function scope that won't match what a standard
3774ba319b5SDimitry Andric         // lookup by address would match
3784bb0738eSEd Maste         if ((resolved & eSymbolContextCompUnit) && m_sc.comp_unit == nullptr)
379ac7ddfbfSEd Maste           m_sc.comp_unit = sc.comp_unit;
3804bb0738eSEd Maste         if ((resolved & eSymbolContextFunction) && m_sc.function == nullptr)
381ac7ddfbfSEd Maste           m_sc.function = sc.function;
3824bb0738eSEd Maste         if ((resolved & eSymbolContextBlock) && m_sc.block == nullptr)
383ac7ddfbfSEd Maste           m_sc.block = sc.block;
3844bb0738eSEd Maste         if ((resolved & eSymbolContextSymbol) && m_sc.symbol == nullptr)
385ac7ddfbfSEd Maste           m_sc.symbol = sc.symbol;
386435933ddSDimitry Andric         if ((resolved & eSymbolContextLineEntry) &&
387435933ddSDimitry Andric             !m_sc.line_entry.IsValid()) {
388ac7ddfbfSEd Maste           m_sc.line_entry = sc.line_entry;
3894bb0738eSEd Maste           m_sc.line_entry.ApplyFileMappings(m_sc.target_sp);
390ac7ddfbfSEd Maste         }
391ac7ddfbfSEd Maste       }
392435933ddSDimitry Andric     } else {
393ac7ddfbfSEd Maste       // If we don't have a module, then we can't have the compile unit,
394ac7ddfbfSEd Maste       // function, block, line entry or symbol, so we can safely call
395ac7ddfbfSEd Maste       // ResolveSymbolContextForAddress with our symbol context member m_sc.
396435933ddSDimitry Andric       if (m_sc.target_sp) {
397435933ddSDimitry Andric         resolved |= m_sc.target_sp->GetImages().ResolveSymbolContextForAddress(
398435933ddSDimitry Andric             lookup_addr, resolve_scope, m_sc);
399ac7ddfbfSEd Maste       }
400ac7ddfbfSEd Maste     }
401ac7ddfbfSEd Maste 
402ac7ddfbfSEd Maste     // Update our internal flags so we remember what we have tried to locate so
403ac7ddfbfSEd Maste     // we don't have to keep trying when more calls to this function are made.
4044ba319b5SDimitry Andric     // We might have dug up more information that was requested (for example if
4054ba319b5SDimitry Andric     // we were asked to only get the block, we will have gotten the compile
4064ba319b5SDimitry Andric     // unit, and function) so set any additional bits that we resolved
407ac7ddfbfSEd Maste     m_flags.Set(resolve_scope | resolved);
408ac7ddfbfSEd Maste   }
409ac7ddfbfSEd Maste 
410ac7ddfbfSEd Maste   // Return the symbol context with everything that was possible to resolve
411ac7ddfbfSEd Maste   // resolved.
412ac7ddfbfSEd Maste   return m_sc;
413ac7ddfbfSEd Maste }
414ac7ddfbfSEd Maste 
GetVariableList(bool get_file_globals)415435933ddSDimitry Andric VariableList *StackFrame::GetVariableList(bool get_file_globals) {
4164bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
417435933ddSDimitry Andric   if (m_flags.IsClear(RESOLVED_VARIABLES)) {
418ac7ddfbfSEd Maste     m_flags.Set(RESOLVED_VARIABLES);
419ac7ddfbfSEd Maste 
420ac7ddfbfSEd Maste     Block *frame_block = GetFrameBlock();
421ac7ddfbfSEd Maste 
422435933ddSDimitry Andric     if (frame_block) {
423ac7ddfbfSEd Maste       const bool get_child_variables = true;
424ac7ddfbfSEd Maste       const bool can_create = true;
425ac7ddfbfSEd Maste       const bool stop_if_child_block_is_inlined_function = true;
426ac7ddfbfSEd Maste       m_variable_list_sp.reset(new VariableList());
427435933ddSDimitry Andric       frame_block->AppendBlockVariables(can_create, get_child_variables,
4284bb0738eSEd Maste                                         stop_if_child_block_is_inlined_function,
429f678e45dSDimitry Andric                                         [](Variable *v) { return true; },
4304bb0738eSEd Maste                                         m_variable_list_sp.get());
431ac7ddfbfSEd Maste     }
432ac7ddfbfSEd Maste   }
433ac7ddfbfSEd Maste 
434435933ddSDimitry Andric   if (m_flags.IsClear(RESOLVED_GLOBAL_VARIABLES) && get_file_globals) {
435ac7ddfbfSEd Maste     m_flags.Set(RESOLVED_GLOBAL_VARIABLES);
436ac7ddfbfSEd Maste 
437ac7ddfbfSEd Maste     if (m_flags.IsClear(eSymbolContextCompUnit))
438ac7ddfbfSEd Maste       GetSymbolContext(eSymbolContextCompUnit);
439ac7ddfbfSEd Maste 
440435933ddSDimitry Andric     if (m_sc.comp_unit) {
441435933ddSDimitry Andric       VariableListSP global_variable_list_sp(
442435933ddSDimitry Andric           m_sc.comp_unit->GetVariableList(true));
443ac7ddfbfSEd Maste       if (m_variable_list_sp)
444ac7ddfbfSEd Maste         m_variable_list_sp->AddVariables(global_variable_list_sp.get());
445ac7ddfbfSEd Maste       else
446ac7ddfbfSEd Maste         m_variable_list_sp = global_variable_list_sp;
447ac7ddfbfSEd Maste     }
448ac7ddfbfSEd Maste   }
449ac7ddfbfSEd Maste 
450ac7ddfbfSEd Maste   return m_variable_list_sp.get();
451ac7ddfbfSEd Maste }
452ac7ddfbfSEd Maste 
453ac7ddfbfSEd Maste VariableListSP
GetInScopeVariableList(bool get_file_globals,bool must_have_valid_location)454435933ddSDimitry Andric StackFrame::GetInScopeVariableList(bool get_file_globals,
455435933ddSDimitry Andric                                    bool must_have_valid_location) {
4564bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
45735617911SEd Maste   // We can't fetch variable information for a history stack frame.
458*b5893f02SDimitry Andric   if (IsHistorical())
45935617911SEd Maste     return VariableListSP();
46035617911SEd Maste 
461ac7ddfbfSEd Maste   VariableListSP var_list_sp(new VariableList);
462ac7ddfbfSEd Maste   GetSymbolContext(eSymbolContextCompUnit | eSymbolContextBlock);
463ac7ddfbfSEd Maste 
464435933ddSDimitry Andric   if (m_sc.block) {
465ac7ddfbfSEd Maste     const bool can_create = true;
466ac7ddfbfSEd Maste     const bool get_parent_variables = true;
467ac7ddfbfSEd Maste     const bool stop_if_block_is_inlined_function = true;
468435933ddSDimitry Andric     m_sc.block->AppendVariables(
469435933ddSDimitry Andric         can_create, get_parent_variables, stop_if_block_is_inlined_function,
470435933ddSDimitry Andric         [this, must_have_valid_location](Variable *v) {
471435933ddSDimitry Andric           return v->IsInScope(this) && (!must_have_valid_location ||
472435933ddSDimitry Andric                                         v->LocationIsValidForFrame(this));
4734bb0738eSEd Maste         },
474ac7ddfbfSEd Maste         var_list_sp.get());
475ac7ddfbfSEd Maste   }
476ac7ddfbfSEd Maste 
477435933ddSDimitry Andric   if (m_sc.comp_unit && get_file_globals) {
478435933ddSDimitry Andric     VariableListSP global_variable_list_sp(
479435933ddSDimitry Andric         m_sc.comp_unit->GetVariableList(true));
480ac7ddfbfSEd Maste     if (global_variable_list_sp)
481ac7ddfbfSEd Maste       var_list_sp->AddVariables(global_variable_list_sp.get());
482ac7ddfbfSEd Maste   }
483ac7ddfbfSEd Maste 
484ac7ddfbfSEd Maste   return var_list_sp;
485ac7ddfbfSEd Maste }
486ac7ddfbfSEd Maste 
GetValueForVariableExpressionPath(llvm::StringRef var_expr,DynamicValueType use_dynamic,uint32_t options,VariableSP & var_sp,Status & error)487435933ddSDimitry Andric ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
488435933ddSDimitry Andric     llvm::StringRef var_expr, DynamicValueType use_dynamic, uint32_t options,
4895517e702SDimitry Andric     VariableSP &var_sp, Status &error) {
490435933ddSDimitry Andric   llvm::StringRef original_var_expr = var_expr;
49135617911SEd Maste   // We can't fetch variable information for a history stack frame.
492*b5893f02SDimitry Andric   if (IsHistorical())
49335617911SEd Maste     return ValueObjectSP();
494ac7ddfbfSEd Maste 
495435933ddSDimitry Andric   if (var_expr.empty()) {
496435933ddSDimitry Andric     error.SetErrorStringWithFormat("invalid variable path '%s'",
497435933ddSDimitry Andric                                    var_expr.str().c_str());
498435933ddSDimitry Andric     return ValueObjectSP();
499435933ddSDimitry Andric   }
500435933ddSDimitry Andric 
501435933ddSDimitry Andric   const bool check_ptr_vs_member =
502435933ddSDimitry Andric       (options & eExpressionPathOptionCheckPtrVsMember) != 0;
503435933ddSDimitry Andric   const bool no_fragile_ivar =
504435933ddSDimitry Andric       (options & eExpressionPathOptionsNoFragileObjcIvar) != 0;
505435933ddSDimitry Andric   const bool no_synth_child =
506435933ddSDimitry Andric       (options & eExpressionPathOptionsNoSyntheticChildren) != 0;
507435933ddSDimitry Andric   // const bool no_synth_array = (options &
508435933ddSDimitry Andric   // eExpressionPathOptionsNoSyntheticArrayRange) != 0;
509ac7ddfbfSEd Maste   error.Clear();
510ac7ddfbfSEd Maste   bool deref = false;
511ac7ddfbfSEd Maste   bool address_of = false;
512ac7ddfbfSEd Maste   ValueObjectSP valobj_sp;
513ac7ddfbfSEd Maste   const bool get_file_globals = true;
514ac7ddfbfSEd Maste   // When looking up a variable for an expression, we need only consider the
515ac7ddfbfSEd Maste   // variables that are in scope.
516ac7ddfbfSEd Maste   VariableListSP var_list_sp(GetInScopeVariableList(get_file_globals));
517ac7ddfbfSEd Maste   VariableList *variable_list = var_list_sp.get();
518ac7ddfbfSEd Maste 
519435933ddSDimitry Andric   if (!variable_list)
520435933ddSDimitry Andric     return ValueObjectSP();
521435933ddSDimitry Andric 
522ac7ddfbfSEd Maste   // If first character is a '*', then show pointer contents
523435933ddSDimitry Andric   std::string var_expr_storage;
524435933ddSDimitry Andric   if (var_expr[0] == '*') {
525ac7ddfbfSEd Maste     deref = true;
526435933ddSDimitry Andric     var_expr = var_expr.drop_front(); // Skip the '*'
527435933ddSDimitry Andric   } else if (var_expr[0] == '&') {
528ac7ddfbfSEd Maste     address_of = true;
529435933ddSDimitry Andric     var_expr = var_expr.drop_front(); // Skip the '&'
530ac7ddfbfSEd Maste   }
531ac7ddfbfSEd Maste 
532435933ddSDimitry Andric   size_t separator_idx = var_expr.find_first_of(".-[=+~|&^%#@!/?,<>{}");
533ac7ddfbfSEd Maste   StreamString var_expr_path_strm;
534ac7ddfbfSEd Maste 
535435933ddSDimitry Andric   ConstString name_const_string(var_expr.substr(0, separator_idx));
536ac7ddfbfSEd Maste 
5379f2f44ceSEd Maste   var_sp = variable_list->FindVariable(name_const_string, false);
538ac7ddfbfSEd Maste 
539ac7ddfbfSEd Maste   bool synthetically_added_instance_object = false;
540ac7ddfbfSEd Maste 
541435933ddSDimitry Andric   if (var_sp) {
542435933ddSDimitry Andric     var_expr = var_expr.drop_front(name_const_string.GetLength());
543ac7ddfbfSEd Maste   }
5449f2f44ceSEd Maste 
545435933ddSDimitry Andric   if (!var_sp && (options & eExpressionPathOptionsAllowDirectIVarAccess)) {
5464ba319b5SDimitry Andric     // Check for direct ivars access which helps us with implicit access to
5474ba319b5SDimitry Andric     // ivars with the "this->" or "self->"
548ac7ddfbfSEd Maste     GetSymbolContext(eSymbolContextFunction | eSymbolContextBlock);
549ac7ddfbfSEd Maste     lldb::LanguageType method_language = eLanguageTypeUnknown;
550ac7ddfbfSEd Maste     bool is_instance_method = false;
551ac7ddfbfSEd Maste     ConstString method_object_name;
552435933ddSDimitry Andric     if (m_sc.GetFunctionMethodInfo(method_language, is_instance_method,
553435933ddSDimitry Andric                                    method_object_name)) {
554435933ddSDimitry Andric       if (is_instance_method && method_object_name) {
555ac7ddfbfSEd Maste         var_sp = variable_list->FindVariable(method_object_name);
556435933ddSDimitry Andric         if (var_sp) {
557ac7ddfbfSEd Maste           separator_idx = 0;
558435933ddSDimitry Andric           var_expr_storage = "->";
559435933ddSDimitry Andric           var_expr_storage += var_expr;
560435933ddSDimitry Andric           var_expr = var_expr_storage;
561ac7ddfbfSEd Maste           synthetically_added_instance_object = true;
562ac7ddfbfSEd Maste         }
563ac7ddfbfSEd Maste       }
564ac7ddfbfSEd Maste     }
565ac7ddfbfSEd Maste   }
566ac7ddfbfSEd Maste 
567435933ddSDimitry Andric   if (!var_sp && (options & eExpressionPathOptionsInspectAnonymousUnions)) {
568435933ddSDimitry Andric     // Check if any anonymous unions are there which contain a variable with
569435933ddSDimitry Andric     // the name we need
570435933ddSDimitry Andric     for (size_t i = 0; i < variable_list->GetSize(); i++) {
571435933ddSDimitry Andric       VariableSP variable_sp = variable_list->GetVariableAtIndex(i);
572435933ddSDimitry Andric       if (!variable_sp)
573435933ddSDimitry Andric         continue;
574435933ddSDimitry Andric       if (!variable_sp->GetName().IsEmpty())
575435933ddSDimitry Andric         continue;
576435933ddSDimitry Andric 
577435933ddSDimitry Andric       Type *var_type = variable_sp->GetType();
578435933ddSDimitry Andric       if (!var_type)
579435933ddSDimitry Andric         continue;
580435933ddSDimitry Andric 
581435933ddSDimitry Andric       if (!var_type->GetForwardCompilerType().IsAnonymousType())
582435933ddSDimitry Andric         continue;
5839f2f44ceSEd Maste       valobj_sp = GetValueObjectForFrameVariable(variable_sp, use_dynamic);
5849f2f44ceSEd Maste       if (!valobj_sp)
5859f2f44ceSEd Maste         return valobj_sp;
5869f2f44ceSEd Maste       valobj_sp = valobj_sp->GetChildMemberWithName(name_const_string, true);
5879f2f44ceSEd Maste       if (valobj_sp)
5889f2f44ceSEd Maste         break;
5899f2f44ceSEd Maste     }
5909f2f44ceSEd Maste   }
5919f2f44ceSEd Maste 
592435933ddSDimitry Andric   if (var_sp && !valobj_sp) {
593ac7ddfbfSEd Maste     valobj_sp = GetValueObjectForFrameVariable(var_sp, use_dynamic);
594ac7ddfbfSEd Maste     if (!valobj_sp)
595ac7ddfbfSEd Maste       return valobj_sp;
5969f2f44ceSEd Maste   }
597435933ddSDimitry Andric   if (!valobj_sp) {
598435933ddSDimitry Andric     error.SetErrorStringWithFormat("no variable named '%s' found in this frame",
599435933ddSDimitry Andric                                    name_const_string.GetCString());
600435933ddSDimitry Andric     return ValueObjectSP();
601435933ddSDimitry Andric   }
602435933ddSDimitry Andric 
603ac7ddfbfSEd Maste   // We are dumping at least one child
604435933ddSDimitry Andric   while (separator_idx != std::string::npos) {
605ac7ddfbfSEd Maste     // Calculate the next separator index ahead of time
606ac7ddfbfSEd Maste     ValueObjectSP child_valobj_sp;
607435933ddSDimitry Andric     const char separator_type = var_expr[0];
608f678e45dSDimitry Andric     bool expr_is_ptr = false;
609435933ddSDimitry Andric     switch (separator_type) {
610ac7ddfbfSEd Maste     case '-':
611f678e45dSDimitry Andric       expr_is_ptr = true;
612435933ddSDimitry Andric       if (var_expr.size() >= 2 && var_expr[1] != '>')
613ac7ddfbfSEd Maste         return ValueObjectSP();
614ac7ddfbfSEd Maste 
615435933ddSDimitry Andric       if (no_fragile_ivar) {
616ac7ddfbfSEd Maste         // Make sure we aren't trying to deref an objective
617ac7ddfbfSEd Maste         // C ivar if this is not allowed
618435933ddSDimitry Andric         const uint32_t pointer_type_flags =
619435933ddSDimitry Andric             valobj_sp->GetCompilerType().GetTypeInfo(nullptr);
6207aa51b79SEd Maste         if ((pointer_type_flags & eTypeIsObjC) &&
621435933ddSDimitry Andric             (pointer_type_flags & eTypeIsPointer)) {
6224ba319b5SDimitry Andric           // This was an objective C object pointer and it was requested we
6234ba319b5SDimitry Andric           // skip any fragile ivars so return nothing here
624ac7ddfbfSEd Maste           return ValueObjectSP();
625ac7ddfbfSEd Maste         }
626ac7ddfbfSEd Maste       }
627f678e45dSDimitry Andric 
628f678e45dSDimitry Andric       // If we have a non pointer type with a sythetic value then lets check if
629f678e45dSDimitry Andric       // we have an sythetic dereference specified.
630f678e45dSDimitry Andric       if (!valobj_sp->IsPointerType() && valobj_sp->HasSyntheticValue()) {
6315517e702SDimitry Andric         Status deref_error;
632f678e45dSDimitry Andric         if (valobj_sp->GetCompilerType().IsReferenceType()) {
633f678e45dSDimitry Andric           valobj_sp = valobj_sp->GetSyntheticValue()->Dereference(deref_error);
634f678e45dSDimitry Andric           if (error.Fail()) {
635f678e45dSDimitry Andric             error.SetErrorStringWithFormatv(
636f678e45dSDimitry Andric                 "Failed to dereference reference type: %s", deref_error);
637f678e45dSDimitry Andric             return ValueObjectSP();
638f678e45dSDimitry Andric           }
639f678e45dSDimitry Andric         }
640f678e45dSDimitry Andric 
641f678e45dSDimitry Andric         valobj_sp = valobj_sp->Dereference(deref_error);
642f678e45dSDimitry Andric         if (error.Fail()) {
643f678e45dSDimitry Andric           error.SetErrorStringWithFormatv(
644f678e45dSDimitry Andric               "Failed to dereference sythetic value: %s", deref_error);
645f678e45dSDimitry Andric           return ValueObjectSP();
646f678e45dSDimitry Andric         }
647f678e45dSDimitry Andric         expr_is_ptr = false;
648f678e45dSDimitry Andric       }
649f678e45dSDimitry Andric 
650435933ddSDimitry Andric       var_expr = var_expr.drop_front(); // Remove the '-'
6514bb0738eSEd Maste       LLVM_FALLTHROUGH;
652435933ddSDimitry Andric     case '.': {
653435933ddSDimitry Andric       var_expr = var_expr.drop_front(); // Remove the '.' or '>'
654435933ddSDimitry Andric       separator_idx = var_expr.find_first_of(".-[");
655435933ddSDimitry Andric       ConstString child_name(var_expr.substr(0, var_expr.find_first_of(".-[")));
656ac7ddfbfSEd Maste 
657435933ddSDimitry Andric       if (check_ptr_vs_member) {
6584ba319b5SDimitry Andric         // We either have a pointer type and need to verify valobj_sp is a
6594ba319b5SDimitry Andric         // pointer, or we have a member of a class/union/struct being accessed
6604ba319b5SDimitry Andric         // with the . syntax and need to verify we don't have a pointer.
661ac7ddfbfSEd Maste         const bool actual_is_ptr = valobj_sp->IsPointerType();
662ac7ddfbfSEd Maste 
663435933ddSDimitry Andric         if (actual_is_ptr != expr_is_ptr) {
6644ba319b5SDimitry Andric           // Incorrect use of "." with a pointer, or "->" with a
6654ba319b5SDimitry Andric           // class/union/struct instance or reference.
666ac7ddfbfSEd Maste           valobj_sp->GetExpressionPath(var_expr_path_strm, false);
667ac7ddfbfSEd Maste           if (actual_is_ptr)
668435933ddSDimitry Andric             error.SetErrorStringWithFormat(
669435933ddSDimitry Andric                 "\"%s\" is a pointer and . was used to attempt to access "
670435933ddSDimitry Andric                 "\"%s\". Did you mean \"%s->%s\"?",
671435933ddSDimitry Andric                 var_expr_path_strm.GetData(), child_name.GetCString(),
672435933ddSDimitry Andric                 var_expr_path_strm.GetData(), var_expr.str().c_str());
673ac7ddfbfSEd Maste           else
674435933ddSDimitry Andric             error.SetErrorStringWithFormat(
675435933ddSDimitry Andric                 "\"%s\" is not a pointer and -> was used to attempt to "
676435933ddSDimitry Andric                 "access \"%s\". Did you mean \"%s.%s\"?",
677435933ddSDimitry Andric                 var_expr_path_strm.GetData(), child_name.GetCString(),
678435933ddSDimitry Andric                 var_expr_path_strm.GetData(), var_expr.str().c_str());
679ac7ddfbfSEd Maste           return ValueObjectSP();
680ac7ddfbfSEd Maste         }
681ac7ddfbfSEd Maste       }
682ac7ddfbfSEd Maste       child_valobj_sp = valobj_sp->GetChildMemberWithName(child_name, true);
683435933ddSDimitry Andric       if (!child_valobj_sp) {
684435933ddSDimitry Andric         if (!no_synth_child) {
685ac7ddfbfSEd Maste           child_valobj_sp = valobj_sp->GetSyntheticValue();
686ac7ddfbfSEd Maste           if (child_valobj_sp)
687435933ddSDimitry Andric             child_valobj_sp =
688435933ddSDimitry Andric                 child_valobj_sp->GetChildMemberWithName(child_name, true);
689ac7ddfbfSEd Maste         }
690ac7ddfbfSEd Maste 
691435933ddSDimitry Andric         if (no_synth_child || !child_valobj_sp) {
692ac7ddfbfSEd Maste           // No child member with name "child_name"
693435933ddSDimitry Andric           if (synthetically_added_instance_object) {
694435933ddSDimitry Andric             // We added a "this->" or "self->" to the beginning of the
6954ba319b5SDimitry Andric             // expression and this is the first pointer ivar access, so just
6964ba319b5SDimitry Andric             // return the normal error
697435933ddSDimitry Andric             error.SetErrorStringWithFormat(
698435933ddSDimitry Andric                 "no variable or instance variable named '%s' found in "
699435933ddSDimitry Andric                 "this frame",
700ac7ddfbfSEd Maste                 name_const_string.GetCString());
701435933ddSDimitry Andric           } else {
702ac7ddfbfSEd Maste             valobj_sp->GetExpressionPath(var_expr_path_strm, false);
703435933ddSDimitry Andric             if (child_name) {
704435933ddSDimitry Andric               error.SetErrorStringWithFormat(
705435933ddSDimitry Andric                   "\"%s\" is not a member of \"(%s) %s\"",
706ac7ddfbfSEd Maste                   child_name.GetCString(),
707ac7ddfbfSEd Maste                   valobj_sp->GetTypeName().AsCString("<invalid type>"),
708435933ddSDimitry Andric                   var_expr_path_strm.GetData());
709435933ddSDimitry Andric             } else {
710435933ddSDimitry Andric               error.SetErrorStringWithFormat(
711435933ddSDimitry Andric                   "incomplete expression path after \"%s\" in \"%s\"",
712435933ddSDimitry Andric                   var_expr_path_strm.GetData(),
713435933ddSDimitry Andric                   original_var_expr.str().c_str());
714ac7ddfbfSEd Maste             }
715ac7ddfbfSEd Maste           }
716ac7ddfbfSEd Maste           return ValueObjectSP();
717ac7ddfbfSEd Maste         }
718ac7ddfbfSEd Maste       }
719ac7ddfbfSEd Maste       synthetically_added_instance_object = false;
720ac7ddfbfSEd Maste       // Remove the child name from the path
721435933ddSDimitry Andric       var_expr = var_expr.drop_front(child_name.GetLength());
722435933ddSDimitry Andric       if (use_dynamic != eNoDynamicValues) {
723435933ddSDimitry Andric         ValueObjectSP dynamic_value_sp(
724435933ddSDimitry Andric             child_valobj_sp->GetDynamicValue(use_dynamic));
725ac7ddfbfSEd Maste         if (dynamic_value_sp)
726ac7ddfbfSEd Maste           child_valobj_sp = dynamic_value_sp;
727ac7ddfbfSEd Maste       }
728435933ddSDimitry Andric     } break;
729ac7ddfbfSEd Maste 
730435933ddSDimitry Andric     case '[': {
7314ba319b5SDimitry Andric       // Array member access, or treating pointer as an array Need at least two
7324ba319b5SDimitry Andric       // brackets and a number
733435933ddSDimitry Andric       if (var_expr.size() <= 2) {
734435933ddSDimitry Andric         error.SetErrorStringWithFormat(
735435933ddSDimitry Andric             "invalid square bracket encountered after \"%s\" in \"%s\"",
736435933ddSDimitry Andric             var_expr_path_strm.GetData(), var_expr.str().c_str());
737435933ddSDimitry Andric         return ValueObjectSP();
738435933ddSDimitry Andric       }
739435933ddSDimitry Andric 
740435933ddSDimitry Andric       // Drop the open brace.
741435933ddSDimitry Andric       var_expr = var_expr.drop_front();
742435933ddSDimitry Andric       long child_index = 0;
743435933ddSDimitry Andric 
744435933ddSDimitry Andric       // If there's no closing brace, this is an invalid expression.
745435933ddSDimitry Andric       size_t end_pos = var_expr.find_first_of(']');
746435933ddSDimitry Andric       if (end_pos == llvm::StringRef::npos) {
747435933ddSDimitry Andric         error.SetErrorStringWithFormat(
748435933ddSDimitry Andric             "missing closing square bracket in expression \"%s\"",
749435933ddSDimitry Andric             var_expr_path_strm.GetData());
750435933ddSDimitry Andric         return ValueObjectSP();
751435933ddSDimitry Andric       }
752435933ddSDimitry Andric       llvm::StringRef index_expr = var_expr.take_front(end_pos);
753435933ddSDimitry Andric       llvm::StringRef original_index_expr = index_expr;
754435933ddSDimitry Andric       // Drop all of "[index_expr]"
755435933ddSDimitry Andric       var_expr = var_expr.drop_front(end_pos + 1);
756435933ddSDimitry Andric 
757435933ddSDimitry Andric       if (index_expr.consumeInteger(0, child_index)) {
758435933ddSDimitry Andric         // If there was no integer anywhere in the index expression, this is
759435933ddSDimitry Andric         // erroneous expression.
760435933ddSDimitry Andric         error.SetErrorStringWithFormat("invalid index expression \"%s\"",
761435933ddSDimitry Andric                                        index_expr.str().c_str());
762435933ddSDimitry Andric         return ValueObjectSP();
763435933ddSDimitry Andric       }
764435933ddSDimitry Andric 
765435933ddSDimitry Andric       if (index_expr.empty()) {
766435933ddSDimitry Andric         // The entire index expression was a single integer.
767435933ddSDimitry Andric 
768435933ddSDimitry Andric         if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) {
769435933ddSDimitry Andric           // what we have is *ptr[low]. the most similar C++ syntax is to deref
770435933ddSDimitry Andric           // ptr and extract bit low out of it. reading array item low would be
771435933ddSDimitry Andric           // done by saying ptr[low], without a deref * sign
7725517e702SDimitry Andric           Status error;
773ac7ddfbfSEd Maste           ValueObjectSP temp(valobj_sp->Dereference(error));
774435933ddSDimitry Andric           if (error.Fail()) {
775ac7ddfbfSEd Maste             valobj_sp->GetExpressionPath(var_expr_path_strm, false);
776435933ddSDimitry Andric             error.SetErrorStringWithFormat(
777435933ddSDimitry Andric                 "could not dereference \"(%s) %s\"",
778ac7ddfbfSEd Maste                 valobj_sp->GetTypeName().AsCString("<invalid type>"),
779435933ddSDimitry Andric                 var_expr_path_strm.GetData());
780ac7ddfbfSEd Maste             return ValueObjectSP();
781ac7ddfbfSEd Maste           }
782ac7ddfbfSEd Maste           valobj_sp = temp;
783ac7ddfbfSEd Maste           deref = false;
784435933ddSDimitry Andric         } else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() &&
785435933ddSDimitry Andric                    deref) {
7864ba319b5SDimitry Andric           // what we have is *arr[low]. the most similar C++ syntax is to get
7874ba319b5SDimitry Andric           // arr[0] (an operation that is equivalent to deref-ing arr) and
7884ba319b5SDimitry Andric           // extract bit low out of it. reading array item low would be done by
7894ba319b5SDimitry Andric           // saying arr[low], without a deref * sign
7905517e702SDimitry Andric           Status error;
791ac7ddfbfSEd Maste           ValueObjectSP temp(valobj_sp->GetChildAtIndex(0, true));
792435933ddSDimitry Andric           if (error.Fail()) {
793ac7ddfbfSEd Maste             valobj_sp->GetExpressionPath(var_expr_path_strm, false);
794435933ddSDimitry Andric             error.SetErrorStringWithFormat(
795435933ddSDimitry Andric                 "could not get item 0 for \"(%s) %s\"",
796ac7ddfbfSEd Maste                 valobj_sp->GetTypeName().AsCString("<invalid type>"),
797435933ddSDimitry Andric                 var_expr_path_strm.GetData());
798ac7ddfbfSEd Maste             return ValueObjectSP();
799ac7ddfbfSEd Maste           }
800ac7ddfbfSEd Maste           valobj_sp = temp;
801ac7ddfbfSEd Maste           deref = false;
802ac7ddfbfSEd Maste         }
803ac7ddfbfSEd Maste 
804ac7ddfbfSEd Maste         bool is_incomplete_array = false;
805435933ddSDimitry Andric         if (valobj_sp->IsPointerType()) {
806ac7ddfbfSEd Maste           bool is_objc_pointer = true;
807ac7ddfbfSEd Maste 
808435933ddSDimitry Andric           if (valobj_sp->GetCompilerType().GetMinimumLanguage() !=
809435933ddSDimitry Andric               eLanguageTypeObjC)
810ac7ddfbfSEd Maste             is_objc_pointer = false;
8119f2f44ceSEd Maste           else if (!valobj_sp->GetCompilerType().IsPointerType())
812ac7ddfbfSEd Maste             is_objc_pointer = false;
813ac7ddfbfSEd Maste 
814435933ddSDimitry Andric           if (no_synth_child && is_objc_pointer) {
815435933ddSDimitry Andric             error.SetErrorStringWithFormat(
816435933ddSDimitry Andric                 "\"(%s) %s\" is an Objective-C pointer, and cannot be "
817435933ddSDimitry Andric                 "subscripted",
818ac7ddfbfSEd Maste                 valobj_sp->GetTypeName().AsCString("<invalid type>"),
819435933ddSDimitry Andric                 var_expr_path_strm.GetData());
820ac7ddfbfSEd Maste 
821ac7ddfbfSEd Maste             return ValueObjectSP();
822435933ddSDimitry Andric           } else if (is_objc_pointer) {
8234ba319b5SDimitry Andric             // dereferencing ObjC variables is not valid.. so let's try and
8244ba319b5SDimitry Andric             // recur to synthetic children
825ac7ddfbfSEd Maste             ValueObjectSP synthetic = valobj_sp->GetSyntheticValue();
8264bb0738eSEd Maste             if (!synthetic                 /* no synthetic */
827435933ddSDimitry Andric                 || synthetic == valobj_sp) /* synthetic is the same as
828435933ddSDimitry Andric                                               the original object */
829ac7ddfbfSEd Maste             {
830ac7ddfbfSEd Maste               valobj_sp->GetExpressionPath(var_expr_path_strm, false);
831435933ddSDimitry Andric               error.SetErrorStringWithFormat(
832435933ddSDimitry Andric                   "\"(%s) %s\" is not an array type",
833ac7ddfbfSEd Maste                   valobj_sp->GetTypeName().AsCString("<invalid type>"),
834435933ddSDimitry Andric                   var_expr_path_strm.GetData());
835435933ddSDimitry Andric             } else if (
836435933ddSDimitry Andric                 static_cast<uint32_t>(child_index) >=
837435933ddSDimitry Andric                 synthetic
838435933ddSDimitry Andric                     ->GetNumChildren() /* synthetic does not have that many values */) {
839ac7ddfbfSEd Maste               valobj_sp->GetExpressionPath(var_expr_path_strm, false);
840435933ddSDimitry Andric               error.SetErrorStringWithFormat(
841435933ddSDimitry Andric                   "array index %ld is not valid for \"(%s) %s\"", child_index,
842ac7ddfbfSEd Maste                   valobj_sp->GetTypeName().AsCString("<invalid type>"),
843435933ddSDimitry Andric                   var_expr_path_strm.GetData());
844435933ddSDimitry Andric             } else {
845ac7ddfbfSEd Maste               child_valobj_sp = synthetic->GetChildAtIndex(child_index, true);
846435933ddSDimitry Andric               if (!child_valobj_sp) {
847ac7ddfbfSEd Maste                 valobj_sp->GetExpressionPath(var_expr_path_strm, false);
848435933ddSDimitry Andric                 error.SetErrorStringWithFormat(
849435933ddSDimitry Andric                     "array index %ld is not valid for \"(%s) %s\"", child_index,
850435933ddSDimitry Andric                     valobj_sp->GetTypeName().AsCString("<invalid type>"),
851435933ddSDimitry Andric                     var_expr_path_strm.GetData());
852435933ddSDimitry Andric               }
853435933ddSDimitry Andric             }
854435933ddSDimitry Andric           } else {
855435933ddSDimitry Andric             child_valobj_sp =
856435933ddSDimitry Andric                 valobj_sp->GetSyntheticArrayMember(child_index, true);
857435933ddSDimitry Andric             if (!child_valobj_sp) {
858435933ddSDimitry Andric               valobj_sp->GetExpressionPath(var_expr_path_strm, false);
859435933ddSDimitry Andric               error.SetErrorStringWithFormat(
860435933ddSDimitry Andric                   "failed to use pointer as array for index %ld for "
861435933ddSDimitry Andric                   "\"(%s) %s\"",
862ac7ddfbfSEd Maste                   child_index,
863ac7ddfbfSEd Maste                   valobj_sp->GetTypeName().AsCString("<invalid type>"),
864435933ddSDimitry Andric                   var_expr_path_strm.GetData());
865ac7ddfbfSEd Maste             }
866ac7ddfbfSEd Maste           }
867435933ddSDimitry Andric         } else if (valobj_sp->GetCompilerType().IsArrayType(
868435933ddSDimitry Andric                        nullptr, nullptr, &is_incomplete_array)) {
8694ba319b5SDimitry Andric           // Pass false to dynamic_value here so we can tell the difference
8704ba319b5SDimitry Andric           // between no dynamic value and no member of this type...
871ac7ddfbfSEd Maste           child_valobj_sp = valobj_sp->GetChildAtIndex(child_index, true);
8724bb0738eSEd Maste           if (!child_valobj_sp && (is_incomplete_array || !no_synth_child))
873435933ddSDimitry Andric             child_valobj_sp =
874435933ddSDimitry Andric                 valobj_sp->GetSyntheticArrayMember(child_index, true);
875ac7ddfbfSEd Maste 
876435933ddSDimitry Andric           if (!child_valobj_sp) {
877ac7ddfbfSEd Maste             valobj_sp->GetExpressionPath(var_expr_path_strm, false);
878435933ddSDimitry Andric             error.SetErrorStringWithFormat(
879435933ddSDimitry Andric                 "array index %ld is not valid for \"(%s) %s\"", child_index,
880ac7ddfbfSEd Maste                 valobj_sp->GetTypeName().AsCString("<invalid type>"),
881435933ddSDimitry Andric                 var_expr_path_strm.GetData());
882ac7ddfbfSEd Maste           }
883435933ddSDimitry Andric         } else if (valobj_sp->GetCompilerType().IsScalarType()) {
884ac7ddfbfSEd Maste           // this is a bitfield asking to display just one bit
885435933ddSDimitry Andric           child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild(
886435933ddSDimitry Andric               child_index, child_index, true);
887435933ddSDimitry Andric           if (!child_valobj_sp) {
888ac7ddfbfSEd Maste             valobj_sp->GetExpressionPath(var_expr_path_strm, false);
889435933ddSDimitry Andric             error.SetErrorStringWithFormat(
890435933ddSDimitry Andric                 "bitfield range %ld-%ld is not valid for \"(%s) %s\"",
891ac7ddfbfSEd Maste                 child_index, child_index,
892ac7ddfbfSEd Maste                 valobj_sp->GetTypeName().AsCString("<invalid type>"),
893435933ddSDimitry Andric                 var_expr_path_strm.GetData());
894ac7ddfbfSEd Maste           }
895435933ddSDimitry Andric         } else {
896ac7ddfbfSEd Maste           ValueObjectSP synthetic = valobj_sp->GetSyntheticValue();
897ac7ddfbfSEd Maste           if (no_synth_child /* synthetic is forbidden */ ||
8984bb0738eSEd Maste               !synthetic                 /* no synthetic */
899435933ddSDimitry Andric               || synthetic == valobj_sp) /* synthetic is the same as the
900435933ddSDimitry Andric                                             original object */
901ac7ddfbfSEd Maste           {
902ac7ddfbfSEd Maste             valobj_sp->GetExpressionPath(var_expr_path_strm, false);
903435933ddSDimitry Andric             error.SetErrorStringWithFormat(
904435933ddSDimitry Andric                 "\"(%s) %s\" is not an array type",
905ac7ddfbfSEd Maste                 valobj_sp->GetTypeName().AsCString("<invalid type>"),
906435933ddSDimitry Andric                 var_expr_path_strm.GetData());
907435933ddSDimitry Andric           } else if (
908435933ddSDimitry Andric               static_cast<uint32_t>(child_index) >=
909435933ddSDimitry Andric               synthetic
910435933ddSDimitry Andric                   ->GetNumChildren() /* synthetic does not have that many values */) {
911ac7ddfbfSEd Maste             valobj_sp->GetExpressionPath(var_expr_path_strm, false);
912435933ddSDimitry Andric             error.SetErrorStringWithFormat(
913435933ddSDimitry Andric                 "array index %ld is not valid for \"(%s) %s\"", child_index,
914ac7ddfbfSEd Maste                 valobj_sp->GetTypeName().AsCString("<invalid type>"),
915435933ddSDimitry Andric                 var_expr_path_strm.GetData());
916435933ddSDimitry Andric           } else {
917ac7ddfbfSEd Maste             child_valobj_sp = synthetic->GetChildAtIndex(child_index, true);
918435933ddSDimitry Andric             if (!child_valobj_sp) {
919ac7ddfbfSEd Maste               valobj_sp->GetExpressionPath(var_expr_path_strm, false);
920435933ddSDimitry Andric               error.SetErrorStringWithFormat(
921435933ddSDimitry Andric                   "array index %ld is not valid for \"(%s) %s\"", child_index,
922ac7ddfbfSEd Maste                   valobj_sp->GetTypeName().AsCString("<invalid type>"),
923435933ddSDimitry Andric                   var_expr_path_strm.GetData());
924ac7ddfbfSEd Maste             }
925ac7ddfbfSEd Maste           }
926ac7ddfbfSEd Maste         }
927ac7ddfbfSEd Maste 
928435933ddSDimitry Andric         if (!child_valobj_sp) {
929ac7ddfbfSEd Maste           // Invalid array index...
930ac7ddfbfSEd Maste           return ValueObjectSP();
931ac7ddfbfSEd Maste         }
932ac7ddfbfSEd Maste 
933435933ddSDimitry Andric         separator_idx = var_expr.find_first_of(".-[");
934435933ddSDimitry Andric         if (use_dynamic != eNoDynamicValues) {
935435933ddSDimitry Andric           ValueObjectSP dynamic_value_sp(
936435933ddSDimitry Andric               child_valobj_sp->GetDynamicValue(use_dynamic));
937ac7ddfbfSEd Maste           if (dynamic_value_sp)
938ac7ddfbfSEd Maste             child_valobj_sp = dynamic_value_sp;
939ac7ddfbfSEd Maste         }
940435933ddSDimitry Andric         // Break out early from the switch since we were able to find the child
941435933ddSDimitry Andric         // member
942ac7ddfbfSEd Maste         break;
943ac7ddfbfSEd Maste       }
944435933ddSDimitry Andric 
945ac7ddfbfSEd Maste       // this is most probably a BitField, let's take a look
946435933ddSDimitry Andric       if (index_expr.front() != '-') {
947435933ddSDimitry Andric         error.SetErrorStringWithFormat("invalid range expression \"'%s'\"",
948435933ddSDimitry Andric                                        original_index_expr.str().c_str());
949435933ddSDimitry Andric         return ValueObjectSP();
950435933ddSDimitry Andric       }
951435933ddSDimitry Andric 
952435933ddSDimitry Andric       index_expr = index_expr.drop_front();
953435933ddSDimitry Andric       long final_index = 0;
954435933ddSDimitry Andric       if (index_expr.getAsInteger(0, final_index)) {
955435933ddSDimitry Andric         error.SetErrorStringWithFormat("invalid range expression \"'%s'\"",
956435933ddSDimitry Andric                                        original_index_expr.str().c_str());
957435933ddSDimitry Andric         return ValueObjectSP();
958435933ddSDimitry Andric       }
959435933ddSDimitry Andric 
960ac7ddfbfSEd Maste       // if the format given is [high-low], swap range
961435933ddSDimitry Andric       if (child_index > final_index) {
962ac7ddfbfSEd Maste         long temp = child_index;
963ac7ddfbfSEd Maste         child_index = final_index;
964ac7ddfbfSEd Maste         final_index = temp;
965ac7ddfbfSEd Maste       }
966ac7ddfbfSEd Maste 
967435933ddSDimitry Andric       if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) {
968435933ddSDimitry Andric         // what we have is *ptr[low-high]. the most similar C++ syntax is to
969435933ddSDimitry Andric         // deref ptr and extract bits low thru high out of it. reading array
9704ba319b5SDimitry Andric         // items low thru high would be done by saying ptr[low-high], without a
9714ba319b5SDimitry Andric         // deref * sign
9725517e702SDimitry Andric         Status error;
973ac7ddfbfSEd Maste         ValueObjectSP temp(valobj_sp->Dereference(error));
974435933ddSDimitry Andric         if (error.Fail()) {
975ac7ddfbfSEd Maste           valobj_sp->GetExpressionPath(var_expr_path_strm, false);
976435933ddSDimitry Andric           error.SetErrorStringWithFormat(
977435933ddSDimitry Andric               "could not dereference \"(%s) %s\"",
978ac7ddfbfSEd Maste               valobj_sp->GetTypeName().AsCString("<invalid type>"),
979435933ddSDimitry Andric               var_expr_path_strm.GetData());
980ac7ddfbfSEd Maste           return ValueObjectSP();
981ac7ddfbfSEd Maste         }
982ac7ddfbfSEd Maste         valobj_sp = temp;
983ac7ddfbfSEd Maste         deref = false;
984435933ddSDimitry Andric       } else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() && deref) {
9854ba319b5SDimitry Andric         // what we have is *arr[low-high]. the most similar C++ syntax is to
9864ba319b5SDimitry Andric         // get arr[0] (an operation that is equivalent to deref-ing arr) and
9874ba319b5SDimitry Andric         // extract bits low thru high out of it. reading array items low thru
9884ba319b5SDimitry Andric         // high would be done by saying arr[low-high], without a deref * sign
9895517e702SDimitry Andric         Status error;
990ac7ddfbfSEd Maste         ValueObjectSP temp(valobj_sp->GetChildAtIndex(0, true));
991435933ddSDimitry Andric         if (error.Fail()) {
992ac7ddfbfSEd Maste           valobj_sp->GetExpressionPath(var_expr_path_strm, false);
993435933ddSDimitry Andric           error.SetErrorStringWithFormat(
994435933ddSDimitry Andric               "could not get item 0 for \"(%s) %s\"",
995ac7ddfbfSEd Maste               valobj_sp->GetTypeName().AsCString("<invalid type>"),
996435933ddSDimitry Andric               var_expr_path_strm.GetData());
997ac7ddfbfSEd Maste           return ValueObjectSP();
998ac7ddfbfSEd Maste         }
999ac7ddfbfSEd Maste         valobj_sp = temp;
1000ac7ddfbfSEd Maste         deref = false;
1001ac7ddfbfSEd Maste       }
1002ac7ddfbfSEd Maste 
1003435933ddSDimitry Andric       child_valobj_sp =
1004435933ddSDimitry Andric           valobj_sp->GetSyntheticBitFieldChild(child_index, final_index, true);
1005435933ddSDimitry Andric       if (!child_valobj_sp) {
1006ac7ddfbfSEd Maste         valobj_sp->GetExpressionPath(var_expr_path_strm, false);
1007435933ddSDimitry Andric         error.SetErrorStringWithFormat(
1008435933ddSDimitry Andric             "bitfield range %ld-%ld is not valid for \"(%s) %s\"", child_index,
1009435933ddSDimitry Andric             final_index, valobj_sp->GetTypeName().AsCString("<invalid type>"),
1010435933ddSDimitry Andric             var_expr_path_strm.GetData());
1011ac7ddfbfSEd Maste       }
1012ac7ddfbfSEd Maste 
1013435933ddSDimitry Andric       if (!child_valobj_sp) {
1014ac7ddfbfSEd Maste         // Invalid bitfield range...
1015ac7ddfbfSEd Maste         return ValueObjectSP();
1016ac7ddfbfSEd Maste       }
1017ac7ddfbfSEd Maste 
1018435933ddSDimitry Andric       separator_idx = var_expr.find_first_of(".-[");
1019435933ddSDimitry Andric       if (use_dynamic != eNoDynamicValues) {
1020435933ddSDimitry Andric         ValueObjectSP dynamic_value_sp(
1021435933ddSDimitry Andric             child_valobj_sp->GetDynamicValue(use_dynamic));
1022ac7ddfbfSEd Maste         if (dynamic_value_sp)
1023ac7ddfbfSEd Maste           child_valobj_sp = dynamic_value_sp;
1024ac7ddfbfSEd Maste       }
1025435933ddSDimitry Andric       // Break out early from the switch since we were able to find the child
1026435933ddSDimitry Andric       // member
1027ac7ddfbfSEd Maste       break;
1028ac7ddfbfSEd Maste     }
1029ac7ddfbfSEd Maste     default:
1030ac7ddfbfSEd Maste       // Failure...
1031ac7ddfbfSEd Maste       {
1032ac7ddfbfSEd Maste         valobj_sp->GetExpressionPath(var_expr_path_strm, false);
1033435933ddSDimitry Andric         error.SetErrorStringWithFormat(
1034435933ddSDimitry Andric             "unexpected char '%c' encountered after \"%s\" in \"%s\"",
1035435933ddSDimitry Andric             separator_type, var_expr_path_strm.GetData(),
1036435933ddSDimitry Andric             var_expr.str().c_str());
1037ac7ddfbfSEd Maste 
1038ac7ddfbfSEd Maste         return ValueObjectSP();
1039ac7ddfbfSEd Maste       }
1040ac7ddfbfSEd Maste     }
1041ac7ddfbfSEd Maste 
1042ac7ddfbfSEd Maste     if (child_valobj_sp)
1043ac7ddfbfSEd Maste       valobj_sp = child_valobj_sp;
1044ac7ddfbfSEd Maste 
1045435933ddSDimitry Andric     if (var_expr.empty())
1046ac7ddfbfSEd Maste       break;
1047ac7ddfbfSEd Maste   }
1048435933ddSDimitry Andric   if (valobj_sp) {
1049435933ddSDimitry Andric     if (deref) {
1050ac7ddfbfSEd Maste       ValueObjectSP deref_valobj_sp(valobj_sp->Dereference(error));
1051ac7ddfbfSEd Maste       valobj_sp = deref_valobj_sp;
1052435933ddSDimitry Andric     } else if (address_of) {
1053ac7ddfbfSEd Maste       ValueObjectSP address_of_valobj_sp(valobj_sp->AddressOf(error));
1054ac7ddfbfSEd Maste       valobj_sp = address_of_valobj_sp;
1055ac7ddfbfSEd Maste     }
1056ac7ddfbfSEd Maste   }
1057ac7ddfbfSEd Maste   return valobj_sp;
1058ac7ddfbfSEd Maste }
1059ac7ddfbfSEd Maste 
GetFrameBaseValue(Scalar & frame_base,Status * error_ptr)10605517e702SDimitry Andric bool StackFrame::GetFrameBaseValue(Scalar &frame_base, Status *error_ptr) {
10614bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
1062435933ddSDimitry Andric   if (!m_cfa_is_valid) {
1063435933ddSDimitry Andric     m_frame_base_error.SetErrorString(
1064435933ddSDimitry Andric         "No frame base available for this historical stack frame.");
106535617911SEd Maste     return false;
106635617911SEd Maste   }
106735617911SEd Maste 
1068435933ddSDimitry Andric   if (m_flags.IsClear(GOT_FRAME_BASE)) {
1069435933ddSDimitry Andric     if (m_sc.function) {
1070ac7ddfbfSEd Maste       m_frame_base.Clear();
1071ac7ddfbfSEd Maste       m_frame_base_error.Clear();
1072ac7ddfbfSEd Maste 
1073ac7ddfbfSEd Maste       m_flags.Set(GOT_FRAME_BASE);
1074ac7ddfbfSEd Maste       ExecutionContext exe_ctx(shared_from_this());
1075ac7ddfbfSEd Maste       Value expr_value;
1076ac7ddfbfSEd Maste       addr_t loclist_base_addr = LLDB_INVALID_ADDRESS;
1077ac7ddfbfSEd Maste       if (m_sc.function->GetFrameBaseExpression().IsLocationList())
1078435933ddSDimitry Andric         loclist_base_addr =
1079435933ddSDimitry Andric             m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(
1080435933ddSDimitry Andric                 exe_ctx.GetTargetPtr());
1081ac7ddfbfSEd Maste 
1082*b5893f02SDimitry Andric       if (!m_sc.function->GetFrameBaseExpression().Evaluate(
1083acac075bSDimitry Andric               &exe_ctx, nullptr, loclist_base_addr, nullptr, nullptr,
1084*b5893f02SDimitry Andric               expr_value, &m_frame_base_error)) {
10854ba319b5SDimitry Andric         // We should really have an error if evaluate returns, but in case we
10864ba319b5SDimitry Andric         // don't, lets set the error to something at least.
1087ac7ddfbfSEd Maste         if (m_frame_base_error.Success())
1088435933ddSDimitry Andric           m_frame_base_error.SetErrorString(
1089435933ddSDimitry Andric               "Evaluation of the frame base expression failed.");
1090435933ddSDimitry Andric       } else {
1091ac7ddfbfSEd Maste         m_frame_base = expr_value.ResolveValue(&exe_ctx);
1092ac7ddfbfSEd Maste       }
1093435933ddSDimitry Andric     } else {
1094ac7ddfbfSEd Maste       m_frame_base_error.SetErrorString("No function in symbol context.");
1095ac7ddfbfSEd Maste     }
1096ac7ddfbfSEd Maste   }
1097ac7ddfbfSEd Maste 
1098ac7ddfbfSEd Maste   if (m_frame_base_error.Success())
1099ac7ddfbfSEd Maste     frame_base = m_frame_base;
1100ac7ddfbfSEd Maste 
1101ac7ddfbfSEd Maste   if (error_ptr)
1102ac7ddfbfSEd Maste     *error_ptr = m_frame_base_error;
1103ac7ddfbfSEd Maste   return m_frame_base_error.Success();
1104ac7ddfbfSEd Maste }
1105ac7ddfbfSEd Maste 
GetFrameBaseExpression(Status * error_ptr)11065517e702SDimitry Andric DWARFExpression *StackFrame::GetFrameBaseExpression(Status *error_ptr) {
1107435933ddSDimitry Andric   if (!m_sc.function) {
1108435933ddSDimitry Andric     if (error_ptr) {
1109435933ddSDimitry Andric       error_ptr->SetErrorString("No function in symbol context.");
1110435933ddSDimitry Andric     }
1111435933ddSDimitry Andric     return nullptr;
1112435933ddSDimitry Andric   }
1113435933ddSDimitry Andric 
1114435933ddSDimitry Andric   return &m_sc.function->GetFrameBaseExpression();
1115435933ddSDimitry Andric }
1116435933ddSDimitry Andric 
GetRegisterContext()1117435933ddSDimitry Andric RegisterContextSP StackFrame::GetRegisterContext() {
11184bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
1119435933ddSDimitry Andric   if (!m_reg_context_sp) {
1120ac7ddfbfSEd Maste     ThreadSP thread_sp(GetThread());
1121ac7ddfbfSEd Maste     if (thread_sp)
1122ac7ddfbfSEd Maste       m_reg_context_sp = thread_sp->CreateRegisterContextForFrame(this);
1123ac7ddfbfSEd Maste   }
1124ac7ddfbfSEd Maste   return m_reg_context_sp;
1125ac7ddfbfSEd Maste }
1126ac7ddfbfSEd Maste 
HasDebugInformation()1127435933ddSDimitry Andric bool StackFrame::HasDebugInformation() {
1128ac7ddfbfSEd Maste   GetSymbolContext(eSymbolContextLineEntry);
1129ac7ddfbfSEd Maste   return m_sc.line_entry.IsValid();
1130ac7ddfbfSEd Maste }
1131ac7ddfbfSEd Maste 
1132ac7ddfbfSEd Maste ValueObjectSP
GetValueObjectForFrameVariable(const VariableSP & variable_sp,DynamicValueType use_dynamic)1133435933ddSDimitry Andric StackFrame::GetValueObjectForFrameVariable(const VariableSP &variable_sp,
1134435933ddSDimitry Andric                                            DynamicValueType use_dynamic) {
11354bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
1136ac7ddfbfSEd Maste   ValueObjectSP valobj_sp;
1137*b5893f02SDimitry Andric   if (IsHistorical()) {
113835617911SEd Maste     return valobj_sp;
113935617911SEd Maste   }
1140ac7ddfbfSEd Maste   VariableList *var_list = GetVariableList(true);
1141435933ddSDimitry Andric   if (var_list) {
1142ac7ddfbfSEd Maste     // Make sure the variable is a frame variable
1143ac7ddfbfSEd Maste     const uint32_t var_idx = var_list->FindIndexForVariable(variable_sp.get());
1144ac7ddfbfSEd Maste     const uint32_t num_variables = var_list->GetSize();
1145435933ddSDimitry Andric     if (var_idx < num_variables) {
1146ac7ddfbfSEd Maste       valobj_sp = m_variable_list_value_objects.GetValueObjectAtIndex(var_idx);
1147435933ddSDimitry Andric       if (!valobj_sp) {
1148ac7ddfbfSEd Maste         if (m_variable_list_value_objects.GetSize() < num_variables)
1149ac7ddfbfSEd Maste           m_variable_list_value_objects.Resize(num_variables);
1150ac7ddfbfSEd Maste         valobj_sp = ValueObjectVariable::Create(this, variable_sp);
1151ac7ddfbfSEd Maste         m_variable_list_value_objects.SetValueObjectAtIndex(var_idx, valobj_sp);
1152ac7ddfbfSEd Maste       }
1153ac7ddfbfSEd Maste     }
1154ac7ddfbfSEd Maste   }
1155435933ddSDimitry Andric   if (use_dynamic != eNoDynamicValues && valobj_sp) {
1156ac7ddfbfSEd Maste     ValueObjectSP dynamic_sp = valobj_sp->GetDynamicValue(use_dynamic);
1157ac7ddfbfSEd Maste     if (dynamic_sp)
1158ac7ddfbfSEd Maste       return dynamic_sp;
1159ac7ddfbfSEd Maste   }
1160ac7ddfbfSEd Maste   return valobj_sp;
1161ac7ddfbfSEd Maste }
1162ac7ddfbfSEd Maste 
TrackGlobalVariable(const VariableSP & variable_sp,DynamicValueType use_dynamic)1163435933ddSDimitry Andric ValueObjectSP StackFrame::TrackGlobalVariable(const VariableSP &variable_sp,
1164435933ddSDimitry Andric                                               DynamicValueType use_dynamic) {
11654bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
1166*b5893f02SDimitry Andric   if (IsHistorical())
116735617911SEd Maste     return ValueObjectSP();
116835617911SEd Maste 
1169ac7ddfbfSEd Maste   // Check to make sure we aren't already tracking this variable?
1170435933ddSDimitry Andric   ValueObjectSP valobj_sp(
1171435933ddSDimitry Andric       GetValueObjectForFrameVariable(variable_sp, use_dynamic));
1172435933ddSDimitry Andric   if (!valobj_sp) {
1173ac7ddfbfSEd Maste     // We aren't already tracking this global
1174ac7ddfbfSEd Maste     VariableList *var_list = GetVariableList(true);
1175ac7ddfbfSEd Maste     // If this frame has no variables, create a new list
11764bb0738eSEd Maste     if (var_list == nullptr)
1177ac7ddfbfSEd Maste       m_variable_list_sp.reset(new VariableList());
1178ac7ddfbfSEd Maste 
1179ac7ddfbfSEd Maste     // Add the global/static variable to this frame
1180ac7ddfbfSEd Maste     m_variable_list_sp->AddVariable(variable_sp);
1181ac7ddfbfSEd Maste 
1182ac7ddfbfSEd Maste     // Now make a value object for it so we can track its changes
1183ac7ddfbfSEd Maste     valobj_sp = GetValueObjectForFrameVariable(variable_sp, use_dynamic);
1184ac7ddfbfSEd Maste   }
1185ac7ddfbfSEd Maste   return valobj_sp;
1186ac7ddfbfSEd Maste }
1187ac7ddfbfSEd Maste 
IsInlined()1188435933ddSDimitry Andric bool StackFrame::IsInlined() {
11894bb0738eSEd Maste   if (m_sc.block == nullptr)
1190ac7ddfbfSEd Maste     GetSymbolContext(eSymbolContextBlock);
1191ac7ddfbfSEd Maste   if (m_sc.block)
11924bb0738eSEd Maste     return m_sc.block->GetContainingInlinedBlock() != nullptr;
1193ac7ddfbfSEd Maste   return false;
1194ac7ddfbfSEd Maste }
1195ac7ddfbfSEd Maste 
IsHistorical() const1196*b5893f02SDimitry Andric bool StackFrame::IsHistorical() const {
1197*b5893f02SDimitry Andric   return m_stack_frame_kind == StackFrame::Kind::History;
1198*b5893f02SDimitry Andric }
1199*b5893f02SDimitry Andric 
IsArtificial() const1200*b5893f02SDimitry Andric bool StackFrame::IsArtificial() const {
1201*b5893f02SDimitry Andric   return m_stack_frame_kind == StackFrame::Kind::Artificial;
1202*b5893f02SDimitry Andric }
1203*b5893f02SDimitry Andric 
GetLanguage()1204435933ddSDimitry Andric lldb::LanguageType StackFrame::GetLanguage() {
12059f2f44ceSEd Maste   CompileUnit *cu = GetSymbolContext(eSymbolContextCompUnit).comp_unit;
12069f2f44ceSEd Maste   if (cu)
12079f2f44ceSEd Maste     return cu->GetLanguage();
12089f2f44ceSEd Maste   return lldb::eLanguageTypeUnknown;
12099f2f44ceSEd Maste }
12109f2f44ceSEd Maste 
GuessLanguage()1211435933ddSDimitry Andric lldb::LanguageType StackFrame::GuessLanguage() {
12124bb0738eSEd Maste   LanguageType lang_type = GetLanguage();
12134bb0738eSEd Maste 
1214435933ddSDimitry Andric   if (lang_type == eLanguageTypeUnknown) {
1215f678e45dSDimitry Andric     SymbolContext sc = GetSymbolContext(eSymbolContextFunction
1216f678e45dSDimitry Andric                                         | eSymbolContextSymbol);
1217f678e45dSDimitry Andric     if (sc.function) {
1218f678e45dSDimitry Andric       lang_type = sc.function->GetMangled().GuessLanguage();
1219f678e45dSDimitry Andric     }
1220f678e45dSDimitry Andric     else if (sc.symbol)
1221f678e45dSDimitry Andric     {
1222f678e45dSDimitry Andric       lang_type = sc.symbol->GetMangled().GuessLanguage();
12234bb0738eSEd Maste     }
12244bb0738eSEd Maste   }
12254bb0738eSEd Maste 
12264bb0738eSEd Maste   return lang_type;
12274bb0738eSEd Maste }
12284bb0738eSEd Maste 
1229435933ddSDimitry Andric namespace {
1230435933ddSDimitry Andric std::pair<const Instruction::Operand *, int64_t>
GetBaseExplainingValue(const Instruction::Operand & operand,RegisterContext & register_context,lldb::addr_t value)1231435933ddSDimitry Andric GetBaseExplainingValue(const Instruction::Operand &operand,
1232435933ddSDimitry Andric                        RegisterContext &register_context, lldb::addr_t value) {
1233435933ddSDimitry Andric   switch (operand.m_type) {
1234435933ddSDimitry Andric   case Instruction::Operand::Type::Dereference:
1235435933ddSDimitry Andric   case Instruction::Operand::Type::Immediate:
1236435933ddSDimitry Andric   case Instruction::Operand::Type::Invalid:
1237435933ddSDimitry Andric   case Instruction::Operand::Type::Product:
1238435933ddSDimitry Andric     // These are not currently interesting
1239435933ddSDimitry Andric     return std::make_pair(nullptr, 0);
1240435933ddSDimitry Andric   case Instruction::Operand::Type::Sum: {
1241435933ddSDimitry Andric     const Instruction::Operand *immediate_child = nullptr;
1242435933ddSDimitry Andric     const Instruction::Operand *variable_child = nullptr;
1243435933ddSDimitry Andric     if (operand.m_children[0].m_type == Instruction::Operand::Type::Immediate) {
1244435933ddSDimitry Andric       immediate_child = &operand.m_children[0];
1245435933ddSDimitry Andric       variable_child = &operand.m_children[1];
1246435933ddSDimitry Andric     } else if (operand.m_children[1].m_type ==
1247435933ddSDimitry Andric                Instruction::Operand::Type::Immediate) {
1248435933ddSDimitry Andric       immediate_child = &operand.m_children[1];
1249435933ddSDimitry Andric       variable_child = &operand.m_children[0];
1250435933ddSDimitry Andric     }
1251435933ddSDimitry Andric     if (!immediate_child) {
1252435933ddSDimitry Andric       return std::make_pair(nullptr, 0);
1253435933ddSDimitry Andric     }
1254435933ddSDimitry Andric     lldb::addr_t adjusted_value = value;
1255435933ddSDimitry Andric     if (immediate_child->m_negative) {
1256435933ddSDimitry Andric       adjusted_value += immediate_child->m_immediate;
1257435933ddSDimitry Andric     } else {
1258435933ddSDimitry Andric       adjusted_value -= immediate_child->m_immediate;
1259435933ddSDimitry Andric     }
1260435933ddSDimitry Andric     std::pair<const Instruction::Operand *, int64_t> base_and_offset =
1261435933ddSDimitry Andric         GetBaseExplainingValue(*variable_child, register_context,
1262435933ddSDimitry Andric                                adjusted_value);
1263435933ddSDimitry Andric     if (!base_and_offset.first) {
1264435933ddSDimitry Andric       return std::make_pair(nullptr, 0);
1265435933ddSDimitry Andric     }
1266435933ddSDimitry Andric     if (immediate_child->m_negative) {
1267435933ddSDimitry Andric       base_and_offset.second -= immediate_child->m_immediate;
1268435933ddSDimitry Andric     } else {
1269435933ddSDimitry Andric       base_and_offset.second += immediate_child->m_immediate;
1270435933ddSDimitry Andric     }
1271435933ddSDimitry Andric     return base_and_offset;
1272435933ddSDimitry Andric   }
1273435933ddSDimitry Andric   case Instruction::Operand::Type::Register: {
1274435933ddSDimitry Andric     const RegisterInfo *info =
1275435933ddSDimitry Andric         register_context.GetRegisterInfoByName(operand.m_register.AsCString());
1276435933ddSDimitry Andric     if (!info) {
1277435933ddSDimitry Andric       return std::make_pair(nullptr, 0);
1278435933ddSDimitry Andric     }
1279435933ddSDimitry Andric     RegisterValue reg_value;
1280435933ddSDimitry Andric     if (!register_context.ReadRegister(info, reg_value)) {
1281435933ddSDimitry Andric       return std::make_pair(nullptr, 0);
1282435933ddSDimitry Andric     }
1283435933ddSDimitry Andric     if (reg_value.GetAsUInt64() == value) {
1284435933ddSDimitry Andric       return std::make_pair(&operand, 0);
1285435933ddSDimitry Andric     } else {
1286435933ddSDimitry Andric       return std::make_pair(nullptr, 0);
1287435933ddSDimitry Andric     }
1288435933ddSDimitry Andric   }
1289435933ddSDimitry Andric   }
1290435933ddSDimitry Andric   return std::make_pair(nullptr, 0);
1291435933ddSDimitry Andric }
1292435933ddSDimitry Andric 
1293435933ddSDimitry Andric std::pair<const Instruction::Operand *, int64_t>
GetBaseExplainingDereference(const Instruction::Operand & operand,RegisterContext & register_context,lldb::addr_t addr)1294435933ddSDimitry Andric GetBaseExplainingDereference(const Instruction::Operand &operand,
1295435933ddSDimitry Andric                              RegisterContext &register_context,
1296435933ddSDimitry Andric                              lldb::addr_t addr) {
1297435933ddSDimitry Andric   if (operand.m_type == Instruction::Operand::Type::Dereference) {
1298435933ddSDimitry Andric     return GetBaseExplainingValue(operand.m_children[0], register_context,
1299435933ddSDimitry Andric                                   addr);
1300435933ddSDimitry Andric   }
1301435933ddSDimitry Andric   return std::make_pair(nullptr, 0);
1302435933ddSDimitry Andric }
1303435933ddSDimitry Andric }
1304435933ddSDimitry Andric 
GuessValueForAddress(lldb::addr_t addr)1305435933ddSDimitry Andric lldb::ValueObjectSP StackFrame::GuessValueForAddress(lldb::addr_t addr) {
1306435933ddSDimitry Andric   TargetSP target_sp = CalculateTarget();
1307435933ddSDimitry Andric 
1308435933ddSDimitry Andric   const ArchSpec &target_arch = target_sp->GetArchitecture();
1309435933ddSDimitry Andric 
1310435933ddSDimitry Andric   AddressRange pc_range;
1311435933ddSDimitry Andric   pc_range.GetBaseAddress() = GetFrameCodeAddress();
1312435933ddSDimitry Andric   pc_range.SetByteSize(target_arch.GetMaximumOpcodeByteSize());
1313435933ddSDimitry Andric 
1314435933ddSDimitry Andric   ExecutionContext exe_ctx(shared_from_this());
1315435933ddSDimitry Andric 
1316435933ddSDimitry Andric   const char *plugin_name = nullptr;
1317435933ddSDimitry Andric   const char *flavor = nullptr;
1318435933ddSDimitry Andric   const bool prefer_file_cache = false;
1319435933ddSDimitry Andric 
1320435933ddSDimitry Andric   DisassemblerSP disassembler_sp = Disassembler::DisassembleRange(
1321435933ddSDimitry Andric       target_arch, plugin_name, flavor, exe_ctx, pc_range, prefer_file_cache);
1322435933ddSDimitry Andric 
1323f678e45dSDimitry Andric   if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) {
1324435933ddSDimitry Andric     return ValueObjectSP();
1325435933ddSDimitry Andric   }
1326435933ddSDimitry Andric 
1327435933ddSDimitry Andric   InstructionSP instruction_sp =
1328435933ddSDimitry Andric       disassembler_sp->GetInstructionList().GetInstructionAtIndex(0);
1329435933ddSDimitry Andric 
1330435933ddSDimitry Andric   llvm::SmallVector<Instruction::Operand, 3> operands;
1331435933ddSDimitry Andric 
1332435933ddSDimitry Andric   if (!instruction_sp->ParseOperands(operands)) {
1333435933ddSDimitry Andric     return ValueObjectSP();
1334435933ddSDimitry Andric   }
1335435933ddSDimitry Andric 
1336435933ddSDimitry Andric   RegisterContextSP register_context_sp = GetRegisterContext();
1337435933ddSDimitry Andric 
1338435933ddSDimitry Andric   if (!register_context_sp) {
1339435933ddSDimitry Andric     return ValueObjectSP();
1340435933ddSDimitry Andric   }
1341435933ddSDimitry Andric 
1342435933ddSDimitry Andric   for (const Instruction::Operand &operand : operands) {
1343435933ddSDimitry Andric     std::pair<const Instruction::Operand *, int64_t> base_and_offset =
1344435933ddSDimitry Andric         GetBaseExplainingDereference(operand, *register_context_sp, addr);
1345435933ddSDimitry Andric 
1346435933ddSDimitry Andric     if (!base_and_offset.first) {
1347435933ddSDimitry Andric       continue;
1348435933ddSDimitry Andric     }
1349435933ddSDimitry Andric 
1350435933ddSDimitry Andric     switch (base_and_offset.first->m_type) {
1351435933ddSDimitry Andric     case Instruction::Operand::Type::Immediate: {
1352435933ddSDimitry Andric       lldb_private::Address addr;
1353435933ddSDimitry Andric       if (target_sp->ResolveLoadAddress(base_and_offset.first->m_immediate +
1354435933ddSDimitry Andric                                             base_and_offset.second,
1355435933ddSDimitry Andric                                         addr)) {
1356435933ddSDimitry Andric         TypeSystem *c_type_system =
1357435933ddSDimitry Andric             target_sp->GetScratchTypeSystemForLanguage(nullptr, eLanguageTypeC);
1358435933ddSDimitry Andric         if (!c_type_system) {
1359435933ddSDimitry Andric           return ValueObjectSP();
1360435933ddSDimitry Andric         } else {
1361435933ddSDimitry Andric           CompilerType void_ptr_type =
1362435933ddSDimitry Andric               c_type_system
1363435933ddSDimitry Andric                   ->GetBasicTypeFromAST(lldb::BasicType::eBasicTypeChar)
1364435933ddSDimitry Andric                   .GetPointerType();
1365435933ddSDimitry Andric           return ValueObjectMemory::Create(this, "", addr, void_ptr_type);
1366435933ddSDimitry Andric         }
1367435933ddSDimitry Andric       } else {
1368435933ddSDimitry Andric         return ValueObjectSP();
1369435933ddSDimitry Andric       }
1370435933ddSDimitry Andric       break;
1371435933ddSDimitry Andric     }
1372435933ddSDimitry Andric     case Instruction::Operand::Type::Register: {
1373435933ddSDimitry Andric       return GuessValueForRegisterAndOffset(base_and_offset.first->m_register,
1374435933ddSDimitry Andric                                             base_and_offset.second);
1375435933ddSDimitry Andric     }
1376435933ddSDimitry Andric     default:
1377435933ddSDimitry Andric       return ValueObjectSP();
1378435933ddSDimitry Andric     }
1379435933ddSDimitry Andric   }
1380435933ddSDimitry Andric 
1381435933ddSDimitry Andric   return ValueObjectSP();
1382435933ddSDimitry Andric }
1383435933ddSDimitry Andric 
1384435933ddSDimitry Andric namespace {
GetValueForOffset(StackFrame & frame,ValueObjectSP & parent,int64_t offset)1385435933ddSDimitry Andric ValueObjectSP GetValueForOffset(StackFrame &frame, ValueObjectSP &parent,
1386435933ddSDimitry Andric                                 int64_t offset) {
1387435933ddSDimitry Andric   if (offset < 0 || uint64_t(offset) >= parent->GetByteSize()) {
1388435933ddSDimitry Andric     return ValueObjectSP();
1389435933ddSDimitry Andric   }
1390435933ddSDimitry Andric 
1391435933ddSDimitry Andric   if (parent->IsPointerOrReferenceType()) {
1392435933ddSDimitry Andric     return parent;
1393435933ddSDimitry Andric   }
1394435933ddSDimitry Andric 
1395435933ddSDimitry Andric   for (int ci = 0, ce = parent->GetNumChildren(); ci != ce; ++ci) {
1396435933ddSDimitry Andric     const bool can_create = true;
1397435933ddSDimitry Andric     ValueObjectSP child_sp = parent->GetChildAtIndex(ci, can_create);
1398435933ddSDimitry Andric 
1399435933ddSDimitry Andric     if (!child_sp) {
1400435933ddSDimitry Andric       return ValueObjectSP();
1401435933ddSDimitry Andric     }
1402435933ddSDimitry Andric 
1403435933ddSDimitry Andric     int64_t child_offset = child_sp->GetByteOffset();
1404435933ddSDimitry Andric     int64_t child_size = child_sp->GetByteSize();
1405435933ddSDimitry Andric 
1406435933ddSDimitry Andric     if (offset >= child_offset && offset < (child_offset + child_size)) {
1407435933ddSDimitry Andric       return GetValueForOffset(frame, child_sp, offset - child_offset);
1408435933ddSDimitry Andric     }
1409435933ddSDimitry Andric   }
1410435933ddSDimitry Andric 
1411435933ddSDimitry Andric   if (offset == 0) {
1412435933ddSDimitry Andric     return parent;
1413435933ddSDimitry Andric   } else {
1414435933ddSDimitry Andric     return ValueObjectSP();
1415435933ddSDimitry Andric   }
1416435933ddSDimitry Andric }
1417435933ddSDimitry Andric 
GetValueForDereferincingOffset(StackFrame & frame,ValueObjectSP & base,int64_t offset)1418435933ddSDimitry Andric ValueObjectSP GetValueForDereferincingOffset(StackFrame &frame,
1419435933ddSDimitry Andric                                              ValueObjectSP &base,
1420435933ddSDimitry Andric                                              int64_t offset) {
1421435933ddSDimitry Andric   // base is a pointer to something
14224ba319b5SDimitry Andric   // offset is the thing to add to the pointer We return the most sensible
14234ba319b5SDimitry Andric   // ValueObject for the result of *(base+offset)
1424435933ddSDimitry Andric 
1425435933ddSDimitry Andric   if (!base->IsPointerOrReferenceType()) {
1426435933ddSDimitry Andric     return ValueObjectSP();
1427435933ddSDimitry Andric   }
1428435933ddSDimitry Andric 
14295517e702SDimitry Andric   Status error;
1430435933ddSDimitry Andric   ValueObjectSP pointee = base->Dereference(error);
1431435933ddSDimitry Andric 
1432435933ddSDimitry Andric   if (!pointee) {
1433435933ddSDimitry Andric     return ValueObjectSP();
1434435933ddSDimitry Andric   }
1435435933ddSDimitry Andric 
1436435933ddSDimitry Andric   if (offset >= 0 && uint64_t(offset) >= pointee->GetByteSize()) {
1437435933ddSDimitry Andric     int64_t index = offset / pointee->GetByteSize();
1438435933ddSDimitry Andric     offset = offset % pointee->GetByteSize();
1439435933ddSDimitry Andric     const bool can_create = true;
1440435933ddSDimitry Andric     pointee = base->GetSyntheticArrayMember(index, can_create);
1441435933ddSDimitry Andric   }
1442435933ddSDimitry Andric 
1443435933ddSDimitry Andric   if (!pointee || error.Fail()) {
1444435933ddSDimitry Andric     return ValueObjectSP();
1445435933ddSDimitry Andric   }
1446435933ddSDimitry Andric 
1447435933ddSDimitry Andric   return GetValueForOffset(frame, pointee, offset);
1448435933ddSDimitry Andric }
1449435933ddSDimitry Andric 
1450435933ddSDimitry Andric //------------------------------------------------------------------
1451435933ddSDimitry Andric /// Attempt to reconstruct the ValueObject for the address contained in a
1452435933ddSDimitry Andric /// given register plus an offset.
1453435933ddSDimitry Andric ///
1454435933ddSDimitry Andric /// @params [in] frame
1455435933ddSDimitry Andric ///   The current stack frame.
1456435933ddSDimitry Andric ///
1457435933ddSDimitry Andric /// @params [in] reg
1458435933ddSDimitry Andric ///   The register.
1459435933ddSDimitry Andric ///
1460435933ddSDimitry Andric /// @params [in] offset
1461435933ddSDimitry Andric ///   The offset from the register.
1462435933ddSDimitry Andric ///
1463435933ddSDimitry Andric /// @param [in] disassembler
1464435933ddSDimitry Andric ///   A disassembler containing instructions valid up to the current PC.
1465435933ddSDimitry Andric ///
1466435933ddSDimitry Andric /// @param [in] variables
1467435933ddSDimitry Andric ///   The variable list from the current frame,
1468435933ddSDimitry Andric ///
1469435933ddSDimitry Andric /// @param [in] pc
1470435933ddSDimitry Andric ///   The program counter for the instruction considered the 'user'.
1471435933ddSDimitry Andric ///
1472435933ddSDimitry Andric /// @return
1473435933ddSDimitry Andric ///   A string describing the base for the ExpressionPath.  This could be a
1474435933ddSDimitry Andric ///     variable, a register value, an argument, or a function return value.
1475435933ddSDimitry Andric ///   The ValueObject if found.  If valid, it has a valid ExpressionPath.
1476435933ddSDimitry Andric //------------------------------------------------------------------
DoGuessValueAt(StackFrame & frame,ConstString reg,int64_t offset,Disassembler & disassembler,VariableList & variables,const Address & pc)1477435933ddSDimitry Andric lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg,
1478435933ddSDimitry Andric                                    int64_t offset, Disassembler &disassembler,
1479435933ddSDimitry Andric                                    VariableList &variables, const Address &pc) {
1480435933ddSDimitry Andric   // Example of operation for Intel:
1481435933ddSDimitry Andric   //
1482435933ddSDimitry Andric   // +14: movq   -0x8(%rbp), %rdi
1483435933ddSDimitry Andric   // +18: movq   0x8(%rdi), %rdi
1484435933ddSDimitry Andric   // +22: addl   0x4(%rdi), %eax
1485435933ddSDimitry Andric   //
1486435933ddSDimitry Andric   // f, a pointer to a struct, is known to be at -0x8(%rbp).
1487435933ddSDimitry Andric   //
14884ba319b5SDimitry Andric   // DoGuessValueAt(frame, rdi, 4, dis, vars, 0x22) finds the instruction at
14894ba319b5SDimitry Andric   // +18 that assigns to rdi, and calls itself recursively for that dereference
1490435933ddSDimitry Andric   //   DoGuessValueAt(frame, rdi, 8, dis, vars, 0x18) finds the instruction at
1491435933ddSDimitry Andric   //   +14 that assigns to rdi, and calls itself recursively for that
1492435933ddSDimitry Andric   //   derefernece
1493435933ddSDimitry Andric   //     DoGuessValueAt(frame, rbp, -8, dis, vars, 0x14) finds "f" in the
1494435933ddSDimitry Andric   //     variable list.
1495435933ddSDimitry Andric   //     Returns a ValueObject for f.  (That's what was stored at rbp-8 at +14)
1496435933ddSDimitry Andric   //   Returns a ValueObject for *(f+8) or f->b (That's what was stored at rdi+8
1497435933ddSDimitry Andric   //   at +18)
1498435933ddSDimitry Andric   // Returns a ValueObject for *(f->b+4) or f->b->a (That's what was stored at
1499435933ddSDimitry Andric   // rdi+4 at +22)
1500435933ddSDimitry Andric 
1501435933ddSDimitry Andric   // First, check the variable list to see if anything is at the specified
1502435933ddSDimitry Andric   // location.
1503435933ddSDimitry Andric 
1504435933ddSDimitry Andric   using namespace OperandMatchers;
1505435933ddSDimitry Andric 
1506435933ddSDimitry Andric   const RegisterInfo *reg_info =
1507435933ddSDimitry Andric       frame.GetRegisterContext()->GetRegisterInfoByName(reg.AsCString());
1508435933ddSDimitry Andric   if (!reg_info) {
1509435933ddSDimitry Andric     return ValueObjectSP();
1510435933ddSDimitry Andric   }
1511435933ddSDimitry Andric 
1512435933ddSDimitry Andric   Instruction::Operand op =
1513435933ddSDimitry Andric       offset ? Instruction::Operand::BuildDereference(
1514435933ddSDimitry Andric                    Instruction::Operand::BuildSum(
1515435933ddSDimitry Andric                        Instruction::Operand::BuildRegister(reg),
1516435933ddSDimitry Andric                        Instruction::Operand::BuildImmediate(offset)))
1517435933ddSDimitry Andric              : Instruction::Operand::BuildDereference(
1518435933ddSDimitry Andric                    Instruction::Operand::BuildRegister(reg));
1519435933ddSDimitry Andric 
1520435933ddSDimitry Andric   for (size_t vi = 0, ve = variables.GetSize(); vi != ve; ++vi) {
1521435933ddSDimitry Andric     VariableSP var_sp = variables.GetVariableAtIndex(vi);
1522435933ddSDimitry Andric     if (var_sp->LocationExpression().MatchesOperand(frame, op)) {
1523435933ddSDimitry Andric       return frame.GetValueObjectForFrameVariable(var_sp, eNoDynamicValues);
1524435933ddSDimitry Andric     }
1525435933ddSDimitry Andric   }
1526435933ddSDimitry Andric 
1527435933ddSDimitry Andric   const uint32_t current_inst =
1528435933ddSDimitry Andric       disassembler.GetInstructionList().GetIndexOfInstructionAtAddress(pc);
1529435933ddSDimitry Andric   if (current_inst == UINT32_MAX) {
1530435933ddSDimitry Andric     return ValueObjectSP();
1531435933ddSDimitry Andric   }
1532435933ddSDimitry Andric 
1533435933ddSDimitry Andric   for (uint32_t ii = current_inst - 1; ii != (uint32_t)-1; --ii) {
1534435933ddSDimitry Andric     // This is not an exact algorithm, and it sacrifices accuracy for
15354ba319b5SDimitry Andric     // generality.  Recognizing "mov" and "ld" instructions –– and which
15364ba319b5SDimitry Andric     // are their source and destination operands -- is something the
15374ba319b5SDimitry Andric     // disassembler should do for us.
1538435933ddSDimitry Andric     InstructionSP instruction_sp =
1539435933ddSDimitry Andric         disassembler.GetInstructionList().GetInstructionAtIndex(ii);
1540435933ddSDimitry Andric 
1541435933ddSDimitry Andric     if (instruction_sp->IsCall()) {
1542435933ddSDimitry Andric       ABISP abi_sp = frame.CalculateProcess()->GetABI();
1543435933ddSDimitry Andric       if (!abi_sp) {
1544435933ddSDimitry Andric         continue;
1545435933ddSDimitry Andric       }
1546435933ddSDimitry Andric 
1547435933ddSDimitry Andric       const char *return_register_name;
1548435933ddSDimitry Andric       if (!abi_sp->GetPointerReturnRegister(return_register_name)) {
1549435933ddSDimitry Andric         continue;
1550435933ddSDimitry Andric       }
1551435933ddSDimitry Andric 
1552435933ddSDimitry Andric       const RegisterInfo *return_register_info =
1553435933ddSDimitry Andric           frame.GetRegisterContext()->GetRegisterInfoByName(
1554435933ddSDimitry Andric               return_register_name);
1555435933ddSDimitry Andric       if (!return_register_info) {
1556435933ddSDimitry Andric         continue;
1557435933ddSDimitry Andric       }
1558435933ddSDimitry Andric 
1559435933ddSDimitry Andric       int64_t offset = 0;
1560435933ddSDimitry Andric 
1561435933ddSDimitry Andric       if (!MatchUnaryOp(MatchOpType(Instruction::Operand::Type::Dereference),
1562435933ddSDimitry Andric                         MatchRegOp(*return_register_info))(op) &&
1563435933ddSDimitry Andric           !MatchUnaryOp(
1564435933ddSDimitry Andric               MatchOpType(Instruction::Operand::Type::Dereference),
1565435933ddSDimitry Andric               MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum),
1566435933ddSDimitry Andric                             MatchRegOp(*return_register_info),
1567435933ddSDimitry Andric                             FetchImmOp(offset)))(op)) {
1568435933ddSDimitry Andric         continue;
1569435933ddSDimitry Andric       }
1570435933ddSDimitry Andric 
1571435933ddSDimitry Andric       llvm::SmallVector<Instruction::Operand, 1> operands;
1572435933ddSDimitry Andric       if (!instruction_sp->ParseOperands(operands) || operands.size() != 1) {
1573435933ddSDimitry Andric         continue;
1574435933ddSDimitry Andric       }
1575435933ddSDimitry Andric 
1576435933ddSDimitry Andric       switch (operands[0].m_type) {
1577435933ddSDimitry Andric       default:
1578435933ddSDimitry Andric         break;
1579435933ddSDimitry Andric       case Instruction::Operand::Type::Immediate: {
1580435933ddSDimitry Andric         SymbolContext sc;
1581435933ddSDimitry Andric         Address load_address;
1582435933ddSDimitry Andric         if (!frame.CalculateTarget()->ResolveLoadAddress(
1583435933ddSDimitry Andric                 operands[0].m_immediate, load_address)) {
1584435933ddSDimitry Andric           break;
1585435933ddSDimitry Andric         }
1586435933ddSDimitry Andric         frame.CalculateTarget()->GetImages().ResolveSymbolContextForAddress(
1587435933ddSDimitry Andric             load_address, eSymbolContextFunction, sc);
1588435933ddSDimitry Andric         if (!sc.function) {
1589435933ddSDimitry Andric           break;
1590435933ddSDimitry Andric         }
1591435933ddSDimitry Andric         CompilerType function_type = sc.function->GetCompilerType();
1592435933ddSDimitry Andric         if (!function_type.IsFunctionType()) {
1593435933ddSDimitry Andric           break;
1594435933ddSDimitry Andric         }
1595435933ddSDimitry Andric         CompilerType return_type = function_type.GetFunctionReturnType();
1596435933ddSDimitry Andric         RegisterValue return_value;
1597435933ddSDimitry Andric         if (!frame.GetRegisterContext()->ReadRegister(return_register_info,
1598435933ddSDimitry Andric                                                       return_value)) {
1599435933ddSDimitry Andric           break;
1600435933ddSDimitry Andric         }
1601435933ddSDimitry Andric         std::string name_str(
1602435933ddSDimitry Andric             sc.function->GetName().AsCString("<unknown function>"));
1603435933ddSDimitry Andric         name_str.append("()");
1604435933ddSDimitry Andric         Address return_value_address(return_value.GetAsUInt64());
1605435933ddSDimitry Andric         ValueObjectSP return_value_sp = ValueObjectMemory::Create(
1606435933ddSDimitry Andric             &frame, name_str, return_value_address, return_type);
1607435933ddSDimitry Andric         return GetValueForDereferincingOffset(frame, return_value_sp, offset);
1608435933ddSDimitry Andric       }
1609435933ddSDimitry Andric       }
1610435933ddSDimitry Andric 
1611435933ddSDimitry Andric       continue;
1612435933ddSDimitry Andric     }
1613435933ddSDimitry Andric 
1614435933ddSDimitry Andric     llvm::SmallVector<Instruction::Operand, 2> operands;
1615435933ddSDimitry Andric     if (!instruction_sp->ParseOperands(operands) || operands.size() != 2) {
1616435933ddSDimitry Andric       continue;
1617435933ddSDimitry Andric     }
1618435933ddSDimitry Andric 
1619435933ddSDimitry Andric     Instruction::Operand *origin_operand = nullptr;
1620435933ddSDimitry Andric     auto clobbered_reg_matcher = [reg_info](const Instruction::Operand &op) {
1621435933ddSDimitry Andric       return MatchRegOp(*reg_info)(op) && op.m_clobbered;
1622435933ddSDimitry Andric     };
1623435933ddSDimitry Andric 
1624435933ddSDimitry Andric     if (clobbered_reg_matcher(operands[0])) {
1625435933ddSDimitry Andric       origin_operand = &operands[1];
1626435933ddSDimitry Andric     }
1627435933ddSDimitry Andric     else if (clobbered_reg_matcher(operands[1])) {
1628435933ddSDimitry Andric       origin_operand = &operands[0];
1629435933ddSDimitry Andric     }
1630435933ddSDimitry Andric     else {
1631435933ddSDimitry Andric       continue;
1632435933ddSDimitry Andric     }
1633435933ddSDimitry Andric 
1634435933ddSDimitry Andric     // We have an origin operand.  Can we track its value down?
1635435933ddSDimitry Andric     ValueObjectSP source_path;
1636435933ddSDimitry Andric     ConstString origin_register;
1637435933ddSDimitry Andric     int64_t origin_offset = 0;
1638435933ddSDimitry Andric 
1639435933ddSDimitry Andric     if (FetchRegOp(origin_register)(*origin_operand)) {
1640435933ddSDimitry Andric       source_path = DoGuessValueAt(frame, origin_register, 0, disassembler,
1641435933ddSDimitry Andric                                    variables, instruction_sp->GetAddress());
1642435933ddSDimitry Andric     } else if (MatchUnaryOp(
1643435933ddSDimitry Andric                    MatchOpType(Instruction::Operand::Type::Dereference),
1644435933ddSDimitry Andric                    FetchRegOp(origin_register))(*origin_operand) ||
1645435933ddSDimitry Andric                MatchUnaryOp(
1646435933ddSDimitry Andric                    MatchOpType(Instruction::Operand::Type::Dereference),
1647435933ddSDimitry Andric                    MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum),
1648435933ddSDimitry Andric                                  FetchRegOp(origin_register),
1649435933ddSDimitry Andric                                  FetchImmOp(origin_offset)))(*origin_operand)) {
1650435933ddSDimitry Andric       source_path =
1651435933ddSDimitry Andric           DoGuessValueAt(frame, origin_register, origin_offset, disassembler,
1652435933ddSDimitry Andric                          variables, instruction_sp->GetAddress());
1653435933ddSDimitry Andric       if (!source_path) {
1654435933ddSDimitry Andric         continue;
1655435933ddSDimitry Andric       }
1656435933ddSDimitry Andric       source_path =
1657435933ddSDimitry Andric           GetValueForDereferincingOffset(frame, source_path, offset);
1658435933ddSDimitry Andric     }
1659435933ddSDimitry Andric 
1660435933ddSDimitry Andric     if (source_path) {
1661435933ddSDimitry Andric       return source_path;
1662435933ddSDimitry Andric     }
1663435933ddSDimitry Andric   }
1664435933ddSDimitry Andric 
1665435933ddSDimitry Andric   return ValueObjectSP();
1666435933ddSDimitry Andric }
1667435933ddSDimitry Andric }
1668435933ddSDimitry Andric 
GuessValueForRegisterAndOffset(ConstString reg,int64_t offset)1669435933ddSDimitry Andric lldb::ValueObjectSP StackFrame::GuessValueForRegisterAndOffset(ConstString reg,
1670435933ddSDimitry Andric                                                                int64_t offset) {
1671435933ddSDimitry Andric   TargetSP target_sp = CalculateTarget();
1672435933ddSDimitry Andric 
1673435933ddSDimitry Andric   const ArchSpec &target_arch = target_sp->GetArchitecture();
1674435933ddSDimitry Andric 
1675435933ddSDimitry Andric   Block *frame_block = GetFrameBlock();
1676435933ddSDimitry Andric 
1677435933ddSDimitry Andric   if (!frame_block) {
1678435933ddSDimitry Andric     return ValueObjectSP();
1679435933ddSDimitry Andric   }
1680435933ddSDimitry Andric 
1681435933ddSDimitry Andric   Function *function = frame_block->CalculateSymbolContextFunction();
1682435933ddSDimitry Andric   if (!function) {
1683435933ddSDimitry Andric     return ValueObjectSP();
1684435933ddSDimitry Andric   }
1685435933ddSDimitry Andric 
1686435933ddSDimitry Andric   AddressRange pc_range = function->GetAddressRange();
1687435933ddSDimitry Andric 
1688435933ddSDimitry Andric   if (GetFrameCodeAddress().GetFileAddress() <
1689435933ddSDimitry Andric           pc_range.GetBaseAddress().GetFileAddress() ||
1690435933ddSDimitry Andric       GetFrameCodeAddress().GetFileAddress() -
1691435933ddSDimitry Andric               pc_range.GetBaseAddress().GetFileAddress() >=
1692435933ddSDimitry Andric           pc_range.GetByteSize()) {
1693435933ddSDimitry Andric     return ValueObjectSP();
1694435933ddSDimitry Andric   }
1695435933ddSDimitry Andric 
1696435933ddSDimitry Andric   ExecutionContext exe_ctx(shared_from_this());
1697435933ddSDimitry Andric 
1698435933ddSDimitry Andric   const char *plugin_name = nullptr;
1699435933ddSDimitry Andric   const char *flavor = nullptr;
1700435933ddSDimitry Andric   const bool prefer_file_cache = false;
1701435933ddSDimitry Andric   DisassemblerSP disassembler_sp = Disassembler::DisassembleRange(
1702435933ddSDimitry Andric       target_arch, plugin_name, flavor, exe_ctx, pc_range, prefer_file_cache);
1703435933ddSDimitry Andric 
1704435933ddSDimitry Andric   if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) {
1705435933ddSDimitry Andric     return ValueObjectSP();
1706435933ddSDimitry Andric   }
1707435933ddSDimitry Andric 
1708435933ddSDimitry Andric   const bool get_file_globals = false;
1709435933ddSDimitry Andric   VariableList *variables = GetVariableList(get_file_globals);
1710435933ddSDimitry Andric 
1711435933ddSDimitry Andric   if (!variables) {
1712435933ddSDimitry Andric     return ValueObjectSP();
1713435933ddSDimitry Andric   }
1714435933ddSDimitry Andric 
1715435933ddSDimitry Andric   return DoGuessValueAt(*this, reg, offset, *disassembler_sp, *variables,
1716435933ddSDimitry Andric                         GetFrameCodeAddress());
1717435933ddSDimitry Andric }
1718435933ddSDimitry Andric 
FindVariable(ConstString name)1719*b5893f02SDimitry Andric lldb::ValueObjectSP StackFrame::FindVariable(ConstString name) {
1720*b5893f02SDimitry Andric   ValueObjectSP value_sp;
1721*b5893f02SDimitry Andric 
1722*b5893f02SDimitry Andric   if (!name)
1723*b5893f02SDimitry Andric     return value_sp;
1724*b5893f02SDimitry Andric 
1725*b5893f02SDimitry Andric   TargetSP target_sp = CalculateTarget();
1726*b5893f02SDimitry Andric   ProcessSP process_sp = CalculateProcess();
1727*b5893f02SDimitry Andric 
1728*b5893f02SDimitry Andric   if (!target_sp && !process_sp)
1729*b5893f02SDimitry Andric     return value_sp;
1730*b5893f02SDimitry Andric 
1731*b5893f02SDimitry Andric   VariableList variable_list;
1732*b5893f02SDimitry Andric   VariableSP var_sp;
1733*b5893f02SDimitry Andric   SymbolContext sc(GetSymbolContext(eSymbolContextBlock));
1734*b5893f02SDimitry Andric 
1735*b5893f02SDimitry Andric   if (sc.block) {
1736*b5893f02SDimitry Andric     const bool can_create = true;
1737*b5893f02SDimitry Andric     const bool get_parent_variables = true;
1738*b5893f02SDimitry Andric     const bool stop_if_block_is_inlined_function = true;
1739*b5893f02SDimitry Andric 
1740*b5893f02SDimitry Andric     if (sc.block->AppendVariables(
1741*b5893f02SDimitry Andric             can_create, get_parent_variables, stop_if_block_is_inlined_function,
1742*b5893f02SDimitry Andric             [this](Variable *v) { return v->IsInScope(this); },
1743*b5893f02SDimitry Andric             &variable_list)) {
1744*b5893f02SDimitry Andric       var_sp = variable_list.FindVariable(name);
1745*b5893f02SDimitry Andric     }
1746*b5893f02SDimitry Andric 
1747*b5893f02SDimitry Andric     if (var_sp)
1748*b5893f02SDimitry Andric       value_sp = GetValueObjectForFrameVariable(var_sp, eNoDynamicValues);
1749*b5893f02SDimitry Andric   }
1750*b5893f02SDimitry Andric 
1751*b5893f02SDimitry Andric   return value_sp;
1752*b5893f02SDimitry Andric }
1753*b5893f02SDimitry Andric 
CalculateTarget()1754435933ddSDimitry Andric TargetSP StackFrame::CalculateTarget() {
1755ac7ddfbfSEd Maste   TargetSP target_sp;
1756ac7ddfbfSEd Maste   ThreadSP thread_sp(GetThread());
1757435933ddSDimitry Andric   if (thread_sp) {
1758ac7ddfbfSEd Maste     ProcessSP process_sp(thread_sp->CalculateProcess());
1759ac7ddfbfSEd Maste     if (process_sp)
1760ac7ddfbfSEd Maste       target_sp = process_sp->CalculateTarget();
1761ac7ddfbfSEd Maste   }
1762ac7ddfbfSEd Maste   return target_sp;
1763ac7ddfbfSEd Maste }
1764ac7ddfbfSEd Maste 
CalculateProcess()1765435933ddSDimitry Andric ProcessSP StackFrame::CalculateProcess() {
1766ac7ddfbfSEd Maste   ProcessSP process_sp;
1767ac7ddfbfSEd Maste   ThreadSP thread_sp(GetThread());
1768ac7ddfbfSEd Maste   if (thread_sp)
1769ac7ddfbfSEd Maste     process_sp = thread_sp->CalculateProcess();
1770ac7ddfbfSEd Maste   return process_sp;
1771ac7ddfbfSEd Maste }
1772ac7ddfbfSEd Maste 
CalculateThread()1773435933ddSDimitry Andric ThreadSP StackFrame::CalculateThread() { return GetThread(); }
1774ac7ddfbfSEd Maste 
CalculateStackFrame()1775435933ddSDimitry Andric StackFrameSP StackFrame::CalculateStackFrame() { return shared_from_this(); }
1776ac7ddfbfSEd Maste 
CalculateExecutionContext(ExecutionContext & exe_ctx)1777435933ddSDimitry Andric void StackFrame::CalculateExecutionContext(ExecutionContext &exe_ctx) {
1778ac7ddfbfSEd Maste   exe_ctx.SetContext(shared_from_this());
1779ac7ddfbfSEd Maste }
1780ac7ddfbfSEd Maste 
DumpUsingSettingsFormat(Stream * strm,bool show_unique,const char * frame_marker)178124d58133SDimitry Andric void StackFrame::DumpUsingSettingsFormat(Stream *strm, bool show_unique,
1782435933ddSDimitry Andric                                          const char *frame_marker) {
17834bb0738eSEd Maste   if (strm == nullptr)
1784ac7ddfbfSEd Maste     return;
1785ac7ddfbfSEd Maste 
1786ac7ddfbfSEd Maste   GetSymbolContext(eSymbolContextEverything);
1787ac7ddfbfSEd Maste   ExecutionContext exe_ctx(shared_from_this());
1788ac7ddfbfSEd Maste   StreamString s;
178935617911SEd Maste 
179035617911SEd Maste   if (frame_marker)
179135617911SEd Maste     s.PutCString(frame_marker);
179235617911SEd Maste 
17934bb0738eSEd Maste   const FormatEntity::Entry *frame_format = nullptr;
1794ac7ddfbfSEd Maste   Target *target = exe_ctx.GetTargetPtr();
179524d58133SDimitry Andric   if (target) {
179624d58133SDimitry Andric     if (show_unique) {
179724d58133SDimitry Andric       frame_format = target->GetDebugger().GetFrameFormatUnique();
179824d58133SDimitry Andric     } else {
1799ac7ddfbfSEd Maste       frame_format = target->GetDebugger().GetFrameFormat();
180024d58133SDimitry Andric     }
180124d58133SDimitry Andric   }
1802435933ddSDimitry Andric   if (frame_format && FormatEntity::Format(*frame_format, s, &m_sc, &exe_ctx,
1803435933ddSDimitry Andric                                            nullptr, nullptr, false, false)) {
1804435933ddSDimitry Andric     strm->PutCString(s.GetString());
1805435933ddSDimitry Andric   } else {
1806ac7ddfbfSEd Maste     Dump(strm, true, false);
1807ac7ddfbfSEd Maste     strm->EOL();
1808ac7ddfbfSEd Maste   }
1809ac7ddfbfSEd Maste }
1810ac7ddfbfSEd Maste 
Dump(Stream * strm,bool show_frame_index,bool show_fullpaths)1811435933ddSDimitry Andric void StackFrame::Dump(Stream *strm, bool show_frame_index,
1812435933ddSDimitry Andric                       bool show_fullpaths) {
18134bb0738eSEd Maste   if (strm == nullptr)
1814ac7ddfbfSEd Maste     return;
1815ac7ddfbfSEd Maste 
1816ac7ddfbfSEd Maste   if (show_frame_index)
1817ac7ddfbfSEd Maste     strm->Printf("frame #%u: ", m_frame_index);
1818ac7ddfbfSEd Maste   ExecutionContext exe_ctx(shared_from_this());
1819ac7ddfbfSEd Maste   Target *target = exe_ctx.GetTargetPtr();
1820ac7ddfbfSEd Maste   strm->Printf("0x%0*" PRIx64 " ",
1821435933ddSDimitry Andric                target ? (target->GetArchitecture().GetAddressByteSize() * 2)
1822435933ddSDimitry Andric                       : 16,
1823ac7ddfbfSEd Maste                GetFrameCodeAddress().GetLoadAddress(target));
1824ac7ddfbfSEd Maste   GetSymbolContext(eSymbolContextEverything);
1825ac7ddfbfSEd Maste   const bool show_module = true;
1826ac7ddfbfSEd Maste   const bool show_inline = true;
18277aa51b79SEd Maste   const bool show_function_arguments = true;
18281c3bbb01SEd Maste   const bool show_function_name = true;
1829435933ddSDimitry Andric   m_sc.DumpStopContext(strm, exe_ctx.GetBestExecutionContextScope(),
1830435933ddSDimitry Andric                        GetFrameCodeAddress(), show_fullpaths, show_module,
1831435933ddSDimitry Andric                        show_inline, show_function_arguments,
18321c3bbb01SEd Maste                        show_function_name);
1833ac7ddfbfSEd Maste }
1834ac7ddfbfSEd Maste 
UpdateCurrentFrameFromPreviousFrame(StackFrame & prev_frame)1835435933ddSDimitry Andric void StackFrame::UpdateCurrentFrameFromPreviousFrame(StackFrame &prev_frame) {
18364bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
1837435933ddSDimitry Andric   assert(GetStackID() ==
1838435933ddSDimitry Andric          prev_frame.GetStackID()); // TODO: remove this after some testing
1839ac7ddfbfSEd Maste   m_variable_list_sp = prev_frame.m_variable_list_sp;
1840ac7ddfbfSEd Maste   m_variable_list_value_objects.Swap(prev_frame.m_variable_list_value_objects);
1841435933ddSDimitry Andric   if (!m_disassembly.GetString().empty()) {
1842435933ddSDimitry Andric     m_disassembly.Clear();
1843435933ddSDimitry Andric     m_disassembly.PutCString(prev_frame.m_disassembly.GetString());
1844435933ddSDimitry Andric   }
1845ac7ddfbfSEd Maste }
1846ac7ddfbfSEd Maste 
UpdatePreviousFrameFromCurrentFrame(StackFrame & curr_frame)1847435933ddSDimitry Andric void StackFrame::UpdatePreviousFrameFromCurrentFrame(StackFrame &curr_frame) {
18484bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
1849435933ddSDimitry Andric   assert(GetStackID() ==
1850435933ddSDimitry Andric          curr_frame.GetStackID());     // TODO: remove this after some testing
1851ac7ddfbfSEd Maste   m_id.SetPC(curr_frame.m_id.GetPC()); // Update the Stack ID PC value
1852ac7ddfbfSEd Maste   assert(GetThread() == curr_frame.GetThread());
1853ac7ddfbfSEd Maste   m_frame_index = curr_frame.m_frame_index;
1854ac7ddfbfSEd Maste   m_concrete_frame_index = curr_frame.m_concrete_frame_index;
1855ac7ddfbfSEd Maste   m_reg_context_sp = curr_frame.m_reg_context_sp;
1856ac7ddfbfSEd Maste   m_frame_code_addr = curr_frame.m_frame_code_addr;
1857435933ddSDimitry Andric   assert(!m_sc.target_sp || !curr_frame.m_sc.target_sp ||
1858435933ddSDimitry Andric          m_sc.target_sp.get() == curr_frame.m_sc.target_sp.get());
1859435933ddSDimitry Andric   assert(!m_sc.module_sp || !curr_frame.m_sc.module_sp ||
1860435933ddSDimitry Andric          m_sc.module_sp.get() == curr_frame.m_sc.module_sp.get());
1861435933ddSDimitry Andric   assert(m_sc.comp_unit == nullptr || curr_frame.m_sc.comp_unit == nullptr ||
1862435933ddSDimitry Andric          m_sc.comp_unit == curr_frame.m_sc.comp_unit);
1863435933ddSDimitry Andric   assert(m_sc.function == nullptr || curr_frame.m_sc.function == nullptr ||
1864435933ddSDimitry Andric          m_sc.function == curr_frame.m_sc.function);
1865ac7ddfbfSEd Maste   m_sc = curr_frame.m_sc;
1866ac7ddfbfSEd Maste   m_flags.Clear(GOT_FRAME_BASE | eSymbolContextEverything);
1867ac7ddfbfSEd Maste   m_flags.Set(m_sc.GetResolvedMask());
1868ac7ddfbfSEd Maste   m_frame_base.Clear();
1869ac7ddfbfSEd Maste   m_frame_base_error.Clear();
1870ac7ddfbfSEd Maste }
1871ac7ddfbfSEd Maste 
HasCachedData() const1872435933ddSDimitry Andric bool StackFrame::HasCachedData() const {
18734bb0738eSEd Maste   if (m_variable_list_sp)
1874ac7ddfbfSEd Maste     return true;
1875ac7ddfbfSEd Maste   if (m_variable_list_value_objects.GetSize() > 0)
1876ac7ddfbfSEd Maste     return true;
1877ac7ddfbfSEd Maste   if (!m_disassembly.GetString().empty())
1878ac7ddfbfSEd Maste     return true;
1879ac7ddfbfSEd Maste   return false;
1880ac7ddfbfSEd Maste }
1881ac7ddfbfSEd Maste 
GetStatus(Stream & strm,bool show_frame_info,bool show_source,bool show_unique,const char * frame_marker)1882435933ddSDimitry Andric bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source,
188324d58133SDimitry Andric                            bool show_unique, const char *frame_marker) {
1884435933ddSDimitry Andric   if (show_frame_info) {
1885ac7ddfbfSEd Maste     strm.Indent();
188624d58133SDimitry Andric     DumpUsingSettingsFormat(&strm, show_unique, frame_marker);
1887ac7ddfbfSEd Maste   }
1888ac7ddfbfSEd Maste 
1889435933ddSDimitry Andric   if (show_source) {
1890ac7ddfbfSEd Maste     ExecutionContext exe_ctx(shared_from_this());
18919f2f44ceSEd Maste     bool have_source = false, have_debuginfo = false;
1892435933ddSDimitry Andric     Debugger::StopDisassemblyType disasm_display =
1893435933ddSDimitry Andric         Debugger::eStopDisassemblyTypeNever;
1894ac7ddfbfSEd Maste     Target *target = exe_ctx.GetTargetPtr();
1895435933ddSDimitry Andric     if (target) {
1896ac7ddfbfSEd Maste       Debugger &debugger = target->GetDebugger();
1897435933ddSDimitry Andric       const uint32_t source_lines_before =
1898435933ddSDimitry Andric           debugger.GetStopSourceLineCount(true);
1899435933ddSDimitry Andric       const uint32_t source_lines_after =
1900435933ddSDimitry Andric           debugger.GetStopSourceLineCount(false);
1901ac7ddfbfSEd Maste       disasm_display = debugger.GetStopDisassemblyDisplay();
1902ac7ddfbfSEd Maste 
1903ac7ddfbfSEd Maste       GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry);
1904435933ddSDimitry Andric       if (m_sc.comp_unit && m_sc.line_entry.IsValid()) {
19059f2f44ceSEd Maste         have_debuginfo = true;
1906435933ddSDimitry Andric         if (source_lines_before > 0 || source_lines_after > 0) {
1907435933ddSDimitry Andric           size_t num_lines =
1908435933ddSDimitry Andric               target->GetSourceManager().DisplaySourceLinesWithLineNumbers(
1909435933ddSDimitry Andric                   m_sc.line_entry.file, m_sc.line_entry.line,
1910435933ddSDimitry Andric                   m_sc.line_entry.column, source_lines_before,
1911435933ddSDimitry Andric                   source_lines_after, "->", &strm);
19129f2f44ceSEd Maste           if (num_lines != 0)
19139f2f44ceSEd Maste             have_source = true;
19149f2f44ceSEd Maste           // TODO: Give here a one time warning if source file is missing.
1915ac7ddfbfSEd Maste         }
1916ac7ddfbfSEd Maste       }
1917435933ddSDimitry Andric       switch (disasm_display) {
1918ac7ddfbfSEd Maste       case Debugger::eStopDisassemblyTypeNever:
1919ac7ddfbfSEd Maste         break;
1920ac7ddfbfSEd Maste 
19219f2f44ceSEd Maste       case Debugger::eStopDisassemblyTypeNoDebugInfo:
19229f2f44ceSEd Maste         if (have_debuginfo)
19239f2f44ceSEd Maste           break;
19244bb0738eSEd Maste         LLVM_FALLTHROUGH;
19259f2f44ceSEd Maste 
1926ac7ddfbfSEd Maste       case Debugger::eStopDisassemblyTypeNoSource:
1927ac7ddfbfSEd Maste         if (have_source)
1928ac7ddfbfSEd Maste           break;
19294bb0738eSEd Maste         LLVM_FALLTHROUGH;
19309f2f44ceSEd Maste 
1931ac7ddfbfSEd Maste       case Debugger::eStopDisassemblyTypeAlways:
1932435933ddSDimitry Andric         if (target) {
1933ac7ddfbfSEd Maste           const uint32_t disasm_lines = debugger.GetDisassemblyLineCount();
1934435933ddSDimitry Andric           if (disasm_lines > 0) {
1935ac7ddfbfSEd Maste             const ArchSpec &target_arch = target->GetArchitecture();
1936ac7ddfbfSEd Maste             AddressRange pc_range;
1937ac7ddfbfSEd Maste             pc_range.GetBaseAddress() = GetFrameCodeAddress();
1938435933ddSDimitry Andric             pc_range.SetByteSize(disasm_lines *
1939435933ddSDimitry Andric                                  target_arch.GetMaximumOpcodeByteSize());
19404bb0738eSEd Maste             const char *plugin_name = nullptr;
19414bb0738eSEd Maste             const char *flavor = nullptr;
1942435933ddSDimitry Andric             const bool mixed_source_and_assembly = false;
1943435933ddSDimitry Andric             Disassembler::Disassemble(
1944435933ddSDimitry Andric                 target->GetDebugger(), target_arch, plugin_name, flavor,
1945435933ddSDimitry Andric                 exe_ctx, pc_range, disasm_lines, mixed_source_and_assembly, 0,
1946435933ddSDimitry Andric                 Disassembler::eOptionMarkPCAddress, strm);
1947ac7ddfbfSEd Maste           }
1948ac7ddfbfSEd Maste         }
1949ac7ddfbfSEd Maste         break;
1950ac7ddfbfSEd Maste       }
1951ac7ddfbfSEd Maste     }
1952ac7ddfbfSEd Maste   }
1953ac7ddfbfSEd Maste   return true;
1954ac7ddfbfSEd Maste }
1955*b5893f02SDimitry Andric 
GetRecognizedFrame()1956*b5893f02SDimitry Andric RecognizedStackFrameSP StackFrame::GetRecognizedFrame() {
1957*b5893f02SDimitry Andric   if (!m_recognized_frame_sp) {
1958*b5893f02SDimitry Andric     m_recognized_frame_sp =
1959*b5893f02SDimitry Andric         StackFrameRecognizerManager::RecognizeFrame(CalculateStackFrame());
1960*b5893f02SDimitry Andric   }
1961*b5893f02SDimitry Andric   return m_recognized_frame_sp;
1962*b5893f02SDimitry Andric }
1963