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