diff --git a/llvm/include/llvm/InterfaceStub/ELFObjHandler.h b/llvm/include/llvm/InterfaceStub/ELFObjHandler.h --- a/llvm/include/llvm/InterfaceStub/ELFObjHandler.h +++ b/llvm/include/llvm/InterfaceStub/ELFObjHandler.h @@ -35,11 +35,10 @@ /// /// @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 --- 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 #include @@ -34,7 +35,18 @@ Unknown = 16, }; +enum class ELFEndiannessType { + Little = ELF::ELFDATA2LSB, + Big = ELF::ELFDATA2MSB, +}; + +enum class ELFBitWidthType { + ELF32 = ELF::ELFCLASS32, + ELF64 = ELF::ELFCLASS64, +}; + struct ELFSymbol { + ELFSymbol() = default; ELFSymbol(std::string SymbolName) : Name(SymbolName) {} std::string Name; uint64_t Size; @@ -45,6 +57,15 @@ bool operator<(const ELFSymbol &RHS) const { return Name < RHS.Name; } }; +struct IFSTarget { + Optional Triple; + Optional ObjectFormat; + Optional Arch; + Optional ArchString; + Optional Endianness; + Optional BitWidth; +}; + // A cumulative representation of ELF stubs. // Both textual and binary stubs will read into and write from this object. class ELFStub { @@ -52,14 +73,34 @@ public: VersionTuple TbeVersion; Optional SoName; - ELFArch Arch; + IFSTarget Target; std::vector NeededLibs; - std::set Symbols; + std::vector 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 different definitions. +// This class makes it possible to map a second traits so the same data +// structure can be used for 2 different yaml schema. +class ELFStubTriple : public ELFStub { +public: + ELFStubTriple() {} + ELFStubTriple(const ELFStub &Stub); + ELFStubTriple(const ELFStubTriple &Stub); + ELFStubTriple(ELFStubTriple &&Stub); +}; + +/// Convert an architecture name into ELF's e_machine value. +Expected convertArchNameToEMachine(StringRef Arch); + +/// Convert an ELF's e_machine value into an architecture name. +Expected convertEMachineToArchName(ELFArch EMachine); + } // end namespace elfabi } // end namespace llvm diff --git a/llvm/include/llvm/InterfaceStub/TBEHandler.h b/llvm/include/llvm/InterfaceStub/TBEHandler.h --- 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 @@ -37,6 +38,22 @@ /// 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 OverrideArch, + Optional OverrideEndianness, + Optional OverrideBitWidth, + Optional 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/InterfaceStub/ELFObjHandler.cpp b/llvm/lib/InterfaceStub/ELFObjHandler.cpp --- a/llvm/lib/InterfaceStub/ELFObjHandler.cpp +++ b/llvm/lib/InterfaceStub/ELFObjHandler.cpp @@ -250,7 +250,7 @@ fillStrTabShdr(ShStrTab); // Finish initializing the ELF header. - initELFHeader(ElfHeader, Stub.Arch); + initELFHeader(ElfHeader, (uint16_t)(Stub.Target.Arch.getValue())); ElfHeader.e_shstrndx = ShStrTab.Index; ElfHeader.e_shnum = LastSection->Index + 1; ElfHeader.e_shoff = @@ -517,7 +517,7 @@ if (!SymName) return SymName.takeError(); ELFSymbol Sym = createELFSym(*SymName, RawSym); - TargetStub.Symbols.insert(std::move(Sym)); + TargetStub.Symbols.push_back(std::move(Sym)); // TODO: Populate symbol warning. } return Error::success(); @@ -561,7 +561,12 @@ DynEnt.StrSize); // Populate Arch from ELF header. - DestStub->Arch = ElfFile.getHeader().e_machine; + DestStub->Target.Arch = (ELFArch)(uint16_t)(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 +672,23 @@ // 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(FilePath, Stub, WriteIfChanged); - if (OutputFormat == ELFTarget::ELF32BE) - return writeELFBinaryToFile(FilePath, Stub, WriteIfChanged); - if (OutputFormat == ELFTarget::ELF64LE) - return writeELFBinaryToFile(FilePath, Stub, WriteIfChanged); - if (OutputFormat == ELFTarget::ELF64BE) - return writeELFBinaryToFile(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(FilePath, Stub, WriteIfChanged); + } else { + return writeELFBinaryToFile(FilePath, Stub, WriteIfChanged); + } + } else { + if (Stub.Target.Endianness == ELFEndiannessType::Little) { + return writeELFBinaryToFile(FilePath, Stub, WriteIfChanged); + } else { + return writeELFBinaryToFile(FilePath, Stub, WriteIfChanged); + } + } llvm_unreachable("invalid binary output target"); } diff --git a/llvm/lib/InterfaceStub/ELFStub.cpp b/llvm/lib/InterfaceStub/ELFStub.cpp --- a/llvm/lib/InterfaceStub/ELFStub.cpp +++ b/llvm/lib/InterfaceStub/ELFStub.cpp @@ -7,13 +7,16 @@ //===-----------------------------------------------------------------------===/ #include "llvm/InterfaceStub/ELFStub.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.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,8 +24,412 @@ 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); +} + +Expected llvm::elfabi::convertArchNameToEMachine(StringRef Arch) { + static StringMap ArchNameMap = { + {"none", ELF::EM_NONE}, + {"m32", ELF::EM_M32}, + {"sparc", ELF::EM_SPARC}, + {"386", ELF::EM_386}, + {"68k", ELF::EM_68K}, + {"88k", ELF::EM_88K}, + {"iamcu", ELF::EM_IAMCU}, + {"860", ELF::EM_860}, + {"mips", ELF::EM_MIPS}, + {"s370", ELF::EM_S370}, + {"mips_rs3_le", ELF::EM_MIPS_RS3_LE}, + {"parisc", ELF::EM_PARISC}, + {"vpp500", ELF::EM_VPP500}, + {"sparc32plus", ELF::EM_SPARC32PLUS}, + {"960", ELF::EM_960}, + {"ppc", ELF::EM_PPC}, + {"ppc64", ELF::EM_PPC64}, + {"s390", ELF::EM_S390}, + {"spu", ELF::EM_SPU}, + {"v800", ELF::EM_V800}, + {"fr20", ELF::EM_FR20}, + {"rh32", ELF::EM_RH32}, + {"rce", ELF::EM_RCE}, + {"arm", ELF::EM_ARM}, + {"alpha", ELF::EM_ALPHA}, + {"sh", ELF::EM_SH}, + {"sparcv9", ELF::EM_SPARCV9}, + {"tricore", ELF::EM_TRICORE}, + {"arc", ELF::EM_ARC}, + {"h8_300", ELF::EM_H8_300}, + {"h8_300h", ELF::EM_H8_300H}, + {"h8s", ELF::EM_H8S}, + {"h8_500", ELF::EM_H8_500}, + {"ia_64", ELF::EM_IA_64}, + {"mips_x", ELF::EM_MIPS_X}, + {"coldfire", ELF::EM_COLDFIRE}, + {"68hc12", ELF::EM_68HC12}, + {"mma", ELF::EM_MMA}, + {"pcp", ELF::EM_PCP}, + {"ncpu", ELF::EM_NCPU}, + {"ndr1", ELF::EM_NDR1}, + {"starcore", ELF::EM_STARCORE}, + {"me16", ELF::EM_ME16}, + {"st100", ELF::EM_ST100}, + {"tinyj", ELF::EM_TINYJ}, + {"x86_64", ELF::EM_X86_64}, + {"pdsp", ELF::EM_PDSP}, + {"pdp10", ELF::EM_PDP10}, + {"pdp11", ELF::EM_PDP11}, + {"fx66", ELF::EM_FX66}, + {"st9plus", ELF::EM_ST9PLUS}, + {"st7", ELF::EM_ST7}, + {"68hc16", ELF::EM_68HC16}, + {"68hc11", ELF::EM_68HC11}, + {"68hc08", ELF::EM_68HC08}, + {"68hc05", ELF::EM_68HC05}, + {"svx", ELF::EM_SVX}, + {"st19", ELF::EM_ST19}, + {"vax", ELF::EM_VAX}, + {"cris", ELF::EM_CRIS}, + {"javelin", ELF::EM_JAVELIN}, + {"firepath", ELF::EM_FIREPATH}, + {"zsp", ELF::EM_ZSP}, + {"mmix", ELF::EM_MMIX}, + {"huany", ELF::EM_HUANY}, + {"prism", ELF::EM_PRISM}, + {"avr", ELF::EM_AVR}, + {"fr30", ELF::EM_FR30}, + {"d10v", ELF::EM_D10V}, + {"d30v", ELF::EM_D30V}, + {"v850", ELF::EM_V850}, + {"m32r", ELF::EM_M32R}, + {"mn10300", ELF::EM_MN10300}, + {"mn10200", ELF::EM_MN10200}, + {"pj", ELF::EM_PJ}, + {"openrisc", ELF::EM_OPENRISC}, + {"arc_compact", ELF::EM_ARC_COMPACT}, + {"xtensa", ELF::EM_XTENSA}, + {"videocore", ELF::EM_VIDEOCORE}, + {"tmm_gpp", ELF::EM_TMM_GPP}, + {"ns32k", ELF::EM_NS32K}, + {"tpc", ELF::EM_TPC}, + {"snp1k", ELF::EM_SNP1K}, + {"st200", ELF::EM_ST200}, + {"ip2k", ELF::EM_IP2K}, + {"max", ELF::EM_MAX}, + {"cr", ELF::EM_CR}, + {"f2mc16", ELF::EM_F2MC16}, + {"msp430", ELF::EM_MSP430}, + {"blackfin", ELF::EM_BLACKFIN}, + {"se_c33", ELF::EM_SE_C33}, + {"sep", ELF::EM_SEP}, + {"arca", ELF::EM_ARCA}, + {"unicore", ELF::EM_UNICORE}, + {"excess", ELF::EM_EXCESS}, + {"dxp", ELF::EM_DXP}, + {"altera_nios2", ELF::EM_ALTERA_NIOS2}, + {"crx", ELF::EM_CRX}, + {"xgate", ELF::EM_XGATE}, + {"c166", ELF::EM_C166}, + {"m16c", ELF::EM_M16C}, + {"dspic30f", ELF::EM_DSPIC30F}, + {"ce", ELF::EM_CE}, + {"m32c", ELF::EM_M32C}, + {"tsk3000", ELF::EM_TSK3000}, + {"rs08", ELF::EM_RS08}, + {"sharc", ELF::EM_SHARC}, + {"ecog2", ELF::EM_ECOG2}, + {"score7", ELF::EM_SCORE7}, + {"dsp24", ELF::EM_DSP24}, + {"videocore3", ELF::EM_VIDEOCORE3}, + {"latticemico32", ELF::EM_LATTICEMICO32}, + {"se_c17", ELF::EM_SE_C17}, + {"ti_c6000", ELF::EM_TI_C6000}, + {"ti_c2000", ELF::EM_TI_C2000}, + {"ti_c5500", ELF::EM_TI_C5500}, + {"mmdsp_plus", ELF::EM_MMDSP_PLUS}, + {"cypress_m8c", ELF::EM_CYPRESS_M8C}, + {"r32c", ELF::EM_R32C}, + {"trimedia", ELF::EM_TRIMEDIA}, + {"hexagon", ELF::EM_HEXAGON}, + {"8051", ELF::EM_8051}, + {"stxp7x", ELF::EM_STXP7X}, + {"nds32", ELF::EM_NDS32}, + {"ecog1", ELF::EM_ECOG1}, + {"ecog1x", ELF::EM_ECOG1X}, + {"maxq30", ELF::EM_MAXQ30}, + {"ximo16", ELF::EM_XIMO16}, + {"manik", ELF::EM_MANIK}, + {"craynv2", ELF::EM_CRAYNV2}, + {"rx", ELF::EM_RX}, + {"metag", ELF::EM_METAG}, + {"mcst_elbrus", ELF::EM_MCST_ELBRUS}, + {"ecog16", ELF::EM_ECOG16}, + {"cr16", ELF::EM_CR16}, + {"etpu", ELF::EM_ETPU}, + {"sle9x", ELF::EM_SLE9X}, + {"l10m", ELF::EM_L10M}, + {"k10m", ELF::EM_K10M}, + {"aarch64", ELF::EM_AARCH64}, + {"avr32", ELF::EM_AVR32}, + {"stm8", ELF::EM_STM8}, + {"tile64", ELF::EM_TILE64}, + {"tilepro", ELF::EM_TILEPRO}, + {"cuda", ELF::EM_CUDA}, + {"tilegx", ELF::EM_TILEGX}, + {"cloudshield", ELF::EM_CLOUDSHIELD}, + {"corea_1st", ELF::EM_COREA_1ST}, + {"corea_2nd", ELF::EM_COREA_2ND}, + {"arc_compact2", ELF::EM_ARC_COMPACT2}, + {"open8", ELF::EM_OPEN8}, + {"rl78", ELF::EM_RL78}, + {"videocore5", ELF::EM_VIDEOCORE5}, + {"78kor", ELF::EM_78KOR}, + {"56800ex", ELF::EM_56800EX}, + {"ba1", ELF::EM_BA1}, + {"ba2", ELF::EM_BA2}, + {"xcore", ELF::EM_XCORE}, + {"mchp_pic", ELF::EM_MCHP_PIC}, + {"intel205", ELF::EM_INTEL205}, + {"intel206", ELF::EM_INTEL206}, + {"intel207", ELF::EM_INTEL207}, + {"intel208", ELF::EM_INTEL208}, + {"intel209", ELF::EM_INTEL209}, + {"km32", ELF::EM_KM32}, + {"kmx32", ELF::EM_KMX32}, + {"kmx16", ELF::EM_KMX16}, + {"kmx8", ELF::EM_KMX8}, + {"kvarc", ELF::EM_KVARC}, + {"cdp", ELF::EM_CDP}, + {"coge", ELF::EM_COGE}, + {"cool", ELF::EM_COOL}, + {"norc", ELF::EM_NORC}, + {"csr_kalimba", ELF::EM_CSR_KALIMBA}, + {"amdgpu", ELF::EM_AMDGPU}, + {"riscv", ELF::EM_RISCV}, + {"lanai", ELF::EM_LANAI}, + {"bpf", ELF::EM_BPF}, + {"ve", ELF::EM_VE}, + {"csky", ELF::EM_CSKY}, + }; + std::string LowerArch = Arch.lower(); + if (ArchNameMap.count(LowerArch)) { + return ArchNameMap[LowerArch]; + } + return ELF::EM_NONE; +} + +Expected +llvm::elfabi::convertEMachineToArchName(ELFArch EMachine) { + DenseMap EMachineMap = { + {ELF::EM_NONE, "None"}, + {ELF::EM_M32, "m32"}, + {ELF::EM_SPARC, "sparc"}, + {ELF::EM_386, "386"}, + {ELF::EM_68K, "68k"}, + {ELF::EM_88K, "88k"}, + {ELF::EM_IAMCU, "iamcu"}, + {ELF::EM_860, "860"}, + {ELF::EM_MIPS, "mips"}, + {ELF::EM_S370, "s370"}, + {ELF::EM_MIPS_RS3_LE, "mips_rs3_le"}, + {ELF::EM_PARISC, "parisc"}, + {ELF::EM_VPP500, "vpp500"}, + {ELF::EM_SPARC32PLUS, "sparc32plus"}, + {ELF::EM_960, "960"}, + {ELF::EM_PPC, "ppc"}, + {ELF::EM_PPC64, "ppc64"}, + {ELF::EM_S390, "s390"}, + {ELF::EM_SPU, "spu"}, + {ELF::EM_V800, "v800"}, + {ELF::EM_FR20, "fr20"}, + {ELF::EM_RH32, "rh32"}, + {ELF::EM_RCE, "rce"}, + {ELF::EM_ARM, "arm"}, + {ELF::EM_ALPHA, "alpha"}, + {ELF::EM_SH, "sh"}, + {ELF::EM_SPARCV9, "sparcv9"}, + {ELF::EM_TRICORE, "tricore"}, + {ELF::EM_ARC, "arc"}, + {ELF::EM_H8_300, "h8_300"}, + {ELF::EM_H8_300H, "h8_300h"}, + {ELF::EM_H8S, "h8s"}, + {ELF::EM_H8_500, "h8_500"}, + {ELF::EM_IA_64, "ia_64"}, + {ELF::EM_MIPS_X, "mips_x"}, + {ELF::EM_COLDFIRE, "coldfire"}, + {ELF::EM_68HC12, "68hc12"}, + {ELF::EM_MMA, "mma"}, + {ELF::EM_PCP, "pcp"}, + {ELF::EM_NCPU, "ncpu"}, + {ELF::EM_NDR1, "ndr1"}, + {ELF::EM_STARCORE, "starcore"}, + {ELF::EM_ME16, "me16"}, + {ELF::EM_ST100, "st100"}, + {ELF::EM_TINYJ, "tinyj"}, + {ELF::EM_X86_64, "x86_64"}, + {ELF::EM_PDSP, "pdsp"}, + {ELF::EM_PDP10, "pdp10"}, + {ELF::EM_PDP11, "pdp11"}, + {ELF::EM_FX66, "fx66"}, + {ELF::EM_ST9PLUS, "st9plus"}, + {ELF::EM_ST7, "st7"}, + {ELF::EM_68HC16, "68hc16"}, + {ELF::EM_68HC11, "68hc11"}, + {ELF::EM_68HC08, "68hc08"}, + {ELF::EM_68HC05, "68hc05"}, + {ELF::EM_SVX, "svx"}, + {ELF::EM_ST19, "st19"}, + {ELF::EM_VAX, "vax"}, + {ELF::EM_CRIS, "cris"}, + {ELF::EM_JAVELIN, "javelin"}, + {ELF::EM_FIREPATH, "firepath"}, + {ELF::EM_ZSP, "zsp"}, + {ELF::EM_MMIX, "mmix"}, + {ELF::EM_HUANY, "huany"}, + {ELF::EM_PRISM, "prism"}, + {ELF::EM_AVR, "avr"}, + {ELF::EM_FR30, "fr30"}, + {ELF::EM_D10V, "d10v"}, + {ELF::EM_D30V, "d30v"}, + {ELF::EM_V850, "v850"}, + {ELF::EM_M32R, "m32r"}, + {ELF::EM_MN10300, "mn10300"}, + {ELF::EM_MN10200, "mn10200"}, + {ELF::EM_PJ, "pj"}, + {ELF::EM_OPENRISC, "openrisc"}, + {ELF::EM_ARC_COMPACT, "arc_compact"}, + {ELF::EM_XTENSA, "xtensa"}, + {ELF::EM_VIDEOCORE, "videocore"}, + {ELF::EM_TMM_GPP, "tmm_gpp"}, + {ELF::EM_NS32K, "ns32k"}, + {ELF::EM_TPC, "tpc"}, + {ELF::EM_SNP1K, "snp1k"}, + {ELF::EM_ST200, "st200"}, + {ELF::EM_IP2K, "ip2k"}, + {ELF::EM_MAX, "max"}, + {ELF::EM_CR, "cr"}, + {ELF::EM_F2MC16, "f2mc16"}, + {ELF::EM_MSP430, "msp430"}, + {ELF::EM_BLACKFIN, "blackfin"}, + {ELF::EM_SE_C33, "se_c33"}, + {ELF::EM_SEP, "sep"}, + {ELF::EM_ARCA, "arca"}, + {ELF::EM_UNICORE, "unicore"}, + {ELF::EM_EXCESS, "excess"}, + {ELF::EM_DXP, "dxp"}, + {ELF::EM_ALTERA_NIOS2, "altera_nios2"}, + {ELF::EM_CRX, "crx"}, + {ELF::EM_XGATE, "xgate"}, + {ELF::EM_C166, "c166"}, + {ELF::EM_M16C, "m16c"}, + {ELF::EM_DSPIC30F, "dspic30f"}, + {ELF::EM_CE, "ce"}, + {ELF::EM_M32C, "m32c"}, + {ELF::EM_TSK3000, "tsk3000"}, + {ELF::EM_RS08, "rs08"}, + {ELF::EM_SHARC, "sharc"}, + {ELF::EM_ECOG2, "ecog2"}, + {ELF::EM_SCORE7, "score7"}, + {ELF::EM_DSP24, "dsp24"}, + {ELF::EM_VIDEOCORE3, "videocore3"}, + {ELF::EM_LATTICEMICO32, "latticemico32"}, + {ELF::EM_SE_C17, "se_c17"}, + {ELF::EM_TI_C6000, "ti_c6000"}, + {ELF::EM_TI_C2000, "ti_c2000"}, + {ELF::EM_TI_C5500, "ti_c5500"}, + {ELF::EM_MMDSP_PLUS, "mmdsp_plus"}, + {ELF::EM_CYPRESS_M8C, "cypress_m8c"}, + {ELF::EM_R32C, "r32c"}, + {ELF::EM_TRIMEDIA, "trimedia"}, + {ELF::EM_HEXAGON, "hexagon"}, + {ELF::EM_8051, "8051"}, + {ELF::EM_STXP7X, "stxp7x"}, + {ELF::EM_NDS32, "nds32"}, + {ELF::EM_ECOG1, "ecog1"}, + {ELF::EM_ECOG1X, "ecog1x"}, + {ELF::EM_MAXQ30, "maxq30"}, + {ELF::EM_XIMO16, "ximo16"}, + {ELF::EM_MANIK, "manik"}, + {ELF::EM_CRAYNV2, "craynv2"}, + {ELF::EM_RX, "rx"}, + {ELF::EM_METAG, "metag"}, + {ELF::EM_MCST_ELBRUS, "mcst_elbrus"}, + {ELF::EM_ECOG16, "ecog16"}, + {ELF::EM_CR16, "cr16"}, + {ELF::EM_ETPU, "etpu"}, + {ELF::EM_SLE9X, "sle9x"}, + {ELF::EM_L10M, "l10m"}, + {ELF::EM_K10M, "k10m"}, + {ELF::EM_AARCH64, "AArch64"}, + {ELF::EM_AVR32, "avr32"}, + {ELF::EM_STM8, "stm8"}, + {ELF::EM_TILE64, "tile64"}, + {ELF::EM_TILEPRO, "tilepro"}, + {ELF::EM_CUDA, "cuda"}, + {ELF::EM_TILEGX, "tilegx"}, + {ELF::EM_CLOUDSHIELD, "cloudshield"}, + {ELF::EM_COREA_1ST, "corea_1st"}, + {ELF::EM_COREA_2ND, "corea_2nd"}, + {ELF::EM_ARC_COMPACT2, "arc_compact2"}, + {ELF::EM_OPEN8, "open8"}, + {ELF::EM_RL78, "rl78"}, + {ELF::EM_VIDEOCORE5, "videocore5"}, + {ELF::EM_78KOR, "78kor"}, + {ELF::EM_56800EX, "56800ex"}, + {ELF::EM_BA1, "ba1"}, + {ELF::EM_BA2, "ba2"}, + {ELF::EM_XCORE, "xcore"}, + {ELF::EM_MCHP_PIC, "mchp_pic"}, + {ELF::EM_INTEL205, "intel205"}, + {ELF::EM_INTEL206, "intel206"}, + {ELF::EM_INTEL207, "intel207"}, + {ELF::EM_INTEL208, "intel208"}, + {ELF::EM_INTEL209, "intel209"}, + {ELF::EM_KM32, "km32"}, + {ELF::EM_KMX32, "kmx32"}, + {ELF::EM_KMX16, "kmx16"}, + {ELF::EM_KMX8, "kmx8"}, + {ELF::EM_KVARC, "kvarc"}, + {ELF::EM_CDP, "cdp"}, + {ELF::EM_COGE, "coge"}, + {ELF::EM_COOL, "cool"}, + {ELF::EM_NORC, "norc"}, + {ELF::EM_CSR_KALIMBA, "csr_kalimba"}, + {ELF::EM_AMDGPU, "amdgpu"}, + {ELF::EM_RISCV, "riscv"}, + {ELF::EM_LANAI, "lanai"}, + {ELF::EM_BPF, "bpf"}, + {ELF::EM_VE, "ve"}, + {ELF::EM_CSKY, "csky"}, + }; + if (EMachineMap.count(EMachine)) { + return EMachineMap[EMachine]; + } + return "None"; +} diff --git a/llvm/lib/InterfaceStub/TBEHandler.cpp b/llvm/lib/InterfaceStub/TBEHandler.cpp --- 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,68 @@ } }; -/// YAML traits for ELFArch. -template <> struct ScalarTraits { - static void output(const ELFArchMapper &Value, void *, +template <> struct ScalarTraits { + 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"; } } - static StringRef input(StringRef Scalar, void *, ELFArchMapper &Value) { - // Map from architecture string to integer. - Value = StringSwitch(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(Scalar) + .Case("big", ELFEndiannessType::Big) + .Case("little", ELFEndiannessType::Little); + return StringRef(); + } + + static QuotingType mustQuote(StringRef) { return QuotingType::None; } +}; + +template <> struct ScalarTraits { + 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; + } + } - // Returning empty StringRef indicates successful parse. + static StringRef input(StringRef Scalar, void *, ELFBitWidthType &Value) { + Value = StringSwitch(Scalar) + .Case("32", ELFBitWidthType::ELF32) + .Case("64", ELFBitWidthType::ELF64); return StringRef(); } - // Don't place quotation marks around architecture value. static QuotingType mustQuote(StringRef) { return QuotingType::None; } }; +template <> struct MappingTraits { + 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; +}; + /// YAML traits for ELFSymbol. template <> struct MappingTraits { 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) { @@ -90,54 +117,208 @@ static const bool flow = true; }; -/// YAML traits for set of ELFSymbols. -template <> struct CustomMappingTraits> { - static void inputOne(IO &IO, StringRef Key, std::set &Set) { - ELFSymbol Sym(Key.str()); - IO.mapRequired(Key.str().c_str(), Sym); - Set.insert(Sym); - } - - static void output(IO &IO, std::set &Set) { - for (auto &Sym : Set) - IO.mapRequired(Sym.Name.c_str(), const_cast(Sym)); - } -}; - /// YAML traits for ELFStub objects. template <> struct MappingTraits { 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 { + 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> elfabi::readTBEFromBuffer(StringRef Buf) { yaml::Input YamlIn(Buf); - std::unique_ptr Stub(new ELFStub()); - YamlIn >> *Stub; - if (std::error_code Err = YamlIn.error()) + std::unique_ptr Stub(new ELFStubTriple()); + if (usesTriple(Buf)) { + YamlIn >> *Stub; + } else { + YamlIn >> *dynamic_cast(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( "TBE version " + Stub->TbeVersion.getAsString() + " is unsupported.", std::make_error_code(std::errc::invalid_argument)); - + if (Stub->Target.ArchString) { + Expected Arch = + convertArchNameToEMachine(Stub->Target.ArchString.getValue()); + if (!Arch) { + return Arch.takeError(); + } + Stub->Target.Arch = Arch.get(); + } return std::move(Stub); } Error elfabi::writeTBEToOutputStream(raw_ostream &OS, const ELFStub &Stub) { yaml::Output YamlOut(OS, NULL, /*WrapColumn =*/0); + std::unique_ptr CopyStub(new ELFStubTriple(Stub)); + if (Stub.Target.Arch) { + Expected ArchString = + convertEMachineToArchName(Stub.Target.Arch.getValue()); + if (!ArchString) { + return ArchString.takeError(); + } + CopyStub->Target.ArchString = ArchString.get(); + } + IFSTarget Target = Stub.Target; + + if (CopyStub->Target.Triple || + (!CopyStub->Target.ArchString && !CopyStub->Target.Endianness && + !CopyStub->Target.BitWidth)) + YamlOut << *CopyStub; + else + YamlOut << *dynamic_cast(CopyStub.get()); + return Error::success(); +} + +Error elfabi::overrideTBETarget(ELFStub &Stub, Optional OverrideArch, + Optional OverrideEndianness, + Optional OverrideBitWidth, + Optional OverrideTriple) { + std::error_code OverrideEC(1, std::generic_category()); + if (OverrideArch) { + if (Stub.Target.Arch && + Stub.Target.Arch.getValue() != OverrideArch.getValue()) { + return make_error( + "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( + "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( + "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( + "Supplied Triple conflicts with the text stub", OverrideEC); + } + Stub.Target.Triple = OverrideTriple.getValue(); + } + return Error::success(); +} - YamlOut << const_cast(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( + "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("Arch is not defined in the text stub", + ValidationEC); + } + if (!Stub.Target.BitWidth) { + return make_error("BitWidth is not defined in the text stub", + ValidationEC); + } + if (!Stub.Target.Endianness) { + return make_error( + "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::ELF64; + 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 --- 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 @@ 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 --- 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 @@ 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 --- 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 --- 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 --- 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 --- 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 @@ # 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 --- 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 --- 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 --- 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 --- 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 --- 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 --- 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 @@ 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 --- 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 --- 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 --- 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 --- 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 --- 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 --- 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 --- 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 --- 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 --- 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 --- 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 --- 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-unsupported-file.test b/llvm/test/tools/llvm-elfabi/read-unsupported-file.test --- 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 --- /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 --- 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 --- 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 --- 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 --- 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 @@ # 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/llvm-elfabi.cpp b/llvm/tools/llvm-elfabi/llvm-elfabi.cpp --- a/llvm/tools/llvm-elfabi/llvm-elfabi.cpp +++ b/llvm/tools/llvm-elfabi/llvm-elfabi.cpp @@ -30,33 +30,50 @@ using namespace llvm::elfabi; // Command line flags: -cl::opt 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 InputFilePath(cl::Positional, cl::desc("input"), cl::Required); -cl::opt - EmitTBE("emit-tbe", - cl::desc("Emit a text-based ELF stub (.tbe) from the input file"), - cl::value_desc("path")); +cl::opt 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 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 OptArch("arch", + cl::desc("Specify the architecture, e.g. x86_64")); +cl::opt OptBitWidth( + "bitwidth", cl::desc("Specify the bit width"), + cl::values(clEnumValN(ELFBitWidthType::ELF32, "32", "32 bits"), + clEnumValN(ELFBitWidthType::ELF64, "64", "64 bits"))); +cl::opt OptEndianness( + "endianness", cl::desc("Specify the endianness"), + cl::values(clEnumValN(ELFEndiannessType::Little, "little", "Little Endian"), + clEnumValN(ELFEndiannessType::Big, "big", "Big Endian"))); +cl::opt OptTargetTriple( + "target", cl::desc("Specify the target triple, e.g. x86_64-linux-gnu")); +cl::opt OptTargetTripleHint( + "hint-ifs-target", + cl::desc("When --output-format is 'TBE', this flag will hint the expected " + "target triple for IFS output")); +cl::opt StripIFSArch( + "strip-ifs-arch", + cl::desc("Strip target architecture information away from IFS output")); +cl::opt StripIFSBitWidth( + "strip-ifs-bitwidth", + cl::desc("Strip target bit width information away from IFS output")); +cl::opt StripIFSEndiannessWidth( + "strip-ifs-endianness", + cl::desc("Strip target endianness information away from IFS output")); +cl::opt StripIFSTarget( + "strip-ifs-target", + cl::desc("Strip all target information away from IFS output")); cl::opt SOName("soname", cl::desc("Manually set the DT_SONAME entry of any emitted files"), cl::value_desc("name")); -cl::opt 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 BinaryOutputFilePath(cl::Positional, cl::desc("output")); +cl::opt OutputFilePath("output", cl::desc("Output file")); cl::opt WriteIfChanged( "write-if-changed", cl::desc("Write the output file only if it is new or has changed.")); @@ -106,8 +123,7 @@ 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> StubFromELF = readELFFile(FileReadBuffer->getMemBufferRef()); if (StubFromELF) { @@ -117,8 +133,7 @@ } // Fall back to reading as a tbe. - if (InputFileFormat.getNumOccurrences() == 0 || - InputFileFormat == FileFormat::TBE) { + if (InputFormat.getNumOccurrences() == 0 || InputFormat == FileFormat::TBE) { Expected> StubFromTBE = readTBEFromBuffer(FileReadBuffer->getBuffer()); if (StubFromTBE) { @@ -145,7 +160,6 @@ int main(int argc, char *argv[]) { // Parse arguments. cl::ParseCommandLineOptions(argc, argv); - Expected> StubOrErr = readInputFile(InputFilePath); if (!StubOrErr) fatalError(StubOrErr.takeError()); @@ -155,22 +169,69 @@ // Change SoName before emitting stubs. if (SOName.getNumOccurrences() == 1) TargetStub->SoName = SOName; - - if (EmitTBE.getNumOccurrences() == 1) { + Optional OverrideArch; + Optional OverrideEndianness; + Optional OverrideBitWidth; + Optional OverrideTriple; + if (OptArch.getNumOccurrences() == 1) { + Expected ArchOrErr = convertArchNameToEMachine(OptArch.getValue()); + if (!ArchOrErr) { + fatalError(ArchOrErr.takeError()); + } + OverrideArch = ArchOrErr.get(); + } + 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( + "Triple hint does not match the actual architecture", HintEC)); + } + if (TargetStub->Target.Endianness.getValue() != + HintTarget.Endianness.getValue()) { + fatalError(make_error( + "Triple hint does not match the actual endianness", HintEC)); + } + if (TargetStub->Target.BitWidth.getValue() != + HintTarget.BitWidth.getValue()) { + fatalError(make_error( + "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/llvm-ifs.cpp b/llvm/tools/llvm-ifs/llvm-ifs.cpp --- a/llvm/tools/llvm-ifs/llvm-ifs.cpp +++ b/llvm/tools/llvm-ifs/llvm-ifs.cpp @@ -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 @@ 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 @@ 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 @@ // 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 --- a/llvm/unittests/InterfaceStub/ELFYAMLTest.cpp +++ b/llvm/unittests/InterfaceStub/ELFYAMLTest.cpp @@ -34,19 +34,21 @@ } 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> StubOrErr = readTBEFromBuffer(Data); ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded()); std::unique_ptr 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, 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> StubOrErr = readTBEFromBuffer(Data); ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded()); std::unique_ptr Stub = std::move(StubOrErr.get()); @@ -119,11 +123,12 @@ } 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> StubOrErr = readTBEFromBuffer(Data); ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded()); @@ -137,7 +142,8 @@ 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> StubOrErr = readTBEFromBuffer(Data); @@ -145,11 +151,12 @@ } 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> StubOrErr = readTBEFromBuffer(Data); std::string ErrorMessage = toString(StubOrErr.takeError()); @@ -158,18 +165,28 @@ 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 @@ 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 @@ 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, 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");