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/Core/ValueObjectConstResult.h"
22 #include "lldb/Symbol/CompileUnit.h"
23 #include "lldb/Symbol/Function.h"
24 #include "lldb/Symbol/Symbol.h"
25 #include "lldb/Symbol/SymbolContextScope.h"
26 #include "lldb/Symbol/VariableList.h"
27 #include "lldb/Target/ExecutionContext.h"
28 #include "lldb/Target/Process.h"
29 #include "lldb/Target/RegisterContext.h"
30 #include "lldb/Target/Target.h"
31 #include "lldb/Target/Thread.h"
32 
33 using namespace lldb;
34 using namespace lldb_private;
35 
36 // The first bits in the flags are reserved for the SymbolContext::Scope bits
37 // so we know if we have tried to look up information in our internal symbol
38 // context (m_sc) already.
39 #define RESOLVED_FRAME_CODE_ADDR        (uint32_t(eSymbolContextEverything + 1))
40 #define RESOLVED_FRAME_ID_SYMBOL_SCOPE  (RESOLVED_FRAME_CODE_ADDR << 1)
41 #define GOT_FRAME_BASE                  (RESOLVED_FRAME_ID_SYMBOL_SCOPE << 1)
42 #define RESOLVED_VARIABLES              (GOT_FRAME_BASE << 1)
43 #define RESOLVED_GLOBAL_VARIABLES       (RESOLVED_VARIABLES << 1)
44 
45 StackFrame::StackFrame (const ThreadSP &thread_sp,
46                         user_id_t frame_idx,
47                         user_id_t unwind_frame_index,
48                         addr_t cfa,
49                         addr_t pc,
50                         const SymbolContext *sc_ptr) :
51     m_thread_wp (thread_sp),
52     m_frame_index (frame_idx),
53     m_concrete_frame_index (unwind_frame_index),
54     m_reg_context_sp (),
55     m_id (pc, cfa, NULL),
56     m_frame_code_addr (pc),
57     m_sc (),
58     m_flags (),
59     m_frame_base (),
60     m_frame_base_error (),
61     m_variable_list_sp (),
62     m_variable_list_value_objects (),
63     m_disassembly ()
64 {
65     if (sc_ptr != NULL)
66     {
67         m_sc = *sc_ptr;
68         m_flags.Set(m_sc.GetResolvedMask ());
69     }
70 }
71 
72 StackFrame::StackFrame (const ThreadSP &thread_sp,
73                         user_id_t frame_idx,
74                         user_id_t unwind_frame_index,
75                         const RegisterContextSP &reg_context_sp,
76                         addr_t cfa,
77                         addr_t pc,
78                         const SymbolContext *sc_ptr) :
79     m_thread_wp (thread_sp),
80     m_frame_index (frame_idx),
81     m_concrete_frame_index (unwind_frame_index),
82     m_reg_context_sp (reg_context_sp),
83     m_id (pc, cfa, NULL),
84     m_frame_code_addr (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     m_disassembly ()
92 {
93     if (sc_ptr != NULL)
94     {
95         m_sc = *sc_ptr;
96         m_flags.Set(m_sc.GetResolvedMask ());
97     }
98 
99     if (reg_context_sp && !m_sc.target_sp)
100     {
101         m_sc.target_sp = reg_context_sp->CalculateTarget();
102         if (m_sc.target_sp)
103             m_flags.Set (eSymbolContextTarget);
104     }
105 }
106 
107 StackFrame::StackFrame (const ThreadSP &thread_sp,
108                         user_id_t frame_idx,
109                         user_id_t unwind_frame_index,
110                         const RegisterContextSP &reg_context_sp,
111                         addr_t cfa,
112                         const Address& pc_addr,
113                         const SymbolContext *sc_ptr) :
114     m_thread_wp (thread_sp),
115     m_frame_index (frame_idx),
116     m_concrete_frame_index (unwind_frame_index),
117     m_reg_context_sp (reg_context_sp),
118     m_id (pc_addr.GetLoadAddress (thread_sp->CalculateTarget().get()), cfa, NULL),
119     m_frame_code_addr (pc_addr),
120     m_sc (),
121     m_flags (),
122     m_frame_base (),
123     m_frame_base_error (),
124     m_variable_list_sp (),
125     m_variable_list_value_objects (),
126     m_disassembly ()
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->CalculateTarget();
137         if (m_sc.target_sp)
138             m_flags.Set (eSymbolContextTarget);
139     }
140 
141     ModuleSP pc_module_sp (pc_addr.GetModule());
142     if (!m_sc.module_sp || m_sc.module_sp != pc_module_sp)
143     {
144         if (pc_module_sp)
145         {
146             m_sc.module_sp = pc_module_sp;
147             m_flags.Set (eSymbolContextModule);
148         }
149         else
150         {
151             m_sc.module_sp.reset();
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 const 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         ThreadSP thread_sp (GetThread());
217         if (thread_sp)
218         {
219             TargetSP target_sp (thread_sp->CalculateTarget());
220             if (target_sp)
221             {
222                 if (m_frame_code_addr.SetOpcodeLoadAddress (m_frame_code_addr.GetOffset(), target_sp.get()))
223                 {
224                     ModuleSP module_sp (m_frame_code_addr.GetModule());
225                     if (module_sp)
226                     {
227                         m_sc.module_sp = module_sp;
228                         m_flags.Set(eSymbolContextModule);
229                     }
230                 }
231             }
232         }
233     }
234     return m_frame_code_addr;
235 }
236 
237 void
238 StackFrame::ChangePC (addr_t pc)
239 {
240     m_frame_code_addr.SetRawAddress(pc);
241     m_sc.Clear();
242     m_flags.Reset(0);
243     ThreadSP thread_sp (GetThread());
244     if (thread_sp)
245         thread_sp->ClearStackFrames ();
246 }
247 
248 const char *
249 StackFrame::Disassemble ()
250 {
251     if (m_disassembly.GetSize() == 0)
252     {
253         ExecutionContext exe_ctx (shared_from_this());
254         Target *target = exe_ctx.GetTargetPtr();
255         if (target)
256         {
257             Disassembler::Disassemble (target->GetDebugger(),
258                                        target->GetArchitecture(),
259                                        NULL,
260                                        exe_ctx,
261                                        0,
262                                        0,
263                                        0,
264                                        m_disassembly);
265         }
266         if (m_disassembly.GetSize() == 0)
267             return NULL;
268     }
269     return m_disassembly.GetData();
270 }
271 
272 Block *
273 StackFrame::GetFrameBlock ()
274 {
275     if (m_sc.block == NULL && m_flags.IsClear (eSymbolContextBlock))
276         GetSymbolContext (eSymbolContextBlock);
277 
278     if (m_sc.block)
279     {
280         Block *inline_block = m_sc.block->GetContainingInlinedBlock();
281         if (inline_block)
282         {
283             // Use the block with the inlined function info
284             // as the frame block we want this frame to have only the variables
285             // for the inlined function and its non-inlined block child blocks.
286             return inline_block;
287         }
288         else
289         {
290             // This block is not contained withing any inlined function blocks
291             // with so we want to use the top most function block.
292             return &m_sc.function->GetBlock (false);
293         }
294     }
295     return NULL;
296 }
297 
298 //----------------------------------------------------------------------
299 // Get the symbol context if we already haven't done so by resolving the
300 // PC address as much as possible. This way when we pass around a
301 // StackFrame object, everyone will have as much information as
302 // possible and no one will ever have to look things up manually.
303 //----------------------------------------------------------------------
304 const SymbolContext&
305 StackFrame::GetSymbolContext (uint32_t resolve_scope)
306 {
307     // Copy our internal symbol context into "sc".
308     if ((m_flags.Get() & resolve_scope) != resolve_scope)
309     {
310         // Resolve our PC to section offset if we haven't alreday done so
311         // and if we don't have a module. The resolved address section will
312         // contain the module to which it belongs
313         if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR))
314             GetFrameCodeAddress();
315 
316         // If this is not frame zero, then we need to subtract 1 from the PC
317         // value when doing address lookups since the PC will be on the
318         // instruction following the function call instruction...
319 
320         Address lookup_addr(GetFrameCodeAddress());
321         if (m_frame_index > 0 && lookup_addr.IsValid())
322         {
323             addr_t offset = lookup_addr.GetOffset();
324             if (offset > 0)
325                 lookup_addr.SetOffset(offset - 1);
326         }
327 
328 
329         uint32_t resolved = 0;
330         if (m_sc.module_sp)
331         {
332             // We have something in our stack frame symbol context, lets check
333             // if we haven't already tried to lookup one of those things. If we
334             // haven't then we will do the query.
335 
336             uint32_t actual_resolve_scope = 0;
337 
338             if (resolve_scope & eSymbolContextCompUnit)
339             {
340                 if (m_flags.IsClear (eSymbolContextCompUnit))
341                 {
342                     if (m_sc.comp_unit)
343                         resolved |= eSymbolContextCompUnit;
344                     else
345                         actual_resolve_scope |= eSymbolContextCompUnit;
346                 }
347             }
348 
349             if (resolve_scope & eSymbolContextFunction)
350             {
351                 if (m_flags.IsClear (eSymbolContextFunction))
352                 {
353                     if (m_sc.function)
354                         resolved |= eSymbolContextFunction;
355                     else
356                         actual_resolve_scope |= eSymbolContextFunction;
357                 }
358             }
359 
360             if (resolve_scope & eSymbolContextBlock)
361             {
362                 if (m_flags.IsClear (eSymbolContextBlock))
363                 {
364                     if (m_sc.block)
365                         resolved |= eSymbolContextBlock;
366                     else
367                         actual_resolve_scope |= eSymbolContextBlock;
368                 }
369             }
370 
371             if (resolve_scope & eSymbolContextSymbol)
372             {
373                 if (m_flags.IsClear (eSymbolContextSymbol))
374                 {
375                     if (m_sc.symbol)
376                         resolved |= eSymbolContextSymbol;
377                     else
378                         actual_resolve_scope |= eSymbolContextSymbol;
379                 }
380             }
381 
382             if (resolve_scope & eSymbolContextLineEntry)
383             {
384                 if (m_flags.IsClear (eSymbolContextLineEntry))
385                 {
386                     if (m_sc.line_entry.IsValid())
387                         resolved |= eSymbolContextLineEntry;
388                     else
389                         actual_resolve_scope |= eSymbolContextLineEntry;
390                 }
391             }
392 
393             if (actual_resolve_scope)
394             {
395                 // We might be resolving less information than what is already
396                 // in our current symbol context so resolve into a temporary
397                 // symbol context "sc" so we don't clear out data we have
398                 // already found in "m_sc"
399                 SymbolContext sc;
400                 // Set flags that indicate what we have tried to resolve
401                 resolved |= m_sc.module_sp->ResolveSymbolContextForAddress (lookup_addr, actual_resolve_scope, sc);
402                 // Only replace what we didn't already have as we may have
403                 // information for an inlined function scope that won't match
404                 // what a standard lookup by address would match
405                 if ((resolved & eSymbolContextCompUnit)  && m_sc.comp_unit == NULL)
406                     m_sc.comp_unit = sc.comp_unit;
407                 if ((resolved & eSymbolContextFunction)  && m_sc.function == NULL)
408                     m_sc.function = sc.function;
409                 if ((resolved & eSymbolContextBlock)     && m_sc.block == NULL)
410                     m_sc.block = sc.block;
411                 if ((resolved & eSymbolContextSymbol)    && m_sc.symbol == NULL)
412                     m_sc.symbol = sc.symbol;
413                 if ((resolved & eSymbolContextLineEntry) && !m_sc.line_entry.IsValid())
414                     m_sc.line_entry = sc.line_entry;
415 
416             }
417         }
418         else
419         {
420             // If we don't have a module, then we can't have the compile unit,
421             // function, block, line entry or symbol, so we can safely call
422             // ResolveSymbolContextForAddress with our symbol context member m_sc.
423             TargetSP target_sp (CalculateTarget());
424             if (target_sp)
425                 resolved |= target_sp->GetImages().ResolveSymbolContextForAddress (lookup_addr, resolve_scope, m_sc);
426         }
427 
428         // If the target was requested add that:
429         if (!m_sc.target_sp)
430         {
431             m_sc.target_sp = CalculateTarget();
432             if (m_sc.target_sp)
433                 resolved |= eSymbolContextTarget;
434         }
435 
436         // Update our internal flags so we remember what we have tried to locate so
437         // we don't have to keep trying when more calls to this function are made.
438         // We might have dug up more information that was requested (for example
439         // if we were asked to only get the block, we will have gotten the
440         // compile unit, and function) so set any additional bits that we resolved
441         m_flags.Set (resolve_scope | resolved);
442     }
443 
444     // Return the symbol context with everything that was possible to resolve
445     // resolved.
446     return m_sc;
447 }
448 
449 
450 VariableList *
451 StackFrame::GetVariableList (bool get_file_globals)
452 {
453     if (m_flags.IsClear(RESOLVED_VARIABLES))
454     {
455         m_flags.Set(RESOLVED_VARIABLES);
456 
457         Block *frame_block = GetFrameBlock();
458 
459         if (frame_block)
460         {
461             const bool get_child_variables = true;
462             const bool can_create = true;
463             const bool stop_if_child_block_is_inlined_function = true;
464             m_variable_list_sp.reset(new VariableList());
465             frame_block->AppendBlockVariables(can_create, get_child_variables, stop_if_child_block_is_inlined_function, m_variable_list_sp.get());
466         }
467     }
468 
469     if (m_flags.IsClear(RESOLVED_GLOBAL_VARIABLES) &&
470         get_file_globals)
471     {
472         m_flags.Set(RESOLVED_GLOBAL_VARIABLES);
473 
474         if (m_flags.IsClear (eSymbolContextCompUnit))
475             GetSymbolContext (eSymbolContextCompUnit);
476 
477         if (m_sc.comp_unit)
478         {
479             VariableListSP global_variable_list_sp (m_sc.comp_unit->GetVariableList(true));
480             if (m_variable_list_sp)
481                 m_variable_list_sp->AddVariables (global_variable_list_sp.get());
482             else
483                 m_variable_list_sp = global_variable_list_sp;
484         }
485     }
486 
487     return m_variable_list_sp.get();
488 }
489 
490 VariableListSP
491 StackFrame::GetInScopeVariableList (bool get_file_globals)
492 {
493     VariableListSP var_list_sp(new VariableList);
494     GetSymbolContext (eSymbolContextCompUnit | eSymbolContextBlock);
495 
496     if (m_sc.block)
497     {
498         const bool can_create = true;
499         const bool get_parent_variables = true;
500         const bool stop_if_block_is_inlined_function = true;
501         m_sc.block->AppendVariables (can_create,
502                                      get_parent_variables,
503                                      stop_if_block_is_inlined_function,
504                                      var_list_sp.get());
505     }
506 
507     if (m_sc.comp_unit)
508     {
509         VariableListSP global_variable_list_sp (m_sc.comp_unit->GetVariableList(true));
510         if (global_variable_list_sp)
511             var_list_sp->AddVariables (global_variable_list_sp.get());
512     }
513 
514     return var_list_sp;
515 }
516 
517 
518 ValueObjectSP
519 StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
520                                                DynamicValueType use_dynamic,
521                                                uint32_t options,
522                                                VariableSP &var_sp,
523                                                Error &error)
524 {
525 
526     if (var_expr_cstr && var_expr_cstr[0])
527     {
528         const bool check_ptr_vs_member = (options & eExpressionPathOptionCheckPtrVsMember) != 0;
529         const bool no_fragile_ivar = (options & eExpressionPathOptionsNoFragileObjcIvar) != 0;
530         const bool no_synth_child = (options & eExpressionPathOptionsNoSyntheticChildren) != 0;
531         //const bool no_synth_array = (options & eExpressionPathOptionsNoSyntheticArrayRange) != 0;
532         error.Clear();
533         bool deref = false;
534         bool address_of = false;
535         ValueObjectSP valobj_sp;
536         const bool get_file_globals = true;
537         // When looking up a variable for an expression, we need only consider the
538         // variables that are in scope.
539         VariableListSP var_list_sp (GetInScopeVariableList (get_file_globals));
540         VariableList *variable_list = var_list_sp.get();
541 
542         if (variable_list)
543         {
544             // If first character is a '*', then show pointer contents
545             const char *var_expr = var_expr_cstr;
546             if (var_expr[0] == '*')
547             {
548                 deref = true;
549                 var_expr++; // Skip the '*'
550             }
551             else if (var_expr[0] == '&')
552             {
553                 address_of = true;
554                 var_expr++; // Skip the '&'
555             }
556 
557             std::string var_path (var_expr);
558             size_t separator_idx = var_path.find_first_of(".-[=+~|&^%#@!/?,<>{}");
559             StreamString var_expr_path_strm;
560 
561             ConstString name_const_string;
562             if (separator_idx == std::string::npos)
563                 name_const_string.SetCString (var_path.c_str());
564             else
565                 name_const_string.SetCStringWithLength (var_path.c_str(), separator_idx);
566 
567             var_sp = variable_list->FindVariable(name_const_string);
568 
569             bool synthetically_added_instance_object = false;
570 
571             if (var_sp)
572             {
573                 var_path.erase (0, name_const_string.GetLength ());
574             }
575             else if (options & eExpressionPathOptionsAllowDirectIVarAccess)
576             {
577                 // Check for direct ivars access which helps us with implicit
578                 // access to ivars with the "this->" or "self->"
579                 GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock);
580                 lldb::LanguageType method_language = eLanguageTypeUnknown;
581                 bool is_instance_method = false;
582                 ConstString method_object_name;
583                 if (m_sc.GetFunctionMethodInfo (method_language, is_instance_method, method_object_name))
584                 {
585                     if (is_instance_method && method_object_name)
586                     {
587                         var_sp = variable_list->FindVariable(method_object_name);
588                         if (var_sp)
589                         {
590                             separator_idx = 0;
591                             var_path.insert(0, "->");
592                             synthetically_added_instance_object = true;
593                         }
594                     }
595                 }
596             }
597 
598             if (var_sp)
599             {
600                 valobj_sp = GetValueObjectForFrameVariable (var_sp, use_dynamic);
601                 if (!valobj_sp)
602                     return valobj_sp;
603 
604                 // We are dumping at least one child
605                 while (separator_idx != std::string::npos)
606                 {
607                     // Calculate the next separator index ahead of time
608                     ValueObjectSP child_valobj_sp;
609                     const char separator_type = var_path[0];
610                     switch (separator_type)
611                     {
612 
613                     case '-':
614                         if (var_path.size() >= 2 && var_path[1] != '>')
615                             return ValueObjectSP();
616 
617                         if (no_fragile_ivar)
618                         {
619                             // Make sure we aren't trying to deref an objective
620                             // C ivar if this is not allowed
621                             const uint32_t pointer_type_flags = ClangASTContext::GetTypeInfo (valobj_sp->GetClangType(), NULL, NULL);
622                             if ((pointer_type_flags & ClangASTContext::eTypeIsObjC) &&
623                                 (pointer_type_flags & ClangASTContext::eTypeIsPointer))
624                             {
625                                 // This was an objective C object pointer and
626                                 // it was requested we skip any fragile ivars
627                                 // so return nothing here
628                                 return ValueObjectSP();
629                             }
630                         }
631                         var_path.erase (0, 1); // Remove the '-'
632                         // Fall through
633                     case '.':
634                         {
635                             const bool expr_is_ptr = var_path[0] == '>';
636 
637                             var_path.erase (0, 1); // Remove the '.' or '>'
638                             separator_idx = var_path.find_first_of(".-[");
639                             ConstString child_name;
640                             if (separator_idx == std::string::npos)
641                                 child_name.SetCString (var_path.c_str());
642                             else
643                                 child_name.SetCStringWithLength(var_path.c_str(), separator_idx);
644 
645                             if (check_ptr_vs_member)
646                             {
647                                 // We either have a pointer type and need to verify
648                                 // valobj_sp is a pointer, or we have a member of a
649                                 // class/union/struct being accessed with the . syntax
650                                 // and need to verify we don't have a pointer.
651                                 const bool actual_is_ptr = valobj_sp->IsPointerType ();
652 
653                                 if (actual_is_ptr != expr_is_ptr)
654                                 {
655                                     // Incorrect use of "." with a pointer, or "->" with
656                                     // a class/union/struct instance or reference.
657                                     valobj_sp->GetExpressionPath (var_expr_path_strm, false);
658                                     if (actual_is_ptr)
659                                         error.SetErrorStringWithFormat ("\"%s\" is a pointer and . was used to attempt to access \"%s\". Did you mean \"%s->%s\"?",
660                                                                         var_expr_path_strm.GetString().c_str(),
661                                                                         child_name.GetCString(),
662                                                                         var_expr_path_strm.GetString().c_str(),
663                                                                         var_path.c_str());
664                                     else
665                                         error.SetErrorStringWithFormat ("\"%s\" is not a pointer and -> was used to attempt to access \"%s\". Did you mean \"%s.%s\"?",
666                                                                         var_expr_path_strm.GetString().c_str(),
667                                                                         child_name.GetCString(),
668                                                                         var_expr_path_strm.GetString().c_str(),
669                                                                         var_path.c_str());
670                                     return ValueObjectSP();
671                                 }
672                             }
673                             child_valobj_sp = valobj_sp->GetChildMemberWithName (child_name, true);
674                             if (!child_valobj_sp)
675                             {
676                                 if (no_synth_child == false)
677                                 {
678                                     child_valobj_sp = valobj_sp->GetSyntheticValue();
679                                     if (child_valobj_sp)
680                                         child_valobj_sp = child_valobj_sp->GetChildMemberWithName (child_name, true);
681                                 }
682 
683                                 if (no_synth_child || !child_valobj_sp)
684                                 {
685                                     // No child member with name "child_name"
686                                     if (synthetically_added_instance_object)
687                                     {
688                                         // We added a "this->" or "self->" to the beginning of the expression
689                                         // and this is the first pointer ivar access, so just return the normal
690                                         // error
691                                         error.SetErrorStringWithFormat("no variable or instance variable named '%s' found in this frame",
692                                                                        name_const_string.GetCString());
693                                     }
694                                     else
695                                     {
696                                         valobj_sp->GetExpressionPath (var_expr_path_strm, false);
697                                         if (child_name)
698                                         {
699                                             error.SetErrorStringWithFormat ("\"%s\" is not a member of \"(%s) %s\"",
700                                                                             child_name.GetCString(),
701                                                                             valobj_sp->GetTypeName().AsCString("<invalid type>"),
702                                                                             var_expr_path_strm.GetString().c_str());
703                                         }
704                                         else
705                                         {
706                                             error.SetErrorStringWithFormat ("incomplete expression path after \"%s\" in \"%s\"",
707                                                                             var_expr_path_strm.GetString().c_str(),
708                                                                             var_expr_cstr);
709                                         }
710                                     }
711                                     return ValueObjectSP();
712                                 }
713                             }
714                             synthetically_added_instance_object = false;
715                             // Remove the child name from the path
716                             var_path.erase(0, child_name.GetLength());
717                             if (use_dynamic != eNoDynamicValues)
718                             {
719                                 ValueObjectSP dynamic_value_sp(child_valobj_sp->GetDynamicValue(use_dynamic));
720                                 if (dynamic_value_sp)
721                                     child_valobj_sp = dynamic_value_sp;
722                             }
723                         }
724                         break;
725 
726                     case '[':
727                         // Array member access, or treating pointer as an array
728                         if (var_path.size() > 2) // Need at least two brackets and a number
729                         {
730                             char *end = NULL;
731                             long child_index = ::strtol (&var_path[1], &end, 0);
732                             if (end && *end == ']'
733                                 && *(end-1) != '[') // this code forces an error in the case of arr[]. as bitfield[] is not a good syntax we're good to go
734                             {
735                                 if (ClangASTContext::IsPointerToScalarType(valobj_sp->GetClangType()) && deref)
736                                 {
737                                     // what we have is *ptr[low]. the most similar C++ syntax is to deref ptr
738                                     // and extract bit low out of it. reading array item low
739                                     // would be done by saying ptr[low], without a deref * sign
740                                     Error error;
741                                     ValueObjectSP temp(valobj_sp->Dereference(error));
742                                     if (error.Fail())
743                                     {
744                                         valobj_sp->GetExpressionPath (var_expr_path_strm, false);
745                                         error.SetErrorStringWithFormat ("could not dereference \"(%s) %s\"",
746                                                                         valobj_sp->GetTypeName().AsCString("<invalid type>"),
747                                                                         var_expr_path_strm.GetString().c_str());
748                                         return ValueObjectSP();
749                                     }
750                                     valobj_sp = temp;
751                                     deref = false;
752                                 }
753                                 else if (ClangASTContext::IsArrayOfScalarType(valobj_sp->GetClangType()) && deref)
754                                 {
755                                     // what we have is *arr[low]. the most similar C++ syntax is to get arr[0]
756                                     // (an operation that is equivalent to deref-ing arr)
757                                     // and extract bit low out of it. reading array item low
758                                     // would be done by saying arr[low], without a deref * sign
759                                     Error error;
760                                     ValueObjectSP temp(valobj_sp->GetChildAtIndex (0, true));
761                                     if (error.Fail())
762                                     {
763                                         valobj_sp->GetExpressionPath (var_expr_path_strm, false);
764                                         error.SetErrorStringWithFormat ("could not get item 0 for \"(%s) %s\"",
765                                                                         valobj_sp->GetTypeName().AsCString("<invalid type>"),
766                                                                         var_expr_path_strm.GetString().c_str());
767                                         return ValueObjectSP();
768                                     }
769                                     valobj_sp = temp;
770                                     deref = false;
771                                 }
772 
773                                 if (valobj_sp->IsPointerType ())
774                                 {
775                                     bool is_objc_pointer = true;
776 
777                                     if (ClangASTType::GetMinimumLanguage(valobj_sp->GetClangAST(), valobj_sp->GetClangType()) != eLanguageTypeObjC)
778                                         is_objc_pointer = false;
779                                     else if (!ClangASTContext::IsPointerType(valobj_sp->GetClangType()))
780                                         is_objc_pointer = false;
781 
782                                     if (no_synth_child && is_objc_pointer)
783                                     {
784                                         error.SetErrorStringWithFormat("\"(%s) %s\" is an Objective-C pointer, and cannot be subscripted",
785                                                                        valobj_sp->GetTypeName().AsCString("<invalid type>"),
786                                                                        var_expr_path_strm.GetString().c_str());
787 
788                                         return ValueObjectSP();
789                                     }
790                                     else if (is_objc_pointer)
791                                     {
792                                         // dereferencing ObjC variables is not valid.. so let's try and recur to synthetic children
793                                         ValueObjectSP synthetic = valobj_sp->GetSyntheticValue();
794                                         if (synthetic.get() == NULL /* no synthetic */
795                                             || synthetic == valobj_sp) /* synthetic is the same as the original object */
796                                         {
797                                             valobj_sp->GetExpressionPath (var_expr_path_strm, false);
798                                             error.SetErrorStringWithFormat ("\"(%s) %s\" is not an array type",
799                                                                             valobj_sp->GetTypeName().AsCString("<invalid type>"),
800                                                                             var_expr_path_strm.GetString().c_str());
801                                         }
802                                         else if (child_index >= synthetic->GetNumChildren() /* synthetic does not have that many values */)
803                                         {
804                                             valobj_sp->GetExpressionPath (var_expr_path_strm, false);
805                                             error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"",
806                                                                             child_index,
807                                                                             valobj_sp->GetTypeName().AsCString("<invalid type>"),
808                                                                             var_expr_path_strm.GetString().c_str());
809                                         }
810                                         else
811                                         {
812                                             child_valobj_sp = synthetic->GetChildAtIndex(child_index, true);
813                                             if (!child_valobj_sp)
814                                             {
815                                                 valobj_sp->GetExpressionPath (var_expr_path_strm, false);
816                                                 error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"",
817                                                                                 child_index,
818                                                                                 valobj_sp->GetTypeName().AsCString("<invalid type>"),
819                                                                                 var_expr_path_strm.GetString().c_str());
820                                             }
821                                         }
822                                     }
823                                     else
824                                     {
825                                         child_valobj_sp = valobj_sp->GetSyntheticArrayMemberFromPointer (child_index, true);
826                                         if (!child_valobj_sp)
827                                         {
828                                             valobj_sp->GetExpressionPath (var_expr_path_strm, false);
829                                             error.SetErrorStringWithFormat ("failed to use pointer as array for index %ld for \"(%s) %s\"",
830                                                                             child_index,
831                                                                             valobj_sp->GetTypeName().AsCString("<invalid type>"),
832                                                                             var_expr_path_strm.GetString().c_str());
833                                         }
834                                     }
835                                 }
836                                 else if (ClangASTContext::IsArrayType (valobj_sp->GetClangType(), NULL, NULL))
837                                 {
838                                     // Pass false to dynamic_value here so we can tell the difference between
839                                     // no dynamic value and no member of this type...
840                                     child_valobj_sp = valobj_sp->GetChildAtIndex (child_index, true);
841                                     if (!child_valobj_sp)
842                                     {
843                                         valobj_sp->GetExpressionPath (var_expr_path_strm, false);
844                                         error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"",
845                                                                         child_index,
846                                                                         valobj_sp->GetTypeName().AsCString("<invalid type>"),
847                                                                         var_expr_path_strm.GetString().c_str());
848                                     }
849                                 }
850                                 else if (ClangASTContext::IsScalarType(valobj_sp->GetClangType()))
851                                 {
852                                     // this is a bitfield asking to display just one bit
853                                     child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild(child_index, child_index, true);
854                                     if (!child_valobj_sp)
855                                     {
856                                         valobj_sp->GetExpressionPath (var_expr_path_strm, false);
857                                         error.SetErrorStringWithFormat ("bitfield range %ld-%ld is not valid for \"(%s) %s\"",
858                                                                         child_index, child_index,
859                                                                         valobj_sp->GetTypeName().AsCString("<invalid type>"),
860                                                                         var_expr_path_strm.GetString().c_str());
861                                     }
862                                 }
863                                 else
864                                 {
865                                     ValueObjectSP synthetic = valobj_sp->GetSyntheticValue();
866                                     if (no_synth_child /* synthetic is forbidden */ ||
867                                         synthetic.get() == NULL /* no synthetic */
868                                         || synthetic == valobj_sp) /* synthetic is the same as the original object */
869                                     {
870                                         valobj_sp->GetExpressionPath (var_expr_path_strm, false);
871                                         error.SetErrorStringWithFormat ("\"(%s) %s\" is not an array type",
872                                                                         valobj_sp->GetTypeName().AsCString("<invalid type>"),
873                                                                         var_expr_path_strm.GetString().c_str());
874                                     }
875                                     else if (child_index >= synthetic->GetNumChildren() /* synthetic does not have that many values */)
876                                     {
877                                         valobj_sp->GetExpressionPath (var_expr_path_strm, false);
878                                         error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"",
879                                                                         child_index,
880                                                                         valobj_sp->GetTypeName().AsCString("<invalid type>"),
881                                                                         var_expr_path_strm.GetString().c_str());
882                                     }
883                                     else
884                                     {
885                                         child_valobj_sp = synthetic->GetChildAtIndex(child_index, true);
886                                         if (!child_valobj_sp)
887                                         {
888                                             valobj_sp->GetExpressionPath (var_expr_path_strm, false);
889                                             error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"",
890                                                                             child_index,
891                                                                             valobj_sp->GetTypeName().AsCString("<invalid type>"),
892                                                                             var_expr_path_strm.GetString().c_str());
893                                         }
894                                     }
895                                 }
896 
897                                 if (!child_valobj_sp)
898                                 {
899                                     // Invalid array index...
900                                     return ValueObjectSP();
901                                 }
902 
903                                 // Erase the array member specification '[%i]' where
904                                 // %i is the array index
905                                 var_path.erase(0, (end - var_path.c_str()) + 1);
906                                 separator_idx = var_path.find_first_of(".-[");
907                                 if (use_dynamic != eNoDynamicValues)
908                                 {
909                                     ValueObjectSP dynamic_value_sp(child_valobj_sp->GetDynamicValue(use_dynamic));
910                                     if (dynamic_value_sp)
911                                         child_valobj_sp = dynamic_value_sp;
912                                 }
913                                 // Break out early from the switch since we were
914                                 // able to find the child member
915                                 break;
916                             }
917                             else if (end && *end == '-')
918                             {
919                                 // this is most probably a BitField, let's take a look
920                                 char *real_end = NULL;
921                                 long final_index = ::strtol (end+1, &real_end, 0);
922                                 bool expand_bitfield = true;
923                                 if (real_end && *real_end == ']')
924                                 {
925                                     // if the format given is [high-low], swap range
926                                     if (child_index > final_index)
927                                     {
928                                         long temp = child_index;
929                                         child_index = final_index;
930                                         final_index = temp;
931                                     }
932 
933                                     if (ClangASTContext::IsPointerToScalarType(valobj_sp->GetClangType()) && deref)
934                                     {
935                                         // what we have is *ptr[low-high]. the most similar C++ syntax is to deref ptr
936                                         // and extract bits low thru high out of it. reading array items low thru high
937                                         // would be done by saying ptr[low-high], without a deref * sign
938                                         Error error;
939                                         ValueObjectSP temp(valobj_sp->Dereference(error));
940                                         if (error.Fail())
941                                         {
942                                             valobj_sp->GetExpressionPath (var_expr_path_strm, false);
943                                             error.SetErrorStringWithFormat ("could not dereference \"(%s) %s\"",
944                                                                             valobj_sp->GetTypeName().AsCString("<invalid type>"),
945                                                                             var_expr_path_strm.GetString().c_str());
946                                             return ValueObjectSP();
947                                         }
948                                         valobj_sp = temp;
949                                         deref = false;
950                                     }
951                                     else if (ClangASTContext::IsArrayOfScalarType(valobj_sp->GetClangType()) && deref)
952                                     {
953                                         // what we have is *arr[low-high]. the most similar C++ syntax is to get arr[0]
954                                         // (an operation that is equivalent to deref-ing arr)
955                                         // and extract bits low thru high out of it. reading array items low thru high
956                                         // would be done by saying arr[low-high], without a deref * sign
957                                         Error error;
958                                         ValueObjectSP temp(valobj_sp->GetChildAtIndex (0, true));
959                                         if (error.Fail())
960                                         {
961                                             valobj_sp->GetExpressionPath (var_expr_path_strm, false);
962                                             error.SetErrorStringWithFormat ("could not get item 0 for \"(%s) %s\"",
963                                                                             valobj_sp->GetTypeName().AsCString("<invalid type>"),
964                                                                             var_expr_path_strm.GetString().c_str());
965                                             return ValueObjectSP();
966                                         }
967                                         valobj_sp = temp;
968                                         deref = false;
969                                     }
970                                     /*else if (valobj_sp->IsArrayType() || valobj_sp->IsPointerType())
971                                     {
972                                         child_valobj_sp = valobj_sp->GetSyntheticArrayRangeChild(child_index, final_index, true);
973                                         expand_bitfield = false;
974                                         if (!child_valobj_sp)
975                                         {
976                                             valobj_sp->GetExpressionPath (var_expr_path_strm, false);
977                                             error.SetErrorStringWithFormat ("array range %i-%i is not valid for \"(%s) %s\"",
978                                                                             child_index, final_index,
979                                                                             valobj_sp->GetTypeName().AsCString("<invalid type>"),
980                                                                             var_expr_path_strm.GetString().c_str());
981                                         }
982                                     }*/
983 
984                                     if (expand_bitfield)
985                                     {
986                                         child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild(child_index, final_index, true);
987                                         if (!child_valobj_sp)
988                                         {
989                                             valobj_sp->GetExpressionPath (var_expr_path_strm, false);
990                                             error.SetErrorStringWithFormat ("bitfield range %ld-%ld is not valid for \"(%s) %s\"",
991                                                                             child_index, final_index,
992                                                                             valobj_sp->GetTypeName().AsCString("<invalid type>"),
993                                                                             var_expr_path_strm.GetString().c_str());
994                                         }
995                                     }
996                                 }
997 
998                                 if (!child_valobj_sp)
999                                 {
1000                                     // Invalid bitfield range...
1001                                     return ValueObjectSP();
1002                                 }
1003 
1004                                 // Erase the bitfield member specification '[%i-%i]' where
1005                                 // %i is the index
1006                                 var_path.erase(0, (real_end - var_path.c_str()) + 1);
1007                                 separator_idx = var_path.find_first_of(".-[");
1008                                 if (use_dynamic != eNoDynamicValues)
1009                                 {
1010                                     ValueObjectSP dynamic_value_sp(child_valobj_sp->GetDynamicValue(use_dynamic));
1011                                     if (dynamic_value_sp)
1012                                         child_valobj_sp = dynamic_value_sp;
1013                                 }
1014                                 // Break out early from the switch since we were
1015                                 // able to find the child member
1016                                 break;
1017 
1018                             }
1019                         }
1020                         else
1021                         {
1022                             error.SetErrorStringWithFormat("invalid square bracket encountered after \"%s\" in \"%s\"",
1023                                                            var_expr_path_strm.GetString().c_str(),
1024                                                            var_path.c_str());
1025                         }
1026                         return ValueObjectSP();
1027 
1028                     default:
1029                         // Failure...
1030                         {
1031                             valobj_sp->GetExpressionPath (var_expr_path_strm, false);
1032                             error.SetErrorStringWithFormat ("unexpected char '%c' encountered after \"%s\" in \"%s\"",
1033                                                             separator_type,
1034                                                             var_expr_path_strm.GetString().c_str(),
1035                                                             var_path.c_str());
1036 
1037                             return ValueObjectSP();
1038                         }
1039                     }
1040 
1041                     if (child_valobj_sp)
1042                         valobj_sp = child_valobj_sp;
1043 
1044                     if (var_path.empty())
1045                         break;
1046 
1047                 }
1048                 if (valobj_sp)
1049                 {
1050                     if (deref)
1051                     {
1052                         ValueObjectSP deref_valobj_sp (valobj_sp->Dereference(error));
1053                         valobj_sp = deref_valobj_sp;
1054                     }
1055                     else if (address_of)
1056                     {
1057                         ValueObjectSP address_of_valobj_sp (valobj_sp->AddressOf(error));
1058                         valobj_sp = address_of_valobj_sp;
1059                     }
1060                 }
1061                 return valobj_sp;
1062             }
1063             else
1064             {
1065                 error.SetErrorStringWithFormat("no variable named '%s' found in this frame",
1066                                                name_const_string.GetCString());
1067             }
1068         }
1069     }
1070     else
1071     {
1072         error.SetErrorStringWithFormat("invalid variable path '%s'", var_expr_cstr);
1073     }
1074     return ValueObjectSP();
1075 }
1076 
1077 bool
1078 StackFrame::GetFrameBaseValue (Scalar &frame_base, Error *error_ptr)
1079 {
1080     if (m_flags.IsClear(GOT_FRAME_BASE))
1081     {
1082         if (m_sc.function)
1083         {
1084             m_frame_base.Clear();
1085             m_frame_base_error.Clear();
1086 
1087             m_flags.Set(GOT_FRAME_BASE);
1088             ExecutionContext exe_ctx (shared_from_this());
1089             Value expr_value;
1090             addr_t loclist_base_addr = LLDB_INVALID_ADDRESS;
1091             if (m_sc.function->GetFrameBaseExpression().IsLocationList())
1092                 loclist_base_addr = m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (exe_ctx.GetTargetPtr());
1093 
1094             if (m_sc.function->GetFrameBaseExpression().Evaluate(&exe_ctx, NULL, NULL, NULL, NULL, loclist_base_addr, NULL, expr_value, &m_frame_base_error) == false)
1095             {
1096                 // We should really have an error if evaluate returns, but in case
1097                 // we don't, lets set the error to something at least.
1098                 if (m_frame_base_error.Success())
1099                     m_frame_base_error.SetErrorString("Evaluation of the frame base expression failed.");
1100             }
1101             else
1102             {
1103                 m_frame_base = expr_value.ResolveValue(&exe_ctx, NULL);
1104             }
1105         }
1106         else
1107         {
1108             m_frame_base_error.SetErrorString ("No function in symbol context.");
1109         }
1110     }
1111 
1112     if (m_frame_base_error.Success())
1113         frame_base = m_frame_base;
1114 
1115     if (error_ptr)
1116         *error_ptr = m_frame_base_error;
1117     return m_frame_base_error.Success();
1118 }
1119 
1120 RegisterContextSP
1121 StackFrame::GetRegisterContext ()
1122 {
1123     if (!m_reg_context_sp)
1124     {
1125         ThreadSP thread_sp (GetThread());
1126         if (thread_sp)
1127             m_reg_context_sp = thread_sp->CreateRegisterContextForFrame (this);
1128     }
1129     return m_reg_context_sp;
1130 }
1131 
1132 bool
1133 StackFrame::HasDebugInformation ()
1134 {
1135     GetSymbolContext (eSymbolContextLineEntry);
1136     return m_sc.line_entry.IsValid();
1137 }
1138 
1139 
1140 ValueObjectSP
1141 StackFrame::GetValueObjectForFrameVariable (const VariableSP &variable_sp, DynamicValueType use_dynamic)
1142 {
1143     ValueObjectSP valobj_sp;
1144     VariableList *var_list = GetVariableList (true);
1145     if (var_list)
1146     {
1147         // Make sure the variable is a frame variable
1148         const uint32_t var_idx = var_list->FindIndexForVariable (variable_sp.get());
1149         const uint32_t num_variables = var_list->GetSize();
1150         if (var_idx < num_variables)
1151         {
1152             valobj_sp = m_variable_list_value_objects.GetValueObjectAtIndex (var_idx);
1153             if (valobj_sp.get() == NULL)
1154             {
1155                 if (m_variable_list_value_objects.GetSize() < num_variables)
1156                     m_variable_list_value_objects.Resize(num_variables);
1157                 valobj_sp = ValueObjectVariable::Create (this, variable_sp);
1158                 m_variable_list_value_objects.SetValueObjectAtIndex (var_idx, valobj_sp);
1159             }
1160         }
1161     }
1162     if (use_dynamic != eNoDynamicValues && valobj_sp)
1163     {
1164         ValueObjectSP dynamic_sp = valobj_sp->GetDynamicValue (use_dynamic);
1165         if (dynamic_sp)
1166             return dynamic_sp;
1167     }
1168     return valobj_sp;
1169 }
1170 
1171 ValueObjectSP
1172 StackFrame::TrackGlobalVariable (const VariableSP &variable_sp, DynamicValueType use_dynamic)
1173 {
1174     // Check to make sure we aren't already tracking this variable?
1175     ValueObjectSP valobj_sp (GetValueObjectForFrameVariable (variable_sp, use_dynamic));
1176     if (!valobj_sp)
1177     {
1178         // We aren't already tracking this global
1179         VariableList *var_list = GetVariableList (true);
1180         // If this frame has no variables, create a new list
1181         if (var_list == NULL)
1182             m_variable_list_sp.reset (new VariableList());
1183 
1184         // Add the global/static variable to this frame
1185         m_variable_list_sp->AddVariable (variable_sp);
1186 
1187         // Now make a value object for it so we can track its changes
1188         valobj_sp = GetValueObjectForFrameVariable (variable_sp, use_dynamic);
1189     }
1190     return valobj_sp;
1191 }
1192 
1193 bool
1194 StackFrame::IsInlined ()
1195 {
1196     if (m_sc.block == NULL)
1197         GetSymbolContext (eSymbolContextBlock);
1198     if (m_sc.block)
1199         return m_sc.block->GetContainingInlinedBlock() != NULL;
1200     return false;
1201 }
1202 
1203 TargetSP
1204 StackFrame::CalculateTarget ()
1205 {
1206     TargetSP target_sp;
1207     ThreadSP thread_sp(GetThread());
1208     if (thread_sp)
1209     {
1210         ProcessSP process_sp (thread_sp->CalculateProcess());
1211         if (process_sp)
1212             target_sp = process_sp->CalculateTarget();
1213     }
1214     return target_sp;
1215 }
1216 
1217 ProcessSP
1218 StackFrame::CalculateProcess ()
1219 {
1220     ProcessSP process_sp;
1221     ThreadSP thread_sp(GetThread());
1222     if (thread_sp)
1223         process_sp = thread_sp->CalculateProcess();
1224     return process_sp;
1225 }
1226 
1227 ThreadSP
1228 StackFrame::CalculateThread ()
1229 {
1230     return GetThread();
1231 }
1232 
1233 StackFrameSP
1234 StackFrame::CalculateStackFrame ()
1235 {
1236     return shared_from_this();
1237 }
1238 
1239 
1240 void
1241 StackFrame::CalculateExecutionContext (ExecutionContext &exe_ctx)
1242 {
1243     exe_ctx.SetContext (shared_from_this());
1244 }
1245 
1246 void
1247 StackFrame::DumpUsingSettingsFormat (Stream *strm)
1248 {
1249     if (strm == NULL)
1250         return;
1251 
1252     GetSymbolContext(eSymbolContextEverything);
1253     ExecutionContext exe_ctx (shared_from_this());
1254     const char *end = NULL;
1255     StreamString s;
1256     const char *frame_format = NULL;
1257     Target *target = exe_ctx.GetTargetPtr();
1258     if (target)
1259         frame_format = target->GetDebugger().GetFrameFormat();
1260     if (frame_format && Debugger::FormatPrompt (frame_format, &m_sc, &exe_ctx, NULL, s, &end))
1261     {
1262         strm->Write(s.GetData(), s.GetSize());
1263     }
1264     else
1265     {
1266         Dump (strm, true, false);
1267         strm->EOL();
1268     }
1269 }
1270 
1271 void
1272 StackFrame::Dump (Stream *strm, bool show_frame_index, bool show_fullpaths)
1273 {
1274     if (strm == NULL)
1275         return;
1276 
1277     if (show_frame_index)
1278         strm->Printf("frame #%u: ", m_frame_index);
1279     ExecutionContext exe_ctx (shared_from_this());
1280     Target *target = exe_ctx.GetTargetPtr();
1281     strm->Printf("0x%0*llx ",
1282                  target ? (target->GetArchitecture().GetAddressByteSize() * 2) : 16,
1283                  GetFrameCodeAddress().GetLoadAddress(target));
1284     GetSymbolContext(eSymbolContextEverything);
1285     const bool show_module = true;
1286     const bool show_inline = true;
1287     m_sc.DumpStopContext (strm,
1288                           exe_ctx.GetBestExecutionContextScope(),
1289                           GetFrameCodeAddress(),
1290                           show_fullpaths,
1291                           show_module,
1292                           show_inline);
1293 }
1294 
1295 void
1296 StackFrame::UpdateCurrentFrameFromPreviousFrame (StackFrame &prev_frame)
1297 {
1298     assert (GetStackID() == prev_frame.GetStackID());    // TODO: remove this after some testing
1299     m_variable_list_sp = prev_frame.m_variable_list_sp;
1300     m_variable_list_value_objects.Swap (prev_frame.m_variable_list_value_objects);
1301     if (!m_disassembly.GetString().empty())
1302         m_disassembly.GetString().swap (m_disassembly.GetString());
1303 }
1304 
1305 
1306 void
1307 StackFrame::UpdatePreviousFrameFromCurrentFrame (StackFrame &curr_frame)
1308 {
1309     assert (GetStackID() == curr_frame.GetStackID());        // TODO: remove this after some testing
1310     m_id.SetPC (curr_frame.m_id.GetPC());       // Update the Stack ID PC value
1311     assert (GetThread() == curr_frame.GetThread());
1312     m_frame_index = curr_frame.m_frame_index;
1313     m_concrete_frame_index = curr_frame.m_concrete_frame_index;
1314     m_reg_context_sp = curr_frame.m_reg_context_sp;
1315     m_frame_code_addr = curr_frame.m_frame_code_addr;
1316     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());
1317     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());
1318     assert (m_sc.comp_unit == NULL || curr_frame.m_sc.comp_unit == NULL || m_sc.comp_unit == curr_frame.m_sc.comp_unit);
1319     assert (m_sc.function == NULL || curr_frame.m_sc.function == NULL || m_sc.function == curr_frame.m_sc.function);
1320     m_sc = curr_frame.m_sc;
1321     m_flags.Clear(GOT_FRAME_BASE | eSymbolContextEverything);
1322     m_flags.Set (m_sc.GetResolvedMask());
1323     m_frame_base.Clear();
1324     m_frame_base_error.Clear();
1325 }
1326 
1327 
1328 bool
1329 StackFrame::HasCachedData () const
1330 {
1331     if (m_variable_list_sp.get())
1332         return true;
1333     if (m_variable_list_value_objects.GetSize() > 0)
1334         return true;
1335     if (!m_disassembly.GetString().empty())
1336         return true;
1337     return false;
1338 }
1339 
1340 bool
1341 StackFrame::GetStatus (Stream& strm,
1342                        bool show_frame_info,
1343                        bool show_source)
1344 {
1345 
1346     if (show_frame_info)
1347     {
1348         strm.Indent();
1349         DumpUsingSettingsFormat (&strm);
1350     }
1351 
1352     if (show_source)
1353     {
1354         ExecutionContext exe_ctx (shared_from_this());
1355         bool have_source = false;
1356         Debugger::StopDisassemblyType disasm_display = Debugger::eStopDisassemblyTypeNever;
1357         Target *target = exe_ctx.GetTargetPtr();
1358         if (target)
1359         {
1360             Debugger &debugger = target->GetDebugger();
1361             const uint32_t source_lines_before = debugger.GetStopSourceLineCount(true);
1362             const uint32_t source_lines_after = debugger.GetStopSourceLineCount(false);
1363             disasm_display = debugger.GetStopDisassemblyDisplay ();
1364 
1365             if (source_lines_before > 0 || source_lines_after > 0)
1366             {
1367                 GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry);
1368 
1369                 if (m_sc.comp_unit && m_sc.line_entry.IsValid())
1370                 {
1371                     if (target->GetSourceManager().DisplaySourceLinesWithLineNumbers (m_sc.line_entry.file,
1372                                                                                       m_sc.line_entry.line,
1373                                                                                       source_lines_before,
1374                                                                                       source_lines_after,
1375                                                                                       "->",
1376                                                                                       &strm))
1377                     {
1378                         have_source = true;
1379                     }
1380                 }
1381             }
1382             switch (disasm_display)
1383             {
1384             case Debugger::eStopDisassemblyTypeNever:
1385                 break;
1386 
1387             case Debugger::eStopDisassemblyTypeNoSource:
1388                 if (have_source)
1389                     break;
1390                 // Fall through to next case
1391             case Debugger::eStopDisassemblyTypeAlways:
1392                 if (target)
1393                 {
1394                     const uint32_t disasm_lines = debugger.GetDisassemblyLineCount();
1395                     if (disasm_lines > 0)
1396                     {
1397                         const ArchSpec &target_arch = target->GetArchitecture();
1398                         AddressRange pc_range;
1399                         pc_range.GetBaseAddress() = GetFrameCodeAddress();
1400                         pc_range.SetByteSize(disasm_lines * target_arch.GetMaximumOpcodeByteSize());
1401                         Disassembler::Disassemble (target->GetDebugger(),
1402                                                    target_arch,
1403                                                    NULL,
1404                                                    exe_ctx,
1405                                                    pc_range,
1406                                                    disasm_lines,
1407                                                    0,
1408                                                    Disassembler::eOptionMarkPCAddress,
1409                                                    strm);
1410                     }
1411                 }
1412                 break;
1413             }
1414         }
1415     }
1416     return true;
1417 }
1418 
1419