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