nso/nro: Add NSO arguments structure to data section

Only added if arguments string is non-empty and a pass is requested by loader.
This commit is contained in:
Zach Hilman 2018-09-30 14:04:48 -04:00
parent 6e4d2e672d
commit e09505ff61
4 changed files with 38 additions and 3 deletions

View File

@ -3,6 +3,7 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <cinttypes> #include <cinttypes>
#include <cstring>
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/file_util.h" #include "common/file_util.h"
#include "common/logging/log.h" #include "common/logging/log.h"
@ -140,7 +141,8 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process)
const FileSys::VirtualFile module_file = dir->GetFile(module); const FileSys::VirtualFile module_file = dir->GetFile(module);
if (module_file != nullptr) { if (module_file != nullptr) {
const VAddr load_addr = next_load_addr; const VAddr load_addr = next_load_addr;
next_load_addr = AppLoader_NSO::LoadModule(module_file, load_addr, pm); next_load_addr =
AppLoader_NSO::LoadModule(module_file, load_addr, std::strcmp(module, "rtld") == 0, pm);
LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr); LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr);
// Register module with GDBStub // Register module with GDBStub
GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false); GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false);

View File

@ -18,7 +18,9 @@
#include "core/hle/kernel/process.h" #include "core/hle/kernel/process.h"
#include "core/hle/kernel/vm_manager.h" #include "core/hle/kernel/vm_manager.h"
#include "core/loader/nro.h" #include "core/loader/nro.h"
#include "core/loader/nso.h"
#include "core/memory.h" #include "core/memory.h"
#include "core/settings.h"
namespace Loader { namespace Loader {
@ -150,6 +152,17 @@ bool AppLoader_NRO::LoadNro(FileSys::VirtualFile file, VAddr load_base) {
codeset->segments[i].size = PageAlignSize(nro_header.segments[i].size); codeset->segments[i].size = PageAlignSize(nro_header.segments[i].size);
} }
if (!Settings::values.program_args.empty()) {
const auto arg_data = Settings::values.program_args;
codeset->DataSegment().size += 0x9000;
NSOArgumentHeader args_header{0x9000, arg_data.size(), {}};
program_image.resize(static_cast<u32>(program_image.size()) + 0x9000);
std::memcpy(program_image.data() + program_image.size() - 0x9000, &args_header,
sizeof(NSOArgumentHeader));
std::memcpy(program_image.data() + program_image.size() - 0x8FE0, arg_data.data(),
arg_data.size());
}
// Read MOD header // Read MOD header
ModHeader mod_header{}; ModHeader mod_header{};
// Default .bss to NRO header bss size if MOD0 section doesn't exist // Default .bss to NRO header bss size if MOD0 section doesn't exist

View File

@ -17,6 +17,7 @@
#include "core/hle/kernel/vm_manager.h" #include "core/hle/kernel/vm_manager.h"
#include "core/loader/nso.h" #include "core/loader/nso.h"
#include "core/memory.h" #include "core/memory.h"
#include "core/settings.h"
namespace Loader { namespace Loader {
@ -94,6 +95,7 @@ static constexpr u32 PageAlignSize(u32 size) {
} }
VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base, VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base,
bool should_pass_arguments,
boost::optional<FileSys::PatchManager> pm) { boost::optional<FileSys::PatchManager> pm) {
if (file == nullptr) if (file == nullptr)
return {}; return {};
@ -125,6 +127,17 @@ VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base,
codeset->segments[i].size = PageAlignSize(static_cast<u32>(data.size())); codeset->segments[i].size = PageAlignSize(static_cast<u32>(data.size()));
} }
if (should_pass_arguments && !Settings::values.program_args.empty()) {
const auto arg_data = Settings::values.program_args;
codeset->DataSegment().size += 0x9000;
NSOArgumentHeader args_header{0x9000, arg_data.size(), {}};
program_image.resize(static_cast<u32>(program_image.size()) + 0x9000);
std::memcpy(program_image.data() + program_image.size() - 0x9000, &args_header,
sizeof(NSOArgumentHeader));
std::memcpy(program_image.data() + program_image.size() - 0x8FE0, arg_data.data(),
arg_data.size());
}
// MOD header pointer is at .text offset + 4 // MOD header pointer is at .text offset + 4
u32 module_offset; u32 module_offset;
std::memcpy(&module_offset, program_image.data() + 4, sizeof(u32)); std::memcpy(&module_offset, program_image.data() + 4, sizeof(u32));
@ -172,7 +185,7 @@ ResultStatus AppLoader_NSO::Load(Kernel::Process& process) {
// Load module // Load module
const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress();
LoadModule(file, base_address); LoadModule(file, base_address, true);
LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), base_address); LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), base_address);
process.Run(base_address, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE); process.Run(base_address, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE);

View File

@ -11,6 +11,13 @@
namespace Loader { namespace Loader {
struct NSOArgumentHeader {
u32_le allocated_size;
u32_le actual_size;
INSERT_PADDING_BYTES(0x18);
};
static_assert(sizeof(NSOArgumentHeader) == 0x20, "NSOArgumentHeader has incorrect size.");
/// Loads an NSO file /// Loads an NSO file
class AppLoader_NSO final : public AppLoader, Linker { class AppLoader_NSO final : public AppLoader, Linker {
public: public:
@ -27,7 +34,7 @@ public:
return IdentifyType(file); return IdentifyType(file);
} }
static VAddr LoadModule(FileSys::VirtualFile file, VAddr load_base, static VAddr LoadModule(FileSys::VirtualFile file, VAddr load_base, bool should_pass_arguments,
boost::optional<FileSys::PatchManager> pm = boost::none); boost::optional<FileSys::PatchManager> pm = boost::none);
ResultStatus Load(Kernel::Process& process) override; ResultStatus Load(Kernel::Process& process) override;