Fix imgdiag crashing for ASLR images
Fixes a bug where the non runtime image was being used to calculate
the size of mirror::Objects, this caused a crash if the image was
ASLR relocated during boot.
This CL fixes imgdiag from crashing and provides a working diff for
app vs zygote. App vs image (for diagnosing shared dirty) is still
incorrect due to ASLR.
Test: test-art-host
Test: adb shell imgdiag --zygote-diff-pid=$(pid zygote64) --image-diff-pid=$(pid system_server) --boot-image=/system/framework/boot.art
Bug: 134614794
(cherry-picked from commit d3b6664f454e7ea61597c0235b4a9df95056f4cd)
Merged-In: I85a5625a60112471778d86a7d00af0b42bc2ef8c
Change-Id: I85a5625a60112471778d86a7d00af0b42bc2ef8c
diff --git a/imgdiag/imgdiag.cc b/imgdiag/imgdiag.cc
index 90563a1..3566498 100644
--- a/imgdiag/imgdiag.cc
+++ b/imgdiag/imgdiag.cc
@@ -217,9 +217,14 @@
return sizeof(*art_method);
}
+// entry1 and entry2 might be relocated, this means we must use the runtime image's entry
+// (image_entry) to avoid crashes.
template <typename T>
-static bool EntriesDiffer(T* entry1, T* entry2) REQUIRES_SHARED(Locks::mutator_lock_) {
- return memcmp(entry1, entry2, EntrySize(entry1)) != 0;
+static bool EntriesDiffer(T* image_entry,
+ T* entry1,
+ T* entry2) REQUIRES_SHARED(Locks::mutator_lock_) {
+ // Use the image entry since entry1 and entry2 might both be remote and relocated.
+ return memcmp(entry1, entry2, EntrySize(image_entry)) != 0;
}
template <typename T>
@@ -1065,18 +1070,18 @@
// Test private dirty first.
bool is_dirty = false;
if (have_zygote) {
- bool private_dirty = EntriesDiffer(entry_zygote, entry_remote);
+ bool private_dirty = EntriesDiffer(entry, entry_zygote, entry_remote);
if (private_dirty) {
// Private dirty, app vs zygote.
is_dirty = true;
RegionCommon<T>::AddImageDirtyEntry(entry);
}
- if (EntriesDiffer(entry_zygote, entry)) {
+ if (EntriesDiffer(entry, entry_zygote, entry)) {
// Shared dirty, zygote vs image.
is_dirty = true;
RegionCommon<T>::AddZygoteDirtyEntry(entry);
}
- } else if (EntriesDiffer(entry_remote, entry)) {
+ } else if (EntriesDiffer(entry, entry_remote, entry)) {
// Shared or private dirty, app vs image.
is_dirty = true;
RegionCommon<T>::AddImageDirtyEntry(entry);
@@ -1540,18 +1545,16 @@
}
}
- // FIXME: Because of ASLR, this check shall fail for most processes.
- // We need to update the entire diff to work with the ASLR. b/77856493
- if (reinterpret_cast<uintptr_t>(image_begin) > boot_map.start ||
- reinterpret_cast<uintptr_t>(image_end) < boot_map.end) {
- // Sanity check that we aren't trying to read a completely different boot image
- os << "Remote boot map is out of range of local boot map: " <<
+ // TODO: We need to update the entire diff to work with the ASLR. b/77856493
+ // Since the images may be relocated, just check the sizes.
+ if (static_cast<uintptr_t>(image_end - image_begin) != boot_map.end - boot_map.start) {
+ os << "Remote boot map is a different size than local boot map: " <<
"local begin " << reinterpret_cast<const void*>(image_begin) <<
", local end " << reinterpret_cast<const void*>(image_end) <<
", remote begin " << reinterpret_cast<const void*>(boot_map.start) <<
", remote end " << reinterpret_cast<const void*>(boot_map.end);
return false;
- // If we wanted even more validation we could map the ImageHeader from the file
+ // For more validation should also check the ImageHeader from the file
}
MappingData mapping_data;