Loader : Collect actually reserved ranges during range-verification (in the emulation DLL, not during reservation in the loader)

This commit is contained in:
PatrickvL 2019-02-07 10:56:38 +01:00 committed by RadWolfie
parent 39a9bd451f
commit c42aff2307
3 changed files with 63 additions and 68 deletions

View File

@ -36,19 +36,6 @@
#include "AddressRanges.h"
#ifdef DEBUG
// This array keeps track of which ranges have successfully been reserved.
// Having this helps debugging, but isn't strictly necessary, as we could
// retrieve the same information using VirtualQuery.
struct {
int Index;
unsigned __int32 Start;
int Size;
} ReservedRanges[128];
int ReservedRangeCount = 0;
#endif // DEBUG
// Reserve an address range up to the extend of what the host allows.
bool ReserveMemoryRange(int index)
{
@ -64,16 +51,6 @@ bool ReserveMemoryRange(int index)
HadAnyFailure = true;
}
#ifdef DEBUG
// Safeguard against bounds overflow
if (ReservedRangeCount < ARRAY_SIZE(ReservedRanges)) {
// Initialize the reservation of a new range
ReservedRanges[ReservedRangeCount].Index = index;
ReservedRanges[ReservedRangeCount].Start = Start;
ReservedRanges[ReservedRangeCount].Size = 0;
}
#endif // DEBUG
// Reserve this range in 64 Kb block increments, so that during emulation
// our memory-management code can VirtualFree() each block individually :
bool HadFailure = HadAnyFailure;
@ -85,44 +62,12 @@ bool ReserveMemoryRange(int index)
HadFailure = true;
HadAnyFailure = true;
}
#ifdef DEBUG
else {
// Safeguard against bounds overflow
if (ReservedRangeCount < ARRAY_SIZE(ReservedRanges)) {
if (HadFailure) {
HadFailure = false;
// Starting a new range - did the previous one have any size?
if (ReservedRanges[ReservedRangeCount].Size > 0) {
// Then start a new range, and copy over the current type
ReservedRangeCount++;
ReservedRanges[ReservedRangeCount].Index = index;
}
// Register a new ranges starting address
ReservedRanges[ReservedRangeCount].Start = Start;
}
// Accumulate the size of each successfull reservation
ReservedRanges[ReservedRangeCount].Size += BlockSize;
}
}
#endif // DEBUG
// Handle the next block
Start += BLOCK_SIZE;
Size -= BLOCK_SIZE;
}
#ifdef DEBUG
// Safeguard against bounds overflow
if (ReservedRangeCount < ARRAY_SIZE(ReservedRanges)) {
// Keep the current block only if it contains a successfully reserved range
if (ReservedRanges[ReservedRangeCount].Size > 0) {
ReservedRangeCount++;
}
}
#endif // DEBUG
// Only a complete success when the entire request was reserved in a single range
// (Otherwise, we have either a complete failure, or reserved it partially over multiple ranges)
return !HadAnyFailure;

View File

