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