diff --git a/libbacktrace/BacktraceMap.cpp b/libbacktrace/BacktraceMap.cpp index 6a967f7d6..781819af5 100644 --- a/libbacktrace/BacktraceMap.cpp +++ b/libbacktrace/BacktraceMap.cpp @@ -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); @@ -68,12 +67,13 @@ static bool ParseLine(const char* line, backtrace_map_t* map) { char permissions[5]; 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 -// 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) { + // 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 + // 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) { return false; } @@ -90,21 +90,21 @@ static bool ParseLine(const char* line, backtrace_map_t* map) { map->flags |= PROT_EXEC; } - map->name = line+name_pos; - if (!map->name.empty() && map->name[map->name.length()-1] == '\n') { - map->name.erase(map->name.length()-1); + map->name = line + name_pos; + if (!map->name.empty() && map->name[map->name.length() - 1] == '\n') { + map->name.erase(map->name.length() - 1); } - ALOGV("Parsed map: start=%p, end=%p, flags=%x, name=%s", - reinterpret_cast(map->start), reinterpret_cast(map->end), - map->flags, map->name.c_str()); + ALOGV("Parsed map: start=%p, end=%p, flags=%x, name=%s", reinterpret_cast(map->start), + reinterpret_cast(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_); @@ -113,7 +113,7 @@ bool BacktraceMap::Build() { return false; } - while(fgets(line, sizeof(line), fp)) { + while (fgets(line, sizeof(line), fp)) { backtrace_map_t map; if (ParseLine(line, &map)) { maps_.push_back(map); @@ -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; diff --git a/libmeminfo/libdmabufinfo/dmabufinfo.cpp b/libmeminfo/libdmabufinfo/dmabufinfo.cpp index b4ad6678a..ff10e96ea 100644 --- a/libmeminfo/libdmabufinfo/dmabufinfo.cpp +++ b/libmeminfo/libdmabufinfo/dmabufinfo.cpp @@ -123,18 +123,14 @@ static bool ReadDmaBufFdRefs(pid_t pid, std::vector* 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() == "") - buf->SetName(name); - if (buf->exporter() == "" || buf->exporter() == "") - buf->SetExporter(exporter); - if (buf->count() == 0) - buf->SetCount(count); + if (buf->name() == "" || buf->name() == "") buf->SetName(name); + if (buf->exporter() == "" || buf->exporter() == "") 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* 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()) { diff --git a/libmeminfo/procmeminfo.cpp b/libmeminfo/procmeminfo.cpp index 069b6b329..934d65c9d 100644 --- a/libmeminfo/procmeminfo.cpp +++ b/libmeminfo/procmeminfo.cpp @@ -246,7 +246,7 @@ bool ProcMemInfo::ReadMaps(bool get_wss, bool use_pageidle) { // parse and read /proc//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; diff --git a/libmemunreachable/ProcessMappings.cpp b/libmemunreachable/ProcessMappings.cpp index 701ce1670..8e1be4c8c 100644 --- a/libmemunreachable/ProcessMappings.cpp +++ b/libmemunreachable/ProcessMappings.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -30,7 +31,8 @@ namespace android { struct ReadMapCallback { ReadMapCallback(allocator::vector& 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); } diff --git a/libprocinfo/include/procinfo/process_map.h b/libprocinfo/include/procinfo/process_map.h index 981241e11..b6ec3cbce 100644 --- a/libprocinfo/include/procinfo/process_map.h +++ b/libprocinfo/include/procinfo/process_map.h @@ -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& callback) { +inline bool ReadMapFile(const std::string& map_file, + const std::function& 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& callback) { +inline bool ReadProcessMaps(pid_t pid, + const std::function& 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* 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 */ diff --git a/libprocinfo/process_map_benchmark.cpp b/libprocinfo/process_map_benchmark.cpp index 04995d4cb..eba4fd0d8 100644 --- a/libprocinfo/process_map_benchmark.cpp +++ b/libprocinfo/process_map_benchmark.cpp @@ -17,6 +17,7 @@ #include #include +#include #include @@ -31,9 +32,10 @@ static void BM_ReadMapFile(benchmark::State& state) { std::string map_file = android::base::GetExecutableDirectory() + "/testdata/maps"; for (auto _ : state) { std::vector maps; - android::procinfo::ReadMapFile( - map_file, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, - const char* name) { maps.emplace_back(start, end, flags, pgoff, name); }); + android::procinfo::ReadMapFile(map_file, [&](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); + }); CHECK_EQ(maps.size(), 2043u); } } diff --git a/libprocinfo/process_map_test.cpp b/libprocinfo/process_map_test.cpp index 170a806f3..562d864fe 100644 --- a/libprocinfo/process_map_test.cpp +++ b/libprocinfo/process_map_test.cpp @@ -26,23 +26,27 @@ TEST(process_map, ReadMapFile) { std::string map_file = android::base::GetExecutableDirectory() + "/testdata/maps"; std::vector maps; ASSERT_TRUE(android::procinfo::ReadMapFile( - map_file, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, - const char* name) { maps.emplace_back(start, end, flags, pgoff, name); })); + map_file, + [&](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); })); ASSERT_EQ(2043u, maps.size()); ASSERT_EQ(maps[0].start, 0x12c00000ULL); ASSERT_EQ(maps[0].end, 0x2ac00000ULL); ASSERT_EQ(maps[0].flags, PROT_READ | PROT_WRITE); ASSERT_EQ(maps[0].pgoff, 0ULL); + ASSERT_EQ(maps[0].inode, 10267643UL); ASSERT_EQ(maps[0].name, "[anon:dalvik-main space (region space)]"); ASSERT_EQ(maps[876].start, 0x70e6c4f000ULL); ASSERT_EQ(maps[876].end, 0x70e6c6b000ULL); ASSERT_EQ(maps[876].flags, PROT_READ | PROT_EXEC); ASSERT_EQ(maps[876].pgoff, 0ULL); + ASSERT_EQ(maps[876].inode, 2407UL); ASSERT_EQ(maps[876].name, "/system/lib64/libutils.so"); ASSERT_EQ(maps[1260].start, 0x70e96fa000ULL); ASSERT_EQ(maps[1260].end, 0x70e96fb000ULL); ASSERT_EQ(maps[1260].flags, PROT_READ); ASSERT_EQ(maps[1260].pgoff, 0ULL); + ASSERT_EQ(maps[1260].inode, 10266154UL); ASSERT_EQ(maps[1260].name, "[anon:dalvik-classes.dex extracted in memory from " "/data/app/com.google.sample.tunnel-HGGRU03Gu1Mwkf_-RnFmvw==/base.apk]"); @@ -51,8 +55,9 @@ TEST(process_map, ReadMapFile) { TEST(process_map, ReadProcessMaps) { std::vector maps; ASSERT_TRUE(android::procinfo::ReadProcessMaps( - getpid(), [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, - const char* name) { maps.emplace_back(start, end, flags, pgoff, name); })); + getpid(), + [&](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); })); ASSERT_GT(maps.size(), 0u); maps.clear(); ASSERT_TRUE(android::procinfo::ReadProcessMaps(getpid(), &maps)); diff --git a/libunwindstack/Maps.cpp b/libunwindstack/Maps.cpp index c90e38309..1e4f72eaa 100644 --- a/libunwindstack/Maps.cpp +++ b/libunwindstack/Maps.cpp @@ -62,7 +62,7 @@ MapInfo* Maps::Find(uint64_t pc) { bool Maps::Parse() { return android::procinfo::ReadMapFile( GetMapsFile(), - [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, const char* name) { + [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t, const char* name) { // Mark a device map in /dev/ and not in /dev/ashmem/ specially. if (strncmp(name, "/dev/", 5) == 0 && strncmp(name + 5, "ashmem/", 7) != 0) { flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP; @@ -102,7 +102,7 @@ bool BufferMaps::Parse() { std::string content(buffer_); return android::procinfo::ReadMapFileContent( &content[0], - [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, const char* name) { + [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t, const char* name) { // Mark a device map in /dev/ and not in /dev/ashmem/ specially. if (strncmp(name, "/dev/", 5) == 0 && strncmp(name + 5, "ashmem/", 7) != 0) { flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;