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
35using namespace lldb;
36using 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
47StackFrame::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
74StackFrame::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
109StackFrame::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//----------------------------------------------------------------------
162StackFrame::~StackFrame()
163{
164}
165
166StackID&
167StackFrame::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
202uint32_t
203StackFrame::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
212void
213StackFrame::SetSymbolContextScope (SymbolContextScope *symbol_scope)
214{
215    m_flags.Set (RESOLVED_FRAME_ID_SYMBOL_SCOPE);
216    m_id.SetSymbolContextScope (symbol_scope);
217}
218
219const Address&
220StackFrame::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
249void
250StackFrame::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
260const char *
261StackFrame::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
287Block *
288StackFrame::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//----------------------------------------------------------------------
319const SymbolContext&
320StackFrame::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
477VariableList *
478StackFrame::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
517VariableListSP
518StackFrame::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
545ValueObjectSP
546StackFrame::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
1108bool
1109StackFrame::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
1151RegisterContextSP
1152StackFrame::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
1163bool
1164StackFrame::HasDebugInformation ()
1165{
1166    GetSymbolContext (eSymbolContextLineEntry);
1167    return m_sc.line_entry.IsValid();
1168}
1169
1170
1171ValueObjectSP
1172StackFrame::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
1202ValueObjectSP
1203StackFrame::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
1224bool
1225StackFrame::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
1234TargetSP
1235StackFrame::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
1248ProcessSP
1249StackFrame::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
1258ThreadSP
1259StackFrame::CalculateThread ()
1260{
1261    return GetThread();
1262}
1263
1264StackFrameSP
1265StackFrame::CalculateStackFrame ()
1266{
1267    return shared_from_this();
1268}
1269
1270
1271void
1272StackFrame::CalculateExecutionContext (ExecutionContext &exe_ctx)
1273{
1274    exe_ctx.SetContext (shared_from_this());
1275}
1276
1277void
1278StackFrame::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
1301void
1302StackFrame::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
1325void
1326StackFrame::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
1336void
1337StackFrame::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
1358bool
1359StackFrame::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
1370bool
1371StackFrame::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