Added a way to set hardware breakpoints from the "breakpoint set" command with the new "--hardware" option. Hardware breakpoints are not a request, they currently are a requirement. So when breakpoints are specified as hardware breakpoints, they might fail to be set when they are able to be resolved and should be used sparingly. This is currently hooked up for GDB remote debugging. Linux and FreeBSD should quickly enable this feature if possible, or return an error for any breakpoints that are hardware breakpoint sites in the "virtual Error Process::EnableBreakpointSite (BreakpointSite *bp_site);" function. llvm-svn: 192491
306 lines
8.0 KiB
C++
306 lines
8.0 KiB
C++
//===-- BreakpointLocationList.cpp ------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
// C Includes
|
|
// C++ Includes
|
|
// Other libraries and framework includes
|
|
// Project includes
|
|
#include "lldb/Breakpoint/BreakpointLocationList.h"
|
|
#include "lldb/Breakpoint/BreakpointLocation.h"
|
|
#include "lldb/Breakpoint/Breakpoint.h"
|
|
#include "lldb/Core/Section.h"
|
|
#include "lldb/Target/Target.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
BreakpointLocationList::BreakpointLocationList(Breakpoint &owner) :
|
|
m_owner (owner),
|
|
m_locations(),
|
|
m_address_to_location (),
|
|
m_mutex (Mutex::eMutexTypeRecursive),
|
|
m_next_id (0),
|
|
m_new_location_recorder (NULL)
|
|
{
|
|
}
|
|
|
|
BreakpointLocationList::~BreakpointLocationList()
|
|
{
|
|
}
|
|
|
|
BreakpointLocationSP
|
|
BreakpointLocationList::Create (const Address &addr)
|
|
{
|
|
Mutex::Locker locker (m_mutex);
|
|
// The location ID is just the size of the location list + 1
|
|
lldb::break_id_t bp_loc_id = ++m_next_id;
|
|
BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, m_owner, addr, LLDB_INVALID_THREAD_ID, m_owner.IsHardware()));
|
|
m_locations.push_back (bp_loc_sp);
|
|
m_address_to_location[addr] = bp_loc_sp;
|
|
return bp_loc_sp;
|
|
}
|
|
|
|
bool
|
|
BreakpointLocationList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t break_id)
|
|
{
|
|
BreakpointLocationSP bp = FindByID (break_id);
|
|
if (bp)
|
|
{
|
|
// Let the BreakpointLocation decide if it should stop here (could not have
|
|
// reached it's target hit count yet, or it could have a callback
|
|
// that decided it shouldn't stop (shared library loads/unloads).
|
|
return bp->ShouldStop (context);
|
|
}
|
|
// We should stop here since this BreakpointLocation isn't valid anymore or it
|
|
// doesn't exist.
|
|
return true;
|
|
}
|
|
|
|
lldb::break_id_t
|
|
BreakpointLocationList::FindIDByAddress (const Address &addr)
|
|
{
|
|
BreakpointLocationSP bp_loc_sp = FindByAddress (addr);
|
|
if (bp_loc_sp)
|
|
{
|
|
return bp_loc_sp->GetID();
|
|
}
|
|
return LLDB_INVALID_BREAK_ID;
|
|
}
|
|
|
|
BreakpointLocationSP
|
|
BreakpointLocationList::FindByID (lldb::break_id_t break_id) const
|
|
{
|
|
BreakpointLocationSP bp_loc_sp;
|
|
Mutex::Locker locker (m_mutex);
|
|
// We never remove a breakpoint locations, so the ID can be translated into
|
|
// the location index by subtracting 1
|
|
uint32_t idx = break_id - 1;
|
|
if (idx <= m_locations.size())
|
|
{
|
|
bp_loc_sp = m_locations[idx];
|
|
}
|
|
return bp_loc_sp;
|
|
}
|
|
|
|
size_t
|
|
BreakpointLocationList::FindInModule (Module *module,
|
|
BreakpointLocationCollection& bp_loc_list)
|
|
{
|
|
Mutex::Locker locker (m_mutex);
|
|
const size_t orig_size = bp_loc_list.GetSize();
|
|
collection::iterator pos, end = m_locations.end();
|
|
|
|
for (pos = m_locations.begin(); pos != end; ++pos)
|
|
{
|
|
BreakpointLocationSP break_loc = (*pos);
|
|
SectionSP section_sp (break_loc->GetAddress().GetSection());
|
|
if (section_sp && section_sp->GetModule().get() == module)
|
|
{
|
|
bp_loc_list.Add (break_loc);
|
|
}
|
|
}
|
|
return bp_loc_list.GetSize() - orig_size;
|
|
}
|
|
|
|
const BreakpointLocationSP
|
|
BreakpointLocationList::FindByAddress (const Address &addr) const
|
|
{
|
|
Mutex::Locker locker (m_mutex);
|
|
BreakpointLocationSP bp_loc_sp;
|
|
if (!m_locations.empty())
|
|
{
|
|
Address so_addr;
|
|
|
|
if (addr.IsSectionOffset())
|
|
{
|
|
so_addr = addr;
|
|
}
|
|
else
|
|
{
|
|
// Try and resolve as a load address if possible.
|
|
m_owner.GetTarget().GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), so_addr);
|
|
if (!so_addr.IsValid())
|
|
{
|
|
// The address didn't resolve, so just set to passed in addr.
|
|
so_addr = addr;
|
|
}
|
|
}
|
|
|
|
addr_map::const_iterator pos = m_address_to_location.find (so_addr);
|
|
if (pos != m_address_to_location.end())
|
|
bp_loc_sp = pos->second;
|
|
}
|
|
|
|
return bp_loc_sp;
|
|
}
|
|
|
|
void
|
|
BreakpointLocationList::Dump (Stream *s) const
|
|
{
|
|
s->Printf("%p: ", this);
|
|
//s->Indent();
|
|
Mutex::Locker locker (m_mutex);
|
|
s->Printf("BreakpointLocationList with %" PRIu64 " BreakpointLocations:\n", (uint64_t)m_locations.size());
|
|
s->IndentMore();
|
|
collection::const_iterator pos, end = m_locations.end();
|
|
for (pos = m_locations.begin(); pos != end; ++pos)
|
|
(*pos).get()->Dump(s);
|
|
s->IndentLess();
|
|
}
|
|
|
|
|
|
BreakpointLocationSP
|
|
BreakpointLocationList::GetByIndex (size_t i)
|
|
{
|
|
Mutex::Locker locker (m_mutex);
|
|
BreakpointLocationSP bp_loc_sp;
|
|
if (i < m_locations.size())
|
|
bp_loc_sp = m_locations[i];
|
|
|
|
return bp_loc_sp;
|
|
}
|
|
|
|
const BreakpointLocationSP
|
|
BreakpointLocationList::GetByIndex (size_t i) const
|
|
{
|
|
Mutex::Locker locker (m_mutex);
|
|
BreakpointLocationSP bp_loc_sp;
|
|
if (i < m_locations.size())
|
|
bp_loc_sp = m_locations[i];
|
|
|
|
return bp_loc_sp;
|
|
}
|
|
|
|
void
|
|
BreakpointLocationList::ClearAllBreakpointSites ()
|
|
{
|
|
Mutex::Locker locker (m_mutex);
|
|
collection::iterator pos, end = m_locations.end();
|
|
for (pos = m_locations.begin(); pos != end; ++pos)
|
|
(*pos)->ClearBreakpointSite();
|
|
}
|
|
|
|
void
|
|
BreakpointLocationList::ResolveAllBreakpointSites ()
|
|
{
|
|
Mutex::Locker locker (m_mutex);
|
|
collection::iterator pos, end = m_locations.end();
|
|
|
|
for (pos = m_locations.begin(); pos != end; ++pos)
|
|
{
|
|
if ((*pos)->IsEnabled())
|
|
(*pos)->ResolveBreakpointSite();
|
|
}
|
|
}
|
|
|
|
uint32_t
|
|
BreakpointLocationList::GetHitCount () const
|
|
{
|
|
uint32_t hit_count = 0;
|
|
Mutex::Locker locker (m_mutex);
|
|
collection::const_iterator pos, end = m_locations.end();
|
|
for (pos = m_locations.begin(); pos != end; ++pos)
|
|
hit_count += (*pos)->GetHitCount();
|
|
return hit_count;
|
|
}
|
|
|
|
size_t
|
|
BreakpointLocationList::GetNumResolvedLocations() const
|
|
{
|
|
Mutex::Locker locker (m_mutex);
|
|
size_t resolve_count = 0;
|
|
collection::const_iterator pos, end = m_locations.end();
|
|
for (pos = m_locations.begin(); pos != end; ++pos)
|
|
{
|
|
if ((*pos)->IsResolved())
|
|
++resolve_count;
|
|
}
|
|
return resolve_count;
|
|
}
|
|
|
|
void
|
|
BreakpointLocationList::GetDescription (Stream *s, lldb::DescriptionLevel level)
|
|
{
|
|
Mutex::Locker locker (m_mutex);
|
|
collection::iterator pos, end = m_locations.end();
|
|
|
|
for (pos = m_locations.begin(); pos != end; ++pos)
|
|
{
|
|
s->Printf(" ");
|
|
(*pos)->GetDescription(s, level);
|
|
}
|
|
}
|
|
|
|
BreakpointLocationSP
|
|
BreakpointLocationList::AddLocation (const Address &addr, bool *new_location)
|
|
{
|
|
Mutex::Locker locker (m_mutex);
|
|
|
|
if (new_location)
|
|
*new_location = false;
|
|
BreakpointLocationSP bp_loc_sp (FindByAddress(addr));
|
|
if (!bp_loc_sp)
|
|
{
|
|
bp_loc_sp = Create (addr);
|
|
if (bp_loc_sp)
|
|
{
|
|
bp_loc_sp->ResolveBreakpointSite();
|
|
|
|
if (new_location)
|
|
*new_location = true;
|
|
if(m_new_location_recorder)
|
|
{
|
|
m_new_location_recorder->Add(bp_loc_sp);
|
|
}
|
|
}
|
|
}
|
|
return bp_loc_sp;
|
|
}
|
|
|
|
bool
|
|
BreakpointLocationList::RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp)
|
|
{
|
|
if (bp_loc_sp)
|
|
{
|
|
Mutex::Locker locker (m_mutex);
|
|
|
|
m_address_to_location.erase (bp_loc_sp->GetAddress());
|
|
|
|
collection::iterator pos, end = m_locations.end();
|
|
for (pos = m_locations.begin(); pos != end; ++pos)
|
|
{
|
|
if ((*pos).get() == bp_loc_sp.get())
|
|
{
|
|
m_locations.erase (pos);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
void
|
|
BreakpointLocationList::StartRecordingNewLocations (BreakpointLocationCollection &new_locations)
|
|
{
|
|
Mutex::Locker locker (m_mutex);
|
|
assert (m_new_location_recorder == NULL);
|
|
m_new_location_recorder = &new_locations;
|
|
}
|
|
|
|
void
|
|
BreakpointLocationList::StopRecordingNewLocations ()
|
|
{
|
|
Mutex::Locker locker (m_mutex);
|
|
m_new_location_recorder = NULL;
|
|
}
|
|
|