blob: c49f6b0fa942ad1b403e746096cf68c9822b8182 [file] [log] [blame]
#ifndef liblldb_FuncUnwinders_h
#define liblldb_FuncUnwinders_h
#include "lldb/Core/AddressRange.h"
#include "lldb/lldb-private-enumerations.h"
#include <mutex>
#include <vector>
namespace lldb_private {
class UnwindTable;
class FuncUnwinders {
// FuncUnwinders objects are used to track UnwindPlans for a function (named
// or not - really just an address range)
// We'll record four different UnwindPlans for each address range:
// 1. Unwinding from a call site (a valid exception throw location)
// This is often sourced from the eh_frame exception handling info
// 2. Unwinding from a non-call site (any location in the function)
// This is often done by analyzing the function prologue assembly
// language instructions
// 3. A fast unwind method for this function which only retrieves a
// limited set of registers necessary to walk the stack
// 4. An architectural default unwind plan when none of the above are
// available for some reason.
// Additionally, FuncUnwinds object can be asked where the prologue
// instructions are finished for migrating breakpoints past the stack frame
// setup instructions when we don't have line table information.
FuncUnwinders(lldb_private::UnwindTable &unwind_table, AddressRange range);
lldb::UnwindPlanSP GetUnwindPlanAtCallSite(Target &target, Thread &thread);
lldb::UnwindPlanSP GetUnwindPlanAtNonCallSite(Target &target,
lldb_private::Thread &thread);
lldb::UnwindPlanSP GetUnwindPlanFastUnwind(Target &target,
lldb_private::Thread &thread);
GetUnwindPlanArchitectureDefault(lldb_private::Thread &thread);
GetUnwindPlanArchitectureDefaultAtFunctionEntry(lldb_private::Thread &thread);
Address &GetFirstNonPrologueInsn(Target &target);
const Address &GetFunctionStartAddress() const;
bool ContainsAddress(const Address &addr) const {
return m_range.ContainsFileAddress(addr);
// A function may have a Language Specific Data Area specified -- a block of
// data in
// the object file which is used in the processing of an exception throw /
// catch. If any of the UnwindPlans have the address of the LSDA region for
// this function, this will return it.
Address GetLSDAAddress(Target &target);
// A function may have a Personality Routine associated with it -- used in the
// processing of throwing an exception. If any of the UnwindPlans have the
// address of the personality routine, this will return it. Read the target-
// pointer at this address to get the personality function address.
Address GetPersonalityRoutinePtrAddress(Target &target);
// The following methods to retrieve specific unwind plans should rarely be
// used. Instead, clients should ask for the *behavior* they are looking for,
// using one of the above UnwindPlan retrieval methods.
lldb::UnwindPlanSP GetAssemblyUnwindPlan(Target &target, Thread &thread);
lldb::UnwindPlanSP GetObjectFileUnwindPlan(Target &target);
lldb::UnwindPlanSP GetObjectFileAugmentedUnwindPlan(Target &target,
Thread &thread);
lldb::UnwindPlanSP GetEHFrameUnwindPlan(Target &target);
lldb::UnwindPlanSP GetEHFrameAugmentedUnwindPlan(Target &target,
Thread &thread);
lldb::UnwindPlanSP GetDebugFrameUnwindPlan(Target &target);
lldb::UnwindPlanSP GetDebugFrameAugmentedUnwindPlan(Target &target,
Thread &thread);
lldb::UnwindPlanSP GetCompactUnwindUnwindPlan(Target &target);
lldb::UnwindPlanSP GetArmUnwindUnwindPlan(Target &target);
lldb::UnwindPlanSP GetSymbolFileUnwindPlan(Thread &thread);
lldb::UnwindPlanSP GetArchDefaultUnwindPlan(Thread &thread);
lldb::UnwindPlanSP GetArchDefaultAtFuncEntryUnwindPlan(Thread &thread);
lldb::UnwindAssemblySP GetUnwindAssemblyProfiler(Target &target);
// Do a simplistic comparison for the register restore rule for getting the
// caller's pc value on two UnwindPlans -- returns LazyBoolYes if they have
// the same unwind rule for the pc, LazyBoolNo if they do not have the same
// unwind rule for the pc, and LazyBoolCalculate if it was unable to
// determine this for some reason.
lldb_private::LazyBool CompareUnwindPlansForIdenticalInitialPCLocation(
Thread &thread, const lldb::UnwindPlanSP &a, const lldb::UnwindPlanSP &b);
UnwindTable &m_unwind_table;
AddressRange m_range;
std::recursive_mutex m_mutex;
lldb::UnwindPlanSP m_unwind_plan_assembly_sp;
lldb::UnwindPlanSP m_unwind_plan_object_file_sp;
lldb::UnwindPlanSP m_unwind_plan_eh_frame_sp;
lldb::UnwindPlanSP m_unwind_plan_debug_frame_sp;
// augmented by assembly inspection so it's valid everywhere
lldb::UnwindPlanSP m_unwind_plan_object_file_augmented_sp;
lldb::UnwindPlanSP m_unwind_plan_eh_frame_augmented_sp;
lldb::UnwindPlanSP m_unwind_plan_debug_frame_augmented_sp;
std::vector<lldb::UnwindPlanSP> m_unwind_plan_compact_unwind;
lldb::UnwindPlanSP m_unwind_plan_arm_unwind_sp;
lldb::UnwindPlanSP m_unwind_plan_symbol_file_sp;
lldb::UnwindPlanSP m_unwind_plan_fast_sp;
lldb::UnwindPlanSP m_unwind_plan_arch_default_sp;
lldb::UnwindPlanSP m_unwind_plan_arch_default_at_func_entry_sp;
// Fetching the UnwindPlans can be expensive - if we've already attempted to
// get one & failed, don't try again.
bool m_tried_unwind_plan_assembly : 1, m_tried_unwind_plan_eh_frame : 1,
m_tried_unwind_plan_object_file : 1,
m_tried_unwind_plan_debug_frame : 1,
m_tried_unwind_plan_object_file_augmented : 1,
m_tried_unwind_plan_eh_frame_augmented : 1,
m_tried_unwind_plan_debug_frame_augmented : 1,
m_tried_unwind_plan_compact_unwind : 1,
m_tried_unwind_plan_arm_unwind : 1, m_tried_unwind_plan_symbol_file : 1,
m_tried_unwind_fast : 1, m_tried_unwind_arch_default : 1,
m_tried_unwind_arch_default_at_func_entry : 1;
Address m_first_non_prologue_insn;
}; // class FuncUnwinders
} // namespace lldb_private
#endif // liblldb_FuncUnwinders_h