From 4f6dc8fddbf2905aab0c22dbab4202d7ff83d94c Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Sun, 19 Nov 2023 12:55:07 +0200 Subject: [PATCH 1/7] functions libkernel to get openrorbis working (without tls) --- .../hle/libraries/libkernel/libkernel.cpp | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/src/core/hle/libraries/libkernel/libkernel.cpp b/src/core/hle/libraries/libkernel/libkernel.cpp index 52e1a8e6..e0cb27bd 100644 --- a/src/core/hle/libraries/libkernel/libkernel.cpp +++ b/src/core/hle/libraries/libkernel/libkernel.cpp @@ -14,11 +14,14 @@ #ifdef _WIN64 #include +#include #endif #include "thread_management.h" namespace Core::Libraries::LibKernel { +constexpr bool log_libkernel_file = true; // disable it to disable logging + static u64 g_stack_chk_guard = 0xDEADBEEF54321ABC; // dummy return int32_t PS4_SYSV_ABI sceKernelReleaseDirectMemory(off_t start, size_t len) { @@ -30,9 +33,72 @@ static PS4_SYSV_ABI void stack_chk_fail() { BREAKPOINT(); } int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len) { BREAKPOINT(); } +void PS4_SYSV_ABI sceKernelUsleep(unsigned int microseconds) { std::this_thread::sleep_for(std::chrono::microseconds(microseconds)); } + +struct iovec { + void* iov_base; /* Base address. */ + size_t iov_len; /* Length. */ +}; + +size_t PS4_SYSV_ABI _writev(int fd, const struct iovec* iov, int iovcn) { + // weird it gives fd ==0 and writes to stdout , i am not sure if it that is valid (found in openorbis) + 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; +} + static thread_local int libc_error; int* PS4_SYSV_ABI __Error() { return &libc_error; } +#define PROT_READ 0x1 +#define PROT_WRITE 0x2 + +int PS4_SYSV_ABI sceKernelMmap(void* addr, u64 len, int prot, int flags, int fd, off_t offset, void** res) { + PRINT_FUNCTION_NAME(); + if (prot > 3) // READ,WRITE or bitwise READ | WRITE supported + { + LOG_ERROR_IF(log_libkernel_file, "sceKernelMmap prot ={} not supported\n", prot); + } + DWORD flProtect; + if (prot & PROT_WRITE) { + flProtect = PAGE_READWRITE; + } + off_t end = len + offset; + HANDLE mmap_fd, h; + if (fd == -1) + mmap_fd = INVALID_HANDLE_VALUE; + else + mmap_fd = (HANDLE)_get_osfhandle(fd); + h = CreateFileMapping(mmap_fd, NULL, flProtect, 0, end, NULL); + int k = GetLastError(); + if (NULL == h) return -1; + DWORD dwDesiredAccess; + if (prot & PROT_WRITE) + dwDesiredAccess = FILE_MAP_WRITE; + else + dwDesiredAccess = FILE_MAP_READ; + void* ret = MapViewOfFile(h, dwDesiredAccess, 0, offset, len); + if (ret == NULL) { + CloseHandle(h); + ret = nullptr; + } + *res = ret; + return 0; +} + +PS4_SYSV_ABI void* posix_mmap(void* addr, u64 len, int prot, int flags, int fd, u64 offset) { + void* ptr; + LOG_INFO_IF(log_libkernel_file, "posix mmap redirect to sceKernelMmap\n"); + // posix call the difference is that there is a different behaviour when it doesn't return 0 or SCE_OK + int result = sceKernelMmap(addr, len, prot, flags, fd, offset, &ptr); + if (result != 0) { + BREAKPOINT(); + } + return ptr; +} + void LibKernel_Register(Loader::SymbolsResolver* sym) { // obj LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard); @@ -49,6 +115,9 @@ void LibKernel_Register(Loader::SymbolsResolver* sym) { LIB_FUNCTION("WslcK1FQcGI", "libkernel", 1, "libkernel", 1, 1, Kernel::sceKernelIsNeoMode); LIB_FUNCTION("Ou3iL1abvng", "libkernel", 1, "libkernel", 1, 1, stack_chk_fail); LIB_FUNCTION("9BcDykPmo1I", "libkernel", 1, "libkernel", 1, 1, __Error); + LIB_FUNCTION("BPE9s9vQQXo", "libkernel", 1, "libkernel", 1, 1, posix_mmap); + LIB_FUNCTION("1jfXLRVzisc", "libkernel", 1, "libkernel", 1, 1, sceKernelUsleep); + LIB_FUNCTION("YSHRBRLn2pI", "libkernel", 1, "libkernel", 1, 1, _writev); Core::Libraries::LibKernel::fileSystemSymbolsRegister(sym); Core::Libraries::LibKernel::timeSymbolsRegister(sym); From b6d98d4b72f2d1ca4af7cc3e20a281fa44dcff3a Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Tue, 21 Nov 2023 16:54:10 +0200 Subject: [PATCH 2/7] some cleanups --- src/core/loader/elf.h | 445 ++++++++++++++++-------------------- src/core/virtual_memory.cpp | 6 +- src/core/virtual_memory.h | 10 + 3 files changed, 216 insertions(+), 245 deletions(-) diff --git a/src/core/loader/elf.h b/src/core/loader/elf.h index 349d8029..2e72e073 100644 --- a/src/core/loader/elf.h +++ b/src/core/loader/elf.h @@ -1,21 +1,20 @@ #pragma once -#include #include #include +#include #include -#include "common/types.h" #include "common/fs_file.h" +#include "common/types.h" -struct self_header -{ +struct self_header { static const u32 signature = 0x1D3D154Fu; u32 magic; u08 version; u08 mode; - u08 endian;// 1 is little endian + u08 endian; // 1 is little endian u08 attributes; u08 category; u08 program_type; @@ -25,34 +24,31 @@ struct self_header u32 file_size; u32 padding2; u16 segment_count; - u16 unknown1A; //always 0x22 + u16 unknown1A; // always 0x22 u32 padding3; }; -struct self_segment_header -{ +struct self_segment_header { bool IsBlocked() const { - return (flags & 0x800) != 0;//0 or 0x800 + return (flags & 0x800) != 0; // 0 or 0x800 } - u32 GetId() const { - return (flags >> 20u) & 0xFFFu; - } + u32 GetId() const { return (flags >> 20u) & 0xFFFu; } bool IsOrdered() const { - return (flags & 1) != 0;//0 or 1 + return (flags & 1) != 0; // 0 or 1 } - bool IsEncrypted() const { - return (flags & 2) != 0;//0 or 2 + bool IsEncrypted() const { + return (flags & 2) != 0; // 0 or 2 } - bool IsSigned() const { - return (flags & 4) != 0;//0 or 4 + bool IsSigned() const { + return (flags & 4) != 0; // 0 or 4 } - bool IsCompressed() const { - return (flags & 8) != 0;//0 or 8 + bool IsCompressed() const { + return (flags & 8) != 0; // 0 or 8 } u64 flags; @@ -61,8 +57,7 @@ struct self_segment_header u64 memory_size; }; - -constexpr u08 EI_MAG0 = 0;/* e_ident[] indexes */ +constexpr u08 EI_MAG0 = 0; /* e_ident[] indexes */ constexpr u08 EI_MAG1 = 1; constexpr u08 EI_MAG2 = 2; constexpr u08 EI_MAG3 = 3; @@ -91,149 +86,132 @@ typedef enum : u16 { } e_type_s; typedef enum : u16 { - EM_NONE = 0, /* No machine */ - EM_M32 = 1, /* AT&T WE 32100 */ - EM_SPARC = 2, /* SPARC */ - EM_386 = 3, /* Intel 80386 */ - EM_68K = 4, /* Motorola 68000 */ - EM_88K = 5, /* Motorola 88000 */ - EM_860 = 7, /* Intel 80860 */ - EM_MIPS = 8, /* MIPS I Architecture */ - EM_S370 = 9, /* IBM System/370 Processor */ - EM_MIPS_RS3_LE = 10, /* MIPS RS3000 Little-endian */ - EM_PARISC = 15, /* Hewlett-Packard PA-RISC */ - EM_VPP500 = 17, /* Fujitsu VPP500 */ - EM_SPARC32PLUS = 18, /* Enhanced instruction set SPARC */ - EM_960 = 19, /* Intel 80960 */ - EM_PPC = 20, /* PowerPC */ - EM_PPC64 = 21, /* 64-bit PowerPC */ - EM_S390 = 22, /* IBM System/390 Processor */ - EM_V800 = 36, /* NEC V800 */ - EM_FR20 = 37, /* Fujitsu FR20 */ - EM_RH32 = 38, /* TRW RH-32 */ - EM_RCE = 39, /* Motorola RCE */ - EM_ARM = 40, /* Advanced RISC Machines ARM */ - EM_ALPHA = 41, /* Digital Alpha */ - EM_SH = 42, /* Hitachi SH */ - EM_SPARCV9 = 43, /* SPARC Version 9 */ - EM_TRICORE = 44, /* Siemens TriCore embedded processor */ - EM_ARC = 45, /* Argonaut RISC Core, Argonaut Technologies Inc. */ - EM_H8_300 = 46, /* Hitachi H8/300 */ - EM_H8_300H = 47, /* Hitachi H8/300H */ - EM_H8S = 48, /* Hitachi H8S */ - EM_H8_500 = 49, /* Hitachi H8/500 */ - EM_IA_64 = 50, /* Intel IA-64 processor architecture */ - EM_MIPS_X = 51, /* Stanford MIPS-X */ + EM_NONE = 0, /* No machine */ + EM_M32 = 1, /* AT&T WE 32100 */ + EM_SPARC = 2, /* SPARC */ + EM_386 = 3, /* Intel 80386 */ + EM_68K = 4, /* Motorola 68000 */ + EM_88K = 5, /* Motorola 88000 */ + EM_860 = 7, /* Intel 80860 */ + EM_MIPS = 8, /* MIPS I Architecture */ + EM_S370 = 9, /* IBM System/370 Processor */ + EM_MIPS_RS3_LE = 10, /* MIPS RS3000 Little-endian */ + EM_PARISC = 15, /* Hewlett-Packard PA-RISC */ + EM_VPP500 = 17, /* Fujitsu VPP500 */ + EM_SPARC32PLUS = 18, /* Enhanced instruction set SPARC */ + EM_960 = 19, /* Intel 80960 */ + EM_PPC = 20, /* PowerPC */ + EM_PPC64 = 21, /* 64-bit PowerPC */ + EM_S390 = 22, /* IBM System/390 Processor */ + EM_V800 = 36, /* NEC V800 */ + EM_FR20 = 37, /* Fujitsu FR20 */ + EM_RH32 = 38, /* TRW RH-32 */ + EM_RCE = 39, /* Motorola RCE */ + EM_ARM = 40, /* Advanced RISC Machines ARM */ + EM_ALPHA = 41, /* Digital Alpha */ + EM_SH = 42, /* Hitachi SH */ + EM_SPARCV9 = 43, /* SPARC Version 9 */ + EM_TRICORE = 44, /* Siemens TriCore embedded processor */ + EM_ARC = 45, /* Argonaut RISC Core, Argonaut Technologies Inc. */ + EM_H8_300 = 46, /* Hitachi H8/300 */ + EM_H8_300H = 47, /* Hitachi H8/300H */ + EM_H8S = 48, /* Hitachi H8S */ + EM_H8_500 = 49, /* Hitachi H8/500 */ + EM_IA_64 = 50, /* Intel IA-64 processor architecture */ + EM_MIPS_X = 51, /* Stanford MIPS-X */ EM_COLDFIRE = 52, /* Motorola ColdFire */ - EM_68HC12 = 53, /* Motorola M68HC12 */ - EM_MMA = 54, /* Fujitsu MMA Multimedia Accelerator */ - EM_PCP = 55, /* Siemens PCP */ - EM_NCPU = 56, /* Sony nCPU embedded RISC processor */ - EM_NDR1 = 57, /* Denso NDR1 microprocessor */ + EM_68HC12 = 53, /* Motorola M68HC12 */ + EM_MMA = 54, /* Fujitsu MMA Multimedia Accelerator */ + EM_PCP = 55, /* Siemens PCP */ + EM_NCPU = 56, /* Sony nCPU embedded RISC processor */ + EM_NDR1 = 57, /* Denso NDR1 microprocessor */ EM_STARCORE = 58, /* Motorola Star*Core processor */ - EM_ME16 = 59, /* Toyota ME16 processor */ - EM_ST100 = 60, /* STMicroelectronics ST100 processor */ - EM_TINYJ = 61, /* Advanced Logic Corp. TinyJ embedded processor family */ - EM_X86_64 = 62, /* AMD x86-64 architecture (PS4) */ - EM_PDSP = 63, /* Sony DSP Processor */ - EM_PDP10 = 64, /* Digital Equipment Corp. PDP-10 */ - EM_PDP11 = 65, /* Digital Equipment Corp. PDP-11 */ - EM_FX66 = 66, /* Siemens FX66 microcontroller */ - EM_ST9PLUS = 67, /* STMicroelectronics ST9+ 8/16 bit microcontroller */ - EM_ST7 = 68, /* STMicroelectronics ST7 8-bit microcontroller */ - EM_68HC16 = 69, /* Motorola MC68HC16 Microcontroller */ - EM_68HC11 = 70, /* Motorola MC68HC11 Microcontroller */ - EM_68HC08 = 71, /* Motorola MC68HC08 Microcontroller */ - EM_68HC05 = 72, /* Motorola MC68HC05 Microcontroller */ - EM_SVX = 73, /* Silicon Graphics SVx */ - EM_ST19 = 75, /* Digital VAX */ - EM_CRIS = 76, /* Axis Communications 32-bit embedded processor */ - EM_JAVELIN = 77, /* Infineon Technologies 32-bit embedded processor */ + EM_ME16 = 59, /* Toyota ME16 processor */ + EM_ST100 = 60, /* STMicroelectronics ST100 processor */ + EM_TINYJ = 61, /* Advanced Logic Corp. TinyJ embedded processor family */ + EM_X86_64 = 62, /* AMD x86-64 architecture (PS4) */ + EM_PDSP = 63, /* Sony DSP Processor */ + EM_PDP10 = 64, /* Digital Equipment Corp. PDP-10 */ + EM_PDP11 = 65, /* Digital Equipment Corp. PDP-11 */ + EM_FX66 = 66, /* Siemens FX66 microcontroller */ + EM_ST9PLUS = 67, /* STMicroelectronics ST9+ 8/16 bit microcontroller */ + EM_ST7 = 68, /* STMicroelectronics ST7 8-bit microcontroller */ + EM_68HC16 = 69, /* Motorola MC68HC16 Microcontroller */ + EM_68HC11 = 70, /* Motorola MC68HC11 Microcontroller */ + EM_68HC08 = 71, /* Motorola MC68HC08 Microcontroller */ + EM_68HC05 = 72, /* Motorola MC68HC05 Microcontroller */ + EM_SVX = 73, /* Silicon Graphics SVx */ + EM_ST19 = 75, /* Digital VAX */ + EM_CRIS = 76, /* Axis Communications 32-bit embedded processor */ + EM_JAVELIN = 77, /* Infineon Technologies 32-bit embedded processor */ EM_FIREPATH = 78, /* Element 14 64-bit DSP Processor */ - EM_ZSP = 79, /* LSI Logic 16-bit DSP Processor */ - EM_MMIX = 80, /* Donald Knuth's educational 64-bit processor */ - EM_HUANY = 81, /* Harvard University machine-independent object files */ - EM_PRISM = 82, /* SiTera Prism */ - EM_AVR = 83, /* Atmel AVR 8-bit microcontroller */ - EM_FR30 = 84, /* Fujitsu FR30 */ - EM_D10V = 85, /* Mitsubishi D10V */ - EM_D30V = 86, /* Mitsubishi D30V */ - EM_V850 = 87, /* NEC v850 */ - EM_M32R = 88, /* Mitsubishi M32R */ - EM_MN10300 = 89, /* Matsushita MN10300 */ - EM_MN10200 = 90, /* Matsushita MN10200 */ - EM_PJ = 91, /* PicoJava */ + EM_ZSP = 79, /* LSI Logic 16-bit DSP Processor */ + EM_MMIX = 80, /* Donald Knuth's educational 64-bit processor */ + EM_HUANY = 81, /* Harvard University machine-independent object files */ + EM_PRISM = 82, /* SiTera Prism */ + EM_AVR = 83, /* Atmel AVR 8-bit microcontroller */ + EM_FR30 = 84, /* Fujitsu FR30 */ + EM_D10V = 85, /* Mitsubishi D10V */ + EM_D30V = 86, /* Mitsubishi D30V */ + EM_V850 = 87, /* NEC v850 */ + EM_M32R = 88, /* Mitsubishi M32R */ + EM_MN10300 = 89, /* Matsushita MN10300 */ + EM_MN10200 = 90, /* Matsushita MN10200 */ + EM_PJ = 91, /* PicoJava */ EM_OPENRISC = 92, /* OpenRISC 32-bit embedded processor */ - EM_ARC_A5 = 93, /* ARC Cores Tangent-A5 */ - EM_XTENSA = 94, /* Tensilica Xtensa Architecture */ - EM_VIDEOCORE = 95, /* Alphamosaic VideoCore processor */ - EM_TMM_GPP = 96, /* Thompson Multimedia General Purpose Processor */ - EM_NS32K = 97, /* National Semiconductor 32000 series */ - EM_TPC = 98, /* Tenor Network TPC processor */ - EM_SNP1K = 99, /* Trebia SNP 1000 processor */ - EM_ST200 = 100, /* STMicroelectronics (www.st.com) ST200 microcontroller */ - EM_IP2K = 101, /* Ubicom IP2xxx microcontroller family */ - EM_MAX = 102, /* MAX Processor */ - EM_CR = 103, /* National Semiconductor CompactRISC microprocessor */ - EM_F2MC16 = 104, /* Fujitsu F2MC16 */ - EM_MSP430 = 105, /* Texas Instruments embedded microcontroller msp430 */ + EM_ARC_A5 = 93, /* ARC Cores Tangent-A5 */ + EM_XTENSA = 94, /* Tensilica Xtensa Architecture */ + EM_VIDEOCORE = 95, /* Alphamosaic VideoCore processor */ + EM_TMM_GPP = 96, /* Thompson Multimedia General Purpose Processor */ + EM_NS32K = 97, /* National Semiconductor 32000 series */ + EM_TPC = 98, /* Tenor Network TPC processor */ + EM_SNP1K = 99, /* Trebia SNP 1000 processor */ + EM_ST200 = 100, /* STMicroelectronics (www.st.com) ST200 microcontroller */ + EM_IP2K = 101, /* Ubicom IP2xxx microcontroller family */ + EM_MAX = 102, /* MAX Processor */ + EM_CR = 103, /* National Semiconductor CompactRISC microprocessor */ + EM_F2MC16 = 104, /* Fujitsu F2MC16 */ + EM_MSP430 = 105, /* Texas Instruments embedded microcontroller msp430 */ EM_BLACKFIN = 106, /* Analog Devices Blackfin (DSP) processor */ - EM_SE_C33 = 107, /* S1C33 Family of Seiko Epson processors */ - EM_SEP = 108, /* Sharp embedded microprocessor */ - EM_ARCA = 109, /* Arca RISC Microprocessor */ - EM_UNICORE = 110 /* Microprocessor series from PKU-Unity Ltd. and MPRC */ + EM_SE_C33 = 107, /* S1C33 Family of Seiko Epson processors */ + EM_SEP = 108, /* Sharp embedded microprocessor */ + EM_ARCA = 109, /* Arca RISC Microprocessor */ + EM_UNICORE = 110 /* Microprocessor series from PKU-Unity Ltd. and MPRC */ } e_machine_es; -typedef enum :u32 { - EV_NONE = 0x0, - EV_CURRENT = 0x1 -} e_version_es; +typedef enum : u32 { EV_NONE = 0x0, EV_CURRENT = 0x1 } e_version_es; + +typedef enum : u08 { ELF_CLASS_NONE = 0x0, ELF_CLASS_32 = 0x1, ELF_CLASS_64 = 0x2, ELF_CLASS_NUM = 0x3 } ident_class_es; + +typedef enum : u08 { ELF_DATA_NONE = 0x0, ELF_DATA_2LSB = 0x1, ELF_DATA_2MSB = 0x2, ELF_DATA_NUM = 0x3 } ident_endian_es; + +typedef enum : u08 { ELF_VERSION_NONE = 0x0, ELF_VERSION_CURRENT = 0x1, ELF_VERSION_NUM = 0x2 } ident_version_es; typedef enum : u08 { - ELF_CLASS_NONE =0x0, - ELF_CLASS_32 =0x1, - ELF_CLASS_64 =0x2, - ELF_CLASS_NUM =0x3 -} ident_class_es; - -typedef enum : u08 { - ELF_DATA_NONE = 0x0, - ELF_DATA_2LSB = 0x1, - ELF_DATA_2MSB = 0x2, - ELF_DATA_NUM = 0x3 -} ident_endian_es; - -typedef enum :u08 { - ELF_VERSION_NONE = 0x0, - ELF_VERSION_CURRENT = 0x1, - ELF_VERSION_NUM = 0x2 -} ident_version_es; - -typedef enum :u08 { - ELF_OSABI_NONE = 0x0, /* No extensions or unspecified */ - ELF_OSABI_HPUX = 0x1, /* Hewlett-Packard HP-UX */ - ELF_OSABI_NETBSD = 0x2, /* NetBSD */ - ELF_OSABI_LINUX = 0x3, /* Linux */ + ELF_OSABI_NONE = 0x0, /* No extensions or unspecified */ + ELF_OSABI_HPUX = 0x1, /* Hewlett-Packard HP-UX */ + ELF_OSABI_NETBSD = 0x2, /* NetBSD */ + ELF_OSABI_LINUX = 0x3, /* Linux */ ELF_OSABI_SOLARIS = 0x6, /* Sun Solaris */ - ELF_OSABI_AIX = 0x7, /* AIX */ - ELF_OSABI_IRIX = 0x8, /* IRIX */ + ELF_OSABI_AIX = 0x7, /* AIX */ + ELF_OSABI_IRIX = 0x8, /* IRIX */ ELF_OSABI_FREEBSD = 0x9, /* FreeBSD (PS4) */ - ELF_OSABI_TRU64 = 0xA, /* Compaq TRU64 UNIX */ + ELF_OSABI_TRU64 = 0xA, /* Compaq TRU64 UNIX */ ELF_OSABI_MODESTO = 0xB, /* Novell Modesto */ ELF_OSABI_OPENBSD = 0xC, /* Open BSD */ ELF_OSABI_OPENVMS = 0xD, /* Open VMS */ - ELF_OSABI_NSK = 0xE, /* Hewlett-Packard Non-Stop Kernel */ - ELF_OSABI_AROS = 0xF, /* Amiga Research OS */ - ELF_OSABI_ARM_AEABI = 0x40, /* ARM EABI */ - ELF_OSABI_ARM = 0x61, /* ARM */ - ELF_OSABI_STANDALONE = 0xFF /* Standalone (embedded applications) */ + ELF_OSABI_NSK = 0xE, /* Hewlett-Packard Non-Stop Kernel */ + ELF_OSABI_AROS = 0xF, /* Amiga Research OS */ + ELF_OSABI_ARM_AEABI = 0x40, /* ARM EABI */ + ELF_OSABI_ARM = 0x61, /* ARM */ + ELF_OSABI_STANDALONE = 0xFF /* Standalone (embedded applications) */ } ident_osabi_es; -typedef enum :u08 { - ELF_ABI_VERSION_AMDGPU_HSA_V2=0x0, - ELF_ABI_VERSION_AMDGPU_HSA_V3=0x1, - ELF_ABI_VERSION_AMDGPU_HSA_V4=0x2, - ELF_ABI_VERSION_AMDGPU_HSA_V5=0x3 +typedef enum : u08 { + ELF_ABI_VERSION_AMDGPU_HSA_V2 = 0x0, + ELF_ABI_VERSION_AMDGPU_HSA_V3 = 0x1, + ELF_ABI_VERSION_AMDGPU_HSA_V4 = 0x2, + ELF_ABI_VERSION_AMDGPU_HSA_V5 = 0x3 } ident_abiversion_es; struct elf_ident { @@ -246,8 +224,7 @@ struct elf_ident { u08 pad[6]; }; -struct elf_header -{ +struct elf_header { static const u32 signature = 0x7F454C46u; elf_ident e_ident; /* ELF identification */ @@ -306,20 +283,18 @@ typedef enum : u32 { PF_READ_WRITE_EXEC = 0x7 } elf_program_flags; -struct elf_program_header -{ +struct elf_program_header { elf_program_type p_type; /* Type of segment */ - elf_program_flags p_flags; /* Segment attributes */ - u64 p_offset; /* Offset in file */ - u64 p_vaddr; /* Virtual address in memory */ - u64 p_paddr; /* Reserved */ - u64 p_filesz; /* Size of segment in file */ - u64 p_memsz; /* Size of segment in memory */ - u64 p_align; /* Alignment of segment */ + elf_program_flags p_flags; /* Segment attributes */ + u64 p_offset; /* Offset in file */ + u64 p_vaddr; /* Virtual address in memory */ + u64 p_paddr; /* Reserved */ + u64 p_filesz; /* Size of segment in file */ + u64 p_memsz; /* Size of segment in memory */ + u64 p_align; /* Alignment of segment */ }; -struct elf_section_header -{ +struct elf_section_header { u32 sh_name; /* Section name */ u32 sh_type; /* Section type */ u64 sh_flags; /* Section attributes */ @@ -332,7 +307,7 @@ struct elf_section_header u64 sh_entsize; /* Size of entries, if section has table */ }; -typedef enum :u64 { +typedef enum : u64 { PT_FAKE = 0x1, PT_NPDRM_EXEC = 0x4, PT_NPDRM_DYNLIB = 0x5, @@ -343,8 +318,7 @@ typedef enum :u64 { PT_SECURE_KERNEL = 0xF } program_type_es; -struct elf_program_id_header -{ +struct elf_program_id_header { u64 authid; program_type_es program_type; u64 appver; @@ -352,79 +326,75 @@ struct elf_program_id_header u08 digest[32]; }; -constexpr s64 DT_NULL = 0; -constexpr s64 DT_NEEDED = 0x00000001; -constexpr s64 DT_RELA = 0x00000007; -constexpr s64 DT_INIT = 0x0000000c; -constexpr s64 DT_FINI = 0x0000000d; -constexpr s64 DT_DEBUG = 0x00000015; -constexpr s64 DT_TEXTREL = 0x00000016; -constexpr s64 DT_INIT_ARRAY = 0x00000019; -constexpr s64 DT_FINI_ARRAY = 0x0000001a; -constexpr s64 DT_INIT_ARRAYSZ = 0x0000001b; -constexpr s64 DT_FINI_ARRAYSZ = 0x0000001c; -constexpr s64 DT_FLAGS = 0x0000001e; -constexpr s64 DT_PREINIT_ARRAY = 0x00000020; -constexpr s64 DT_PREINIT_ARRAYSZ = 0x00000021; -constexpr s64 DT_SCE_FINGERPRINT = 0x61000007; +constexpr s64 DT_NULL = 0; +constexpr s64 DT_NEEDED = 0x00000001; +constexpr s64 DT_RELA = 0x00000007; +constexpr s64 DT_INIT = 0x0000000c; +constexpr s64 DT_FINI = 0x0000000d; +constexpr s64 DT_DEBUG = 0x00000015; +constexpr s64 DT_TEXTREL = 0x00000016; +constexpr s64 DT_INIT_ARRAY = 0x00000019; +constexpr s64 DT_FINI_ARRAY = 0x0000001a; +constexpr s64 DT_INIT_ARRAYSZ = 0x0000001b; +constexpr s64 DT_FINI_ARRAYSZ = 0x0000001c; +constexpr s64 DT_FLAGS = 0x0000001e; +constexpr s64 DT_PREINIT_ARRAY = 0x00000020; +constexpr s64 DT_PREINIT_ARRAYSZ = 0x00000021; +constexpr s64 DT_SCE_FINGERPRINT = 0x61000007; constexpr s64 DT_SCE_ORIGINAL_FILENAME = 0x61000009; -constexpr s64 DT_SCE_MODULE_INFO = 0x6100000d; -constexpr s64 DT_SCE_NEEDED_MODULE = 0x6100000f; -constexpr s64 DT_SCE_MODULE_ATTR = 0x61000011; -constexpr s64 DT_SCE_EXPORT_LIB = 0x61000013; -constexpr s64 DT_SCE_IMPORT_LIB = 0x61000015; -constexpr s64 DT_SCE_IMPORT_LIB_ATTR = 0x61000019; -constexpr s64 DT_SCE_HASH = 0x61000025; -constexpr s64 DT_SCE_PLTGOT = 0x61000027; -constexpr s64 DT_SCE_JMPREL = 0x61000029; -constexpr s64 DT_SCE_PLTREL = 0x6100002b; -constexpr s64 DT_SCE_PLTRELSZ = 0x6100002d; -constexpr s64 DT_SCE_RELA = 0x6100002f; -constexpr s64 DT_SCE_RELASZ = 0x61000031; -constexpr s64 DT_SCE_RELAENT = 0x61000033; -constexpr s64 DT_SCE_SYMENT = 0x6100003b; -constexpr s64 DT_SCE_HASHSZ = 0x6100003d; -constexpr s64 DT_SCE_STRTAB = 0x61000035; -constexpr s64 DT_SCE_STRSZ = 0x61000037; -constexpr s64 DT_SCE_SYMTAB = 0x61000039; -constexpr s64 DT_SCE_SYMTABSZ = 0x6100003f; +constexpr s64 DT_SCE_MODULE_INFO = 0x6100000d; +constexpr s64 DT_SCE_NEEDED_MODULE = 0x6100000f; +constexpr s64 DT_SCE_MODULE_ATTR = 0x61000011; +constexpr s64 DT_SCE_EXPORT_LIB = 0x61000013; +constexpr s64 DT_SCE_IMPORT_LIB = 0x61000015; +constexpr s64 DT_SCE_IMPORT_LIB_ATTR = 0x61000019; +constexpr s64 DT_SCE_HASH = 0x61000025; +constexpr s64 DT_SCE_PLTGOT = 0x61000027; +constexpr s64 DT_SCE_JMPREL = 0x61000029; +constexpr s64 DT_SCE_PLTREL = 0x6100002b; +constexpr s64 DT_SCE_PLTRELSZ = 0x6100002d; +constexpr s64 DT_SCE_RELA = 0x6100002f; +constexpr s64 DT_SCE_RELASZ = 0x61000031; +constexpr s64 DT_SCE_RELAENT = 0x61000033; +constexpr s64 DT_SCE_SYMENT = 0x6100003b; +constexpr s64 DT_SCE_HASHSZ = 0x6100003d; +constexpr s64 DT_SCE_STRTAB = 0x61000035; +constexpr s64 DT_SCE_STRSZ = 0x61000037; +constexpr s64 DT_SCE_SYMTAB = 0x61000039; +constexpr s64 DT_SCE_SYMTABSZ = 0x6100003f; - -struct elf_dynamic -{ +struct elf_dynamic { s64 d_tag; - union - { + union { u64 d_val; u64 d_ptr; } d_un; }; -constexpr u08 STB_LOCAL = 0; +constexpr u08 STB_LOCAL = 0; constexpr u08 STB_GLOBAL = 1; -constexpr u08 STB_WEAK = 2; +constexpr u08 STB_WEAK = 2; -constexpr u08 STT_NOTYPE = 0; -constexpr u08 STT_OBJECT = 1; -constexpr u08 STT_FUN = 2; +constexpr u08 STT_NOTYPE = 0; +constexpr u08 STT_OBJECT = 1; +constexpr u08 STT_FUN = 2; constexpr u08 STT_SECTION = 3; -constexpr u08 STT_FILE = 4; -constexpr u08 STT_COMMON = 5; -constexpr u08 STT_TLS = 6; -constexpr u08 STT_LOOS = 10; -constexpr u08 STT_SCE = 11; //module_start/module_stop -constexpr u08 STT_HIOS = 12; -constexpr u08 STT_LOPRO = 13; +constexpr u08 STT_FILE = 4; +constexpr u08 STT_COMMON = 5; +constexpr u08 STT_TLS = 6; +constexpr u08 STT_LOOS = 10; +constexpr u08 STT_SCE = 11; // module_start/module_stop +constexpr u08 STT_HIOS = 12; +constexpr u08 STT_LOPRO = 13; constexpr u08 STT_SPARC_REGISTER = 13; -constexpr u08 STT_HIPROC = 15; +constexpr u08 STT_HIPROC = 15; constexpr u08 STV_DEFAULT = 0; constexpr u08 STV_INTERNAL = 1; constexpr u08 STV_HIDDEN = 2; constexpr u08 STV_PROTECTED = 3; -struct elf_symbol -{ +struct elf_symbol { u08 GetBind() const { return st_info >> 4u; } u08 GetType() const { return st_info & 0xfu; } u08 GetVisibility() const { return st_other & 3u; } @@ -437,18 +407,19 @@ struct elf_symbol u64 st_size; }; -struct elf_relocation -{ +struct elf_relocation { u32 GetSymbol() const { return static_cast(rel_info >> 32u); } - u32 GetType() const { return static_cast(rel_info & 0xffffffff); } + u32 GetType() const { return static_cast(rel_info & 0xffffffff); } u64 rel_offset; u64 rel_info; s64 rel_addend; }; -constexpr u32 R_X86_64_64 = 1; // Direct 64 bit -constexpr u32 R_X86_64_JUMP_SLOT = 7; // Create PLT entry -constexpr u32 R_X86_64_RELATIVE = 8; // Adjust by program base +constexpr u32 R_X86_64_64 = 1; // Direct 64 bit +constexpr u32 R_X86_64_GLOB_DAT = 6; +constexpr u32 R_X86_64_JUMP_SLOT = 7; // Create PLT entry +constexpr u32 R_X86_64_RELATIVE = 8; // Adjust by program base +constexpr u32 R_X86_64_DTPMOD64 = 16; namespace Core::Loader { @@ -457,30 +428,20 @@ class Elf { Elf() = default; virtual ~Elf(); - void Open(const std::string & file_name); + void Open(const std::string& file_name); bool isSelfFile() const; bool isElfFile() const; void DebugDump(); - [[nodiscard]] self_header GetSElfHeader() const { - return m_self; - } + [[nodiscard]] self_header GetSElfHeader() const { return m_self; } - [[nodiscard]] elf_header GetElfHeader() const { - return m_elf_header; - } + [[nodiscard]] elf_header GetElfHeader() const { return m_elf_header; } - [[nodiscard]] std::span GetProgramHeader() const { - return m_elf_phdr; - } + [[nodiscard]] std::span GetProgramHeader() const { return m_elf_phdr; } - [[nodiscard]] std::span GetSegmentHeader() const { - return m_self_segments; - } + [[nodiscard]] std::span GetSegmentHeader() const { return m_self_segments; } - [[nodiscard]] u64 GetElfEntry() const { - return m_elf_header.e_entry; - } + [[nodiscard]] u64 GetElfEntry() const { return m_elf_header.e_entry; } std::string SElfHeaderStr(); std::string SELFSegHeader(u16 no); @@ -505,4 +466,4 @@ class Elf { elf_program_id_header m_self_id_header{}; }; -} // namespace Core::Loader +} // namespace Core::Loader diff --git a/src/core/virtual_memory.cpp b/src/core/virtual_memory.cpp index 1aed5514..f730aff4 100644 --- a/src/core/virtual_memory.cpp +++ b/src/core/virtual_memory.cpp @@ -1,6 +1,7 @@ -#include "common/log.h" #include "core/virtual_memory.h" +#include "common/log.h" + #ifdef _WIN64 #include #else @@ -107,8 +108,7 @@ bool memory_patch(u64 vaddr, u64 value) { memory_protect(vaddr, 8, old_mode, nullptr); // if mode is executable flush it so insure that cpu finds it - if ((old_mode == MemoryMode::Execute || old_mode == MemoryMode::ExecuteRead || old_mode == MemoryMode::ExecuteWrite || - old_mode == MemoryMode::ExecuteReadWrite)) { + if (containsExecuteMode(old_mode)) { memory_flush(vaddr, 8); } diff --git a/src/core/virtual_memory.h b/src/core/virtual_memory.h index 6b255301..ef83a900 100644 --- a/src/core/virtual_memory.h +++ b/src/core/virtual_memory.h @@ -25,4 +25,14 @@ bool memory_protect(u64 address, u64 size, MemoryMode mode, MemoryMode* old_mode bool memory_flush(u64 address, u64 size); bool memory_patch(u64 vaddr, u64 value); +inline bool containsExecuteMode(MemoryMode mode) { + switch (mode) { + case MemoryMode::Execute: return true; + case MemoryMode::ExecuteRead: return true; + case MemoryMode::ExecuteWrite: return true; + case MemoryMode::ExecuteReadWrite: return true; + default: return false; + } +} + } // namespace VirtualMemory \ No newline at end of file From af1845395012050a6dad4363318beab98b0a66d3 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Tue, 21 Nov 2023 17:27:11 +0200 Subject: [PATCH 3/7] initial PT_TLS support --- src/core/linker.cpp | 28 ++++++++-------------------- src/core/linker.h | 7 +++++++ 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 77094b70..fdedbee5 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -158,29 +158,17 @@ 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: + m->tls.image_virtual_addr = elf_pheader[i].p_vaddr + m->base_virtual_addr; + m->tls.image_size = get_aligned_size(elf_pheader[i]); + LOG_INFO_IF(debug_loader, "tls virtual address ={:#x}\n", m->tls.image_virtual_addr); + LOG_INFO_IF(debug_loader, "tls image size ={}\n", m->tls.image_size); + break; default: LOG_ERROR_IF(debug_loader, "Unimplemented type {}\n", m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type)); } } LOG_INFO_IF(debug_loader, "program entry addr ..........: {:#018x}\n", m->elf.GetElfEntry() + m->base_virtual_addr); - - auto* rt1 = reinterpret_cast(m->elf.GetElfEntry() + m->base_virtual_addr); - ZyanU64 runtime_address = m->elf.GetElfEntry() + m->base_virtual_addr; - - // Loop over the instructions in our buffer. - ZyanUSize offset = 0; - ZydisDisassembledInstruction instruction; - while (ZYAN_SUCCESS(ZydisDisassembleIntel( - /* machine_mode: */ ZYDIS_MACHINE_MODE_LONG_64, - /* runtime_address: */ runtime_address, - /* buffer: */ rt1 + offset, - /* length: */ sizeof(rt1) - offset, - /* instruction: */ &instruction - ))) { - fmt::print("{:#x}" PRIX64 " {}\n", runtime_address, instruction.text); - offset += instruction.info.length; - runtime_address += instruction.info.length; - } } void Linker::LoadDynamicInfo(Module* m) @@ -316,7 +304,7 @@ void Linker::LoadDynamicInfo(Module* m) break; case DT_SCE_IMPORT_LIB_ATTR: //The upper 32-bits should contain the module index multiplied by 0x10000. The lower 32-bits should be a constant 0x9. - LOG_INFO_IF(debug_loader, "unsupported DT_SCE_IMPORT_LIB_ATTR value = ..........: {:#018x}\n", dyn->d_un.d_val); + LOG_INFO_IF(debug_loader, "unsupported DT_SCE_IMPORT_LIB_ATTR value = ......: {:#018x}\n", dyn->d_un.d_val); break; case DT_SCE_ORIGINAL_FILENAME: m->dynamic_info.filename = m->dynamic_info.str_table + dyn->d_un.d_val; @@ -507,7 +495,7 @@ static void relocate(u32 idx, elf_relocation* rel, Module* m, bool isJmpRel) { case R_X86_64_RELATIVE: if (symbol != 0) // should be always zero { - LOG_INFO_IF(debug_loader, "R_X86_64_RELATIVE symbol not zero = {:#010x}\n", type, symbol); + //LOG_INFO_IF(debug_loader, "R_X86_64_RELATIVE symbol not zero = {:#010x}\n", type, symbol);//found it openorbis but i am not sure it worth logging } rel_value = rel_base_virtual_addr + addend; rel_isResolved = true; diff --git a/src/core/linker.h b/src/core/linker.h index 0d2672c3..5f1e9a37 100644 --- a/src/core/linker.h +++ b/src/core/linker.h @@ -43,6 +43,11 @@ struct LibraryInfo { std::string enc_id; }; +struct PS4ThreadLocal { + u64 image_virtual_addr = 0; + u64 image_size = 0; + u64 handler_virtual_addr = 0; +}; struct DynamicModuleInfo { void* hash_table = nullptr; u64 hash_table_size = 0; @@ -99,6 +104,8 @@ struct Module { Loader::SymbolsResolver export_sym; Loader::SymbolsResolver import_sym; + + PS4ThreadLocal tls; }; class Linker { From 724c56d8aa07782615023b1e9b288d086d2b9db5 Mon Sep 17 00:00:00 2001 From: Stefanos Kornilios Mitsis Poiitidis Date: Sat, 20 Jan 2024 14:29:23 +0200 Subject: [PATCH 4/7] Basic TLS with patching + int 0x80 --- src/common/log.cpp | 26 +++++++++++++++++++ src/core/linker.cpp | 62 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/src/common/log.cpp b/src/common/log.cpp index eba58f6f..2a3c5114 100644 --- a/src/common/log.cpp +++ b/src/common/log.cpp @@ -19,8 +19,34 @@ void Flush() { spdlog::details::registry::instance().flush_all(); } +thread_local uint8_t TLS[1024]; + +uint64_t tls_access(int64_t tls_offset) { + if (tls_offset == 0) { + return (uint64_t)TLS; + } +} + #ifdef _WIN64 static LONG WINAPI ExceptionHandler(PEXCEPTION_POINTERS pExp) noexcept { + if (*(uint8_t *)pExp->ContextRecord->Rip == 0xcd) { + int reg = *(uint8_t *)(pExp->ContextRecord->Rip + 1) - 0x80; + int sizes = *(uint8_t *)(pExp->ContextRecord->Rip + 2); + int pattern_size = sizes & 0xF; + int imm_size = sizes >> 4; + + int64_t tls_offset; + if (imm_size == 4) + tls_offset = *(int32_t *)(pExp->ContextRecord->Rip + pattern_size); + else + tls_offset = *(int64_t *)(pExp->ContextRecord->Rip + pattern_size); + + (&pExp->ContextRecord->Rax)[reg] = tls_access(tls_offset); /* TLS_ACCESS */ + pExp->ContextRecord->Rip += pattern_size + imm_size; + + return EXCEPTION_CONTINUE_EXECUTION; + } + const u32 ec = pExp->ExceptionRecord->ExceptionCode; switch (ec) { case EXCEPTION_ACCESS_VIOLATION: { diff --git a/src/core/linker.cpp b/src/core/linker.cpp index fdedbee5..cc35c884 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -95,8 +95,62 @@ Module* Linker::FindModule(/*u32 id*/) return &m_modules[0]; } -void Linker::LoadModuleToMemory(Module* m) -{ +struct TLSPattern{ + uint8_t pattern[5]; + uint8_t pattern_size; + uint8_t imm_size; + uint8_t target_reg; +}; + +constexpr TLSPattern tls_patterns[] = { + {{0x64, 0x48, 0xA1}, 3, 8, 0}, // 64 48 A1 | 00 00 00 00 00 00 00 00 # mov rax, qword ptr fs:[64b imm] + + {{0x64, 0x48, 0x8B, 0x4, 0x25}, 5, 4, 0}, // 64 48 8B 04 25 | 00 00 00 00 # mov rax,qword ptr fs:[0] + {{0x64, 0x48, 0x8B, 0xC, 0x25}, 5, 4, 1}, // rcx + {{0x64, 0x48, 0x8B, 0x14, 0x25}, 5, 4, 2}, // rdx + {{0x64, 0x48, 0x8B, 0x1C, 0x25}, 5, 4, 3}, // rbx + {{0x64, 0x48, 0x8B, 0x24, 0x25}, 5, 4, 4}, // rsp + {{0x64, 0x48, 0x8B, 0x2C, 0x25}, 5, 4, 5}, // rbp + {{0x64, 0x48, 0x8B, 0x34, 0x25}, 5, 4, 6}, // rsi + {{0x64, 0x48, 0x8B, 0x3C, 0x25}, 5, 4, 7}, // rdi + {{0x64, 0x4C, 0x8B, 0x4, 0x25}, 5, 4, 8}, // r8 + {{0x64, 0x4C, 0x8B, 0xC, 0x25}, 5, 4, 9}, // r9 + {{0x64, 0x4C, 0x8B, 0x14, 0x25}, 5, 4, 10},// r10 + {{0x64, 0x4C, 0x8B, 0x1C, 0x25}, 5, 4, 11},// r11 + {{0x64, 0x4C, 0x8B, 0x24, 0x25}, 5, 4, 12},// r12 + {{0x64, 0x4C, 0x8B, 0x2C, 0x25}, 5, 4, 13},// r13 + {{0x64, 0x4C, 0x8B, 0x34, 0x25}, 5, 4, 14},// r14 + {{0x64, 0x4C, 0x8B, 0x3C, 0x25}, 5, 4, 15},// r15 +}; + +void PatchTLS(u64 segment_addr, u64 segment_size) { + uint8_t* code = (uint8_t*)segment_addr; + auto remaining_size = segment_size; + + while (remaining_size) { + for (auto& tls_pattern : tls_patterns) { + auto total_size = tls_pattern.pattern_size + tls_pattern.imm_size; + if (remaining_size >= total_size) { + if (memcmp(code, tls_pattern.pattern, tls_pattern.pattern_size) == 0) { + if (tls_pattern.imm_size == 4) + printf("PATTERN32 FOUND @ %p, reg: %d offset: %X\n", code, tls_pattern.target_reg, *(uint32_t*)(code + tls_pattern.pattern_size)); + else + printf("PATTERN64 FOUND @ %p, reg: %d offset: %lX\n", code, tls_pattern.target_reg, *(uint64_t*)(code + tls_pattern.pattern_size)); + code[0] = 0xcd; + code[1] = 0x80 + tls_pattern.target_reg; + code[2] = tls_pattern.pattern_size | (tls_pattern.imm_size << 4); + code += total_size - 1; + remaining_size -= total_size - 1; + break; + } + } + } + code++; + remaining_size--; + } +} + +void Linker::LoadModuleToMemory(Module* m) { //get elf header, program header const auto elf_header = m->elf.GetElfHeader(); const auto elf_pheader = m->elf.GetProgramHeader(); @@ -130,6 +184,10 @@ void Linker::LoadModuleToMemory(Module* m) LOG_INFO_IF(debug_loader, "segment_mode ..........: {}\n", segment_mode); m->elf.LoadSegment(segment_addr, elf_pheader[i].p_offset, segment_file_size); + + if (elf_pheader[i].p_flags & PF_EXEC) { + PatchTLS(segment_addr, segment_file_size); + } } else { From 57ddf939d472bb801eb51725b4355d60d9978c8e Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Wed, 24 Jan 2024 14:46:02 +0200 Subject: [PATCH 5/7] orbis weird sceVideoOut calls --- src/core/PS4/HLE/Graphics/video_out.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/core/PS4/HLE/Graphics/video_out.cpp b/src/core/PS4/HLE/Graphics/video_out.cpp index c87c1a87..7fdb2193 100644 --- a/src/core/PS4/HLE/Graphics/video_out.cpp +++ b/src/core/PS4/HLE/Graphics/video_out.cpp @@ -330,5 +330,14 @@ void videoOutRegisterLib(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("zgXifHT9ErY", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutIsFlipPending); LIB_FUNCTION("N5KDtkIjjJ4", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutUnregisterBuffers); LIB_FUNCTION("uquVH4-Du78", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutClose); + + // openOrbis appears to have libSceVideoOut_v1 module libSceVideoOut_v1.1 + LIB_FUNCTION("Up36PTk687E", "libSceVideoOut", 1, "libSceVideoOut", 1, 1, sceVideoOutOpen); + LIB_FUNCTION("CBiu4mCE1DA", "libSceVideoOut", 1, "libSceVideoOut", 1, 1, sceVideoOutSetFlipRate); + LIB_FUNCTION("HXzjK9yI30k", "libSceVideoOut", 1, "libSceVideoOut", 1, 1, sceVideoOutAddFlipEvent); + LIB_FUNCTION("i6-sR91Wt-4", "libSceVideoOut", 1, "libSceVideoOut", 1, 1, sceVideoOutSetBufferAttribute); + LIB_FUNCTION("w3BY+tAEiQY", "libSceVideoOut", 1, "libSceVideoOut", 1, 1, sceVideoOutRegisterBuffers); + LIB_FUNCTION("U46NwOiJpys", "libSceVideoOut", 1, "libSceVideoOut", 1, 1, sceVideoOutSubmitFlip); + LIB_FUNCTION("SbU3dwp80lQ", "libSceVideoOut", 1, "libSceVideoOut", 1, 1, sceVideoOutGetFlipStatus); } } // namespace HLE::Libs::Graphics::VideoOut From ff43fec76a99d5e55209a4bcaecfa34b70d68ebe Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Fri, 26 Jan 2024 18:01:27 +0200 Subject: [PATCH 6/7] some fs work for openorbis (WIP) --- CMakeLists.txt | 2 +- src/common/io_file.cpp | 138 ++++++++++++++++++ src/common/io_file.h | 41 ++++++ src/core/file_sys/fs.h | 3 +- .../hle/libraries/libkernel/file_system.cpp | 40 ++++- .../hle/libraries/libkernel/file_system.h | 7 +- 6 files changed, 225 insertions(+), 6 deletions(-) create mode 100644 src/common/io_file.cpp create mode 100644 src/common/io_file.h diff --git a/CMakeLists.txt b/CMakeLists.txt index adede79d..7db7e5b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,7 +147,7 @@ add_executable(shadps4 src/emuTimer.h src/core/hle/libraries/libkernel/time_management.cpp src/core/hle/libraries/libkernel/time_management.h -) + "src/common/io_file.cpp" "src/common/io_file.h") create_target_directory_groups(shadps4) diff --git a/src/common/io_file.cpp b/src/common/io_file.cpp new file mode 100644 index 00000000..86874c08 --- /dev/null +++ b/src/common/io_file.cpp @@ -0,0 +1,138 @@ +#include "io_file.h" + +//#include "helpers.hpp" + +#ifdef _MSC_VER +// 64 bit offsets for MSVC +#define fseeko _fseeki64 +#define ftello _ftelli64 +#define fileno _fileno + +#pragma warning(disable : 4996) +#endif + +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif + +#ifdef WIN32 +#include // For _chsize_s +#else +#include // For ftruncate +#endif + +IOFile::IOFile(const std::filesystem::path& path, const char* permissions) : handle(nullptr) { + open(path, permissions); +} + +bool IOFile::open(const std::filesystem::path& path, const char* permissions) { + const auto str = + path.string(); // For some reason converting paths directly with c_str() doesn't work + return open(str.c_str(), permissions); +} + +bool IOFile::open(const char* filename, const char* permissions) { + // If this IOFile is already bound to an open file descriptor, release the file descriptor + // To avoid leaking it and/or erroneously locking the file + if (isOpen()) { + close(); + } + + handle = std::fopen(filename, permissions); + return isOpen(); +} + +void IOFile::close() { + if (isOpen()) { + fclose(handle); + handle = nullptr; + } +} + +std::pair IOFile::read(void* data, std::size_t length, std::size_t dataSize) { + if (!isOpen()) { + return {false, std::numeric_limits::max()}; + } + + if (length == 0) + return {true, 0}; + return {true, std::fread(data, dataSize, length, handle)}; +} + +std::pair IOFile::write(const void* data, std::size_t length, + std::size_t dataSize) { + if (!isOpen()) { + return {false, std::numeric_limits::max()}; + } + + if (length == 0) { + return {true, 0}; + } else { + return {true, std::fwrite(data, dataSize, length, handle)}; + } +} + +std::pair IOFile::readBytes(void* data, std::size_t count) { + return read(data, count, sizeof(std::uint8_t)); +} +std::pair IOFile::writeBytes(const void* data, std::size_t count) { + return write(data, count, sizeof(std::uint8_t)); +} + +std::optional IOFile::size() { + if (!isOpen()) + return {}; + + std::uint64_t pos = ftello(handle); + if (fseeko(handle, 0, SEEK_END) != 0) { + return {}; + } + + std::uint64_t size = ftello(handle); + if ((size != pos) && (fseeko(handle, pos, SEEK_SET) != 0)) { + return {}; + } + + return size; +} + +bool IOFile::seek(std::int64_t offset, int origin) { + if (!isOpen() || fseeko(handle, offset, origin) != 0) + return false; + + return true; +} + +bool IOFile::flush() { + if (!isOpen() || fflush(handle)) + return false; + + return true; +} + +bool IOFile::rewind() { + return seek(0, SEEK_SET); +} +FILE* IOFile::getHandle() { + return handle; +} + +void IOFile::setAppDataDir(const std::filesystem::path& dir) { + //if (dir == "") + // Helpers::panic("Failed to set app data directory"); + appData = dir; +} + +bool IOFile::setSize(std::uint64_t size) { + if (!isOpen()) + return false; + bool success; + +#ifdef WIN32 + success = _chsize_s(_fileno(handle), size) == 0; +#else + success = ftruncate(fileno(handle), size) == 0; +#endif + fflush(handle); + return success; +} \ No newline at end of file diff --git a/src/common/io_file.h b/src/common/io_file.h new file mode 100644 index 00000000..85f7a78e --- /dev/null +++ b/src/common/io_file.h @@ -0,0 +1,41 @@ +#pragma once +#include +#include +#include + +class IOFile { + FILE* handle = nullptr; + static inline std::filesystem::path appData =""; // Directory for holding app data. AppData on Windows + +public: + IOFile() : handle(nullptr) {} + IOFile(FILE* handle) : handle(handle) {} + IOFile(const std::filesystem::path& path, const char* permissions = "rb"); + + bool isOpen() { + return handle != nullptr; + } + bool open(const std::filesystem::path& path, const char* permissions = "rb"); + bool open(const char* filename, const char* permissions = "rb"); + void close(); + + std::pair read(void* data, std::size_t length, std::size_t dataSize); + std::pair readBytes(void* data, std::size_t count); + + std::pair write(const void* data, std::size_t length, std::size_t dataSize); + std::pair writeBytes(const void* data, std::size_t count); + + std::optional size(); + + bool seek(std::int64_t offset, int origin = SEEK_SET); + bool rewind(); + bool flush(); + FILE* getHandle(); + static void setAppDataDir(const std::filesystem::path& dir); + static std::filesystem::path getAppData() { + return appData; + } + + // Sets the size of the file to "size" and returns whether it succeeded or not + bool setSize(std::uint64_t size); +}; \ No newline at end of file diff --git a/src/core/file_sys/fs.h b/src/core/file_sys/fs.h index 3255cc52..45bf718f 100644 --- a/src/core/file_sys/fs.h +++ b/src/core/file_sys/fs.h @@ -4,6 +4,7 @@ #include #include "common/fs_file.h" +#include namespace Core::FileSys { @@ -32,7 +33,7 @@ struct File { std::atomic_bool isDirectory; std::string m_host_name; std::string m_guest_name; - Common::FS::File f; + IOFile f; //std::vector dirents; u32 dirents_index; std::mutex m_mutex; diff --git a/src/core/hle/libraries/libkernel/file_system.cpp b/src/core/hle/libraries/libkernel/file_system.cpp index 271cf363..57d08cae 100644 --- a/src/core/hle/libraries/libkernel/file_system.cpp +++ b/src/core/hle/libraries/libkernel/file_system.cpp @@ -2,6 +2,9 @@ #include "common/debug.h" #include "core/hle/libraries/libkernel/file_system.h" #include "core/hle/libraries/libs.h" +#include +#include +#include namespace Core::Libraries::LibKernel { @@ -9,10 +12,25 @@ constexpr bool log_file_fs = true; // disable it to disable logging int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) { LOG_INFO_IF(log_file_fs, "sceKernelOpen path = {} flags = {:#x} mode = {:#x}\n", path, flags, mode); - return 0; + auto* h = Common::Singleton::Instance(); + auto* mnt = Common::Singleton::Instance(); + + // only open files support! + u32 handle = h->createHandle(); + auto* file = h->getFile(handle); + file->m_guest_name = path; + file->m_host_name = mnt->getHostFile(file->m_guest_name); + + bool result = file->f.open(file->m_host_name); + if (!result) { + h->deleteHandle(handle); + return SCE_KERNEL_ERROR_EACCES; + } + file->isOpened = true; + return handle; } -int PS4_SYSV_ABI open(const char* path, int flags, /* SceKernelMode*/ u16 mode) { +int PS4_SYSV_ABI posix_open(const char* path, int flags, /* SceKernelMode*/ u16 mode) { LOG_INFO_IF(log_file_fs, "posix open redirect to sceKernelOpen\n"); int result = sceKernelOpen(path, flags, mode); if (result < 0) { @@ -21,9 +39,25 @@ int PS4_SYSV_ABI open(const char* path, int flags, /* SceKernelMode*/ u16 mode) return result; } +size_t PS4_SYSV_ABI _readv(int d, const SceKernelIovec* iov, int iovcnt) { + auto* h = Common::Singleton::Instance(); + auto* file = h->getFile(d); + size_t total_read = 0; + file->m_mutex.lock(); + for (int i = 0; i < iovcnt; i++) { + total_read += file->f.readBytes(iov[i].iov_base,iov[i].iov_len).second; + } + file->m_mutex.unlock(); + return total_read; +} + void fileSystemSymbolsRegister(Loader::SymbolsResolver* sym) { LIB_FUNCTION("1G3lF1Gg1k8", "libkernel", 1, "libkernel", 1, 1, sceKernelOpen); - LIB_FUNCTION("wuCroIGjt2g", "libScePosix", 1, "libkernel", 1, 1, open); + LIB_FUNCTION("wuCroIGjt2g", "libScePosix", 1, "libkernel", 1, 1, posix_open); + LIB_FUNCTION("+WRlkKjZvag", "libkernel", 1, "libkernel", 1, 1, _readv); + + // openOrbis (to check if it is valid out of OpenOrbis + LIB_FUNCTION("6c3rCVE-fTU", "libkernel", 1, "libkernel", 1, 1, posix_open); // _open shoudld be equal to open function } } // namespace Core::Libraries::LibKernel diff --git a/src/core/hle/libraries/libkernel/file_system.h b/src/core/hle/libraries/libkernel/file_system.h index f5be1d1e..8a3ef3bb 100644 --- a/src/core/hle/libraries/libkernel/file_system.h +++ b/src/core/hle/libraries/libkernel/file_system.h @@ -8,9 +8,14 @@ class SymbolsResolver; namespace Core::Libraries::LibKernel { +struct SceKernelIovec { + void *iov_base; + size_t iov_len; +}; + int PS4_SYSV_ABI sceKernelOpen(const char *path, int flags, /* SceKernelMode*/ u16 mode); -int PS4_SYSV_ABI open(const char *path, int flags, /* SceKernelMode*/ u16 mode); +int PS4_SYSV_ABI posix_open(const char *path, int flags, /* SceKernelMode*/ u16 mode); void fileSystemSymbolsRegister(Loader::SymbolsResolver *sym); From 6de4736e50b2c2b911b82cfe1f0614f755a88ef8 Mon Sep 17 00:00:00 2001 From: Stefanos Kornilios Mitsis Poiitidis Date: Sat, 27 Jan 2024 16:59:59 +0200 Subject: [PATCH 7/7] skip over 0x66 prefixes in TLS --- src/common/log.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/common/log.cpp b/src/common/log.cpp index 2a3c5114..535d4bd0 100644 --- a/src/common/log.cpp +++ b/src/common/log.cpp @@ -29,6 +29,9 @@ uint64_t tls_access(int64_t tls_offset) { #ifdef _WIN64 static LONG WINAPI ExceptionHandler(PEXCEPTION_POINTERS pExp) noexcept { + auto orig_rip = pExp->ContextRecord->Rip; + while (*(uint8_t *)pExp->ContextRecord->Rip == 0x66) pExp->ContextRecord->Rip++; + if (*(uint8_t *)pExp->ContextRecord->Rip == 0xcd) { int reg = *(uint8_t *)(pExp->ContextRecord->Rip + 1) - 0x80; int sizes = *(uint8_t *)(pExp->ContextRecord->Rip + 2); @@ -47,6 +50,7 @@ static LONG WINAPI ExceptionHandler(PEXCEPTION_POINTERS pExp) noexcept { return EXCEPTION_CONTINUE_EXECUTION; } + pExp->ContextRecord->Rip = orig_rip; const u32 ec = pExp->ExceptionRecord->ExceptionCode; switch (ec) { case EXCEPTION_ACCESS_VIOLATION: {