def ReadConfig(): # Mock out ReadConfig if running unittests. Settings are applied directly # by DriverTestEnv rather than reading this configuration file. if env.has('PNACL_RUNNING_UNITTESTS'): return driver_bin = env.getone('DRIVER_BIN') driver_conf = pathtools.join(driver_bin, 'driver.conf') fp = DriverOpen(driver_conf, 'r') linecount = 0 for line in fp: linecount += 1 line = line.strip() if line == '' or line.startswith('#'): continue sep = line.find('=') if sep < 0: Log.Fatal("%s: Parse error, missing '=' on line %d", pathtools.touser(driver_conf), linecount) keyname = line[:sep].strip() value = line[sep + 1:].strip() env.setraw(keyname, value) DriverClose(fp) if env.getone('LIBMODE') not in ('newlib', 'glibc'): Log.Fatal('Invalid LIBMODE in %s', pathtools.touser(driver_conf))
def RunLDSandboxed(): 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') files = LinkerFiles(all_inputs) ld_flags = env.get('LD_FLAGS') script = MakeSelUniversalScriptForLD(ld_flags, main_input, files, outfile) Run('${SEL_UNIVERSAL_PREFIX} ${SEL_UNIVERSAL} ' + '${SEL_UNIVERSAL_FLAGS} -- ${LD_SB}', stdin_contents=script, # stdout/stderr will be automatically dumped # upon failure redirect_stderr=subprocess.PIPE, redirect_stdout=subprocess.PIPE)
def RunLLCSandboxed(): driver_tools.CheckTranslatorPrerequisites() infile = env.getone('input') outfile = env.getone('output') if not driver_tools.IsPNaClBitcode(infile): Log.Fatal('Input to sandboxed translator must be PNaCl bitcode') script = MakeSelUniversalScriptForLLC(infile, outfile) command = ( '${SEL_UNIVERSAL_PREFIX} ${SEL_UNIVERSAL} ${SEL_UNIVERSAL_FLAGS} ' '-- ${LLC_SB}') _, stdout, _ = driver_tools.Run( command, stdin_contents=script, # stdout/stderr will be automatically dumped # upon failure redirect_stderr=subprocess.PIPE, redirect_stdout=subprocess.PIPE) # Get the values returned from the llc RPC to use in input to ld is_shared = re.search(r'output\s+0:\s+i\(([0|1])\)', stdout).group(1) is_shared = (is_shared == '1') soname = re.search(r'output\s+1:\s+s\("(.*)"\)', stdout).group(1) needed_str = re.search(r'output\s+2:\s+s\("(.*)"\)', stdout).group(1) # If the delimiter changes, this line needs to change needed_libs = [lib for lib in needed_str.split(r'\n') if lib] return is_shared, soname, needed_libs
def MakeSelUniversalScriptForCompiler(infile, outfile, is_pnacl, use_sz): script = [] script.append('readwrite_file objfile %s' % outfile) if use_sz: modules = 1 threads = int(env.getone('SZ_THREADS')) toolname = 'pnacl-sz' else: modules = int(env.getone('SPLIT_MODULE')) threads = modules toolname = 'pnacl-llc' if modules > 1: script.extend(['readwrite_file objfile%d %s.module%d' % (m, outfile, m) for m in range(1, modules)]) stream_rate = int(env.getraw('BITCODE_STREAM_RATE')) assert stream_rate != 0 cmdline_len, cmdline_escaped = BuildOverrideCompilerCommandLine(is_pnacl, use_sz) assert modules in range(1, 17) script.append('rpc StreamInitWithSplit i(%d) h(objfile) ' % threads + ' '.join(['h(objfile%d)' % m for m in range(1, modules)] + ['h(invalid)' for x in range(modules, 16)]) + ' C(%d,%s) * s()' % (cmdline_len, cmdline_escaped)) # specify filename, chunk size and rate in bits/s script.append('stream_file %s %s %s' % (infile, 64 * 1024, stream_rate)) script.append('rpc StreamEnd * i() s() s() s()') script.append('echo "%s complete"' % toolname) script.append('') return '\n'.join(script)
def ReadConfig(): # Mock out ReadConfig if running unittests. Settings are applied directly # by DriverTestEnv rather than reading this configuration file. if env.has('PNACL_RUNNING_UNITTESTS'): return driver_bin = env.getone('DRIVER_BIN') driver_conf = pathtools.join(driver_bin, 'driver.conf') fp = DriverOpen(driver_conf, 'r') linecount = 0 for line in fp: linecount += 1 line = line.strip() if line == '' or line.startswith('#'): continue sep = line.find('=') if sep < 0: Log.Fatal("%s: Parse error, missing '=' on line %d", pathtools.touser(driver_conf), linecount) keyname = line[:sep].strip() value = line[sep+1:].strip() env.setraw(keyname, value) DriverClose(fp) if env.getone('LIBMODE') not in ('newlib', 'glibc'): Log.Fatal('Invalid LIBMODE in %s', pathtools.touser(driver_conf))
def RunSandboxedCompiler(use_sz): driver_tools.CheckTranslatorPrerequisites() infile = env.getone('input') is_pnacl = filetype.IsPNaClBitcode(infile) if not is_pnacl and not env.getbool('ALLOW_LLVM_BITCODE_INPUT'): Log.Fatal('Translator expects finalized PNaCl bitcode. ' 'Pass --allow-llvm-bitcode-input to override.') threads = int(env.getone('SPLIT_MODULE')) command = [driver_tools.SelLdrCommand(), '-a', # Allow file access '-E NACL_IRT_PNACL_TRANSLATOR_COMPILE_INPUT=%s' % infile] driver_tools.AddListToEnv(command, 'NACL_IRT_PNACL_TRANSLATOR_COMPILE_OUTPUT', GetObjectFiles(use_sz)) driver_tools.AddListToEnv(command, 'NACL_IRT_PNACL_TRANSLATOR_COMPILE_ARG', BuildOverrideCompilerCommandLine(is_pnacl, use_sz)) command.extend(['-E NACL_IRT_PNACL_TRANSLATOR_COMPILE_THREADS=%d' % threads, '--']) if use_sz: command.append('${PNACL_SZ_SB}') else: command.append('${LLC_SB}') driver_tools.Run(' '.join(command), # stdout/stderr will be automatically dumped # upon failure redirect_stderr=subprocess.PIPE, redirect_stdout=subprocess.PIPE)
def SetUpArch(): base_arch = env.getone('BASE_ARCH') env.set('TARGET_OS', 'nacl') if base_arch.endswith('_LINUX'): base_arch = base_arch[:-len('_LINUX')] env.set('TARGET_OS', 'linux') elif base_arch.endswith('_MAC'): base_arch = base_arch[:-len('_MAC')] env.set('TARGET_OS', 'mac') if env.getbool('NONSFI_NACL'): triple_map = { 'nacl': {'X8632': 'i686-linux-gnu', 'ARM': 'armv7a-linux-gnueabihf'}} else: triple_map = { 'nacl': {'X8632': 'i686-none-nacl-gnu', 'X8664': 'x86_64-none-nacl-gnu', 'ARM': 'armv7a-none-nacl-gnueabihf', 'MIPS32': 'mipsel-none-nacl-gnu'}, 'linux': {'X8632': 'i686-linux-gnu'}, 'mac': {'X8632': 'i686-apple-darwin'}} env.set('TRIPLE', triple_map[env.getone('TARGET_OS')][base_arch]) # CPU that is representative of baseline feature requirements for NaCl # and/or chrome. We may want to make this more like "-mtune" # by specifying both "-mcpu=X" and "-mattr=+feat1,-feat2,...". # Note: this may be different from the in-browser translator, which may # do auto feature detection based on CPUID, but constrained by what is # accepted by NaCl validators. cpu_map = { 'X8632': 'pentium4', 'X8664': 'core2', 'ARM': 'cortex-a9', 'MIPS32': 'mips32r2'} env.set('LLC_MCPU', '-mcpu=%s' % cpu_map[base_arch]) llc_flags_map = { 'ARM': ['-arm-reserve-r9', '-sfi-disable-cp', '-sfi-load', '-sfi-store', '-sfi-stack', '-sfi-branch', '-sfi-data', '-no-inline-jumptables', '-float-abi=hard', '-mattr=+neon'], # Once PNaCl's build of compiler-rt (libgcc.a) defines __aeabi_* # functions, we can drop the following ad-hoc option. 'ARM_NONSFI': ['-arm-enable-aeabi-functions=0'], 'MIPS32': ['-sfi-load', '-sfi-store', '-sfi-stack', '-sfi-branch', '-sfi-data']} env.set('LLC_FLAGS_ARCH', *llc_flags_map.get(env.getone('ARCH'), [])) # When linking against a host OS's libc (such as Linux glibc), don't # use %gs:0 to read the thread pointer because that won't be # compatible with the libc's use of %gs:0. Similarly, Non-SFI Mode # currently offers no optimized path for reading the thread pointer. if env.getone('TARGET_OS') != 'nacl' or env.getbool('NONSFI_NACL'): env.append('LLC_FLAGS_ARCH', '-mtls-use-call')
def RunHostLD(infile, outfile): if env.getone('TARGET_OS') == 'linux': driver_tools.Run(['objcopy', '--redefine-sym', '_start=_user_start', infile]) lib_dir = (env.getone('BASE_LIB_NATIVE') + 'x86-32-%s' % env.getone('TARGET_OS')) args = ['gcc', '-m32', infile, '-o', outfile, os.path.join(lib_dir, 'unsandboxed_irt.o'), '-lpthread'] if env.getone('TARGET_OS') == 'linux': args.append('-lrt') # For clock_gettime() driver_tools.Run(args)
def FindBaseHost(tool): """ Find the base directory for host binaries (i.e. llvm/binutils) """ if env.has('BPREFIXES'): for prefix in env.get('BPREFIXES'): if os.path.exists(pathtools.join(prefix, 'bin', tool + env.getone('EXEC_EXT'))): return prefix base_pnacl = FindBasePNaCl() if not pathtools.exists(pathtools.join(base_pnacl, 'bin', tool + env.getone('EXEC_EXT'))): Log.Fatal('Could not find PNaCl host directory for ' + tool) return base_pnacl
def RunHostLD(infile, outfile): if env.getone('TARGET_OS') == 'linux': driver_tools.Run( ['objcopy', '--redefine-sym', '_start=_user_start', infile]) lib_dir = (env.getone('BASE_LIB_NATIVE') + 'x86-32-%s' % env.getone('TARGET_OS')) args = [ 'gcc', '-m32', infile, '-o', outfile, os.path.join(lib_dir, 'unsandboxed_irt.o'), '-lpthread' ] if env.getone('TARGET_OS') == 'linux': args.append('-lrt') # For clock_gettime() driver_tools.Run(args)
def GetObjectFiles(use_sz): if use_sz: # Subzero only creates one object file when using multiple threads. # Note that, with Subzero, specifying more object files here would # work, but it would be unnecessary: The IRT interface used by the # sandboxed translator would create the extra object files, but they # would be left as empty. obj_file_count = 1 else: obj_file_count = int(env.getone('SPLIT_MODULE')) base_filename = env.getone('output') return ([base_filename] + ['%s.module%d' % (base_filename, number) for number in xrange(1, obj_file_count)])
def RunLLCSandboxed(): driver_tools.CheckTranslatorPrerequisites() infile = env.getone('input') outfile = env.getone('output') if not filetype.IsPNaClBitcode(infile): Log.Fatal('Input to sandboxed translator must be PNaCl bitcode') script = MakeSelUniversalScriptForLLC(infile, outfile) command = ('${SEL_UNIVERSAL_PREFIX} ${SEL_UNIVERSAL} ${SEL_UNIVERSAL_FLAGS} ' '-- ${LLC_SB}') driver_tools.Run(command, stdin_contents=script, # stdout/stderr will be automatically dumped # upon failure redirect_stderr=subprocess.PIPE, redirect_stdout=subprocess.PIPE)
def get_help(unused_argv): return """ Usage: %s [-]{dmpqrstx}[abcDfilMNoPsSTuvV] [member-name] [count] archive-file file... commands: d - delete file(s) from the archive m[ab] - move file(s) in the archive p - print file(s) found in the archive q[f] - quick append file(s) to the archive r[ab][f][u] - replace existing or insert new file(s) into the archive s - act as ranlib t - display contents of archive x[o] - extract file(s) from the archive command specific modifiers: [a] - put file(s) after [member-name] [b] - put file(s) before [member-name] (same as [i]) [D] - use zero for timestamps and uids/gids [N] - use instance [count] of name [f] - truncate inserted file names [P] - use full path names when matching [o] - preserve original dates [u] - only replace files that are newer than current archive contents generic modifiers: [c] - do not warn if the library had to be created [s] - create an archive index (cf. ranlib) [S] - do not build a symbol table [T] - make a thin archive [v] - be verbose [V] - display the version number @<file> - read options from <file> """ % env.getone('SCRIPT_NAME')
def main(argv): env.update(EXTRA_ENV) driver_tools.ParseArgs(argv, PrepPatterns) inputs = env.get('INPUTS') output = env.getone('OUTPUT') if len(inputs) != 1: Log.Fatal('Can only have one input') f_input = inputs[0] # Allow in-place file changes if output isn't specified.. if output != '': f_output = output else: f_output = f_input if env.getbool('DISABLE_FINALIZE') or filetype.IsPNaClBitcode(f_input): # Just copy the input file to the output file. if f_input != f_output: shutil.copyfile(f_input, f_output) return 0 opt_flags = ['-disable-opt', '-strip', '-strip-metadata', '--bitcode-format=pnacl', f_input, '-o', f_output] # Transform the file, and convert it to a PNaCl bitcode file. driver_tools.RunDriver('opt', opt_flags) # Compress the result if requested. if env.getbool('COMPRESS'): driver_tools.RunDriver('compress', [f_output]) return 0
def GetBitcodeMetadata(filename, assume_pexe): assert(IsBitcode(filename)) # The argument |assume_pexe| helps break a dependency on bitcode metadata, # as the shared library metadata is not finalized yet. if assume_pexe: return { 'OutputFormat': 'executable', 'SOName' : '', 'NeedsLibrary': [] } global FORCED_METADATA if filename in FORCED_METADATA: return FORCED_METADATA[filename] llvm_dis = env.getone('LLVM_DIS') args = [ llvm_dis, '-dump-metadata', filename ] _, stdout_contents, _ = Run(args, redirect_stdout=subprocess.PIPE) metadata = { 'OutputFormat': '', 'SOName' : '', 'NeedsLibrary': [] } for line in stdout_contents.split('\n'): if not line.strip(): continue k, v = line.split(':') k = k.strip() v = v.strip() if k.startswith('NeededRecord_'): metadata[k] = '' assert(k in metadata) if isinstance(metadata[k], list): metadata[k].append(v) else: metadata[k] = v return metadata
def main(argv): env.update(EXTRA_ENV) ParseArgs(argv, LDPatterns) GetArch(required=True) inputs = env.get('INPUTS') output = env.getone('OUTPUT') if output == '': output = pathtools.normalize('a.out') # Expand all parameters # This resolves -lfoo into actual filenames, # and expands linker scripts into command-line arguments. inputs = ldtools.ExpandInputs(inputs, env.get('SEARCH_DIRS'), env.getbool('STATIC'), ldtools.LibraryTypes.NATIVE) env.push() env.set('inputs', *inputs) env.set('output', output) if env.getbool('SANDBOXED'): RunLDSandboxed() else: Run('${RUN_LD}') env.pop() # only reached in case of no errors return 0
def main(argv): env.update(EXTRA_ENV) driver_tools.ParseArgs(argv, StripPatterns) inputs = env.get('INPUTS') output = env.getone('OUTPUT') if len(inputs) > 1 and output != '': Log.Fatal('Cannot have -o with multiple inputs') if '--info' in env.get('STRIP_FLAGS'): code, _, _ = driver_tools.Run('${STRIP} ${STRIP_FLAGS}') return code for f in inputs: if output != '': f_output = output else: f_output = f if driver_tools.IsBitcode(f): driver_tools.RunWithEnv('${RUN_OPT}', input=f, output=f_output) if env.getbool('DO_WRAP'): driver_tools.WrapBitcode(f_output) elif driver_tools.IsELF(f): driver_tools.RunWithEnv('${RUN_STRIP}', input=f, output=f_output) else: Log.Fatal('%s: File is neither ELF nor bitcode', pathtools.touser(f)) return 0
def main(argv): env.update(EXTRA_ENV) driver_tools.ParseArgs(argv, PrepPatterns) inputs = env.get('INPUTS') output = env.getone('OUTPUT') if len(inputs) != 1: Log.Fatal('Can only have one input') f_input = inputs[0] # Allow in-place file changes if output isn't specified.. if output != '': f_output = output else: f_output = f_input if env.getbool('DISABLE_FINALIZE'): # Just copy the input file to the output file. if f_input != f_output: shutil.copyfile(f_input, f_output) return 0 # Transform the file, and convert it to a PNaCl bitcode file. driver_tools.RunWithEnv(' '.join(['${RUN_OPT}', '--bitcode-format=pnacl']), input=inputs[0], output=f_output) return 0
def main(argv): env.update(EXTRA_ENV) driver_tools.ParseArgs(argv, StripPatterns) inputs = env.get('INPUTS') output = env.getone('OUTPUT') if len(inputs) > 1 and output != '': Log.Fatal('Cannot have -o with multiple inputs') if '--info' in env.get('STRIP_FLAGS'): code, _, _ = driver_tools.Run('${STRIP} ${STRIP_FLAGS}') return code for f in inputs: if output != '': f_output = output else: f_output = f if driver_tools.IsBitcode(f): driver_tools.RunWithEnv('${RUN_OPT}', input=f, output=f_output) if env.getbool('DO_WRAP'): driver_tools.WrapBitcode(f_output) elif driver_tools.IsELF(f) or driver_tools.IsNativeArchive(f): driver_tools.RunWithEnv('${RUN_STRIP}', input=f, output=f_output) elif driver_tools.IsBitcodeArchive(f): # The strip tool supports native archives, but it does not support the # LLVM gold plugin so cannot handle bitcode. There is also no bitcode # tool like opt that support archives. Log.Fatal('%s: strip does not support bitcode archives', pathtools.touser(f)) else: Log.Fatal('%s: File is neither ELF, nor bitcode', pathtools.touser(f)) return 0
def GetBitcodeMetadata(filename): assert(IsBitcode(filename)) global FORCED_METADATA if filename in FORCED_METADATA: return FORCED_METADATA[filename] llvm_dis = env.getone('LLVM_DIS') args = [ llvm_dis, '-dump-metadata', filename ] _, stdout_contents, _ = Run(args, redirect_stdout=subprocess.PIPE) metadata = { 'OutputFormat': '', 'SOName' : '', 'NeedsLibrary': [] } for line in stdout_contents.split('\n'): if not line.strip(): continue k, v = line.split(':') k = k.strip() v = v.strip() if k.startswith('NeededRecord_'): metadata[k] = '' assert(k in metadata) if isinstance(metadata[k], list): metadata[k].append(v) else: metadata[k] = v return metadata
def CheckTranslatorPrerequisites(): """ Assert that the scons artifacts for running the sandboxed translator exist: sel_universal, and sel_ldr. """ for var in ['SEL_UNIVERSAL', 'SEL_LDR', 'BOOTSTRAP_LDR']: needed_file = env.getone(var) if not pathtools.exists(needed_file): Log.Fatal('Could not find %s [%s]', var, needed_file)
def main(argv): env.update(EXTRA_ENV) driver_tools.ParseArgs(argv, PrepPatterns) inputs = env.get('INPUTS') output = env.getone('OUTPUT') if len(inputs) != 1: Log.Fatal('Can only have one input') f_input = inputs[0] # Allow in-place file changes if output isn't specified.. if output != '': f_output = output else: f_output = f_input if env.getbool('DISABLE_FINALIZE') or filetype.IsPNaClBitcode(f_input): # Just copy the input file to the output file. if f_input != f_output: shutil.copyfile(f_input, f_output) return 0 opt_flags = ['-disable-opt', '-strip', '-strip-metadata', '--bitcode-format=pnacl', f_input, '-o', f_output] # Transform the file, and convert it to a PNaCl bitcode file. driver_tools.RunDriver('opt', opt_flags) return 0
def GetBitcodeMetadata(filename, assume_pexe=False): assert (IsPNaClBitcode(filename) or IsLLVMBitcode(filename)) # The argument |assume_pexe| helps break a dependency on bitcode metadata, # as the shared library metadata is not finalized yet. if assume_pexe: return {'OutputFormat': 'executable', 'SOName': '', 'NeedsLibrary': []} global FORCED_METADATA if filename in FORCED_METADATA: return FORCED_METADATA[filename] llvm_dis = env.getone('LLVM_DIS') args = [llvm_dis, '-dump-metadata', filename] if IsPNaClBitcode(filename): args += ['-bitcode-format=pnacl'] _, stdout_contents, _ = Run(args, redirect_stdout=subprocess.PIPE) metadata = {'OutputFormat': '', 'SOName': '', 'NeedsLibrary': []} for line in stdout_contents.split('\n'): if not line.strip(): continue k, v = line.split(':') k = k.strip() v = v.strip() if k.startswith('NeededRecord_'): metadata[k] = '' assert (k in metadata) if isinstance(metadata[k], list): metadata[k].append(v) else: metadata[k] = v return metadata
def main(argv): env.update(EXTRA_ENV) driver_tools.ParseArgs(argv, StripPatterns) inputs = env.get('INPUTS') output = env.getone('OUTPUT') if len(inputs) > 1 and output != '': Log.Fatal('Cannot have -o with multiple inputs') if '--info' in env.get('STRIP_FLAGS'): code, _, _ = driver_tools.Run('${STRIP} ${STRIP_FLAGS}') return code for f in inputs: if output != '': f_output = output else: f_output = f if driver_tools.IsLLVMBitcode(f): driver_tools.RunWithEnv('${RUN_OPT}', input=f, output=f_output) elif driver_tools.IsELF(f) or driver_tools.IsNativeArchive(f): driver_tools.RunWithEnv('${RUN_STRIP}', input=f, output=f_output) elif driver_tools.IsBitcodeArchive(f): # The strip tool supports native archives, but it does not support the # LLVM gold plugin so cannot handle bitcode. There is also no bitcode # tool like opt that support archives. Log.Fatal('%s: strip does not support bitcode archives', pathtools.touser(f)) else: Log.Fatal('%s: File is neither ELF, nor bitcode', pathtools.touser(f)) return 0
def main(argv): env.update(EXTRA_ENV) driver_tools.ParseArgs(argv, DISPatterns) inputs = env.get('INPUTS') output = env.getone('OUTPUT') if len(inputs) == 0: Log.Fatal("No input files given") if len(inputs) > 1 and output != '': Log.Fatal("Cannot have -o with multiple inputs") for infile in inputs: env.push() env.set('input', infile) env.set('output', output) # When we output to stdout, set redirect_stdout and set log_stdout # to False to bypass the driver's line-by-line handling of stdout # which is extremely slow when you have a lot of output if (filetype.IsLLVMBitcode(infile) or filetype.IsPNaClBitcode(infile)): bitcodetype = 'PNaCl' if filetype.IsPNaClBitcode( infile) else 'LLVM' format = bitcodetype.lower() if env.has('FILE_TYPE'): sys.stdout.write('%s: %s bitcode\n' % (infile, bitcodetype)) continue env.append('FLAGS', '-bitcode-format=' + format) if output == '': # LLVM by default outputs to a file if -o is missing # Let's instead output to stdout env.set('output', '-') env.append('FLAGS', '-f') driver_tools.Run('${LLVM_DIS} ${FLAGS} ${input} -o ${output}') elif filetype.IsELF(infile): if env.has('FILE_TYPE'): sys.stdout.write('%s: ELF\n' % infile) continue flags = env.get('FLAGS') if len(flags) == 0: env.append('FLAGS', '-d') if output == '': # objdump to stdout driver_tools.Run('"${OBJDUMP}" ${FLAGS} ${input}') else: # objdump always outputs to stdout, and doesn't recognize -o # Let's add this feature to be consistent. fp = DriverOpen(output, 'w') driver_tools.Run('${OBJDUMP} ${FLAGS} ${input}', redirect_stdout=fp) DriverClose(fp) else: Log.Fatal('Unknown file type') env.pop() # only reached in case of no errors return 0
def RunLLCSandboxed(): driver_tools.CheckTranslatorPrerequisites() infile = env.getone('input') outfile = env.getone('output') is_pnacl = filetype.IsPNaClBitcode(infile) if not is_pnacl and not env.getbool('ALLOW_LLVM_BITCODE_INPUT'): Log.Fatal('Translator expects finalized PNaCl bitcode. ' 'Pass --allow-llvm-bitcode-input to override.') script = MakeSelUniversalScriptForLLC(infile, outfile, is_pnacl) command = ('${SEL_UNIVERSAL_PREFIX} ${SEL_UNIVERSAL} ${SEL_UNIVERSAL_FLAGS} ' '-- ${LLC_SB}') driver_tools.Run(command, stdin_contents=script, # stdout/stderr will be automatically dumped # upon failure redirect_stderr=subprocess.PIPE, redirect_stdout=subprocess.PIPE)
def RunLLCSandboxed(): driver_tools.CheckTranslatorPrerequisites() infile = env.getone('input') outfile = env.getone('output') if not filetype.IsPNaClBitcode(infile): Log.Fatal('Input to sandboxed translator must be PNaCl bitcode') script = MakeSelUniversalScriptForLLC(infile, outfile) command = ( '${SEL_UNIVERSAL_PREFIX} ${SEL_UNIVERSAL} ${SEL_UNIVERSAL_FLAGS} ' '-- ${LLC_SB}') driver_tools.Run( command, stdin_contents=script, # stdout/stderr will be automatically dumped # upon failure redirect_stderr=subprocess.PIPE, redirect_stdout=subprocess.PIPE)
def RunHostLD(infile, outfile): driver_tools.Run(['objcopy', '--redefine-sym', '_start=_user_start', infile]) lib_dir = env.getone('BASE_LIB_NATIVE') + 'linux-x86-32' driver_tools.Run(['gcc', '-m32', infile, os.path.join(lib_dir, 'unsandboxed_irt.o'), '-lpthread', '-lrt', # For clock_gettime() '-o', outfile])
def main(argv): env.update(EXTRA_ENV) driver_tools.ParseArgs(argv, PATTERNS) driver_tools.Run( '"${LLVM_OPT}" ${ARGS} ' + '${DISABLE_SIMPLIFY_LIBCALLS ? -disable-simplify-libcalls} ' + '${HAVE_OUTPUT ? -o ${OUTPUT}} ' + '${INPUT}') # Opt is the only tool that will modify a file in-place. If this happens we # need to clear the filetype cache so future invocations of the type checking # routines will re-check the file. if env.getone('INPUT') == env.getone('OUTPUT'): filetype.ClearFileTypeCaches() # only reached in case of no errors return 0
def main(argv): env.update(EXTRA_ENV) driver_tools.ParseArgs(argv, DISPatterns) inputs = env.get('INPUTS') output = env.getone('OUTPUT') if len(inputs) == 0: Log.Fatal("No input files given") if len(inputs) > 1 and output != '': Log.Fatal("Cannot have -o with multiple inputs") for infile in inputs: env.push() env.set('input', infile) env.set('output', output) # When we output to stdout, set redirect_stdout and set log_stdout # to False to bypass the driver's line-by-line handling of stdout # which is extremely slow when you have a lot of output if (filetype.IsLLVMBitcode(infile) or filetype.IsPNaClBitcode(infile)): bitcodetype = 'PNaCl' if filetype.IsPNaClBitcode(infile) else 'LLVM' format = bitcodetype.lower() if env.has('FILE_TYPE'): sys.stdout.write('%s: %s bitcode\n' % (infile, bitcodetype)) continue env.append('FLAGS', '-bitcode-format=' + format) if output == '': # LLVM by default outputs to a file if -o is missing # Let's instead output to stdout env.set('output', '-') env.append('FLAGS', '-f') driver_tools.Run('${LLVM_DIS} ${FLAGS} ${input} -o ${output}') elif filetype.IsELF(infile): if env.has('FILE_TYPE'): sys.stdout.write('%s: ELF\n' % infile) continue flags = env.get('FLAGS') if len(flags) == 0: env.append('FLAGS', '-d') if output == '': # objdump to stdout driver_tools.Run('"${OBJDUMP}" ${FLAGS} ${input}') else: # objdump always outputs to stdout, and doesn't recognize -o # Let's add this feature to be consistent. fp = DriverOpen(output, 'w') driver_tools.Run('${OBJDUMP} ${FLAGS} ${input}', redirect_stdout=fp) DriverClose(fp) else: Log.Fatal('Unknown file type') env.pop() # only reached in case of no errors return 0
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 GetArch(required = False): arch = env.getone('ARCH') if arch == '': arch = None if required and not arch: Log.Fatal('Missing -arch!') return arch
def get_help(unused_argv): return """ Usage: %s [option(s)] [file(s)] List symbols in [file(s)]. * For stable PNaCl bitcode files, this calls the llvm-nm tool. * For all other files, this calls the standard nm from binutils - please see that tool's help pages for options. """ % env.getone('SCRIPT_NAME')
def FindBaseDir(function): Depth = 0 cur = env.getone('DRIVER_BIN') while not function(cur) and Depth < 16: cur = pathtools.dirname(cur) Depth += 1 if function(cur): return cur return None
def get_help(unused_argv): return """ Usage: %s [options] archive Generate an index to speed access to archives The options are: @<file> Read options from <file> -t Update the archive's symbol map timestamp -h --help Print this help message -v --version Print version information """ % env.getone('SCRIPT_NAME')
def get_help(unused_argv): script = env.getone('SCRIPT_NAME') return """Usage: %s <options> in-file This tool prepares a PNaCl bitcode application for ABI stability. The options are: -h --help Display this output -o <file> Place the output into <file>. Otherwise, the input file is modified in-place. """ % script
def RunHostLD(infile, outfile): if env.getone('TARGET_OS') == 'linux': driver_tools.Run(['objcopy', '--redefine-sym', '_start=_user_start', infile]) lib_dir = (env.getone('BASE_LIB_NATIVE') + 'x86-32-%s/lib' % env.getone('TARGET_OS')) # TODO(stichnot): Consider making fully linked executable smaller by packaging # the .o files into an archive, and/or building the .o files with # -function-sections and linking with -gc-sections. args = ['gcc', '-m32', infile, '-o', outfile, os.path.join(lib_dir, 'unsandboxed_irt.o'), os.path.join(lib_dir, 'irt_random.o'), os.path.join(lib_dir, 'irt_query_list.o'), os.path.join(lib_dir, 'szrt.o'), os.path.join(lib_dir, 'szrt_ll.o'), '-lm', '-lpthread'] if env.getone('TARGET_OS') == 'linux': args.append('-lrt') # For clock_gettime() driver_tools.Run(args)
def RunLLCSandboxed(): driver_tools.CheckTranslatorPrerequisites() infile = env.getone('input') outfile = env.getone('output') is_pnacl = filetype.IsPNaClBitcode(infile) if not is_pnacl and not env.getbool('ALLOW_LLVM_BITCODE_INPUT'): Log.Fatal('Translator expects finalized PNaCl bitcode. ' 'Pass --allow-llvm-bitcode-input to override.') script = MakeSelUniversalScriptForLLC(infile, outfile, is_pnacl) command = ( '${SEL_UNIVERSAL_PREFIX} ${SEL_UNIVERSAL} ${SEL_UNIVERSAL_FLAGS} ' '-- ${LLC_SB}') driver_tools.Run( command, stdin_contents=script, # stdout/stderr will be automatically dumped # upon failure redirect_stderr=subprocess.PIPE, redirect_stdout=subprocess.PIPE)
def ReadDriverRevision(): rev_file = env.getone('DRIVER_REV_FILE') nacl_ver = DriverOpen(rev_file, 'rb').readlines()[0] m = re.search(r'\[GIT\].*/native_client(?:\.git)?:\s*([0-9a-f]{40})', nacl_ver) if m: return m.group(1) # fail-fast: if the REV file exists but regex search failed, # we need to fix the regex to get nacl-version. if not m: Log.Fatal('Failed to parse REV file to get nacl-version.')
def main(argv): env.update(EXTRA_ENV) ParseArgs(argv, LDPatterns) GetArch(required=True) inputs = env.get('INPUTS') output = env.getone('OUTPUT') if output == '': output = pathtools.normalize('a.out') # As we will modify the output file in-place for non-SFI, we output # the file to a temporary file first and then rename it. Otherwise, # build systems such as make assume the output file is ready even # if the last build failed during the in-place update. tmp_output = output + '.tmp' # Expand all parameters # This resolves -lfoo into actual filenames, # and expands linker scripts into command-line arguments. inputs = ldtools.ExpandInputs(inputs, env.get('SEARCH_DIRS'), True, ldtools.LibraryTypes.NATIVE) env.push() env.set('inputs', *inputs) env.set('output', tmp_output) if env.getbool('SANDBOXED'): RunLDSandboxed() else: Run('${RUN_LD}') if env.getbool('NONSFI_NACL'): # Remove PT_INTERP in non-SFI binaries as we never use host's # dynamic linker/loader. # # This is necessary otherwise we get a statically linked # executable that is not directly runnable by Linux, because Linux # tries to load the non-existent file that PT_INTERP points to. # # This is fairly hacky. It would be better if the linker provided # an option for omitting PT_INTERP (e.g. "--dynamic-linker ''"). RemoveInterpProgramHeader(tmp_output) if driver_tools.IsWindowsPython() and os.path.exists(output): # On Windows (but not on Unix), the os.rename() call would fail if the # output file already exists. os.remove(output) os.rename(tmp_output, output) env.pop() # only reached in case of no errors return 0
def BuildOverrideLLCCommandLine(): extra_flags = env.get('LLC_FLAGS_EXTRA') # The mcpu is not part of the default flags, so append that too. mcpu = env.getone('LLC_MCPU') if mcpu: extra_flags.append(mcpu) # command_line is a NUL (\x00) terminated sequence. kTerminator = '\0' command_line = kTerminator.join(extra_flags) + kTerminator command_line_escaped = command_line.replace(kTerminator, '\\x00') return len(command_line), command_line_escaped
def CheckTranslatorPrerequisites(): """ Assert that the scons artifacts for running the sandboxed translator exist: sel_universal, and sel_ldr. """ reqs = ['SEL_UNIVERSAL', 'SEL_LDR'] # Linux also requires the nacl bootstrap helper. if GetBuildOS() == 'linux': reqs.append('BOOTSTRAP_LDR') for var in reqs: needed_file = env.getone(var) if not pathtools.exists(needed_file): Log.Fatal('Could not find %s [%s]', var, needed_file)
def get_help(unused_argv): script = env.getone('SCRIPT_NAME') return """Usage: %s <options> in-file This tool prepares a PNaCl bitcode application for ABI stability. The options are: -h --help Display this output -o <file> Place the output into <file>. Otherwise, the input file is modified in-place. --no-finalize Don't run preparation steps (just copy in -> out). """ % script
def get_help(argv): tool = env.getone('SCRIPT_NAME') if '--help-full' in argv: # To get ${CC}, etc. env.update(EXTRA_ENV) code, stdout, stderr = Run('"${CC}" -help', redirect_stdout=subprocess.PIPE, redirect_stderr=subprocess.STDOUT, errexit=False) return stdout else: return """ This is a "GCC-compatible" driver using clang under the hood. Usage: %s [options] <inputs> ... BASIC OPTIONS: -o <file> Output to <file>. -E Only run the preprocessor. -S Generate bitcode assembly. -c Generate bitcode object. -I <dir> Add header search path. -L <dir> Add library search path. -D<key>[=<val>] Add definition for the preprocessor. -W<id> Toggle warning <id>. -f<feature> Enable <feature>. -Wl,<arg> Pass <arg> to the linker. -Xlinker <arg> Pass <arg> to the linker. -Wt,<arg> Pass <arg> to the translator. -Xtranslator <arg> Pass <arg> to the translator. -Wp,<arg> Pass <arg> to the preprocessor. -Xpreprocessor,<arg> Pass <arg> to the preprocessor. -x <language> Treat subsequent input files as having type <language>. -static Produce a static executable. -shared Produce a shared object. -Bstatic Link subsequent libraries statically. -Bdynamic Link subsequent libraries dynamically. -fPIC Ignored (only used by translator backend) (accepted for compatibility). -pipe Ignored (for compatibility). -O<n> Optimation level <n>: 0, 1, 2, 3, 4 or s. -g Generate complete debug information. -gline-tables-only Generate debug line-information only (allowing for stack traces). -flimit-debug-info Generate limited debug information. -save-temps Keep intermediate compilation results. -v Verbose output / show commands. -h | --help Show this help. --help-full Show underlying clang driver's help message (warning: not all options supported). """ % (tool)
def BuildOverrideCompilerCommandLine(is_pnacl, use_sz): if use_sz: # Subzero doesn't allow -mcpu=X tuning, only -mattr=X. extra_flags = env.get('SZ_FLAGS_EXTRA') else: extra_flags = env.get('LLC_FLAGS_EXTRA') # The mcpu is not part of the default flags, so append that too. mcpu = env.getone('LLC_MCPU') if mcpu: extra_flags.append(mcpu) if not is_pnacl: extra_flags.append('-bitcode-format=llvm') return extra_flags