diff --git a/appveyor.yml b/appveyor.yml index 9ecea4e..6d2585a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 0.1.2.build-{build} +version: 0.1.3.build-{build} image: Visual Studio 2019 environment: matrix: diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index e863571..af71697 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -82,7 +82,7 @@ if (KYTY_LINKER STREQUAL LD) set(KYTY_LD_OPTIONS "-Wl,--image-base=0x100000000000") endif() -project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.1.2) +project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.1.3) include(src_script.cmake) diff --git a/source/emulator/include/Emulator/Kernel/Memory.h b/source/emulator/include/Emulator/Kernel/Memory.h index 31b807e..7e192cf 100644 --- a/source/emulator/include/Emulator/Kernel/Memory.h +++ b/source/emulator/include/Emulator/Kernel/Memory.h @@ -13,6 +13,7 @@ namespace Kyty::Libs::LibKernel::Memory { KYTY_SUBSYSTEM_DEFINE(Memory); int KYTY_SYSV_ABI KernelMapNamedFlexibleMemory(void** addr_in_out, size_t len, int prot, int flags, const char* name); +int KYTY_SYSV_ABI KernelMapFlexibleMemory(void** addr_in_out, size_t len, int prot, int flags); int KYTY_SYSV_ABI KernelMunmap(uint64_t vaddr, size_t len); size_t KYTY_SYSV_ABI KernelGetDirectMemorySize(); int KYTY_SYSV_ABI KernelAllocateDirectMemory(int64_t search_start, int64_t search_end, size_t len, size_t alignment, int memory_type, @@ -21,6 +22,7 @@ int KYTY_SYSV_ABI KernelReleaseDirectMemory(int64_t start, size_t len); int KYTY_SYSV_ABI KernelMapDirectMemory(void** addr, size_t len, int prot, int flags, int64_t direct_memory_start, size_t alignment); int KYTY_SYSV_ABI KernelQueryMemoryProtection(void* addr, void** start, void** end, int* prot); int KYTY_SYSV_ABI KernelDirectMemoryQuery(int64_t offset, int flags, void* info, size_t info_size); +int KYTY_SYSV_ABI KernelAvailableFlexibleMemorySize(size_t* size); } // namespace Kyty::Libs::LibKernel::Memory diff --git a/source/emulator/include/Emulator/Kernel/Pthread.h b/source/emulator/include/Emulator/Kernel/Pthread.h index 9dde74c..d9db63f 100644 --- a/source/emulator/include/Emulator/Kernel/Pthread.h +++ b/source/emulator/include/Emulator/Kernel/Pthread.h @@ -177,6 +177,9 @@ int KYTY_SYSV_ABI pthread_setspecific(LibKernel::PthreadKey key, void* value); void* KYTY_SYSV_ABI pthread_getspecific(LibKernel::PthreadKey key); int KYTY_SYSV_ABI pthread_mutex_destroy(LibKernel::PthreadMutex* mutex); int KYTY_SYSV_ABI pthread_mutex_init(LibKernel::PthreadMutex* mutex, const LibKernel::PthreadMutexattr* attr); +int KYTY_SYSV_ABI pthread_mutexattr_init(LibKernel::PthreadMutexattr* attr); +int KYTY_SYSV_ABI pthread_mutexattr_settype(LibKernel::PthreadMutexattr* attr, int type); +int KYTY_SYSV_ABI pthread_mutexattr_destroy(LibKernel::PthreadMutexattr* attr); } // namespace Posix diff --git a/source/emulator/src/Kernel/Memory.cpp b/source/emulator/src/Kernel/Memory.cpp index a9fd5aa..d6d4ef1 100644 --- a/source/emulator/src/Kernel/Memory.cpp +++ b/source/emulator/src/Kernel/Memory.cpp @@ -74,12 +74,16 @@ public: KYTY_CLASS_NO_COPY(FlexibleMemory); + static uint64_t Size() { return static_cast(448) * 1024 * 1024; } + uint64_t Available(); + bool Map(uint64_t vaddr, size_t len, int prot, VirtualMemory::Mode mode, Graphics::GpuMemoryMode gpu_mode); bool Unmap(uint64_t vaddr, uint64_t size, Graphics::GpuMemoryMode* gpu_mode); bool Find(uint64_t vaddr, uint64_t* base_addr, size_t* len, int* prot, VirtualMemory::Mode* mode, Graphics::GpuMemoryMode* gpu_mode); private: Vector m_allocated; + uint64_t m_allocated_total = 0; Core::Mutex m_mutex; }; @@ -311,6 +315,7 @@ bool FlexibleMemory::Map(uint64_t vaddr, size_t len, int prot, VirtualMemory::Mo b.gpu_mode = gpu_mode; m_allocated.Add(b); + m_allocated_total += len; return true; } @@ -329,6 +334,7 @@ bool FlexibleMemory::Unmap(uint64_t vaddr, uint64_t size, Graphics::GpuMemoryMod *gpu_mode = b.gpu_mode; m_allocated.RemoveAt(index); + m_allocated_total -= size; return true; } index++; @@ -374,6 +380,13 @@ bool FlexibleMemory::Find(uint64_t vaddr, uint64_t* base_addr, size_t* len, int* }); } +uint64_t FlexibleMemory::Available() +{ + Core::LockGuard lock(m_mutex); + + return Size() - m_allocated_total; +} + int32_t KYTY_SYSV_ABI KernelMapNamedFlexibleMemory(void** addr_in_out, size_t len, int prot, int flags, const char* name) { PRINT_NAME(); @@ -396,6 +409,11 @@ int32_t KYTY_SYSV_ABI KernelMapNamedFlexibleMemory(void** addr_in_out, size_t le case 5: mode = VirtualMemory::Mode::ExecuteRead; break; case 6: case 7: mode = VirtualMemory::Mode::ExecuteReadWrite; break; + case 0x32: + case 0x33: + mode = VirtualMemory::Mode::ReadWrite; + gpu_mode = Graphics::GpuMemoryMode::ReadWrite; + break; default: EXIT("unknown prot: %d\n", prot); } @@ -405,25 +423,36 @@ int32_t KYTY_SYSV_ABI KernelMapNamedFlexibleMemory(void** addr_in_out, size_t le if (!g_flexible_memory->Map(out_addr, len, prot, mode, gpu_mode)) { - printf(FG_RED "\t[Fail]\n" FG_DEFAULT); + printf(FG_RED "\t [Fail]\n" FG_DEFAULT); VirtualMemory::Free(out_addr); return KERNEL_ERROR_ENOMEM; } - printf("\tin_addr = 0x%016" PRIx64 "\n", in_addr); - printf("\tout_addr = 0x%016" PRIx64 "\n", out_addr); - printf("\tsize = %" PRIu64 "\n", len); - printf("\tmode = %s\n", Core::EnumName(mode).C_Str()); - printf("\tname = %s\n", name); + printf("\t in_addr = 0x%016" PRIx64 "\n", in_addr); + printf("\t out_addr = 0x%016" PRIx64 "\n", out_addr); + printf("\t size = %" PRIu64 "\n", len); + printf("\t mode = %s\n", Core::EnumName(mode).C_Str()); + printf("\t name = %s\n", name); + printf("\t gpu_mode = %s\n", Core::EnumName(gpu_mode).C_Str()); if (out_addr == 0) { return KERNEL_ERROR_ENOMEM; } + if (gpu_mode != Graphics::GpuMemoryMode::NoAccess) + { + Graphics::GpuMemorySetAllocatedRange(out_addr, len); + } + return OK; } +int KYTY_SYSV_ABI KernelMapFlexibleMemory(void** addr_in_out, size_t len, int prot, int flags) +{ + return KernelMapNamedFlexibleMemory(addr_in_out, len, prot, flags, ""); +} + int KYTY_SYSV_ABI KernelMunmap(uint64_t vaddr, size_t len) { PRINT_NAME(); @@ -688,6 +717,21 @@ int KYTY_SYSV_ABI KernelQueryMemoryProtection(void* addr, void** start, void** e return OK; } +int KYTY_SYSV_ABI KernelAvailableFlexibleMemorySize(size_t* size) +{ + PRINT_NAME(); + + EXIT_IF(g_flexible_memory == nullptr); + + EXIT_NOT_IMPLEMENTED(size == nullptr); + + *size = g_flexible_memory->Available(); + + printf("\t *size = 0x%016" PRIx64 "\n", *size); + + return OK; +} + } // namespace Kyty::Libs::LibKernel::Memory #endif // KYTY_EMU_ENABLED diff --git a/source/emulator/src/Kernel/Pthread.cpp b/source/emulator/src/Kernel/Pthread.cpp index 4febf64..b39b635 100644 --- a/source/emulator/src/Kernel/Pthread.cpp +++ b/source/emulator/src/Kernel/Pthread.cpp @@ -631,6 +631,8 @@ int KYTY_SYSV_ABI PthreadMutexattrInit(PthreadMutexattr* attr) { // PRINT_NAME(); + EXIT_NOT_IMPLEMENTED(attr == nullptr); + *attr = new PthreadMutexattrPrivate {}; int result = pthread_mutexattr_init(&(*attr)->p); @@ -669,6 +671,8 @@ int KYTY_SYSV_ABI PthreadMutexattrSettype(PthreadMutexattr* attr, int type) { // PRINT_NAME(); + EXIT_NOT_IMPLEMENTED(attr == nullptr || *attr == nullptr); + int ptype = PTHREAD_MUTEX_DEFAULT; switch (type) { @@ -693,6 +697,8 @@ int KYTY_SYSV_ABI PthreadMutexattrSetprotocol([[maybe_unused]] PthreadMutexattr* { // PRINT_NAME(); + EXIT_NOT_IMPLEMENTED(attr == nullptr || *attr == nullptr); + [[maybe_unused]] int pprotocol = PTHREAD_PRIO_NONE; switch (protocol) { @@ -2656,6 +2662,27 @@ int KYTY_SYSV_ABI pthread_mutex_init(LibKernel::PthreadMutex* mutex, const LibKe return POSIX_PTHREAD_CALL(LibKernel::PthreadMutexInit(mutex, attr, nullptr)); } +int KYTY_SYSV_ABI pthread_mutexattr_init(LibKernel::PthreadMutexattr* attr) +{ + PRINT_NAME(); + + return POSIX_PTHREAD_CALL(LibKernel::PthreadMutexattrInit(attr)); +} + +int KYTY_SYSV_ABI pthread_mutexattr_settype(LibKernel::PthreadMutexattr* attr, int type) +{ + PRINT_NAME(); + + return POSIX_PTHREAD_CALL(LibKernel::PthreadMutexattrSettype(attr, type)); +} + +int KYTY_SYSV_ABI pthread_mutexattr_destroy(LibKernel::PthreadMutexattr* attr) +{ + PRINT_NAME(); + + return POSIX_PTHREAD_CALL(LibKernel::PthreadMutexattrDestroy(attr)); +} + } // namespace Posix } // namespace Kyty::Libs diff --git a/source/emulator/src/Libs/LibKernel.cpp b/source/emulator/src/Libs/LibKernel.cpp index 5906459..652955d 100644 --- a/source/emulator/src/Libs/LibKernel.cpp +++ b/source/emulator/src/Libs/LibKernel.cpp @@ -417,6 +417,13 @@ int KYTY_SYSV_ABI clock_gettime(int clock_id, LibKernel::KernelTimespec* time) return POSIX_CALL(LibKernel::KernelClockGettime(clock_id, time)); } +void KYTY_SYSV_ABI KernelSetGPO(uint32_t bits) +{ + PRINT_NAME(); + + printf("\t bits = %08" PRIx32 "\n", bits); +} + } // namespace LibKernel namespace Posix { @@ -455,6 +462,9 @@ LIB_DEFINE(InitLibKernel_1_Posix) LIB_FUNC("7H0iTOciTLo", Posix::pthread_mutex_lock); LIB_FUNC("2Z+PpY6CaJg", Posix::pthread_mutex_unlock); LIB_FUNC("ttHNfU+qDBU", Posix::pthread_mutex_init); + LIB_FUNC("dQHWEsJtoE4", Posix::pthread_mutexattr_init); + LIB_FUNC("mDmgMOGVUqg", Posix::pthread_mutexattr_settype); + LIB_FUNC("HF7lK46xzjY", Posix::pthread_mutexattr_destroy); LIB_FUNC("ltCfaGr2JGE", Posix::pthread_mutex_destroy); LIB_FUNC("mkx2fVhNMsg", Posix::pthread_cond_broadcast); LIB_FUNC("Op8TBGY5KHg", Posix::pthread_cond_wait); @@ -492,6 +502,7 @@ LIB_DEFINE(InitLibKernel_1_FS) LIB_DEFINE(InitLibKernel_1_Mem) { LIB_FUNC("mL8NDH86iQI", Memory::KernelMapNamedFlexibleMemory); + LIB_FUNC("IWIBBdTHit4", Memory::KernelMapFlexibleMemory); LIB_FUNC("cQke9UuBQOk", Memory::KernelMunmap); LIB_FUNC("pO96TwzOm5E", Memory::KernelGetDirectMemorySize); LIB_FUNC("rTXw65xmLIA", Memory::KernelAllocateDirectMemory); @@ -499,6 +510,7 @@ LIB_DEFINE(InitLibKernel_1_Mem) LIB_FUNC("MBuItvba6z8", Memory::KernelReleaseDirectMemory); LIB_FUNC("WFcfL2lzido", Memory::KernelQueryMemoryProtection); LIB_FUNC("BHouLQzh0X0", Memory::KernelDirectMemoryQuery); + LIB_FUNC("aNz11fnnzi4", Memory::KernelAvailableFlexibleMemorySize); } LIB_DEFINE(InitLibKernel_1_Equeue) @@ -600,34 +612,34 @@ LIB_DEFINE(InitLibKernel_1) LIB_OBJECT("f7uOxY9mM1U", &LibKernel::g_stack_chk_guard); LIB_OBJECT("djxxOmW6-aw", &LibKernel::g_progname); - LIB_FUNC("Ou3iL1abvng", LibKernel::stack_chk_fail); - LIB_FUNC("wzvqT4UqKX8", LibKernel::KernelLoadStartModule); - LIB_FUNC("QKd0qM58Qes", LibKernel::KernelStopUnloadModule); - LIB_FUNC("vNe1w4diLCs", LibKernel::tls_get_addr); + LIB_FUNC("1jfXLRVzisc", LibKernel::KernelUsleep); + LIB_FUNC("6xVpy0Fdq+I", LibKernel::sigprocmask); + LIB_FUNC("6Z83sYWFlA8", LibKernel::exit); + LIB_FUNC("8OnWXlgQlvo", LibKernel::KernelRtldThreadAtexitDecrement); LIB_FUNC("959qrazPIrg", LibKernel::KernelGetProcParam); - LIB_FUNC("p5EcQeEeJAE", LibKernel::KernelRtldSetApplicationHeapAPI); - LIB_FUNC("FxVZqBAA7ks", LibKernel::write); + LIB_FUNC("9BcDykPmo1I", LibKernel::get_error_addr); + LIB_FUNC("bnZxYgAFeA0", LibKernel::KernelGetSanitizerNewReplaceExternal); + LIB_FUNC("ca7v6Cxulzs", LibKernel::KernelSetGPO); LIB_FUNC("DRuBt2pvICk", LibKernel::read); LIB_FUNC("f7KBOafysXo", LibKernel::KernelGetModuleInfoFromAddr); - LIB_FUNC("zE-wXIZjLoM", LibKernel::KernelDebugRaiseExceptionOnReleaseMode); - LIB_FUNC("OMDRKKAZ8I4", LibKernel::KernelDebugRaiseException); - LIB_FUNC("6Z83sYWFlA8", LibKernel::exit); - LIB_FUNC("py6L8jiVAN8", LibKernel::KernelGetSanitizerMallocReplaceExternal); - LIB_FUNC("bnZxYgAFeA0", LibKernel::KernelGetSanitizerNewReplaceExternal); LIB_FUNC("Fjc4-n1+y2g", LibKernel::elf_phdr_match_addr); + LIB_FUNC("FxVZqBAA7ks", LibKernel::write); LIB_FUNC("kbw4UHHSYy0", LibKernel::pthread_cxa_finalize); - LIB_FUNC("Xjoosiw+XPI", LibKernel::KernelUuidCreate); - LIB_FUNC("WslcK1FQcGI", LibKernel::KernelIsNeoMode); - LIB_FUNC("9BcDykPmo1I", LibKernel::get_error_addr); - LIB_FUNC("6xVpy0Fdq+I", LibKernel::sigprocmask); LIB_FUNC("lLMT9vJAck0", LibKernel::clock_gettime); - - LIB_FUNC("1jfXLRVzisc", LibKernel::KernelUsleep); - LIB_FUNC("rNhWz+lvOMU", LibKernel::KernelSetThreadDtors); - LIB_FUNC("WhCc1w3EhSI", LibKernel::KernelSetThreadAtexitReport); + LIB_FUNC("OMDRKKAZ8I4", LibKernel::KernelDebugRaiseException); + LIB_FUNC("Ou3iL1abvng", LibKernel::stack_chk_fail); + LIB_FUNC("p5EcQeEeJAE", LibKernel::KernelRtldSetApplicationHeapAPI); LIB_FUNC("pB-yGZ2nQ9o", LibKernel::KernelSetThreadAtexitCount); + LIB_FUNC("py6L8jiVAN8", LibKernel::KernelGetSanitizerMallocReplaceExternal); + LIB_FUNC("QKd0qM58Qes", LibKernel::KernelStopUnloadModule); + LIB_FUNC("rNhWz+lvOMU", LibKernel::KernelSetThreadDtors); LIB_FUNC("Tz4RNUCBbGI", LibKernel::KernelRtldThreadAtexitIncrement); - LIB_FUNC("8OnWXlgQlvo", LibKernel::KernelRtldThreadAtexitDecrement); + LIB_FUNC("vNe1w4diLCs", LibKernel::tls_get_addr); + LIB_FUNC("WhCc1w3EhSI", LibKernel::KernelSetThreadAtexitReport); + LIB_FUNC("WslcK1FQcGI", LibKernel::KernelIsNeoMode); + LIB_FUNC("wzvqT4UqKX8", LibKernel::KernelLoadStartModule); + LIB_FUNC("Xjoosiw+XPI", LibKernel::KernelUuidCreate); + LIB_FUNC("zE-wXIZjLoM", LibKernel::KernelDebugRaiseExceptionOnReleaseMode); } } // namespace Kyty::Libs diff --git a/source/emulator/src/RuntimeLinker.cpp b/source/emulator/src/RuntimeLinker.cpp index 1feeab3..7c5a481 100644 --- a/source/emulator/src/RuntimeLinker.cpp +++ b/source/emulator/src/RuntimeLinker.cpp @@ -68,13 +68,17 @@ struct RelocateHandlerStack uint64_t stack[3]; }; -constexpr uint64_t INVALID_MEMORY = 0x840000000; -constexpr uint64_t DESIRED_BASE_ADDR = 0x010000000; +constexpr uint64_t SYSTEM_RESERVED = 0x800000000u; +constexpr uint64_t CODE_BASE_INCR = 0x010000000u; +constexpr uint64_t INVALID_OFFSET = 0x040000000u; +constexpr uint64_t CODE_BASE_OFFSET = 0x100000000u; +constexpr uint64_t INVALID_MEMORY = SYSTEM_RESERVED + INVALID_OFFSET; constexpr size_t XSAVE_BUFFER_SIZE = 2688; -constexpr uint64_t XSAVE_CHK_GUARD = 0xDeadBeef5533CCAA; +constexpr uint64_t XSAVE_CHK_GUARD = 0xDeadBeef5533CCAAu; -static uint64_t g_desired_base_addr = DESIRED_BASE_ADDR; +static uint64_t g_desired_base_addr = SYSTEM_RESERVED + CODE_BASE_OFFSET; +static uint64_t g_invalid_memory = 0; static Program* g_tls_main_program = nullptr; alignas(64) static uint8_t g_tls_reg_save_area[XSAVE_BUFFER_SIZE + sizeof(XSAVE_CHK_GUARD)]; @@ -191,7 +195,8 @@ static void KYTY_SYSV_ABI stackwalk_x86(uint64_t rbp, void** stack, int* depth, void KYTY_SYSV_ABI sys_stack_walk_x86(uint64_t rbp, void** stack, int* depth) { - stackwalk_x86(rbp, stack, depth, 0, UINT64_MAX, DESIRED_BASE_ADDR, g_desired_base_addr - DESIRED_BASE_ADDR); + stackwalk_x86(rbp, stack, depth, 0, UINT64_MAX, SYSTEM_RESERVED + CODE_BASE_OFFSET, + g_desired_base_addr - (SYSTEM_RESERVED + CODE_BASE_OFFSET)); } static void kyty_exception_handler(const VirtualMemory::ExceptionHandler::ExceptionInfo* info) @@ -209,7 +214,7 @@ static void kyty_exception_handler(const VirtualMemory::ExceptionHandler::Except Core::Singleton::Instance()->StackTrace(info->rbp); EXIT("Access violation: %s [%016" PRIx64 "] %s\n", Core::EnumName(info->access_violation_type).C_Str(), - info->access_violation_vaddr, (info->access_violation_vaddr == INVALID_MEMORY ? "(Unpatched object)" : "")); + info->access_violation_vaddr, (info->access_violation_vaddr == g_invalid_memory ? "(Unpatched object)" : "")); } EXIT("Unknown exception!!!"); @@ -426,7 +431,7 @@ static void relocate(uint32_t index, Elf64_Rela* r, Program* program, bool jmpre bool weak = (ri.bind == BindType::Weak || !program->fail_if_global_not_resolved); if (ri.type == SymbolType::Object && weak) { - value = INVALID_MEMORY; + value = g_invalid_memory; } else if (ri.type == SymbolType::Func && jmprela_table && weak) { if (program->custom_call_plt_vaddr != 0) @@ -722,7 +727,7 @@ Program* RuntimeLinker::LoadProgram(const String& elf_name) if (elf_name.FilenameWithoutExtension().EndsWith(U"libc") || elf_name.FilenameWithoutExtension().EndsWith(U"Fios2") || elf_name.FilenameWithoutExtension().EndsWith(U"Fios2_debug") || elf_name.FilenameWithoutExtension().EndsWith(U"NpToolkit") || - elf_name.FilenameWithoutExtension().EndsWith(U"NpToolkit2")) + elf_name.FilenameWithoutExtension().EndsWith(U"NpToolkit2") || elf_name.FilenameWithoutExtension().EndsWith(U"JobManager")) { program->fail_if_global_not_resolved = false; } @@ -1130,7 +1135,7 @@ void RuntimeLinker::LoadProgramToMemory(Program* program) program->tls.handler_vaddr = program->base_vaddr + program->base_size_aligned + exception_handler_size; } - g_desired_base_addr += DESIRED_BASE_ADDR * (1 + alloc_size / DESIRED_BASE_ADDR); + g_desired_base_addr += CODE_BASE_INCR * (1 + alloc_size / CODE_BASE_INCR); EXIT_IF(program->base_vaddr == 0); EXIT_IF(program->base_size_aligned < program->base_size); @@ -1152,8 +1157,9 @@ void RuntimeLinker::LoadProgramToMemory(Program* program) program->base_size_aligned + exception_handler_size + tls_handler_size, kyty_exception_handler); } else { - program->exception_handler->Install(0, program->base_vaddr + program->base_size_aligned, - program->base_vaddr + program->base_size_aligned + exception_handler_size + tls_handler_size, + program->exception_handler->Install(SYSTEM_RESERVED, program->base_vaddr + program->base_size_aligned, + program->base_vaddr + program->base_size_aligned + exception_handler_size + tls_handler_size - + SYSTEM_RESERVED, kyty_exception_handler); if (Libs::Graphics::GpuMemoryWatcherEnabled()) @@ -1381,7 +1387,8 @@ static void InstallRelocateHandler(Program* program) { program->custom_call_plt_num = program->dynamic_info->jmprela_table_size / sizeof(Elf64_Rela); auto size = Jit::CallPlt::GetSize(program->custom_call_plt_num); - program->custom_call_plt_vaddr = VirtualMemory::Alloc(0, size, VirtualMemory::Mode::Write); + program->custom_call_plt_vaddr = VirtualMemory::Alloc(SYSTEM_RESERVED, size, VirtualMemory::Mode::Write); + EXIT_NOT_IMPLEMENTED(program->custom_call_plt_vaddr == 0); auto* code = new (reinterpret_cast(program->custom_call_plt_vaddr)) Jit::CallPlt(program->custom_call_plt_num); code->SetPltGot(pltgot_vaddr); VirtualMemory::Protect(program->custom_call_plt_vaddr, size, VirtualMemory::Mode::Execute); @@ -1395,6 +1402,12 @@ void RuntimeLinker::Relocate(Program* program) EXIT_IF(program == nullptr); + if (g_invalid_memory == 0) + { + g_invalid_memory = VirtualMemory::Alloc(INVALID_MEMORY, 4096, VirtualMemory::Mode::NoAccess); + EXIT_NOT_IMPLEMENTED(g_invalid_memory == 0); + } + printf("--- Relocate program: " FG_WHITE BOLD "%s" DEFAULT " ---\n", program->file_name.C_Str()); EXIT_NOT_IMPLEMENTED(program->dynamic_info->symbol_table_entry_size != sizeof(Elf64_Sym)); diff --git a/source/emulator/src/VirtualMemory.cpp b/source/emulator/src/VirtualMemory.cpp index 8986b90..b88dffb 100644 --- a/source/emulator/src/VirtualMemory.cpp +++ b/source/emulator/src/VirtualMemory.cpp @@ -27,6 +27,7 @@ // IWYU pragma: no_include // IWYU pragma: no_include // IWYU pragma: no_include +// IWYU pragma: no_include //#include @@ -299,12 +300,21 @@ void Init() uint64_t Alloc(uint64_t address, uint64_t size, Mode mode) { - auto ptr = reinterpret_cast(VirtualAlloc(reinterpret_cast(static_cast(address)), size, - static_cast(MEM_COMMIT) | static_cast(MEM_RESERVE), - get_protection_flag(mode))); + auto ptr = (address == 0 ? AllocAligned(address, size, mode, 1) + : reinterpret_cast(VirtualAlloc(reinterpret_cast(static_cast(address)), size, + static_cast(MEM_COMMIT) | static_cast(MEM_RESERVE), + get_protection_flag(mode)))); if (ptr == 0) { - printf("VirtualAlloc() failed: 0x%08" PRIx32 "\n", static_cast(GetLastError())); + auto err = static_cast(GetLastError()); + + if (err != ERROR_INVALID_ADDRESS) + { + printf("VirtualAlloc() failed: 0x%08" PRIx32 "\n", err); + } else + { + return AllocAligned(address, size, mode, 1); + } } return ptr; } @@ -325,16 +335,30 @@ uint64_t AllocAligned(uint64_t address, uint64_t size, Mode mode, uint64_t align { if (alignment == 0) { + printf("VirtualAlloc2 failed: 0x%08" PRIx32 "\n", static_cast(GetLastError())); return 0; } - MEM_ADDRESS_REQUIREMENTS req2 {}; + static constexpr uint64_t SYSTEM_MANAGED_MIN = 0x0000040000u; + static constexpr uint64_t SYSTEM_MANAGED_MAX = 0x07FFFFBFFFu; + static constexpr uint64_t USER_MIN = 0x1000000000u; + static constexpr uint64_t USER_MAX = 0xFBFFFFFFFFu; + + MEM_ADDRESS_REQUIREMENTS req {}; MEM_EXTENDED_PARAMETER param {}; - req2.LowestStartingAddress = nullptr; - req2.HighestEndingAddress = reinterpret_cast(0xffffffffffu); // nullptr; + req.LowestStartingAddress = (address == 0 ? reinterpret_cast(SYSTEM_MANAGED_MIN) : reinterpret_cast(address)); + req.HighestEndingAddress = (address == 0 ? reinterpret_cast(SYSTEM_MANAGED_MAX) : reinterpret_cast(USER_MAX)); + req.Alignment = alignment; + param.Type = MemExtendedParameterAddressRequirements; + param.Pointer = &req; + + MEM_ADDRESS_REQUIREMENTS req2 {}; + MEM_EXTENDED_PARAMETER param2 {}; + req2.LowestStartingAddress = (address == 0 ? reinterpret_cast(USER_MIN) : reinterpret_cast(address)); + req2.HighestEndingAddress = reinterpret_cast(USER_MAX); req2.Alignment = alignment; - param.Type = MemExtendedParameterAddressRequirements; - param.Pointer = &req2; + param2.Type = MemExtendedParameterAddressRequirements; + param2.Pointer = &req2; static auto virtual_alloc2 = ResolveVirtualAlloc2(); @@ -343,11 +367,24 @@ uint64_t AllocAligned(uint64_t address, uint64_t size, Mode mode, uint64_t align auto ptr = reinterpret_cast(virtual_alloc2(GetCurrentProcess(), nullptr, size, static_cast(MEM_COMMIT) | static_cast(MEM_RESERVE), get_protection_flag(mode), ¶m, 1)); + if (ptr == 0) { - printf("VirtualAlloc2(alignment = 0x%016" PRIx64 ") failed: 0x%08" PRIx32 "\n", alignment, static_cast(GetLastError())); + ptr = reinterpret_cast(virtual_alloc2(GetCurrentProcess(), nullptr, size, + static_cast(MEM_COMMIT) | static_cast(MEM_RESERVE), + get_protection_flag(mode), ¶m2, 1)); + } - return AllocAligned(address, size, mode, alignment << 1u); + if (ptr == 0) + { + auto err = static_cast(GetLastError()); + if (err != ERROR_INVALID_PARAMETER) + { + printf("VirtualAlloc2(alignment = 0x%016" PRIx64 ") failed: 0x%08" PRIx32 "\n", alignment, err); + } else + { + return AllocAligned(address, size, mode, alignment << 1u); + } } return ptr; } diff --git a/source/include/Kyty/Core/DbgAssert.h b/source/include/Kyty/Core/DbgAssert.h index 56a9025..24e014e 100644 --- a/source/include/Kyty/Core/DbgAssert.h +++ b/source/include/Kyty/Core/DbgAssert.h @@ -12,15 +12,17 @@ namespace Kyty::Core { #ifdef __clang__ -int dbg_exit_handler(char const* file, int line, const char* f, ...) KYTY_FORMAT_PRINTF(3, 4) __attribute__((analyzer_noreturn)); -int dbg_assert_handler(char const* expr, char const* file, int line) __attribute__((analyzer_noreturn)); -int dbg_exit_if_handler(char const* expr, char const* file, int line) __attribute__((analyzer_noreturn)); -int dbg_not_implemented_handler(char const* expr, char const* file, int line) __attribute__((analyzer_noreturn)); +int dbg_exit_handler(char const* file, int line, const char* f, ...) KYTY_FORMAT_PRINTF(3, 4) __attribute__((analyzer_noreturn)); +int dbg_assert_handler(char const* expr, char const* file, int line) __attribute__((analyzer_noreturn)); +int dbg_exit_if_handler(char const* expr, char const* file, int line) __attribute__((analyzer_noreturn)); +int dbg_not_implemented_handler(char const* expr, char const* file, int line) __attribute__((analyzer_noreturn)); +void dbg_exit(int status) __attribute__((analyzer_noreturn)); #else -int dbg_exit_handler(char const* file, int line, const char* f, ...) KYTY_FORMAT_PRINTF(3, 4); -int dbg_assert_handler(char const* expr, char const* file, int line); -int dbg_exit_if_handler(char const* expr, char const* file, int line); -int dbg_not_implemented_handler(char const* expr, char const* file, int line); +int dbg_exit_handler(char const* file, int line, const char* f, ...) KYTY_FORMAT_PRINTF(3, 4); +int dbg_assert_handler(char const* expr, char const* file, int line); +int dbg_exit_if_handler(char const* expr, char const* file, int line); +int dbg_not_implemented_handler(char const* expr, char const* file, int line); +void dbg_exit(int status); #endif bool dbg_is_debugger_present(); @@ -33,7 +35,8 @@ bool dbg_is_debugger_present(); #if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS #define ASSERT_HALT() \ - (Kyty::Core::dbg_is_debugger_present() ? (::fflush(nullptr), *(reinterpret_cast(1)) = 0) : (std::_Exit(321), 1)) + (Kyty::Core::dbg_is_debugger_present() ? (::fflush(nullptr), *(reinterpret_cast(1)) = 0) \ + : (Kyty::Core::dbg_exit(321), 1)) #else #define ASSERT_HALT() (std::_Exit(321), 1) #endif diff --git a/source/lib/Core/src/DbgAssert.cpp b/source/lib/Core/src/DbgAssert.cpp index 5270d8a..bb0f4fd 100644 --- a/source/lib/Core/src/DbgAssert.cpp +++ b/source/lib/Core/src/DbgAssert.cpp @@ -73,6 +73,11 @@ int dbg_exit_handler(char const* file, int line, const char* f, ...) return 1; } +void dbg_exit(int status) +{ + std::_Exit(status); +} + bool dbg_is_debugger_present() { #if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS