[llvm] 8b4acb0 - [elfabi] Prepare elfabi/ifs merging.

Haowei Wu via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 19 11:23:47 PDT 2021


Author: Haowei Wu
Date: 2021-07-19T11:22:43-07:00
New Revision: 8b4acb067fd38ac33a63669ef46966dfee59257e

URL: https://github.com/llvm/llvm-project/commit/8b4acb067fd38ac33a63669ef46966dfee59257e
DIFF: https://github.com/llvm/llvm-project/commit/8b4acb067fd38ac33a63669ef46966dfee59257e.diff

LOG: [elfabi] Prepare elfabi/ifs merging.

This change implements unified text stub format and command line
interface proposed in the elfabi/ifs merge plan.

Differential Revision: https://reviews.llvm.org/D99399

Added: 
    llvm/lib/BinaryFormat/ELF.cpp
    llvm/test/tools/llvm-elfabi/read-tbe-with-bad-bitwidth.test
    llvm/test/tools/llvm-elfabi/read-tbe-with-bad-endianness.test
    llvm/test/tools/llvm-elfabi/strip-target.test

Modified: 
    llvm/include/llvm/BinaryFormat/ELF.h
    llvm/include/llvm/InterfaceStub/ELFObjHandler.h
    llvm/include/llvm/InterfaceStub/ELFStub.h
    llvm/include/llvm/InterfaceStub/TBEHandler.h
    llvm/lib/BinaryFormat/CMakeLists.txt
    llvm/lib/InterfaceStub/CMakeLists.txt
    llvm/lib/InterfaceStub/ELFObjHandler.cpp
    llvm/lib/InterfaceStub/ELFStub.cpp
    llvm/lib/InterfaceStub/TBEHandler.cpp
    llvm/test/tools/llvm-elfabi/binary-read-add-soname.test
    llvm/test/tools/llvm-elfabi/binary-read-arch.test
    llvm/test/tools/llvm-elfabi/binary-read-bad-soname.test
    llvm/test/tools/llvm-elfabi/binary-read-bad-vaddr.test
    llvm/test/tools/llvm-elfabi/binary-read-neededlibs-bad-offset.test
    llvm/test/tools/llvm-elfabi/binary-read-neededlibs.test
    llvm/test/tools/llvm-elfabi/binary-read-no-dt-strsz.test
    llvm/test/tools/llvm-elfabi/binary-read-no-dt-strtab.test
    llvm/test/tools/llvm-elfabi/binary-read-no-dynamic.test
    llvm/test/tools/llvm-elfabi/binary-read-replace-soname.test
    llvm/test/tools/llvm-elfabi/binary-read-soname-no-null.test
    llvm/test/tools/llvm-elfabi/binary-read-soname.test
    llvm/test/tools/llvm-elfabi/binary-read-syms-gnu-hash.test
    llvm/test/tools/llvm-elfabi/binary-read-syms-sysv-hash.test
    llvm/test/tools/llvm-elfabi/fail-file-open.test
    llvm/test/tools/llvm-elfabi/fail-file-write-windows.test
    llvm/test/tools/llvm-elfabi/fail-file-write.test
    llvm/test/tools/llvm-elfabi/output-target-error.test
    llvm/test/tools/llvm-elfabi/preserve-dates-stub.test
    llvm/test/tools/llvm-elfabi/preserve-dates-tbe.test
    llvm/test/tools/llvm-elfabi/read-elf-dynsym.test
    llvm/test/tools/llvm-elfabi/read-tbe-as-elf.test
    llvm/test/tools/llvm-elfabi/read-tbe-as-tbe.test
    llvm/test/tools/llvm-elfabi/read-unsupported-file.test
    llvm/test/tools/llvm-elfabi/tbe-emits-current-version.test
    llvm/test/tools/llvm-elfabi/tbe-read-basic.test
    llvm/test/tools/llvm-elfabi/write-stub-no-nonlocal-symbol.test
    llvm/test/tools/llvm-elfabi/write-stub.test
    llvm/tools/llvm-elfabi/CMakeLists.txt
    llvm/tools/llvm-elfabi/llvm-elfabi.cpp
    llvm/tools/llvm-ifs/CMakeLists.txt
    llvm/tools/llvm-ifs/llvm-ifs.cpp
    llvm/unittests/InterfaceStub/ELFYAMLTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index 8660d40ca039b..d8961aa43c48b 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -19,8 +19,10 @@
 #ifndef LLVM_BINARYFORMAT_ELF_H
 #define LLVM_BINARYFORMAT_ELF_H
 
+#include "llvm/ADT/StringRef.h"
 #include <cstdint>
 #include <cstring>
+#include <string>
 
 namespace llvm {
 namespace ELF {
@@ -1673,6 +1675,12 @@ enum {
   ELFCOMPRESS_HIPROC = 0x7fffffff  // End of processor-specific.
 };
 
+/// Convert an architecture name into ELF's e_machine value.
+uint16_t convertArchNameToEMachine(StringRef Arch);
+
+/// Convert an ELF's e_machine value into an architecture name.
+StringRef convertEMachineToArchName(uint16_t EMachine);
+
 } // end namespace ELF
 } // end namespace llvm
 

diff  --git a/llvm/include/llvm/InterfaceStub/ELFObjHandler.h b/llvm/include/llvm/InterfaceStub/ELFObjHandler.h
index 43cac176d1013..a96f02bc3881e 100644
--- a/llvm/include/llvm/InterfaceStub/ELFObjHandler.h
+++ b/llvm/include/llvm/InterfaceStub/ELFObjHandler.h
@@ -35,11 +35,10 @@ Expected<std::unique_ptr<ELFStub>> readELFFile(MemoryBufferRef Buf);
 ///
 /// @param FilePath File path for writing the ELF binary.
 /// @param Stub Source ELFStub to generate a binary ELF stub from.
-/// @param OutputFormat Target ELFType to write binary as.
 /// @param WriteIfChanged Whether or not to preserve timestamp if
 ///        the output stays the same.
 Error writeBinaryStub(StringRef FilePath, const ELFStub &Stub,
-                      ELFTarget OutputFormat, bool WriteIfChanged = false);
+                      bool WriteIfChanged = false);
 
 } // end namespace elfabi
 } // end namespace llvm

diff  --git a/llvm/include/llvm/InterfaceStub/ELFStub.h b/llvm/include/llvm/InterfaceStub/ELFStub.h
index 20c1ab449bda3..a8c3f22a22a1b 100644
--- a/llvm/include/llvm/InterfaceStub/ELFStub.h
+++ b/llvm/include/llvm/InterfaceStub/ELFStub.h
@@ -15,6 +15,7 @@
 #define LLVM_INTERFACESTUB_ELFSTUB_H
 
 #include "llvm/BinaryFormat/ELF.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/VersionTuple.h"
 #include <set>
 #include <vector>
@@ -34,8 +35,25 @@ enum class ELFSymbolType {
   Unknown = 16,
 };
 
+enum class ELFEndiannessType {
+  Little = ELF::ELFDATA2LSB,
+  Big = ELF::ELFDATA2MSB,
+
+  // Endianness info is 1 bytes, 256 is safely out of rance.
+  Unknown = 256,
+};
+
+enum class ELFBitWidthType {
+  ELF32 = ELF::ELFCLASS32,
+  ELF64 = ELF::ELFCLASS64,
+
+  // Bit width info is 1 bytes, 256 is safely out of rance.
+  Unknown = 256,
+};
+
 struct ELFSymbol {
-  ELFSymbol(std::string SymbolName) : Name(SymbolName) {}
+  ELFSymbol() = default;
+  explicit ELFSymbol(std::string SymbolName) : Name(std::move(SymbolName)) {}
   std::string Name;
   uint64_t Size;
   ELFSymbolType Type;
@@ -45,21 +63,42 @@ struct ELFSymbol {
   bool operator<(const ELFSymbol &RHS) const { return Name < RHS.Name; }
 };
 
+struct IFSTarget {
+  Optional<std::string> Triple;
+  Optional<std::string> ObjectFormat;
+  Optional<ELFArch> Arch;
+  Optional<std::string> ArchString;
+  Optional<ELFEndiannessType> Endianness;
+  Optional<ELFBitWidthType> BitWidth;
+};
+
 // A cumulative representation of ELF stubs.
 // Both textual and binary stubs will read into and write from this object.
-class ELFStub {
+struct ELFStub {
   // TODO: Add support for symbol versioning.
-public:
   VersionTuple TbeVersion;
   Optional<std::string> SoName;
-  ELFArch Arch;
+  IFSTarget Target;
   std::vector<std::string> NeededLibs;
-  std::set<ELFSymbol> Symbols;
+  std::vector<ELFSymbol> Symbols;
 
   ELFStub() {}
   ELFStub(const ELFStub &Stub);
   ELFStub(ELFStub &&Stub);
 };
+
+// Create a alias class for ELFStub.
+// LLVM's YAML library does not allow mapping a class with 2 traits,
+// which prevents us using 'Target:' field with 
diff erent definitions.
+// This class makes it possible to map a second traits so the same data
+// structure can be used for 2 
diff erent yaml schema.
+struct ELFStubTriple : ELFStub {
+  ELFStubTriple() {}
+  ELFStubTriple(const ELFStub &Stub);
+  ELFStubTriple(const ELFStubTriple &Stub);
+  ELFStubTriple(ELFStubTriple &&Stub);
+};
+
 } // end namespace elfabi
 } // end namespace llvm
 

diff  --git a/llvm/include/llvm/InterfaceStub/TBEHandler.h b/llvm/include/llvm/InterfaceStub/TBEHandler.h
index aee7ed0d0fcbb..0caa07af33021 100644
--- a/llvm/include/llvm/InterfaceStub/TBEHandler.h
+++ b/llvm/include/llvm/InterfaceStub/TBEHandler.h
@@ -15,6 +15,7 @@
 #ifndef LLVM_INTERFACESTUB_TBEHANDLER_H
 #define LLVM_INTERFACESTUB_TBEHANDLER_H
 
+#include "ELFStub.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/VersionTuple.h"
 #include <memory>
@@ -27,7 +28,7 @@ class StringRef;
 
 namespace elfabi {
 
-class ELFStub;
+struct ELFStub;
 
 const VersionTuple TBEVersionCurrent(1, 0);
 
@@ -37,6 +38,22 @@ Expected<std::unique_ptr<ELFStub>> readTBEFromBuffer(StringRef Buf);
 /// Attempts to write an ELF interface file to a raw_ostream.
 Error writeTBEToOutputStream(raw_ostream &OS, const ELFStub &Stub);
 
+/// Override the target platform inforation in the text stub.
+Error overrideTBETarget(ELFStub &Stub, Optional<ELFArch> OverrideArch,
+                        Optional<ELFEndiannessType> OverrideEndianness,
+                        Optional<ELFBitWidthType> OverrideBitWidth,
+                        Optional<std::string> OverrideTriple);
+
+/// Validate the target platform inforation in the text stub.
+Error validateTBETarget(ELFStub &Stub, bool ParseTriple);
+
+/// Strips target platform information from the text stub.
+void stripTBETarget(ELFStub &Stub, bool StripTriple, bool StripArch,
+                    bool StripEndianness, bool StripBitWidth);
+
+/// Parse llvm triple string into a IFSTarget struct.
+IFSTarget parseTriple(StringRef TripleStr);
+
 } // end namespace elfabi
 } // end namespace llvm
 

