diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 7470a97cad..b0c3f4ae16 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -6,6 +6,7 @@ #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/memory.h" +#include "core/hle/kernel/object_address_table.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/resource_limit.h" #include "core/hle/kernel/thread.h" @@ -35,7 +36,9 @@ void Init(u32 system_mode) { /// Shutdown the kernel void Shutdown() { - g_handle_table.Clear(); // Free all kernel objects + // Free all kernel objects + g_handle_table.Clear(); + g_object_address_table.Clear(); Kernel::ThreadingShutdown(); g_current_process = nullptr; @@ -45,4 +48,4 @@ void Shutdown() { Kernel::MemoryShutdown(); } -} // namespace +} // namespace Kernel diff --git a/src/core/hle/kernel/object_address_table.cpp b/src/core/hle/kernel/object_address_table.cpp new file mode 100644 index 0000000000..dda532a88b --- /dev/null +++ b/src/core/hle/kernel/object_address_table.cpp @@ -0,0 +1,34 @@ +// Copyright 2018 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/assert.h" +#include "core/hle/kernel/object_address_table.h" + +namespace Kernel { + +ObjectAddressTable g_object_address_table; + +void ObjectAddressTable::Insert(VAddr addr, SharedPtr obj) { + ASSERT_MSG(objects.find(addr) == objects.end(), "Object already exists with addr=0x%llx", addr); + objects[addr] = obj; +} + +void ObjectAddressTable::Close(VAddr addr) { + ASSERT_MSG(objects.find(addr) != objects.end(), "Object does not exist with addr=0x%llx", addr); + objects.erase(addr); +} + +SharedPtr ObjectAddressTable::GetGeneric(VAddr addr) const { + auto iter = objects.find(addr); + if (iter != objects.end()) { + return iter->second; + } + return {}; +} + +void ObjectAddressTable::Clear() { + objects.clear(); +} + +} // namespace Kernel diff --git a/src/core/hle/kernel/object_address_table.h b/src/core/hle/kernel/object_address_table.h new file mode 100644 index 0000000000..ba0aac9e3a --- /dev/null +++ b/src/core/hle/kernel/object_address_table.h @@ -0,0 +1,62 @@ +// Copyright 2018 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include "common/common_types.h" +#include "core/hle/kernel/kernel.h" + +namespace Kernel { + +/** + * This class is used to keep a table of Kernel objects and their respective addresses in emulated + * memory. For certain Switch SVCs, Kernel objects are referenced by an address to an object the + * guest application manages, so we use this table to look these kernel objects up. This is similiar + * to the HandleTable class. + */ +class ObjectAddressTable final : NonCopyable { +public: + ObjectAddressTable() = default; + + /** + * Inserts an object and address pair into the table. + */ + void Insert(VAddr addr, SharedPtr obj); + + /** + * Closes an object by its address, removing it from the table and decreasing the object's + * ref-count. + * @return `RESULT_SUCCESS` or one of the following errors: + * - `ERR_INVALID_HANDLE`: an invalid handle was passed in. + */ + void Close(VAddr addr); + + /** + * Looks up an object by its address. + * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid. + */ + SharedPtr GetGeneric(VAddr addr) const; + + /** + * Looks up an object by its address while verifying its type. + * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid or its + * type differs from the requested one. + */ + template + SharedPtr Get(VAddr addr) const { + return DynamicObjectCast(GetGeneric(addr)); + } + + /// Closes all addresses held in this table. + void Clear(); + +private: + /// Stores the Object referenced by the address + std::map> objects; +}; + +extern ObjectAddressTable g_object_address_table; + +} // namespace Kernel