Initial checkin of lldb code from internal Apple repo.


git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@105619 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Target/StackFrame.cpp b/source/Target/StackFrame.cpp
new file mode 100644
index 0000000..cb83295
--- /dev/null
+++ b/source/Target/StackFrame.cpp
@@ -0,0 +1,393 @@
+//===-- StackFrame.cpp ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/StackFrame.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+// The first bits in the flags are reserved for the SymbolContext::Scope bits
+// so we know if we have tried to look up information in our internal symbol
+// context (m_sc) already.
+#define RESOLVED_PC_SO_ADDR (uint32_t(eSymbolContextEverything + 1))
+#define RESOLVED_FRAME_ID   (RESOLVED_PC_SO_ADDR << 1)
+#define GOT_FRAME_BASE      (RESOLVED_FRAME_ID << 1)
+#define FRAME_IS_OBSOLETE   (GOT_FRAME_BASE << 1)
+#define RESOLVED_VARIABLES  (FRAME_IS_OBSOLETE << 1)
+
+StackFrame::StackFrame (lldb::user_id_t frame_idx, Thread &thread, lldb::addr_t cfa, lldb::addr_t pc, const SymbolContext *sc_ptr) :
+    UserID (frame_idx),
+    m_thread (thread),
+    m_reg_context_sp(),
+    m_id(cfa),
+    m_pc(NULL, pc),
+    m_sc(),
+    m_flags(),
+    m_frame_base(),
+    m_frame_base_error(),
+    m_variable_list_sp (),
+    m_value_object_list ()
+{
+    if (sc_ptr != NULL)
+        m_sc = *sc_ptr;
+}
+
+StackFrame::StackFrame (lldb::user_id_t frame_idx, Thread &thread, RegisterContextSP &reg_context_sp, lldb::addr_t cfa, lldb::addr_t pc, const SymbolContext *sc_ptr) :
+    UserID (frame_idx),
+    m_thread (thread),
+    m_reg_context_sp(reg_context_sp),
+    m_id(cfa),
+    m_pc(NULL, pc),
+    m_sc(),
+    m_flags(),
+    m_frame_base(),
+    m_frame_base_error(),
+    m_variable_list_sp (),
+    m_value_object_list ()
+{
+    if (sc_ptr != NULL)
+        m_sc = *sc_ptr;
+}
+
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+StackFrame::~StackFrame()
+{
+}
+
+StackID&
+StackFrame::GetStackID()
+{
+    // Make sure we have resolved our stack ID's address range before we give
+    // it out to any external clients
+    if (m_id.GetStartAddress().IsValid() == 0 && m_flags.IsClear(RESOLVED_FRAME_ID))
+    {
+        m_flags.Set (RESOLVED_FRAME_ID);
+
+        // Resolve our PC to section offset if we haven't alreday done so
+        // and if we don't have a module. The resolved address section will
+        // contain the module to which it belongs.
+        if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_PC_SO_ADDR))
+            GetPC();
+
+        const uint32_t resolve_scope = eSymbolContextModule |
+                                       eSymbolContextCompUnit |
+                                       eSymbolContextFunction;
+
+        if (m_sc.module_sp)
+        {
+            if (m_sc.module_sp->ResolveSymbolContextForAddress (GetPC(), resolve_scope, m_sc) & eSymbolContextFunction)
+            {
+                assert (m_sc.function);
+                m_id.SetStartAddress(m_sc.function->GetAddressRange().GetBaseAddress());
+            }
+            else if (m_sc.module_sp->ResolveSymbolContextForAddress (GetPC(), resolve_scope, m_sc) & eSymbolContextSymbol)
+            {
+                assert (m_sc.symbol);
+                AddressRange *symbol_range_ptr = m_sc.symbol->GetAddressRangePtr();
+                if (symbol_range_ptr)
+                    m_id.SetStartAddress(symbol_range_ptr->GetBaseAddress());
+            }
+        }
+//      else if (m_sc.target != NULL)
+//      {
+//          if (m_sc.target->GetImages().ResolveSymbolContextForAddress (GetPC(), resolve_scope, m_sc) & eSymbolContextFunction)
+//          {
+//              assert (m_sc.function);
+//              m_id.GetAddressRange() = m_sc.function->GetAddressRange();
+//          }
+//          else if (m_sc.target->GetImages().ResolveSymbolContextForAddress (GetPC(), resolve_scope, m_sc) & eSymbolContextSymbol)
+//          {
+//              assert (m_sc.symbol);
+//              AddressRange *symbol_range_ptr = m_sc.symbol->GetAddressRange();
+//              if (symbol_range_ptr)
+//                  m_id.GetAddressRange() = *symbol_range_ptr;
+//          }
+//      }
+    }
+    return m_id;
+}
+
+Address&
+StackFrame::GetPC()
+{
+    if (m_flags.IsClear(RESOLVED_PC_SO_ADDR) && !m_pc.IsSectionOffset())
+    {
+        m_flags.Set (RESOLVED_PC_SO_ADDR);
+
+        // Resolve the PC into a temporary address because if ResolveLoadAddress
+        // fails to resolve the address, it will clear the address object...
+        Address resolved_pc;
+        if (m_thread.GetProcess().ResolveLoadAddress(m_pc.GetOffset(), resolved_pc))
+        {
+            m_pc = resolved_pc;
+            const Section *section = m_pc.GetSection();
+            if (section)
+            {
+                Module *module = section->GetModule();
+                if (module)
+                {
+                    m_sc.module_sp = module->GetSP();
+                    if (m_sc.module_sp)
+                        m_flags.Set(eSymbolContextModule);
+                }
+            }
+        }
+    }
+    return m_pc;
+}
+
+void
+StackFrame::ChangePC (addr_t pc)
+{
+    m_pc.SetOffset(pc);
+    m_pc.SetSection(NULL);
+    m_sc.Clear();
+    m_flags.SetAllFlagBits(0);
+    m_thread.ClearStackFrames ();
+}
+
+const char *
+StackFrame::Disassemble ()
+{
+    if (m_disassembly.GetSize() == 0)
+    {
+        ExecutionContext exe_ctx;
+        Calculate(exe_ctx);
+        Disassembler::Disassemble (m_thread.GetProcess().GetTarget().GetArchitecture(),
+                                   exe_ctx,
+                                   0,
+                                   m_disassembly);
+        if (m_disassembly.GetSize() == 0)
+            return NULL;
+    }
+    return m_disassembly.GetData();
+}
+
+//----------------------------------------------------------------------
+// Get the symbol context if we already haven't done so by resolving the
+// PC address as much as possible. This way when we pass around a
+// StackFrame object, everyone will have as much information as
+// possible and no one will ever have to look things up manually.
+//----------------------------------------------------------------------
+const SymbolContext&
+StackFrame::GetSymbolContext (uint32_t resolve_scope)
+{
+    // Copy our internal symbol context into "sc".
+
+    if ((m_flags.GetAllFlagBits() & resolve_scope) != resolve_scope)
+    {
+        // Resolve our PC to section offset if we haven't alreday done so
+        // and if we don't have a module. The resolved address section will
+        // contain the module to which it belongs
+        if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_PC_SO_ADDR))
+            GetPC();
+
+        // If this is not frame zero, then we need to subtract 1 from the PC
+        // value when doing address lookups since the PC will be on the 
+        // instruction following the function call instruction...
+        
+        Address lookup_addr(GetPC());
+        if (GetID() > 0 && lookup_addr.IsValid())
+        {
+            addr_t offset = lookup_addr.GetOffset();
+            if (offset > 0)
+                lookup_addr.SetOffset(offset - 1);
+        }
+
+        if (m_sc.module_sp)
+        {
+            // We have something in our stack frame symbol context, lets check
+            // if we haven't already tried to lookup one of those things. If we
+            // haven't then we will do the query.
+            if ((m_sc.comp_unit == NULL     && (resolve_scope & eSymbolContextCompUnit ) && m_flags.IsClear(eSymbolContextCompUnit   )) ||
+                (m_sc.function  == NULL     && (resolve_scope & eSymbolContextFunction ) && m_flags.IsClear(eSymbolContextFunction   )) ||
+                (m_sc.block     == NULL     && (resolve_scope & eSymbolContextBlock    ) && m_flags.IsClear(eSymbolContextBlock      )) ||
+                (m_sc.symbol    == NULL     && (resolve_scope & eSymbolContextSymbol   ) && m_flags.IsClear(eSymbolContextSymbol     )) ||
+                (!m_sc.line_entry.IsValid() && (resolve_scope & eSymbolContextLineEntry) && m_flags.IsClear(eSymbolContextLineEntry  )))
+            {
+                // We might be resolving less information than what is already
+                // in our current symbol context so resolve into a temporary 
+                // symbol context "sc" so we don't clear out data we have 
+                // already found in "m_sc"
+                SymbolContext sc;
+                // Set flags that indicate what we have tried to resolve
+                const uint32_t resolved = m_sc.module_sp->ResolveSymbolContextForAddress (lookup_addr, resolve_scope, sc);
+                if (resolved & eSymbolContextCompUnit)  m_sc.comp_unit  = sc.comp_unit;
+                if (resolved & eSymbolContextFunction)  m_sc.function   = sc.function;
+                if (resolved & eSymbolContextBlock)     m_sc.block      = sc.block;
+                if (resolved & eSymbolContextSymbol)    m_sc.symbol     = sc.symbol;
+                if (resolved & eSymbolContextLineEntry) m_sc.line_entry = sc.line_entry;
+            }
+        }
+        else
+        {
+            // If we don't have a module, then we can't have the compile unit,
+            // function, block, line entry or symbol, so we can safely call
+            // ResolveSymbolContextForAddress with our symbol context member m_sc.
+            m_thread.GetProcess().GetTarget().GetImages().ResolveSymbolContextForAddress (lookup_addr, resolve_scope, m_sc);
+        }
+
+        // If the target was requested add that:
+        if (m_sc.target_sp.get() == NULL)
+            m_sc.target_sp = CalculateProcess()->GetTarget().GetSP();
+
+        // Update our internal flags so we remember what we have tried to locate so
+        // we don't have to keep trying when more calls to this function are made.
+        m_flags.Set(resolve_scope);
+    }
+
+    // Return the symbol context with everything that was possible to resolve
+    // resolved.
+    return m_sc;
+}
+
+
+VariableList *
+StackFrame::GetVariableList ()
+{
+    if (m_flags.IsClear(RESOLVED_VARIABLES))
+    {
+        m_flags.Set(RESOLVED_VARIABLES);
+
+        GetSymbolContext(eSymbolContextFunction);
+        if (m_sc.function)
+        {
+            bool get_child_variables = true;
+            bool can_create = true;
+            m_variable_list_sp = m_sc.function->GetBlocks(can_create).GetVariableList (Block::RootID, get_child_variables, can_create);
+        }
+    }
+    return m_variable_list_sp.get();
+}
+
+
+bool
+StackFrame::GetFrameBaseValue (Scalar &frame_base, Error *error_ptr)
+{
+    if (m_flags.IsClear(GOT_FRAME_BASE))
+    {
+        if (m_sc.function)
+        {
+            m_frame_base.Clear();
+            m_frame_base_error.Clear();
+
+            m_flags.Set(GOT_FRAME_BASE);
+            ExecutionContext exe_ctx (&m_thread.GetProcess(), &m_thread, this);
+            Value expr_value;
+            if (m_sc.function->GetFrameBaseExpression().Evaluate(&exe_ctx, NULL, NULL, expr_value, &m_frame_base_error) < 0)
+            {
+                // We should really have an error if evaluate returns, but in case
+                // we don't, lets set the error to something at least.
+                if (m_frame_base_error.Success())
+                    m_frame_base_error.SetErrorString("Evaluation of the frame base expression failed.");
+            }
+            else
+            {
+                m_frame_base = expr_value.ResolveValue(&exe_ctx, NULL);
+            }
+        }
+        else
+        {
+            m_frame_base_error.SetErrorString ("No function in symbol context.");
+        }
+    }
+
+    if (m_frame_base_error.Success())
+        frame_base = m_frame_base;
+
+    if (error_ptr)
+        *error_ptr = m_frame_base_error;
+    return m_frame_base_error.Success();
+}
+
+RegisterContext *
+StackFrame::GetRegisterContext ()
+{
+    if (m_reg_context_sp.get() == NULL)
+        m_reg_context_sp.reset (m_thread.CreateRegisterContextForFrame (this));
+    return m_reg_context_sp.get();
+}
+
+bool
+StackFrame::HasDebugInformation ()
+{
+    GetSymbolContext(eSymbolContextLineEntry);
+    return m_sc.line_entry.IsValid();
+}
+
+ValueObjectList &
+StackFrame::GetValueObjectList()
+{
+    return m_value_object_list;
+}
+
+
+Target *
+StackFrame::CalculateTarget ()
+{
+    return m_thread.CalculateTarget();
+}
+
+Process *
+StackFrame::CalculateProcess ()
+{
+    return m_thread.CalculateProcess();
+}
+
+Thread *
+StackFrame::CalculateThread ()
+{
+    return &m_thread;
+}
+
+StackFrame *
+StackFrame::CalculateStackFrame ()
+{
+    return this;
+}
+
+
+void
+StackFrame::Calculate (ExecutionContext &exe_ctx)
+{
+    m_thread.Calculate (exe_ctx);
+    exe_ctx.frame = this;
+}
+
+void
+StackFrame::Dump (Stream *strm, bool show_frame_index)
+{
+    if (strm == NULL)
+        return;
+
+    if (show_frame_index)
+        strm->Printf("frame #%u: ", GetID());
+    strm->Printf("pc = 0x%0*llx", m_thread.GetProcess().GetAddressByteSize() * 2, GetRegisterContext()->GetPC());
+    SymbolContext sc (GetSymbolContext(eSymbolContextEverything));
+    strm->PutCString(", where = ");
+    sc.DumpStopContext(strm, &m_thread.GetProcess(), GetPC());
+}
+