Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions Action.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ in the source distribution for its full text.
#include "ListItem.h"
#include "Macros.h"
#include "MainPanel.h"
#include "MapsScreen.h"
#include "MemoryMeter.h"
#include "Object.h"
#include "OpenFilesScreen.h"
Expand Down Expand Up @@ -747,6 +748,7 @@ static const struct {
{ .key = " i: ", .roInactive = true, .info = "set IO priority" },
{ .key = " l: ", .roInactive = true, .info = "list open files with lsof" },
{ .key = " x: ", .roInactive = false, .info = "list file locks of process" },
{ .key = " r: ", .roInactive = false, .info = "show memory maps of process" },
{ .key = " s: ", .roInactive = true, .info = "trace syscalls with strace" },
{ .key = " w: ", .roInactive = false, .info = "wrap process command in multiple lines" },
#ifdef SCHEDULER_SUPPORT
Expand Down Expand Up @@ -941,6 +943,24 @@ static Htop_Reaction actionShowEnvScreen(State* st) {
return HTOP_REFRESH | HTOP_REDRAW_BAR;
}

static Htop_Reaction actionShowMaps(State *st) {
if (!Action_readableProcess(st))
return HTOP_OK;

Process *p = (Process *)Panel_getSelected((Panel *)st->mainPanel);
if (!p)
return HTOP_OK;

assert(Object_isA((const Object *)p, (const ObjectClass *)&Process_class));

MapsScreen *es = MapsScreen_new(p);
InfoScreen_run((InfoScreen *)es);
MapsScreen_delete((Object *)es);
clear();
CRT_enableDelay();
return HTOP_REFRESH | HTOP_REDRAW_BAR;
}

static Htop_Reaction actionShowCommandScreen(State* st) {
if (!Action_readableProcess(st))
return HTOP_OK;
Expand Down Expand Up @@ -1007,6 +1027,7 @@ void Action_setBindings(Htop_Action* keys) {
keys['m'] = actionToggleMergedCommand;
keys['p'] = actionToggleProgramPath;
keys['q'] = actionQuit;
keys['r'] = actionShowMaps;
keys['s'] = actionStrace;
keys['t'] = actionToggleTreeView;
keys['u'] = actionFilterByUser;
Expand Down
2 changes: 2 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ myhtopsources = \
LoadAverageMeter.c \
Machine.c \
MainPanel.c \
MapsScreen.c \
MemoryMeter.c \
MemorySwapMeter.c \
Meter.c \
Expand Down Expand Up @@ -131,6 +132,7 @@ myhtopheaders = \
Machine.h \
Macros.h \
MainPanel.h \
MapsScreen.h \
MemoryMeter.h \
MemorySwapMeter.h \
Meter.h \
Expand Down
73 changes: 73 additions & 0 deletions MapsScreen.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
htop - MapsScreen.c
(C) 2025 Pierre Wilke
(C) 2025 htop dev team
Released under the GNU GPLv2+, see the COPYING file
in the source distribution for its full text.
*/

#include "config.h" // IWYU pragma: keep

#include "MapsScreen.h"

#include <stdlib.h>
#include <string.h>

#include "Macros.h"
#include "Panel.h"
#include "Platform.h"
#include "ProvideCurses.h"
#include "XUtils.h"


MapsScreen* MapsScreen_new(Process* process) {
MapsScreen* this = xMalloc(sizeof(MapsScreen));
Object_setClass(this, Class(MapsScreen));
return (MapsScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " ");
}

void MapsScreen_delete(Object* this) {
free(InfoScreen_done((InfoScreen*)this));
}

static void MapsScreen_draw(InfoScreen* this) {
InfoScreen_drawTitled(this, "Maps of process %d - %s", Process_getPid(this->process), Process_getCommand(this->process));
}

static void MapsScreen_scan(InfoScreen* this) {
Panel* panel = this->display;
int idx = MAXIMUM(Panel_getSelectedIndex(panel), 0);

Panel_prune(panel);

char* maps = Platform_getProcessMaps(Process_getPid(this->process));
if (maps) {
char* p = maps;
char* pp = maps;
while (*p) {
if (*p == '\n') {
*p = '\0';
InfoScreen_addLine(this, pp);
pp = p + 1;
}
p++;
}
free(maps);
} else {
InfoScreen_addLine(this, "Could not read process maps.");
}

/* The kernel already lists mappings in ascending start-address order;
keep it rather than sorting the lines as text (which would order the
addresses lexically). */
Panel_setSelected(panel, idx);
}

const InfoScreenClass MapsScreen_class = {
.super = {
.extends = Class(Object),
.delete = MapsScreen_delete
},
.scan = MapsScreen_scan,
.draw = MapsScreen_draw
};
26 changes: 26 additions & 0 deletions MapsScreen.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef HEADER_MapsScreen
#define HEADER_MapsScreen
/*
htop - MapsScreen.h
(C) 2025 Pierre Wilke
(C) 2025 htop dev team
Released under the GNU GPLv2+, see the COPYING file
in the source distribution for its full text.
*/

#include "InfoScreen.h"
#include "Object.h"
#include "Process.h"


typedef struct MapsScreen_ {
InfoScreen super;
} MapsScreen;

extern const InfoScreenClass MapsScreen_class;

MapsScreen* MapsScreen_new(Process* process);

void MapsScreen_delete(Object* this);

#endif
5 changes: 5 additions & 0 deletions darwin/Platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,11 @@ char* Platform_getProcessEnv(pid_t pid) {
return env;
}

char* Platform_getProcessMaps(pid_t pid) {
(void)pid;
return NULL;
}

FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
(void)pid;
return NULL;
Expand Down
2 changes: 2 additions & 0 deletions darwin/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ void Platform_setZfsCompressedArcValues(Meter* this);

char* Platform_getProcessEnv(pid_t pid);

char* Platform_getProcessMaps(pid_t pid);

FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid);

void Platform_getFileDescriptors(double* used, double* max);
Expand Down
5 changes: 5 additions & 0 deletions dragonflybsd/Platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,11 @@ char* Platform_getProcessEnv(pid_t pid) {
return NULL;
}

char* Platform_getProcessMaps(pid_t pid) {
(void)pid;
return NULL;
}

FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
(void)pid;
return NULL;
Expand Down
2 changes: 2 additions & 0 deletions dragonflybsd/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ void Platform_setSwapValues(Meter* this);

char* Platform_getProcessEnv(pid_t pid);

char* Platform_getProcessMaps(pid_t pid);

FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid);

void Platform_getFileDescriptors(double* used, double* max);
Expand Down
5 changes: 5 additions & 0 deletions freebsd/Platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,11 @@ char* Platform_getProcessEnv(pid_t pid) {
return env;
}

char* Platform_getProcessMaps(pid_t pid) {
(void)pid;
return NULL;
}

FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
(void)pid;
return NULL;
Expand Down
2 changes: 2 additions & 0 deletions freebsd/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ void Platform_setZfsCompressedArcValues(Meter* this);

char* Platform_getProcessEnv(pid_t pid);

char* Platform_getProcessMaps(pid_t pid);

FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid);

