libmeminfo: Swap accounting bug fixes

This fixes a couple issues:
  1. Swap offsets are 50-bit wide, so store them in uint64_t instead of
     uint16_t.
  2. Swap offset starts from 1 instead of 0.  Add one extra slot in
     swap offset count array to account for this.

Test: Run procrank and does not see incorrect PSwap numbers anymore.
Change-Id: I2471970d4a29909e8a0874f6c69af3f9a0b15b02
diff --git a/include/meminfo/procmeminfo.h b/include/meminfo/procmeminfo.h
index 8c1280f..4c4a27d 100644
--- a/include/meminfo/procmeminfo.h
+++ b/include/meminfo/procmeminfo.h
@@ -83,7 +83,7 @@
     // Returns 'true' on success and the value of Pss in the out parameter.
     bool SmapsOrRollupPss(uint64_t* pss) const;
 
-    const std::vector<uint16_t>& SwapOffsets();
+    const std::vector<uint64_t>& SwapOffsets();
 
     // Reads /proc/<pid>/pagemap for this process for each page within
     // the 'vma' and stores that in 'pagemap'. It is assumed that the 'vma'
@@ -106,7 +106,7 @@
     std::vector<Vma> maps_;
 
     MemUsage usage_;
-    std::vector<uint16_t> swap_offsets_;
+    std::vector<uint64_t> swap_offsets_;
 };
 
 // Makes callback for each 'vma' or 'map' found in file provided. The file is expected to be in the
diff --git a/libmeminfo_test.cpp b/libmeminfo_test.cpp
index d75357d..5d5f22e 100644
--- a/libmeminfo_test.cpp
+++ b/libmeminfo_test.cpp
@@ -202,7 +202,7 @@
     // If we created the object for getting working set,
     // the swap offsets must be empty
     ProcMemInfo proc_mem(pid, true);
-    const std::vector<uint16_t>& swap_offsets = proc_mem.SwapOffsets();
+    const std::vector<uint64_t>& swap_offsets = proc_mem.SwapOffsets();
     EXPECT_EQ(swap_offsets.size(), 0);
 }
 
diff --git a/procmeminfo.cpp b/procmeminfo.cpp
index 9e9a705..e755ff1 100644
--- a/procmeminfo.cpp
+++ b/procmeminfo.cpp
@@ -202,7 +202,7 @@
     return SmapsOrRollupPssFromFile(path, pss);
 }
 
-const std::vector<uint16_t>& ProcMemInfo::SwapOffsets() {
+const std::vector<uint64_t>& ProcMemInfo::SwapOffsets() {
     if (get_wss_) {
         LOG(WARNING) << "Trying to read process swap offsets for " << pid_
                      << " using invalid object";
diff --git a/tools/procrank.cpp b/tools/procrank.cpp
index 1e44ff9..e7c1af9 100644
--- a/tools/procrank.cpp
+++ b/tools/procrank.cpp
@@ -85,7 +85,8 @@
 
     bool valid() const { return pid_ != -1; }
 
-    void CalculateSwap(const uint16_t* swap_offset_array, float zram_compression_ratio) {
+    void CalculateSwap(const std::vector<uint16_t>& swap_offset_array,
+                       float zram_compression_ratio) {
         for (auto& off : swap_offsets_) {
             proportional_swap_ += getpagesize() / swap_offset_array[off];
             unique_swap_ += swap_offset_array[off] == 1 ? getpagesize() : 0;
@@ -102,7 +103,7 @@
     uint64_t zswap() const { return zswap_; }
 
     // Wrappers to ProcMemInfo
-    const std::vector<uint16_t>& SwapOffsets() const { return swap_offsets_; }
+    const std::vector<uint64_t>& SwapOffsets() const { return swap_offsets_; }
     const MemUsage& Usage() const { return usage_or_wss_; }
     const MemUsage& Wss() const { return usage_or_wss_; }
 
@@ -114,7 +115,7 @@
     uint64_t unique_swap_;
     uint64_t zswap_;
     MemUsage usage_or_wss_;
-    std::vector<uint16_t> swap_offsets_;
+    std::vector<uint64_t> swap_offsets_;
 };
 
 // Show working set instead of memory consumption
@@ -177,11 +178,11 @@
     return true;
 }
 
-static bool count_swap_offsets(const ProcessRecord& proc, uint16_t* swap_offset_array,
-                               uint32_t size) {
-    const std::vector<uint16_t>& swp_offs = proc.SwapOffsets();
+static bool count_swap_offsets(const ProcessRecord& proc,
+                               std::vector<uint16_t>& swap_offset_array) {
+    const std::vector<uint64_t>& swp_offs = proc.SwapOffsets();
     for (auto& off : swp_offs) {
-        if (off >= size) {
+        if (off >= swap_offset_array.size()) {
             std::cerr << "swap offset " << off << " is out of bounds for process: " << proc.pid()
                       << std::endl;
             return false;
@@ -249,7 +250,7 @@
 }
 
 static void print_processes(std::stringstream& ss, std::vector<ProcessRecord>& procs,
-                            uint16_t* swap_offset_array) {
+                            const std::vector<uint16_t>& swap_offset_array) {
     for (auto& proc : procs) {
         total_pss += show_wss ? proc.Wss().pss : proc.Usage().pss;
         total_uss += show_wss ? proc.Wss().uss : proc.Usage().uss;
@@ -446,7 +447,7 @@
     uint64_t swap_total = smi.mem_swap_kb() * 1024;
     has_swap = swap_total > 0;
     // Allocate the swap array
-    auto swap_offset_array = std::make_unique<uint16_t[]>(swap_total / getpagesize());
+    std::vector<uint16_t> swap_offset_array(swap_total / getpagesize() + 1, 0);
     if (has_swap) {
         has_zram = smi.mem_zram_kb() > 0;
         if (has_zram) {
@@ -476,7 +477,7 @@
 
         // collect swap_offset counts from all processes in 1st pass
         if (!show_wss && has_swap &&
-            !count_swap_offsets(proc, swap_offset_array.get(), swap_total / getpagesize())) {
+            !count_swap_offsets(proc, swap_offset_array)) {
             std::cerr << "Failed to count swap offsets for process: " << pid << std::endl;
             return false;
         }
@@ -515,7 +516,7 @@
     ss << std::endl;
 
     // 2nd pass to calculate and get per process stats to add them up
-    print_processes(ss, procs, swap_offset_array.get());
+    print_processes(ss, procs, swap_offset_array);
 
     // Add separator to output
     print_separator(ss);