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