Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Monitor: Add ability to inspect process memory layout
Browse files Browse the repository at this point in the history
  • Loading branch information
byteduck committed Mar 2, 2024
1 parent 34342a1 commit 59a7ab5
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 6 deletions.
2 changes: 1 addition & 1 deletion programs/applications/monitor/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
SET(SOURCES main.cpp ProcessListWidget.cpp MemoryUsageWidget.cpp ProcessManager.cpp ProcessInspectorWidget.cpp)
SET(SOURCES main.cpp ProcessListWidget.cpp MemoryUsageWidget.cpp ProcessManager.cpp ProcessInspectorWidget.cpp ProcessMemoryLayoutWidget.cpp)
MAKE_APP(monitor)
TARGET_LINK_LIBRARIES(monitor libui libsys)
17 changes: 13 additions & 4 deletions programs/applications/monitor/ProcessInspectorWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include <libui/widget/NamedCell.h>

ProcessInspectorWidget::ProcessInspectorWidget(const Sys::Process& process):
UI::BoxLayout(VERTICAL),
UI::FlexLayout(VERTICAL),
m_process(process)
{
m_timer = UI::set_interval([this] {
Expand All @@ -25,7 +25,7 @@ ProcessInspectorWidget::ProcessInspectorWidget(const Sys::Process& process):
void ProcessInspectorWidget::initialize() {
// Header
{
auto header = UI::BoxLayout::make(HORIZONTAL, 4);
auto header = UI::BoxLayout::make(UI::BoxLayout::HORIZONTAL, 4);
auto name = m_process.name();
Duck::Ptr<const Gfx::Image> image;
if (m_app_info.exists()) {
Expand All @@ -43,7 +43,7 @@ void ProcessInspectorWidget::initialize() {

// Status
{
auto stack = UI::BoxLayout::make(VERTICAL);
auto stack = UI::BoxLayout::make(UI::BoxLayout::VERTICAL);
stack->add_child(m_pid = UI::Label::make("PID: " + std::to_string(m_process.pid()), UI::BEGINNING));
stack->add_child(m_executable = UI::Label::make("Executable: " + m_process.exe(), UI::BEGINNING));
stack->add_child(m_parent = UI::Label::make("Parent: " + std::to_string(m_process.ppid()), UI::BEGINNING));
Expand All @@ -54,13 +54,21 @@ void ProcessInspectorWidget::initialize() {

// Memory info
{
auto stack = UI::BoxLayout::make(VERTICAL);
auto stack = UI::BoxLayout::make(UI::BoxLayout::VERTICAL);
stack->add_child(m_memory_phys = UI::Label::make("", UI::BEGINNING));
stack->add_child(m_memory_virt = UI::Label::make("", UI::BEGINNING));
stack->add_child(m_memory_shared = UI::Label::make("", UI::BEGINNING));
add_child(UI::NamedCell::make("Memory", stack));
}

// Memory layout
{
m_memory_layout = ProcessMemoryLayoutWidget::make(m_process);
auto cell = UI::NamedCell::make("Memory Layout", m_memory_layout);
cell->set_sizing_mode(UI::FILL);
add_child(cell);
}

update();
}

Expand All @@ -73,4 +81,5 @@ void ProcessInspectorWidget::update() {
m_memory_phys->set_label("Physical: " + m_process.physical_mem().readable());
m_memory_virt->set_label("Virtual: " + m_process.virtual_mem().readable());
m_memory_shared->set_label("Shared: " + m_process.shared_mem().readable());
m_memory_layout->update();
}
4 changes: 3 additions & 1 deletion programs/applications/monitor/ProcessInspectorWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
#include <libui/Timer.h>
#include <libsys/Process.h>
#include <libui/widget/Label.h>
#include "ProcessMemoryLayoutWidget.h"

class ProcessInspectorWidget: public UI::BoxLayout {
class ProcessInspectorWidget: public UI::FlexLayout {
public:
WIDGET_DEF(ProcessInspectorWidget);

Expand All @@ -33,4 +34,5 @@ class ProcessInspectorWidget: public UI::BoxLayout {
Duck::Ptr<UI::Label> m_memory_phys;
Duck::Ptr<UI::Label> m_memory_virt;
Duck::Ptr<UI::Label> m_memory_shared;
Duck::Ptr<ProcessMemoryLayoutWidget> m_memory_layout;
};
1 change: 1 addition & 0 deletions programs/applications/monitor/ProcessListWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ Duck::Ptr<UI::Menu> ProcessListWidget::tv_entry_menu(int row) {
auto window = UI::Window::make();
window->set_contents(ProcessInspectorWidget::make(process));
window->set_title(process.name() + "(" + std::to_string(process.pid()) + ")");
window->set_resizable(true);
window->show();
})
});
Expand Down
112 changes: 112 additions & 0 deletions programs/applications/monitor/ProcessMemoryLayoutWidget.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright © 2016-2024 Byteduck */

#include "ProcessMemoryLayoutWidget.h"
#include <libui/widget/Label.h>

using namespace Sys;
using namespace UI;

ProcessMemoryLayoutWidget::ProcessMemoryLayoutWidget(Sys::Process process):
m_process(std::move(process))
{}

void ProcessMemoryLayoutWidget::update() {
m_memory_regions = m_process.memory_regions();
m_table_view->update_data();
}

void ProcessMemoryLayoutWidget::initialize() {
set_sizing_mode(UI::FILL);
m_table_view->set_delegate(self());
add_child(m_table_view);
}

Duck::Ptr<UI::Widget> ProcessMemoryLayoutWidget::tv_create_entry(int row, int col) {
auto reg = m_memory_regions[row];
std::string contents;

switch(col) {
case Col::Start:
contents = Duck::format("{#x}", reg.start);
break;
case Col::Size:
contents = reg.size.readable();
break;
case Col::Offset:
contents = Duck::format("{#x}", reg.object_start);
break;
case Col::Mode:
contents = Duck::format("{}{}{}{}",
reg.shared ? "s" : "p",
reg.prot.read ? "r" : "-",
reg.prot.write ? "w" : "-",
reg.prot.execute ? "x" : "-");
break;
case Col::Type:
contents = reg.type == Sys::Process::MemoryRegion::Inode ? "Inode" : "Anonymous";
break;
case Col::Name:
contents = reg.name;
break;
default:
break;
}

return Label::make(contents);
}

std::string ProcessMemoryLayoutWidget::tv_column_name(int col) {
switch(col) {
case Col::Start:
return "Start";
case Col::Size:
return "Size";
case Col::Offset:
return "Offset";
case Col::Mode:
return "Mode";
case Col::Type:
return "Type";
case Col::Name:
return "Name";
default:
return "";
}
}

int ProcessMemoryLayoutWidget::tv_num_entries() {
return m_memory_regions.size();
}

int ProcessMemoryLayoutWidget::tv_row_height() {
return 18;
}

int ProcessMemoryLayoutWidget::tv_column_width(int col) {
switch(col) {
case Col::Start:
return 80;
case Col::Size:
return 50;
case Col::Offset:
return 100;
case Col::Mode:
return 40;
case Col::Type:
return 80;
case Col::Name:
return -1;
default:
return -1;
}
}

void ProcessMemoryLayoutWidget::tv_selection_changed(const std::set<int>& selected_items) {
TableViewDelegate::tv_selection_changed(selected_items);
}

Duck::Ptr<UI::Menu> ProcessMemoryLayoutWidget::tv_entry_menu(int row) {
return TableViewDelegate::tv_entry_menu(row);
}

43 changes: 43 additions & 0 deletions programs/applications/monitor/ProcessMemoryLayoutWidget.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright © 2016-2024 Byteduck */

#pragma once

#include <libui/widget/TableView.h>
#include <libsys/Process.h>

class ProcessMemoryLayoutWidget: public UI::Widget, public UI::TableViewDelegate {
public:
WIDGET_DEF(ProcessMemoryLayoutWidget);
void update();

protected:
// ListViewDelegate
Duck::Ptr<Widget> tv_create_entry(int row, int col) override;
std::string tv_column_name(int col) override;
int tv_num_entries() override;
int tv_row_height() override;
int tv_column_width(int col) override;
UI::TableViewSelectionMode tv_selection_mode() override { return UI::TableViewSelectionMode::SINGLE; }
void tv_selection_changed(const std::set<int>& selected_items) override;
Duck::Ptr<UI::Menu> tv_entry_menu(int row) override;

// Object
void initialize() override;

private:
enum Col {
Start = 0,
Size = 1,
Offset = 2,
Mode = 3,
Type = 4,
Name = 5
};

ProcessMemoryLayoutWidget(Sys::Process process);

Sys::Process m_process;
Duck::Ptr<UI::TableView> m_table_view = UI::TableView::make(6, true);
std::vector<Sys::Process::MemoryRegion> m_memory_regions;
};

0 comments on commit 59a7ab5

Please sign in to comment.