diff  --git a/llvm/lib/BinaryFormat/CMakeLists.txt b/llvm/lib/BinaryFormat/CMakeLists.txt
index 66c890524543a..37f6865a487e8 100644
--- a/llvm/lib/BinaryFormat/CMakeLists.txt
+++ b/llvm/lib/BinaryFormat/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_llvm_component_library(LLVMBinaryFormat
   AMDGPUMetadataVerifier.cpp
   Dwarf.cpp
+  ELF.cpp
   MachO.cpp
   Magic.cpp
   Minidump.cpp

diff  --git a/llvm/lib/BinaryFormat/ELF.cpp b/llvm/lib/BinaryFormat/ELF.cpp
new file mode 100644
index 0000000000000..2ede63f464d3a
--- /dev/null
+++ b/llvm/lib/BinaryFormat/ELF.cpp
@@ -0,0 +1,568 @@
+//===- llvm/BinaryFormat/ELF.cpp - The ELF format ---------------*- C++ -*-===//
+//
+// 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/BinaryFormat/ELF.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Error.h"
+
+using namespace llvm;
+using namespace ELF;
+
+/// Convert an architecture name into ELF's e_machine value.
+uint16_t ELF::convertArchNameToEMachine(StringRef Arch) {
+  std::string LowerArch = Arch.lower();
+  return StringSwitch<uint16_t>(LowerArch)
+      .Case("none", EM_NONE)
+      .Case("m32", EM_M32)
+      .Case("sparc", EM_SPARC)
+      .Case("386", EM_386)
+      .Case("68k", EM_68K)
+      .Case("88k", EM_88K)
+      .Case("iamcu", EM_IAMCU)
+      .Case("860", EM_860)
+      .Case("mips", EM_MIPS)
+      .Case("s370", EM_S370)
+      .Case("mips_rs3_le", EM_MIPS_RS3_LE)
+      .Case("parisc", EM_PARISC)
+      .Case("vpp500", EM_VPP500)
+      .Case("sparc32plus", EM_SPARC32PLUS)
+      .Case("960", EM_960)
+      .Case("ppc", EM_PPC)
+      .Case("ppc64", EM_PPC64)
+      .Case("s390", EM_S390)
+      .Case("spu", EM_SPU)
+      .Case("v800", EM_V800)
+      .Case("fr20", EM_FR20)
+      .Case("rh32", EM_RH32)
+      .Case("rce", EM_RCE)
+      .Case("arm", EM_ARM)
+      .Case("alpha", EM_ALPHA)
+      .Case("sh", EM_SH)
+      .Case("sparcv9", EM_SPARCV9)
+      .Case("tricore", EM_TRICORE)
+      .Case("arc", EM_ARC)
+      .Case("h8_300", EM_H8_300)
+      .Case("h8_300h", EM_H8_300H)
+      .Case("h8s", EM_H8S)
+      .Case("h8_500", EM_H8_500)
+      .Case("ia_64", EM_IA_64)
+      .Case("mips_x", EM_MIPS_X)
+      .Case("coldfire", EM_COLDFIRE)
+      .Case("68hc12", EM_68HC12)
+      .Case("mma", EM_MMA)
+      .Case("pcp", EM_PCP)
+      .Case("ncpu", EM_NCPU)
+      .Case("ndr1", EM_NDR1)
+      .Case("starcore", EM_STARCORE)
+      .Case("me16", EM_ME16)
+      .Case("st100", EM_ST100)
+      .Case("tinyj", EM_TINYJ)
+      .Case("x86_64", EM_X86_64)
+      .Case("pdsp", EM_PDSP)
+      .Case("pdp10", EM_PDP10)
+      .Case("pdp11", EM_PDP11)
+      .Case("fx66", EM_FX66)
+      .Case("st9plus", EM_ST9PLUS)
+      .Case("st7", EM_ST7)
+      .Case("68hc16", EM_68HC16)
+      .Case("68hc11", EM_68HC11)
+      .Case("68hc08", EM_68HC08)
+      .Case("68hc05", EM_68HC05)
+      .Case("svx", EM_SVX)
+      .Case("st19", EM_ST19)
+      .Case("vax", EM_VAX)
+      .Case("cris", EM_CRIS)
+      .Case("javelin", EM_JAVELIN)
+      .Case("firepath", EM_FIREPATH)
+      .Case("zsp", EM_ZSP)
+      .Case("mmix", EM_MMIX)
+      .Case("huany", EM_HUANY)
+      .Case("prism", EM_PRISM)
+      .Case("avr", EM_AVR)
+      .Case("fr30", EM_FR30)
+      .Case("d10v", EM_D10V)
+      .Case("d30v", EM_D30V)
+      .Case("v850", EM_V850)
+      .Case("m32r", EM_M32R)
+      .Case("mn10300", EM_MN10300)
+      .Case("mn10200", EM_MN10200)
+      .Case("pj", EM_PJ)
+      .Case("openrisc", EM_OPENRISC)
+      .Case("arc_compact", EM_ARC_COMPACT)
+      .Case("xtensa", EM_XTENSA)
+      .Case("videocore", EM_VIDEOCORE)
+      .Case("tmm_gpp", EM_TMM_GPP)
+      .Case("ns32k", EM_NS32K)
+      .Case("tpc", EM_TPC)
+      .Case("snp1k", EM_SNP1K)
+      .Case("st200", EM_ST200)
+      .Case("ip2k", EM_IP2K)
+      .Case("max", EM_MAX)
+      .Case("cr", EM_CR)
+      .Case("f2mc16", EM_F2MC16)
+      .Case("msp430", EM_MSP430)
+      .Case("blackfin", EM_BLACKFIN)
+      .Case("se_c33", EM_SE_C33)
+      .Case("sep", EM_SEP)
+      .Case("arca", EM_ARCA)
+      .Case("unicore", EM_UNICORE)
+      .Case("excess", EM_EXCESS)
+      .Case("dxp", EM_DXP)
+      .Case("altera_nios2", EM_ALTERA_NIOS2)
+      .Case("crx", EM_CRX)
+      .Case("xgate", EM_XGATE)
+      .Case("c166", EM_C166)
+      .Case("m16c", EM_M16C)
+      .Case("dspic30f", EM_DSPIC30F)
+      .Case("ce", EM_CE)
+      .Case("m32c", EM_M32C)
+      .Case("tsk3000", EM_TSK3000)
+      .Case("rs08", EM_RS08)
+      .Case("sharc", EM_SHARC)
+      .Case("ecog2", EM_ECOG2)
+      .Case("score7", EM_SCORE7)
+      .Case("dsp24", EM_DSP24)
+      .Case("videocore3", EM_VIDEOCORE3)
+      .Case("latticemico32", EM_LATTICEMICO32)
+      .Case("se_c17", EM_SE_C17)
+      .Case("ti_c6000", EM_TI_C6000)
+      .Case("ti_c2000", EM_TI_C2000)
+      .Case("ti_c5500", EM_TI_C5500)
+      .Case("mmdsp_plus", EM_MMDSP_PLUS)
+      .Case("cypress_m8c", EM_CYPRESS_M8C)
+      .Case("r32c", EM_R32C)
+      .Case("trimedia", EM_TRIMEDIA)
+      .Case("hexagon", EM_HEXAGON)
+      .Case("8051", EM_8051)
+      .Case("stxp7x", EM_STXP7X)
+      .Case("nds32", EM_NDS32)
+      .Case("ecog1", EM_ECOG1)
+      .Case("ecog1x", EM_ECOG1X)
+      .Case("maxq30", EM_MAXQ30)
+      .Case("ximo16", EM_XIMO16)
+      .Case("manik", EM_MANIK)
+      .Case("craynv2", EM_CRAYNV2)
+      .Case("rx", EM_RX)
+      .Case("metag", EM_METAG)
+      .Case("mcst_elbrus", EM_MCST_ELBRUS)
+      .Case("ecog16", EM_ECOG16)
+      .Case("cr16", EM_CR16)
+      .Case("etpu", EM_ETPU)
+      .Case("sle9x", EM_SLE9X)
+      .Case("l10m", EM_L10M)
+      .Case("k10m", EM_K10M)
+      .Case("aarch64", EM_AARCH64)
+      .Case("avr32", EM_AVR32)
+      .Case("stm8", EM_STM8)
+      .Case("tile64", EM_TILE64)
+      .Case("tilepro", EM_TILEPRO)
+      .Case("cuda", EM_CUDA)
+      .Case("tilegx", EM_TILEGX)
+      .Case("cloudshield", EM_CLOUDSHIELD)
+      .Case("corea_1st", EM_COREA_1ST)
+      .Case("corea_2nd", EM_COREA_2ND)
+      .Case("arc_compact2", EM_ARC_COMPACT2)
+      .Case("open8", EM_OPEN8)
+      .Case("rl78", EM_RL78)
+      .Case("videocore5", EM_VIDEOCORE5)
+      .Case("78kor", EM_78KOR)
+      .Case("56800ex", EM_56800EX)
+      .Case("ba1", EM_BA1)
+      .Case("ba2", EM_BA2)
+      .Case("xcore", EM_XCORE)
+      .Case("mchp_pic", EM_MCHP_PIC)
+      .Case("intel205", EM_INTEL205)
+      .Case("intel206", EM_INTEL206)
+      .Case("intel207", EM_INTEL207)
+      .Case("intel208", EM_INTEL208)
+      .Case("intel209", EM_INTEL209)
+      .Case("km32", EM_KM32)
+      .Case("kmx32", EM_KMX32)
+      .Case("kmx16", EM_KMX16)
+      .Case("kmx8", EM_KMX8)
+      .Case("kvarc", EM_KVARC)
+      .Case("cdp", EM_CDP)
+      .Case("coge", EM_COGE)
+      .Case("cool", EM_COOL)
+      .Case("norc", EM_NORC)
+      .Case("csr_kalimba", EM_CSR_KALIMBA)
+      .Case("amdgpu", EM_AMDGPU)
+      .Case("riscv", EM_RISCV)
+      .Case("lanai", EM_LANAI)
+      .Case("bpf", EM_BPF)
+      .Case("ve", EM_VE)
+      .Case("csky", EM_CSKY)
+      .Default(EM_NONE);
+}
+
+/// Convert an ELF's e_machine value into an architecture name.
+StringRef ELF::convertEMachineToArchName(uint16_t EMachine) {
+  switch (EMachine) {
+  case EM_NONE:
+    return "None";
+  case EM_M32:
+    return "m32";
+  case EM_SPARC:
+    return "sparc";
+  case EM_386:
+    return "386";
+  case EM_68K:
+    return "68k";
+  case EM_88K:
+    return "88k";
+  case EM_IAMCU:
+    return "iamcu";
+  case EM_860:
+    return "860";
+  case EM_MIPS:
+    return "mips";
+  case EM_S370:
+    return "s370";
+  case EM_MIPS_RS3_LE:
+    return "mips_rs3_le";
+  case EM_PARISC:
+    return "parisc";
+  case EM_VPP500:
+    return "vpp500";
+  case EM_SPARC32PLUS:
+    return "sparc32plus";
+  case EM_960:
+    return "960";
+  case EM_PPC:
+    return "ppc";
+  case EM_PPC64:
+    return "ppc64";
+  case EM_S390:
+    return "s390";
+  case EM_SPU:
+    return "spu";
+  case EM_V800:
+    return "v800";
+  case EM_FR20:
+    return "fr20";
+  case EM_RH32:
+    return "rh32";
+  case EM_RCE:
+    return "rce";
+  case EM_ARM:
+    return "arm";
+  case EM_ALPHA:
+    return "alpha";
+  case EM_SH:
+    return "sh";
+  case EM_SPARCV9:
+    return "sparcv9";
+  case EM_TRICORE:
+    return "tricore";
+  case EM_ARC:
+    return "arc";
+  case EM_H8_300:
+    return "h8_300";
+  case EM_H8_300H:
+    return "h8_300h";
+  case EM_H8S:
+    return "h8s";
+  case EM_H8_500:
+    return "h8_500";
+  case EM_IA_64:
+    return "ia_64";
+  case EM_MIPS_X:
+    return "mips_x";
+  case EM_COLDFIRE:
+    return "coldfire";
+  case EM_68HC12:
+    return "68hc12";
+  case EM_MMA:
+    return "mma";
+  case EM_PCP:
+    return "pcp";
+  case EM_NCPU:
+    return "ncpu";
+  case EM_NDR1:
+    return "ndr1";
+  case EM_STARCORE:
+    return "starcore";
+  case EM_ME16:
+    return "me16";
+  case EM_ST100:
+    return "st100";
+  case EM_TINYJ:
+    return "tinyj";
+  case EM_X86_64:
+    return "x86_64";
+  case EM_PDSP:
+    return "pdsp";
+  case EM_PDP10:
+    return "pdp10";
+  case EM_PDP11:
+    return "pdp11";
+  case EM_FX66:
+    return "fx66";
+  case EM_ST9PLUS:
+    return "st9plus";
+  case EM_ST7:
+    return "st7";
+  case EM_68HC16:
+    return "68hc16";
+  case EM_68HC11:
+    return "68hc11";
+  case EM_68HC08:
+    return "68hc08";
+  case EM_68HC05:
+    return "68hc05";
+  case EM_SVX:
+    return "svx";
+  case EM_ST19:
+    return "st19";
+  case EM_VAX:
+    return "vax";
+  case EM_CRIS:
+    return "cris";
+  case EM_JAVELIN:
+    return "javelin";
+  case EM_FIREPATH:
+    return "firepath";
+  case EM_ZSP:
+    return "zsp";
+  case EM_MMIX:
+    return "mmix";
+  case EM_HUANY:
+    return "huany";
+  case EM_PRISM:
+    return "prism";
+  case EM_AVR:
+    return "avr";
+  case EM_FR30:
+    return "fr30";
+  case EM_D10V:
+    return "d10v";
+  case EM_D30V:
+    return "d30v";
+  case EM_V850:
+    return "v850";
+  case EM_M32R:
+    return "m32r";
+  case EM_MN10300:
+    return "mn10300";
+  case EM_MN10200:
+    return "mn10200";
+  case EM_PJ:
+    return "pj";
+  case EM_OPENRISC:
+    return "openrisc";
+  case EM_ARC_COMPACT:
+    return "arc_compact";
+  case EM_XTENSA:
+    return "xtensa";
+  case EM_VIDEOCORE:
+    return "videocore";
+  case EM_TMM_GPP:
+    return "tmm_gpp";
+  case EM_NS32K:
+    return "ns32k";
+  case EM_TPC:
+    return "tpc";
+  case EM_SNP1K:
+    return "snp1k";
+  case EM_ST200:
+    return "st200";
+  case EM_IP2K:
+    return "ip2k";
+  case EM_MAX:
+    return "max";
+  case EM_CR:
+    return "cr";
+  case EM_F2MC16:
+    return "f2mc16";
+  case EM_MSP430:
+    return "msp430";
+  case EM_BLACKFIN:
+    return "blackfin";
+  case EM_SE_C33:
+    return "se_c33";
+  case EM_SEP:
+    return "sep";
+  case EM_ARCA:
+    return "arca";
+  case EM_UNICORE:
+    return "unicore";
+  case EM_EXCESS:
+    return "excess";
+  case EM_DXP:
+    return "dxp";
+  case EM_ALTERA_NIOS2:
+    return "altera_nios2";
+  case EM_CRX:
+    return "crx";
+  case EM_XGATE:
+    return "xgate";
+  case EM_C166:
+    return "c166";
+  case EM_M16C:
+    return "m16c";
+  case EM_DSPIC30F:
+    return "dspic30f";
+  case EM_CE:
+    return "ce";
+  case EM_M32C:
+    return "m32c";
+  case EM_TSK3000:
+    return "tsk3000";
+  case EM_RS08:
+    return "rs08";
+  case EM_SHARC:
+    return "sharc";
+  case EM_ECOG2:
+    return "ecog2";
+  case EM_SCORE7:
+    return "score7";
+  case EM_DSP24:
+    return "dsp24";
+  case EM_VIDEOCORE3:
+    return "videocore3";
+  case EM_LATTICEMICO32:
+    return "latticemico32";
+  case EM_SE_C17:
+    return "se_c17";
+  case EM_TI_C6000:
+    return "ti_c6000";
+  case EM_TI_C2000:
+    return "ti_c2000";
+  case EM_TI_C5500:
+    return "ti_c5500";
+  case EM_MMDSP_PLUS:
+    return "mmdsp_plus";
+  case EM_CYPRESS_M8C:
+    return "cypress_m8c";
+  case EM_R32C:
+    return "r32c";
+  case EM_TRIMEDIA:
+    return "trimedia";
+  case EM_HEXAGON:
+    return "hexagon";
+  case EM_8051:
+    return "8051";
+  case EM_STXP7X:
+    return "stxp7x";
+  case EM_NDS32:
+    return "nds32";
+  case EM_ECOG1:
+    return "ecog1";
+  case EM_MAXQ30:
+    return "maxq30";
+  case EM_XIMO16:
+    return "ximo16";
+  case EM_MANIK:
+    return "manik";
+  case EM_CRAYNV2:
+    return "craynv2";
+  case EM_RX:
+    return "rx";
+  case EM_METAG:
+    return "metag";
+  case EM_MCST_ELBRUS:
+    return "mcst_elbrus";
+  case EM_ECOG16:
+    return "ecog16";
+  case EM_CR16:
+    return "cr16";
+  case EM_ETPU:
+    return "etpu";
+  case EM_SLE9X:
+    return "sle9x";
+  case EM_L10M:
+    return "l10m";
+  case EM_K10M:
+    return "k10m";
+  case EM_AARCH64:
+    return "AArch64";
+  case EM_AVR32:
+    return "avr32";
+  case EM_STM8:
+    return "stm8";
+  case EM_TILE64:
+    return "tile64";
+  case EM_TILEPRO:
+    return "tilepro";
+  case EM_CUDA:
+    return "cuda";
+  case EM_TILEGX:
+    return "tilegx";
+  case EM_CLOUDSHIELD:
+    return "cloudshield";
+  case EM_COREA_1ST:
+    return "corea_1st";
+  case EM_COREA_2ND:
+    return "corea_2nd";
+  case EM_ARC_COMPACT2:
+    return "arc_compact2";
+  case EM_OPEN8:
+    return "open8";
+  case EM_RL78:
+    return "rl78";
+  case EM_VIDEOCORE5:
+    return "videocore5";
+  case EM_78KOR:
+    return "78kor";
+  case EM_56800EX:
+    return "56800ex";
+  case EM_BA1:
+    return "ba1";
+  case EM_BA2:
+    return "ba2";
+  case EM_XCORE:
+    return "xcore";
+  case EM_MCHP_PIC:
+    return "mchp_pic";
+  case EM_INTEL205:
+    return "intel205";
+  case EM_INTEL206:
+    return "intel206";
+  case EM_INTEL207:
+    return "intel207";
+  case EM_INTEL208:
+    return "intel208";
+  case EM_INTEL209:
+    return "intel209";
+  case EM_KM32:
+    return "km32";
+  case EM_KMX32:
+    return "kmx32";
+  case EM_KMX16:
+    return "kmx16";
+  case EM_KMX8:
+    return "kmx8";
+  case EM_KVARC:
+    return "kvarc";
+  case EM_CDP:
+    return "cdp";
+  case EM_COGE:
+    return "coge";
+  case EM_COOL:
+    return "cool";
+  case EM_NORC:
+    return "norc";
+  case EM_CSR_KALIMBA:
+    return "csr_kalimba";
+  case EM_AMDGPU:
+    return "amdgpu";
+  case EM_RISCV:
+    return "riscv";
+  case EM_LANAI:
+    return "lanai";
+  case EM_BPF:
+    return "bpf";
+  case EM_VE:
+    return "ve";
+  case EM_CSKY:
+    return "csky";
+  default:
+    return "None";
+  }
+}

diff  --git a/llvm/lib/InterfaceStub/CMakeLists.txt b/llvm/lib/InterfaceStub/CMakeLists.txt
index 17801999c485a..497cd6d78104c 100644
--- a/llvm/lib/InterfaceStub/CMakeLists.txt
+++ b/llvm/lib/InterfaceStub/CMakeLists.txt
@@ -4,6 +4,7 @@ add_llvm_component_library(LLVMInterfaceStub
   TBEHandler.cpp
 
   LINK_COMPONENTS
+  BinaryFormat
   MC
   Object
   Support

diff  --git a/llvm/lib/InterfaceStub/ELFObjHandler.cpp b/llvm/lib/InterfaceStub/ELFObjHandler.cpp
index 9deb5ba0ae45d..6ed52befa04f2 100644
--- a/llvm/lib/InterfaceStub/ELFObjHandler.cpp
+++ b/llvm/lib/InterfaceStub/ELFObjHandler.cpp
@@ -250,7 +250,8 @@ template <class ELFT> class ELFStubBuilder {
     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 =
@@ -517,7 +518,7 @@ static Error populateSymbols(ELFStub &TargetStub,
     if (!SymName)
       return SymName.takeError();
     ELFSymbol Sym = createELFSym<ELFT>(*SymName, RawSym);
-    TargetStub.Symbols.insert(std::move(Sym));
+    TargetStub.Symbols.push_back(std::move(Sym));
     // TODO: Populate symbol warning.
   }
   return Error::success();
@@ -561,7 +562,12 @@ buildStub(const ELFObjectFile<ELFT> &ElfObj) {
                    DynEnt.StrSize);
 
   // Populate Arch from ELF header.
-  DestStub->Arch = ElfFile.getHeader().e_machine;
+  DestStub->Target.Arch = static_cast<ELFArch>(ElfFile.getHeader().e_machine);
+  DestStub->Target.BitWidth =
+      (ELFBitWidthType)ElfFile.getHeader().e_ident[EI_CLASS];
+  DestStub->Target.Endianness =
+      (ELFEndiannessType)ElfFile.getHeader().e_ident[EI_DATA];
+  DestStub->Target.ObjectFormat = "ELF";
 
   // Populate SoName from .dynamic entries and dynamic string table.
   if (DynEnt.SONameOffset.hasValue()) {
@@ -667,15 +673,23 @@ 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);
+                      bool WriteIfChanged) {
+  assert(Stub.Target.Arch);
+  assert(Stub.Target.BitWidth);
+  assert(Stub.Target.Endianness);
+  if (Stub.Target.BitWidth == ELFBitWidthType::ELF32) {
+    if (Stub.Target.Endianness == ELFEndiannessType::Little) {
+      return writeELFBinaryToFile<ELF32LE>(FilePath, Stub, WriteIfChanged);
+    } else {
+      return writeELFBinaryToFile<ELF32BE>(FilePath, Stub, WriteIfChanged);
+    }
+  } else {
+    if (Stub.Target.Endianness == ELFEndiannessType::Little) {
+      return writeELFBinaryToFile<ELF64LE>(FilePath, Stub, WriteIfChanged);
+    } else {
+      return writeELFBinaryToFile<ELF64BE>(FilePath, Stub, WriteIfChanged);
+    }
+  }
   llvm_unreachable("invalid binary output target");
 }
 

diff  --git a/llvm/lib/InterfaceStub/ELFStub.cpp b/llvm/lib/InterfaceStub/ELFStub.cpp
index 3c637695d8e71..81c521b5413ee 100644
--- a/llvm/lib/InterfaceStub/ELFStub.cpp
+++ b/llvm/lib/InterfaceStub/ELFStub.cpp
@@ -7,13 +7,14 @@
 //===-----------------------------------------------------------------------===/
 
 #include "llvm/InterfaceStub/ELFStub.h"
+#include "llvm/Support/Error.h"
 
 using namespace llvm;
 using namespace llvm::elfabi;
 
 ELFStub::ELFStub(ELFStub const &Stub) {
   TbeVersion = Stub.TbeVersion;
-  Arch = Stub.Arch;
+  Target = Stub.Target;
   SoName = Stub.SoName;
   NeededLibs = Stub.NeededLibs;
   Symbols = Stub.Symbols;
@@ -21,7 +22,31 @@ ELFStub::ELFStub(ELFStub const &Stub) {
 
 ELFStub::ELFStub(ELFStub &&Stub) {
   TbeVersion = std::move(Stub.TbeVersion);
-  Arch = std::move(Stub.Arch);
+  Target = std::move(Stub.Target);
+  SoName = std::move(Stub.SoName);
+  NeededLibs = std::move(Stub.NeededLibs);
+  Symbols = std::move(Stub.Symbols);
+}
+
+ELFStubTriple::ELFStubTriple(ELFStubTriple const &Stub) {
+  TbeVersion = Stub.TbeVersion;
+  Target = Stub.Target;
+  SoName = Stub.SoName;
+  NeededLibs = Stub.NeededLibs;
+  Symbols = Stub.Symbols;
+}
+
+ELFStubTriple::ELFStubTriple(ELFStub const &Stub) {
+  TbeVersion = Stub.TbeVersion;
+  Target = Stub.Target;
+  SoName = Stub.SoName;
+  NeededLibs = Stub.NeededLibs;
+  Symbols = Stub.Symbols;
+}
+
+ELFStubTriple::ELFStubTriple(ELFStubTriple &&Stub) {
+  TbeVersion = std::move(Stub.TbeVersion);
+  Target = std::move(Stub.Target);
   SoName = std::move(Stub.SoName);
   NeededLibs = std::move(Stub.NeededLibs);
   Symbols = std::move(Stub.Symbols);

diff  --git a/llvm/lib/InterfaceStub/TBEHandler.cpp b/llvm/lib/InterfaceStub/TBEHandler.cpp
index ee95d21ee6618..ea2dd7a26b4ac 100644
--- a/llvm/lib/InterfaceStub/TBEHandler.cpp
+++ b/llvm/lib/InterfaceStub/TBEHandler.cpp
@@ -9,14 +9,16 @@
 #include "llvm/InterfaceStub/TBEHandler.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
 #include "llvm/InterfaceStub/ELFStub.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/LineIterator.h"
 #include "llvm/Support/YAMLTraits.h"
 
 using namespace llvm;
 using namespace llvm::elfabi;
 
-LLVM_YAML_STRONG_TYPEDEF(ELFArch, ELFArchMapper)
+LLVM_YAML_IS_SEQUENCE_VECTOR(ELFSymbol)
 
 namespace llvm {
 namespace yaml {
@@ -35,43 +37,80 @@ template <> struct ScalarEnumerationTraits<ELFSymbolType> {
   }
 };
 
-/// YAML traits for ELFArch.
-template <> struct ScalarTraits<ELFArchMapper> {
-  static void output(const ELFArchMapper &Value, void *,
+template <> struct ScalarTraits<ELFEndiannessType> {
+  static void output(const ELFEndiannessType &Value, void *,
                      llvm::raw_ostream &Out) {
-    // Map from integer to architecture string.
     switch (Value) {
-    case (ELFArch)ELF::EM_X86_64:
-      Out << "x86_64";
+    case ELFEndiannessType::Big:
+      Out << "big";
       break;
-    case (ELFArch)ELF::EM_AARCH64:
-      Out << "AArch64";
+    case ELFEndiannessType::Little:
+      Out << "little";
       break;
-    case (ELFArch)ELF::EM_NONE:
     default:
-      Out << "Unknown";
+      llvm_unreachable("Unsupported endianness");
     }
   }
 
-  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);
+  static StringRef input(StringRef Scalar, void *, ELFEndiannessType &Value) {
+    Value = StringSwitch<ELFEndiannessType>(Scalar)
+                .Case("big", ELFEndiannessType::Big)
+                .Case("little", ELFEndiannessType::Little)
+                .Default(ELFEndiannessType::Unknown);
+    if (Value == ELFEndiannessType::Unknown) {
+      return "Unsupported endianness";
+    }
+    return StringRef();
+  }
+
+  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+template <> struct ScalarTraits<ELFBitWidthType> {
+  static void output(const ELFBitWidthType &Value, void *,
+                     llvm::raw_ostream &Out) {
+    switch (Value) {
+    case ELFBitWidthType::ELF32:
+      Out << "32";
+      break;
+    case ELFBitWidthType::ELF64:
+      Out << "64";
+      break;
+    default:
+      llvm_unreachable("Unsupported bit width");
+    }
+  }
 
-    // Returning empty StringRef indicates successful parse.
+  static StringRef input(StringRef Scalar, void *, ELFBitWidthType &Value) {
+    Value = StringSwitch<ELFBitWidthType>(Scalar)
+                .Case("32", ELFBitWidthType::ELF32)
+                .Case("64", ELFBitWidthType::ELF64)
+                .Default(ELFBitWidthType::Unknown);
+    if (Value == ELFBitWidthType::Unknown) {
+      return "Unsupported bit width";
+    }
     return StringRef();
   }
 
-  // Don't place quotation marks around architecture value.
   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<ELFSymbol> {
   static void mapping(IO &IO, ELFSymbol &Symbol) {
+    IO.mapRequired("Name", Symbol.Name);
     IO.mapRequired("Type", Symbol.Type);
     // The need for symbol size depends on the symbol type.
     if (Symbol.Type == ELFSymbolType::NoType) {
@@ -87,57 +126,203 @@ template <> struct MappingTraits<ELFSymbol> {
   }
 
   // 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));
-  }
+  static const bool flow = true; // NOLINT(readability-identifier-naming)
 };
 
 /// YAML traits for ELFStub objects.
 template <> struct MappingTraits<ELFStub> {
   static void mapping(IO &IO, ELFStub &Stub) {
-    if (!IO.mapTag("!tapi-tbe", true))
+    if (!IO.mapTag("!ifs-v1", 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("Target", Stub.Target);
     IO.mapOptional("NeededLibs", Stub.NeededLibs);
     IO.mapRequired("Symbols", Stub.Symbols);
   }
 };
 
+/// YAML traits for ELFStubTriple objects.
+template <> struct MappingTraits<ELFStubTriple> {
+  static void mapping(IO &IO, ELFStubTriple &Stub) {
+    if (!IO.mapTag("!ifs-v1", true))
+      IO.setError("Not a .tbe YAML file.");
+    IO.mapRequired("TbeVersion", Stub.TbeVersion);
+    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<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())
+  std::unique_ptr<ELFStubTriple> Stub(new ELFStubTriple());
+  if (usesTriple(Buf)) {
+    YamlIn >> *Stub;
+  } else {
+    YamlIn >> *static_cast<ELFStub *>(Stub.get());
+  }
+  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));
-
+  if (Stub->Target.ArchString) {
+    Stub->Target.Arch =
+        ELF::convertArchNameToEMachine(Stub->Target.ArchString.getValue());
+  }
   return std::move(Stub);
 }
 
 Error elfabi::writeTBEToOutputStream(raw_ostream &OS, const ELFStub &Stub) {
   yaml::Output YamlOut(OS, NULL, /*WrapColumn =*/0);
+  std::unique_ptr<ELFStubTriple> CopyStub(new ELFStubTriple(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<ELFStub *>(CopyStub.get());
+  return Error::success();
+}
+
+Error elfabi::overrideTBETarget(ELFStub &Stub, Optional<ELFArch> OverrideArch,
+                                Optional<ELFEndiannessType> OverrideEndianness,
+                                Optional<ELFBitWidthType> 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();
+}
 
-  YamlOut << const_cast<ELFStub &>(Stub);
+Error elfabi::validateTBETarget(ELFStub &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 elfabi::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 = (ELFArch)ELF::EM_AARCH64;
+    break;
+  case Triple::ArchType::x86_64:
+    RetTarget.Arch = (ELFArch)ELF::EM_X86_64;
+    break;
+  default:
+    RetTarget.Arch = (ELFArch)ELF::EM_NONE;
+  }
+  RetTarget.Endianness = IFSTriple.isLittleEndian() ? ELFEndiannessType::Little
+                                                    : ELFEndiannessType::Big;
+  RetTarget.BitWidth =
+      IFSTriple.isArch64Bit() ? ELFBitWidthType::ELF64 : ELFBitWidthType::ELF32;
+  return RetTarget;
+}
+
+void elfabi::stripTBETarget(ELFStub &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/test/tools/llvm-elfabi/binary-read-add-soname.test b/llvm/test/tools/llvm-elfabi/binary-read-add-soname.test
index 0f75a4c3b3412..90f0849748c7d 100644
--- a/llvm/test/tools/llvm-elfabi/binary-read-add-soname.test
+++ b/llvm/test/tools/llvm-elfabi/binary-read-add-soname.test
@@ -1,5 +1,5 @@
 # RUN: yaml2obj %s -o %t
-# RUN: llvm-elfabi --elf %t --emit-tbe=- --soname=best.so | FileCheck %s
+# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --output=- --soname=best.so %t | FileCheck %s
 
 !ELF
 FileHeader:
@@ -42,9 +42,9 @@ ProgramHeaders:
     FirstSec: .dynamic
     LastSec:  .dynamic
 
-# CHECK:      --- !tapi-tbe
+# CHECK:      --- !ifs-v1
 # CHECK-NEXT: TbeVersion: {{[1-9]\d*\.(0|([1-9]\d*))}}
 # CHECK-NEXT: SoName: best.so{{$}}
-# CHECK-NEXT: Arch: AArch64
-# CHECK-NEXT: Symbols: {}
+# CHECK-NEXT: Target: { ObjectFormat: ELF, Arch: AArch64, Endianness: little, BitWidth: 64 }
+# CHECK-NEXT: Symbols: []
 # CHECK-NEXT: ...

diff  --git a/llvm/test/tools/llvm-elfabi/binary-read-arch.test b/llvm/test/tools/llvm-elfabi/binary-read-arch.test
index e0e6ddd7f9cbf..1bf5c91a9e6c3 100644
--- a/llvm/test/tools/llvm-elfabi/binary-read-arch.test
+++ b/llvm/test/tools/llvm-elfabi/binary-read-arch.test
@@ -1,7 +1,8 @@
-# RUN: yaml2obj %s -o %t
-# RUN: llvm-elfabi --elf %t --emit-tbe=- | FileCheck %s
+# RUN: yaml2obj --docnum=1 %s -o %t
+# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --output=- %t | FileCheck %s -DTARGET="{ ObjectFormat: ELF, Arch: x86_64, Endianness: little, BitWidth: 64 }"
+# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --output=- --hint-ifs-target="x86_64-linux-gnu" %t | FileCheck %s -DTARGET="x86_64-linux-gnu"
 
-!ELF
+--- !ELF
 FileHeader:
   Class:           ELFCLASS64
   Data:            ELFDATA2LSB
@@ -42,8 +43,101 @@ ProgramHeaders:
     FirstSec: .dynamic
     LastSec:  .dynamic
 
-# CHECK:      --- !tapi-tbe
+# CHECK:      --- !ifs-v1
 # CHECK-NEXT: TbeVersion: {{[1-9]\d*\.(0|([1-9]\d*))}}
-# CHECK-NEXT: Arch: x86_64
-# CHECK-NEXT: Symbols: {}
+# CHECK-NEXT: Target: [[TARGET]]
+# CHECK-NEXT: Symbols: []
 # CHECK-NEXT: ...
+
+# HINTERR: error: Triple hint does not match the actual [[MSG]]
+
+# RUN: yaml2obj --docnum=1 %s -o %t
+# RUN: not llvm-elfabi --input-format=ELF --output-format=TBE --output=%t.tbe --hint-ifs-target="aarch64-linux-gnu" %t 2>&1 | FileCheck %s -DMSG=architecture --check-prefix=HINTERR
+
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2MSB
+  Type:            ET_DYN
+  Machine:         EM_X86_64
+Sections:
+  - Name:            .dynstr
+    Type:            SHT_STRTAB
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x0000
+    Content:         "00"
+  - Name:            .dynamic
+    Type:            SHT_DYNAMIC
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x0000000000000008
+    Link:            .dynstr
+    AddressAlign:    0x0000000000000008
+    EntSize:         0x0000000000000010
+    Entries:
+      - Tag:             DT_STRSZ
+        Value:           0x0000000000000001
+      - Tag:             DT_STRTAB
+        Value:           0x0000000000000000
+      - Tag:             DT_SYMTAB
+        Value:           0x0000000000000000
+      - Tag:             DT_NULL
+        Value:           0x0000000000000000
+ProgramHeaders:
+  - Type:     PT_LOAD
+    Flags:    [ PF_R ]
+    VAddr:    0x0000
+    Align:    8
+    FirstSec: .dynstr
+    LastSec:  .dynamic
+  - Type:     PT_DYNAMIC
+    Flags:    [ PF_X, PF_R ]
+    VAddr:    0x0008
+    FirstSec: .dynamic
+    LastSec:  .dynamic
+
+# RUN: yaml2obj --docnum=2 %s -o %t
+# RUN: not llvm-elfabi --input-format=ELF --output-format=TBE --output=%t.tbe --hint-ifs-target="x86_64-unknown-linux-gnu" %t 2>&1 | FileCheck %s -DMSG="endianness" --check-prefix=HINTERR
+
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_DYN
+  Machine:         EM_X86_64
+Sections:
+  - Name:            .dynstr
+    Type:            SHT_STRTAB
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x0000
+    Content:         "00"
+  - Name:            .dynamic
+    Type:            SHT_DYNAMIC
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x0000000000000008
+    Link:            .dynstr
+    AddressAlign:    0x0000000000000008
+    EntSize:         0x0000000000000010
+    Entries:
+      - Tag:             DT_STRSZ
+        Value:           0x0000000000000001
+      - Tag:             DT_STRTAB
+        Value:           0x0000000000000000
+      - Tag:             DT_SYMTAB
+        Value:           0x0000000000000000
+      - Tag:             DT_NULL
+        Value:           0x0000000000000000
+ProgramHeaders:
+  - Type:     PT_LOAD
+    Flags:    [ PF_R ]
+    VAddr:    0x0000
+    Align:    8
+    FirstSec: .dynstr
+    LastSec:  .dynamic
+  - Type:     PT_DYNAMIC
+    Flags:    [ PF_X, PF_R ]
+    VAddr:    0x0008
+    FirstSec: .dynamic
+    LastSec:  .dynamic
+
+# RUN: yaml2obj --docnum=3 %s -o %t
+# RUN: not llvm-elfabi --input-format=ELF --output-format=TBE --output=%t.tbe --hint-ifs-target="x86_64-unknown-linux-gnu" %t 2>&1 | FileCheck %s -DMSG="bit width" --check-prefix=HINTERR

diff  --git a/llvm/test/tools/llvm-elfabi/binary-read-bad-soname.test b/llvm/test/tools/llvm-elfabi/binary-read-bad-soname.test
index 032d3e1c82aa8..e1c2bdf3a002c 100644
--- a/llvm/test/tools/llvm-elfabi/binary-read-bad-soname.test
+++ b/llvm/test/tools/llvm-elfabi/binary-read-bad-soname.test
@@ -1,5 +1,5 @@
 # RUN: yaml2obj %s -o %t
-# RUN: not llvm-elfabi --elf %t --emit-tbe=%t.tbe 2>&1 | FileCheck %s
+# RUN: not llvm-elfabi --input-format=ELF --output-format=TBE --output=%t.tbe %t 2>&1 | FileCheck %s
 
 !ELF
 FileHeader:

diff  --git a/llvm/test/tools/llvm-elfabi/binary-read-bad-vaddr.test b/llvm/test/tools/llvm-elfabi/binary-read-bad-vaddr.test
index 666a01acca626..41ccbd5d7dc33 100644
--- a/llvm/test/tools/llvm-elfabi/binary-read-bad-vaddr.test
+++ b/llvm/test/tools/llvm-elfabi/binary-read-bad-vaddr.test
@@ -1,5 +1,5 @@
 # RUN: yaml2obj %s -o %t
-# RUN: not llvm-elfabi --elf %t --emit-tbe=%t.tbe 2>&1 | FileCheck %s
+# RUN: not llvm-elfabi --input-format=ELF --output-format=TBE --output=%t.tbe %t 2>&1 | FileCheck %s
 
 !ELF
 FileHeader:

diff  --git a/llvm/test/tools/llvm-elfabi/binary-read-neededlibs-bad-offset.test b/llvm/test/tools/llvm-elfabi/binary-read-neededlibs-bad-offset.test
index 3c2edcbb9eae2..e057c817becb0 100644
--- a/llvm/test/tools/llvm-elfabi/binary-read-neededlibs-bad-offset.test
+++ b/llvm/test/tools/llvm-elfabi/binary-read-neededlibs-bad-offset.test
@@ -1,5 +1,5 @@
 # RUN: yaml2obj %s -o %t
-# RUN: not llvm-elfabi --elf %t --emit-tbe=%t.tbe 2>&1 | FileCheck %s
+# RUN: not llvm-elfabi --input-format=ELF --output-format=TBE --output=%t.tbe %t 2>&1 | FileCheck %s
 
 !ELF
 FileHeader:

diff  --git a/llvm/test/tools/llvm-elfabi/binary-read-neededlibs.test b/llvm/test/tools/llvm-elfabi/binary-read-neededlibs.test
index 51adf60866c98..b6ad1103d4b31 100644
--- a/llvm/test/tools/llvm-elfabi/binary-read-neededlibs.test
+++ b/llvm/test/tools/llvm-elfabi/binary-read-neededlibs.test
@@ -1,5 +1,5 @@
 # RUN: yaml2obj %s -o %t
-# RUN: llvm-elfabi --elf %t --emit-tbe=- | FileCheck %s
+# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --output=- %t | FileCheck %s
 
 !ELF
 FileHeader:
@@ -48,4 +48,4 @@ ProgramHeaders:
 # CHECK:      NeededLibs:
 # CHECK-NEXT:   - libfoo.so{{$}}
 # CHECK-NEXT:   - libbar.so{{$}}
-# CHECK-NEXT: Symbols: {}
+# CHECK-NEXT: Symbols: []

diff  --git a/llvm/test/tools/llvm-elfabi/binary-read-no-dt-strsz.test b/llvm/test/tools/llvm-elfabi/binary-read-no-dt-strsz.test
index 0a21fd84ead14..1685a4ae153f4 100644
--- a/llvm/test/tools/llvm-elfabi/binary-read-no-dt-strsz.test
+++ b/llvm/test/tools/llvm-elfabi/binary-read-no-dt-strsz.test
@@ -1,5 +1,5 @@
 # RUN: yaml2obj %s -o %t
-# RUN: not llvm-elfabi --elf %t --emit-tbe=%t.tbe 2>&1 | FileCheck %s
+# RUN: not llvm-elfabi --input-format=ELF --output-format=TBE --output=%t.tbe %t 2>&1 | FileCheck %s
 
 !ELF
 FileHeader:

diff  --git a/llvm/test/tools/llvm-elfabi/binary-read-no-dt-strtab.test b/llvm/test/tools/llvm-elfabi/binary-read-no-dt-strtab.test
index 4d3c0c7601a39..3b208f0e39f34 100644
--- a/llvm/test/tools/llvm-elfabi/binary-read-no-dt-strtab.test
+++ b/llvm/test/tools/llvm-elfabi/binary-read-no-dt-strtab.test
@@ -1,5 +1,5 @@
 # RUN: yaml2obj %s -o %t
-# RUN: not llvm-elfabi --elf %t --emit-tbe=%t.tbe 2>&1 | FileCheck %s
+# RUN: not llvm-elfabi --input-format=ELF --output-format=TBE --output=%t.tbe %t 2>&1 | FileCheck %s
 
 !ELF
 FileHeader:

diff  --git a/llvm/test/tools/llvm-elfabi/binary-read-no-dynamic.test b/llvm/test/tools/llvm-elfabi/binary-read-no-dynamic.test
index fc88d83340e23..a1e99e5b35baf 100644
--- a/llvm/test/tools/llvm-elfabi/binary-read-no-dynamic.test
+++ b/llvm/test/tools/llvm-elfabi/binary-read-no-dynamic.test
@@ -1,5 +1,5 @@
 # RUN: yaml2obj %s -o %t
-# RUN: not llvm-elfabi --elf %t --emit-tbe=%t.tbe 2>&1 | FileCheck %s
+# RUN: not llvm-elfabi --input-format=ELF --output-format=TBE --output=%t.tbe %t 2>&1 | FileCheck %s
 
 !ELF
 FileHeader:

diff  --git a/llvm/test/tools/llvm-elfabi/binary-read-replace-soname.test b/llvm/test/tools/llvm-elfabi/binary-read-replace-soname.test
index e58e8e9a7dcf4..e0c26d0c4876b 100644
--- a/llvm/test/tools/llvm-elfabi/binary-read-replace-soname.test
+++ b/llvm/test/tools/llvm-elfabi/binary-read-replace-soname.test
@@ -1,6 +1,6 @@
 # RUN: yaml2obj %s -o %t
-# RUN: llvm-elfabi --elf %t --emit-tbe=- | FileCheck %s --check-prefix=ORIGINAL
-# RUN: llvm-elfabi --elf %t --emit-tbe=- --soname=libbest.so | FileCheck %s --check-prefix=REPLACED
+# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --output=- %t | FileCheck %s --check-prefix=ORIGINAL
+# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --soname=libbest.so --output=- %t | FileCheck %s --check-prefix=REPLACED
 
 !ELF
 FileHeader:

diff  --git a/llvm/test/tools/llvm-elfabi/binary-read-soname-no-null.test b/llvm/test/tools/llvm-elfabi/binary-read-soname-no-null.test
index 4ffa44ce98b33..3eb8ccdc41c41 100644
--- a/llvm/test/tools/llvm-elfabi/binary-read-soname-no-null.test
+++ b/llvm/test/tools/llvm-elfabi/binary-read-soname-no-null.test
@@ -1,5 +1,5 @@
 # RUN: yaml2obj %s -o %t
-# RUN: not llvm-elfabi --elf %t --emit-tbe=%t.tbe 2>&1 | FileCheck %s
+# RUN: not llvm-elfabi --input-format=ELF --output-format=TBE --output=%t.tbe %t 2>&1 | FileCheck %s
 
 !ELF
 FileHeader:

diff  --git a/llvm/test/tools/llvm-elfabi/binary-read-soname.test b/llvm/test/tools/llvm-elfabi/binary-read-soname.test
index 7436a38147048..979bb21605bf5 100644
--- a/llvm/test/tools/llvm-elfabi/binary-read-soname.test
+++ b/llvm/test/tools/llvm-elfabi/binary-read-soname.test
@@ -1,5 +1,5 @@
 # RUN: yaml2obj %s -o %t
-# RUN: llvm-elfabi --elf %t --emit-tbe=- | FileCheck %s
+# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --output=- %t | FileCheck %s
 
 !ELF
 FileHeader:
@@ -45,9 +45,9 @@ ProgramHeaders:
     FirstSec: .dynamic
     LastSec:  .dynamic
 
-# CHECK:      --- !tapi-tbe
+# CHECK:      --- !ifs-v1
 # CHECK-NEXT: TbeVersion: {{[1-9]\d*\.(0|([1-9]\d*))}}
 # CHECK-NEXT: SoName: somelib.so{{$}}
-# CHECK-NEXT: Arch: x86_64
-# CHECK-NEXT: Symbols: {}
+# CHECK-NEXT: Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, BitWidth: 64 }
+# CHECK-NEXT: Symbols: []
 # CHECK-NEXT: ...

diff  --git a/llvm/test/tools/llvm-elfabi/binary-read-syms-gnu-hash.test b/llvm/test/tools/llvm-elfabi/binary-read-syms-gnu-hash.test
index 777f2714b28f7..73c39cfecbc93 100644
--- a/llvm/test/tools/llvm-elfabi/binary-read-syms-gnu-hash.test
+++ b/llvm/test/tools/llvm-elfabi/binary-read-syms-gnu-hash.test
@@ -1,22 +1,22 @@
-# RUN: llvm-elfabi --elf %p/Inputs/gnu_hash.so --emit-tbe=- | FileCheck %s
+# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --output=- %p/Inputs/gnu_hash.so | FileCheck %s
 
-# CHECK:      --- !tapi-tbe
+# CHECK:      --- !ifs-v1
 # CHECK-NEXT: TbeVersion:      1.0
 # CHECK-NEXT: SoName:          libsomething.so
-# CHECK-NEXT: Arch:            x86_64
+# CHECK-NEXT: Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, BitWidth: 64 }
 # CHECK-NEXT: NeededLibs:
 # CHECK-NEXT:   - libm.so.6
 # CHECK-NEXT:   - libc.so.6
 # CHECK-NEXT:   - ld-linux-x86-64.so.2
 # CHECK-NEXT: Symbols:
-# CHECK-NEXT:   AGlobalInteger:  { Type: Object, Size: 4 }
-# CHECK-NEXT:   AThreadLocalLongInteger: { Type: TLS, Size: 8 }
-# CHECK-NEXT:   _ITM_deregisterTMCloneTable: { Type: NoType, Undefined: true, Weak: true }
-# CHECK-NEXT:   _ITM_registerTMCloneTable: { Type: NoType, Undefined: true, Weak: true }
-# CHECK-NEXT:   _Z11rotateArrayPii: { Type: Func }
-# CHECK-NEXT:   __cxa_finalize:  { Type: Func, Undefined: true, Weak: true }
-# CHECK-NEXT:   __gmon_start__:  { Type: NoType, Undefined: true, Weak: true }
-# CHECK-NEXT:   __tls_get_addr:  { Type: Func, Undefined: true }
-# CHECK-NEXT:   _fini:           { Type: Func }
-# CHECK-NEXT:   _init:           { Type: Func }
+# CHECK-NEXT:   - { Name: __gmon_start__, Type: NoType, Undefined: true, Weak: true }
+# CHECK-NEXT:   - { Name: _ITM_deregisterTMCloneTable, Type: NoType, Undefined: true, Weak: true }
+# CHECK-NEXT:   - { Name: _ITM_registerTMCloneTable, Type: NoType, Undefined: true, Weak: true }
+# CHECK-NEXT:   - { Name: __cxa_finalize, Type: Func, Undefined: true, Weak: true }
+# CHECK-NEXT:   - { Name: __tls_get_addr, Type: Func, Undefined: true }
+# CHECK-NEXT:   - { Name: _init, Type: Func }
+# CHECK-NEXT:   - { Name: _fini, Type: Func }
+# CHECK-NEXT:   - { Name: AGlobalInteger, Type: Object, Size: 4 }
+# CHECK-NEXT:   - { Name: AThreadLocalLongInteger, Type: TLS, Size: 8 }
+# CHECK-NEXT:   - { Name: _Z11rotateArrayPii, Type: Func }
 # CHECK-NEXT: ...

diff  --git a/llvm/test/tools/llvm-elfabi/binary-read-syms-sysv-hash.test b/llvm/test/tools/llvm-elfabi/binary-read-syms-sysv-hash.test
index 0f2908529989d..f945355248852 100644
--- a/llvm/test/tools/llvm-elfabi/binary-read-syms-sysv-hash.test
+++ b/llvm/test/tools/llvm-elfabi/binary-read-syms-sysv-hash.test
@@ -1,22 +1,22 @@
-# RUN: llvm-elfabi --elf %p/Inputs/sysv_hash.so --emit-tbe=- | FileCheck %s
+# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --output=- %p/Inputs/sysv_hash.so | FileCheck %s
 
-# CHECK:      --- !tapi-tbe
+# CHECK:      --- !ifs-v1
 # CHECK-NEXT: TbeVersion:      1.0
 # CHECK-NEXT: SoName:          libsomething.so
-# CHECK-NEXT: Arch:            x86_64
+# CHECK-NEXT: Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, BitWidth: 64 }
 # CHECK-NEXT: NeededLibs:
 # CHECK-NEXT:   - libm.so.6
 # CHECK-NEXT:   - libc.so.6
 # CHECK-NEXT:   - ld-linux-x86-64.so.2
 # CHECK-NEXT: Symbols:
-# CHECK-NEXT:   AGlobalInteger:  { Type: Object, Size: 4 }
-# CHECK-NEXT:   AThreadLocalLongInteger: { Type: TLS, Size: 8 }
-# CHECK-NEXT:   _ITM_deregisterTMCloneTable: { Type: NoType, Undefined: true, Weak: true }
-# CHECK-NEXT:   _ITM_registerTMCloneTable: { Type: NoType, Undefined: true, Weak: true }
-# CHECK-NEXT:   _Z11rotateArrayPii: { Type: Func }
-# CHECK-NEXT:   __cxa_finalize:  { Type: Func, Undefined: true, Weak: true }
-# CHECK-NEXT:   __gmon_start__:  { Type: NoType, Undefined: true, Weak: true }
-# CHECK-NEXT:   __tls_get_addr:  { Type: Func, Undefined: true }
-# CHECK-NEXT:   _fini:           { Type: Func }
-# CHECK-NEXT:   _init:           { Type: Func }
+# CHECK-NEXT:   - { Name: __gmon_start__, Type: NoType, Undefined: true, Weak: true }
+# CHECK-NEXT:   - { Name: _init, Type: Func }
+# CHECK-NEXT:   - { Name: _fini, Type: Func }
+# CHECK-NEXT:   - { Name: _ITM_deregisterTMCloneTable, Type: NoType, Undefined: true, Weak: true }
+# CHECK-NEXT:   - { Name: _ITM_registerTMCloneTable, Type: NoType, Undefined: true, Weak: true }
+# CHECK-NEXT:   - { Name: __cxa_finalize, Type: Func, Undefined: true, Weak: true }
+# CHECK-NEXT:   - { Name: AGlobalInteger, Type: Object, Size: 4 }
+# CHECK-NEXT:   - { Name: AThreadLocalLongInteger, Type: TLS, Size: 8 }
+# CHECK-NEXT:   - { Name: _Z11rotateArrayPii, Type: Func }
+# CHECK-NEXT:   - { Name: __tls_get_addr, Type: Func, Undefined: true }
 # CHECK-NEXT: ...

diff  --git a/llvm/test/tools/llvm-elfabi/fail-file-open.test b/llvm/test/tools/llvm-elfabi/fail-file-open.test
index b4019af9feb9e..0e4e75d901039 100644
--- a/llvm/test/tools/llvm-elfabi/fail-file-open.test
+++ b/llvm/test/tools/llvm-elfabi/fail-file-open.test
@@ -1,4 +1,4 @@
-# RUN: not llvm-elfabi %s.NotAFileInTestingDir --emit-tbe=%t 2>&1 | FileCheck %s
+# RUN: not llvm-elfabi --output-format=TBE --output=%t.tbe %s.NotAFileInTestingDir 2>&1 | FileCheck %s
 
 This file will not be read. An invalid file path is fed to llvm-elfabi.
 

diff  --git a/llvm/test/tools/llvm-elfabi/fail-file-write-windows.test b/llvm/test/tools/llvm-elfabi/fail-file-write-windows.test
index fb3a1a63884c8..c7efb5679f398 100644
--- a/llvm/test/tools/llvm-elfabi/fail-file-write-windows.test
+++ b/llvm/test/tools/llvm-elfabi/fail-file-write-windows.test
@@ -3,14 +3,14 @@
 # REQUIRES: system-windows
 # RUN: touch %t.TestFile
 # RUN: chmod 400 %t.TestFile
-# RUN: not llvm-elfabi %s --output-target=elf64-little %t.TestFile 2>&1 | FileCheck -DMSG=%errc_EACCES %s --check-prefix=ERR
+# RUN: not llvm-elfabi --output-format=ELF --output=%t.TestFile %s 2>&1 | FileCheck -DMSG=%errc_EACCES %s --check-prefix=ERR
 # RUN: chmod 777 %t.TestFile
 # RUN: rm -rf %t.TestFile
 
---- !tapi-tbe
+--- !ifs-v1
 TbeVersion: 1.0
-Arch: AArch64
-Symbols: {}
+Target: { ObjectFormat: ELF, Arch: AArch64, Endianness: little, BitWidth: 64 }
+Symbols: []
 ...
 
 # ERR: error: [[MSG]]

diff  --git a/llvm/test/tools/llvm-elfabi/fail-file-write.test b/llvm/test/tools/llvm-elfabi/fail-file-write.test
index 928528d16c69f..1ac9ef792979b 100644
--- a/llvm/test/tools/llvm-elfabi/fail-file-write.test
+++ b/llvm/test/tools/llvm-elfabi/fail-file-write.test
@@ -5,14 +5,14 @@
 # RUN: mkdir %t.TestDir
 # RUN: touch %t.TestDir/Output.TestFile
 # RUN: chmod 400 %t.TestDir
-# RUN: not llvm-elfabi %s --output-target=elf64-little %t.TestDir/Output.TestFile 2>&1 | FileCheck -DMSG=%errc_EACCES %s --check-prefix=ERR
+# RUN: not llvm-elfabi --output-format=ELF --output=%t.TestDir/Output.TestFile %s 2>&1 | FileCheck -DMSG=%errc_EACCES %s --check-prefix=ERR
 # RUN: chmod 777 %t.TestDir
 # RUN: rm -rf %t.TestDir
 
---- !tapi-tbe
+--- !ifs-v1
 TbeVersion: 1.0
-Arch: AArch64
-Symbols: {}
+Target: { ObjectFormat: ELF, Arch: AArch64, Endianness: little, BitWidth: 64 }
+Symbols: []
 ...
 
 # ERR: [[MSG]] when trying to open `{{.*}}.TestDir/Output.TestFile` for writing

diff  --git a/llvm/test/tools/llvm-elfabi/output-target-error.test b/llvm/test/tools/llvm-elfabi/output-target-error.test
index a0c4bec545197..b2726e61a8bd3 100644
--- a/llvm/test/tools/llvm-elfabi/output-target-error.test
+++ b/llvm/test/tools/llvm-elfabi/output-target-error.test
@@ -1,15 +1,15 @@
 ## Test running llvm-elfabi without specifying a valid target.
 
-# RUN: not llvm-elfabi %s %t 2>&1 | FileCheck %s --check-prefix=MISSING
-# RUN: not llvm-elfabi %s --output-target=nope %t 2>&1 | FileCheck %s --check-prefix=INVALID
+# RUN: not llvm-elfabi --output=%t %s 2>&1 | FileCheck %s --check-prefix=MISSING
+# RUN: not llvm-elfabi --output-format=nope --output=%t %s 2>&1 | FileCheck %s --check-prefix=INVALID
 
---- !tapi-tbe
+--- !ifs-v1
 SoName: somelib.so
 TbeVersion: 1.0
-Arch: x86_64
-Symbols: {}
+Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, BitWidth: 64 }
+Symbols: []
 ...
 
-# MISSING: error: no binary output target specified.
+# MISSING: llvm-elfabi: for the --output-format option: must be specified at least once!
 
-# INVALID: llvm-elfabi: for the --output-target option: Cannot find option named 'nope'!
+# INVALID: llvm-elfabi: for the --output-format option: Cannot find option named 'nope'!

diff  --git a/llvm/test/tools/llvm-elfabi/preserve-dates-stub.test b/llvm/test/tools/llvm-elfabi/preserve-dates-stub.test
index 9742a61aa2814..5c41a05ee2e86 100644
--- a/llvm/test/tools/llvm-elfabi/preserve-dates-stub.test
+++ b/llvm/test/tools/llvm-elfabi/preserve-dates-stub.test
@@ -1,19 +1,19 @@
 ## Test writing unchanged content to ELF Stub file with --write-if-changed flag.
 
-# RUN: llvm-elfabi %s --output-target=elf64-little %t
+# RUN: llvm-elfabi --output-format=ELF --output=%t %s
 # RUN: env TZ=GMT touch -m -t 197001010000 %t
-# RUN: llvm-elfabi %s --output-target=elf64-little %t --write-if-changed
+# RUN: llvm-elfabi --output-format=ELF --output=%t --write-if-changed %s
 # RUN: env TZ=GMT ls -l %t | FileCheck %s
 
---- !tapi-tbe
+--- !ifs-v1
 TbeVersion: 1.0
-Arch: x86_64
+Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, BitWidth: 64 }
 NeededLibs:
   - libc.so.6
 Symbols:
-  bar: { Type: Object, Size: 42 }
-  baz: { Type: TLS, Size: 3 }
-  plus: { Type: Func }
+  - { Name: bar, Type: Object, Size: 42 }
+  - { Name: baz, Type: TLS, Size: 3 }
+  - { Name: plus, Type: Func }
 ...
 
 # CHECK: {{[[:space:]]1970}}

diff  --git a/llvm/test/tools/llvm-elfabi/preserve-dates-tbe.test b/llvm/test/tools/llvm-elfabi/preserve-dates-tbe.test
index 3ec190067c73a..e1edb6c9fc304 100644
--- a/llvm/test/tools/llvm-elfabi/preserve-dates-tbe.test
+++ b/llvm/test/tools/llvm-elfabi/preserve-dates-tbe.test
@@ -1,8 +1,8 @@
 ## Test writing unchanged content to TBE file with --write-if-changed flag.
 
-# RUN: llvm-elfabi --elf %p/Inputs/gnu_hash.so --emit-tbe=%t
+# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --output=%t %p/Inputs/gnu_hash.so
 # RUN: env TZ=GMT touch -m -t 197001010000 %t
-# RUN: llvm-elfabi --elf %p/Inputs/gnu_hash.so --emit-tbe=%t --write-if-changed
+# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --output=%t --write-if-changed %p/Inputs/gnu_hash.so
 # RUN: env TZ=GMT ls -l %t | FileCheck %s
 
 # CHECK: {{[[:space:]]1970}}

diff  --git a/llvm/test/tools/llvm-elfabi/read-elf-dynsym.test b/llvm/test/tools/llvm-elfabi/read-elf-dynsym.test
index 8c2fe2bf049d2..7de9b9317f3e8 100644
--- a/llvm/test/tools/llvm-elfabi/read-elf-dynsym.test
+++ b/llvm/test/tools/llvm-elfabi/read-elf-dynsym.test
@@ -5,26 +5,26 @@
 
 ## Test if llvm-elfabi reads DT_SYMTAB size through section headers by puting the wrong terminator in DT_GNU_HASH.
 # RUN: yaml2obj %s -o %tfull -DGNUHASHVALUE="[0x9]" -DTAG1="DT_GNU_HASH" -DVAL1="0xC00"
-# RUN: llvm-elfabi --elf %tfull --emit-tbe=- | FileCheck %s
+# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --output=- %tfull | FileCheck %s
 
 ## Test if llvm-elfabi fails to read DT_SYMTAB size through section headers when the value of sh_entsize is invalid.
 # RUN: yaml2obj %s -o %tfull -DGNUHASHVALUE="[0x9]" -DTAG1="DT_GNU_HASH" -DVAL1="0xC00" -DENTSIZE="0x19"
-# RUN: not llvm-elfabi --elf %tfull --emit-tbe=- 2>&1 | FileCheck %s --check-prefix=BADENTSIZE
+# RUN: not llvm-elfabi --input-format=ELF --output-format=TBE --output=- %tfull 2>&1 | FileCheck %s --check-prefix=BADENTSIZE
 
 ## Test if llvm-elfabi reads DT_SYMTAB size through DT_GNU_HASH.
 # RUN: yaml2obj %s -o %tw.gnu.hash -DGNUHASHVALUE="[0x8, 0x9]" -DTAG1="DT_GNU_HASH" -DVAL1="0xC00" -DNOHEADER="true"
-# RUN: llvm-elfabi --elf %tw.gnu.hash --emit-tbe=- | FileCheck %s
+# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --output=- %tw.gnu.hash | FileCheck %s
 
 ## Test if llvm-elfabi fails to read DT_SYMTAB size through DT_GNU_HASH when there is no terminator.
 # RUN: yaml2obj %s -o %tw.gnu.hash -DGNUHASHVALUE="[0x8, 0xA]" -DTAG1="DT_GNU_HASH" -DVAL1="0xC00" -DNOHEADER="true"
-# RUN: not llvm-elfabi --elf %tw.gnu.hash --emit-tbe=- 2>&1 | FileCheck %s --check-prefix=NOTERMINATOR
+# RUN: not llvm-elfabi --input-format=ELF --output-format=TBE --output=- %tw.gnu.hash  2>&1 | FileCheck %s --check-prefix=NOTERMINATOR
 
-# CHECK:      --- !tapi-tbe
+# CHECK:      --- !ifs-v1
 # CHECK-NEXT: TbeVersion:      1.0
-# CHECK-NEXT: Arch:            AArch64
+# CHECK-NEXT: Target: { ObjectFormat: ELF, Arch: AArch64, Endianness: little, BitWidth: 64 }
 # CHECK-NEXT: Symbols:
-# CHECK-NEXT:  bar:             { Type: Object, Size: 0, Undefined: true }
-# CHECK-NEXT:  foo:             { Type: Func, Undefined: true }
+# CHECK-NEXT:   - { Name: foo, Type: Func, Undefined: true }
+# CHECK-NEXT:   - { Name: bar, Type: Object, Size: 0, Undefined: true }
 # CHECK-NEXT: ...
 
 # BADENTSIZE: SHT_DYNSYM section has sh_size (72) % sh_entsize (25) that is not 0

diff  --git a/llvm/test/tools/llvm-elfabi/read-tbe-as-elf.test b/llvm/test/tools/llvm-elfabi/read-tbe-as-elf.test
index eaddd38867a5b..ceae17699d9a5 100644
--- a/llvm/test/tools/llvm-elfabi/read-tbe-as-elf.test
+++ b/llvm/test/tools/llvm-elfabi/read-tbe-as-elf.test
@@ -1,15 +1,15 @@
-# RUN: not llvm-elfabi --elf %s --emit-tbe=%t  2>&1 | FileCheck %s
+# RUN: not llvm-elfabi --input-format=ELF --output-format=TBE --output=%t %s 2>&1 | FileCheck %s
 
---- !tapi-tbe
+--- !ifs-v1
 SoName: somelib.so
 TbeVersion: 1.0
-Arch: x86_64
+Target: { ObjectFormat: ELF, Arch: AArch64, Endianness: little, BitWidth: 64 }
 Symbols:
-  foo: { Type: Func }
-  bar: { Type: Object, Size: 42 }
-  baz: { Type: Object, Size: 8 }
-  not: { Type: Object, Undefined: true, Size: 128 }
-  nor: { Type: Func, Undefined: true }
+  - { Name: foo, Type: Func }
+  - { Name: bar, Type: Object, Size: 42 }
+  - { Name: baz, Type: Object, Size: 8 }
+  - { Name: not, Type: Object, Undefined: true, Size: 128 }
+  - { Name: nor, Type: Func, Undefined: true }
 ...
 
 # CHECK: The file was not recognized as a valid object file

diff  --git a/llvm/test/tools/llvm-elfabi/read-tbe-as-tbe.test b/llvm/test/tools/llvm-elfabi/read-tbe-as-tbe.test
index a5e2d44134e10..154b6eebb6c3a 100644
--- a/llvm/test/tools/llvm-elfabi/read-tbe-as-tbe.test
+++ b/llvm/test/tools/llvm-elfabi/read-tbe-as-tbe.test
@@ -1,13 +1,13 @@
-# RUN: llvm-elfabi --tbe %s --emit-tbe=- | FileCheck %s
+# RUN: llvm-elfabi --input-format=TBE --output-format=TBE --output=- %s | FileCheck %s
 
---- !tapi-tbe
+--- !ifs-v1
 TbeVersion: 1.0
-Arch: AArch64
-Symbols: {}
+Target: { ObjectFormat: ELF, Arch: AArch64, Endianness: little, BitWidth: 64 }
+Symbols: []
 ...
 
-# CHECK:      --- !tapi-tbe
+# CHECK:      --- !ifs-v1
 # CHECK-NEXT: TbeVersion: {{[1-9]\d*\.(0|([1-9]\d*))}}
-# CHECK-NEXT: Arch: AArch64
-# CHECK-NEXT: Symbols: {}
+# CHECK-NEXT: Target: { ObjectFormat: ELF, Arch: AArch64, Endianness: little, BitWidth: 64 }
+# CHECK-NEXT: Symbols: []
 # CHECK-NEXT: ...

diff  --git a/llvm/test/tools/llvm-elfabi/read-tbe-with-bad-bitwidth.test b/llvm/test/tools/llvm-elfabi/read-tbe-with-bad-bitwidth.test
new file mode 100644
index 0000000000000..1ca314436ba89
--- /dev/null
+++ b/llvm/test/tools/llvm-elfabi/read-tbe-with-bad-bitwidth.test
@@ -0,0 +1,17 @@
+## Test reading TBE file with bad bit width.
+
+# RUN: not llvm-elfabi --output-format=TBE --output=- %s 2>&1 | FileCheck %s
+
+--- !ifs-v1
+SoName: somelib.so
+TbeVersion: 1.0
+Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, BitWidth: 65 }
+Symbols:
+  - { Name: foo, Type: Func }
+  - { Name: bar, Type: Object, Size: 42 }
+  - { Name: baz, Type: Object, Size: 8 }
+  - { Name: not, Type: Object, Size: 128, Undefined: true }
+  - { Name: nor, Type: Func, Undefined: true }
+...
+
+# CHECK:      YAML:8:74: error: Unsupported bit width

diff  --git a/llvm/test/tools/llvm-elfabi/read-tbe-with-bad-endianness.test b/llvm/test/tools/llvm-elfabi/read-tbe-with-bad-endianness.test
new file mode 100644
index 0000000000000..5413855c5b4b5
--- /dev/null
+++ b/llvm/test/tools/llvm-elfabi/read-tbe-with-bad-endianness.test
@@ -0,0 +1,17 @@
+## Test reading TBE file with bad endianness.
+
+# RUN: not llvm-elfabi --output-format=TBE --output=- %s 2>&1 | FileCheck %s
+
+--- !ifs-v1
+SoName: somelib.so
+TbeVersion: 1.0
+Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: lit, BitWidth: 64 }
+Symbols:
+  - { Name: foo, Type: Func }
+  - { Name: bar, Type: Object, Size: 42 }
+  - { Name: baz, Type: Object, Size: 8 }
+  - { Name: not, Type: Object, Size: 128, Undefined: true }
+  - { Name: nor, Type: Func, Undefined: true }
+...
+
+# CHECK:      YAML:8:56: error: Unsupported endianness

diff  --git a/llvm/test/tools/llvm-elfabi/read-unsupported-file.test b/llvm/test/tools/llvm-elfabi/read-unsupported-file.test
index 4ebe1bcc6d419..d84a47ae558cf 100644
--- a/llvm/test/tools/llvm-elfabi/read-unsupported-file.test
+++ b/llvm/test/tools/llvm-elfabi/read-unsupported-file.test
@@ -1,4 +1,4 @@
-# RUN: not llvm-elfabi %s --emit-tbe=%t 2>&1 | FileCheck %s
+# RUN: not llvm-elfabi --output-format=TBE --output=- %s 2>&1| FileCheck %s
 
 This is just some text that cannot be read by llvm-elfabi.
 

diff  --git a/llvm/test/tools/llvm-elfabi/strip-target.test b/llvm/test/tools/llvm-elfabi/strip-target.test
new file mode 100644
index 0000000000000..f9da26a99e183
--- /dev/null
+++ b/llvm/test/tools/llvm-elfabi/strip-target.test
@@ -0,0 +1,27 @@
+## Test writing tbe with stripped target information.
+
+# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --strip-ifs-target --output=- %p/Inputs/sysv_hash.so | FileCheck %s --check-prefix=NOTARGET
+# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --strip-ifs-arch --strip-ifs-endianness --strip-ifs-bitwidth --output=- %p/Inputs/sysv_hash.so | FileCheck %s --check-prefix=NOTARGET
+# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --strip-ifs-arch --output=- %p/Inputs/sysv_hash.so | FileCheck %s -DELFTARGET="ObjectFormat: ELF, Endianness: little, BitWidth: 64" --check-prefix=CHECK
+# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --strip-ifs-endianness --output=- %p/Inputs/sysv_hash.so | FileCheck %s -DELFTARGET="ObjectFormat: ELF, Arch: x86_64, BitWidth: 64" --check-prefix=CHECK
+# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --strip-ifs-bitwidth --output=- %p/Inputs/sysv_hash.so | FileCheck %s -DELFTARGET="ObjectFormat: ELF, Arch: x86_64, Endianness: little" --check-prefix=CHECK
+
+
+# CHECK:      --- !ifs-v1
+# CHECK-NEXT: TbeVersion:      1.0
+# CHECK-NEXT: SoName:          libsomething.so
+# CHECK-NEXT: Target: { [[ELFTARGET]] }
+# CHECK-NEXT: NeededLibs:
+# CHECK-NEXT:   - libm.so.6
+# CHECK-NEXT:   - libc.so.6
+# CHECK-NEXT:   - ld-linux-x86-64.so.2
+# CHECK-NEXT: Symbols:
+
+# NOTARGET:      --- !ifs-v1
+# NOTARGET-NEXT: TbeVersion:      1.0
+# NOTARGET-NEXT: SoName:          libsomething.so
+# NOTARGET-NEXT: NeededLibs:
+# NOTARGET-NEXT:   - libm.so.6
+# NOTARGET-NEXT:   - libc.so.6
+# NOTARGET-NEXT:   - ld-linux-x86-64.so.2
+# NOTARGET-NEXT: Symbols:

diff  --git a/llvm/test/tools/llvm-elfabi/tbe-emits-current-version.test b/llvm/test/tools/llvm-elfabi/tbe-emits-current-version.test
index 12a5476175a00..0799a14f4ef55 100644
--- a/llvm/test/tools/llvm-elfabi/tbe-emits-current-version.test
+++ b/llvm/test/tools/llvm-elfabi/tbe-emits-current-version.test
@@ -1,13 +1,13 @@
-# RUN: llvm-elfabi %s --emit-tbe=- | FileCheck %s
+# RUN: llvm-elfabi --output-format=TBE --output=- %s | FileCheck %s
 
---- !tapi-tbe
+--- !ifs-v1
 TbeVersion: 1.0
-Arch: AArch64
-Symbols: {}
+Target: { ObjectFormat: ELF, Arch: AArch64, Endianness: little, BitWidth: 64 }
+Symbols: []
 ...
 
 # As the tbe reader/writer is updated, update this check to ensure --emit-tbe
 # uses the latest tbe writer by default.
 
-# CHECK:      --- !tapi-tbe
+# CHECK:      --- !ifs-v1
 # CHECK-NEXT: TbeVersion: 1.0

diff  --git a/llvm/test/tools/llvm-elfabi/tbe-read-basic.test b/llvm/test/tools/llvm-elfabi/tbe-read-basic.test
index 1599f5a891e9f..a8e285c7eb6f1 100644
--- a/llvm/test/tools/llvm-elfabi/tbe-read-basic.test
+++ b/llvm/test/tools/llvm-elfabi/tbe-read-basic.test
@@ -1,25 +1,25 @@
-# RUN: llvm-elfabi %s --emit-tbe=- | FileCheck %s
+# RUN: llvm-elfabi --output-format=TBE --output=- %s | FileCheck %s
 
---- !tapi-tbe
+--- !ifs-v1
 SoName: somelib.so
 TbeVersion: 1.0
-Arch: x86_64
+Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, BitWidth: 64 }
 Symbols:
-  foo: { Type: Func }
-  bar: { Type: Object, Size: 42 }
-  baz: { Type: Object, Size: 8 }
-  not: { Type: Object, Undefined: true, Size: 128 }
-  nor: { Type: Func, Undefined: true }
+  - { Name: foo, Type: Func }
+  - { Name: bar, Type: Object, Size: 42 }
+  - { Name: baz, Type: Object, Size: 8 }
+  - { Name: not, Type: Object, Size: 128, Undefined: true }
+  - { Name: nor, Type: Func, Undefined: true }
 ...
 
-# CHECK:      --- !tapi-tbe
+# CHECK:      --- !ifs-v1
 # CHECK-NEXT: TbeVersion: {{[1-9]\d*\.(0|([1-9]\d*))}}
 # CHECK-NEXT: SoName: somelib.so
-# CHECK-NEXT: Arch: x86_64
+# CHECK-NEXT: Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, BitWidth: 64 }
 # CHECK-NEXT: Symbols:
-# CHECK-NEXT:   bar: { Type: Object, Size: 42 }
-# CHECK-NEXT:   baz: { Type: Object, Size: 8 }
-# CHECK-NEXT:   foo: { Type: Func }
-# CHECK-NEXT:   nor: { Type: Func, Undefined: true }
-# CHECK-NEXT:   not: { Type: Object, Size: 128, Undefined: true }
+# CHECK-NEXT:   - { Name: foo, Type: Func }
+# CHECK-NEXT:   - { Name: bar, Type: Object, Size: 42 }
+# CHECK-NEXT:   - { Name: baz, Type: Object, Size: 8 }
+# CHECK-NEXT:   - { Name: not, Type: Object, Size: 128, Undefined: true }
+# CHECK-NEXT:   - { Name: nor, Type: Func, Undefined: true }
 # CHECK-NEXT: ...

diff  --git a/llvm/test/tools/llvm-elfabi/write-stub-no-nonlocal-symbol.test b/llvm/test/tools/llvm-elfabi/write-stub-no-nonlocal-symbol.test
index 98dece0e37d63..3f7531f2a0b4d 100644
--- a/llvm/test/tools/llvm-elfabi/write-stub-no-nonlocal-symbol.test
+++ b/llvm/test/tools/llvm-elfabi/write-stub-no-nonlocal-symbol.test
@@ -1,14 +1,14 @@
 ## Test writing stub elf when symbol table contains no non-local symbol.
 
-# RUN: llvm-elfabi %s --output-target=elf64-little %t
+# RUN: llvm-elfabi --output-format=ELF --output=%t %s
 # RUN: llvm-readobj -S %t | FileCheck %s -DCLASS="64-bit (0x2)" -DDE="LittleEndian (0x1)" -DHS=64 -DPHES=56 -DSHES=64 -DDYNSYMAL=8 -DDYNSYMES=24 -DDYNAMICAL=8 -DDYNAMICES=16 -DDYNTABZ=000000000
 
---- !tapi-tbe
+--- !ifs-v1
 TbeVersion: 1.0
-Arch: x86_64
+Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, BitWidth: 64 }
 NeededLibs:
   - libc.so.6
-Symbols: {}
+Symbols: []
 ...
 
 # CHECK:      Section {

diff  --git a/llvm/test/tools/llvm-elfabi/write-stub.test b/llvm/test/tools/llvm-elfabi/write-stub.test
index 837c508b48581..78e40f05be40f 100644
--- a/llvm/test/tools/llvm-elfabi/write-stub.test
+++ b/llvm/test/tools/llvm-elfabi/write-stub.test
@@ -1,26 +1,44 @@
 ## Test writing stub elf with minimal sections.
 
-# RUN: llvm-elfabi %s --output-target=elf32-little %t.elf32l
+# RUN: llvm-elfabi --output-format=ELF --output=%t.elf32l --arch=x86_64 --bitwidth=32 --endianness=little %s
 # RUN: llvm-readobj -h -S --string-dump .dynstr --string-dump .shstrtab --dyn-symbols --dynamic-table %t.elf32l | FileCheck %s -DCLASS="32-bit (0x1)" -DDE="LittleEndian (0x1)" -DHS=52 -DPHES=32 -DSHES=40 -DDYNSYMAL=4 -DDYNSYMES=16 -DDYNAMICAL=4 -DDYNAMICES=8 -DDYNTABZ=0
 
-# RUN: llvm-elfabi %s --output-target=elf32-big %t.elf32b
+# RUN: llvm-elfabi --output-format=ELF --output=%t.elf32b --arch=x86_64 --bitwidth=32 --endianness=big %s
 # RUN: llvm-readobj -h -S --string-dump .dynstr --string-dump .shstrtab --dyn-symbols --dynamic-table %t.elf32b | FileCheck %s -DCLASS="32-bit (0x1)" -DDE="BigEndian (0x2)" -DHS=52 -DPHES=32 -DSHES=40 -DDYNSYMAL=4 -DDYNSYMES=16 -DDYNAMICAL=4 -DDYNAMICES=8 -DDYNTABZ=0
 
-# RUN: llvm-elfabi %s --output-target=elf64-little %t.elf64l
+# RUN: llvm-elfabi --output-format=ELF --output=%t.elf64l --arch=x86_64 --bitwidth=64 --endianness=little %s
 # RUN: llvm-readobj -h -S --string-dump .dynstr --string-dump .shstrtab --dyn-symbols --dynamic-table %t.elf64l | FileCheck %s -DCLASS="64-bit (0x2)" -DDE="LittleEndian (0x1)" -DHS=64 -DPHES=56 -DSHES=64 -DDYNSYMAL=8 -DDYNSYMES=24 -DDYNAMICAL=8 -DDYNAMICES=16 -DDYNTABZ=000000000
 
-# RUN: llvm-elfabi %s --output-target=elf64-big %t.elf64b
+# RUN: llvm-elfabi --output-format=ELF --output=%t.elf64l --target=x86_64-linux-gnu %s
+# RUN: llvm-readobj -h -S --string-dump .dynstr --string-dump .shstrtab --dyn-symbols --dynamic-table %t.elf64l | FileCheck %s -DCLASS="64-bit (0x2)" -DDE="LittleEndian (0x1)" -DHS=64 -DPHES=56 -DSHES=64 -DDYNSYMAL=8 -DDYNSYMES=24 -DDYNAMICAL=8 -DDYNAMICES=16 -DDYNTABZ=000000000
+
+# RUN: llvm-elfabi --output-format=ELF --output=%t.elf64b --arch=x86_64 --bitwidth=64 --endianness=big %s
 # RUN: llvm-readobj -h -S --string-dump .dynstr --string-dump .shstrtab --dyn-symbols --dynamic-table %t.elf64b | FileCheck %s -DCLASS="64-bit (0x2)" -DDE="BigEndian (0x2)" -DHS=64 -DPHES=56 -DSHES=64 -DDYNSYMAL=8 -DDYNSYMES=24 -DDYNAMICAL=8 -DDYNAMICES=16 -DDYNTABZ=000000000
 
---- !tapi-tbe
+# RUN: not llvm-elfabi --output-format=ELF --output=%t --arch=x86_64 --bitwidth=64 --endianness=big --target=x86_64-linux-gnu %s 2>&1 | FileCheck %s --check-prefix=TRIPLEERR
+
+# RUN: not llvm-elfabi --output-format=ELF --output=%t --bitwidth=64 --endianness=big %s 2>&1 | FileCheck %s -DMSG="Arch" --check-prefix=TARGETERR
+
+# RUN: not llvm-elfabi --output-format=ELF --output=%t --arch=x86_64 --endianness=big %s 2>&1 | FileCheck %s -DMSG="BitWidth" --check-prefix=TARGETERR
+
+# RUN: not llvm-elfabi --output-format=ELF --output=%t --arch=x86_64 --bitwidth=64 %s 2>&1 | FileCheck %s -DMSG="Endianness" --check-prefix=TARGETERR
+
+# RUN: llvm-elfabi --output-format=TBE --output=%t.target --target=x86_64-linux-gnu %s
+# RUN: not llvm-elfabi --output-format=ELF --output=%t --target=aarch64-linux-gnu %t.target 2>&1 | FileCheck %s -DMSG="Triple" --check-prefix=CONFLICTERR
+
+# RUN: llvm-elfabi --output-format=TBE --output=%t.target --arch=x86_64 --endianness=little --bitwidth=64 %s
+# RUN: not llvm-elfabi --output-format=ELF --output=%t --arch=AArch64 %t.target 2>&1 | FileCheck %s -DMSG=Arch --check-prefix=CONFLICTERR
+# RUN: not llvm-elfabi --output-format=ELF --output=%t --endianness=big %t.target 2>&1 | FileCheck %s -DMSG=Endianness --check-prefix=CONFLICTERR
+# RUN: not llvm-elfabi --output-format=ELF --output=%t --bitwidth=32 %t.target 2>&1 | FileCheck %s -DMSG=BitWidth --check-prefix=CONFLICTERR
+
+--- !ifs-v1
 TbeVersion: 1.0
-Arch: x86_64
 NeededLibs:
   - libc.so.6
 Symbols:
-  bar: { Type: Object, Size: 42 }
-  baz: { Type: TLS, Size: 3 }
-  plus: { Type: Func }
+  - { Name: bar, Type: Object, Size: 42 }
+  - { Name: baz, Type: TLS, Size: 3 }
+  - { Name: plus, Type: Func }
 ...
 
 # CHECK:      ElfHeader {
@@ -175,3 +193,7 @@ Symbols:
 # CHECK-NEXT: [     9] .dynsym
 # CHECK-NEXT: [    11] .dynamic
 # CHECK-NEXT: [    1a] .shstrtab
+
+# TRIPLEERR: error: Target triple cannot be used simultaneously with ELF target format
+# TARGETERR: error: [[MSG]] is not defined in the text stub
+# CONFLICTERR: error: Supplied [[MSG]] conflicts with the text stub
\ No newline at end of file

diff  --git a/llvm/tools/llvm-elfabi/CMakeLists.txt b/llvm/tools/llvm-elfabi/CMakeLists.txt
index 43b4b5b5faa96..85eb3a4ed7785 100644
--- a/llvm/tools/llvm-elfabi/CMakeLists.txt
+++ b/llvm/tools/llvm-elfabi/CMakeLists.txt
@@ -1,4 +1,5 @@
 set(LLVM_LINK_COMPONENTS
+  BinaryFormat
   InterfaceStub
   Object
   Support

diff  --git a/llvm/tools/llvm-elfabi/llvm-elfabi.cpp b/llvm/tools/llvm-elfabi/llvm-elfabi.cpp
index 761c6a80b345e..b94d075177ca7 100644
--- a/llvm/tools/llvm-elfabi/llvm-elfabi.cpp
+++ b/llvm/tools/llvm-elfabi/llvm-elfabi.cpp
@@ -30,33 +30,50 @@ using namespace llvm;
 using namespace llvm::elfabi;
 
 // Command line flags:
-cl::opt<FileFormat> InputFileFormat(
-    cl::desc("Force input file format:"),
-    cl::values(clEnumValN(FileFormat::TBE, "tbe",
-                          "Read `input` as text-based ELF stub"),
-               clEnumValN(FileFormat::ELF, "elf",
-                          "Read `input` as ELF binary")));
 cl::opt<std::string> InputFilePath(cl::Positional, cl::desc("input"),
                                    cl::Required);
-cl::opt<std::string>
-    EmitTBE("emit-tbe",
-            cl::desc("Emit a text-based ELF stub (.tbe) from the input file"),
-            cl::value_desc("path"));
+cl::opt<FileFormat> InputFormat(
+    "input-format", cl::desc("Specify the input file format"),
+    cl::values(clEnumValN(FileFormat::TBE, "TBE", "Text based ELF stub file"),
+               clEnumValN(FileFormat::ELF, "ELF", "ELF object file")));
+cl::opt<FileFormat> OutputFormat(
+    "output-format", cl::desc("Specify the output file format"),
+    cl::values(clEnumValN(FileFormat::TBE, "TBE", "Text based ELF stub file"),
+               clEnumValN(FileFormat::ELF, "ELF", "ELF stub file")),
+    cl::Required);
+cl::opt<std::string> OptArch("arch",
+                             cl::desc("Specify the architecture, e.g. x86_64"));
+cl::opt<ELFBitWidthType> OptBitWidth(
+    "bitwidth", cl::desc("Specify the bit width"),
+    cl::values(clEnumValN(ELFBitWidthType::ELF32, "32", "32 bits"),
+               clEnumValN(ELFBitWidthType::ELF64, "64", "64 bits")));
+cl::opt<ELFEndiannessType> OptEndianness(
+    "endianness", cl::desc("Specify the endianness"),
+    cl::values(clEnumValN(ELFEndiannessType::Little, "little", "Little Endian"),
+               clEnumValN(ELFEndiannessType::Big, "big", "Big Endian")));
+cl::opt<std::string> OptTargetTriple(
+    "target", cl::desc("Specify the target triple, e.g. x86_64-linux-gnu"));
+cl::opt<std::string> OptTargetTripleHint(
+    "hint-ifs-target",
+    cl::desc("When --output-format is 'TBE', this flag will hint the expected "
+             "target triple for IFS output"));
+cl::opt<bool> StripIFSArch(
+    "strip-ifs-arch",
+    cl::desc("Strip target architecture information away from IFS output"));
+cl::opt<bool> StripIFSBitWidth(
+    "strip-ifs-bitwidth",
+    cl::desc("Strip target bit width information away from IFS output"));
+cl::opt<bool> StripIFSEndiannessWidth(
+    "strip-ifs-endianness",
+    cl::desc("Strip target endianness information away from IFS output"));
+cl::opt<bool> StripIFSTarget(
+    "strip-ifs-target",
+    cl::desc("Strip all target information away from IFS output"));
 cl::opt<std::string>
     SOName("soname",
            cl::desc("Manually set the DT_SONAME entry of any emitted files"),
            cl::value_desc("name"));
-cl::opt<ELFTarget> BinaryOutputTarget(
-    "output-target", cl::desc("Create a binary stub for the specified target"),
-    cl::values(clEnumValN(ELFTarget::ELF32LE, "elf32-little",
-                          "32-bit little-endian ELF stub"),
-               clEnumValN(ELFTarget::ELF32BE, "elf32-big",
-                          "32-bit big-endian ELF stub"),
-               clEnumValN(ELFTarget::ELF64LE, "elf64-little",
-                          "64-bit little-endian ELF stub"),
-               clEnumValN(ELFTarget::ELF64BE, "elf64-big",
-                          "64-bit big-endian ELF stub")));
-cl::opt<std::string> BinaryOutputFilePath(cl::Positional, cl::desc("output"));
+cl::opt<std::string> OutputFilePath("output", cl::desc("Output file"));
 cl::opt<bool> WriteIfChanged(
     "write-if-changed",
     cl::desc("Write the output file only if it is new or has changed."));
@@ -106,8 +123,7 @@ static Expected<std::unique_ptr<ELFStub>> readInputFile(StringRef FilePath) {
   ErrorCollector EC(/*UseFatalErrors=*/false);
 
   // First try to read as a binary (fails fast if not binary).
-  if (InputFileFormat.getNumOccurrences() == 0 ||
-      InputFileFormat == FileFormat::ELF) {
+  if (InputFormat.getNumOccurrences() == 0 || InputFormat == FileFormat::ELF) {
     Expected<std::unique_ptr<ELFStub>> StubFromELF =
         readELFFile(FileReadBuffer->getMemBufferRef());
     if (StubFromELF) {
@@ -117,8 +133,7 @@ static Expected<std::unique_ptr<ELFStub>> readInputFile(StringRef FilePath) {
   }
 
   // Fall back to reading as a tbe.
-  if (InputFileFormat.getNumOccurrences() == 0 ||
-      InputFileFormat == FileFormat::TBE) {
+  if (InputFormat.getNumOccurrences() == 0 || InputFormat == FileFormat::TBE) {
     Expected<std::unique_ptr<ELFStub>> StubFromTBE =
         readTBEFromBuffer(FileReadBuffer->getBuffer());
     if (StubFromTBE) {
@@ -145,7 +160,6 @@ static void fatalError(Error Err) {
 int main(int argc, char *argv[]) {
   // Parse arguments.
   cl::ParseCommandLineOptions(argc, argv);
-
   Expected<std::unique_ptr<ELFStub>> StubOrErr = readInputFile(InputFilePath);
   if (!StubOrErr)
     fatalError(StubOrErr.takeError());
@@ -155,22 +169,65 @@ int main(int argc, char *argv[]) {
   // Change SoName before emitting stubs.
   if (SOName.getNumOccurrences() == 1)
     TargetStub->SoName = SOName;
-
-  if (EmitTBE.getNumOccurrences() == 1) {
+  Optional<ELFArch> OverrideArch;
+  Optional<ELFEndiannessType> OverrideEndianness;
+  Optional<ELFBitWidthType> OverrideBitWidth;
+  Optional<std::string> OverrideTriple;
+  if (OptArch.getNumOccurrences() == 1) {
+    OverrideArch = ELF::convertArchNameToEMachine(OptArch.getValue());
+  }
+  if (OptEndianness.getNumOccurrences() == 1)
+    OverrideEndianness = OptEndianness.getValue();
+  if (OptBitWidth.getNumOccurrences() == 1)
+    OverrideBitWidth = OptBitWidth.getValue();
+  if (OptTargetTriple.getNumOccurrences() == 1)
+    OverrideTriple = OptTargetTriple.getValue();
+  Error OverrideError =
+      overrideTBETarget(*TargetStub, OverrideArch, OverrideEndianness,
+                        OverrideBitWidth, OverrideTriple);
+  if (OverrideError)
+    fatalError(std::move(OverrideError));
+  switch (OutputFormat.getValue()) {
+  case FileFormat::TBE: {
     TargetStub->TbeVersion = TBEVersionCurrent;
-    Error TBEWriteError = writeTBE(EmitTBE, *TargetStub);
+    if (InputFormat.getValue() == FileFormat::ELF &&
+        OptTargetTripleHint.getNumOccurrences() == 1) {
+      std::error_code HintEC(1, std::generic_category());
+      IFSTarget HintTarget = parseTriple(OptTargetTripleHint);
+      if (TargetStub->Target.Arch.getValue() != HintTarget.Arch.getValue()) {
+        fatalError(make_error<StringError>(
+            "Triple hint does not match the actual architecture", HintEC));
+      }
+      if (TargetStub->Target.Endianness.getValue() !=
+          HintTarget.Endianness.getValue()) {
+        fatalError(make_error<StringError>(
+            "Triple hint does not match the actual endianness", HintEC));
+      }
+      if (TargetStub->Target.BitWidth.getValue() !=
+          HintTarget.BitWidth.getValue()) {
+        fatalError(make_error<StringError>(
+            "Triple hint does not match the actual bit width", HintEC));
+      }
+      stripTBETarget(*TargetStub, true, false, false, false);
+      TargetStub->Target.Triple = OptTargetTripleHint.getValue();
+    } else {
+      stripTBETarget(*TargetStub, StripIFSTarget, StripIFSArch,
+                     StripIFSEndiannessWidth, StripIFSBitWidth);
+    }
+    Error TBEWriteError = writeTBE(OutputFilePath.getValue(), *TargetStub);
     if (TBEWriteError)
       fatalError(std::move(TBEWriteError));
+    break;
   }
-
-  // Write out binary ELF stub.
-  if (BinaryOutputFilePath.getNumOccurrences() == 1) {
-    if (BinaryOutputTarget.getNumOccurrences() == 0)
-      fatalError(createStringError(errc::not_supported,
-                                   "no binary output target specified."));
-    Error BinaryWriteError = writeBinaryStub(
-        BinaryOutputFilePath, *TargetStub, BinaryOutputTarget, WriteIfChanged);
+  case FileFormat::ELF: {
+    Error TargetError = validateTBETarget(*TargetStub, true);
+    if (TargetError)
+      fatalError(std::move(TargetError));
+    Error BinaryWriteError =
+        writeBinaryStub(OutputFilePath, *TargetStub, WriteIfChanged);
     if (BinaryWriteError)
       fatalError(std::move(BinaryWriteError));
+    break;
+  }
   }
 }

diff  --git a/llvm/tools/llvm-ifs/CMakeLists.txt b/llvm/tools/llvm-ifs/CMakeLists.txt
index 456f88d2b761d..373ef2ba2c287 100644
--- a/llvm/tools/llvm-ifs/CMakeLists.txt
+++ b/llvm/tools/llvm-ifs/CMakeLists.txt
@@ -1,5 +1,5 @@
 set(LLVM_LINK_COMPONENTS
-  InterfaceStub
+  InterfaceStub  
   Object
   Support
   TextAPI

diff  --git a/llvm/tools/llvm-ifs/llvm-ifs.cpp b/llvm/tools/llvm-ifs/llvm-ifs.cpp
index b6a1b4a95128e..8ab5ef9101f99 100644
--- a/llvm/tools/llvm-ifs/llvm-ifs.cpp
+++ b/llvm/tools/llvm-ifs/llvm-ifs.cpp
@@ -10,6 +10,8 @@
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/InterfaceStub/ELFObjHandler.h"
+#include "llvm/InterfaceStub/ELFStub.h"
+#include "llvm/InterfaceStub/TBEHandler.h"
 #include "llvm/ObjectYAML/yaml2obj.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
@@ -348,23 +350,10 @@ static int writeElfStub(const Triple &T, const std::vector<IFSSymbol> &Symbols,
   return convertYAML(YIn, Out, ErrHandler) ? 0 : 1;
 }
 
-static elfabi::ELFTarget convertIFSStub(const IFSStub &IfsStub,
-                                        elfabi::ELFStub &ElfStub) {
+static Error 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.Target.Triple = IfsStub.Triple;
   ElfStub.NeededLibs = IfsStub.NeededLibs;
   for (const IFSSymbol &IfsSymbol : IfsStub.Symbols) {
     elfabi::ELFSymbol ElfSymbol(IfsSymbol.Name);
@@ -387,9 +376,9 @@ static elfabi::ELFTarget convertIFSStub(const IFSStub &IfsStub,
     ElfSymbol.Undefined = false;
     ElfSymbol.Weak = IfsSymbol.Weak;
     ElfSymbol.Warning = IfsSymbol.Warning;
-    ElfStub.Symbols.insert(ElfSymbol);
+    ElfStub.Symbols.push_back(ElfSymbol);
   }
-  return Target;
+  return llvm::elfabi::validateTBETarget(ElfStub, true);
 }
 
 static int writeIfso(const IFSStub &Stub, bool IsWriteIfs) {
@@ -400,9 +389,11 @@ static int writeIfso(const IFSStub &Stub, bool IsWriteIfs) {
   // format is ELF.
   if (UseInterfaceStub && (!IsWriteIfs) && ObjectFileFormat != "TBD") {
     elfabi::ELFStub ElfStub;
-    elfabi::ELFTarget Target = convertIFSStub(Stub, ElfStub);
-    Error BinaryWriteError =
-        elfabi::writeBinaryStub(OutputFilename, ElfStub, Target);
+    Error ConvertError = convertIFSStub(Stub, ElfStub);
+    if (ConvertError) {
+      return -1;
+    }
+    Error BinaryWriteError = elfabi::writeBinaryStub(OutputFilename, ElfStub);
     if (BinaryWriteError) {
       return -1;
     }

diff  --git a/llvm/unittests/InterfaceStub/ELFYAMLTest.cpp b/llvm/unittests/InterfaceStub/ELFYAMLTest.cpp
index aa048839d3b9c..e438f841eb9b8 100644
--- a/llvm/unittests/InterfaceStub/ELFYAMLTest.cpp
+++ b/llvm/unittests/InterfaceStub/ELFYAMLTest.cpp
@@ -34,19 +34,21 @@ void compareByLine(StringRef LHS, StringRef RHS) {
 }
 
 TEST(ElfYamlTextAPI, YAMLReadableTBE) {
-  const char Data[] = "--- !tapi-tbe\n"
+  const char Data[] = "--- !ifs-v1\n"
                       "TbeVersion: 1.0\n"
-                      "Arch: x86_64\n"
+                      "Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: "
+                      "little, BitWidth: 64 }\n"
                       "NeededLibs: [libc.so, libfoo.so, libbar.so]\n"
                       "Symbols:\n"
-                      "  foo: { Type: Func, Undefined: true }\n"
+                      "  - { Name: foo, Type: Func, Undefined: true }\n"
                       "...\n";
   Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
   ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded());
   std::unique_ptr<ELFStub> Stub = std::move(StubOrErr.get());
   EXPECT_NE(Stub.get(), nullptr);
   EXPECT_FALSE(Stub->SoName.hasValue());
-  EXPECT_EQ(Stub->Arch, (uint16_t)llvm::ELF::EM_X86_64);
+  EXPECT_TRUE(Stub->Target.Arch.hasValue());
+  EXPECT_EQ(Stub->Target.Arch.getValue(), (uint16_t)llvm::ELF::EM_X86_64);
   EXPECT_EQ(Stub->NeededLibs.size(), 3u);
   EXPECT_STREQ(Stub->NeededLibs[0].c_str(), "libc.so");
   EXPECT_STREQ(Stub->NeededLibs[1].c_str(), "libfoo.so");
@@ -54,18 +56,20 @@ TEST(ElfYamlTextAPI, YAMLReadableTBE) {
 }
 
 TEST(ElfYamlTextAPI, YAMLReadsTBESymbols) {
-  const char Data[] = "--- !tapi-tbe\n"
-                      "TbeVersion: 1.0\n"
-                      "SoName: test.so\n"
-                      "Arch: x86_64\n"
-                      "Symbols:\n"
-                      "  bar: { Type: Object, Size: 42 }\n"
-                      "  baz: { Type: TLS, Size: 3 }\n"
-                      "  foo: { Type: Func, Warning: \"Deprecated!\" }\n"
-                      "  nor: { Type: NoType, Undefined: true }\n"
-                      "  not: { Type: File, Undefined: true, Size: 111, "
-                      "Weak: true, Warning: \'All fields populated!\' }\n"
-                      "...\n";
+  const char Data[] =
+      "--- !ifs-v1\n"
+      "TbeVersion: 1.0\n"
+      "SoName: test.so\n"
+      "Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, "
+      "BitWidth: 64 }\n"
+      "Symbols:\n"
+      "  - { Name: bar, Type: Object, Size: 42 }\n"
+      "  - { Name: baz, Type: TLS, Size: 3 }\n"
+      "  - { Name: foo, Type: Func, Warning: \"Deprecated!\" }\n"
+      "  - { Name: nor, Type: NoType, Undefined: true }\n"
+      "  - { Name: not, Type: File, Undefined: true, Size: 111, "
+      "Weak: true, Warning: \'All fields populated!\' }\n"
+      "...\n";
   Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
   ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded());
   std::unique_ptr<ELFStub> Stub = std::move(StubOrErr.get());
@@ -119,11 +123,12 @@ TEST(ElfYamlTextAPI, YAMLReadsTBESymbols) {
 }
 
 TEST(ElfYamlTextAPI, YAMLReadsNoTBESyms) {
-  const char Data[] = "--- !tapi-tbe\n"
+  const char Data[] = "--- !ifs-v1\n"
                       "TbeVersion: 1.0\n"
                       "SoName: test.so\n"
-                      "Arch: x86_64\n"
-                      "Symbols: {}\n"
+                      "Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: "
+                      "little, BitWidth: 64 }\n"
+                      "Symbols: []\n"
                       "...\n";
   Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
   ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded());
@@ -137,7 +142,8 @@ TEST(ElfYamlTextAPI, YAMLUnreadableTBE) {
   const char Data[] = "--- !tapi-tbz\n"
                       "TbeVersion: z.3\n"
                       "SoName: test.so\n"
-                      "Arch: x86_64\n"
+                      "Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: "
+                      "little, BitWidth: 64 }\n"
                       "Symbols:\n"
                       "  foo: { Type: Func, Undefined: true }\n";
   Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
@@ -145,11 +151,12 @@ TEST(ElfYamlTextAPI, YAMLUnreadableTBE) {
 }
 
 TEST(ElfYamlTextAPI, YAMLUnsupportedVersion) {
-  const char Data[] = "--- !tapi-tbe\n"
+  const char Data[] = "--- !ifs-v1\n"
                       "TbeVersion: 9.9.9\n"
                       "SoName: test.so\n"
-                      "Arch: x86_64\n"
-                      "Symbols: {}\n"
+                      "Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: "
+                      "little, BitWidth: 64 }\n"
+                      "Symbols: []\n"
                       "...\n";
   Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
   std::string ErrorMessage = toString(StubOrErr.takeError());
@@ -158,18 +165,28 @@ TEST(ElfYamlTextAPI, YAMLUnsupportedVersion) {
 
 TEST(ElfYamlTextAPI, YAMLWritesTBESymbols) {
   const char Expected[] =
-      "--- !tapi-tbe\n"
+      "--- !ifs-v1\n"
       "TbeVersion:      1.0\n"
-      "Arch:            AArch64\n"
+      "Target:          { ObjectFormat: ELF, Arch: AArch64, Endianness: "
+      "little, BitWidth: 64 }\n"
       "Symbols:\n"
-      "  bar:             { Type: Func, Weak: true }\n"
-      "  foo:             { Type: NoType, Size: 99, Warning: Does nothing }\n"
-      "  nor:             { Type: Func, Undefined: true }\n"
-      "  not:             { Type: Unknown, Size: 12345678901234 }\n"
+      "  - { Name: bar, Type: Func, Weak: true }\n"
+      "  - { Name: foo, Type: NoType, Size: 99, Warning: Does nothing }\n"
+      "  - { Name: nor, Type: Func, Undefined: true }\n"
+      "  - { Name: not, Type: Unknown, Size: 12345678901234 }\n"
       "...\n";
   ELFStub Stub;
   Stub.TbeVersion = VersionTuple(1, 0);
-  Stub.Arch = ELF::EM_AARCH64;
+  Stub.Target.Arch = ELF::EM_AARCH64;
+  Stub.Target.BitWidth = ELFBitWidthType::ELF64;
+  Stub.Target.Endianness = ELFEndiannessType::Little;
+  Stub.Target.ObjectFormat = "ELF";
+
+  ELFSymbol SymBar("bar");
+  SymBar.Size = 128u;
+  SymBar.Type = ELFSymbolType::Func;
+  SymBar.Undefined = false;
+  SymBar.Weak = true;
 
   ELFSymbol SymFoo("foo");
   SymFoo.Size = 99u;
@@ -178,12 +195,6 @@ TEST(ElfYamlTextAPI, YAMLWritesTBESymbols) {
   SymFoo.Weak = false;
   SymFoo.Warning = "Does nothing";
 
-  ELFSymbol SymBar("bar");
-  SymBar.Size = 128u;
-  SymBar.Type = ELFSymbolType::Func;
-  SymBar.Undefined = false;
-  SymBar.Weak = true;
-
   ELFSymbol SymNor("nor");
   SymNor.Size = 1234u;
   SymNor.Type = ELFSymbolType::Func;
@@ -196,11 +207,11 @@ TEST(ElfYamlTextAPI, YAMLWritesTBESymbols) {
   SymNot.Undefined = false;
   SymNot.Weak = false;
 
-  // Deliberately not in order to check that result is sorted.
-  Stub.Symbols.insert(SymNot);
-  Stub.Symbols.insert(SymBar);
-  Stub.Symbols.insert(SymFoo);
-  Stub.Symbols.insert(SymNor);
+  // Symbol order is preserved instead of being sorted.
+  Stub.Symbols.push_back(SymBar);
+  Stub.Symbols.push_back(SymFoo);
+  Stub.Symbols.push_back(SymNor);
+  Stub.Symbols.push_back(SymNot);
 
   // Ensure move constructor works as expected.
   ELFStub Moved = std::move(Stub);
@@ -213,20 +224,24 @@ TEST(ElfYamlTextAPI, YAMLWritesTBESymbols) {
 }
 
 TEST(ElfYamlTextAPI, YAMLWritesNoTBESyms) {
-  const char Expected[] = "--- !tapi-tbe\n"
+  const char Expected[] = "--- !ifs-v1\n"
                           "TbeVersion:      1.0\n"
                           "SoName:          nosyms.so\n"
-                          "Arch:            x86_64\n"
+                          "Target:          { ObjectFormat: ELF, Arch: x86_64, "
+                          "Endianness: little, BitWidth: 64 }\n"
                           "NeededLibs:\n"
                           "  - libc.so\n"
                           "  - libfoo.so\n"
                           "  - libbar.so\n"
-                          "Symbols:         {}\n"
+                          "Symbols:         []\n"
                           "...\n";
   ELFStub Stub;
   Stub.TbeVersion = VersionTuple(1, 0);
   Stub.SoName = "nosyms.so";
-  Stub.Arch = ELF::EM_X86_64;
+  Stub.Target.Arch = ELF::EM_X86_64;
+  Stub.Target.BitWidth = ELFBitWidthType::ELF64;
+  Stub.Target.Endianness = ELFEndiannessType::Little;
+  Stub.Target.ObjectFormat = "ELF";
   Stub.NeededLibs.push_back("libc.so");
   Stub.NeededLibs.push_back("libfoo.so");
   Stub.NeededLibs.push_back("libbar.so");


        


More information about the llvm-commits mailing list