fix(libs): fix args sysv abi for types (windows)
This commit is contained in:
parent
d23e1ca84e
commit
b765cefa42
|
|
@ -37,9 +37,11 @@ void patchAccess(std::vector<PeSection>& sections, const TlsAccess& access, cons
|
|||
|
||||
PeDirectory WindowsTlsBuilder::Build(const std::vector<std::uint8_t>& source, const std::vector<Domain::ProgramHeader>& headers, const WindowsLoadImage& image, std::vector<PeSection>& sections, std::vector<std::uint32_t>& relocations, std::uint32_t& nextRva) const {
|
||||
const Domain::ProgramHeader* tls = nullptr;
|
||||
const Codegen::X64InstructionDecoder decoder;
|
||||
|
||||
std::vector<TlsAccess> accesses;
|
||||
std::set<std::uint32_t> branchTargets;
|
||||
const Codegen::X64InstructionDecoder decoder;
|
||||
|
||||
for (const auto& header : headers) {
|
||||
if (header.Type == 7) {
|
||||
if (tls != nullptr)
|
||||
|
|
@ -52,11 +54,13 @@ PeDirectory WindowsTlsBuilder::Build(const std::vector<std::uint8_t>& source, co
|
|||
const auto* bytes = source.data() + header.Offset + offset;
|
||||
const auto info = decoder.DecodeInstruction(bytes, header.FileSize - offset);
|
||||
const auto rva = image.GetRva(header.MappedAddress + offset, info.Length);
|
||||
|
||||
if (info.HasBranchTarget && !info.HasRipRelativeDisp) {
|
||||
const auto target = static_cast<std::int64_t>(rva) + static_cast<std::int64_t>(info.Length) + info.BranchDisp;
|
||||
if (target >= 0 && target <= std::numeric_limits<std::uint32_t>::max())
|
||||
branchTargets.insert(static_cast<std::uint32_t>(target));
|
||||
}
|
||||
|
||||
if (info.SegmentPrefix != 0) {
|
||||
const auto position = info.OpcodeOffset;
|
||||
if (info.SegmentPrefix != 0x64 || info.RexPrefix != 0x48 || info.Length - position != 7 || bytes[position] != 0x8b || bytes[position + 1] != 0x04 || bytes[position + 2] != 0x25 || Io::ReadU32(source, header.Offset + offset + position + 3) != 0)
|
||||
|
|
@ -66,36 +70,43 @@ PeDirectory WindowsTlsBuilder::Build(const std::vector<std::uint8_t>& source, co
|
|||
offset += info.Length;
|
||||
}
|
||||
}
|
||||
|
||||
if (tls == nullptr) {
|
||||
if (!accesses.empty())
|
||||
throw Domain::RelinkerException("Guest TLS access without PT_TLS");
|
||||
return {};
|
||||
}
|
||||
|
||||
if (tls->MemorySize == 0 || tls->FileSize > tls->MemorySize || tls->Offset > source.size() || tls->FileSize > source.size() - tls->Offset || !std::has_single_bit(tls->Alignment) || tls->Alignment > 8192 || tls->MemorySize > 0x7fff0000u)
|
||||
throw Domain::RelinkerException("Invalid or unsupported ELF TLS layout", tls->Offset);
|
||||
const auto alignment = std::max<std::uint64_t>(tls->Alignment, 16);
|
||||
const auto blockSize = CheckedRva((tls->MemorySize + alignment - 1) & ~(alignment - 1));
|
||||
const auto templateOffset = CheckedRva((64 + alignment - 1) & ~(alignment - 1));
|
||||
PeSection data{".gtls", nextRva, SectionRead | SectionWrite | 0x40u, std::vector<std::uint8_t>(templateOffset + blockSize + 16)};
|
||||
|
||||
const auto indexRva = nextRva + 40;
|
||||
const auto callbackTableRva = nextRva + 48;
|
||||
const auto templateRva = nextRva + templateOffset;
|
||||
const auto codeRva = AlignRva(nextRva + data.Data.size());
|
||||
|
||||
WindowsStubEmitter code(codeRva);
|
||||
const auto loadPointer = [&] {
|
||||
code.Rip({0x8b, 0x0d}, indexRva);
|
||||
code.Emit({0x65, 0x48, 0x8b, 0x04, 0x25, 0x58, 0, 0, 0, 0x48, 0x8b, 0x04, 0xc8, 0x48, 0x8d, 0x80});
|
||||
code.U32(blockSize);
|
||||
};
|
||||
|
||||
code.Emit({0x83, 0xfa, 1});
|
||||
const auto processAttach = code.Branch({0x0f, 0x84});
|
||||
code.Emit({0x83, 0xfa, 2});
|
||||
const auto skipCallback = code.Branch({0x0f, 0x85});
|
||||
code.PatchBranch(processAttach, code.GetRva());
|
||||
loadPointer();
|
||||
|
||||
code.Emit({0x48, 0x89, 0x00});
|
||||
code.PatchBranch(skipCallback, code.GetRva());
|
||||
code.Emit({0xc3});
|
||||
|
||||
for (const auto& access : accesses) {
|
||||
const auto target = branchTargets.upper_bound(access.Rva);
|
||||
if (target != branchTargets.end() && *target < access.Rva + access.Length)
|
||||
|
|
@ -106,16 +117,19 @@ PeDirectory WindowsTlsBuilder::Build(const std::vector<std::uint8_t>& source, co
|
|||
code.Emit({0x59, 0x48, 0x8d, 0xa4, 0x24, 0x80, 0, 0, 0});
|
||||
code.Rip({0xe9}, CheckedRva(access.Rva + access.Length));
|
||||
}
|
||||
|
||||
std::copy_n(source.begin() + tls->Offset, tls->FileSize, data.Data.begin() + templateOffset);
|
||||
const auto writeAddress = [&](const std::size_t offset, const std::uint32_t rva) {
|
||||
Io::WriteU64(data.Data, offset, ImageBase + rva);
|
||||
relocations.push_back(CheckedRva(data.Rva + offset));
|
||||
};
|
||||
|
||||
writeAddress(0, templateRva);
|
||||
writeAddress(8, CheckedRva(templateRva + blockSize + 16));
|
||||
writeAddress(16, indexRva);
|
||||
writeAddress(24, callbackTableRva);
|
||||
writeAddress(48, codeRva);
|
||||
|
||||
Io::WriteU32(data.Data, 36, static_cast<std::uint32_t>(std::bit_width(alignment)) << 20);
|
||||
const PeDirectory directory{data.Rva, 40};
|
||||
sections.push_back(std::move(data));
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include "prx/libc/include/general/VabiMacros.hpp"
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
typedef float __m128 __attribute__((__vector_size__(16), __aligned__(16)));
|
||||
|
|
@ -161,6 +162,7 @@ struct PthreadCondPrivate;
|
|||
using KernelSema = KernelSemaPrivate*;
|
||||
using KernelEventFlag = KernelEventFlagPrivate*;
|
||||
using Pthread = PthreadPrivate*;
|
||||
using PthreadEntry = void* (APS5_VABI *)(void*);
|
||||
using PthreadAttr = PthreadAttrPrivate*;
|
||||
using PthreadMutex = PthreadMutexPrivate*;
|
||||
using PthreadMutexattr = PthreadMutexattrPrivate*;
|
||||
|
|
@ -1882,7 +1884,7 @@ struct UltMutexOptParam {
|
|||
|
||||
struct UltUlthreadRuntimeOptParam { std::uint8_t bytes[128]; };
|
||||
|
||||
using UltUlthreadEntry = std::int32_t (*)(std::uint64_t);
|
||||
using UltUlthreadEntry = std::int32_t (APS5_VABI *)(std::uint64_t);
|
||||
|
||||
struct VideoOutBufferAttribute2 {
|
||||
std::uint32_t reserved0;
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@
|
|||
#include "prx/libc/include/General.hpp"
|
||||
#include "SceUltTypes.hpp"
|
||||
|
||||
extern "C" int scePthreadCreate(Pthread* thread, const PthreadAttr* attr, void* (*entry)(void*), void* arg, const char* name);
|
||||
extern "C" int scePthreadJoin(Pthread thread, void** retval);
|
||||
extern "C" int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name);
|
||||
extern "C" int APS5_VABI scePthreadJoin(Pthread thread, void** retval);
|
||||
|
||||
namespace {
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ int queueGetState(void* queue, std::shared_ptr<UltQueueState>* out) {
|
|||
return ULT_OK;
|
||||
}
|
||||
|
||||
void* ulthreadRunner(void* arg) {
|
||||
void* APS5_VABI ulthreadRunner(void* arg) {
|
||||
auto* state = static_cast<UltUlthreadState*>(arg);
|
||||
return reinterpret_cast<void*>(static_cast<std::intptr_t>(state->_entry(state->_arg)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ static constexpr int DETACH_DETACHED = 1;
|
|||
static constexpr int SCHED_FIFO_PS5 = 1;
|
||||
|
||||
struct ThreadArgs {
|
||||
void* (*entry)(void*);
|
||||
PthreadEntry entry;
|
||||
void* arg;
|
||||
PthreadPrivate* self;
|
||||
};
|
||||
|
|
@ -253,7 +253,7 @@ int APS5_VABI scePthreadAttrGet(Pthread thread, PthreadAttr* attr) {
|
|||
return SCE_OK;
|
||||
}
|
||||
|
||||
int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, void* (*entry)(void*), void* arg, const char*) {
|
||||
int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char*) {
|
||||
if (!thread || !entry) throw std::runtime_error("scePthreadCreate: null arg");
|
||||
auto p = std::make_unique<PthreadPrivate>();
|
||||
bool detached = false;
|
||||
|
|
|
|||
|
|
@ -3,18 +3,18 @@
|
|||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
extern "C" int scePthreadCreate(Pthread* thread, const PthreadAttr* attr, void* (*entry)(void*), void* arg, const char* name);
|
||||
extern "C" int scePthreadJoin(Pthread thread, void** retval);
|
||||
extern "C" int scePthreadAttrInit(PthreadAttr* attr);
|
||||
extern "C" int scePthreadAttrDestroy(PthreadAttr* attr);
|
||||
extern "C" int scePthreadAttrGet(Pthread thread, PthreadAttr* attr);
|
||||
extern "C" int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name);
|
||||
extern "C" int APS5_VABI scePthreadJoin(Pthread thread, void** retval);
|
||||
extern "C" int APS5_VABI scePthreadAttrInit(PthreadAttr* attr);
|
||||
extern "C" int APS5_VABI scePthreadAttrDestroy(PthreadAttr* attr);
|
||||
extern "C" int APS5_VABI scePthreadAttrGet(Pthread thread, PthreadAttr* attr);
|
||||
|
||||
struct ThreadContext {
|
||||
Pthread thread = nullptr;
|
||||
std::promise<void> checked;
|
||||
};
|
||||
|
||||
static void* CheckThread(void* arg) {
|
||||
static void* APS5_VABI CheckThread(void* arg) {
|
||||
auto& context = *static_cast<ThreadContext*>(arg);
|
||||
if (!context.thread) throw std::runtime_error("Thread handle was not published");
|
||||
if (context.thread->_thr.get_id() != std::this_thread::get_id()) throw std::runtime_error("Thread object was not initialized");
|
||||
|
|
|
|||
Loading…
Reference in New Issue