Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
def main(argv):
  env.update(EXTRA_ENV)
  ParseArgs(argv, PATTERNS)
  inputs = env.get('INPUTS')
  if len(inputs) == 0:
    Log.Fatal("No input files given")

  for infile in inputs:
    env.push()
    env.set('input', infile)
    if filetype.IsLLVMBitcode(infile):
      # Hack to support newlib build.
      # Newlib determines whether the toolchain supports .init_array, etc., by
      # compiling a small test and looking for a specific section tidbit using
      # "readelf -S". Since pnacl compiles to bitcode, readelf isn't available.
      # (there is a line: "if ${READELF} -S conftest | grep -e INIT_ARRAY"
      # in newlib's configure file).
      # TODO(sehr): we may want to implement a whole readelf on bitcode.
      flags = env.get('FLAGS')
      if len(flags) == 1 and flags[0] == '-S':
        print 'INIT_ARRAY'
        return 0
      Log.Fatal('Cannot handle pnacl-readelf %s' % str(argv))
      return 1
    Run('"${READELF}" ${FLAGS} ${input}')
    env.pop()

  # only reached in case of no errors
  return 0
Ejemplo n.º 3
0
def main(argv):
    if len(argv) == 0:
        print get_help(argv)
        return 1

    env.update(EXTRA_ENV)
    ParseArgs(argv, PATTERNS)
    Run('"${RANLIB}" --plugin=${GOLD_PLUGIN_SO} ${ARGS}')
    # only reached in case of no errors
    return 0
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
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 (the default).
  -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)
Ejemplo n.º 6
0
def main(argv):
  env.set('ARGS', *argv)
  if filetype.IsLLVMBitcode(argv[1]):
    # Hack to support newlib build.
    # Newlib determines whether the toolchain supports .init_array, etc., by
    # compiling a small test and looking for a specific section tidbit using
    # readelf.  Since pnacl compiles to bitcode, readelf isn't available.
    # TODO(sehr): we may want to implement a whole readelf on bitcode.
    if len(argv) == 2 and argv[0] == '-S':
      print 'INIT_ARRAY'
      return 0
    return 1
  Run('${READELF} ${ARGS}')
  # only reached in case of no errors
  return 0
Ejemplo n.º 7
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:]

    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)
Ejemplo n.º 8
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'))
    if modules > 1:
        first_mainfile = all_inputs.index(main_input)
        first_extra = all_inputs.index(main_input) + modules
        # Just the split module files
        llc_outputs = all_inputs[first_mainfile:first_extra]
        # everything else
        all_inputs = all_inputs[:first_mainfile] + all_inputs[first_extra:]
    else:
        llc_outputs = [main_input]

    files = LinkerFiles(all_inputs)
    ld_flags = env.get('LD_FLAGS')

    script = MakeSelUniversalScriptForLD(ld_flags, llc_outputs, 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)
