Index: tools/android/memdump/memdump.cc |
diff --git a/tools/android/memdump/memdump.cc b/tools/android/memdump/memdump.cc |
index 21ef291f3d76d8f3b47814ade2e758f2725a3e95..05ccba6e615ad877c417434322fab3830480ac36 100644 |
--- a/tools/android/memdump/memdump.cc |
+++ b/tools/android/memdump/memdump.cc |
@@ -16,6 +16,7 @@ |
#include <utility> |
#include <vector> |
+#include "base/base64.h" |
#include "base/basictypes.h" |
#include "base/bind.h" |
#include "base/bind_helpers.h" |
@@ -30,6 +31,31 @@ |
namespace { |
+class BitSet { |
+ public: |
+ BitSet() : data_(0) {} |
pliard
2013/07/23 09:08:22
This will use the std::vector<char>::vector<char>(
Primiano Tucci (use gerrit)
2013/07/23 22:00:17
Well, the default constructor without the argument
|
+ |
+ void resize(size_t nbits) { |
+ data_.resize((nbits + 7) / 8); |
+ } |
+ |
+ void set(uint32 bit) { |
+ const uint32 byte_idx = bit / 8; |
+ CHECK(byte_idx < data_.size()); |
+ data_[byte_idx] |= (1 << (bit & 7)); |
+ } |
+ |
+ const std::string AsB64String() const { |
pliard
2013/07/23 09:08:22
Nit: this 'const' is superfluous since you are ret
Primiano Tucci (use gerrit)
2013/07/23 22:00:17
Yeah, that was a leftover from a previous attempt
|
+ std::string bits(&data_[0], data_.size()); |
+ std::string b64_string; |
+ base::Base64Encode(bits, &b64_string); |
+ return b64_string; |
+ } |
+ |
+ private: |
+ std::vector<char> data_; |
+}; |
+ |
// An entry in /proc/<pid>/pagemap. |
struct PageMapEntry { |
uint64 page_frame_number : 55; |
@@ -49,6 +75,7 @@ struct MemoryMap { |
std::string flags; |
uint start_address; |
uint end_address; |
+ uint offset; |
int private_count; |
int unevictable_private_count; |
int other_shared_count; |
@@ -57,6 +84,9 @@ struct MemoryMap { |
// (only among the processes that are being analyzed). |
std::vector<int> app_shared_counts; |
std::vector<PageInfo> committed_pages; |
+ // committed_pages_bits is a bitset reflecting the present bit for all the |
+ // virtual pages of the mapping. |
+ BitSet committed_pages_bits; |
}; |
struct ProcessMemory { |
@@ -114,6 +144,11 @@ bool ParseMemoryMapLine(const std::string& line, |
if (tokens->at(1).size() != strlen("rwxp")) |
return false; |
memory_map->flags.swap(tokens->at(1)); |
+ if (!base::HexStringToUInt64(tokens->at(2), &tmp)) |
+ return false; |
+ memory_map->offset = static_cast<uint>(tmp); |
+ memory_map->committed_pages_bits.resize( |
+ (memory_map->end_address - memory_map->start_address) / PAGE_SIZE); |
const int map_name_index = 5; |
if (tokens->size() >= map_name_index + 1) { |
for (std::vector<std::string>::const_iterator it = |
@@ -167,9 +202,11 @@ bool GetProcessMaps(pid_t pid, std::vector<MemoryMap>* process_maps) { |
// provided memory map. |
bool GetPagesForMemoryMap(int pagemap_fd, |
const MemoryMap& memory_map, |
- std::vector<PageInfo>* committed_pages) { |
- for (uint addr = memory_map.start_address; addr < memory_map.end_address; |
- addr += PAGE_SIZE) { |
+ std::vector<PageInfo>* committed_pages, |
+ BitSet* committed_pages_bits) { |
+ for (uint addr = memory_map.start_address, page_index = 0; |
+ addr < memory_map.end_address; |
+ addr += PAGE_SIZE, ++page_index) { |
DCHECK_EQ(0, addr % PAGE_SIZE); |
PageMapEntry page_map_entry = {}; |
COMPILE_ASSERT(sizeof(PageMapEntry) == sizeof(uint64), unexpected_size); |
@@ -182,6 +219,7 @@ bool GetPagesForMemoryMap(int pagemap_fd, |
PageInfo page_info = {}; |
page_info.page_frame_number = page_map_entry.page_frame_number; |
committed_pages->push_back(page_info); |
+ committed_pages_bits->set(page_index); |
} |
} |
return true; |
@@ -387,6 +425,40 @@ void DumpProcessesMemoryMapsInShortFormat( |
} |
} |
+void DumpProcessesMemoryMapsInExtendedFormat( |
+ const std::vector<ProcessMemory>& processes_memory) { |
+ std::string buf; |
+ std::string app_shared_buf; |
+ for (std::vector<ProcessMemory>::const_iterator it = processes_memory.begin(); |
+ it != processes_memory.end(); ++it) { |
+ const ProcessMemory& process_memory = *it; |
+ std::cout << "[ PID=" << process_memory.pid << "]" << '\n'; |
+ const std::vector<MemoryMap>& memory_maps = process_memory.memory_maps; |
+ for (std::vector<MemoryMap>::const_iterator it = memory_maps.begin(); |
+ it != memory_maps.end(); ++it) { |
+ const MemoryMap& memory_map = *it; |
+ app_shared_buf.clear(); |
+ AppendAppSharedField(memory_map.app_shared_counts, &app_shared_buf); |
+ base::SStringPrintf( |
+ &buf, |
+ "%x-%x %s %x private_unevictable=%d private=%d shared_app=%s " |
+ "shared_other_unevictable=%d shared_other=%d \"%s\" [%s]\n", |
+ memory_map.start_address, |
+ memory_map.end_address, |
+ memory_map.flags.c_str(), |
+ memory_map.offset, |
+ memory_map.unevictable_private_count * PAGE_SIZE, |
+ memory_map.private_count * PAGE_SIZE, |
+ app_shared_buf.c_str(), |
+ memory_map.unevictable_other_shared_count * PAGE_SIZE, |
+ memory_map.other_shared_count * PAGE_SIZE, |
+ memory_map.name.c_str(), |
+ memory_map.committed_pages_bits.AsB64String().c_str()); |
+ std::cout << buf; |
+ } |
+ } |
+} |
+ |
bool CollectProcessMemoryInformation(int page_count_fd, |
int page_flags_fd, |
ProcessMemory* process_memory) { |
@@ -404,7 +476,8 @@ bool CollectProcessMemoryInformation(int page_count_fd, |
for (std::vector<MemoryMap>::iterator it = process_maps->begin(); |
it != process_maps->end(); ++it) { |
std::vector<PageInfo>* const committed_pages = &it->committed_pages; |
- GetPagesForMemoryMap(pagemap_fd, *it, committed_pages); |
+ BitSet* const pages_bits = &it->committed_pages_bits; |
+ GetPagesForMemoryMap(pagemap_fd, *it, committed_pages, pages_bits); |
SetPagesInfo(page_count_fd, page_flags_fd, committed_pages); |
} |
return true; |
@@ -420,17 +493,17 @@ void KillAll(const std::vector<pid_t>& pids, int signal_number) { |
} // namespace |
int main(int argc, char** argv) { |
- bool short_output = false; |
if (argc == 1) { |
- LOG(ERROR) << "Usage: " << argv[0] << " [-a] <PID1>... <PIDN>"; |
+ LOG(ERROR) << "Usage: " << argv[0] << " [-a|-x] <PID1>... <PIDN>"; |
return EXIT_FAILURE; |
} |
- if (!strncmp(argv[1], "-a", 2)) { |
+ const bool short_output = !strncmp(argv[1], "-a", 2); |
+ const bool extended_output = !strncmp(argv[1], "-x", 2); |
+ if (short_output || extended_output) { |
if (argc == 2) { |
- LOG(ERROR) << "Usage: " << argv[0] << " [-a] <PID1>... <PIDN>"; |
+ LOG(ERROR) << "Usage: " << argv[0] << " [-a|-x] <PID1>... <PIDN>"; |
return EXIT_FAILURE; |
} |
- short_output = true; |
++argv; |
} |
std::vector<pid_t> pids; |
@@ -476,6 +549,8 @@ int main(int argc, char** argv) { |
ClassifyPages(&processes_memory); |
if (short_output) |
DumpProcessesMemoryMapsInShortFormat(processes_memory); |
+ else if (extended_output) |
+ DumpProcessesMemoryMapsInExtendedFormat(processes_memory); |
else |
DumpProcessesMemoryMaps(processes_memory); |
return EXIT_SUCCESS; |