diff options
| author | Yuri Kunde Schlesner <yuriks@yuriks.net> | 2015-07-11 20:07:49 -0700 | 
|---|---|---|
| committer | Yuri Kunde Schlesner <yuriks@yuriks.net> | 2015-07-11 20:07:49 -0700 | 
| commit | 4e900d56f3dd2b5c9871b523689322028123d891 (patch) | |
| tree | 2b233263cff7c001506f660373e2364c8e702637 /src/core/hle | |
| parent | b0d72e3de1ec2350716300c86bc02930893e9e23 (diff) | |
| parent | 5c5cf2f8e000d1bf4fc12ff20351aa60367cb563 (diff) | |
Merge pull request #912 from yuriks/process-loading
Core: Properly configure address space during binary loading
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/kernel/event.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/event.h | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 38 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.h | 43 | ||||
| -rw-r--r-- | src/core/hle/kernel/vm_manager.cpp | 14 | ||||
| -rw-r--r-- | src/core/hle/kernel/vm_manager.h | 6 | 
7 files changed, 89 insertions, 16 deletions
| diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index f338f3266..53feebbc0 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -21,7 +21,7 @@ SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) {      SharedPtr<Event> evt(new Event);      evt->signaled = false; -    evt->reset_type = evt->intitial_reset_type = reset_type; +    evt->reset_type = reset_type;      evt->name = std::move(name);      return evt; diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index fba960d2a..89d405236 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -26,7 +26,6 @@ public:      static const HandleType HANDLE_TYPE = HandleType::Event;      HandleType GetHandleType() const override { return HANDLE_TYPE; } -    ResetType intitial_reset_type;          ///< ResetType specified at Event initialization      ResetType reset_type;                   ///< Current ResetType      bool signaled;                          ///< Whether the event has already been signaled diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index b29260b5d..4c4486c19 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -47,6 +47,7 @@ enum class HandleType : u32 {      Semaphore       = 10,      Timer           = 11,      ResourceLimit   = 12, +    CodeSet         = 13,  };  enum { diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index b0e75ba59..a7892c652 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -5,24 +5,39 @@  #include "common/assert.h"  #include "common/common_funcs.h"  #include "common/logging/log.h" +#include "common/make_unique.h"  #include "core/hle/kernel/process.h"  #include "core/hle/kernel/resource_limit.h"  #include "core/hle/kernel/thread.h" +#include "core/hle/kernel/vm_manager.h" +#include "core/mem_map.h"  #include "core/memory.h"  namespace Kernel { +SharedPtr<CodeSet> CodeSet::Create(std::string name, u64 program_id) { +    SharedPtr<CodeSet> codeset(new CodeSet); + +    codeset->name = std::move(name); +    codeset->program_id = program_id; + +    return codeset; +} + +CodeSet::CodeSet() {} +CodeSet::~CodeSet() {} +  u32 Process::next_process_id; -SharedPtr<Process> Process::Create(std::string name, u64 program_id) { +SharedPtr<Process> Process::Create(SharedPtr<CodeSet> code_set) {      SharedPtr<Process> process(new Process); -    process->name = std::move(name); -    process->program_id = program_id; - +    process->codeset = std::move(code_set);      process->flags.raw = 0;      process->flags.memory_region = MemoryRegion::APPLICATION; +    process->address_space = Common::make_unique<VMManager>(); +    Memory::InitLegacyAddressSpace(*process->address_space);      return process;  } @@ -87,8 +102,19 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {      }  } -void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) { -    Kernel::SetupMainThread(entry_point, main_thread_priority); +void Process::Run(s32 main_thread_priority, u32 stack_size) { +    auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, MemoryState memory_state) { +        auto vma = address_space->MapMemoryBlock(segment.addr, codeset->memory, +                segment.offset, segment.size, memory_state).Unwrap(); +        address_space->Reprotect(vma, permissions); +    }; + +    MapSegment(codeset->code,   VMAPermission::ReadExecute, MemoryState::Code); +    MapSegment(codeset->rodata, VMAPermission::Read,        MemoryState::Code); +    MapSegment(codeset->data,   VMAPermission::ReadWrite,   MemoryState::Private); + +    address_space->LogLayout(); +    Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority);  }  Kernel::Process::Process() {} diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 674f5093a..92fa0fa6f 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -47,23 +47,51 @@ union ProcessFlags {  };  class ResourceLimit; +class VMManager; + +struct CodeSet final : public Object { +    static SharedPtr<CodeSet> Create(std::string name, u64 program_id); + +    std::string GetTypeName() const override { return "CodeSet"; } +    std::string GetName() const override { return name; } + +    static const HandleType HANDLE_TYPE = HandleType::CodeSet; +    HandleType GetHandleType() const override { return HANDLE_TYPE; } + +    /// Name of the process +    std::string name; +    /// Title ID corresponding to the process +    u64 program_id; + +    std::shared_ptr<std::vector<u8>> memory; + +    struct Segment { +        size_t offset = 0; +        VAddr addr = 0; +        u32 size = 0; +    }; + +    Segment code, rodata, data; +    VAddr entrypoint; + +private: +    CodeSet(); +    ~CodeSet() override; +};  class Process final : public Object {  public: -    static SharedPtr<Process> Create(std::string name, u64 program_id); +    static SharedPtr<Process> Create(SharedPtr<CodeSet> code_set);      std::string GetTypeName() const override { return "Process"; } -    std::string GetName() const override { return name; } +    std::string GetName() const override { return codeset->name; }      static const HandleType HANDLE_TYPE = HandleType::Process;      HandleType GetHandleType() const override { return HANDLE_TYPE; }      static u32 next_process_id; -    /// Name of the process -    std::string name; -    /// Title ID corresponding to the process -    u64 program_id; +    SharedPtr<CodeSet> codeset;      /// Resource limit descriptor for this process      SharedPtr<ResourceLimit> resource_limit; @@ -81,6 +109,7 @@ public:      /// Bitmask of the used TLS slots      std::bitset<300> used_tls_slots; +    std::unique_ptr<VMManager> address_space;      /**       * Parses a list of kernel capability descriptors (as found in the ExHeader) and applies them @@ -91,7 +120,7 @@ public:      /**       * Applies address space changes and launches the process main thread.       */ -    void Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size); +    void Run(s32 main_thread_priority, u32 stack_size);  private:      Process(); diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index ec437cd61..205cc7b53 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -35,6 +35,10 @@ VMManager::VMManager() {      Reset();  } +VMManager::~VMManager() { +    Reset(); +} +  void VMManager::Reset() {      vma_map.clear(); @@ -130,6 +134,16 @@ void VMManager::Reprotect(VMAHandle vma_handle, VMAPermission new_perms) {      MergeAdjacent(iter);  } +void VMManager::LogLayout() const { +    for (const auto& p : vma_map) { +        const VirtualMemoryArea& vma = p.second; +        LOG_DEBUG(Kernel, "%08X - %08X  size: %8X %c%c%c", vma.base, vma.base + vma.size, vma.size, +            (u8)vma.permissions & (u8)VMAPermission::Read    ? 'R' : '-', +            (u8)vma.permissions & (u8)VMAPermission::Write   ? 'W' : '-', +            (u8)vma.permissions & (u8)VMAPermission::Execute ? 'X' : '-'); +    } +} +  VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle & iter) {      // This uses a neat C++ trick to convert a const_iterator to a regular iterator, given      // non-const access to its container. diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index 271e2333e..b3795a94a 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h @@ -101,7 +101,7 @@ struct VirtualMemoryArea {   *  - http://duartes.org/gustavo/blog/post/how-the-kernel-manages-your-memory/   *  - http://duartes.org/gustavo/blog/post/page-cache-the-affair-between-memory-and-files/   */ -class VMManager { +class VMManager final {      // TODO(yuriks): Make page tables switchable to support multiple VMManagers  public:      /** @@ -121,6 +121,7 @@ public:      using VMAHandle = decltype(vma_map)::const_iterator;      VMManager(); +    ~VMManager();      /// Clears the address space map, re-initializing with a single free area.      void Reset(); @@ -168,6 +169,9 @@ public:      /// Changes the permissions of the given VMA.      void Reprotect(VMAHandle vma, VMAPermission new_perms); +    /// Dumps the address space layout to the log, for debugging +    void LogLayout() const; +  private:      using VMAIter = decltype(vma_map)::iterator; | 
