mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[llvm-tapi] initial commit, supports ELF text stubs
http://lists.llvm.org/pipermail/llvm-dev/2018-September/126472.html TextAPI is a library and accompanying tool that allows conversion between binary shared object stubs and textual counterparts. The motivations and uses cases for this are explained thoroughly in the llvm-dev proposal [1]. This initial commit proposes a potential structure for the TAPI library, also including support for reading/writing text-based ELF stubs (.tbe) in addition to preliminary support for reading binary ELF files. The goal for this patch is to ensure the project architecture appropriately welcomes integration of Mach-O stubbing from Apple's TAPI [2]. Added: - TextAPI library - .tbe read support - .tbe write (to raw_ostream) support [1] http://lists.llvm.org/pipermail/llvm-dev/2018-September/126472.html [2] https://github.com/ributzka/tapi Differential Revision: https://reviews.llvm.org/D53051 llvm-svn: 348170
This commit is contained in:
parent
7d1c45a131
commit
29999e01da
69
include/llvm/TextAPI/ELF/ELFStub.h
Normal file
69
include/llvm/TextAPI/ELF/ELFStub.h
Normal file
@ -0,0 +1,69 @@
|
||||
//===- ELFStub.h ------------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===-----------------------------------------------------------------------===/
|
||||
///
|
||||
/// \file
|
||||
/// This file defines an internal representation of an ELF stub.
|
||||
///
|
||||
//===-----------------------------------------------------------------------===/
|
||||
|
||||
#ifndef LLVM_TEXTAPI_ELF_ELFSTUB_H
|
||||
#define LLVM_TEXTAPI_ELF_ELFSTUB_H
|
||||
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/Support/VersionTuple.h"
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
namespace llvm {
|
||||
namespace elfabi {
|
||||
|
||||
typedef uint16_t ELFArch;
|
||||
|
||||
enum class ELFSymbolType {
|
||||
NoType = ELF::STT_NOTYPE,
|
||||
Object = ELF::STT_OBJECT,
|
||||
Func = ELF::STT_FUNC,
|
||||
TLS = ELF::STT_TLS,
|
||||
|
||||
// Type information is 4 bits, so 16 is safely out of range.
|
||||
Unknown = 16,
|
||||
};
|
||||
|
||||
struct ELFSymbol {
|
||||
ELFSymbol(std::string SymbolName) : Name(SymbolName) {}
|
||||
std::string Name;
|
||||
uint64_t Size;
|
||||
ELFSymbolType Type;
|
||||
bool Undefined;
|
||||
bool Weak;
|
||||
Optional<std::string> Warning;
|
||||
bool operator<(const ELFSymbol &RHS) const {
|
||||
return Name < RHS.Name;
|
||||
}
|
||||
};
|
||||
|
||||
// A cumulative representation of ELF stubs.
|
||||
// Both textual and binary stubs will read into and write from this object.
|
||||
class ELFStub {
|
||||
// TODO: Add support for symbol versioning.
|
||||
public:
|
||||
VersionTuple TbeVersion;
|
||||
std::string SoName;
|
||||
ELFArch Arch;
|
||||
std::vector<std::string> NeededLibs;
|
||||
std::set<ELFSymbol> Symbols;
|
||||
|
||||
ELFStub() {}
|
||||
ELFStub(const ELFStub &Stub);
|
||||
ELFStub(ELFStub &&Stub);
|
||||
};
|
||||
} // end namespace elfabi
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_TEXTAPI_ELF_ELFSTUB_H
|
46
include/llvm/TextAPI/ELF/TBEHandler.h
Normal file
46
include/llvm/TextAPI/ELF/TBEHandler.h
Normal file
@ -0,0 +1,46 @@
|
||||
//===- TBEHandler.h ---------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===-----------------------------------------------------------------------===/
|
||||
///
|
||||
/// \file
|
||||
/// This file declares an interface for reading and writing .tbe (text-based
|
||||
/// ELF) files.
|
||||
///
|
||||
//===-----------------------------------------------------------------------===/
|
||||
|
||||
#ifndef LLVM_TEXTAPI_ELF_TBEHANDLER_H
|
||||
#define LLVM_TEXTAPI_ELF_TBEHANDLER_H
|
||||
|
||||
#include "llvm/Support/VersionTuple.h"
|
||||
#include <memory>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class raw_ostream;
|
||||
class Error;
|
||||
class StringRef;
|
||||
class VersionTuple;
|
||||
|
||||
namespace elfabi {
|
||||
|
||||
class ELFStub;
|
||||
|
||||
const VersionTuple TBEVersionCurrent(1, 0);
|
||||
|
||||
class TBEHandler {
|
||||
public:
|
||||
/// Attempts to read an ELF interface file from a StringRef buffer.
|
||||
std::unique_ptr<ELFStub> readFile(StringRef Buf);
|
||||
|
||||
/// Attempts to write an ELF interface file to a raw_ostream.
|
||||
Error writeFile(raw_ostream &OS, const ELFStub &Stub);
|
||||
};
|
||||
} // end namespace elfabi
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_TEXTAPI_ELF_TBEHANDLER_H
|
@ -23,6 +23,7 @@ add_subdirectory(AsmParser)
|
||||
add_subdirectory(LineEditor)
|
||||
add_subdirectory(ProfileData)
|
||||
add_subdirectory(Passes)
|
||||
add_subdirectory(TextAPI)
|
||||
add_subdirectory(ToolDrivers)
|
||||
add_subdirectory(XRay)
|
||||
add_subdirectory(Testing)
|
||||
|
@ -40,6 +40,7 @@ subdirectories =
|
||||
ProfileData
|
||||
Support
|
||||
TableGen
|
||||
TextAPI
|
||||
Target
|
||||
Testing
|
||||
ToolDrivers
|
||||
|
7
lib/TextAPI/CMakeLists.txt
Normal file
7
lib/TextAPI/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
add_llvm_library(LLVMTextAPI
|
||||
ELF/ELFStub.cpp
|
||||
ELF/TBEHandler.cpp
|
||||
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
"${LLVM_MAIN_INCLUDE_DIR}/llvm/TextAPI"
|
||||
)
|
29
lib/TextAPI/ELF/ELFStub.cpp
Normal file
29
lib/TextAPI/ELF/ELFStub.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
//===- ELFStub.cpp --------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===-----------------------------------------------------------------------===/
|
||||
|
||||
#include "llvm/TextAPI/ELF/ELFStub.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::elfabi;
|
||||
|
||||
ELFStub::ELFStub(ELFStub const &Stub) {
|
||||
TbeVersion = Stub.TbeVersion;
|
||||
Arch = Stub.Arch;
|
||||
SoName = Stub.SoName;
|
||||
NeededLibs = Stub.NeededLibs;
|
||||
Symbols = Stub.Symbols;
|
||||
}
|
||||
|
||||
ELFStub::ELFStub(ELFStub &&Stub) {
|
||||
TbeVersion = std::move(Stub.TbeVersion);
|
||||
Arch = std::move(Stub.Arch);
|
||||
SoName = std::move(Stub.SoName);
|
||||
NeededLibs = std::move(Stub.NeededLibs);
|
||||
Symbols = std::move(Stub.Symbols);
|
||||
}
|
176
lib/TextAPI/ELF/TBEHandler.cpp
Normal file
176
lib/TextAPI/ELF/TBEHandler.cpp
Normal file
@ -0,0 +1,176 @@
|
||||
//===- TBEHandler.cpp -----------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===-----------------------------------------------------------------------===/
|
||||
|
||||
#include "llvm/TextAPI/ELF/TBEHandler.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/YAMLTraits.h"
|
||||
#include "llvm/TextAPI/ELF/ELFStub.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::elfabi;
|
||||
|
||||
LLVM_YAML_STRONG_TYPEDEF(ELFArch, ELFArchMapper);
|
||||
|
||||
namespace llvm {
|
||||
namespace yaml {
|
||||
|
||||
/// YAML traits for ELFSymbolType.
|
||||
template <> struct ScalarEnumerationTraits<ELFSymbolType> {
|
||||
static void enumeration(IO &IO, ELFSymbolType &SymbolType) {
|
||||
IO.enumCase(SymbolType, "NoType", ELFSymbolType::NoType);
|
||||
IO.enumCase(SymbolType, "Func", ELFSymbolType::Func);
|
||||
IO.enumCase(SymbolType, "Object", ELFSymbolType::Object);
|
||||
IO.enumCase(SymbolType, "TLS", ELFSymbolType::TLS);
|
||||
IO.enumCase(SymbolType, "Unknown", ELFSymbolType::Unknown);
|
||||
// Treat other symbol types as noise, and map to Unknown.
|
||||
if (!IO.outputting() && IO.matchEnumFallback())
|
||||
SymbolType = ELFSymbolType::Unknown;
|
||||
}
|
||||
};
|
||||
|
||||
/// YAML traits for ELFArch.
|
||||
template <> struct ScalarTraits<ELFArchMapper> {
|
||||
static void output(const ELFArchMapper &Value, void *,
|
||||
llvm::raw_ostream &Out) {
|
||||
// Map from integer to architecture string.
|
||||
switch (Value) {
|
||||
case (ELFArch)ELF::EM_X86_64:
|
||||
Out << "x86_64";
|
||||
break;
|
||||
case (ELFArch)ELF::EM_AARCH64:
|
||||
Out << "AArch64";
|
||||
break;
|
||||
case (ELFArch)ELF::EM_NONE:
|
||||
default:
|
||||
Out << "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static StringRef input(StringRef Scalar, void *, ELFArchMapper &Value) {
|
||||
// Map from architecture string to integer.
|
||||
Value = StringSwitch<ELFArch>(Scalar)
|
||||
.Case("x86_64", ELF::EM_X86_64)
|
||||
.Case("AArch64", ELF::EM_AARCH64)
|
||||
.Case("Unknown", ELF::EM_NONE)
|
||||
.Default(ELF::EM_NONE);
|
||||
|
||||
// Returning empty StringRef indicates successful parse.
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
// Don't place quotation marks around architecture value.
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
|
||||
};
|
||||
|
||||
/// YAML traits for TbeVersion.
|
||||
template <> struct ScalarTraits<VersionTuple> {
|
||||
static void output(const VersionTuple &Value, void *,
|
||||
llvm::raw_ostream &Out) {
|
||||
Out << Value.getAsString();
|
||||
}
|
||||
|
||||
static StringRef input(StringRef Scalar, void *, VersionTuple &Value) {
|
||||
if (Value.tryParse(Scalar))
|
||||
return StringRef("Can't parse version: invalid version format.");
|
||||
|
||||
if (Value > TBEVersionCurrent)
|
||||
return StringRef("Unsupported TBE version.");
|
||||
|
||||
// Returning empty StringRef indicates successful parse.
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
// Don't place quotation marks around version value.
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
|
||||
};
|
||||
|
||||
/// YAML traits for ELFSymbol.
|
||||
template <> struct MappingTraits<ELFSymbol> {
|
||||
static void mapping(IO &IO, ELFSymbol &Symbol) {
|
||||
IO.mapRequired("Type", Symbol.Type);
|
||||
// The need for symbol size depends on the symbol type.
|
||||
if (Symbol.Type == ELFSymbolType::NoType) {
|
||||
IO.mapOptional("Size", Symbol.Size, (uint64_t)0);
|
||||
} else if (Symbol.Type == ELFSymbolType::Func) {
|
||||
Symbol.Size = 0;
|
||||
} else {
|
||||
IO.mapRequired("Size", Symbol.Size);
|
||||
}
|
||||
IO.mapOptional("Undefined", Symbol.Undefined, false);
|
||||
IO.mapOptional("Warning", Symbol.Warning);
|
||||
}
|
||||
|
||||
// Compacts symbol information into a single line.
|
||||
static const bool flow = true;
|
||||
};
|
||||
|
||||
/// YAML traits for set of ELFSymbols.
|
||||
template <> struct CustomMappingTraits<std::set<ELFSymbol>> {
|
||||
static void inputOne(IO &IO, StringRef Key, std::set<ELFSymbol> &Set) {
|
||||
ELFSymbol Sym(Key.str());
|
||||
IO.mapRequired(Key.str().c_str(), Sym);
|
||||
Set.insert(Sym);
|
||||
}
|
||||
|
||||
static void output(IO &IO, std::set<ELFSymbol> &Set) {
|
||||
for (auto &Sym : Set)
|
||||
IO.mapRequired(Sym.Name.c_str(), const_cast<ELFSymbol &>(Sym));
|
||||
}
|
||||
};
|
||||
|
||||
/// YAML traits for generic string vectors (i.e. list of needed libraries).
|
||||
template <> struct SequenceTraits<std::vector<std::string>> {
|
||||
static size_t size(IO &IO, std::vector<std::string> &List) {
|
||||
return List.size();
|
||||
}
|
||||
|
||||
static std::string &element(IO &IO, std::vector<std::string> &List,
|
||||
size_t Index) {
|
||||
if (Index >= List.size())
|
||||
List.resize(Index + 1);
|
||||
return List[Index];
|
||||
}
|
||||
|
||||
// Compacts list of needed libraries into a single line.
|
||||
static const bool flow = true;
|
||||
};
|
||||
|
||||
/// YAML traits for ELFStub objects.
|
||||
template <> struct MappingTraits<ELFStub> {
|
||||
static void mapping(IO &IO, ELFStub &Stub) {
|
||||
if (!IO.mapTag("!tapi-tbe", true))
|
||||
IO.setError("Not a .tbe YAML file.");
|
||||
IO.mapRequired("TbeVersion", Stub.TbeVersion);
|
||||
IO.mapRequired("SoName", Stub.SoName);
|
||||
IO.mapRequired("Arch", (ELFArchMapper &)Stub.Arch);
|
||||
IO.mapOptional("NeededLibs", Stub.NeededLibs);
|
||||
IO.mapRequired("Symbols", Stub.Symbols);
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace yaml
|
||||
} // end namespace llvm
|
||||
|
||||
std::unique_ptr<ELFStub> TBEHandler::readFile(StringRef Buf) {
|
||||
yaml::Input YamlIn(Buf);
|
||||
std::unique_ptr<ELFStub> Stub(new ELFStub());
|
||||
YamlIn >> *Stub;
|
||||
if (YamlIn.error())
|
||||
return nullptr;
|
||||
return Stub;
|
||||
}
|
||||
|
||||
Error TBEHandler::writeFile(raw_ostream &OS, const ELFStub &Stub) {
|
||||
yaml::Output YamlOut(OS, NULL, /*WrapColumn =*/0);
|
||||
|
||||
YamlOut << const_cast<ELFStub &>(Stub);
|
||||
return Error::success();
|
||||
}
|
22
lib/TextAPI/LLVMBuild.txt
Normal file
22
lib/TextAPI/LLVMBuild.txt
Normal file
@ -0,0 +1,22 @@
|
||||
;===- ./lib/TextAPI/LLVMBuild.txt ------------------------------*- Conf -*--===;
|
||||
;
|
||||
; The LLVM Compiler Infrastructure
|
||||
;
|
||||
; This file is distributed under the University of Illinois Open Source
|
||||
; License. See LICENSE.TXT for details.
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
;
|
||||
; This is an LLVMBuild description file for the components in this subdirectory.
|
||||
;
|
||||
; For more information on the LLVMBuild system, please see:
|
||||
;
|
||||
; http://llvm.org/docs/LLVMBuild.html
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[component_0]
|
||||
type = Library
|
||||
name = TextAPI
|
||||
parent = Libraries
|
||||
required_libraries = Support BinaryFormat
|
@ -30,6 +30,7 @@ add_subdirectory(OptRemarks)
|
||||
add_subdirectory(Passes)
|
||||
add_subdirectory(ProfileData)
|
||||
add_subdirectory(Support)
|
||||
add_subdirectory(TextAPI)
|
||||
add_subdirectory(Target)
|
||||
add_subdirectory(Transforms)
|
||||
add_subdirectory(XRay)
|
||||
|
7
unittests/TextAPI/CMakeLists.txt
Normal file
7
unittests/TextAPI/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
set(LLVM_LINK_COMPONENTS
|
||||
TextAPI
|
||||
)
|
||||
|
||||
add_llvm_unittest(TapiTests
|
||||
ELFYAMLTest.cpp
|
||||
)
|
216
unittests/TextAPI/ELFYAMLTest.cpp
Normal file
216
unittests/TextAPI/ELFYAMLTest.cpp
Normal file
@ -0,0 +1,216 @@
|
||||
//===- llvm/unittests/TextAPI/YAMLTest.cpp --------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===-----------------------------------------------------------------------===/
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/TextAPI/ELF/ELFStub.h"
|
||||
#include "llvm/TextAPI/ELF/TBEHandler.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <string>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::ELF;
|
||||
using namespace llvm::elfabi;
|
||||
|
||||
std::unique_ptr<ELFStub> readFromBuffer(const char Data[]) {
|
||||
TBEHandler Handler;
|
||||
|
||||
StringRef Buf(Data);
|
||||
|
||||
std::unique_ptr<ELFStub> Stub = Handler.readFile(Buf);
|
||||
EXPECT_NE(Stub.get(), nullptr);
|
||||
return Stub;
|
||||
}
|
||||
|
||||
void compareByLine(StringRef LHS, StringRef RHS) {
|
||||
StringRef Line1;
|
||||
StringRef Line2;
|
||||
while (LHS.size() > 0 && RHS.size() > 0) {
|
||||
std::tie(Line1, LHS) = LHS.split('\n');
|
||||
std::tie(Line2, RHS) = RHS.split('\n');
|
||||
// Comparing StringRef objects works, but has messy output when not equal.
|
||||
// Using STREQ on StringRef.data() doesn't work since these substrings are
|
||||
// not null terminated.
|
||||
// This is inefficient, but forces null terminated strings that can be
|
||||
// cleanly compared.
|
||||
EXPECT_STREQ(Line1.str().data(), Line2.str().data());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ElfYamlTextAPI, YAMLReadableTBE) {
|
||||
const char Data[] = "--- !tapi-tbe\n"
|
||||
"TbeVersion: 1.0\n"
|
||||
"SoName: test.so\n"
|
||||
"Arch: x86_64\n"
|
||||
"NeededLibs: [libc.so, libfoo.so, libbar.so]\n"
|
||||
"Symbols:\n"
|
||||
" foo: { Type: Func, Undefined: true }\n"
|
||||
"...\n";
|
||||
StringRef Buf = StringRef(Data);
|
||||
TBEHandler Handler;
|
||||
std::unique_ptr<ELFStub> Stub = Handler.readFile(Buf);
|
||||
EXPECT_NE(Stub.get(), nullptr);
|
||||
EXPECT_EQ(Stub->Arch, (uint16_t)llvm::ELF::EM_X86_64);
|
||||
EXPECT_STREQ(Stub->SoName.c_str(), "test.so");
|
||||
EXPECT_EQ(Stub->NeededLibs.size(), 3u);
|
||||
EXPECT_STREQ(Stub->NeededLibs[0].c_str(), "libc.so");
|
||||
EXPECT_STREQ(Stub->NeededLibs[1].c_str(), "libfoo.so");
|
||||
EXPECT_STREQ(Stub->NeededLibs[2].c_str(), "libbar.so");
|
||||
}
|
||||
|
||||
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, "
|
||||
"Warning: \'All fields populated!\' }\n"
|
||||
"...\n";
|
||||
std::unique_ptr<ELFStub> Stub = readFromBuffer(Data);
|
||||
EXPECT_EQ(Stub->Symbols.size(), 5u);
|
||||
|
||||
auto Iterator = Stub->Symbols.begin();
|
||||
ELFSymbol const &SymBar = *Iterator++;
|
||||
EXPECT_STREQ(SymBar.Name.c_str(), "bar");
|
||||
EXPECT_EQ(SymBar.Size, 42u);
|
||||
EXPECT_EQ(SymBar.Type, ELFSymbolType::Object);
|
||||
EXPECT_FALSE(SymBar.Undefined);
|
||||
EXPECT_FALSE(SymBar.Warning.hasValue());
|
||||
|
||||
ELFSymbol const &SymBaz = *Iterator++;
|
||||
EXPECT_STREQ(SymBaz.Name.c_str(), "baz");
|
||||
EXPECT_EQ(SymBaz.Size, 3u);
|
||||
EXPECT_EQ(SymBaz.Type, ELFSymbolType::TLS);
|
||||
EXPECT_FALSE(SymBaz.Undefined);
|
||||
EXPECT_FALSE(SymBaz.Warning.hasValue());
|
||||
|
||||
ELFSymbol const &SymFoo = *Iterator++;
|
||||
EXPECT_STREQ(SymFoo.Name.c_str(), "foo");
|
||||
EXPECT_EQ(SymFoo.Size, 0u);
|
||||
EXPECT_EQ(SymFoo.Type, ELFSymbolType::Func);
|
||||
EXPECT_FALSE(SymFoo.Undefined);
|
||||
EXPECT_TRUE(SymFoo.Warning.hasValue());
|
||||
EXPECT_STREQ(SymFoo.Warning->c_str(), "Deprecated!");
|
||||
|
||||
ELFSymbol const &SymNor = *Iterator++;
|
||||
EXPECT_STREQ(SymNor.Name.c_str(), "nor");
|
||||
EXPECT_EQ(SymNor.Size, 0u);
|
||||
EXPECT_EQ(SymNor.Type, ELFSymbolType::NoType);
|
||||
EXPECT_TRUE(SymNor.Undefined);
|
||||
EXPECT_FALSE(SymNor.Warning.hasValue());
|
||||
|
||||
ELFSymbol const &SymNot = *Iterator++;
|
||||
EXPECT_STREQ(SymNot.Name.c_str(), "not");
|
||||
EXPECT_EQ(SymNot.Size, 111u);
|
||||
EXPECT_EQ(SymNot.Type, ELFSymbolType::Unknown);
|
||||
EXPECT_TRUE(SymNot.Undefined);
|
||||
EXPECT_TRUE(SymNot.Warning.hasValue());
|
||||
EXPECT_STREQ(SymNot.Warning->c_str(), "All fields populated!");
|
||||
}
|
||||
|
||||
TEST(ElfYamlTextAPI, YAMLReadsNoTBESyms) {
|
||||
const char Data[] = "--- !tapi-tbe\n"
|
||||
"TbeVersion: 1.0\n"
|
||||
"SoName: test.so\n"
|
||||
"Arch: x86_64\n"
|
||||
"Symbols: {}\n"
|
||||
"...\n";
|
||||
std::unique_ptr<ELFStub> Stub = readFromBuffer(Data);
|
||||
EXPECT_EQ(0u, Stub->Symbols.size());
|
||||
}
|
||||
|
||||
TEST(ElfYamlTextAPI, YAMLUnreadableTBE) {
|
||||
TBEHandler Handler;
|
||||
// Can't read: wrong format/version.
|
||||
const char Data[] = "--- !tapi-tbz\n"
|
||||
"TbeVersion: z.3\n"
|
||||
"SoName: test.so\n"
|
||||
"Arch: x86_64\n"
|
||||
"Symbols:\n"
|
||||
" foo: { Type: Func, Undefined: true }\n";
|
||||
StringRef Buf = StringRef(Data);
|
||||
std::unique_ptr<ELFStub> Stub = Handler.readFile(Buf);
|
||||
EXPECT_EQ(Stub.get(), nullptr);
|
||||
}
|
||||
|
||||
TEST(ElfYamlTextAPI, YAMLWritesTBESymbols) {
|
||||
const char Expected[] =
|
||||
"--- !tapi-tbe\n"
|
||||
"TbeVersion: 1.0\n"
|
||||
"SoName: test.so\n"
|
||||
"Arch: AArch64\n"
|
||||
"Symbols: \n"
|
||||
" foo: { Type: NoType, Size: 99, Warning: Does nothing }\n"
|
||||
" nor: { Type: Func, Undefined: true }\n"
|
||||
" not: { Type: Unknown, Size: 12345678901234 }\n"
|
||||
"...\n";
|
||||
ELFStub Stub;
|
||||
Stub.TbeVersion = VersionTuple(1, 0);
|
||||
Stub.SoName = "test.so";
|
||||
Stub.Arch = ELF::EM_AARCH64;
|
||||
|
||||
ELFSymbol SymFoo("foo");
|
||||
SymFoo.Size = 99u;
|
||||
SymFoo.Type = ELFSymbolType::NoType;
|
||||
SymFoo.Undefined = false;
|
||||
SymFoo.Warning = "Does nothing";
|
||||
|
||||
ELFSymbol SymNor("nor");
|
||||
SymNor.Type = ELFSymbolType::Func;
|
||||
SymNor.Undefined = true;
|
||||
|
||||
ELFSymbol SymNot("not");
|
||||
SymNot.Size = 12345678901234u;
|
||||
SymNot.Type = ELFSymbolType::Unknown;
|
||||
SymNot.Undefined = false;
|
||||
|
||||
// Deliberately not in order to check that result is sorted.
|
||||
Stub.Symbols.insert(SymNot);
|
||||
Stub.Symbols.insert(SymFoo);
|
||||
Stub.Symbols.insert(SymNor);
|
||||
|
||||
// Ensure move constructor works as expected.
|
||||
ELFStub Moved = std::move(Stub);
|
||||
|
||||
std::string Result;
|
||||
raw_string_ostream OS(Result);
|
||||
TBEHandler Handler;
|
||||
EXPECT_FALSE(Handler.writeFile(OS, Moved));
|
||||
Result = OS.str();
|
||||
compareByLine(Result.c_str(), Expected);
|
||||
}
|
||||
|
||||
TEST(ElfYamlTextAPI, YAMLWritesNoTBESyms) {
|
||||
const char Expected[] = "--- !tapi-tbe\n"
|
||||
"TbeVersion: 1.0\n"
|
||||
"SoName: nosyms.so\n"
|
||||
"Arch: x86_64\n"
|
||||
"NeededLibs: [ libc.so, libfoo.so, libbar.so ]\n"
|
||||
"Symbols: {}\n"
|
||||
"...\n";
|
||||
ELFStub Stub;
|
||||
Stub.TbeVersion = VersionTuple(1, 0);
|
||||
Stub.SoName = "nosyms.so";
|
||||
Stub.Arch = ELF::EM_X86_64;
|
||||
Stub.NeededLibs.push_back("libc.so");
|
||||
Stub.NeededLibs.push_back("libfoo.so");
|
||||
Stub.NeededLibs.push_back("libbar.so");
|
||||
|
||||
std::string Result;
|
||||
raw_string_ostream OS(Result);
|
||||
TBEHandler Handler;
|
||||
EXPECT_FALSE(Handler.writeFile(OS, Stub));
|
||||
Result = OS.str();
|
||||
compareByLine(Result.c_str(), Expected);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user