summaryrefslogtreecommitdiff
path: root/llvm/lib/InterfaceStub
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/InterfaceStub')
-rw-r--r--llvm/lib/InterfaceStub/ELFObjHandler.cpp115
-rw-r--r--llvm/lib/InterfaceStub/ELFStub.cpp28
-rw-r--r--llvm/lib/InterfaceStub/IFSHandler.cpp329
-rw-r--r--llvm/lib/InterfaceStub/IFSStub.cpp133
-rw-r--r--llvm/lib/InterfaceStub/TBEHandler.cpp143
5 files changed, 517 insertions, 231 deletions
diff --git a/llvm/lib/InterfaceStub/ELFObjHandler.cpp b/llvm/lib/InterfaceStub/ELFObjHandler.cpp
index 255d301362eb..112c1cea354a 100644
--- a/llvm/lib/InterfaceStub/ELFObjHandler.cpp
+++ b/llvm/lib/InterfaceStub/ELFObjHandler.cpp
@@ -7,7 +7,7 @@
//===-----------------------------------------------------------------------===/
#include "llvm/InterfaceStub/ELFObjHandler.h"
-#include "llvm/InterfaceStub/ELFStub.h"
+#include "llvm/InterfaceStub/IFSStub.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/ELFObjectFile.h"
@@ -27,7 +27,7 @@ using namespace llvm::object;
using namespace llvm::ELF;
namespace llvm {
-namespace elfabi {
+namespace ifs {
// Simple struct to hold relevant .dynamic entries.
struct DynamicEntries {
@@ -180,7 +180,7 @@ public:
ELFStubBuilder(const ELFStubBuilder &) = delete;
ELFStubBuilder(ELFStubBuilder &&) = default;
- explicit ELFStubBuilder(const ELFStub &Stub) {
+ explicit ELFStubBuilder(const IFSStub &Stub) {
DynSym.Name = ".dynsym";
DynSym.Align = sizeof(Elf_Addr);
DynStr.Name = ".dynstr";
@@ -191,7 +191,7 @@ public:
ShStrTab.Align = 1;
// Populate string tables.
- for (const ELFSymbol &Sym : Stub.Symbols)
+ for (const IFSSymbol &Sym : Stub.Symbols)
DynStr.Content.add(Sym.Name);
for (const std::string &Lib : Stub.NeededLibs)
DynStr.Content.add(Lib);
@@ -213,14 +213,14 @@ public:
DynStr.Size = DynStr.Content.getSize();
// Populate dynamic symbol table.
- for (const ELFSymbol &Sym : Stub.Symbols) {
+ for (const IFSSymbol &Sym : Stub.Symbols) {
uint8_t Bind = Sym.Weak ? STB_WEAK : STB_GLOBAL;
// For non-undefined symbols, value of the shndx is not relevant at link
// time as long as it is not SHN_UNDEF. Set shndx to 1, which
// points to ".dynsym".
uint16_t Shndx = Sym.Undefined ? SHN_UNDEF : 1;
DynSym.Content.add(DynStr.Content.getOffset(Sym.Name), Sym.Size, Bind,
- (uint8_t)Sym.Type, 0, Shndx);
+ convertIFSSymbolTypeToELF(Sym.Type), 0, Shndx);
}
DynSym.Size = DynSym.Content.getSize();
@@ -250,7 +250,8 @@ public:
fillStrTabShdr(ShStrTab);
// Finish initializing the ELF header.
- initELFHeader<ELFT>(ElfHeader, Stub.Arch);
+ initELFHeader<ELFT>(ElfHeader,
+ static_cast<uint16_t>(Stub.Target.Arch.getValue()));
ElfHeader.e_shstrndx = ShStrTab.Index;
ElfHeader.e_shnum = LastSection->Index + 1;
ElfHeader.e_shoff =
@@ -303,7 +304,10 @@ private:
SymTab.Shdr.sh_flags = SHF_ALLOC;
SymTab.Shdr.sh_addr = SymTab.Addr;
SymTab.Shdr.sh_offset = SymTab.Offset;
- SymTab.Shdr.sh_info = SymTab.Size / sizeof(Elf_Sym) > 1 ? 1 : 0;
+ // Only non-local symbols are included in the tbe file, so .dynsym only
+ // contains 1 local symbol (the undefined symbol at index 0). The sh_info
+ // should always be 1.
+ SymTab.Shdr.sh_info = 1;
SymTab.Shdr.sh_size = SymTab.Size;
SymTab.Shdr.sh_name = this->ShStrTab.Content.getOffset(SymTab.Name);
SymTab.Shdr.sh_addralign = SymTab.Align;
@@ -440,37 +444,15 @@ static Error populateDynamic(DynamicEntries &Dyn,
return Error::success();
}
-/// This function extracts symbol type from a symbol's st_info member and
-/// maps it to an ELFSymbolType enum.
-/// Currently, STT_NOTYPE, STT_OBJECT, STT_FUNC, and STT_TLS are supported.
-/// Other symbol types are mapped to ELFSymbolType::Unknown.
-///
-/// @param Info Binary symbol st_info to extract symbol type from.
-static ELFSymbolType convertInfoToType(uint8_t Info) {
- Info = Info & 0xf;
- switch (Info) {
- case ELF::STT_NOTYPE:
- return ELFSymbolType::NoType;
- case ELF::STT_OBJECT:
- return ELFSymbolType::Object;
- case ELF::STT_FUNC:
- return ELFSymbolType::Func;
- case ELF::STT_TLS:
- return ELFSymbolType::TLS;
- default:
- return ELFSymbolType::Unknown;
- }
-}
-
-/// This function creates an ELFSymbol and populates all members using
+/// This function creates an IFSSymbol and populates all members using
/// information from a binary ELFT::Sym.
///
-/// @param SymName The desired name of the ELFSymbol.
+/// @param SymName The desired name of the IFSSymbol.
/// @param RawSym ELFT::Sym to extract symbol information from.
template <class ELFT>
-static ELFSymbol createELFSym(StringRef SymName,
+static IFSSymbol createELFSym(StringRef SymName,
const typename ELFT::Sym &RawSym) {
- ELFSymbol TargetSym{std::string(SymName)};
+ IFSSymbol TargetSym{std::string(SymName)};
uint8_t Binding = RawSym.getBinding();
if (Binding == STB_WEAK)
TargetSym.Weak = true;
@@ -478,9 +460,9 @@ static ELFSymbol createELFSym(StringRef SymName,
TargetSym.Weak = false;
TargetSym.Undefined = RawSym.isUndefined();
- TargetSym.Type = convertInfoToType(RawSym.st_info);
+ TargetSym.Type = convertELFSymbolTypeToIFS(RawSym.st_info);
- if (TargetSym.Type == ELFSymbolType::Func) {
+ if (TargetSym.Type == IFSSymbolType::Func) {
TargetSym.Size = 0;
} else {
TargetSym.Size = RawSym.st_size;
@@ -488,14 +470,14 @@ static ELFSymbol createELFSym(StringRef SymName,
return TargetSym;
}
-/// This function populates an ELFStub with symbols using information read
+/// This function populates an IFSStub with symbols using information read
/// from an ELF binary.
///
-/// @param TargetStub ELFStub to add symbols to.
+/// @param TargetStub IFSStub to add symbols to.
/// @param DynSym Range of dynamic symbols to add to TargetStub.
/// @param DynStr StringRef to the dynamic string table.
template <class ELFT>
-static Error populateSymbols(ELFStub &TargetStub,
+static Error populateSymbols(IFSStub &TargetStub,
const typename ELFT::SymRange DynSym,
StringRef DynStr) {
// Skips the first symbol since it's the NULL symbol.
@@ -508,28 +490,28 @@ static Error populateSymbols(ELFStub &TargetStub,
uint8_t Visibility = RawSym.getVisibility();
if (!(Visibility == STV_DEFAULT || Visibility == STV_PROTECTED))
continue;
- // Create an ELFSymbol and populate it with information from the symbol
+ // Create an IFSSymbol and populate it with information from the symbol
// table entry.
Expected<StringRef> SymName = terminatedSubstr(DynStr, RawSym.st_name);
if (!SymName)
return SymName.takeError();
- ELFSymbol Sym = createELFSym<ELFT>(*SymName, RawSym);
- TargetStub.Symbols.insert(std::move(Sym));
+ IFSSymbol Sym = createELFSym<ELFT>(*SymName, RawSym);
+ TargetStub.Symbols.push_back(std::move(Sym));
// TODO: Populate symbol warning.
}
return Error::success();
}
-/// Returns a new ELFStub with all members populated from an ELFObjectFile.
+/// Returns a new IFSStub with all members populated from an ELFObjectFile.
/// @param ElfObj Source ELFObjectFile.
template <class ELFT>
-static Expected<std::unique_ptr<ELFStub>>
+static Expected<std::unique_ptr<IFSStub>>
buildStub(const ELFObjectFile<ELFT> &ElfObj) {
using Elf_Dyn_Range = typename ELFT::DynRange;
using Elf_Phdr_Range = typename ELFT::PhdrRange;
using Elf_Sym_Range = typename ELFT::SymRange;
using Elf_Sym = typename ELFT::Sym;
- std::unique_ptr<ELFStub> DestStub = std::make_unique<ELFStub>();
+ std::unique_ptr<IFSStub> DestStub = std::make_unique<IFSStub>();
const ELFFile<ELFT> &ElfFile = ElfObj.getELFFile();
// Fetch .dynamic table.
Expected<Elf_Dyn_Range> DynTable = ElfFile.dynamicEntries();
@@ -558,7 +540,12 @@ buildStub(const ELFObjectFile<ELFT> &ElfObj) {
DynEnt.StrSize);
// Populate Arch from ELF header.
- DestStub->Arch = ElfFile.getHeader().e_machine;
+ DestStub->Target.Arch = static_cast<IFSArch>(ElfFile.getHeader().e_machine);
+ DestStub->Target.BitWidth =
+ convertELFBitWidthToIFS(ElfFile.getHeader().e_ident[EI_CLASS]);
+ DestStub->Target.Endianness =
+ convertELFEndiannessToIFS(ElfFile.getHeader().e_ident[EI_DATA]);
+ DestStub->Target.ObjectFormat = "ELF";
// Populate SoName from .dynamic entries and dynamic string table.
if (DynEnt.SONameOffset.hasValue()) {
@@ -606,9 +593,9 @@ buildStub(const ELFObjectFile<ELFT> &ElfObj) {
/// the file.
///
/// @param FilePath File path for writing the ELF binary.
-/// @param Stub Source ELFStub to generate a binary ELF stub from.
+/// @param Stub Source InterFace Stub to generate a binary ELF stub from.
template <class ELFT>
-static Error writeELFBinaryToFile(StringRef FilePath, const ELFStub &Stub,
+static Error writeELFBinaryToFile(StringRef FilePath, const IFSStub &Stub,
bool WriteIfChanged) {
ELFStubBuilder<ELFT> Builder{Stub};
// Write Stub to memory first.
@@ -642,7 +629,7 @@ static Error writeELFBinaryToFile(StringRef FilePath, const ELFStub &Stub,
return FileBuf->commit();
}
-Expected<std::unique_ptr<ELFStub>> readELFFile(MemoryBufferRef Buf) {
+Expected<std::unique_ptr<IFSStub>> readELFFile(MemoryBufferRef Buf) {
Expected<std::unique_ptr<Binary>> BinOrErr = createBinary(Buf);
if (!BinOrErr) {
return BinOrErr.takeError();
@@ -663,18 +650,26 @@ Expected<std::unique_ptr<ELFStub>> readELFFile(MemoryBufferRef Buf) {
// This function wraps the ELFT writeELFBinaryToFile() so writeBinaryStub()
// can be called without having to use ELFType templates directly.
-Error writeBinaryStub(StringRef FilePath, const ELFStub &Stub,
- ELFTarget OutputFormat, bool WriteIfChanged) {
- if (OutputFormat == ELFTarget::ELF32LE)
- return writeELFBinaryToFile<ELF32LE>(FilePath, Stub, WriteIfChanged);
- if (OutputFormat == ELFTarget::ELF32BE)
- return writeELFBinaryToFile<ELF32BE>(FilePath, Stub, WriteIfChanged);
- if (OutputFormat == ELFTarget::ELF64LE)
- return writeELFBinaryToFile<ELF64LE>(FilePath, Stub, WriteIfChanged);
- if (OutputFormat == ELFTarget::ELF64BE)
- return writeELFBinaryToFile<ELF64BE>(FilePath, Stub, WriteIfChanged);
+Error writeBinaryStub(StringRef FilePath, const IFSStub &Stub,
+ bool WriteIfChanged) {
+ assert(Stub.Target.Arch);
+ assert(Stub.Target.BitWidth);
+ assert(Stub.Target.Endianness);
+ if (Stub.Target.BitWidth == IFSBitWidthType::IFS32) {
+ if (Stub.Target.Endianness == IFSEndiannessType::Little) {
+ return writeELFBinaryToFile<ELF32LE>(FilePath, Stub, WriteIfChanged);
+ } else {
+ return writeELFBinaryToFile<ELF32BE>(FilePath, Stub, WriteIfChanged);
+ }
+ } else {
+ if (Stub.Target.Endianness == IFSEndiannessType::Little) {
+ return writeELFBinaryToFile<ELF64LE>(FilePath, Stub, WriteIfChanged);
+ } else {
+ return writeELFBinaryToFile<ELF64BE>(FilePath, Stub, WriteIfChanged);
+ }
+ }
llvm_unreachable("invalid binary output target");
}
-} // end namespace elfabi
+} // end namespace ifs
} // end namespace llvm
diff --git a/llvm/lib/InterfaceStub/ELFStub.cpp b/llvm/lib/InterfaceStub/ELFStub.cpp
deleted file mode 100644
index 3c637695d8e7..000000000000
--- a/llvm/lib/InterfaceStub/ELFStub.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-//===- ELFStub.cpp --------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===-----------------------------------------------------------------------===/
-
-#include "llvm/InterfaceStub/ELFStub.h"
-
-using namespace llvm;
-using namespace llvm::elfabi;
-
-ELFStub::ELFStub(ELFStub const &Stub) {
- TbeVersion = Stub.TbeVersion;
- Arch = Stub.Arch;
- SoName = Stub.SoName;
- NeededLibs = Stub.NeededLibs;
- Symbols = Stub.Symbols;
-}
-
-ELFStub::ELFStub(ELFStub &&Stub) {
- TbeVersion = std::move(Stub.TbeVersion);
- Arch = std::move(Stub.Arch);
- SoName = std::move(Stub.SoName);
- NeededLibs = std::move(Stub.NeededLibs);
- Symbols = std::move(Stub.Symbols);
-}
diff --git a/llvm/lib/InterfaceStub/IFSHandler.cpp b/llvm/lib/InterfaceStub/IFSHandler.cpp
new file mode 100644
index 000000000000..d3d351fa2ed4
--- /dev/null
+++ b/llvm/lib/InterfaceStub/IFSHandler.cpp
@@ -0,0 +1,329 @@
+//===- IFSHandler.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===-----------------------------------------------------------------------===/
+
+#include "llvm/InterfaceStub/IFSHandler.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/InterfaceStub/IFSStub.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/LineIterator.h"
+#include "llvm/Support/YAMLTraits.h"
+
+using namespace llvm;
+using namespace llvm::ifs;
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(IFSSymbol)
+
+namespace llvm {
+namespace yaml {
+
+/// YAML traits for ELFSymbolType.
+template <> struct ScalarEnumerationTraits<IFSSymbolType> {
+ static void enumeration(IO &IO, IFSSymbolType &SymbolType) {
+ IO.enumCase(SymbolType, "NoType", IFSSymbolType::NoType);
+ IO.enumCase(SymbolType, "Func", IFSSymbolType::Func);
+ IO.enumCase(SymbolType, "Object", IFSSymbolType::Object);
+ IO.enumCase(SymbolType, "TLS", IFSSymbolType::TLS);
+ IO.enumCase(SymbolType, "Unknown", IFSSymbolType::Unknown);
+ // Treat other symbol types as noise, and map to Unknown.
+ if (!IO.outputting() && IO.matchEnumFallback())
+ SymbolType = IFSSymbolType::Unknown;
+ }
+};
+
+template <> struct ScalarTraits<IFSEndiannessType> {
+ static void output(const IFSEndiannessType &Value, void *,
+ llvm::raw_ostream &Out) {
+ switch (Value) {
+ case IFSEndiannessType::Big:
+ Out << "big";
+ break;
+ case IFSEndiannessType::Little:
+ Out << "little";
+ break;
+ default:
+ llvm_unreachable("Unsupported endianness");
+ }
+ }
+
+ static StringRef input(StringRef Scalar, void *, IFSEndiannessType &Value) {
+ Value = StringSwitch<IFSEndiannessType>(Scalar)
+ .Case("big", IFSEndiannessType::Big)
+ .Case("little", IFSEndiannessType::Little)
+ .Default(IFSEndiannessType::Unknown);
+ if (Value == IFSEndiannessType::Unknown) {
+ return "Unsupported endianness";
+ }
+ return StringRef();
+ }
+
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+template <> struct ScalarTraits<IFSBitWidthType> {
+ static void output(const IFSBitWidthType &Value, void *,
+ llvm::raw_ostream &Out) {
+ switch (Value) {
+ case IFSBitWidthType::IFS32:
+ Out << "32";
+ break;
+ case IFSBitWidthType::IFS64:
+ Out << "64";
+ break;
+ default:
+ llvm_unreachable("Unsupported bit width");
+ }
+ }
+
+ static StringRef input(StringRef Scalar, void *, IFSBitWidthType &Value) {
+ Value = StringSwitch<IFSBitWidthType>(Scalar)
+ .Case("32", IFSBitWidthType::IFS32)
+ .Case("64", IFSBitWidthType::IFS64)
+ .Default(IFSBitWidthType::Unknown);
+ if (Value == IFSBitWidthType::Unknown) {
+ return "Unsupported bit width";
+ }
+ return StringRef();
+ }
+
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+template <> struct MappingTraits<IFSTarget> {
+ static void mapping(IO &IO, IFSTarget &Target) {
+ IO.mapOptional("ObjectFormat", Target.ObjectFormat);
+ IO.mapOptional("Arch", Target.ArchString);
+ IO.mapOptional("Endianness", Target.Endianness);
+ IO.mapOptional("BitWidth", Target.BitWidth);
+ }
+
+ // Compacts symbol information into a single line.
+ static const bool flow = true; // NOLINT(readability-identifier-naming)
+};
+
+/// YAML traits for ELFSymbol.
+template <> struct MappingTraits<IFSSymbol> {
+ static void mapping(IO &IO, IFSSymbol &Symbol) {
+ IO.mapRequired("Name", Symbol.Name);
+ IO.mapRequired("Type", Symbol.Type);
+ // The need for symbol size depends on the symbol type.
+ if (Symbol.Type == IFSSymbolType::NoType) {
+ IO.mapOptional("Size", Symbol.Size, (uint64_t)0);
+ } else if (Symbol.Type == IFSSymbolType::Func) {
+ Symbol.Size = 0;
+ } else {
+ IO.mapRequired("Size", Symbol.Size);
+ }
+ IO.mapOptional("Undefined", Symbol.Undefined, false);
+ IO.mapOptional("Weak", Symbol.Weak, false);
+ IO.mapOptional("Warning", Symbol.Warning);
+ }
+
+ // Compacts symbol information into a single line.
+ static const bool flow = true; // NOLINT(readability-identifier-naming)
+};
+
+/// YAML traits for ELFStub objects.
+template <> struct MappingTraits<IFSStub> {
+ static void mapping(IO &IO, IFSStub &Stub) {
+ if (!IO.mapTag("!ifs-v1", true))
+ IO.setError("Not a .tbe YAML file.");
+ IO.mapRequired("IfsVersion", Stub.IfsVersion);
+ IO.mapOptional("SoName", Stub.SoName);
+ IO.mapOptional("Target", Stub.Target);
+ IO.mapOptional("NeededLibs", Stub.NeededLibs);
+ IO.mapRequired("Symbols", Stub.Symbols);
+ }
+};
+
+/// YAML traits for ELFStubTriple objects.
+template <> struct MappingTraits<IFSStubTriple> {
+ static void mapping(IO &IO, IFSStubTriple &Stub) {
+ if (!IO.mapTag("!ifs-v1", true))
+ IO.setError("Not a .tbe YAML file.");
+ IO.mapRequired("IfsVersion", Stub.IfsVersion);
+ IO.mapOptional("SoName", Stub.SoName);
+ IO.mapOptional("Target", Stub.Target.Triple);
+ IO.mapOptional("NeededLibs", Stub.NeededLibs);
+ IO.mapRequired("Symbols", Stub.Symbols);
+ }
+};
+} // end namespace yaml
+} // end namespace llvm
+
+/// Attempt to determine if a Text stub uses target triple.
+bool usesTriple(StringRef Buf) {
+ for (line_iterator I(MemoryBufferRef(Buf, "ELFStub")); !I.is_at_eof(); ++I) {
+ StringRef Line = (*I).trim();
+ if (Line.startswith("Target:")) {
+ if (Line == "Target:" || (Line.find("{") != Line.npos)) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+Expected<std::unique_ptr<IFSStub>> ifs::readIFSFromBuffer(StringRef Buf) {
+ yaml::Input YamlIn(Buf);
+ std::unique_ptr<IFSStubTriple> Stub(new IFSStubTriple());
+ if (usesTriple(Buf)) {
+ YamlIn >> *Stub;
+ } else {
+ YamlIn >> *static_cast<IFSStub *>(Stub.get());
+ }
+ if (std::error_code Err = YamlIn.error()) {
+ return createStringError(Err, "YAML failed reading as IFS");
+ }
+
+ if (Stub->IfsVersion > IFSVersionCurrent)
+ return make_error<StringError>(
+ "IFS version " + Stub->IfsVersion.getAsString() + " is unsupported.",
+ std::make_error_code(std::errc::invalid_argument));
+ if (Stub->Target.ArchString) {
+ Stub->Target.Arch =
+ ELF::convertArchNameToEMachine(Stub->Target.ArchString.getValue());
+ }
+ return std::move(Stub);
+}
+
+Error ifs::writeIFSToOutputStream(raw_ostream &OS, const IFSStub &Stub) {
+ yaml::Output YamlOut(OS, NULL, /*WrapColumn =*/0);
+ std::unique_ptr<IFSStubTriple> CopyStub(new IFSStubTriple(Stub));
+ if (Stub.Target.Arch) {
+ CopyStub->Target.ArchString = std::string(
+ ELF::convertEMachineToArchName(Stub.Target.Arch.getValue()));
+ }
+ IFSTarget Target = Stub.Target;
+
+ if (CopyStub->Target.Triple ||
+ (!CopyStub->Target.ArchString && !CopyStub->Target.Endianness &&
+ !CopyStub->Target.BitWidth))
+ YamlOut << *CopyStub;
+ else
+ YamlOut << *static_cast<IFSStub *>(CopyStub.get());
+ return Error::success();
+}
+
+Error ifs::overrideIFSTarget(IFSStub &Stub, Optional<IFSArch> OverrideArch,
+ Optional<IFSEndiannessType> OverrideEndianness,
+ Optional<IFSBitWidthType> OverrideBitWidth,
+ Optional<std::string> OverrideTriple) {
+ std::error_code OverrideEC(1, std::generic_category());
+ if (OverrideArch) {
+ if (Stub.Target.Arch &&
+ Stub.Target.Arch.getValue() != OverrideArch.getValue()) {
+ return make_error<StringError>(
+ "Supplied Arch conflicts with the text stub", OverrideEC);
+ }
+ Stub.Target.Arch = OverrideArch.getValue();
+ }
+ if (OverrideEndianness) {
+ if (Stub.Target.Endianness &&
+ Stub.Target.Endianness.getValue() != OverrideEndianness.getValue()) {
+ return make_error<StringError>(
+ "Supplied Endianness conflicts with the text stub", OverrideEC);
+ }
+ Stub.Target.Endianness = OverrideEndianness.getValue();
+ }
+ if (OverrideBitWidth) {
+ if (Stub.Target.BitWidth &&
+ Stub.Target.BitWidth.getValue() != OverrideBitWidth.getValue()) {
+ return make_error<StringError>(
+ "Supplied BitWidth conflicts with the text stub", OverrideEC);
+ }
+ Stub.Target.BitWidth = OverrideBitWidth.getValue();
+ }
+ if (OverrideTriple) {
+ if (Stub.Target.Triple &&
+ Stub.Target.Triple.getValue() != OverrideTriple.getValue()) {
+ return make_error<StringError>(
+ "Supplied Triple conflicts with the text stub", OverrideEC);
+ }
+ Stub.Target.Triple = OverrideTriple.getValue();
+ }
+ return Error::success();
+}
+
+Error ifs::validateIFSTarget(IFSStub &Stub, bool ParseTriple) {
+ std::error_code ValidationEC(1, std::generic_category());
+ if (Stub.Target.Triple) {
+ if (Stub.Target.Arch || Stub.Target.BitWidth || Stub.Target.Endianness ||
+ Stub.Target.ObjectFormat) {
+ return make_error<StringError>(
+ "Target triple cannot be used simultaneously with ELF target format",
+ ValidationEC);
+ }
+ if (ParseTriple) {
+ IFSTarget TargetFromTriple = parseTriple(Stub.Target.Triple.getValue());
+ Stub.Target.Arch = TargetFromTriple.Arch;
+ Stub.Target.BitWidth = TargetFromTriple.BitWidth;
+ Stub.Target.Endianness = TargetFromTriple.Endianness;
+ }
+ return Error::success();
+ }
+ if (!Stub.Target.Arch || !Stub.Target.BitWidth || !Stub.Target.Endianness) {
+ // TODO: unify the error message.
+ if (!Stub.Target.Arch) {
+ return make_error<StringError>("Arch is not defined in the text stub",
+ ValidationEC);
+ }
+ if (!Stub.Target.BitWidth) {
+ return make_error<StringError>("BitWidth is not defined in the text stub",
+ ValidationEC);
+ }
+ if (!Stub.Target.Endianness) {
+ return make_error<StringError>(
+ "Endianness is not defined in the text stub", ValidationEC);
+ }
+ }
+ return Error::success();
+}
+
+IFSTarget ifs::parseTriple(StringRef TripleStr) {
+ Triple IFSTriple(TripleStr);
+ IFSTarget RetTarget;
+ // TODO: Implement a Triple Arch enum to e_machine map.
+ switch (IFSTriple.getArch()) {
+ case Triple::ArchType::aarch64:
+ RetTarget.Arch = (IFSArch)ELF::EM_AARCH64;
+ break;
+ case Triple::ArchType::x86_64:
+ RetTarget.Arch = (IFSArch)ELF::EM_X86_64;
+ break;
+ default:
+ RetTarget.Arch = (IFSArch)ELF::EM_NONE;
+ }
+ RetTarget.Endianness = IFSTriple.isLittleEndian() ? IFSEndiannessType::Little
+ : IFSEndiannessType::Big;
+ RetTarget.BitWidth =
+ IFSTriple.isArch64Bit() ? IFSBitWidthType::IFS64 : IFSBitWidthType::IFS32;
+ return RetTarget;
+}
+
+void ifs::stripIFSTarget(IFSStub &Stub, bool StripTriple, bool StripArch,
+ bool StripEndianness, bool StripBitWidth) {
+ if (StripTriple || StripArch) {
+ Stub.Target.Arch.reset();
+ Stub.Target.ArchString.reset();
+ }
+ if (StripTriple || StripEndianness) {
+ Stub.Target.Endianness.reset();
+ }
+ if (StripTriple || StripBitWidth) {
+ Stub.Target.BitWidth.reset();
+ }
+ if (StripTriple) {
+ Stub.Target.Triple.reset();
+ }
+ if (!Stub.Target.Arch && !Stub.Target.BitWidth && !Stub.Target.Endianness) {
+ Stub.Target.ObjectFormat.reset();
+ }
+}
diff --git a/llvm/lib/InterfaceStub/IFSStub.cpp b/llvm/lib/InterfaceStub/IFSStub.cpp
new file mode 100644
index 000000000000..bbc91ada1ded
--- /dev/null
+++ b/llvm/lib/InterfaceStub/IFSStub.cpp
@@ -0,0 +1,133 @@
+//===- IFSStub.cpp --------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===-----------------------------------------------------------------------===/
+
+#include "llvm/InterfaceStub/IFSStub.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/Support/Error.h"
+
+using namespace llvm;
+using namespace llvm::ifs;
+
+IFSStub::IFSStub(IFSStub const &Stub) {
+ IfsVersion = Stub.IfsVersion;
+ Target = Stub.Target;
+ SoName = Stub.SoName;
+ NeededLibs = Stub.NeededLibs;
+ Symbols = Stub.Symbols;
+}
+
+IFSStub::IFSStub(IFSStub &&Stub) {
+ IfsVersion = std::move(Stub.IfsVersion);
+ Target = std::move(Stub.Target);
+ SoName = std::move(Stub.SoName);
+ NeededLibs = std::move(Stub.NeededLibs);
+ Symbols = std::move(Stub.Symbols);
+}
+
+IFSStubTriple::IFSStubTriple(IFSStubTriple const &Stub) {
+ IfsVersion = Stub.IfsVersion;
+ Target = Stub.Target;
+ SoName = Stub.SoName;
+ NeededLibs = Stub.NeededLibs;
+ Symbols = Stub.Symbols;
+}
+
+IFSStubTriple::IFSStubTriple(IFSStub const &Stub) {
+ IfsVersion = Stub.IfsVersion;
+ Target = Stub.Target;
+ SoName = Stub.SoName;
+ NeededLibs = Stub.NeededLibs;
+ Symbols = Stub.Symbols;
+}
+
+IFSStubTriple::IFSStubTriple(IFSStubTriple &&Stub) {
+ IfsVersion = std::move(Stub.IfsVersion);
+ Target = std::move(Stub.Target);
+ SoName = std::move(Stub.SoName);
+ NeededLibs = std::move(Stub.NeededLibs);
+ Symbols = std::move(Stub.Symbols);
+}
+
+bool IFSTarget::empty() {
+ return !Triple && !ObjectFormat && !Arch && !ArchString && !Endianness &&
+ !BitWidth;
+}
+
+uint8_t ifs::convertIFSBitWidthToELF(IFSBitWidthType BitWidth) {
+ switch (BitWidth) {
+ case IFSBitWidthType::IFS32:
+ return ELF::ELFCLASS32;
+ case IFSBitWidthType::IFS64:
+ return ELF::ELFCLASS64;
+ default:
+ llvm_unreachable("unknown bitwidth");
+ }
+}
+
+uint8_t ifs::convertIFSEndiannessToELF(IFSEndiannessType Endianness) {
+ switch (Endianness) {
+ case IFSEndiannessType::Little:
+ return ELF::ELFDATA2LSB;
+ case IFSEndiannessType::Big:
+ return ELF::ELFDATA2MSB;
+ default:
+ llvm_unreachable("unknown endianness");
+ }
+}
+
+uint8_t ifs::convertIFSSymbolTypeToELF(IFSSymbolType SymbolType) {
+ switch (SymbolType) {
+ case IFSSymbolType::Object:
+ return ELF::STT_OBJECT;
+ case IFSSymbolType::Func:
+ return ELF::STT_FUNC;
+ case IFSSymbolType::TLS:
+ return ELF::STT_TLS;
+ case IFSSymbolType::NoType:
+ default:
+ return ELF::STT_NOTYPE;
+ }
+}
+
+IFSBitWidthType ifs::convertELFBitWidthToIFS(uint8_t BitWidth) {
+ switch (BitWidth) {
+ case ELF::ELFCLASS32:
+ return IFSBitWidthType::IFS32;
+ case ELF::ELFCLASS64:
+ return IFSBitWidthType::IFS64;
+ default:
+ return IFSBitWidthType::Unknown;
+ }
+}
+
+IFSEndiannessType ifs::convertELFEndiannessToIFS(uint8_t Endianness) {
+ switch (Endianness) {
+ case ELF::ELFDATA2LSB:
+ return IFSEndiannessType::Little;
+ case ELF::ELFDATA2MSB:
+ return IFSEndiannessType::Big;
+ default:
+ return IFSEndiannessType::Unknown;
+ }
+}
+
+IFSSymbolType ifs::convertELFSymbolTypeToIFS(uint8_t SymbolType) {
+ SymbolType = SymbolType & 0xf;
+ switch (SymbolType) {
+ case ELF::STT_OBJECT:
+ return IFSSymbolType::Object;
+ case ELF::STT_FUNC:
+ return IFSSymbolType::Func;
+ case ELF::STT_TLS:
+ return IFSSymbolType::TLS;
+ case ELF::STT_NOTYPE:
+ return IFSSymbolType::NoType;
+ default:
+ return IFSSymbolType::Unknown;
+ }
+}
diff --git a/llvm/lib/InterfaceStub/TBEHandler.cpp b/llvm/lib/InterfaceStub/TBEHandler.cpp
deleted file mode 100644
index ee95d21ee661..000000000000
--- a/llvm/lib/InterfaceStub/TBEHandler.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-//===- TBEHandler.cpp -----------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===-----------------------------------------------------------------------===/
-
-#include "llvm/InterfaceStub/TBEHandler.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/InterfaceStub/ELFStub.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/YAMLTraits.h"
-
-using namespace llvm;
-using namespace llvm::elfabi;
-
-LLVM_YAML_STRONG_TYPEDEF(ELFArch, ELFArchMapper)
-
-namespace llvm {
-namespace yaml {
-
-/// YAML traits for ELFSymbolType.
-template <> struct ScalarEnumerationTraits<ELFSymbolType> {
- static void enumeration(IO &IO, ELFSymbolType &SymbolType) {
- IO.enumCase(SymbolType, "NoType", ELFSymbolType::NoType);
- IO.enumCase(SymbolType, "Func", ELFSymbolType::Func);
- IO.enumCase(SymbolType, "Object", ELFSymbolType::Object);
- IO.enumCase(SymbolType, "TLS", ELFSymbolType::TLS);
- IO.enumCase(SymbolType, "Unknown", ELFSymbolType::Unknown);
- // Treat other symbol types as noise, and map to Unknown.
- if (!IO.outputting() && IO.matchEnumFallback())
- SymbolType = ELFSymbolType::Unknown;
- }
-};
-
-/// YAML traits for ELFArch.
-template <> struct ScalarTraits<ELFArchMapper> {
- static void output(const ELFArchMapper &Value, void *,
- llvm::raw_ostream &Out) {
- // Map from integer to architecture string.
- switch (Value) {
- case (ELFArch)ELF::EM_X86_64:
- Out << "x86_64";
- break;
- case (ELFArch)ELF::EM_AARCH64:
- Out << "AArch64";
- break;
- case (ELFArch)ELF::EM_NONE:
- default:
- Out << "Unknown";
- }
- }
-
- static StringRef input(StringRef Scalar, void *, ELFArchMapper &Value) {
- // Map from architecture string to integer.
- Value = StringSwitch<ELFArch>(Scalar)
- .Case("x86_64", ELF::EM_X86_64)
- .Case("AArch64", ELF::EM_AARCH64)
- .Case("Unknown", ELF::EM_NONE)
- .Default(ELF::EM_NONE);
-
- // Returning empty StringRef indicates successful parse.
- return StringRef();
- }
-
- // Don't place quotation marks around architecture value.
- static QuotingType mustQuote(StringRef) { return QuotingType::None; }
-};
-
-/// YAML traits for ELFSymbol.
-template <> struct MappingTraits<ELFSymbol> {
- static void mapping(IO &IO, ELFSymbol &Symbol) {
- IO.mapRequired("Type", Symbol.Type);
- // The need for symbol size depends on the symbol type.
- if (Symbol.Type == ELFSymbolType::NoType) {
- IO.mapOptional("Size", Symbol.Size, (uint64_t)0);
- } else if (Symbol.Type == ELFSymbolType::Func) {
- Symbol.Size = 0;
- } else {
- IO.mapRequired("Size", Symbol.Size);
- }
- IO.mapOptional("Undefined", Symbol.Undefined, false);
- IO.mapOptional("Weak", Symbol.Weak, false);
- IO.mapOptional("Warning", Symbol.Warning);
- }
-
- // Compacts symbol information into a single line.
- static const bool flow = true;
-};
-
-/// YAML traits for set of ELFSymbols.
-template <> struct CustomMappingTraits<std::set<ELFSymbol>> {
- static void inputOne(IO &IO, StringRef Key, std::set<ELFSymbol> &Set) {
- ELFSymbol Sym(Key.str());
- IO.mapRequired(Key.str().c_str(), Sym);
- Set.insert(Sym);
- }
-
- static void output(IO &IO, std::set<ELFSymbol> &Set) {
- for (auto &Sym : Set)
- IO.mapRequired(Sym.Name.c_str(), const_cast<ELFSymbol &>(Sym));
- }
-};
-
-/// YAML traits for ELFStub objects.
-template <> struct MappingTraits<ELFStub> {
- static void mapping(IO &IO, ELFStub &Stub) {
- if (!IO.mapTag("!tapi-tbe", true))
- IO.setError("Not a .tbe YAML file.");
- IO.mapRequired("TbeVersion", Stub.TbeVersion);
- IO.mapOptional("SoName", Stub.SoName);
- IO.mapRequired("Arch", (ELFArchMapper &)Stub.Arch);
- IO.mapOptional("NeededLibs", Stub.NeededLibs);
- IO.mapRequired("Symbols", Stub.Symbols);
- }
-};
-
-} // end namespace yaml
-} // end namespace llvm
-
-Expected<std::unique_ptr<ELFStub>> elfabi::readTBEFromBuffer(StringRef Buf) {
- yaml::Input YamlIn(Buf);
- std::unique_ptr<ELFStub> Stub(new ELFStub());
- YamlIn >> *Stub;
- if (std::error_code Err = YamlIn.error())
- return createStringError(Err, "YAML failed reading as TBE");
-
- if (Stub->TbeVersion > elfabi::TBEVersionCurrent)
- return make_error<StringError>(
- "TBE version " + Stub->TbeVersion.getAsString() + " is unsupported.",
- std::make_error_code(std::errc::invalid_argument));
-
- return std::move(Stub);
-}
-
-Error elfabi::writeTBEToOutputStream(raw_ostream &OS, const ELFStub &Stub) {
- yaml::Output YamlOut(OS, NULL, /*WrapColumn =*/0);
-
- YamlOut << const_cast<ELFStub &>(Stub);
- return Error::success();
-}