[Lldb-commits] [PATCH] Fix a bug in IRMemoryMap which generated bogus allocations
Zachary Turner
zturner at google.com
Wed Jun 25 01:09:48 PDT 2014
The IRMemoryMap represents a set of disjoint allocations, stored as an interval map. A bug in its allocation algorithm would cause this disjoint property to be violated, resulting in overlapping intervals in the map.
Consider the following scenario:
Allocation 1: 8 bytes, address 8192 is chosen by the allocator
Allocation 2: 524288, address 0 is probed
Without this patch, the IntersectsAllocation() method would behave as follows:
1) lower_bound(0) returns an iterator referring to allocation 1
2) 0 is compared against 8192, and since 0 < 8192, it says there is no intersection.
With the patch, it does proper interval tests.
http://reviews.llvm.org/D4286
Files:
include/lldb/Expression/IRMemoryMap.h
source/Expression/IRMemoryMap.cpp
Index: include/lldb/Expression/IRMemoryMap.h
===================================================================
--- include/lldb/Expression/IRMemoryMap.h
+++ include/lldb/Expression/IRMemoryMap.h
@@ -27,7 +27,8 @@
/// This class encapsulates a group of memory objects that must be readable
/// or writable from the host process regardless of whether the process
/// exists. This allows the IR interpreter as well as JITted code to access
-/// the same memory.
+/// the same memory. All allocations made by this class are represented as
+/// disjoint intervals.
///
/// Point queries against this group of memory objects can be made by the
/// address in the tar at which they reside. If the inferior does not
@@ -118,7 +119,12 @@
lldb::addr_t FindSpace (size_t size);
bool ContainsHostOnlyAllocations ();
AllocationMap::iterator FindAllocation (lldb::addr_t addr, size_t size);
- bool IntersectsAllocation (lldb::addr_t addr, size_t size);
+
+ // Returns true if the given allocation intersects any allocation in the memory map.
+ bool IntersectsAllocation (lldb::addr_t addr, size_t size) const;
+
+ // Returns true if the two given allocations intersect each other.
+ bool IntersectsAllocation (lldb::addr_t addr1, size_t size1, lldb::addr_t addr2, size_t size2) const;
};
}
Index: source/Expression/IRMemoryMap.cpp
===================================================================
--- source/Expression/IRMemoryMap.cpp
+++ source/Expression/IRMemoryMap.cpp
@@ -125,33 +125,48 @@
}
bool
-IRMemoryMap::IntersectsAllocation (lldb::addr_t addr, size_t size)
+IRMemoryMap::IntersectsAllocation (lldb::addr_t addr, size_t size) const
{
if (addr == LLDB_INVALID_ADDRESS)
return false;
- AllocationMap::iterator iter = m_allocations.lower_bound (addr);
+ AllocationMap::const_iterator iter = m_allocations.lower_bound (addr);
- if (iter == m_allocations.end() ||
- iter->first > addr)
- {
- if (iter == m_allocations.begin())
- return false;
-
- iter--;
+ // Since we only know that the returned interval begins at a location greater than or
+ // equal to where the given interval begins, it's possible that the given interval
+ // intersects either the returned interval or the previous interval. Thus, we need to
+ // check both. Note that we only need to check these two intervals. Since all intervals
+ // are disjoint it is not possible that an adjacent interval does not intersect, but a
+ // non-adjacent interval does intersect.
+ if (iter != m_allocations.end()) {
+ if (IntersectsAllocation(addr, size, iter->second.m_process_start, iter->second.m_size))
+ return true;
}
-
- while (iter != m_allocations.end() && iter->second.m_process_alloc < addr + size)
- {
- if (iter->second.m_process_start + iter->second.m_size > addr)
+
+ if (iter != m_allocations.begin()) {
+ --iter;
+ if (IntersectsAllocation(addr, size, iter->second.m_process_start, iter->second.m_size))
return true;
-
- ++iter;
}
-
+
return false;
}
+bool
+IRMemoryMap::IntersectsAllocation(lldb::addr_t addr1, size_t size1, lldb::addr_t addr2, size_t size2) const {
+ // Given two half open intervals [A, B) and [X, Y), the only 6 permutations that satisfy
+ // A<B and X<Y are the following:
+ // A B X Y
+ // A X B Y (intersects)
+ // A X Y B (intersects)
+ // X A B Y (intersects)
+ // X A Y B (intersects)
+ // X Y A B
+ // The first is B <= X, and the last is Y <= A.
+ // So the condition is !(B <= X || Y <= A)), or (X < B && A < Y)
+ return (addr2 < (addr1 + size1)) && (addr1 < (addr2 + size2));
+}
+
lldb::ByteOrder
IRMemoryMap::GetByteOrder()
{
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D4286.10822.patch
Type: text/x-patch
Size: 3804 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/lldb-commits/attachments/20140625/2219d212/attachment.bin>
More information about the lldb-commits
mailing list