blob: 2e841b3b34bd667f67bfb514a2e095f31eaa3bd6 [file] [log] [blame]
#ifndef LLDB_SYMBOL_FUNCUNWINDERS_H
#define LLDB_SYMBOL_FUNCUNWINDERS_H
#include "lldb/Core/AddressRange.h"
#include "lldb/lldb-private-enumerations.h"
#include <mutex>
#include <vector>
namespace lldb_private {
class UnwindTable;
class FuncUnwinders {
public:
// 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);
~FuncUnwinders();
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);
lldb::UnwindPlanSP
GetUnwindPlanArchitectureDefault(lldb_private::Thread &thread);
lldb::UnwindPlanSP
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);
private:
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;
FuncUnwinders(const FuncUnwinders &) = delete;
const FuncUnwinders &operator=(const FuncUnwinders &) = delete;
}; // class FuncUnwinders
} // namespace lldb_private
#endif // LLDB_SYMBOL_FUNCUNWINDERS_H