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

Michael Meeks michael.meeks at collabora.com
Wed Nov 29 04:11:50 UTC 2017


 common/Util.hpp |   51 +++++++++++++++++++++++++
 net/Socket.cpp  |   44 +--------------------
 tools/map.cpp   |  114 +++++++++++++++++++++++++++++++++++++++++++++++++-------
 3 files changed, 154 insertions(+), 55 deletions(-)

New commits:
commit 0778b726978fffd83f6cc1e75e4f3291ef2b69a4
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Wed Nov 29 03:23:45 2017 +0000

    Dump hex contents of un-shared memory.
    
    Change-Id: I47dfa8a0b48d0ba34b7462301b83e2721617814d

diff --git a/common/Util.hpp b/common/Util.hpp
index e97d1808..c2495a11 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>
 #include <Poco/Path.h>
@@ -131,6 +132,56 @@ namespace Util
     // Extract all json entries into a map.
     std::map<std::string, std::string> JsonToMap(const std::string& jsonString);
 
+    /// 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)
+    {
+        unsigned int i, j;
+        char scratch[64];
+
+        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)
+            {
+                j -= width;
+                os << "... dup " << skip - 1 << "...\n";
+            }
+
+            sprintf (scratch, "%s0x%.4x  ", prefix, j);
+            os << scratch;
+            for (i = 0; i < width; i++)
+            {
+                if (i && (i % 8) == 0)
+                    os << " ";
+                if ((j + i) < buffer.size())
+                    sprintf (scratch, "%.2x ", (unsigned char)buffer[j+i]);
+                else
+                    sprintf (scratch, "   ");
+                os << scratch;
+            }
+            os << " | ";
+
+            for (i = 0; i < width; i++)
+            {
+                if ((j + i) < buffer.size() && ::isprint(buffer[j+i]))
+                    sprintf (scratch, "%c", buffer[j+i]);
+                else
+                    sprintf (scratch, ".");
+                os << scratch;
+            }
+            os << "\n";
+        }
+        os.flush();
+    }
+
     /// Trim spaces from the left. Just spaces.
     inline std::string& ltrim(std::string& s)
     {
diff --git a/net/Socket.cpp b/net/Socket.cpp
index 13424cd3..475649ac 100644
--- a/net/Socket.cpp
+++ b/net/Socket.cpp
@@ -137,50 +137,12 @@ void SocketDisposition::execute()
     _socketMove = nullptr;
 }
 
-namespace {
-
-void dump_hex (std::ostream &os, const char *legend, const char *prefix, std::vector<char> buffer)
-{
-    unsigned int i, j;
-    char scratch[64];
-
-    os << legend;
-    for (j = 0; j < buffer.size() + 15; j += 16)
-    {
-        sprintf (scratch, "%s0x%.4x  ", prefix, j);
-        os << scratch;
-        for (i = 0; i < 16; i++)
-        {
-            if ((j + i) < buffer.size())
-                sprintf (scratch, "%.2x ", (unsigned char)buffer[j+i]);
-            else
-                sprintf (scratch, "   ");
-            os << scratch;
-            if (i == 8)
-                os << " ";
-        }
-        os << " | ";
-
-        for (i = 0; i < 16; i++)
-        {
-            if ((j + i) < buffer.size() && ::isprint(buffer[j+i]))
-                sprintf (scratch, "%c", buffer[j+i]);
-            else
-                sprintf (scratch, ".");
-            os << scratch;
-        }
-        os << "\n";
-    }
-}
-
-} // namespace
-
 void WebSocketHandler::dumpState(std::ostream& os)
 {
     os << (_shuttingDown ? "shutd " : "alive ")
        << std::setw(5) << 1.0*_pingTimeUs/1000 << "ms ";
     if (_wsPayload.size() > 0)
-        dump_hex(os, "\t\tws queued payload:\n", "\t\t", _wsPayload);
+        Util::dumpHex(os, "\t\tws queued payload:\n", "\t\t", _wsPayload);
     os << "\n";
 }
 
@@ -193,9 +155,9 @@ void StreamSocket::dumpState(std::ostream& os)
        << " r: " << _bytesRecvd << "\t w: " << _bytesSent << "\t";
     _socketHandler->dumpState(os);
     if (_inBuffer.size() > 0)
