summaryrefslogtreecommitdiffstats
path: root/lldb/source/Target/Process.cpp
diff options
context:
space:
mode:
authorGreg Clayton <gclayton@apple.com>2013-06-12 00:46:38 +0000
committerGreg Clayton <gclayton@apple.com>2013-06-12 00:46:38 +0000
commitd8cf1a119d4c38e59ade90018a4df015dff63383 (patch)
tree606b745e59a29f527781d29bd8709ff5e8a814f1 /lldb/source/Target/Process.cpp
parentec36f9a73429dda07049473625d3354b209cc5b7 (diff)
downloadbcm5719-llvm-d8cf1a119d4c38e59ade90018a4df015dff63383.tar.gz
bcm5719-llvm-d8cf1a119d4c38e59ade90018a4df015dff63383.zip
Huge performance improvements when one breakpoint contains many locations.
325,000 breakpoints for running "breakpoint set --func-regex ." on lldb itself (after hitting a breakpoint at main so that LLDB.framework is loaded) used to take up to an hour to set, now we are down under a minute. With warm file caches, we are at 40 seconds, and that is with setting 325,000 breakpoint through the GDB remote API. Linux and the native debuggers might be faster. I haven't timed what how much is debug info parsing and how much is the protocol traffic to/from GDB remote. That there were many performance issues. Most of them were due to storing breakpoints in the wrong data structures, or using the wrong iterators to traverse the lists, traversing the lists in inefficient ways, and not optimizing certain function name lookups/symbol merges correctly. Debugging after that is also now very efficient. There were issues with replacing the breakpoint opcodes in memory that was read, and those routines were also fixed. llvm-svn: 183820
Diffstat (limited to 'lldb/source/Target/Process.cpp')
-rw-r--r--lldb/source/Target/Process.cpp144
1 files changed, 74 insertions, 70 deletions
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 1127446be51..92107d60802 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -2007,12 +2007,10 @@ Process::GetBreakpointSiteList() const
void
Process::DisableAllBreakpointSites ()
{
- m_breakpoint_site_list.SetEnabledForAll (false);
- size_t num_sites = m_breakpoint_site_list.GetSize();
- for (size_t i = 0; i < num_sites; i++)
- {
- DisableBreakpointSite (m_breakpoint_site_list.GetByIndex(i).get());
- }
+ m_breakpoint_site_list.ForEach([this](BreakpointSite *bp_site) -> void {
+// bp_site->SetEnabled(true);
+ DisableBreakpointSite(bp_site);
+ });
}
Error
@@ -2116,29 +2114,26 @@ size_t
Process::RemoveBreakpointOpcodesFromBuffer (addr_t bp_addr, size_t size, uint8_t *buf) const
{
size_t bytes_removed = 0;
- addr_t intersect_addr;
- size_t intersect_size;
- size_t opcode_offset;
- size_t idx;
- BreakpointSiteSP bp_sp;
BreakpointSiteList bp_sites_in_range;
if (m_breakpoint_site_list.FindInRange (bp_addr, bp_addr + size, bp_sites_in_range))
{
- for (idx = 0; (bp_sp = bp_sites_in_range.GetByIndex(idx)); ++idx)
- {
- if (bp_sp->GetType() == BreakpointSite::eSoftware)
+ bp_sites_in_range.ForEach([bp_addr, size, buf, &bytes_removed](BreakpointSite *bp_site) -> void {
+ if (bp_site->GetType() == BreakpointSite::eSoftware)
{
- if (bp_sp->IntersectsRange(bp_addr, size, &intersect_addr, &intersect_size, &opcode_offset))
+ addr_t intersect_addr;
+ size_t intersect_size;
+ size_t opcode_offset;
+ if (bp_site->IntersectsRange(bp_addr, size, &intersect_addr, &intersect_size, &opcode_offset))
{
assert(bp_addr <= intersect_addr && intersect_addr < bp_addr + size);
assert(bp_addr < intersect_addr + intersect_size && intersect_addr + intersect_size <= bp_addr + size);
- assert(opcode_offset + intersect_size <= bp_sp->GetByteSize());
+ assert(opcode_offset + intersect_size <= bp_site->GetByteSize());
size_t buf_offset = intersect_addr - bp_addr;
- ::memcpy(buf + buf_offset, bp_sp->GetSavedOpcodeBytes() + opcode_offset, intersect_size);
+ ::memcpy(buf + buf_offset, bp_site->GetSavedOpcodeBytes() + opcode_offset, intersect_size);
}
}
- }
+ });
}
return bytes_removed;
}
@@ -2596,64 +2591,73 @@ Process::WriteMemory (addr_t addr, const void *buf, size_t size, Error &error)
// (enabled software breakpoints) any software traps (breakpoints) that we
// may have placed in our tasks memory.
- BreakpointSiteList::collection::const_iterator iter = m_breakpoint_site_list.GetMap()->lower_bound (addr);
- BreakpointSiteList::collection::const_iterator end = m_breakpoint_site_list.GetMap()->end();
-
- if (iter == end || iter->second->GetLoadAddress() > addr + size)
- return WriteMemoryPrivate (addr, buf, size, error);
-
- BreakpointSiteList::collection::const_iterator pos;
- size_t bytes_written = 0;
- addr_t intersect_addr = 0;
- size_t intersect_size = 0;
- size_t opcode_offset = 0;
- const uint8_t *ubuf = (const uint8_t *)buf;
-
- for (pos = iter; pos != end; ++pos)
+ BreakpointSiteList bp_sites_in_range;
+
+ if (m_breakpoint_site_list.FindInRange (addr, addr + size, bp_sites_in_range))
{
- BreakpointSiteSP bp;
- bp = pos->second;
-
- assert(bp->IntersectsRange(addr, size, &intersect_addr, &intersect_size, &opcode_offset));
- assert(addr <= intersect_addr && intersect_addr < addr + size);
- assert(addr < intersect_addr + intersect_size && intersect_addr + intersect_size <= addr + size);
- assert(opcode_offset + intersect_size <= bp->GetByteSize());
-
- // Check for bytes before this breakpoint
- const addr_t curr_addr = addr + bytes_written;
- if (intersect_addr > curr_addr)
+ // No breakpoint sites overlap
+ if (bp_sites_in_range.IsEmpty())
+ return WriteMemoryPrivate (addr, buf, size, error);
+ else
{
- // There are some bytes before this breakpoint that we need to
- // just write to memory
- size_t curr_size = intersect_addr - curr_addr;
- size_t curr_bytes_written = WriteMemoryPrivate (curr_addr,
- ubuf + bytes_written,
- curr_size,
- error);
- bytes_written += curr_bytes_written;
- if (curr_bytes_written != curr_size)
- {
- // We weren't able to write all of the requested bytes, we
- // are done looping and will return the number of bytes that
- // we have written so far.
- break;
- }
- }
+ const uint8_t *ubuf = (const uint8_t *)buf;
+ uint64_t bytes_written = 0;
- // Now write any bytes that would cover up any software breakpoints
- // directly into the breakpoint opcode buffer
- ::memcpy(bp->GetSavedOpcodeBytes() + opcode_offset, ubuf + bytes_written, intersect_size);
- bytes_written += intersect_size;
+ bp_sites_in_range.ForEach([this, addr, size, &bytes_written, &ubuf, &error](BreakpointSite *bp) -> void {
+
+ if (error.Success())
+ {
+ addr_t intersect_addr;
+ size_t intersect_size;
+ size_t opcode_offset;
+ const bool intersects = bp->IntersectsRange(addr, size, &intersect_addr, &intersect_size, &opcode_offset);
+ assert(intersects);
+ assert(addr <= intersect_addr && intersect_addr < addr + size);
+ assert(addr < intersect_addr + intersect_size && intersect_addr + intersect_size <= addr + size);
+ assert(opcode_offset + intersect_size <= bp->GetByteSize());
+
+ // Check for bytes before this breakpoint
+ const addr_t curr_addr = addr + bytes_written;
+ if (intersect_addr > curr_addr)
+ {
+ // There are some bytes before this breakpoint that we need to
+ // just write to memory
+ size_t curr_size = intersect_addr - curr_addr;
+ size_t curr_bytes_written = WriteMemoryPrivate (curr_addr,
+ ubuf + bytes_written,
+ curr_size,
+ error);
+ bytes_written += curr_bytes_written;
+ if (curr_bytes_written != curr_size)
+ {
+ // We weren't able to write all of the requested bytes, we
+ // are done looping and will return the number of bytes that
+ // we have written so far.
+ if (error.Success())
+ error.SetErrorToGenericError();
+ }
+ }
+ // Now write any bytes that would cover up any software breakpoints
+ // directly into the breakpoint opcode buffer
+ ::memcpy(bp->GetSavedOpcodeBytes() + opcode_offset, ubuf + bytes_written, intersect_size);
+ bytes_written += intersect_size;
+ }
+ });
+
+ if (bytes_written < size)
+ bytes_written += WriteMemoryPrivate (addr + bytes_written,
+ ubuf + bytes_written,
+ size - bytes_written,
+ error);
+ }
+ }
+ else
+ {
+ return WriteMemoryPrivate (addr, buf, size, error);
}
// Write any remaining bytes after the last breakpoint if we have any left
- if (bytes_written < size)
- bytes_written += WriteMemoryPrivate (addr + bytes_written,
- ubuf + bytes_written,
- size - bytes_written,
- error);
-
- return bytes_written;
+ return 0; //bytes_written;
}
size_t
OpenPOWER on IntegriCloud