diff --git a/matrix/matrix-android/matrix-hooks/src/main/cpp/common/Maps.cpp b/matrix/matrix-android/matrix-hooks/src/main/cpp/common/Maps.cpp index 77870e75f..7327a18b0 100644 --- a/matrix/matrix-android/matrix-hooks/src/main/cpp/common/Maps.cpp +++ b/matrix/matrix-android/matrix-hooks/src/main/cpp/common/Maps.cpp @@ -31,7 +31,7 @@ bool matrix::IterateMaps(const MapsEntryCallback& cb, void* args) { char perm[4] = {}; int pathnamePos = 0; - if (::sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %4s %*x %*x:%*x %*d%n", &start, &end, perm, &pathnamePos) != 3) { + if (::sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %4c %*x %*x:%*x %*d%n", &start, &end, perm, &pathnamePos) != 3) { continue; } @@ -49,15 +49,17 @@ bool matrix::IterateMaps(const MapsEntryCallback& cb, void* args) { continue; } char* pathname = line + pathnamePos; - while (pathLen >= 0 && pathname[pathLen - 1] == '\n') { + while (pathLen > 0 && pathname[pathLen - 1] == '\n') { pathname[pathLen - 1] = '\0'; --pathLen; } if (cb(start, end, perm, pathname, args)) { + ::fclose(fp); return true; } } + ::fclose(fp); return false; } \ No newline at end of file diff --git a/matrix/matrix-android/matrix-hooks/src/main/cpp/common/ScopedCleaner.h b/matrix/matrix-android/matrix-hooks/src/main/cpp/common/ScopedCleaner.h index 5055f322f..1bf2ba3a8 100644 --- a/matrix/matrix-android/matrix-hooks/src/main/cpp/common/ScopedCleaner.h +++ b/matrix/matrix-android/matrix-hooks/src/main/cpp/common/ScopedCleaner.h @@ -31,7 +31,7 @@ namespace matrix { ScopedCleaner(const TDtor& dtor): mDtor(dtor), mOmitted(false) {} ScopedCleaner(ScopedCleaner&& other): mDtor(other.mDtor), mOmitted(other.mOmitted) { - other.omit(); + other.Omit(); } ~ScopedCleaner() { diff --git a/matrix/matrix-android/matrix-hooks/src/main/cpp/memory/GCSemiSpaceTrimmer.cpp b/matrix/matrix-android/matrix-hooks/src/main/cpp/memory/GCSemiSpaceTrimmer.cpp index 80107cff2..44f8f43d7 100644 --- a/matrix/matrix-android/matrix-hooks/src/main/cpp/memory/GCSemiSpaceTrimmer.cpp +++ b/matrix/matrix-android/matrix-hooks/src/main/cpp/memory/GCSemiSpaceTrimmer.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -35,13 +36,43 @@ static std::condition_variable sBlocker; class SemiSpaceSearcher { public: SemiSpaceSearcher() - : mStatus(STATUS_OUTSIDE_TARGETS), + : mIsSpaceNameSame(false), + mVMHeapSize(0), + mStatus(STATUS_OUTSIDE_TARGETS), mSpace1Start(0), mSpace1End(0), mSpace1Size(0), mSpace2Start(0), mSpace2End(0), - mSpace2Size(0) {} + mSpace2Size(0) { + int api_level = android_get_device_api_level(); + // Android 5.x + if (api_level >= 21 && api_level <= 22) { + mIsSpaceNameSame = true; + } + + char vmHeapSize[16] = {0}; + if (__system_property_get("dalvik.vm.heapsize", vmHeapSize) > 0) { + char* hsCh = vmHeapSize + sizeof(vmHeapSize) - 1; + size_t hsUnit = 1; + while (hsCh >= vmHeapSize) { + if (::isdigit(*hsCh)) { + break; + } else if (*hsCh == 'G' || *hsCh == 'g') { + hsUnit = 1024 * 1024 * 1024; + } else if (*hsCh == 'M' || *hsCh == 'm') { + hsUnit = 1024 * 1024; + } else if (*hsCh == 'K' || *hsCh == 'k') { + hsUnit = 1024; + } + *hsCh = '\0'; + --hsCh; + } + if (hsCh >= vmHeapSize) { + mVMHeapSize = ::strtol(vmHeapSize, nullptr, 10) * hsUnit; + } + } + } bool operator()(uintptr_t start, uintptr_t end, char perms[4], const char *path, void *args) { while (true) { @@ -50,15 +81,29 @@ class SemiSpaceSearcher { if (mSpace1Start != 0 && mSpace1End != 0 && mSpace2Start != 0 && mSpace2End != 0) { mStatus = STATUS_ALL_SPACES_FOUND; } else { - if (strstr(path, SS_MAIN_SPACE_NAMES[1]) != nullptr - || strstr(path, SS_BUMPER_SPACE_NAMES[1]) != nullptr) { - mStatus = STATUS_FOUND_FRIST_SPACE_TWO_ENTRY; - } else if (strstr(path, SS_MAIN_SPACE_NAMES[0]) != nullptr - || strstr(path, SS_BUMPER_SPACE_NAMES[0]) != nullptr) { - mStatus = STATUS_FOUND_FRIST_SPACE_ONE_ENTRY; + if (mIsSpaceNameSame) { + if (strstr(path, SS_MAIN_SPACE_NAMES[0]) != nullptr + || strstr(path, SS_BUMPER_SPACE_NAMES[0]) != nullptr) { + if (mSpace1Start == 0) { + mStatus = STATUS_FOUND_FRIST_SPACE_ONE_ENTRY; + } else if (mSpace2Start == 0) { + mStatus = STATUS_FOUND_FRIST_SPACE_TWO_ENTRY; + } + } else { + // Continue searching next entry. + return false; + } } else { - // Continue searching next entry. - return false; + if (strstr(path, SS_MAIN_SPACE_NAMES[1]) != nullptr + || strstr(path, SS_BUMPER_SPACE_NAMES[1]) != nullptr) { + mStatus = STATUS_FOUND_FRIST_SPACE_TWO_ENTRY; + } else if (strstr(path, SS_MAIN_SPACE_NAMES[0]) != nullptr + || strstr(path, SS_BUMPER_SPACE_NAMES[0]) != nullptr) { + mStatus = STATUS_FOUND_FRIST_SPACE_ONE_ENTRY; + } else { + // Continue searching next entry. + return false; + } } } break; @@ -76,20 +121,40 @@ class SemiSpaceSearcher { break; } case STATUS_INSIDE_SPACE_ONE_REGION: { - if (strstr(path, SS_MAIN_SPACE_NAMES[1]) != nullptr - || strstr(path, SS_BUMPER_SPACE_NAMES[1]) != nullptr) { - mStatus = STATUS_FOUND_FRIST_SPACE_TWO_ENTRY; - } else if (strstr(path, SS_MAIN_SPACE_NAMES[0]) != nullptr - || strstr(path, SS_BUMPER_SPACE_NAMES[0]) != nullptr) { - if (start == mSpace1End) { - mSpace1End = end; - // Continue searching next entry. - return false; + if (mIsSpaceNameSame) { + if (strstr(path, SS_MAIN_SPACE_NAMES[0]) != nullptr + || strstr(path, SS_BUMPER_SPACE_NAMES[0]) != nullptr) { + // 512M or 256M in Anroid 5.x + if (end - mSpace1Start > mVMHeapSize) { + mStatus = STATUS_FOUND_FRIST_SPACE_TWO_ENTRY; + } else { + if (start == mSpace1End) { + mSpace1End = end; + // Continue searching next entry. + return false; + } else { + mStatus = STATUS_DISCONTINOUS_SPACE_FOUND; + } + } } else { - mStatus = STATUS_DISCONTINOUS_SPACE_FOUND; + mStatus = STATUS_OUTSIDE_TARGETS; } } else { - mStatus = STATUS_OUTSIDE_TARGETS; + if (strstr(path, SS_MAIN_SPACE_NAMES[1]) != nullptr + || strstr(path, SS_BUMPER_SPACE_NAMES[1]) != nullptr) { + mStatus = STATUS_FOUND_FRIST_SPACE_TWO_ENTRY; + } else if (strstr(path, SS_MAIN_SPACE_NAMES[0]) != nullptr + || strstr(path, SS_BUMPER_SPACE_NAMES[0]) != nullptr) { + if (start == mSpace1End) { + mSpace1End = end; + // Continue searching next entry. + return false; + } else { + mStatus = STATUS_DISCONTINOUS_SPACE_FOUND; + } + } else { + mStatus = STATUS_OUTSIDE_TARGETS; + } } break; } @@ -106,20 +171,40 @@ class SemiSpaceSearcher { break; } case STATUS_INSIDE_SPACE_TWO_REGION: { - if (strstr(path, SS_MAIN_SPACE_NAMES[1]) != nullptr - || strstr(path, SS_BUMPER_SPACE_NAMES[1]) != nullptr) { - if (start == mSpace2End) { - mSpace2End = end; - // Continue searching next entry. - return false; + if (mIsSpaceNameSame) { + if (strstr(path, SS_MAIN_SPACE_NAMES[0]) != nullptr + || strstr(path, SS_BUMPER_SPACE_NAMES[0]) != nullptr) { + // 512M or 256M in Anroid 5.x + if (end - mSpace2Start <= mVMHeapSize) { + if (start == mSpace2End) { + mSpace2End = end; + // Continue searching next entry. + return false; + } else { + mStatus = STATUS_DISCONTINOUS_SPACE_FOUND; + } + } else { + mStatus = STATUS_FOUND_FRIST_SPACE_ONE_ENTRY; + } } else { - mStatus = STATUS_DISCONTINOUS_SPACE_FOUND; + mStatus = STATUS_OUTSIDE_TARGETS; } - } else if (strstr(path, SS_MAIN_SPACE_NAMES[0]) != nullptr - || strstr(path, SS_BUMPER_SPACE_NAMES[0]) != nullptr) { - mStatus = STATUS_FOUND_FRIST_SPACE_ONE_ENTRY; } else { - mStatus = STATUS_OUTSIDE_TARGETS; + if (strstr(path, SS_MAIN_SPACE_NAMES[1]) != nullptr + || strstr(path, SS_BUMPER_SPACE_NAMES[1]) != nullptr) { + if (start == mSpace2End) { + mSpace2End = end; + // Continue searching next entry. + return false; + } else { + mStatus = STATUS_DISCONTINOUS_SPACE_FOUND; + } + } else if (strstr(path, SS_MAIN_SPACE_NAMES[0]) != nullptr + || strstr(path, SS_BUMPER_SPACE_NAMES[0]) != nullptr) { + mStatus = STATUS_FOUND_FRIST_SPACE_ONE_ENTRY; + } else { + mStatus = STATUS_OUTSIDE_TARGETS; + } } break; } @@ -166,11 +251,17 @@ class SemiSpaceSearcher { return mSpace2Size; } + size_t getVMHeapSize() const { + return mVMHeapSize; + } + bool foundAllSpaces() const { return (mStatus == STATUS_ALL_SPACES_FOUND); } void reset() { + mIsSpaceNameSame = false; + mVMHeapSize = 0; mStatus = STATUS_OUTSIDE_TARGETS; mSpace1Start = 0; mSpace1End = 0; @@ -194,6 +285,8 @@ class SemiSpaceSearcher { static constexpr const char* SS_MAIN_SPACE_NAMES[2] = {"dalvik-main space", "dalvik-main space 1"}; static constexpr const char* SS_BUMPER_SPACE_NAMES[2] = {"Bump pointer space 1", "Bump pointer space 2"}; + bool mIsSpaceNameSame; + size_t mVMHeapSize; int mStatus; uintptr_t mSpace1Start; uintptr_t mSpace1End; @@ -248,36 +341,12 @@ bool matrix::gc_ss_trimmer::Install(JNIEnv* env) { } // Found target spaces. - char vmHeapSize[16] = {}; - if (__system_property_get("dalvik.vm.heapsize", vmHeapSize) < 1) { - LOGE(LOG_TAG, "Fail to get vm heap size, skip processing."); - break; - } - char* hsCh = vmHeapSize + sizeof(vmHeapSize) - 1; - size_t hsUnit = 1; - while (hsCh >= vmHeapSize) { - if (::isdigit(*hsCh)) { - break; - } else if (*hsCh == 'G' || *hsCh == 'g') { - hsUnit = 1024 * 1024 * 1024; - } else if (*hsCh == 'M' || *hsCh == 'm') { - hsUnit = 1024 * 1024; - } else if (*hsCh == 'K' || *hsCh == 'k') { - hsUnit = 1024; - } - *hsCh = '\0'; - --hsCh; - } - if (hsCh < vmHeapSize) { - LOGE(LOG_TAG, "Illegal vm heap size value, skip processing."); - break; - } - size_t vmHeapSizeNum = ::strtol(vmHeapSize, nullptr, 10) * hsUnit; const size_t space1Size = semiSpaceSearcher.getSpace1Size(); const size_t space2Size = semiSpaceSearcher.getSpace2Size(); - if (space1Size != space2Size || space1Size != vmHeapSizeNum) { - LOGE(LOG_TAG, "Unexpected space size, expected: %u, actual_space1: %u, actual_space2: %u", - vmHeapSizeNum, space1Size, space2Size); + const size_t vmHeapSize = semiSpaceSearcher.getVMHeapSize(); + if (space1Size != space2Size || space1Size > vmHeapSize) { + LOGE(LOG_TAG, "Unexpected space size, vmHeapSize: %u, actual_space1: %u, actual_space2: %u", + vmHeapSize, space1Size, space2Size); break; } jbyteArray leakedArr = env->NewByteArray(1);