Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f31c7098 authored by Sandeep Patil's avatar Sandeep Patil
Browse files

procinfo: Read inode number from /proc/<pid>/maps



Adjust all callbacks to include the inode number as well.

Fixes: 123532375
Test: libprocinfo_test
Test: libdmabufinfo_test
Test: libmeminfo_test

Change-Id: I71fd75d90d5ee44585011c5ae654a1dd7e185458
Signed-off-by: default avatarSandeep Patil <sspatil@google.com>
parent c6a2d7d5
Loading
Loading
Loading
Loading
+17 −17
Original line number Diff line number Diff line
@@ -46,8 +46,7 @@ BacktraceMap::BacktraceMap(pid_t pid) : pid_(pid) {
  }
}

BacktraceMap::~BacktraceMap() {
}
BacktraceMap::~BacktraceMap() {}

void BacktraceMap::FillIn(uint64_t addr, backtrace_map_t* map) {
  ScopedBacktraceMapIteratorLock lock(this);
@@ -69,11 +68,12 @@ static bool ParseLine(const char* line, backtrace_map_t* map) {
  int name_pos;

  // Mac OS vmmap(1) output:
// __TEXT                 0009f000-000a1000 [    8K     8K] r-x/rwx SM=COW  /Volumes/android/dalvik-dev/out/host/darwin-x86/bin/libcorkscrew_test\n
  // __TEXT                 0009f000-000a1000 [    8K     8K] r-x/rwx SM=COW
  // /Volumes/android/dalvik-dev/out/host/darwin-x86/bin/libcorkscrew_test\n
  // 012345678901234567890123456789012345678901234567890123456789
  // 0         1         2         3         4         5
  if (sscanf(line, "%*21c %" SCNx64 "-%" SCNx64 " [%*13c] %3c/%*3c SM=%*3c  %n",
             &start, &end, permissions, &name_pos) != 3) {
  if (sscanf(line, "%*21c %" SCNx64 "-%" SCNx64 " [%*13c] %3c/%*3c SM=%*3c  %n", &start, &end,
             permissions, &name_pos) != 3) {
    return false;
  }

@@ -95,16 +95,16 @@ static bool ParseLine(const char* line, backtrace_map_t* map) {
    map->name.erase(map->name.length() - 1);
  }

  ALOGV("Parsed map: start=%p, end=%p, flags=%x, name=%s",
        reinterpret_cast<void*>(map->start), reinterpret_cast<void*>(map->end),
        map->flags, map->name.c_str());
  ALOGV("Parsed map: start=%p, end=%p, flags=%x, name=%s", reinterpret_cast<void*>(map->start),
        reinterpret_cast<void*>(map->end), map->flags, map->name.c_str());
  return true;
}
#endif  // defined(__APPLE__)

bool BacktraceMap::Build() {
#if defined(__APPLE__)
  char cmd[sizeof(pid_t)*3 + sizeof("vmmap -w -resident -submap -allSplitLibs -interleaved ") + 1];
  char
      cmd[sizeof(pid_t) * 3 + sizeof("vmmap -w -resident -submap -allSplitLibs -interleaved ") + 1];
  char line[1024];
  // cmd is guaranteed to always be big enough to hold this string.
  snprintf(cmd, sizeof(cmd), "vmmap -w -resident -submap -allSplitLibs -interleaved %d", pid_);
@@ -123,7 +123,7 @@ bool BacktraceMap::Build() {
  return true;
#else
  return android::procinfo::ReadProcessMaps(
      pid_, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t, const char* name) {
      pid_, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t, ino_t, const char* name) {
        maps_.resize(maps_.size() + 1);
        backtrace_map_t& map = maps_.back();
        map.start = start;
+5 −26
Original line number Diff line number Diff line
@@ -123,18 +123,14 @@ static bool ReadDmaBufFdRefs(pid_t pid, std::vector<DmaBuffer>* dmabufs) {
        auto buf = std::find_if(dmabufs->begin(), dmabufs->end(),
                                [&inode](const DmaBuffer& dbuf) { return dbuf.inode() == inode; });
        if (buf != dmabufs->end()) {
            if (buf->name() == "" || buf->name() == "<unknown>")
                buf->SetName(name);
            if (buf->exporter() == "" || buf->exporter() == "<unknown>")
                buf->SetExporter(exporter);
            if (buf->count() == 0)
                buf->SetCount(count);
            if (buf->name() == "" || buf->name() == "<unknown>") buf->SetName(name);
            if (buf->exporter() == "" || buf->exporter() == "<unknown>") buf->SetExporter(exporter);
            if (buf->count() == 0) buf->SetCount(count);
            buf->AddFdRef(pid);
            return true;
        }

        DmaBuffer& db =
                dmabufs->emplace_back(sb.st_ino, sb.st_blocks * 512, count, exporter, name);
        DmaBuffer& db = dmabufs->emplace_back(sb.st_ino, sb.st_blocks * 512, count, exporter, name);
        db.AddFdRef(pid);
    }

@@ -155,29 +151,12 @@ static bool ReadDmaBufMapRefs(pid_t pid, std::vector<DmaBuffer>* dmabufs) {
    // Process the map if it is dmabuf. Add map reference to existing object in 'dmabufs'
    // if it was already found. If it wasn't create a new one and append it to 'dmabufs'
    auto account_dmabuf = [&](uint64_t start, uint64_t end, uint16_t /* flags */,
                              uint64_t /* pgoff */, const char* name) {
                              uint64_t /* pgoff */, ino_t inode, const char* name) {
        // no need to look into this mapping if it is not dmabuf
        if (!FileIsDmaBuf(std::string(name))) {
            return;
        }

        // TODO (b/123532375) : Add inode number to the callback of ReadMapFileContent.
        //
        // Workaround: we know 'name' points to the name at the end of 'line'.
        // We use that to backtrack and pick up the inode number from the line as well.
        // start    end      flag pgoff    mj:mn inode   name
        // 00400000-00409000 r-xp 00000000 00:00 426998  /dmabuf (deleted)
        const char* p = name;
        p--;
        // skip spaces
        while (p != line && *p == ' ') {
            p--;
        }
        // walk backwards to the beginning of inode number
        while (p != line && isdigit(*p)) {
            p--;
        }
        uint64_t inode = strtoull(p, nullptr, 10);
        auto buf = std::find_if(dmabufs->begin(), dmabufs->end(),
                                [&inode](const DmaBuffer& dbuf) { return dbuf.inode() == inode; });
        if (buf != dmabufs->end()) {
+2 −2
Original line number Diff line number Diff line
@@ -246,7 +246,7 @@ bool ProcMemInfo::ReadMaps(bool get_wss, bool use_pageidle) {
    // parse and read /proc/<pid>/maps
    std::string maps_file = ::android::base::StringPrintf("/proc/%d/maps", pid_);
    if (!::android::procinfo::ReadMapFile(
                maps_file, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff,
                maps_file, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t,
                               const char* name) {
                    maps_.emplace_back(Vma(start, end, pgoff, flags, name));
                })) {
@@ -394,7 +394,7 @@ bool ForEachVmaFromFile(const std::string& path, const VmaCallback& callback) {
        // If it has, we are looking for the vma stats
        // 00400000-00409000 r-xp 00000000 fc:00 426998  /usr/lib/gvfs/gvfsd-http
        if (!::android::procinfo::ReadMapFileContent(
                    line, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff,
                    line, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t,
                              const char* name) {
                        vma.start = start;
                        vma.end = end;
+3 −1
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <fcntl.h>
#include <inttypes.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

#include <android-base/unique_fd.h>
@@ -30,7 +31,8 @@ namespace android {
struct ReadMapCallback {
  ReadMapCallback(allocator::vector<Mapping>& mappings) : mappings_(mappings) {}

  void operator()(uint64_t start, uint64_t end, uint16_t flags, uint64_t, const char* name) const {
  void operator()(uint64_t start, uint64_t end, uint16_t flags, uint64_t, ino_t,
                  const char* name) const {
    mappings_.emplace_back(start, end, flags & PROT_READ, flags & PROT_WRITE, flags & PROT_EXEC,
                           name);
  }
+22 −13
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ bool ReadMapFileContent(char* content, const CallbackType& callback) {
  uint64_t end_addr;
  uint16_t flags;
  uint64_t pgoff;
  ino_t inode;
  char* next_line = content;
  char* p;

@@ -124,18 +125,25 @@ bool ReadMapFileContent(char* content, const CallbackType& callback) {
      return false;
    }
    // inode
    if (!pass_xdigit() || (*p != '\0' && !pass_space())) {
    inode = strtoull(p, &end, 10);
    if (end == p) {
      return false;
    }
    p = end;

    if (*p != '\0' && !pass_space()) {
      return false;
    }

    // filename
    callback(start_addr, end_addr, flags, pgoff, p);
    callback(start_addr, end_addr, flags, pgoff, inode, p);
  }
  return true;
}

inline bool ReadMapFile(
    const std::string& map_file,
    const std::function<void(uint64_t, uint64_t, uint16_t, uint64_t, const char*)>& callback) {
inline bool ReadMapFile(const std::string& map_file,
                        const std::function<void(uint64_t, uint64_t, uint16_t, uint64_t, ino_t,
                                                 const char*)>& callback) {
  std::string content;
  if (!android::base::ReadFileToString(map_file, &content)) {
    return false;
@@ -143,9 +151,9 @@ inline bool ReadMapFile(
  return ReadMapFileContent(&content[0], callback);
}

inline bool ReadProcessMaps(
    pid_t pid,
    const std::function<void(uint64_t, uint64_t, uint16_t, uint64_t, const char*)>& callback) {
inline bool ReadProcessMaps(pid_t pid,
                            const std::function<void(uint64_t, uint64_t, uint16_t, uint64_t, ino_t,
                                                     const char*)>& callback) {
  return ReadMapFile("/proc/" + std::to_string(pid) + "/maps", callback);
}

@@ -154,17 +162,18 @@ struct MapInfo {
  uint64_t end;
  uint16_t flags;
  uint64_t pgoff;
  ino_t inode;
  std::string name;

  MapInfo(uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, const char* name)
      : start(start), end(end), flags(flags), pgoff(pgoff), name(name) {}
  MapInfo(uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode,
          const char* name)
      : start(start), end(end), flags(flags), pgoff(pgoff), inode(inode), name(name) {}
};

inline bool ReadProcessMaps(pid_t pid, std::vector<MapInfo>* maps) {
  return ReadProcessMaps(
      pid, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, const char* name) {
        maps->emplace_back(start, end, flags, pgoff, name);
      });
      pid, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode,
               const char* name) { maps->emplace_back(start, end, flags, pgoff, inode, name); });
}

} /* namespace procinfo */
Loading