Add private dirty image section breakdown

Print how many private dirty pages there are for each image section.

Example output:

Image sections (total private dirty pages 157)
SectionObjects size=1997864 range=0-1997864 private dirty pages=53
SectionArtFields size=494988 range=1997864-2492852 private dirty pages=0
SectionArtMethods size=1397120 range=2492852-3889972 private dirty pages=29
SectionRuntimeMethods size=37824 range=4076856-4114680 private dirty pages=1
SectionImTables size=149468 range=3889972-4039440 private dirty pages=0
SectionIMTConflictTables size=37416 range=4039440-4076856 private dirty pages=0
SectionDexCacheArrays size=556680 range=4114680-4671360 private dirty pages=74
SectionInternedStrings size=200940 range=4671360-4872300 private dirty pages=0
SectionClassTable size=21468 range=4872304-4893772 private dirty pages=0
SectionImageBitmap size=32768 range=4894720-4927488 private dirty pages=0

Bug: 62554875
Test: test-art-target-imgdiag_test

(cherry picked from commit e618fe5f87e6e977215a96e9f76ee9e7ae675906)

Change-Id: I4853559568df5f4873de5df6c995ccf651d56ce3
diff --git a/imgdiag/imgdiag.cc b/imgdiag/imgdiag.cc
index fb8e894..7ef24c7 100644
--- a/imgdiag/imgdiag.cc
+++ b/imgdiag/imgdiag.cc
@@ -1075,6 +1075,8 @@
       }
     }
 
+    std::vector<size_t> private_dirty_pages_for_section(ImageHeader::kSectionCount, 0u);
+
     // Iterate through one byte at a time.
     ptrdiff_t page_off_begin = image_header_.GetImageBegin() - image_begin;
     for (uintptr_t begin = boot_map_.start; begin != boot_map_.end; ++begin) {
@@ -1127,6 +1129,12 @@
 
         if (is_dirty && is_private) {
           mapping_data->private_dirty_pages++;
+          for (size_t i = 0; i < ImageHeader::kSectionCount; ++i) {
+            const ImageHeader::ImageSections section = static_cast<ImageHeader::ImageSections>(i);
+            if (image_header_.GetImageSection(section).Contains(offset)) {
+              ++private_dirty_pages_for_section[i];
+            }
+          }
         }
       }
     }
@@ -1138,7 +1146,19 @@
        << mapping_data->dirty_pages << " pages are dirty;\n  "
        << mapping_data->false_dirty_pages << " pages are false dirty;\n  "
        << mapping_data->private_pages << " pages are private;\n  "
-       << mapping_data->private_dirty_pages << " pages are Private_Dirty\n  ";
+       << mapping_data->private_dirty_pages << " pages are Private_Dirty\n  "
+       << "\n";
+
+    size_t total_private_dirty_pages = std::accumulate(private_dirty_pages_for_section.begin(),
+                                                       private_dirty_pages_for_section.end(),
+                                                       0u);
+    os << "Image sections (total private dirty pages " << total_private_dirty_pages << ")\n";
+    for (size_t i = 0; i < ImageHeader::kSectionCount; ++i) {
+      const ImageHeader::ImageSections section = static_cast<ImageHeader::ImageSections>(i);
+      os << section << " " << image_header_.GetImageSection(section)
+         << " private dirty pages=" << private_dirty_pages_for_section[i] << "\n";
+    }
+    os << "\n";
 
     return true;
   }