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 ®loc); 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 ®_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