Home | History | Annotate | Download | only in imgdiag
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <stdio.h>
     18 #include <stdlib.h>
     19 
     20 #include <fstream>
     21 #include <functional>
     22 #include <iostream>
     23 #include <string>
     24 #include <vector>
     25 #include <set>
     26 #include <map>
     27 #include <unordered_set>
     28 
     29 #include "android-base/stringprintf.h"
     30 
     31 #include "art_field-inl.h"
     32 #include "art_method-inl.h"
     33 #include "base/unix_file/fd_file.h"
     34 #include "class_linker.h"
     35 #include "gc/space/image_space.h"
     36 #include "gc/heap.h"
     37 #include "mirror/class-inl.h"
     38 #include "mirror/object-inl.h"
     39 #include "image.h"
     40 #include "oat.h"
     41 #include "oat_file.h"
     42 #include "oat_file_manager.h"
     43 #include "os.h"
     44 #include "scoped_thread_state_change-inl.h"
     45 
     46 #include "cmdline.h"
     47 #include "backtrace/BacktraceMap.h"
     48 
     49 #include <sys/stat.h>
     50 #include <sys/types.h>
     51 #include <signal.h>
     52 
     53 namespace art {
     54 
     55 using android::base::StringPrintf;
     56 
     57 namespace {
     58 
     59 constexpr size_t kMaxAddressPrint = 5;
     60 
     61 enum class ProcessType {
     62   kZygote,
     63   kRemote
     64 };
     65 
     66 enum class RemoteProcesses {
     67   kImageOnly,
     68   kZygoteOnly,
     69   kImageAndZygote
     70 };
     71 
     72 struct MappingData {
     73   // The count of pages that are considered dirty by the OS.
     74   size_t dirty_pages = 0;
     75   // The count of pages that differ by at least one byte.
     76   size_t different_pages = 0;
     77   // The count of differing bytes.
     78   size_t different_bytes = 0;
     79   // The count of differing four-byte units.
     80   size_t different_int32s = 0;
     81   // The count of pages that have mapping count == 1.
     82   size_t private_pages = 0;
     83   // The count of private pages that are also dirty.
     84   size_t private_dirty_pages = 0;
     85   // The count of pages that are marked dirty but do not differ.
     86   size_t false_dirty_pages = 0;
     87   // Set of the local virtual page indices that are dirty.
     88   std::set<size_t> dirty_page_set;
     89 };
     90 
     91 static std::string GetClassDescriptor(mirror::Class* klass)
     92     REQUIRES_SHARED(Locks::mutator_lock_) {
     93   CHECK(klass != nullptr);
     94 
     95   std::string descriptor;
     96   const char* descriptor_str = klass->GetDescriptor(&descriptor /*out*/);
     97 
     98   return std::string(descriptor_str);
     99 }
    100 
    101 static std::string PrettyFieldValue(ArtField* field, mirror::Object* object)
    102     REQUIRES_SHARED(Locks::mutator_lock_) {
    103   std::ostringstream oss;
    104   switch (field->GetTypeAsPrimitiveType()) {
    105     case Primitive::kPrimNot: {
    106       oss << object->GetFieldObject<mirror::Object, kVerifyNone, kWithoutReadBarrier>(
    107           field->GetOffset());
    108       break;
    109     }
    110     case Primitive::kPrimBoolean: {
    111       oss << static_cast<bool>(object->GetFieldBoolean<kVerifyNone>(field->GetOffset()));
    112       break;
    113     }
    114     case Primitive::kPrimByte: {
    115       oss << static_cast<int32_t>(object->GetFieldByte<kVerifyNone>(field->GetOffset()));
    116       break;
    117     }
    118     case Primitive::kPrimChar: {
    119       oss << object->GetFieldChar<kVerifyNone>(field->GetOffset());
    120       break;
    121     }
    122     case Primitive::kPrimShort: {
    123       oss << object->GetFieldShort<kVerifyNone>(field->GetOffset());
    124       break;
    125     }
    126     case Primitive::kPrimInt: {
    127       oss << object->GetField32<kVerifyNone>(field->GetOffset());
    128       break;
    129     }
    130     case Primitive::kPrimLong: {
    131       oss << object->GetField64<kVerifyNone>(field->GetOffset());
    132       break;
    133     }
    134     case Primitive::kPrimFloat: {
    135       oss << object->GetField32<kVerifyNone>(field->GetOffset());
    136       break;
    137     }
    138     case Primitive::kPrimDouble: {
    139       oss << object->GetField64<kVerifyNone>(field->GetOffset());
    140       break;
    141     }
    142     case Primitive::kPrimVoid: {
    143       oss << "void";
    144       break;
    145     }
    146   }
    147   return oss.str();
    148 }
    149 
    150 template <typename K, typename V, typename D>
    151 static std::vector<std::pair<V, K>> SortByValueDesc(
    152     const std::map<K, D> map,
    153     std::function<V(const D&)> value_mapper = [](const D& d) { return static_cast<V>(d); }) {
    154   // Store value->key so that we can use the default sort from pair which
    155   // sorts by value first and then key
    156   std::vector<std::pair<V, K>> value_key_vector;
    157 
    158   for (const auto& kv_pair : map) {
    159     value_key_vector.push_back(std::make_pair(value_mapper(kv_pair.second), kv_pair.first));
    160   }
    161 
    162   // Sort in reverse (descending order)
    163   std::sort(value_key_vector.rbegin(), value_key_vector.rend());
    164   return value_key_vector;
    165 }
    166 
    167 // Fixup a remote pointer that we read from a foreign boot.art to point to our own memory.
    168 // Returned pointer will point to inside of remote_contents.
    169 template <typename T>
    170 static T* FixUpRemotePointer(T* remote_ptr,
    171                              std::vector<uint8_t>& remote_contents,
    172                              const backtrace_map_t& boot_map) {
    173   if (remote_ptr == nullptr) {
    174     return nullptr;
    175   }
    176 
    177   uintptr_t remote = reinterpret_cast<uintptr_t>(remote_ptr);
    178 
    179   CHECK_LE(boot_map.start, remote);
    180   CHECK_GT(boot_map.end, remote);
    181 
    182   off_t boot_offset = remote - boot_map.start;
    183 
    184   return reinterpret_cast<T*>(&remote_contents[boot_offset]);
    185 }
    186 
    187 template <typename T>
    188 static T* RemoteContentsPointerToLocal(T* remote_ptr,
    189                                        std::vector<uint8_t>& remote_contents,
    190                                        const ImageHeader& image_header) {
    191   if (remote_ptr == nullptr) {
    192     return nullptr;
    193   }
    194 
    195   uint8_t* remote = reinterpret_cast<uint8_t*>(remote_ptr);
    196   ptrdiff_t boot_offset = remote - &remote_contents[0];
    197 
    198   const uint8_t* local_ptr = reinterpret_cast<const uint8_t*>(&image_header) + boot_offset;
    199 
    200   return reinterpret_cast<T*>(const_cast<uint8_t*>(local_ptr));
    201 }
    202 
    203 template <typename T> size_t EntrySize(T* entry);
    204 template<> size_t EntrySize(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_) {
    205   return object->SizeOf();
    206 }
    207 template<> size_t EntrySize(ArtMethod* art_method) REQUIRES_SHARED(Locks::mutator_lock_) {
    208   return sizeof(*art_method);
    209 }
    210 
    211 template <typename T>
    212 static bool EntriesDiffer(T* entry1, T* entry2) REQUIRES_SHARED(Locks::mutator_lock_) {
    213   return memcmp(entry1, entry2, EntrySize(entry1)) != 0;
    214 }
    215 
    216 template <typename T>
    217 struct RegionCommon {
    218  public:
    219   RegionCommon(std::ostream* os,
    220                std::vector<uint8_t>* remote_contents,
    221                std::vector<uint8_t>* zygote_contents,
    222                const backtrace_map_t& boot_map,
    223                const ImageHeader& image_header) :
    224     os_(*os),
    225     remote_contents_(remote_contents),
    226     zygote_contents_(zygote_contents),
    227     boot_map_(boot_map),
    228     image_header_(image_header),
    229     different_entries_(0),
    230     dirty_entry_bytes_(0),
    231     false_dirty_entry_bytes_(0) {
    232     CHECK(remote_contents != nullptr);
    233     CHECK(zygote_contents != nullptr);
    234   }
    235 
    236   void DumpSamplesAndOffsetCount() {
    237     os_ << "      sample object addresses: ";
    238     for (size_t i = 0; i < dirty_entries_.size() && i < kMaxAddressPrint; ++i) {
    239       T* entry = dirty_entries_[i];
    240       os_ << reinterpret_cast<void*>(entry) << ", ";
    241     }
    242     os_ << "\n";
    243     os_ << "      dirty byte +offset:count list = ";
    244     std::vector<std::pair<size_t, off_t>> field_dirty_count_sorted =
    245         SortByValueDesc<off_t, size_t, size_t>(field_dirty_count_);
    246     for (const std::pair<size_t, off_t>& pair : field_dirty_count_sorted) {
    247       off_t offset = pair.second;
    248       size_t count = pair.first;
    249       os_ << "+" << offset << ":" << count << ", ";
    250     }
    251     os_ << "\n";
    252   }
    253 
    254   size_t GetDifferentEntryCount() const { return different_entries_; }
    255   size_t GetDirtyEntryBytes() const { return dirty_entry_bytes_; }
    256   size_t GetFalseDirtyEntryCount() const { return false_dirty_entries_.size(); }
    257   size_t GetFalseDirtyEntryBytes() const { return false_dirty_entry_bytes_; }
    258   size_t GetZygoteDirtyEntryCount() const { return zygote_dirty_entries_.size(); }
    259 
    260  protected:
    261   bool IsEntryOnDirtyPage(T* entry, const std::set<size_t>& dirty_pages) const
    262       REQUIRES_SHARED(Locks::mutator_lock_) {
    263     size_t size = EntrySize(entry);
    264     size_t page_off = 0;
    265     size_t current_page_idx;
    266     uintptr_t entry_address = reinterpret_cast<uintptr_t>(entry);
    267     // Iterate every page this entry belongs to
    268     do {
    269       current_page_idx = entry_address / kPageSize + page_off;
    270       if (dirty_pages.find(current_page_idx) != dirty_pages.end()) {
    271         // This entry is on a dirty page
    272         return true;
    273       }
    274       page_off++;
    275     } while ((current_page_idx * kPageSize) < RoundUp(entry_address + size, kObjectAlignment));
    276     return false;
    277   }
    278 
    279   void AddZygoteDirtyEntry(T* entry) REQUIRES_SHARED(Locks::mutator_lock_) {
    280     zygote_dirty_entries_.insert(entry);
    281   }
    282 
    283   void AddImageDirtyEntry(T* entry) REQUIRES_SHARED(Locks::mutator_lock_) {
    284     image_dirty_entries_.insert(entry);
    285   }
    286 
    287   void AddFalseDirtyEntry(T* entry) REQUIRES_SHARED(Locks::mutator_lock_) {
    288     false_dirty_entries_.push_back(entry);
    289     false_dirty_entry_bytes_ += EntrySize(entry);
    290   }
    291 
    292   // The output stream to write to.
    293   std::ostream& os_;
    294   // The byte contents of the remote (image) process' image.
    295   std::vector<uint8_t>* remote_contents_;
    296   // The byte contents of the zygote process' image.
    297   std::vector<uint8_t>* zygote_contents_;
    298   const backtrace_map_t& boot_map_;
    299   const ImageHeader& image_header_;
    300 
    301   // Count of entries that are different.
    302   size_t different_entries_;
    303 
    304   // Local entries that are dirty (differ in at least one byte).
    305   size_t dirty_entry_bytes_;
    306   std::vector<T*> dirty_entries_;
    307 
    308   // Local entries that are clean, but located on dirty pages.
    309   size_t false_dirty_entry_bytes_;
    310   std::vector<T*> false_dirty_entries_;
    311 
    312   // Image dirty entries
    313   // If zygote_pid_only_ == true, these are shared dirty entries in the zygote.
    314   // If zygote_pid_only_ == false, these are private dirty entries in the application.
    315   std::set<T*> image_dirty_entries_;
    316 
    317   // Zygote dirty entries (probably private dirty).
    318   // We only add entries here if they differed in both the image and the zygote, so
    319   // they are probably private dirty.
    320   std::set<T*> zygote_dirty_entries_;
    321 
    322   std::map<off_t /* field offset */, size_t /* count */> field_dirty_count_;
    323 
    324  private:
    325   DISALLOW_COPY_AND_ASSIGN(RegionCommon);
    326 };
    327 
    328 template <typename T>
    329 class RegionSpecializedBase : public RegionCommon<T> {
    330 };
    331 
    332 // Region analysis for mirror::Objects
    333 class ImgObjectVisitor : public ObjectVisitor {
    334  public:
    335   using ComputeDirtyFunc = std::function<void(mirror::Object* object,
    336                                               const uint8_t* begin_image_ptr,
    337                                               const std::set<size_t>& dirty_pages)>;
    338   ImgObjectVisitor(ComputeDirtyFunc dirty_func,
    339                    const uint8_t* begin_image_ptr,
    340                    const std::set<size_t>& dirty_pages) :
    341     dirty_func_(dirty_func),
    342     begin_image_ptr_(begin_image_ptr),
    343     dirty_pages_(dirty_pages) { }
    344 
    345   virtual ~ImgObjectVisitor() OVERRIDE { }
    346 
    347   virtual void Visit(mirror::Object* object) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
    348     // Sanity check that we are reading a real mirror::Object
    349     CHECK(object->GetClass() != nullptr) << "Image object at address "
    350                                          << object
    351                                          << " has null class";
    352     if (kUseBakerReadBarrier) {
    353       object->AssertReadBarrierState();
    354     }
    355     dirty_func_(object, begin_image_ptr_, dirty_pages_);
    356   }
    357 
    358  private:
    359   ComputeDirtyFunc dirty_func_;
    360   const uint8_t* begin_image_ptr_;
    361   const std::set<size_t>& dirty_pages_;
    362 };
    363 
    364 template<>
    365 class RegionSpecializedBase<mirror::Object> : public RegionCommon<mirror::Object> {
    366  public:
    367   RegionSpecializedBase(std::ostream* os,
    368                         std::vector<uint8_t>* remote_contents,
    369                         std::vector<uint8_t>* zygote_contents,
    370                         const backtrace_map_t& boot_map,
    371                         const ImageHeader& image_header,
    372                         bool dump_dirty_objects)
    373       : RegionCommon<mirror::Object>(os, remote_contents, zygote_contents, boot_map, image_header),
    374         os_(*os),
    375         dump_dirty_objects_(dump_dirty_objects) { }
    376 
    377   // Define a common public type name for use by RegionData.
    378   using VisitorClass = ImgObjectVisitor;
    379 
    380   void VisitEntries(VisitorClass* visitor,
    381                     uint8_t* base,
    382                     PointerSize pointer_size)
    383       REQUIRES_SHARED(Locks::mutator_lock_) {
    384     RegionCommon<mirror::Object>::image_header_.VisitObjects(visitor, base, pointer_size);
    385   }
    386 
    387   void VisitEntry(mirror::Object* entry)
    388       REQUIRES_SHARED(Locks::mutator_lock_) {
    389     // Unconditionally store the class descriptor in case we need it later
    390     mirror::Class* klass = entry->GetClass();
    391     class_data_[klass].descriptor = GetClassDescriptor(klass);
    392   }
    393 
    394   void AddCleanEntry(mirror::Object* entry)
    395       REQUIRES_SHARED(Locks::mutator_lock_) {
    396     class_data_[entry->GetClass()].AddCleanObject();
    397   }
    398 
    399   void AddFalseDirtyEntry(mirror::Object* entry)
    400       REQUIRES_SHARED(Locks::mutator_lock_) {
    401     RegionCommon<mirror::Object>::AddFalseDirtyEntry(entry);
    402     class_data_[entry->GetClass()].AddFalseDirtyObject(entry);
    403   }
    404 
    405   void AddDirtyEntry(mirror::Object* entry, mirror::Object* entry_remote)
    406       REQUIRES_SHARED(Locks::mutator_lock_) {
    407     size_t entry_size = EntrySize(entry);
    408     ++different_entries_;
    409     dirty_entry_bytes_ += entry_size;
    410     // Log dirty count and objects for class objects only.
    411     mirror::Class* klass = entry->GetClass();
    412     if (klass->IsClassClass()) {
    413       // Increment counts for the fields that are dirty
    414       const uint8_t* current = reinterpret_cast<const uint8_t*>(entry);
    415       const uint8_t* current_remote = reinterpret_cast<const uint8_t*>(entry_remote);
    416       for (size_t i = 0; i < entry_size; ++i) {
    417         if (current[i] != current_remote[i]) {
    418           field_dirty_count_[i]++;
    419         }
    420       }
    421       dirty_entries_.push_back(entry);
    422     }
    423     class_data_[klass].AddDirtyObject(entry, entry_remote);
    424   }
    425 
    426   void DiffEntryContents(mirror::Object* entry,
    427                          uint8_t* remote_bytes,
    428                          const uint8_t* base_ptr,
    429                          bool log_dirty_objects)
    430       REQUIRES_SHARED(Locks::mutator_lock_) {
    431     const char* tabs = "    ";
    432     // Attempt to find fields for all dirty bytes.
    433     mirror::Class* klass = entry->GetClass();
    434     if (entry->IsClass()) {
    435       os_ << tabs
    436           << "Class " << mirror::Class::PrettyClass(entry->AsClass()) << " " << entry << "\n";
    437     } else {
    438       os_ << tabs
    439           << "Instance of " << mirror::Class::PrettyClass(klass) << " " << entry << "\n";
    440     }
    441 
    442     std::unordered_set<ArtField*> dirty_instance_fields;
    443     std::unordered_set<ArtField*> dirty_static_fields;
    444     // Examine the bytes comprising the Object, computing which fields are dirty
    445     // and recording them for later display.  If the Object is an array object,
    446     // compute the dirty entries.
    447     mirror::Object* remote_entry = reinterpret_cast<mirror::Object*>(remote_bytes);
    448     for (size_t i = 0, count = entry->SizeOf(); i < count; ++i) {
    449       if (base_ptr[i] != remote_bytes[i]) {
    450         ArtField* field = ArtField::FindInstanceFieldWithOffset</*exact*/false>(klass, i);
    451         if (field != nullptr) {
    452           dirty_instance_fields.insert(field);
    453         } else if (entry->IsClass()) {
    454           field = ArtField::FindStaticFieldWithOffset</*exact*/false>(entry->AsClass(), i);
    455           if (field != nullptr) {
    456             dirty_static_fields.insert(field);
    457           }
    458         }
    459         if (field == nullptr) {
    460           if (klass->IsArrayClass()) {
    461             mirror::Class* component_type = klass->GetComponentType();
    462             Primitive::Type primitive_type = component_type->GetPrimitiveType();
    463             size_t component_size = Primitive::ComponentSize(primitive_type);
    464             size_t data_offset = mirror::Array::DataOffset(component_size).Uint32Value();
    465             if (i >= data_offset) {
    466               os_ << tabs << "Dirty array element " << (i - data_offset) / component_size << "\n";
    467               // Skip to next element to prevent spam.
    468               i += component_size - 1;
    469               continue;
    470             }
    471           }
    472           os_ << tabs << "No field for byte offset " << i << "\n";
    473         }
    474       }
    475     }
    476     // Dump different fields.
    477     if (!dirty_instance_fields.empty()) {
    478       os_ << tabs << "Dirty instance fields " << dirty_instance_fields.size() << "\n";
    479       for (ArtField* field : dirty_instance_fields) {
    480         os_ << tabs << ArtField::PrettyField(field)
    481             << " original=" << PrettyFieldValue(field, entry)
    482             << " remote=" << PrettyFieldValue(field, remote_entry) << "\n";
    483       }
    484     }
    485     if (!dirty_static_fields.empty()) {
    486       if (dump_dirty_objects_ && log_dirty_objects) {
    487         dirty_objects_.insert(entry);
    488       }
    489       os_ << tabs << "Dirty static fields " << dirty_static_fields.size() << "\n";
    490       for (ArtField* field : dirty_static_fields) {
    491         os_ << tabs << ArtField::PrettyField(field)
    492             << " original=" << PrettyFieldValue(field, entry)
    493             << " remote=" << PrettyFieldValue(field, remote_entry) << "\n";
    494       }
    495     }
    496     os_ << "\n";
    497   }
    498 
    499   void DumpDirtyObjects() REQUIRES_SHARED(Locks::mutator_lock_) {
    500     for (mirror::Object* obj : dirty_objects_) {
    501       if (obj->IsClass()) {
    502         os_ << "Private dirty object: " << obj->AsClass()->PrettyDescriptor() << "\n";
    503       }
    504     }
    505   }
    506 
    507   void DumpDirtyEntries() REQUIRES_SHARED(Locks::mutator_lock_) {
    508     // vector of pairs (size_t count, Class*)
    509     auto dirty_object_class_values =
    510         SortByValueDesc<mirror::Class*, size_t, ClassData>(
    511             class_data_,
    512             [](const ClassData& d) { return d.dirty_object_count; });
    513     os_ << "\n" << "  Dirty object count by class:\n";
    514     for (const auto& vk_pair : dirty_object_class_values) {
    515       size_t dirty_object_count = vk_pair.first;
    516       mirror::Class* klass = vk_pair.second;
    517       ClassData& class_data = class_data_[klass];
    518       size_t object_sizes = class_data.dirty_object_size_in_bytes;
    519       float avg_dirty_bytes_per_class =
    520           class_data.dirty_object_byte_count * 1.0f / object_sizes;
    521       float avg_object_size = object_sizes * 1.0f / dirty_object_count;
    522       const std::string& descriptor = class_data.descriptor;
    523       os_ << "    " << mirror::Class::PrettyClass(klass) << " ("
    524           << "objects: " << dirty_object_count << ", "
    525           << "avg dirty bytes: " << avg_dirty_bytes_per_class << ", "
    526           << "avg object size: " << avg_object_size << ", "
    527           << "class descriptor: '" << descriptor << "'"
    528           << ")\n";
    529       if (strcmp(descriptor.c_str(), "Ljava/lang/Class;") == 0) {
    530         DumpSamplesAndOffsetCount();
    531         os_ << "      field contents:\n";
    532         for (mirror::Object* object : class_data.dirty_objects) {
    533           // remote class object
    534           auto remote_klass = reinterpret_cast<mirror::Class*>(object);
    535           // local class object
    536           auto local_klass =
    537               RemoteContentsPointerToLocal(remote_klass,
    538                                            *RegionCommon<mirror::Object>::remote_contents_,
    539                                            RegionCommon<mirror::Object>::image_header_);
    540           os_ << "        " << reinterpret_cast<const void*>(object) << " ";
    541           os_ << "  class_status (remote): " << remote_klass->GetStatus() << ", ";
    542           os_ << "  class_status (local): " << local_klass->GetStatus();
    543           os_ << "\n";
    544         }
    545       }
    546     }
    547   }
    548 
    549   void DumpFalseDirtyEntries() REQUIRES_SHARED(Locks::mutator_lock_) {
    550     // vector of pairs (size_t count, Class*)
    551     auto false_dirty_object_class_values =
    552         SortByValueDesc<mirror::Class*, size_t, ClassData>(
    553             class_data_,
    554             [](const ClassData& d) { return d.false_dirty_object_count; });
    555     os_ << "\n" << "  False-dirty object count by class:\n";
    556     for (const auto& vk_pair : false_dirty_object_class_values) {
    557       size_t object_count = vk_pair.first;
    558       mirror::Class* klass = vk_pair.second;
    559       ClassData& class_data = class_data_[klass];
    560       size_t object_sizes = class_data.false_dirty_byte_count;
    561       float avg_object_size = object_sizes * 1.0f / object_count;
    562       const std::string& descriptor = class_data.descriptor;
    563       os_ << "    " << mirror::Class::PrettyClass(klass) << " ("
    564           << "objects: " << object_count << ", "
    565           << "avg object size: " << avg_object_size << ", "
    566           << "total bytes: " << object_sizes << ", "
    567           << "class descriptor: '" << descriptor << "'"
    568           << ")\n";
    569     }
    570   }
    571 
    572   void DumpCleanEntries() REQUIRES_SHARED(Locks::mutator_lock_) {
    573     // vector of pairs (size_t count, Class*)
    574     auto clean_object_class_values =
    575         SortByValueDesc<mirror::Class*, size_t, ClassData>(
    576             class_data_,
    577             [](const ClassData& d) { return d.clean_object_count; });
    578     os_ << "\n" << "  Clean object count by class:\n";
    579     for (const auto& vk_pair : clean_object_class_values) {
    580       os_ << "    " << mirror::Class::PrettyClass(vk_pair.second) << " (" << vk_pair.first << ")\n";
    581     }
    582   }
    583 
    584  private:
    585   // Aggregate and detail class data from an image diff.
    586   struct ClassData {
    587     size_t dirty_object_count = 0;
    588     // Track only the byte-per-byte dirtiness (in bytes)
    589     size_t dirty_object_byte_count = 0;
    590     // Track the object-by-object dirtiness (in bytes)
    591     size_t dirty_object_size_in_bytes = 0;
    592     size_t clean_object_count = 0;
    593     std::string descriptor;
    594     size_t false_dirty_byte_count = 0;
    595     size_t false_dirty_object_count = 0;
    596     std::vector<mirror::Object*> false_dirty_objects;
    597     // Remote pointers to dirty objects
    598     std::vector<mirror::Object*> dirty_objects;
    599 
    600     void AddCleanObject() REQUIRES_SHARED(Locks::mutator_lock_) {
    601       ++clean_object_count;
    602     }
    603 
    604     void AddDirtyObject(mirror::Object* object, mirror::Object* object_remote)
    605         REQUIRES_SHARED(Locks::mutator_lock_) {
    606       ++dirty_object_count;
    607       dirty_object_byte_count += CountDirtyBytes(object, object_remote);
    608       dirty_object_size_in_bytes += EntrySize(object);
    609       dirty_objects.push_back(object_remote);
    610     }
    611 
    612     void AddFalseDirtyObject(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_) {
    613       ++false_dirty_object_count;
    614       false_dirty_objects.push_back(object);
    615       false_dirty_byte_count += EntrySize(object);
    616     }
    617 
    618    private:
    619     // Go byte-by-byte and figure out what exactly got dirtied
    620     static size_t CountDirtyBytes(mirror::Object* object1, mirror::Object* object2)
    621         REQUIRES_SHARED(Locks::mutator_lock_) {
    622       const uint8_t* cur1 = reinterpret_cast<const uint8_t*>(object1);
    623       const uint8_t* cur2 = reinterpret_cast<const uint8_t*>(object2);
    624       size_t dirty_bytes = 0;
    625       size_t object_size = EntrySize(object1);
    626       for (size_t i = 0; i < object_size; ++i) {
    627         if (cur1[i] != cur2[i]) {
    628           dirty_bytes++;
    629         }
    630       }
    631       return dirty_bytes;
    632     }
    633   };
    634 
    635   std::ostream& os_;
    636   bool dump_dirty_objects_;
    637   std::unordered_set<mirror::Object*> dirty_objects_;
    638   std::map<mirror::Class*, ClassData> class_data_;
    639 
    640   DISALLOW_COPY_AND_ASSIGN(RegionSpecializedBase);
    641 };
    642 
    643 // Region analysis for ArtMethods.
    644 class ImgArtMethodVisitor : public ArtMethodVisitor {
    645  public:
    646   using ComputeDirtyFunc = std::function<void(ArtMethod*,
    647                                               const uint8_t*,
    648                                               const std::set<size_t>&)>;
    649   ImgArtMethodVisitor(ComputeDirtyFunc dirty_func,
    650                       const uint8_t* begin_image_ptr,
    651                       const std::set<size_t>& dirty_pages) :
    652     dirty_func_(dirty_func),
    653     begin_image_ptr_(begin_image_ptr),
    654     dirty_pages_(dirty_pages) { }
    655   virtual ~ImgArtMethodVisitor() OVERRIDE { }
    656   virtual void Visit(ArtMethod* method) OVERRIDE {
    657     dirty_func_(method, begin_image_ptr_, dirty_pages_);
    658   }
    659 
    660  private:
    661   ComputeDirtyFunc dirty_func_;
    662   const uint8_t* begin_image_ptr_;
    663   const std::set<size_t>& dirty_pages_;
    664 };
    665 
    666 // Struct and functor for computing offsets of members of ArtMethods.
    667 // template <typename RegionType>
    668 struct MemberInfo {
    669   template <typename T>
    670   void operator() (const ArtMethod* method, const T* member_address, const std::string& name) {
    671     // Check that member_address is a pointer inside *method.
    672     DCHECK(reinterpret_cast<uintptr_t>(method) <= reinterpret_cast<uintptr_t>(member_address));
    673     DCHECK(reinterpret_cast<uintptr_t>(member_address) + sizeof(T) <=
    674            reinterpret_cast<uintptr_t>(method) + sizeof(ArtMethod));
    675     size_t offset =
    676         reinterpret_cast<uintptr_t>(member_address) - reinterpret_cast<uintptr_t>(method);
    677     offset_to_name_size_.insert({offset, NameAndSize(sizeof(T), name)});
    678   }
    679 
    680   struct NameAndSize {
    681     size_t size_;
    682     std::string name_;
    683     NameAndSize(size_t size, const std::string& name) : size_(size), name_(name) { }
    684     NameAndSize() : size_(0), name_("INVALID") { }
    685   };
    686 
    687   std::map<size_t, NameAndSize> offset_to_name_size_;
    688 };
    689 
    690 template<>
    691 class RegionSpecializedBase<ArtMethod> : public RegionCommon<ArtMethod> {
    692  public:
    693   RegionSpecializedBase(std::ostream* os,
    694                         std::vector<uint8_t>* remote_contents,
    695                         std::vector<uint8_t>* zygote_contents,
    696                         const backtrace_map_t& boot_map,
    697                         const ImageHeader& image_header,
    698                         bool dump_dirty_objects ATTRIBUTE_UNUSED)
    699       : RegionCommon<ArtMethod>(os, remote_contents, zygote_contents, boot_map, image_header),
    700         os_(*os) {
    701     // Prepare the table for offset to member lookups.
    702     ArtMethod* art_method = reinterpret_cast<ArtMethod*>(&(*remote_contents)[0]);
    703     art_method->VisitMembers(member_info_);
    704     // Prepare the table for address to symbolic entry point names.
    705     BuildEntryPointNames();
    706     class_linker_ = Runtime::Current()->GetClassLinker();
    707   }
    708 
    709   // Define a common public type name for use by RegionData.
    710   using VisitorClass = ImgArtMethodVisitor;
    711 
    712   void VisitEntries(VisitorClass* visitor,
    713                     uint8_t* base,
    714                     PointerSize pointer_size)
    715       REQUIRES_SHARED(Locks::mutator_lock_) {
    716     RegionCommon<ArtMethod>::image_header_.VisitPackedArtMethods(visitor, base, pointer_size);
    717   }
    718 
    719   void VisitEntry(ArtMethod* method ATTRIBUTE_UNUSED)
    720       REQUIRES_SHARED(Locks::mutator_lock_) {
    721   }
    722 
    723   void AddCleanEntry(ArtMethod* method ATTRIBUTE_UNUSED) {
    724   }
    725 
    726   void AddFalseDirtyEntry(ArtMethod* method)
    727       REQUIRES_SHARED(Locks::mutator_lock_) {
    728     RegionCommon<ArtMethod>::AddFalseDirtyEntry(method);
    729   }
    730 
    731   void AddDirtyEntry(ArtMethod* method, ArtMethod* method_remote)
    732       REQUIRES_SHARED(Locks::mutator_lock_) {
    733     size_t entry_size = EntrySize(method);
    734     ++different_entries_;
    735     dirty_entry_bytes_ += entry_size;
    736     // Increment counts for the fields that are dirty
    737     const uint8_t* current = reinterpret_cast<const uint8_t*>(method);
    738     const uint8_t* current_remote = reinterpret_cast<const uint8_t*>(method_remote);
    739     // ArtMethods always log their dirty count and entries.
    740     for (size_t i = 0; i < entry_size; ++i) {
    741       if (current[i] != current_remote[i]) {
    742         field_dirty_count_[i]++;
    743       }
    744     }
    745     dirty_entries_.push_back(method);
    746   }
    747 
    748   void DiffEntryContents(ArtMethod* method,
    749                          uint8_t* remote_bytes,
    750                          const uint8_t* base_ptr,
    751                          bool log_dirty_objects ATTRIBUTE_UNUSED)
    752       REQUIRES_SHARED(Locks::mutator_lock_) {
    753     const char* tabs = "    ";
    754     os_ << tabs << "ArtMethod " << ArtMethod::PrettyMethod(method) << "\n";
    755 
    756     std::unordered_set<size_t> dirty_members;
    757     // Examine the members comprising the ArtMethod, computing which members are dirty.
    758     for (const std::pair<size_t, MemberInfo::NameAndSize>& p : member_info_.offset_to_name_size_) {
    759       const size_t offset = p.first;
    760       if (memcmp(base_ptr + offset, remote_bytes + offset, p.second.size_) != 0) {
    761         dirty_members.insert(p.first);
    762       }
    763     }
    764     // Dump different fields.
    765     if (!dirty_members.empty()) {
    766       os_ << tabs << "Dirty members " << dirty_members.size() << "\n";
    767       for (size_t offset : dirty_members) {
    768         const MemberInfo::NameAndSize& member_info = member_info_.offset_to_name_size_[offset];
    769         os_ << tabs << member_info.name_
    770             << " original=" << StringFromBytes(base_ptr + offset, member_info.size_)
    771             << " remote=" << StringFromBytes(remote_bytes + offset, member_info.size_)
    772             << "\n";
    773       }
    774     }
    775     os_ << "\n";
    776   }
    777 
    778   void DumpDirtyObjects() REQUIRES_SHARED(Locks::mutator_lock_) {
    779   }
    780 
    781   void DumpDirtyEntries() REQUIRES_SHARED(Locks::mutator_lock_) {
    782     DumpSamplesAndOffsetCount();
    783     os_ << "      offset to field map:\n";
    784     for (const std::pair<size_t, MemberInfo::NameAndSize>& p : member_info_.offset_to_name_size_) {
    785       const size_t offset = p.first;
    786       const size_t size = p.second.size_;
    787       os_ << StringPrintf("        %zu-%zu: ", offset, offset + size - 1)
    788           << p.second.name_
    789           << std::endl;
    790     }
    791 
    792     os_ << "      field contents:\n";
    793     for (ArtMethod* method : dirty_entries_) {
    794       // remote method
    795       auto art_method = reinterpret_cast<ArtMethod*>(method);
    796       // remote class
    797       mirror::Class* remote_declaring_class =
    798         FixUpRemotePointer(art_method->GetDeclaringClass(),
    799                            *RegionCommon<ArtMethod>::remote_contents_,
    800                            RegionCommon<ArtMethod>::boot_map_);
    801       // local class
    802       mirror::Class* declaring_class =
    803         RemoteContentsPointerToLocal(remote_declaring_class,
    804                                      *RegionCommon<ArtMethod>::remote_contents_,
    805                                      RegionCommon<ArtMethod>::image_header_);
    806       DumpOneArtMethod(art_method, declaring_class, remote_declaring_class);
    807     }
    808   }
    809 
    810   void DumpFalseDirtyEntries() REQUIRES_SHARED(Locks::mutator_lock_) {
    811     os_ << "\n" << "  False-dirty ArtMethods\n";
    812     os_ << "      field contents:\n";
    813     for (ArtMethod* method : false_dirty_entries_) {
    814       // local class
    815       mirror::Class* declaring_class = method->GetDeclaringClass();
    816       DumpOneArtMethod(method, declaring_class, nullptr);
    817     }
    818   }
    819 
    820   void DumpCleanEntries() REQUIRES_SHARED(Locks::mutator_lock_) {
    821   }
    822 
    823  private:
    824   std::ostream& os_;
    825   MemberInfo member_info_;
    826   std::map<const void*, std::string> entry_point_names_;
    827   ClassLinker* class_linker_;
    828 
    829   // Compute a map of addresses to names in the boot OAT file(s).
    830   void BuildEntryPointNames() {
    831     OatFileManager& oat_file_manager = Runtime::Current()->GetOatFileManager();
    832     std::vector<const OatFile*> boot_oat_files = oat_file_manager.GetBootOatFiles();
    833     for (const OatFile* oat_file : boot_oat_files) {
    834       const OatHeader& oat_header = oat_file->GetOatHeader();
    835       const void* i2ib = oat_header.GetInterpreterToInterpreterBridge();
    836       if (i2ib != nullptr) {
    837         entry_point_names_[i2ib] = "InterpreterToInterpreterBridge (from boot oat file)";
    838       }
    839       const void* i2ccb = oat_header.GetInterpreterToCompiledCodeBridge();
    840       if (i2ccb != nullptr) {
    841         entry_point_names_[i2ccb] = "InterpreterToCompiledCodeBridge (from boot oat file)";
    842       }
    843       const void* jdl = oat_header.GetJniDlsymLookup();
    844       if (jdl != nullptr) {
    845         entry_point_names_[jdl] = "JniDlsymLookup (from boot oat file)";
    846       }
    847       const void* qgjt = oat_header.GetQuickGenericJniTrampoline();
    848       if (qgjt != nullptr) {
    849         entry_point_names_[qgjt] = "QuickGenericJniTrampoline (from boot oat file)";
    850       }
    851       const void* qrt = oat_header.GetQuickResolutionTrampoline();
    852       if (qrt != nullptr) {
    853         entry_point_names_[qrt] = "QuickResolutionTrampoline (from boot oat file)";
    854       }
    855       const void* qict = oat_header.GetQuickImtConflictTrampoline();
    856       if (qict != nullptr) {
    857         entry_point_names_[qict] = "QuickImtConflictTrampoline (from boot oat file)";
    858       }
    859       const void* q2ib = oat_header.GetQuickToInterpreterBridge();
    860       if (q2ib != nullptr) {
    861         entry_point_names_[q2ib] = "QuickToInterpreterBridge (from boot oat file)";
    862       }
    863     }
    864   }
    865 
    866   std::string StringFromBytes(const uint8_t* bytes, size_t size) {
    867     switch (size) {
    868       case 1:
    869         return StringPrintf("%" PRIx8, *bytes);
    870       case 2:
    871         return StringPrintf("%" PRIx16, *reinterpret_cast<const uint16_t*>(bytes));
    872       case 4:
    873       case 8: {
    874         // Compute an address if the bytes might contain one.
    875         uint64_t intval;
    876         if (size == 4) {
    877           intval = *reinterpret_cast<const uint32_t*>(bytes);
    878         } else {
    879           intval = *reinterpret_cast<const uint64_t*>(bytes);
    880         }
    881         const void* addr = reinterpret_cast<const void*>(intval);
    882         // Match the address against those that have Is* methods in the ClassLinker.
    883         if (class_linker_->IsQuickToInterpreterBridge(addr)) {
    884           return "QuickToInterpreterBridge";
    885         } else if (class_linker_->IsQuickGenericJniStub(addr)) {
    886           return "QuickGenericJniStub";
    887         } else if (class_linker_->IsQuickResolutionStub(addr)) {
    888           return "QuickResolutionStub";
    889         } else if (class_linker_->IsJniDlsymLookupStub(addr)) {
    890           return "JniDlsymLookupStub";
    891         }
    892         // Match the address against those that we saved from the boot OAT files.
    893         if (entry_point_names_.find(addr) != entry_point_names_.end()) {
    894           return entry_point_names_[addr];
    895         }
    896         return StringPrintf("%" PRIx64, intval);
    897       }
    898       default:
    899         LOG(WARNING) << "Don't know how to convert " << size << " bytes to integer";
    900         return "<UNKNOWN>";
    901     }
    902   }
    903 
    904   void DumpOneArtMethod(ArtMethod* art_method,
    905                         mirror::Class* declaring_class,
    906                         mirror::Class* remote_declaring_class)
    907       REQUIRES_SHARED(Locks::mutator_lock_) {
    908     PointerSize pointer_size = InstructionSetPointerSize(Runtime::Current()->GetInstructionSet());
    909     os_ << "        " << reinterpret_cast<const void*>(art_method) << " ";
    910     os_ << "  entryPointFromJni: "
    911         << reinterpret_cast<const void*>(art_method->GetDataPtrSize(pointer_size)) << ", ";
    912     os_ << "  entryPointFromQuickCompiledCode: "
    913         << reinterpret_cast<const void*>(
    914                art_method->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size))
    915         << ", ";
    916     os_ << "  isNative? " << (art_method->IsNative() ? "yes" : "no") << ", ";
    917     // Null for runtime metionds.
    918     if (declaring_class != nullptr) {
    919       os_ << "  class_status (local): " << declaring_class->GetStatus();
    920     }
    921     if (remote_declaring_class != nullptr) {
    922       os_ << ",  class_status (remote): " << remote_declaring_class->GetStatus();
    923     }
    924     os_ << "\n";
    925   }
    926 
    927   DISALLOW_COPY_AND_ASSIGN(RegionSpecializedBase);
    928 };
    929 
    930 template <typename T>
    931 class RegionData : public RegionSpecializedBase<T> {
    932  public:
    933   RegionData(std::ostream* os,
    934              std::vector<uint8_t>* remote_contents,
    935              std::vector<uint8_t>* zygote_contents,
    936              const backtrace_map_t& boot_map,
    937              const ImageHeader& image_header,
    938              bool dump_dirty_objects)
    939       : RegionSpecializedBase<T>(os,
    940                                  remote_contents,
    941                                  zygote_contents,
    942                                  boot_map,
    943                                  image_header,
    944                                  dump_dirty_objects),
    945         os_(*os) {
    946     CHECK(remote_contents != nullptr);
    947     CHECK(zygote_contents != nullptr);
    948   }
    949 
    950   // Walk over the type T entries in theregion between begin_image_ptr and end_image_ptr,
    951   // collecting and reporting data regarding dirty, difference, etc.
    952   void ProcessRegion(const MappingData& mapping_data,
    953                      RemoteProcesses remotes,
    954                      const uint8_t* begin_image_ptr)
    955       REQUIRES_SHARED(Locks::mutator_lock_) {
    956     typename RegionSpecializedBase<T>::VisitorClass visitor(
    957         [this](T* entry,
    958                const uint8_t* begin_image_ptr,
    959                const std::set<size_t>& dirty_page_set) REQUIRES_SHARED(Locks::mutator_lock_) {
    960           this->ComputeEntryDirty(entry, begin_image_ptr, dirty_page_set);
    961         },
    962         begin_image_ptr,
    963         mapping_data.dirty_page_set);
    964     PointerSize pointer_size = InstructionSetPointerSize(Runtime::Current()->GetInstructionSet());
    965     RegionSpecializedBase<T>::VisitEntries(&visitor,
    966                                            const_cast<uint8_t*>(begin_image_ptr),
    967                                            pointer_size);
    968 
    969     // Looking at only dirty pages, figure out how many of those bytes belong to dirty entries.
    970     // TODO: fix this now that there are multiple regions in a mapping.
    971     float true_dirtied_percent =
    972         RegionCommon<T>::GetDirtyEntryBytes() * 1.0f / (mapping_data.dirty_pages * kPageSize);
    973 
    974     // Entry specific statistics.
    975     os_ << RegionCommon<T>::GetDifferentEntryCount() << " different entries, \n  "
    976         << RegionCommon<T>::GetDirtyEntryBytes() << " different entry [bytes], \n  "
    977         << RegionCommon<T>::GetFalseDirtyEntryCount() << " false dirty entries,\n  "
    978         << RegionCommon<T>::GetFalseDirtyEntryBytes() << " false dirty entry [bytes], \n  "
    979         << true_dirtied_percent << " different entries-vs-total in a dirty page;\n  "
    980         << "\n";
    981 
    982     const uint8_t* base_ptr = begin_image_ptr;
    983     switch (remotes) {
    984       case RemoteProcesses::kZygoteOnly:
    985         os_ << "  Zygote shared dirty entries: ";
    986         break;
    987       case RemoteProcesses::kImageAndZygote:
    988         os_ << "  Application dirty entries (private dirty): ";
    989         // If we are dumping private dirty, diff against the zygote map to make it clearer what
    990         // fields caused the page to be private dirty.
    991         base_ptr = &RegionCommon<T>::zygote_contents_->operator[](0);
    992         break;
    993       case RemoteProcesses::kImageOnly:
    994         os_ << "  Application dirty entries (unknown whether private or shared dirty): ";
    995         break;
    996     }
    997     DiffDirtyEntries(ProcessType::kRemote,
    998                      begin_image_ptr,
    999                      RegionCommon<T>::remote_contents_,
   1000                      base_ptr,
   1001                      /*log_dirty_objects*/true);
   1002     // Print shared dirty after since it's less important.
   1003     if (RegionCommon<T>::GetZygoteDirtyEntryCount() != 0) {
   1004       // We only reach this point if both pids were specified.  Furthermore,
   1005       // entries are only displayed here if they differed in both the image
   1006       // and the zygote, so they are probably private dirty.
   1007       CHECK(remotes == RemoteProcesses::kImageAndZygote);
   1008       os_ << "\n" << "  Zygote dirty entries (probably shared dirty): ";
   1009       DiffDirtyEntries(ProcessType::kZygote,
   1010                        begin_image_ptr,
   1011                        RegionCommon<T>::zygote_contents_,
   1012                        begin_image_ptr,
   1013                        /*log_dirty_objects*/false);
   1014     }
   1015     RegionSpecializedBase<T>::DumpDirtyObjects();
   1016     RegionSpecializedBase<T>::DumpDirtyEntries();
   1017     RegionSpecializedBase<T>::DumpFalseDirtyEntries();
   1018     RegionSpecializedBase<T>::DumpCleanEntries();
   1019   }
   1020 
   1021  private:
   1022   std::ostream& os_;
   1023 
   1024   void DiffDirtyEntries(ProcessType process_type,
   1025                         const uint8_t* begin_image_ptr,
   1026                         std::vector<uint8_t>* contents,
   1027                         const uint8_t* base_ptr,
   1028                         bool log_dirty_objects)
   1029       REQUIRES_SHARED(Locks::mutator_lock_) {
   1030     os_ << RegionCommon<T>::dirty_entries_.size() << "\n";
   1031     const std::set<T*>& entries =
   1032         (process_type == ProcessType::kZygote) ?
   1033             RegionCommon<T>::zygote_dirty_entries_:
   1034             RegionCommon<T>::image_dirty_entries_;
   1035     for (T* entry : entries) {
   1036       uint8_t* entry_bytes = reinterpret_cast<uint8_t*>(entry);
   1037       ptrdiff_t offset = entry_bytes - begin_image_ptr;
   1038       uint8_t* remote_bytes = &(*contents)[offset];
   1039       RegionSpecializedBase<T>::DiffEntryContents(entry,
   1040                                                   remote_bytes,
   1041                                                   &base_ptr[offset],
   1042                                                   log_dirty_objects);
   1043     }
   1044   }
   1045 
   1046   void ComputeEntryDirty(T* entry,
   1047                          const uint8_t* begin_image_ptr,
   1048                          const std::set<size_t>& dirty_pages)
   1049       REQUIRES_SHARED(Locks::mutator_lock_) {
   1050     // Set up pointers in the remote and the zygote for comparison.
   1051     uint8_t* current = reinterpret_cast<uint8_t*>(entry);
   1052     ptrdiff_t offset = current - begin_image_ptr;
   1053     T* entry_remote =
   1054         reinterpret_cast<T*>(const_cast<uint8_t*>(&(*RegionCommon<T>::remote_contents_)[offset]));
   1055     const bool have_zygote = !RegionCommon<T>::zygote_contents_->empty();
   1056     const uint8_t* current_zygote =
   1057         have_zygote ? &(*RegionCommon<T>::zygote_contents_)[offset] : nullptr;
   1058     T* entry_zygote = reinterpret_cast<T*>(const_cast<uint8_t*>(current_zygote));
   1059     // Visit and classify entries at the current location.
   1060     RegionSpecializedBase<T>::VisitEntry(entry);
   1061 
   1062     // Test private dirty first.
   1063     bool is_dirty = false;
   1064     if (have_zygote) {
   1065       bool private_dirty = EntriesDiffer(entry_zygote, entry_remote);
   1066       if (private_dirty) {
   1067         // Private dirty, app vs zygote.
   1068         is_dirty = true;
   1069         RegionCommon<T>::AddImageDirtyEntry(entry);
   1070       }
   1071       if (EntriesDiffer(entry_zygote, entry)) {
   1072         // Shared dirty, zygote vs image.
   1073         is_dirty = true;
   1074         RegionCommon<T>::AddZygoteDirtyEntry(entry);
   1075       }
   1076     } else if (EntriesDiffer(entry_remote, entry)) {
   1077       // Shared or private dirty, app vs image.
   1078       is_dirty = true;
   1079       RegionCommon<T>::AddImageDirtyEntry(entry);
   1080     }
   1081     if (is_dirty) {
   1082       // TODO: Add support dirty entries in zygote and image.
   1083       RegionSpecializedBase<T>::AddDirtyEntry(entry, entry_remote);
   1084     } else {
   1085       RegionSpecializedBase<T>::AddCleanEntry(entry);
   1086       if (RegionCommon<T>::IsEntryOnDirtyPage(entry, dirty_pages)) {
   1087         // This entry was either never mutated or got mutated back to the same value.
   1088         // TODO: Do I want to distinguish a "different" vs a "dirty" page here?
   1089         RegionSpecializedBase<T>::AddFalseDirtyEntry(entry);
   1090       }
   1091     }
   1092   }
   1093 
   1094   DISALLOW_COPY_AND_ASSIGN(RegionData);
   1095 };
   1096 
   1097 }  // namespace
   1098 
   1099 
   1100 class ImgDiagDumper {
   1101  public:
   1102   explicit ImgDiagDumper(std::ostream* os,
   1103                          const ImageHeader& image_header,
   1104                          const std::string& image_location,
   1105                          pid_t image_diff_pid,
   1106                          pid_t zygote_diff_pid,
   1107                          bool dump_dirty_objects)
   1108       : os_(os),
   1109         image_header_(image_header),
   1110         image_location_(image_location),
   1111         image_diff_pid_(image_diff_pid),
   1112         zygote_diff_pid_(zygote_diff_pid),
   1113         dump_dirty_objects_(dump_dirty_objects),
   1114         zygote_pid_only_(false) {}
   1115 
   1116   bool Init() {
   1117     std::ostream& os = *os_;
   1118 
   1119     if (image_diff_pid_ < 0 && zygote_diff_pid_ < 0) {
   1120       os << "Either --image-diff-pid or --zygote-diff-pid (or both) must be specified.\n";
   1121       return false;
   1122     }
   1123 
   1124     // To avoid the combinations of command-line argument use cases:
   1125     // If the user invoked with only --zygote-diff-pid, shuffle that to
   1126     // image_diff_pid_, invalidate zygote_diff_pid_, and remember that
   1127     // image_diff_pid_ is now special.
   1128     if (image_diff_pid_ < 0) {
   1129       image_diff_pid_ = zygote_diff_pid_;
   1130       zygote_diff_pid_ = -1;
   1131       zygote_pid_only_ = true;
   1132     }
   1133 
   1134     {
   1135       struct stat sts;
   1136       std::string proc_pid_str =
   1137           StringPrintf("/proc/%ld", static_cast<long>(image_diff_pid_));  // NOLINT [runtime/int]
   1138       if (stat(proc_pid_str.c_str(), &sts) == -1) {
   1139         os << "Process does not exist";
   1140         return false;
   1141       }
   1142     }
   1143 
   1144     // Open /proc/$pid/maps to view memory maps
   1145     auto tmp_proc_maps = std::unique_ptr<BacktraceMap>(BacktraceMap::Create(image_diff_pid_));
   1146     if (tmp_proc_maps == nullptr) {
   1147       os << "Could not read backtrace maps";
   1148       return false;
   1149     }
   1150 
   1151     bool found_boot_map = false;
   1152     // Find the memory map only for boot.art
   1153     for (const backtrace_map_t& map : *tmp_proc_maps) {
   1154       if (EndsWith(map.name, GetImageLocationBaseName())) {
   1155         if ((map.flags & PROT_WRITE) != 0) {
   1156           boot_map_ = map;
   1157           found_boot_map = true;
   1158           break;
   1159         }
   1160         // In actuality there's more than 1 map, but the second one is read-only.
   1161         // The one we care about is the write-able map.
   1162         // The readonly maps are guaranteed to be identical, so its not interesting to compare
   1163         // them.
   1164       }
   1165     }
   1166 
   1167     if (!found_boot_map) {
   1168       os << "Could not find map for " << GetImageLocationBaseName();
   1169       return false;
   1170     }
   1171     // Sanity check boot_map_.
   1172     CHECK(boot_map_.end >= boot_map_.start);
   1173     boot_map_size_ = boot_map_.end - boot_map_.start;
   1174 
   1175     // Open /proc/<image_diff_pid_>/mem and read as remote_contents_.
   1176     std::string image_file_name =
   1177         StringPrintf("/proc/%ld/mem", static_cast<long>(image_diff_pid_));  // NOLINT [runtime/int]
   1178     auto image_map_file = std::unique_ptr<File>(OS::OpenFileForReading(image_file_name.c_str()));
   1179     if (image_map_file == nullptr) {
   1180       os << "Failed to open " << image_file_name << " for reading";
   1181       return false;
   1182     }
   1183     std::vector<uint8_t> tmp_remote_contents(boot_map_size_);
   1184     if (!image_map_file->PreadFully(&tmp_remote_contents[0], boot_map_size_, boot_map_.start)) {
   1185       os << "Could not fully read file " << image_file_name;
   1186       return false;
   1187     }
   1188 
   1189     // If zygote_diff_pid_ != -1, open /proc/<zygote_diff_pid_>/mem and read as zygote_contents_.
   1190     std::vector<uint8_t> tmp_zygote_contents;
   1191     if (zygote_diff_pid_ != -1) {
   1192       std::string zygote_file_name =
   1193           StringPrintf("/proc/%ld/mem", static_cast<long>(zygote_diff_pid_));  // NOLINT [runtime/int]
   1194       std::unique_ptr<File> zygote_map_file(OS::OpenFileForReading(zygote_file_name.c_str()));
   1195       if (zygote_map_file == nullptr) {
   1196         os << "Failed to open " << zygote_file_name << " for reading";
   1197         return false;
   1198       }
   1199       // The boot map should be at the same address.
   1200       tmp_zygote_contents.resize(boot_map_size_);
   1201       if (!zygote_map_file->PreadFully(&tmp_zygote_contents[0], boot_map_size_, boot_map_.start)) {
   1202         LOG(WARNING) << "Could not fully read zygote file " << zygote_file_name;
   1203         return false;
   1204       }
   1205     }
   1206 
   1207     // Open /proc/<image_diff_pid_>/pagemap.
   1208     std::string pagemap_file_name = StringPrintf(
   1209         "/proc/%ld/pagemap", static_cast<long>(image_diff_pid_));  // NOLINT [runtime/int]
   1210     auto tmp_pagemap_file =
   1211         std::unique_ptr<File>(OS::OpenFileForReading(pagemap_file_name.c_str()));
   1212     if (tmp_pagemap_file == nullptr) {
   1213       os << "Failed to open " << pagemap_file_name << " for reading: " << strerror(errno);
   1214       return false;
   1215     }
   1216 
   1217     // Not truly clean, mmap-ing boot.art again would be more pristine, but close enough
   1218     const char* clean_pagemap_file_name = "/proc/self/pagemap";
   1219     auto tmp_clean_pagemap_file = std::unique_ptr<File>(
   1220         OS::OpenFileForReading(clean_pagemap_file_name));
   1221     if (tmp_clean_pagemap_file == nullptr) {
   1222       os << "Failed to open " << clean_pagemap_file_name << " for reading: " << strerror(errno);
   1223       return false;
   1224     }
   1225 
   1226     auto tmp_kpageflags_file = std::unique_ptr<File>(OS::OpenFileForReading("/proc/kpageflags"));
   1227     if (tmp_kpageflags_file == nullptr) {
   1228       os << "Failed to open /proc/kpageflags for reading: " << strerror(errno);
   1229       return false;
   1230     }
   1231 
   1232     auto tmp_kpagecount_file = std::unique_ptr<File>(OS::OpenFileForReading("/proc/kpagecount"));
   1233     if (tmp_kpagecount_file == nullptr) {
   1234       os << "Failed to open /proc/kpagecount for reading:" << strerror(errno);
   1235       return false;
   1236     }
   1237 
   1238     // Commit the mappings, etc.
   1239     proc_maps_ = std::move(tmp_proc_maps);
   1240     remote_contents_ = std::move(tmp_remote_contents);
   1241     zygote_contents_ = std::move(tmp_zygote_contents);
   1242     pagemap_file_ = std::move(*tmp_pagemap_file.release());
   1243     clean_pagemap_file_ = std::move(*tmp_clean_pagemap_file.release());
   1244     kpageflags_file_ = std::move(*tmp_kpageflags_file.release());
   1245     kpagecount_file_ = std::move(*tmp_kpagecount_file.release());
   1246 
   1247     return true;
   1248   }
   1249 
   1250   bool Dump() REQUIRES_SHARED(Locks::mutator_lock_) {
   1251     std::ostream& os = *os_;
   1252     os << "IMAGE LOCATION: " << image_location_ << "\n\n";
   1253 
   1254     os << "MAGIC: " << image_header_.GetMagic() << "\n\n";
   1255 
   1256     os << "IMAGE BEGIN: " << reinterpret_cast<void*>(image_header_.GetImageBegin()) << "\n\n";
   1257 
   1258     PrintPidLine("IMAGE", image_diff_pid_);
   1259     os << "\n\n";
   1260     PrintPidLine("ZYGOTE", zygote_diff_pid_);
   1261     bool ret = true;
   1262     if (image_diff_pid_ >= 0 || zygote_diff_pid_ >= 0) {
   1263       ret = DumpImageDiff();
   1264       os << "\n\n";
   1265     }
   1266 
   1267     os << std::flush;
   1268 
   1269     return ret;
   1270   }
   1271 
   1272  private:
   1273   bool DumpImageDiff()
   1274       REQUIRES_SHARED(Locks::mutator_lock_) {
   1275     return DumpImageDiffMap();
   1276   }
   1277 
   1278   bool ComputeDirtyBytes(const uint8_t* image_begin, MappingData* mapping_data /*out*/) {
   1279     std::ostream& os = *os_;
   1280 
   1281     size_t virtual_page_idx = 0;   // Virtual page number (for an absolute memory address)
   1282     size_t page_idx = 0;           // Page index relative to 0
   1283     size_t previous_page_idx = 0;  // Previous page index relative to 0
   1284 
   1285 
   1286     // Iterate through one page at a time. Boot map begin/end already implicitly aligned.
   1287     for (uintptr_t begin = boot_map_.start; begin != boot_map_.end; begin += kPageSize) {
   1288       ptrdiff_t offset = begin - boot_map_.start;
   1289 
   1290       // We treat the image header as part of the memory map for now
   1291       // If we wanted to change this, we could pass base=start+sizeof(ImageHeader)
   1292       // But it might still be interesting to see if any of the ImageHeader data mutated
   1293       const uint8_t* local_ptr = reinterpret_cast<const uint8_t*>(&image_header_) + offset;
   1294       uint8_t* remote_ptr = &remote_contents_[offset];
   1295 
   1296       if (memcmp(local_ptr, remote_ptr, kPageSize) != 0) {
   1297         mapping_data->different_pages++;
   1298 
   1299         // Count the number of 32-bit integers that are different.
   1300         for (size_t i = 0; i < kPageSize / sizeof(uint32_t); ++i) {
   1301           uint32_t* remote_ptr_int32 = reinterpret_cast<uint32_t*>(remote_ptr);
   1302           const uint32_t* local_ptr_int32 = reinterpret_cast<const uint32_t*>(local_ptr);
   1303 
   1304           if (remote_ptr_int32[i] != local_ptr_int32[i]) {
   1305             mapping_data->different_int32s++;
   1306           }
   1307         }
   1308       }
   1309     }
   1310 
   1311     std::vector<size_t> private_dirty_pages_for_section(ImageHeader::kSectionCount, 0u);
   1312 
   1313     // Iterate through one byte at a time.
   1314     ptrdiff_t page_off_begin = image_header_.GetImageBegin() - image_begin;
   1315     for (uintptr_t begin = boot_map_.start; begin != boot_map_.end; ++begin) {
   1316       previous_page_idx = page_idx;
   1317       ptrdiff_t offset = begin - boot_map_.start;
   1318 
   1319       // We treat the image header as part of the memory map for now
   1320       // If we wanted to change this, we could pass base=start+sizeof(ImageHeader)
   1321       // But it might still be interesting to see if any of the ImageHeader data mutated
   1322       const uint8_t* local_ptr = reinterpret_cast<const uint8_t*>(&image_header_) + offset;
   1323       uint8_t* remote_ptr = &remote_contents_[offset];
   1324 
   1325       virtual_page_idx = reinterpret_cast<uintptr_t>(local_ptr) / kPageSize;
   1326 
   1327       // Calculate the page index, relative to the 0th page where the image begins
   1328       page_idx = (offset + page_off_begin) / kPageSize;
   1329       if (*local_ptr != *remote_ptr) {
   1330         // Track number of bytes that are different
   1331         mapping_data->different_bytes++;
   1332       }
   1333 
   1334       // Independently count the # of dirty pages on the remote side
   1335       size_t remote_virtual_page_idx = begin / kPageSize;
   1336       if (previous_page_idx != page_idx) {
   1337         uint64_t page_count = 0xC0FFEE;
   1338         // TODO: virtual_page_idx needs to be from the same process
   1339         std::string error_msg;
   1340         int dirtiness = (IsPageDirty(&pagemap_file_,           // Image-diff-pid procmap
   1341                                      &clean_pagemap_file_,     // Self procmap
   1342                                      &kpageflags_file_,
   1343                                      &kpagecount_file_,
   1344                                      remote_virtual_page_idx,  // potentially "dirty" page
   1345                                      virtual_page_idx,         // true "clean" page
   1346                                      &page_count,
   1347                                      &error_msg));
   1348         if (dirtiness < 0) {
   1349           os << error_msg;
   1350           return false;
   1351         } else if (dirtiness > 0) {
   1352           mapping_data->dirty_pages++;
   1353           mapping_data->dirty_page_set.insert(mapping_data->dirty_page_set.end(), virtual_page_idx);
   1354         }
   1355 
   1356         bool is_dirty = dirtiness > 0;
   1357         bool is_private = page_count == 1;
   1358 
   1359         if (page_count == 1) {
   1360           mapping_data->private_pages++;
   1361         }
   1362 
   1363         if (is_dirty && is_private) {
   1364           mapping_data->private_dirty_pages++;
   1365           for (size_t i = 0; i < ImageHeader::kSectionCount; ++i) {
   1366             const ImageHeader::ImageSections section = static_cast<ImageHeader::ImageSections>(i);
   1367             if (image_header_.GetImageSection(section).Contains(offset)) {
   1368               ++private_dirty_pages_for_section[i];
   1369             }
   1370           }
   1371         }
   1372       }
   1373     }
   1374     mapping_data->false_dirty_pages = mapping_data->dirty_pages - mapping_data->different_pages;
   1375     // Print low-level (bytes, int32s, pages) statistics.
   1376     os << mapping_data->different_bytes << " differing bytes,\n  "
   1377        << mapping_data->different_int32s << " differing int32s,\n  "
   1378        << mapping_data->different_pages << " differing pages,\n  "
   1379        << mapping_data->dirty_pages << " pages are dirty;\n  "
   1380        << mapping_data->false_dirty_pages << " pages are false dirty;\n  "
   1381        << mapping_data->private_pages << " pages are private;\n  "
   1382        << mapping_data->private_dirty_pages << " pages are Private_Dirty\n  "
   1383        << "\n";
   1384 
   1385     size_t total_private_dirty_pages = std::accumulate(private_dirty_pages_for_section.begin(),
   1386                                                        private_dirty_pages_for_section.end(),
   1387                                                        0u);
   1388     os << "Image sections (total private dirty pages " << total_private_dirty_pages << ")\n";
   1389     for (size_t i = 0; i < ImageHeader::kSectionCount; ++i) {
   1390       const ImageHeader::ImageSections section = static_cast<ImageHeader::ImageSections>(i);
   1391       os << section << " " << image_header_.GetImageSection(section)
   1392          << " private dirty pages=" << private_dirty_pages_for_section[i] << "\n";
   1393     }
   1394     os << "\n";
   1395 
   1396     return true;
   1397   }
   1398 
   1399   // Look at /proc/$pid/mem and only diff the things from there
   1400   bool DumpImageDiffMap()
   1401       REQUIRES_SHARED(Locks::mutator_lock_) {
   1402     std::ostream& os = *os_;
   1403     std::string error_msg;
   1404 
   1405     // Walk the bytes and diff against our boot image
   1406     os << "\nObserving boot image header at address "
   1407        << reinterpret_cast<const void*>(&image_header_)
   1408        << "\n\n";
   1409 
   1410     const uint8_t* image_begin_unaligned = image_header_.GetImageBegin();
   1411     const uint8_t* image_end_unaligned = image_begin_unaligned + image_header_.GetImageSize();
   1412 
   1413     // Adjust range to nearest page
   1414     const uint8_t* image_begin = AlignDown(image_begin_unaligned, kPageSize);
   1415     const uint8_t* image_end = AlignUp(image_end_unaligned, kPageSize);
   1416 
   1417     if (reinterpret_cast<uintptr_t>(image_begin) > boot_map_.start ||
   1418         reinterpret_cast<uintptr_t>(image_end) < boot_map_.end) {
   1419       // Sanity check that we aren't trying to read a completely different boot image
   1420       os << "Remote boot map is out of range of local boot map: " <<
   1421         "local begin " << reinterpret_cast<const void*>(image_begin) <<
   1422         ", local end " << reinterpret_cast<const void*>(image_end) <<
   1423         ", remote begin " << reinterpret_cast<const void*>(boot_map_.start) <<
   1424         ", remote end " << reinterpret_cast<const void*>(boot_map_.end);
   1425       return false;
   1426       // If we wanted even more validation we could map the ImageHeader from the file
   1427     }
   1428 
   1429     MappingData mapping_data;
   1430 
   1431     os << "Mapping at [" << reinterpret_cast<void*>(boot_map_.start) << ", "
   1432        << reinterpret_cast<void*>(boot_map_.end) << ") had:\n  ";
   1433     if (!ComputeDirtyBytes(image_begin, &mapping_data)) {
   1434       return false;
   1435     }
   1436     RemoteProcesses remotes;
   1437     if (zygote_pid_only_) {
   1438       remotes = RemoteProcesses::kZygoteOnly;
   1439     } else if (zygote_diff_pid_ > 0) {
   1440       remotes = RemoteProcesses::kImageAndZygote;
   1441     } else {
   1442       remotes = RemoteProcesses::kImageOnly;
   1443     }
   1444 
   1445     // Check all the mirror::Object entries in the image.
   1446     RegionData<mirror::Object> object_region_data(os_,
   1447                                                   &remote_contents_,
   1448                                                   &zygote_contents_,
   1449                                                   boot_map_,
   1450                                                   image_header_,
   1451                                                   dump_dirty_objects_);
   1452     object_region_data.ProcessRegion(mapping_data,
   1453                                      remotes,
   1454                                      image_begin_unaligned);
   1455 
   1456     // Check all the ArtMethod entries in the image.
   1457     RegionData<ArtMethod> artmethod_region_data(os_,
   1458                                                 &remote_contents_,
   1459                                                 &zygote_contents_,
   1460                                                 boot_map_,
   1461                                                 image_header_,
   1462                                                 dump_dirty_objects_);
   1463     artmethod_region_data.ProcessRegion(mapping_data,
   1464                                         remotes,
   1465                                         image_begin_unaligned);
   1466     return true;
   1467   }
   1468 
   1469   static bool GetPageFrameNumber(File* page_map_file,
   1470                                 size_t virtual_page_index,
   1471                                 uint64_t* page_frame_number,
   1472                                 std::string* error_msg) {
   1473     CHECK(page_map_file != nullptr);
   1474     CHECK(page_frame_number != nullptr);
   1475     CHECK(error_msg != nullptr);
   1476 
   1477     constexpr size_t kPageMapEntrySize = sizeof(uint64_t);
   1478     constexpr uint64_t kPageFrameNumberMask = (1ULL << 55) - 1;  // bits 0-54 [in /proc/$pid/pagemap]
   1479     constexpr uint64_t kPageSoftDirtyMask = (1ULL << 55);  // bit 55 [in /proc/$pid/pagemap]
   1480 
   1481     uint64_t page_map_entry = 0;
   1482 
   1483     // Read 64-bit entry from /proc/$pid/pagemap to get the physical page frame number
   1484     if (!page_map_file->PreadFully(&page_map_entry, kPageMapEntrySize,
   1485                                   virtual_page_index * kPageMapEntrySize)) {
   1486       *error_msg = StringPrintf("Failed to read the virtual page index entry from %s",
   1487                                 page_map_file->GetPath().c_str());
   1488       return false;
   1489     }
   1490 
   1491     // TODO: seems useless, remove this.
   1492     bool soft_dirty = (page_map_entry & kPageSoftDirtyMask) != 0;
   1493     if ((false)) {
   1494       LOG(VERBOSE) << soft_dirty;  // Suppress unused warning
   1495       UNREACHABLE();
   1496     }
   1497 
   1498     *page_frame_number = page_map_entry & kPageFrameNumberMask;
   1499 
   1500     return true;
   1501   }
   1502 
   1503   static int IsPageDirty(File* page_map_file,
   1504                          File* clean_pagemap_file,
   1505                          File* kpageflags_file,
   1506                          File* kpagecount_file,
   1507                          size_t virtual_page_idx,
   1508                          size_t clean_virtual_page_idx,
   1509                          // Out parameters:
   1510                          uint64_t* page_count, std::string* error_msg) {
   1511     CHECK(page_map_file != nullptr);
   1512     CHECK(clean_pagemap_file != nullptr);
   1513     CHECK_NE(page_map_file, clean_pagemap_file);
   1514     CHECK(kpageflags_file != nullptr);
   1515     CHECK(kpagecount_file != nullptr);
   1516     CHECK(page_count != nullptr);
   1517     CHECK(error_msg != nullptr);
   1518 
   1519     // Constants are from https://www.kernel.org/doc/Documentation/vm/pagemap.txt
   1520 
   1521     constexpr size_t kPageFlagsEntrySize = sizeof(uint64_t);
   1522     constexpr size_t kPageCountEntrySize = sizeof(uint64_t);
   1523     constexpr uint64_t kPageFlagsDirtyMask = (1ULL << 4);  // in /proc/kpageflags
   1524     constexpr uint64_t kPageFlagsNoPageMask = (1ULL << 20);  // in /proc/kpageflags
   1525     constexpr uint64_t kPageFlagsMmapMask = (1ULL << 11);  // in /proc/kpageflags
   1526 
   1527     uint64_t page_frame_number = 0;
   1528     if (!GetPageFrameNumber(page_map_file, virtual_page_idx, &page_frame_number, error_msg)) {
   1529       return -1;
   1530     }
   1531 
   1532     uint64_t page_frame_number_clean = 0;
   1533     if (!GetPageFrameNumber(clean_pagemap_file, clean_virtual_page_idx, &page_frame_number_clean,
   1534                             error_msg)) {
   1535       return -1;
   1536     }
   1537 
   1538     // Read 64-bit entry from /proc/kpageflags to get the dirty bit for a page
   1539     uint64_t kpage_flags_entry = 0;
   1540     if (!kpageflags_file->PreadFully(&kpage_flags_entry,
   1541                                      kPageFlagsEntrySize,
   1542                                      page_frame_number * kPageFlagsEntrySize)) {
   1543       *error_msg = StringPrintf("Failed to read the page flags from %s",
   1544                                 kpageflags_file->GetPath().c_str());
   1545       return -1;
   1546     }
   1547 
   1548     // Read 64-bit entyry from /proc/kpagecount to get mapping counts for a page
   1549     if (!kpagecount_file->PreadFully(page_count /*out*/,
   1550                                      kPageCountEntrySize,
   1551                                      page_frame_number * kPageCountEntrySize)) {
   1552       *error_msg = StringPrintf("Failed to read the page count from %s",
   1553                                 kpagecount_file->GetPath().c_str());
   1554       return -1;
   1555     }
   1556 
   1557     // There must be a page frame at the requested address.
   1558     CHECK_EQ(kpage_flags_entry & kPageFlagsNoPageMask, 0u);
   1559     // The page frame must be memory mapped
   1560     CHECK_NE(kpage_flags_entry & kPageFlagsMmapMask, 0u);
   1561 
   1562     // Page is dirty, i.e. has diverged from file, if the 4th bit is set to 1
   1563     bool flags_dirty = (kpage_flags_entry & kPageFlagsDirtyMask) != 0;
   1564 
   1565     // page_frame_number_clean must come from the *same* process
   1566     // but a *different* mmap than page_frame_number
   1567     if (flags_dirty) {
   1568       CHECK_NE(page_frame_number, page_frame_number_clean);
   1569     }
   1570 
   1571     return page_frame_number != page_frame_number_clean;
   1572   }
   1573 
   1574   void PrintPidLine(const std::string& kind, pid_t pid) {
   1575     if (pid < 0) {
   1576       *os_ << kind << " DIFF PID: disabled\n\n";
   1577     } else {
   1578       *os_ << kind << " DIFF PID (" << pid << "): ";
   1579     }
   1580   }
   1581 
   1582   static bool EndsWith(const std::string& str, const std::string& suffix) {
   1583     return str.size() >= suffix.size() &&
   1584            str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
   1585   }
   1586 
   1587   // Return suffix of the file path after the last /. (e.g. /foo/bar -> bar, bar -> bar)
   1588   static std::string BaseName(const std::string& str) {
   1589     size_t idx = str.rfind('/');
   1590     if (idx == std::string::npos) {
   1591       return str;
   1592     }
   1593 
   1594     return str.substr(idx + 1);
   1595   }
   1596 
   1597   // Return the image location, stripped of any directories, e.g. "boot.art" or "core.art"
   1598   std::string GetImageLocationBaseName() const {
   1599     return BaseName(std::string(image_location_));
   1600   }
   1601 
   1602   std::ostream* os_;
   1603   const ImageHeader& image_header_;
   1604   const std::string image_location_;
   1605   pid_t image_diff_pid_;  // Dump image diff against boot.art if pid is non-negative
   1606   pid_t zygote_diff_pid_;  // Dump image diff against zygote boot.art if pid is non-negative
   1607   bool dump_dirty_objects_;  // Adds dumping of objects that are dirty.
   1608   bool zygote_pid_only_;  // The user only specified a pid for the zygote.
   1609 
   1610   // BacktraceMap used for finding the memory mapping of the image file.
   1611   std::unique_ptr<BacktraceMap> proc_maps_;
   1612   // Boot image mapping.
   1613   backtrace_map_t boot_map_{};  // NOLINT
   1614   // The size of the boot image mapping.
   1615   size_t boot_map_size_;
   1616   // The contents of /proc/<image_diff_pid_>/maps.
   1617   std::vector<uint8_t> remote_contents_;
   1618   // The contents of /proc/<zygote_diff_pid_>/maps.
   1619   std::vector<uint8_t> zygote_contents_;
   1620   // A File for reading /proc/<zygote_diff_pid_>/maps.
   1621   File pagemap_file_;
   1622   // A File for reading /proc/self/pagemap.
   1623   File clean_pagemap_file_;
   1624   // A File for reading /proc/kpageflags.
   1625   File kpageflags_file_;
   1626   // A File for reading /proc/kpagecount.
   1627   File kpagecount_file_;
   1628 
   1629   DISALLOW_COPY_AND_ASSIGN(ImgDiagDumper);
   1630 };
   1631 
   1632 static int DumpImage(Runtime* runtime,
   1633                      std::ostream* os,
   1634                      pid_t image_diff_pid,
   1635                      pid_t zygote_diff_pid,
   1636                      bool dump_dirty_objects) {
   1637   ScopedObjectAccess soa(Thread::Current());
   1638   gc::Heap* heap = runtime->GetHeap();
   1639   std::vector<gc::space::ImageSpace*> image_spaces = heap->GetBootImageSpaces();
   1640   CHECK(!image_spaces.empty());
   1641   for (gc::space::ImageSpace* image_space : image_spaces) {
   1642     const ImageHeader& image_header = image_space->GetImageHeader();
   1643     if (!image_header.IsValid()) {
   1644       fprintf(stderr, "Invalid image header %s\n", image_space->GetImageLocation().c_str());
   1645       return EXIT_FAILURE;
   1646     }
   1647 
   1648     ImgDiagDumper img_diag_dumper(os,
   1649                                   image_header,
   1650                                   image_space->GetImageLocation(),
   1651                                   image_diff_pid,
   1652                                   zygote_diff_pid,
   1653                                   dump_dirty_objects);
   1654     if (!img_diag_dumper.Init()) {
   1655       return EXIT_FAILURE;
   1656     }
   1657     if (!img_diag_dumper.Dump()) {
   1658       return EXIT_FAILURE;
   1659     }
   1660   }
   1661   return EXIT_SUCCESS;
   1662 }
   1663 
   1664 struct ImgDiagArgs : public CmdlineArgs {
   1665  protected:
   1666   using Base = CmdlineArgs;
   1667 
   1668   virtual ParseStatus ParseCustom(const StringPiece& option,
   1669                                   std::string* error_msg) OVERRIDE {
   1670     {
   1671       ParseStatus base_parse = Base::ParseCustom(option, error_msg);
   1672       if (base_parse != kParseUnknownArgument) {
   1673         return base_parse;
   1674       }
   1675     }
   1676 
   1677     if (option.starts_with("--image-diff-pid=")) {
   1678       const char* image_diff_pid = option.substr(strlen("--image-diff-pid=")).data();
   1679 
   1680       if (!ParseInt(image_diff_pid, &image_diff_pid_)) {
   1681         *error_msg = "Image diff pid out of range";
   1682         return kParseError;
   1683       }
   1684     } else if (option.starts_with("--zygote-diff-pid=")) {
   1685       const char* zygote_diff_pid = option.substr(strlen("--zygote-diff-pid=")).data();
   1686 
   1687       if (!ParseInt(zygote_diff_pid, &zygote_diff_pid_)) {
   1688         *error_msg = "Zygote diff pid out of range";
   1689         return kParseError;
   1690       }
   1691     } else if (option == "--dump-dirty-objects") {
   1692       dump_dirty_objects_ = true;
   1693     } else {
   1694       return kParseUnknownArgument;
   1695     }
   1696 
   1697     return kParseOk;
   1698   }
   1699 
   1700   virtual ParseStatus ParseChecks(std::string* error_msg) OVERRIDE {
   1701     // Perform the parent checks.
   1702     ParseStatus parent_checks = Base::ParseChecks(error_msg);
   1703     if (parent_checks != kParseOk) {
   1704       return parent_checks;
   1705     }
   1706 
   1707     // Perform our own checks.
   1708 
   1709     if (kill(image_diff_pid_,
   1710              /*sig*/0) != 0) {  // No signal is sent, perform error-checking only.
   1711       // Check if the pid exists before proceeding.
   1712       if (errno == ESRCH) {
   1713         *error_msg = "Process specified does not exist";
   1714       } else {
   1715         *error_msg = StringPrintf("Failed to check process status: %s", strerror(errno));
   1716       }
   1717       return kParseError;
   1718     } else if (instruction_set_ != kRuntimeISA) {
   1719       // Don't allow different ISAs since the images are ISA-specific.
   1720       // Right now the code assumes both the runtime ISA and the remote ISA are identical.
   1721       *error_msg = "Must use the default runtime ISA; changing ISA is not supported.";
   1722       return kParseError;
   1723     }
   1724 
   1725     return kParseOk;
   1726   }
   1727 
   1728   virtual std::string GetUsage() const {
   1729     std::string usage;
   1730 
   1731     usage +=
   1732         "Usage: imgdiag [options] ...\n"
   1733         "    Example: imgdiag --image-diff-pid=$(pidof dex2oat)\n"
   1734         "    Example: adb shell imgdiag --image-diff-pid=$(pid zygote)\n"
   1735         "\n";
   1736 
   1737     usage += Base::GetUsage();
   1738 
   1739     usage +=  // Optional.
   1740         "  --image-diff-pid=<pid>: provide the PID of a process whose boot.art you want to diff.\n"
   1741         "      Example: --image-diff-pid=$(pid zygote)\n"
   1742         "  --zygote-diff-pid=<pid>: provide the PID of the zygote whose boot.art you want to diff "
   1743         "against.\n"
   1744         "      Example: --zygote-diff-pid=$(pid zygote)\n"
   1745         "  --dump-dirty-objects: additionally output dirty objects of interest.\n"
   1746         "\n";
   1747 
   1748     return usage;
   1749   }
   1750 
   1751  public:
   1752   pid_t image_diff_pid_ = -1;
   1753   pid_t zygote_diff_pid_ = -1;
   1754   bool dump_dirty_objects_ = false;
   1755 };
   1756 
   1757 struct ImgDiagMain : public CmdlineMain<ImgDiagArgs> {
   1758   virtual bool ExecuteWithRuntime(Runtime* runtime) {
   1759     CHECK(args_ != nullptr);
   1760 
   1761     return DumpImage(runtime,
   1762                      args_->os_,
   1763                      args_->image_diff_pid_,
   1764                      args_->zygote_diff_pid_,
   1765                      args_->dump_dirty_objects_) == EXIT_SUCCESS;
   1766   }
   1767 };
   1768 
   1769 }  // namespace art
   1770 
   1771 int main(int argc, char** argv) {
   1772   art::ImgDiagMain main;
   1773   return main.Main(argc, argv);
   1774 }
   1775