Path: blob/main/contrib/llvm-project/lldb/source/Breakpoint/BreakpointSite.cpp
39587 views
//===-- BreakpointSite.cpp ------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include <cinttypes>910#include "lldb/Breakpoint/BreakpointSite.h"1112#include "lldb/Breakpoint/Breakpoint.h"13#include "lldb/Breakpoint/BreakpointLocation.h"14#include "lldb/Utility/Stream.h"1516using namespace lldb;17using namespace lldb_private;1819BreakpointSite::BreakpointSite(const BreakpointLocationSP &constituent,20lldb::addr_t addr, bool use_hardware)21: StoppointSite(GetNextID(), addr, 0, use_hardware),22m_type(eSoftware), // Process subclasses need to set this correctly using23// SetType()24m_saved_opcode(), m_trap_opcode(),25m_enabled(false) // Need to create it disabled, so the first enable turns26// it on.27{28m_constituents.Add(constituent);29}3031BreakpointSite::~BreakpointSite() {32BreakpointLocationSP bp_loc_sp;33const size_t constituent_count = m_constituents.GetSize();34for (size_t i = 0; i < constituent_count; i++) {35m_constituents.GetByIndex(i)->ClearBreakpointSite();36}37}3839break_id_t BreakpointSite::GetNextID() {40static break_id_t g_next_id = 0;41return ++g_next_id;42}4344// RETURNS - true if we should stop at this breakpoint, false if we45// should continue.4647bool BreakpointSite::ShouldStop(StoppointCallbackContext *context) {48m_hit_counter.Increment();49// ShouldStop can do a lot of work, and might even come back and hit50// this breakpoint site again. So don't hold the m_constituents_mutex the51// whole while. Instead make a local copy of the collection and call52// ShouldStop on the copy.53BreakpointLocationCollection constituents_copy;54{55std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);56constituents_copy = m_constituents;57}58return constituents_copy.ShouldStop(context);59}6061bool BreakpointSite::IsBreakpointAtThisSite(lldb::break_id_t bp_id) {62std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);63const size_t constituent_count = m_constituents.GetSize();64for (size_t i = 0; i < constituent_count; i++) {65if (m_constituents.GetByIndex(i)->GetBreakpoint().GetID() == bp_id)66return true;67}68return false;69}7071void BreakpointSite::Dump(Stream *s) const {72if (s == nullptr)73return;7475s->Printf("BreakpointSite %u: addr = 0x%8.8" PRIx6476" type = %s breakpoint hit_count = %-4u",77GetID(), (uint64_t)m_addr, IsHardware() ? "hardware" : "software",78GetHitCount());79}8081void BreakpointSite::GetDescription(Stream *s, lldb::DescriptionLevel level) {82std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);83if (level != lldb::eDescriptionLevelBrief)84s->Printf("breakpoint site: %d at 0x%8.8" PRIx64, GetID(),85GetLoadAddress());86m_constituents.GetDescription(s, level);87}8889bool BreakpointSite::IsInternal() const { return m_constituents.IsInternal(); }9091uint8_t *BreakpointSite::GetTrapOpcodeBytes() { return &m_trap_opcode[0]; }9293const uint8_t *BreakpointSite::GetTrapOpcodeBytes() const {94return &m_trap_opcode[0];95}9697size_t BreakpointSite::GetTrapOpcodeMaxByteSize() const {98return sizeof(m_trap_opcode);99}100101bool BreakpointSite::SetTrapOpcode(const uint8_t *trap_opcode,102uint32_t trap_opcode_size) {103if (trap_opcode_size > 0 && trap_opcode_size <= sizeof(m_trap_opcode)) {104m_byte_size = trap_opcode_size;105::memcpy(m_trap_opcode, trap_opcode, trap_opcode_size);106return true;107}108m_byte_size = 0;109return false;110}111112uint8_t *BreakpointSite::GetSavedOpcodeBytes() { return &m_saved_opcode[0]; }113114const uint8_t *BreakpointSite::GetSavedOpcodeBytes() const {115return &m_saved_opcode[0];116}117118bool BreakpointSite::IsEnabled() const { return m_enabled; }119120void BreakpointSite::SetEnabled(bool enabled) { m_enabled = enabled; }121122void BreakpointSite::AddConstituent(const BreakpointLocationSP &constituent) {123std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);124m_constituents.Add(constituent);125}126127size_t BreakpointSite::RemoveConstituent(lldb::break_id_t break_id,128lldb::break_id_t break_loc_id) {129std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);130m_constituents.Remove(break_id, break_loc_id);131return m_constituents.GetSize();132}133134size_t BreakpointSite::GetNumberOfConstituents() {135std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);136return m_constituents.GetSize();137}138139BreakpointLocationSP BreakpointSite::GetConstituentAtIndex(size_t index) {140std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);141return m_constituents.GetByIndex(index);142}143144bool BreakpointSite::ValidForThisThread(Thread &thread) {145std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);146return m_constituents.ValidForThisThread(thread);147}148149void BreakpointSite::BumpHitCounts() {150std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);151for (BreakpointLocationSP loc_sp : m_constituents.BreakpointLocations()) {152loc_sp->BumpHitCount();153}154}155156bool BreakpointSite::IntersectsRange(lldb::addr_t addr, size_t size,157lldb::addr_t *intersect_addr,158size_t *intersect_size,159size_t *opcode_offset) const {160// The function should be called only for software breakpoints.161lldbassert(GetType() == Type::eSoftware);162163if (m_byte_size == 0)164return false;165166const lldb::addr_t bp_end_addr = m_addr + m_byte_size;167const lldb::addr_t end_addr = addr + size;168// Is the breakpoint end address before the passed in start address?169if (bp_end_addr <= addr)170return false;171172// Is the breakpoint start address after passed in end address?173if (end_addr <= m_addr)174return false;175176if (intersect_addr || intersect_size || opcode_offset) {177if (m_addr < addr) {178if (intersect_addr)179*intersect_addr = addr;180if (intersect_size)181*intersect_size =182std::min<lldb::addr_t>(bp_end_addr, end_addr) - addr;183if (opcode_offset)184*opcode_offset = addr - m_addr;185} else {186if (intersect_addr)187*intersect_addr = m_addr;188if (intersect_size)189*intersect_size =190std::min<lldb::addr_t>(bp_end_addr, end_addr) - m_addr;191if (opcode_offset)192*opcode_offset = 0;193}194}195return true;196}197198size_t BreakpointSite::CopyConstituentsList(199BreakpointLocationCollection &out_collection) {200std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);201for (BreakpointLocationSP loc_sp : m_constituents.BreakpointLocations()) {202out_collection.Add(loc_sp);203}204return out_collection.GetSize();205}206207208