Add a new target setting, trap-handler-names, where a user can
authorJason Molenda <jmolenda@apple.com>
Fri, 14 Feb 2014 05:06:49 +0000 (05:06 +0000)
committerJason Molenda <jmolenda@apple.com>
Fri, 14 Feb 2014 05:06:49 +0000 (05:06 +0000)
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

lldb/include/lldb/Target/Target.h
lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
lldb/source/Plugins/Process/Utility/UnwindLLDB.h
lldb/source/Target/Target.cpp

index 75fd1d9..e65a511 100644 (file)
@@ -177,6 +177,11 @@ public:
     MemoryModuleLoadLevel
     GetMemoryModuleLoadLevel() const;
 
+    bool
+    GetUserSpecifiedTrapHandlerNames (Args &args) const;
+
+    void
+    SetUserSpecifiedTrapHandlerNames (const Args &args);
 };
 
 typedef std::shared_ptr<TargetProperties> TargetPropertiesSP;
index 3f4c660..f87db58 100644 (file)
@@ -172,21 +172,15 @@ RegisterContextLLDB::InitializeZerothFrame()
     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;
+    }
+    else
+    {
+        // FIXME:  Detect eDebuggerFrame here.
+        m_frame_type = eNormalFrame;
     }
-    // FIXME:  Detect eDebuggerFrame here.
 
     // 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 @@ RegisterContextLLDB::InitializeNonZerothFrame()
         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 @@ RegisterContextLLDB::IsSkipFrame () const
     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 @@ RegisterContextLLDB::UnwindLogMsgVerbose (const char *fmt, ...)
     }
 }
 
+
index 5054572..bf9dd9a 100644 (file)
@@ -123,6 +123,19 @@ private:
     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.
index 36223db..a3a7002 100644 (file)
@@ -26,8 +26,21 @@ using namespace lldb_private;
 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
index 5725654..eb54003 100644 (file)
@@ -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 @@ protected:
     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 @@ private:
                             // 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 ();
index 3a98025..e781626 100644 (file)
@@ -2638,6 +2638,7 @@ g_properties[] =
         "'partial' will load sections and attempt to find function bounds without downloading the symbol table (faster, still accurate, missing symbol names). "
         "'minimal' is the fastest setting and will load section data with no symbols, but should rarely be used as stack frames in these memory regions will be inaccurate and not provide any context (fastest). " },
     { "display-expression-in-crashlogs"    , OptionValue::eTypeBoolean   , false, false,                      NULL, NULL, "Expressions that crash will show up in crash logs if the host system supports executable specific crash log strings and this setting is set to true." },
+    { "trap-handler-names"                 , OptionValue::eTypeArray     , true,  OptionValue::eTypeString,   NULL, NULL, "A list of trap handler function names, e.g. a common Unix user process one is _sigtramp." },
     { NULL                                 , OptionValue::eTypeInvalid   , false, 0                         , NULL, NULL, NULL }
 };
 enum
@@ -2670,7 +2671,8 @@ enum
     ePropertyUseFastStepping,
     ePropertyLoadScriptFromSymbolFile,
     ePropertyMemoryModuleLoadLevel,
-    ePropertyDisplayExpressionsInCrashlogs
+    ePropertyDisplayExpressionsInCrashlogs,
+    ePropertyTrapHandlerNames
 };
 
 
@@ -3077,7 +3079,19 @@ TargetProperties::GetMemoryModuleLoadLevel() const
     return (MemoryModuleLoadLevel)m_collection_sp->GetPropertyAtIndexAsEnumeration(NULL, idx, g_properties[idx].default_uint_value);
 }
 
+bool
+TargetProperties::GetUserSpecifiedTrapHandlerNames (Args &args) const
+{
+    const uint32_t idx = ePropertyTrapHandlerNames;
+    return m_collection_sp->GetPropertyAtIndexAsArgs (NULL, idx, args);
+}
 
+void
+TargetProperties::SetUserSpecifiedTrapHandlerNames (const Args &args)
+{
+    const uint32_t idx = ePropertyTrapHandlerNames;
+    m_collection_sp->SetPropertyAtIndexFromArgs (NULL, idx, args);
+}
 
 //----------------------------------------------------------------------
 // Target::TargetEventData