10b57cec5SDimitry Andric //===-- BreakpointSite.h ----------------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 95ffd83dbSDimitry Andric #ifndef LLDB_BREAKPOINT_BREAKPOINTSITE_H 105ffd83dbSDimitry Andric #define LLDB_BREAKPOINT_BREAKPOINTSITE_H 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include <list> 130b57cec5SDimitry Andric #include <mutex> 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointLocationCollection.h" 17e8d8bef9SDimitry Andric #include "lldb/Breakpoint/StoppointSite.h" 18e8d8bef9SDimitry Andric #include "lldb/Utility/LLDBAssert.h" 190b57cec5SDimitry Andric #include "lldb/Utility/UserID.h" 200b57cec5SDimitry Andric #include "lldb/lldb-forward.h" 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric namespace lldb_private { 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric /// \class BreakpointSite BreakpointSite.h "lldb/Breakpoint/BreakpointSite.h" 250b57cec5SDimitry Andric /// Class that manages the actual breakpoint that will be inserted into the 260b57cec5SDimitry Andric /// running program. 270b57cec5SDimitry Andric /// 280b57cec5SDimitry Andric /// The BreakpointSite class handles the physical breakpoint that is actually 290b57cec5SDimitry Andric /// inserted in the target program. As such, it is also the one that gets 300b57cec5SDimitry Andric /// hit, when the program stops. It keeps a list of all BreakpointLocations 310b57cec5SDimitry Andric /// that share this physical site. When the breakpoint is hit, all the 320b57cec5SDimitry Andric /// locations are informed by the breakpoint site. Breakpoint sites are owned 330b57cec5SDimitry Andric /// by the process. 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric class BreakpointSite : public std::enable_shared_from_this<BreakpointSite>, 36e8d8bef9SDimitry Andric public StoppointSite { 370b57cec5SDimitry Andric public: 380b57cec5SDimitry Andric enum Type { 390b57cec5SDimitry Andric eSoftware, // Breakpoint opcode has been written to memory and 400b57cec5SDimitry Andric // m_saved_opcode 410b57cec5SDimitry Andric // and m_trap_opcode contain the saved and written opcode. 420b57cec5SDimitry Andric eHardware, // Breakpoint site is set as a hardware breakpoint 430b57cec5SDimitry Andric eExternal // Breakpoint site is managed by an external debug nub or 440b57cec5SDimitry Andric // debug interface where memory reads transparently will not 450b57cec5SDimitry Andric // display any breakpoint opcodes. 460b57cec5SDimitry Andric }; 470b57cec5SDimitry Andric 485f757f3fSDimitry Andric typedef lldb::break_id_t SiteID; 495f757f3fSDimitry Andric typedef lldb::break_id_t ConstituentID; 505f757f3fSDimitry Andric 510b57cec5SDimitry Andric ~BreakpointSite() override; 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric // This section manages the breakpoint traps 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric /// Returns the Opcode Bytes for this breakpoint 560b57cec5SDimitry Andric uint8_t *GetTrapOpcodeBytes(); 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric /// Returns the Opcode Bytes for this breakpoint - const version 590b57cec5SDimitry Andric const uint8_t *GetTrapOpcodeBytes() const; 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric /// Get the size of the trap opcode for this address 620b57cec5SDimitry Andric size_t GetTrapOpcodeMaxByteSize() const; 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric /// Sets the trap opcode 650b57cec5SDimitry Andric bool SetTrapOpcode(const uint8_t *trap_opcode, uint32_t trap_opcode_size); 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric /// Gets the original instruction bytes that were overwritten by the trap 680b57cec5SDimitry Andric uint8_t *GetSavedOpcodeBytes(); 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric /// Gets the original instruction bytes that were overwritten by the trap 710b57cec5SDimitry Andric /// const version 720b57cec5SDimitry Andric const uint8_t *GetSavedOpcodeBytes() const; 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric /// Says whether \a addr and size \a size intersects with the address \a 750b57cec5SDimitry Andric /// intersect_addr 760b57cec5SDimitry Andric bool IntersectsRange(lldb::addr_t addr, size_t size, 770b57cec5SDimitry Andric lldb::addr_t *intersect_addr, size_t *intersect_size, 780b57cec5SDimitry Andric size_t *opcode_offset) const; 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric /// Tells whether the current breakpoint site is enabled or not 810b57cec5SDimitry Andric /// 820b57cec5SDimitry Andric /// This is a low-level enable bit for the breakpoint sites. If a 835f757f3fSDimitry Andric /// breakpoint site has no enabled constituents, it should just get removed. 845f757f3fSDimitry Andric /// This enable/disable is for the low-level target code to enable and disable 850b57cec5SDimitry Andric /// breakpoint sites when single stepping, etc. 860b57cec5SDimitry Andric bool IsEnabled() const; 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric /// Sets whether the current breakpoint site is enabled or not 890b57cec5SDimitry Andric /// 900b57cec5SDimitry Andric /// \param[in] enabled 910b57cec5SDimitry Andric /// \b true if the breakpoint is enabled, \b false otherwise. 920b57cec5SDimitry Andric void SetEnabled(bool enabled); 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric /// Enquires of the breakpoint locations that produced this breakpoint site 950b57cec5SDimitry Andric /// whether we should stop at this location. 960b57cec5SDimitry Andric /// 970b57cec5SDimitry Andric /// \param[in] context 980b57cec5SDimitry Andric /// This contains the information about this stop. 990b57cec5SDimitry Andric /// 1000b57cec5SDimitry Andric /// \return 1010b57cec5SDimitry Andric /// \b true if we should stop, \b false otherwise. 1020b57cec5SDimitry Andric bool ShouldStop(StoppointCallbackContext *context) override; 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric /// Standard Dump method 1050b57cec5SDimitry Andric void Dump(Stream *s) const override; 1060b57cec5SDimitry Andric 1075f757f3fSDimitry Andric /// The "Constituents" are the breakpoint locations that share this breakpoint 1085f757f3fSDimitry Andric /// site. The method adds the \a constituent to this breakpoint site's 1095f757f3fSDimitry Andric /// constituent list. 1100b57cec5SDimitry Andric /// 1115f757f3fSDimitry Andric /// \param[in] constituent 1125f757f3fSDimitry Andric /// \a constituent is the Breakpoint Location to add. 1135f757f3fSDimitry Andric void AddConstituent(const lldb::BreakpointLocationSP &constituent); 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric /// This method returns the number of breakpoint locations currently located 1160b57cec5SDimitry Andric /// at this breakpoint site. 1170b57cec5SDimitry Andric /// 1180b57cec5SDimitry Andric /// \return 1195f757f3fSDimitry Andric /// The number of constituents. 1205f757f3fSDimitry Andric size_t GetNumberOfConstituents(); 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric /// This method returns the breakpoint location at index \a index located at 1235f757f3fSDimitry Andric /// this breakpoint site. The constituents are listed ordinally from 0 to 1245f757f3fSDimitry Andric /// GetNumberOfConstituents() - 1 so you can use this method to iterate over 1255f757f3fSDimitry Andric /// the constituents 1260b57cec5SDimitry Andric /// 127480093f4SDimitry Andric /// \param[in] idx 1285f757f3fSDimitry Andric /// The index in the list of constituents for which you wish the 1295f757f3fSDimitry Andric /// constituent location. 130480093f4SDimitry Andric /// 1310b57cec5SDimitry Andric /// \return 1320b57cec5SDimitry Andric /// A shared pointer to the breakpoint location at that index. 1335f757f3fSDimitry Andric lldb::BreakpointLocationSP GetConstituentAtIndex(size_t idx); 1340b57cec5SDimitry Andric 1355f757f3fSDimitry Andric /// This method copies the breakpoint site's constituents into a new 1365f757f3fSDimitry Andric /// collection. It does this while the constituents mutex is locked. 1370b57cec5SDimitry Andric /// 1380b57cec5SDimitry Andric /// \param[out] out_collection 1395f757f3fSDimitry Andric /// The BreakpointLocationCollection into which to put the constituents 1400b57cec5SDimitry Andric /// of this breakpoint site. 1410b57cec5SDimitry Andric /// 1420b57cec5SDimitry Andric /// \return 1430b57cec5SDimitry Andric /// The number of elements copied into out_collection. 1445f757f3fSDimitry Andric size_t CopyConstituentsList(BreakpointLocationCollection &out_collection); 1450b57cec5SDimitry Andric 1465f757f3fSDimitry Andric /// Check whether the constituents of this breakpoint site have any thread 1470b57cec5SDimitry Andric /// specifiers, and if yes, is \a thread contained in any of these 1480b57cec5SDimitry Andric /// specifiers. 1490b57cec5SDimitry Andric /// 1500b57cec5SDimitry Andric /// \param[in] thread 1510b57cec5SDimitry Andric /// The thread against which to test. 1520b57cec5SDimitry Andric /// 1530b57cec5SDimitry Andric /// return 1540b57cec5SDimitry Andric /// \b true if the collection contains at least one location that 1550b57cec5SDimitry Andric /// would be valid for this thread, false otherwise. 156fe6060f1SDimitry Andric bool ValidForThisThread(Thread &thread); 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric /// Print a description of this breakpoint site to the stream \a s. 1595f757f3fSDimitry Andric /// GetDescription tells you about the breakpoint site's constituents. Use 1600b57cec5SDimitry Andric /// BreakpointSite::Dump(Stream *) to get information about the breakpoint 1610b57cec5SDimitry Andric /// site itself. 1620b57cec5SDimitry Andric /// 1630b57cec5SDimitry Andric /// \param[in] s 1640b57cec5SDimitry Andric /// The stream to which to print the description. 1650b57cec5SDimitry Andric /// 1660b57cec5SDimitry Andric /// \param[in] level 1670b57cec5SDimitry Andric /// The description level that indicates the detail level to 1680b57cec5SDimitry Andric /// provide. 1690b57cec5SDimitry Andric /// 1700b57cec5SDimitry Andric /// \see lldb::DescriptionLevel 1710b57cec5SDimitry Andric void GetDescription(Stream *s, lldb::DescriptionLevel level); 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric /// Tell whether a breakpoint has a location at this site. 1740b57cec5SDimitry Andric /// 1750b57cec5SDimitry Andric /// \param[in] bp_id 1760b57cec5SDimitry Andric /// The breakpoint id to query. 1770b57cec5SDimitry Andric /// 1780b57cec5SDimitry Andric /// \result 1790b57cec5SDimitry Andric /// \b true if bp_id has a location that is at this site, 1800b57cec5SDimitry Andric /// \b false otherwise. 1810b57cec5SDimitry Andric bool IsBreakpointAtThisSite(lldb::break_id_t bp_id); 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric /// Tell whether ALL the breakpoints in the location collection are 1840b57cec5SDimitry Andric /// internal. 1850b57cec5SDimitry Andric /// 1860b57cec5SDimitry Andric /// \result 1870b57cec5SDimitry Andric /// \b true if all breakpoint locations are owned by internal breakpoints, 1880b57cec5SDimitry Andric /// \b false otherwise. 1890b57cec5SDimitry Andric bool IsInternal() const; 1900b57cec5SDimitry Andric IsHardware()191e8d8bef9SDimitry Andric bool IsHardware() const override { 192e8d8bef9SDimitry Andric lldbassert(BreakpointSite::Type::eHardware == GetType() || 193e8d8bef9SDimitry Andric !HardwareRequired()); 194e8d8bef9SDimitry Andric return BreakpointSite::Type::eHardware == GetType(); 195e8d8bef9SDimitry Andric } 196e8d8bef9SDimitry Andric GetType()1970b57cec5SDimitry Andric BreakpointSite::Type GetType() const { return m_type; } 1980b57cec5SDimitry Andric SetType(BreakpointSite::Type type)1990b57cec5SDimitry Andric void SetType(BreakpointSite::Type type) { m_type = type; } 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric private: 2020b57cec5SDimitry Andric friend class Process; 2030b57cec5SDimitry Andric friend class BreakpointLocation; 2040b57cec5SDimitry Andric // The StopInfoBreakpoint knows when it is processing a hit for a thread for 2050b57cec5SDimitry Andric // a site, so let it be the one to manage setting the location hit count once 2060b57cec5SDimitry Andric // and only once. 2070b57cec5SDimitry Andric friend class StopInfoBreakpoint; 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric void BumpHitCounts(); 2100b57cec5SDimitry Andric 2115f757f3fSDimitry Andric /// The method removes the constituent at \a break_loc_id from this breakpoint 2120b57cec5SDimitry Andric /// list. 2135f757f3fSDimitry Andric size_t RemoveConstituent(lldb::break_id_t break_id, 2145f757f3fSDimitry Andric lldb::break_id_t break_loc_id); 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric BreakpointSite::Type m_type; ///< The type of this breakpoint site. 2170b57cec5SDimitry Andric uint8_t m_saved_opcode[8]; ///< The saved opcode bytes if this breakpoint site 2180b57cec5SDimitry Andric ///uses trap opcodes. 2190b57cec5SDimitry Andric uint8_t m_trap_opcode[8]; ///< The opcode that was used to create the 2200b57cec5SDimitry Andric ///breakpoint if it is a software breakpoint site. 2210b57cec5SDimitry Andric bool 2220b57cec5SDimitry Andric m_enabled; ///< Boolean indicating if this breakpoint site enabled or not. 2230b57cec5SDimitry Andric 2245f757f3fSDimitry Andric // Consider adding an optimization where if there is only one constituent, we 2255f757f3fSDimitry Andric // don't store a list. The usual case will be only one constituent... 2265f757f3fSDimitry Andric BreakpointLocationCollection 2275f757f3fSDimitry Andric m_constituents; ///< This has the BreakpointLocations 2280b57cec5SDimitry Andric /// that share this breakpoint site. 2295f757f3fSDimitry Andric std::recursive_mutex m_constituents_mutex; ///< This mutex protects the 2305f757f3fSDimitry Andric ///< constituents collection. 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric static lldb::break_id_t GetNextID(); 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric // Only the Process can create breakpoint sites in 2350b57cec5SDimitry Andric // Process::CreateBreakpointSite (lldb::BreakpointLocationSP &, bool). 2365f757f3fSDimitry Andric BreakpointSite(const lldb::BreakpointLocationSP &constituent, 2375f757f3fSDimitry Andric lldb::addr_t m_addr, bool use_hardware); 2380b57cec5SDimitry Andric 2395ffd83dbSDimitry Andric BreakpointSite(const BreakpointSite &) = delete; 2405ffd83dbSDimitry Andric const BreakpointSite &operator=(const BreakpointSite &) = delete; 2410b57cec5SDimitry Andric }; 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric } // namespace lldb_private 2440b57cec5SDimitry Andric 2455ffd83dbSDimitry Andric #endif // LLDB_BREAKPOINT_BREAKPOINTSITE_H 246