def RunDriver(invocation, args, suppress_inherited_arch_args=False): """ RunDriver() is used to invoke "driver" tools, e.g. those prefixed with "pnacl-" It automatically appends some additional flags to the invocation which were inherited from the current invocation. Those flags were preserved by ParseArgs """ if isinstance(args, str): args = shell.split(env.eval(args)) module_name = 'pnacl-%s' % invocation script = env.eval('${DRIVER_BIN}/%s' % module_name) script = shell.unescape(script) inherited_driver_args = env.get('INHERITED_DRIVER_ARGS') if suppress_inherited_arch_args: inherited_driver_args = FilterOutArchArgs(inherited_driver_args) script = pathtools.tosys(script) cmd = [script] + args + inherited_driver_args Log.Info('Driver invocation: %s', repr(cmd)) module = __import__(module_name) # Save the environment, reset the environment, run # the driver module, and then restore the environment. env.push() env.reset() DriverMain(module, cmd) env.pop()
def RunDriver(module_name, args, suppress_inherited_arch_args=False): """ RunDriver() is used to invoke "driver" tools, e.g. those prefixed with "pnacl-" It automatically appends some additional flags to the invocation which were inherited from the current invocation. Those flags were preserved by ParseArgs """ if isinstance(args, str): args = shell.split(env.eval(args)) script = env.eval('${DRIVER_BIN}/%s' % module_name) script = shell.unescape(script) inherited_driver_args = env.get('INHERITED_DRIVER_ARGS') if suppress_inherited_arch_args: inherited_driver_args = FilterOutArchArgs(inherited_driver_args) script = pathtools.tosys(script) cmd = [script] + args + inherited_driver_args Log.Info('Driver invocation: %s', repr(cmd)) module = __import__(module_name) # Save the environment, reset the environment, run # the driver module, and then restore the environment. env.push() env.reset() DriverMain(module, cmd) env.pop()
def SetExecutableMode(path): if os.name == "posix": realpath = pathtools.tosys(path) # os.umask gets and sets at the same time. # There's no way to get it without setting it. umask = os.umask(0) os.umask(umask) os.chmod(realpath, 0755 & ~umask)
def DriverOpen(filename, mode, fail_ok=False): try: fp = open(pathtools.tosys(filename), mode) except Exception: if not fail_ok: Log.Fatal("%s: Unable to open file", pathtools.touser(filename)) DriverExit(1) else: return None return fp
def DriverOpen(filename, mode, fail_ok = False): try: fp = open(pathtools.tosys(filename), mode) except Exception: if not fail_ok: Log.Fatal("%s: Unable to open file", pathtools.touser(filename)) DriverExit(1) else: return None return fp
def Run(args, errexit=True, redirect_stdout=None, redirect_stderr=None): """ Run: Run a command. Returns: return_code, stdout, stderr Run() is used to invoke "other" tools, e.g. those NOT prefixed with "pnacl-" stdout and stderr only contain meaningful data if redirect_{stdout,stderr} == subprocess.PIPE Run will terminate the program upon failure unless errexit == False TODO(robertm): errexit == True has not been tested and needs more work redirect_stdout and redirect_stderr are passed straight to subprocess.Popen """ result_stdout = None result_stderr = None if isinstance(args, str): args = shell.split(env.eval(args)) args = [pathtools.tosys(args[0])] + args[1:] Log.Info('Running: ' + StringifyCommand(args)) if env.getbool('DRY_RUN'): if redirect_stderr or redirect_stdout: # TODO(pdox): Prevent this from happening, so that # dry-run is more useful. Log.Fatal("Unhandled dry-run case.") return 0, None, None try: # If we have too long of a cmdline on windows, running it would fail. # Attempt to use a file with the command line options instead in that case. if ArgsTooLongForWindows(args): actual_args = ConvertArgsToFile(args) Log.Info('Wrote long commandline to file for Windows: ' + StringifyCommand(actual_args)) else: actual_args = args p = subprocess.Popen(actual_args, stdout=redirect_stdout, stderr=redirect_stderr) result_stdout, result_stderr = p.communicate() except Exception, e: msg = '%s\nCommand was: %s' % (str(e), StringifyCommand(args)) print(msg) DriverExit(1)
def Run(args, errexit=True, redirect_stdout=None, redirect_stderr=None): """ Run: Run a command. Returns: return_code, stdout, stderr Run() is used to invoke "other" tools, e.g. those NOT prefixed with "pnacl-" stdout and stderr only contain meaningful data if redirect_{stdout,stderr} == subprocess.PIPE Run will terminate the program upon failure unless errexit == False TODO(robertm): errexit == True has not been tested and needs more work redirect_stdout and redirect_stderr are passed straight to subprocess.Popen """ result_stdout = None result_stderr = None if isinstance(args, str): args = shell.split(env.eval(args)) args = [pathtools.tosys(args[0])] + args[1:] Log.Info('Running: ' + StringifyCommand(args)) if env.getbool('DRY_RUN'): if redirect_stderr or redirect_stdout: # TODO(pdox): Prevent this from happening, so that # dry-run is more useful. Log.Fatal("Unhandled dry-run case.") return 0, None, None try: # If we have too long of a cmdline on windows, running it would fail. # Attempt to use a file with the command line options instead in that case. if ArgsTooLongForWindows(args): actual_args = ConvertArgsToFile(args) Log.Info('Wrote long commandline to file for Windows: ' + StringifyCommand(actual_args)) else: actual_args = args p = subprocess.Popen(actual_args, stdout=redirect_stdout, stderr=redirect_stderr) result_stdout, result_stderr = p.communicate() except Exception, e: msg = '%s\nCommand was: %s' % (str(e), StringifyCommand(args)) print msg DriverExit(1)
def wipe(self): for path in self.files: try: os.remove(pathtools.tosys(path)) except OSError as err: # If we're exiting early, the temp file # may have never been created. Log.Warning("TempFileHandler: Unable to wipe file %s w/ error %s", pathtools.touser(path), err.strerror) self.files = []
def wipe(self): for path in self.files: try: sys_path = pathtools.tosys(path) # If exiting early, the file may not have been created yet. if os.path.exists(sys_path): os.remove(sys_path) except OSError as err: Log.Fatal("TempFileHandler: Unable to wipe file %s w/ error %s", pathtools.touser(path), err.strerror) self.files = []
def wipe(self): for path in self.files: try: sys_path = pathtools.tosys(path) # If exiting early, the file may not have been created yet. if os.path.exists(sys_path): os.remove(sys_path) except OSError as err: Log.Error( "TempFileHandler: Unable to wipe file %s w/ error %s", pathtools.touser(path), err.strerror) self.files = []
def RunLDSandboxed(): if not env.getbool('USE_STDLIB'): Log.Fatal('-nostdlib is not supported by the sandboxed translator') CheckTranslatorPrerequisites() # The "main" input file is the application's combined object file. all_inputs = env.get('inputs') main_input = env.getone('LLC_TRANSLATED_FILE') if not main_input: Log.Fatal("Sandboxed LD requires one shm input file") outfile = env.getone('output') modules = int(env.getone('SPLIT_MODULE')) assert modules >= 1 first_mainfile = all_inputs.index(main_input) first_extra = all_inputs.index(main_input) + modules # Have a list of just the split module files. llc_outputs = all_inputs[first_mainfile:first_extra] # Have a list of everything else. other_inputs = all_inputs[:first_mainfile] + all_inputs[first_extra:] if driver_tools.GetBuildOS() == 'linux': sel_ldr_command = ('${BOOTSTRAP_LDR} ${SEL_LDR} --reserved_at_zero=0x%s' % ('X' * 16)) else: sel_ldr_command = '${SEL_LDR}' native_libs_dirname = pathtools.tosys(GetNativeLibsDirname(other_inputs)) command = ['${SEL_LDR_PREFIX}', sel_ldr_command, '${SEL_LDR_FLAGS}', '-a'] for index, filename in enumerate(llc_outputs): command.extend( ['-E', 'NACL_IRT_PNACL_TRANSLATOR_LINK_INPUT_%d=%s' % (index, filename)]) command.extend([ '-E', 'NACL_IRT_PNACL_TRANSLATOR_LINK_OUTPUT=%s ' % outfile, '-E', 'NACL_IRT_OPEN_RESOURCE_BASE=%s' % native_libs_dirname, '-E', 'NACL_IRT_OPEN_RESOURCE_REMAP=%s' % 'libpnacl_irt_shim.a:libpnacl_irt_shim_dummy.a', '--', '${LD_SB}']) Run(' '.join(command), # stdout/stderr will be automatically dumped # upon failure redirect_stderr=subprocess.PIPE, redirect_stdout=subprocess.PIPE)
def RunLDSandboxed(): if not env.getbool('USE_STDLIB'): Log.Fatal('-nostdlib is not supported by the sandboxed translator') CheckTranslatorPrerequisites() # The "main" input file is the application's combined object file. all_inputs = env.get('inputs') main_input = env.getone('LLC_TRANSLATED_FILE') if not main_input: Log.Fatal("Sandboxed LD requires one shm input file") outfile = env.getone('output') modules = int(env.getone('SPLIT_MODULE')) assert modules >= 1 first_mainfile = all_inputs.index(main_input) first_extra = all_inputs.index(main_input) + modules # Have a list of just the split module files. llc_outputs = all_inputs[first_mainfile:first_extra] # Have a list of everything else. other_inputs = all_inputs[:first_mainfile] + all_inputs[first_extra:] ld_flags = env.get('LD_FLAGS') script = MakeSelUniversalScriptForLD(ld_flags, llc_outputs, outfile) native_libs_dirname = pathtools.tosys(GetNativeLibsDirname(other_inputs)) Run('${SEL_UNIVERSAL_PREFIX} ${SEL_UNIVERSAL} ' + '${SEL_UNIVERSAL_FLAGS} -a -B ${IRT_BLOB} ' + '-E NACL_IRT_OPEN_RESOURCE_BASE=' + native_libs_dirname + ' ' + '-E NACL_IRT_OPEN_RESOURCE_REMAP=' + 'libpnacl_irt_shim.a:libpnacl_irt_shim_dummy.a' + ' -- ${LD_SB}', stdin_contents=script, # stdout/stderr will be automatically dumped # upon failure redirect_stderr=subprocess.PIPE, redirect_stdout=subprocess.PIPE)
def RunLDSandboxed(): if not env.getbool('USE_STDLIB'): Log.Fatal('-nostdlib is not supported by the sandboxed translator') CheckTranslatorPrerequisites() # The "main" input file is the application's combined object file. all_inputs = env.get('inputs') main_input = env.getone('LLC_TRANSLATED_FILE') if not main_input: Log.Fatal("Sandboxed LD requires one shm input file") outfile = env.getone('output') modules = int(env.getone('SPLIT_MODULE')) assert modules >= 1 first_mainfile = all_inputs.index(main_input) first_extra = all_inputs.index(main_input) + modules # Have a list of just the split module files. llc_outputs = all_inputs[first_mainfile:first_extra] # Have a list of everything else. other_inputs = all_inputs[:first_mainfile] + all_inputs[first_extra:] native_libs_dirname = pathtools.tosys(GetNativeLibsDirname(other_inputs)) command = [driver_tools.SelLdrCommand(), '-a'] # Allow file access driver_tools.AddListToEnv(command, 'NACL_IRT_PNACL_TRANSLATOR_LINK_INPUT', llc_outputs) command.extend([ '-E', 'NACL_IRT_PNACL_TRANSLATOR_LINK_OUTPUT=%s ' % outfile, '-E', 'NACL_IRT_OPEN_RESOURCE_BASE=%s' % native_libs_dirname, '-E', 'NACL_IRT_OPEN_RESOURCE_REMAP=%s' % 'libpnacl_irt_shim.a:libpnacl_irt_shim_dummy.a', '--', '${LD_SB}' ]) Run( ' '.join(command), # stdout/stderr will be automatically dumped # upon failure redirect_stderr=subprocess.PIPE, redirect_stdout=subprocess.PIPE)
def RunLDSandboxed(): if not env.getbool('USE_STDLIB'): Log.Fatal('-nostdlib is not supported by the sandboxed translator') CheckTranslatorPrerequisites() # The "main" input file is the application's combined object file. all_inputs = env.get('inputs') main_input = env.getone('LLC_TRANSLATED_FILE') if not main_input: Log.Fatal("Sandboxed LD requires one shm input file") outfile = env.getone('output') modules = int(env.getone('SPLIT_MODULE')) assert modules >= 1 first_mainfile = all_inputs.index(main_input) first_extra = all_inputs.index(main_input) + modules # Have a list of just the split module files. llc_outputs = all_inputs[first_mainfile:first_extra] # Have a list of everything else. other_inputs = all_inputs[:first_mainfile] + all_inputs[first_extra:] native_libs_dirname = pathtools.tosys(GetNativeLibsDirname(other_inputs)) command = [driver_tools.SelLdrCommand(), '-a'] # Allow file access driver_tools.AddListToEnv(command, 'NACL_IRT_PNACL_TRANSLATOR_LINK_INPUT', llc_outputs) command.extend([ '-E', 'NACL_IRT_PNACL_TRANSLATOR_LINK_OUTPUT=%s ' % outfile, '-E', 'NACL_IRT_OPEN_RESOURCE_BASE=%s' % native_libs_dirname, '-E', 'NACL_IRT_OPEN_RESOURCE_REMAP=%s' % 'libpnacl_irt_shim.a:libpnacl_irt_shim_dummy.a', '--', '${LD_SB}']) Run(' '.join(command), # stdout/stderr will be automatically dumped # upon failure redirect_stderr=subprocess.PIPE, redirect_stdout=subprocess.PIPE)
def main(argv): env.update(EXTRA_ENV) driver_tools.ParseArgs(argv, TranslatorPatterns) if env.getbool('SHARED'): env.set('PIC', '1') if env.getbool('SHARED') and env.getbool('STATIC'): Log.Fatal('Cannot mix -static and -shared') driver_tools.GetArch(required=True) inputs = env.get('INPUTS') output = env.getone('OUTPUT') if len(inputs) == 0: Log.Fatal("No input files") if output == '': Log.Fatal("Please specify output file with -o") # Find the bitcode file on the command line. bcfiles = [ f for f in inputs if driver_tools.IsPNaClBitcode(f) or driver_tools.IsLLVMBitcode(f) or driver_tools.FileType(f) == 'll' ] if len(bcfiles) > 1: Log.Fatal('Expecting at most 1 bitcode file') elif len(bcfiles) == 1: bcfile = bcfiles[0] else: bcfile = None # If there's a bitcode file, translate it now. tng = driver_tools.TempNameGen(inputs + bcfiles, output) output_type = env.getone('OUTPUT_TYPE') metadata = None if bcfile: sfile = None if output_type == 's': sfile = output elif env.getbool('FORCE_INTERMEDIATE_S'): sfile = tng.TempNameForInput(bcfile, 's') ofile = None if output_type == 'o': ofile = output elif output_type != 's': ofile = tng.TempNameForInput(bcfile, 'o') if sfile: RunLLC(bcfile, sfile, filetype='asm') if ofile: RunAS(sfile, ofile) else: RunLLC(bcfile, ofile, filetype='obj') else: ofile = None # If we've been told to stop after translation, stop now. if output_type in ('o', 's'): return 0 # Replace the bitcode file with __BITCODE__ in the input list if bcfile: inputs = ListReplace(inputs, bcfile, '__BITCODE__') env.set('INPUTS', *inputs) # Get bitcode type and metadata if bcfile: # Until we stabilize the ABI for shared libraries, # assume that pnacl-translate only handles pexes # to avoid a dependency on bitcode metadata. assert not env.getbool('SHARED') bctype = driver_tools.GetBitcodeType(bcfile, True) metadata = driver_tools.GetBitcodeMetadata(bcfile, True) # Determine the output type, in this order of precedence: # 1) Output type can be specified on command-line (-S, -c, -shared, -static) # 2) If bitcode file given, use its output type. (pso->so, pexe->nexe, po->o) # 3) Otherwise, assume nexe output. if env.getbool('SHARED'): output_type = 'so' elif env.getbool('STATIC'): output_type = 'nexe' elif bcfile: DefaultOutputTypes = { 'pso': 'so', 'pexe': 'nexe', 'po': 'o', } output_type = DefaultOutputTypes[bctype] else: output_type = 'nexe' # If the bitcode is of type "object", no linking is required. if output_type == 'o': # Copy ofile to output Log.Info('Copying %s to %s' % (ofile, output)) shutil.copy(pathtools.tosys(ofile), pathtools.tosys(output)) return 0 if bcfile: ApplyBitcodeConfig(metadata, bctype) # NOTE: we intentionally delay setting STATIC here to give user choices # preference but we should think about dropping the support for # the -static, -shared flags in the translator and have everything # be determined by bctype if metadata is None: env.set('STATIC', '1') elif len(metadata['NeedsLibrary']) == 0 and not env.getbool('SHARED'): env.set('STATIC', '1') assert output_type in ('so', 'nexe') RunLD(ofile, output) return 0
def SetupCygwinLibs(): bindir = env.getone('DRIVER_BIN') # Prepend the directory containing cygwin1.dll etc. to the PATH to ensure we # get the right one. os.environ['PATH'] = os.pathsep.join( [pathtools.tosys(bindir)] + os.environ['PATH'].split(os.pathsep))
def main(argv): env.update(EXTRA_ENV) driver_tools.ParseArgs(argv, TranslatorPatterns) if env.getbool("SHARED"): env.set("PIC", "1") if env.getbool("SHARED") and env.getbool("STATIC"): Log.Fatal("Cannot mix -static and -shared") driver_tools.GetArch(required=True) inputs = env.get("INPUTS") output = env.getone("OUTPUT") if len(inputs) == 0: Log.Fatal("No input files") if output == "": Log.Fatal("Please specify output file with -o") # Find the bitcode file on the command line. bcfiles = filter(driver_tools.IsBitcode, inputs) if len(bcfiles) > 1: Log.Fatal("Expecting at most 1 bitcode file") elif len(bcfiles) == 1: bcfile = bcfiles[0] else: bcfile = None # If there's a bitcode file, translate it now. tng = driver_tools.TempNameGen(inputs + bcfiles, output) output_type = env.getone("OUTPUT_TYPE") metadata = None if bcfile: sfile = None if output_type == "s": sfile = output elif env.getbool("FORCE_INTERMEDIATE_S"): sfile = tng.TempNameForInput(bcfile, "s") ofile = None if output_type == "o": ofile = output elif output_type != "s": ofile = tng.TempNameForInput(bcfile, "o") if sfile: RunLLC(bcfile, sfile, filetype="asm") if ofile: RunAS(sfile, ofile) else: RunLLC(bcfile, ofile, filetype="obj") else: ofile = None # If we've been told to stop after translation, stop now. if output_type in ("o", "s"): return 0 # Replace the bitcode file with __BITCODE__ in the input list if bcfile: inputs = ListReplace(inputs, bcfile, "__BITCODE__") env.set("INPUTS", *inputs) # Get bitcode type and metadata if bcfile: bctype = driver_tools.FileType(bcfile) # sanity checking if bctype == "pso": assert not env.getbool("STATIC") assert env.getbool("SHARED") assert env.getbool("PIC") assert env.get("ARCH") != "arm", "no glibc support for arm yet" elif bctype == "pexe": if env.getbool("LIBMODE_GLIBC"): # this is our proxy for dynamic images assert not env.getbool("STATIC") assert not env.getbool("SHARED") assert env.get("ARCH") != "arm", "no glibc support for arm yet" # for the dynamic case we require non-pic because we do not # have the necessary tls rewrites in gold assert not env.getbool("PIC") else: assert env.getbool("LIBMODE_NEWLIB") assert not env.getbool("SHARED") # for static images we tolerate both PIC and non-PIC else: assert False metadata = driver_tools.GetBitcodeMetadata(bcfile) # Determine the output type, in this order of precedence: # 1) Output type can be specified on command-line (-S, -c, -shared, -static) # 2) If bitcode file given, use its output type. (pso->so, pexe->nexe, po->o) # 3) Otherwise, assume nexe output. if env.getbool("SHARED"): output_type = "so" elif env.getbool("STATIC"): output_type = "nexe" elif bcfile: DefaultOutputTypes = {"pso": "so", "pexe": "nexe", "po": "o"} output_type = DefaultOutputTypes[bctype] else: output_type = "nexe" # If the bitcode is of type "object", no linking is required. if output_type == "o": # Copy ofile to output Log.Info("Copying %s to %s" % (ofile, output)) shutil.copy(pathtools.tosys(ofile), pathtools.tosys(output)) return 0 if bcfile: ApplyBitcodeConfig(metadata, bctype) # NOTE: we intentionally delay setting STATIC here to give user choices # preference but we should think about dropping the support for # the -static, -shared flags in the translator and have everything # be determined by bctype if metadata is None: env.set("STATIC", "1") elif len(metadata["NeedsLibrary"]) == 0 and not env.getbool("SHARED"): env.set("STATIC", "1") assert output_type in ("so", "nexe") RunLD(ofile, output) return 0
def main(argv): env.update(EXTRA_ENV) driver_tools.ParseArgs(argv, TranslatorPatterns) if env.getbool('SHARED'): env.set('PIC', '1') if env.getbool('SHARED') and env.getbool('STATIC'): Log.Fatal('Cannot mix -static and -shared') driver_tools.GetArch(required = True) inputs = env.get('INPUTS') output = env.getone('OUTPUT') if len(inputs) == 0: Log.Fatal("No input files") if output == '': Log.Fatal("Please specify output file with -o") # Find the bitcode file on the command line. bcfiles = [f for f in inputs if driver_tools.IsBitcode(f) or driver_tools.FileType(f) == 'll'] if len(bcfiles) > 1: Log.Fatal('Expecting at most 1 bitcode file') elif len(bcfiles) == 1: bcfile = bcfiles[0] else: bcfile = None # If there's a bitcode file, translate it now. tng = driver_tools.TempNameGen(inputs + bcfiles, output) output_type = env.getone('OUTPUT_TYPE') metadata = None if bcfile: sfile = None if output_type == 's': sfile = output elif env.getbool('FORCE_INTERMEDIATE_S'): sfile = tng.TempNameForInput(bcfile, 's') ofile = None if output_type == 'o': ofile = output elif output_type != 's': ofile = tng.TempNameForInput(bcfile, 'o') if sfile: RunLLC(bcfile, sfile, filetype='asm') if ofile: RunAS(sfile, ofile) else: RunLLC(bcfile, ofile, filetype='obj') else: ofile = None # If we've been told to stop after translation, stop now. if output_type in ('o','s'): return 0 # Replace the bitcode file with __BITCODE__ in the input list if bcfile: inputs = ListReplace(inputs, bcfile, '__BITCODE__') env.set('INPUTS', *inputs) # Get bitcode type and metadata if bcfile: # Until we stabilize the ABI for shared libraries, # assume that pnacl-translate only handles pexes # to avoid a dependency on bitcode metadata. assert not env.getbool('SHARED') bctype = driver_tools.GetBitcodeType(bcfile, True) metadata = driver_tools.GetBitcodeMetadata(bcfile, True) # Determine the output type, in this order of precedence: # 1) Output type can be specified on command-line (-S, -c, -shared, -static) # 2) If bitcode file given, use its output type. (pso->so, pexe->nexe, po->o) # 3) Otherwise, assume nexe output. if env.getbool('SHARED'): output_type = 'so' elif env.getbool('STATIC'): output_type = 'nexe' elif bcfile: DefaultOutputTypes = { 'pso' : 'so', 'pexe': 'nexe', 'po' : 'o', } output_type = DefaultOutputTypes[bctype] else: output_type = 'nexe' # If the bitcode is of type "object", no linking is required. if output_type == 'o': # Copy ofile to output Log.Info('Copying %s to %s' % (ofile, output)) shutil.copy(pathtools.tosys(ofile), pathtools.tosys(output)) return 0 if bcfile: ApplyBitcodeConfig(metadata, bctype) # NOTE: we intentionally delay setting STATIC here to give user choices # preference but we should think about dropping the support for # the -static, -shared flags in the translator and have everything # be determined by bctype if metadata is None: env.set('STATIC', '1') elif len(metadata['NeedsLibrary']) == 0 and not env.getbool('SHARED'): env.set('STATIC', '1') assert output_type in ('so','nexe') RunLD(ofile, output) return 0
def SetupCygwinLibs(): bindir = env.getone('DRIVER_BIN') os.environ['PATH'] += os.pathsep + pathtools.tosys(bindir)