| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| //===- IFSHandler.h ---------------------------------------------*- 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 | ||
| // | ||
| //===-----------------------------------------------------------------------===/ | ||
| /// | ||
| /// \file | ||
| /// This file declares an interface for reading and writing .ifs (text-based | ||
| /// InterFace Stub) files. | ||
| /// | ||
| //===-----------------------------------------------------------------------===/ | ||
|
|
||
| #ifndef LLVM_INTERFACESTUB_IFSHANDLER_H | ||
| #define LLVM_INTERFACESTUB_IFSHANDLER_H | ||
|
|
||
| #include "IFSStub.h" | ||
| #include "llvm/Support/Error.h" | ||
| #include "llvm/Support/VersionTuple.h" | ||
| #include <memory> | ||
|
|
||
| namespace llvm { | ||
|
|
||
| class raw_ostream; | ||
| class Error; | ||
| class StringRef; | ||
|
|
||
| namespace ifs { | ||
|
|
||
| struct IFSStub; | ||
|
|
||
| const VersionTuple IFSVersionCurrent(3, 0); | ||
|
|
||
| /// Attempts to read an IFS interface file from a StringRef buffer. | ||
| Expected<std::unique_ptr<IFSStub>> readIFSFromBuffer(StringRef Buf); | ||
|
|
||
| /// Attempts to write an IFS interface file to a raw_ostream. | ||
| Error writeIFSToOutputStream(raw_ostream &OS, const IFSStub &Stub); | ||
|
|
||
| /// Override the target platform inforation in the text stub. | ||
| Error overrideIFSTarget(IFSStub &Stub, Optional<IFSArch> OverrideArch, | ||
| Optional<IFSEndiannessType> OverrideEndianness, | ||
| Optional<IFSBitWidthType> OverrideBitWidth, | ||
| Optional<std::string> OverrideTriple); | ||
|
|
||
| /// Validate the target platform inforation in the text stub. | ||
| Error validateIFSTarget(IFSStub &Stub, bool ParseTriple); | ||
|
|
||
| /// Strips target platform information from the text stub. | ||
| void stripIFSTarget(IFSStub &Stub, bool StripTriple, bool StripArch, | ||
| bool StripEndianness, bool StripBitWidth); | ||
|
|
||
| /// Parse llvm triple string into a IFSTarget struct. | ||
| IFSTarget parseTriple(StringRef TripleStr); | ||
|
|
||
| } // end namespace ifs | ||
| } // end namespace llvm | ||
|
|
||
| #endif // LLVM_INTERFACESTUB_IFSHANDLER_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,157 @@ | ||
| //===- IFSStub.h ------------------------------------------------*- 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 | ||
| // | ||
| //===-----------------------------------------------------------------------===/ | ||
| /// | ||
| /// \file | ||
| /// This file defines an internal representation of an InterFace Stub. | ||
| /// | ||
| //===-----------------------------------------------------------------------===/ | ||
|
|
||
| #ifndef LLVM_INTERFACESTUB_IFSSTUB_H | ||
| #define LLVM_INTERFACESTUB_IFSSTUB_H | ||
|
|
||
| #include "llvm/Support/Error.h" | ||
| #include "llvm/Support/VersionTuple.h" | ||
| #include <set> | ||
| #include <vector> | ||
|
|
||
| namespace llvm { | ||
| namespace ifs { | ||
|
|
||
| typedef uint16_t IFSArch; | ||
|
|
||
| enum class IFSSymbolType { | ||
| NoType, | ||
| Object, | ||
| Func, | ||
| TLS, | ||
|
|
||
| // Type information is 4 bits, so 16 is safely out of range. | ||
| Unknown = 16, | ||
| }; | ||
|
|
||
| enum class IFSEndiannessType { | ||
| Little, | ||
| Big, | ||
|
|
||
| // Endianness info is 1 bytes, 256 is safely out of range. | ||
| Unknown = 256, | ||
| }; | ||
|
|
||
| enum class IFSBitWidthType { | ||
| IFS32, | ||
| IFS64, | ||
|
|
||
| // Bit width info is 1 bytes, 256 is safely out of range. | ||
| Unknown = 256, | ||
| }; | ||
|
|
||
| struct IFSSymbol { | ||
| IFSSymbol() = default; | ||
| explicit IFSSymbol(std::string SymbolName) : Name(std::move(SymbolName)) {} | ||
| std::string Name; | ||
| uint64_t Size; | ||
| IFSSymbolType Type; | ||
| bool Undefined; | ||
| bool Weak; | ||
| Optional<std::string> Warning; | ||
| bool operator<(const IFSSymbol &RHS) const { return Name < RHS.Name; } | ||
| }; | ||
|
|
||
| struct IFSTarget { | ||
| Optional<std::string> Triple; | ||
| Optional<std::string> ObjectFormat; | ||
| Optional<IFSArch> Arch; | ||
| Optional<std::string> ArchString; | ||
| Optional<IFSEndiannessType> Endianness; | ||
| Optional<IFSBitWidthType> BitWidth; | ||
|
|
||
| bool empty(); | ||
| }; | ||
|
|
||
| inline bool operator==(const IFSTarget &Lhs, const IFSTarget &Rhs) { | ||
| if (Lhs.Arch != Rhs.Arch || Lhs.BitWidth != Rhs.BitWidth || | ||
| Lhs.Endianness != Rhs.Endianness || | ||
| Lhs.ObjectFormat != Rhs.ObjectFormat || Lhs.Triple != Rhs.Triple) | ||
| return false; | ||
| return true; | ||
| } | ||
|
|
||
| inline bool operator!=(const IFSTarget &Lhs, const IFSTarget &Rhs) { | ||
| return !(Lhs == Rhs); | ||
| } | ||
|
|
||
| // A cumulative representation of InterFace stubs. | ||
| // Both textual and binary stubs will read into and write from this object. | ||
| struct IFSStub { | ||
| // TODO: Add support for symbol versioning. | ||
| VersionTuple IfsVersion; | ||
| Optional<std::string> SoName; | ||
| IFSTarget Target; | ||
| std::vector<std::string> NeededLibs; | ||
| std::vector<IFSSymbol> Symbols; | ||
|
|
||
| IFSStub() {} | ||
| IFSStub(const IFSStub &Stub); | ||
| IFSStub(IFSStub &&Stub); | ||
| }; | ||
|
|
||
| // Create a alias class for IFSStub. | ||
| // 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. | ||
| struct IFSStubTriple : IFSStub { | ||
| IFSStubTriple() {} | ||
| IFSStubTriple(const IFSStub &Stub); | ||
| IFSStubTriple(const IFSStubTriple &Stub); | ||
| IFSStubTriple(IFSStubTriple &&Stub); | ||
| }; | ||
|
|
||
| /// This function convert bit width type from IFS enum to ELF format | ||
| /// Currently, ELFCLASS32 and ELFCLASS64 are supported. | ||
| /// | ||
| /// @param BitWidth IFS bit width type. | ||
| uint8_t convertIFSBitWidthToELF(IFSBitWidthType BitWidth); | ||
|
|
||
| /// This function convert endianness type from IFS enum to ELF format | ||
| /// Currently, ELFDATA2LSB and ELFDATA2MSB are supported. | ||
| /// | ||
| /// @param Endianness IFS endianness type. | ||
| uint8_t convertIFSEndiannessToELF(IFSEndiannessType Endianness); | ||
|
|
||
| /// This function convert symbol type from IFS enum to ELF format | ||
| /// Currently, STT_NOTYPE, STT_OBJECT, STT_FUNC, and STT_TLS are supported. | ||
| /// | ||
| /// @param SymbolType IFS symbol type. | ||
| uint8_t convertIFSSymbolTypeToELF(IFSSymbolType SymbolType); | ||
|
|
||
| /// This function extracts ELF bit width from e_ident[EI_CLASS] of an ELF file | ||
| /// Currently, ELFCLASS32 and ELFCLASS64 are supported. | ||
| /// Other endianness types are mapped to IFSBitWidthType::Unknown. | ||
| /// | ||
| /// @param BitWidth e_ident[EI_CLASS] value to extract bit width from. | ||
| IFSBitWidthType convertELFBitWidthToIFS(uint8_t BitWidth); | ||
|
|
||
| /// This function extracts ELF endianness from e_ident[EI_DATA] of an ELF file | ||
| /// Currently, ELFDATA2LSB and ELFDATA2MSB are supported. | ||
| /// Other endianness types are mapped to IFSEndiannessType::Unknown. | ||
| /// | ||
| /// @param Endianness e_ident[EI_DATA] value to extract endianness type from. | ||
| IFSEndiannessType convertELFEndiannessToIFS(uint8_t Endianness); | ||
|
|
||
| /// This function extracts symbol type from a symbol's st_info member and | ||
| /// maps it to an IFSSymbolType enum. | ||
| /// Currently, STT_NOTYPE, STT_OBJECT, STT_FUNC, and STT_TLS are supported. | ||
| /// Other symbol types are mapped to IFSSymbolType::Unknown. | ||
| /// | ||
| /// @param SymbolType Binary symbol st_info to extract symbol type from. | ||
| IFSSymbolType convertELFSymbolTypeToIFS(uint8_t SymbolType); | ||
| } // namespace ifs | ||
| } // end namespace llvm | ||
|
|
||
| #endif // LLVM_INTERFACESTUB_IFSSTUB_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,329 @@ | ||
| //===- IFSHandler.cpp -----------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===-----------------------------------------------------------------------===/ | ||
|
|
||
| #include "llvm/InterfaceStub/IFSHandler.h" | ||
| #include "llvm/ADT/StringRef.h" | ||
| #include "llvm/ADT/StringSwitch.h" | ||
| #include "llvm/ADT/Triple.h" | ||
| #include "llvm/BinaryFormat/ELF.h" | ||
| #include "llvm/InterfaceStub/IFSStub.h" | ||
| #include "llvm/Support/Error.h" | ||
| #include "llvm/Support/LineIterator.h" | ||
| #include "llvm/Support/YAMLTraits.h" | ||
|
|
||
| using namespace llvm; | ||
| using namespace llvm::ifs; | ||
|
|
||
| LLVM_YAML_IS_SEQUENCE_VECTOR(IFSSymbol) | ||
|
|
||
| namespace llvm { | ||
| namespace yaml { | ||
|
|
||
| /// YAML traits for ELFSymbolType. | ||
| template <> struct ScalarEnumerationTraits<IFSSymbolType> { | ||
| static void enumeration(IO &IO, IFSSymbolType &SymbolType) { | ||
| IO.enumCase(SymbolType, "NoType", IFSSymbolType::NoType); | ||
| IO.enumCase(SymbolType, "Func", IFSSymbolType::Func); | ||
| IO.enumCase(SymbolType, "Object", IFSSymbolType::Object); | ||
| IO.enumCase(SymbolType, "TLS", IFSSymbolType::TLS); | ||
| IO.enumCase(SymbolType, "Unknown", IFSSymbolType::Unknown); | ||
| // Treat other symbol types as noise, and map to Unknown. | ||
| if (!IO.outputting() && IO.matchEnumFallback()) | ||
| SymbolType = IFSSymbolType::Unknown; | ||
| } | ||
| }; | ||
|
|
||
| template <> struct ScalarTraits<IFSEndiannessType> { | ||
| static void output(const IFSEndiannessType &Value, void *, | ||
| llvm::raw_ostream &Out) { | ||
| switch (Value) { | ||
| case IFSEndiannessType::Big: | ||
| Out << "big"; | ||
| break; | ||
| case IFSEndiannessType::Little: | ||
| Out << "little"; | ||
| break; | ||
| default: | ||
| llvm_unreachable("Unsupported endianness"); | ||
| } | ||
| } | ||
|
|
||
| static StringRef input(StringRef Scalar, void *, IFSEndiannessType &Value) { | ||
| Value = StringSwitch<IFSEndiannessType>(Scalar) | ||
| .Case("big", IFSEndiannessType::Big) | ||
| .Case("little", IFSEndiannessType::Little) | ||
| .Default(IFSEndiannessType::Unknown); | ||
| if (Value == IFSEndiannessType::Unknown) { | ||
| return "Unsupported endianness"; | ||
| } | ||
| return StringRef(); | ||
| } | ||
|
|
||
| static QuotingType mustQuote(StringRef) { return QuotingType::None; } | ||
| }; | ||
|
|
||
| template <> struct ScalarTraits<IFSBitWidthType> { | ||
| static void output(const IFSBitWidthType &Value, void *, | ||
| llvm::raw_ostream &Out) { | ||
| switch (Value) { | ||
| case IFSBitWidthType::IFS32: | ||
| Out << "32"; | ||
| break; | ||
| case IFSBitWidthType::IFS64: | ||
| Out << "64"; | ||
| break; | ||
| default: | ||
| llvm_unreachable("Unsupported bit width"); | ||
| } | ||
| } | ||
|
|
||
| static StringRef input(StringRef Scalar, void *, IFSBitWidthType &Value) { | ||
| Value = StringSwitch<IFSBitWidthType>(Scalar) | ||
| .Case("32", IFSBitWidthType::IFS32) | ||
| .Case("64", IFSBitWidthType::IFS64) | ||
| .Default(IFSBitWidthType::Unknown); | ||
| if (Value == IFSBitWidthType::Unknown) { | ||
| return "Unsupported bit width"; | ||
| } | ||
| return StringRef(); | ||
| } | ||
|
|
||
| static QuotingType mustQuote(StringRef) { return QuotingType::None; } | ||
| }; | ||
|
|
||
| template <> struct MappingTraits<IFSTarget> { | ||
| static void mapping(IO &IO, IFSTarget &Target) { | ||
| IO.mapOptional("ObjectFormat", Target.ObjectFormat); | ||
| IO.mapOptional("Arch", Target.ArchString); | ||
| IO.mapOptional("Endianness", Target.Endianness); | ||
| IO.mapOptional("BitWidth", Target.BitWidth); | ||
| } | ||
|
|
||
| // Compacts symbol information into a single line. | ||
| static const bool flow = true; // NOLINT(readability-identifier-naming) | ||
| }; | ||
|
|
||
| /// YAML traits for ELFSymbol. | ||
| template <> struct MappingTraits<IFSSymbol> { | ||
| static void mapping(IO &IO, IFSSymbol &Symbol) { | ||
| IO.mapRequired("Name", Symbol.Name); | ||
| IO.mapRequired("Type", Symbol.Type); | ||
| // The need for symbol size depends on the symbol type. | ||
| if (Symbol.Type == IFSSymbolType::NoType) { | ||
| IO.mapOptional("Size", Symbol.Size, (uint64_t)0); | ||
| } else if (Symbol.Type == IFSSymbolType::Func) { | ||
| Symbol.Size = 0; | ||
| } else { | ||
| IO.mapRequired("Size", Symbol.Size); | ||
| } | ||
| IO.mapOptional("Undefined", Symbol.Undefined, false); | ||
| IO.mapOptional("Weak", Symbol.Weak, false); | ||
| IO.mapOptional("Warning", Symbol.Warning); | ||
| } | ||
|
|
||
| // Compacts symbol information into a single line. | ||
| static const bool flow = true; // NOLINT(readability-identifier-naming) | ||
| }; | ||
|
|
||
| /// YAML traits for ELFStub objects. | ||
| template <> struct MappingTraits<IFSStub> { | ||
| static void mapping(IO &IO, IFSStub &Stub) { | ||
| if (!IO.mapTag("!ifs-v1", true)) | ||
| IO.setError("Not a .tbe YAML file."); | ||
| IO.mapRequired("IfsVersion", Stub.IfsVersion); | ||
| IO.mapOptional("SoName", Stub.SoName); | ||
| IO.mapOptional("Target", Stub.Target); | ||
| IO.mapOptional("NeededLibs", Stub.NeededLibs); | ||
| IO.mapRequired("Symbols", Stub.Symbols); | ||
| } | ||
| }; | ||
|
|
||
| /// YAML traits for ELFStubTriple objects. | ||
| template <> struct MappingTraits<IFSStubTriple> { | ||
| static void mapping(IO &IO, IFSStubTriple &Stub) { | ||
| if (!IO.mapTag("!ifs-v1", true)) | ||
| IO.setError("Not a .tbe YAML file."); | ||
| IO.mapRequired("IfsVersion", Stub.IfsVersion); | ||
| IO.mapOptional("SoName", Stub.SoName); | ||
| IO.mapOptional("Target", Stub.Target.Triple); | ||
| IO.mapOptional("NeededLibs", Stub.NeededLibs); | ||
| IO.mapRequired("Symbols", Stub.Symbols); | ||
| } | ||
| }; | ||
| } // end namespace yaml | ||
| } // end namespace llvm | ||
|
|
||
| /// Attempt to determine if a Text stub uses target triple. | ||
| bool usesTriple(StringRef Buf) { | ||
| for (line_iterator I(MemoryBufferRef(Buf, "ELFStub")); !I.is_at_eof(); ++I) { | ||
| StringRef Line = (*I).trim(); | ||
| if (Line.startswith("Target:")) { | ||
| if (Line == "Target:" || (Line.find("{") != Line.npos)) { | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| Expected<std::unique_ptr<IFSStub>> ifs::readIFSFromBuffer(StringRef Buf) { | ||
| yaml::Input YamlIn(Buf); | ||
| std::unique_ptr<IFSStubTriple> Stub(new IFSStubTriple()); | ||
| if (usesTriple(Buf)) { | ||
| YamlIn >> *Stub; | ||
| } else { | ||
| YamlIn >> *static_cast<IFSStub *>(Stub.get()); | ||
| } | ||
| if (std::error_code Err = YamlIn.error()) { | ||
| return createStringError(Err, "YAML failed reading as IFS"); | ||
| } | ||
|
|
||
| if (Stub->IfsVersion > IFSVersionCurrent) | ||
| return make_error<StringError>( | ||
| "IFS version " + Stub->IfsVersion.getAsString() + " is unsupported.", | ||
| std::make_error_code(std::errc::invalid_argument)); | ||
| if (Stub->Target.ArchString) { | ||
| Stub->Target.Arch = | ||
| ELF::convertArchNameToEMachine(Stub->Target.ArchString.getValue()); | ||
| } | ||
| return std::move(Stub); | ||
| } | ||
|
|
||
| Error ifs::writeIFSToOutputStream(raw_ostream &OS, const IFSStub &Stub) { | ||
| yaml::Output YamlOut(OS, NULL, /*WrapColumn =*/0); | ||
| std::unique_ptr<IFSStubTriple> CopyStub(new IFSStubTriple(Stub)); | ||
| if (Stub.Target.Arch) { | ||
| CopyStub->Target.ArchString = std::string( | ||
| ELF::convertEMachineToArchName(Stub.Target.Arch.getValue())); | ||
| } | ||
| IFSTarget Target = Stub.Target; | ||
|
|
||
| if (CopyStub->Target.Triple || | ||
| (!CopyStub->Target.ArchString && !CopyStub->Target.Endianness && | ||
| !CopyStub->Target.BitWidth)) | ||
| YamlOut << *CopyStub; | ||
| else | ||
| YamlOut << *static_cast<IFSStub *>(CopyStub.get()); | ||
| return Error::success(); | ||
| } | ||
|
|
||
| Error ifs::overrideIFSTarget(IFSStub &Stub, Optional<IFSArch> OverrideArch, | ||
| Optional<IFSEndiannessType> OverrideEndianness, | ||
| Optional<IFSBitWidthType> OverrideBitWidth, | ||
| Optional<std::string> OverrideTriple) { | ||
| std::error_code OverrideEC(1, std::generic_category()); | ||
| if (OverrideArch) { | ||
| if (Stub.Target.Arch && | ||
| Stub.Target.Arch.getValue() != OverrideArch.getValue()) { | ||
| return make_error<StringError>( | ||
| "Supplied Arch conflicts with the text stub", OverrideEC); | ||
| } | ||
| Stub.Target.Arch = OverrideArch.getValue(); | ||
| } | ||
| if (OverrideEndianness) { | ||
| if (Stub.Target.Endianness && | ||
| Stub.Target.Endianness.getValue() != OverrideEndianness.getValue()) { | ||
| return make_error<StringError>( | ||
| "Supplied Endianness conflicts with the text stub", OverrideEC); | ||
| } | ||
| Stub.Target.Endianness = OverrideEndianness.getValue(); | ||
| } | ||
| if (OverrideBitWidth) { | ||
| if (Stub.Target.BitWidth && | ||
| Stub.Target.BitWidth.getValue() != OverrideBitWidth.getValue()) { | ||
| return make_error<StringError>( | ||
| "Supplied BitWidth conflicts with the text stub", OverrideEC); | ||
| } | ||
| Stub.Target.BitWidth = OverrideBitWidth.getValue(); | ||
| } | ||
| if (OverrideTriple) { | ||
| if (Stub.Target.Triple && | ||
| Stub.Target.Triple.getValue() != OverrideTriple.getValue()) { | ||
| return make_error<StringError>( | ||
| "Supplied Triple conflicts with the text stub", OverrideEC); | ||
| } | ||
| Stub.Target.Triple = OverrideTriple.getValue(); | ||
| } | ||
| return Error::success(); | ||
| } | ||
|
|
||
| Error ifs::validateIFSTarget(IFSStub &Stub, bool ParseTriple) { | ||
| std::error_code ValidationEC(1, std::generic_category()); | ||
| if (Stub.Target.Triple) { | ||
| if (Stub.Target.Arch || Stub.Target.BitWidth || Stub.Target.Endianness || | ||
| Stub.Target.ObjectFormat) { | ||
| return make_error<StringError>( | ||
| "Target triple cannot be used simultaneously with ELF target format", | ||
| ValidationEC); | ||
| } | ||
| if (ParseTriple) { | ||
| IFSTarget TargetFromTriple = parseTriple(Stub.Target.Triple.getValue()); | ||
| Stub.Target.Arch = TargetFromTriple.Arch; | ||
| Stub.Target.BitWidth = TargetFromTriple.BitWidth; | ||
| Stub.Target.Endianness = TargetFromTriple.Endianness; | ||
| } | ||
| return Error::success(); | ||
| } | ||
| if (!Stub.Target.Arch || !Stub.Target.BitWidth || !Stub.Target.Endianness) { | ||
| // TODO: unify the error message. | ||
| if (!Stub.Target.Arch) { | ||
| return make_error<StringError>("Arch is not defined in the text stub", | ||
| ValidationEC); | ||
| } | ||
| if (!Stub.Target.BitWidth) { | ||
| return make_error<StringError>("BitWidth is not defined in the text stub", | ||
| ValidationEC); | ||
| } | ||
| if (!Stub.Target.Endianness) { | ||
| return make_error<StringError>( | ||
| "Endianness is not defined in the text stub", ValidationEC); | ||
| } | ||
| } | ||
| return Error::success(); | ||
| } | ||
|
|
||
| IFSTarget ifs::parseTriple(StringRef TripleStr) { | ||
| Triple IFSTriple(TripleStr); | ||
| IFSTarget RetTarget; | ||
| // TODO: Implement a Triple Arch enum to e_machine map. | ||
| switch (IFSTriple.getArch()) { | ||
| case Triple::ArchType::aarch64: | ||
| RetTarget.Arch = (IFSArch)ELF::EM_AARCH64; | ||
| break; | ||
| case Triple::ArchType::x86_64: | ||
| RetTarget.Arch = (IFSArch)ELF::EM_X86_64; | ||
| break; | ||
| default: | ||
| RetTarget.Arch = (IFSArch)ELF::EM_NONE; | ||
| } | ||
| RetTarget.Endianness = IFSTriple.isLittleEndian() ? IFSEndiannessType::Little | ||
| : IFSEndiannessType::Big; | ||
| RetTarget.BitWidth = | ||
| IFSTriple.isArch64Bit() ? IFSBitWidthType::IFS64 : IFSBitWidthType::IFS32; | ||
| return RetTarget; | ||
| } | ||
|
|
||
| void ifs::stripIFSTarget(IFSStub &Stub, bool StripTriple, bool StripArch, | ||
| bool StripEndianness, bool StripBitWidth) { | ||
| if (StripTriple || StripArch) { | ||
| Stub.Target.Arch.reset(); | ||
| Stub.Target.ArchString.reset(); | ||
| } | ||
| if (StripTriple || StripEndianness) { | ||
| Stub.Target.Endianness.reset(); | ||
| } | ||
| if (StripTriple || StripBitWidth) { | ||
| Stub.Target.BitWidth.reset(); | ||
| } | ||
| if (StripTriple) { | ||
| Stub.Target.Triple.reset(); | ||
| } | ||
| if (!Stub.Target.Arch && !Stub.Target.BitWidth && !Stub.Target.Endianness) { | ||
| Stub.Target.ObjectFormat.reset(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| //===- IFSStub.cpp --------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===-----------------------------------------------------------------------===/ | ||
|
|
||
| #include "llvm/InterfaceStub/IFSStub.h" | ||
| #include "llvm/BinaryFormat/ELF.h" | ||
| #include "llvm/Support/Error.h" | ||
|
|
||
| using namespace llvm; | ||
| using namespace llvm::ifs; | ||
|
|
||
| IFSStub::IFSStub(IFSStub const &Stub) { | ||
| IfsVersion = Stub.IfsVersion; | ||
| Target = Stub.Target; | ||
| SoName = Stub.SoName; | ||
| NeededLibs = Stub.NeededLibs; | ||
| Symbols = Stub.Symbols; | ||
| } | ||
|
|
||
| IFSStub::IFSStub(IFSStub &&Stub) { | ||
| IfsVersion = std::move(Stub.IfsVersion); | ||
| Target = std::move(Stub.Target); | ||
| SoName = std::move(Stub.SoName); | ||
| NeededLibs = std::move(Stub.NeededLibs); | ||
| Symbols = std::move(Stub.Symbols); | ||
| } | ||
|
|
||
| IFSStubTriple::IFSStubTriple(IFSStubTriple const &Stub) { | ||
| IfsVersion = Stub.IfsVersion; | ||
| Target = Stub.Target; | ||
| SoName = Stub.SoName; | ||
| NeededLibs = Stub.NeededLibs; | ||
| Symbols = Stub.Symbols; | ||
| } | ||
|
|
||
| IFSStubTriple::IFSStubTriple(IFSStub const &Stub) { | ||
| IfsVersion = Stub.IfsVersion; | ||
| Target = Stub.Target; | ||
| SoName = Stub.SoName; | ||
| NeededLibs = Stub.NeededLibs; | ||
| Symbols = Stub.Symbols; | ||
| } | ||
|
|
||
| IFSStubTriple::IFSStubTriple(IFSStubTriple &&Stub) { | ||
| IfsVersion = std::move(Stub.IfsVersion); | ||
| Target = std::move(Stub.Target); | ||
| SoName = std::move(Stub.SoName); | ||
| NeededLibs = std::move(Stub.NeededLibs); | ||
| Symbols = std::move(Stub.Symbols); | ||
| } | ||
|
|
||
| bool IFSTarget::empty() { | ||
| return !Triple && !ObjectFormat && !Arch && !ArchString && !Endianness && | ||
| !BitWidth; | ||
| } | ||
|
|
||
| uint8_t ifs::convertIFSBitWidthToELF(IFSBitWidthType BitWidth) { | ||
| switch (BitWidth) { | ||
| case IFSBitWidthType::IFS32: | ||
| return ELF::ELFCLASS32; | ||
| case IFSBitWidthType::IFS64: | ||
| return ELF::ELFCLASS64; | ||
| case IFSBitWidthType::Unknown: | ||
| llvm_unreachable("unkown bitwidth"); | ||
| } | ||
| } | ||
|
|
||
| uint8_t ifs::convertIFSEndiannessToELF(IFSEndiannessType Endianness) { | ||
| switch (Endianness) { | ||
| case IFSEndiannessType::Little: | ||
| return ELF::ELFDATA2LSB; | ||
| case IFSEndiannessType::Big: | ||
| return ELF::ELFDATA2MSB; | ||
| case IFSEndiannessType::Unknown: | ||
| llvm_unreachable("unknown endianness"); | ||
| } | ||
| } | ||
|
|
||
| uint8_t ifs::convertIFSSymbolTypeToELF(IFSSymbolType SymbolType) { | ||
| switch (SymbolType) { | ||
| case IFSSymbolType::Object: | ||
| return ELF::STT_OBJECT; | ||
| case IFSSymbolType::Func: | ||
| return ELF::STT_FUNC; | ||
| case IFSSymbolType::TLS: | ||
| return ELF::STT_TLS; | ||
| case IFSSymbolType::NoType: | ||
| default: | ||
| return ELF::STT_NOTYPE; | ||
| } | ||
| } | ||
|
|
||
| IFSBitWidthType ifs::convertELFBitWidthToIFS(uint8_t BitWidth) { | ||
| switch (BitWidth) { | ||
| case ELF::ELFCLASS32: | ||
| return IFSBitWidthType::IFS32; | ||
| case ELF::ELFCLASS64: | ||
| return IFSBitWidthType::IFS64; | ||
| default: | ||
| return IFSBitWidthType::Unknown; | ||
| } | ||
| } | ||
|
|
||
| IFSEndiannessType ifs::convertELFEndiannessToIFS(uint8_t Endianness) { | ||
| switch (Endianness) { | ||
| case ELF::ELFDATA2LSB: | ||
| return IFSEndiannessType::Little; | ||
| case ELF::ELFDATA2MSB: | ||
| return IFSEndiannessType::Big; | ||
| default: | ||
| return IFSEndiannessType::Unknown; | ||
| } | ||
| } | ||
|
|
||
| IFSSymbolType ifs::convertELFSymbolTypeToIFS(uint8_t SymbolType) { | ||
| SymbolType = SymbolType & 0xf; | ||
| switch (SymbolType) { | ||
| case ELF::STT_OBJECT: | ||
| return IFSSymbolType::Object; | ||
| case ELF::STT_FUNC: | ||
| return IFSSymbolType::Func; | ||
| case ELF::STT_TLS: | ||
| return IFSSymbolType::TLS; | ||
| case ELF::STT_NOTYPE: | ||
| return IFSSymbolType::NoType; | ||
| default: | ||
| return IFSSymbolType::Unknown; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -77,7 +77,6 @@ set(LLVM_TEST_DEPENDS | |
| dsymutil | ||
| llvm-dwarfdump | ||
| llvm-dwp | ||
| llvm-exegesis | ||
| llvm-extract | ||
| llvm-gsymutil | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,7 @@ | ||
| # NOTE: Used by weak-mismatch.ifs | ||
| --- !ifs-v1 | ||
| IfsVersion: 3.0 | ||
| Target: x86_64-unknown-linux-gnu | ||
| Symbols: | ||
| - { Name: foobar, Type: Object, Size: 2 } | ||
| ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,7 @@ | ||
| # NOTE: Used by weak-mismatch.ifs | ||
| --- !ifs-v1 | ||
| IfsVersion: 3.0 | ||
| Target: x86_64-unknown-linux-gnu | ||
| Symbols: | ||
| - { Name: foobar, Type: Func } | ||
| ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,143 @@ | ||
| # RUN: yaml2obj --docnum=1 %s -o %t | ||
| # RUN: llvm-ifs --input-format=ELF --output-format=IFS --output=- %t | FileCheck %s -DTARGET="{ ObjectFormat: ELF, Arch: x86_64, Endianness: little, BitWidth: 64 }" | ||
| # RUN: llvm-ifs --input-format=ELF --output-format=IFS --output=- --hint-ifs-target="x86_64-linux-gnu" %t | FileCheck %s -DTARGET="x86_64-linux-gnu" | ||
|
|
||
| --- !ELF | ||
| FileHeader: | ||
| Class: ELFCLASS64 | ||
| 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 | ||
|
|
||
| # CHECK: --- !ifs-v1 | ||
| # CHECK-NEXT: IfsVersion: {{[1-9]\d*\.(0|([1-9]\d*))}} | ||
| # 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-ifs --input-format=ELF --output-format=IFS --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-ifs --input-format=ELF --output-format=IFS --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-ifs --input-format=ELF --output-format=IFS --output=%t.tbe --hint-ifs-target="x86_64-unknown-linux-gnu" %t 2>&1 | FileCheck %s -DMSG="bit width" --check-prefix=HINTERR |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| # RUN: llvm-ifs --input-format=ELF --output-format=IFS --output=- %p/Inputs/gnu_hash.so | FileCheck %s | ||
|
|
||
| # CHECK: --- !ifs-v1 | ||
| # CHECK-NEXT: IfsVersion: 3.0 | ||
| # CHECK-NEXT: SoName: libsomething.so | ||
| # 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: - { Name: AGlobalInteger, Type: Object, Size: 4 } | ||
| # CHECK-NEXT: - { Name: AThreadLocalLongInteger, Type: TLS, Size: 8 } | ||
| # 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: _Z11rotateArrayPii, Type: Func } | ||
| # CHECK-NEXT: - { Name: __cxa_finalize, Type: Func, Undefined: true, Weak: true } | ||
| # CHECK-NEXT: - { Name: __gmon_start__, Type: NoType, Undefined: true, Weak: true } | ||
| # CHECK-NEXT: - { Name: __tls_get_addr, Type: Func, Undefined: true } | ||
| # CHECK-NEXT: - { Name: _fini, Type: Func } | ||
| # CHECK-NEXT: - { Name: _init, Type: Func } | ||
| # CHECK-NEXT: ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| # RUN: llvm-ifs --input-format=ELF --output-format=IFS --output=- %p/Inputs/sysv_hash.so | FileCheck %s | ||
|
|
||
| # CHECK: --- !ifs-v1 | ||
| # CHECK-NEXT: IfsVersion: 3.0 | ||
| # CHECK-NEXT: SoName: libsomething.so | ||
| # 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: - { Name: AGlobalInteger, Type: Object, Size: 4 } | ||
| # CHECK-NEXT: - { Name: AThreadLocalLongInteger, Type: TLS, Size: 8 } | ||
| # 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: _Z11rotateArrayPii, Type: Func } | ||
| # CHECK-NEXT: - { Name: __cxa_finalize, Type: Func, Undefined: true, Weak: true } | ||
| # CHECK-NEXT: - { Name: __gmon_start__, Type: NoType, Undefined: true, Weak: true } | ||
| # CHECK-NEXT: - { Name: __tls_get_addr, Type: Func, Undefined: true } | ||
| # CHECK-NEXT: - { Name: _fini, Type: Func } | ||
| # CHECK-NEXT: - { Name: _init, Type: Func } | ||
| # CHECK-NEXT: ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,12 @@ | ||
| # RUN: not llvm-ifs --input-format=IFS --output-format=IFS -o - %s %S/object.ifs 2>&1 | \ | ||
| # RUN: FileCheck %s --check-prefixes=CHECK-IFS | ||
|
|
||
| # CHECK-IFS: error: Interface Stub: Target Mismatch. | ||
| # CHECK-IFS-NEXT: Filenames: | ||
|
|
||
| --- !ifs-v1 | ||
| IfsVersion: 3.0 | ||
| Target: mips-unknown-linux | ||
| Symbols: | ||
| - { Name: a, Type: Func } | ||
| ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,15 @@ | ||
| # RUN: not llvm-ifs --input-format=IFS --output-format=IFS -o - %s %S/object.ifs 2>&1 | \ | ||
| # RUN: FileCheck %s --check-prefixes=CHECK-IFS | ||
|
|
||
| # RUN: not llvm-ifs --input-format=IFS --output-format=IFS -o - %s 2>&1 | \ | ||
| # RUN: FileCheck %s --check-prefixes=CHECK-IFS2 | ||
|
|
||
| # CHECK-IFS: error: Interface Stub: IfsVersion Mismatch. | ||
| # CHECK-IFS2: error: Interface Stub: Bad IfsVersion: 0.0, llvm-ifs supported version: 3.0. | ||
|
|
||
| --- !ifs-v1 | ||
| IfsVersion: 0.0 | ||
| Target: x86_64-unknown-linux-gnu | ||
| Symbols: | ||
| - { Name: a, Type: Func } | ||
| ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,12 @@ | ||
| # RUN: llvm-ifs --input-format=IFS --output-format=IFS -o - %s %S/func.ifs 2>&1 | \ | ||
| # RUN: FileCheck %s --check-prefixes=CHECK-IFS | ||
|
|
||
| # CHECK-IFS: Symbols: | ||
| # CHECK-IFS-NEXT: - { Name: a, Type: Func, Weak: true } | ||
|
|
||
| --- !ifs-v1 | ||
| IfsVersion: 3.0 | ||
| Target: x86_64-unknown-linux-gnu | ||
| Symbols: | ||
| - { Name: a, Type: Func, Weak: true } | ||
| ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,25 +1,20 @@ | ||
| # RUN: llvm-ifs --input-format=IFS --output-format=IFS -o - %s | FileCheck --check-prefixes=CHECK-DEFAULT %s | ||
| # RUN: llvm-ifs --input-format=IFS --output-format=IFS -o - %S/weak.ifs %s | FileCheck --check-prefixes=CHECK-MERGE %s | ||
|
|
||
| # CHECK-DEFAULT: --- !ifs-v1 | ||
| # CHECK-DEFAULT-NEXT: IfsVersion: 3.0 | ||
| # CHECK-DEFAULT-NEXT: Symbols: [] | ||
| # CHECK-DEFAULT-NEXT: ... | ||
|
|
||
| # CHECK-MERGE: --- !ifs-v1 | ||
| # CHECK-MERGE-NEXT: IfsVersion: 3.0 | ||
| # CHECK-MERGE-NEXT: Target: x86_64-unknown-linux-gnu | ||
| # CHECK-MERGE-NEXT: Symbols: | ||
| # CHECK-MERGE-DAG: - { Name: _Z8weakFuncv, Type: Func, Weak: true } | ||
| # CHECK-MERGE-DAG: - { Name: _Z10strongFuncv, Type: Func } | ||
| # CHECK-MERGE: ... | ||
|
|
||
| --- !ifs-v1 | ||
| IfsVersion: 3.0 | ||
| Symbols: [] | ||
| ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,15 +1,13 @@ | ||
| # RUN: llvm-ifs --input-format=IFS --output-format=IFS -o - %s | FileCheck %s | ||
|
|
||
| # CHECK: --- !ifs-v1 | ||
| # CHECK-NEXT: IfsVersion: 3.0 | ||
| # CHECK-NEXT: Target: x86_64-unknown-linux-gnu | ||
| # CHECK-NEXT: Symbols: [] | ||
| # CHECK: ... | ||
|
|
||
| --- !ifs-v1 | ||
| IfsVersion: 3.0 | ||
| Target: x86_64-unknown-linux-gnu | ||
| Symbols: [] | ||
| ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,15 +1,13 @@ | ||
| # RUN: llvm-ifs --input-format=IFS --output-format=IFS -o - %s | FileCheck %s | ||
|
|
||
| # CHECK: --- !ifs-v1 | ||
| # CHECK-NEXT: IfsVersion: 3.0 | ||
| # CHECK-NEXT: Target: x86_64-unknown-linux-gnu | ||
| # CHECK-NEXT: Symbols: [] | ||
| # CHECK: ... | ||
|
|
||
| --- !ifs-v1 | ||
| IfsVersion: 3.0 | ||
| Target: x86_64-unknown-linux-gnu | ||
| Symbols: | ||
| ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| # RUN: not llvm-ifs --output-format=IFS --output=%t.tbe %s.NotAFileInTestingDir 2>&1 | FileCheck %s | ||
|
|
||
| This file will not be read. An invalid file path is fed to llvm-ifs. | ||
|
|
||
| # CHECK: error: Could not open `{{.*}}.NotAFileInTestingDir` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| ## Test failing to write output file on windows platform. | ||
|
|
||
| # REQUIRES: system-windows | ||
| # RUN: touch %t.TestFile | ||
| # RUN: chmod 400 %t.TestFile | ||
| # RUN: not llvm-ifs --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 | ||
|
|
||
| --- !ifs-v1 | ||
| IfsVersion: 3.0 | ||
| Target: { ObjectFormat: ELF, Arch: AArch64, Endianness: little, BitWidth: 64 } | ||
| Symbols: [] | ||
| ... | ||
|
|
||
| # ERR: error: [[MSG]] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| # RUN: llvm-ifs --output-format=IFS --output=- %s | FileCheck %s | ||
|
|
||
| --- !ifs-v1 | ||
| IfsVersion: 3.0 | ||
| 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: --- !ifs-v1 | ||
| # CHECK-NEXT: IfsVersion: 3.0 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| # RUN: llvm-ifs --output-format=IFS --output=- %s | FileCheck %s | ||
|
|
||
| --- !ifs-v1 | ||
| SoName: somelib.so | ||
| IfsVersion: 3.0 | ||
| Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, 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: --- !ifs-v1 | ||
| # CHECK-NEXT: IfsVersion: {{[1-9]\d*\.(0|([1-9]\d*))}} | ||
| # CHECK-NEXT: SoName: somelib.so | ||
| # CHECK-NEXT: Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, BitWidth: 64 } | ||
| # CHECK-NEXT: Symbols: | ||
| # CHECK-NEXT: - { Name: bar, Type: Object, Size: 42 } | ||
| # CHECK-NEXT: - { Name: baz, Type: Object, Size: 8 } | ||
| # CHECK-NEXT: - { Name: foo, Type: Func } | ||
| # CHECK-NEXT: - { Name: nor, Type: Func, Undefined: true } | ||
| # CHECK-NEXT: - { Name: not, Type: Object, Size: 128, Undefined: true } | ||
| # CHECK-NEXT: ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| ## Test running llvm-ifs without specifying a valid target. | ||
|
|
||
| # RUN: not llvm-ifs --output=%t %s 2>&1 | FileCheck %s --check-prefix=MISSING | ||
| # RUN: not llvm-ifs --output-format=nope --output=%t %s 2>&1 | FileCheck %s --check-prefix=INVALID | ||
|
|
||
| --- !ifs-v1 | ||
| SoName: somelib.so | ||
| IfsVersion: 3.0 | ||
| Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, BitWidth: 64 } | ||
| Symbols: [] | ||
| ... | ||
|
|
||
| # MISSING: {{llvm-ifs(\.exe)?}}: for the --output-format option: must be specified at least once! | ||
|
|
||
| # INVALID: {{llvm-ifs(\.exe)?}}: for the --output-format option: Cannot find option named 'nope'! |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| ## Test writing unchanged content to TBE file with --write-if-changed flag. | ||
|
|
||
| # RUN: llvm-ifs --input-format=ELF --output-format=IFS --output=%t %p/Inputs/gnu_hash.so | ||
| # RUN: env TZ=GMT touch -m -t 197001010000 %t | ||
| # RUN: llvm-ifs --input-format=ELF --output-format=IFS --output=%t --write-if-changed %p/Inputs/gnu_hash.so | ||
| # RUN: env TZ=GMT ls -l %t | FileCheck %s | ||
|
|
||
| # CHECK: {{[[:space:]]1970}} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| ## Test writing unchanged content to ELF Stub file with --write-if-changed flag. | ||
|
|
||
| # RUN: llvm-ifs --output-format=ELF --output=%t %s | ||
| # RUN: env TZ=GMT touch -m -t 197001010000 %t | ||
| # RUN: llvm-ifs --output-format=ELF --output=%t --write-if-changed %s | ||
| # RUN: env TZ=GMT ls -l %t | FileCheck %s | ||
|
|
||
| --- !ifs-v1 | ||
| IfsVersion: 3.0 | ||
| Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, BitWidth: 64 } | ||
| NeededLibs: | ||
| - libc.so.6 | ||
| Symbols: | ||
| - { Name: bar, Type: Object, Size: 42 } | ||
| - { Name: baz, Type: TLS, Size: 3 } | ||
| - { Name: plus, Type: Func } | ||
| ... | ||
|
|
||
| # CHECK: {{[[:space:]]1970}} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| # RUN: not llvm-ifs --input-format=ELF --output-format=IFS --output=%t %s 2>&1 | FileCheck %s | ||
|
|
||
| --- !ifs-v1 | ||
| SoName: somelib.so | ||
| IfsVersion: 3.0 | ||
| Target: { ObjectFormat: ELF, Arch: AArch64, Endianness: little, BitWidth: 64 } | ||
| Symbols: | ||
| - { 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 | ||
| # CHECK: No file readers succeeded reading `{{.*}}read-ifs-as-elf.test` (unsupported/malformed file?) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| # RUN: llvm-ifs --input-format=IFS --output-format=IFS --output=- %s | FileCheck %s | ||
|
|
||
| --- !ifs-v1 | ||
| IfsVersion: 3.0 | ||
| Target: { ObjectFormat: ELF, Arch: AArch64, Endianness: little, BitWidth: 64 } | ||
| Symbols: [] | ||
| ... | ||
|
|
||
| # CHECK: --- !ifs-v1 | ||
| # CHECK-NEXT: IfsVersion: {{[1-9]\d*\.(0|([1-9]\d*))}} | ||
| # CHECK-NEXT: Target: { ObjectFormat: ELF, Arch: AArch64, Endianness: little, BitWidth: 64 } | ||
| # CHECK-NEXT: Symbols: [] | ||
| # CHECK-NEXT: ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| ## Test reading TBE file with bad bit width. | ||
|
|
||
| # RUN: not llvm-ifs --output-format=IFS --output=- %s 2>&1 | FileCheck %s | ||
|
|
||
| --- !ifs-v1 | ||
| SoName: somelib.so | ||
| IfsVersion: 3.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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| ## Test reading TBE file with bad endianness. | ||
|
|
||
| # RUN: not llvm-ifs --output-format=IFS --output=- %s 2>&1 | FileCheck %s | ||
|
|
||
| --- !ifs-v1 | ||
| SoName: somelib.so | ||
| IfsVersion: 3.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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| # RUN: not llvm-ifs --output-format=IFS --output=- %s 2>&1| FileCheck %s | ||
|
|
||
| This is just some text that cannot be read by llvm-ifs. | ||
|
|
||
| # CHECK: The file was not recognized as a valid object file | ||
| # CHECK: YAML failed reading as IFS | ||
| # CHECK: No file readers succeeded reading `{{.*}}` (unsupported/malformed file?) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| ## Test writing tbe with stripped target information. | ||
|
|
||
| # RUN: llvm-ifs --input-format=ELF --output-format=IFS --strip-ifs-target --output=- %p/Inputs/sysv_hash.so | FileCheck %s --check-prefix=NOTARGET | ||
| # RUN: llvm-ifs --input-format=ELF --output-format=IFS --strip-ifs-arch --strip-ifs-endianness --strip-ifs-bitwidth --output=- %p/Inputs/sysv_hash.so | FileCheck %s --check-prefix=NOTARGET | ||
| # RUN: llvm-ifs --input-format=ELF --output-format=IFS --strip-ifs-arch --output=- %p/Inputs/sysv_hash.so | FileCheck %s -DELFTARGET="ObjectFormat: ELF, Endianness: little, BitWidth: 64" --check-prefix=CHECK | ||
| # RUN: llvm-ifs --input-format=ELF --output-format=IFS --strip-ifs-endianness --output=- %p/Inputs/sysv_hash.so | FileCheck %s -DELFTARGET="ObjectFormat: ELF, Arch: x86_64, BitWidth: 64" --check-prefix=CHECK | ||
| # RUN: llvm-ifs --input-format=ELF --output-format=IFS --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: IfsVersion: 3.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: IfsVersion: 3.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: |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,17 +1,15 @@ | ||
| # RUN: llvm-ifs --input-format=IFS --output-format=IFS -o - %s %S/strong.ifs | FileCheck %s --check-prefixes=CHECK-IFS | ||
|
|
||
| # CHECK-IFS: --- !ifs-v1 | ||
| # CHECK-IFS-NEXT: IfsVersion: 3.0 | ||
| # CHECK-IFS-NEXT: Target: x86_64-unknown-linux-gnu | ||
| # CHECK-IFS-NEXT: Symbols: | ||
| # CHECK-IFS-DAG: - { Name: _Z8weakFuncv, Type: Func } | ||
| # CHECK-IFS: ... | ||
|
|
||
| --- !ifs-v1 | ||
| IfsVersion: 3.0 | ||
| Target: x86_64-unknown-linux-gnu | ||
| Symbols: | ||
| - { Name: _Z8weakFuncv, Type: Func } | ||
| ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,8 @@ | ||
| # RUN: llvm-ifs --input-format=IFS --output-format=IFS -o - %s %S/object.ifs | ||
|
|
||
| --- !ifs-v1 | ||
| IfsVersion: 3.0 | ||
| Target: x86_64-unknown-linux-gnu | ||
| Symbols: | ||
| - { Name: a, Type: Func } | ||
| ... |