tools/map.cpp | 221 +++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 181 insertions(+), 40 deletions(-)
New commits: commit 44600de7c7dbe11da0545cf73ccae9dfa653d141 Author: Michael Meeks <michael.me...@collabora.com> Date: Sat Dec 9 17:33:15 2017 +0000 loolmap: implement a simple string scan and dump function. Change-Id: I056f764c99f977a0178105511dfd5406ea6dbfa5 diff --git a/tools/map.cpp b/tools/map.cpp index 88c1aa07..c69db7d2 100644 --- a/tools/map.cpp +++ b/tools/map.cpp @@ -31,6 +31,7 @@ typedef unsigned long long addr_t; bool DumpHex = false; bool DumpAll = false; +bool DumpStrings = false; #define MAP_SIZE 20 #define PATH_SIZE 1000 // No harm in having it much larger than strictly necessary. Avoids compiler warning. @@ -138,20 +139,44 @@ static void dumpDiff(const std::string &pageStr, const std::string &parentStr) } } +struct AddrSpace; + struct Map { addr_t _start; addr_t _end; std::string _name; + size_t size() { return _end - _start; } +}; + +struct StringData { + size_t _count; + size_t _chars; + StringData() : + _count(0), + _chars(0) + {} }; struct AddrSpace { unsigned _proc_id; std::vector<Map> _maps; + StringData _strings[3]; AddrSpace(unsigned proc_id) : _proc_id(proc_id) { } + void printStats() + { + char prefixes[] = { 'S', 'U', 'c' }; + for (int i = 0; i < 2; ++i) + { + printf("%cStrings :%20lld, %lld chars\n", + prefixes[i], (addr_t)_strings[i]._count, + (addr_t)_strings[i]._chars); + } + } + std::string findName(addr_t page) const { for (const Map &i : _maps) @@ -162,6 +187,81 @@ struct AddrSpace { return std::string(""); } + void insert(addr_t start, addr_t end, const char *name) + { + Map map; + map._start = start; + map._end = end; + map._name = std::string(name); + _maps.push_back(map); + } + + // Normal OUString: + // 20 00 00 00 00 00 00 00 02 00 00 00 05 00 00 00 4b 00 45 00 59 00 5f 00 55 00 00 00 00 00 00 00 | ...............K.E.Y._.U...... + // 20 00 00 00 00 00 00 00 02 00 00 00 05 00 00 00 4b 45 59 5f 55 00 00 00 00 00 00 00 00 00 00 00 | ...............KEY_U.......... + + bool isStringAtOffset(const std::vector<unsigned char> &data, size_t i, + uint32_t len, bool isUnicode, std::string &str) + { + str = isUnicode ? "U_" : "S_"; + int step = isUnicode ? 2 : 1; + for (size_t j = i; j < i + len*step && j < data.size(); j += step) + { + if (isascii(data[j]) && !iscntrl(data[j])) + str += static_cast<char>(data[j]); + else + return false; + } + return true; + } + + void scanForSalStrings(Map &map, const std::vector<unsigned char> &data) + { + for (size_t i = 0; i < data.size() - 24; i += 4) + { + const uint32_t *p = reinterpret_cast<const uint32_t *>(&data[i]); + uint32_t len; + if ((p[0] & 0xffffff) < 0x1000 && // plausible max ref-count + (len = p[1]) < 0x100 && // plausible max string length + len <= (data.size() - i) && + len > 0) + { + std::string str; + bool isUnicode = data[i+1] == 0 && data[i+3] == 0; + if (isStringAtOffset(data, i + 8, len, isUnicode, str)) + { + StringData &sdata = _strings[isUnicode ? 1 : 0]; + sdata._count ++; + sdata._chars += len; + if (DumpStrings) + printf("string address 0x%.8llx %s\n", + map._start + i, str.c_str()); + } + i += 8; + } + } + } + + void scanMapsForStrings() + { + int mem_fd = openPid(_proc_id, "mem"); + if (DumpStrings) + printf("String dump:\n"); + for (auto &map : _maps) + { + std::vector<unsigned char> data; + data.resize (map.size()); + if (lseek(mem_fd, map._start, SEEK_SET) < 0 || + read(mem_fd, &data[0], map.size()) != (int)map.size()) + error(EXIT_FAILURE, errno, "Failed to seek in /proc/%d/mem to %lld", + _proc_id, map._start); + + scanForSalStrings(map, data); + } + if (DumpStrings) + printf("String dump ends.\n"); + close (mem_fd); + } }; static void dumpPages(unsigned proc_id, unsigned parent_id, const char *type, const std::vector<addr_t> &pages, const AddrSpace &space) @@ -191,12 +291,6 @@ static void dumpPages(unsigned proc_id, unsigned parent_id, const char *type, co 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); - int touched = 0; const char *style; if (parentData.size() > 0) @@ -231,6 +325,12 @@ static void dumpPages(unsigned proc_id, unsigned parent_id, const char *type, co if (DumpHex) { + // 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) - touched: %d - %s - from %s\n", type, page, (int)++cnt, (int)pages.size(), touched, style, space.findName(page).c_str()); @@ -364,17 +464,12 @@ static void total_smaps(unsigned proc_id, unsigned parent_id, // 012d0000-0372f000 rw-p 00000000 00:00 0 [heap] if (sscanf(buffer, "%llx-%llx rw-p", &start, &end) == 2) { - Map map; - map._start = start; - map._end = end; const char *name = strchr(buffer, '['); if (!name) name = strchr(buffer, '/'); - if (name) - map._name = std::string(name); - else - map._name = std::string("[anon]"); - space._maps.push_back(map); + if (!name) + name = "[anon]"; + space.insert(start, end, name); for (addr_t p = start; p < end; p += 0x1000) pushTo->push_back(p); } @@ -409,6 +504,7 @@ static void total_smaps(unsigned proc_id, unsigned parent_id, } } } + space.scanMapsForStrings(); printf("%s\n", cmdline); printf("Process ID :%20d\n", proc_id); @@ -425,6 +521,8 @@ static void total_smaps(unsigned proc_id, unsigned parent_id, printf("Heap page cnt :%20lld\n", (addr_t)heapVAddrs.size()); printf("Anon page cnt :%20lld\n", (addr_t)anonVAddrs.size()); printf("File page cnt :%20lld\n", (addr_t)fileVAddrs.size()); + printf("--------------------------------------\n"); + space.printStats(); printf("\n"); dump_unshared(proc_id, parent_id, "heap", heapVAddrs, space); @@ -463,6 +561,7 @@ int main(int argc, char **argv) char path_proc[PATH_SIZE]; char cmdline[BUFFER_SIZE]; + bool found = false; bool help = false; unsigned forPid = 0; const char *appOrPid = nullptr; @@ -479,6 +578,8 @@ int main(int argc, char **argv) DumpHex = true; else if (strstr(arg, "--all")) DumpAll = true; + else if (strstr(arg, "--strings")) + DumpStrings = true; else appOrPid = arg; } @@ -489,8 +590,9 @@ int main(int argc, char **argv) { fprintf(stderr, "Usage: loolmap --hex <name of process|pid>\n"); fprintf(stderr, "Dump memory map information for a given process\n"); - fprintf(stderr, " --hex Hex dump relevant page contents and diff to parent process\n"); - fprintf(stderr, " --all Hex dump all writable pages whether touched or not\n"); + fprintf(stderr, " --hex Hex dump relevant page contents and diff to parent process\n"); + fprintf(stderr, " --strings Print all detected strings\n"); + fprintf(stderr, " --all Hex dump all writable pages whether touched or not\n"); return 0; } @@ -516,10 +618,14 @@ int main(int argc, char **argv) unsigned parent_id = getParent(pid_proc); snprintf(path_proc, sizeof(path_proc), "/proc/%s/%s", dir_proc->d_name, "smaps"); total_smaps(pid_proc, parent_id, path_proc, cmdline); + found = true; } } } + if (!found) + fprintf(stderr, "Failed to find process %s\n", appOrPid); + return EXIT_SUCCESS; } commit 7dcd2ddd900b08629b59cf6e518b98af2ab4b402 Author: Michael Meeks <michael.me...@collabora.com> Date: Sat Dec 9 17:18:59 2017 +0000 loolmap: share some /proc opening pieces. Change-Id: I2d8b6eeec4afad52f74153c3d7ac904dfcb5db8f diff --git a/tools/map.cpp b/tools/map.cpp index 7d1be8b6..88c1aa07 100644 --- a/tools/map.cpp +++ b/tools/map.cpp @@ -87,6 +87,15 @@ static int read_buffer(char *buffer, unsigned size, return total_bytes; } +static int openPid(unsigned proc_id, const char *name) +{ + char path_proc[PATH_SIZE]; + snprintf(path_proc, sizeof(path_proc), "/proc/%d/%s", proc_id, name); + int fd = open(path_proc, 0); + if (fd < 0) + error(EXIT_FAILURE, errno, "Failed to open %s", path_proc); + return fd; +} static std::vector<std::string> lineBreak(std::string str) { @@ -136,8 +145,13 @@ struct Map { }; struct AddrSpace { + unsigned _proc_id; std::vector<Map> _maps; + AddrSpace(unsigned proc_id) : + _proc_id(proc_id) + { + } std::string findName(addr_t page) const { for (const Map &i : _maps) @@ -147,20 +161,13 @@ struct AddrSpace { } return std::string(""); } + }; static void dumpPages(unsigned proc_id, unsigned parent_id, const char *type, const std::vector<addr_t> &pages, const AddrSpace &space) { - 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); - - 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); + int mem_fd = openPid(proc_id, "mem"); + int parent_fd = openPid(parent_id, "mem"); if (DumpHex) printf ("\nUn-shared data dump\n"); @@ -277,11 +284,7 @@ static void dump_unshared(unsigned proc_id, unsigned parent_id, const char *type, const std::vector<addr_t> &vaddrs, const AddrSpace & space) { - char path_proc[PATH_SIZE]; - snprintf(path_proc, sizeof(path_proc), "/proc/%d/pagemap", proc_id); - int fd = open(path_proc, 0); - if (fd < 0) - error(EXIT_FAILURE, errno, "Failed to open %s", path_proc); + int fd = openPid(proc_id, "pagemap"); std::vector<char> bitmap; std::vector<addr_t> vunshared; @@ -337,7 +340,7 @@ static void total_smaps(unsigned proc_id, unsigned parent_id, addr_t smap_value; char smap_key[MAP_SIZE]; - AddrSpace space; + AddrSpace space(proc_id); std::vector<addr_t> heapVAddrs, anonVAddrs, fileVAddrs; std::vector<addr_t> *pushTo = nullptr; @@ -369,6 +372,8 @@ static void total_smaps(unsigned proc_id, unsigned parent_id, name = strchr(buffer, '/'); if (name) map._name = std::string(name); + else + map._name = std::string("[anon]"); space._maps.push_back(map); for (addr_t p = start; p < end; p += 0x1000) pushTo->push_back(p); @@ -429,15 +434,12 @@ static void total_smaps(unsigned proc_id, unsigned parent_id, 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); + int fd = openPid(proc_id, "stat"); + char buffer[4096]; int len; if ((len = read(fd, buffer, sizeof (buffer))) < 0) - error(EXIT_FAILURE, errno, "Failed to read %s", path_proc); + error(EXIT_FAILURE, errno, "Failed to read /proc/%d/stat", proc_id); close (fd); buffer[len] = '\0'; @@ -445,8 +447,8 @@ static unsigned getParent(int proc_id) 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); + fprintf(stderr, "Failed to locate parent from " + "/proc/%d/stat : '%s'\n", proc_id, buffer); exit (1); } commit 50cdc168842e6e197bd927558cf9d3f9785c8149 Author: Michael Meeks <michael.me...@collabora.com> Date: Fri Dec 8 18:13:09 2017 +0000 loolmap: store address space mappings. Change-Id: I30b61ed8407996923f07368263bc8b773dfdc061 diff --git a/tools/map.cpp b/tools/map.cpp index 41025c9e..7d1be8b6 100644 --- a/tools/map.cpp +++ b/tools/map.cpp @@ -129,7 +129,27 @@ static void dumpDiff(const std::string &pageStr, const std::string &parentStr) } } -static void dumpPages(unsigned proc_id, unsigned parent_id, const char *type, const std::vector<addr_t> &pages) +struct Map { + addr_t _start; + addr_t _end; + std::string _name; +}; + +struct AddrSpace { + std::vector<Map> _maps; + + std::string findName(addr_t page) const + { + for (const Map &i : _maps) + { + if (i._start <= page && i._end > page) + return i._name; + } + return std::string(""); + } +}; + +static void dumpPages(unsigned proc_id, unsigned parent_id, const char *type, const std::vector<addr_t> &pages, const AddrSpace &space) { char path_proc[PATH_SIZE]; snprintf(path_proc, sizeof(path_proc), "/proc/%d/mem", proc_id); @@ -204,11 +224,11 @@ static void dumpPages(unsigned proc_id, unsigned parent_id, const char *type, co if (DumpHex) { - printf ("%s page: 0x%.8llx (%d/%d) - touched: %d - %s\n", + printf ("%s page: 0x%.8llx (%d/%d) - touched: %d - %s - from %s\n", type, page, (int)++cnt, (int)pages.size(), touched, - style); + style, space.findName(page).c_str()); - if (parentData.size() == 0) + if (touched == 0) printf("%s", pageStr.str().c_str()); else dumpDiff(pageStr.str(), parentStr.str()); @@ -254,7 +274,8 @@ static std::vector<char> compressBitmap(const std::vector<char> &bitmap) } static void dump_unshared(unsigned proc_id, unsigned parent_id, - const char *type, const std::vector<addr_t> &vaddrs) + const char *type, const std::vector<addr_t> &vaddrs, + const AddrSpace & space) { char path_proc[PATH_SIZE]; snprintf(path_proc, sizeof(path_proc), "/proc/%d/pagemap", proc_id); @@ -300,7 +321,7 @@ static void dump_unshared(unsigned proc_id, unsigned parent_id, std::vector<char> compressed = compressBitmap(bitmap); printf ("\tRLE sharing bitmap:\n%s\n", &compressed[0]); - dumpPages(proc_id, parent_id, type, vunshared); + dumpPages(proc_id, parent_id, type, vunshared, space); } static void total_smaps(unsigned proc_id, unsigned parent_id, @@ -316,6 +337,8 @@ static void total_smaps(unsigned proc_id, unsigned parent_id, addr_t smap_value; char smap_key[MAP_SIZE]; + AddrSpace space; + std::vector<addr_t> heapVAddrs, anonVAddrs, fileVAddrs; std::vector<addr_t> *pushTo = nullptr; @@ -338,6 +361,15 @@ static void total_smaps(unsigned proc_id, unsigned parent_id, // 012d0000-0372f000 rw-p 00000000 00:00 0 [heap] if (sscanf(buffer, "%llx-%llx rw-p", &start, &end) == 2) { + Map map; + map._start = start; + map._end = end; + const char *name = strchr(buffer, '['); + if (!name) + name = strchr(buffer, '/'); + if (name) + map._name = std::string(name); + space._maps.push_back(map); for (addr_t p = start; p < end; p += 0x1000) pushTo->push_back(p); } @@ -389,9 +421,10 @@ static void total_smaps(unsigned proc_id, unsigned parent_id, 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, parent_id, "heap", heapVAddrs); - dump_unshared(proc_id, parent_id, "anon", anonVAddrs); - dump_unshared(proc_id, parent_id, "file", fileVAddrs); + + dump_unshared(proc_id, parent_id, "heap", heapVAddrs, space); + dump_unshared(proc_id, parent_id, "anon", anonVAddrs, space); + dump_unshared(proc_id, parent_id, "file", fileVAddrs, space); } static unsigned getParent(int proc_id) _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits