Serenity Operating System
1/*
2 * Copyright (c) 2020-2022, the SerenityOS developers.
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <AK/DeprecatedString.h>
8#include <AK/JsonObject.h>
9#include <AK/QuickSort.h>
10#include <LibCore/ArgsParser.h>
11#include <LibCore/File.h>
12#include <LibCore/System.h>
13#include <LibMain/Main.h>
14
15ErrorOr<int> serenity_main(Main::Arguments arguments)
16{
17 TRY(Core::System::pledge("stdio rpath"));
18 TRY(Core::System::unveil("/proc", "r"));
19 TRY(Core::System::unveil(nullptr, nullptr));
20
21 StringView pid;
22 static bool extended = false;
23
24 Core::ArgsParser args_parser;
25 args_parser.add_option(extended, "Extended output", nullptr, 'x');
26 args_parser.add_positional_argument(pid, "PID", "PID", Core::ArgsParser::Required::Yes);
27 args_parser.parse(arguments);
28
29 auto file = TRY(Core::File::open(DeprecatedString::formatted("/proc/{}/vm", pid), Core::File::OpenMode::Read));
30
31 outln("{}:", pid);
32
33 auto padding = " ";
34
35 if (extended) {
36 outln("Address{} Size Resident Dirty Access VMObject Type Purgeable CoW Pages Name", padding);
37 } else {
38 outln("Address{} Size Access Name", padding);
39 }
40
41 auto file_contents = TRY(file->read_until_eof());
42 auto json = TRY(JsonValue::from_string(file_contents));
43
44 Vector<JsonValue> sorted_regions = json.as_array().values();
45 quick_sort(sorted_regions, [](auto& a, auto& b) {
46 return a.as_object().get_addr("address"sv).value_or(0) < b.as_object().get_addr("address"sv).value_or(0);
47 });
48
49 for (auto& value : sorted_regions) {
50 auto& map = value.as_object();
51 auto address = map.get_addr("address"sv).value_or(0);
52 auto size = map.get("size"sv).value_or({}).to_deprecated_string();
53
54 auto access = DeprecatedString::formatted("{}{}{}{}{}",
55 (map.get_bool("readable"sv).value_or(false) ? "r" : "-"),
56 (map.get_bool("writable"sv).value_or(false) ? "w" : "-"),
57 (map.get_bool("executable"sv).value_or(false) ? "x" : "-"),
58 (map.get_bool("shared"sv).value_or(false) ? "s" : "-"),
59 (map.get_bool("syscall"sv).value_or(false) ? "c" : "-"));
60
61 out("{:p} ", address);
62 out("{:>10} ", size);
63 if (extended) {
64 auto resident = map.get("amount_resident"sv).value_or({}).to_deprecated_string();
65 auto dirty = map.get("amount_dirty"sv).value_or({}).to_deprecated_string();
66 auto vmobject = map.get_deprecated_string("vmobject"sv).value_or({});
67 if (vmobject.ends_with("VMObject"sv))
68 vmobject = vmobject.substring(0, vmobject.length() - 8);
69 auto purgeable = map.get("purgeable"sv).value_or({}).to_deprecated_string();
70 auto cow_pages = map.get("cow_pages"sv).value_or({}).to_deprecated_string();
71 out("{:>10} ", resident);
72 out("{:>10} ", dirty);
73 out("{:6} ", access);
74 out("{:14} ", vmobject);
75 out("{:10} ", purgeable);
76 out("{:>10} ", cow_pages);
77 } else {
78 out("{:6} ", access);
79 }
80 auto name = map.get_deprecated_string("name"sv).value_or({});
81 out("{:20}", name);
82 outln();
83 }
84
85 return 0;
86}