mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 22:06:59 +01:00
memory: refactor
This commit is contained in:
+405
-1036
File diff suppressed because it is too large
Load Diff
@@ -225,6 +225,11 @@ bool TestPlaceholderRangeIsFree(uint64_t vaddr, uint64_t size);
|
|||||||
bool TestGuestAddressRangeIsOwned(uint64_t vaddr, uint64_t size);
|
bool TestGuestAddressRangeIsOwned(uint64_t vaddr, uint64_t size);
|
||||||
bool TestGuestBackingOutsideAddressSpace();
|
bool TestGuestBackingOutsideAddressSpace();
|
||||||
uint64_t TestGuestBackingSize();
|
uint64_t TestGuestBackingSize();
|
||||||
|
uint64_t TestFlexibleBackingHighWater();
|
||||||
|
uint64_t TestGuestFreeRangeVisits();
|
||||||
|
uint64_t TestDirectMappingCount();
|
||||||
|
uint64_t TestFlexibleMappingCount();
|
||||||
|
uint64_t TestBackingBytesZeroed();
|
||||||
bool TestGuestFreeRangeBounds();
|
bool TestGuestFreeRangeBounds();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -203,6 +203,9 @@ public:
|
|||||||
}
|
}
|
||||||
std::lock_guard lock(m_mutex);
|
std::lock_guard lock(m_mutex);
|
||||||
std::memset(m_backing_base + backing_offset, 0, size);
|
std::memset(m_backing_base + backing_offset, 0, size);
|
||||||
|
#if defined(KYTY_VIRTUAL_MEMORY_ALLOCATION_TESTS)
|
||||||
|
g_test_backing_bytes_zeroed += size;
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,6 +290,18 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ProtectViews(uint64_t vaddr, uint64_t size, VirtualMemory::Mode mode) {
|
||||||
|
std::shared_lock lock(m_mutex);
|
||||||
|
bool ok = true;
|
||||||
|
ForEachSparseRange(
|
||||||
|
m_maps, vaddr, size,
|
||||||
|
[&](const auto&, uint64_t start, uint64_t bytes) {
|
||||||
|
ok = ok && VirtualMemory::Protect(start, bytes, mode);
|
||||||
|
},
|
||||||
|
[&](uint64_t, uint64_t) { ok = false; });
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
bool MapFixed(uint64_t vaddr, uint64_t size, uint64_t backing_offset,
|
bool MapFixed(uint64_t vaddr, uint64_t size, uint64_t backing_offset,
|
||||||
VirtualMemory::Mode mode, FailureReason* failure_reason = nullptr) {
|
VirtualMemory::Mode mode, FailureReason* failure_reason = nullptr) {
|
||||||
if (!IsAvailable() || !RangeOk(backing_offset, size)) {
|
if (!IsAvailable() || !RangeOk(backing_offset, size)) {
|
||||||
@@ -324,15 +339,11 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Unmap(uint64_t vaddr, uint64_t size, bool* placeholder_preserved = nullptr) {
|
bool Unmap(uint64_t vaddr, uint64_t size) {
|
||||||
if (size == 0 || UINT64_MAX - vaddr < size) {
|
if (size == 0 || UINT64_MAX - vaddr < size) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (placeholder_preserved != nullptr) {
|
|
||||||
*placeholder_preserved = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto end = vaddr + size;
|
const auto end = vaddr + size;
|
||||||
std::vector<MapEntry> targets;
|
std::vector<MapEntry> targets;
|
||||||
{
|
{
|
||||||
@@ -350,42 +361,36 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MapEntry> removed;
|
size_t removed = 0;
|
||||||
removed.reserve(targets.size());
|
auto rollback = [&] {
|
||||||
|
while (removed != 0) {
|
||||||
|
const auto& previous = targets[--removed];
|
||||||
|
EXIT_IF(!MapFixed(previous.vaddr, previous.size, previous.backing_offset,
|
||||||
|
previous.mode));
|
||||||
|
}
|
||||||
|
};
|
||||||
for (const auto& entry: targets) {
|
for (const auto& entry: targets) {
|
||||||
bool part_placeholder_preserved = false;
|
if (!UnmapOne(entry.vaddr, entry.size)) {
|
||||||
if (!UnmapOne(entry.vaddr, entry.size, &part_placeholder_preserved)) {
|
rollback();
|
||||||
for (auto it = removed.rbegin(); it != removed.rend(); ++it) {
|
|
||||||
EXIT_IF(!MapFixed(it->vaddr, it->size, it->backing_offset, it->mode));
|
|
||||||
}
|
|
||||||
if (placeholder_preserved != nullptr) {
|
|
||||||
*placeholder_preserved = false;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
EXIT_IF(!part_placeholder_preserved);
|
++removed;
|
||||||
removed.push_back(entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||||
// Each unmapped file view becomes a separate Windows placeholder. The address-space owner
|
// Each unmapped file view becomes a separate Windows placeholder. The address-space owner
|
||||||
// records this contiguous guest span as one free range, so normalize fragmented backing
|
// records this contiguous guest span as one free range, so normalize fragmented backing
|
||||||
// views into one placeholder before publishing it there.
|
// views into one placeholder before publishing it there.
|
||||||
if (removed.size() > 1 && !CoalescePlaceholders(vaddr, size)) {
|
if (removed > 1 && !CoalescePlaceholders(vaddr, size)) {
|
||||||
for (auto it = removed.rbegin(); it != removed.rend(); ++it) {
|
rollback();
|
||||||
EXIT_IF(!MapFixed(it->vaddr, it->size, it->backing_offset, it->mode));
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (placeholder_preserved != nullptr) {
|
|
||||||
*placeholder_preserved = true;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UnmapOne(uint64_t vaddr, uint64_t size, bool* placeholder_preserved = nullptr) {
|
bool UnmapOne(uint64_t vaddr, uint64_t size) {
|
||||||
#if defined(KYTY_VIRTUAL_MEMORY_ALLOCATION_TESTS)
|
#if defined(KYTY_VIRTUAL_MEMORY_ALLOCATION_TESTS)
|
||||||
if (g_test_backing_store_unmaps_before_failure == 0) {
|
if (g_test_backing_store_unmaps_before_failure == 0) {
|
||||||
g_test_backing_store_unmaps_before_failure = UINT32_MAX;
|
g_test_backing_store_unmaps_before_failure = UINT32_MAX;
|
||||||
@@ -428,9 +433,7 @@ public:
|
|||||||
m_maps.emplace(old.vaddr, old);
|
m_maps.emplace(old.vaddr, old);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (placeholder_preserved != nullptr) {
|
|
||||||
*placeholder_preserved = true;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,9 +454,6 @@ public:
|
|||||||
ok;
|
ok;
|
||||||
}
|
}
|
||||||
if (ok) {
|
if (ok) {
|
||||||
if (placeholder_preserved != nullptr) {
|
|
||||||
*placeholder_preserved = true;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -481,9 +481,6 @@ public:
|
|||||||
std::lock_guard lock(m_mutex);
|
std::lock_guard lock(m_mutex);
|
||||||
RemoveMappingsUnlocked(vaddr, size);
|
RemoveMappingsUnlocked(vaddr, size);
|
||||||
|
|
||||||
if (placeholder_preserved != nullptr) {
|
|
||||||
*placeholder_preserved = true;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -634,8 +631,6 @@ private:
|
|||||||
|
|
||||||
HANDLE m_handle = nullptr;
|
HANDLE m_handle = nullptr;
|
||||||
#elif KYTY_PLATFORM == KYTY_PLATFORM_LINUX
|
#elif KYTY_PLATFORM == KYTY_PLATFORM_LINUX
|
||||||
[[nodiscard]] static uint64_t GetMappableTestSize() { return 0x4000; }
|
|
||||||
|
|
||||||
static int GetProtect(VirtualMemory::Mode mode) {
|
static int GetProtect(VirtualMemory::Mode mode) {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case VirtualMemory::Mode::Read: return PROT_READ;
|
case VirtualMemory::Mode::Read: return PROT_READ;
|
||||||
@@ -760,7 +755,7 @@ public:
|
|||||||
if (size == 0 || UINT64_MAX - vaddr < size) {
|
if (size == 0 || UINT64_MAX - vaddr < size) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::lock_guard lock(m_mutex);
|
std::shared_lock lock(m_mutex);
|
||||||
return std::any_of(m_owned.begin(), m_owned.end(), [vaddr, size](const auto& range) {
|
return std::any_of(m_owned.begin(), m_owned.end(), [vaddr, size](const auto& range) {
|
||||||
return VirtualRangesOverlap(vaddr, size, range.first, range.second);
|
return VirtualRangesOverlap(vaddr, size, range.first, range.second);
|
||||||
});
|
});
|
||||||
@@ -864,11 +859,7 @@ public:
|
|||||||
if (!ContainsMappedUnlocked(vaddr, size, MappingType::Backing)) {
|
if (!ContainsMappedUnlocked(vaddr, size, MappingType::Backing)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool placeholder_preserved = false;
|
if (!m_backing->Unmap(vaddr, size)) {
|
||||||
if (!m_backing->Unmap(vaddr, size, &placeholder_preserved)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!placeholder_preserved) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
EXIT_IF(!RemoveMappedUnlocked(vaddr, size, MappingType::Backing));
|
EXIT_IF(!RemoveMappedUnlocked(vaddr, size, MappingType::Backing));
|
||||||
@@ -876,12 +867,13 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reservations live in VirtualRanges; these free-range checks only read the host placeholders.
|
||||||
uint64_t ReserveAligned(uint64_t search_addr, uint64_t size, uint64_t alignment) {
|
uint64_t ReserveAligned(uint64_t search_addr, uint64_t size, uint64_t alignment) {
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
alignment = std::max<uint64_t>(alignment != 0 ? alignment : PageSize(), PageSize());
|
alignment = std::max<uint64_t>(alignment != 0 ? alignment : PageSize(), PageSize());
|
||||||
std::lock_guard lock(m_mutex);
|
std::shared_lock lock(m_mutex);
|
||||||
if (search_addr == 0) {
|
if (search_addr == 0) {
|
||||||
auto addr = FindFreeAlignedUnlocked(HOST_SYSTEM_MANAGED_MIN,
|
auto addr = FindFreeAlignedUnlocked(HOST_SYSTEM_MANAGED_MIN,
|
||||||
HOST_SYSTEM_MANAGED_MAX + 1u, size, alignment);
|
HOST_SYSTEM_MANAGED_MAX + 1u, size, alignment);
|
||||||
@@ -898,7 +890,7 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
alignment = std::max<uint64_t>(alignment, PageSize());
|
alignment = std::max<uint64_t>(alignment, PageSize());
|
||||||
std::lock_guard lock(m_mutex);
|
std::shared_lock lock(m_mutex);
|
||||||
return FindFreeAlignedUnlocked(search_start, search_end, size, alignment);
|
return FindFreeAlignedUnlocked(search_start, search_end, size, alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -906,19 +898,19 @@ public:
|
|||||||
if (vaddr == 0 || size == 0 || !IsPageAligned(vaddr) || !IsPageAligned(size)) {
|
if (vaddr == 0 || size == 0 || !IsPageAligned(vaddr) || !IsPageAligned(size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::lock_guard lock(m_mutex);
|
std::shared_lock lock(m_mutex);
|
||||||
return FindContaining(vaddr, size) != m_free.end();
|
return FindContaining(vaddr, size) != m_free.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(KYTY_VIRTUAL_MEMORY_ALLOCATION_TESTS)
|
#if defined(KYTY_VIRTUAL_MEMORY_ALLOCATION_TESTS)
|
||||||
bool TestContainsFree(uint64_t vaddr, uint64_t size) {
|
bool TestContainsFree(uint64_t vaddr, uint64_t size) {
|
||||||
std::lock_guard lock(m_mutex);
|
std::shared_lock lock(m_mutex);
|
||||||
return FindContaining(vaddr, size) != m_free.end();
|
return FindContaining(vaddr, size) != m_free.end();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool ReleaseFree(uint64_t vaddr, uint64_t size) {
|
bool ReleaseFree(uint64_t vaddr, uint64_t size) {
|
||||||
std::lock_guard lock(m_mutex);
|
std::shared_lock lock(m_mutex);
|
||||||
return FindContaining(vaddr, size) != m_free.end();
|
return FindContaining(vaddr, size) != m_free.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1041,10 +1033,6 @@ private:
|
|||||||
return (value & (PageSize() - 1u)) == 0;
|
return (value & (PageSize() - 1u)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool IsGranularityAligned(uint64_t value) const {
|
|
||||||
return (value & (m_granularity - 1u)) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ProtectMappedUnlocked(uint64_t vaddr, uint64_t size, VirtualMemory::Mode mode) {
|
bool ProtectMappedUnlocked(uint64_t vaddr, uint64_t size, VirtualMemory::Mode mode) {
|
||||||
const auto end = vaddr + size;
|
const auto end = vaddr + size;
|
||||||
auto it = m_mapped.upper_bound(vaddr);
|
auto it = m_mapped.upper_bound(vaddr);
|
||||||
@@ -1055,8 +1043,20 @@ private:
|
|||||||
const auto& region = it->second;
|
const auto& region = it->second;
|
||||||
const auto range_start = std::max(vaddr, region.vaddr);
|
const auto range_start = std::max(vaddr, region.vaddr);
|
||||||
const auto range_end = std::min(end, region.vaddr + region.size);
|
const auto range_end = std::min(end, region.vaddr + region.size);
|
||||||
if (range_start < range_end &&
|
if (range_start >= range_end) {
|
||||||
!VirtualMemory::Protect(range_start, range_end - range_start, mode)) {
|
continue;
|
||||||
|
}
|
||||||
|
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||||
|
// Rollback can split a backing view without changing the owner interval.
|
||||||
|
// Windows protection calls must stay within each actual view.
|
||||||
|
if (region.type == MappingType::Backing) {
|
||||||
|
if (!m_backing->ProtectViews(range_start, range_end - range_start, mode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (!VirtualMemory::Protect(range_start, range_end - range_start, mode)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1312,11 +1312,20 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t FindFreeAlignedUnlocked(uint64_t search_start, uint64_t search_end, uint64_t size,
|
uint64_t FindFreeAlignedUnlocked(uint64_t search_start, uint64_t search_end, uint64_t size,
|
||||||
uint64_t alignment) {
|
uint64_t alignment) const {
|
||||||
if (search_start >= search_end || size > search_end - search_start) {
|
if (search_start >= search_end || size > search_end - search_start) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for (const auto& [base, range_size]: m_free) {
|
// Include the predecessor because search_start can lie inside a free range.
|
||||||
|
auto it = m_free.upper_bound(search_start);
|
||||||
|
if (it != m_free.begin()) {
|
||||||
|
--it;
|
||||||
|
}
|
||||||
|
for (; it != m_free.end() && it->first < search_end; ++it) {
|
||||||
|
#if defined(KYTY_VIRTUAL_MEMORY_ALLOCATION_TESTS)
|
||||||
|
g_test_free_range_visits.fetch_add(1, std::memory_order_relaxed);
|
||||||
|
#endif
|
||||||
|
const auto& [base, range_size] = *it;
|
||||||
const auto candidate = AlignUp(std::max(base, search_start), alignment);
|
const auto candidate = AlignUp(std::max(base, search_start), alignment);
|
||||||
if (candidate < search_end && size <= search_end - candidate &&
|
if (candidate < search_end && size <= search_end - candidate &&
|
||||||
GuestFreeRangeContains(base, range_size, candidate, size)) {
|
GuestFreeRangeContains(base, range_size, candidate, size)) {
|
||||||
@@ -1332,8 +1341,7 @@ private:
|
|||||||
return m_free.end();
|
return m_free.end();
|
||||||
}
|
}
|
||||||
auto it = std::prev(next);
|
auto it = std::prev(next);
|
||||||
auto end = it->first + it->second;
|
return GuestFreeRangeContains(it->first, it->second, vaddr, size) ? it : m_free.end();
|
||||||
return (vaddr >= it->first && vaddr + size <= end ? it : m_free.end());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SplitUnlocked(std::map<uint64_t, uint64_t>::iterator it, uint64_t vaddr, uint64_t size) {
|
bool SplitUnlocked(std::map<uint64_t, uint64_t>::iterator it, uint64_t vaddr, uint64_t size) {
|
||||||
|
|||||||
+24
-6
@@ -39,7 +39,7 @@ struct Global {
|
|||||||
|
|
||||||
struct Shadow {
|
struct Shadow {
|
||||||
uintptr_t start = 0;
|
uintptr_t start = 0;
|
||||||
int count = 0;
|
uint64_t covered_bytes = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AsanContext {
|
struct AsanContext {
|
||||||
@@ -50,6 +50,14 @@ struct AsanContext {
|
|||||||
static uint32_t g_fake_stack = 0;
|
static uint32_t g_fake_stack = 0;
|
||||||
static AsanContext* g_ctx = nullptr;
|
static AsanContext* g_ctx = nullptr;
|
||||||
|
|
||||||
|
// Allocation and release callbacks can partition the same guest range differently.
|
||||||
|
static uint64_t ShadowCoverage(uintptr_t page, uintptr_t min_addr, uintptr_t max_addr) {
|
||||||
|
const auto guest_start = (page - 0x10000000000ull) << 3u;
|
||||||
|
const auto guest_end = guest_start + 0x80000ull - 1;
|
||||||
|
return std::min<uintptr_t>(max_addr, guest_end) - std::max<uintptr_t>(min_addr, guest_start) +
|
||||||
|
1;
|
||||||
|
}
|
||||||
|
|
||||||
static void AllocShadow(uintptr_t min_addr, uintptr_t max_addr) {
|
static void AllocShadow(uintptr_t min_addr, uintptr_t max_addr) {
|
||||||
EXIT_IF(g_ctx == nullptr);
|
EXIT_IF(g_ctx == nullptr);
|
||||||
|
|
||||||
@@ -67,10 +75,11 @@ static void AllocShadow(uintptr_t min_addr, uintptr_t max_addr) {
|
|||||||
static_cast<uint64_t>(min_shadow), static_cast<uint64_t>(size));
|
static_cast<uint64_t>(min_shadow), static_cast<uint64_t>(size));
|
||||||
|
|
||||||
for (uintptr_t page = min_shadow; page <= max_shadow; page += page_size) {
|
for (uintptr_t page = min_shadow; page <= max_shadow; page += page_size) {
|
||||||
|
const auto bytes = ShadowCoverage(page, min_addr, max_addr);
|
||||||
const auto it = std::find_if(g_ctx->shadows.begin(), g_ctx->shadows.end(),
|
const auto it = std::find_if(g_ctx->shadows.begin(), g_ctx->shadows.end(),
|
||||||
[page](const Shadow& s) { return s.start == page; });
|
[page](const Shadow& s) { return s.start == page; });
|
||||||
if (it != g_ctx->shadows.end()) {
|
if (it != g_ctx->shadows.end()) {
|
||||||
it->count++;
|
it->covered_bytes += bytes;
|
||||||
} else {
|
} else {
|
||||||
if (!Common::VirtualMemory::AllocFixed(page, page_size,
|
if (!Common::VirtualMemory::AllocFixed(page, page_size,
|
||||||
Common::VirtualMemory::Mode::ReadWrite)) {
|
Common::VirtualMemory::Mode::ReadWrite)) {
|
||||||
@@ -79,7 +88,7 @@ static void AllocShadow(uintptr_t min_addr, uintptr_t max_addr) {
|
|||||||
|
|
||||||
Shadow s;
|
Shadow s;
|
||||||
s.start = page;
|
s.start = page;
|
||||||
s.count = 1;
|
s.covered_bytes = bytes;
|
||||||
g_ctx->shadows.push_back(s);
|
g_ctx->shadows.push_back(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,14 +114,15 @@ static void FreeShadow(uintptr_t min_addr, uintptr_t max_addr) {
|
|||||||
const auto it = std::find_if(g_ctx->shadows.begin(), g_ctx->shadows.end(),
|
const auto it = std::find_if(g_ctx->shadows.begin(), g_ctx->shadows.end(),
|
||||||
[page](const Shadow& s) { return s.start == page; });
|
[page](const Shadow& s) { return s.start == page; });
|
||||||
if (it != g_ctx->shadows.end()) {
|
if (it != g_ctx->shadows.end()) {
|
||||||
it->count--;
|
const auto bytes = ShadowCoverage(page, min_addr, max_addr);
|
||||||
|
if (bytes >= it->covered_bytes) {
|
||||||
if (it->count <= 0) {
|
|
||||||
if (!Common::VirtualMemory::Free(page)) {
|
if (!Common::VirtualMemory::Free(page)) {
|
||||||
EXIT("can't free shadow memory\n");
|
EXIT("can't free shadow memory\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
g_ctx->shadows.erase(it);
|
g_ctx->shadows.erase(it);
|
||||||
|
} else {
|
||||||
|
it->covered_bytes -= bytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,6 +136,14 @@ static void KernelFree(uintptr_t addr, size_t size) {
|
|||||||
FreeShadow(addr, addr + size - 1);
|
FreeShadow(addr, addr + size - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(KYTY_VIRTUAL_MEMORY_ALLOCATION_TESTS)
|
||||||
|
void TestRegisterMemoryCallbacks() {
|
||||||
|
EXIT_IF(g_ctx != nullptr);
|
||||||
|
g_ctx = new AsanContext;
|
||||||
|
LibKernel::Memory::RegisterCallbacks(KernelAlloc, KernelFree);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void KYTY_SYSV_ABI asan_init() {
|
static void KYTY_SYSV_ABI asan_init() {
|
||||||
PRINT_NAME();
|
PRINT_NAME();
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user