xref: /aosp_15_r20/external/angle/build/toolchain/win/ml.py (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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