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/Disassembler.h"
18 #include "lldb/Core/Value.h"
19 #include "lldb/Core/ValueObjectVariable.h"
20 #include "lldb/Symbol/Function.h"
21 #include "lldb/Symbol/VariableList.h"
22 #include "lldb/Target/ExecutionContext.h"
23 #include "lldb/Target/Process.h"
24 #include "lldb/Target/RegisterContext.h"
25 #include "lldb/Target/Target.h"
26 #include "lldb/Target/Thread.h"
27 
28 using namespace lldb;
29 using namespace lldb_private;
30 
31 // The first bits in the flags are reserved for the SymbolContext::Scope bits
32 // so we know if we have tried to look up information in our internal symbol
33 // context (m_sc) already.
34 #define RESOLVED_FRAME_CODE_ADDR        (uint32_t(eSymbolContextEverything + 1))
35 #define RESOLVED_FRAME_ID_START_ADDR    (RESOLVED_FRAME_CODE_ADDR << 1)
36 #define RESOLVED_FRAME_ID_SYMBOL_SCOPE  (RESOLVED_FRAME_ID_START_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 (LLDB_INVALID_ADDRESS, 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 (LLDB_INVALID_ADDRESS, 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 (LLDB_INVALID_ADDRESS, 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     if (m_sc.module_sp.get() == NULL && pc_addr.GetSection())
141     {
142         Module *pc_module = pc_addr.GetSection()->GetModule();
143         if (pc_module)
144         {
145             m_sc.module_sp = pc_module->GetSP();
146             m_flags.Set (eSymbolContextModule);
147         }
148     }
149 }
150 
151 
152 //----------------------------------------------------------------------
153 // Destructor
154 //----------------------------------------------------------------------
155 StackFrame::~StackFrame()
156 {
157 }
158 
159 StackID&
160 StackFrame::GetStackID()
161 {
162     // Make sure we have resolved our stack ID's start PC before we give
163     // it out to any external clients. This allows us to not have to lookup
164     // this information if it is never asked for.
165     if (m_flags.IsClear(RESOLVED_FRAME_ID_START_ADDR))
166     {
167         m_flags.Set (RESOLVED_FRAME_ID_START_ADDR);
168 
169         if (m_id.GetStartAddress() == LLDB_INVALID_ADDRESS)
170         {
171             // Resolve our PC to section offset if we haven't alreday done so
172             // and if we don't have a module. The resolved address section will
173             // contain the module to which it belongs.
174             if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR))
175                 GetFrameCodeAddress();
176 
177             if (GetSymbolContext (eSymbolContextFunction).function)
178             {
179                 m_id.SetStartAddress (m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (&m_thread.GetProcess()));
180             }
181             else if (GetSymbolContext (eSymbolContextSymbol).symbol)
182             {
183                 AddressRange *symbol_range_ptr = m_sc.symbol->GetAddressRangePtr();
184                 if (symbol_range_ptr)
185                     m_id.SetStartAddress(symbol_range_ptr->GetBaseAddress().GetLoadAddress (&m_thread.GetProcess()));
186             }
187 
188             // We didn't find a function or symbol, just use the frame code address
189             // which will be the same as the PC in the frame.
190             if (m_id.GetStartAddress() == LLDB_INVALID_ADDRESS)
191                 m_id.SetStartAddress (m_frame_code_addr.GetLoadAddress (&m_thread.GetProcess()));
192         }
193     }
194 
195     if (m_flags.IsClear (RESOLVED_FRAME_ID_SYMBOL_SCOPE))
196     {
197         if (m_id.GetSymbolContextScope ())
198         {
199             m_flags.Set (RESOLVED_FRAME_ID_SYMBOL_SCOPE);
200         }
201         else
202         {
203             GetSymbolContext (eSymbolContextFunction | eSymbolContextBlock);
204 
205             if (m_sc.block)
206             {
207                 Block *inline_block = m_sc.block->GetContainingInlinedBlock();
208                 if (inline_block)
209                 {
210                     // Use the block with the inlined function info
211                     // as the symbol context since we want this frame
212                     // to have only the variables for the inlined function
213                     SetSymbolContextScope (inline_block);
214                 }
215                 else
216                 {
217                     // This block is not inlined with means it has no
218                     // inlined parents either, so we want to use the top
219                     // most function block.
220                     SetSymbolContextScope (&m_sc.function->GetBlock(false));
221                 }
222             }
223             else
224             {
225                 // The current stack frame doesn't have a block. Check to see
226                 // if it has a symbol. If it does we will use this as the
227                 // symbol scope. It is ok if "m_sc.symbol" is NULL below as
228                 // it will set the symbol context to NULL and set the
229                 // RESOLVED_FRAME_ID_SYMBOL_SCOPE flag bit.
230                 GetSymbolContext (eSymbolContextSymbol);
231                 SetSymbolContextScope (m_sc.symbol);
232             }
233         }
234     }
235     return m_id;
236 }
237 
238 void
239 StackFrame::SetSymbolContextScope (SymbolContextScope *symbol_scope)
240 {
241     m_flags.Set (RESOLVED_FRAME_ID_SYMBOL_SCOPE);
242     m_id.SetSymbolContextScope (symbol_scope);
243 }
244 
245 Address&
246 StackFrame::GetFrameCodeAddress()
247 {
248     if (m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR) && !m_frame_code_addr.IsSectionOffset())
249     {
250         m_flags.Set (RESOLVED_FRAME_CODE_ADDR);
251 
252         // Resolve the PC into a temporary address because if ResolveLoadAddress
253         // fails to resolve the address, it will clear the address object...
254         Address resolved_pc;
255         if (m_thread.GetProcess().ResolveLoadAddress(m_frame_code_addr.GetOffset(), resolved_pc))
256         {
257             m_frame_code_addr = resolved_pc;
258             const Section *section = m_frame_code_addr.GetSection();
259             if (section)
260             {
261                 Module *module = section->GetModule();
262                 if (module)
263                 {
264                     m_sc.module_sp = module->GetSP();
265                     if (m_sc.module_sp)
266                         m_flags.Set(eSymbolContextModule);
267                 }
268             }
269         }
270     }
271     return m_frame_code_addr;
272 }
273 
274 void
275 StackFrame::ChangePC (addr_t pc)
276 {
277     m_frame_code_addr.SetOffset(pc);
278     m_frame_code_addr.SetSection(NULL);
279     m_sc.Clear();
280     m_flags.SetAllFlagBits(0);
281     m_thread.ClearStackFrames ();
282 }
283 
284 const char *
285 StackFrame::Disassemble ()
286 {
287     if (m_disassembly.GetSize() == 0)
288     {
289         ExecutionContext exe_ctx;
290         Calculate(exe_ctx);
291         Target &target = m_thread.GetProcess().GetTarget();
292         Disassembler::Disassemble (target.GetDebugger(),
293                                    target.GetArchitecture(),
294                                    exe_ctx,
295                                    0,
296                                    false,
297                                    m_disassembly);
298         if (m_disassembly.GetSize() == 0)
299             return NULL;
300     }
301     return m_disassembly.GetData();
302 }
303 
304 //----------------------------------------------------------------------
305 // Get the symbol context if we already haven't done so by resolving the
306 // PC address as much as possible. This way when we pass around a
307 // StackFrame object, everyone will have as much information as
308 // possible and no one will ever have to look things up manually.
309 //----------------------------------------------------------------------
310 const SymbolContext&
311 StackFrame::GetSymbolContext (uint32_t resolve_scope)
312 {
313     // Copy our internal symbol context into "sc".
314     if ((m_flags.GetAllFlagBits() & resolve_scope) != resolve_scope)
315     {
316         // Resolve our PC to section offset if we haven't alreday done so
317         // and if we don't have a module. The resolved address section will
318         // contain the module to which it belongs
319         if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR))
320             GetFrameCodeAddress();
321 
322         // If this is not frame zero, then we need to subtract 1 from the PC
323         // value when doing address lookups since the PC will be on the
324         // instruction following the function call instruction...
325 
326         Address lookup_addr(GetFrameCodeAddress());
327         if (m_frame_index > 0 && lookup_addr.IsValid())
328         {
329             addr_t offset = lookup_addr.GetOffset();
330             if (offset > 0)
331                 lookup_addr.SetOffset(offset - 1);
332         }
333 
334 
335         uint32_t resolved = 0;
336         if (m_sc.module_sp)
337         {
338             // We have something in our stack frame symbol context, lets check
339             // if we haven't already tried to lookup one of those things. If we
340             // haven't then we will do the query.
341 
342             uint32_t actual_resolve_scope = 0;
343 
344             if (resolve_scope & eSymbolContextCompUnit)
345             {
346                 if (m_flags.IsClear (eSymbolContextCompUnit))
347                 {
348                     if (m_sc.comp_unit)
349                         resolved |= eSymbolContextCompUnit;
350                     else
351                         actual_resolve_scope |= eSymbolContextCompUnit;
352                 }
353             }
354 
355             if (resolve_scope & eSymbolContextFunction)
356             {
357                 if (m_flags.IsClear (eSymbolContextFunction))
358                 {
359                     if (m_sc.function)
360                         resolved |= eSymbolContextFunction;
361                     else
362                         actual_resolve_scope |= eSymbolContextFunction;
363                 }
364             }
365 
366             if (resolve_scope & eSymbolContextBlock)
367             {
368                 if (m_flags.IsClear (eSymbolContextBlock))
369                 {
370                     if (m_sc.block)
371                         resolved |= eSymbolContextBlock;
372                     else
373                         actual_resolve_scope |= eSymbolContextBlock;
374                 }
375             }
376 
377             if (resolve_scope & eSymbolContextSymbol)
378             {
379                 if (m_flags.IsClear (eSymbolContextSymbol))
380                 {
381                     if (m_sc.symbol)
382                         resolved |= eSymbolContextSymbol;
383                     else
384                         actual_resolve_scope |= eSymbolContextSymbol;
385                 }
386             }
387 
388             if (resolve_scope & eSymbolContextLineEntry)
389             {
390                 if (m_flags.IsClear (eSymbolContextLineEntry))
391                 {
392                     if (m_sc.line_entry.IsValid())
393                         resolved |= eSymbolContextLineEntry;
394                     else
395                         actual_resolve_scope |= eSymbolContextLineEntry;
396                 }
397             }
398 
399             if (actual_resolve_scope)
400             {
401                 // We might be resolving less information than what is already
402                 // in our current symbol context so resolve into a temporary
403                 // symbol context "sc" so we don't clear out data we have
404                 // already found in "m_sc"
405                 SymbolContext sc;
406                 // Set flags that indicate what we have tried to resolve
407                 resolved |= m_sc.module_sp->ResolveSymbolContextForAddress (lookup_addr, actual_resolve_scope, sc);
408                 // Only replace what we didn't already have as we may have
409                 // information for an inlined function scope that won't match
410                 // what a standard lookup by address would match
411                 if ((resolved & eSymbolContextCompUnit)  && m_sc.comp_unit == NULL)
412                     m_sc.comp_unit = sc.comp_unit;
413                 if ((resolved & eSymbolContextFunction)  && m_sc.function == NULL)
414                     m_sc.function = sc.function;
415                 if ((resolved & eSymbolContextBlock)     && m_sc.block == NULL)
416                     m_sc.block = sc.block;
417                 if ((resolved & eSymbolContextSymbol)    && m_sc.symbol == NULL)
418                     m_sc.symbol = sc.symbol;
419                 if ((resolved & eSymbolContextLineEntry) && !m_sc.line_entry.IsValid())
420                     m_sc.line_entry = sc.line_entry;
421 
422             }
423         }
424         else
425         {
426             // If we don't have a module, then we can't have the compile unit,
427             // function, block, line entry or symbol, so we can safely call
428             // ResolveSymbolContextForAddress with our symbol context member m_sc.
429             resolved |= m_thread.GetProcess().GetTarget().GetImages().ResolveSymbolContextForAddress (lookup_addr, resolve_scope, m_sc);
430         }
431 
432         // If the target was requested add that:
433         if (m_sc.target_sp.get() == NULL)
434         {
435             m_sc.target_sp = CalculateProcess()->GetTarget().GetSP();
436             if (m_sc.target_sp)
437                 resolved |= eSymbolContextTarget;
438         }
439 
440         // Update our internal flags so we remember what we have tried to locate so
441         // we don't have to keep trying when more calls to this function are made.
442         // We might have dug up more information that was requested (for example
443         // if we were asked to only get the block, we will have gotten the
444         // compile unit, and function) so set any additional bits that we resolved
445         m_flags.Set (resolve_scope | resolved);
446     }
447 
448     // Return the symbol context with everything that was possible to resolve
449     // resolved.
450     return m_sc;
451 }
452 
453 
454 VariableList *
455 StackFrame::GetVariableList (bool get_file_globals)
456 {
457     if (m_flags.IsClear(RESOLVED_VARIABLES))
458     {
459         m_flags.Set(RESOLVED_VARIABLES);
460 
461         GetSymbolContext (eSymbolContextCompUnit |
462                           eSymbolContextFunction |
463                           eSymbolContextBlock);
464 
465         if (m_sc.block)
466         {
467             bool get_child_variables = true;
468             bool can_create = true;
469             m_variable_list_sp = m_sc.function->GetBlock (can_create).GetVariableList (get_child_variables, can_create);
470         }
471 
472         if (get_file_globals && m_sc.comp_unit)
473         {
474             VariableListSP global_variable_list_sp (m_sc.comp_unit->GetVariableList(true));
475             if (m_variable_list_sp)
476                 m_variable_list_sp->AddVariables (global_variable_list_sp.get());
477             else
478                 m_variable_list_sp = global_variable_list_sp;
479         }
480     }
481     return m_variable_list_sp.get();
482 }
483 
484 
485 bool
486 StackFrame::GetFrameBaseValue (Scalar &frame_base, Error *error_ptr)
487 {
488     if (m_flags.IsClear(GOT_FRAME_BASE))
489     {
490         if (m_sc.function)
491         {
492             m_frame_base.Clear();
493             m_frame_base_error.Clear();
494 
495             m_flags.Set(GOT_FRAME_BASE);
496             ExecutionContext exe_ctx (&m_thread.GetProcess(), &m_thread, this);
497             Value expr_value;
498             if (m_sc.function->GetFrameBaseExpression().Evaluate(&exe_ctx, NULL, NULL, expr_value, &m_frame_base_error) < 0)
499             {
500                 // We should really have an error if evaluate returns, but in case
501                 // we don't, lets set the error to something at least.
502                 if (m_frame_base_error.Success())
503                     m_frame_base_error.SetErrorString("Evaluation of the frame base expression failed.");
504             }
505             else
506             {
507                 m_frame_base = expr_value.ResolveValue(&exe_ctx, NULL);
508             }
509         }
510         else
511         {
512             m_frame_base_error.SetErrorString ("No function in symbol context.");
513         }
514     }
515 
516     if (m_frame_base_error.Success())
517         frame_base = m_frame_base;
518 
519     if (error_ptr)
520         *error_ptr = m_frame_base_error;
521     return m_frame_base_error.Success();
522 }
523 
524 RegisterContext *
525 StackFrame::GetRegisterContext ()
526 {
527     if (m_reg_context_sp.get() == NULL)
528         m_reg_context_sp.reset (m_thread.CreateRegisterContextForFrame (this));
529     return m_reg_context_sp.get();
530 }
531 
532 bool
533 StackFrame::HasDebugInformation ()
534 {
535     GetSymbolContext (eSymbolContextLineEntry);
536     return m_sc.line_entry.IsValid();
537 }
538 
539 
540 ValueObjectSP
541 StackFrame::GetValueObjectForFrameVariable (const VariableSP &variable_sp)
542 {
543     ValueObjectSP valobj_sp;
544     VariableList *var_list = GetVariableList (true);
545     if (var_list)
546     {
547         // Make sure the variable is a frame variable
548         const uint32_t var_idx = var_list->FindIndexForVariable (variable_sp.get());
549         const uint32_t num_variables = var_list->GetSize();
550         if (var_idx < num_variables)
551         {
552             valobj_sp = m_variable_list_value_objects.GetValueObjectAtIndex (var_idx);
553             if (valobj_sp.get() == NULL)
554             {
555                 if (m_variable_list_value_objects.GetSize() < num_variables)
556                     m_variable_list_value_objects.Resize(num_variables);
557                 valobj_sp.reset (new ValueObjectVariable (variable_sp));
558                 m_variable_list_value_objects.SetValueObjectAtIndex (var_idx, valobj_sp);
559             }
560         }
561     }
562     return valobj_sp;
563 }
564 
565 ValueObjectSP
566 StackFrame::TrackGlobalVariable (const VariableSP &variable_sp)
567 {
568     // Check to make sure we aren't already tracking this variable?
569     ValueObjectSP valobj_sp (GetValueObjectForFrameVariable (variable_sp));
570     if (!valobj_sp)
571     {
572         // We aren't already tracking this global
573         VariableList *var_list = GetVariableList (true);
574         // If this frame has no variables, create a new list
575         if (var_list == NULL)
576             m_variable_list_sp.reset (new VariableList());
577 
578         // Add the global/static variable to this frame
579         m_variable_list_sp->AddVariable (variable_sp);
580 
581         // Now make a value object for it so we can track its changes
582         valobj_sp = GetValueObjectForFrameVariable (variable_sp);
583     }
584     return valobj_sp;
585 }
586 
587 bool
588 StackFrame::IsInlined ()
589 {
590     if (m_sc.block == NULL)
591         GetSymbolContext (eSymbolContextBlock);
592     if (m_sc.block)
593         return m_sc.block->GetContainingInlinedBlock() != NULL;
594     return false;
595 }
596 
597 Target *
598 StackFrame::CalculateTarget ()
599 {
600     return m_thread.CalculateTarget();
601 }
602 
603 Process *
604 StackFrame::CalculateProcess ()
605 {
606     return m_thread.CalculateProcess();
607 }
608 
609 Thread *
610 StackFrame::CalculateThread ()
611 {
612     return &m_thread;
613 }
614 
615 StackFrame *
616 StackFrame::CalculateStackFrame ()
617 {
618     return this;
619 }
620 
621 
622 void
623 StackFrame::Calculate (ExecutionContext &exe_ctx)
624 {
625     m_thread.Calculate (exe_ctx);
626     exe_ctx.frame = this;
627 }
628 
629 void
630 StackFrame::Dump (Stream *strm, bool show_frame_index)
631 {
632     if (strm == NULL)
633         return;
634 
635     if (show_frame_index)
636         strm->Printf("frame #%u: ", m_frame_index);
637     strm->Printf("0x%0*llx", m_thread.GetProcess().GetAddressByteSize() * 2, GetFrameCodeAddress().GetLoadAddress(&m_thread.GetProcess()));
638     GetSymbolContext(eSymbolContextEverything);
639     strm->PutCString(", where = ");
640     // TODO: need to get the
641     const bool show_module = true;
642     const bool show_inline = true;
643     m_sc.DumpStopContext(strm, &m_thread.GetProcess(), GetFrameCodeAddress(), show_module, show_inline);
644 }
645 
646 void
647 StackFrame::UpdateCurrentFrameFromPreviousFrame (StackFrame &prev_frame)
648 {
649     assert (GetStackID() == prev_frame.GetStackID());    // TODO: remove this after some testing
650     m_variable_list_sp = prev_frame.m_variable_list_sp;
651     m_variable_list_value_objects.Swap (prev_frame.m_variable_list_value_objects);
652     if (!m_disassembly.GetString().empty())
653         m_disassembly.GetString().swap (m_disassembly.GetString());
654 }
655 
656 
657 void
658 StackFrame::UpdatePreviousFrameFromCurrentFrame (StackFrame &curr_frame)
659 {
660     assert (GetStackID() == curr_frame.GetStackID());    // TODO: remove this after some testing
661     assert (&m_thread == &curr_frame.m_thread);
662     m_frame_index = curr_frame.m_frame_index;
663     m_unwind_frame_index = curr_frame.m_unwind_frame_index;
664     m_reg_context_sp = curr_frame.m_reg_context_sp;
665     m_frame_code_addr = curr_frame.m_frame_code_addr;
666     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());
667     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());
668     assert (m_sc.comp_unit == NULL || curr_frame.m_sc.comp_unit == NULL || m_sc.comp_unit == curr_frame.m_sc.comp_unit);
669     assert (m_sc.function == NULL || curr_frame.m_sc.function == NULL || m_sc.function == curr_frame.m_sc.function);
670     m_sc = curr_frame.m_sc;
671     m_flags.Clear(GOT_FRAME_BASE | eSymbolContextEverything);
672     m_flags.Set (m_sc.GetResolvedMask());
673     m_frame_base.Clear();
674     m_frame_base_error.Clear();
675 }
676 
677 
678