From 511595aca79778313ba4a2e855fafeb59f73a85b Mon Sep 17 00:00:00 2001 From: raphaelthegreat <47210458+raphaelthegreat@users.noreply.github.com> Date: Mon, 3 Jun 2024 12:52:49 +0300 Subject: [PATCH] linker: Fix buggy R_X86_64_DTPMOD64 --- src/core/libraries/kernel/libkernel.cpp | 21 +++++ src/core/libraries/kernel/time_management.cpp | 84 ++++++++++++------- src/core/libraries/kernel/time_management.h | 11 +++ src/core/linker.cpp | 10 +-- src/core/linker.h | 2 +- .../texture_cache/texture_cache.cpp | 4 + 6 files changed, 95 insertions(+), 37 deletions(-) diff --git a/src/core/libraries/kernel/libkernel.cpp b/src/core/libraries/kernel/libkernel.cpp index b52e6b4f..d4ff41c6 100644 --- a/src/core/libraries/kernel/libkernel.cpp +++ b/src/core/libraries/kernel/libkernel.cpp @@ -4,6 +4,7 @@ #include #include #include "common/assert.h" +#include "common/error.h" #include "common/logging/log.h" #include "common/singleton.h" #include "core/libraries/error_codes.h" @@ -165,7 +166,27 @@ s64 PS4_SYSV_ABI ps4__write(int d, const void* buf, std::size_t nbytes) { int PS4_SYSV_ABI sceKernelConvertUtcToLocaltime(time_t time, time_t* local_time, struct OrbisTimesec* st, unsigned long* dst_sec) { + return ORBIS_OK; LOG_TRACE(Kernel, "Called"); + timeval val; + timezone tmz; + gettimeofday(&val, &tmz); + + if (local_time) { + *local_time = (tmz.tz_minuteswest + tmz.tz_dsttime) * 60 + time; + } + + if (st) { + st->t = time; + st->dst_sec = tmz.tz_dsttime * 60; + st->west_sec = tmz.tz_minuteswest * 60; + } + + if (dst_sec) { + *dst_sec = tmz.tz_dsttime * 60; + } + return ORBIS_OK; + const auto* time_zone = std::chrono::current_zone(); auto info = time_zone->get_info(std::chrono::system_clock::now()); diff --git a/src/core/libraries/kernel/time_management.cpp b/src/core/libraries/kernel/time_management.cpp index 74b5b94c..0a1b1156 100644 --- a/src/core/libraries/kernel/time_management.cpp +++ b/src/core/libraries/kernel/time_management.cpp @@ -39,44 +39,66 @@ u64 PS4_SYSV_ABI sceKernelReadTsc() { int PS4_SYSV_ABI sceKernelGettimeofday(SceKernelTimeval* tp) {} -#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) -#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 -#else -#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL -#endif +#define FILETIME_1970 116444736000000000ull /* seconds between 1/1/1601 and 1/1/1970 */ +#define HECTONANOSEC_PER_SEC 10000000ull -struct timezone { - int tz_minuteswest; /* minutes W of Greenwich */ - int tz_dsttime; /* type of dst correction */ -}; +int PS4_SYSV_ABI getntptimeofday(struct timespec *tp, struct timezone *z) { + int res = 0; + union { + unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */ + FILETIME ft; + } _now; + TIME_ZONE_INFORMATION TimeZoneInformation; + DWORD tzi; -struct timeval { - long tv_sec; - long tv_usec; -}; + if (z != NULL) + { + if ((tzi = GetTimeZoneInformation(&TimeZoneInformation)) != TIME_ZONE_ID_INVALID) { + z->tz_minuteswest = TimeZoneInformation.Bias; + if (tzi == TIME_ZONE_ID_DAYLIGHT) + z->tz_dsttime = 1; + else + z->tz_dsttime = 0; + } + else + { + z->tz_minuteswest = 0; + z->tz_dsttime = 0; + } + } -/* FILETIME of Jan 1 1970 00:00:00, the PostgreSQL epoch */ -static const unsigned __int64 epoch = 116444736000000000ULL; + if (tp != NULL) { + typedef void (WINAPI * GetSystemTimeAsFileTime_t)(LPFILETIME); + static GetSystemTimeAsFileTime_t GetSystemTimeAsFileTime_p /* = 0 */; -/* - * FILETIME represents the number of 100-nanosecond intervals since - * January 1, 1601 (UTC). - */ -#define FILETIME_UNITS_PER_SEC 10000000L -#define FILETIME_UNITS_PER_USEC 10 + /* Set function pointer during first call */ + GetSystemTimeAsFileTime_t get_time = + __atomic_load_n (&GetSystemTimeAsFileTime_p, __ATOMIC_RELAXED); + if (get_time == NULL) { + /* Use GetSystemTimePreciseAsFileTime() if available (Windows 8 or later) */ + get_time = (GetSystemTimeAsFileTime_t)(intptr_t) GetProcAddress ( + GetModuleHandle ("kernel32.dll"), + "GetSystemTimePreciseAsFileTime"); /* <1us precision on Windows 10 */ + if (get_time == NULL) + get_time = GetSystemTimeAsFileTime; /* >15ms precision on Windows 10 */ + __atomic_store_n (&GetSystemTimeAsFileTime_p, get_time, __ATOMIC_RELAXED); + } -int PS4_SYSV_ABI gettimeofday(struct timeval* tp, struct timezone* tzp) { - FILETIME file_time; - ULARGE_INTEGER ularge; + get_time (&_now.ft); /* 100 nano-seconds since 1-1-1601 */ + _now.ns100 -= FILETIME_1970; /* 100 nano-seconds since 1-1-1970 */ + tp->tv_sec = _now.ns100 / HECTONANOSEC_PER_SEC; /* seconds since 1-1-1970 */ + tp->tv_nsec = (long) (_now.ns100 % HECTONANOSEC_PER_SEC) * 100; /* nanoseconds */ + } + return res; +} - GetSystemTimePreciseAsFileTime(&file_time); - ularge.LowPart = file_time.dwLowDateTime; - ularge.HighPart = file_time.dwHighDateTime; - - tp->tv_sec = (long)((ularge.QuadPart - epoch) / FILETIME_UNITS_PER_SEC); - tp->tv_usec = - (long)(((ularge.QuadPart - epoch) % FILETIME_UNITS_PER_SEC) / FILETIME_UNITS_PER_USEC); +int PS4_SYSV_ABI gettimeofday(struct timeval *p, struct timezone *z) { + struct timespec tp; + if (getntptimeofday (&tp, z)) + return -1; + p->tv_sec=tp.tv_sec; + p->tv_usec=(tp.tv_nsec/1000); return 0; } diff --git a/src/core/libraries/kernel/time_management.h b/src/core/libraries/kernel/time_management.h index 808ba638..bc081b93 100644 --- a/src/core/libraries/kernel/time_management.h +++ b/src/core/libraries/kernel/time_management.h @@ -16,12 +16,23 @@ struct SceKernelTimeval { s64 tv_usec; }; +struct timezone { + int tz_minuteswest; /* minutes W of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +struct timeval { + long tv_sec; + long tv_usec; +}; + u64 PS4_SYSV_ABI sceKernelGetTscFrequency(); u64 PS4_SYSV_ABI sceKernelGetProcessTime(); u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounter(); u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounterFrequency(); u64 PS4_SYSV_ABI sceKernelReadTsc(); int PS4_SYSV_ABI sceKernelGettimeofday(SceKernelTimeval* tp); +int PS4_SYSV_ABI gettimeofday(struct timeval* tp, struct timezone* tzp); void timeSymbolsRegister(Core::Loader::SymbolsResolver* sym); diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 7065a792..d5ecb793 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -71,8 +71,8 @@ void Linker::Execute() { InitTlsForThread(true); // Relocate all modules - for (const auto& m : m_modules) { - Relocate(m.get()); + for (u32 i = 1; const auto& m : m_modules) { + Relocate(i, m.get()); } // Start shared library modules @@ -113,7 +113,7 @@ Module* Linker::LoadModule(const std::filesystem::path& elf_name) { return m_modules.emplace_back(std::move(module)).get(); } -void Linker::Relocate(Module* module) { +void Linker::Relocate(u32 index, Module* module) { module->ForEachRelocation([&](elf_relocation* rel, bool isJmpRel) { auto type = rel->GetType(); auto symbol = rel->GetSymbol(); @@ -134,7 +134,7 @@ void Linker::Relocate(Module* module) { rel_is_resolved = true; break; case R_X86_64_DTPMOD64: - rel_value = reinterpret_cast(module); + rel_value = static_cast(index); rel_is_resolved = true; rel_sym_type = Loader::SymbolType::Tls; break; @@ -257,7 +257,7 @@ void* Linker::TlsGetAddr(u64 module_index, u64 offset) { ASSERT_MSG(dtv_table[0].counter == dtv_generation_counter, "Reallocation of DTV table is not supported"); - void* module = dtv_table[module_index - 1].pointer; + void* module = dtv_table[module_index + 1].pointer; ASSERT_MSG(module, "DTV allocation is not supported"); return module; } diff --git a/src/core/linker.h b/src/core/linker.h index 385ac118..7de851bd 100644 --- a/src/core/linker.h +++ b/src/core/linker.h @@ -54,7 +54,7 @@ public: Module* LoadModule(const std::filesystem::path& elf_name); - void Relocate(Module* module); + void Relocate(u32 index, Module* module); void Resolve(const std::string& name, Loader::SymbolType type, Module* module, Loader::SymbolRecord* return_info); void Execute(); diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index 85b44018..85891ec4 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -321,6 +321,10 @@ void TextureCache::UntrackImage(Image& image, ImageId image_id) { void TextureCache::UpdatePagesCachedCount(VAddr addr, u64 size, s32 delta) { std::scoped_lock lk{mutex}; const u64 num_pages = ((addr + size - 1) >> PageShift) - (addr >> PageShift) + 1; + if (num_pages == 0) { + return; + } + const u64 page_start = addr >> PageShift; const u64 page_end = page_start + num_pages;