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