void Platform_getFileDescriptors(double* used, double* max);
Expand Down
40 changes: 40 additions & 0 deletions linux/Platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,46 @@ char* Platform_getProcessEnv(pid_t pid) {
return env;
}

char* Platform_getProcessMaps(pid_t pid) {
char procname[128];
xSnprintf(procname, sizeof(procname), PROCDIR "/%d/maps", pid);
FILE* fp = fopen(procname, "r");
if (!fp)
return NULL;

char* maps = NULL;

size_t capacity = 0;
size_t size = 0;

while (true) {
if (size == capacity) {
capacity += 4096;
maps = xRealloc(maps, capacity);
}

size_t bytes = fread(maps + size, 1, capacity - size, fp);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The clang analyzer complains about this line, with EOF/error state not properly checked.

size += bytes;
if (bytes == 0)
break;
}

bool failed = ferror(fp);
fclose(fp);

if (failed) {
free(maps);
return NULL;
}

maps = xRealloc(maps, size + 2);

maps[size] = '\0';
maps[size + 1] = '\0';

return maps;
}

FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
FileLocks_ProcessData* pdata = xCalloc(1, sizeof(FileLocks_ProcessData));
DIR* dirp;
Expand Down
2 changes: 2 additions & 0 deletions linux/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ void Platform_setZfsCompressedArcValues(Meter* this);

