Esempio n. 1
0
/// claim_file_hook - called by gold to see whether this file is one that
/// our plugin can handle. We'll try to open it and register all the symbols
/// with add_symbol if possible.
static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file,
                                        int *claimed) {
  LTOModule *M;
  const void *view;
  std::unique_ptr<MemoryBuffer> buffer;
  if (get_view) {
    if (get_view(file->handle, &view) != LDPS_OK) {
      (*message)(LDPL_ERROR, "Failed to get a view of %s", file->name);
      return LDPS_ERR;
    }
  } else {
    int64_t offset = 0;
    // Gold has found what might be IR part-way inside of a file, such as
    // an .a archive.
    if (file->offset) {
      offset = file->offset;
    }
    if (std::error_code ec = MemoryBuffer::getOpenFileSlice(
            file->fd, file->name, buffer, file->filesize, offset)) {
      (*message)(LDPL_ERROR, ec.message().c_str());
      return LDPS_ERR;
    }
    view = buffer->getBufferStart();
  }

  if (!LTOModule::isBitcodeFile(view, file->filesize))
    return LDPS_OK;

  std::string Error;
  M = LTOModule::makeLTOModule(view, file->filesize, TargetOpts, Error);
  if (!M) {
    (*message)(LDPL_ERROR,
               "LLVM gold plugin has failed to create LTO module: %s",
               Error.c_str());
    return LDPS_OK;
  }

  *claimed = 1;
  Modules.resize(Modules.size() + 1);
  claimed_file &cf = Modules.back();

  if (!options::triple.empty())
    M->setTargetTriple(options::triple.c_str());

  cf.handle = file->handle;
  unsigned sym_count = M->getSymbolCount();
  cf.syms.reserve(sym_count);

  for (unsigned i = 0; i != sym_count; ++i) {
    lto_symbol_attributes attrs = M->getSymbolAttributes(i);
    if ((attrs & LTO_SYMBOL_SCOPE_MASK) == LTO_SYMBOL_SCOPE_INTERNAL)
      continue;

    cf.syms.push_back(ld_plugin_symbol());
    ld_plugin_symbol &sym = cf.syms.back();
    sym.name = strdup(M->getSymbolName(i));
    sym.version = NULL;

    int scope = attrs & LTO_SYMBOL_SCOPE_MASK;
    bool CanBeHidden = scope == LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN;
    if (!CanBeHidden)
      CannotBeHidden.insert(sym.name);
    switch (scope) {
      case LTO_SYMBOL_SCOPE_HIDDEN:
        sym.visibility = LDPV_HIDDEN;
        break;
      case LTO_SYMBOL_SCOPE_PROTECTED:
        sym.visibility = LDPV_PROTECTED;
        break;
      case 0: // extern
      case LTO_SYMBOL_SCOPE_DEFAULT:
      case LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN:
        sym.visibility = LDPV_DEFAULT;
        break;
      default:
        (*message)(LDPL_ERROR, "Unknown scope attribute: %d", scope);
        return LDPS_ERR;
    }

    int definition = attrs & LTO_SYMBOL_DEFINITION_MASK;
    sym.comdat_key = NULL;
    switch (definition) {
      case LTO_SYMBOL_DEFINITION_REGULAR:
        sym.def = LDPK_DEF;
        break;
      case LTO_SYMBOL_DEFINITION_UNDEFINED:
        sym.def = LDPK_UNDEF;
        break;
      case LTO_SYMBOL_DEFINITION_TENTATIVE:
        sym.def = LDPK_COMMON;
        break;
      case LTO_SYMBOL_DEFINITION_WEAK:
        sym.comdat_key = sym.name;
        sym.def = LDPK_WEAKDEF;
        break;
      case LTO_SYMBOL_DEFINITION_WEAKUNDEF:
        sym.def = LDPK_WEAKUNDEF;
        break;
      default:
        (*message)(LDPL_ERROR, "Unknown definition attribute: %d", definition);
        return LDPS_ERR;
    }

    sym.size = 0;

    sym.resolution = LDPR_UNKNOWN;
  }

  cf.syms.reserve(cf.syms.size());

  if (!cf.syms.empty()) {
    if ((*add_symbols)(cf.handle, cf.syms.size(), &cf.syms[0]) != LDPS_OK) {
      (*message)(LDPL_ERROR, "Unable to add symbols!");
      return LDPS_ERR;
    }
  }

  if (CodeGen) {
    std::string Error;
    if (!CodeGen->addModule(M, Error)) {
      (*message)(LDPL_ERROR, "Error linking module: %s", Error.c_str());
      return LDPS_ERR;
    }
  }

  delete M;

  return LDPS_OK;
}
Esempio n. 2
0
int main(int argc, char **argv) {
    // Print a stack trace if we signal out.
    sys::PrintStackTraceOnErrorSignal();
    PrettyStackTraceProgram X(argc, argv);

    llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
    cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n");

    if (OptLevel < '0' || OptLevel > '3') {
        errs() << argv[0] << ": optimization level must be between 0 and 3\n";
        return 1;
    }

    // Initialize the configured targets.
    InitializeAllTargets();
    InitializeAllTargetMCs();
    InitializeAllAsmPrinters();
    InitializeAllAsmParsers();

    // set up the TargetOptions for the machine
    TargetOptions Options = InitTargetOptionsFromCodeGenFlags();

    if (ListSymbolsOnly)
        return listSymbols(argv[0], Options);

    unsigned BaseArg = 0;

    LTOCodeGenerator CodeGen;

    if (UseDiagnosticHandler)
        CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr);

    switch (RelocModel) {
    case Reloc::Static:
        CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_STATIC);
        break;
    case Reloc::PIC_:
        CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC);
        break;
    case Reloc::DynamicNoPIC:
        CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC);
        break;
    default:
        CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DEFAULT);
    }

    CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF);
    CodeGen.setTargetOptions(Options);

    llvm::StringSet<llvm::MallocAllocator> DSOSymbolsSet;
    for (unsigned i = 0; i < DSOSymbols.size(); ++i)
        DSOSymbolsSet.insert(DSOSymbols[i]);

    std::vector<std::string> KeptDSOSyms;

    for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) {
        std::string error;
        std::unique_ptr<LTOModule> Module(
            LTOModule::createFromFile(InputFilenames[i].c_str(), Options, error));
        if (!error.empty()) {
            errs() << argv[0] << ": error loading file '" << InputFilenames[i]
                   << "': " << error << "\n";
            return 1;
        }

        LTOModule *LTOMod = Module.get();

        // We use the first input module as the destination module when
        // SetMergedModule is true.
        if (SetMergedModule && i == BaseArg) {
            // Transfer ownership to the code generator.
            CodeGen.setModule(Module.release());
        } else if (!CodeGen.addModule(Module.get())) {
            // Print a message here so that we know addModule() did not abort.
            errs() << argv[0] << ": error adding file '" << InputFilenames[i] << "'\n";
            return 1;
        }

        unsigned NumSyms = LTOMod->getSymbolCount();
        for (unsigned I = 0; I < NumSyms; ++I) {
            StringRef Name = LTOMod->getSymbolName(I);
            if (!DSOSymbolsSet.count(Name))
                continue;
            lto_symbol_attributes Attrs = LTOMod->getSymbolAttributes(I);
            unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK;
            if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN)
                KeptDSOSyms.push_back(Name);
        }
    }

    // Add all the exported symbols to the table of symbols to preserve.
    for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
        CodeGen.addMustPreserveSymbol(ExportedSymbols[i].c_str());

    // Add all the dso symbols to the table of symbols to expose.
    for (unsigned i = 0; i < KeptDSOSyms.size(); ++i)
        CodeGen.addMustPreserveSymbol(KeptDSOSyms[i].c_str());

    // Set cpu and attrs strings for the default target/subtarget.
    CodeGen.setCpu(MCPU.c_str());

    CodeGen.setOptLevel(OptLevel - '0');

    std::string attrs;
    for (unsigned i = 0; i < MAttrs.size(); ++i) {
        if (i > 0)
            attrs.append(",");
        attrs.append(MAttrs[i]);
    }

    if (!attrs.empty())
        CodeGen.setAttr(attrs.c_str());

    if (!OutputFilename.empty()) {
        std::string ErrorInfo;
        std::unique_ptr<MemoryBuffer> Code = CodeGen.compile(
                DisableInline, DisableGVNLoadPRE, DisableLTOVectorization, ErrorInfo);
        if (!Code) {
            errs() << argv[0]
                   << ": error compiling the code: " << ErrorInfo << "\n";
            return 1;
        }

        std::error_code EC;
        raw_fd_ostream FileStream(OutputFilename, EC, sys::fs::F_None);
        if (EC) {
            errs() << argv[0] << ": error opening the file '" << OutputFilename
                   << "': " << EC.message() << "\n";
            return 1;
        }

        FileStream.write(Code->getBufferStart(), Code->getBufferSize());
    } else {
        std::string ErrorInfo;
        const char *OutputName = nullptr;
        if (!CodeGen.compile_to_file(&OutputName, DisableInline,
                                     DisableGVNLoadPRE, DisableLTOVectorization,
                                     ErrorInfo)) {
            errs() << argv[0]
                   << ": error compiling the code: " << ErrorInfo
                   << "\n";
            return 1;
        }

        outs() << "Wrote native object file '" << OutputName << "'\n";
    }

    return 0;
}