Ejemplo n.º 9
0
def main(argv):
  env.update(EXTRA_ENV)
  CheckSetup()
  ParseArgs(argv, CustomPatterns + GCCPatterns)

  # "configure", especially when run as part of a toolchain bootstrap
  # process, will invoke gcc with various diagnostic options and
  # parse the output. In these cases we do not alter the incoming
  # commandline. It is also important to not emit spurious messages.
  if env.getbool('DIAGNOSTIC'):
    if env.getbool('SHOW_VERSION'):
      code, stdout, stderr = Run(env.get('CC') + env.get('CC_FLAGS'),
                                 redirect_stdout=subprocess.PIPE)
      out = stdout.split('\n')
      nacl_version = ReadDriverRevision()
      out[0] += ' nacl-version=%s' % nacl_version
      stdout = '\n'.join(out)
      print stdout,
    else:
      Run(env.get('CC') + env.get('CC_FLAGS'))
    return 0

  unmatched = env.get('UNMATCHED')
  if len(unmatched) > 0:
    UnrecognizedOption(*unmatched)

  # If -arch was given, we are compiling directly to native code
  compiling_to_native = GetArch() is not None

  if env.getbool('ALLOW_NATIVE') and not compiling_to_native:
    Log.Fatal("--pnacl-allow-native without -arch is not meaningful.")

  if not env.get('STDLIB'):
    # Default C++ Standard Library.
    SetStdLib('libc++')

  inputs = env.get('INPUTS')
  output = env.getone('OUTPUT')

  if len(inputs) == 0:
    if env.getbool('VERBOSE'):
      # -v can be invoked without any inputs. Runs the original
      # command without modifying the commandline for this case.
      Run(env.get('CC') + env.get('CC_FLAGS'))
      return 0
    else:
      Log.Fatal('No input files')

  gcc_mode = env.getone('GCC_MODE')
  output_type = DriverOutputTypes(gcc_mode, compiling_to_native)
  needs_linking = (gcc_mode == '')

  if env.getbool('NEED_DASH_E') and gcc_mode != '-E':
    Log.Fatal("-E or -x required when input is from stdin")

  # There are multiple input files and no linking is being done.
  # There will be multiple outputs. Handle this case separately.
  if not needs_linking:
    # Filter out flags
    inputs = [f for f in inputs if not IsFlag(f)]
    if output != '' and len(inputs) > 1:
      Log.Fatal('Cannot have -o with -c, -S, or -E and multiple inputs: %s',
                repr(inputs))

    for f in inputs:
      if IsFlag(f):
        continue
      intype = filetype.FileType(f)
      if not filetype.IsSourceType(intype):
        if ((output_type == 'pp' and intype != 'S') or
            (output_type == 'll') or
            (output_type == 'po' and intype != 'll') or
            (output_type == 's' and intype not in ('ll','po','S')) or
            (output_type == 'o' and intype not in ('ll','po','S','s'))):
          Log.Fatal("%s: Unexpected type of file for '%s'",
                    pathtools.touser(f), gcc_mode)

      if output == '':
        f_output = DefaultOutputName(f, output_type)
      else:
        f_output = output

      namegen = TempNameGen([f], f_output)
      CompileOne(f, output_type, namegen, f_output)
    return 0

  # Linking case
  assert(needs_linking)
  assert(output_type in ('pso','so','pexe','nexe'))

  if output == '':
    output = pathtools.normalize('a.out')
  namegen = TempNameGen(inputs, output)

  # Compile all source files (c/c++/ll) to .po
  for i in xrange(0, len(inputs)):
    if IsFlag(inputs[i]):
      continue
    intype = filetype.FileType(inputs[i])
    if filetype.IsSourceType(intype) or intype == 'll':
      inputs[i] = CompileOne(inputs[i], 'po', namegen)

  # Compile all .s/.S to .o
  if env.getbool('ALLOW_NATIVE'):
    for i in xrange(0, len(inputs)):
      if IsFlag(inputs[i]):
        continue
      intype = filetype.FileType(inputs[i])
      if intype in ('s','S'):
        inputs[i] = CompileOne(inputs[i], 'o', namegen)

  # We should only be left with .po and .o and libraries
  for f in inputs:
    if IsFlag(f):
      continue
    intype = filetype.FileType(f)
    if intype in ('o','s','S') or filetype.IsNativeArchive(f):
      if not env.getbool('ALLOW_NATIVE'):
        Log.Fatal('%s: Native object files not allowed in link. '
                  'Use --pnacl-allow-native to override.', pathtools.touser(f))
    assert(intype in ('po','o','so','ldscript') or filetype.IsArchive(f))

  # Fix the user-specified linker arguments
  ld_inputs = []
  for f in inputs:
    if f.startswith('-Xlinker='):
      ld_inputs.append(f[len('-Xlinker='):])
    elif f.startswith('-Wl,'):
      ld_inputs += f[len('-Wl,'):].split(',')
    else:
      ld_inputs.append(f)

  if env.getbool('ALLOW_NATIVE'):
    ld_inputs.append('--pnacl-allow-native')

  # Invoke the linker
  env.set('ld_inputs', *ld_inputs)

  ld_args = env.get('LD_ARGS')
  ld_flags = env.get('LD_FLAGS')

  RunDriver('ld', ld_flags + ld_args + ['-o', output])
  return 0
