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