1*795d594fSAndroid Build Coastguard Worker#!/usr/bin/env python 2*795d594fSAndroid Build Coastguard Worker# 3*795d594fSAndroid Build Coastguard Worker# Copyright (C) 2017 The Android Open Source Project 4*795d594fSAndroid Build Coastguard Worker# 5*795d594fSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*795d594fSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*795d594fSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*795d594fSAndroid Build Coastguard Worker# 9*795d594fSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*795d594fSAndroid Build Coastguard Worker# 11*795d594fSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*795d594fSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*795d594fSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*795d594fSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*795d594fSAndroid Build Coastguard Worker# limitations under the License. 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker"""Outputs quantitative information about Address Sanitizer traces.""" 18*795d594fSAndroid Build Coastguard Worker 19*795d594fSAndroid Build Coastguard Workerfrom __future__ import absolute_import 20*795d594fSAndroid Build Coastguard Workerfrom __future__ import division 21*795d594fSAndroid Build Coastguard Workerfrom __future__ import print_function 22*795d594fSAndroid Build Coastguard Worker 23*795d594fSAndroid Build Coastguard Workerfrom collections import Counter 24*795d594fSAndroid Build Coastguard Workerfrom datetime import datetime 25*795d594fSAndroid Build Coastguard Workerimport argparse 26*795d594fSAndroid Build Coastguard Workerimport bisect 27*795d594fSAndroid Build Coastguard Workerimport os 28*795d594fSAndroid Build Coastguard Workerimport re 29*795d594fSAndroid Build Coastguard Worker 30*795d594fSAndroid Build Coastguard Worker 31*795d594fSAndroid Build Coastguard Workerdef find_match(list_substrings, big_string): 32*795d594fSAndroid Build Coastguard Worker """Returns the category a trace belongs to by searching substrings.""" 33*795d594fSAndroid Build Coastguard Worker for ind, substr in enumerate(list_substrings): 34*795d594fSAndroid Build Coastguard Worker if big_string.find(substr) != -1: 35*795d594fSAndroid Build Coastguard Worker return ind 36*795d594fSAndroid Build Coastguard Worker return list_substrings.index("Uncategorized") 37*795d594fSAndroid Build Coastguard Worker 38*795d594fSAndroid Build Coastguard Worker 39*795d594fSAndroid Build Coastguard Workerdef absolute_to_relative(data_lists, symbol_traces): 40*795d594fSAndroid Build Coastguard Worker """Address changed to Dex File offset and shifting time to 0 min in ms.""" 41*795d594fSAndroid Build Coastguard Worker 42*795d594fSAndroid Build Coastguard Worker offsets = data_lists["offsets"] 43*795d594fSAndroid Build Coastguard Worker time_offsets = data_lists["times"] 44*795d594fSAndroid Build Coastguard Worker 45*795d594fSAndroid Build Coastguard Worker # Format of time provided by logcat 46*795d594fSAndroid Build Coastguard Worker time_format_str = "%H:%M:%S.%f" 47*795d594fSAndroid Build Coastguard Worker first_access_time = datetime.strptime(data_lists["plot_list"][0][0], 48*795d594fSAndroid Build Coastguard Worker time_format_str) 49*795d594fSAndroid Build Coastguard Worker for ind, elem in enumerate(data_lists["plot_list"]): 50*795d594fSAndroid Build Coastguard Worker elem_date_time = datetime.strptime(elem[0], time_format_str) 51*795d594fSAndroid Build Coastguard Worker # Shift time values so that first access is at time 0 milliseconds 52*795d594fSAndroid Build Coastguard Worker elem[0] = int((elem_date_time - first_access_time).total_seconds() * 53*795d594fSAndroid Build Coastguard Worker 1000) 54*795d594fSAndroid Build Coastguard Worker address_access = int(elem[1], 16) 55*795d594fSAndroid Build Coastguard Worker # For each poisoned address, find highest Dex File starting address less 56*795d594fSAndroid Build Coastguard Worker # than address_access 57*795d594fSAndroid Build Coastguard Worker dex_start_list, dex_size_list = zip(*data_lists["dex_ends_list"]) 58*795d594fSAndroid Build Coastguard Worker dex_file_ind = bisect.bisect(dex_start_list, address_access) - 1 59*795d594fSAndroid Build Coastguard Worker dex_offset = address_access - dex_start_list[dex_file_ind] 60*795d594fSAndroid Build Coastguard Worker # Assumes that offsets is already sorted and constrains offset to be 61*795d594fSAndroid Build Coastguard Worker # within range of the dex_file 62*795d594fSAndroid Build Coastguard Worker max_offset = min(offsets[1], dex_size_list[dex_file_ind]) 63*795d594fSAndroid Build Coastguard Worker # Meant to nullify data that does not meet offset criteria if specified 64*795d594fSAndroid Build Coastguard Worker if (dex_offset >= offsets[0] and dex_offset < max_offset and 65*795d594fSAndroid Build Coastguard Worker elem[0] >= time_offsets[0] and elem[0] < time_offsets[1]): 66*795d594fSAndroid Build Coastguard Worker 67*795d594fSAndroid Build Coastguard Worker elem.insert(1, dex_offset) 68*795d594fSAndroid Build Coastguard Worker # Category that a data point belongs to 69*795d594fSAndroid Build Coastguard Worker elem.insert(2, data_lists["cat_list"][ind]) 70*795d594fSAndroid Build Coastguard Worker else: 71*795d594fSAndroid Build Coastguard Worker elem[:] = 4 * [None] 72*795d594fSAndroid Build Coastguard Worker symbol_traces[ind] = None 73*795d594fSAndroid Build Coastguard Worker data_lists["cat_list"][ind] = None 74*795d594fSAndroid Build Coastguard Worker 75*795d594fSAndroid Build Coastguard Worker 76*795d594fSAndroid Build Coastguard Workerdef print_category_info(cat_split, outname, out_dir_name, title): 77*795d594fSAndroid Build Coastguard Worker """Prints information of category and puts related traces in a files.""" 78*795d594fSAndroid Build Coastguard Worker trace_counts_dict = Counter(cat_split) 79*795d594fSAndroid Build Coastguard Worker trace_counts_list_ordered = trace_counts_dict.most_common() 80*795d594fSAndroid Build Coastguard Worker print(53 * "-") 81*795d594fSAndroid Build Coastguard Worker print(title) 82*795d594fSAndroid Build Coastguard Worker print("\tNumber of distinct traces: " + 83*795d594fSAndroid Build Coastguard Worker str(len(trace_counts_list_ordered))) 84*795d594fSAndroid Build Coastguard Worker print("\tSum of trace counts: " + 85*795d594fSAndroid Build Coastguard Worker str(sum([trace[1] for trace in trace_counts_list_ordered]))) 86*795d594fSAndroid Build Coastguard Worker print("\n\tCount: How many traces appeared with count\n\t", end="") 87*795d594fSAndroid Build Coastguard Worker print(Counter([trace[1] for trace in trace_counts_list_ordered])) 88*795d594fSAndroid Build Coastguard Worker with open(os.path.join(out_dir_name, outname), "w") as output_file: 89*795d594fSAndroid Build Coastguard Worker for trace in trace_counts_list_ordered: 90*795d594fSAndroid Build Coastguard Worker output_file.write("\n\nNumber of times appeared: " + 91*795d594fSAndroid Build Coastguard Worker str(trace[1]) + 92*795d594fSAndroid Build Coastguard Worker "\n") 93*795d594fSAndroid Build Coastguard Worker output_file.write(trace[0].strip()) 94*795d594fSAndroid Build Coastguard Worker 95*795d594fSAndroid Build Coastguard Worker 96*795d594fSAndroid Build Coastguard Workerdef print_categories(categories, symbol_file_split, out_dir_name): 97*795d594fSAndroid Build Coastguard Worker """Prints details of all categories.""" 98*795d594fSAndroid Build Coastguard Worker symbol_file_split = [trace for trace in symbol_file_split 99*795d594fSAndroid Build Coastguard Worker if trace is not None] 100*795d594fSAndroid Build Coastguard Worker # Info of traces containing a call to current category 101*795d594fSAndroid Build Coastguard Worker for cat_num, cat_name in enumerate(categories[1:]): 102*795d594fSAndroid Build Coastguard Worker print("\nCategory #%d" % (cat_num + 1)) 103*795d594fSAndroid Build Coastguard Worker cat_split = [trace for trace in symbol_file_split 104*795d594fSAndroid Build Coastguard Worker if cat_name in trace] 105*795d594fSAndroid Build Coastguard Worker cat_file_name = cat_name.lower() + "cat_output" 106*795d594fSAndroid Build Coastguard Worker print_category_info(cat_split, cat_file_name, out_dir_name, 107*795d594fSAndroid Build Coastguard Worker "Traces containing: " + cat_name) 108*795d594fSAndroid Build Coastguard Worker noncat_split = [trace for trace in symbol_file_split 109*795d594fSAndroid Build Coastguard Worker if cat_name not in trace] 110*795d594fSAndroid Build Coastguard Worker print_category_info(noncat_split, "non" + cat_file_name, 111*795d594fSAndroid Build Coastguard Worker out_dir_name, 112*795d594fSAndroid Build Coastguard Worker "Traces not containing: " + 113*795d594fSAndroid Build Coastguard Worker cat_name) 114*795d594fSAndroid Build Coastguard Worker 115*795d594fSAndroid Build Coastguard Worker # All traces (including uncategorized) together 116*795d594fSAndroid Build Coastguard Worker print_category_info(symbol_file_split, "allcat_output", 117*795d594fSAndroid Build Coastguard Worker out_dir_name, 118*795d594fSAndroid Build Coastguard Worker "All traces together:") 119*795d594fSAndroid Build Coastguard Worker # Traces containing none of keywords 120*795d594fSAndroid Build Coastguard Worker # Only used if categories are passed in 121*795d594fSAndroid Build Coastguard Worker if len(categories) > 1: 122*795d594fSAndroid Build Coastguard Worker noncat_split = [trace for trace in symbol_file_split if 123*795d594fSAndroid Build Coastguard Worker all(cat_name not in trace 124*795d594fSAndroid Build Coastguard Worker for cat_name in categories)] 125*795d594fSAndroid Build Coastguard Worker print_category_info(noncat_split, "noncat_output", 126*795d594fSAndroid Build Coastguard Worker out_dir_name, 127*795d594fSAndroid Build Coastguard Worker "Uncategorized calls") 128*795d594fSAndroid Build Coastguard Worker 129*795d594fSAndroid Build Coastguard Worker 130*795d594fSAndroid Build Coastguard Workerdef is_directory(path_name): 131*795d594fSAndroid Build Coastguard Worker """Checks if a path is an actual directory.""" 132*795d594fSAndroid Build Coastguard Worker if not os.path.isdir(path_name): 133*795d594fSAndroid Build Coastguard Worker dir_error = "%s is not a directory" % (path_name) 134*795d594fSAndroid Build Coastguard Worker raise argparse.ArgumentTypeError(dir_error) 135*795d594fSAndroid Build Coastguard Worker return path_name 136*795d594fSAndroid Build Coastguard Worker 137*795d594fSAndroid Build Coastguard Worker 138*795d594fSAndroid Build Coastguard Workerdef parse_args(argv): 139*795d594fSAndroid Build Coastguard Worker """Parses arguments passed in.""" 140*795d594fSAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 141*795d594fSAndroid Build Coastguard Worker parser.add_argument("-d", action="store", 142*795d594fSAndroid Build Coastguard Worker default="", dest="out_dir_name", type=is_directory, 143*795d594fSAndroid Build Coastguard Worker help="Output Directory") 144*795d594fSAndroid Build Coastguard Worker parser.add_argument("--dex-file", action="store", 145*795d594fSAndroid Build Coastguard Worker default=None, dest="dex_file", 146*795d594fSAndroid Build Coastguard Worker type=argparse.FileType("r"), 147*795d594fSAndroid Build Coastguard Worker help="Baksmali Dex File Dump") 148*795d594fSAndroid Build Coastguard Worker parser.add_argument("--offsets", action="store", nargs=2, 149*795d594fSAndroid Build Coastguard Worker default=[float(0), float("inf")], 150*795d594fSAndroid Build Coastguard Worker dest="offsets", 151*795d594fSAndroid Build Coastguard Worker metavar="OFFSET", 152*795d594fSAndroid Build Coastguard Worker type=float, 153*795d594fSAndroid Build Coastguard Worker help="Filters out accesses not between provided" 154*795d594fSAndroid Build Coastguard Worker " offsets if provided. Can provide 'inf'" 155*795d594fSAndroid Build Coastguard Worker " for infinity") 156*795d594fSAndroid Build Coastguard Worker parser.add_argument("--times", action="store", nargs=2, 157*795d594fSAndroid Build Coastguard Worker default=[float(0), float("inf")], 158*795d594fSAndroid Build Coastguard Worker dest="times", 159*795d594fSAndroid Build Coastguard Worker metavar="TIME", 160*795d594fSAndroid Build Coastguard Worker type=float, 161*795d594fSAndroid Build Coastguard Worker help="Filters out accesses not between provided" 162*795d594fSAndroid Build Coastguard Worker " time offsets if provided. Can provide 'inf'" 163*795d594fSAndroid Build Coastguard Worker " for infinity") 164*795d594fSAndroid Build Coastguard Worker parser.add_argument("sanitizer_trace", action="store", 165*795d594fSAndroid Build Coastguard Worker type=argparse.FileType("r"), 166*795d594fSAndroid Build Coastguard Worker help="File containing sanitizer traces filtered by " 167*795d594fSAndroid Build Coastguard Worker "prune_sanitizer_output.py") 168*795d594fSAndroid Build Coastguard Worker parser.add_argument("symbol_trace", action="store", 169*795d594fSAndroid Build Coastguard Worker type=argparse.FileType("r"), 170*795d594fSAndroid Build Coastguard Worker help="File containing symbolized traces that match " 171*795d594fSAndroid Build Coastguard Worker "sanitizer_trace") 172*795d594fSAndroid Build Coastguard Worker parser.add_argument("dex_starts", action="store", 173*795d594fSAndroid Build Coastguard Worker type=argparse.FileType("r"), 174*795d594fSAndroid Build Coastguard Worker help="File containing starting addresses of Dex Files") 175*795d594fSAndroid Build Coastguard Worker parser.add_argument("categories", action="store", nargs="*", 176*795d594fSAndroid Build Coastguard Worker help="Keywords expected to show in large amounts of" 177*795d594fSAndroid Build Coastguard Worker " symbolized traces") 178*795d594fSAndroid Build Coastguard Worker 179*795d594fSAndroid Build Coastguard Worker return parser.parse_args(argv) 180*795d594fSAndroid Build Coastguard Worker 181*795d594fSAndroid Build Coastguard Worker 182*795d594fSAndroid Build Coastguard Workerdef get_dex_offset_data(line, dex_file_item): 183*795d594fSAndroid Build Coastguard Worker """ Returns a tuple of dex file offset, item name, and data of a line.""" 184*795d594fSAndroid Build Coastguard Worker return (int(line[:line.find(":")], 16), 185*795d594fSAndroid Build Coastguard Worker (dex_file_item, 186*795d594fSAndroid Build Coastguard Worker line.split("|")[1].strip()) 187*795d594fSAndroid Build Coastguard Worker ) 188*795d594fSAndroid Build Coastguard Worker 189*795d594fSAndroid Build Coastguard Worker 190*795d594fSAndroid Build Coastguard Workerdef read_data(parsed_argv): 191*795d594fSAndroid Build Coastguard Worker """Reads data from filepath arguments and parses them into lists.""" 192*795d594fSAndroid Build Coastguard Worker # Using a dictionary to establish relation between lists added 193*795d594fSAndroid Build Coastguard Worker data_lists = {} 194*795d594fSAndroid Build Coastguard Worker categories = parsed_argv.categories 195*795d594fSAndroid Build Coastguard Worker # Makes sure each trace maps to some category 196*795d594fSAndroid Build Coastguard Worker categories.insert(0, "Uncategorized") 197*795d594fSAndroid Build Coastguard Worker 198*795d594fSAndroid Build Coastguard Worker data_lists["offsets"] = parsed_argv.offsets 199*795d594fSAndroid Build Coastguard Worker data_lists["offsets"].sort() 200*795d594fSAndroid Build Coastguard Worker 201*795d594fSAndroid Build Coastguard Worker data_lists["times"] = parsed_argv.times 202*795d594fSAndroid Build Coastguard Worker data_lists["times"].sort() 203*795d594fSAndroid Build Coastguard Worker 204*795d594fSAndroid Build Coastguard Worker logcat_file_data = parsed_argv.sanitizer_trace.readlines() 205*795d594fSAndroid Build Coastguard Worker parsed_argv.sanitizer_trace.close() 206*795d594fSAndroid Build Coastguard Worker 207*795d594fSAndroid Build Coastguard Worker symbol_file_split = parsed_argv.symbol_trace.read().split("Stack Trace") 208*795d594fSAndroid Build Coastguard Worker # Removes text before first trace 209*795d594fSAndroid Build Coastguard Worker symbol_file_split = symbol_file_split[1:] 210*795d594fSAndroid Build Coastguard Worker parsed_argv.symbol_trace.close() 211*795d594fSAndroid Build Coastguard Worker 212*795d594fSAndroid Build Coastguard Worker dex_start_file_data = parsed_argv.dex_starts.readlines() 213*795d594fSAndroid Build Coastguard Worker parsed_argv.dex_starts.close() 214*795d594fSAndroid Build Coastguard Worker 215*795d594fSAndroid Build Coastguard Worker if parsed_argv.dex_file is not None: 216*795d594fSAndroid Build Coastguard Worker dex_file_data = parsed_argv.dex_file.read() 217*795d594fSAndroid Build Coastguard Worker parsed_argv.dex_file.close() 218*795d594fSAndroid Build Coastguard Worker # Splits baksmali dump by each item 219*795d594fSAndroid Build Coastguard Worker item_split = [s.splitlines() for s in re.split(r"\|\[[0-9]+\] ", 220*795d594fSAndroid Build Coastguard Worker dex_file_data)] 221*795d594fSAndroid Build Coastguard Worker # Splits each item by line and creates a list of offsets and a 222*795d594fSAndroid Build Coastguard Worker # corresponding list of the data associated with that line 223*795d594fSAndroid Build Coastguard Worker offset_list, offset_data = zip(*[get_dex_offset_data(line, item[0]) 224*795d594fSAndroid Build Coastguard Worker for item in item_split 225*795d594fSAndroid Build Coastguard Worker for line in item[1:] 226*795d594fSAndroid Build Coastguard Worker if re.search("[0-9a-f]{6}:", line) 227*795d594fSAndroid Build Coastguard Worker is not None and 228*795d594fSAndroid Build Coastguard Worker line.find("|") != -1]) 229*795d594fSAndroid Build Coastguard Worker data_lists["offset_list"] = offset_list 230*795d594fSAndroid Build Coastguard Worker data_lists["offset_data"] = offset_data 231*795d594fSAndroid Build Coastguard Worker else: 232*795d594fSAndroid Build Coastguard Worker dex_file_data = None 233*795d594fSAndroid Build Coastguard Worker 234*795d594fSAndroid Build Coastguard Worker # Each element is a tuple of time and address accessed 235*795d594fSAndroid Build Coastguard Worker data_lists["plot_list"] = [[elem[1] for elem in enumerate(line.split()) 236*795d594fSAndroid Build Coastguard Worker if elem[0] in (1, 11) 237*795d594fSAndroid Build Coastguard Worker ] 238*795d594fSAndroid Build Coastguard Worker for line in logcat_file_data 239*795d594fSAndroid Build Coastguard Worker if "use-after-poison" in line or 240*795d594fSAndroid Build Coastguard Worker "unknown-crash" in line 241*795d594fSAndroid Build Coastguard Worker ] 242*795d594fSAndroid Build Coastguard Worker # Contains a mapping between traces and the category they belong to 243*795d594fSAndroid Build Coastguard Worker # based on arguments 244*795d594fSAndroid Build Coastguard Worker data_lists["cat_list"] = [categories[find_match(categories, trace)] 245*795d594fSAndroid Build Coastguard Worker for trace in symbol_file_split] 246*795d594fSAndroid Build Coastguard Worker 247*795d594fSAndroid Build Coastguard Worker # Contains a list of starting address of all dex files to calculate dex 248*795d594fSAndroid Build Coastguard Worker # offsets 249*795d594fSAndroid Build Coastguard Worker data_lists["dex_ends_list"] = [(int(line.split()[9], 16), 250*795d594fSAndroid Build Coastguard Worker int(line.split()[12]) 251*795d594fSAndroid Build Coastguard Worker ) 252*795d594fSAndroid Build Coastguard Worker for line in dex_start_file_data 253*795d594fSAndroid Build Coastguard Worker if "RegisterDexFile" in line 254*795d594fSAndroid Build Coastguard Worker ] 255*795d594fSAndroid Build Coastguard Worker # Dex File Starting addresses must be sorted because bisect requires sorted 256*795d594fSAndroid Build Coastguard Worker # lists. 257*795d594fSAndroid Build Coastguard Worker data_lists["dex_ends_list"].sort() 258*795d594fSAndroid Build Coastguard Worker 259*795d594fSAndroid Build Coastguard Worker return data_lists, categories, symbol_file_split 260*795d594fSAndroid Build Coastguard Worker 261*795d594fSAndroid Build Coastguard Worker 262*795d594fSAndroid Build Coastguard Workerdef main(): 263*795d594fSAndroid Build Coastguard Worker """Takes in trace information and outputs details about them.""" 264*795d594fSAndroid Build Coastguard Worker parsed_argv = parse_args(None) 265*795d594fSAndroid Build Coastguard Worker data_lists, categories, symbol_file_split = read_data(parsed_argv) 266*795d594fSAndroid Build Coastguard Worker 267*795d594fSAndroid Build Coastguard Worker # Formats plot_list such that each element is a data point 268*795d594fSAndroid Build Coastguard Worker absolute_to_relative(data_lists, symbol_file_split) 269*795d594fSAndroid Build Coastguard Worker for file_ext, cat_name in enumerate(categories): 270*795d594fSAndroid Build Coastguard Worker out_file_name = os.path.join(parsed_argv.out_dir_name, "time_output_" + 271*795d594fSAndroid Build Coastguard Worker str(file_ext) + 272*795d594fSAndroid Build Coastguard Worker ".dat") 273*795d594fSAndroid Build Coastguard Worker with open(out_file_name, "w") as output_file: 274*795d594fSAndroid Build Coastguard Worker output_file.write("# Category: " + cat_name + "\n") 275*795d594fSAndroid Build Coastguard Worker output_file.write("# Time, Dex File Offset_10, Dex File Offset_16," 276*795d594fSAndroid Build Coastguard Worker " Address, Item Accessed, Item Member Accessed" 277*795d594fSAndroid Build Coastguard Worker " Unaligned\n") 278*795d594fSAndroid Build Coastguard Worker for time, dex_offset, category, address in data_lists["plot_list"]: 279*795d594fSAndroid Build Coastguard Worker if category == cat_name: 280*795d594fSAndroid Build Coastguard Worker output_file.write( 281*795d594fSAndroid Build Coastguard Worker str(time) + 282*795d594fSAndroid Build Coastguard Worker " " + 283*795d594fSAndroid Build Coastguard Worker str(dex_offset) + 284*795d594fSAndroid Build Coastguard Worker " #" + 285*795d594fSAndroid Build Coastguard Worker hex(dex_offset) + 286*795d594fSAndroid Build Coastguard Worker " " + 287*795d594fSAndroid Build Coastguard Worker str(address)) 288*795d594fSAndroid Build Coastguard Worker if "offset_list" in data_lists: 289*795d594fSAndroid Build Coastguard Worker dex_offset_index = bisect.bisect( 290*795d594fSAndroid Build Coastguard Worker data_lists["offset_list"], 291*795d594fSAndroid Build Coastguard Worker dex_offset) - 1 292*795d594fSAndroid Build Coastguard Worker aligned_dex_offset = (data_lists["offset_list"] 293*795d594fSAndroid Build Coastguard Worker [dex_offset_index]) 294*795d594fSAndroid Build Coastguard Worker dex_offset_data = (data_lists["offset_data"] 295*795d594fSAndroid Build Coastguard Worker [dex_offset_index]) 296*795d594fSAndroid Build Coastguard Worker output_file.write( 297*795d594fSAndroid Build Coastguard Worker " " + 298*795d594fSAndroid Build Coastguard Worker "|".join(dex_offset_data) + 299*795d594fSAndroid Build Coastguard Worker " " + 300*795d594fSAndroid Build Coastguard Worker str(aligned_dex_offset != dex_offset)) 301*795d594fSAndroid Build Coastguard Worker output_file.write("\n") 302*795d594fSAndroid Build Coastguard Worker print_categories(categories, symbol_file_split, parsed_argv.out_dir_name) 303*795d594fSAndroid Build Coastguard Worker 304*795d594fSAndroid Build Coastguard Worker 305*795d594fSAndroid Build Coastguard Workerif __name__ == "__main__": 306*795d594fSAndroid Build Coastguard Worker main() 307