diff --git a/src/Core/PS4/HLE/LibKernel.cpp b/src/Core/PS4/HLE/LibKernel.cpp index d3819855d..acee1ed19 100644 --- a/src/Core/PS4/HLE/LibKernel.cpp +++ b/src/Core/PS4/HLE/LibKernel.cpp @@ -123,7 +123,10 @@ PS4_SYSV_ABI void poll() { BREAKPOINT(); } PS4_SYSV_ABI void munmap() { BREAKPOINT(); } -PS4_SYSV_ABI void sceKernelUsleep() { BREAKPOINT(); } +PS4_SYSV_ABI void sceKernelUsleep(unsigned int microseconds) { + std::this_thread::sleep_for(std::chrono::microseconds(microseconds)); + //BREAKPOINT(); +} #define PROT_READ 0x1 @@ -174,7 +177,18 @@ PS4_SYSV_ABI void close() { BREAKPOINT(); } PS4_SYSV_ABI void madvise() { BREAKPOINT(); } -PS4_SYSV_ABI void _writev() { BREAKPOINT(); } +struct iovec { + void* iov_base; /* Base address. */ + size_t iov_len; /* Length. */ +}; + +PS4_SYSV_ABI size_t _writev(int fd, const struct iovec* iov, int iovcn) { + size_t total_written = 0; + for (int i = 0; i < iovcn; i++) { + total_written += ::fwrite(iov[i].iov_base, 1, iov[i].iov_len, stdout); + } + return total_written; +} PS4_SYSV_ABI void lseek() { BREAKPOINT(); } PS4_SYSV_ABI int* __error() { return _errno(); } diff --git a/src/Core/PS4/Linker.cpp b/src/Core/PS4/Linker.cpp index e3b957f10..63e168638 100644 --- a/src/Core/PS4/Linker.cpp +++ b/src/Core/PS4/Linker.cpp @@ -169,6 +169,8 @@ void Linker::LoadModuleToMemory(Module* m) LOG_ERROR_IF(debug_loader, "p_filesz==0 in type {}\n", m->elf->ElfPheaderTypeStr(elf_pheader[i].p_type)); } break; + case PT_TLS: + LOG_ERROR("TLS SIZE: memsz: {} filesz: {}\n", elf_pheader[i].p_memsz, elf_pheader[i].p_filesz); default: LOG_ERROR_IF(debug_loader, "Unimplemented type {}\n", m->elf->ElfPheaderTypeStr(elf_pheader[i].p_type)); } @@ -632,17 +634,47 @@ void Linker::Resolve(const std::string& name, int Symtype, Module* m, SymbolReco } -using exit_func_t = PS4_SYSV_ABI void (*)(); +static thread_local void* tls_block_top; + +// this assumes TLS will do mov rax|rcx, fs:[0] and +// that fs:[0] will be a nullptr in windows (seems to be so) +// and, that fs:[0] points to the top of the static TLS +static LONG CALLBACK ExceptionHandlerTLS(PEXCEPTION_POINTERS ExceptionInfo) { + + static const uint8_t rax_fs0_deref[] = {0x64, 0x48, 0x8B, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00}; + + static const uint8_t rcx_fs0_deref[] = {0x64, 0x48, 0x8B, 0x0C, 0x25, 0x00, 0x00, 0x00, 0x00}; + + if (memcmp((void*)ExceptionInfo->ContextRecord->Rip, rax_fs0_deref, sizeof(rax_fs0_deref)) == 0) { + ExceptionInfo->ContextRecord->Rip += sizeof(rax_fs0_deref); + ExceptionInfo->ContextRecord->Rax = *(DWORD64*)tls_block_top; + + return EXCEPTION_CONTINUE_EXECUTION; + } else if (memcmp((void*)ExceptionInfo->ContextRecord->Rip, rcx_fs0_deref, sizeof(rcx_fs0_deref)) == 0) { + ExceptionInfo->ContextRecord->Rip += sizeof(rcx_fs0_deref); + ExceptionInfo->ContextRecord->Rcx = *(DWORD64*)tls_block_top; + + return EXCEPTION_CONTINUE_EXECUTION; + } + + return EXCEPTION_CONTINUE_SEARCH; +} + + using exit_func_t = PS4_SYSV_ABI void (*)(); using entry_func_t = PS4_SYSV_ABI void (*)(EntryParams* params, exit_func_t atexit_func); static PS4_SYSV_ABI void ProgramExitFunc() { - printf("exit function called\n"); } static void run_main_entry(u64 addr, EntryParams* params, exit_func_t exit_func) { //reinterpret_cast(addr)(params, exit_func); // can't be used, stack has to have a specific layout + void** tls_block = (void**)malloc(16); // this assumes 8 bytes of TLS storage, with the top of TLS pointing to itself + tls_block_top = tls_block[1] = &tls_block[1]; + + AddVectoredExceptionHandler(TRUE, ExceptionHandlerTLS); + asm volatile ( "andq $-16, %%rsp\n"// Align to 16 bytes "subq $8, %%rsp\n" // videoout_basic expects the stack to be misaligned