linker: Fix buggy R_X86_64_DTPMOD64

This commit is contained in:
raphaelthegreat 2024-06-03 12:52:49 +03:00
parent 2bbe1349c2
commit 511595aca7
6 changed files with 95 additions and 37 deletions

View File

@ -4,6 +4,7 @@
#include <chrono> #include <chrono>
#include <thread> #include <thread>
#include "common/assert.h" #include "common/assert.h"
#include "common/error.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/singleton.h" #include "common/singleton.h"
#include "core/libraries/error_codes.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, int PS4_SYSV_ABI sceKernelConvertUtcToLocaltime(time_t time, time_t* local_time,
struct OrbisTimesec* st, unsigned long* dst_sec) { struct OrbisTimesec* st, unsigned long* dst_sec) {
return ORBIS_OK;
LOG_TRACE(Kernel, "Called"); 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(); const auto* time_zone = std::chrono::current_zone();
auto info = time_zone->get_info(std::chrono::system_clock::now()); auto info = time_zone->get_info(std::chrono::system_clock::now());

View File

@ -39,44 +39,66 @@ u64 PS4_SYSV_ABI sceKernelReadTsc() {
int PS4_SYSV_ABI sceKernelGettimeofday(SceKernelTimeval* tp) {} int PS4_SYSV_ABI sceKernelGettimeofday(SceKernelTimeval* tp) {}
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) #define FILETIME_1970 116444736000000000ull /* seconds between 1/1/1601 and 1/1/1970 */
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 #define HECTONANOSEC_PER_SEC 10000000ull
#else
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
#endif
struct timezone { int PS4_SYSV_ABI getntptimeofday(struct timespec *tp, struct timezone *z) {
int tz_minuteswest; /* minutes W of Greenwich */ int res = 0;
int tz_dsttime; /* type of dst correction */ union {
}; unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */
FILETIME ft;
} _now;
TIME_ZONE_INFORMATION TimeZoneInformation;
DWORD tzi;
struct timeval { if (z != NULL)
long tv_sec; {
long tv_usec; 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 */ if (tp != NULL) {
static const unsigned __int64 epoch = 116444736000000000ULL; typedef void (WINAPI * GetSystemTimeAsFileTime_t)(LPFILETIME);
static GetSystemTimeAsFileTime_t GetSystemTimeAsFileTime_p /* = 0 */;
/* /* Set function pointer during first call */
* FILETIME represents the number of 100-nanosecond intervals since GetSystemTimeAsFileTime_t get_time =
* January 1, 1601 (UTC). __atomic_load_n (&GetSystemTimeAsFileTime_p, __ATOMIC_RELAXED);
*/ if (get_time == NULL) {
#define FILETIME_UNITS_PER_SEC 10000000L /* Use GetSystemTimePreciseAsFileTime() if available (Windows 8 or later) */
#define FILETIME_UNITS_PER_USEC 10 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) { get_time (&_now.ft); /* 100 nano-seconds since 1-1-1601 */
FILETIME file_time; _now.ns100 -= FILETIME_1970; /* 100 nano-seconds since 1-1-1970 */
ULARGE_INTEGER ularge; 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); int PS4_SYSV_ABI gettimeofday(struct timeval *p, struct timezone *z) {
ularge.LowPart = file_time.dwLowDateTime; struct timespec tp;
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);
if (getntptimeofday (&tp, z))
return -1;
p->tv_sec=tp.tv_sec;
p->tv_usec=(tp.tv_nsec/1000);
return 0; return 0;
} }

View File

@ -16,12 +16,23 @@ struct SceKernelTimeval {
s64 tv_usec; 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 sceKernelGetTscFrequency();
u64 PS4_SYSV_ABI sceKernelGetProcessTime(); u64 PS4_SYSV_ABI sceKernelGetProcessTime();
u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounter(); u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounter();
u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounterFrequency(); u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounterFrequency();
u64 PS4_SYSV_ABI sceKernelReadTsc(); u64 PS4_SYSV_ABI sceKernelReadTsc();
int PS4_SYSV_ABI sceKernelGettimeofday(SceKernelTimeval* tp); int PS4_SYSV_ABI sceKernelGettimeofday(SceKernelTimeval* tp);
int PS4_SYSV_ABI gettimeofday(struct timeval* tp, struct timezone* tzp);
void timeSymbolsRegister(Core::Loader::SymbolsResolver* sym); void timeSymbolsRegister(Core::Loader::SymbolsResolver* sym);

View File

@ -71,8 +71,8 @@ void Linker::Execute() {
InitTlsForThread(true); InitTlsForThread(true);
// Relocate all modules // Relocate all modules
for (const auto& m : m_modules) { for (u32 i = 1; const auto& m : m_modules) {
Relocate(m.get()); Relocate(i, m.get());
} }
// Start shared library modules // 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(); 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) { module->ForEachRelocation([&](elf_relocation* rel, bool isJmpRel) {
auto type = rel->GetType(); auto type = rel->GetType();
auto symbol = rel->GetSymbol(); auto symbol = rel->GetSymbol();
@ -134,7 +134,7 @@ void Linker::Relocate(Module* module) {
rel_is_resolved = true; rel_is_resolved = true;
break; break;
case R_X86_64_DTPMOD64: case R_X86_64_DTPMOD64:
rel_value = reinterpret_cast<uint64_t>(module); rel_value = static_cast<uint64_t>(index);
rel_is_resolved = true; rel_is_resolved = true;
rel_sym_type = Loader::SymbolType::Tls; rel_sym_type = Loader::SymbolType::Tls;
break; break;
@ -257,7 +257,7 @@ void* Linker::TlsGetAddr(u64 module_index, u64 offset) {
ASSERT_MSG(dtv_table[0].counter == dtv_generation_counter, ASSERT_MSG(dtv_table[0].counter == dtv_generation_counter,
"Reallocation of DTV table is not supported"); "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"); ASSERT_MSG(module, "DTV allocation is not supported");
return module; return module;
} }

View File

@ -54,7 +54,7 @@ public:
Module* LoadModule(const std::filesystem::path& elf_name); 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, void Resolve(const std::string& name, Loader::SymbolType type,
Module* module, Loader::SymbolRecord* return_info); Module* module, Loader::SymbolRecord* return_info);
void Execute(); void Execute();

View File

@ -321,6 +321,10 @@ void TextureCache::UntrackImage(Image& image, ImageId image_id) {
void TextureCache::UpdatePagesCachedCount(VAddr addr, u64 size, s32 delta) { void TextureCache::UpdatePagesCachedCount(VAddr addr, u64 size, s32 delta) {
std::scoped_lock lk{mutex}; std::scoped_lock lk{mutex};
const u64 num_pages = ((addr + size - 1) >> PageShift) - (addr >> PageShift) + 1; 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_start = addr >> PageShift;
const u64 page_end = page_start + num_pages; const u64 page_end = page_start + num_pages;