1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
|
//===-- RegisterContextLLDB.h --------------------------------------------*- C++
//-*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef lldb_RegisterContextLLDB_h_
#define lldb_RegisterContextLLDB_h_
// C Includes
// C++ Includes
#include <vector>
// Other libraries and framework includes
// Project includes
#include "UnwindLLDB.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/RegisterNumber.h"
#include "lldb/lldb-private.h"
namespace lldb_private {
class UnwindLLDB;
class RegisterContextLLDB : public lldb_private::RegisterContext {
public:
typedef std::shared_ptr<RegisterContextLLDB> SharedPtr;
RegisterContextLLDB(lldb_private::Thread &thread, const SharedPtr &next_frame,
lldb_private::SymbolContext &sym_ctx,
uint32_t frame_number,
lldb_private::UnwindLLDB &unwind_lldb);
~RegisterContextLLDB() override = default;
void InvalidateAllRegisters() override;
size_t GetRegisterCount() override;
const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override;
size_t GetRegisterSetCount() override;
const lldb_private::RegisterSet *GetRegisterSet(size_t reg_set) override;
bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
lldb_private::RegisterValue &value) override;
bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
const lldb_private::RegisterValue &value) override;
bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
uint32_t num) override;
bool IsValid() const;
bool IsTrapHandlerFrame() const;
bool GetCFA(lldb::addr_t &cfa);
bool GetStartPC(lldb::addr_t &start_pc);
bool ReadPC(lldb::addr_t &start_pc);
private:
enum FrameType {
eNormalFrame,
eTrapHandlerFrame,
eDebuggerFrame, // a debugger inferior function call frame; we get caller's
// registers from debugger
eSkipFrame, // The unwind resulted in a bogus frame but may get back on
// track so we don't want to give up yet
eNotAValidFrame // this frame is invalid for some reason - most likely it is
// past the top (end) of the stack
};
// UnwindLLDB needs to pass around references to RegisterLocations
friend class UnwindLLDB;
// Returns true if we have an unwind loop -- the same stack frame unwinding
// multiple times.
bool CheckIfLoopingStack();
// Indicates whether this frame is frame zero -- the currently
// executing frame -- or not.
bool IsFrameZero() const;
void InitializeZerothFrame();
void InitializeNonZerothFrame();
SharedPtr GetNextFrame() const;
SharedPtr GetPrevFrame() const;
// A SkipFrame occurs when the unwind out of frame 0 didn't go right -- we've
// got one bogus frame at frame #1.
// There is a good chance we'll get back on track if we follow the frame
// pointer chain (or whatever is appropriate
// on this ABI) so we allow one invalid frame to be in the stack. Ideally
// we'll mark this frame specially at some
// point and indicate to the user that the unwinder had a hiccup. Often when
// this happens we will miss a frame of
// the program's actual stack in the unwind and we want to flag that for the
// user somehow.
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.
//
// The RegisterLocation type may be set to eRegisterNotAvailable -- this will
// happen for a volatile register
// being queried mid-stack. Instead of floating frame 0's contents of that
// register up the stack (which may
// or may not be the value of that reg when the function was executing), we
// won't return any value.
//
// If a non-volatile register (a "preserved" register) is requested mid-stack
// and no frames "below" the requested
// stack have saved the register anywhere, it is safe to assume that frame 0's
// register values are still the same
// as the requesting frame's.
lldb_private::UnwindLLDB::RegisterSearchResult
SavedLocationForRegister(uint32_t lldb_regnum,
lldb_private::UnwindLLDB::RegisterLocation ®loc);
bool ReadRegisterValueFromRegisterLocation(
lldb_private::UnwindLLDB::RegisterLocation regloc,
const lldb_private::RegisterInfo *reg_info,
lldb_private::RegisterValue &value);
bool WriteRegisterValueToRegisterLocation(
lldb_private::UnwindLLDB::RegisterLocation regloc,
const lldb_private::RegisterInfo *reg_info,
const lldb_private::RegisterValue &value);
//------------------------------------------------------------------
/// If the unwind has to the caller frame has failed, try something else
///
/// If lldb is using an assembly language based UnwindPlan for a frame and
/// the unwind to the caller frame fails, try falling back to a generic
/// UnwindPlan (architecture default unwindplan) to see if that might work
/// better. This is mostly helping to work around problems where the
/// assembly language inspection fails on hand-written assembly code.
///
/// @return
/// Returns true if a fallback unwindplan was found & was installed.
//------------------------------------------------------------------
bool TryFallbackUnwindPlan();
//------------------------------------------------------------------
/// Switch to the fallback unwind plan unconditionally without any safety
/// checks that it is providing better results than the normal unwind plan.
///
/// The only time it is valid to call this method is if the full unwindplan is
/// found to be fundamentally incorrect/impossible.
///
/// Returns true if it was able to install the fallback unwind plan.
//------------------------------------------------------------------
bool ForceSwitchToFallbackUnwindPlan();
// Get the contents of a general purpose (address-size) register for this
// frame
// (usually retrieved from the next frame)
bool ReadGPRValue(lldb::RegisterKind register_kind, uint32_t regnum,
lldb::addr_t &value);
bool ReadGPRValue(const RegisterNumber ®_num, lldb::addr_t &value);
// Get the CFA register for a given frame.
bool ReadCFAValueForRow(lldb::RegisterKind register_kind,
const UnwindPlan::RowSP &row, lldb::addr_t &value);
lldb::UnwindPlanSP GetFastUnwindPlanForFrame();
lldb::UnwindPlanSP GetFullUnwindPlanForFrame();
void UnwindLogMsg(const char *fmt, ...) __attribute__((format(printf, 2, 3)));
void UnwindLogMsgVerbose(const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
bool IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp,
int &valid_pc_offset);
lldb_private::Thread &m_thread;
///
// The following tell us how to retrieve the CALLER's register values (ie the
// "previous" frame, aka the frame above)
// i.e. where THIS frame saved them
///
lldb::UnwindPlanSP m_fast_unwind_plan_sp; // may be NULL
lldb::UnwindPlanSP m_full_unwind_plan_sp;
lldb::UnwindPlanSP m_fallback_unwind_plan_sp; // may be NULL
bool m_all_registers_available; // Can we retrieve all regs or just
// nonvolatile regs?
int m_frame_type; // enum FrameType
lldb::addr_t m_cfa;
lldb_private::Address m_start_pc;
lldb_private::Address m_current_pc;
int m_current_offset; // how far into the function we've executed; -1 if
// unknown
// 0 if no instructions have been executed yet.
int m_current_offset_backed_up_one; // how far into the function we've
// executed; -1 if unknown
// 0 if no instructions have been executed yet.
// On architectures where the return address on the stack points
// to the instruction after the CALL, this value will have 1
// subtracted from it. Else a function that ends in a CALL will
// have an offset pointing into the next function's address range.
// m_current_pc has the actual address of the "current" pc.
lldb_private::SymbolContext &m_sym_ctx;
bool m_sym_ctx_valid; // if ResolveSymbolContextForAddress fails, don't try to
// use m_sym_ctx
uint32_t m_frame_number; // What stack frame this RegisterContext is
std::map<uint32_t, lldb_private::UnwindLLDB::RegisterLocation>
m_registers; // where to find reg values for this frame
lldb_private::UnwindLLDB &m_parent_unwind; // The UnwindLLDB that is creating
// this RegisterContextLLDB
//------------------------------------------------------------------
// For RegisterContextLLDB only
//------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN(RegisterContextLLDB);
};
} // namespace lldb_private
#endif // lldb_RegisterContextLLDB_h_
|