Add a new target setting, trap-handler-names, where a user can
specify a list of functions which should be treated as trap handlers.
This will be primarily useful to people working in non-user-level
process debugging - kernels and other standalone environments.
For most people, the trap handler functions provided by the Platform
plugin will be sufficient.

<rdar://problem/15835846>, <rdar://problem/15982682> 

llvm-svn: 201386
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index 3f4c660..f87db58 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -172,21 +172,15 @@
     AddressRange addr_range;
     m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range);
 
-    m_frame_type = eNormalFrame;
-    PlatformSP platform_sp (process->GetTarget().GetPlatform());
-    if (platform_sp)
+    if (IsTrapHandlerSymbol (process, m_sym_ctx))
     {
-        const std::vector<ConstString> trap_handler_names (platform_sp->GetTrapHandlerSymbolNames());
-        for (ConstString name : trap_handler_names)
-        {
-            if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == name) ||
-                (m_sym_ctx.symbol   && m_sym_ctx.symbol->GetName()   == name))
-            {
-                m_frame_type = eTrapHandlerFrame;
-            }
-        }
+        m_frame_type = eTrapHandlerFrame;
     }
-    // FIXME:  Detect eDebuggerFrame here.
+    else
+    {
+        // FIXME:  Detect eDebuggerFrame here.
+        m_frame_type = eNormalFrame;
+    }
 
     // If we were able to find a symbol/function, set addr_range to the bounds of that symbol/function.
     // else treat the current pc value as the start_pc and record no offset.
@@ -497,25 +491,18 @@
         m_current_offset_backed_up_one = -1;
     }
 
-    if (m_frame_type != eSkipFrame) // don't override eSkipFrame
+    if (IsTrapHandlerSymbol (process, m_sym_ctx))
     {
-        m_frame_type = eNormalFrame;
+        m_frame_type = eTrapHandlerFrame;
     }
-    PlatformSP platform_sp (process->GetTarget().GetPlatform());
-    if (platform_sp)
+    else
     {
-        const std::vector<ConstString> trap_handler_names (platform_sp->GetTrapHandlerSymbolNames());
-        for (ConstString name : trap_handler_names)
+        // FIXME:  Detect eDebuggerFrame here.
+        if (m_frame_type != eSkipFrame) // don't override eSkipFrame
         {
-            if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == name) ||
-                (m_sym_ctx.symbol   && m_sym_ctx.symbol->GetName()   == name))
-            {
-                m_frame_type = eTrapHandlerFrame;
-            }
+            m_frame_type = eNormalFrame;
         }
     }
-    // FIXME:  Detect eDebuggerFrame here.
-
 
     // We've set m_frame_type and m_sym_ctx before this call.
     m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame ();
@@ -1010,6 +997,35 @@
     return m_frame_type == eSkipFrame;
 }
 
+bool
+RegisterContextLLDB::IsTrapHandlerSymbol (lldb_private::Process *process, const lldb_private::SymbolContext &m_sym_ctx) const
+{
+    PlatformSP platform_sp (process->GetTarget().GetPlatform());
+    if (platform_sp)
+    {
+        const std::vector<ConstString> trap_handler_names (platform_sp->GetTrapHandlerSymbolNames());
+        for (ConstString name : trap_handler_names)
+        {
+            if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == name) ||
+                (m_sym_ctx.symbol   && m_sym_ctx.symbol->GetName()   == name))
+            {
+                return true;
+            }
+        }
+    }
+    const std::vector<ConstString> user_specified_trap_handler_names (m_parent_unwind.GetUserSpecifiedTrapHandlerFunctionNames());
+    for (ConstString name : user_specified_trap_handler_names)
+    {   
+        if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == name) ||
+            (m_sym_ctx.symbol   && m_sym_ctx.symbol->GetName()   == name))
+        {   
+            return true;
+        }   
+    }   
+
+    return false;
+}
+
 // Answer the question: Where did THIS frame save the CALLER frame ("previous" frame)'s register value?
 
 enum UnwindLLDB::RegisterSearchResult
@@ -1633,3 +1649,4 @@
     }
 }
 
+
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
index 5054572..bf9dd9a 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
@@ -123,6 +123,19 @@
     bool
     IsSkipFrame () const;
 
+
+    //------------------------------------------------------------------
+    /// Determines if a SymbolContext is a trap handler or not
+    ///
+    /// Given a SymbolContext, determines if this is a trap handler function
+    /// aka asynchronous signal handler.
+    ///
+    /// @return
+    ///     Returns true if the SymbolContext is a trap handler.
+    //------------------------------------------------------------------
+    bool
+    IsTrapHandlerSymbol (lldb_private::Process *process, const lldb_private::SymbolContext &m_sym_ctx) const;
+
     // Provide a location for where THIS function saved the CALLER's register value
     // Or a frame "below" this one saved it, i.e. a function called by this one, preserved a register that this
     // function didn't modify/use.
diff --git a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
index 36223db..a3a7002 100644
--- a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
+++ b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
@@ -26,8 +26,21 @@
 UnwindLLDB::UnwindLLDB (Thread &thread) :
     Unwind (thread),
     m_frames(),
-    m_unwind_complete(false)
+    m_unwind_complete(false),
+    m_user_supplied_trap_handler_functions()
 {
+    ProcessSP process_sp(thread.GetProcess());
+    if (process_sp)
+    {
+        Args args;
+        process_sp->GetTarget().GetUserSpecifiedTrapHandlerNames (args);
+        size_t count = args.GetArgumentCount();
+        for (size_t i = 0; i < count; i++)
+        {
+            const char *func_name = args.GetArgumentAtIndex(i);
+            m_user_supplied_trap_handler_functions.push_back (ConstString (func_name));
+        }
+    }
 }
 
 uint32_t
diff --git a/lldb/source/Plugins/Process/Utility/UnwindLLDB.h b/lldb/source/Plugins/Process/Utility/UnwindLLDB.h
index 5725654..eb54003 100644
--- a/lldb/source/Plugins/Process/Utility/UnwindLLDB.h
+++ b/lldb/source/Plugins/Process/Utility/UnwindLLDB.h
@@ -13,6 +13,7 @@
 #include <vector>
 
 #include "lldb/lldb-public.h"
+#include "lldb/Core/ConstString.h"
 #include "lldb/Symbol/FuncUnwinders.h"
 #include "lldb/Symbol/UnwindPlan.h"
 #include "lldb/Target/RegisterContext.h"
@@ -90,6 +91,24 @@
     SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc, uint32_t starting_frame_num, bool pc_register);
 
 
+    //------------------------------------------------------------------
+    /// Provide the list of user-specified trap handler functions
+    ///
+    /// The Platform is one source of trap handler function names; that
+    /// may be augmented via a setting.  The setting needs to be converted
+    /// into an array of ConstStrings before it can be used - we only want
+    /// to do that once per thread so it's here in the UnwindLLDB object.
+    ///
+    /// @return
+    ///     Vector of ConstStrings of trap handler function names.  May be
+    ///     empty.
+    //------------------------------------------------------------------
+    const std::vector<ConstString> &
+    GetUserSpecifiedTrapHandlerFunctionNames ()
+    {
+        return m_user_supplied_trap_handler_functions;
+    }
+
 private:
 
     struct Cursor
@@ -110,6 +129,7 @@
                             // number of frames, etc.  Otherwise we've only gone as far as directly asked, and m_frames.size()
                             // is how far we've currently gone.
  
+    std::vector<ConstString> m_user_supplied_trap_handler_functions;
 
     bool AddOneMoreFrame (ABI *abi);
     bool AddFirstFrame ();