#include "Common/ArgumentLoader.h" #include "Common/EnvironmentLoader.h" #include "CommonCore/HostFactory.h" #include "HarnessHelpers.h" #include "Tests/LinuxSyscalls/Syscalls.h" #include "Tests/LinuxSyscalls/SignalDelegator.h" #include #include #include #include #include #include #include #include #include #include #include #include #include void MsgHandler(LogMan::DebugLevels Level, char const *Message) { const char *CharLevel{nullptr}; switch (Level) { case LogMan::NONE: CharLevel = "NONE"; break; case LogMan::ASSERT: CharLevel = "ASSERT"; break; case LogMan::ERROR: CharLevel = "ERROR"; break; case LogMan::DEBUG: CharLevel = "DEBUG"; break; case LogMan::INFO: CharLevel = "Info"; break; default: CharLevel = "???"; break; } printf("[%s] %s\n", CharLevel, Message); } void AssertHandler(char const *Message) { printf("[ASSERT] %s\n", Message); } int main(int argc, char **argv, char **const envp) { LogMan::Throw::InstallHandler(AssertHandler); LogMan::Msg::InstallHandler(MsgHandler); FEXCore::Config::Initialize(); FEXCore::Config::AddLayer(std::make_unique(argc, argv)); FEXCore::Config::AddLayer(std::make_unique(envp)); FEXCore::Config::Load(); FEXCore::Config::Value CoreConfig{FEXCore::Config::CONFIG_DEFAULTCORE, 0}; FEXCore::Config::Value BlockSizeConfig{FEXCore::Config::CONFIG_MAXBLOCKINST, 1}; FEXCore::Config::Value SingleStepConfig{FEXCore::Config::CONFIG_SINGLESTEP, false}; FEXCore::Config::Value MultiblockConfig{FEXCore::Config::CONFIG_MULTIBLOCK, false}; FEXCore::Config::Value GdbServerConfig{FEXCore::Config::CONFIG_GDBSERVER, false}; FEXCore::Config::Value ThreadsConfig{FEXCore::Config::CONFIG_EMULATED_CPU_CORES, 1}; FEXCore::Config::Value LDPath{FEXCore::Config::CONFIG_ROOTFSPATH, ""}; FEXCore::Config::Value ThunkLibsPath{FEXCore::Config::CONFIG_THUNKLIBSPATH, ""}; FEXCore::Config::Value SilentLog{FEXCore::Config::CONFIG_SILENTLOGS, false}; FEXCore::Config::Value Environment{FEXCore::Config::CONFIG_ENVIRONMENT, ""}; FEXCore::Config::Value OutputLog{FEXCore::Config::CONFIG_OUTPUTLOG, "stderr"}; FEXCore::Config::Value DumpIR{FEXCore::Config::CONFIG_DUMPIR, "no"}; FEXCore::Config::Value TSOEnabledConfig{FEXCore::Config::CONFIG_TSO_ENABLED, true}; FEXCore::Config::Value SMCChecksConfig{FEXCore::Config::CONFIG_SMC_CHECKS, FEXCore::Config::CONFIG_SMC_MMAN}; FEXCore::Config::Value ABILocalFlags{FEXCore::Config::CONFIG_ABI_LOCAL_FLAGS, false}; FEXCore::Config::Value AbiNoPF{FEXCore::Config::CONFIG_ABI_NO_PF, false}; auto Args = FEX::ArgLoader::Get(); LogMan::Throw::A(Args.size() > 1, "Not enough arguments"); FEX::HarnessHelper::HarnessCodeLoader Loader{Args[0], Args[1].c_str()}; FEXCore::Context::InitializeStaticTables(Loader.Is64BitMode() ? FEXCore::Context::MODE_64BIT : FEXCore::Context::MODE_32BIT); auto CTX = FEXCore::Context::CreateNewContext(); FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_DEFAULTCORE, CoreConfig()); FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_MULTIBLOCK, MultiblockConfig()); FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_SINGLESTEP, SingleStepConfig()); FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_MAXBLOCKINST, BlockSizeConfig()); FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_IS64BIT_MODE, Loader.Is64BitMode()); FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_TSO_ENABLED, TSOEnabledConfig()); FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_SMC_CHECKS, SMCChecksConfig()); FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_ABI_LOCAL_FLAGS, ABILocalFlags()); FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_ABI_NO_PF, AbiNoPF()); FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_DUMPIR, DumpIR()); FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_VALIDATE_IR_PARSER, true); FEXCore::Context::SetCustomCPUBackendFactory(CTX, HostFactory::CPUCreationFactory); FEXCore::Context::InitializeContext(CTX); FEXCore::Config::Set(FEXCore::Config::CONFIG_IS64BIT_MODE, Loader.Is64BitMode() ? "1" : "0"); std::unique_ptr SignalDelegation = std::make_unique(); std::unique_ptr SyscallHandler{ FEX::HLE::CreateHandler( Loader.Is64BitMode() ? FEXCore::Context::OperatingMode::MODE_64BIT : FEXCore::Context::OperatingMode::MODE_32BIT, CTX, SignalDelegation.get(), &Loader)}; bool DidFault = false; SignalDelegation->RegisterFrontendHostSignalHandler(SIGSEGV, [&DidFault](FEXCore::Core::InternalThreadState *Thread, int Signal, void *info, void *ucontext) { DidFault = true; return false; }); FEXCore::Context::SetSignalDelegator(CTX, SignalDelegation.get()); FEXCore::Context::SetSyscallHandler(CTX, SyscallHandler.get()); bool Result1 = FEXCore::Context::InitCore(CTX, &Loader); if (!Result1) return 1; FEXCore::Context::RunUntilExit(CTX); // Just re-use compare state. It also checks against the expected values in config. FEXCore::Core::CPUState State; FEXCore::Context::GetCPUState(CTX, &State); bool Passed = !DidFault && Loader.CompareStates(&State, nullptr); LogMan::Msg::I("Faulted? %s", DidFault ? "Yes" : "No"); LogMan::Msg::I("Passed? %s", Passed ? "Yes" : "No"); FEXCore::Context::DestroyContext(CTX); return Passed ? 0 : -1; }