Просмотр исходного кода

kernel: offset code entry point for 39-bit address space type (#11326)

liamwhite 2 лет назад
Родитель
Сommit
18ad55be0b

+ 20 - 5
src/core/hle/kernel/k_process.cpp

@@ -38,7 +38,7 @@ namespace {
  */
 void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority,
                      KProcessAddress stack_top) {
-    const KProcessAddress entry_point = owner_process.GetPageTable().GetCodeRegionStart();
+    const KProcessAddress entry_point = owner_process.GetEntryPoint();
     ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::ThreadCountMax, 1));
 
     KThread* thread = KThread::Create(system.Kernel());
@@ -358,6 +358,21 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
     m_system_resource_size = metadata.GetSystemResourceSize();
     m_image_size = code_size;
 
+    if (metadata.GetAddressSpaceType() == FileSys::ProgramAddressSpaceType::Is39Bit) {
+        // For 39-bit processes, the ASLR region starts at 0x800'0000 and is ~512GiB large.
+        // However, some (buggy) programs/libraries like skyline incorrectly depend on the
+        // existence of ASLR pages before the entry point, so we will adjust the load address
+        // to point to about 2GiB into the ASLR region.
+        m_code_address = 0x8000'0000;
+    } else {
+        // All other processes can be mapped at the beginning of the code region.
+        if (metadata.GetAddressSpaceType() == FileSys::ProgramAddressSpaceType::Is36Bit) {
+            m_code_address = 0x800'0000;
+        } else {
+            m_code_address = 0x20'0000;
+        }
+    }
+
     KScopedResourceReservation memory_reservation(
         m_resource_limit, LimitableResource::PhysicalMemoryMax, code_size + m_system_resource_size);
     if (!memory_reservation.Succeeded()) {
@@ -368,15 +383,15 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
     // Initialize process address space
     if (const Result result{m_page_table.InitializeForProcess(
             metadata.GetAddressSpaceType(), false, false, false, KMemoryManager::Pool::Application,
-            0x8000000, code_size, std::addressof(m_kernel.GetAppSystemResource()), m_resource_limit,
-            m_kernel.System().ApplicationMemory())};
+            this->GetEntryPoint(), code_size, std::addressof(m_kernel.GetAppSystemResource()),
+            m_resource_limit, m_kernel.System().ApplicationMemory())};
         result.IsError()) {
         R_RETURN(result);
     }
 
     // Map process code region
-    if (const Result result{m_page_table.MapProcessCode(m_page_table.GetCodeRegionStart(),
-                                                        code_size / PageSize, KMemoryState::Code,
+    if (const Result result{m_page_table.MapProcessCode(this->GetEntryPoint(), code_size / PageSize,
+                                                        KMemoryState::Code,
                                                         KMemoryPermission::None)};
         result.IsError()) {
         R_RETURN(result);

+ 7 - 0
src/core/hle/kernel/k_process.h

@@ -177,6 +177,10 @@ public:
         return m_program_id;
     }
 
+    KProcessAddress GetEntryPoint() const {
+        return m_code_address;
+    }
+
     /// Gets the resource limit descriptor for this process
     KResourceLimit* GetResourceLimit() const;
 
@@ -485,6 +489,9 @@ private:
     /// Address indicating the location of the process' dedicated TLS region.
     KProcessAddress m_plr_address = 0;
 
+    /// Address indicating the location of the process's entry point.
+    KProcessAddress m_code_address = 0;
+
     /// Random values for svcGetInfo RandomEntropy
     std::array<u64, RANDOM_ENTROPY_SIZE> m_random_entropy{};
 

+ 1 - 1
src/core/loader/deconstructed_rom_directory.cpp

@@ -153,7 +153,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
 
     // Load NSO modules
     modules.clear();
-    const VAddr base_address{GetInteger(process.GetPageTable().GetCodeRegionStart())};
+    const VAddr base_address{GetInteger(process.GetEntryPoint())};
     VAddr next_load_addr{base_address};
     const FileSys::PatchManager pm{metadata.GetTitleID(), system.GetFileSystemController(),
                                    system.GetContentProvider()};

+ 1 - 1
src/core/loader/kip.cpp

@@ -96,7 +96,7 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process,
     }
 
     codeset.memory = std::move(program_image);
-    const VAddr base_address = GetInteger(process.GetPageTable().GetCodeRegionStart());
+    const VAddr base_address = GetInteger(process.GetEntryPoint());
     process.LoadModule(std::move(codeset), base_address);
 
     LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", kip->GetName(), base_address);

+ 1 - 1
src/core/loader/nro.cpp

@@ -203,7 +203,7 @@ static bool LoadNroImpl(Kernel::KProcess& process, const std::vector<u8>& data)
 
     // Load codeset for current process
     codeset.memory = std::move(program_image);
-    process.LoadModule(std::move(codeset), process.GetPageTable().GetCodeRegionStart());
+    process.LoadModule(std::move(codeset), process.GetEntryPoint());
 
     return true;
 }

+ 1 - 1
src/core/loader/nso.cpp

@@ -167,7 +167,7 @@ AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::KProcess& process, Core::S
     modules.clear();
 
     // Load module
-    const VAddr base_address = GetInteger(process.GetPageTable().GetCodeRegionStart());
+    const VAddr base_address = GetInteger(process.GetEntryPoint());
     if (!LoadModule(process, system, *file, base_address, true, true)) {
         return {ResultStatus::ErrorLoadingNSO, {}};
     }

+ 2 - 2
src/core/reporter.cpp

@@ -117,8 +117,8 @@ json GetProcessorStateDataAuto(Core::System& system) {
     arm.SaveContext(context);
 
     return GetProcessorStateData(process->Is64BitProcess() ? "AArch64" : "AArch32",
-                                 GetInteger(process->GetPageTable().GetCodeRegionStart()),
-                                 context.sp, context.pc, context.pstate, context.cpu_registers);
+                                 GetInteger(process->GetEntryPoint()), context.sp, context.pc,
+                                 context.pstate, context.cpu_registers);
 }
 
 json GetBacktraceData(Core::System& system) {