From 32d6df4ec2c755c09b3beb06b1f2c10fcf0483af Mon Sep 17 00:00:00 2001 From: Maschell Date: Sun, 15 Feb 2026 12:49:11 +0100 Subject: [PATCH] Add "aroma plugins list" iopshell command --- source/ShellCommands.cpp | 77 +++++++++++++++++++++++-- source/plugin/FunctionData.cpp | 7 +++ source/plugin/FunctionData.h | 4 ++ source/plugin/FunctionSymbolData.cpp | 6 ++ source/plugin/FunctionSymbolData.h | 4 ++ source/plugin/PluginConfigData.cpp | 8 +++ source/plugin/PluginConfigData.h | 3 + source/plugin/PluginContainer.cpp | 33 +++++++++++ source/plugin/PluginContainer.h | 2 + source/plugin/PluginData.cpp | 14 +++++ source/plugin/PluginData.h | 2 + source/plugin/PluginLinkInformation.cpp | 32 ++++++++++ source/plugin/PluginLinkInformation.h | 4 +- source/plugin/PluginMetaInformation.cpp | 14 +++++ source/plugin/PluginMetaInformation.h | 2 + source/plugin/RelocationData.cpp | 8 +++ source/plugin/RelocationData.h | 3 + source/plugin/SectionInfo.cpp | 6 ++ source/plugin/SectionInfo.h | 4 ++ source/utils/HeapMemoryFixedSize.cpp | 12 ++++ source/utils/HeapMemoryFixedSize.h | 4 ++ 21 files changed, 243 insertions(+), 6 deletions(-) diff --git a/source/ShellCommands.cpp b/source/ShellCommands.cpp index 80af048..f9231c3 100644 --- a/source/ShellCommands.cpp +++ b/source/ShellCommands.cpp @@ -36,6 +36,7 @@ namespace ShellCommands { } void Print() { + OSReport("\n"); PrintSeparator(); OSReport("|"); @@ -115,12 +116,12 @@ namespace ShellCommands { void PrintHeapUsage() { ConsoleTable table; - table.AddColumn("Plugin Name", ConsoleTable::LEFT); + table.AddColumn("Plugin name", ConsoleTable::LEFT); table.AddColumn("Current usage", ConsoleTable::RIGHT); table.AddColumn("Peak usage", ConsoleTable::RIGHT); - table.AddColumn("Currently allocated", ConsoleTable::RIGHT); - table.AddColumn("Total allocated", ConsoleTable::RIGHT); - table.AddColumn("Total freed", ConsoleTable::RIGHT); + table.AddColumn("Current allocations", ConsoleTable::RIGHT); + table.AddColumn("Total allocations", ConsoleTable::RIGHT); + table.AddColumn("Total frees", ConsoleTable::RIGHT); uint32_t totalCurrentBytes = 0; uint32_t totalPeakBytes = 0; @@ -164,11 +165,79 @@ namespace ShellCommands { } + void ListPlugins(int argc, char **argv) { + bool showAll = false; + if (argc > 1 && (std::string_view(argv[1]) == "-a" || std::string_view(argv[1]) == "--all")) { + showAll = true; + } + + ConsoleTable table; + + // Define Columns + table.AddColumn("Name", ConsoleTable::LEFT); + table.AddColumn("Author", ConsoleTable::LEFT); + table.AddColumn("Version", ConsoleTable::LEFT); + if (showAll) { + table.AddColumn("Active", ConsoleTable::LEFT); + } + table.AddColumn("API", ConsoleTable::LEFT); + table.AddColumn("Memory footprint", ConsoleTable::RIGHT); + table.AddColumn("Heap usage", ConsoleTable::RIGHT); + uint32_t totalSizeOther = 0; + for (const auto &plugin : gLoadedPlugins) { + if (!showAll && !plugin.isLinkedAndLoaded()) { + totalSizeOther += plugin.getMemoryFootprint(); + continue; + } + + auto meta = plugin.getMetaInformation(); + + std::string heapUsage = "unknown"; + if (const auto tracking = plugin.getTrackingMemoryAllocator()) { + uint32_t heapUsageSize = 0; + if (const auto stats = tracking->GetHeapMemoryUsageSnapshot()) { + heapUsageSize = stats->currentAllocated; + } + heapUsage = BytesToHumanReadable(heapUsageSize); + } + + std::vector rowData; + rowData.emplace_back(meta.getName()); + rowData.emplace_back(meta.getAuthor()); + rowData.emplace_back(meta.getVersion()); + if (showAll) { + rowData.emplace_back(plugin.isLinkedAndLoaded() ? "Yes" : "No"); + } + rowData.emplace_back(meta.getWUPSVersion().toString()); + rowData.emplace_back("~ " + BytesToHumanReadable(plugin.getMemoryFootprint())); + rowData.emplace_back(heapUsage); + + table.AddRow(rowData); + } + + if (totalSizeOther > 0 && !showAll) { + std::vector rowData; + rowData.emplace_back("Inactive Plugins"); + rowData.emplace_back("-"); + rowData.emplace_back("-"); + + rowData.emplace_back("-"); + rowData.emplace_back("~ " + BytesToHumanReadable(totalSizeOther)); + rowData.emplace_back("-"); + + table.AddFooter(rowData); + } + + table.Print(); + } + void Init() { sPluginGroup = std::make_unique("plugins", "Manage aroma plugins"); sPluginGroup->AddCommand("heap_usage", PrintHeapUsage, "Show current heap usage for tracked plugins"); + sPluginGroup->AddRawCommand("list", ListPlugins, "Lists active plugins", "Usage: \"list -a\" to list all plugins"); + sPluginCmdHandle = sPluginGroup->Register(); } } // namespace ShellCommands \ No newline at end of file diff --git a/source/plugin/FunctionData.cpp b/source/plugin/FunctionData.cpp index b1bb932..984297c 100644 --- a/source/plugin/FunctionData.cpp +++ b/source/plugin/FunctionData.cpp @@ -92,3 +92,10 @@ bool FunctionData::RemovePatch() { return true; } + +size_t FunctionData::getMemoryFootprint() const { + size_t totalSize = sizeof(*this); + + totalSize += mName.capacity(); + return totalSize; +} diff --git a/source/plugin/FunctionData.h b/source/plugin/FunctionData.h index 277999d..33ab2e4 100644 --- a/source/plugin/FunctionData.h +++ b/source/plugin/FunctionData.h @@ -53,6 +53,8 @@ public: bool RemovePatch(); private: + [[nodiscard]] size_t getMemoryFootprint() const; + void *mPAddress = nullptr; void *mVAddress = nullptr; std::string mName; @@ -62,4 +64,6 @@ private: void *mReplaceCall = nullptr; PatchedFunctionHandle mHandle = 0; + + friend class PluginLinkInformation; }; diff --git a/source/plugin/FunctionSymbolData.cpp b/source/plugin/FunctionSymbolData.cpp index 1692bf0..6728e8e 100644 --- a/source/plugin/FunctionSymbolData.cpp +++ b/source/plugin/FunctionSymbolData.cpp @@ -23,4 +23,10 @@ FunctionSymbolData::~FunctionSymbolData() = default; [[nodiscard]] uint32_t FunctionSymbolData::getSize() const { return mSize; +} + +size_t FunctionSymbolData::getMemoryFootprint() const { + size_t totalSize = sizeof(*this); + totalSize += mName.capacity(); + return totalSize; } \ No newline at end of file diff --git a/source/plugin/FunctionSymbolData.h b/source/plugin/FunctionSymbolData.h index 6daa3d9..61d0d7f 100644 --- a/source/plugin/FunctionSymbolData.h +++ b/source/plugin/FunctionSymbolData.h @@ -40,7 +40,11 @@ public: [[nodiscard]] uint32_t getSize() const; private: + [[nodiscard]] size_t getMemoryFootprint() const; + std::string mName; void *mAddress; uint32_t mSize; + + friend class PluginLinkInformation; }; \ No newline at end of file diff --git a/source/plugin/PluginConfigData.cpp b/source/plugin/PluginConfigData.cpp index 6762a02..4732cc5 100644 --- a/source/plugin/PluginConfigData.cpp +++ b/source/plugin/PluginConfigData.cpp @@ -35,6 +35,14 @@ WUPSConfigAPIStatus PluginConfigData::CallMenuClosedCallback() const { return WUPSCONFIG_API_RESULT_SUCCESS; } +size_t PluginConfigData::getMemoryFootprint() const { + size_t totalSize = sizeof(*this); + + totalSize += mName.capacity() * sizeof(char); + + return totalSize; +} + std::optional PluginConfigData::create(const WUPSConfigAPIOptions options, const WUPSConfigAPI_MenuOpenedCallback openedCallback, const WUPSConfigAPI_MenuClosedCallback closedCallback) { diff --git a/source/plugin/PluginConfigData.h b/source/plugin/PluginConfigData.h index 1e21290..459fb89 100644 --- a/source/plugin/PluginConfigData.h +++ b/source/plugin/PluginConfigData.h @@ -21,7 +21,10 @@ public: static std::optional create(WUPSConfigAPIOptions options, WUPSConfigAPI_MenuOpenedCallback openedCallback, WUPSConfigAPI_MenuClosedCallback closedCallback); private: + [[nodiscard]] size_t getMemoryFootprint() const; + std::string mName; WUPSConfigAPI_MenuOpenedCallback mOpenedCallback; WUPSConfigAPI_MenuClosedCallback mClosedCallback; + friend class PluginContainer; }; diff --git a/source/plugin/PluginContainer.cpp b/source/plugin/PluginContainer.cpp index 4508dc3..b21ebce 100644 --- a/source/plugin/PluginContainer.cpp +++ b/source/plugin/PluginContainer.cpp @@ -179,3 +179,36 @@ const TrackingPluginHeapMemoryAllocator *PluginContainer::getTrackingMemoryAlloc } return nullptr; } + +size_t PluginContainer::getMemoryFootprint() const { + size_t totalSize = sizeof(*this); + + if (mHandle) { + totalSize += sizeof(uint32_t); + } + + if (mPluginData) { + totalSize += mPluginData->getMemoryFootprint(); + } + + if (mPluginConfigData.has_value()) { + size_t configFootprint = mPluginConfigData->getMemoryFootprint(); + if (configFootprint > sizeof(PluginConfigData)) { + totalSize += (configFootprint - sizeof(PluginConfigData)); + } + } + { + size_t metaFootprint = mMetaInformation.getMemoryFootprint(); + if (metaFootprint > sizeof(PluginMetaInformation)) { + totalSize += (metaFootprint - sizeof(PluginMetaInformation)); + } + } + { + size_t linkFootprint = mPluginLinkInformation.getMemoryFootprint(); + if (linkFootprint > sizeof(PluginLinkInformation)) { + totalSize += (linkFootprint - sizeof(PluginLinkInformation)); + } + } + + return totalSize; +} \ No newline at end of file diff --git a/source/plugin/PluginContainer.h b/source/plugin/PluginContainer.h index 93b2a15..b3e043e 100644 --- a/source/plugin/PluginContainer.h +++ b/source/plugin/PluginContainer.h @@ -81,6 +81,8 @@ public: [[nodiscard]] const TrackingPluginHeapMemoryAllocator *getTrackingMemoryAllocator() const; + [[nodiscard]] size_t getMemoryFootprint() const; + private: PluginMetaInformation mMetaInformation; PluginLinkInformation mPluginLinkInformation; diff --git a/source/plugin/PluginData.cpp b/source/plugin/PluginData.cpp index 0d4b823..39c4b21 100644 --- a/source/plugin/PluginData.cpp +++ b/source/plugin/PluginData.cpp @@ -33,3 +33,17 @@ std::span PluginData::getBuffer() const { const std::string &PluginData::getSource() const { return mSource; } + +size_t PluginData::getMemoryFootprint() const { + size_t totalSize = sizeof(*this); + + totalSize += mBuffer.capacity() * sizeof(uint8_t); + + totalSize += mSource.capacity() * sizeof(char); + + if (mHandle) { + totalSize += sizeof(uint32_t); + } + + return totalSize; +} diff --git a/source/plugin/PluginData.h b/source/plugin/PluginData.h index fc18cb8..1ca4ce1 100644 --- a/source/plugin/PluginData.h +++ b/source/plugin/PluginData.h @@ -43,6 +43,8 @@ public: [[nodiscard]] const std::string &getSource() const; + size_t getMemoryFootprint() const; + private: std::vector mBuffer; std::string mSource; diff --git a/source/plugin/PluginLinkInformation.cpp b/source/plugin/PluginLinkInformation.cpp index 244c9fa..8f40725 100644 --- a/source/plugin/PluginLinkInformation.cpp +++ b/source/plugin/PluginLinkInformation.cpp @@ -120,3 +120,35 @@ std::span PluginLinkInformation::getTrampData() c const auto &entry = mAllocatedTextAndTrampMemoryAddress[1]; // 1 is tramp data return std::span(static_cast(entry.data()), entry.size() / sizeof(relocation_trampoline_entry_t)); } + +size_t PluginLinkInformation::getMemoryFootprint() const { + size_t totalSize = sizeof(*this); + + totalSize += mHookDataList.capacity() * sizeof(HookData); + + totalSize += mFunctionDataList.capacity() * sizeof(FunctionData); + for (const auto &func : mFunctionDataList) { + totalSize += (func.getMemoryFootprint() - sizeof(FunctionData)); + } + + totalSize += mRelocationDataList.capacity() * sizeof(RelocationData); + for (const auto &reloc : mRelocationDataList) { + totalSize += (reloc.getMemoryFootprint() - sizeof(RelocationData)); + } + + for (const auto &symbol : mSymbolDataList) { + totalSize += sizeof(FunctionSymbolData); + totalSize += (symbol.getMemoryFootprint() - sizeof(FunctionSymbolData)); + } + + for (const auto &[key, section] : mSectionInfoList) { + totalSize += sizeof(std::string) + sizeof(SectionInfo); + totalSize += key.capacity(); + totalSize += (section.getMemoryFootprint() - sizeof(SectionInfo)); + } + + totalSize += (mAllocatedTextAndTrampMemoryAddress.getMemoryFootprint() - sizeof(HeapMemoryFixedSizePool)); + totalSize += (mAllocatedDataMemoryAddress.getMemoryFootprint() - sizeof(HeapMemoryFixedSizePool)); + + return totalSize; +} diff --git a/source/plugin/PluginLinkInformation.h b/source/plugin/PluginLinkInformation.h index 451163c..a415275 100644 --- a/source/plugin/PluginLinkInformation.h +++ b/source/plugin/PluginLinkInformation.h @@ -70,10 +70,10 @@ public: [[nodiscard]] bool hasValidData() const; - [[nodiscard]] int numberOfSegments() const; - [[nodiscard]] std::span getTrampData() const; + size_t getMemoryFootprint() const; + private: PluginLinkInformation() = default; diff --git a/source/plugin/PluginMetaInformation.cpp b/source/plugin/PluginMetaInformation.cpp index 4fcfe92..79918a3 100644 --- a/source/plugin/PluginMetaInformation.cpp +++ b/source/plugin/PluginMetaInformation.cpp @@ -86,4 +86,18 @@ void PluginMetaInformation::setStorageId(std::string storageId) { void PluginMetaInformation::setHeapTrackingOptions(HeapTrackingOptions value) { mHeapTrackingOptions = value; +} + +size_t PluginMetaInformation::getMemoryFootprint() const { + size_t totalSize = sizeof(*this); + + totalSize += mName.capacity(); + totalSize += mAuthor.capacity(); + totalSize += mVersion.capacity(); + totalSize += mLicense.capacity(); + totalSize += mBuildTimestamp.capacity(); + totalSize += mDescription.capacity(); + totalSize += mStorageId.capacity(); + + return totalSize; } \ No newline at end of file diff --git a/source/plugin/PluginMetaInformation.h b/source/plugin/PluginMetaInformation.h index ed3b87b..1056ead 100644 --- a/source/plugin/PluginMetaInformation.h +++ b/source/plugin/PluginMetaInformation.h @@ -79,6 +79,8 @@ private: void setHeapTrackingOptions(HeapTrackingOptions value); + size_t getMemoryFootprint() const; + std::string mName; std::string mAuthor; std::string mVersion; diff --git a/source/plugin/RelocationData.cpp b/source/plugin/RelocationData.cpp index b51b026..11dc1c8 100644 --- a/source/plugin/RelocationData.cpp +++ b/source/plugin/RelocationData.cpp @@ -39,4 +39,12 @@ RelocationData::~RelocationData() = default; [[nodiscard]] const ImportRPLInformation &RelocationData::getImportRPLInformation() const { return *mRPLInfo; +} + +size_t RelocationData::getMemoryFootprint() const { + size_t totalSize = sizeof(*this); + + totalSize += mName.capacity(); + + return totalSize; } \ No newline at end of file diff --git a/source/plugin/RelocationData.h b/source/plugin/RelocationData.h index 36edb30..2dce232 100644 --- a/source/plugin/RelocationData.h +++ b/source/plugin/RelocationData.h @@ -46,10 +46,13 @@ public: [[nodiscard]] const ImportRPLInformation &getImportRPLInformation() const; private: + [[nodiscard]] size_t getMemoryFootprint() const; + char mType; size_t mOffset; int32_t mAddend; void *mDestination; std::string mName; std::shared_ptr mRPLInfo; + friend class PluginLinkInformation; }; diff --git a/source/plugin/SectionInfo.cpp b/source/plugin/SectionInfo.cpp index f109220..317e0b9 100644 --- a/source/plugin/SectionInfo.cpp +++ b/source/plugin/SectionInfo.cpp @@ -21,4 +21,10 @@ SectionInfo::SectionInfo(std::string name, [[nodiscard]] uint32_t SectionInfo::isInSection(uint32_t addr) const { return addr >= mAddress && addr < mAddress + mSectionSize; +} + +size_t SectionInfo::getMemoryFootprint() const { + size_t totalSize = sizeof(*this); + totalSize += mName.capacity(); + return totalSize; } \ No newline at end of file diff --git a/source/plugin/SectionInfo.h b/source/plugin/SectionInfo.h index 13fae4f..69882ff 100644 --- a/source/plugin/SectionInfo.h +++ b/source/plugin/SectionInfo.h @@ -35,7 +35,11 @@ public: [[nodiscard]] uint32_t isInSection(uint32_t addr) const; private: + [[nodiscard]] size_t getMemoryFootprint() const; + std::string mName; uint32_t mAddress = {}; uint32_t mSectionSize = {}; + + friend class PluginLinkInformation; }; diff --git a/source/utils/HeapMemoryFixedSize.cpp b/source/utils/HeapMemoryFixedSize.cpp index 478f3d9..52bf463 100644 --- a/source/utils/HeapMemoryFixedSize.cpp +++ b/source/utils/HeapMemoryFixedSize.cpp @@ -66,4 +66,16 @@ HeapMemoryFixedSizePool::MemorySegmentInfo HeapMemoryFixedSizePool::operator[](c DEBUG_FUNCTION_LINE_ERR("Out of bounce access (tried to access index %d; size is %d", idx, mSegmentInfos.size()); } return mSegmentInfos[idx]; +} + +size_t HeapMemoryFixedSizePool::getMemoryFootprint() const { + size_t totalSize = sizeof(*this); + + if (mData) { + totalSize += mTotalSize; + } + + totalSize += mSegmentInfos.capacity() * sizeof(MemorySegmentInfo); + + return totalSize; } \ No newline at end of file diff --git a/source/utils/HeapMemoryFixedSize.h b/source/utils/HeapMemoryFixedSize.h index b576624..8a206c9 100644 --- a/source/utils/HeapMemoryFixedSize.h +++ b/source/utils/HeapMemoryFixedSize.h @@ -39,7 +39,11 @@ public: MemorySegmentInfo operator[](int idx) const; private: + [[nodiscard]] size_t getMemoryFootprint() const; + std::unique_ptr mData{}; std::size_t mTotalSize{}; std::vector mSegmentInfos; + + friend class PluginLinkInformation; };