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 ®_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 ®_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 ®ister_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 ®ister_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