Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright (c) 2012 The Native Client Authors. All rights reserved. | 2 # Copyright (c) 2012 The Native Client Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 # | 5 # |
| 6 # | 6 # |
| 7 # This is a thin wrapper for native LD. This is not meant to be | 7 # This is a thin wrapper for native LD. This is not meant to be |
| 8 # used by the user, but is called from pnacl-translate. | 8 # used by the user, but is called from pnacl-translate. |
| 9 # This implements the native linking part of translation. | 9 # This implements the native linking part of translation. |
| 10 # | 10 # |
| 11 # All inputs must be native objects or linker scripts. | 11 # All inputs must be native objects or linker scripts. |
| 12 # | 12 # |
| 13 # --pnacl-sb will cause the sandboxed LD to be used. | 13 # --pnacl-sb will cause the sandboxed LD to be used. |
| 14 # The bulk of this file is logic to invoke the sandboxed translator. | 14 # The bulk of this file is logic to invoke the sandboxed translator. |
| 15 | 15 |
| 16 import subprocess | 16 import subprocess |
| 17 | 17 |
| 18 from driver_tools import CheckTranslatorPrerequisites, GetArch, ParseArgs, \ | 18 from driver_tools import CheckTranslatorPrerequisites, GetArch, ParseArgs, \ |
| 19 Run, UnrecognizedOption | 19 Run, UnrecognizedOption |
| 20 from driver_env import env | 20 from driver_env import env |
| 21 from driver_log import Log | 21 from driver_log import Log |
| 22 import ldtools | 22 import ldtools |
| 23 import pathtools | 23 import pathtools |
| 24 | 24 |
| 25 | 25 |
| 26 EXTRA_ENV = { | 26 EXTRA_ENV = { |
| 27 'INPUTS' : '', | 27 'INPUTS' : '', |
| 28 'OUTPUT' : '', | 28 'OUTPUT' : '', |
| 29 | 29 |
| 30 # the INPUTS file coming from the llc translation step | 30 # The INPUTS file coming from the llc translation step |
| 31 'LLC_TRANSLATED_FILE' : '', | 31 'LLC_TRANSLATED_FILE' : '', |
| 32 # Number of separate modules used for multi-threaded translation. This should | |
| 33 # have been set by pnacl-translate, but default to 0 for checking. | |
| 32 'SPLIT_MODULE' : '0', | 34 'SPLIT_MODULE' : '0', |
| 33 'USE_STDLIB': '1', | 35 'USE_STDLIB': '1', |
| 34 | 36 |
| 35 # Upstream gold has the segment gap built in, but the gap can be modified | 37 # Upstream gold has the segment gap built in, but the gap can be modified |
| 36 # when not using the IRT. The gap does need to be at least one bundle so the | 38 # when not using the IRT. The gap does need to be at least one bundle so the |
| 37 # halt sled can be added for the TCB in case the segment ends up being a | 39 # halt sled can be added for the TCB in case the segment ends up being a |
| 38 # multiple of 64k. | 40 # multiple of 64k. |
| 39 # --eh-frame-hdr asks the linker to generate an .eh_frame_hdr section, | 41 # --eh-frame-hdr asks the linker to generate an .eh_frame_hdr section, |
| 40 # which is a presorted list of registered frames. This section is | 42 # which is a presorted list of registered frames. This section is |
| 41 # used by libgcc_eh/libgcc_s to avoid doing the sort during runtime. | 43 # used by libgcc_eh/libgcc_s to avoid doing the sort during runtime. |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 176 # The "main" input file is the application's combined object file. | 178 # The "main" input file is the application's combined object file. |
| 177 all_inputs = env.get('inputs') | 179 all_inputs = env.get('inputs') |
| 178 | 180 |
| 179 main_input = env.getone('LLC_TRANSLATED_FILE') | 181 main_input = env.getone('LLC_TRANSLATED_FILE') |
| 180 if not main_input: | 182 if not main_input: |
| 181 Log.Fatal("Sandboxed LD requires one shm input file") | 183 Log.Fatal("Sandboxed LD requires one shm input file") |
| 182 | 184 |
| 183 outfile = env.getone('output') | 185 outfile = env.getone('output') |
| 184 | 186 |
| 185 modules = int(env.getone('SPLIT_MODULE')) | 187 modules = int(env.getone('SPLIT_MODULE')) |
| 186 if modules > 1: | 188 assert modules >= 1 |
| 187 first_mainfile = all_inputs.index(main_input) | 189 first_mainfile = all_inputs.index(main_input) |
|
Mark Seaborn
2014/12/01 20:54:16
Is this part just general cleanup, on the grounds
jvoung (off chromium)
2014/12/01 22:00:09
I want the "else" case to be the same as the "if"
| |
| 188 first_extra = all_inputs.index(main_input) + modules | 190 first_extra = all_inputs.index(main_input) + modules |
| 189 # Just the split module files | 191 # Have a list of just the split module files. |
| 190 llc_outputs = all_inputs[first_mainfile:first_extra] | 192 llc_outputs = all_inputs[first_mainfile:first_extra] |
| 191 # everything else | 193 # Have a list of everything else. |
| 192 all_inputs = all_inputs[:first_mainfile] + all_inputs[first_extra:] | 194 other_inputs = all_inputs[:first_mainfile] + all_inputs[first_extra:] |
| 193 else: | |
| 194 llc_outputs = [main_input] | |
| 195 | 195 |
| 196 files = LinkerFiles(all_inputs) | |
| 197 ld_flags = env.get('LD_FLAGS') | 196 ld_flags = env.get('LD_FLAGS') |
| 198 | 197 |
| 199 script = MakeSelUniversalScriptForLD(ld_flags, | 198 script = MakeSelUniversalScriptForLD(ld_flags, |
| 200 llc_outputs, | 199 llc_outputs, |
| 201 files, | |
| 202 outfile) | 200 outfile) |
| 203 | 201 |
| 204 | 202 native_libs_dirname = pathtools.tosys(GetNativeLibsDirname(other_inputs)) |
| 205 Run('${SEL_UNIVERSAL_PREFIX} ${SEL_UNIVERSAL} ' + | 203 Run('${SEL_UNIVERSAL_PREFIX} ${SEL_UNIVERSAL} ' + |
| 206 '${SEL_UNIVERSAL_FLAGS} -B ${IRT_BLOB} -- ${LD_SB}', | 204 '${SEL_UNIVERSAL_FLAGS} -a -B ${IRT_BLOB} ' + |
| 205 '-E NACL_IRT_OPEN_RESOURCE_BASE=' + native_libs_dirname + ' ' + | |
| 206 '-E NACL_IRT_OPEN_RESOURCE_REMAP=' + | |
| 207 'libpnacl_irt_shim.a:libpnacl_irt_shim_dummy.a' + | |
| 208 ' -- ${LD_SB}', | |
| 207 stdin_contents=script, | 209 stdin_contents=script, |
| 208 # stdout/stderr will be automatically dumped | 210 # stdout/stderr will be automatically dumped |
| 209 # upon failure | 211 # upon failure |
| 210 redirect_stderr=subprocess.PIPE, | 212 redirect_stderr=subprocess.PIPE, |
| 211 redirect_stdout=subprocess.PIPE) | 213 redirect_stdout=subprocess.PIPE) |
| 212 | 214 |
| 213 | 215 |
| 214 def MakeSelUniversalScriptForLD(ld_flags, | 216 def MakeSelUniversalScriptForLD(ld_flags, |
| 215 llc_outputs, | 217 llc_outputs, |
| 216 files, | |
| 217 outfile): | 218 outfile): |
| 218 """ Return sel_universal script text for invoking LD.nexe with the | 219 """ Return sel_universal script text for invoking LD.nexe with the |
| 219 given ld_flags, llc_outputs (which are treated specially), and | 220 given ld_flags, and llc_outputs (which are treated specially). |
| 220 other input files (for native libraries). The output will be written | 221 The output will be written to outfile. """ |
| 221 to outfile. """ | |
| 222 script = [] | 222 script = [] |
| 223 | 223 |
| 224 # Open the output file. | 224 # Open the output file. |
| 225 script.append('readwrite_file nexefile %s' % outfile) | 225 script.append('readwrite_file nexefile %s' % outfile) |
| 226 | 226 |
| 227 files_to_map = list(files) | |
| 228 # Create a reverse-service mapping for each input file and add it to | |
| 229 # the sel universal script. | |
| 230 for f in files_to_map: | |
| 231 basename = pathtools.basename(f) | |
| 232 # If we are using the dummy shim, map it with the filename of the real | |
| 233 # shim, so the baked-in commandline will work. | |
| 234 if basename == 'libpnacl_irt_shim_dummy.a': | |
| 235 basename = 'libpnacl_irt_shim.a' | |
| 236 script.append('reverse_service_add_manifest_mapping files/%s %s' % | |
| 237 (basename, f)) | |
| 238 | |
| 239 modules = len(llc_outputs) | 227 modules = len(llc_outputs) |
| 240 script.extend(['readonly_file objfile%d %s' % (i, f) | 228 script.extend(['readonly_file objfile%d %s' % (i, f) |
| 241 for i, f in zip(range(modules), llc_outputs)]) | 229 for i, f in zip(range(modules), llc_outputs)]) |
| 242 script.append('rpc RunWithSplit i(%d) ' % modules + | 230 script.append('rpc RunWithSplit i(%d) ' % modules + |
| 243 ' '.join(['h(objfile%s)' % m for m in range(modules)] + | 231 ' '.join(['h(objfile%s)' % m for m in range(modules)] + |
| 244 ['h(invalid)' for x in range(modules, 16)]) + | 232 ['h(invalid)' for x in range(modules, 16)]) + |
| 245 ' h(nexefile) *') | 233 ' h(nexefile) *') |
| 246 script.append('echo "ld complete"') | 234 script.append('echo "ld complete"') |
| 247 script.append('') | 235 script.append('') |
| 248 return '\n'.join(script) | 236 return '\n'.join(script) |
| 249 | 237 |
| 250 # Given linker arguments (including -L, -l, and filenames), | 238 |
| 251 # returns the list of files which are pulled by the linker, | 239 def GetNativeLibsDirname(other_inputs): |
| 252 # with real path names set set up the real -> flat name mapping. | 240 """Check that native libs have a common directory and return the directory.""" |
| 253 def LinkerFiles(args): | 241 dirname = None |
| 254 ret = [] | 242 for f in other_inputs: |
| 255 for f in args: | |
| 256 if IsFlag(f): | 243 if IsFlag(f): |
| 257 continue | 244 continue |
| 258 else: | 245 else: |
| 259 if not pathtools.exists(f): | 246 if not pathtools.exists(f): |
| 260 Log.Fatal("Unable to open '%s'", pathtools.touser(f)) | 247 Log.Fatal("Unable to open '%s'", pathtools.touser(f)) |
| 261 ret.append(f) | 248 if dirname is None: |
| 262 return ret | 249 dirname = pathtools.dirname(f) |
| 250 else: | |
| 251 if dirname != pathtools.dirname(f): | |
| 252 Log.Fatal('Need a common directory for native libs: %s != %s', | |
| 253 dirname, pathtools.dirname(f)) | |
| 254 if not dirname: | |
| 255 Log.Fatal('No native libraries found') | |
| 256 return dirname + '/' | |
| OLD | NEW |