diff --git a/scripts/native_heapdump_viewer.py b/scripts/native_heapdump_viewer.py index 32b99db3c..b74b1b52c 100755 --- a/scripts/native_heapdump_viewer.py +++ b/scripts/native_heapdump_viewer.py @@ -117,11 +117,52 @@ def GetVersion(native_heap): return m.group('version') return None +def NumFieldValid(native_heap): + """Determine if the num field is valid. + + Malloc debug for N incorrectly set the num field to the number of + backtraces instead of the number of allocations with the same size and + backtrace. Read the file and if at least three lines all have the field + set to the number of backtraces values, then consider this generated by + the buggy malloc debug and indicate the num field is not valid. + + Returns: + True if the num field is valid. + False if the num field is not valid and should be ignored. + """ + + re_backtrace = re.compile("Backtrace\s+size:\s+(?P\d+)") + + re_line = re.compile("z\s+(?P\d+)\s+sz\s+(?P\d+)\s+num\s+(?P\d+)") + matched = 0 + backtrace_size = 0 + for line in open(native_heap, "r"): + if backtrace_size == 0: + m = re_backtrace.match(line) + if m: + backtrace_size = int(m.group('backtrace_size')) + parts = line.split() + if len(parts) > 7 and parts[0] == "z" and parts[2] == "sz": + m = re_line.match(line) + if m: + num_allocations = int(m.group('num_allocations')) + if num_allocations == backtrace_size: + # At least three lines must match this pattern before + # considering this the old buggy version of malloc debug. + matched += 1 + if matched == 3: + return False + else: + return True + return matched == 0 + version = GetVersion(native_heap) if not version or version == "v1.0": # Version v1.0 was produced by a buggy version of malloc debug where the # num field was set incorrectly. - num_field_valid = False + # Unfortunately, Android P produced a v1.0 version that does set the + # num field. Do one more check to see if this is the broken version. + num_field_valid = NumFieldValid(native_heap) else: num_field_valid = True