-        dump_hex(os, "\t\tinBuffer:\n", "\t\t", _inBuffer);
+        Util::dumpHex(os, "\t\tinBuffer:\n", "\t\t", _inBuffer);
     if (_outBuffer.size() > 0)
-        dump_hex(os, "\t\toutBuffer:\n", "\t\t", _inBuffer);
+        Util::dumpHex(os, "\t\toutBuffer:\n", "\t\t", _inBuffer);
 }
 
 void StreamSocket::send(Poco::Net::HTTPResponse& response)
diff --git a/tools/map.cpp b/tools/map.cpp
index 09cec706..6a1aaefa 100644
--- a/tools/map.cpp
+++ b/tools/map.cpp
@@ -10,6 +10,7 @@
 #include "config.h"
 
 #include <vector>
+#include <iostream>
 
 #include <stdint.h>
 #include <string.h>
@@ -23,8 +24,12 @@
 #include <dirent.h>
 #include <locale.h>
 
+#include <Util.hpp>
+
 typedef unsigned long long addr_t;
 
+bool DumpHex = false;
+
 #define MAP_SIZE 20
 #define PATH_SIZE 1000 // No harm in having it much larger than strictly necessary. Avoids compiler warning.
 #define BUFFER_SIZE 9600
@@ -80,6 +85,33 @@ 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)
+{
+    char path_proc[PATH_SIZE];
+    snprintf(path_proc, sizeof(path_proc), "/proc/%d/mem", proc_id);
+    int mem_fd = open(path_proc, 0);
+    if (mem_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;
+        pageData.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);
+    }
+
+    close (mem_fd);
+}
+
 static std::vector<char> compressBitmap(const std::vector<char> &bitmap)
 {
     size_t i;
@@ -117,6 +149,7 @@ static void dump_unshared(unsigned proc_id, const char *type, const std::vector<
         error(EXIT_FAILURE, errno, "Failed to open %s", path_proc);
 
     std::vector<char> bitmap;
+    std::vector<addr_t> vunshared;
     addr_t numShared = 0, numOwn = 0;
     for (auto p : vaddrs)
     {
@@ -133,6 +166,7 @@ static void dump_unshared(unsigned proc_id, const char *type, const std::vector<
             {
                 numOwn++;
                 bitmap.push_back('*');
+                vunshared.push_back(p);
             }
             else
             {
@@ -141,6 +175,7 @@ static void dump_unshared(unsigned proc_id, const char *type, const std::vector<
             }
         }
     }
+    close (fd);
 
     printf ("Totals for %s\n", type);
     printf ("\tshared   %5lld (%lldkB)\n", numShared, numShared * 4);
@@ -148,6 +183,12 @@ static void dump_unshared(unsigned proc_id, const char *type, const std::vector<
 
     std::vector<char> compressed = compressBitmap(bitmap);
     printf ("RLE sharing bitmap:\n%s\n\n", &compressed[0]);
+
+    if (DumpHex)
+    {
+        printf ("Un-shared data dump\n");
+        dumpPages(proc_id, type, vunshared);
+    }
 }
 
 static void total_smaps(unsigned proc_id, const char *file, const char *cmdline)
@@ -246,19 +287,35 @@ int main(int argc, char **argv)
 
     char path_proc[PATH_SIZE];
     char cmdline[BUFFER_SIZE];
+
+    bool help = false;
     unsigned forPid = 0;
+    const char *appOrPid = nullptr;
 
     setlocale (LC_ALL, "");
     getopt(argc, argv, "");
 
-    if (argc < 1 || strstr(argv[1], "--help"))
+    for (int i = 1; i < argc; ++i)
+    {
+        const char *arg = argv[i];
+        if (strstr(arg, "--help"))
+            help = true;
+        else if (strstr(arg, "--hex"))
+            DumpHex = true;
+        else
+            appOrPid = arg;
+    }
+    if (appOrPid == NULL && forPid == 0)
+        help = true;
+
+    if (help)
     {
-        fprintf(stderr, "Usage: loolmap <name of process|pid>\n");
+        fprintf(stderr, "Usage: loolmap --hex <name of process|pid>\n");
         fprintf(stderr, "Dump memory map information for a given process\n");
         return 0;
     }
 
-    forPid = atoi(argv[1]);
+    forPid = atoi(appOrPid);
 
     root_proc = opendir("/proc");
     if (!root_proc)
@@ -274,7 +331,7 @@ int main(int argc, char **argv)
             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, argv[1]) && !strstr(cmdline, argv[0]))))