char* Platform_getProcessEnv(pid_t pid);

char* Platform_getProcessMaps(pid_t pid);

FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid);

void Platform_getPressureStall(const char* file, bool some, double* ten, double* sixty, double* threehundred);
Expand Down
5 changes: 5 additions & 0 deletions netbsd/Platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,11 @@ char* Platform_getProcessEnv(pid_t pid) {
return env;
}

char* Platform_getProcessMaps(pid_t pid) {
(void)pid;
return NULL;
}

FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
(void)pid;
return NULL;
Expand Down
2 changes: 2 additions & 0 deletions netbsd/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ void Platform_setSwapValues(Meter* this);

char* Platform_getProcessEnv(pid_t pid);

char* Platform_getProcessMaps(pid_t pid);

FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid);

void Platform_getFileDescriptors(double* used, double* max);
Expand Down
5 changes: 5 additions & 0 deletions openbsd/Platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,11 @@ char* Platform_getProcessEnv(pid_t pid) {
return env;
}

char* Platform_getProcessMaps(pid_t pid) {
(void)pid;
return NULL;
}

FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
(void)pid;
return NULL;
Expand Down
2 changes: 2 additions & 0 deletions openbsd/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ void Platform_setSwapValues(Meter* this);

char* Platform_getProcessEnv(pid_t pid);

char* Platform_getProcessMaps(pid_t pid);

FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid);

void Platform_getFileDescriptors(double* used, double* max);
Expand Down
5 changes: 5 additions & 0 deletions pcp/Platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,11 @@ char* Platform_getProcessEnv(pid_t pid) {
return value.cp;
}

char* Platform_getProcessMaps(pid_t pid) {
(void)pid;
return NULL;
}

FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
(void)pid;
return NULL;
Expand Down
2 changes: 2 additions & 0 deletions pcp/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ void Platform_setZfsCompressedArcValues(Meter* this);

char* Platform_getProcessEnv(pid_t pid);

char* Platform_getProcessMaps(pid_t pid);

FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid);

void Platform_getPressureStall(const char* file, bool some, double* ten, double* sixty, double* threehundred);
Expand Down
5 changes: 5 additions & 0 deletions solaris/Platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,11 @@ char* Platform_getProcessEnv(pid_t pid) {
return xRealloc(envBuilder.env, envBuilder.size + 1);
}

char* Platform_getProcessMaps(pid_t pid) {
(void)pid;
return NULL;
}

FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
(void)pid;
return NULL;
Expand Down
2 changes: 2 additions & 0 deletions solaris/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ void Platform_setZfsCompressedArcValues(Meter* this);

char* Platform_getProcessEnv(pid_t pid);

char* Platform_getProcessMaps(pid_t pid);

FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid);

void Platform_getFileDescriptors(double* used, double* max);
Expand Down
5 changes: 5 additions & 0 deletions unsupported/Platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,11 @@ char* Platform_getProcessEnv(pid_t pid) {
return NULL;
}

char* Platform_getProcessMaps(pid_t pid) {
(void)pid;
return NULL;
}

FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
(void)pid;
return NULL;
Expand Down
2 changes: 2 additions & 0 deletions unsupported/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ void Platform_setSwapValues(Meter* this);

char* Platform_getProcessEnv(pid_t pid);

char* Platform_getProcessMaps(pid_t pid);

FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid);

void Platform_getFileDescriptors(double* used, double* max);
Expand Down
Loading