xref: /freebsd-src/contrib/llvm-project/lldb/include/lldb/Target/RegisterContextUnwind.h (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
15ffd83dbSDimitry Andric //===-- RegisterContextUnwind.h ---------------------------------*- C++ -*-===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric 
95ffd83dbSDimitry Andric #ifndef LLDB_TARGET_REGISTERCONTEXTUNWIND_H
105ffd83dbSDimitry Andric #define LLDB_TARGET_REGISTERCONTEXTUNWIND_H
115ffd83dbSDimitry Andric 
125ffd83dbSDimitry Andric #include <vector>
135ffd83dbSDimitry Andric 
145ffd83dbSDimitry Andric #include "lldb/Symbol/SymbolContext.h"
155ffd83dbSDimitry Andric #include "lldb/Symbol/UnwindPlan.h"
165ffd83dbSDimitry Andric #include "lldb/Target/RegisterContext.h"
175ffd83dbSDimitry Andric #include "lldb/Target/RegisterNumber.h"
185ffd83dbSDimitry Andric #include "lldb/Target/UnwindLLDB.h"
195ffd83dbSDimitry Andric #include "lldb/lldb-private.h"
205ffd83dbSDimitry Andric 
215ffd83dbSDimitry Andric namespace lldb_private {
225ffd83dbSDimitry Andric 
235ffd83dbSDimitry Andric class UnwindLLDB;
245ffd83dbSDimitry Andric 
255ffd83dbSDimitry Andric class RegisterContextUnwind : public lldb_private::RegisterContext {
265ffd83dbSDimitry Andric public:
275ffd83dbSDimitry Andric   typedef std::shared_ptr<RegisterContextUnwind> SharedPtr;
285ffd83dbSDimitry Andric 
295ffd83dbSDimitry Andric   RegisterContextUnwind(lldb_private::Thread &thread,
305ffd83dbSDimitry Andric                         const SharedPtr &next_frame,
315ffd83dbSDimitry Andric                         lldb_private::SymbolContext &sym_ctx,
325ffd83dbSDimitry Andric                         uint32_t frame_number,
335ffd83dbSDimitry Andric                         lldb_private::UnwindLLDB &unwind_lldb);
345ffd83dbSDimitry Andric 
355ffd83dbSDimitry Andric   ~RegisterContextUnwind() override = default;
365ffd83dbSDimitry Andric 
375ffd83dbSDimitry Andric   void InvalidateAllRegisters() override;
385ffd83dbSDimitry Andric 
395ffd83dbSDimitry Andric   size_t GetRegisterCount() override;
405ffd83dbSDimitry Andric 
415ffd83dbSDimitry Andric   const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override;
425ffd83dbSDimitry Andric 
435ffd83dbSDimitry Andric   size_t GetRegisterSetCount() override;
445ffd83dbSDimitry Andric 
455ffd83dbSDimitry Andric   const lldb_private::RegisterSet *GetRegisterSet(size_t reg_set) override;
465ffd83dbSDimitry Andric 
475ffd83dbSDimitry Andric   bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
485ffd83dbSDimitry Andric                     lldb_private::RegisterValue &value) override;
495ffd83dbSDimitry Andric 
505ffd83dbSDimitry Andric   bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
515ffd83dbSDimitry Andric                      const lldb_private::RegisterValue &value) override;
525ffd83dbSDimitry Andric 
53*81ad6265SDimitry Andric   bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;
545ffd83dbSDimitry Andric 
555ffd83dbSDimitry Andric   bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
565ffd83dbSDimitry Andric 
575ffd83dbSDimitry Andric   uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
585ffd83dbSDimitry Andric                                                uint32_t num) override;
595ffd83dbSDimitry Andric 
605ffd83dbSDimitry Andric   bool IsValid() const;
615ffd83dbSDimitry Andric 
625ffd83dbSDimitry Andric   bool IsTrapHandlerFrame() const;
635ffd83dbSDimitry Andric 
645ffd83dbSDimitry Andric   bool GetCFA(lldb::addr_t &cfa);
655ffd83dbSDimitry Andric 
665ffd83dbSDimitry Andric   bool GetStartPC(lldb::addr_t &start_pc);
675ffd83dbSDimitry Andric 
685ffd83dbSDimitry Andric   bool ReadPC(lldb::addr_t &start_pc);
695ffd83dbSDimitry Andric 
70fe6060f1SDimitry Andric   // Indicates whether this frame *behaves* like frame zero -- the currently
71fe6060f1SDimitry Andric   // executing frame -- or not.  This can be true in the middle of the stack
72fe6060f1SDimitry Andric   // above asynchronous trap handlers (sigtramp) for instance.
73fe6060f1SDimitry Andric   bool BehavesLikeZerothFrame() const override;
74fe6060f1SDimitry Andric 
755ffd83dbSDimitry Andric private:
765ffd83dbSDimitry Andric   enum FrameType {
775ffd83dbSDimitry Andric     eNormalFrame,
785ffd83dbSDimitry Andric     eTrapHandlerFrame,
795ffd83dbSDimitry Andric     eDebuggerFrame, // a debugger inferior function call frame; we get caller's
805ffd83dbSDimitry Andric                     // registers from debugger
815ffd83dbSDimitry Andric     eSkipFrame,     // The unwind resulted in a bogus frame but may get back on
825ffd83dbSDimitry Andric                     // track so we don't want to give up yet
835ffd83dbSDimitry Andric     eNotAValidFrame // this frame is invalid for some reason - most likely it is
845ffd83dbSDimitry Andric                     // past the top (end) of the stack
855ffd83dbSDimitry Andric   };
865ffd83dbSDimitry Andric 
875ffd83dbSDimitry Andric   // UnwindLLDB needs to pass around references to RegisterLocations
885ffd83dbSDimitry Andric   friend class UnwindLLDB;
895ffd83dbSDimitry Andric 
905ffd83dbSDimitry Andric   // Returns true if we have an unwind loop -- the same stack frame unwinding
915ffd83dbSDimitry Andric   // multiple times.
925ffd83dbSDimitry Andric   bool CheckIfLoopingStack();
935ffd83dbSDimitry Andric 
945ffd83dbSDimitry Andric   // Indicates whether this frame is frame zero -- the currently
955ffd83dbSDimitry Andric   // executing frame -- or not.
965ffd83dbSDimitry Andric   bool IsFrameZero() const;
975ffd83dbSDimitry Andric 
985ffd83dbSDimitry Andric   void InitializeZerothFrame();
995ffd83dbSDimitry Andric 
1005ffd83dbSDimitry Andric   void InitializeNonZerothFrame();
1015ffd83dbSDimitry Andric 
1025ffd83dbSDimitry Andric   SharedPtr GetNextFrame() const;
1035ffd83dbSDimitry Andric 
1045ffd83dbSDimitry Andric   SharedPtr GetPrevFrame() const;
1055ffd83dbSDimitry Andric 
1065ffd83dbSDimitry Andric   // A SkipFrame occurs when the unwind out of frame 0 didn't go right -- we've
1075ffd83dbSDimitry Andric   // got one bogus frame at frame #1.
1085ffd83dbSDimitry Andric   // There is a good chance we'll get back on track if we follow the frame
1095ffd83dbSDimitry Andric   // pointer chain (or whatever is appropriate
1105ffd83dbSDimitry Andric   // on this ABI) so we allow one invalid frame to be in the stack.  Ideally
1115ffd83dbSDimitry Andric   // we'll mark this frame specially at some
1125ffd83dbSDimitry Andric   // point and indicate to the user that the unwinder had a hiccup.  Often when
1135ffd83dbSDimitry Andric   // this happens we will miss a frame of
1145ffd83dbSDimitry Andric   // the program's actual stack in the unwind and we want to flag that for the
1155ffd83dbSDimitry Andric   // user somehow.
1165ffd83dbSDimitry Andric   bool IsSkipFrame() const;
1175ffd83dbSDimitry Andric 
1185ffd83dbSDimitry Andric   /// Determines if a SymbolContext is a trap handler or not
1195ffd83dbSDimitry Andric   ///
1205ffd83dbSDimitry Andric   /// Given a SymbolContext, determines if this is a trap handler function
1215ffd83dbSDimitry Andric   /// aka asynchronous signal handler.
1225ffd83dbSDimitry Andric   ///
1235ffd83dbSDimitry Andric   /// \return
1245ffd83dbSDimitry Andric   ///     Returns true if the SymbolContext is a trap handler.
1255ffd83dbSDimitry Andric   bool IsTrapHandlerSymbol(lldb_private::Process *process,
1265ffd83dbSDimitry Andric                            const lldb_private::SymbolContext &m_sym_ctx) const;
1275ffd83dbSDimitry Andric 
1285ffd83dbSDimitry Andric   /// Check if the given unwind plan indicates a signal trap handler, and
1295ffd83dbSDimitry Andric   /// update frame type and symbol context if so.
1305ffd83dbSDimitry Andric   void PropagateTrapHandlerFlagFromUnwindPlan(lldb::UnwindPlanSP unwind_plan);
1315ffd83dbSDimitry Andric 
1325ffd83dbSDimitry Andric   // Provide a location for where THIS function saved the CALLER's register
1335ffd83dbSDimitry Andric   // value
1345ffd83dbSDimitry Andric   // Or a frame "below" this one saved it, i.e. a function called by this one,
1355ffd83dbSDimitry Andric   // preserved a register that this
1365ffd83dbSDimitry Andric   // function didn't modify/use.
1375ffd83dbSDimitry Andric   //
1385ffd83dbSDimitry Andric   // The RegisterLocation type may be set to eRegisterNotAvailable -- this will
1395ffd83dbSDimitry Andric   // happen for a volatile register
1405ffd83dbSDimitry Andric   // being queried mid-stack.  Instead of floating frame 0's contents of that
1415ffd83dbSDimitry Andric   // register up the stack (which may
1425ffd83dbSDimitry Andric   // or may not be the value of that reg when the function was executing), we
1435ffd83dbSDimitry Andric   // won't return any value.
1445ffd83dbSDimitry Andric   //
1455ffd83dbSDimitry Andric   // If a non-volatile register (a "preserved" register) is requested mid-stack
1465ffd83dbSDimitry Andric   // and no frames "below" the requested
1475ffd83dbSDimitry Andric   // stack have saved the register anywhere, it is safe to assume that frame 0's
1485ffd83dbSDimitry Andric   // register values are still the same
1495ffd83dbSDimitry Andric   // as the requesting frame's.
1505ffd83dbSDimitry Andric   lldb_private::UnwindLLDB::RegisterSearchResult
1515ffd83dbSDimitry Andric   SavedLocationForRegister(uint32_t lldb_regnum,
1525ffd83dbSDimitry Andric                            lldb_private::UnwindLLDB::RegisterLocation &regloc);
1535ffd83dbSDimitry Andric 
1545ffd83dbSDimitry Andric   bool ReadRegisterValueFromRegisterLocation(
1555ffd83dbSDimitry Andric       lldb_private::UnwindLLDB::RegisterLocation regloc,
1565ffd83dbSDimitry Andric       const lldb_private::RegisterInfo *reg_info,
1575ffd83dbSDimitry Andric       lldb_private::RegisterValue &value);
1585ffd83dbSDimitry Andric 
1595ffd83dbSDimitry Andric   bool WriteRegisterValueToRegisterLocation(
1605ffd83dbSDimitry Andric       lldb_private::UnwindLLDB::RegisterLocation regloc,
1615ffd83dbSDimitry Andric       const lldb_private::RegisterInfo *reg_info,
1625ffd83dbSDimitry Andric       const lldb_private::RegisterValue &value);
1635ffd83dbSDimitry Andric 
1645ffd83dbSDimitry Andric   /// If the unwind has to the caller frame has failed, try something else
1655ffd83dbSDimitry Andric   ///
1665ffd83dbSDimitry Andric   /// If lldb is using an assembly language based UnwindPlan for a frame and
1675ffd83dbSDimitry Andric   /// the unwind to the caller frame fails, try falling back to a generic
1685ffd83dbSDimitry Andric   /// UnwindPlan (architecture default unwindplan) to see if that might work
1695ffd83dbSDimitry Andric   /// better.  This is mostly helping to work around problems where the
1705ffd83dbSDimitry Andric   /// assembly language inspection fails on hand-written assembly code.
1715ffd83dbSDimitry Andric   ///
1725ffd83dbSDimitry Andric   /// \return
1735ffd83dbSDimitry Andric   ///     Returns true if a fallback unwindplan was found & was installed.
1745ffd83dbSDimitry Andric   bool TryFallbackUnwindPlan();
1755ffd83dbSDimitry Andric 
1765ffd83dbSDimitry Andric   /// Switch to the fallback unwind plan unconditionally without any safety
1775ffd83dbSDimitry Andric   /// checks that it is providing better results than the normal unwind plan.
1785ffd83dbSDimitry Andric   ///
1795ffd83dbSDimitry Andric   /// The only time it is valid to call this method is if the full unwindplan is
1805ffd83dbSDimitry Andric   /// found to be fundamentally incorrect/impossible.
1815ffd83dbSDimitry Andric   ///
1825ffd83dbSDimitry Andric   /// Returns true if it was able to install the fallback unwind plan.
1835ffd83dbSDimitry Andric   bool ForceSwitchToFallbackUnwindPlan();
1845ffd83dbSDimitry Andric 
1855ffd83dbSDimitry Andric   // Get the contents of a general purpose (address-size) register for this
1865ffd83dbSDimitry Andric   // frame
1875ffd83dbSDimitry Andric   // (usually retrieved from the next frame)
1885ffd83dbSDimitry Andric   bool ReadGPRValue(lldb::RegisterKind register_kind, uint32_t regnum,
1895ffd83dbSDimitry Andric                     lldb::addr_t &value);
1905ffd83dbSDimitry Andric 
1915ffd83dbSDimitry Andric   bool ReadGPRValue(const RegisterNumber &reg_num, lldb::addr_t &value);
1925ffd83dbSDimitry Andric 
1935ffd83dbSDimitry Andric   // Get the Frame Address register for a given frame.
1945ffd83dbSDimitry Andric   bool ReadFrameAddress(lldb::RegisterKind register_kind,
1955ffd83dbSDimitry Andric                           UnwindPlan::Row::FAValue &fa, lldb::addr_t &address);
1965ffd83dbSDimitry Andric 
1975ffd83dbSDimitry Andric   lldb::UnwindPlanSP GetFastUnwindPlanForFrame();
1985ffd83dbSDimitry Andric 
1995ffd83dbSDimitry Andric   lldb::UnwindPlanSP GetFullUnwindPlanForFrame();
2005ffd83dbSDimitry Andric 
2015ffd83dbSDimitry Andric   void UnwindLogMsg(const char *fmt, ...) __attribute__((format(printf, 2, 3)));
2025ffd83dbSDimitry Andric 
2035ffd83dbSDimitry Andric   void UnwindLogMsgVerbose(const char *fmt, ...)
2045ffd83dbSDimitry Andric       __attribute__((format(printf, 2, 3)));
2055ffd83dbSDimitry Andric 
206*81ad6265SDimitry Andric   bool IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp);
2075ffd83dbSDimitry Andric 
2085ffd83dbSDimitry Andric   lldb::addr_t GetReturnAddressHint(int32_t plan_offset);
2095ffd83dbSDimitry Andric 
2105ffd83dbSDimitry Andric   lldb_private::Thread &m_thread;
2115ffd83dbSDimitry Andric 
2125ffd83dbSDimitry Andric   ///
2135ffd83dbSDimitry Andric   // The following tell us how to retrieve the CALLER's register values (ie the
2145ffd83dbSDimitry Andric   // "previous" frame, aka the frame above)
2155ffd83dbSDimitry Andric   // i.e. where THIS frame saved them
2165ffd83dbSDimitry Andric   ///
2175ffd83dbSDimitry Andric 
2185ffd83dbSDimitry Andric   lldb::UnwindPlanSP m_fast_unwind_plan_sp; // may be NULL
2195ffd83dbSDimitry Andric   lldb::UnwindPlanSP m_full_unwind_plan_sp;
2205ffd83dbSDimitry Andric   lldb::UnwindPlanSP m_fallback_unwind_plan_sp; // may be NULL
2215ffd83dbSDimitry Andric 
2225ffd83dbSDimitry Andric   bool m_all_registers_available; // Can we retrieve all regs or just
2235ffd83dbSDimitry Andric                                   // nonvolatile regs?
2245ffd83dbSDimitry Andric   int m_frame_type;               // enum FrameType
2255ffd83dbSDimitry Andric 
2265ffd83dbSDimitry Andric   lldb::addr_t m_cfa;
2275ffd83dbSDimitry Andric   lldb::addr_t m_afa;
2285ffd83dbSDimitry Andric   lldb_private::Address m_start_pc;
2295ffd83dbSDimitry Andric   lldb_private::Address m_current_pc;
2305ffd83dbSDimitry Andric 
2315ffd83dbSDimitry Andric   int m_current_offset; // how far into the function we've executed; -1 if
2325ffd83dbSDimitry Andric                         // unknown
2335ffd83dbSDimitry Andric                         // 0 if no instructions have been executed yet.
2345ffd83dbSDimitry Andric 
2355ffd83dbSDimitry Andric   // 0 if no instructions have been executed yet.
2365ffd83dbSDimitry Andric   // On architectures where the return address on the stack points
2375ffd83dbSDimitry Andric   // to the instruction after the CALL, this value will have 1
2385ffd83dbSDimitry Andric   // subtracted from it.  Else a function that ends in a CALL will
2395ffd83dbSDimitry Andric   // have an offset pointing into the next function's address range.
2405ffd83dbSDimitry Andric   // m_current_pc has the actual address of the "current" pc.
241fe6060f1SDimitry Andric   int m_current_offset_backed_up_one; // how far into the function we've
242fe6060f1SDimitry Andric                                       // executed; -1 if unknown
243fe6060f1SDimitry Andric 
244fe6060f1SDimitry Andric   bool m_behaves_like_zeroth_frame; // this frame behaves like frame zero
2455ffd83dbSDimitry Andric 
2465ffd83dbSDimitry Andric   lldb_private::SymbolContext &m_sym_ctx;
2475ffd83dbSDimitry Andric   bool m_sym_ctx_valid; // if ResolveSymbolContextForAddress fails, don't try to
2485ffd83dbSDimitry Andric                         // use m_sym_ctx
2495ffd83dbSDimitry Andric 
2505ffd83dbSDimitry Andric   uint32_t m_frame_number; // What stack frame this RegisterContext is
2515ffd83dbSDimitry Andric 
2525ffd83dbSDimitry Andric   std::map<uint32_t, lldb_private::UnwindLLDB::RegisterLocation>
2535ffd83dbSDimitry Andric       m_registers; // where to find reg values for this frame
2545ffd83dbSDimitry Andric 
2555ffd83dbSDimitry Andric   lldb_private::UnwindLLDB &m_parent_unwind; // The UnwindLLDB that is creating
2565ffd83dbSDimitry Andric                                              // this RegisterContextUnwind
2575ffd83dbSDimitry Andric 
2585ffd83dbSDimitry Andric   RegisterContextUnwind(const RegisterContextUnwind &) = delete;
2595ffd83dbSDimitry Andric   const RegisterContextUnwind &
2605ffd83dbSDimitry Andric   operator=(const RegisterContextUnwind &) = delete;
2615ffd83dbSDimitry Andric };
2625ffd83dbSDimitry Andric 
2635ffd83dbSDimitry Andric } // namespace lldb_private
2645ffd83dbSDimitry Andric 
2655ffd83dbSDimitry Andric #endif // LLDB_TARGET_REGISTERCONTEXTUNWIND_H
266