@ -36,10 +36,20 @@
#include "AddressRanges.h"
// This array keeps track of which ranges have successfully been reserved.
struct {
int RangeIndex; // = index into XboxAddressRanges[]
uint32_t Start;
int Size;
} ReservedRanges[128];
int ReservedRangeCount = 0;
bool VerifyAddressRange(int index)
{
unsigned __int32 BaseAddress = XboxAddressRanges[index].Start;
uint32_t BaseAddress = XboxAddressRanges[index].Start;
int Size = XboxAddressRanges[index].Size;
bool HadAnyFailure = false;
if (BaseAddress == 0) {
// The zero page (the entire first 64 KB block) can't be verified
@ -48,8 +58,17 @@ bool VerifyAddressRange(int index)
Size -= BLOCK_SIZE;
}
// Safeguard against bounds overflow
if (ReservedRangeCount < ARRAY_SIZE(ReservedRanges)) {
// Initialize the reservation of a new range
ReservedRanges[ReservedRangeCount].RangeIndex = index;
ReservedRanges[ReservedRangeCount].Start = BaseAddress;
ReservedRanges[ReservedRangeCount].Size = 0;
}
// Verify this range in 64 Kb block increments, as they are supposed
// to have been reserved like that too:
bool HadFailure = HadAnyFailure;
const DWORD AllocationProtect = (XboxAddressRanges[index].Start == 0) ? PAGE_EXECUTE_WRITECOPY : XboxAddressRanges[index].InitialMemoryProtection;
MEMORY_BASIC_INFORMATION mbi;
while (Size > 0) {
@ -63,6 +82,8 @@ bool VerifyAddressRange(int index)
// Allowed deviations
if (XboxAddressRanges[index].Start == 0) {
AllocationBase = (PVOID)0x10000;
State = MEM_COMMIT;
Type = MEM_IMAGE;
// TODO : Either update below to current section layout, or reduce the number of sections
// (by merging them, preferrably into a single section if possible).
// (Note, that merging sections would make the loader smaller, so that's preferrable.)
@ -84,14 +105,10 @@ bool VerifyAddressRange(int index)
Protect = PAGE_READONLY;
break;
case 0x24000: // section .idata
RegionSize = 0x0999b000; // == ? - ?
RegionSize = 0x0999a000; // == ? - ?
Protect = PAGE_READWRITE;
break;
}
State = MEM_COMMIT;
Type = MEM_IMAGE;
break;
}
}
// Verify each block
@ -111,16 +128,46 @@ bool VerifyAddressRange(int index)
if (Okay)
Okay = (mbi.Type == Type);
if (!Okay)
if (!IsOptionalAddressRange(index))
return false;
if (!Okay) {
HadFailure = true;
if (!IsOptionalAddressRange(index)) {
HadAnyFailure = true;
}
} else {
// Safeguard against bounds overflow
if (ReservedRangeCount < ARRAY_SIZE(ReservedRanges)) {
if (HadFailure) {
HadFailure = false;
// Starting a new range - did the previous one have any size?
if (ReservedRanges[ReservedRangeCount].Size > 0) {
// Then start a new range, and copy over the current type
ReservedRangeCount++;
ReservedRanges[ReservedRangeCount].RangeIndex = index;
}
// Register a new ranges starting address
ReservedRanges[ReservedRangeCount].Start = BaseAddress;
}
// Accumulate the size of each successfull reservation
ReservedRanges[ReservedRangeCount].Size += RegionSize;
}
}
// Handle the next region
BaseAddress += RegionSize;
Size -= RegionSize;
}
return true;
// Safeguard against bounds overflow
if (ReservedRangeCount < ARRAY_SIZE(ReservedRanges)) {
// Keep the current block only if it contains a successfully reserved range
if (ReservedRanges[ReservedRangeCount].Size > 0) {
ReservedRangeCount++;
}
}
return !HadAnyFailure;
}
bool VerifyAddressRanges(const int system)
@ -143,7 +190,7 @@ bool VerifyAddressRanges(const int system)
void UnreserveMemoryRange(const int index)
{
unsigned __int32 Start = XboxAddressRanges[index].Start;
uint32_t Start = XboxAddressRanges[index].Start;
int Size = XboxAddressRanges[index].Size;
while (Size > 0) {
@ -155,7 +202,7 @@ void UnreserveMemoryRange(const int index)
bool AllocateMemoryRange(const int index)
{
unsigned __int32 Start = XboxAddressRanges[index].Start;
uint32_t Start = XboxAddressRanges[index].Start;
int Size = XboxAddressRanges[index].Size;
while (Size > 0) {

View File

@ -35,6 +35,9 @@
// ******************************************************************
#pragma once
// TODO : extern ReservedRanges[];
extern int ReservedRangeCount;
extern bool VerifyAddressRanges(const int system);
extern void UnreserveMemoryRange(const int index);
extern bool AllocateMemoryRange(const int index);