diff --git a/source/module/ModuleDataFactory.cpp b/source/module/ModuleDataFactory.cpp index 8c1aab4..d672a05 100644 --- a/source/module/ModuleDataFactory.cpp +++ b/source/module/ModuleDataFactory.cpp @@ -16,6 +16,7 @@ ****************************************************************************/ #include "ModuleDataFactory.h" +#include "../utils/FileUtils.h" #include "ElfUtils.h" #include #include @@ -29,10 +30,18 @@ ModuleDataFactory::load(const std::string &path, uint32_t destination_address_en elfio reader; std::shared_ptr moduleData = std::make_shared(); + uint8_t *buffer = nullptr; + uint32_t fsize = 0; + if (LoadFileToMem(path.c_str(), &buffer, &fsize) < 0) { + DEBUG_FUNCTION_LINE("Failed to load file"); + return {}; + } + // Load ELF data - if (!reader.load(path)) { + if (!reader.load(reinterpret_cast(buffer), fsize)) { DEBUG_FUNCTION_LINE("Can't find or process %s", path.c_str()); - return std::nullopt; + free(buffer); + return {}; } uint32_t sec_num = reader.sections.size(); @@ -52,6 +61,8 @@ ModuleDataFactory::load(const std::string &path, uint32_t destination_address_en if (sizeOfModule > maximum_size) { DEBUG_FUNCTION_LINE("Module is too big."); + free(destinations); + free(buffer); return {}; } @@ -78,6 +89,8 @@ ModuleDataFactory::load(const std::string &path, uint32_t destination_address_en totalSize += sectionSize; if (totalSize > maximum_size) { DEBUG_FUNCTION_LINE("Couldn't load setup module because it's too big."); + free(destinations); + free(buffer); return {}; } @@ -100,6 +113,7 @@ ModuleDataFactory::load(const std::string &path, uint32_t destination_address_en } else { DEBUG_FUNCTION_LINE("Unhandled case"); free(destinations); + free(buffer); return std::nullopt; } @@ -138,6 +152,7 @@ ModuleDataFactory::load(const std::string &path, uint32_t destination_address_en if (!linkSection(reader, psec->get_index(), (uint32_t) destinations[psec->get_index()], offset_text, offset_data, trampolin_data, trampolin_data_length)) { DEBUG_FUNCTION_LINE("elfLink failed"); free(destinations); + free(buffer); return std::nullopt; } } @@ -152,6 +167,7 @@ ModuleDataFactory::load(const std::string &path, uint32_t destination_address_en ICInvalidateRange((void *) baseOffset, totalSize); free(destinations); + free(buffer); moduleData->setStartAddress(startAddress); moduleData->setEndAddress(endAddress); diff --git a/source/utils/FileUtils.cpp b/source/utils/FileUtils.cpp new file mode 100644 index 0000000..aa9b2fa --- /dev/null +++ b/source/utils/FileUtils.cpp @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include +#include + +#define ROUNDDOWN(val, align) ((val) & ~(align - 1)) +#define ROUNDUP(val, align) ROUNDDOWN(((val) + (align - 1)), align) + +int32_t LoadFileToMem(const char *filepath, uint8_t **inbuffer, uint32_t *size) { + //! always initialze input + *inbuffer = NULL; + if (size) { + *size = 0; + } + + int32_t iFd = open(filepath, O_RDONLY); + if (iFd < 0) { + return -1; + } + + uint32_t filesize = lseek(iFd, 0, SEEK_END); + lseek(iFd, 0, SEEK_SET); + + auto *buffer = (uint8_t *) memalign(0x40, ROUNDUP(filesize, 0x40)); + if (buffer == nullptr) { + close(iFd); + return -2; + } + + uint32_t blocksize = 0x20000; + uint32_t done = 0; + int32_t readBytes = 0; + + while (done < filesize) { + if (done + blocksize > filesize) { + blocksize = filesize - done; + } + readBytes = read(iFd, buffer + done, blocksize); + if (readBytes <= 0) + break; + done += readBytes; + } + + ::close(iFd); + + if (done != filesize) { + free(buffer); + buffer = nullptr; + return -3; + } + + *inbuffer = buffer; + + //! sign is optional input + if (size) { + *size = filesize; + } + + return filesize; +} diff --git a/source/utils/FileUtils.h b/source/utils/FileUtils.h new file mode 100644 index 0000000..e9b0bc7 --- /dev/null +++ b/source/utils/FileUtils.h @@ -0,0 +1,3 @@ +#pragma once + +int32_t LoadFileToMem(const char *filepath, uint8_t **inbuffer, uint32_t *size); \ No newline at end of file