diff options
author | Andreas Kling <kling@serenityos.org> | 2021-02-06 23:08:51 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-02-06 23:15:44 +0100 |
commit | 89483a94085a03b5c422ba4ad0e2f43841f07719 (patch) | |
tree | 392f13d5177c7c7761126834c34204d4878112d0 /Userland/DevTools | |
parent | 9dacd7c0ecb8ee78595c93d33bd432e18c00fe00 (diff) | |
download | serenity-89483a94085a03b5c422ba4ad0e2f43841f07719.zip |
UserspaceEmulator: Implement a proper VM allocator
This patch brings Kernel::RangeAllocator to UserspaceEmulator in a
slightly simplified form.
It supports the basic three allocation types needed by virt$mmap():
allocate_anywhere, allocate_specific, and allocate_randomized.
Porting virt$mmap() and virt$munmap() to use the allocator makes
UE work correctly once again. :^)
Diffstat (limited to 'Userland/DevTools')
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/CMakeLists.txt | 2 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/Emulator.cpp | 56 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/Emulator.h | 6 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/MmapRegion.h | 2 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/Range.cpp | 45 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/Range.h | 84 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/RangeAllocator.cpp | 207 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/RangeAllocator.h | 57 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/Region.cpp | 3 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/Region.h | 12 |
10 files changed, 438 insertions, 36 deletions
diff --git a/Userland/DevTools/UserspaceEmulator/CMakeLists.txt b/Userland/DevTools/UserspaceEmulator/CMakeLists.txt index 43164b0d6d..5068bdd56e 100644 --- a/Userland/DevTools/UserspaceEmulator/CMakeLists.txt +++ b/Userland/DevTools/UserspaceEmulator/CMakeLists.txt @@ -2,6 +2,8 @@ set(SOURCES Emulator.cpp MallocTracer.cpp MmapRegion.cpp + Range.cpp + RangeAllocator.cpp Region.cpp SimpleRegion.cpp SoftCPU.cpp diff --git a/Userland/DevTools/UserspaceEmulator/Emulator.cpp b/Userland/DevTools/UserspaceEmulator/Emulator.cpp index b19457e8bd..59e4730bad 100644 --- a/Userland/DevTools/UserspaceEmulator/Emulator.cpp +++ b/Userland/DevTools/UserspaceEmulator/Emulator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,6 +32,7 @@ #include <AK/Format.h> #include <AK/LexicalPath.h> #include <AK/MappedFile.h> +#include <AK/Random.h> #include <LibELF/AuxiliaryVector.h> #include <LibELF/Image.h> #include <LibELF/Validation.h> @@ -81,6 +82,19 @@ Emulator::Emulator(const String& executable_path, const Vector<String>& argument , m_cpu(*this) { m_malloc_tracer = make<MallocTracer>(*this); + + static constexpr FlatPtr userspace_range_base = 0x00800000; + static constexpr FlatPtr userspace_range_ceiling = 0xbe000000; +#ifdef UE_ASLR + static constexpr FlatPtr page_mask = 0xfffff000u; + size_t random_offset = (AK::get_random<u8>() % 32 * MiB) & page_mask; + FlatPtr base = userspace_range_base + random_offset; +#else + FlatPtr base = userspace_range_base; +#endif + + m_range_allocator.initialize_with_range(VirtualAddress(base), userspace_range_ceiling - base); + ASSERT(!s_the); s_the = this; // setup_stack(arguments, environment); @@ -972,41 +986,31 @@ u32 Emulator::virt$munmap(FlatPtr address, u32 size) ASSERT(region); if (region->size() != round_up_to_power_of_two(size, PAGE_SIZE)) TODO(); + m_range_allocator.deallocate(region->range()); mmu().remove_region(*region); return 0; } -FlatPtr Emulator::allocate_vm(size_t size, size_t alignment) -{ - // FIXME: Write a proper VM allocator - static FlatPtr next_address = 0x30000000; - - FlatPtr final_address; - - if (!alignment) - alignment = PAGE_SIZE; - - // FIXME: What if alignment is not a power of 2? - final_address = round_up_to_power_of_two(next_address, alignment); - next_address = round_up_to_power_of_two(final_address + size, PAGE_SIZE); - return final_address; -} - u32 Emulator::virt$mmap(u32 params_addr) { Syscall::SC_mmap_params params; mmu().copy_from_vm(¶ms, params_addr, sizeof(params)); - u32 final_size = round_up_to_power_of_two(params.size, PAGE_SIZE); - u32 final_address = allocate_vm(final_size, params.alignment); - if (params.addr != 0) { - // NOTE: We currently do not support allocating VM at a requeted address in the emulator. - // The loader needs this functionality to load .data just after .text. - // Luckily, since the loader calls mmap for .data right after it calls mmap for .text, - // the emulator will allocate a chunk of memory that is just after what we allocated for .text - // because of the way we currently allocate VM. - ASSERT(params.addr == final_address); + u32 requested_size = round_up_to_power_of_two(params.size, PAGE_SIZE); + FlatPtr final_address; + + Optional<Range> result; + if (params.flags & MAP_RANDOMIZED) { + result = m_range_allocator.allocate_randomized(requested_size, params.alignment); + } else if (params.flags & MAP_FIXED) { + result = m_range_allocator.allocate_specific(VirtualAddress { params.addr }, requested_size); + } else { + result = m_range_allocator.allocate_anywhere(requested_size, params.alignment); } + if (!result.has_value()) + return -ENOMEM; + final_address = result.value().base().get(); + auto final_size = result.value().size(); if (params.flags & MAP_ANONYMOUS) mmu().add_region(MmapRegion::create_anonymous(final_address, final_size, params.prot)); diff --git a/Userland/DevTools/UserspaceEmulator/Emulator.h b/Userland/DevTools/UserspaceEmulator/Emulator.h index 03e051028f..caaf32e391 100644 --- a/Userland/DevTools/UserspaceEmulator/Emulator.h +++ b/Userland/DevTools/UserspaceEmulator/Emulator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,6 +27,7 @@ #pragma once #include "MallocTracer.h" +#include "RangeAllocator.h" #include "Report.h" #include "SoftCPU.h" #include "SoftMMU.h" @@ -174,7 +175,6 @@ private: int virt$sendfd(int, int); int virt$msyscall(FlatPtr); - FlatPtr allocate_vm(size_t size, size_t alignment); bool find_malloc_symbols(const MmapRegion& libc_text); void dispatch_one_pending_signal(); @@ -213,6 +213,8 @@ private: }; HashMap<String, CachedELF> m_dynamic_library_cache; + + RangeAllocator m_range_allocator; }; ALWAYS_INLINE bool Emulator::is_in_malloc_or_free() const diff --git a/Userland/DevTools/UserspaceEmulator/MmapRegion.h b/Userland/DevTools/UserspaceEmulator/MmapRegion.h index 75a42340ab..47fb8e0ec7 100644 --- a/Userland/DevTools/UserspaceEmulator/MmapRegion.h +++ b/Userland/DevTools/UserspaceEmulator/MmapRegion.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/Userland/DevTools/UserspaceEmulator/Range.cpp b/Userland/DevTools/UserspaceEmulator/Range.cpp new file mode 100644 index 0000000000..af6b09d19d --- /dev/null +++ b/Userland/DevTools/UserspaceEmulator/Range.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "Range.h" +#include <AK/Vector.h> + +namespace UserspaceEmulator { + +Vector<Range, 2> Range::carve(const Range& taken) +{ + ASSERT((taken.size() % PAGE_SIZE) == 0); + Vector<Range, 2> parts; + if (taken == *this) + return {}; + if (taken.base() > base()) + parts.append({ base(), taken.base().get() - base().get() }); + if (taken.end() < end()) + parts.append({ taken.end(), end().get() - taken.end().get() }); + return parts; +} + +} diff --git a/Userland/DevTools/UserspaceEmulator/Range.h b/Userland/DevTools/UserspaceEmulator/Range.h new file mode 100644 index 0000000000..08a8e9caaf --- /dev/null +++ b/Userland/DevTools/UserspaceEmulator/Range.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include <AK/Types.h> +#include <Kernel/VirtualAddress.h> + +namespace UserspaceEmulator { + +class Range { + friend class RangeAllocator; + +public: + Range() = delete; + Range(VirtualAddress base, size_t size) + : m_base(base) + , m_size(size) + { + } + + VirtualAddress base() const { return m_base; } + size_t size() const { return m_size; } + bool is_valid() const { return !m_base.is_null(); } + + bool contains(VirtualAddress vaddr) const { return vaddr >= base() && vaddr < end(); } + + VirtualAddress end() const { return m_base.offset(m_size); } + + bool operator==(const Range& other) const + { + return m_base == other.m_base && m_size == other.m_size; + } + + bool contains(VirtualAddress base, size_t size) const + { + if (base.offset(size) < base) + return false; + return base >= m_base && base.offset(size) <= end(); + } + + bool contains(const Range& other) const + { + return contains(other.base(), other.size()); + } + + Vector<Range, 2> carve(const Range&); + +private: + VirtualAddress m_base; + size_t m_size { 0 }; +}; + +} + +namespace AK { +template<> +struct Traits<UserspaceEmulator::Range> : public GenericTraits<UserspaceEmulator::Range> { + static constexpr bool is_trivial() { return true; } +}; +} diff --git a/Userland/DevTools/UserspaceEmulator/RangeAllocator.cpp b/Userland/DevTools/UserspaceEmulator/RangeAllocator.cpp new file mode 100644 index 0000000000..f4f6fc1341 --- /dev/null +++ b/Userland/DevTools/UserspaceEmulator/RangeAllocator.cpp @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "RangeAllocator.h" +#include <AK/BinarySearch.h> +#include <AK/Checked.h> +#include <AK/QuickSort.h> +#include <AK/Random.h> + +#define VM_GUARD_PAGES +#define PAGE_MASK ((FlatPtr)0xfffff000u) + +namespace UserspaceEmulator { + +RangeAllocator::RangeAllocator() + : m_total_range({}, 0) +{ +} + +void RangeAllocator::initialize_with_range(VirtualAddress base, size_t size) +{ + m_total_range = { base, size }; + m_available_ranges.append({ base, size }); +} + +RangeAllocator::~RangeAllocator() +{ +} + +void RangeAllocator::dump() const +{ + dbgln("RangeAllocator({})", this); + for (auto& range : m_available_ranges) { + dbgln(" {:x} -> {:x}", range.base().get(), range.end().get() - 1); + } +} + +void RangeAllocator::carve_at_index(int index, const Range& range) +{ + auto remaining_parts = m_available_ranges[index].carve(range); + ASSERT(remaining_parts.size() >= 1); + ASSERT(m_total_range.contains(remaining_parts[0])); + m_available_ranges[index] = remaining_parts[0]; + if (remaining_parts.size() == 2) { + ASSERT(m_total_range.contains(remaining_parts[1])); + m_available_ranges.insert(index + 1, move(remaining_parts[1])); + } +} + +Optional<Range> RangeAllocator::allocate_randomized(size_t size, size_t alignment) +{ + if (!size) + return {}; + + ASSERT((size % PAGE_SIZE) == 0); + ASSERT((alignment % PAGE_SIZE) == 0); + + // FIXME: I'm sure there's a smarter way to do this. + static constexpr size_t maximum_randomization_attempts = 1000; + for (size_t i = 0; i < maximum_randomization_attempts; ++i) { + VirtualAddress random_address { AK::get_random<FlatPtr>() }; + random_address.mask(PAGE_MASK); + + if (!m_total_range.contains(random_address, size)) + continue; + + auto range = allocate_specific(random_address, size); + if (range.has_value()) + return range; + } + + return allocate_anywhere(size, alignment); +} + +Optional<Range> RangeAllocator::allocate_anywhere(size_t size, size_t alignment) +{ + if (!size) + return {}; + + ASSERT((size % PAGE_SIZE) == 0); + ASSERT((alignment % PAGE_SIZE) == 0); + +#ifdef VM_GUARD_PAGES + // NOTE: We pad VM allocations with a guard page on each side. + if (Checked<size_t>::addition_would_overflow(size, PAGE_SIZE * 2)) + return {}; + + size_t effective_size = size + PAGE_SIZE * 2; + size_t offset_from_effective_base = PAGE_SIZE; +#else + size_t effective_size = size; + size_t offset_from_effective_base = 0; +#endif + + if (Checked<size_t>::addition_would_overflow(effective_size, alignment)) + return {}; + + for (size_t i = 0; i < m_available_ranges.size(); ++i) { + auto& available_range = m_available_ranges[i]; + // FIXME: This check is probably excluding some valid candidates when using a large alignment. + if (available_range.size() < (effective_size + alignment)) + continue; + + FlatPtr initial_base = available_range.base().offset(offset_from_effective_base).get(); + FlatPtr aligned_base = round_up_to_power_of_two(initial_base, alignment); + + Range allocated_range(VirtualAddress(aligned_base), size); + ASSERT(m_total_range.contains(allocated_range)); + + if (available_range == allocated_range) { + m_available_ranges.remove(i); + return allocated_range; + } + carve_at_index(i, allocated_range); + return allocated_range; + } + klog() << "RangeAllocator: Failed to allocate anywhere: " << size << ", " << alignment; + return {}; +} + +Optional<Range> RangeAllocator::allocate_specific(VirtualAddress base, size_t size) +{ + if (!size) + return {}; + + ASSERT(base.is_page_aligned()); + ASSERT((size % PAGE_SIZE) == 0); + + Range allocated_range(base, size); + for (size_t i = 0; i < m_available_ranges.size(); ++i) { + auto& available_range = m_available_ranges[i]; + ASSERT(m_total_range.contains(allocated_range)); + if (!available_range.contains(base, size)) + continue; + if (available_range == allocated_range) { + m_available_ranges.remove(i); + return allocated_range; + } + carve_at_index(i, allocated_range); + return allocated_range; + } + return {}; +} + +void RangeAllocator::deallocate(const Range& range) +{ + ASSERT(m_total_range.contains(range)); + ASSERT(range.size()); + ASSERT((range.size() % PAGE_SIZE) == 0); + ASSERT(range.base() < range.end()); + ASSERT(!m_available_ranges.is_empty()); + + size_t nearby_index = 0; + auto* existing_range = binary_search( + m_available_ranges.span(), + range, + &nearby_index, + [](auto& a, auto& b) { return a.base().get() - b.end().get(); }); + + size_t inserted_index = 0; + if (existing_range) { + existing_range->m_size += range.size(); + inserted_index = nearby_index; + } else { + m_available_ranges.insert_before_matching( + Range(range), [&](auto& entry) { + return entry.base() >= range.end(); + }, + nearby_index, &inserted_index); + } + + if (inserted_index < (m_available_ranges.size() - 1)) { + // We already merged with previous. Try to merge with next. + auto& inserted_range = m_available_ranges[inserted_index]; + auto& next_range = m_available_ranges[inserted_index + 1]; + if (inserted_range.end() == next_range.base()) { + inserted_range.m_size += next_range.size(); + m_available_ranges.remove(inserted_index + 1); + return; + } + } +} + +} diff --git a/Userland/DevTools/UserspaceEmulator/RangeAllocator.h b/Userland/DevTools/UserspaceEmulator/RangeAllocator.h new file mode 100644 index 0000000000..5619dc52d9 --- /dev/null +++ b/Userland/DevTools/UserspaceEmulator/RangeAllocator.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "Range.h" +#include <AK/Vector.h> + +namespace UserspaceEmulator { + +class RangeAllocator { +public: + RangeAllocator(); + ~RangeAllocator(); + + void initialize_with_range(VirtualAddress, size_t); + + Optional<Range> allocate_anywhere(size_t, size_t alignment = PAGE_SIZE); + Optional<Range> allocate_specific(VirtualAddress, size_t); + Optional<Range> allocate_randomized(size_t, size_t alignment); + void deallocate(const Range&); + + void dump() const; + + bool contains(const Range& range) const { return m_total_range.contains(range); } + +private: + void carve_at_index(int, const Range&); + + Vector<Range> m_available_ranges; + Range m_total_range; +}; + +} diff --git a/Userland/DevTools/UserspaceEmulator/Region.cpp b/Userland/DevTools/UserspaceEmulator/Region.cpp index c5f989c802..54c145a2a7 100644 --- a/Userland/DevTools/UserspaceEmulator/Region.cpp +++ b/Userland/DevTools/UserspaceEmulator/Region.cpp @@ -31,8 +31,7 @@ namespace UserspaceEmulator { Region::Region(u32 base, u32 size) : m_emulator(Emulator::the()) - , m_base(base) - , m_size(size) + , m_range(Range { VirtualAddress { base }, size }) { } diff --git a/Userland/DevTools/UserspaceEmulator/Region.h b/Userland/DevTools/UserspaceEmulator/Region.h index ffb15cf941..589f7b77a7 100644 --- a/Userland/DevTools/UserspaceEmulator/Region.h +++ b/Userland/DevTools/UserspaceEmulator/Region.h @@ -26,6 +26,7 @@ #pragma once +#include "Range.h" #include "ValueWithShadow.h" #include <AK/TypeCasts.h> #include <AK/Types.h> @@ -38,9 +39,11 @@ class Region { public: virtual ~Region() { } - u32 base() const { return m_base; } - u32 size() const { return m_size; } - u32 end() const { return m_base + m_size; } + const Range& range() const { return m_range; } + + u32 base() const { return m_range.base().get(); } + u32 size() const { return m_range.size(); } + u32 end() const { return m_range.end().get(); } bool contains(u32 address) const { return address >= base() && address < end(); } @@ -82,8 +85,7 @@ protected: private: Emulator& m_emulator; - u32 m_base { 0 }; - u32 m_size { 0 }; + Range m_range; bool m_stack { false }; bool m_text { false }; |