Merge pull request #1621 from TheAggie/fix/libc-heap-32-byte-alignment
fix(libc): align guest heap allocations to 32 bytes
This commit is contained in:
commit
e6f9348b31
|
|
@ -24,7 +24,8 @@ namespace {
|
|||
|
||||
// Each block is preceded by a header holding the raw block address and its size in bytes.
|
||||
constexpr std::size_t HeaderBytes = 2 * sizeof(void*);
|
||||
constexpr std::size_t MinimumAlignment = 16;
|
||||
constexpr std::size_t RawAlignment = 16;
|
||||
constexpr std::size_t MinimumAlignment = 32;
|
||||
constexpr std::size_t PageBytes = 0x4000;
|
||||
constexpr std::size_t SpanBytes = 1u << 20;
|
||||
constexpr std::size_t MaximumSmallBytes = 64u * 1024u;
|
||||
|
|
@ -200,7 +201,7 @@ void rawFree(void* raw, std::size_t blockBytes) {
|
|||
void* allocate(GuestAllocations::Mutation& mutation, std::size_t alignment, std::size_t bytes) {
|
||||
if (alignment == 0 || (alignment & (alignment - 1)) != 0) throw std::invalid_argument("invalid guest heap alignment");
|
||||
alignment = std::max(alignment, MinimumAlignment);
|
||||
const std::size_t padding = alignment > MinimumAlignment ? alignment : 0;
|
||||
const std::size_t padding = alignment > RawAlignment ? alignment : 0;
|
||||
if (bytes > std::numeric_limits<std::size_t>::max() - HeaderBytes - padding) throw std::length_error("guest heap allocation overflow");
|
||||
std::size_t blockBytes = 0;
|
||||
void* raw = rawAllocate(bytes + HeaderBytes + padding, blockBytes);
|
||||
|
|
|
|||
|
|
@ -664,6 +664,24 @@ static void CheckSharedDirectMemoryLifecycle() {
|
|||
Require(sceKernelReleaseDirectMemory(phys, page * 3) == 0);
|
||||
}
|
||||
|
||||
static void CheckHeapAlignment() {
|
||||
std::vector<std::pair<unsigned char*, std::size_t>> blocks;
|
||||
for (std::size_t bytes = 1; bytes <= 600; ++bytes) blocks.emplace_back(static_cast<unsigned char*>(GuestHeap::GuestHeapAllocate_nid_postfix(bytes)), bytes);
|
||||
for (const std::size_t bytes : {std::size_t{4000}, std::size_t{70000}, std::size_t{0x30000}}) blocks.emplace_back(static_cast<unsigned char*>(GuestHeap::GuestHeapAllocate_nid_postfix(bytes)), bytes);
|
||||
auto* grown = static_cast<unsigned char*>(GuestHeap::GuestHeapReallocate_nid_postfix(GuestHeap::GuestHeapAllocate_nid_postfix(8), 333));
|
||||
blocks.emplace_back(grown, 333);
|
||||
for (std::size_t index = 0; index < blocks.size(); ++index) {
|
||||
const auto [pointer, bytes] = blocks[index];
|
||||
Require((reinterpret_cast<std::uintptr_t>(pointer) & 31u) == 0);
|
||||
std::memset(pointer, static_cast<int>(index & 0xffu), bytes);
|
||||
}
|
||||
for (std::size_t index = 0; index < blocks.size(); ++index) {
|
||||
const auto [pointer, bytes] = blocks[index];
|
||||
for (std::size_t at = 0; at < bytes; ++at) Require(pointer[at] == static_cast<unsigned char>(index & 0xffu));
|
||||
GuestHeap::GuestHeapFree_nid_postfix(pointer);
|
||||
}
|
||||
}
|
||||
|
||||
static void CheckHeapAfterMappingReuse() {
|
||||
constexpr std::size_t bytes = 0x30000;
|
||||
auto* pointer = static_cast<unsigned char*>(GuestHeap::GuestHeapAllocate_nid_postfix(bytes));
|
||||
|
|
@ -1080,6 +1098,7 @@ int main() {
|
|||
CheckSharedDirectMemoryLifecycle();
|
||||
CheckGetDirectMemoryType();
|
||||
CheckMtypeprotect();
|
||||
CheckHeapAlignment();
|
||||
CheckHeapAfterMappingReuse();
|
||||
#ifdef _WIN32
|
||||
CheckNoOverwriteRejectsHostOccupiedMapping();
|
||||
|
|
|
|||
Loading…
Reference in New Issue