1 //===-- StackFrame.cpp ------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Target/StackFrame.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Core/Module.h"
17 #include "lldb/Core/Debugger.h"
18 #include "lldb/Core/Disassembler.h"
19 #include "lldb/Core/Value.h"
20 #include "lldb/Core/ValueObjectVariable.h"
21 #include "lldb/Symbol/Function.h"
22 #include "lldb/Symbol/VariableList.h"
23 #include "lldb/Target/ExecutionContext.h"
24 #include "lldb/Target/Process.h"
25 #include "lldb/Target/RegisterContext.h"
26 #include "lldb/Target/Target.h"
27 #include "lldb/Target/Thread.h"
28 
29 using namespace lldb;
30 using namespace lldb_private;
31 
32 // The first bits in the flags are reserved for the SymbolContext::Scope bits
33 // so we know if we have tried to look up information in our internal symbol
34 // context (m_sc) already.
35 #define RESOLVED_FRAME_CODE_ADDR        (uint32_t(eSymbolContextEverything + 1))
36 #define RESOLVED_FRAME_ID_SYMBOL_SCOPE  (RESOLVED_FRAME_CODE_ADDR << 1)
37 #define GOT_FRAME_BASE                  (RESOLVED_FRAME_ID_SYMBOL_SCOPE << 1)
38 #define RESOLVED_VARIABLES              (GOT_FRAME_BASE << 1)
39 
40 StackFrame::StackFrame
41 (
42     lldb::user_id_t frame_idx,
43     lldb::user_id_t unwind_frame_index,
44     Thread &thread,
45     lldb::addr_t cfa,
46     lldb::addr_t pc,
47     const SymbolContext *sc_ptr
48 ) :
49     m_frame_index (frame_idx),
50     m_unwind_frame_index (unwind_frame_index),
51     m_thread (thread),
52     m_reg_context_sp (),
53     m_id (pc, cfa, NULL),
54     m_frame_code_addr (NULL, pc),
55     m_sc (),
56     m_flags (),
57     m_frame_base (),
58     m_frame_base_error (),
59     m_variable_list_sp (),
60     m_variable_list_value_objects ()
61 {
62     if (sc_ptr != NULL)
63     {
64         m_sc = *sc_ptr;
65         m_flags.Set(m_sc.GetResolvedMask ());
66     }
67 }
68 
69 StackFrame::StackFrame
70 (
71     lldb::user_id_t frame_idx,
72     lldb::user_id_t unwind_frame_index,
73     Thread &thread,
74     const RegisterContextSP &reg_context_sp,
75     lldb::addr_t cfa,
76     lldb::addr_t pc,
77     const SymbolContext *sc_ptr
78 ) :
79     m_frame_index (frame_idx),
80     m_unwind_frame_index (unwind_frame_index),
81     m_thread (thread),
82     m_reg_context_sp (reg_context_sp),
83     m_id (pc, cfa, NULL),
84     m_frame_code_addr (NULL, pc),
85     m_sc (),
86     m_flags (),
87     m_frame_base (),
88     m_frame_base_error (),
89     m_variable_list_sp (),
90     m_variable_list_value_objects ()
91 {
92     if (sc_ptr != NULL)
93     {
94         m_sc = *sc_ptr;
95         m_flags.Set(m_sc.GetResolvedMask ());
96     }
97 
98     if (reg_context_sp && !m_sc.target_sp)
99     {
100         m_sc.target_sp = reg_context_sp->GetThread().GetProcess().GetTarget().GetSP();
101         m_flags.Set (eSymbolContextTarget);
102     }
103 }
104 
105 StackFrame::StackFrame
106 (
107     lldb::user_id_t frame_idx,
108     lldb::user_id_t unwind_frame_index,
109     Thread &thread,
110     const RegisterContextSP &reg_context_sp,
111     lldb::addr_t cfa,
112     const Address& pc_addr,
113     const SymbolContext *sc_ptr
114 ) :
115     m_frame_index (frame_idx),
116     m_unwind_frame_index (unwind_frame_index),
117     m_thread (thread),
118     m_reg_context_sp (reg_context_sp),
119     m_id (pc_addr.GetLoadAddress (&thread.GetProcess().GetTarget()), cfa, NULL),
120     m_frame_code_addr (pc_addr),
121     m_sc (),
122     m_flags (),
123     m_frame_base (),
124     m_frame_base_error (),
125     m_variable_list_sp (),
126     m_variable_list_value_objects ()
127 {
128     if (sc_ptr != NULL)
129     {
130         m_sc = *sc_ptr;
131         m_flags.Set(m_sc.GetResolvedMask ());
132     }
133 
134     if (m_sc.target_sp.get() == NULL && reg_context_sp)
135     {
136         m_sc.target_sp = reg_context_sp->GetThread().GetProcess().GetTarget().GetSP();
137         m_flags.Set (eSymbolContextTarget);
138     }
139 
140     Module *pc_module = pc_addr.GetModule();
141     if (m_sc.module_sp.get() == NULL || m_sc.module_sp.get() != pc_module)
142     {
143         if (pc_module)
144         {
145             m_sc.module_sp = pc_module->GetSP();
146             m_flags.Set (eSymbolContextModule);
147         }
148         else
149         {
150             m_sc.module_sp.reset();
151         }
152 
153     }
154 }
155 
156 
157 //----------------------------------------------------------------------
158 // Destructor
159 //----------------------------------------------------------------------
160 StackFrame::~StackFrame()
161 {
162 }
163 
164 StackID&
165 StackFrame::GetStackID()
166 {
167     // Make sure we have resolved the StackID object's symbol context scope if
168     // we already haven't looked it up.
169 
170     if (m_flags.IsClear (RESOLVED_FRAME_ID_SYMBOL_SCOPE))
171     {
172         if (m_id.GetSymbolContextScope ())
173         {
174             // We already have a symbol context scope, we just don't have our
175             // flag bit set.
176             m_flags.Set (RESOLVED_FRAME_ID_SYMBOL_SCOPE);
177         }
178         else
179         {
180             // Calculate the frame block and use this for the stack ID symbol
181             // context scope if we have one.
182             SymbolContextScope *scope = GetFrameBlock ();
183             if (scope == NULL)
184             {
185                 // We don't have a block, so use the symbol
186                 if (m_flags.IsClear (eSymbolContextSymbol))
187                     GetSymbolContext (eSymbolContextSymbol);
188 
189                 // It is ok if m_sc.symbol is NULL here
190                 scope = m_sc.symbol;
191             }
192             // Set the symbol context scope (the accessor will set the
193             // RESOLVED_FRAME_ID_SYMBOL_SCOPE bit in m_flags).
194             SetSymbolContextScope (scope);
195         }
196     }
197     return m_id;
198 }
199 
200 void
201 StackFrame::SetSymbolContextScope (SymbolContextScope *symbol_scope)
202 {
203     m_flags.Set (RESOLVED_FRAME_ID_SYMBOL_SCOPE);
204     m_id.SetSymbolContextScope (symbol_scope);
205 }
206 
207 Address&
208 StackFrame::GetFrameCodeAddress()
209 {
210     if (m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR) && !m_frame_code_addr.IsSectionOffset())
211     {
212         m_flags.Set (RESOLVED_FRAME_CODE_ADDR);
213 
214         // Resolve the PC into a temporary address because if ResolveLoadAddress
215         // fails to resolve the address, it will clear the address object...
216         Address resolved_pc;
217         if (m_thread.GetProcess().GetTarget().GetSectionLoadList().ResolveLoadAddress(m_frame_code_addr.GetOffset(), resolved_pc))
218         {
219             m_frame_code_addr = resolved_pc;
220             const Section *section = m_frame_code_addr.GetSection();
221             if (section)
222             {
223                 Module *module = section->GetModule();
224                 if (module)
225                 {
226                     m_sc.module_sp = module->GetSP();
227                     if (m_sc.module_sp)
228                         m_flags.Set(eSymbolContextModule);
229                 }
230             }
231         }
232     }
233     return m_frame_code_addr;
234 }
235 
236 void
237 StackFrame::ChangePC (addr_t pc)
238 {
239     m_frame_code_addr.SetOffset(pc);
240     m_frame_code_addr.SetSection(NULL);
241     m_sc.Clear();
242     m_flags.SetAllFlagBits(0);
243     m_thread.ClearStackFrames ();
244 }
245 
246 const char *
247 StackFrame::Disassemble ()
248 {
249     if (m_disassembly.GetSize() == 0)
250     {
251         ExecutionContext exe_ctx;
252         CalculateExecutionContext(exe_ctx);
253         Target &target = m_thread.GetProcess().GetTarget();
254         Disassembler::Disassemble (target.GetDebugger(),
255                                    target.GetArchitecture(),
256                                    exe_ctx,
257                                    0,
258                                    false,
259                                    m_disassembly);
260         if (m_disassembly.GetSize() == 0)
261             return NULL;
262     }
263     return m_disassembly.GetData();
264 }
265 
266 Block *
267 StackFrame::GetFrameBlock ()
268 {
269     if (m_sc.block == NULL && m_flags.IsClear (eSymbolContextBlock))
270         GetSymbolContext (eSymbolContextBlock);
271 
272     if (m_sc.block)
273     {
274         Block *inline_block = m_sc.block->GetContainingInlinedBlock();
275         if (inline_block)
276         {
277             // Use the block with the inlined function info
278             // as the frame block we want this frame to have only the variables
279             // for the inlined function and its non-inlined block child blocks.
280             return inline_block;
281         }
282         else
283         {
284             // This block is not contained withing any inlined function blocks
285             // with so we want to use the top most function block.
286             return &m_sc.function->GetBlock (false);
287         }
288     }
289     return NULL;
290 }
291 
292 //----------------------------------------------------------------------
293 // Get the symbol context if we already haven't done so by resolving the
294 // PC address as much as possible. This way when we pass around a
295 // StackFrame object, everyone will have as much information as
296 // possible and no one will ever have to look things up manually.
297 //----------------------------------------------------------------------
298 const SymbolContext&
299 StackFrame::GetSymbolContext (uint32_t resolve_scope)
300 {
301     // Copy our internal symbol context into "sc".
302     if ((m_flags.GetAllFlagBits() & resolve_scope) != resolve_scope)
303     {
304         // Resolve our PC to section offset if we haven't alreday done so
305         // and if we don't have a module. The resolved address section will
306         // contain the module to which it belongs
307         if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR))
308             GetFrameCodeAddress();
309 
310         // If this is not frame zero, then we need to subtract 1 from the PC
311         // value when doing address lookups since the PC will be on the
312         // instruction following the function call instruction...
313 
314         Address lookup_addr(GetFrameCodeAddress());
315         if (m_frame_index > 0 && lookup_addr.IsValid())
316         {
317             addr_t offset = lookup_addr.GetOffset();
318             if (offset > 0)
319                 lookup_addr.SetOffset(offset - 1);
320         }
321 
322 
323         uint32_t resolved = 0;
324         if (m_sc.module_sp)
325         {
326             // We have something in our stack frame symbol context, lets check
327             // if we haven't already tried to lookup one of those things. If we
328             // haven't then we will do the query.
329 
330             uint32_t actual_resolve_scope = 0;
331 
332             if (resolve_scope & eSymbolContextCompUnit)
333             {
334                 if (m_flags.IsClear (eSymbolContextCompUnit))
335                 {
336                     if (m_sc.comp_unit)
337                         resolved |= eSymbolContextCompUnit;
338                     else
339                         actual_resolve_scope |= eSymbolContextCompUnit;
340                 }
341             }
342 
343             if (resolve_scope & eSymbolContextFunction)
344             {
345                 if (m_flags.IsClear (eSymbolContextFunction))
346                 {
347                     if (m_sc.function)
348                         resolved |= eSymbolContextFunction;
349                     else
350                         actual_resolve_scope |= eSymbolContextFunction;
351                 }
352             }
353 
354             if (resolve_scope & eSymbolContextBlock)
355             {
356                 if (m_flags.IsClear (eSymbolContextBlock))
357                 {
358                     if (m_sc.block)
359                         resolved |= eSymbolContextBlock;
360                     else
361                         actual_resolve_scope |= eSymbolContextBlock;
362                 }
363             }
364 
365             if (resolve_scope & eSymbolContextSymbol)
366             {
367                 if (m_flags.IsClear (eSymbolContextSymbol))
368                 {
369                     if (m_sc.symbol)
370                         resolved |= eSymbolContextSymbol;
371                     else
372                         actual_resolve_scope |= eSymbolContextSymbol;
373                 }
374             }
375 
376             if (resolve_scope & eSymbolContextLineEntry)
377             {
378                 if (m_flags.IsClear (eSymbolContextLineEntry))
379                 {
380                     if (m_sc.line_entry.IsValid())
381                         resolved |= eSymbolContextLineEntry;
382                     else
383                         actual_resolve_scope |= eSymbolContextLineEntry;
384                 }
385             }
386 
387             if (actual_resolve_scope)
388             {
389                 // We might be resolving less information than what is already
390                 // in our current symbol context so resolve into a temporary
391                 // symbol context "sc" so we don't clear out data we have
392                 // already found in "m_sc"
393                 SymbolContext sc;
394                 // Set flags that indicate what we have tried to resolve
395                 resolved |= m_sc.module_sp->ResolveSymbolContextForAddress (lookup_addr, actual_resolve_scope, sc);
396                 // Only replace what we didn't already have as we may have
397                 // information for an inlined function scope that won't match
398                 // what a standard lookup by address would match
399                 if ((resolved & eSymbolContextCompUnit)  && m_sc.comp_unit == NULL)
400                     m_sc.comp_unit = sc.comp_unit;
401                 if ((resolved & eSymbolContextFunction)  && m_sc.function == NULL)
402                     m_sc.function = sc.function;
403                 if ((resolved & eSymbolContextBlock)     && m_sc.block == NULL)
404                     m_sc.block = sc.block;
405                 if ((resolved & eSymbolContextSymbol)    && m_sc.symbol == NULL)
406                     m_sc.symbol = sc.symbol;
407                 if ((resolved & eSymbolContextLineEntry) && !m_sc.line_entry.IsValid())
408                     m_sc.line_entry = sc.line_entry;
409 
410             }
411         }
412         else
413         {
414             // If we don't have a module, then we can't have the compile unit,
415             // function, block, line entry or symbol, so we can safely call
416             // ResolveSymbolContextForAddress with our symbol context member m_sc.
417             resolved |= m_thread.GetProcess().GetTarget().GetImages().ResolveSymbolContextForAddress (lookup_addr, resolve_scope, m_sc);
418         }
419 
420         // If the target was requested add that:
421         if (m_sc.target_sp.get() == NULL)
422         {
423             m_sc.target_sp = CalculateProcess()->GetTarget().GetSP();
424             if (m_sc.target_sp)
425                 resolved |= eSymbolContextTarget;
426         }
427 
428         // Update our internal flags so we remember what we have tried to locate so
429         // we don't have to keep trying when more calls to this function are made.
430         // We might have dug up more information that was requested (for example
431         // if we were asked to only get the block, we will have gotten the
432         // compile unit, and function) so set any additional bits that we resolved
433         m_flags.Set (resolve_scope | resolved);
434     }
435 
436     // Return the symbol context with everything that was possible to resolve
437     // resolved.
438     return m_sc;
439 }
440 
441 
442 VariableList *
443 StackFrame::GetVariableList (bool get_file_globals)
444 {
445     if (m_flags.IsClear(RESOLVED_VARIABLES))
446     {
447         m_flags.Set(RESOLVED_VARIABLES);
448 
449         Block *frame_block = GetFrameBlock();
450 
451         if (frame_block)
452         {
453             const bool get_child_variables = true;
454             const bool can_create = true;
455             m_variable_list_sp = frame_block->GetVariableList (get_child_variables, can_create);
456         }
457 
458         if (get_file_globals)
459         {
460             if (m_flags.IsClear (eSymbolContextCompUnit))
461                 GetSymbolContext (eSymbolContextCompUnit);
462 
463             if (m_sc.comp_unit)
464             {
465                 VariableListSP global_variable_list_sp (m_sc.comp_unit->GetVariableList(true));
466                 if (m_variable_list_sp)
467                     m_variable_list_sp->AddVariables (global_variable_list_sp.get());
468                 else
469                     m_variable_list_sp = global_variable_list_sp;
470             }
471         }
472     }
473     return m_variable_list_sp.get();
474 }
475 
476 
477 bool
478 StackFrame::GetFrameBaseValue (Scalar &frame_base, Error *error_ptr)
479 {
480     if (m_flags.IsClear(GOT_FRAME_BASE))
481     {
482         if (m_sc.function)
483         {
484             m_frame_base.Clear();
485             m_frame_base_error.Clear();
486 
487             m_flags.Set(GOT_FRAME_BASE);
488             ExecutionContext exe_ctx (&m_thread.GetProcess(), &m_thread, this);
489             Value expr_value;
490             addr_t loclist_base_addr = LLDB_INVALID_ADDRESS;
491             if (m_sc.function->GetFrameBaseExpression().IsLocationList())
492                 loclist_base_addr = m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (&m_thread.GetProcess().GetTarget());
493 
494             if (m_sc.function->GetFrameBaseExpression().Evaluate(&exe_ctx, NULL, loclist_base_addr, NULL, expr_value, &m_frame_base_error) == false)
495             {
496                 // We should really have an error if evaluate returns, but in case
497                 // we don't, lets set the error to something at least.
498                 if (m_frame_base_error.Success())
499                     m_frame_base_error.SetErrorString("Evaluation of the frame base expression failed.");
500             }
501             else
502             {
503                 m_frame_base = expr_value.ResolveValue(&exe_ctx, NULL);
504             }
505         }
506         else
507         {
508             m_frame_base_error.SetErrorString ("No function in symbol context.");
509         }
510     }
511 
512     if (m_frame_base_error.Success())
513         frame_base = m_frame_base;
514 
515     if (error_ptr)
516         *error_ptr = m_frame_base_error;
517     return m_frame_base_error.Success();
518 }
519 
520 RegisterContext *
521 StackFrame::GetRegisterContext ()
522 {
523     if (m_reg_context_sp.get() == NULL)
524         m_reg_context_sp.reset (m_thread.CreateRegisterContextForFrame (this));
525     return m_reg_context_sp.get();
526 }
527 
528 bool
529 StackFrame::HasDebugInformation ()
530 {
531     GetSymbolContext (eSymbolContextLineEntry);
532     return m_sc.line_entry.IsValid();
533 }
534 
535 
536 ValueObjectSP
537 StackFrame::GetValueObjectForFrameVariable (const VariableSP &variable_sp)
538 {
539     ValueObjectSP valobj_sp;
540     VariableList *var_list = GetVariableList (true);
541     if (var_list)
542     {
543         // Make sure the variable is a frame variable
544         const uint32_t var_idx = var_list->FindIndexForVariable (variable_sp.get());
545         const uint32_t num_variables = var_list->GetSize();
546         if (var_idx < num_variables)
547         {
548             valobj_sp = m_variable_list_value_objects.GetValueObjectAtIndex (var_idx);
549             if (valobj_sp.get() == NULL)
550             {
551                 if (m_variable_list_value_objects.GetSize() < num_variables)
552                     m_variable_list_value_objects.Resize(num_variables);
553                 valobj_sp.reset (new ValueObjectVariable (variable_sp));
554                 m_variable_list_value_objects.SetValueObjectAtIndex (var_idx, valobj_sp);
555             }
556         }
557     }
558     return valobj_sp;
559 }
560 
561 ValueObjectSP
562 StackFrame::TrackGlobalVariable (const VariableSP &variable_sp)
563 {
564     // Check to make sure we aren't already tracking this variable?
565     ValueObjectSP valobj_sp (GetValueObjectForFrameVariable (variable_sp));
566     if (!valobj_sp)
567     {
568         // We aren't already tracking this global
569         VariableList *var_list = GetVariableList (true);
570         // If this frame has no variables, create a new list
571         if (var_list == NULL)
572             m_variable_list_sp.reset (new VariableList());
573 
574         // Add the global/static variable to this frame
575         m_variable_list_sp->AddVariable (variable_sp);
576 
577         // Now make a value object for it so we can track its changes
578         valobj_sp = GetValueObjectForFrameVariable (variable_sp);
579     }
580     return valobj_sp;
581 }
582 
583 bool
584 StackFrame::IsInlined ()
585 {
586     if (m_sc.block == NULL)
587         GetSymbolContext (eSymbolContextBlock);
588     if (m_sc.block)
589         return m_sc.block->GetContainingInlinedBlock() != NULL;
590     return false;
591 }
592 
593 Target *
594 StackFrame::CalculateTarget ()
595 {
596     return m_thread.CalculateTarget();
597 }
598 
599 Process *
600 StackFrame::CalculateProcess ()
601 {
602     return m_thread.CalculateProcess();
603 }
604 
605 Thread *
606 StackFrame::CalculateThread ()
607 {
608     return &m_thread;
609 }
610 
611 StackFrame *
612 StackFrame::CalculateStackFrame ()
613 {
614     return this;
615 }
616 
617 
618 void
619 StackFrame::CalculateExecutionContext (ExecutionContext &exe_ctx)
620 {
621     m_thread.CalculateExecutionContext (exe_ctx);
622     exe_ctx.frame = this;
623 }
624 
625 void
626 StackFrame::DumpUsingSettingsFormat (Stream *strm)
627 {
628     if (strm == NULL)
629         return;
630 
631     GetSymbolContext(eSymbolContextEverything);
632     ExecutionContext exe_ctx;
633     CalculateExecutionContext(exe_ctx);
634     const char *end = NULL;
635     StreamString s;
636     const char *frame_format = m_thread.GetProcess().GetTarget().GetDebugger().GetFrameFormat();
637     if (frame_format && Debugger::FormatPrompt (frame_format, &m_sc, &exe_ctx, NULL, s, &end))
638     {
639         strm->Write(s.GetData(), s.GetSize());
640     }
641     else
642     {
643         Dump (strm, true, false);
644         strm->EOL();
645     }
646 }
647 
648 void
649 StackFrame::Dump (Stream *strm, bool show_frame_index, bool show_fullpaths)
650 {
651     if (strm == NULL)
652         return;
653 
654     if (show_frame_index)
655         strm->Printf("frame #%u: ", m_frame_index);
656     strm->Printf("0x%0*llx ", m_thread.GetProcess().GetAddressByteSize() * 2, GetFrameCodeAddress().GetLoadAddress(&m_thread.GetProcess().GetTarget()));
657     GetSymbolContext(eSymbolContextEverything);
658     const bool show_module = true;
659     const bool show_inline = true;
660     m_sc.DumpStopContext(strm, &m_thread.GetProcess(), GetFrameCodeAddress(), show_fullpaths, show_module, show_inline);
661 }
662 
663 void
664 StackFrame::UpdateCurrentFrameFromPreviousFrame (StackFrame &prev_frame)
665 {
666     assert (GetStackID() == prev_frame.GetStackID());    // TODO: remove this after some testing
667     m_variable_list_sp = prev_frame.m_variable_list_sp;
668     m_variable_list_value_objects.Swap (prev_frame.m_variable_list_value_objects);
669     if (!m_disassembly.GetString().empty())
670         m_disassembly.GetString().swap (m_disassembly.GetString());
671 }
672 
673 
674 void
675 StackFrame::UpdatePreviousFrameFromCurrentFrame (StackFrame &curr_frame)
676 {
677     assert (GetStackID() == curr_frame.GetStackID());        // TODO: remove this after some testing
678     m_id.SetPC (curr_frame.m_id.GetPC());       // Update the Stack ID PC value
679     assert (&m_thread == &curr_frame.m_thread);
680     m_frame_index = curr_frame.m_frame_index;
681     m_unwind_frame_index = curr_frame.m_unwind_frame_index;
682     m_reg_context_sp = curr_frame.m_reg_context_sp;
683     m_frame_code_addr = curr_frame.m_frame_code_addr;
684     assert (m_sc.target_sp.get() == NULL || curr_frame.m_sc.target_sp.get() == NULL || m_sc.target_sp.get() == curr_frame.m_sc.target_sp.get());
685     assert (m_sc.module_sp.get() == NULL || curr_frame.m_sc.module_sp.get() == NULL || m_sc.module_sp.get() == curr_frame.m_sc.module_sp.get());
686     assert (m_sc.comp_unit == NULL || curr_frame.m_sc.comp_unit == NULL || m_sc.comp_unit == curr_frame.m_sc.comp_unit);
687     assert (m_sc.function == NULL || curr_frame.m_sc.function == NULL || m_sc.function == curr_frame.m_sc.function);
688     m_sc = curr_frame.m_sc;
689     m_flags.Clear(GOT_FRAME_BASE | eSymbolContextEverything);
690     m_flags.Set (m_sc.GetResolvedMask());
691     m_frame_base.Clear();
692     m_frame_base_error.Clear();
693 }
694 
695 
696 bool
697 StackFrame::HasCachedData () const
698 {
699     if (m_variable_list_sp.get())
700         return true;
701     if (m_variable_list_value_objects.GetSize() > 0)
702         return true;
703     if (!m_disassembly.GetString().empty())
704         return true;
705     return false;
706 }
707 
708 lldb::StackFrameSP
709 StackFrame::GetSP ()
710 {
711     return m_thread.GetStackFrameSPForStackFramePtr (this);
712 }