Ejemplo n.º 10
0
def main(argv):
    env.update(EXTRA_ENV)
    CheckSetup()
    ParseArgs(argv, CustomPatterns + GCCPatterns)

    # "configure", especially when run as part of a toolchain bootstrap
    # process, will invoke gcc with various diagnostic options and
    # parse the output. In these cases we do not alter the incoming
    # commandline. It is also important to not emit spurious messages.
    if env.getbool('DIAGNOSTIC'):
        if env.getbool('SHOW_VERSION'):
            code, stdout, stderr = Run(env.get('CC') + env.get('CC_FLAGS'),
                                       redirect_stdout=subprocess.PIPE)
            out = stdout.split('\n')
            nacl_version = ReadDriverRevision()
            out[0] += ' nacl-version=%s' % nacl_version
            stdout = '\n'.join(out)
            print stdout,
        else:
            Run(env.get('CC') + env.get('CC_FLAGS'))
        return 0

    unmatched = env.get('UNMATCHED')
    if len(unmatched) > 0:
        UnrecognizedOption(*unmatched)

    # If -arch was given, we are compiling directly to native code
    compiling_to_native = GetArch() is not None

    if env.getbool('ALLOW_NATIVE'):
        if not compiling_to_native:
            Log.Fatal("--pnacl-allow-native without -arch is not meaningful.")
        # For native/mixed links, also bring in the native libgcc and
        # libcrt_platform to avoid link failure if pre-translated native
        # code needs functions from it.
        env.append('LD_FLAGS', env.eval('-L${LIBS_NATIVE_ARCH}'))
        env.append('STDLIBS', '-lgcc')
        env.append('STDLIBS', '-lcrt_platform')

    flags_and_inputs = env.get('INPUTS')
    output = env.getone('OUTPUT')

    if len(flags_and_inputs) == 0:
        if env.getbool('VERBOSE'):
            # -v can be invoked without any inputs. Runs the original
            # command without modifying the commandline for this case.
            Run(env.get('CC') + env.get('CC_FLAGS'))
            return 0
        else:
            Log.Fatal('No input files')

    gcc_mode = env.getone('GCC_MODE')
    output_type = DriverOutputTypes(gcc_mode, compiling_to_native)

    # '-shared' modifies the output from the linker and should be considered when
    # determining the final output type.
    if env.getbool('SHARED'):
        if compiling_to_native:
            Log.Fatal('Building native shared libraries not supported')
        if gcc_mode != '':
            Log.Fatal('-c, -S, and -E are disallowed with -shared')
        output_type = 'pll'

    # INPUTS consists of actual input files and a subset of flags like -Wl,<foo>.
    # Create a version with just the files.
    inputs = [f for f in flags_and_inputs if not IsFlag(f)]
    header_inputs = [
        f for f in inputs if filetype.IsHeaderType(filetype.FileType(f))
    ]
    # Handle PCH case specially (but only for a limited sense...)
    if header_inputs and gcc_mode != '-E':
        # We only handle doing pre-compiled headers for all inputs or not at
        # all at the moment. This is because DriverOutputTypes only assumes
        # one type of output, depending on the "gcc_mode" flag. When mixing
        # header inputs w/ non-header inputs, some of the outputs will be
        # pch while others will be output_type. We would also need to modify
        # the input->output chaining for the needs_linking case.
        if len(header_inputs) != len(inputs):
            Log.Fatal('mixed compiling of headers and source not supported')
        CompileHeaders(header_inputs, output)
        return 0

    needs_linking = (gcc_mode == '')

    if env.getbool('NEED_DASH_E') and gcc_mode != '-E':
        Log.Fatal("-E or -x required when input is from stdin")

    # There are multiple input files and no linking is being done.
    # There will be multiple outputs. Handle this case separately.
    if not needs_linking:
        if output != '' and len(inputs) > 1:
            Log.Fatal(
                'Cannot have -o with -c, -S, or -E and multiple inputs: %s',
                repr(inputs))

        for f in inputs:
            intype = filetype.FileType(f)
            if not (filetype.IsSourceType(intype)
                    or filetype.IsHeaderType(intype)):
                if ((output_type == 'pp' and intype != 'S')
                        or (output_type == 'll')
                        or (output_type == 'po' and intype != 'll') or
                    (output_type == 's' and intype not in ('ll', 'po', 'S'))
                        or (output_type == 'o'
                            and intype not in ('ll', 'po', 'S', 's'))):
                    Log.Fatal("%s: Unexpected type of file for '%s'",
                              pathtools.touser(f), gcc_mode)

            if output == '':
                f_output = DefaultOutputName(f, output_type)
            else:
                f_output = output

            namegen = TempNameGen([f], f_output)
            CompileOne(f, output_type, namegen, f_output)
        return 0

    # Linking case
    assert (needs_linking)
    assert (output_type in ('pll', 'pexe', 'nexe'))

    if output == '':
        output = pathtools.normalize('a.out')
    namegen = TempNameGen(flags_and_inputs, output)

    # Compile all source files (c/c++/ll) to .po
    for i in xrange(0, len(flags_and_inputs)):
        if IsFlag(flags_and_inputs[i]):
            continue
        intype = filetype.FileType(flags_and_inputs[i])
        if filetype.IsSourceType(intype) or intype == 'll':
            flags_and_inputs[i] = CompileOne(flags_and_inputs[i], 'po',
                                             namegen)

    # Compile all .s/.S to .o
    if env.getbool('ALLOW_NATIVE'):
        for i in xrange(0, len(flags_and_inputs)):
            if IsFlag(flags_and_inputs[i]):
                continue
            intype = filetype.FileType(flags_and_inputs[i])
            if intype in ('s', 'S'):
                flags_and_inputs[i] = CompileOne(flags_and_inputs[i], 'o',
                                                 namegen)

    # We should only be left with .po and .o and libraries
    for f in flags_and_inputs:
        if IsFlag(f):
            continue
        intype = filetype.FileType(f)
        if intype in ('o', 's', 'S') or filetype.IsNativeArchive(f):
            if not env.getbool('ALLOW_NATIVE'):
                Log.Fatal(
                    '%s: Native object files not allowed in link. '
                    'Use --pnacl-allow-native to override.',
                    pathtools.touser(f))
        assert (intype in ('po', 'o', 'so', 'ldscript')
                or filetype.IsArchive(f))

    # Fix the user-specified linker arguments
    ld_inputs = []
    for f in flags_and_inputs:
        if f.startswith('-Xlinker='):
            ld_inputs.append(f[len('-Xlinker='):])
        elif f.startswith('-Wl,'):
            ld_inputs += f[len('-Wl,'):].split(',')
        else:
            ld_inputs.append(f)

    if env.getbool('ALLOW_NATIVE'):
        ld_inputs.append('--pnacl-allow-native')

    # Invoke the linker
    env.set('ld_inputs', *ld_inputs)

    ld_args = env.get('LD_ARGS')
    ld_flags = env.get('LD_FLAGS')

    RunDriver('pnacl-ld', ld_flags + ld_args + ['-o', output])
    return 0
Ejemplo n.º 11
0
def main(argv):
    env.update(EXTRA_ENV)
    ParseArgs(argv, PATTERNS)
    Run('"${NM}" --plugin=${GOLD_PLUGIN_SO} ${ARGS}')
    # only reached in case of no errors
    return 0