+                (forPid == pid_proc || (forPid == 0 && strstr(cmdline, appOrPid) && !strstr(cmdline, argv[0]))))
             {
                 snprintf(path_proc, sizeof(path_proc), "/proc/%s/%s", dir_proc->d_name, "smaps");
                 total_smaps(pid_proc, path_proc, cmdline);
commit 16898cbffc5d8ae4da88a7be0c5d30f7869ce2e8
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Wed Nov 29 02:38:33 2017 +0000

    RLE compress sharing bitmap for display.
    
    Change-Id: Ib47e2ceb481c0a9b4c36fc6f5304bf03acec128b

diff --git a/tools/map.cpp b/tools/map.cpp
index f3fb76b5..09cec706 100644
--- a/tools/map.cpp
+++ b/tools/map.cpp
@@ -80,8 +80,35 @@ static int read_buffer(char *buffer, unsigned size,
     return total_bytes;
 }
 
+static std::vector<char> compressBitmap(const std::vector<char> &bitmap)
+{
+    size_t i;
+    std::vector<char> output;
+    for (i = 0; i < bitmap.size(); ++i)
+    {
+        char cur;
+        int cnt = 0;
+        size_t j = i;
+        for (cur = bitmap[j]; bitmap[j] == cur; ++j)
+            ++cnt;
+        output.push_back(cur);
+        if (cnt > 3)
+        {
+            char num[16];
+            output.push_back('[');
+            sprintf(num, "%d", cnt);
+            for (int cpy = 0; num[cpy] != '\0'; ++cpy)
+                output.push_back(num[cpy]);
+            output.push_back(']');
+            i += cnt - 1;
+        }
+    }
 
-static void dump_unshared(unsigned proc_id, const std::vector<addr_t> &vaddrs)
+    output.push_back('\0');
+    return output;
+}
+
+static void dump_unshared(unsigned proc_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);
@@ -89,7 +116,7 @@ static void dump_unshared(unsigned proc_id, const std::vector<addr_t> &vaddrs)
     if (fd < 0)
         error(EXIT_FAILURE, errno, "Failed to open %s", path_proc);
 
-    printf("Sharing map:\n");
+    std::vector<char> bitmap;
     addr_t numShared = 0, numOwn = 0;
     for (auto p : vaddrs)
     {
@@ -105,20 +132,22 @@ static void dump_unshared(unsigned proc_id, const std::vector<addr_t> &vaddrs)
             if (vaddrData & ((addr_t)1 << 56))
             {
                 numOwn++;
-                printf("*");
+                bitmap.push_back('*');
             }
             else
             {
                 numShared++;
-                printf(".");
+                bitmap.push_back('.');
             }
         }
-        if (!((numShared + numOwn) % 128))
-            printf("\n");
     }
-    printf ("\nTotals:\n");
+
+    printf ("Totals for %s\n", type);
     printf ("\tshared   %5lld (%lldkB)\n", numShared, numShared * 4);
     printf ("\tunshared %5lld (%lldkB)\n", numOwn, numOwn * 4);
+
+    std::vector<char> compressed = compressBitmap(bitmap);
+    printf ("RLE sharing bitmap:\n%s\n\n", &compressed[0]);
 }
 
 static void total_smaps(unsigned proc_id, const char *file, const char *cmdline)
@@ -205,9 +234,9 @@ 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, heapVAddrs);
-    dump_unshared(proc_id, anonVAddrs);
-    dump_unshared(proc_id, fileVAddrs);
+    dump_unshared(proc_id, "heap", heapVAddrs);
+    dump_unshared(proc_id, "anon", anonVAddrs);
+    dump_unshared(proc_id, "file", fileVAddrs);
 }
 
 int main(int argc, char **argv)


More information about the Libreoffice-commits mailing list