[Libreoffice-commits] online.git: common/Util.hpp tools/map.cpp

Michael Meeks michael.meeks at collabora.com
Thu Nov 30 13:33:50 UTC 2017


 common/Util.hpp |   27 ++++++-----
 tools/map.cpp   |  131 ++++++++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 133 insertions(+), 25 deletions(-)

New commits:
commit 26876e6165315961142e726738e6635c5a010276
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Wed Nov 29 21:56:25 2017 +0000

    loolmap - read the parent's page data for unshared pages too.
    
    Change-Id: I23bb319fa4694638efc82c7af86224d2e041160c

diff --git a/common/Util.hpp b/common/Util.hpp
index c2495a11..0fc56eb9 100644
--- a/common/Util.hpp
+++ b/common/Util.hpp
@@ -18,6 +18,7 @@
 #include <set>
 #include <sstream>
 #include <string>
+
 #include <memory.h>
 
 #include <Poco/File.h>
@@ -134,7 +135,8 @@ namespace Util
 
     /// Dump data as hex and chars to stream
     inline void dumpHex (std::ostream &os, const char *legend, const char *prefix,
-                         const std::vector<char> &buffer, const unsigned int width = 32)
+                         const std::vector<char> &buffer, bool skipDup = true,
+                         const unsigned int width = 32)
     {
         unsigned int i, j;
         char scratch[64];
@@ -142,17 +144,20 @@ namespace Util
         os << legend;
         for (j = 0; j < buffer.size() + width - 1; j += width)
         {
-            int skip = 0;
-            while (j >= width && j < buffer.size() - width &&
-                   !memcmp(&buffer[j], &buffer[j-width], width))
-            {
-                skip++;
-                j += width;
-            }
-            if (skip > 1)
+            if (skipDup)
             {
-                j -= width;
-                os << "... dup " << skip - 1 << "...\n";
+                int skip = 0;
+                while (j >= width && j < buffer.size() - width &&
+                       !memcmp(&buffer[j], &buffer[j-width], width))
+                {
+                    skip++;
+                    j += width;
+                }
+                if (skip > 1)
+                {
+                    j -= width;
+                    os << "... dup " << skip - 1 << "...\n";
+                }
             }
 
             sprintf (scratch, "%s0x%.4x  ", prefix, j);
diff --git a/tools/map.cpp b/tools/map.cpp
index 6a1aaefa..1e1b4de6 100644
--- a/tools/map.cpp
+++ b/tools/map.cpp
@@ -11,6 +11,7 @@
 
 #include <vector>
 #include <iostream>
+#include <sstream>
 
 #include <stdint.h>
 #include <string.h>
@@ -85,7 +86,54 @@ static int read_buffer(char *buffer, unsigned size,
     return total_bytes;
 }
 
-static void dumpPages(unsigned proc_id, const char *type, const std::vector<addr_t> &pages)
+
+static std::vector<std::string> lineBreak(std::string str)
+{
+    std::vector<std::string> lines;
+    while (str.size())
+    {
+        size_t idx = str.find('\n');
+        if (idx != std::string::npos) {
+            lines.push_back(str.substr(0,idx));
+            str = str.substr(idx+1);
+        }
+    }
+    lines.push_back(str);
+
+    return lines;
+}
+
+static void dumpDiff(const std::string &pageStr, const std::string &parentStr)
+{
+    if (pageStr == parentStr)
+    {
+        printf ("unusual: page identical to parent\n");
+        printf ("%s", pageStr.c_str());
+        return;
+    }
+    std::vector<std::string> page = lineBreak(pageStr);
+    std::vector<std::string> parent = lineBreak(parentStr);
+    assert(page.size() == parent.size());
+    for (size_t i = 0; i < page.size(); ++i)
+    {
+        printf("%s\n", page[i].c_str());
+        if (page[i] != parent[i])
+        {
+            printf ("----");
+            assert(page[i].length() == parent[i].length());
+            for (size_t j = 4; j < page[i].length(); ++j)
+            {
+                if (page[i][j] == parent[i][j])
+                    printf(" ");
+                else
+                    printf("%c", parent[i][j]);
+            }
+            printf("\n");
+        }
+    }
+}
+
+static void dumpPages(unsigned proc_id, unsigned parent_id, const char *type, const std::vector<addr_t> &pages)
 {
     char path_proc[PATH_SIZE];
     snprintf(path_proc, sizeof(path_proc), "/proc/%d/mem", proc_id);
@@ -93,23 +141,46 @@ static void dumpPages(unsigned proc_id, const char *type, const std::vector<addr
     if (mem_fd < 0)
         error(EXIT_FAILURE, errno, "Failed to open %s", path_proc);
 
+    snprintf(path_proc, sizeof(path_proc), "/proc/%d/mem", parent_id);
+    int parent_fd = open(path_proc, 0);
+    if (parent_fd < 0)
+        error(EXIT_FAILURE, errno, "Failed to open %s", path_proc);
+
     size_t cnt = 0;
     for (auto page : pages)
     {
-        printf ("%s page: 0x%.8llx (%d/%d)\n",
-                type, page, (int)++cnt, (int)pages.size());
-
-        std::vector<char> pageData;
+        std::vector<char> pageData, parentData;
         pageData.resize(0x1000);
+        parentData.resize(0x1000);
 
         if (lseek(mem_fd, page, SEEK_SET) < 0)
             error(EXIT_FAILURE, errno, "Failed to seek in /proc/<pid>/mem to %lld", page);
         if (read(mem_fd, &pageData[0], 0x1000) != 0x1000)
             error(EXIT_FAILURE, errno, "Failed to read page %lld from /proc/<pid>/mem", page);
-        Util::dumpHex(std::cout, "", "", pageData);
+
+        if (lseek(parent_fd, page, SEEK_SET) < 0)
+            parentData.resize(0);
+        else if (read(parent_fd, &parentData[0], 0x1000) != 0x1000)
+            parentData.resize(0); // missing equivalent page.
+
+        // Diff as ASCII
+        std::stringstream pageStr;
+        Util::dumpHex(pageStr, "", "", pageData, false);
+        std::stringstream parentStr;
+        Util::dumpHex(parentStr, "", "", parentData, false);
+
+        printf ("%s page: 0x%.8llx (%d/%d) %s\n",
+                type, page, (int)++cnt, (int)pages.size(),
+                parentData.size() == 0 ? "- unique" : "- was shared");
+
+        if (parentData.size() == 0)
+            printf("%s", pageStr.str().c_str());
+        else
+            dumpDiff(pageStr.str(), parentStr.str());
     }
 
     close (mem_fd);
+    close (parent_fd);
 }
 
 static std::vector<char> compressBitmap(const std::vector<char> &bitmap)
@@ -140,7 +211,8 @@ static std::vector<char> compressBitmap(const std::vector<char> &bitmap)
     return output;
 }
 
-static void dump_unshared(unsigned proc_id, const char *type, const std::vector<addr_t> &vaddrs)
+static void dump_unshared(unsigned proc_id, unsigned parent_id,
+                          const char *type, const std::vector<addr_t> &vaddrs)
 {
     char path_proc[PATH_SIZE];
     snprintf(path_proc, sizeof(path_proc), "/proc/%d/pagemap", proc_id);
@@ -187,11 +259,12 @@ static void dump_unshared(unsigned proc_id, const char *type, const std::vector<
     if (DumpHex)
     {
         printf ("Un-shared data dump\n");
-        dumpPages(proc_id, type, vunshared);
+        dumpPages(proc_id, parent_id, type, vunshared);
     }
 }
 
-static void total_smaps(unsigned proc_id, const char *file, const char *cmdline)
+static void total_smaps(unsigned proc_id, unsigned parent_id,
+                        const char *file, const char *cmdline)
 {
     FILE *file_pointer;
     char buffer[BUFFER_SIZE];
@@ -262,6 +335,7 @@ static void total_smaps(unsigned proc_id, const char *file, const char *cmdline)
 
     printf("%s\n", cmdline);
     printf("Process ID    :%20d\n", proc_id);
+    printf(" parent ID    :%20d\n", parent_id);
     printf("--------------------------------------\n");
     printf("Shared Clean  :%20lld kB\n", total_shared_clean);
     printf("Shared Dirty  :%20lld kB\n", total_shared_dirty);
@@ -275,9 +349,36 @@ static void total_smaps(unsigned proc_id, const char *file, const char *cmdline)
     printf("Anon page cnt :%20lld\n", (addr_t)anonVAddrs.size());
     printf("File page cnt :%20lld\n", (addr_t)fileVAddrs.size());
     printf("\n");
-    dump_unshared(proc_id, "heap", heapVAddrs);
-    dump_unshared(proc_id, "anon", anonVAddrs);
-    dump_unshared(proc_id, "file", fileVAddrs);
+    dump_unshared(proc_id, parent_id, "heap", heapVAddrs);
+    dump_unshared(proc_id, parent_id, "anon", anonVAddrs);
+    dump_unshared(proc_id, parent_id, "file", fileVAddrs);
+}
+
+static unsigned getParent(int proc_id)
+{
+    char path_proc[PATH_SIZE];
+    snprintf(path_proc, sizeof(path_proc), "/proc/%d/stat", proc_id);
+    int fd = open(path_proc, 0);
+    if (fd < 0)
+        error(EXIT_FAILURE, errno, "Failed to open %s", path_proc);
+    char buffer[4096];
+    int len;
+    if ((len = read(fd, buffer, sizeof (buffer))) < 0)
+        error(EXIT_FAILURE, errno, "Failed to read %s", path_proc);
+    close (fd);
+    buffer[len] = '\0';
+
+    char state, cmd[4096];
+    unsigned unused, ppid = 0;
+    if (sscanf(buffer, "%d %s %c %d", &unused, cmd, &state, &ppid) != 4 || ppid == 0)
+    {
+        fprintf(stderr, "Failed to locate parent from file '%s' : '%s'\n",
+                path_proc, buffer);
+        exit (1);
+    }
+    fprintf(stderr,"parent of %u is %u\n", proc_id, ppid);
+
+    return ppid;
 }
 
 int main(int argc, char **argv)
@@ -293,7 +394,7 @@ int main(int argc, char **argv)
     const char *appOrPid = nullptr;
 
     setlocale (LC_ALL, "");
-    getopt(argc, argv, "");
+    getopt(argc, argv, ""); // FIXME: Should use this properly.
 
     for (int i = 1; i < argc; ++i)
     {
@@ -329,12 +430,14 @@ int main(int argc, char **argv)
         if (*dir_proc->d_name > '0' && *dir_proc->d_name <= '9')
         {
             unsigned pid_proc = strtoul(dir_proc->d_name, nullptr, 10);
+
             snprintf(path_proc, sizeof(path_proc), "/proc/%s/%s", dir_proc->d_name, "cmdline");
             if (read_buffer(cmdline, sizeof(cmdline), path_proc, ' ') &&
                 (forPid == pid_proc || (forPid == 0 && strstr(cmdline, appOrPid) && !strstr(cmdline, argv[0]))))
             {
+                unsigned parent_id = getParent(pid_proc);
                 snprintf(path_proc, sizeof(path_proc), "/proc/%s/%s", dir_proc->d_name, "smaps");
-                total_smaps(pid_proc, path_proc, cmdline);
+                total_smaps(pid_proc, parent_id, path_proc, cmdline);
             }
         }
     }


More information about the Libreoffice-commits mailing list