diff --git a/llvm/test/tools/llvm-ifs/func.ifs b/llvm/test/tools/llvm-ifs/func.ifs --- a/llvm/test/tools/llvm-ifs/func.ifs +++ b/llvm/test/tools/llvm-ifs/func.ifs @@ -4,6 +4,9 @@ # RUN: llvm-ifs -action write-bin -o - %s %S/object.ifs | \ # RUN: llvm-readelf --all - | FileCheck %s --check-prefixes=CHECK-ELF +# RUN: llvm-ifs -action write-bin -o - %s %S/object.ifs -use-interfacestub | \ +# RUN: llvm-readelf --all - | FileCheck %s --check-prefixes=CHECK-ELF + # RUN: llvm-ifs -action write-bin -force-format TBD -o - %s %S/object.ifs | \ # RUN: FileCheck %s --check-prefixes=CHECK-DARWIN-TBD3 diff --git a/llvm/tools/llvm-ifs/CMakeLists.txt b/llvm/tools/llvm-ifs/CMakeLists.txt --- a/llvm/tools/llvm-ifs/CMakeLists.txt +++ b/llvm/tools/llvm-ifs/CMakeLists.txt @@ -1,4 +1,5 @@ set(LLVM_LINK_COMPONENTS + InterfaceStub Object Support TextAPI diff --git a/llvm/tools/llvm-ifs/llvm-ifs.cpp b/llvm/tools/llvm-ifs/llvm-ifs.cpp --- a/llvm/tools/llvm-ifs/llvm-ifs.cpp +++ b/llvm/tools/llvm-ifs/llvm-ifs.cpp @@ -9,6 +9,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" +#include "llvm/InterfaceStub/ELFObjHandler.h" #include "llvm/ObjectYAML/yaml2obj.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -54,6 +55,11 @@ static cl::opt OutputFilename("o", cl::desc(""), cl::value_desc("path")); +static cl::opt UseInterfaceStub( + "use-interfacestub", + cl::desc("Write output ELF file using latest InterfaceStub backend"), + cl::init(false)); + enum class IFSSymbolType { NoType = 0, Object, @@ -342,16 +348,82 @@ return convertYAML(YIn, Out, ErrHandler) ? 0 : 1; } -static int writeIfso(const IFSStub &Stub, bool IsWriteIfs, raw_ostream &Out) { +static elfabi::ELFTarget convertIFSStub(const IFSStub &IfsStub, + elfabi::ELFStub &ElfStub) { + ElfStub.TbeVersion = IfsStub.IfsVersion; + ElfStub.SoName = IfsStub.SOName; + // TODO: Support more archs and targets. + Triple IFSTriple(IfsStub.Triple); + elfabi::ELFTarget Target = elfabi::ELFTarget::ELF64LE; + switch (IFSTriple.getArch()) { + case Triple::ArchType::aarch64: + ElfStub.Arch = (elfabi::ELFArch)ELF::EM_AARCH64; + break; + case Triple::ArchType::x86_64: + ElfStub.Arch = (elfabi::ELFArch)ELF::EM_X86_64; + break; + default: + ElfStub.Arch = (elfabi::ELFArch)ELF::EM_NONE; + } + ElfStub.NeededLibs = IfsStub.NeededLibs; + for (const IFSSymbol &IfsSymbol : IfsStub.Symbols) { + elfabi::ELFSymbol ElfSymbol(IfsSymbol.Name); + switch (IfsSymbol.Type) { + case IFSSymbolType::Func: + ElfSymbol.Type = elfabi::ELFSymbolType::Func; + break; + case IFSSymbolType::NoType: + ElfSymbol.Type = elfabi::ELFSymbolType::NoType; + break; + case IFSSymbolType::Object: + ElfSymbol.Type = elfabi::ELFSymbolType::Object; + break; + default: + ElfSymbol.Type = elfabi::ELFSymbolType::Unknown; + break; + // TODO: Add support for TLS? + } + ElfSymbol.Size = IfsSymbol.Size; + ElfSymbol.Undefined = false; + ElfSymbol.Weak = IfsSymbol.Weak; + ElfSymbol.Warning = IfsSymbol.Warning; + ElfStub.Symbols.insert(ElfSymbol); + } + return Target; +} + +static int writeIfso(const IFSStub &Stub, bool IsWriteIfs) { + std::string ObjectFileFormat = + ForceFormat.empty() ? Stub.ObjectFileFormat : ForceFormat; + + // Use InterfaceStub library if the option is enabled and output + // format is ELF. + if (UseInterfaceStub && (!IsWriteIfs) && ObjectFileFormat != "TBD") { + elfabi::ELFStub ElfStub; + elfabi::ELFTarget Target = convertIFSStub(Stub, ElfStub); + Error BinaryWriteError = + elfabi::writeBinaryStub(OutputFilename, ElfStub, Target); + if (BinaryWriteError) { + return -1; + } + return 0; + } + + // Open file for writing. + std::error_code SysErr; + raw_fd_ostream Out(OutputFilename, SysErr); + if (SysErr) { + WithColor::error() << "Couldn't open " << OutputFilename + << " for writing.\n"; + return -1; + } + if (IsWriteIfs) { yaml::Output YamlOut(Out, NULL, /*WrapColumn =*/0); YamlOut << const_cast(Stub); return 0; } - std::string ObjectFileFormat = - ForceFormat.empty() ? Stub.ObjectFileFormat : ForceFormat; - if (ObjectFileFormat == "ELF" || ForceFormat == "ELFOBJYAML") return writeElfStub(llvm::Triple(Stub.Triple), Stub.Symbols, Stub.ObjectFileFormat, Out); @@ -498,15 +570,5 @@ for (auto &Entry : SymbolMap) Stub.Symbols.push_back(Entry.second); - std::error_code SysErr; - - // Open file for writing. - raw_fd_ostream Out(OutputFilename, SysErr); - if (SysErr) { - WithColor::error() << "Couldn't open " << OutputFilename - << " for writing.\n"; - return -1; - } - - return writeIfso(Stub, (Action == "write-ifs"), Out); + return writeIfso(Stub, (Action == "write-ifs")); }