1*8975f5c5SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*8975f5c5SAndroid Build Coastguard Worker# Copyright 2018 The Chromium Authors 3*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 4*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file. 5*8975f5c5SAndroid Build Coastguard Worker"""Wraps ml.exe or ml64.exe and postprocesses the output to be deterministic. 6*8975f5c5SAndroid Build Coastguard WorkerSets timestamp in .obj file to 0, hence incompatible with link.exe /incremental. 7*8975f5c5SAndroid Build Coastguard Worker 8*8975f5c5SAndroid Build Coastguard WorkerUse by prefixing the ml(64).exe invocation with this script: 9*8975f5c5SAndroid Build Coastguard Worker python ml.py ml.exe [args...]""" 10*8975f5c5SAndroid Build Coastguard Worker 11*8975f5c5SAndroid Build Coastguard Workerimport array 12*8975f5c5SAndroid Build Coastguard Workerimport collections 13*8975f5c5SAndroid Build Coastguard Workerimport struct 14*8975f5c5SAndroid Build Coastguard Workerimport subprocess 15*8975f5c5SAndroid Build Coastguard Workerimport sys 16*8975f5c5SAndroid Build Coastguard Worker 17*8975f5c5SAndroid Build Coastguard Worker 18*8975f5c5SAndroid Build Coastguard Workerclass Struct(object): 19*8975f5c5SAndroid Build Coastguard Worker """A thin wrapper around the struct module that returns a namedtuple""" 20*8975f5c5SAndroid Build Coastguard Worker 21*8975f5c5SAndroid Build Coastguard Worker def __init__(self, name, *args): 22*8975f5c5SAndroid Build Coastguard Worker """Pass the name of the return type, and then an interleaved list of 23*8975f5c5SAndroid Build Coastguard Worker format strings as used by the struct module and of field names.""" 24*8975f5c5SAndroid Build Coastguard Worker self.fmt = '<' + ''.join(args[0::2]) 25*8975f5c5SAndroid Build Coastguard Worker self.type = collections.namedtuple(name, args[1::2]) 26*8975f5c5SAndroid Build Coastguard Worker 27*8975f5c5SAndroid Build Coastguard Worker def pack_into(self, buffer, offset, data): 28*8975f5c5SAndroid Build Coastguard Worker return struct.pack_into(self.fmt, buffer, offset, *data) 29*8975f5c5SAndroid Build Coastguard Worker 30*8975f5c5SAndroid Build Coastguard Worker def unpack_from(self, buffer, offset=0): 31*8975f5c5SAndroid Build Coastguard Worker return self.type(*struct.unpack_from(self.fmt, buffer, offset)) 32*8975f5c5SAndroid Build Coastguard Worker 33*8975f5c5SAndroid Build Coastguard Worker def size(self): 34*8975f5c5SAndroid Build Coastguard Worker return struct.calcsize(self.fmt) 35*8975f5c5SAndroid Build Coastguard Worker 36*8975f5c5SAndroid Build Coastguard Worker 37*8975f5c5SAndroid Build Coastguard Workerdef Subtract(nt, **kwargs): 38*8975f5c5SAndroid Build Coastguard Worker """Subtract(nt, f=2) returns a new namedtuple with 2 subtracted from nt.f""" 39*8975f5c5SAndroid Build Coastguard Worker return nt._replace(**{k: getattr(nt, k) - v for k, v in kwargs.items()}) 40*8975f5c5SAndroid Build Coastguard Worker 41*8975f5c5SAndroid Build Coastguard Worker 42*8975f5c5SAndroid Build Coastguard Workerdef MakeDeterministic(objdata): 43*8975f5c5SAndroid Build Coastguard Worker # Takes data produced by ml(64).exe (without any special flags) and 44*8975f5c5SAndroid Build Coastguard Worker # 1. Sets the timestamp to 0 45*8975f5c5SAndroid Build Coastguard Worker # 2. Strips the .debug$S section (which contains an unwanted absolute path) 46*8975f5c5SAndroid Build Coastguard Worker 47*8975f5c5SAndroid Build Coastguard Worker # This makes several assumptions about ml's output: 48*8975f5c5SAndroid Build Coastguard Worker # - Section data is in the same order as the corresponding section headers: 49*8975f5c5SAndroid Build Coastguard Worker # section headers preceding the .debug$S section header have their data 50*8975f5c5SAndroid Build Coastguard Worker # preceding the .debug$S section data; likewise for section headers 51*8975f5c5SAndroid Build Coastguard Worker # following the .debug$S section. 52*8975f5c5SAndroid Build Coastguard Worker # - The .debug$S section contains only the absolute path to the obj file and 53*8975f5c5SAndroid Build Coastguard Worker # nothing else, in particular there's only a single entry in the symbol 54*8975f5c5SAndroid Build Coastguard Worker # table referring to the .debug$S section. 55*8975f5c5SAndroid Build Coastguard Worker # - There are no COFF line number entries. 56*8975f5c5SAndroid Build Coastguard Worker # - There's no IMAGE_SYM_CLASS_CLR_TOKEN symbol. 57*8975f5c5SAndroid Build Coastguard Worker # These seem to hold in practice; if they stop holding this script needs to 58*8975f5c5SAndroid Build Coastguard Worker # become smarter. 59*8975f5c5SAndroid Build Coastguard Worker 60*8975f5c5SAndroid Build Coastguard Worker objdata = array.array('b', objdata) # Writable, e.g. via struct.pack_into. 61*8975f5c5SAndroid Build Coastguard Worker 62*8975f5c5SAndroid Build Coastguard Worker # Read coff header. 63*8975f5c5SAndroid Build Coastguard Worker COFFHEADER = Struct('COFFHEADER', 'H', 'Machine', 'H', 'NumberOfSections', 64*8975f5c5SAndroid Build Coastguard Worker 'I', 'TimeDateStamp', 'I', 'PointerToSymbolTable', 'I', 65*8975f5c5SAndroid Build Coastguard Worker 'NumberOfSymbols', 'H', 'SizeOfOptionalHeader', 'H', 66*8975f5c5SAndroid Build Coastguard Worker 'Characteristics') 67*8975f5c5SAndroid Build Coastguard Worker coff_header = COFFHEADER.unpack_from(objdata) 68*8975f5c5SAndroid Build Coastguard Worker assert coff_header.SizeOfOptionalHeader == 0 # Only set for binaries. 69*8975f5c5SAndroid Build Coastguard Worker 70*8975f5c5SAndroid Build Coastguard Worker # Read section headers following coff header. 71*8975f5c5SAndroid Build Coastguard Worker SECTIONHEADER = Struct('SECTIONHEADER', '8s', 'Name', 'I', 'VirtualSize', 'I', 72*8975f5c5SAndroid Build Coastguard Worker 'VirtualAddress', 'I', 'SizeOfRawData', 'I', 73*8975f5c5SAndroid Build Coastguard Worker 'PointerToRawData', 'I', 'PointerToRelocations', 'I', 74*8975f5c5SAndroid Build Coastguard Worker 'PointerToLineNumbers', 'H', 'NumberOfRelocations', 75*8975f5c5SAndroid Build Coastguard Worker 'H', 'NumberOfLineNumbers', 'I', 'Characteristics') 76*8975f5c5SAndroid Build Coastguard Worker section_headers = [] 77*8975f5c5SAndroid Build Coastguard Worker debug_section_index = -1 78*8975f5c5SAndroid Build Coastguard Worker for i in range(0, coff_header.NumberOfSections): 79*8975f5c5SAndroid Build Coastguard Worker section_header = SECTIONHEADER.unpack_from(objdata, 80*8975f5c5SAndroid Build Coastguard Worker offset=COFFHEADER.size() + 81*8975f5c5SAndroid Build Coastguard Worker i * SECTIONHEADER.size()) 82*8975f5c5SAndroid Build Coastguard Worker assert not section_header[0].startswith(b'/') # Support short names only. 83*8975f5c5SAndroid Build Coastguard Worker section_headers.append(section_header) 84*8975f5c5SAndroid Build Coastguard Worker 85*8975f5c5SAndroid Build Coastguard Worker if section_header.Name == b'.debug$S': 86*8975f5c5SAndroid Build Coastguard Worker assert debug_section_index == -1 87*8975f5c5SAndroid Build Coastguard Worker debug_section_index = i 88*8975f5c5SAndroid Build Coastguard Worker assert debug_section_index != -1 89*8975f5c5SAndroid Build Coastguard Worker 90*8975f5c5SAndroid Build Coastguard Worker data_start = COFFHEADER.size() + len(section_headers) * SECTIONHEADER.size() 91*8975f5c5SAndroid Build Coastguard Worker 92*8975f5c5SAndroid Build Coastguard Worker # Verify the .debug$S section looks like we expect. 93*8975f5c5SAndroid Build Coastguard Worker assert section_headers[debug_section_index].Name == b'.debug$S' 94*8975f5c5SAndroid Build Coastguard Worker assert section_headers[debug_section_index].VirtualSize == 0 95*8975f5c5SAndroid Build Coastguard Worker assert section_headers[debug_section_index].VirtualAddress == 0 96*8975f5c5SAndroid Build Coastguard Worker debug_size = section_headers[debug_section_index].SizeOfRawData 97*8975f5c5SAndroid Build Coastguard Worker debug_offset = section_headers[debug_section_index].PointerToRawData 98*8975f5c5SAndroid Build Coastguard Worker assert section_headers[debug_section_index].PointerToRelocations == 0 99*8975f5c5SAndroid Build Coastguard Worker assert section_headers[debug_section_index].PointerToLineNumbers == 0 100*8975f5c5SAndroid Build Coastguard Worker assert section_headers[debug_section_index].NumberOfRelocations == 0 101*8975f5c5SAndroid Build Coastguard Worker assert section_headers[debug_section_index].NumberOfLineNumbers == 0 102*8975f5c5SAndroid Build Coastguard Worker 103*8975f5c5SAndroid Build Coastguard Worker # Make sure sections in front of .debug$S have their data preceding it. 104*8975f5c5SAndroid Build Coastguard Worker for header in section_headers[:debug_section_index]: 105*8975f5c5SAndroid Build Coastguard Worker assert header.PointerToRawData < debug_offset 106*8975f5c5SAndroid Build Coastguard Worker assert header.PointerToRelocations < debug_offset 107*8975f5c5SAndroid Build Coastguard Worker assert header.PointerToLineNumbers < debug_offset 108*8975f5c5SAndroid Build Coastguard Worker 109*8975f5c5SAndroid Build Coastguard Worker # Make sure sections after of .debug$S have their data following it. 110*8975f5c5SAndroid Build Coastguard Worker for header in section_headers[debug_section_index + 1:]: 111*8975f5c5SAndroid Build Coastguard Worker # Make sure the .debug$S data is at the very end of section data: 112*8975f5c5SAndroid Build Coastguard Worker assert header.PointerToRawData > debug_offset 113*8975f5c5SAndroid Build Coastguard Worker assert header.PointerToRelocations == 0 114*8975f5c5SAndroid Build Coastguard Worker assert header.PointerToLineNumbers == 0 115*8975f5c5SAndroid Build Coastguard Worker 116*8975f5c5SAndroid Build Coastguard Worker # Make sure the first non-empty section's data starts right after the section 117*8975f5c5SAndroid Build Coastguard Worker # headers. 118*8975f5c5SAndroid Build Coastguard Worker for section_header in section_headers: 119*8975f5c5SAndroid Build Coastguard Worker if section_header.PointerToRawData == 0: 120*8975f5c5SAndroid Build Coastguard Worker assert section_header.PointerToRelocations == 0 121*8975f5c5SAndroid Build Coastguard Worker assert section_header.PointerToLineNumbers == 0 122*8975f5c5SAndroid Build Coastguard Worker continue 123*8975f5c5SAndroid Build Coastguard Worker assert section_header.PointerToRawData == data_start 124*8975f5c5SAndroid Build Coastguard Worker break 125*8975f5c5SAndroid Build Coastguard Worker 126*8975f5c5SAndroid Build Coastguard Worker # Make sure the symbol table (and hence, string table) appear after the last 127*8975f5c5SAndroid Build Coastguard Worker # section: 128*8975f5c5SAndroid Build Coastguard Worker assert ( 129*8975f5c5SAndroid Build Coastguard Worker coff_header.PointerToSymbolTable >= 130*8975f5c5SAndroid Build Coastguard Worker section_headers[-1].PointerToRawData + section_headers[-1].SizeOfRawData) 131*8975f5c5SAndroid Build Coastguard Worker 132*8975f5c5SAndroid Build Coastguard Worker # The symbol table contains a symbol for the no-longer-present .debug$S 133*8975f5c5SAndroid Build Coastguard Worker # section. If we leave it there, lld-link will complain: 134*8975f5c5SAndroid Build Coastguard Worker # 135*8975f5c5SAndroid Build Coastguard Worker # lld-link: error: .debug$S should not refer to non-existent section 5 136*8975f5c5SAndroid Build Coastguard Worker # 137*8975f5c5SAndroid Build Coastguard Worker # so we need to remove that symbol table entry as well. This shifts symbol 138*8975f5c5SAndroid Build Coastguard Worker # entries around and we need to update symbol table indices in: 139*8975f5c5SAndroid Build Coastguard Worker # - relocations 140*8975f5c5SAndroid Build Coastguard Worker # - line number records (never present) 141*8975f5c5SAndroid Build Coastguard Worker # - one aux symbol entry (IMAGE_SYM_CLASS_CLR_TOKEN; not present in ml output) 142*8975f5c5SAndroid Build Coastguard Worker SYM = Struct( 143*8975f5c5SAndroid Build Coastguard Worker 'SYM', 144*8975f5c5SAndroid Build Coastguard Worker '8s', 145*8975f5c5SAndroid Build Coastguard Worker 'Name', 146*8975f5c5SAndroid Build Coastguard Worker 'I', 147*8975f5c5SAndroid Build Coastguard Worker 'Value', 148*8975f5c5SAndroid Build Coastguard Worker 'h', 149*8975f5c5SAndroid Build Coastguard Worker 'SectionNumber', # Note: Signed! 150*8975f5c5SAndroid Build Coastguard Worker 'H', 151*8975f5c5SAndroid Build Coastguard Worker 'Type', 152*8975f5c5SAndroid Build Coastguard Worker 'B', 153*8975f5c5SAndroid Build Coastguard Worker 'StorageClass', 154*8975f5c5SAndroid Build Coastguard Worker 'B', 155*8975f5c5SAndroid Build Coastguard Worker 'NumberOfAuxSymbols') 156*8975f5c5SAndroid Build Coastguard Worker i = 0 157*8975f5c5SAndroid Build Coastguard Worker debug_sym = -1 158*8975f5c5SAndroid Build Coastguard Worker while i < coff_header.NumberOfSymbols: 159*8975f5c5SAndroid Build Coastguard Worker sym_offset = coff_header.PointerToSymbolTable + i * SYM.size() 160*8975f5c5SAndroid Build Coastguard Worker sym = SYM.unpack_from(objdata, sym_offset) 161*8975f5c5SAndroid Build Coastguard Worker 162*8975f5c5SAndroid Build Coastguard Worker # 107 is IMAGE_SYM_CLASS_CLR_TOKEN, which has aux entry "CLR Token 163*8975f5c5SAndroid Build Coastguard Worker # Definition", which contains a symbol index. Check it's never present. 164*8975f5c5SAndroid Build Coastguard Worker assert sym.StorageClass != 107 165*8975f5c5SAndroid Build Coastguard Worker 166*8975f5c5SAndroid Build Coastguard Worker # Note: sym.SectionNumber is 1-based, debug_section_index is 0-based. 167*8975f5c5SAndroid Build Coastguard Worker if sym.SectionNumber - 1 == debug_section_index: 168*8975f5c5SAndroid Build Coastguard Worker assert debug_sym == -1, 'more than one .debug$S symbol found' 169*8975f5c5SAndroid Build Coastguard Worker debug_sym = i 170*8975f5c5SAndroid Build Coastguard Worker # Make sure the .debug$S symbol looks like we expect. 171*8975f5c5SAndroid Build Coastguard Worker # In particular, it should have exactly one aux symbol. 172*8975f5c5SAndroid Build Coastguard Worker assert sym.Name == b'.debug$S' 173*8975f5c5SAndroid Build Coastguard Worker assert sym.Value == 0 174*8975f5c5SAndroid Build Coastguard Worker assert sym.Type == 0 175*8975f5c5SAndroid Build Coastguard Worker assert sym.StorageClass == 3 176*8975f5c5SAndroid Build Coastguard Worker assert sym.NumberOfAuxSymbols == 1 177*8975f5c5SAndroid Build Coastguard Worker elif sym.SectionNumber > debug_section_index: 178*8975f5c5SAndroid Build Coastguard Worker sym = Subtract(sym, SectionNumber=1) 179*8975f5c5SAndroid Build Coastguard Worker SYM.pack_into(objdata, sym_offset, sym) 180*8975f5c5SAndroid Build Coastguard Worker i += 1 + sym.NumberOfAuxSymbols 181*8975f5c5SAndroid Build Coastguard Worker assert debug_sym != -1, '.debug$S symbol not found' 182*8975f5c5SAndroid Build Coastguard Worker 183*8975f5c5SAndroid Build Coastguard Worker # Note: Usually the .debug$S section is the last, but for files saying 184*8975f5c5SAndroid Build Coastguard Worker # `includelib foo.lib`, like safe_terminate_process.asm in 32-bit builds, 185*8975f5c5SAndroid Build Coastguard Worker # this isn't true: .drectve is after .debug$S. 186*8975f5c5SAndroid Build Coastguard Worker 187*8975f5c5SAndroid Build Coastguard Worker # Update symbol table indices in relocations. 188*8975f5c5SAndroid Build Coastguard Worker # There are a few processor types that have one or two relocation types 189*8975f5c5SAndroid Build Coastguard Worker # where SymbolTableIndex has a different meaning, but not for x86. 190*8975f5c5SAndroid Build Coastguard Worker REL = Struct('REL', 'I', 'VirtualAddress', 'I', 'SymbolTableIndex', 'H', 191*8975f5c5SAndroid Build Coastguard Worker 'Type') 192*8975f5c5SAndroid Build Coastguard Worker for header in section_headers[0:debug_section_index]: 193*8975f5c5SAndroid Build Coastguard Worker for j in range(0, header.NumberOfRelocations): 194*8975f5c5SAndroid Build Coastguard Worker rel_offset = header.PointerToRelocations + j * REL.size() 195*8975f5c5SAndroid Build Coastguard Worker rel = REL.unpack_from(objdata, rel_offset) 196*8975f5c5SAndroid Build Coastguard Worker assert rel.SymbolTableIndex != debug_sym 197*8975f5c5SAndroid Build Coastguard Worker if rel.SymbolTableIndex > debug_sym: 198*8975f5c5SAndroid Build Coastguard Worker rel = Subtract(rel, SymbolTableIndex=2) 199*8975f5c5SAndroid Build Coastguard Worker REL.pack_into(objdata, rel_offset, rel) 200*8975f5c5SAndroid Build Coastguard Worker 201*8975f5c5SAndroid Build Coastguard Worker # Update symbol table indices in line numbers -- just check they don't exist. 202*8975f5c5SAndroid Build Coastguard Worker for header in section_headers: 203*8975f5c5SAndroid Build Coastguard Worker assert header.NumberOfLineNumbers == 0 204*8975f5c5SAndroid Build Coastguard Worker 205*8975f5c5SAndroid Build Coastguard Worker # Now that all indices are updated, remove the symbol table entry referring to 206*8975f5c5SAndroid Build Coastguard Worker # .debug$S and its aux entry. 207*8975f5c5SAndroid Build Coastguard Worker del objdata[coff_header.PointerToSymbolTable + 208*8975f5c5SAndroid Build Coastguard Worker debug_sym * SYM.size():coff_header.PointerToSymbolTable + 209*8975f5c5SAndroid Build Coastguard Worker (debug_sym + 2) * SYM.size()] 210*8975f5c5SAndroid Build Coastguard Worker 211*8975f5c5SAndroid Build Coastguard Worker # Now we know that it's safe to write out the input data, with just the 212*8975f5c5SAndroid Build Coastguard Worker # timestamp overwritten to 0, the last section header cut out (and the 213*8975f5c5SAndroid Build Coastguard Worker # offsets of all other section headers decremented by the size of that 214*8975f5c5SAndroid Build Coastguard Worker # one section header), and the last section's data cut out. The symbol 215*8975f5c5SAndroid Build Coastguard Worker # table offset needs to be reduced by one section header and the size of 216*8975f5c5SAndroid Build Coastguard Worker # the missing section. 217*8975f5c5SAndroid Build Coastguard Worker # (The COFF spec only requires on-disk sections to be aligned in image files, 218*8975f5c5SAndroid Build Coastguard Worker # for obj files it's not required. If that wasn't the case, deleting slices 219*8975f5c5SAndroid Build Coastguard Worker # if data would not generally be safe.) 220*8975f5c5SAndroid Build Coastguard Worker 221*8975f5c5SAndroid Build Coastguard Worker # Update section offsets and remove .debug$S section data. 222*8975f5c5SAndroid Build Coastguard Worker for i in range(0, debug_section_index): 223*8975f5c5SAndroid Build Coastguard Worker header = section_headers[i] 224*8975f5c5SAndroid Build Coastguard Worker if header.SizeOfRawData: 225*8975f5c5SAndroid Build Coastguard Worker header = Subtract(header, PointerToRawData=SECTIONHEADER.size()) 226*8975f5c5SAndroid Build Coastguard Worker if header.NumberOfRelocations: 227*8975f5c5SAndroid Build Coastguard Worker header = Subtract(header, PointerToRelocations=SECTIONHEADER.size()) 228*8975f5c5SAndroid Build Coastguard Worker if header.NumberOfLineNumbers: 229*8975f5c5SAndroid Build Coastguard Worker header = Subtract(header, PointerToLineNumbers=SECTIONHEADER.size()) 230*8975f5c5SAndroid Build Coastguard Worker SECTIONHEADER.pack_into(objdata, 231*8975f5c5SAndroid Build Coastguard Worker COFFHEADER.size() + i * SECTIONHEADER.size(), 232*8975f5c5SAndroid Build Coastguard Worker header) 233*8975f5c5SAndroid Build Coastguard Worker for i in range(debug_section_index + 1, len(section_headers)): 234*8975f5c5SAndroid Build Coastguard Worker header = section_headers[i] 235*8975f5c5SAndroid Build Coastguard Worker shift = SECTIONHEADER.size() + debug_size 236*8975f5c5SAndroid Build Coastguard Worker if header.SizeOfRawData: 237*8975f5c5SAndroid Build Coastguard Worker header = Subtract(header, PointerToRawData=shift) 238*8975f5c5SAndroid Build Coastguard Worker if header.NumberOfRelocations: 239*8975f5c5SAndroid Build Coastguard Worker header = Subtract(header, PointerToRelocations=shift) 240*8975f5c5SAndroid Build Coastguard Worker if header.NumberOfLineNumbers: 241*8975f5c5SAndroid Build Coastguard Worker header = Subtract(header, PointerToLineNumbers=shift) 242*8975f5c5SAndroid Build Coastguard Worker SECTIONHEADER.pack_into(objdata, 243*8975f5c5SAndroid Build Coastguard Worker COFFHEADER.size() + i * SECTIONHEADER.size(), 244*8975f5c5SAndroid Build Coastguard Worker header) 245*8975f5c5SAndroid Build Coastguard Worker 246*8975f5c5SAndroid Build Coastguard Worker del objdata[debug_offset:debug_offset + debug_size] 247*8975f5c5SAndroid Build Coastguard Worker 248*8975f5c5SAndroid Build Coastguard Worker # Finally, remove .debug$S section header and update coff header. 249*8975f5c5SAndroid Build Coastguard Worker coff_header = coff_header._replace(TimeDateStamp=0) 250*8975f5c5SAndroid Build Coastguard Worker coff_header = Subtract(coff_header, 251*8975f5c5SAndroid Build Coastguard Worker NumberOfSections=1, 252*8975f5c5SAndroid Build Coastguard Worker PointerToSymbolTable=SECTIONHEADER.size() + debug_size, 253*8975f5c5SAndroid Build Coastguard Worker NumberOfSymbols=2) 254*8975f5c5SAndroid Build Coastguard Worker COFFHEADER.pack_into(objdata, 0, coff_header) 255*8975f5c5SAndroid Build Coastguard Worker 256*8975f5c5SAndroid Build Coastguard Worker del objdata[COFFHEADER.size() + 257*8975f5c5SAndroid Build Coastguard Worker debug_section_index * SECTIONHEADER.size():COFFHEADER.size() + 258*8975f5c5SAndroid Build Coastguard Worker (debug_section_index + 1) * SECTIONHEADER.size()] 259*8975f5c5SAndroid Build Coastguard Worker 260*8975f5c5SAndroid Build Coastguard Worker # All done! 261*8975f5c5SAndroid Build Coastguard Worker if sys.version_info.major == 2: 262*8975f5c5SAndroid Build Coastguard Worker return objdata.tostring() 263*8975f5c5SAndroid Build Coastguard Worker else: 264*8975f5c5SAndroid Build Coastguard Worker return objdata.tobytes() 265*8975f5c5SAndroid Build Coastguard Worker 266*8975f5c5SAndroid Build Coastguard Worker 267*8975f5c5SAndroid Build Coastguard Workerdef main(): 268*8975f5c5SAndroid Build Coastguard Worker ml_result = subprocess.call(sys.argv[1:]) 269*8975f5c5SAndroid Build Coastguard Worker if ml_result != 0: 270*8975f5c5SAndroid Build Coastguard Worker return ml_result 271*8975f5c5SAndroid Build Coastguard Worker 272*8975f5c5SAndroid Build Coastguard Worker objfile = None 273*8975f5c5SAndroid Build Coastguard Worker for i in range(1, len(sys.argv)): 274*8975f5c5SAndroid Build Coastguard Worker if sys.argv[i].startswith('/Fo'): 275*8975f5c5SAndroid Build Coastguard Worker objfile = sys.argv[i][len('/Fo'):] 276*8975f5c5SAndroid Build Coastguard Worker assert objfile, 'failed to find ml output' 277*8975f5c5SAndroid Build Coastguard Worker 278*8975f5c5SAndroid Build Coastguard Worker with open(objfile, 'rb') as f: 279*8975f5c5SAndroid Build Coastguard Worker objdata = f.read() 280*8975f5c5SAndroid Build Coastguard Worker objdata = MakeDeterministic(objdata) 281*8975f5c5SAndroid Build Coastguard Worker with open(objfile, 'wb') as f: 282*8975f5c5SAndroid Build Coastguard Worker f.write(objdata) 283*8975f5c5SAndroid Build Coastguard Worker 284*8975f5c5SAndroid Build Coastguard Worker 285*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__': 286*8975f5c5SAndroid Build Coastguard Worker sys.exit(main()) 287