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.me...@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.me...@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) _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits