aboutsummaryrefslogtreecommitdiff
path: root/src/memory/maps.cc
blob: 290675a6d04d3f6847d5ae6b0b48220f1d3416c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include "memory/maps.hh"

namespace memory {

static std::string get_pid_from_name(const std::string& name) {
    for (const auto& pid : std::filesystem::directory_iterator("/proc")) {
        if (!pid.is_directory()) {
            continue;
        }

        std::ifstream file{std::string{pid.path()} + "/comm"};
        if (!file.is_open()) {
            continue;
        }
        const std::string contents{std::istreambuf_iterator<char>{file},
                                   std::istreambuf_iterator<char>{}};
        if (!contents.starts_with(name)) {
            continue;
        }

        const std::string pathname = pid.path();
        const auto pos = static_cast<long>(pathname.find_last_of('/'));
        return {std::next(std::begin(pathname) + pos), std::end(pathname)};
    }

    throw std::runtime_error{"failed to get pid from name \"" + name +
                             "\", is it open?"};
}

maps::maps(const char* const name) : pid(get_pid_from_name(name)) {
    std::ifstream file{"/proc/" + this->pid + "/maps"};
    if (!file.is_open()) {
        throw std::runtime_error{"failed to open maps for pid \"" + this->pid +
                                 '\"'};
    }
    std::stringstream file_ss;
    file_ss << file.rdbuf();
    for (std::string line; std::getline(file_ss, line);) {
        if (line.empty()) {
            continue;
        }

        std::stringstream line_ss{line};

        // address           perms offset  dev   inode       pathname
        // 00400000-00452000 r-xp 00000000 08:02 173521      /usr/bin/dbus-daemon
        maps::region region;
        line_ss >> region.start;
        line_ss.ignore(); // ignore dash
        line_ss >> region.end;
        line_ss >> region.perms;
        line_ss >> region.offset;
        line_ss >> region.dev;
        line_ss >> region.inode;
        line_ss >> region.pathname;
        this->regions.push_back(std::move(region));
    }
}

} // namespace memory