- use const auto& where possible

- avoid using const std::unique_ptr& and const std::shared_ptr&
- avoid wrapping results in std::optional
- prefer std::string_view over const std::string&
- update FSUtils::LoadFileToMem to write into std::vector<uint8_t>
- use std::span when possible
- Avoid unnessecary copies in PluginDataFactory
- allocate plugins as HeapMemoryFixedSize which bascially is a std::unique_ptr with fixed size
This commit is contained in:
Maschell
2023-11-04 15:32:45 +01:00
parent baee1afda3
commit cc5acd0980
37 changed files with 477 additions and 583 deletions

View File

@@ -24,18 +24,23 @@
class FunctionData {
public:
FunctionData(void *paddress, void *vaddress, std::string name, function_replacement_library_type_t library, void *replaceAddr, void *replaceCall,
FunctionData(void *paddress, void *vaddress, std::string_view name, function_replacement_library_type_t library, void *replaceAddr, void *replaceCall,
FunctionPatcherTargetProcess targetProcess) {
this->paddress = paddress;
this->vaddress = vaddress;
this->name = std::move(name);
this->name = name;
this->library = library;
this->targetProcess = targetProcess;
this->replaceAddr = replaceAddr;
this->replaceCall = replaceCall;
}
~FunctionData() = default;
~FunctionData() {
if (handle != 0) {
DEBUG_FUNCTION_LINE_WARN("Destroying FunctionData while it was still patched. This should never happen.");
RemovePatch();
}
}
[[nodiscard]] const std::string &getName() const {
return this->name;
@@ -81,7 +86,7 @@ public:
}};
if (FunctionPatcher_AddFunctionPatch(&functionData, &handle, nullptr) != FUNCTION_PATCHER_RESULT_SUCCESS) {
DEBUG_FUNCTION_LINE_ERR("Failed to add patch for function");
DEBUG_FUNCTION_LINE_ERR("Failed to add patch for function (\"%s\" PA:%08X VA:%08X)", this->name.c_str(), this->paddress, this->vaddress);
return false;
}
} else {

View File

@@ -24,31 +24,31 @@ class FunctionSymbolData {
public:
FunctionSymbolData(const FunctionSymbolData &o2) = default;
FunctionSymbolData(std::string &name, void *address, uint32_t size) : name(name),
address(address),
size(size) {
FunctionSymbolData(std::string_view name, void *address, uint32_t size) : mName(name),
mAddress(address),
mSize(size) {
}
bool operator<(const FunctionSymbolData &rhs) const {
return (uint32_t) address < (uint32_t) rhs.address;
return (uint32_t) mAddress < (uint32_t) rhs.mAddress;
}
virtual ~FunctionSymbolData() = default;
[[nodiscard]] const std::string &getName() const {
return name;
return mName;
}
[[nodiscard]] void *getAddress() const {
return address;
return mAddress;
}
[[nodiscard]] uint32_t getSize() const {
return size;
return mSize;
}
private:
std::string name;
void *address;
uint32_t size;
std::string mName;
void *mAddress;
uint32_t mSize;
};

View File

@@ -24,24 +24,24 @@
class ImportRPLInformation {
public:
explicit ImportRPLInformation(std::string name) {
this->name = std::move(name);
explicit ImportRPLInformation(std::string_view name) {
this->mName = name;
}
~ImportRPLInformation() = default;
[[nodiscard]] const std::string &getName() const {
return name;
return mName;
}
[[nodiscard]] std::string getRPLName() const {
return name.substr(strlen(".dimport_"));
return mName.substr(strlen(".dimport_"));
}
[[nodiscard]] bool isData() const {
return name.starts_with(".dimport_");
return mName.starts_with(".dimport_");
}
private:
std::string name;
std::string mName;
};

View File

@@ -26,28 +26,29 @@
class PluginContainer {
public:
PluginContainer(std::unique_ptr<PluginMetaInformation> metaInformation, std::unique_ptr<PluginInformation> pluginInformation, std::shared_ptr<PluginData> pluginData)
: metaInformation(std::move(metaInformation)),
pluginInformation(std::move(pluginInformation)),
pluginData(std::move(pluginData)) {
: mMetaInformation(std::move(metaInformation)),
mPluginInformation(std::move(pluginInformation)),
mPluginData(std::move(pluginData)) {
}
[[nodiscard]] const std::unique_ptr<PluginMetaInformation> &getMetaInformation() const {
return this->metaInformation;
[[nodiscard]] const PluginMetaInformation &getMetaInformation() const {
return *this->mMetaInformation;
}
[[nodiscard]] const std::unique_ptr<PluginInformation> &getPluginInformation() const {
return pluginInformation;
[[nodiscard]] const PluginInformation &getPluginInformation() const {
return *this->mPluginInformation;
}
[[nodiscard]] const std::shared_ptr<PluginData> &getPluginData() const {
return pluginData;
[[nodiscard]] std::shared_ptr<PluginData> getPluginDataCopy() const {
return mPluginData;
}
uint32_t getHandle() {
return (uint32_t) this;
}
const std::unique_ptr<PluginMetaInformation> metaInformation;
const std::unique_ptr<PluginInformation> pluginInformation;
const std::shared_ptr<PluginData> pluginData;
private:
const std::unique_ptr<PluginMetaInformation> mMetaInformation;
const std::unique_ptr<PluginInformation> mPluginInformation;
const std::shared_ptr<PluginData> mPluginData;
};

View File

@@ -1,15 +0,0 @@
#include "PluginData.h"
#include "utils/logger.h"
#include "utils/utils.h"
PluginData::PluginData(const std::vector<uint8_t> &input, std::string source) : length(input.size()), mSource(std::move(source)) {
auto data_copy = make_unique_nothrow<uint8_t[]>(length);
if (!data_copy) {
DEBUG_FUNCTION_LINE_ERR("Failed to allocate space on default heap");
this->length = 0;
} else {
DEBUG_FUNCTION_LINE_VERBOSE("Allocated %d kb on default heap", length / 1024);
memcpy(data_copy.get(), &input[0], length);
this->buffer = std::move(data_copy);
}
}

View File

@@ -21,17 +21,31 @@
#include <malloc.h>
#include <memory>
#include <optional>
#include <span>
#include <utility>
#include <vector>
class PluginData {
public:
explicit PluginData(const std::vector<uint8_t> &buffer, std::string source);
explicit PluginData(std::vector<uint8_t> &&buffer, std::string_view source) : mBuffer(std::move(buffer)), mSource(source) {
}
uint32_t getHandle() {
explicit PluginData(std::span<uint8_t> buffer, std::string_view source) : mBuffer(buffer.begin(), buffer.end()), mSource(source) {
}
[[nodiscard]] uint32_t getHandle() const {
return (uint32_t) this;
}
size_t length = 0;
std::unique_ptr<uint8_t[]> buffer;
[[nodiscard]] std::span<uint8_t const> getBuffer() const {
return mBuffer;
}
[[nodiscard]] const std::string &getSource() const {
return mSource;
}
private:
std::vector<uint8_t> mBuffer;
std::string mSource;
};

View File

@@ -23,10 +23,9 @@
#include <dirent.h>
#include <forward_list>
#include <memory>
#include <sys/stat.h>
std::forward_list<std::shared_ptr<PluginData>> PluginDataFactory::loadDir(const std::string &path) {
std::forward_list<std::shared_ptr<PluginData>> result;
std::set<std::shared_ptr<PluginData>> PluginDataFactory::loadDir(std::string_view path) {
std::set<std::shared_ptr<PluginData>> result;
struct dirent *dp;
DIR *dfd;
@@ -35,8 +34,8 @@ std::forward_list<std::shared_ptr<PluginData>> PluginDataFactory::loadDir(const
return result;
}
if ((dfd = opendir(path.c_str())) == nullptr) {
DEBUG_FUNCTION_LINE_ERR("Couldn't open dir %s", path.c_str());
if ((dfd = opendir(path.data())) == nullptr) {
DEBUG_FUNCTION_LINE_ERR("Couldn't open dir %s", path.data());
return result;
}
@@ -45,15 +44,15 @@ std::forward_list<std::shared_ptr<PluginData>> PluginDataFactory::loadDir(const
continue;
}
if (std::string_view(dp->d_name).starts_with('.') || std::string_view(dp->d_name).starts_with('_') || !std::string_view(dp->d_name).ends_with(".wps")) {
DEBUG_FUNCTION_LINE_WARN("Skip file %s/%s", path.c_str(), dp->d_name);
DEBUG_FUNCTION_LINE_WARN("Skip file %s/%s", path.data(), dp->d_name);
continue;
}
auto full_file_path = string_format("%s/%s", path.c_str(), dp->d_name);
auto full_file_path = string_format("%s/%s", path.data(), dp->d_name);
DEBUG_FUNCTION_LINE("Loading plugin: %s", full_file_path.c_str());
auto pluginData = load(full_file_path);
if (pluginData) {
result.push_front(std::move(pluginData.value()));
result.insert(std::move(pluginData));
} else {
auto errMsg = string_format("Failed to load plugin: %s", full_file_path.c_str());
DEBUG_FUNCTION_LINE_ERR("%s", errMsg.c_str());
@@ -66,33 +65,21 @@ std::forward_list<std::shared_ptr<PluginData>> PluginDataFactory::loadDir(const
return result;
}
std::optional<std::unique_ptr<PluginData>> PluginDataFactory::load(const std::string &filename) {
uint8_t *buffer = nullptr;
uint32_t fsize = 0;
if (FSUtils::LoadFileToMem(filename.c_str(), &buffer, &fsize) < 0) {
DEBUG_FUNCTION_LINE_ERR("Failed to load %s into memory", filename.c_str());
return {};
std::unique_ptr<PluginData> PluginDataFactory::load(std::string_view filename) {
std::vector<uint8_t> buffer;
if (FSUtils::LoadFileToMem(filename, buffer) < 0) {
DEBUG_FUNCTION_LINE_ERR("Failed to load %s into memory", filename.data());
return nullptr;
}
std::vector<uint8_t> result;
result.resize(fsize);
memcpy(&result[0], buffer, fsize);
free(buffer);
DEBUG_FUNCTION_LINE_VERBOSE("Loaded file!");
return load(result, filename);
return load(std::move(buffer), filename);
}
std::optional<std::unique_ptr<PluginData>> PluginDataFactory::load(const std::vector<uint8_t> &buffer, const std::string &source) {
std::unique_ptr<PluginData> PluginDataFactory::load(std::vector<uint8_t> &&buffer, std::string_view source) {
if (buffer.empty()) {
return {};
return nullptr;
}
auto res = make_unique_nothrow<PluginData>(buffer, source);
if (!res) {
return {};
}
return res;
return make_unique_nothrow<PluginData>(std::move(buffer), source);
}

View File

@@ -22,14 +22,15 @@
#include <forward_list>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>
class PluginDataFactory {
public:
static std::forward_list<std::shared_ptr<PluginData>> loadDir(const std::string &path);
static std::set<std::shared_ptr<PluginData>> loadDir(std::string_view path);
static std::optional<std::unique_ptr<PluginData>> load(const std::string &path);
static std::unique_ptr<PluginData> load(std::string_view path);
static std::optional<std::unique_ptr<PluginData>> load(const std::vector<uint8_t> &buffer, const std::string &source);
static std::unique_ptr<PluginData> load(std::vector<uint8_t> &&buffer, std::string_view source);
};

View File

@@ -23,6 +23,8 @@
#include "PluginMetaInformation.h"
#include "RelocationData.h"
#include "SectionInfo.h"
#include "utils/HeapMemoryFixedSize.h"
#include "utils/utils.h"
#include <map>
#include <memory>
#include <optional>
@@ -32,109 +34,101 @@
#include <vector>
struct FunctionSymbolDataComparator {
bool operator()(const std::shared_ptr<FunctionSymbolData> &lhs,
const std::shared_ptr<FunctionSymbolData> &rhs) const {
return (uint32_t) lhs->getAddress() < (uint32_t) rhs->getAddress();
bool operator()(const std::unique_ptr<FunctionSymbolData> &lhs,
const std::unique_ptr<FunctionSymbolData> &rhs) const {
return *lhs < *rhs;
}
};
class PluginInformation {
public:
void addHookData(std::unique_ptr<HookData> hook_data) {
hook_data_list.push_back(std::move(hook_data));
mHookDataList.push_back(std::move(hook_data));
}
[[nodiscard]] const std::vector<std::unique_ptr<HookData>> &getHookDataList() const {
return hook_data_list;
return mHookDataList;
}
void addFunctionData(std::unique_ptr<FunctionData> function_data) {
function_data_list.push_back(std::move(function_data));
mFunctionDataList.push_back(std::move(function_data));
}
[[nodiscard]] const std::vector<std::unique_ptr<FunctionData>> &getFunctionDataList() const {
return function_data_list;
return mFunctionDataList;
}
void addRelocationData(std::unique_ptr<RelocationData> relocation_data) {
relocation_data_list.push_back(std::move(relocation_data));
mRelocationDataList.push_back(std::move(relocation_data));
}
[[nodiscard]] const std::vector<std::unique_ptr<RelocationData>> &getRelocationDataList() const {
return relocation_data_list;
return mRelocationDataList;
}
void addFunctionSymbolData(std::shared_ptr<FunctionSymbolData> symbol_data) {
symbol_data_list.insert(std::move(symbol_data));
void addFunctionSymbolData(std::unique_ptr<FunctionSymbolData> symbol_data) {
mSymbolDataList.insert(std::move(symbol_data));
}
[[nodiscard]] const std::set<std::shared_ptr<FunctionSymbolData>, FunctionSymbolDataComparator> &getFunctionSymbolDataList() const {
return symbol_data_list;
void addSectionInfo(std::unique_ptr<SectionInfo> sectionInfo) {
mSectionInfoList[sectionInfo->getName()] = std::move(sectionInfo);
}
void addSectionInfo(std::shared_ptr<SectionInfo> sectionInfo) {
section_info_list[sectionInfo->getName()] = std::move(sectionInfo);
[[nodiscard]] const std::map<std::string, std::unique_ptr<SectionInfo>> &getSectionInfoList() const {
return mSectionInfoList;
}
[[nodiscard]] const std::map<std::string, std::shared_ptr<SectionInfo>> &getSectionInfoList() const {
return section_info_list;
}
[[nodiscard]] std::optional<std::shared_ptr<SectionInfo>> getSectionInfo(const std::string &sectionName) const {
[[nodiscard]] SectionInfo *getSectionInfo(const std::string &sectionName) const {
if (getSectionInfoList().contains(sectionName)) {
return section_info_list.at(sectionName);
return mSectionInfoList.at(sectionName).get();
}
return std::nullopt;
return nullptr;
}
void setTrampolineId(uint8_t _trampolineId) {
this->trampolineId = _trampolineId;
void setTrampolineId(uint8_t trampolineId) {
this->mTrampolineId = trampolineId;
}
[[nodiscard]] uint8_t getTrampolineId() const {
return trampolineId;
return mTrampolineId;
}
[[nodiscard]] std::optional<std::shared_ptr<FunctionSymbolData>> getNearestFunctionSymbolData(uint32_t address) const {
std::shared_ptr<FunctionSymbolData> result;
[[nodiscard]] FunctionSymbolData *getNearestFunctionSymbolData(uint32_t address) const {
FunctionSymbolData *result = nullptr;
bool foundHit = false;
for (auto &cur : symbol_data_list) {
for (auto &cur : mSymbolDataList) {
if (foundHit && address < (uint32_t) cur->getAddress()) {
break;
}
if (address >= (uint32_t) cur->getAddress()) {
result = cur;
result = cur.get();
foundHit = true;
}
}
if (result) {
return result;
}
return {};
return result;
}
void *getTextMemoryAddress() {
return allocatedTextMemoryAddress.get();
[[nodiscard]] const HeapMemoryFixedSize &getTextMemory() const {
return mAllocatedTextMemoryAddress;
}
void *getDataMemoryAddress() {
return allocatedDataMemoryAddress.get();
[[nodiscard]] const HeapMemoryFixedSize &getDataMemory() const {
return mAllocatedDataMemoryAddress;
}
private:
std::vector<std::unique_ptr<HookData>> hook_data_list;
std::vector<std::unique_ptr<FunctionData>> function_data_list;
std::vector<std::unique_ptr<RelocationData>> relocation_data_list;
std::set<std::shared_ptr<FunctionSymbolData>, FunctionSymbolDataComparator> symbol_data_list;
std::map<std::string, std::shared_ptr<SectionInfo>> section_info_list;
std::vector<std::unique_ptr<HookData>> mHookDataList;
std::vector<std::unique_ptr<FunctionData>> mFunctionDataList;
std::vector<std::unique_ptr<RelocationData>> mRelocationDataList;
std::set<std::unique_ptr<FunctionSymbolData>, FunctionSymbolDataComparator> mSymbolDataList;
std::map<std::string, std::unique_ptr<SectionInfo>> mSectionInfoList;
uint8_t trampolineId = 0;
uint8_t mTrampolineId = 0;
std::unique_ptr<uint8_t[]> allocatedTextMemoryAddress;
std::unique_ptr<uint8_t[]> allocatedDataMemoryAddress;
HeapMemoryFixedSize mAllocatedTextMemoryAddress;
HeapMemoryFixedSize mAllocatedDataMemoryAddress;
friend class PluginInformationFactory;
};

View File

@@ -18,6 +18,7 @@
#include "PluginInformationFactory.h"
#include "../utils/ElfUtils.h"
#include "../utils/utils.h"
#include "utils/HeapMemoryFixedSize.h"
#include "utils/wiiu_zlib.hpp"
#include <coreinit/cache.h>
#include <map>
@@ -27,33 +28,34 @@
using namespace ELFIO;
std::optional<std::unique_ptr<PluginInformation>>
PluginInformationFactory::load(const std::shared_ptr<PluginData> &pluginData, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length,
uint8_t trampolineId) {
if (!pluginData->buffer) {
DEBUG_FUNCTION_LINE_ERR("Buffer was nullptr");
return {};
std::unique_ptr<PluginInformation>
PluginInformationFactory::load(const PluginData &pluginData, std::vector<relocation_trampoline_entry_t> &trampolineData, uint8_t trampolineId) {
auto buffer = pluginData.getBuffer();
if (buffer.empty()) {
DEBUG_FUNCTION_LINE_ERR("Buffer was empty");
return nullptr;
}
elfio reader(new wiiu_zlib);
if (!reader.load(reinterpret_cast<const char *>(pluginData->buffer.get()), pluginData->length)) {
if (!reader.load(reinterpret_cast<const char *>(buffer.data()), buffer.size())) {
DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio");
return {};
return nullptr;
}
auto pluginInfo = make_unique_nothrow<PluginInformation>();
if (!pluginInfo) {
DEBUG_FUNCTION_LINE_ERR("Failed to allocate PluginInformation");
return {};
return nullptr;
}
uint32_t sec_num = reader.sections.size();
auto destinations = make_unique_nothrow<uint8_t *[]>(sec_num);
if (!destinations) {
auto destinationsData = make_unique_nothrow<uint8_t *[]>(sec_num);
if (!destinationsData) {
DEBUG_FUNCTION_LINE_ERR("Failed alloc memory for destinations array");
return {};
return nullptr;
}
std::span<uint8_t *> destinations(destinationsData.get(), sec_num);
uint32_t totalSize = 0;
@@ -80,22 +82,18 @@ PluginInformationFactory::load(const std::shared_ptr<PluginData> &pluginData, re
}
}
auto text_data = make_unique_nothrow<uint8_t[]>(text_size);
HeapMemoryFixedSize text_data(text_size);
if (!text_data) {
DEBUG_FUNCTION_LINE_ERR("Failed to alloc memory for the .text section (%d bytes)", text_size);
return {};
return nullptr;
}
DEBUG_FUNCTION_LINE_VERBOSE("Allocated %d kb", text_size / 1024);
auto data_data = make_unique_nothrow<uint8_t[]>(data_size);
HeapMemoryFixedSize data_data(data_size);
if (!data_data) {
DEBUG_FUNCTION_LINE_ERR("Failed to alloc memory for the .data section (%d bytes)", data_size);
return {};
return nullptr;
}
DEBUG_FUNCTION_LINE_VERBOSE("Allocated %d kb", data_size / 1024);
for (uint32_t i = 0; i < sec_num; ++i) {
section *psec = reader.sections[i];
if (psec->get_type() == 0x80000002 || psec->get_name() == ".wut_load_bounds") {
@@ -108,29 +106,29 @@ PluginInformationFactory::load(const std::shared_ptr<PluginData> &pluginData, re
uint32_t destination = address;
if ((address >= 0x02000000) && address < 0x10000000) {
destination += (uint32_t) text_data.get();
destination += (uint32_t) text_data.data();
destination -= 0x02000000;
destinations[psec->get_index()] = (uint8_t *) text_data.get();
destinations[psec->get_index()] = (uint8_t *) text_data.data();
if (destination + sectionSize > (uint32_t) text_data.get() + text_size) {
DEBUG_FUNCTION_LINE_ERR("Tried to overflow .text buffer. %08X > %08X", destination + sectionSize, (uint32_t) text_data.get() + text_size);
if (destination + sectionSize > (uint32_t) text_data.data() + text_size) {
DEBUG_FUNCTION_LINE_ERR("Tried to overflow .text buffer. %08X > %08X", destination + sectionSize, (uint32_t) text_data.data() + text_data.size());
OSFatal("WUPSLoader: Tried to overflow buffer");
}
} else if ((address >= 0x10000000) && address < 0xC0000000) {
destination += (uint32_t) data_data.get();
destination += (uint32_t) data_data.data();
destination -= 0x10000000;
destinations[psec->get_index()] = (uint8_t *) data_data.get();
destinations[psec->get_index()] = (uint8_t *) data_data.data();
if (destination + sectionSize > (uint32_t) data_data.get() + data_size) {
DEBUG_FUNCTION_LINE_ERR("Tried to overflow .data buffer. %08X > %08X", destination + sectionSize, (uint32_t) data_data.get() + data_size);
if (destination + sectionSize > (uint32_t) data_data.data() + data_data.size()) {
DEBUG_FUNCTION_LINE_ERR("Tried to overflow .data buffer. %08X > %08X", destination + sectionSize, (uint32_t) text_data.data() + text_data.size());
OSFatal("WUPSLoader: Tried to overflow buffer");
}
} else if (address >= 0xC0000000) {
DEBUG_FUNCTION_LINE_ERR("Loading section from 0xC0000000 is NOT supported");
return std::nullopt;
return nullptr;
} else {
DEBUG_FUNCTION_LINE_ERR("Unhandled case");
return std::nullopt;
return nullptr;
}
const char *p = psec->get_data();
@@ -146,7 +144,7 @@ PluginInformationFactory::load(const std::shared_ptr<PluginData> &pluginData, re
auto sectionInfo = make_unique_nothrow<SectionInfo>(psec->get_name(), destination, sectionSize);
if (!sectionInfo) {
DEBUG_FUNCTION_LINE_ERR("Failed to allocat SectionInfo");
return {};
return nullptr;
}
pluginInfo->addSectionInfo(std::move(sectionInfo));
@@ -163,30 +161,30 @@ PluginInformationFactory::load(const std::shared_ptr<PluginData> &pluginData, re
section *psec = reader.sections[i];
if ((psec->get_type() == SHT_PROGBITS || psec->get_type() == SHT_NOBITS) && (psec->get_flags() & SHF_ALLOC)) {
DEBUG_FUNCTION_LINE_VERBOSE("Linking (%d)... %s at %08X", i, psec->get_name().c_str(), destinations[psec->get_index()]);
if (!linkSection(reader, psec->get_index(), (uint32_t) destinations[psec->get_index()], (uint32_t) text_data.get(), (uint32_t) data_data.get(), trampoline_data, trampoline_data_length,
if (!linkSection(reader, psec->get_index(), (uint32_t) destinations[psec->get_index()], (uint32_t) text_data.data(), (uint32_t) data_data.data(), trampolineData,
trampolineId)) {
DEBUG_FUNCTION_LINE_ERR("linkSection failed");
return {};
return nullptr;
}
}
}
if (!PluginInformationFactory::addImportRelocationData(pluginInfo, reader, destinations)) {
if (!PluginInformationFactory::addImportRelocationData(*pluginInfo, reader, destinations)) {
DEBUG_FUNCTION_LINE_ERR("addImportRelocationData failed");
return {};
return nullptr;
}
DCFlushRange((void *) text_data.get(), text_size);
ICInvalidateRange((void *) text_data.get(), text_size);
DCFlushRange((void *) data_data.get(), data_size);
ICInvalidateRange((void *) data_data.get(), data_size);
DCFlushRange((void *) text_data.data(), text_data.size());
ICInvalidateRange((void *) text_data.data(), text_data.size());
DCFlushRange((void *) data_data.data(), data_data.size());
ICInvalidateRange((void *) data_data.data(), data_data.size());
pluginInfo->setTrampolineId(trampolineId);
auto secInfo = pluginInfo->getSectionInfo(".wups.hooks");
if (secInfo && secInfo.value()->getSize() > 0) {
size_t entries_count = secInfo.value()->getSize() / sizeof(wups_loader_hook_t);
auto *entries = (wups_loader_hook_t *) secInfo.value()->getAddress();
if (secInfo && secInfo->getSize() > 0) {
size_t entries_count = secInfo->getSize() / sizeof(wups_loader_hook_t);
auto *entries = (wups_loader_hook_t *) secInfo->getAddress();
if (entries != nullptr) {
for (size_t j = 0; j < entries_count; j++) {
wups_loader_hook_t *hook = &entries[j];
@@ -194,7 +192,7 @@ PluginInformationFactory::load(const std::shared_ptr<PluginData> &pluginData, re
auto hookData = make_unique_nothrow<HookData>((void *) hook->target, hook->type);
if (!hookData) {
DEBUG_FUNCTION_LINE_ERR("Failed to allocate HookData");
return {};
return nullptr;
}
pluginInfo->addHookData(std::move(hookData));
}
@@ -202,14 +200,14 @@ PluginInformationFactory::load(const std::shared_ptr<PluginData> &pluginData, re
}
secInfo = pluginInfo->getSectionInfo(".wups.load");
if (secInfo && secInfo.value()->getSize() > 0) {
size_t entries_count = secInfo.value()->getSize() / sizeof(wups_loader_entry_t);
auto *entries = (wups_loader_entry_t *) secInfo.value()->getAddress();
if (secInfo && secInfo->getSize() > 0) {
size_t entries_count = secInfo->getSize() / sizeof(wups_loader_entry_t);
auto *entries = (wups_loader_entry_t *) secInfo->getAddress();
if (entries != nullptr) {
for (size_t j = 0; j < entries_count; j++) {
wups_loader_entry_t *cur_function = &entries[j];
DEBUG_FUNCTION_LINE_VERBOSE("Saving function \"%s\" of plugin . PA:%08X VA:%08X Library: %08X, target: %08X, call_addr: %08X",
cur_function->_function.name /*,pluginData->getPluginInformation()->getName().c_str()*/,
cur_function->_function.name /*,mPluginData->getPluginInformation()->getName().c_str()*/,
cur_function->_function.physical_address, cur_function->_function.virtual_address, cur_function->_function.library, cur_function->_function.target,
(void *) cur_function->_function.call_addr);
@@ -222,7 +220,7 @@ PluginInformationFactory::load(const std::shared_ptr<PluginData> &pluginData, re
(FunctionPatcherTargetProcess) cur_function->_function.targetProcess);
if (!functionData) {
DEBUG_FUNCTION_LINE_ERR("Failed to allocate FunctionData");
return {};
return nullptr;
}
pluginInfo->addFunctionData(std::move(functionData));
}
@@ -248,18 +246,18 @@ PluginInformationFactory::load(const std::shared_ptr<PluginData> &pluginData, re
if (symbols.get_symbol(j, name, value, size, bind, type, section, other)) {
if (type == STT_FUNC) { // We only care about functions.
auto sectionVal = reader.sections[section];
auto offsetVal = value - sectionVal->get_address();
auto sectionOpt = pluginInfo->getSectionInfo(sectionVal->get_name());
if (!sectionOpt.has_value()) {
auto sectionVal = reader.sections[section];
auto offsetVal = value - sectionVal->get_address();
auto sectionInfo = pluginInfo->getSectionInfo(sectionVal->get_name());
if (!sectionInfo) {
continue;
}
auto finalAddress = offsetVal + sectionOpt.value()->getAddress();
auto finalAddress = offsetVal + sectionInfo->getAddress();
auto functionSymbolData = make_unique_nothrow<FunctionSymbolData>(name, (void *) finalAddress, (uint32_t) size);
if (!functionSymbolData) {
DEBUG_FUNCTION_LINE_ERR("Failed to allocate FunctionSymbolData");
return {};
return nullptr;
}
pluginInfo->addFunctionSymbolData(std::move(functionSymbolData));
}
@@ -272,17 +270,18 @@ PluginInformationFactory::load(const std::shared_ptr<PluginData> &pluginData, re
if (totalSize > text_size + data_size) {
DEBUG_FUNCTION_LINE_ERR("We didn't allocate enough memory!!");
return std::nullopt;
return nullptr;
}
// Save the addresses for the allocated memory. This way we can free it again :)
pluginInfo->allocatedDataMemoryAddress = std::move(data_data);
pluginInfo->allocatedTextMemoryAddress = std::move(text_data);
pluginInfo->mAllocatedDataMemoryAddress = std::move(data_data);
pluginInfo->mAllocatedTextMemoryAddress = std::move(text_data);
return pluginInfo;
}
bool PluginInformationFactory::addImportRelocationData(const std::unique_ptr<PluginInformation> &pluginInfo, const elfio &reader, const std::unique_ptr<uint8_t *[]> &destinations) {
bool PluginInformationFactory::addImportRelocationData(PluginInformation &pluginInfo, const elfio &reader, std::span<uint8_t *> destinations) {
std::map<uint32_t, std::shared_ptr<ImportRPLInformation>> infoMap;
uint32_t sec_num = reader.sections.size();
@@ -352,16 +351,15 @@ bool PluginInformationFactory::addImportRelocationData(const std::unique_ptr<Plu
return false;
}
pluginInfo->addRelocationData(std::move(relocationData));
pluginInfo.addRelocationData(std::move(relocationData));
}
}
}
return true;
}
bool PluginInformationFactory::linkSection(const elfio &reader, uint32_t section_index, uint32_t destination, uint32_t base_text, uint32_t base_data, relocation_trampoline_entry_t *trampoline_data,
uint32_t trampoline_data_length,
uint8_t trampolineId) {
bool PluginInformationFactory::linkSection(const elfio &reader, uint32_t section_index, uint32_t destination, uint32_t base_text, uint32_t base_data,
std::vector<relocation_trampoline_entry_t> &trampolineData, uint8_t trampolineId) {
uint32_t sec_num = reader.sections.size();
for (uint32_t i = 0; i < sec_num; ++i) {
@@ -431,7 +429,7 @@ bool PluginInformationFactory::linkSection(const elfio &reader, uint32_t section
}
// DEBUG_FUNCTION_LINE_VERBOSE("sym_value %08X adjusted_sym_value %08X offset %08X adjusted_offset %08X", (uint32_t) sym_value, adjusted_sym_value, (uint32_t) offset, adjusted_offset);
if (!ElfUtils::elfLinkOne(type, adjusted_offset, addend, destination, adjusted_sym_value, trampoline_data, trampoline_data_length, RELOC_TYPE_FIXED, trampolineId)) {
if (!ElfUtils::elfLinkOne(type, adjusted_offset, addend, destination, adjusted_sym_value, trampolineData, RELOC_TYPE_FIXED, trampolineId)) {
DEBUG_FUNCTION_LINE_ERR("Link failed");
return false;
}

View File

@@ -27,17 +27,15 @@
#include <vector>
#include <wums/defines/relocation_defines.h>
class PluginInformationFactory {
public:
static std::optional<std::unique_ptr<PluginInformation>>
load(const std::shared_ptr<PluginData> &pluginData, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length,
uint8_t trampolineId);
static std::unique_ptr<PluginInformation>
load(const PluginData &pluginData, std::vector<relocation_trampoline_entry_t> &trampolineData, uint8_t trampolineId);
static bool
linkSection(const ELFIO::elfio &reader, uint32_t section_index, uint32_t destination, uint32_t base_text, uint32_t base_data, relocation_trampoline_entry_t *trampoline_data,
uint32_t trampoline_data_length,
uint8_t trampolineId);
linkSection(const ELFIO::elfio &reader, uint32_t section_index, uint32_t destination, uint32_t base_text, uint32_t base_data,
std::vector<relocation_trampoline_entry_t> &trampolineData, uint8_t trampolineId);
static bool addImportRelocationData(const std::unique_ptr<PluginInformation> &pluginInfo, const ELFIO::elfio &reader, const std::unique_ptr<uint8_t *[]> &destinations);
static bool
addImportRelocationData(PluginInformation &pluginInfo, const ELFIO::elfio &reader, std::span<uint8_t *> destinations);
};

View File

@@ -22,55 +22,34 @@
#include "utils/wiiu_zlib.hpp"
#include <memory>
std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFactory::loadPlugin(const std::shared_ptr<PluginData> &pluginData, PluginParseErrors &error) {
if (!pluginData->buffer) {
std::unique_ptr<PluginMetaInformation> PluginMetaInformationFactory::loadPlugin(const PluginData &pluginData, PluginParseErrors &error) {
return loadPlugin(pluginData.getBuffer(), error);
}
std::unique_ptr<PluginMetaInformation> PluginMetaInformationFactory::loadPlugin(std::string_view filePath, PluginParseErrors &error) {
std::vector<uint8_t> buffer;
if (FSUtils::LoadFileToMem(filePath, buffer) < 0) {
DEBUG_FUNCTION_LINE_ERR("Failed to load file to memory");
error = PLUGIN_PARSE_ERROR_IO_ERROR;
return {};
}
return loadPlugin(buffer, error);
}
std::unique_ptr<PluginMetaInformation> PluginMetaInformationFactory::loadPlugin(std::span<const uint8_t> buffer, PluginParseErrors &error) {
if (buffer.empty()) {
error = PLUGIN_PARSE_ERROR_BUFFER_EMPTY;
DEBUG_FUNCTION_LINE_ERR("Buffer is empty");
return {};
}
ELFIO::elfio reader(new wiiu_zlib);
if (!reader.load(reinterpret_cast<const char *>(pluginData->buffer.get()), pluginData->length)) {
error = PLUGIN_PARSE_ERROR_ELFIO_PARSE_FAILED;
DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio");
return {};
}
return loadPlugin(reader, error);
}
std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFactory::loadPlugin(const std::string &filePath, PluginParseErrors &error) {
ELFIO::elfio reader(new wiiu_zlib);
uint8_t *buffer = nullptr;
uint32_t length = 0;
if (FSUtils::LoadFileToMem(filePath.c_str(), &buffer, &length) < 0) {
DEBUG_FUNCTION_LINE_ERR("Failed to load file to memory");
error = PLUGIN_PARSE_ERROR_IO_ERROR;
return {};
}
if (!reader.load(reinterpret_cast<const char *>(buffer), length)) {
error = PLUGIN_PARSE_ERROR_ELFIO_PARSE_FAILED;
DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio");
return {};
}
auto res = loadPlugin(reader, error);
free(buffer);
return res;
}
std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFactory::loadPlugin(char *buffer, size_t size, PluginParseErrors &error) {
ELFIO::elfio reader(new wiiu_zlib);
if (!reader.load(reinterpret_cast<const char *>(buffer), size)) {
if (!reader.load(reinterpret_cast<const char *>(buffer.data()), buffer.size())) {
error = PLUGIN_PARSE_ERROR_ELFIO_PARSE_FAILED;
DEBUG_FUNCTION_LINE_ERR("Can't find or process ELF file");
return std::nullopt;
return nullptr;
}
return loadPlugin(reader, error);
}
std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFactory::loadPlugin(const ELFIO::elfio &reader, PluginParseErrors &error) {
size_t pluginSize = 0;
auto pluginInfo = std::unique_ptr<PluginMetaInformation>(new PluginMetaInformation);
@@ -127,7 +106,7 @@ std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFacto
if (value != "0.7.1") {
error = PLUGIN_PARSE_ERROR_INCOMPATIBLE_VERSION;
DEBUG_FUNCTION_LINE_ERR("Warning: Ignoring plugin - Unsupported WUPS version: %s.", value.c_str());
return std::nullopt;
return nullptr;
}
}
}

View File

@@ -36,11 +36,9 @@ enum PluginParseErrors {
class PluginMetaInformationFactory {
public:
static std::optional<std::unique_ptr<PluginMetaInformation>> loadPlugin(const std::shared_ptr<PluginData> &pluginData, PluginParseErrors &error);
static std::unique_ptr<PluginMetaInformation> loadPlugin(const PluginData &pluginData, PluginParseErrors &error);
static std::optional<std::unique_ptr<PluginMetaInformation>> loadPlugin(const std::string &filePath, PluginParseErrors &error);
static std::unique_ptr<PluginMetaInformation> loadPlugin(std::string_view filePath, PluginParseErrors &error);
static std::optional<std::unique_ptr<PluginMetaInformation>> loadPlugin(char *buffer, size_t size, PluginParseErrors &error);
static std::optional<std::unique_ptr<PluginMetaInformation>> loadPlugin(const ELFIO::elfio &reader, PluginParseErrors &error);
static std::unique_ptr<PluginMetaInformation> loadPlugin(std::span<const uint8_t> buffer, PluginParseErrors &error);
};

View File

@@ -57,8 +57,8 @@ public:
return name;
}
[[nodiscard]] const std::shared_ptr<ImportRPLInformation> &getImportRPLInformation() const {
return rplInfo;
[[nodiscard]] const ImportRPLInformation &getImportRPLInformation() const {
return *rplInfo;
}
private: