Merge pull request #710 from Sonicadvance1/brk_improvements

More improvements to BRK handling
This commit is contained in:
Ryan Houdek authored and GitHub committed 2021-01-27 10:49:07 -08:00
commit 2d8b70bbd5
7 files changed
+96 -20

No files matched your search

+12
View File
@@ -1,3 +1,4 @@
#include <FEXCore/Utils/Common/MathUtils.h>
#include <FEXCore/Utils/ELFLoader.h>
#include <FEXCore/Utils/LogManager.h>
#include <cstring>
@@ -201,6 +202,9 @@ bool ELFContainer::LoadELF_32() {
DynamicProgram = Header._32.e_type != ET_EXEC;
// Default BRK size
BRKSize = 4096;
return true;
}
@@ -239,6 +243,9 @@ bool ELFContainer::LoadELF_64() {
DynamicProgram = Header._64.e_type != ET_EXEC;
// Default BRK size
BRKSize = 0x1000'0000;
return true;
}
@@ -330,6 +337,11 @@ void ELFContainer::CalculateMemoryLayouts() {
}
}
// Calculate BRK
MaxPhysAddr = AlignUp(MaxPhysAddr, 4096);
BRKBase = MaxPhysAddr;
MaxPhysAddr += BRKSize;
PhysMemSize = MaxPhysAddr - MinPhysAddr;
MinPhysicalMemoryLocation = MinPhysAddr;
+20
View File
@@ -40,6 +40,15 @@ public:
PhysicalMemorySize);
}
struct BRKInfo {
uint64_t Base;
uint64_t Size;
};
BRKInfo GetBRKInfo() const {
return {BRKBase, BRKSize};
}
// Data, Physical, Size
using MemoryWriter = std::function<void(void *, uint64_t, uint64_t)>;
void WriteLoadableSections(MemoryWriter Writer, uint64_t Offset = 0);
@@ -67,6 +76,14 @@ public:
void GetInitLocations(uint64_t GuestELFBase, std::vector<uint64_t> *Locations);
bool HasTLS() const { return TLSHeader._64 != nullptr; }
uint64_t GetTLSBase() const {
if (GetMode() == ELFMode::MODE_64BIT) {
return TLSHeader._64->p_vaddr;
}
else {
return TLSHeader._32->p_vaddr;
}
}
enum ELFMode {
MODE_32BIT,
@@ -122,6 +139,9 @@ private:
uint64_t MinPhysicalMemoryLocation{0};
uint64_t MaxPhysicalMemoryLocation{0};
uint64_t PhysicalMemorySize{0};
uint64_t BRKBase{};
uint64_t BRKSize{};
ProgramHeader InterpreterHeader{};
bool DynamicProgram{false};
std::string DynamicLinker;
+2 -1
View File
@@ -207,7 +207,6 @@ int main(int argc, char **argv, char **const envp) {
FEXCore::Config::Value<bool> ABILocalFlags{FEXCore::Config::CONFIG_ABI_LOCAL_FLAGS, false};
FEXCore::Config::Value<bool> AbiNoPF{FEXCore::Config::CONFIG_ABI_NO_PF, false};
::SilentLog = SilentLog();
if (!::SilentLog) {
@@ -269,6 +268,8 @@ int main(int argc, char **argv, char **const envp) {
CTX,
SignalDelegation.get(),
&Loader)};
auto BRKInfo = Loader.GetBRKInfo();
SyscallHandler->DefaultProgramBreak(BRKInfo.Base, BRKInfo.Size);
FEXCore::Context::SetSignalDelegator(CTX, SignalDelegation.get());
FEXCore::Context::SetSyscallHandler(CTX, SyscallHandler.get());
+11 -4
View File
@@ -495,13 +495,13 @@ public:
//AuxVariables.emplace_back(auxv_t{24, ~0ULL}); // AT_PLATFORM
// On x86 only allows userspace to check for monitor and fs/gs base writing in CPL3
//AuxVariables.emplace_back(auxv_t{26, 0}); // AT_HWCAP2
AuxVariables.emplace_back(auxv_t{32, 0ULL}); // sysinfo (vDSO)
AuxVariables.emplace_back(auxv_t{33, 0ULL}); // sysinfo (vDSO)
AuxVariables.emplace_back(auxv_t{32, 0}); // AT_SYSINFO - Entry point to syscall
AuxVariables.emplace_back(auxv_t{33, 0}); // AT_SYSINFO_EHDR - Address of the start of VDSO
}
else {
AuxVariables.emplace_back(auxv_t{4, 0x20}); // AT_PHENT
AuxVariables.emplace_back(auxv_t{32, 0ULL}); // sysinfo (vDSO)
AuxVariables.emplace_back(auxv_t{33, 0ULL}); // sysinfo (vDSO)
AuxVariables.emplace_back(auxv_t{32, 0}); // AT_SYSINFO - Entry point to syscall
AuxVariables.emplace_back(auxv_t{33, 0}); // AT_SYSINFO_EHDR - Address of the start of VDSO
}
AuxVariables.emplace_back(auxv_t{3, DB.GetElfBase()}); // Program header
@@ -733,9 +733,16 @@ public:
bool Is64BitMode() const { return File.GetMode() == ::ELFLoader::ELFContainer::MODE_64BIT; }
::ELFLoader::ELFContainer::BRKInfo GetBRKInfo() const {
auto Info = File.GetBRKInfo();
Info.Base += DB.GetElfBase();
return Info;
}
private:
::ELFLoader::ELFContainer File;
::ELFLoader::ELFSymbolDatabase DB;
std::vector<std::string> Args;
std::vector<std::string> EnvironmentVariables;
std::vector<char const*> LoaderArgs;
+47 -12
View File
@@ -20,18 +20,13 @@
#include <sys/syscall.h>
#include <unistd.h>
#define BRK_SIZE 0x1000'0000
namespace FEX::HLE {
SyscallHandler *_SyscallHandler{};
uint64_t SyscallHandler::HandleBRK(FEXCore::Core::InternalThreadState *Thread, void *Addr) {
std::lock_guard<std::mutex> lk(MMapMutex);
uint64_t Result;
if (DataSpace == 0) {
DefaultProgramBreak(Thread);
}
uint64_t Result;
if (Addr == nullptr) { // Just wants to get the location of the program break atm
Result = DataSpace + DataSpaceSize;
@@ -46,10 +41,45 @@ uint64_t SyscallHandler::HandleBRK(FEXCore::Core::InternalThreadState *Thread, v
}
else {
uint64_t NewSize = NewEnd - DataSpace;
uint64_t NewSizeAligned = AlignUp(NewSize, 4096);
// make sure we don't overflow to TLS storage
if (NewSize >= BRK_SIZE)
return -ENOMEM;
if (NewSizeAligned < DataSpaceMaxSize) {
// If we are shrinking the brk then munmap the ranges
// That way we gain the memory back and also give the application zero pages if it allocates again
// DataspaceMaxSize is always page aligned
uint64_t RemainingSize = DataSpaceMaxSize - NewSizeAligned;
// We have pages we can unmap
munmap(reinterpret_cast<void*>(DataSpace + NewSizeAligned), RemainingSize);
DataSpaceMaxSize = NewSizeAligned;
}
else if (NewSize > DataSpaceMaxSize) {
constexpr static uint64_t SizeAlignment = 8 * 1024 * 1024;
uint64_t AllocateNewSize = AlignUp(NewSize, SizeAlignment) - DataSpaceMaxSize;
if (!Is64BitMode() &&
(DataSpace + DataSpaceMaxSize + AllocateNewSize > 0x1'0000'0000ULL)) {
// If we are 32bit and we tried going about the 32bit limit then out of memory
return DataSpace + DataSpaceSize;
}
uint64_t NewBRK = (uint64_t)mmap((void*)(DataSpace + DataSpaceMaxSize), AllocateNewSize, PROT_READ | PROT_WRITE, MAP_FIXED_NOREPLACE | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (NewBRK != (DataSpace + DataSpaceMaxSize)) {
// Couldn't allocate that the region we wanted
// Can happen if MAP_FIXED_NOREPLACE isn't understood by the kernel
munmap(reinterpret_cast<void*>(NewBRK), AllocateNewSize);
NewBRK = ~0ULL;
}
if (NewBRK == ~0ULL) {
// If we couldn't allocate a new region then out of memory
return DataSpace + DataSpaceSize;
}
else {
// Increase our BRK size
DataSpaceMaxSize += AllocateNewSize;
}
}
DataSpaceSize = NewSize;
}
@@ -58,9 +88,10 @@ uint64_t SyscallHandler::HandleBRK(FEXCore::Core::InternalThreadState *Thread, v
return Result;
}
void SyscallHandler::DefaultProgramBreak(FEXCore::Core::InternalThreadState *Thread) {
DataSpaceSize = 0;
DataSpace = (uint64_t)mmap(nullptr, BRK_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
void SyscallHandler::DefaultProgramBreak(uint64_t Base, uint64_t Size) {
DataSpace = Base;
DataSpaceMaxSize = Size;
DataSpaceStartingSize = Size;
}
SyscallHandler::SyscallHandler(FEXCore::Context::Context *ctx, FEX::HLE::SignalDelegator *_SignalDelegation)
@@ -70,6 +101,10 @@ SyscallHandler::SyscallHandler(FEXCore::Context::Context *ctx, FEX::HLE::SignalD
HostKernelVersion = CalculateHostKernelVersion();
}
SyscallHandler::~SyscallHandler() {
munmap(reinterpret_cast<void*>(DataSpace + DataSpaceStartingSize), DataSpaceMaxSize - DataSpaceStartingSize);
}
uint32_t SyscallHandler::CalculateHostKernelVersion() {
struct utsname buf{};
if (uname(&buf) == -1) {
+4 -2
View File
@@ -47,12 +47,12 @@ namespace FEX::HLE {
class SyscallHandler : public FEXCore::HLE::SyscallHandler {
public:
SyscallHandler(FEXCore::Context::Context *ctx, FEX::HLE::SignalDelegator *_SignalDelegation);
virtual ~SyscallHandler() = default;
virtual ~SyscallHandler();
// In the case that the syscall doesn't hit the optimized path then we still need to go here
uint64_t HandleSyscall(FEXCore::Core::InternalThreadState *Thread, FEXCore::HLE::SyscallArguments *Args) final override;
void DefaultProgramBreak(FEXCore::Core::InternalThreadState *Thread);
void DefaultProgramBreak(uint64_t Base, uint64_t Size);
using SyscallPtrArg0 = uint64_t(*)(FEXCore::Core::InternalThreadState *Thread);
using SyscallPtrArg1 = uint64_t(*)(FEXCore::Core::InternalThreadState *Thread, uint64_t);
@@ -116,6 +116,8 @@ protected:
// BRK management
uint64_t DataSpace {};
uint64_t DataSpaceSize {};
uint64_t DataSpaceMaxSize {};
uint64_t DataSpaceStartingSize{};
// (Major << 24) | (Minor << 16) | Patch
uint32_t HostKernelVersion{};
-1
View File
@@ -68,7 +68,6 @@ aio_test
alarm_test
arch_prctl_test
bad_test
brk_test
chmod_test
chown_test
clock_nanosleep_test