From a4bea72ee72a8e477e9f6fd139ad24754efeac02 Mon Sep 17 00:00:00 2001 From: Jason Molenda Date: Fri, 14 Feb 2014 05:06:49 +0000 Subject: [PATCH] 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. , llvm-svn: 201386 --- lldb/include/lldb/Target/Target.h | 5 ++ .../Process/Utility/RegisterContextLLDB.cpp | 69 ++++++++++++------- .../Process/Utility/RegisterContextLLDB.h | 13 ++++ .../Plugins/Process/Utility/UnwindLLDB.cpp | 15 +++- .../Plugins/Process/Utility/UnwindLLDB.h | 20 ++++++ lldb/source/Target/Target.cpp | 16 ++++- 6 files changed, 110 insertions(+), 28 deletions(-) diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 75fd1d9703b5..e65a511ab77a 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -177,6 +177,11 @@ public: MemoryModuleLoadLevel GetMemoryModuleLoadLevel() const; + bool + GetUserSpecifiedTrapHandlerNames (Args &args) const; + + void + SetUserSpecifiedTrapHandlerNames (const Args &args); }; typedef std::shared_ptr TargetPropertiesSP; diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index 3f4c6609a523..f87db5810740 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -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 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 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 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 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, ...) } } + diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h index 505457260da0..bf9dd9a29319 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h @@ -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. diff --git a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp index 36223db8186d..a3a7002ea099 100644 --- a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp +++ b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp @@ -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 diff --git a/lldb/source/Plugins/Process/Utility/UnwindLLDB.h b/lldb/source/Plugins/Process/Utility/UnwindLLDB.h index 5725654a6869..eb5400389df3 100644 --- a/lldb/source/Plugins/Process/Utility/UnwindLLDB.h +++ b/lldb/source/Plugins/Process/Utility/UnwindLLDB.h @@ -13,6 +13,7 @@ #include #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 ®loc, 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 & + 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 m_user_supplied_trap_handler_functions; bool AddOneMoreFrame (ABI *abi); bool AddFirstFrame (); diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 3a980251ef69..e7816266b415 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -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