feat(libs): add new std symbols + unused filter off by default
This commit is contained in:
parent
fa27b50832
commit
594656581e
|
|
@ -14,7 +14,7 @@ The [shader recompiler](core/shader/recompiler/Recompiler.cpp) successfully prod
|
|||
|
||||
The real game reaches the render loop and **successfully presents its first frames** (logo).
|
||||
|
||||
Current error: [relinker](core/relinker/relinker/src/analysis/UnusedNidFilter.cpp) with `unused-filter=1` removes the used [_ZSt21_sceLibcClassicLocale](core/libs/prx/libc/src/LocaleSupport.cpp) import, causing a null-pointer access. `unused_filter=2` preserves imports for functions that are not yet implemented in the [prx](core/libs/prx).
|
||||
Current error: Access Violation after `Could not open file /_sd/SAVEDATA00/-saveindex` at ~frame 71, presumably caused by a null pointer dereference.
|
||||
|
||||
## Build
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "Unwind.cpp"
|
||||
#include "Runtime.cpp"
|
||||
#include "TypeInfo.cpp"
|
||||
#include "ExceptionPointer.cpp"
|
||||
#include "StandardExceptions.cpp"
|
||||
#include "ArraySupport.cpp"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "prx/libc/include/exceptions/Runtime.hpp"
|
||||
#include <limits>
|
||||
#include <regex>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace LibcException {
|
||||
struct TypeRecord { const void* const* vtable; const char* name; const TypeRecord* base; };
|
||||
|
|
@ -110,12 +111,17 @@ ExceptionObject* Assign(ExceptionObject* object, const ExceptionObject* source)
|
|||
}
|
||||
|
||||
extern "C" {
|
||||
LibcException::TypeRecord _ZTISt8ios_base_nid_postfix {LibcException::ClassTypeVtable + 2, "St8ios_base", nullptr};
|
||||
LibcException::TypeRecord _ZTISt9exception_nid_postfix {LibcException::ClassTypeVtable + 2, "St9exception", nullptr};
|
||||
LibcException::ExceptionVtable _ZTVSt9exception_nid_postfix {0, &_ZTISt9exception_nid_postfix, LibcException::DestroyPlain, LibcException::DeletePlain, LibcException::PlainWhat};
|
||||
void APS5_VABI _ZNSt9exceptionD1Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyPlain(self); }
|
||||
void APS5_VABI _ZNSt9exceptionD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyPlain(self); }
|
||||
void APS5_VABI _ZNSt9exceptionD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeletePlain(self); }
|
||||
const char* APS5_VABI _ZNKSt9exception4whatEv_nid_postfix(const LibcException::ExceptionObject* self) { return LibcException::PlainWhat(self); }
|
||||
[[noreturn]] void APS5_VABI _ZNKSt9exception8_DoraiseEv_nid_postfix(const LibcException::ExceptionObject* self) {
|
||||
if (!self) throw std::invalid_argument("exception object is null");
|
||||
LibcException::ThrowPlain(_ZTVSt9exception_nid_postfix);
|
||||
}
|
||||
void APS5_VABI _ZNSt9exceptionC1Ev_nid_postfix(LibcException::ExceptionObject* self) { self->vtable = &_ZTVSt9exception_nid_postfix.destroy; }
|
||||
void APS5_VABI _ZNSt9exceptionC2Ev_nid_postfix(LibcException::ExceptionObject* self) { self->vtable = &_ZTVSt9exception_nid_postfix.destroy; }
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
#include "prx/libc/include/exceptions/Runtime.hpp"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace LibcException {
|
||||
namespace {
|
||||
|
||||
using ClassTypeInfo = __cxxabiv1::__class_type_info;
|
||||
|
||||
void APS5_VABI DestroyTypeInfo(std::type_info*) {}
|
||||
|
||||
void APS5_VABI DeleteTypeInfo(std::type_info*) {
|
||||
throw std::runtime_error("deleting guest RTTI is not supported");
|
||||
}
|
||||
|
||||
bool APS5_VABI IsPointerTypeInfo(const std::type_info*) { return false; }
|
||||
|
||||
bool APS5_VABI CatchTypeInfo(const std::type_info* self, const std::type_info* thrown, void** object, unsigned) {
|
||||
if (!self || !thrown || !object) throw std::invalid_argument("invalid RTTI catch arguments");
|
||||
return Match(self, thrown, *object);
|
||||
}
|
||||
|
||||
bool APS5_VABI UpcastTypeInfo(const std::type_info* self, const ClassTypeInfo* base, void** object) {
|
||||
if (!self || !base || !object) throw std::invalid_argument("invalid RTTI upcast arguments");
|
||||
Search search {base};
|
||||
Bases(self, *object, search);
|
||||
if (search.count != 1) return false;
|
||||
*object = search.found;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool APS5_VABI UpcastTypeInfoResult(const ClassTypeInfo*, const ClassTypeInfo*, const void*, ClassTypeInfo::__upcast_result&) {
|
||||
throw std::runtime_error("RTTI __upcast_result is not supported");
|
||||
}
|
||||
|
||||
bool APS5_VABI DynamicCastTypeInfo(const ClassTypeInfo*, std::ptrdiff_t, ClassTypeInfo::__sub_kind, const ClassTypeInfo*, const void*, const ClassTypeInfo*, const void*, ClassTypeInfo::__dyncast_result&) {
|
||||
throw std::runtime_error("RTTI __dyncast_result is not supported");
|
||||
}
|
||||
|
||||
ClassTypeInfo::__sub_kind APS5_VABI FindPublicTypeInfo(const ClassTypeInfo*, std::ptrdiff_t, const void*, const ClassTypeInfo*, const void*) {
|
||||
throw std::runtime_error("RTTI __do_find_public_src is not supported");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct TypeInfoVtable {
|
||||
std::ptrdiff_t offset;
|
||||
const std::type_info* type;
|
||||
decltype(&DestroyTypeInfo) destroy = DestroyTypeInfo;
|
||||
decltype(&DeleteTypeInfo) deleteObject = DeleteTypeInfo;
|
||||
decltype(&IsPointerTypeInfo) isPointer = IsPointerTypeInfo;
|
||||
decltype(&IsPointerTypeInfo) isFunction = IsPointerTypeInfo;
|
||||
decltype(&CatchTypeInfo) catchType = CatchTypeInfo;
|
||||
decltype(&UpcastTypeInfo) upcast = UpcastTypeInfo;
|
||||
decltype(&UpcastTypeInfoResult) upcastResult = UpcastTypeInfoResult;
|
||||
decltype(&DynamicCastTypeInfo) dynamicCast = DynamicCastTypeInfo;
|
||||
decltype(&FindPublicTypeInfo) findPublic = FindPublicTypeInfo;
|
||||
};
|
||||
|
||||
static_assert(offsetof(TypeInfoVtable, destroy) == 2 * sizeof(void*));
|
||||
static_assert(sizeof(TypeInfoVtable) == 11 * sizeof(void*));
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
LibcException::TypeInfoVtable _ZTVN10__cxxabiv117__class_type_infoE_nid_postfix {0, &typeid(__cxxabiv1::__class_type_info)};
|
||||
LibcException::TypeInfoVtable _ZTVN10__cxxabiv120__si_class_type_infoE_nid_postfix {0, &typeid(__cxxabiv1::__si_class_type_info)};
|
||||
LibcException::TypeInfoVtable _ZTVN10__cxxabiv121__vmi_class_type_infoE_nid_postfix {0, &typeid(__cxxabiv1::__vmi_class_type_info)};
|
||||
}
|
||||
|
|
@ -5,6 +5,51 @@
|
|||
#include <array>
|
||||
#include <exception>
|
||||
#include <thread>
|
||||
#include <cstddef>
|
||||
#include <typeinfo>
|
||||
#include "../prx/libc/include/general/VabiMacros.hpp"
|
||||
|
||||
extern "C" {
|
||||
extern const unsigned char _ZTVN10__cxxabiv117__class_type_infoE_nid_postfix[];
|
||||
extern const unsigned char _ZTVN10__cxxabiv120__si_class_type_infoE_nid_postfix[];
|
||||
extern const unsigned char _ZTVN10__cxxabiv121__vmi_class_type_infoE_nid_postfix[];
|
||||
}
|
||||
|
||||
static void TestTypeInfoVtables() {
|
||||
struct TypeRecord { const void* vtable; const char* name; };
|
||||
struct SingleRecord { TypeRecord type; const TypeRecord* base; };
|
||||
struct BaseRecord { const TypeRecord* type; std::ptrdiff_t flags; };
|
||||
struct MultipleRecord { TypeRecord type; unsigned flags; unsigned count; BaseRecord bases[2]; };
|
||||
const auto* classTable = _ZTVN10__cxxabiv117__class_type_infoE_nid_postfix;
|
||||
const auto* singleTable = _ZTVN10__cxxabiv120__si_class_type_infoE_nid_postfix;
|
||||
const auto* multipleTable = _ZTVN10__cxxabiv121__vmi_class_type_infoE_nid_postfix;
|
||||
const unsigned char* tables[] {classTable, singleTable, multipleTable};
|
||||
const char* names[] {"N10__cxxabiv117__class_type_infoE", "N10__cxxabiv120__si_class_type_infoE", "N10__cxxabiv121__vmi_class_type_infoE"};
|
||||
for (std::size_t i = 0; i < 3; ++i) {
|
||||
const std::type_info* category;
|
||||
std::memcpy(&category, tables[i] + sizeof(void*), sizeof(category));
|
||||
if (std::strcmp(category->name(), names[i])) throw std::runtime_error("incorrect RTTI category");
|
||||
}
|
||||
TypeRecord base {classTable + 2 * sizeof(void*), "4Base"};
|
||||
TypeRecord other {classTable + 2 * sizeof(void*), "5Other"};
|
||||
SingleRecord single {{singleTable + 2 * sizeof(void*), "6Single"}, &base};
|
||||
MultipleRecord multiple {{multipleTable + 2 * sizeof(void*), "8Multiple"}, 0, 2, {{&other, 2}, {&base, (16 << 8) | 2}}};
|
||||
using CatchType = bool (APS5_VABI *)(const void*, const void*, void**, unsigned);
|
||||
using UpcastType = bool (APS5_VABI *)(const void*, const void*, void**);
|
||||
CatchType catchType;
|
||||
UpcastType upcastType;
|
||||
std::memcpy(&catchType, classTable + 6 * sizeof(void*), sizeof(catchType));
|
||||
std::memcpy(&upcastType, multipleTable + 7 * sizeof(void*), sizeof(upcastType));
|
||||
std::array<unsigned char, 32> storage {};
|
||||
void* object = storage.data();
|
||||
if (!catchType(&base, &single, &object, 0) || object != storage.data()) throw std::runtime_error("single RTTI catch failed");
|
||||
object = storage.data();
|
||||
if (!catchType(&base, &multiple, &object, 0) || object != storage.data() + 16) throw std::runtime_error("multiple RTTI catch failed");
|
||||
object = storage.data();
|
||||
if (!upcastType(&multiple, &base, &object) || object != storage.data() + 16) throw std::runtime_error("multiple RTTI upcast failed");
|
||||
object = storage.data();
|
||||
if (catchType(&other, &single, &object, 0)) throw std::runtime_error("unrelated RTTI catch succeeded");
|
||||
}
|
||||
|
||||
extern "C" void NotImplemented_nid_no_patch(const char*);
|
||||
|
||||
|
|
@ -61,6 +106,7 @@ static void testExceptionPointer() {
|
|||
}
|
||||
|
||||
int main() {
|
||||
TestTypeInfoVtables();
|
||||
testExceptionPointer();
|
||||
try {
|
||||
Rethrow();
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ struct Args {
|
|||
bool lazyBinding = false;
|
||||
bool autorun = false;
|
||||
bool windowsDiagnostics = false;
|
||||
std::uint32_t unusedFilterLevel = 1;
|
||||
std::uint32_t unusedFilterLevel = 0;
|
||||
std::string inputPath;
|
||||
std::string outputPath;
|
||||
std::string runPath = "$ORIGIN/libs";
|
||||
|
|
|
|||
|
|
@ -5,12 +5,28 @@
|
|||
#include <elfpatcher/windows/WindowsRelocationBuilder.hpp>
|
||||
#include <elfpatcher/windows/WindowsTlsBuilder.hpp>
|
||||
#include <io/BufferUtils.hpp>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
|
||||
namespace Elfpatcher::Windows {
|
||||
|
||||
namespace {
|
||||
|
||||
void writeDiagnosticsImports(const std::vector<PeImport>& imports) {
|
||||
const std::filesystem::path path = std::filesystem::absolute("windows-diagnostics-imports.txt");
|
||||
std::ofstream stream(path, std::ios::trunc);
|
||||
if (!stream)
|
||||
throw Domain::RelinkerException("Cannot open windows-diagnostics-imports.txt for writing");
|
||||
for (const auto& import : imports)
|
||||
stream << import.Name << '\n';
|
||||
if (!stream)
|
||||
throw Domain::RelinkerException("Cannot write windows-diagnostics-imports.txt");
|
||||
stream.close();
|
||||
std::cout << "Wrote Windows import diagnostics to " << path.string() << '\n';
|
||||
}
|
||||
|
||||
void writeGotStub(std::vector<PeSection>& sections, const std::uint32_t targetRva, const std::uint32_t stubRva) {
|
||||
for (auto& section : sections) {
|
||||
if (targetRva < section.Rva || targetRva - section.Rva > section.Data.size() - 4)
|
||||
|
|
@ -63,6 +79,8 @@ std::vector<std::uint8_t> WindowsPePatcher::Patch(const std::vector<std::uint8_t
|
|||
directories[12] = nativeImports.AddressTable;
|
||||
nextRva = AlignRva(nextRva + nativeImports.Section.Data.size());
|
||||
const auto libraries = importBuilder.ReadLibraries(dynamicSection);
|
||||
if (dependencyDiagnostics)
|
||||
writeDiagnosticsImports(relocations.Imports);
|
||||
auto entry = WindowsEntryStubBuilder().Build(nextRva, image.GetEntryRva(), nativeImports, libraries, relocations.Imports, runPath, lazyBinding, dependencyDiagnostics);
|
||||
directories[3] = entry.ExceptionDirectory;
|
||||
const auto entryRva = entry.Code.Rva;
|
||||
|
|
|
|||
Loading…
Reference in New Issue