xref: /src/contrib/llvm-project/lldb/source/Target/StackFrame.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1cfca06d7SDimitry Andric //===-- StackFrame.cpp ----------------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f3fbd1c0SDimitry Andric #include "lldb/Target/StackFrame.h"
10f034231aSEd Maste #include "lldb/Core/Debugger.h"
11f034231aSEd Maste #include "lldb/Core/Disassembler.h"
1212bd4897SEd Maste #include "lldb/Core/FormatEntity.h"
13f3fbd1c0SDimitry Andric #include "lldb/Core/Mangled.h"
14f3fbd1c0SDimitry Andric #include "lldb/Core/Module.h"
15f034231aSEd Maste #include "lldb/Core/Value.h"
16f034231aSEd Maste #include "lldb/Core/ValueObjectConstResult.h"
1714f1b3e8SDimitry Andric #include "lldb/Core/ValueObjectMemory.h"
1814f1b3e8SDimitry Andric #include "lldb/Core/ValueObjectVariable.h"
19f034231aSEd Maste #include "lldb/Symbol/CompileUnit.h"
20f034231aSEd Maste #include "lldb/Symbol/Function.h"
21f034231aSEd Maste #include "lldb/Symbol/Symbol.h"
22f034231aSEd Maste #include "lldb/Symbol/SymbolContextScope.h"
23e3b55780SDimitry Andric #include "lldb/Symbol/SymbolFile.h"
24e81d9d49SDimitry Andric #include "lldb/Symbol/Type.h"
25f034231aSEd Maste #include "lldb/Symbol/VariableList.h"
2614f1b3e8SDimitry Andric #include "lldb/Target/ABI.h"
27f034231aSEd Maste #include "lldb/Target/ExecutionContext.h"
28f034231aSEd Maste #include "lldb/Target/Process.h"
29f034231aSEd Maste #include "lldb/Target/RegisterContext.h"
3094994d37SDimitry Andric #include "lldb/Target/StackFrameRecognizer.h"
31f034231aSEd Maste #include "lldb/Target/Target.h"
32f034231aSEd Maste #include "lldb/Target/Thread.h"
33145449b1SDimitry Andric #include "lldb/Utility/LLDBLog.h"
34ead24645SDimitry Andric #include "lldb/Utility/Log.h"
3594994d37SDimitry Andric #include "lldb/Utility/RegisterValue.h"
3694994d37SDimitry Andric 
3794994d37SDimitry Andric #include "lldb/lldb-enumerations.h"
38f034231aSEd Maste 
395f29bb8aSDimitry Andric #include <memory>
405f29bb8aSDimitry Andric 
41f034231aSEd Maste using namespace lldb;
42f034231aSEd Maste using namespace lldb_private;
43f034231aSEd Maste 
44f034231aSEd Maste // The first bits in the flags are reserved for the SymbolContext::Scope bits
45f034231aSEd Maste // so we know if we have tried to look up information in our internal symbol
46f034231aSEd Maste // context (m_sc) already.
47e3b55780SDimitry Andric #define RESOLVED_FRAME_CODE_ADDR (uint32_t(eSymbolContextLastItem) << 1)
48f034231aSEd Maste #define RESOLVED_FRAME_ID_SYMBOL_SCOPE (RESOLVED_FRAME_CODE_ADDR << 1)
49f034231aSEd Maste #define GOT_FRAME_BASE (RESOLVED_FRAME_ID_SYMBOL_SCOPE << 1)
50f034231aSEd Maste #define RESOLVED_VARIABLES (GOT_FRAME_BASE << 1)
51f034231aSEd Maste #define RESOLVED_GLOBAL_VARIABLES (RESOLVED_VARIABLES << 1)
52f034231aSEd 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,bool behaves_like_zeroth_frame,const SymbolContext * sc_ptr)5314f1b3e8SDimitry Andric StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,
5414f1b3e8SDimitry Andric                        user_id_t unwind_frame_index, addr_t cfa,
5594994d37SDimitry Andric                        bool cfa_is_valid, addr_t pc, StackFrame::Kind kind,
56ead24645SDimitry Andric                        bool behaves_like_zeroth_frame,
57f3fbd1c0SDimitry Andric                        const SymbolContext *sc_ptr)
5814f1b3e8SDimitry Andric     : m_thread_wp(thread_sp), m_frame_index(frame_idx),
5914f1b3e8SDimitry Andric       m_concrete_frame_index(unwind_frame_index), m_reg_context_sp(),
6014f1b3e8SDimitry Andric       m_id(pc, cfa, nullptr), m_frame_code_addr(pc), m_sc(), m_flags(),
6114f1b3e8SDimitry Andric       m_frame_base(), m_frame_base_error(), m_cfa_is_valid(cfa_is_valid),
62ead24645SDimitry Andric       m_stack_frame_kind(kind),
63ead24645SDimitry Andric       m_behaves_like_zeroth_frame(behaves_like_zeroth_frame),
64ead24645SDimitry Andric       m_variable_list_sp(), m_variable_list_value_objects(),
65ead24645SDimitry Andric       m_recognized_frame_sp(), m_disassembly(), m_mutex() {
6614f1b3e8SDimitry Andric   // If we don't have a CFA value, use the frame index for our StackID so that
67f73363f1SDimitry Andric   // recursive functions properly aren't confused with one another on a history
68f73363f1SDimitry Andric   // stack.
6994994d37SDimitry Andric   if (IsHistorical() && !m_cfa_is_valid) {
70f21a844fSEd Maste     m_id.SetCFA(m_frame_index);
71f21a844fSEd Maste   }
72f21a844fSEd Maste 
7314f1b3e8SDimitry Andric   if (sc_ptr != nullptr) {
74f034231aSEd Maste     m_sc = *sc_ptr;
75f034231aSEd Maste     m_flags.Set(m_sc.GetResolvedMask());
76f034231aSEd Maste   }
77f034231aSEd Maste }
78f034231aSEd 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,bool behaves_like_zeroth_frame,const SymbolContext * sc_ptr)7914f1b3e8SDimitry Andric StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,
8014f1b3e8SDimitry Andric                        user_id_t unwind_frame_index,
8114f1b3e8SDimitry Andric                        const RegisterContextSP &reg_context_sp, addr_t cfa,
82ead24645SDimitry Andric                        addr_t pc, bool behaves_like_zeroth_frame,
83ead24645SDimitry Andric                        const SymbolContext *sc_ptr)
8414f1b3e8SDimitry Andric     : m_thread_wp(thread_sp), m_frame_index(frame_idx),
85f034231aSEd Maste       m_concrete_frame_index(unwind_frame_index),
8614f1b3e8SDimitry Andric       m_reg_context_sp(reg_context_sp), m_id(pc, cfa, nullptr),
8714f1b3e8SDimitry Andric       m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(),
8894994d37SDimitry Andric       m_frame_base_error(), m_cfa_is_valid(true),
89ead24645SDimitry Andric       m_stack_frame_kind(StackFrame::Kind::Regular),
90ead24645SDimitry Andric       m_behaves_like_zeroth_frame(behaves_like_zeroth_frame),
91ead24645SDimitry Andric       m_variable_list_sp(), m_variable_list_value_objects(),
92ead24645SDimitry Andric       m_recognized_frame_sp(), m_disassembly(), m_mutex() {
9314f1b3e8SDimitry Andric   if (sc_ptr != nullptr) {
94f034231aSEd Maste     m_sc = *sc_ptr;
95f034231aSEd Maste     m_flags.Set(m_sc.GetResolvedMask());
96f034231aSEd Maste   }
97f034231aSEd Maste 
9814f1b3e8SDimitry Andric   if (reg_context_sp && !m_sc.target_sp) {
99f034231aSEd Maste     m_sc.target_sp = reg_context_sp->CalculateTarget();
100f034231aSEd Maste     if (m_sc.target_sp)
101f034231aSEd Maste       m_flags.Set(eSymbolContextTarget);
102f034231aSEd Maste   }
103f034231aSEd Maste }
104f034231aSEd 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,bool behaves_like_zeroth_frame,const SymbolContext * sc_ptr)10514f1b3e8SDimitry Andric StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,
10614f1b3e8SDimitry Andric                        user_id_t unwind_frame_index,
10714f1b3e8SDimitry Andric                        const RegisterContextSP &reg_context_sp, addr_t cfa,
108ead24645SDimitry Andric                        const Address &pc_addr, bool behaves_like_zeroth_frame,
109ead24645SDimitry Andric                        const SymbolContext *sc_ptr)
11014f1b3e8SDimitry Andric     : m_thread_wp(thread_sp), m_frame_index(frame_idx),
111f034231aSEd Maste       m_concrete_frame_index(unwind_frame_index),
112f034231aSEd Maste       m_reg_context_sp(reg_context_sp),
11314f1b3e8SDimitry Andric       m_id(pc_addr.GetLoadAddress(thread_sp->CalculateTarget().get()), cfa,
11414f1b3e8SDimitry Andric            nullptr),
11514f1b3e8SDimitry Andric       m_frame_code_addr(pc_addr), m_sc(), m_flags(), m_frame_base(),
11694994d37SDimitry Andric       m_frame_base_error(), m_cfa_is_valid(true),
117ead24645SDimitry Andric       m_stack_frame_kind(StackFrame::Kind::Regular),
118ead24645SDimitry Andric       m_behaves_like_zeroth_frame(behaves_like_zeroth_frame),
119ead24645SDimitry Andric       m_variable_list_sp(), m_variable_list_value_objects(),
120ead24645SDimitry Andric       m_recognized_frame_sp(), m_disassembly(), m_mutex() {
12114f1b3e8SDimitry Andric   if (sc_ptr != nullptr) {
122f034231aSEd Maste     m_sc = *sc_ptr;
123f034231aSEd Maste     m_flags.Set(m_sc.GetResolvedMask());
124f034231aSEd Maste   }
125f034231aSEd Maste 
12614f1b3e8SDimitry Andric   if (!m_sc.target_sp && reg_context_sp) {
127f034231aSEd Maste     m_sc.target_sp = reg_context_sp->CalculateTarget();
128f034231aSEd Maste     if (m_sc.target_sp)
129f034231aSEd Maste       m_flags.Set(eSymbolContextTarget);
130f034231aSEd Maste   }
131f034231aSEd Maste 
132f034231aSEd Maste   ModuleSP pc_module_sp(pc_addr.GetModule());
13314f1b3e8SDimitry Andric   if (!m_sc.module_sp || m_sc.module_sp != pc_module_sp) {
13414f1b3e8SDimitry Andric     if (pc_module_sp) {
135f034231aSEd Maste       m_sc.module_sp = pc_module_sp;
136f034231aSEd Maste       m_flags.Set(eSymbolContextModule);
13714f1b3e8SDimitry Andric     } else {
138f034231aSEd Maste       m_sc.module_sp.reset();
139f034231aSEd Maste     }
140f034231aSEd Maste   }
141f034231aSEd Maste }
142f034231aSEd Maste 
143f3fbd1c0SDimitry Andric StackFrame::~StackFrame() = default;
144f034231aSEd Maste 
GetStackID()14514f1b3e8SDimitry Andric StackID &StackFrame::GetStackID() {
146f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
147f73363f1SDimitry Andric   // Make sure we have resolved the StackID object's symbol context scope if we
148f73363f1SDimitry Andric   // already haven't looked it up.
149f034231aSEd Maste 
15014f1b3e8SDimitry Andric   if (m_flags.IsClear(RESOLVED_FRAME_ID_SYMBOL_SCOPE)) {
15114f1b3e8SDimitry Andric     if (m_id.GetSymbolContextScope()) {
152f73363f1SDimitry Andric       // We already have a symbol context scope, we just don't have our flag
153f73363f1SDimitry Andric       // bit set.
154f034231aSEd Maste       m_flags.Set(RESOLVED_FRAME_ID_SYMBOL_SCOPE);
15514f1b3e8SDimitry Andric     } else {
156f73363f1SDimitry Andric       // Calculate the frame block and use this for the stack ID symbol context
157f73363f1SDimitry Andric       // scope if we have one.
158f034231aSEd Maste       SymbolContextScope *scope = GetFrameBlock();
15914f1b3e8SDimitry Andric       if (scope == nullptr) {
160f034231aSEd Maste         // We don't have a block, so use the symbol
161f034231aSEd Maste         if (m_flags.IsClear(eSymbolContextSymbol))
162f034231aSEd Maste           GetSymbolContext(eSymbolContextSymbol);
163f034231aSEd Maste 
164f3fbd1c0SDimitry Andric         // It is ok if m_sc.symbol is nullptr here
165f034231aSEd Maste         scope = m_sc.symbol;
166f034231aSEd Maste       }
167f034231aSEd Maste       // Set the symbol context scope (the accessor will set the
168f034231aSEd Maste       // RESOLVED_FRAME_ID_SYMBOL_SCOPE bit in m_flags).
169f034231aSEd Maste       SetSymbolContextScope(scope);
170f034231aSEd Maste     }
171f034231aSEd Maste   }
172f034231aSEd Maste   return m_id;
173f034231aSEd Maste }
174f034231aSEd Maste 
GetFrameIndex() const17514f1b3e8SDimitry Andric uint32_t StackFrame::GetFrameIndex() const {
176f034231aSEd Maste   ThreadSP thread_sp = GetThread();
177f034231aSEd Maste   if (thread_sp)
17814f1b3e8SDimitry Andric     return thread_sp->GetStackFrameList()->GetVisibleStackFrameIndex(
17914f1b3e8SDimitry Andric         m_frame_index);
180f034231aSEd Maste   else
181f034231aSEd Maste     return m_frame_index;
182f034231aSEd Maste }
183f034231aSEd Maste 
SetSymbolContextScope(SymbolContextScope * symbol_scope)18414f1b3e8SDimitry Andric void StackFrame::SetSymbolContextScope(SymbolContextScope *symbol_scope) {
185f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
186f034231aSEd Maste   m_flags.Set(RESOLVED_FRAME_ID_SYMBOL_SCOPE);
187f034231aSEd Maste   m_id.SetSymbolContextScope(symbol_scope);
188f034231aSEd Maste }
189f034231aSEd Maste 
GetFrameCodeAddress()19014f1b3e8SDimitry Andric const Address &StackFrame::GetFrameCodeAddress() {
191f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
19214f1b3e8SDimitry Andric   if (m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR) &&
19314f1b3e8SDimitry Andric       !m_frame_code_addr.IsSectionOffset()) {
194f034231aSEd Maste     m_flags.Set(RESOLVED_FRAME_CODE_ADDR);
195f034231aSEd Maste 
196f034231aSEd Maste     // Resolve the PC into a temporary address because if ResolveLoadAddress
197f034231aSEd Maste     // fails to resolve the address, it will clear the address object...
198f034231aSEd Maste     ThreadSP thread_sp(GetThread());
19914f1b3e8SDimitry Andric     if (thread_sp) {
200f034231aSEd Maste       TargetSP target_sp(thread_sp->CalculateTarget());
20114f1b3e8SDimitry Andric       if (target_sp) {
202f1d04915SDimitry Andric         const bool allow_section_end = true;
20314f1b3e8SDimitry Andric         if (m_frame_code_addr.SetOpcodeLoadAddress(
20414f1b3e8SDimitry Andric                 m_frame_code_addr.GetOffset(), target_sp.get(),
205f73363f1SDimitry Andric                 AddressClass::eCode, allow_section_end)) {
206f034231aSEd Maste           ModuleSP module_sp(m_frame_code_addr.GetModule());
20714f1b3e8SDimitry Andric           if (module_sp) {
208f034231aSEd Maste             m_sc.module_sp = module_sp;
209f034231aSEd Maste             m_flags.Set(eSymbolContextModule);
210f034231aSEd Maste           }
211f034231aSEd Maste         }
212f034231aSEd Maste       }
213f034231aSEd Maste     }
214f034231aSEd Maste   }
215f034231aSEd Maste   return m_frame_code_addr;
216f034231aSEd Maste }
217f034231aSEd Maste 
218344a3780SDimitry Andric // This can't be rewritten into a call to
219344a3780SDimitry Andric // RegisterContext::GetPCForSymbolication because this
220344a3780SDimitry Andric // StackFrame may have been constructed with a special pc,
221344a3780SDimitry Andric // e.g. tail-call artificial frames.
GetFrameCodeAddressForSymbolication()222344a3780SDimitry Andric Address StackFrame::GetFrameCodeAddressForSymbolication() {
223344a3780SDimitry Andric   Address lookup_addr(GetFrameCodeAddress());
224344a3780SDimitry Andric   if (!lookup_addr.IsValid())
225344a3780SDimitry Andric     return lookup_addr;
226344a3780SDimitry Andric   if (m_behaves_like_zeroth_frame)
227344a3780SDimitry Andric     return lookup_addr;
228344a3780SDimitry Andric 
229344a3780SDimitry Andric   addr_t offset = lookup_addr.GetOffset();
230344a3780SDimitry Andric   if (offset > 0) {
231344a3780SDimitry Andric     lookup_addr.SetOffset(offset - 1);
232344a3780SDimitry Andric   } else {
233344a3780SDimitry Andric     // lookup_addr is the start of a section.  We need do the math on the
234344a3780SDimitry Andric     // actual load address and re-compute the section.  We're working with
235344a3780SDimitry Andric     // a 'noreturn' function at the end of a section.
236344a3780SDimitry Andric     TargetSP target_sp = CalculateTarget();
237344a3780SDimitry Andric     if (target_sp) {
238344a3780SDimitry Andric       addr_t addr_minus_one = lookup_addr.GetOpcodeLoadAddress(
239344a3780SDimitry Andric                                   target_sp.get(), AddressClass::eCode) -
240344a3780SDimitry Andric                               1;
241344a3780SDimitry Andric       lookup_addr.SetOpcodeLoadAddress(addr_minus_one, target_sp.get());
242344a3780SDimitry Andric     }
243344a3780SDimitry Andric   }
244344a3780SDimitry Andric   return lookup_addr;
245344a3780SDimitry Andric }
246344a3780SDimitry Andric 
ChangePC(addr_t pc)24714f1b3e8SDimitry Andric bool StackFrame::ChangePC(addr_t pc) {
248f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
249f21a844fSEd Maste   // We can't change the pc value of a history stack frame - it is immutable.
25094994d37SDimitry Andric   if (IsHistorical())
251f21a844fSEd Maste     return false;
252f034231aSEd Maste   m_frame_code_addr.SetRawAddress(pc);
253f034231aSEd Maste   m_sc.Clear(false);
254f034231aSEd Maste   m_flags.Reset(0);
255f034231aSEd Maste   ThreadSP thread_sp(GetThread());
256f034231aSEd Maste   if (thread_sp)
257f034231aSEd Maste     thread_sp->ClearStackFrames();
258f21a844fSEd Maste   return true;
259f034231aSEd Maste }
260f034231aSEd Maste 
Disassemble()26114f1b3e8SDimitry Andric const char *StackFrame::Disassemble() {
262f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
263b60736ecSDimitry Andric   if (!m_disassembly.Empty())
264b60736ecSDimitry Andric     return m_disassembly.GetData();
265b60736ecSDimitry Andric 
266f034231aSEd Maste   ExecutionContext exe_ctx(shared_from_this());
267b60736ecSDimitry Andric   if (Target *target = exe_ctx.GetTargetPtr()) {
268b60736ecSDimitry Andric     Disassembler::Disassemble(target->GetDebugger(), target->GetArchitecture(),
269b60736ecSDimitry Andric                               *this, m_disassembly);
27074a628f7SDimitry Andric   }
27174a628f7SDimitry Andric 
272b60736ecSDimitry Andric   return m_disassembly.Empty() ? nullptr : m_disassembly.GetData();
273f034231aSEd Maste }
274f034231aSEd Maste 
GetFrameBlock()27514f1b3e8SDimitry Andric Block *StackFrame::GetFrameBlock() {
276f3fbd1c0SDimitry Andric   if (m_sc.block == nullptr && m_flags.IsClear(eSymbolContextBlock))
277f034231aSEd Maste     GetSymbolContext(eSymbolContextBlock);
278f034231aSEd Maste 
27914f1b3e8SDimitry Andric   if (m_sc.block) {
280f034231aSEd Maste     Block *inline_block = m_sc.block->GetContainingInlinedBlock();
28114f1b3e8SDimitry Andric     if (inline_block) {
282f73363f1SDimitry Andric       // Use the block with the inlined function info as the frame block we
283f73363f1SDimitry Andric       // want this frame to have only the variables for the inlined function
284f73363f1SDimitry Andric       // and its non-inlined block child blocks.
285f034231aSEd Maste       return inline_block;
28614f1b3e8SDimitry Andric     } else {
287f73363f1SDimitry Andric       // This block is not contained within any inlined function blocks with so
288f73363f1SDimitry Andric       // we want to use the top most function block.
289f034231aSEd Maste       return &m_sc.function->GetBlock(false);
290f034231aSEd Maste     }
291f034231aSEd Maste   }
292f3fbd1c0SDimitry Andric   return nullptr;
293f034231aSEd Maste }
294f034231aSEd Maste 
295f034231aSEd Maste // Get the symbol context if we already haven't done so by resolving the
296f034231aSEd Maste // PC address as much as possible. This way when we pass around a
297f73363f1SDimitry Andric // StackFrame object, everyone will have as much information as possible and no
298f73363f1SDimitry Andric // one will ever have to look things up manually.
29994994d37SDimitry Andric const SymbolContext &
GetSymbolContext(SymbolContextItem resolve_scope)30094994d37SDimitry Andric StackFrame::GetSymbolContext(SymbolContextItem resolve_scope) {
301f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
302f034231aSEd Maste   // Copy our internal symbol context into "sc".
30314f1b3e8SDimitry Andric   if ((m_flags.Get() & resolve_scope) != resolve_scope) {
304f034231aSEd Maste     uint32_t resolved = 0;
305f034231aSEd Maste 
306f034231aSEd Maste     // If the target was requested add that:
30714f1b3e8SDimitry Andric     if (!m_sc.target_sp) {
308f034231aSEd Maste       m_sc.target_sp = CalculateTarget();
309f034231aSEd Maste       if (m_sc.target_sp)
310f034231aSEd Maste         resolved |= eSymbolContextTarget;
311f034231aSEd Maste     }
312f034231aSEd Maste 
313f73363f1SDimitry Andric     // Resolve our PC to section offset if we haven't already done so and if we
314f73363f1SDimitry Andric     // don't have a module. The resolved address section will contain the
315f73363f1SDimitry Andric     // module to which it belongs
316f034231aSEd Maste     if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR))
317f034231aSEd Maste       GetFrameCodeAddress();
318f034231aSEd Maste 
319f73363f1SDimitry Andric     // If this is not frame zero, then we need to subtract 1 from the PC value
320f73363f1SDimitry Andric     // when doing address lookups since the PC will be on the instruction
321f73363f1SDimitry Andric     // following the function call instruction...
322344a3780SDimitry Andric     Address lookup_addr(GetFrameCodeAddressForSymbolication());
323f034231aSEd Maste 
32414f1b3e8SDimitry Andric     if (m_sc.module_sp) {
325f73363f1SDimitry Andric       // We have something in our stack frame symbol context, lets check if we
326f73363f1SDimitry Andric       // haven't already tried to lookup one of those things. If we haven't
327f73363f1SDimitry Andric       // then we will do the query.
328f034231aSEd Maste 
32994994d37SDimitry Andric       SymbolContextItem actual_resolve_scope = SymbolContextItem(0);
330f034231aSEd Maste 
33114f1b3e8SDimitry Andric       if (resolve_scope & eSymbolContextCompUnit) {
33214f1b3e8SDimitry Andric         if (m_flags.IsClear(eSymbolContextCompUnit)) {
333f034231aSEd Maste           if (m_sc.comp_unit)
334f034231aSEd Maste             resolved |= eSymbolContextCompUnit;
335f034231aSEd Maste           else
336f034231aSEd Maste             actual_resolve_scope |= eSymbolContextCompUnit;
337f034231aSEd Maste         }
338f034231aSEd Maste       }
339f034231aSEd Maste 
34014f1b3e8SDimitry Andric       if (resolve_scope & eSymbolContextFunction) {
34114f1b3e8SDimitry Andric         if (m_flags.IsClear(eSymbolContextFunction)) {
342f034231aSEd Maste           if (m_sc.function)
343f034231aSEd Maste             resolved |= eSymbolContextFunction;
344f034231aSEd Maste           else
345f034231aSEd Maste             actual_resolve_scope |= eSymbolContextFunction;
346f034231aSEd Maste         }
347f034231aSEd Maste       }
348f034231aSEd Maste 
34914f1b3e8SDimitry Andric       if (resolve_scope & eSymbolContextBlock) {
35014f1b3e8SDimitry Andric         if (m_flags.IsClear(eSymbolContextBlock)) {
351f034231aSEd Maste           if (m_sc.block)
352f034231aSEd Maste             resolved |= eSymbolContextBlock;
353f034231aSEd Maste           else
354f034231aSEd Maste             actual_resolve_scope |= eSymbolContextBlock;
355f034231aSEd Maste         }
356f034231aSEd Maste       }
357f034231aSEd Maste 
35814f1b3e8SDimitry Andric       if (resolve_scope & eSymbolContextSymbol) {
35914f1b3e8SDimitry Andric         if (m_flags.IsClear(eSymbolContextSymbol)) {
360f034231aSEd Maste           if (m_sc.symbol)
361f034231aSEd Maste             resolved |= eSymbolContextSymbol;
362f034231aSEd Maste           else
363f034231aSEd Maste             actual_resolve_scope |= eSymbolContextSymbol;
364f034231aSEd Maste         }
365f034231aSEd Maste       }
366f034231aSEd Maste 
36714f1b3e8SDimitry Andric       if (resolve_scope & eSymbolContextLineEntry) {
36814f1b3e8SDimitry Andric         if (m_flags.IsClear(eSymbolContextLineEntry)) {
369f034231aSEd Maste           if (m_sc.line_entry.IsValid())
370f034231aSEd Maste             resolved |= eSymbolContextLineEntry;
371f034231aSEd Maste           else
372f034231aSEd Maste             actual_resolve_scope |= eSymbolContextLineEntry;
373f034231aSEd Maste         }
374f034231aSEd Maste       }
375f034231aSEd Maste 
37614f1b3e8SDimitry Andric       if (actual_resolve_scope) {
377f73363f1SDimitry Andric         // We might be resolving less information than what is already in our
378f73363f1SDimitry Andric         // current symbol context so resolve into a temporary symbol context
379f73363f1SDimitry Andric         // "sc" so we don't clear out data we have already found in "m_sc"
380f034231aSEd Maste         SymbolContext sc;
381f034231aSEd Maste         // Set flags that indicate what we have tried to resolve
38214f1b3e8SDimitry Andric         resolved |= m_sc.module_sp->ResolveSymbolContextForAddress(
38314f1b3e8SDimitry Andric             lookup_addr, actual_resolve_scope, sc);
384f73363f1SDimitry Andric         // Only replace what we didn't already have as we may have information
385f73363f1SDimitry Andric         // for an inlined function scope that won't match what a standard
386f73363f1SDimitry Andric         // lookup by address would match
387f3fbd1c0SDimitry Andric         if ((resolved & eSymbolContextCompUnit) && m_sc.comp_unit == nullptr)
388f034231aSEd Maste           m_sc.comp_unit = sc.comp_unit;
389f3fbd1c0SDimitry Andric         if ((resolved & eSymbolContextFunction) && m_sc.function == nullptr)
390f034231aSEd Maste           m_sc.function = sc.function;
391f3fbd1c0SDimitry Andric         if ((resolved & eSymbolContextBlock) && m_sc.block == nullptr)
392f034231aSEd Maste           m_sc.block = sc.block;
393f3fbd1c0SDimitry Andric         if ((resolved & eSymbolContextSymbol) && m_sc.symbol == nullptr)
394f034231aSEd Maste           m_sc.symbol = sc.symbol;
39514f1b3e8SDimitry Andric         if ((resolved & eSymbolContextLineEntry) &&
39614f1b3e8SDimitry Andric             !m_sc.line_entry.IsValid()) {
397f034231aSEd Maste           m_sc.line_entry = sc.line_entry;
398f3fbd1c0SDimitry Andric           m_sc.line_entry.ApplyFileMappings(m_sc.target_sp);
399f034231aSEd Maste         }
400f034231aSEd Maste       }
40114f1b3e8SDimitry Andric     } else {
402f034231aSEd Maste       // If we don't have a module, then we can't have the compile unit,
403f034231aSEd Maste       // function, block, line entry or symbol, so we can safely call
404f034231aSEd Maste       // ResolveSymbolContextForAddress with our symbol context member m_sc.
40514f1b3e8SDimitry Andric       if (m_sc.target_sp) {
40614f1b3e8SDimitry Andric         resolved |= m_sc.target_sp->GetImages().ResolveSymbolContextForAddress(
40714f1b3e8SDimitry Andric             lookup_addr, resolve_scope, m_sc);
408f034231aSEd Maste       }
409f034231aSEd Maste     }
410f034231aSEd Maste 
411f034231aSEd Maste     // Update our internal flags so we remember what we have tried to locate so
412f034231aSEd Maste     // we don't have to keep trying when more calls to this function are made.
413f73363f1SDimitry Andric     // We might have dug up more information that was requested (for example if
414f73363f1SDimitry Andric     // we were asked to only get the block, we will have gotten the compile
415f73363f1SDimitry Andric     // unit, and function) so set any additional bits that we resolved
416f034231aSEd Maste     m_flags.Set(resolve_scope | resolved);
417f034231aSEd Maste   }
418f034231aSEd Maste 
419f034231aSEd Maste   // Return the symbol context with everything that was possible to resolve
420f034231aSEd Maste   // resolved.
421f034231aSEd Maste   return m_sc;
422f034231aSEd Maste }
423f034231aSEd Maste 
GetVariableList(bool get_file_globals,Status * error_ptr)424e3b55780SDimitry Andric VariableList *StackFrame::GetVariableList(bool get_file_globals,
425e3b55780SDimitry Andric                                           Status *error_ptr) {
426f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
42714f1b3e8SDimitry Andric   if (m_flags.IsClear(RESOLVED_VARIABLES)) {
428f034231aSEd Maste     m_flags.Set(RESOLVED_VARIABLES);
429e3b55780SDimitry Andric     m_variable_list_sp = std::make_shared<VariableList>();
430f034231aSEd Maste 
431f034231aSEd Maste     Block *frame_block = GetFrameBlock();
432f034231aSEd Maste 
43314f1b3e8SDimitry Andric     if (frame_block) {
434f034231aSEd Maste       const bool get_child_variables = true;
435f034231aSEd Maste       const bool can_create = true;
436f034231aSEd Maste       const bool stop_if_child_block_is_inlined_function = true;
43714f1b3e8SDimitry Andric       frame_block->AppendBlockVariables(can_create, get_child_variables,
438f3fbd1c0SDimitry Andric                                         stop_if_child_block_is_inlined_function,
43974a628f7SDimitry Andric                                         [](Variable *v) { return true; },
440f3fbd1c0SDimitry Andric                                         m_variable_list_sp.get());
441f034231aSEd Maste     }
442f034231aSEd Maste   }
443f034231aSEd Maste 
44414f1b3e8SDimitry Andric   if (m_flags.IsClear(RESOLVED_GLOBAL_VARIABLES) && get_file_globals) {
445f034231aSEd Maste     m_flags.Set(RESOLVED_GLOBAL_VARIABLES);
446f034231aSEd Maste 
447f034231aSEd Maste     if (m_flags.IsClear(eSymbolContextCompUnit))
448f034231aSEd Maste       GetSymbolContext(eSymbolContextCompUnit);
449f034231aSEd Maste 
45014f1b3e8SDimitry Andric     if (m_sc.comp_unit) {
45114f1b3e8SDimitry Andric       VariableListSP global_variable_list_sp(
45214f1b3e8SDimitry Andric           m_sc.comp_unit->GetVariableList(true));
453f034231aSEd Maste       if (m_variable_list_sp)
454f034231aSEd Maste         m_variable_list_sp->AddVariables(global_variable_list_sp.get());
455f034231aSEd Maste       else
456f034231aSEd Maste         m_variable_list_sp = global_variable_list_sp;
457f034231aSEd Maste     }
458f034231aSEd Maste   }
459f034231aSEd Maste 
460e3b55780SDimitry Andric   if (error_ptr && m_variable_list_sp->GetSize() == 0) {
461e3b55780SDimitry Andric     // Check with the symbol file to check if there is an error for why we
462e3b55780SDimitry Andric     // don't have variables that the user might need to know about.
463e3b55780SDimitry Andric     GetSymbolContext(eSymbolContextEverything);
464e3b55780SDimitry Andric     if (m_sc.module_sp) {
465e3b55780SDimitry Andric       SymbolFile *sym_file = m_sc.module_sp->GetSymbolFile();
466e3b55780SDimitry Andric       if (sym_file)
467e3b55780SDimitry Andric         *error_ptr = sym_file->GetFrameVariableError(*this);
468e3b55780SDimitry Andric     }
469e3b55780SDimitry Andric   }
470e3b55780SDimitry Andric 
471f034231aSEd Maste   return m_variable_list_sp.get();
472f034231aSEd Maste }
473f034231aSEd Maste 
474f034231aSEd Maste VariableListSP
GetInScopeVariableList(bool get_file_globals,bool must_have_valid_location)47514f1b3e8SDimitry Andric StackFrame::GetInScopeVariableList(bool get_file_globals,
47614f1b3e8SDimitry Andric                                    bool must_have_valid_location) {
477f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
478f21a844fSEd Maste   // We can't fetch variable information for a history stack frame.
47994994d37SDimitry Andric   if (IsHistorical())
480f21a844fSEd Maste     return VariableListSP();
481f21a844fSEd Maste 
482f034231aSEd Maste   VariableListSP var_list_sp(new VariableList);
483f034231aSEd Maste   GetSymbolContext(eSymbolContextCompUnit | eSymbolContextBlock);
484f034231aSEd Maste 
48514f1b3e8SDimitry Andric   if (m_sc.block) {
486f034231aSEd Maste     const bool can_create = true;
487f034231aSEd Maste     const bool get_parent_variables = true;
488f034231aSEd Maste     const bool stop_if_block_is_inlined_function = true;
48914f1b3e8SDimitry Andric     m_sc.block->AppendVariables(
49014f1b3e8SDimitry Andric         can_create, get_parent_variables, stop_if_block_is_inlined_function,
49114f1b3e8SDimitry Andric         [this, must_have_valid_location](Variable *v) {
49214f1b3e8SDimitry Andric           return v->IsInScope(this) && (!must_have_valid_location ||
49314f1b3e8SDimitry Andric                                         v->LocationIsValidForFrame(this));
494f3fbd1c0SDimitry Andric         },
495f034231aSEd Maste         var_list_sp.get());
496f034231aSEd Maste   }
497f034231aSEd Maste 
49814f1b3e8SDimitry Andric   if (m_sc.comp_unit && get_file_globals) {
49914f1b3e8SDimitry Andric     VariableListSP global_variable_list_sp(
50014f1b3e8SDimitry Andric         m_sc.comp_unit->GetVariableList(true));
501f034231aSEd Maste     if (global_variable_list_sp)
502f034231aSEd Maste       var_list_sp->AddVariables(global_variable_list_sp.get());
503f034231aSEd Maste   }
504f034231aSEd Maste 
505f034231aSEd Maste   return var_list_sp;
506f034231aSEd Maste }
507f034231aSEd Maste 
GetValueForVariableExpressionPath(llvm::StringRef var_expr,DynamicValueType use_dynamic,uint32_t options,VariableSP & var_sp,Status & error)50814f1b3e8SDimitry Andric ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
50914f1b3e8SDimitry Andric     llvm::StringRef var_expr, DynamicValueType use_dynamic, uint32_t options,
510b76161e4SDimitry Andric     VariableSP &var_sp, Status &error) {
51114f1b3e8SDimitry Andric   llvm::StringRef original_var_expr = var_expr;
512f21a844fSEd Maste   // We can't fetch variable information for a history stack frame.
51394994d37SDimitry Andric   if (IsHistorical())
514f21a844fSEd Maste     return ValueObjectSP();
515f034231aSEd Maste 
51614f1b3e8SDimitry Andric   if (var_expr.empty()) {
51714f1b3e8SDimitry Andric     error.SetErrorStringWithFormat("invalid variable path '%s'",
51814f1b3e8SDimitry Andric                                    var_expr.str().c_str());
51914f1b3e8SDimitry Andric     return ValueObjectSP();
52014f1b3e8SDimitry Andric   }
52114f1b3e8SDimitry Andric 
52214f1b3e8SDimitry Andric   const bool check_ptr_vs_member =
52314f1b3e8SDimitry Andric       (options & eExpressionPathOptionCheckPtrVsMember) != 0;
52414f1b3e8SDimitry Andric   const bool no_fragile_ivar =
52514f1b3e8SDimitry Andric       (options & eExpressionPathOptionsNoFragileObjcIvar) != 0;
52614f1b3e8SDimitry Andric   const bool no_synth_child =
52714f1b3e8SDimitry Andric       (options & eExpressionPathOptionsNoSyntheticChildren) != 0;
52814f1b3e8SDimitry Andric   // const bool no_synth_array = (options &
52914f1b3e8SDimitry Andric   // eExpressionPathOptionsNoSyntheticArrayRange) != 0;
530f034231aSEd Maste   error.Clear();
531f034231aSEd Maste   bool deref = false;
532f034231aSEd Maste   bool address_of = false;
533f034231aSEd Maste   ValueObjectSP valobj_sp;
534f034231aSEd Maste   const bool get_file_globals = true;
535f034231aSEd Maste   // When looking up a variable for an expression, we need only consider the
536f034231aSEd Maste   // variables that are in scope.
537f034231aSEd Maste   VariableListSP var_list_sp(GetInScopeVariableList(get_file_globals));
538f034231aSEd Maste   VariableList *variable_list = var_list_sp.get();
539f034231aSEd Maste 
54014f1b3e8SDimitry Andric   if (!variable_list)
54114f1b3e8SDimitry Andric     return ValueObjectSP();
54214f1b3e8SDimitry Andric 
543f034231aSEd Maste   // If first character is a '*', then show pointer contents
54414f1b3e8SDimitry Andric   std::string var_expr_storage;
54514f1b3e8SDimitry Andric   if (var_expr[0] == '*') {
546f034231aSEd Maste     deref = true;
54714f1b3e8SDimitry Andric     var_expr = var_expr.drop_front(); // Skip the '*'
54814f1b3e8SDimitry Andric   } else if (var_expr[0] == '&') {
549f034231aSEd Maste     address_of = true;
55014f1b3e8SDimitry Andric     var_expr = var_expr.drop_front(); // Skip the '&'
551f034231aSEd Maste   }
552f034231aSEd Maste 
55314f1b3e8SDimitry Andric   size_t separator_idx = var_expr.find_first_of(".-[=+~|&^%#@!/?,<>{}");
554f034231aSEd Maste   StreamString var_expr_path_strm;
555f034231aSEd Maste 
55614f1b3e8SDimitry Andric   ConstString name_const_string(var_expr.substr(0, separator_idx));
557f034231aSEd Maste 
558e81d9d49SDimitry Andric   var_sp = variable_list->FindVariable(name_const_string, false);
559f034231aSEd Maste 
560f034231aSEd Maste   bool synthetically_added_instance_object = false;
561f034231aSEd Maste 
56214f1b3e8SDimitry Andric   if (var_sp) {
56314f1b3e8SDimitry Andric     var_expr = var_expr.drop_front(name_const_string.GetLength());
564f034231aSEd Maste   }
565e81d9d49SDimitry Andric 
56614f1b3e8SDimitry Andric   if (!var_sp && (options & eExpressionPathOptionsAllowDirectIVarAccess)) {
567f73363f1SDimitry Andric     // Check for direct ivars access which helps us with implicit access to
568145449b1SDimitry Andric     // ivars using "this" or "self".
569f034231aSEd Maste     GetSymbolContext(eSymbolContextFunction | eSymbolContextBlock);
5707fa27ce4SDimitry Andric     llvm::StringRef instance_var_name = m_sc.GetInstanceVariableName();
5717fa27ce4SDimitry Andric     if (!instance_var_name.empty()) {
5727fa27ce4SDimitry Andric       var_sp = variable_list->FindVariable(ConstString(instance_var_name));
57314f1b3e8SDimitry Andric       if (var_sp) {
574f034231aSEd Maste         separator_idx = 0;
575145449b1SDimitry Andric         if (Type *var_type = var_sp->GetType())
576145449b1SDimitry Andric           if (auto compiler_type = var_type->GetForwardCompilerType())
577145449b1SDimitry Andric             if (!compiler_type.IsPointerType())
578145449b1SDimitry Andric               var_expr_storage = ".";
579145449b1SDimitry Andric 
580145449b1SDimitry Andric         if (var_expr_storage.empty())
58114f1b3e8SDimitry Andric           var_expr_storage = "->";
58214f1b3e8SDimitry Andric         var_expr_storage += var_expr;
58314f1b3e8SDimitry Andric         var_expr = var_expr_storage;
584f034231aSEd Maste         synthetically_added_instance_object = true;
585f034231aSEd Maste       }
586f034231aSEd Maste     }
587f034231aSEd Maste   }
588f034231aSEd Maste 
58914f1b3e8SDimitry Andric   if (!var_sp && (options & eExpressionPathOptionsInspectAnonymousUnions)) {
59014f1b3e8SDimitry Andric     // Check if any anonymous unions are there which contain a variable with
59114f1b3e8SDimitry Andric     // the name we need
592706b4fc4SDimitry Andric     for (const VariableSP &variable_sp : *variable_list) {
59314f1b3e8SDimitry Andric       if (!variable_sp)
59414f1b3e8SDimitry Andric         continue;
59514f1b3e8SDimitry Andric       if (!variable_sp->GetName().IsEmpty())
59614f1b3e8SDimitry Andric         continue;
59714f1b3e8SDimitry Andric 
59814f1b3e8SDimitry Andric       Type *var_type = variable_sp->GetType();
59914f1b3e8SDimitry Andric       if (!var_type)
60014f1b3e8SDimitry Andric         continue;
60114f1b3e8SDimitry Andric 
60214f1b3e8SDimitry Andric       if (!var_type->GetForwardCompilerType().IsAnonymousType())
60314f1b3e8SDimitry Andric         continue;
604e81d9d49SDimitry Andric       valobj_sp = GetValueObjectForFrameVariable(variable_sp, use_dynamic);
605e81d9d49SDimitry Andric       if (!valobj_sp)
606e81d9d49SDimitry Andric         return valobj_sp;
6077fa27ce4SDimitry Andric       valobj_sp = valobj_sp->GetChildMemberWithName(name_const_string);
608e81d9d49SDimitry Andric       if (valobj_sp)
609e81d9d49SDimitry Andric         break;
610e81d9d49SDimitry Andric     }
611e81d9d49SDimitry Andric   }
612e81d9d49SDimitry Andric 
61314f1b3e8SDimitry Andric   if (var_sp && !valobj_sp) {
614f034231aSEd Maste     valobj_sp = GetValueObjectForFrameVariable(var_sp, use_dynamic);
615f034231aSEd Maste     if (!valobj_sp)
616f034231aSEd Maste       return valobj_sp;
617e81d9d49SDimitry Andric   }
61814f1b3e8SDimitry Andric   if (!valobj_sp) {
61914f1b3e8SDimitry Andric     error.SetErrorStringWithFormat("no variable named '%s' found in this frame",
62014f1b3e8SDimitry Andric                                    name_const_string.GetCString());
62114f1b3e8SDimitry Andric     return ValueObjectSP();
62214f1b3e8SDimitry Andric   }
62314f1b3e8SDimitry Andric 
624f034231aSEd Maste   // We are dumping at least one child
625cfca06d7SDimitry Andric   while (!var_expr.empty()) {
626f034231aSEd Maste     // Calculate the next separator index ahead of time
627f034231aSEd Maste     ValueObjectSP child_valobj_sp;
62814f1b3e8SDimitry Andric     const char separator_type = var_expr[0];
62974a628f7SDimitry Andric     bool expr_is_ptr = false;
63014f1b3e8SDimitry Andric     switch (separator_type) {
631f034231aSEd Maste     case '-':
63274a628f7SDimitry Andric       expr_is_ptr = true;
63314f1b3e8SDimitry Andric       if (var_expr.size() >= 2 && var_expr[1] != '>')
634f034231aSEd Maste         return ValueObjectSP();
635f034231aSEd Maste 
63614f1b3e8SDimitry Andric       if (no_fragile_ivar) {
637f034231aSEd Maste         // Make sure we aren't trying to deref an objective
638f034231aSEd Maste         // C ivar if this is not allowed
63914f1b3e8SDimitry Andric         const uint32_t pointer_type_flags =
64014f1b3e8SDimitry Andric             valobj_sp->GetCompilerType().GetTypeInfo(nullptr);
641205afe67SEd Maste         if ((pointer_type_flags & eTypeIsObjC) &&
64214f1b3e8SDimitry Andric             (pointer_type_flags & eTypeIsPointer)) {
643f73363f1SDimitry Andric           // This was an objective C object pointer and it was requested we
644f73363f1SDimitry Andric           // skip any fragile ivars so return nothing here
645f034231aSEd Maste           return ValueObjectSP();
646f034231aSEd Maste         }
647f034231aSEd Maste       }
64874a628f7SDimitry Andric 
64974a628f7SDimitry Andric       // If we have a non pointer type with a sythetic value then lets check if
65074a628f7SDimitry Andric       // we have an sythetic dereference specified.
65174a628f7SDimitry Andric       if (!valobj_sp->IsPointerType() && valobj_sp->HasSyntheticValue()) {
652b76161e4SDimitry Andric         Status deref_error;
65374a628f7SDimitry Andric         if (valobj_sp->GetCompilerType().IsReferenceType()) {
65474a628f7SDimitry Andric           valobj_sp = valobj_sp->GetSyntheticValue()->Dereference(deref_error);
655312c0ed1SDimitry Andric           if (!valobj_sp || deref_error.Fail()) {
65674a628f7SDimitry Andric             error.SetErrorStringWithFormatv(
65774a628f7SDimitry Andric                 "Failed to dereference reference type: %s", deref_error);
65874a628f7SDimitry Andric             return ValueObjectSP();
65974a628f7SDimitry Andric           }
66074a628f7SDimitry Andric         }
66174a628f7SDimitry Andric 
66274a628f7SDimitry Andric         valobj_sp = valobj_sp->Dereference(deref_error);
663312c0ed1SDimitry Andric         if (!valobj_sp || deref_error.Fail()) {
66474a628f7SDimitry Andric           error.SetErrorStringWithFormatv(
6655f29bb8aSDimitry Andric               "Failed to dereference sythetic value: {0}", deref_error);
6665f29bb8aSDimitry Andric           return ValueObjectSP();
6675f29bb8aSDimitry Andric         }
6685f29bb8aSDimitry Andric         // Some synthetic plug-ins fail to set the error in Dereference
6695f29bb8aSDimitry Andric         if (!valobj_sp) {
6705f29bb8aSDimitry Andric           error.SetErrorString("Failed to dereference sythetic value");
67174a628f7SDimitry Andric           return ValueObjectSP();
67274a628f7SDimitry Andric         }
67374a628f7SDimitry Andric         expr_is_ptr = false;
67474a628f7SDimitry Andric       }
67574a628f7SDimitry Andric 
67614f1b3e8SDimitry Andric       var_expr = var_expr.drop_front(); // Remove the '-'
677e3b55780SDimitry Andric       [[fallthrough]];
67814f1b3e8SDimitry Andric     case '.': {
67914f1b3e8SDimitry Andric       var_expr = var_expr.drop_front(); // Remove the '.' or '>'
68014f1b3e8SDimitry Andric       separator_idx = var_expr.find_first_of(".-[");
68114f1b3e8SDimitry Andric       ConstString child_name(var_expr.substr(0, var_expr.find_first_of(".-[")));
682f034231aSEd Maste 
68314f1b3e8SDimitry Andric       if (check_ptr_vs_member) {
684f73363f1SDimitry Andric         // We either have a pointer type and need to verify valobj_sp is a
685f73363f1SDimitry Andric         // pointer, or we have a member of a class/union/struct being accessed
686f73363f1SDimitry Andric         // with the . syntax and need to verify we don't have a pointer.
687f034231aSEd Maste         const bool actual_is_ptr = valobj_sp->IsPointerType();
688f034231aSEd Maste 
68914f1b3e8SDimitry Andric         if (actual_is_ptr != expr_is_ptr) {
690f73363f1SDimitry Andric           // Incorrect use of "." with a pointer, or "->" with a
691f73363f1SDimitry Andric           // class/union/struct instance or reference.
692cfca06d7SDimitry Andric           valobj_sp->GetExpressionPath(var_expr_path_strm);
693f034231aSEd Maste           if (actual_is_ptr)
69414f1b3e8SDimitry Andric             error.SetErrorStringWithFormat(
69514f1b3e8SDimitry Andric                 "\"%s\" is a pointer and . was used to attempt to access "
69614f1b3e8SDimitry Andric                 "\"%s\". Did you mean \"%s->%s\"?",
69714f1b3e8SDimitry Andric                 var_expr_path_strm.GetData(), child_name.GetCString(),
69814f1b3e8SDimitry Andric                 var_expr_path_strm.GetData(), var_expr.str().c_str());
699f034231aSEd Maste           else
70014f1b3e8SDimitry Andric             error.SetErrorStringWithFormat(
70114f1b3e8SDimitry Andric                 "\"%s\" is not a pointer and -> was used to attempt to "
70214f1b3e8SDimitry Andric                 "access \"%s\". Did you mean \"%s.%s\"?",
70314f1b3e8SDimitry Andric                 var_expr_path_strm.GetData(), child_name.GetCString(),
70414f1b3e8SDimitry Andric                 var_expr_path_strm.GetData(), var_expr.str().c_str());
705f034231aSEd Maste           return ValueObjectSP();
706f034231aSEd Maste         }
707f034231aSEd Maste       }
7087fa27ce4SDimitry Andric       child_valobj_sp = valobj_sp->GetChildMemberWithName(child_name);
70914f1b3e8SDimitry Andric       if (!child_valobj_sp) {
71014f1b3e8SDimitry Andric         if (!no_synth_child) {
711f034231aSEd Maste           child_valobj_sp = valobj_sp->GetSyntheticValue();
712f034231aSEd Maste           if (child_valobj_sp)
71314f1b3e8SDimitry Andric             child_valobj_sp =
7147fa27ce4SDimitry Andric                 child_valobj_sp->GetChildMemberWithName(child_name);
715f034231aSEd Maste         }
716f034231aSEd Maste 
71714f1b3e8SDimitry Andric         if (no_synth_child || !child_valobj_sp) {
718f034231aSEd Maste           // No child member with name "child_name"
71914f1b3e8SDimitry Andric           if (synthetically_added_instance_object) {
72014f1b3e8SDimitry Andric             // We added a "this->" or "self->" to the beginning of the
721f73363f1SDimitry Andric             // expression and this is the first pointer ivar access, so just
722f73363f1SDimitry Andric             // return the normal error
72314f1b3e8SDimitry Andric             error.SetErrorStringWithFormat(
72414f1b3e8SDimitry Andric                 "no variable or instance variable named '%s' found in "
72514f1b3e8SDimitry Andric                 "this frame",
726f034231aSEd Maste                 name_const_string.GetCString());
72714f1b3e8SDimitry Andric           } else {
728cfca06d7SDimitry Andric             valobj_sp->GetExpressionPath(var_expr_path_strm);
72914f1b3e8SDimitry Andric             if (child_name) {
73014f1b3e8SDimitry Andric               error.SetErrorStringWithFormat(
73114f1b3e8SDimitry Andric                   "\"%s\" is not a member of \"(%s) %s\"",
732f034231aSEd Maste                   child_name.GetCString(),
733f034231aSEd Maste                   valobj_sp->GetTypeName().AsCString("<invalid type>"),
73414f1b3e8SDimitry Andric                   var_expr_path_strm.GetData());
73514f1b3e8SDimitry Andric             } else {
73614f1b3e8SDimitry Andric               error.SetErrorStringWithFormat(
73714f1b3e8SDimitry Andric                   "incomplete expression path after \"%s\" in \"%s\"",
73814f1b3e8SDimitry Andric                   var_expr_path_strm.GetData(),
73914f1b3e8SDimitry Andric                   original_var_expr.str().c_str());
740f034231aSEd Maste             }
741f034231aSEd Maste           }
742f034231aSEd Maste           return ValueObjectSP();
743f034231aSEd Maste         }
744f034231aSEd Maste       }
745f034231aSEd Maste       synthetically_added_instance_object = false;
746f034231aSEd Maste       // Remove the child name from the path
74714f1b3e8SDimitry Andric       var_expr = var_expr.drop_front(child_name.GetLength());
74814f1b3e8SDimitry Andric       if (use_dynamic != eNoDynamicValues) {
74914f1b3e8SDimitry Andric         ValueObjectSP dynamic_value_sp(
75014f1b3e8SDimitry Andric             child_valobj_sp->GetDynamicValue(use_dynamic));
751f034231aSEd Maste         if (dynamic_value_sp)
752f034231aSEd Maste           child_valobj_sp = dynamic_value_sp;
753f034231aSEd Maste       }
75414f1b3e8SDimitry Andric     } break;
755f034231aSEd Maste 
75614f1b3e8SDimitry Andric     case '[': {
757f73363f1SDimitry Andric       // Array member access, or treating pointer as an array Need at least two
758f73363f1SDimitry Andric       // brackets and a number
75914f1b3e8SDimitry Andric       if (var_expr.size() <= 2) {
76014f1b3e8SDimitry Andric         error.SetErrorStringWithFormat(
76114f1b3e8SDimitry Andric             "invalid square bracket encountered after \"%s\" in \"%s\"",
76214f1b3e8SDimitry Andric             var_expr_path_strm.GetData(), var_expr.str().c_str());
76314f1b3e8SDimitry Andric         return ValueObjectSP();
76414f1b3e8SDimitry Andric       }
76514f1b3e8SDimitry Andric 
76614f1b3e8SDimitry Andric       // Drop the open brace.
76714f1b3e8SDimitry Andric       var_expr = var_expr.drop_front();
76814f1b3e8SDimitry Andric       long child_index = 0;
76914f1b3e8SDimitry Andric 
77014f1b3e8SDimitry Andric       // If there's no closing brace, this is an invalid expression.
77114f1b3e8SDimitry Andric       size_t end_pos = var_expr.find_first_of(']');
77214f1b3e8SDimitry Andric       if (end_pos == llvm::StringRef::npos) {
77314f1b3e8SDimitry Andric         error.SetErrorStringWithFormat(
77414f1b3e8SDimitry Andric             "missing closing square bracket in expression \"%s\"",
77514f1b3e8SDimitry Andric             var_expr_path_strm.GetData());
77614f1b3e8SDimitry Andric         return ValueObjectSP();
77714f1b3e8SDimitry Andric       }
77814f1b3e8SDimitry Andric       llvm::StringRef index_expr = var_expr.take_front(end_pos);
77914f1b3e8SDimitry Andric       llvm::StringRef original_index_expr = index_expr;
78014f1b3e8SDimitry Andric       // Drop all of "[index_expr]"
78114f1b3e8SDimitry Andric       var_expr = var_expr.drop_front(end_pos + 1);
78214f1b3e8SDimitry Andric 
78314f1b3e8SDimitry Andric       if (index_expr.consumeInteger(0, child_index)) {
78414f1b3e8SDimitry Andric         // If there was no integer anywhere in the index expression, this is
78514f1b3e8SDimitry Andric         // erroneous expression.
78614f1b3e8SDimitry Andric         error.SetErrorStringWithFormat("invalid index expression \"%s\"",
78714f1b3e8SDimitry Andric                                        index_expr.str().c_str());
78814f1b3e8SDimitry Andric         return ValueObjectSP();
78914f1b3e8SDimitry Andric       }
79014f1b3e8SDimitry Andric 
79114f1b3e8SDimitry Andric       if (index_expr.empty()) {
79214f1b3e8SDimitry Andric         // The entire index expression was a single integer.
79314f1b3e8SDimitry Andric 
79414f1b3e8SDimitry Andric         if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) {
79514f1b3e8SDimitry Andric           // what we have is *ptr[low]. the most similar C++ syntax is to deref
79614f1b3e8SDimitry Andric           // ptr and extract bit low out of it. reading array item low would be
79714f1b3e8SDimitry Andric           // done by saying ptr[low], without a deref * sign
798312c0ed1SDimitry Andric           Status deref_error;
799312c0ed1SDimitry Andric           ValueObjectSP temp(valobj_sp->Dereference(deref_error));
800312c0ed1SDimitry Andric           if (!temp || deref_error.Fail()) {
801cfca06d7SDimitry Andric             valobj_sp->GetExpressionPath(var_expr_path_strm);
80214f1b3e8SDimitry Andric             error.SetErrorStringWithFormat(
80314f1b3e8SDimitry Andric                 "could not dereference \"(%s) %s\"",
804f034231aSEd Maste                 valobj_sp->GetTypeName().AsCString("<invalid type>"),
80514f1b3e8SDimitry Andric                 var_expr_path_strm.GetData());
806f034231aSEd Maste             return ValueObjectSP();
807f034231aSEd Maste           }
808f034231aSEd Maste           valobj_sp = temp;
809f034231aSEd Maste           deref = false;
81014f1b3e8SDimitry Andric         } else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() &&
81114f1b3e8SDimitry Andric                    deref) {
812f73363f1SDimitry Andric           // what we have is *arr[low]. the most similar C++ syntax is to get
813f73363f1SDimitry Andric           // arr[0] (an operation that is equivalent to deref-ing arr) and
814f73363f1SDimitry Andric           // extract bit low out of it. reading array item low would be done by
815f73363f1SDimitry Andric           // saying arr[low], without a deref * sign
8167fa27ce4SDimitry Andric           ValueObjectSP temp(valobj_sp->GetChildAtIndex(0));
817312c0ed1SDimitry Andric           if (!temp) {
818cfca06d7SDimitry Andric             valobj_sp->GetExpressionPath(var_expr_path_strm);
81914f1b3e8SDimitry Andric             error.SetErrorStringWithFormat(
82014f1b3e8SDimitry Andric                 "could not get item 0 for \"(%s) %s\"",
821f034231aSEd Maste                 valobj_sp->GetTypeName().AsCString("<invalid type>"),
82214f1b3e8SDimitry Andric                 var_expr_path_strm.GetData());
823f034231aSEd Maste             return ValueObjectSP();
824f034231aSEd Maste           }
825f034231aSEd Maste           valobj_sp = temp;
826f034231aSEd Maste           deref = false;
827f034231aSEd Maste         }
828f034231aSEd Maste 
829f034231aSEd Maste         bool is_incomplete_array = false;
83014f1b3e8SDimitry Andric         if (valobj_sp->IsPointerType()) {
831f034231aSEd Maste           bool is_objc_pointer = true;
832f034231aSEd Maste 
83314f1b3e8SDimitry Andric           if (valobj_sp->GetCompilerType().GetMinimumLanguage() !=
83414f1b3e8SDimitry Andric               eLanguageTypeObjC)
835f034231aSEd Maste             is_objc_pointer = false;
836e81d9d49SDimitry Andric           else if (!valobj_sp->GetCompilerType().IsPointerType())
837f034231aSEd Maste             is_objc_pointer = false;
838f034231aSEd Maste 
83914f1b3e8SDimitry Andric           if (no_synth_child && is_objc_pointer) {
84014f1b3e8SDimitry Andric             error.SetErrorStringWithFormat(
84114f1b3e8SDimitry Andric                 "\"(%s) %s\" is an Objective-C pointer, and cannot be "
84214f1b3e8SDimitry Andric                 "subscripted",
843f034231aSEd Maste                 valobj_sp->GetTypeName().AsCString("<invalid type>"),
84414f1b3e8SDimitry Andric                 var_expr_path_strm.GetData());
845f034231aSEd Maste 
846f034231aSEd Maste             return ValueObjectSP();
84714f1b3e8SDimitry Andric           } else if (is_objc_pointer) {
848f73363f1SDimitry Andric             // dereferencing ObjC variables is not valid.. so let's try and
849f73363f1SDimitry Andric             // recur to synthetic children
850f034231aSEd Maste             ValueObjectSP synthetic = valobj_sp->GetSyntheticValue();
851f3fbd1c0SDimitry Andric             if (!synthetic                 /* no synthetic */
85214f1b3e8SDimitry Andric                 || synthetic == valobj_sp) /* synthetic is the same as
85314f1b3e8SDimitry Andric                                               the original object */
854f034231aSEd Maste             {
855cfca06d7SDimitry Andric               valobj_sp->GetExpressionPath(var_expr_path_strm);
85614f1b3e8SDimitry Andric               error.SetErrorStringWithFormat(
85714f1b3e8SDimitry Andric                   "\"(%s) %s\" is not an array type",
858f034231aSEd Maste                   valobj_sp->GetTypeName().AsCString("<invalid type>"),
85914f1b3e8SDimitry Andric                   var_expr_path_strm.GetData());
860ac9a064cSDimitry Andric             } else if (static_cast<uint32_t>(child_index) >=
86114f1b3e8SDimitry Andric                        synthetic
862ac9a064cSDimitry Andric                            ->GetNumChildrenIgnoringErrors() /* synthetic does
863ac9a064cSDimitry Andric                                                                 not have that
864ac9a064cSDimitry Andric                                                                 many values */) {
865cfca06d7SDimitry Andric               valobj_sp->GetExpressionPath(var_expr_path_strm);
86614f1b3e8SDimitry Andric               error.SetErrorStringWithFormat(
86714f1b3e8SDimitry Andric                   "array index %ld is not valid for \"(%s) %s\"", child_index,
868f034231aSEd Maste                   valobj_sp->GetTypeName().AsCString("<invalid type>"),
86914f1b3e8SDimitry Andric                   var_expr_path_strm.GetData());
87014f1b3e8SDimitry Andric             } else {
8717fa27ce4SDimitry Andric               child_valobj_sp = synthetic->GetChildAtIndex(child_index);
87214f1b3e8SDimitry Andric               if (!child_valobj_sp) {
873cfca06d7SDimitry Andric                 valobj_sp->GetExpressionPath(var_expr_path_strm);
87414f1b3e8SDimitry Andric                 error.SetErrorStringWithFormat(
87514f1b3e8SDimitry Andric                     "array index %ld is not valid for \"(%s) %s\"", child_index,
87614f1b3e8SDimitry Andric                     valobj_sp->GetTypeName().AsCString("<invalid type>"),
87714f1b3e8SDimitry Andric                     var_expr_path_strm.GetData());
87814f1b3e8SDimitry Andric               }
87914f1b3e8SDimitry Andric             }
88014f1b3e8SDimitry Andric           } else {
88114f1b3e8SDimitry Andric             child_valobj_sp =
88214f1b3e8SDimitry Andric                 valobj_sp->GetSyntheticArrayMember(child_index, true);
88314f1b3e8SDimitry Andric             if (!child_valobj_sp) {
884cfca06d7SDimitry Andric               valobj_sp->GetExpressionPath(var_expr_path_strm);
88514f1b3e8SDimitry Andric               error.SetErrorStringWithFormat(
88614f1b3e8SDimitry Andric                   "failed to use pointer as array for index %ld for "
88714f1b3e8SDimitry Andric                   "\"(%s) %s\"",
888f034231aSEd Maste                   child_index,
889f034231aSEd Maste                   valobj_sp->GetTypeName().AsCString("<invalid type>"),
89014f1b3e8SDimitry Andric                   var_expr_path_strm.GetData());
891f034231aSEd Maste             }
892f034231aSEd Maste           }
89314f1b3e8SDimitry Andric         } else if (valobj_sp->GetCompilerType().IsArrayType(
89414f1b3e8SDimitry Andric                        nullptr, nullptr, &is_incomplete_array)) {
895f73363f1SDimitry Andric           // Pass false to dynamic_value here so we can tell the difference
896f73363f1SDimitry Andric           // between no dynamic value and no member of this type...
8977fa27ce4SDimitry Andric           child_valobj_sp = valobj_sp->GetChildAtIndex(child_index);
898f3fbd1c0SDimitry Andric           if (!child_valobj_sp && (is_incomplete_array || !no_synth_child))
89914f1b3e8SDimitry Andric             child_valobj_sp =
90014f1b3e8SDimitry Andric                 valobj_sp->GetSyntheticArrayMember(child_index, true);
901f034231aSEd Maste 
90214f1b3e8SDimitry Andric           if (!child_valobj_sp) {
903cfca06d7SDimitry Andric             valobj_sp->GetExpressionPath(var_expr_path_strm);
90414f1b3e8SDimitry Andric             error.SetErrorStringWithFormat(
90514f1b3e8SDimitry Andric                 "array index %ld is not valid for \"(%s) %s\"", child_index,
906f034231aSEd Maste                 valobj_sp->GetTypeName().AsCString("<invalid type>"),
90714f1b3e8SDimitry Andric                 var_expr_path_strm.GetData());
908f034231aSEd Maste           }
90914f1b3e8SDimitry Andric         } else if (valobj_sp->GetCompilerType().IsScalarType()) {
910f034231aSEd Maste           // this is a bitfield asking to display just one bit
91114f1b3e8SDimitry Andric           child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild(
91214f1b3e8SDimitry Andric               child_index, child_index, true);
91314f1b3e8SDimitry Andric           if (!child_valobj_sp) {
914cfca06d7SDimitry Andric             valobj_sp->GetExpressionPath(var_expr_path_strm);
91514f1b3e8SDimitry Andric             error.SetErrorStringWithFormat(
91614f1b3e8SDimitry Andric                 "bitfield range %ld-%ld is not valid for \"(%s) %s\"",
917f034231aSEd Maste                 child_index, child_index,
918f034231aSEd Maste                 valobj_sp->GetTypeName().AsCString("<invalid type>"),
91914f1b3e8SDimitry Andric                 var_expr_path_strm.GetData());
920f034231aSEd Maste           }
92114f1b3e8SDimitry Andric         } else {
922f034231aSEd Maste           ValueObjectSP synthetic = valobj_sp->GetSyntheticValue();
923f034231aSEd Maste           if (no_synth_child /* synthetic is forbidden */ ||
924f3fbd1c0SDimitry Andric               !synthetic                 /* no synthetic */
92514f1b3e8SDimitry Andric               || synthetic == valobj_sp) /* synthetic is the same as the
92614f1b3e8SDimitry Andric                                             original object */
927f034231aSEd Maste           {
928cfca06d7SDimitry Andric             valobj_sp->GetExpressionPath(var_expr_path_strm);
92914f1b3e8SDimitry Andric             error.SetErrorStringWithFormat(
93014f1b3e8SDimitry Andric                 "\"(%s) %s\" is not an array type",
931f034231aSEd Maste                 valobj_sp->GetTypeName().AsCString("<invalid type>"),
93214f1b3e8SDimitry Andric                 var_expr_path_strm.GetData());
933ac9a064cSDimitry Andric           } else if (static_cast<uint32_t>(child_index) >=
934ac9a064cSDimitry Andric                      synthetic->GetNumChildrenIgnoringErrors() /* synthetic
935ac9a064cSDimitry Andric                                      does not have that many values */) {
936cfca06d7SDimitry Andric             valobj_sp->GetExpressionPath(var_expr_path_strm);
93714f1b3e8SDimitry Andric             error.SetErrorStringWithFormat(
93814f1b3e8SDimitry Andric                 "array index %ld is not valid for \"(%s) %s\"", child_index,
939f034231aSEd Maste                 valobj_sp->GetTypeName().AsCString("<invalid type>"),
94014f1b3e8SDimitry Andric                 var_expr_path_strm.GetData());
94114f1b3e8SDimitry Andric           } else {
9427fa27ce4SDimitry Andric             child_valobj_sp = synthetic->GetChildAtIndex(child_index);
94314f1b3e8SDimitry Andric             if (!child_valobj_sp) {
944cfca06d7SDimitry Andric               valobj_sp->GetExpressionPath(var_expr_path_strm);
94514f1b3e8SDimitry Andric               error.SetErrorStringWithFormat(
94614f1b3e8SDimitry Andric                   "array index %ld is not valid for \"(%s) %s\"", child_index,
947f034231aSEd Maste                   valobj_sp->GetTypeName().AsCString("<invalid type>"),
94814f1b3e8SDimitry Andric                   var_expr_path_strm.GetData());
949f034231aSEd Maste             }
950f034231aSEd Maste           }
951f034231aSEd Maste         }
952f034231aSEd Maste 
95314f1b3e8SDimitry Andric         if (!child_valobj_sp) {
954f034231aSEd Maste           // Invalid array index...
955f034231aSEd Maste           return ValueObjectSP();
956f034231aSEd Maste         }
957f034231aSEd Maste 
95814f1b3e8SDimitry Andric         if (use_dynamic != eNoDynamicValues) {
95914f1b3e8SDimitry Andric           ValueObjectSP dynamic_value_sp(
96014f1b3e8SDimitry Andric               child_valobj_sp->GetDynamicValue(use_dynamic));
961f034231aSEd Maste           if (dynamic_value_sp)
962f034231aSEd Maste             child_valobj_sp = dynamic_value_sp;
963f034231aSEd Maste         }
96414f1b3e8SDimitry Andric         // Break out early from the switch since we were able to find the child
96514f1b3e8SDimitry Andric         // member
966f034231aSEd Maste         break;
967f034231aSEd Maste       }
96814f1b3e8SDimitry Andric 
969f034231aSEd Maste       // this is most probably a BitField, let's take a look
97014f1b3e8SDimitry Andric       if (index_expr.front() != '-') {
97114f1b3e8SDimitry Andric         error.SetErrorStringWithFormat("invalid range expression \"'%s'\"",
97214f1b3e8SDimitry Andric                                        original_index_expr.str().c_str());
97314f1b3e8SDimitry Andric         return ValueObjectSP();
97414f1b3e8SDimitry Andric       }
97514f1b3e8SDimitry Andric 
97614f1b3e8SDimitry Andric       index_expr = index_expr.drop_front();
97714f1b3e8SDimitry Andric       long final_index = 0;
97814f1b3e8SDimitry Andric       if (index_expr.getAsInteger(0, final_index)) {
97914f1b3e8SDimitry Andric         error.SetErrorStringWithFormat("invalid range expression \"'%s'\"",
98014f1b3e8SDimitry Andric                                        original_index_expr.str().c_str());
98114f1b3e8SDimitry Andric         return ValueObjectSP();
98214f1b3e8SDimitry Andric       }
98314f1b3e8SDimitry Andric 
984f034231aSEd Maste       // if the format given is [high-low], swap range
98514f1b3e8SDimitry Andric       if (child_index > final_index) {
986f034231aSEd Maste         long temp = child_index;
987f034231aSEd Maste         child_index = final_index;
988f034231aSEd Maste         final_index = temp;
989f034231aSEd Maste       }
990f034231aSEd Maste 
99114f1b3e8SDimitry Andric       if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) {
99214f1b3e8SDimitry Andric         // what we have is *ptr[low-high]. the most similar C++ syntax is to
99314f1b3e8SDimitry Andric         // deref ptr and extract bits low thru high out of it. reading array
994f73363f1SDimitry Andric         // items low thru high would be done by saying ptr[low-high], without a
995f73363f1SDimitry Andric         // deref * sign
996312c0ed1SDimitry Andric         Status deref_error;
997312c0ed1SDimitry Andric         ValueObjectSP temp(valobj_sp->Dereference(deref_error));
998312c0ed1SDimitry Andric         if (!temp || deref_error.Fail()) {
999cfca06d7SDimitry Andric           valobj_sp->GetExpressionPath(var_expr_path_strm);
100014f1b3e8SDimitry Andric           error.SetErrorStringWithFormat(
100114f1b3e8SDimitry Andric               "could not dereference \"(%s) %s\"",
1002f034231aSEd Maste               valobj_sp->GetTypeName().AsCString("<invalid type>"),
100314f1b3e8SDimitry Andric               var_expr_path_strm.GetData());
1004f034231aSEd Maste           return ValueObjectSP();
1005f034231aSEd Maste         }
1006f034231aSEd Maste         valobj_sp = temp;
1007f034231aSEd Maste         deref = false;
100814f1b3e8SDimitry Andric       } else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() && deref) {
1009f73363f1SDimitry Andric         // what we have is *arr[low-high]. the most similar C++ syntax is to
1010f73363f1SDimitry Andric         // get arr[0] (an operation that is equivalent to deref-ing arr) and
1011f73363f1SDimitry Andric         // extract bits low thru high out of it. reading array items low thru
1012f73363f1SDimitry Andric         // high would be done by saying arr[low-high], without a deref * sign
10137fa27ce4SDimitry Andric         ValueObjectSP temp(valobj_sp->GetChildAtIndex(0));
1014312c0ed1SDimitry Andric         if (!temp) {
1015cfca06d7SDimitry Andric           valobj_sp->GetExpressionPath(var_expr_path_strm);
101614f1b3e8SDimitry Andric           error.SetErrorStringWithFormat(
101714f1b3e8SDimitry Andric               "could not get item 0 for \"(%s) %s\"",
1018f034231aSEd Maste               valobj_sp->GetTypeName().AsCString("<invalid type>"),
101914f1b3e8SDimitry Andric               var_expr_path_strm.GetData());
1020f034231aSEd Maste           return ValueObjectSP();
1021f034231aSEd Maste         }
1022f034231aSEd Maste         valobj_sp = temp;
1023f034231aSEd Maste         deref = false;
1024f034231aSEd Maste       }
1025f034231aSEd Maste 
102614f1b3e8SDimitry Andric       child_valobj_sp =
102714f1b3e8SDimitry Andric           valobj_sp->GetSyntheticBitFieldChild(child_index, final_index, true);
102814f1b3e8SDimitry Andric       if (!child_valobj_sp) {
1029cfca06d7SDimitry Andric         valobj_sp->GetExpressionPath(var_expr_path_strm);
103014f1b3e8SDimitry Andric         error.SetErrorStringWithFormat(
103114f1b3e8SDimitry Andric             "bitfield range %ld-%ld is not valid for \"(%s) %s\"", child_index,
103214f1b3e8SDimitry Andric             final_index, valobj_sp->GetTypeName().AsCString("<invalid type>"),
103314f1b3e8SDimitry Andric             var_expr_path_strm.GetData());
1034f034231aSEd Maste       }
1035f034231aSEd Maste 
103614f1b3e8SDimitry Andric       if (!child_valobj_sp) {
1037f034231aSEd Maste         // Invalid bitfield range...
1038f034231aSEd Maste         return ValueObjectSP();
1039f034231aSEd Maste       }
1040f034231aSEd Maste 
104114f1b3e8SDimitry Andric       if (use_dynamic != eNoDynamicValues) {
104214f1b3e8SDimitry Andric         ValueObjectSP dynamic_value_sp(
104314f1b3e8SDimitry Andric             child_valobj_sp->GetDynamicValue(use_dynamic));
1044f034231aSEd Maste         if (dynamic_value_sp)
1045f034231aSEd Maste           child_valobj_sp = dynamic_value_sp;
1046f034231aSEd Maste       }
104714f1b3e8SDimitry Andric       // Break out early from the switch since we were able to find the child
104814f1b3e8SDimitry Andric       // member
1049f034231aSEd Maste       break;
1050f034231aSEd Maste     }
1051f034231aSEd Maste     default:
1052f034231aSEd Maste       // Failure...
1053f034231aSEd Maste       {
1054cfca06d7SDimitry Andric         valobj_sp->GetExpressionPath(var_expr_path_strm);
105514f1b3e8SDimitry Andric         error.SetErrorStringWithFormat(
105614f1b3e8SDimitry Andric             "unexpected char '%c' encountered after \"%s\" in \"%s\"",
105714f1b3e8SDimitry Andric             separator_type, var_expr_path_strm.GetData(),
105814f1b3e8SDimitry Andric             var_expr.str().c_str());
1059f034231aSEd Maste 
1060f034231aSEd Maste         return ValueObjectSP();
1061f034231aSEd Maste       }
1062f034231aSEd Maste     }
1063f034231aSEd Maste 
1064f034231aSEd Maste     if (child_valobj_sp)
1065f034231aSEd Maste       valobj_sp = child_valobj_sp;
1066f034231aSEd Maste   }
106714f1b3e8SDimitry Andric   if (valobj_sp) {
106814f1b3e8SDimitry Andric     if (deref) {
1069f034231aSEd Maste       ValueObjectSP deref_valobj_sp(valobj_sp->Dereference(error));
1070f034231aSEd Maste       valobj_sp = deref_valobj_sp;
107114f1b3e8SDimitry Andric     } else if (address_of) {
1072f034231aSEd Maste       ValueObjectSP address_of_valobj_sp(valobj_sp->AddressOf(error));
1073f034231aSEd Maste       valobj_sp = address_of_valobj_sp;
1074f034231aSEd Maste     }
1075f034231aSEd Maste   }
1076f034231aSEd Maste   return valobj_sp;
1077f034231aSEd Maste }
1078f034231aSEd Maste 
GetFrameBaseValue(Scalar & frame_base,Status * error_ptr)1079b76161e4SDimitry Andric bool StackFrame::GetFrameBaseValue(Scalar &frame_base, Status *error_ptr) {
1080f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
108114f1b3e8SDimitry Andric   if (!m_cfa_is_valid) {
108214f1b3e8SDimitry Andric     m_frame_base_error.SetErrorString(
108314f1b3e8SDimitry Andric         "No frame base available for this historical stack frame.");
1084f21a844fSEd Maste     return false;
1085f21a844fSEd Maste   }
1086f21a844fSEd Maste 
108714f1b3e8SDimitry Andric   if (m_flags.IsClear(GOT_FRAME_BASE)) {
108814f1b3e8SDimitry Andric     if (m_sc.function) {
1089f034231aSEd Maste       m_frame_base.Clear();
1090f034231aSEd Maste       m_frame_base_error.Clear();
1091f034231aSEd Maste 
1092f034231aSEd Maste       m_flags.Set(GOT_FRAME_BASE);
1093f034231aSEd Maste       ExecutionContext exe_ctx(shared_from_this());
1094f034231aSEd Maste       addr_t loclist_base_addr = LLDB_INVALID_ADDRESS;
10951f917f69SDimitry Andric       if (!m_sc.function->GetFrameBaseExpression().IsAlwaysValidSingleExpr())
109614f1b3e8SDimitry Andric         loclist_base_addr =
109714f1b3e8SDimitry Andric             m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(
109814f1b3e8SDimitry Andric                 exe_ctx.GetTargetPtr());
1099f034231aSEd Maste 
1100ac9a064cSDimitry Andric       llvm::Expected<Value> expr_value =
1101ac9a064cSDimitry Andric           m_sc.function->GetFrameBaseExpression().Evaluate(
1102ac9a064cSDimitry Andric               &exe_ctx, nullptr, loclist_base_addr, nullptr, nullptr);
1103ac9a064cSDimitry Andric       if (!expr_value)
1104ac9a064cSDimitry Andric         m_frame_base_error = expr_value.takeError();
1105ac9a064cSDimitry Andric       else
1106ac9a064cSDimitry Andric         m_frame_base = expr_value->ResolveValue(&exe_ctx);
110714f1b3e8SDimitry Andric     } else {
1108f034231aSEd Maste       m_frame_base_error.SetErrorString("No function in symbol context.");
1109f034231aSEd Maste     }
1110f034231aSEd Maste   }
1111f034231aSEd Maste 
1112f034231aSEd Maste   if (m_frame_base_error.Success())
1113f034231aSEd Maste     frame_base = m_frame_base;
1114f034231aSEd Maste 
1115f034231aSEd Maste   if (error_ptr)
1116f034231aSEd Maste     *error_ptr = m_frame_base_error;
1117f034231aSEd Maste   return m_frame_base_error.Success();
1118f034231aSEd Maste }
1119f034231aSEd Maste 
GetFrameBaseExpression(Status * error_ptr)11201f917f69SDimitry Andric DWARFExpressionList *StackFrame::GetFrameBaseExpression(Status *error_ptr) {
112114f1b3e8SDimitry Andric   if (!m_sc.function) {
112214f1b3e8SDimitry Andric     if (error_ptr) {
112314f1b3e8SDimitry Andric       error_ptr->SetErrorString("No function in symbol context.");
112414f1b3e8SDimitry Andric     }
112514f1b3e8SDimitry Andric     return nullptr;
112614f1b3e8SDimitry Andric   }
112714f1b3e8SDimitry Andric 
112814f1b3e8SDimitry Andric   return &m_sc.function->GetFrameBaseExpression();
112914f1b3e8SDimitry Andric }
113014f1b3e8SDimitry Andric 
GetRegisterContext()113114f1b3e8SDimitry Andric RegisterContextSP StackFrame::GetRegisterContext() {
1132f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
113314f1b3e8SDimitry Andric   if (!m_reg_context_sp) {
1134f034231aSEd Maste     ThreadSP thread_sp(GetThread());
1135f034231aSEd Maste     if (thread_sp)
1136f034231aSEd Maste       m_reg_context_sp = thread_sp->CreateRegisterContextForFrame(this);
1137f034231aSEd Maste   }
1138f034231aSEd Maste   return m_reg_context_sp;
1139f034231aSEd Maste }
1140f034231aSEd Maste 
HasDebugInformation()114114f1b3e8SDimitry Andric bool StackFrame::HasDebugInformation() {
1142f034231aSEd Maste   GetSymbolContext(eSymbolContextLineEntry);
1143f034231aSEd Maste   return m_sc.line_entry.IsValid();
1144f034231aSEd Maste }
1145f034231aSEd Maste 
1146f034231aSEd Maste ValueObjectSP
GetValueObjectForFrameVariable(const VariableSP & variable_sp,DynamicValueType use_dynamic)114714f1b3e8SDimitry Andric StackFrame::GetValueObjectForFrameVariable(const VariableSP &variable_sp,
114814f1b3e8SDimitry Andric                                            DynamicValueType use_dynamic) {
1149f034231aSEd Maste   ValueObjectSP valobj_sp;
115008e8dd7bSDimitry Andric   { // Scope for stack frame mutex.  We need to drop this mutex before we figure
115108e8dd7bSDimitry Andric     // out the dynamic value.  That will require converting the StackID in the
115208e8dd7bSDimitry Andric     // VO back to a StackFrame, which will in turn require locking the
115308e8dd7bSDimitry Andric     // StackFrameList.  If we still hold the StackFrame mutex, we could suffer
115408e8dd7bSDimitry Andric     // lock inversion against the pattern of getting the StackFrameList and
115508e8dd7bSDimitry Andric     // then the stack frame, which is fairly common.
115608e8dd7bSDimitry Andric     std::lock_guard<std::recursive_mutex> guard(m_mutex);
115794994d37SDimitry Andric     if (IsHistorical()) {
1158f21a844fSEd Maste       return valobj_sp;
1159f21a844fSEd Maste     }
1160e3b55780SDimitry Andric     VariableList *var_list = GetVariableList(true, nullptr);
116114f1b3e8SDimitry Andric     if (var_list) {
1162f034231aSEd Maste       // Make sure the variable is a frame variable
1163f034231aSEd Maste       const uint32_t var_idx = var_list->FindIndexForVariable(variable_sp.get());
1164f034231aSEd Maste       const uint32_t num_variables = var_list->GetSize();
116514f1b3e8SDimitry Andric       if (var_idx < num_variables) {
1166f034231aSEd Maste         valobj_sp = m_variable_list_value_objects.GetValueObjectAtIndex(var_idx);
116714f1b3e8SDimitry Andric         if (!valobj_sp) {
1168f034231aSEd Maste           if (m_variable_list_value_objects.GetSize() < num_variables)
1169f034231aSEd Maste             m_variable_list_value_objects.Resize(num_variables);
1170f034231aSEd Maste           valobj_sp = ValueObjectVariable::Create(this, variable_sp);
117108e8dd7bSDimitry Andric           m_variable_list_value_objects.SetValueObjectAtIndex(var_idx,
117208e8dd7bSDimitry Andric                                                               valobj_sp);
1173f034231aSEd Maste         }
1174f034231aSEd Maste       }
1175f034231aSEd Maste     }
117608e8dd7bSDimitry Andric   } // End of StackFrame mutex scope.
117714f1b3e8SDimitry Andric   if (use_dynamic != eNoDynamicValues && valobj_sp) {
1178f034231aSEd Maste     ValueObjectSP dynamic_sp = valobj_sp->GetDynamicValue(use_dynamic);
1179f034231aSEd Maste     if (dynamic_sp)
1180f034231aSEd Maste       return dynamic_sp;
1181f034231aSEd Maste   }
1182f034231aSEd Maste   return valobj_sp;
1183f034231aSEd Maste }
1184f034231aSEd Maste 
IsInlined()118514f1b3e8SDimitry Andric bool StackFrame::IsInlined() {
1186f3fbd1c0SDimitry Andric   if (m_sc.block == nullptr)
1187f034231aSEd Maste     GetSymbolContext(eSymbolContextBlock);
1188f034231aSEd Maste   if (m_sc.block)
1189f3fbd1c0SDimitry Andric     return m_sc.block->GetContainingInlinedBlock() != nullptr;
1190f034231aSEd Maste   return false;
1191f034231aSEd Maste }
1192f034231aSEd Maste 
IsHistorical() const119394994d37SDimitry Andric bool StackFrame::IsHistorical() const {
119494994d37SDimitry Andric   return m_stack_frame_kind == StackFrame::Kind::History;
119594994d37SDimitry Andric }
119694994d37SDimitry Andric 
IsArtificial() const119794994d37SDimitry Andric bool StackFrame::IsArtificial() const {
119894994d37SDimitry Andric   return m_stack_frame_kind == StackFrame::Kind::Artificial;
119994994d37SDimitry Andric }
120094994d37SDimitry Andric 
GetLanguage()1201ac9a064cSDimitry Andric SourceLanguage StackFrame::GetLanguage() {
1202e81d9d49SDimitry Andric   CompileUnit *cu = GetSymbolContext(eSymbolContextCompUnit).comp_unit;
1203e81d9d49SDimitry Andric   if (cu)
1204e81d9d49SDimitry Andric     return cu->GetLanguage();
1205ac9a064cSDimitry Andric   return {};
1206e81d9d49SDimitry Andric }
1207e81d9d49SDimitry Andric 
GuessLanguage()1208ac9a064cSDimitry Andric SourceLanguage StackFrame::GuessLanguage() {
1209ac9a064cSDimitry Andric   SourceLanguage lang_type = GetLanguage();
1210f3fbd1c0SDimitry Andric 
121114f1b3e8SDimitry Andric   if (lang_type == eLanguageTypeUnknown) {
1212ac9a064cSDimitry Andric     SymbolContext sc =
1213ac9a064cSDimitry Andric         GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol);
1214ac9a064cSDimitry Andric     if (sc.function)
1215ac9a064cSDimitry Andric       lang_type = LanguageType(sc.function->GetMangled().GuessLanguage());
121674a628f7SDimitry Andric     else if (sc.symbol)
1217ac9a064cSDimitry Andric       lang_type = SourceLanguage(sc.symbol->GetMangled().GuessLanguage());
1218f3fbd1c0SDimitry Andric   }
1219f3fbd1c0SDimitry Andric 
1220f3fbd1c0SDimitry Andric   return lang_type;
1221f3fbd1c0SDimitry Andric }
1222f3fbd1c0SDimitry Andric 
122314f1b3e8SDimitry Andric namespace {
122414f1b3e8SDimitry Andric std::pair<const Instruction::Operand *, int64_t>
GetBaseExplainingValue(const Instruction::Operand & operand,RegisterContext & register_context,lldb::addr_t value)122514f1b3e8SDimitry Andric GetBaseExplainingValue(const Instruction::Operand &operand,
122614f1b3e8SDimitry Andric                        RegisterContext &register_context, lldb::addr_t value) {
122714f1b3e8SDimitry Andric   switch (operand.m_type) {
122814f1b3e8SDimitry Andric   case Instruction::Operand::Type::Dereference:
122914f1b3e8SDimitry Andric   case Instruction::Operand::Type::Immediate:
123014f1b3e8SDimitry Andric   case Instruction::Operand::Type::Invalid:
123114f1b3e8SDimitry Andric   case Instruction::Operand::Type::Product:
123214f1b3e8SDimitry Andric     // These are not currently interesting
123314f1b3e8SDimitry Andric     return std::make_pair(nullptr, 0);
123414f1b3e8SDimitry Andric   case Instruction::Operand::Type::Sum: {
123514f1b3e8SDimitry Andric     const Instruction::Operand *immediate_child = nullptr;
123614f1b3e8SDimitry Andric     const Instruction::Operand *variable_child = nullptr;
123714f1b3e8SDimitry Andric     if (operand.m_children[0].m_type == Instruction::Operand::Type::Immediate) {
123814f1b3e8SDimitry Andric       immediate_child = &operand.m_children[0];
123914f1b3e8SDimitry Andric       variable_child = &operand.m_children[1];
124014f1b3e8SDimitry Andric     } else if (operand.m_children[1].m_type ==
124114f1b3e8SDimitry Andric                Instruction::Operand::Type::Immediate) {
124214f1b3e8SDimitry Andric       immediate_child = &operand.m_children[1];
124314f1b3e8SDimitry Andric       variable_child = &operand.m_children[0];
124414f1b3e8SDimitry Andric     }
124514f1b3e8SDimitry Andric     if (!immediate_child) {
124614f1b3e8SDimitry Andric       return std::make_pair(nullptr, 0);
124714f1b3e8SDimitry Andric     }
124814f1b3e8SDimitry Andric     lldb::addr_t adjusted_value = value;
124914f1b3e8SDimitry Andric     if (immediate_child->m_negative) {
125014f1b3e8SDimitry Andric       adjusted_value += immediate_child->m_immediate;
125114f1b3e8SDimitry Andric     } else {
125214f1b3e8SDimitry Andric       adjusted_value -= immediate_child->m_immediate;
125314f1b3e8SDimitry Andric     }
125414f1b3e8SDimitry Andric     std::pair<const Instruction::Operand *, int64_t> base_and_offset =
125514f1b3e8SDimitry Andric         GetBaseExplainingValue(*variable_child, register_context,
125614f1b3e8SDimitry Andric                                adjusted_value);
125714f1b3e8SDimitry Andric     if (!base_and_offset.first) {
125814f1b3e8SDimitry Andric       return std::make_pair(nullptr, 0);
125914f1b3e8SDimitry Andric     }
126014f1b3e8SDimitry Andric     if (immediate_child->m_negative) {
126114f1b3e8SDimitry Andric       base_and_offset.second -= immediate_child->m_immediate;
126214f1b3e8SDimitry Andric     } else {
126314f1b3e8SDimitry Andric       base_and_offset.second += immediate_child->m_immediate;
126414f1b3e8SDimitry Andric     }
126514f1b3e8SDimitry Andric     return base_and_offset;
126614f1b3e8SDimitry Andric   }
126714f1b3e8SDimitry Andric   case Instruction::Operand::Type::Register: {
126814f1b3e8SDimitry Andric     const RegisterInfo *info =
126914f1b3e8SDimitry Andric         register_context.GetRegisterInfoByName(operand.m_register.AsCString());
127014f1b3e8SDimitry Andric     if (!info) {
127114f1b3e8SDimitry Andric       return std::make_pair(nullptr, 0);
127214f1b3e8SDimitry Andric     }
127314f1b3e8SDimitry Andric     RegisterValue reg_value;
127414f1b3e8SDimitry Andric     if (!register_context.ReadRegister(info, reg_value)) {
127514f1b3e8SDimitry Andric       return std::make_pair(nullptr, 0);
127614f1b3e8SDimitry Andric     }
127714f1b3e8SDimitry Andric     if (reg_value.GetAsUInt64() == value) {
127814f1b3e8SDimitry Andric       return std::make_pair(&operand, 0);
127914f1b3e8SDimitry Andric     } else {
128014f1b3e8SDimitry Andric       return std::make_pair(nullptr, 0);
128114f1b3e8SDimitry Andric     }
128214f1b3e8SDimitry Andric   }
128314f1b3e8SDimitry Andric   }
128414f1b3e8SDimitry Andric   return std::make_pair(nullptr, 0);
128514f1b3e8SDimitry Andric }
128614f1b3e8SDimitry Andric 
128714f1b3e8SDimitry Andric std::pair<const Instruction::Operand *, int64_t>
GetBaseExplainingDereference(const Instruction::Operand & operand,RegisterContext & register_context,lldb::addr_t addr)128814f1b3e8SDimitry Andric GetBaseExplainingDereference(const Instruction::Operand &operand,
128914f1b3e8SDimitry Andric                              RegisterContext &register_context,
129014f1b3e8SDimitry Andric                              lldb::addr_t addr) {
129114f1b3e8SDimitry Andric   if (operand.m_type == Instruction::Operand::Type::Dereference) {
129214f1b3e8SDimitry Andric     return GetBaseExplainingValue(operand.m_children[0], register_context,
129314f1b3e8SDimitry Andric                                   addr);
129414f1b3e8SDimitry Andric   }
129514f1b3e8SDimitry Andric   return std::make_pair(nullptr, 0);
129614f1b3e8SDimitry Andric }
1297ac9a064cSDimitry Andric } // namespace
129814f1b3e8SDimitry Andric 
GuessValueForAddress(lldb::addr_t addr)129914f1b3e8SDimitry Andric lldb::ValueObjectSP StackFrame::GuessValueForAddress(lldb::addr_t addr) {
130014f1b3e8SDimitry Andric   TargetSP target_sp = CalculateTarget();
130114f1b3e8SDimitry Andric 
130214f1b3e8SDimitry Andric   const ArchSpec &target_arch = target_sp->GetArchitecture();
130314f1b3e8SDimitry Andric 
130414f1b3e8SDimitry Andric   AddressRange pc_range;
130514f1b3e8SDimitry Andric   pc_range.GetBaseAddress() = GetFrameCodeAddress();
130614f1b3e8SDimitry Andric   pc_range.SetByteSize(target_arch.GetMaximumOpcodeByteSize());
130714f1b3e8SDimitry Andric 
130814f1b3e8SDimitry Andric   const char *plugin_name = nullptr;
130914f1b3e8SDimitry Andric   const char *flavor = nullptr;
1310344a3780SDimitry Andric   const bool force_live_memory = true;
131114f1b3e8SDimitry Andric 
1312cfca06d7SDimitry Andric   DisassemblerSP disassembler_sp =
1313cfca06d7SDimitry Andric       Disassembler::DisassembleRange(target_arch, plugin_name, flavor,
1314344a3780SDimitry Andric                                      *target_sp, pc_range, force_live_memory);
131514f1b3e8SDimitry Andric 
131674a628f7SDimitry Andric   if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) {
131714f1b3e8SDimitry Andric     return ValueObjectSP();
131814f1b3e8SDimitry Andric   }
131914f1b3e8SDimitry Andric 
132014f1b3e8SDimitry Andric   InstructionSP instruction_sp =
132114f1b3e8SDimitry Andric       disassembler_sp->GetInstructionList().GetInstructionAtIndex(0);
132214f1b3e8SDimitry Andric 
132314f1b3e8SDimitry Andric   llvm::SmallVector<Instruction::Operand, 3> operands;
132414f1b3e8SDimitry Andric 
132514f1b3e8SDimitry Andric   if (!instruction_sp->ParseOperands(operands)) {
132614f1b3e8SDimitry Andric     return ValueObjectSP();
132714f1b3e8SDimitry Andric   }
132814f1b3e8SDimitry Andric 
132914f1b3e8SDimitry Andric   RegisterContextSP register_context_sp = GetRegisterContext();
133014f1b3e8SDimitry Andric 
133114f1b3e8SDimitry Andric   if (!register_context_sp) {
133214f1b3e8SDimitry Andric     return ValueObjectSP();
133314f1b3e8SDimitry Andric   }
133414f1b3e8SDimitry Andric 
133514f1b3e8SDimitry Andric   for (const Instruction::Operand &operand : operands) {
133614f1b3e8SDimitry Andric     std::pair<const Instruction::Operand *, int64_t> base_and_offset =
133714f1b3e8SDimitry Andric         GetBaseExplainingDereference(operand, *register_context_sp, addr);
133814f1b3e8SDimitry Andric 
133914f1b3e8SDimitry Andric     if (!base_and_offset.first) {
134014f1b3e8SDimitry Andric       continue;
134114f1b3e8SDimitry Andric     }
134214f1b3e8SDimitry Andric 
134314f1b3e8SDimitry Andric     switch (base_and_offset.first->m_type) {
134414f1b3e8SDimitry Andric     case Instruction::Operand::Type::Immediate: {
134514f1b3e8SDimitry Andric       lldb_private::Address addr;
134614f1b3e8SDimitry Andric       if (target_sp->ResolveLoadAddress(base_and_offset.first->m_immediate +
134714f1b3e8SDimitry Andric                                             base_and_offset.second,
134814f1b3e8SDimitry Andric                                         addr)) {
1349ead24645SDimitry Andric         auto c_type_system_or_err =
1350ead24645SDimitry Andric             target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeC);
1351ead24645SDimitry Andric         if (auto err = c_type_system_or_err.takeError()) {
1352145449b1SDimitry Andric           LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), std::move(err),
13537fa27ce4SDimitry Andric                          "Unable to guess value for given address: {0}");
135414f1b3e8SDimitry Andric           return ValueObjectSP();
135514f1b3e8SDimitry Andric         } else {
1356e3b55780SDimitry Andric           auto ts = *c_type_system_or_err;
1357e3b55780SDimitry Andric           if (!ts)
1358e3b55780SDimitry Andric             return {};
135914f1b3e8SDimitry Andric           CompilerType void_ptr_type =
1360e3b55780SDimitry Andric               ts->GetBasicTypeFromAST(lldb::BasicType::eBasicTypeChar)
136114f1b3e8SDimitry Andric                   .GetPointerType();
136214f1b3e8SDimitry Andric           return ValueObjectMemory::Create(this, "", addr, void_ptr_type);
136314f1b3e8SDimitry Andric         }
136414f1b3e8SDimitry Andric       } else {
136514f1b3e8SDimitry Andric         return ValueObjectSP();
136614f1b3e8SDimitry Andric       }
136714f1b3e8SDimitry Andric       break;
136814f1b3e8SDimitry Andric     }
136914f1b3e8SDimitry Andric     case Instruction::Operand::Type::Register: {
137014f1b3e8SDimitry Andric       return GuessValueForRegisterAndOffset(base_and_offset.first->m_register,
137114f1b3e8SDimitry Andric                                             base_and_offset.second);
137214f1b3e8SDimitry Andric     }
137314f1b3e8SDimitry Andric     default:
137414f1b3e8SDimitry Andric       return ValueObjectSP();
137514f1b3e8SDimitry Andric     }
137614f1b3e8SDimitry Andric   }
137714f1b3e8SDimitry Andric 
137814f1b3e8SDimitry Andric   return ValueObjectSP();
137914f1b3e8SDimitry Andric }
138014f1b3e8SDimitry Andric 
138114f1b3e8SDimitry Andric namespace {
GetValueForOffset(StackFrame & frame,ValueObjectSP & parent,int64_t offset)138214f1b3e8SDimitry Andric ValueObjectSP GetValueForOffset(StackFrame &frame, ValueObjectSP &parent,
138314f1b3e8SDimitry Andric                                 int64_t offset) {
138414f1b3e8SDimitry Andric   if (offset < 0 || uint64_t(offset) >= parent->GetByteSize()) {
138514f1b3e8SDimitry Andric     return ValueObjectSP();
138614f1b3e8SDimitry Andric   }
138714f1b3e8SDimitry Andric 
138814f1b3e8SDimitry Andric   if (parent->IsPointerOrReferenceType()) {
138914f1b3e8SDimitry Andric     return parent;
139014f1b3e8SDimitry Andric   }
139114f1b3e8SDimitry Andric 
1392ac9a064cSDimitry Andric   for (int ci = 0, ce = parent->GetNumChildrenIgnoringErrors(); ci != ce;
1393ac9a064cSDimitry Andric        ++ci) {
13947fa27ce4SDimitry Andric     ValueObjectSP child_sp = parent->GetChildAtIndex(ci);
139514f1b3e8SDimitry Andric 
139614f1b3e8SDimitry Andric     if (!child_sp) {
139714f1b3e8SDimitry Andric       return ValueObjectSP();
139814f1b3e8SDimitry Andric     }
139914f1b3e8SDimitry Andric 
140014f1b3e8SDimitry Andric     int64_t child_offset = child_sp->GetByteOffset();
1401145449b1SDimitry Andric     int64_t child_size = child_sp->GetByteSize().value_or(0);
140214f1b3e8SDimitry Andric 
140314f1b3e8SDimitry Andric     if (offset >= child_offset && offset < (child_offset + child_size)) {
140414f1b3e8SDimitry Andric       return GetValueForOffset(frame, child_sp, offset - child_offset);
140514f1b3e8SDimitry Andric     }
140614f1b3e8SDimitry Andric   }
140714f1b3e8SDimitry Andric 
140814f1b3e8SDimitry Andric   if (offset == 0) {
140914f1b3e8SDimitry Andric     return parent;
141014f1b3e8SDimitry Andric   } else {
141114f1b3e8SDimitry Andric     return ValueObjectSP();
141214f1b3e8SDimitry Andric   }
141314f1b3e8SDimitry Andric }
141414f1b3e8SDimitry Andric 
GetValueForDereferincingOffset(StackFrame & frame,ValueObjectSP & base,int64_t offset)141514f1b3e8SDimitry Andric ValueObjectSP GetValueForDereferincingOffset(StackFrame &frame,
141614f1b3e8SDimitry Andric                                              ValueObjectSP &base,
141714f1b3e8SDimitry Andric                                              int64_t offset) {
141814f1b3e8SDimitry Andric   // base is a pointer to something
1419f73363f1SDimitry Andric   // offset is the thing to add to the pointer We return the most sensible
1420f73363f1SDimitry Andric   // ValueObject for the result of *(base+offset)
142114f1b3e8SDimitry Andric 
142214f1b3e8SDimitry Andric   if (!base->IsPointerOrReferenceType()) {
142314f1b3e8SDimitry Andric     return ValueObjectSP();
142414f1b3e8SDimitry Andric   }
142514f1b3e8SDimitry Andric 
1426b76161e4SDimitry Andric   Status error;
142714f1b3e8SDimitry Andric   ValueObjectSP pointee = base->Dereference(error);
142814f1b3e8SDimitry Andric 
142914f1b3e8SDimitry Andric   if (!pointee) {
143014f1b3e8SDimitry Andric     return ValueObjectSP();
143114f1b3e8SDimitry Andric   }
143214f1b3e8SDimitry Andric 
143314f1b3e8SDimitry Andric   if (offset >= 0 && uint64_t(offset) >= pointee->GetByteSize()) {
1434145449b1SDimitry Andric     int64_t index = offset / pointee->GetByteSize().value_or(1);
1435145449b1SDimitry Andric     offset = offset % pointee->GetByteSize().value_or(1);
143614f1b3e8SDimitry Andric     const bool can_create = true;
143714f1b3e8SDimitry Andric     pointee = base->GetSyntheticArrayMember(index, can_create);
143814f1b3e8SDimitry Andric   }
143914f1b3e8SDimitry Andric 
144014f1b3e8SDimitry Andric   if (!pointee || error.Fail()) {
144114f1b3e8SDimitry Andric     return ValueObjectSP();
144214f1b3e8SDimitry Andric   }
144314f1b3e8SDimitry Andric 
144414f1b3e8SDimitry Andric   return GetValueForOffset(frame, pointee, offset);
144514f1b3e8SDimitry Andric }
144614f1b3e8SDimitry Andric 
144714f1b3e8SDimitry Andric /// Attempt to reconstruct the ValueObject for the address contained in a
144814f1b3e8SDimitry Andric /// given register plus an offset.
144914f1b3e8SDimitry Andric ///
14506f8fc217SDimitry Andric /// \param [in] frame
145114f1b3e8SDimitry Andric ///   The current stack frame.
145214f1b3e8SDimitry Andric ///
14536f8fc217SDimitry Andric /// \param [in] reg
145414f1b3e8SDimitry Andric ///   The register.
145514f1b3e8SDimitry Andric ///
14566f8fc217SDimitry Andric /// \param [in] offset
145714f1b3e8SDimitry Andric ///   The offset from the register.
145814f1b3e8SDimitry Andric ///
14595f29bb8aSDimitry Andric /// \param [in] disassembler
146014f1b3e8SDimitry Andric ///   A disassembler containing instructions valid up to the current PC.
146114f1b3e8SDimitry Andric ///
14625f29bb8aSDimitry Andric /// \param [in] variables
146314f1b3e8SDimitry Andric ///   The variable list from the current frame,
146414f1b3e8SDimitry Andric ///
14655f29bb8aSDimitry Andric /// \param [in] pc
146614f1b3e8SDimitry Andric ///   The program counter for the instruction considered the 'user'.
146714f1b3e8SDimitry Andric ///
14685f29bb8aSDimitry Andric /// \return
146914f1b3e8SDimitry Andric ///   A string describing the base for the ExpressionPath.  This could be a
147014f1b3e8SDimitry Andric ///     variable, a register value, an argument, or a function return value.
147114f1b3e8SDimitry Andric ///   The ValueObject if found.  If valid, it has a valid ExpressionPath.
DoGuessValueAt(StackFrame & frame,ConstString reg,int64_t offset,Disassembler & disassembler,VariableList & variables,const Address & pc)147214f1b3e8SDimitry Andric lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg,
147314f1b3e8SDimitry Andric                                    int64_t offset, Disassembler &disassembler,
147414f1b3e8SDimitry Andric                                    VariableList &variables, const Address &pc) {
147514f1b3e8SDimitry Andric   // Example of operation for Intel:
147614f1b3e8SDimitry Andric   //
147714f1b3e8SDimitry Andric   // +14: movq   -0x8(%rbp), %rdi
147814f1b3e8SDimitry Andric   // +18: movq   0x8(%rdi), %rdi
147914f1b3e8SDimitry Andric   // +22: addl   0x4(%rdi), %eax
148014f1b3e8SDimitry Andric   //
148114f1b3e8SDimitry Andric   // f, a pointer to a struct, is known to be at -0x8(%rbp).
148214f1b3e8SDimitry Andric   //
1483f73363f1SDimitry Andric   // DoGuessValueAt(frame, rdi, 4, dis, vars, 0x22) finds the instruction at
1484f73363f1SDimitry Andric   // +18 that assigns to rdi, and calls itself recursively for that dereference
148514f1b3e8SDimitry Andric   //   DoGuessValueAt(frame, rdi, 8, dis, vars, 0x18) finds the instruction at
148614f1b3e8SDimitry Andric   //   +14 that assigns to rdi, and calls itself recursively for that
1487cfca06d7SDimitry Andric   //   dereference
148814f1b3e8SDimitry Andric   //     DoGuessValueAt(frame, rbp, -8, dis, vars, 0x14) finds "f" in the
148914f1b3e8SDimitry Andric   //     variable list.
149014f1b3e8SDimitry Andric   //     Returns a ValueObject for f.  (That's what was stored at rbp-8 at +14)
149114f1b3e8SDimitry Andric   //   Returns a ValueObject for *(f+8) or f->b (That's what was stored at rdi+8
149214f1b3e8SDimitry Andric   //   at +18)
149314f1b3e8SDimitry Andric   // Returns a ValueObject for *(f->b+4) or f->b->a (That's what was stored at
149414f1b3e8SDimitry Andric   // rdi+4 at +22)
149514f1b3e8SDimitry Andric 
149614f1b3e8SDimitry Andric   // First, check the variable list to see if anything is at the specified
149714f1b3e8SDimitry Andric   // location.
149814f1b3e8SDimitry Andric 
149914f1b3e8SDimitry Andric   using namespace OperandMatchers;
150014f1b3e8SDimitry Andric 
150114f1b3e8SDimitry Andric   const RegisterInfo *reg_info =
150214f1b3e8SDimitry Andric       frame.GetRegisterContext()->GetRegisterInfoByName(reg.AsCString());
150314f1b3e8SDimitry Andric   if (!reg_info) {
150414f1b3e8SDimitry Andric     return ValueObjectSP();
150514f1b3e8SDimitry Andric   }
150614f1b3e8SDimitry Andric 
150714f1b3e8SDimitry Andric   Instruction::Operand op =
150814f1b3e8SDimitry Andric       offset ? Instruction::Operand::BuildDereference(
150914f1b3e8SDimitry Andric                    Instruction::Operand::BuildSum(
151014f1b3e8SDimitry Andric                        Instruction::Operand::BuildRegister(reg),
151114f1b3e8SDimitry Andric                        Instruction::Operand::BuildImmediate(offset)))
151214f1b3e8SDimitry Andric              : Instruction::Operand::BuildDereference(
151314f1b3e8SDimitry Andric                    Instruction::Operand::BuildRegister(reg));
151414f1b3e8SDimitry Andric 
1515706b4fc4SDimitry Andric   for (VariableSP var_sp : variables) {
15161f917f69SDimitry Andric     if (var_sp->LocationExpressionList().MatchesOperand(frame, op))
151714f1b3e8SDimitry Andric       return frame.GetValueObjectForFrameVariable(var_sp, eNoDynamicValues);
151814f1b3e8SDimitry Andric   }
151914f1b3e8SDimitry Andric 
152014f1b3e8SDimitry Andric   const uint32_t current_inst =
152114f1b3e8SDimitry Andric       disassembler.GetInstructionList().GetIndexOfInstructionAtAddress(pc);
152214f1b3e8SDimitry Andric   if (current_inst == UINT32_MAX) {
152314f1b3e8SDimitry Andric     return ValueObjectSP();
152414f1b3e8SDimitry Andric   }
152514f1b3e8SDimitry Andric 
152614f1b3e8SDimitry Andric   for (uint32_t ii = current_inst - 1; ii != (uint32_t)-1; --ii) {
152714f1b3e8SDimitry Andric     // This is not an exact algorithm, and it sacrifices accuracy for
1528f73363f1SDimitry Andric     // generality.  Recognizing "mov" and "ld" instructions –– and which
1529f73363f1SDimitry Andric     // are their source and destination operands -- is something the
1530f73363f1SDimitry Andric     // disassembler should do for us.
153114f1b3e8SDimitry Andric     InstructionSP instruction_sp =
153214f1b3e8SDimitry Andric         disassembler.GetInstructionList().GetInstructionAtIndex(ii);
153314f1b3e8SDimitry Andric 
153414f1b3e8SDimitry Andric     if (instruction_sp->IsCall()) {
153514f1b3e8SDimitry Andric       ABISP abi_sp = frame.CalculateProcess()->GetABI();
153614f1b3e8SDimitry Andric       if (!abi_sp) {
153714f1b3e8SDimitry Andric         continue;
153814f1b3e8SDimitry Andric       }
153914f1b3e8SDimitry Andric 
154014f1b3e8SDimitry Andric       const char *return_register_name;
154114f1b3e8SDimitry Andric       if (!abi_sp->GetPointerReturnRegister(return_register_name)) {
154214f1b3e8SDimitry Andric         continue;
154314f1b3e8SDimitry Andric       }
154414f1b3e8SDimitry Andric 
154514f1b3e8SDimitry Andric       const RegisterInfo *return_register_info =
154614f1b3e8SDimitry Andric           frame.GetRegisterContext()->GetRegisterInfoByName(
154714f1b3e8SDimitry Andric               return_register_name);
154814f1b3e8SDimitry Andric       if (!return_register_info) {
154914f1b3e8SDimitry Andric         continue;
155014f1b3e8SDimitry Andric       }
155114f1b3e8SDimitry Andric 
155214f1b3e8SDimitry Andric       int64_t offset = 0;
155314f1b3e8SDimitry Andric 
155414f1b3e8SDimitry Andric       if (!MatchUnaryOp(MatchOpType(Instruction::Operand::Type::Dereference),
155514f1b3e8SDimitry Andric                         MatchRegOp(*return_register_info))(op) &&
155614f1b3e8SDimitry Andric           !MatchUnaryOp(
155714f1b3e8SDimitry Andric               MatchOpType(Instruction::Operand::Type::Dereference),
155814f1b3e8SDimitry Andric               MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum),
155914f1b3e8SDimitry Andric                             MatchRegOp(*return_register_info),
156014f1b3e8SDimitry Andric                             FetchImmOp(offset)))(op)) {
156114f1b3e8SDimitry Andric         continue;
156214f1b3e8SDimitry Andric       }
156314f1b3e8SDimitry Andric 
156414f1b3e8SDimitry Andric       llvm::SmallVector<Instruction::Operand, 1> operands;
156514f1b3e8SDimitry Andric       if (!instruction_sp->ParseOperands(operands) || operands.size() != 1) {
156614f1b3e8SDimitry Andric         continue;
156714f1b3e8SDimitry Andric       }
156814f1b3e8SDimitry Andric 
156914f1b3e8SDimitry Andric       switch (operands[0].m_type) {
157014f1b3e8SDimitry Andric       default:
157114f1b3e8SDimitry Andric         break;
157214f1b3e8SDimitry Andric       case Instruction::Operand::Type::Immediate: {
157314f1b3e8SDimitry Andric         SymbolContext sc;
157414f1b3e8SDimitry Andric         Address load_address;
157514f1b3e8SDimitry Andric         if (!frame.CalculateTarget()->ResolveLoadAddress(
157614f1b3e8SDimitry Andric                 operands[0].m_immediate, load_address)) {
157714f1b3e8SDimitry Andric           break;
157814f1b3e8SDimitry Andric         }
157914f1b3e8SDimitry Andric         frame.CalculateTarget()->GetImages().ResolveSymbolContextForAddress(
158014f1b3e8SDimitry Andric             load_address, eSymbolContextFunction, sc);
158114f1b3e8SDimitry Andric         if (!sc.function) {
158214f1b3e8SDimitry Andric           break;
158314f1b3e8SDimitry Andric         }
158414f1b3e8SDimitry Andric         CompilerType function_type = sc.function->GetCompilerType();
158514f1b3e8SDimitry Andric         if (!function_type.IsFunctionType()) {
158614f1b3e8SDimitry Andric           break;
158714f1b3e8SDimitry Andric         }
158814f1b3e8SDimitry Andric         CompilerType return_type = function_type.GetFunctionReturnType();
158914f1b3e8SDimitry Andric         RegisterValue return_value;
159014f1b3e8SDimitry Andric         if (!frame.GetRegisterContext()->ReadRegister(return_register_info,
159114f1b3e8SDimitry Andric                                                       return_value)) {
159214f1b3e8SDimitry Andric           break;
159314f1b3e8SDimitry Andric         }
159414f1b3e8SDimitry Andric         std::string name_str(
159514f1b3e8SDimitry Andric             sc.function->GetName().AsCString("<unknown function>"));
159614f1b3e8SDimitry Andric         name_str.append("()");
159714f1b3e8SDimitry Andric         Address return_value_address(return_value.GetAsUInt64());
159814f1b3e8SDimitry Andric         ValueObjectSP return_value_sp = ValueObjectMemory::Create(
159914f1b3e8SDimitry Andric             &frame, name_str, return_value_address, return_type);
160014f1b3e8SDimitry Andric         return GetValueForDereferincingOffset(frame, return_value_sp, offset);
160114f1b3e8SDimitry Andric       }
160214f1b3e8SDimitry Andric       }
160314f1b3e8SDimitry Andric 
160414f1b3e8SDimitry Andric       continue;
160514f1b3e8SDimitry Andric     }
160614f1b3e8SDimitry Andric 
160714f1b3e8SDimitry Andric     llvm::SmallVector<Instruction::Operand, 2> operands;
160814f1b3e8SDimitry Andric     if (!instruction_sp->ParseOperands(operands) || operands.size() != 2) {
160914f1b3e8SDimitry Andric       continue;
161014f1b3e8SDimitry Andric     }
161114f1b3e8SDimitry Andric 
161214f1b3e8SDimitry Andric     Instruction::Operand *origin_operand = nullptr;
161314f1b3e8SDimitry Andric     auto clobbered_reg_matcher = [reg_info](const Instruction::Operand &op) {
161414f1b3e8SDimitry Andric       return MatchRegOp(*reg_info)(op) && op.m_clobbered;
161514f1b3e8SDimitry Andric     };
161614f1b3e8SDimitry Andric 
161714f1b3e8SDimitry Andric     if (clobbered_reg_matcher(operands[0])) {
161814f1b3e8SDimitry Andric       origin_operand = &operands[1];
161914f1b3e8SDimitry Andric     }
162014f1b3e8SDimitry Andric     else if (clobbered_reg_matcher(operands[1])) {
162114f1b3e8SDimitry Andric       origin_operand = &operands[0];
162214f1b3e8SDimitry Andric     }
162314f1b3e8SDimitry Andric     else {
162414f1b3e8SDimitry Andric       continue;
162514f1b3e8SDimitry Andric     }
162614f1b3e8SDimitry Andric 
162714f1b3e8SDimitry Andric     // We have an origin operand.  Can we track its value down?
162814f1b3e8SDimitry Andric     ValueObjectSP source_path;
162914f1b3e8SDimitry Andric     ConstString origin_register;
163014f1b3e8SDimitry Andric     int64_t origin_offset = 0;
163114f1b3e8SDimitry Andric 
163214f1b3e8SDimitry Andric     if (FetchRegOp(origin_register)(*origin_operand)) {
163314f1b3e8SDimitry Andric       source_path = DoGuessValueAt(frame, origin_register, 0, disassembler,
163414f1b3e8SDimitry Andric                                    variables, instruction_sp->GetAddress());
163514f1b3e8SDimitry Andric     } else if (MatchUnaryOp(
163614f1b3e8SDimitry Andric                    MatchOpType(Instruction::Operand::Type::Dereference),
163714f1b3e8SDimitry Andric                    FetchRegOp(origin_register))(*origin_operand) ||
163814f1b3e8SDimitry Andric                MatchUnaryOp(
163914f1b3e8SDimitry Andric                    MatchOpType(Instruction::Operand::Type::Dereference),
164014f1b3e8SDimitry Andric                    MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum),
164114f1b3e8SDimitry Andric                                  FetchRegOp(origin_register),
164214f1b3e8SDimitry Andric                                  FetchImmOp(origin_offset)))(*origin_operand)) {
164314f1b3e8SDimitry Andric       source_path =
164414f1b3e8SDimitry Andric           DoGuessValueAt(frame, origin_register, origin_offset, disassembler,
164514f1b3e8SDimitry Andric                          variables, instruction_sp->GetAddress());
164614f1b3e8SDimitry Andric       if (!source_path) {
164714f1b3e8SDimitry Andric         continue;
164814f1b3e8SDimitry Andric       }
164914f1b3e8SDimitry Andric       source_path =
165014f1b3e8SDimitry Andric           GetValueForDereferincingOffset(frame, source_path, offset);
165114f1b3e8SDimitry Andric     }
165214f1b3e8SDimitry Andric 
165314f1b3e8SDimitry Andric     if (source_path) {
165414f1b3e8SDimitry Andric       return source_path;
165514f1b3e8SDimitry Andric     }
165614f1b3e8SDimitry Andric   }
165714f1b3e8SDimitry Andric 
165814f1b3e8SDimitry Andric   return ValueObjectSP();
165914f1b3e8SDimitry Andric }
166014f1b3e8SDimitry Andric }
166114f1b3e8SDimitry Andric 
GuessValueForRegisterAndOffset(ConstString reg,int64_t offset)166214f1b3e8SDimitry Andric lldb::ValueObjectSP StackFrame::GuessValueForRegisterAndOffset(ConstString reg,
166314f1b3e8SDimitry Andric                                                                int64_t offset) {
166414f1b3e8SDimitry Andric   TargetSP target_sp = CalculateTarget();
166514f1b3e8SDimitry Andric 
166614f1b3e8SDimitry Andric   const ArchSpec &target_arch = target_sp->GetArchitecture();
166714f1b3e8SDimitry Andric 
166814f1b3e8SDimitry Andric   Block *frame_block = GetFrameBlock();
166914f1b3e8SDimitry Andric 
167014f1b3e8SDimitry Andric   if (!frame_block) {
167114f1b3e8SDimitry Andric     return ValueObjectSP();
167214f1b3e8SDimitry Andric   }
167314f1b3e8SDimitry Andric 
167414f1b3e8SDimitry Andric   Function *function = frame_block->CalculateSymbolContextFunction();
167514f1b3e8SDimitry Andric   if (!function) {
167614f1b3e8SDimitry Andric     return ValueObjectSP();
167714f1b3e8SDimitry Andric   }
167814f1b3e8SDimitry Andric 
167914f1b3e8SDimitry Andric   AddressRange pc_range = function->GetAddressRange();
168014f1b3e8SDimitry Andric 
168114f1b3e8SDimitry Andric   if (GetFrameCodeAddress().GetFileAddress() <
168214f1b3e8SDimitry Andric           pc_range.GetBaseAddress().GetFileAddress() ||
168314f1b3e8SDimitry Andric       GetFrameCodeAddress().GetFileAddress() -
168414f1b3e8SDimitry Andric               pc_range.GetBaseAddress().GetFileAddress() >=
168514f1b3e8SDimitry Andric           pc_range.GetByteSize()) {
168614f1b3e8SDimitry Andric     return ValueObjectSP();
168714f1b3e8SDimitry Andric   }
168814f1b3e8SDimitry Andric 
168914f1b3e8SDimitry Andric   const char *plugin_name = nullptr;
169014f1b3e8SDimitry Andric   const char *flavor = nullptr;
1691344a3780SDimitry Andric   const bool force_live_memory = true;
1692cfca06d7SDimitry Andric   DisassemblerSP disassembler_sp =
1693cfca06d7SDimitry Andric       Disassembler::DisassembleRange(target_arch, plugin_name, flavor,
1694344a3780SDimitry Andric                                      *target_sp, pc_range, force_live_memory);
169514f1b3e8SDimitry Andric 
169614f1b3e8SDimitry Andric   if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) {
169714f1b3e8SDimitry Andric     return ValueObjectSP();
169814f1b3e8SDimitry Andric   }
169914f1b3e8SDimitry Andric 
170014f1b3e8SDimitry Andric   const bool get_file_globals = false;
1701e3b55780SDimitry Andric   VariableList *variables = GetVariableList(get_file_globals, nullptr);
170214f1b3e8SDimitry Andric 
170314f1b3e8SDimitry Andric   if (!variables) {
170414f1b3e8SDimitry Andric     return ValueObjectSP();
170514f1b3e8SDimitry Andric   }
170614f1b3e8SDimitry Andric 
170714f1b3e8SDimitry Andric   return DoGuessValueAt(*this, reg, offset, *disassembler_sp, *variables,
170814f1b3e8SDimitry Andric                         GetFrameCodeAddress());
170914f1b3e8SDimitry Andric }
171014f1b3e8SDimitry Andric 
FindVariable(ConstString name)171194994d37SDimitry Andric lldb::ValueObjectSP StackFrame::FindVariable(ConstString name) {
171294994d37SDimitry Andric   ValueObjectSP value_sp;
171394994d37SDimitry Andric 
171494994d37SDimitry Andric   if (!name)
171594994d37SDimitry Andric     return value_sp;
171694994d37SDimitry Andric 
171794994d37SDimitry Andric   TargetSP target_sp = CalculateTarget();
171894994d37SDimitry Andric   ProcessSP process_sp = CalculateProcess();
171994994d37SDimitry Andric 
172094994d37SDimitry Andric   if (!target_sp && !process_sp)
172194994d37SDimitry Andric     return value_sp;
172294994d37SDimitry Andric 
172394994d37SDimitry Andric   VariableList variable_list;
172494994d37SDimitry Andric   VariableSP var_sp;
172594994d37SDimitry Andric   SymbolContext sc(GetSymbolContext(eSymbolContextBlock));
172694994d37SDimitry Andric 
172794994d37SDimitry Andric   if (sc.block) {
172894994d37SDimitry Andric     const bool can_create = true;
172994994d37SDimitry Andric     const bool get_parent_variables = true;
173094994d37SDimitry Andric     const bool stop_if_block_is_inlined_function = true;
173194994d37SDimitry Andric 
173294994d37SDimitry Andric     if (sc.block->AppendVariables(
173394994d37SDimitry Andric             can_create, get_parent_variables, stop_if_block_is_inlined_function,
173494994d37SDimitry Andric             [this](Variable *v) { return v->IsInScope(this); },
173594994d37SDimitry Andric             &variable_list)) {
173694994d37SDimitry Andric       var_sp = variable_list.FindVariable(name);
173794994d37SDimitry Andric     }
173894994d37SDimitry Andric 
173994994d37SDimitry Andric     if (var_sp)
174094994d37SDimitry Andric       value_sp = GetValueObjectForFrameVariable(var_sp, eNoDynamicValues);
174194994d37SDimitry Andric   }
174294994d37SDimitry Andric 
174394994d37SDimitry Andric   return value_sp;
174494994d37SDimitry Andric }
174594994d37SDimitry Andric 
CalculateTarget()174614f1b3e8SDimitry Andric TargetSP StackFrame::CalculateTarget() {
1747f034231aSEd Maste   TargetSP target_sp;
1748f034231aSEd Maste   ThreadSP thread_sp(GetThread());
174914f1b3e8SDimitry Andric   if (thread_sp) {
1750f034231aSEd Maste     ProcessSP process_sp(thread_sp->CalculateProcess());
1751f034231aSEd Maste     if (process_sp)
1752f034231aSEd Maste       target_sp = process_sp->CalculateTarget();
1753f034231aSEd Maste   }
1754f034231aSEd Maste   return target_sp;
1755f034231aSEd Maste }
1756f034231aSEd Maste 
CalculateProcess()175714f1b3e8SDimitry Andric ProcessSP StackFrame::CalculateProcess() {
1758f034231aSEd Maste   ProcessSP process_sp;
1759f034231aSEd Maste   ThreadSP thread_sp(GetThread());
1760f034231aSEd Maste   if (thread_sp)
1761f034231aSEd Maste     process_sp = thread_sp->CalculateProcess();
1762f034231aSEd Maste   return process_sp;
1763f034231aSEd Maste }
1764f034231aSEd Maste 
CalculateThread()176514f1b3e8SDimitry Andric ThreadSP StackFrame::CalculateThread() { return GetThread(); }
1766f034231aSEd Maste 
CalculateStackFrame()176714f1b3e8SDimitry Andric StackFrameSP StackFrame::CalculateStackFrame() { return shared_from_this(); }
1768f034231aSEd Maste 
CalculateExecutionContext(ExecutionContext & exe_ctx)176914f1b3e8SDimitry Andric void StackFrame::CalculateExecutionContext(ExecutionContext &exe_ctx) {
1770f034231aSEd Maste   exe_ctx.SetContext(shared_from_this());
1771f034231aSEd Maste }
1772f034231aSEd Maste 
DumpUsingFormat(Stream & strm,const FormatEntity::Entry * format,llvm::StringRef frame_marker)1773b1c73532SDimitry Andric bool StackFrame::DumpUsingFormat(Stream &strm,
1774b1c73532SDimitry Andric                                  const FormatEntity::Entry *format,
1775b1c73532SDimitry Andric                                  llvm::StringRef frame_marker) {
1776b1c73532SDimitry Andric   GetSymbolContext(eSymbolContextEverything);
1777b1c73532SDimitry Andric   ExecutionContext exe_ctx(shared_from_this());
1778b1c73532SDimitry Andric   StreamString s;
1779b1c73532SDimitry Andric   s.PutCString(frame_marker);
1780b1c73532SDimitry Andric 
1781b1c73532SDimitry Andric   if (format && FormatEntity::Format(*format, s, &m_sc, &exe_ctx, nullptr,
1782b1c73532SDimitry Andric                                      nullptr, false, false)) {
1783b1c73532SDimitry Andric     strm.PutCString(s.GetString());
1784b1c73532SDimitry Andric     return true;
1785b1c73532SDimitry Andric   }
1786b1c73532SDimitry Andric   return false;
1787b1c73532SDimitry Andric }
1788b1c73532SDimitry Andric 
DumpUsingSettingsFormat(Stream * strm,bool show_unique,const char * frame_marker)17894befb1f9SDimitry Andric void StackFrame::DumpUsingSettingsFormat(Stream *strm, bool show_unique,
179014f1b3e8SDimitry Andric                                          const char *frame_marker) {
1791f3fbd1c0SDimitry Andric   if (strm == nullptr)
1792f034231aSEd Maste     return;
1793f034231aSEd Maste 
1794f034231aSEd Maste   ExecutionContext exe_ctx(shared_from_this());
1795f21a844fSEd Maste 
1796f3fbd1c0SDimitry Andric   const FormatEntity::Entry *frame_format = nullptr;
1797f034231aSEd Maste   Target *target = exe_ctx.GetTargetPtr();
17984befb1f9SDimitry Andric   if (target) {
17994befb1f9SDimitry Andric     if (show_unique) {
18004befb1f9SDimitry Andric       frame_format = target->GetDebugger().GetFrameFormatUnique();
18014befb1f9SDimitry Andric     } else {
1802f034231aSEd Maste       frame_format = target->GetDebugger().GetFrameFormat();
18034befb1f9SDimitry Andric     }
18044befb1f9SDimitry Andric   }
1805b1c73532SDimitry Andric   if (!DumpUsingFormat(*strm, frame_format, frame_marker)) {
1806f034231aSEd Maste     Dump(strm, true, false);
1807f034231aSEd Maste     strm->EOL();
1808f034231aSEd Maste   }
1809f034231aSEd Maste }
1810f034231aSEd Maste 
Dump(Stream * strm,bool show_frame_index,bool show_fullpaths)181114f1b3e8SDimitry Andric void StackFrame::Dump(Stream *strm, bool show_frame_index,
181214f1b3e8SDimitry Andric                       bool show_fullpaths) {
1813f3fbd1c0SDimitry Andric   if (strm == nullptr)
1814f034231aSEd Maste     return;
1815f034231aSEd Maste 
1816f034231aSEd Maste   if (show_frame_index)
1817f034231aSEd Maste     strm->Printf("frame #%u: ", m_frame_index);
1818f034231aSEd Maste   ExecutionContext exe_ctx(shared_from_this());
1819f034231aSEd Maste   Target *target = exe_ctx.GetTargetPtr();
1820f034231aSEd Maste   strm->Printf("0x%0*" PRIx64 " ",
182114f1b3e8SDimitry Andric                target ? (target->GetArchitecture().GetAddressByteSize() * 2)
182214f1b3e8SDimitry Andric                       : 16,
1823f034231aSEd Maste                GetFrameCodeAddress().GetLoadAddress(target));
1824f034231aSEd Maste   GetSymbolContext(eSymbolContextEverything);
1825f034231aSEd Maste   const bool show_module = true;
1826f034231aSEd Maste   const bool show_inline = true;
1827205afe67SEd Maste   const bool show_function_arguments = true;
18285e95aa85SEd Maste   const bool show_function_name = true;
182914f1b3e8SDimitry Andric   m_sc.DumpStopContext(strm, exe_ctx.GetBestExecutionContextScope(),
183014f1b3e8SDimitry Andric                        GetFrameCodeAddress(), show_fullpaths, show_module,
183114f1b3e8SDimitry Andric                        show_inline, show_function_arguments,
18325e95aa85SEd Maste                        show_function_name);
1833f034231aSEd Maste }
1834f034231aSEd Maste 
UpdateCurrentFrameFromPreviousFrame(StackFrame & prev_frame)183514f1b3e8SDimitry Andric void StackFrame::UpdateCurrentFrameFromPreviousFrame(StackFrame &prev_frame) {
1836f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
183714f1b3e8SDimitry Andric   assert(GetStackID() ==
183814f1b3e8SDimitry Andric          prev_frame.GetStackID()); // TODO: remove this after some testing
1839f034231aSEd Maste   m_variable_list_sp = prev_frame.m_variable_list_sp;
1840f034231aSEd Maste   m_variable_list_value_objects.Swap(prev_frame.m_variable_list_value_objects);
184114f1b3e8SDimitry Andric   if (!m_disassembly.GetString().empty()) {
184214f1b3e8SDimitry Andric     m_disassembly.Clear();
184314f1b3e8SDimitry Andric     m_disassembly.PutCString(prev_frame.m_disassembly.GetString());
184414f1b3e8SDimitry Andric   }
1845f034231aSEd Maste }
1846f034231aSEd Maste 
UpdatePreviousFrameFromCurrentFrame(StackFrame & curr_frame)184714f1b3e8SDimitry Andric void StackFrame::UpdatePreviousFrameFromCurrentFrame(StackFrame &curr_frame) {
1848f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
184914f1b3e8SDimitry Andric   assert(GetStackID() ==
185014f1b3e8SDimitry Andric          curr_frame.GetStackID());     // TODO: remove this after some testing
1851f034231aSEd Maste   m_id.SetPC(curr_frame.m_id.GetPC()); // Update the Stack ID PC value
1852f034231aSEd Maste   assert(GetThread() == curr_frame.GetThread());
1853f034231aSEd Maste   m_frame_index = curr_frame.m_frame_index;
1854f034231aSEd Maste   m_concrete_frame_index = curr_frame.m_concrete_frame_index;
1855f034231aSEd Maste   m_reg_context_sp = curr_frame.m_reg_context_sp;
1856f034231aSEd Maste   m_frame_code_addr = curr_frame.m_frame_code_addr;
1857cfca06d7SDimitry Andric   m_behaves_like_zeroth_frame = curr_frame.m_behaves_like_zeroth_frame;
185814f1b3e8SDimitry Andric   assert(!m_sc.target_sp || !curr_frame.m_sc.target_sp ||
185914f1b3e8SDimitry Andric          m_sc.target_sp.get() == curr_frame.m_sc.target_sp.get());
186014f1b3e8SDimitry Andric   assert(!m_sc.module_sp || !curr_frame.m_sc.module_sp ||
186114f1b3e8SDimitry Andric          m_sc.module_sp.get() == curr_frame.m_sc.module_sp.get());
186214f1b3e8SDimitry Andric   assert(m_sc.comp_unit == nullptr || curr_frame.m_sc.comp_unit == nullptr ||
186314f1b3e8SDimitry Andric          m_sc.comp_unit == curr_frame.m_sc.comp_unit);
186414f1b3e8SDimitry Andric   assert(m_sc.function == nullptr || curr_frame.m_sc.function == nullptr ||
186514f1b3e8SDimitry Andric          m_sc.function == curr_frame.m_sc.function);
1866f034231aSEd Maste   m_sc = curr_frame.m_sc;
1867f034231aSEd Maste   m_flags.Clear(GOT_FRAME_BASE | eSymbolContextEverything);
1868f034231aSEd Maste   m_flags.Set(m_sc.GetResolvedMask());
1869f034231aSEd Maste   m_frame_base.Clear();
1870f034231aSEd Maste   m_frame_base_error.Clear();
1871f034231aSEd Maste }
1872f034231aSEd Maste 
HasCachedData() const187314f1b3e8SDimitry Andric bool StackFrame::HasCachedData() const {
1874f3fbd1c0SDimitry Andric   if (m_variable_list_sp)
1875f034231aSEd Maste     return true;
1876f034231aSEd Maste   if (m_variable_list_value_objects.GetSize() > 0)
1877f034231aSEd Maste     return true;
1878f034231aSEd Maste   if (!m_disassembly.GetString().empty())
1879f034231aSEd Maste     return true;
1880f034231aSEd Maste   return false;
1881f034231aSEd Maste }
1882f034231aSEd Maste 
GetStatus(Stream & strm,bool show_frame_info,bool show_source,bool show_unique,const char * frame_marker)188314f1b3e8SDimitry Andric bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source,
18844befb1f9SDimitry Andric                            bool show_unique, const char *frame_marker) {
188514f1b3e8SDimitry Andric   if (show_frame_info) {
1886f034231aSEd Maste     strm.Indent();
18874befb1f9SDimitry Andric     DumpUsingSettingsFormat(&strm, show_unique, frame_marker);
1888f034231aSEd Maste   }
1889f034231aSEd Maste 
189014f1b3e8SDimitry Andric   if (show_source) {
1891f034231aSEd Maste     ExecutionContext exe_ctx(shared_from_this());
1892e81d9d49SDimitry Andric     bool have_source = false, have_debuginfo = false;
189314f1b3e8SDimitry Andric     Debugger::StopDisassemblyType disasm_display =
189414f1b3e8SDimitry Andric         Debugger::eStopDisassemblyTypeNever;
1895f034231aSEd Maste     Target *target = exe_ctx.GetTargetPtr();
189614f1b3e8SDimitry Andric     if (target) {
1897f034231aSEd Maste       Debugger &debugger = target->GetDebugger();
189814f1b3e8SDimitry Andric       const uint32_t source_lines_before =
189914f1b3e8SDimitry Andric           debugger.GetStopSourceLineCount(true);
190014f1b3e8SDimitry Andric       const uint32_t source_lines_after =
190114f1b3e8SDimitry Andric           debugger.GetStopSourceLineCount(false);
1902f034231aSEd Maste       disasm_display = debugger.GetStopDisassemblyDisplay();
1903f034231aSEd Maste 
1904f034231aSEd Maste       GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry);
190514f1b3e8SDimitry Andric       if (m_sc.comp_unit && m_sc.line_entry.IsValid()) {
1906e81d9d49SDimitry Andric         have_debuginfo = true;
190714f1b3e8SDimitry Andric         if (source_lines_before > 0 || source_lines_after > 0) {
190877fc4c14SDimitry Andric           uint32_t start_line = m_sc.line_entry.line;
190977fc4c14SDimitry Andric           if (!start_line && m_sc.function) {
191077fc4c14SDimitry Andric             FileSpec source_file;
191177fc4c14SDimitry Andric             m_sc.function->GetStartLineSourceInfo(source_file, start_line);
191277fc4c14SDimitry Andric           }
191377fc4c14SDimitry Andric 
191414f1b3e8SDimitry Andric           size_t num_lines =
191514f1b3e8SDimitry Andric               target->GetSourceManager().DisplaySourceLinesWithLineNumbers(
1916ac9a064cSDimitry Andric                   m_sc.line_entry.GetFile(), start_line, m_sc.line_entry.column,
191777fc4c14SDimitry Andric                   source_lines_before, source_lines_after, "->", &strm);
1918e81d9d49SDimitry Andric           if (num_lines != 0)
1919e81d9d49SDimitry Andric             have_source = true;
1920e81d9d49SDimitry Andric           // TODO: Give here a one time warning if source file is missing.
192177fc4c14SDimitry Andric           if (!m_sc.line_entry.line) {
192277fc4c14SDimitry Andric             ConstString fn_name = m_sc.GetFunctionName();
192377fc4c14SDimitry Andric 
192477fc4c14SDimitry Andric             if (!fn_name.IsEmpty())
192577fc4c14SDimitry Andric               strm.Printf(
192677fc4c14SDimitry Andric                   "Note: this address is compiler-generated code in function "
192777fc4c14SDimitry Andric                   "%s that has no source code associated with it.",
192877fc4c14SDimitry Andric                   fn_name.AsCString());
192977fc4c14SDimitry Andric             else
193077fc4c14SDimitry Andric               strm.Printf("Note: this address is compiler-generated code that "
193177fc4c14SDimitry Andric                           "has no source code associated with it.");
193277fc4c14SDimitry Andric             strm.EOL();
193377fc4c14SDimitry Andric           }
1934f034231aSEd Maste         }
1935f034231aSEd Maste       }
193614f1b3e8SDimitry Andric       switch (disasm_display) {
1937f034231aSEd Maste       case Debugger::eStopDisassemblyTypeNever:
1938f034231aSEd Maste         break;
1939f034231aSEd Maste 
1940e81d9d49SDimitry Andric       case Debugger::eStopDisassemblyTypeNoDebugInfo:
1941e81d9d49SDimitry Andric         if (have_debuginfo)
1942e81d9d49SDimitry Andric           break;
1943e3b55780SDimitry Andric         [[fallthrough]];
1944e81d9d49SDimitry Andric 
1945f034231aSEd Maste       case Debugger::eStopDisassemblyTypeNoSource:
1946f034231aSEd Maste         if (have_source)
1947f034231aSEd Maste           break;
1948e3b55780SDimitry Andric         [[fallthrough]];
1949e81d9d49SDimitry Andric 
1950f034231aSEd Maste       case Debugger::eStopDisassemblyTypeAlways:
195114f1b3e8SDimitry Andric         if (target) {
1952f034231aSEd Maste           const uint32_t disasm_lines = debugger.GetDisassemblyLineCount();
195314f1b3e8SDimitry Andric           if (disasm_lines > 0) {
1954f034231aSEd Maste             const ArchSpec &target_arch = target->GetArchitecture();
1955f3fbd1c0SDimitry Andric             const char *plugin_name = nullptr;
1956f3fbd1c0SDimitry Andric             const char *flavor = nullptr;
195714f1b3e8SDimitry Andric             const bool mixed_source_and_assembly = false;
195814f1b3e8SDimitry Andric             Disassembler::Disassemble(
195914f1b3e8SDimitry Andric                 target->GetDebugger(), target_arch, plugin_name, flavor,
1960cfca06d7SDimitry Andric                 exe_ctx, GetFrameCodeAddress(),
1961cfca06d7SDimitry Andric                 {Disassembler::Limit::Instructions, disasm_lines},
1962cfca06d7SDimitry Andric                 mixed_source_and_assembly, 0,
196314f1b3e8SDimitry Andric                 Disassembler::eOptionMarkPCAddress, strm);
1964f034231aSEd Maste           }
1965f034231aSEd Maste         }
1966f034231aSEd Maste         break;
1967f034231aSEd Maste       }
1968f034231aSEd Maste     }
1969f034231aSEd Maste   }
1970f034231aSEd Maste   return true;
1971f034231aSEd Maste }
197294994d37SDimitry Andric 
GetRecognizedFrame()197394994d37SDimitry Andric RecognizedStackFrameSP StackFrame::GetRecognizedFrame() {
197494994d37SDimitry Andric   if (!m_recognized_frame_sp) {
1975b60736ecSDimitry Andric     m_recognized_frame_sp = GetThread()
1976b60736ecSDimitry Andric                                 ->GetProcess()
1977b60736ecSDimitry Andric                                 ->GetTarget()
1978b60736ecSDimitry Andric                                 .GetFrameRecognizerManager()
1979b60736ecSDimitry Andric                                 .RecognizeFrame(CalculateStackFrame());
198094994d37SDimitry Andric   }
198194994d37SDimitry Andric   return m_recognized_frame_sp;
198294994d37SDimitry Andric }
1983