Add "aroma plugins list" iopshell command

This commit is contained in:
Maschell 2026-02-15 12:49:11 +01:00
parent 185aeee387
commit 32d6df4ec2
21 changed files with 243 additions and 6 deletions

View File

@ -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<std::string> 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<std::string> 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<IOPShellModule::CommandGroup>("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

View File

@ -92,3 +92,10 @@ bool FunctionData::RemovePatch() {
return true;
}
size_t FunctionData::getMemoryFootprint() const {
size_t totalSize = sizeof(*this);
totalSize += mName.capacity();
return totalSize;
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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> PluginConfigData::create(const WUPSConfigAPIOptions options,
const WUPSConfigAPI_MenuOpenedCallback openedCallback,
const WUPSConfigAPI_MenuClosedCallback closedCallback) {

View File

@ -21,7 +21,10 @@ public:
static std::optional<PluginConfigData> 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;
};

View File

@ -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;
}

View File

@ -81,6 +81,8 @@ public:
[[nodiscard]] const TrackingPluginHeapMemoryAllocator *getTrackingMemoryAllocator() const;
[[nodiscard]] size_t getMemoryFootprint() const;
private:
PluginMetaInformation mMetaInformation;
PluginLinkInformation mPluginLinkInformation;

View File

@ -33,3 +33,17 @@ std::span<const uint8_t> 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;
}

View File

@ -43,6 +43,8 @@ public:
[[nodiscard]] const std::string &getSource() const;
size_t getMemoryFootprint() const;
private:
std::vector<uint8_t> mBuffer;
std::string mSource;

View File

@ -120,3 +120,35 @@ std::span<relocation_trampoline_entry_t> PluginLinkInformation::getTrampData() c
const auto &entry = mAllocatedTextAndTrampMemoryAddress[1]; // 1 is tramp data
return std::span(static_cast<relocation_trampoline_entry_t *>(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;
}

View File

@ -70,10 +70,10 @@ public:
[[nodiscard]] bool hasValidData() const;
[[nodiscard]] int numberOfSegments() const;
[[nodiscard]] std::span<relocation_trampoline_entry_t> getTrampData() const;
size_t getMemoryFootprint() const;
private:
PluginLinkInformation() = default;

View File

@ -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;
}

View File

@ -79,6 +79,8 @@ private:
void setHeapTrackingOptions(HeapTrackingOptions value);
size_t getMemoryFootprint() const;
std::string mName;
std::string mAuthor;
std::string mVersion;

View File

@ -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;
}

View File

@ -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<ImportRPLInformation> mRPLInfo;
friend class PluginLinkInformation;
};

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -39,7 +39,11 @@ public:
MemorySegmentInfo operator[](int idx) const;
private:
[[nodiscard]] size_t getMemoryFootprint() const;
std::unique_ptr<uint8_t[]> mData{};
std::size_t mTotalSize{};
std::vector<MemorySegmentInfo> mSegmentInfos;
friend class PluginLinkInformation;
};