diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index 9a86e5824..61808d094 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -3,6 +3,7 @@
 // Refer to the license.txt file included.
 
 #include <cinttypes>
+#include <cstring>
 #include "common/common_funcs.h"
 #include "common/file_util.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);
         if (module_file != nullptr) {
             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);
             // Register module with GDBStub
             GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false);
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp
index c10f826a4..4109b9974 100644
--- a/src/core/loader/nro.cpp
+++ b/src/core/loader/nro.cpp
@@ -18,7 +18,9 @@
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/vm_manager.h"
 #include "core/loader/nro.h"
+#include "core/loader/nso.h"
 #include "core/memory.h"
+#include "core/settings.h"
 
 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);
     }
 
+    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
     ModHeader mod_header{};
     // Default .bss to NRO header bss size if MOD0 section doesn't exist
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index 2186b02af..8ee2c6f2b 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -17,6 +17,7 @@
 #include "core/hle/kernel/vm_manager.h"
 #include "core/loader/nso.h"
 #include "core/memory.h"
+#include "core/settings.h"
 
 namespace Loader {
 
@@ -94,6 +95,7 @@ static constexpr u32 PageAlignSize(u32 size) {
 }
 
 VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base,
+                                bool should_pass_arguments,
                                 boost::optional<FileSys::PatchManager> pm) {
     if (file == nullptr)
         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()));
     }
 
+    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
     u32 module_offset;
     std::memcpy(&module_offset, program_image.data() + 4, sizeof(u32));
@@ -172,7 +185,7 @@ ResultStatus AppLoader_NSO::Load(Kernel::Process& process) {
 
     // Load module
     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);
 
     process.Run(base_address, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE);
diff --git a/src/core/loader/nso.h b/src/core/loader/nso.h
index 05353d4d9..7833af6ee 100644
--- a/src/core/loader/nso.h
+++ b/src/core/loader/nso.h
@@ -11,6 +11,13 @@
 
 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
 class AppLoader_NSO final : public AppLoader, Linker {
 public:
@@ -27,7 +34,7 @@ public:
         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);
 
     ResultStatus Load(Kernel::Process& process) override;