[ifs] Prepare llvm-ifs for elfabi/ifs merging.

This diff changes llvm-ifs to use unified IFS file format
and perform other renaming changes in preparation for the
merging between elfabi/ifs.

Differential Revision: https://reviews.llvm.org/D99810
This commit is contained in:
Haowei Wu 2021-04-07 15:50:12 -07:00
parent 8b4acb067f
commit 61fa9afe4c
96 changed files with 784 additions and 739 deletions

View File

@ -4449,7 +4449,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
StringRef ArgStr =
Args.hasArg(options::OPT_interface_stub_version_EQ)
? Args.getLastArgValue(options::OPT_interface_stub_version_EQ)
: "experimental-ifs-v2";
: "ifs-v1";
CmdArgs.push_back("-emit-interface-stubs");
CmdArgs.push_back(
Args.MakeArgString(Twine("-interface-stub-version=") + ArgStr.str()));

View File

@ -2618,24 +2618,24 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
StringRef ArgStr =
Args.hasArg(OPT_interface_stub_version_EQ)
? Args.getLastArgValue(OPT_interface_stub_version_EQ)
: "experimental-ifs-v2";
: "ifs-v1";
if (ArgStr == "experimental-yaml-elf-v1" ||
ArgStr == "experimental-ifs-v1" ||
ArgStr == "experimental-ifs-v1" || ArgStr == "experimental-ifs-v2" ||
ArgStr == "experimental-tapi-elf-v1") {
std::string ErrorMessage =
"Invalid interface stub format: " + ArgStr.str() +
" is deprecated.";
Diags.Report(diag::err_drv_invalid_value)
<< "Must specify a valid interface stub format type, ie: "
"-interface-stub-version=experimental-ifs-v2"
"-interface-stub-version=ifs-v1"
<< ErrorMessage;
ProgramAction = frontend::ParseSyntaxOnly;
} else if (!ArgStr.startswith("experimental-ifs-")) {
} else if (!ArgStr.startswith("ifs-")) {
std::string ErrorMessage =
"Invalid interface stub format: " + ArgStr.str() + ".";
Diags.Report(diag::err_drv_invalid_value)
<< "Must specify a valid interface stub format type, ie: "
"-interface-stub-version=experimental-ifs-v2"
"-interface-stub-version=ifs-v1"
<< ErrorMessage;
ProgramAction = frontend::ParseSyntaxOnly;
}

View File

@ -290,11 +290,8 @@ public:
const ASTContext &context, StringRef Format,
raw_ostream &OS) -> void {
OS << "--- !" << Format << "\n";
OS << "IfsVersion: 2.0\n";
OS << "Triple: " << T.str() << "\n";
OS << "ObjectFileFormat: "
<< "ELF"
<< "\n"; // TODO: For now, just ELF.
OS << "IfsVersion: 3.0\n";
OS << "Target: " << T.str() << "\n";
OS << "Symbols:\n";
for (const auto &E : Symbols) {
const MangledSymbol &Symbol = E.second;
@ -330,7 +327,7 @@ public:
OS.flush();
};
assert(Format == "experimental-ifs-v2" && "Unexpected IFS Format.");
assert(Format == "ifs-v1" && "Unexpected IFS Format.");
writeIfsV1(Instance.getTarget().getTriple(), Symbols, context, Format, *OS);
}
};
@ -339,6 +336,5 @@ public:
std::unique_ptr<ASTConsumer>
GenerateInterfaceStubsAction::CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) {
return std::make_unique<InterfaceStubFunctionsConsumer>(
CI, InFile, "experimental-ifs-v2");
return std::make_unique<InterfaceStubFunctionsConsumer>(CI, InFile, "ifs-v1");
}

View File

@ -10,6 +10,9 @@
// RUN: not %clang -emit-interface-stubs -interface-stub-version=experimental-ifs-v1 %s 2>&1 | \
// RUN: FileCheck -check-prefix=CHECK-V1-DEPRECATED %s
// RUN: not %clang -emit-interface-stubs -interface-stub-version=experimental-ifs-v2 %s 2>&1 | \
// RUN: FileCheck -check-prefix=CHECK-V2-DEPRECATED %s
// RUN: not %clang -emit-interface-stubs -interface-stub-version=bad-format %s 2>&1 | \
// RUN: FileCheck %s
@ -24,22 +27,28 @@
// CHECK: error: invalid value
// CHECK: 'Invalid interface stub format: bad-format.' in 'Must specify a
// CHECK: valid interface stub format type, ie:
// CHECK: -interface-stub-version=experimental-ifs-v2'
// CHECK: -interface-stub-version=ifs-v1'
// CHECK-TAPI-DEPRECATED: error: invalid value
// CHECK-TAPI-DEPRECATED: 'Invalid interface stub format:
// CHECK-TAPI-DEPRECATED: experimental-tapi-elf-v1 is deprecated.' in 'Must
// CHECK-TAPI-DEPRECATED: specify a valid interface stub format type, ie:
// CHECK-TAPI-DEPRECATED: -interface-stub-version=experimental-ifs-v2'
// CHECK-TAPI-DEPRECATED: -interface-stub-version=ifs-v1'
// CHECK-YAML-DEPRECATED: error: invalid value
// CHECK-YAML-DEPRECATED: 'Invalid interface stub format:
// CHECK-YAML-DEPRECATED: experimental-yaml-elf-v1 is deprecated.' in 'Must
// CHECK-YAML-DEPRECATED: specify a valid interface stub format type, ie:
// CHECK-YAML-DEPRECATED: -interface-stub-version=experimental-ifs-v2'
// CHECK-YAML-DEPRECATED: -interface-stub-version=ifs-v1'
// CHECK-V1-DEPRECATED: error: invalid value
// CHECK-V1-DEPRECATED: 'Invalid interface stub format:
// CHECK-V1-DEPRECATED: experimental-ifs-v1 is deprecated.' in 'Must
// CHECK-V1-DEPRECATED: specify a valid interface stub format type, ie:
// CHECK-V1-DEPRECATED: -interface-stub-version=experimental-ifs-v2'
// CHECK-V1-DEPRECATED: -interface-stub-version=ifs-v1'
// CHECK-V2-DEPRECATED: error: invalid value
// CHECK-V2-DEPRECATED: 'Invalid interface stub format:
// CHECK-V2-DEPRECATED: experimental-ifs-v2 is deprecated.' in 'Must
// CHECK-V2-DEPRECATED: specify a valid interface stub format type, ie:
// CHECK-V2-DEPRECATED: -interface-stub-version=ifs-v1'

View File

@ -1,9 +1,8 @@
// RUN: %clang_cc1 -emit-interface-stubs -fblocks -o - %s | FileCheck %s
// CHECK: --- !experimental-ifs-v2
// CHECK-NEXT: IfsVersion: 2.0
// CHECK-NEXT: Triple:
// CHECK-NEXT: ObjectFileFormat: ELF
// CHECK: --- !ifs-v1
// CHECK-NEXT: IfsVersion: 3.0
// CHECK-NEXT: Target:
// CHECK-NEXT: Symbols:
// CHECK-NEXT: ...
static void (^f)(void*) = ^(void* data) { int i; };

View File

@ -1,9 +1,8 @@
// RUN: %clang_cc1 -o - -emit-interface-stubs %s | FileCheck %s
// CHECK: --- !experimental-ifs-v2
// CHECK-NEXT: IfsVersion: 2.0
// CHECK-NEXT: Triple:
// CHECK-NEXT: ObjectFileFormat: ELF
// CHECK: --- !ifs-v1
// CHECK-NEXT: IfsVersion: 3.0
// CHECK-NEXT: Target:
// CHECK-NEXT: Symbols:
// CHECK-NEXT: ...

View File

@ -7,10 +7,9 @@
# CHECK-IFS-NEXT: Filename:
# CHECK-IFS-NEXT: Type Values: Object Func
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: x86_64-linux-gnu
ObjectFileFormat: ELF
--- !ifs-v1
IfsVersion: 3.0
Target: x86_64-linux-gnu
Symbols:
- { Name: a, Type: Object, Size: 1 }
...

View File

@ -1,9 +1,8 @@
// RUN: %clang_cc1 -o - -emit-interface-stubs %s | FileCheck %s
// CHECK: --- !experimental-ifs-v2
// CHECK-NEXT: IfsVersion: 2.0
// CHECK-NEXT: Triple:
// CHECK-NEXT: ObjectFileFormat: ELF
// CHECK: --- !ifs-v1
// CHECK-NEXT: IfsVersion: 3.0
// CHECK-NEXT: Target:
// CHECK-NEXT: Symbols:
// CHECK-NEXT: ...

View File

@ -1,9 +1,8 @@
// RUN: %clang_cc1 -o - -emit-interface-stubs %s | FileCheck %s
// CHECK: --- !experimental-ifs-v2
// CHECK-NEXT: IfsVersion: 2.0
// CHECK-NEXT: Triple:
// CHECK-NEXT: ObjectFileFormat: ELF
// CHECK: --- !ifs-v1
// CHECK-NEXT: IfsVersion: 3.0
// CHECK-NEXT: Target:
// CHECK-NEXT: Symbols:
// CHECK-NEXT: ...

View File

@ -1,9 +1,8 @@
// RUN: %clang_cc1 -o - -emit-interface-stubs -std=c++17 %s | FileCheck %s
// CHECK: --- !experimental-ifs-v2
// CHECK-NEXT: IfsVersion: 2.0
// CHECK-NEXT: Triple:
// CHECK-NEXT: ObjectFileFormat: ELF
// CHECK: --- !ifs-v1
// CHECK-NEXT: IfsVersion: 3.0
// CHECK-NEXT: Target:
// CHECK-NEXT: Symbols:
// CHECK-NEXT: ...

View File

@ -8,10 +8,9 @@
// CHECK-OBJ: bar
// CHECK-IFS: --- !experimental-ifs-v2
// CHECK-IFS: --- !ifs-v1
// CHECK-IFS-NEXT: IfsVersion:
// CHECK-IFS-NEXT: Triple:
// CHECK-IFS-NEXT: ObjectFileFormat:
// CHECK-IFS-NEXT: Target:
// CHECK-IFS-NEXT: Symbols:
// CHECK-IFS-NEXT: - { Name: "bar", Type: Func }
// CHECK-IFS-NEXT: ...

View File

@ -1,8 +1,7 @@
// RUN: %clang_cc1 -o - -emit-interface-stubs %s | FileCheck %s
// CHECK: --- !experimental-ifs-v2
// CHECK-NEXT: IfsVersion: 2.0
// CHECK-NEXT: Triple:
// CHECK-NEXT: ObjectFileFormat:
// CHECK: --- !ifs-v1
// CHECK-NEXT: IfsVersion: 3.0
// CHECK-NEXT: Target:
// CHECK-NEXT: Symbols:
// CHECK-NEXT: ...

View File

@ -7,10 +7,9 @@
# RUN: %clang -emit-interface-stubs -o - %s %s -emit-merged-ifs | \
# RUN: FileCheck %s --check-prefixes=CHECK-MERGE-IFS
# CHECK-IFS: --- !experimental-ifs-v2
# CHECK-IFS-NEXT: IfsVersion: 2.0
# CHECK-IFS-NEXT: Triple: x86_64-linux-gnu
# CHECK-IFS-NEXT: ObjectFileFormat: ELF
# CHECK-IFS: --- !ifs-v1
# CHECK-IFS-NEXT: IfsVersion: 3.0
# CHECK-IFS-NEXT: Target: x86_64-linux-gnu
# CHECK-IFS-NEXT: Symbols:
# CHECK-IFS-DAG: - { Name: a, Type: Func }
# CHECK-IFS-DAG: - { Name: b, Type: Object, Size: 4 }
@ -23,18 +22,16 @@
# CHECK-ELF: OBJECT GLOBAL DEFAULT 1 b
# Here we are testing to see if two identical symbols will merge.
# CHECK-MERGE-IFS: --- !experimental-ifs-v2
# CHECK-MERGE-IFS-NEXT: IfsVersion: 2.0
# CHECK-MERGE-IFS-NEXT: Triple: x86_64-linux-gnu
# CHECK-MERGE-IFS-NEXT: ObjectFileFormat: ELF
# CHECK-MERGE-IFS: --- !ifs-v1
# CHECK-MERGE-IFS-NEXT: IfsVersion: 3.0
# CHECK-MERGE-IFS-NEXT: Target: x86_64-linux-gnu
# CHECK-MERGE-IFS-NEXT: Symbols:
# CHECK-MERGE-IFS-NEXT: - { Name: a, Type: Func }
# CHECK-MERGE-IFS-NEXT: ...
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: x86_64-linux-gnu
ObjectFileFormat: ELF
--- !ifs-v1
IfsVersion: 3.0
Target: x86_64-linux-gnu
Symbols:
- { Name: a, Type: Func }
...

View File

@ -14,7 +14,7 @@
// RUN: -DPARENT_METHOD_VISIBILITY="" -DCHILD_METHOD_VISIBILITY="" %s | \
// RUN: FileCheck -check-prefix=CHECK-HP %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -o - -emit-interface-stubs \
// RUN: -interface-stub-version=experimental-ifs-v2 \
// RUN: -interface-stub-version=ifs-v1 \
// RUN: -DPARENT_CLASS_VISIBILITY=HIDDEN -DCHILD_CLASS_VISIBILITY="" \
// RUN: -DPARENT_METHOD_VISIBILITY="" -DCHILD_METHOD_VISIBILITY="" %s | \
// RUN: FileCheck -check-prefix=CHECK-HP2 %s

View File

@ -1,9 +1,8 @@
// RUN: %clang_cc1 -o - -emit-interface-stubs %s | FileCheck %s
// CHECK: --- !experimental-ifs-v2
// CHECK-NEXT: IfsVersion: 2.0
// CHECK-NEXT: Triple:
// CHECK-NEXT: ObjectFileFormat: ELF
// CHECK: --- !ifs-v1
// CHECK-NEXT: IfsVersion: 3.0
// CHECK-NEXT: Target:
// CHECK-NEXT: Symbols:
// CHECK-NEXT: ...

View File

@ -1,10 +1,9 @@
// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-interface-stubs -o - %s \
// RUN: | FileCheck %s
// CHECK: --- !experimental-ifs-v2
// CHECK-NEXT: IfsVersion: 2.0
// CHECK-NEXT: Triple:
// CHECK-NEXT: ObjectFileFormat: ELF
// CHECK: --- !ifs-v1
// CHECK-NEXT: IfsVersion: 3.0
// CHECK-NEXT: Target:
// CHECK-NEXT: Symbols:
// CHECK-NEXT: f", Type: Object, Size: 1 }
// CHECK-NEXT: ...

View File

@ -1,9 +1,8 @@
// RUN: %clang_cc1 -o - -emit-interface-stubs %s | FileCheck %s
// CHECK: --- !experimental-ifs-v2
// CHECK-NEXT: IfsVersion: 2.0
// CHECK-NEXT: Triple:
// CHECK-NEXT: ObjectFileFormat: ELF
// CHECK: --- !ifs-v1
// CHECK-NEXT: IfsVersion: 3.0
// CHECK-NEXT: Target:
// CHECK-NEXT: Symbols:
// CHECK-NEXT: ...

View File

@ -1,9 +1,8 @@
// RUN: %clang_cc1 -o - -emit-interface-stubs %s | FileCheck %s
// CHECK: --- !experimental-ifs-v2
// CHECK-NEXT: IfsVersion: 2.0
// CHECK-NEXT: Triple:
// CHECK-NEXT: ObjectFileFormat: ELF
// CHECK: --- !ifs-v1
// CHECK-NEXT: IfsVersion: 3.0
// CHECK-NEXT: Target:
// CHECK-NEXT: Symbols:
// CHECK-NEXT: ...

View File

@ -1,9 +1,8 @@
// RUN: %clang_cc1 -o - -emit-interface-stubs %s | FileCheck %s
// CHECK: --- !experimental-ifs-v2
// CHECK-NEXT: IfsVersion: 2.0
// CHECK-NEXT: Triple:
// CHECK-NEXT: ObjectFileFormat: ELF
// CHECK: --- !ifs-v1
// CHECK-NEXT: IfsVersion: 3.0
// CHECK-NEXT: Target:
// CHECK-NEXT: Symbols:
// CHECK-NEXT: ...

View File

@ -4,10 +4,9 @@
# RUN: %clang -emit-interface-stubs -o - %s | llvm-readelf --all - | \
# RUN: FileCheck %s --check-prefixes=CHECK-ELF
# CHECK-IFS: --- !experimental-ifs-v2
# CHECK-IFS-NEXT: IfsVersion: 2.0
# CHECK-IFS-NEXT: Triple: x86_64-linux-gnu
# CHECK-IFS-NEXT: ObjectFileFormat: ELF
# CHECK-IFS: --- !ifs-v1
# CHECK-IFS-NEXT: IfsVersion: 3.0
# CHECK-IFS-NEXT: Target: x86_64-linux-gnu
# CHECK-IFS-NEXT: Symbols:
# CHECK-IFS-NEXT: - { Name: b, Type: Object, Size: 4 }
# CHECK-IFS-NEXT: ...
@ -19,10 +18,9 @@
# CHECK-ELF-NOT: FUNC GLOBAL DEFAULT 1 a
# CHECK-ELF: OBJECT GLOBAL DEFAULT 1 b
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: x86_64-linux-gnu
ObjectFileFormat: ELF
--- !ifs-v1
IfsVersion: 3.0
Target: x86_64-linux-gnu
Symbols:
- { Name: b, Type: Object, Size: 4 }
...

View File

@ -4,11 +4,11 @@
// RUN: -emit-interface-stubs -emit-merged-ifs -S | \
// RUN: FileCheck -check-prefix=CHECK-IFS %s
// CHECK-IFS: --- !experimental-ifs-v2
// CHECK-IFS: IfsVersion: 2.0
// CHECK-IFS: Triple: powerpc64le
// CHECK-IFS: --- !ifs-v1
// CHECK-IFS: IfsVersion: 3.0
// CHECK-IFS: Target: powerpc64le
// CHECK-IFS: Symbols:
// CHECK-IFS: - { Name: _Z8helloPPCv, Type: Func }
// CHECK-IFS: ...
int helloPPC();
int helloPPC();

View File

@ -1,9 +1,8 @@
// RUN: %clang_cc1 -o - -emit-interface-stubs %s | FileCheck %s
// CHECK: --- !experimental-ifs-v2
// CHECK-NEXT: IfsVersion: 2.0
// CHECK-NEXT: Triple:
// CHECK-NEXT: ObjectFileFormat: ELF
// CHECK: --- !ifs-v1
// CHECK-NEXT: IfsVersion: 3.0
// CHECK-NEXT: Target:
// CHECK-NEXT: Symbols:
// CHECK-NEXT: ...

View File

@ -1,9 +1,8 @@
// RUN: %clang_cc1 -o - -emit-interface-stubs %s | FileCheck %s
// CHECK: --- !experimental-ifs-v2
// CHECK-NEXT: IfsVersion: 2.0
// CHECK-NEXT: Triple:
// CHECK-NEXT: ObjectFileFormat: ELF
// CHECK: --- !ifs-v1
// CHECK-NEXT: IfsVersion: 3.0
// CHECK-NEXT: Target:
// CHECK-NEXT: Symbols:
// CHECK-NEXT: ...

View File

@ -2,10 +2,9 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcxx-exceptions -o - -emit-interface-stubs %s | FileCheck %s
// CHECK: --- !experimental-ifs-v2
// CHECK-NEXT: IfsVersion: 2.0
// CHECK-NEXT: Triple: x86_64-unknown-linux-gnu
// CHECK-NEXT: ObjectFileFormat: ELF
// CHECK: --- !ifs-v1
// CHECK-NEXT: IfsVersion: 3.0
// CHECK-NEXT: Target: x86_64-unknown-linux-gnu
// CHECK-NEXT: Symbols:
// CHECK-NEXT: - { Name: "_Z1fv", Type: Func }
// CHECK-NEXT: ...

View File

@ -1,9 +1,8 @@
// RUN: %clang_cc1 -o - -emit-interface-stubs %s | FileCheck %s
// CHECK: --- !experimental-ifs-v2
// CHECK-NEXT: IfsVersion: 2.0
// CHECK-NEXT: Triple:
// CHECK-NEXT: ObjectFileFormat: ELF
// CHECK: --- !ifs-v1
// CHECK-NEXT: IfsVersion: 3.0
// CHECK-NEXT: Target:
// CHECK-NEXT: Symbols:
// CHECK-NEXT: ...

View File

@ -1,9 +1,8 @@
// RUN: %clang_cc1 -o - -emit-interface-stubs %s | FileCheck %s
// CHECK: --- !experimental-ifs-v2
// CHECK-NEXT: IfsVersion: 2.0
// CHECK-NEXT: Triple:
// CHECK-NEXT: ObjectFileFormat: ELF
// CHECK: --- !ifs-v1
// CHECK-NEXT: IfsVersion: 3.0
// CHECK-NEXT: Target:
// CHECK-NEXT: Symbols:
// CHECK-NEXT: ...

View File

@ -1,10 +1,9 @@
// REQUIRES: x86-registered-target
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -o - -emit-interface-stubs %s | FileCheck %s
// CHECK: --- !experimental-ifs-v2
// CHECK-NEXT: IfsVersion: 2.0
// CHECK-NEXT: Triple: x86_64-unknown-linux-gnu
// CHECK-NEXT: ObjectFileFormat: ELF
// CHECK: --- !ifs-v1
// CHECK-NEXT: IfsVersion: 3.0
// CHECK-NEXT: Target: x86_64-unknown-linux-gnu
// CHECK-NEXT: Symbols:
// CHECK-NEXT: - { Name: "a", Type: Object, Size: 4 }
// CHECK-NEXT: ...

View File

@ -1,6 +1,6 @@
// REQUIRES: x86-registered-target
// RUN: %clang_cc1 -triple x86_64-linux-gnu -o - -emit-interface-stubs \
// RUN: -interface-stub-version=experimental-ifs-v2 %s | \
// RUN: -interface-stub-version=ifs-v1 %s | \
// RUN: FileCheck %s
// RUN: %clang -target x86_64-unknown-linux-gnu -o - -c %s | llvm-nm - 2>&1 | \

View File

@ -6,9 +6,9 @@
// CHECK-CC1: Symbols:
// CHECK-CC1-NEXT: ?helloWindowsMsvc@@YAHXZ
// CHECK-IFS: --- !experimental-ifs-v2
// CHECK-IFS: IfsVersion: 2.0
// CHECK-IFS: Triple:
// CHECK-IFS: --- !ifs-v1
// CHECK-IFS: IfsVersion: 3.0
// CHECK-IFS: Target:
// CHECK-IFS: Symbols:
// CHECK-IFS: - { Name: '?helloWindowsMsvc@@YAHXZ', Type: Func }
// CHECK-IFS: ...

View File

@ -13,7 +13,7 @@
#ifndef LLVM_INTERFACESTUB_ELFOBJHANDLER_H
#define LLVM_INTERFACESTUB_ELFOBJHANDLER_H
#include "llvm/InterfaceStub/ELFStub.h"
#include "llvm/InterfaceStub/IFSStub.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/ELFTypes.h"
#include "llvm/Support/FileSystem.h"
@ -24,10 +24,8 @@ class MemoryBuffer;
namespace elfabi {
enum class ELFTarget { ELF32LE, ELF32BE, ELF64LE, ELF64BE };
/// Attempt to read a binary ELF file from a MemoryBuffer.
Expected<std::unique_ptr<ELFStub>> readELFFile(MemoryBufferRef Buf);
Expected<std::unique_ptr<IFSStub>> readELFFile(MemoryBufferRef Buf);
/// Attempt to write a binary ELF stub.
/// This function determines appropriate ELFType using the passed ELFTarget and
@ -37,7 +35,7 @@ Expected<std::unique_ptr<ELFStub>> readELFFile(MemoryBufferRef Buf);
/// @param Stub Source ELFStub to generate a binary ELF stub from.
/// @param WriteIfChanged Whether or not to preserve timestamp if
/// the output stays the same.
Error writeBinaryStub(StringRef FilePath, const ELFStub &Stub,
Error writeBinaryStub(StringRef FilePath, const IFSStub &Stub,
bool WriteIfChanged = false);
} // end namespace elfabi

View File

@ -1,105 +0,0 @@
//===- ELFStub.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 ELF stub.
///
//===-----------------------------------------------------------------------===/
#ifndef LLVM_INTERFACESTUB_ELFSTUB_H
#define LLVM_INTERFACESTUB_ELFSTUB_H
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/VersionTuple.h"
#include <set>
#include <vector>
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,
};
enum class ELFEndiannessType {
Little = ELF::ELFDATA2LSB,
Big = ELF::ELFDATA2MSB,
// Endianness info is 1 bytes, 256 is safely out of rance.
Unknown = 256,
};
enum class ELFBitWidthType {
ELF32 = ELF::ELFCLASS32,
ELF64 = ELF::ELFCLASS64,
// Bit width info is 1 bytes, 256 is safely out of rance.
Unknown = 256,
};
struct ELFSymbol {
ELFSymbol() = default;
explicit ELFSymbol(std::string SymbolName) : Name(std::move(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; }
};
struct IFSTarget {
Optional<std::string> Triple;
Optional<std::string> ObjectFormat;
Optional<ELFArch> Arch;
Optional<std::string> ArchString;
Optional<ELFEndiannessType> Endianness;
Optional<ELFBitWidthType> BitWidth;
};
// A cumulative representation of ELF stubs.
// Both textual and binary stubs will read into and write from this object.
struct ELFStub {
// TODO: Add support for symbol versioning.
VersionTuple TbeVersion;
Optional<std::string> SoName;
IFSTarget Target;
std::vector<std::string> NeededLibs;
std::vector<ELFSymbol> Symbols;
ELFStub() {}
ELFStub(const ELFStub &Stub);
ELFStub(ELFStub &&Stub);
};
// Create a alias class for ELFStub.
// LLVM's YAML library does not allow mapping a class with 2 traits,
// which prevents us using 'Target:' field with 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 ELFStubTriple : ELFStub {
ELFStubTriple() {}
ELFStubTriple(const ELFStub &Stub);
ELFStubTriple(const ELFStubTriple &Stub);
ELFStubTriple(ELFStubTriple &&Stub);
};
} // end namespace elfabi
} // end namespace llvm
#endif // LLVM_INTERFACESTUB_ELFSTUB_H

View File

@ -1,4 +1,4 @@
//===- TBEHandler.h ---------------------------------------------*- C++ -*-===//
//===- 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.
@ -7,15 +7,15 @@
//===-----------------------------------------------------------------------===/
///
/// \file
/// This file declares an interface for reading and writing .tbe (text-based
/// ELF) files.
/// This file declares an interface for reading and writing .ifs (text-based
/// InterFace Stub) files.
///
//===-----------------------------------------------------------------------===/
#ifndef LLVM_INTERFACESTUB_TBEHANDLER_H
#define LLVM_INTERFACESTUB_TBEHANDLER_H
#ifndef LLVM_INTERFACESTUB_IFSHANDLER_H
#define LLVM_INTERFACESTUB_IFSHANDLER_H
#include "ELFStub.h"
#include "IFSStub.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/VersionTuple.h"
#include <memory>
@ -28,27 +28,27 @@ class StringRef;
namespace elfabi {
struct ELFStub;
struct IFSStub;
const VersionTuple TBEVersionCurrent(1, 0);
const VersionTuple IFSVersionCurrent(3, 0);
/// Attempts to read an ELF interface file from a StringRef buffer.
Expected<std::unique_ptr<ELFStub>> readTBEFromBuffer(StringRef Buf);
/// Attempts to read an IFS interface file from a StringRef buffer.
Expected<std::unique_ptr<IFSStub>> readIFSFromBuffer(StringRef Buf);
/// Attempts to write an ELF interface file to a raw_ostream.
Error writeTBEToOutputStream(raw_ostream &OS, const ELFStub &Stub);
/// 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 overrideTBETarget(ELFStub &Stub, Optional<ELFArch> OverrideArch,
Optional<ELFEndiannessType> OverrideEndianness,
Optional<ELFBitWidthType> OverrideBitWidth,
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 validateTBETarget(ELFStub &Stub, bool ParseTriple);
Error validateIFSTarget(IFSStub &Stub, bool ParseTriple);
/// Strips target platform information from the text stub.
void stripTBETarget(ELFStub &Stub, bool StripTriple, bool StripArch,
void stripIFSTarget(IFSStub &Stub, bool StripTriple, bool StripArch,
bool StripEndianness, bool StripBitWidth);
/// Parse llvm triple string into a IFSTarget struct.
@ -57,4 +57,4 @@ IFSTarget parseTriple(StringRef TripleStr);
} // end namespace elfabi
} // end namespace llvm
#endif // LLVM_INTERFACESTUB_TBEHANDLER_H
#endif // LLVM_INTERFACESTUB_IFSHANDLER_H

View File

@ -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 elfabi {
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);
} // end namespace elfabi
} // end namespace llvm
#endif // LLVM_INTERFACESTUB_IFSSTUB_H

View File

@ -1,7 +1,7 @@
add_llvm_component_library(LLVMInterfaceStub
ELFObjHandler.cpp
ELFStub.cpp
TBEHandler.cpp
IFSHandler.cpp
IFSStub.cpp
LINK_COMPONENTS
BinaryFormat

View File

@ -7,7 +7,7 @@
//===-----------------------------------------------------------------------===/
#include "llvm/InterfaceStub/ELFObjHandler.h"
#include "llvm/InterfaceStub/ELFStub.h"
#include "llvm/InterfaceStub/IFSStub.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/ELFObjectFile.h"
@ -180,7 +180,7 @@ public:
ELFStubBuilder(const ELFStubBuilder &) = delete;
ELFStubBuilder(ELFStubBuilder &&) = default;
explicit ELFStubBuilder(const ELFStub &Stub) {
explicit ELFStubBuilder(const IFSStub &Stub) {
DynSym.Name = ".dynsym";
DynSym.Align = sizeof(Elf_Addr);
DynStr.Name = ".dynstr";
@ -191,7 +191,7 @@ public:
ShStrTab.Align = 1;
// Populate string tables.
for (const ELFSymbol &Sym : Stub.Symbols)
for (const IFSSymbol &Sym : Stub.Symbols)
DynStr.Content.add(Sym.Name);
for (const std::string &Lib : Stub.NeededLibs)
DynStr.Content.add(Lib);
@ -213,14 +213,14 @@ public:
DynStr.Size = DynStr.Content.getSize();
// Populate dynamic symbol table.
for (const ELFSymbol &Sym : Stub.Symbols) {
for (const IFSSymbol &Sym : Stub.Symbols) {
uint8_t Bind = Sym.Weak ? STB_WEAK : STB_GLOBAL;
// For non-undefined symbols, value of the shndx is not relevant at link
// time as long as it is not SHN_UNDEF. Set shndx to 1, which
// points to ".dynsym".
uint16_t Shndx = Sym.Undefined ? SHN_UNDEF : 1;
DynSym.Content.add(DynStr.Content.getOffset(Sym.Name), Sym.Size, Bind,
(uint8_t)Sym.Type, 0, Shndx);
convertIFSSymbolTypeToELF(Sym.Type), 0, Shndx);
}
DynSym.Size = DynSym.Content.getSize();
@ -444,37 +444,15 @@ static Error populateDynamic(DynamicEntries &Dyn,
return Error::success();
}
/// This function extracts symbol type from a symbol's st_info member and
/// maps it to an ELFSymbolType enum.
/// Currently, STT_NOTYPE, STT_OBJECT, STT_FUNC, and STT_TLS are supported.
/// Other symbol types are mapped to ELFSymbolType::Unknown.
///
/// @param Info Binary symbol st_info to extract symbol type from.
static ELFSymbolType convertInfoToType(uint8_t Info) {
Info = Info & 0xf;
switch (Info) {
case ELF::STT_NOTYPE:
return ELFSymbolType::NoType;
case ELF::STT_OBJECT:
return ELFSymbolType::Object;
case ELF::STT_FUNC:
return ELFSymbolType::Func;
case ELF::STT_TLS:
return ELFSymbolType::TLS;
default:
return ELFSymbolType::Unknown;
}
}
/// This function creates an ELFSymbol and populates all members using
/// This function creates an IFSSymbol and populates all members using
/// information from a binary ELFT::Sym.
///
/// @param SymName The desired name of the ELFSymbol.
/// @param SymName The desired name of the IFSSymbol.
/// @param RawSym ELFT::Sym to extract symbol information from.
template <class ELFT>
static ELFSymbol createELFSym(StringRef SymName,
static IFSSymbol createELFSym(StringRef SymName,
const typename ELFT::Sym &RawSym) {
ELFSymbol TargetSym{std::string(SymName)};
IFSSymbol TargetSym{std::string(SymName)};
uint8_t Binding = RawSym.getBinding();
if (Binding == STB_WEAK)
TargetSym.Weak = true;
@ -482,9 +460,9 @@ static ELFSymbol createELFSym(StringRef SymName,
TargetSym.Weak = false;
TargetSym.Undefined = RawSym.isUndefined();
TargetSym.Type = convertInfoToType(RawSym.st_info);
TargetSym.Type = convertELFSymbolTypeToIFS(RawSym.st_info);
if (TargetSym.Type == ELFSymbolType::Func) {
if (TargetSym.Type == IFSSymbolType::Func) {
TargetSym.Size = 0;
} else {
TargetSym.Size = RawSym.st_size;
@ -492,14 +470,14 @@ static ELFSymbol createELFSym(StringRef SymName,
return TargetSym;
}
/// This function populates an ELFStub with symbols using information read
/// This function populates an IFSStub with symbols using information read
/// from an ELF binary.
///
/// @param TargetStub ELFStub to add symbols to.
/// @param TargetStub IFSStub to add symbols to.
/// @param DynSym Range of dynamic symbols to add to TargetStub.
/// @param DynStr StringRef to the dynamic string table.
template <class ELFT>
static Error populateSymbols(ELFStub &TargetStub,
static Error populateSymbols(IFSStub &TargetStub,
const typename ELFT::SymRange DynSym,
StringRef DynStr) {
// Skips the first symbol since it's the NULL symbol.
@ -512,28 +490,28 @@ static Error populateSymbols(ELFStub &TargetStub,
uint8_t Visibility = RawSym.getVisibility();
if (!(Visibility == STV_DEFAULT || Visibility == STV_PROTECTED))
continue;
// Create an ELFSymbol and populate it with information from the symbol
// Create an IFSSymbol and populate it with information from the symbol
// table entry.
Expected<StringRef> SymName = terminatedSubstr(DynStr, RawSym.st_name);
if (!SymName)
return SymName.takeError();
ELFSymbol Sym = createELFSym<ELFT>(*SymName, RawSym);
IFSSymbol Sym = createELFSym<ELFT>(*SymName, RawSym);
TargetStub.Symbols.push_back(std::move(Sym));
// TODO: Populate symbol warning.
}
return Error::success();
}
/// Returns a new ELFStub with all members populated from an ELFObjectFile.
/// Returns a new IFSStub with all members populated from an ELFObjectFile.
/// @param ElfObj Source ELFObjectFile.
template <class ELFT>
static Expected<std::unique_ptr<ELFStub>>
static Expected<std::unique_ptr<IFSStub>>
buildStub(const ELFObjectFile<ELFT> &ElfObj) {
using Elf_Dyn_Range = typename ELFT::DynRange;
using Elf_Phdr_Range = typename ELFT::PhdrRange;
using Elf_Sym_Range = typename ELFT::SymRange;
using Elf_Sym = typename ELFT::Sym;
std::unique_ptr<ELFStub> DestStub = std::make_unique<ELFStub>();
std::unique_ptr<IFSStub> DestStub = std::make_unique<IFSStub>();
const ELFFile<ELFT> &ElfFile = ElfObj.getELFFile();
// Fetch .dynamic table.
Expected<Elf_Dyn_Range> DynTable = ElfFile.dynamicEntries();
@ -562,11 +540,11 @@ buildStub(const ELFObjectFile<ELFT> &ElfObj) {
DynEnt.StrSize);
// Populate Arch from ELF header.
DestStub->Target.Arch = static_cast<ELFArch>(ElfFile.getHeader().e_machine);
DestStub->Target.Arch = static_cast<IFSArch>(ElfFile.getHeader().e_machine);
DestStub->Target.BitWidth =
(ELFBitWidthType)ElfFile.getHeader().e_ident[EI_CLASS];
convertELFBitWidthToIFS(ElfFile.getHeader().e_ident[EI_CLASS]);
DestStub->Target.Endianness =
(ELFEndiannessType)ElfFile.getHeader().e_ident[EI_DATA];
convertELFEndiannessToIFS(ElfFile.getHeader().e_ident[EI_DATA]);
DestStub->Target.ObjectFormat = "ELF";
// Populate SoName from .dynamic entries and dynamic string table.
@ -615,9 +593,9 @@ buildStub(const ELFObjectFile<ELFT> &ElfObj) {
/// the file.
///
/// @param FilePath File path for writing the ELF binary.
/// @param Stub Source ELFStub to generate a binary ELF stub from.
/// @param Stub Source InterFace Stub to generate a binary ELF stub from.
template <class ELFT>
static Error writeELFBinaryToFile(StringRef FilePath, const ELFStub &Stub,
static Error writeELFBinaryToFile(StringRef FilePath, const IFSStub &Stub,
bool WriteIfChanged) {
ELFStubBuilder<ELFT> Builder{Stub};
// Write Stub to memory first.
@ -651,7 +629,7 @@ static Error writeELFBinaryToFile(StringRef FilePath, const ELFStub &Stub,
return FileBuf->commit();
}
Expected<std::unique_ptr<ELFStub>> readELFFile(MemoryBufferRef Buf) {
Expected<std::unique_ptr<IFSStub>> readELFFile(MemoryBufferRef Buf) {
Expected<std::unique_ptr<Binary>> BinOrErr = createBinary(Buf);
if (!BinOrErr) {
return BinOrErr.takeError();
@ -672,19 +650,19 @@ Expected<std::unique_ptr<ELFStub>> readELFFile(MemoryBufferRef Buf) {
// This function wraps the ELFT writeELFBinaryToFile() so writeBinaryStub()
// can be called without having to use ELFType templates directly.
Error writeBinaryStub(StringRef FilePath, const ELFStub &Stub,
Error writeBinaryStub(StringRef FilePath, const IFSStub &Stub,
bool WriteIfChanged) {
assert(Stub.Target.Arch);
assert(Stub.Target.BitWidth);
assert(Stub.Target.Endianness);
if (Stub.Target.BitWidth == ELFBitWidthType::ELF32) {
if (Stub.Target.Endianness == ELFEndiannessType::Little) {
if (Stub.Target.BitWidth == IFSBitWidthType::IFS32) {
if (Stub.Target.Endianness == IFSEndiannessType::Little) {
return writeELFBinaryToFile<ELF32LE>(FilePath, Stub, WriteIfChanged);
} else {
return writeELFBinaryToFile<ELF32BE>(FilePath, Stub, WriteIfChanged);
}
} else {
if (Stub.Target.Endianness == ELFEndiannessType::Little) {
if (Stub.Target.Endianness == IFSEndiannessType::Little) {
return writeELFBinaryToFile<ELF64LE>(FilePath, Stub, WriteIfChanged);
} else {
return writeELFBinaryToFile<ELF64BE>(FilePath, Stub, WriteIfChanged);
@ -693,5 +671,5 @@ Error writeBinaryStub(StringRef FilePath, const ELFStub &Stub,
llvm_unreachable("invalid binary output target");
}
} // end namespace elfabi
} // namespace elfabi
} // end namespace llvm

View File

@ -1,53 +0,0 @@
//===- ELFStub.cpp --------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===-----------------------------------------------------------------------===/
#include "llvm/InterfaceStub/ELFStub.h"
#include "llvm/Support/Error.h"
using namespace llvm;
using namespace llvm::elfabi;
ELFStub::ELFStub(ELFStub const &Stub) {
TbeVersion = Stub.TbeVersion;
Target = Stub.Target;
SoName = Stub.SoName;
NeededLibs = Stub.NeededLibs;
Symbols = Stub.Symbols;
}
ELFStub::ELFStub(ELFStub &&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);
}
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);
}

View File

@ -1,4 +1,4 @@
//===- TBEHandler.cpp -----------------------------------------------------===//
//===- 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.
@ -6,11 +6,12 @@
//
//===-----------------------------------------------------------------------===/
#include "llvm/InterfaceStub/TBEHandler.h"
#include "llvm/InterfaceStub/IFSHandler.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/InterfaceStub/ELFStub.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"
@ -18,33 +19,33 @@
using namespace llvm;
using namespace llvm::elfabi;
LLVM_YAML_IS_SEQUENCE_VECTOR(ELFSymbol)
LLVM_YAML_IS_SEQUENCE_VECTOR(IFSSymbol)
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);
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 = ELFSymbolType::Unknown;
SymbolType = IFSSymbolType::Unknown;
}
};
template <> struct ScalarTraits<ELFEndiannessType> {
static void output(const ELFEndiannessType &Value, void *,
template <> struct ScalarTraits<IFSEndiannessType> {
static void output(const IFSEndiannessType &Value, void *,
llvm::raw_ostream &Out) {
switch (Value) {
case ELFEndiannessType::Big:
case IFSEndiannessType::Big:
Out << "big";
break;
case ELFEndiannessType::Little:
case IFSEndiannessType::Little:
Out << "little";
break;
default:
@ -52,12 +53,12 @@ template <> struct ScalarTraits<ELFEndiannessType> {
}
}
static StringRef input(StringRef Scalar, void *, ELFEndiannessType &Value) {
Value = StringSwitch<ELFEndiannessType>(Scalar)
.Case("big", ELFEndiannessType::Big)
.Case("little", ELFEndiannessType::Little)
.Default(ELFEndiannessType::Unknown);
if (Value == ELFEndiannessType::Unknown) {
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();
@ -66,14 +67,14 @@ template <> struct ScalarTraits<ELFEndiannessType> {
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
};
template <> struct ScalarTraits<ELFBitWidthType> {
static void output(const ELFBitWidthType &Value, void *,
template <> struct ScalarTraits<IFSBitWidthType> {
static void output(const IFSBitWidthType &Value, void *,
llvm::raw_ostream &Out) {
switch (Value) {
case ELFBitWidthType::ELF32:
case IFSBitWidthType::IFS32:
Out << "32";
break;
case ELFBitWidthType::ELF64:
case IFSBitWidthType::IFS64:
Out << "64";
break;
default:
@ -81,12 +82,12 @@ template <> struct ScalarTraits<ELFBitWidthType> {
}
}
static StringRef input(StringRef Scalar, void *, ELFBitWidthType &Value) {
Value = StringSwitch<ELFBitWidthType>(Scalar)
.Case("32", ELFBitWidthType::ELF32)
.Case("64", ELFBitWidthType::ELF64)
.Default(ELFBitWidthType::Unknown);
if (Value == ELFBitWidthType::Unknown) {
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();
@ -108,14 +109,14 @@ template <> struct MappingTraits<IFSTarget> {
};
/// YAML traits for ELFSymbol.
template <> struct MappingTraits<ELFSymbol> {
static void mapping(IO &IO, ELFSymbol &Symbol) {
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 == ELFSymbolType::NoType) {
if (Symbol.Type == IFSSymbolType::NoType) {
IO.mapOptional("Size", Symbol.Size, (uint64_t)0);
} else if (Symbol.Type == ELFSymbolType::Func) {
} else if (Symbol.Type == IFSSymbolType::Func) {
Symbol.Size = 0;
} else {
IO.mapRequired("Size", Symbol.Size);
@ -130,11 +131,11 @@ template <> struct MappingTraits<ELFSymbol> {
};
/// YAML traits for ELFStub objects.
template <> struct MappingTraits<ELFStub> {
static void mapping(IO &IO, ELFStub &Stub) {
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("TbeVersion", Stub.TbeVersion);
IO.mapRequired("IfsVersion", Stub.IfsVersion);
IO.mapOptional("SoName", Stub.SoName);
IO.mapOptional("Target", Stub.Target);
IO.mapOptional("NeededLibs", Stub.NeededLibs);
@ -143,11 +144,11 @@ template <> struct MappingTraits<ELFStub> {
};
/// YAML traits for ELFStubTriple objects.
template <> struct MappingTraits<ELFStubTriple> {
static void mapping(IO &IO, ELFStubTriple &Stub) {
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("TbeVersion", Stub.TbeVersion);
IO.mapRequired("IfsVersion", Stub.IfsVersion);
IO.mapOptional("SoName", Stub.SoName);
IO.mapOptional("Target", Stub.Target.Triple);
IO.mapOptional("NeededLibs", Stub.NeededLibs);
@ -170,21 +171,21 @@ bool usesTriple(StringRef Buf) {
return true;
}
Expected<std::unique_ptr<ELFStub>> elfabi::readTBEFromBuffer(StringRef Buf) {
Expected<std::unique_ptr<IFSStub>> elfabi::readIFSFromBuffer(StringRef Buf) {
yaml::Input YamlIn(Buf);
std::unique_ptr<ELFStubTriple> Stub(new ELFStubTriple());
std::unique_ptr<IFSStubTriple> Stub(new IFSStubTriple());
if (usesTriple(Buf)) {
YamlIn >> *Stub;
} else {
YamlIn >> *static_cast<ELFStub *>(Stub.get());
YamlIn >> *static_cast<IFSStub *>(Stub.get());
}
if (std::error_code Err = YamlIn.error()) {
return createStringError(Err, "YAML failed reading as TBE");
return createStringError(Err, "YAML failed reading as IFS");
}
if (Stub->TbeVersion > elfabi::TBEVersionCurrent)
if (Stub->IfsVersion > elfabi::IFSVersionCurrent)
return make_error<StringError>(
"TBE version " + Stub->TbeVersion.getAsString() + " is unsupported.",
"IFS version " + Stub->IfsVersion.getAsString() + " is unsupported.",
std::make_error_code(std::errc::invalid_argument));
if (Stub->Target.ArchString) {
Stub->Target.Arch =
@ -193,9 +194,9 @@ Expected<std::unique_ptr<ELFStub>> elfabi::readTBEFromBuffer(StringRef Buf) {
return std::move(Stub);
}
Error elfabi::writeTBEToOutputStream(raw_ostream &OS, const ELFStub &Stub) {
Error elfabi::writeIFSToOutputStream(raw_ostream &OS, const IFSStub &Stub) {
yaml::Output YamlOut(OS, NULL, /*WrapColumn =*/0);
std::unique_ptr<ELFStubTriple> CopyStub(new ELFStubTriple(Stub));
std::unique_ptr<IFSStubTriple> CopyStub(new IFSStubTriple(Stub));
if (Stub.Target.Arch) {
CopyStub->Target.ArchString = std::string(
ELF::convertEMachineToArchName(Stub.Target.Arch.getValue()));
@ -207,13 +208,13 @@ Error elfabi::writeTBEToOutputStream(raw_ostream &OS, const ELFStub &Stub) {
!CopyStub->Target.BitWidth))
YamlOut << *CopyStub;
else
YamlOut << *static_cast<ELFStub *>(CopyStub.get());
YamlOut << *static_cast<IFSStub *>(CopyStub.get());
return Error::success();
}
Error elfabi::overrideTBETarget(ELFStub &Stub, Optional<ELFArch> OverrideArch,
Optional<ELFEndiannessType> OverrideEndianness,
Optional<ELFBitWidthType> OverrideBitWidth,
Error elfabi::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) {
@ -251,7 +252,7 @@ Error elfabi::overrideTBETarget(ELFStub &Stub, Optional<ELFArch> OverrideArch,
return Error::success();
}
Error elfabi::validateTBETarget(ELFStub &Stub, bool ParseTriple) {
Error elfabi::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 ||
@ -292,22 +293,22 @@ IFSTarget elfabi::parseTriple(StringRef TripleStr) {
// TODO: Implement a Triple Arch enum to e_machine map.
switch (IFSTriple.getArch()) {
case Triple::ArchType::aarch64:
RetTarget.Arch = (ELFArch)ELF::EM_AARCH64;
RetTarget.Arch = (IFSArch)ELF::EM_AARCH64;
break;
case Triple::ArchType::x86_64:
RetTarget.Arch = (ELFArch)ELF::EM_X86_64;
RetTarget.Arch = (IFSArch)ELF::EM_X86_64;
break;
default:
RetTarget.Arch = (ELFArch)ELF::EM_NONE;
RetTarget.Arch = (IFSArch)ELF::EM_NONE;
}
RetTarget.Endianness = IFSTriple.isLittleEndian() ? ELFEndiannessType::Little
: ELFEndiannessType::Big;
RetTarget.Endianness = IFSTriple.isLittleEndian() ? IFSEndiannessType::Little
: IFSEndiannessType::Big;
RetTarget.BitWidth =
IFSTriple.isArch64Bit() ? ELFBitWidthType::ELF64 : ELFBitWidthType::ELF32;
IFSTriple.isArch64Bit() ? IFSBitWidthType::IFS64 : IFSBitWidthType::IFS32;
return RetTarget;
}
void elfabi::stripTBETarget(ELFStub &Stub, bool StripTriple, bool StripArch,
void elfabi::stripIFSTarget(IFSStub &Stub, bool StripTriple, bool StripArch,
bool StripEndianness, bool StripBitWidth) {
if (StripTriple || StripArch) {
Stub.Target.Arch.reset();

View File

@ -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::elfabi;
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 elfabi::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 elfabi::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 elfabi::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 elfabi::convertELFBitWidthToIFS(uint8_t BitWidth) {
switch (BitWidth) {
case ELF::ELFCLASS32:
return IFSBitWidthType::IFS32;
case ELF::ELFCLASS64:
return IFSBitWidthType::IFS64;
default:
return IFSBitWidthType::Unknown;
}
}
IFSEndiannessType elfabi::convertELFEndiannessToIFS(uint8_t Endianness) {
switch (Endianness) {
case ELF::ELFDATA2LSB:
return IFSEndiannessType::Little;
case ELF::ELFDATA2MSB:
return IFSEndiannessType::Big;
default:
return IFSEndiannessType::Unknown;
}
}
IFSSymbolType elfabi::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;
}
}

View File

@ -1,8 +1,7 @@
# NOTE: Used by weak-mismatch.ifs
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: x86_64-unknown-linux-gnu
ObjectFileFormat: ELF
--- !ifs-v1
IfsVersion: 3.0
Target: x86_64-unknown-linux-gnu
Symbols:
- { Name: foobar, Type: Object, Size: 2 }
...

View File

@ -1,8 +1,7 @@
# NOTE: Used by weak-mismatch.ifs
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: x86_64-unknown-linux-gnu
ObjectFileFormat: ELF
--- !ifs-v1
IfsVersion: 3.0
Target: x86_64-unknown-linux-gnu
Symbols:
- { Name: foobar, Type: Func }
...

View File

@ -1,5 +1,5 @@
# RUN: yaml2obj %s -o %t
# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --output=- --soname=best.so %t | FileCheck %s
# RUN: llvm-elfabi --input-format=ELF --output-format=IFS --output=- --soname=best.so %t | FileCheck %s
!ELF
FileHeader:
@ -43,7 +43,7 @@ ProgramHeaders:
LastSec: .dynamic
# CHECK: --- !ifs-v1
# CHECK-NEXT: TbeVersion: {{[1-9]\d*\.(0|([1-9]\d*))}}
# CHECK-NEXT: IfsVersion: {{[1-9]\d*\.(0|([1-9]\d*))}}
# CHECK-NEXT: SoName: best.so{{$}}
# CHECK-NEXT: Target: { ObjectFormat: ELF, Arch: AArch64, Endianness: little, BitWidth: 64 }
# CHECK-NEXT: Symbols: []

View File

@ -1,6 +1,6 @@
# 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"
# RUN: llvm-elfabi --input-format=ELF --output-format=IFS --output=- %t | FileCheck %s -DTARGET="{ ObjectFormat: ELF, Arch: x86_64, Endianness: little, BitWidth: 64 }"
# RUN: llvm-elfabi --input-format=ELF --output-format=IFS --output=- --hint-ifs-target="x86_64-linux-gnu" %t | FileCheck %s -DTARGET="x86_64-linux-gnu"
--- !ELF
FileHeader:
@ -44,7 +44,7 @@ ProgramHeaders:
LastSec: .dynamic
# CHECK: --- !ifs-v1
# CHECK-NEXT: TbeVersion: {{[1-9]\d*\.(0|([1-9]\d*))}}
# CHECK-NEXT: IfsVersion: {{[1-9]\d*\.(0|([1-9]\d*))}}
# CHECK-NEXT: Target: [[TARGET]]
# CHECK-NEXT: Symbols: []
# CHECK-NEXT: ...
@ -52,7 +52,7 @@ ProgramHeaders:
# 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
# RUN: not llvm-elfabi --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:
@ -96,7 +96,7 @@ ProgramHeaders:
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
# RUN: not llvm-elfabi --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:
@ -140,4 +140,4 @@ ProgramHeaders:
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
# RUN: not llvm-elfabi --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

View File

@ -1,5 +1,5 @@
# RUN: yaml2obj %s -o %t
# RUN: not llvm-elfabi --input-format=ELF --output-format=TBE --output=%t.tbe %t 2>&1 | FileCheck %s
# RUN: not llvm-elfabi --input-format=ELF --output-format=IFS --output=%t.tbe %t 2>&1 | FileCheck %s
!ELF
FileHeader:

View File

@ -1,5 +1,5 @@
# RUN: yaml2obj %s -o %t
# RUN: not llvm-elfabi --input-format=ELF --output-format=TBE --output=%t.tbe %t 2>&1 | FileCheck %s
# RUN: not llvm-elfabi --input-format=ELF --output-format=IFS --output=%t.tbe %t 2>&1 | FileCheck %s
!ELF
FileHeader:

View File

@ -1,5 +1,5 @@
# RUN: yaml2obj %s -o %t
# RUN: not llvm-elfabi --input-format=ELF --output-format=TBE --output=%t.tbe %t 2>&1 | FileCheck %s
# RUN: not llvm-elfabi --input-format=ELF --output-format=IFS --output=%t.tbe %t 2>&1 | FileCheck %s
!ELF
FileHeader:

View File

@ -1,5 +1,5 @@
# RUN: yaml2obj %s -o %t
# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --output=- %t | FileCheck %s
# RUN: llvm-elfabi --input-format=ELF --output-format=IFS --output=- %t | FileCheck %s
!ELF
FileHeader:

View File

@ -1,5 +1,5 @@
# RUN: yaml2obj %s -o %t
# RUN: not llvm-elfabi --input-format=ELF --output-format=TBE --output=%t.tbe %t 2>&1 | FileCheck %s
# RUN: not llvm-elfabi --input-format=ELF --output-format=IFS --output=%t.tbe %t 2>&1 | FileCheck %s
!ELF
FileHeader:

View File

@ -1,5 +1,5 @@
# RUN: yaml2obj %s -o %t
# RUN: not llvm-elfabi --input-format=ELF --output-format=TBE --output=%t.tbe %t 2>&1 | FileCheck %s
# RUN: not llvm-elfabi --input-format=ELF --output-format=IFS --output=%t.tbe %t 2>&1 | FileCheck %s
!ELF
FileHeader:

View File

@ -1,5 +1,5 @@
# RUN: yaml2obj %s -o %t
# RUN: not llvm-elfabi --input-format=ELF --output-format=TBE --output=%t.tbe %t 2>&1 | FileCheck %s
# RUN: not llvm-elfabi --input-format=ELF --output-format=IFS --output=%t.tbe %t 2>&1 | FileCheck %s
!ELF
FileHeader:

View File

@ -1,6 +1,6 @@
# RUN: yaml2obj %s -o %t
# 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
# RUN: llvm-elfabi --input-format=ELF --output-format=IFS --output=- %t | FileCheck %s --check-prefix=ORIGINAL
# RUN: llvm-elfabi --input-format=ELF --output-format=IFS --soname=libbest.so --output=- %t | FileCheck %s --check-prefix=REPLACED
!ELF
FileHeader:

View File

@ -1,5 +1,5 @@
# RUN: yaml2obj %s -o %t
# RUN: not llvm-elfabi --input-format=ELF --output-format=TBE --output=%t.tbe %t 2>&1 | FileCheck %s
# RUN: not llvm-elfabi --input-format=ELF --output-format=IFS --output=%t.tbe %t 2>&1 | FileCheck %s
!ELF
FileHeader:

View File

@ -1,5 +1,5 @@
# RUN: yaml2obj %s -o %t
# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --output=- %t | FileCheck %s
# RUN: llvm-elfabi --input-format=ELF --output-format=IFS --output=- %t | FileCheck %s
!ELF
FileHeader:
@ -46,7 +46,7 @@ ProgramHeaders:
LastSec: .dynamic
# CHECK: --- !ifs-v1
# CHECK-NEXT: TbeVersion: {{[1-9]\d*\.(0|([1-9]\d*))}}
# 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: []

View File

@ -1,7 +1,7 @@
# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --output=- %p/Inputs/gnu_hash.so | FileCheck %s
# RUN: llvm-elfabi --input-format=ELF --output-format=IFS --output=- %p/Inputs/gnu_hash.so | FileCheck %s
# CHECK: --- !ifs-v1
# CHECK-NEXT: TbeVersion: 1.0
# 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:

View File

@ -1,7 +1,7 @@
# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --output=- %p/Inputs/sysv_hash.so | FileCheck %s
# RUN: llvm-elfabi --input-format=ELF --output-format=IFS --output=- %p/Inputs/sysv_hash.so | FileCheck %s
# CHECK: --- !ifs-v1
# CHECK-NEXT: TbeVersion: 1.0
# 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:

View File

@ -1,14 +0,0 @@
# RUN: not llvm-ifs -action write-ifs -o - %s %S/object.ifs 2>&1 | \
# RUN: FileCheck %s --check-prefixes=CHECK-IFS
# CHECK-IFS: error: Interface Stub: ObjectFileFormat Mismatch.
# CHECK-IFS-NEXT: Filenames:
# CHECK-IFS-NEXT: ObjectFileFormat Values: TBD ELF
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: x86_64-apple-unknown
ObjectFileFormat: TBD
Symbols:
- { Name: a, Type: Func }
...

View File

@ -5,10 +5,9 @@
# CHECK-IFS-NEXT: Filenames:
# CHECK-IFS-NEXT: Triple Values: mips-unknown-linux x86_64-unknown-linux-gnu
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: mips-unknown-linux
ObjectFileFormat: ELF
--- !ifs-v1
IfsVersion: 3.0
Target: mips-unknown-linux
Symbols:
- { Name: a, Type: Func }
...

View File

@ -5,12 +5,11 @@
# 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: 2.0.
# CHECK-IFS2: error: Interface Stub: Bad IfsVersion: 0.0, llvm-ifs supported version: 3.0.
--- !experimental-ifs-v2
--- !ifs-v1
IfsVersion: 0.0
Triple: x86_64-unknown-linux-gnu
ObjectFileFormat: ELF
Target: x86_64-unknown-linux-gnu
Symbols:
- { Name: a, Type: Func }
...

View File

@ -7,10 +7,9 @@
# CHECK-IFS-NEXT: Filename:
# CHECK-IFS-NEXT: Size Values: 1 4
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: x86_64-unknown-linux-gnu
ObjectFileFormat: ELF
--- !ifs-v1
IfsVersion: 3.0
Target: x86_64-unknown-linux-gnu
Symbols:
- { Name: b, Type: Object, Size: 1 }
...

View File

@ -7,10 +7,9 @@
# CHECK-IFS-NEXT: Filename:
# CHECK-IFS-NEXT: Type Values: Object Func
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: x86_64-unknown-linux-gnu
ObjectFileFormat: ELF
--- !ifs-v1
IfsVersion: 3.0
Target: x86_64-unknown-linux-gnu
Symbols:
- { Name: a, Type: Object, Size: 1 }
...

View File

@ -4,10 +4,9 @@
# CHECK-IFS: Symbols:
# CHECK-IFS-NEXT: - { Name: a, Type: Func, Weak: true }
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: x86_64-unknown-linux-gnu
ObjectFileFormat: ELF
--- !ifs-v1
IfsVersion: 3.0
Target: x86_64-unknown-linux-gnu
Symbols:
- { Name: a, Type: Func, Weak: true }
...

View File

@ -1,25 +1,22 @@
# RUN: llvm-ifs -action write-ifs -o - %s | FileCheck --check-prefixes=CHECK-DEFAULT %s
# RUN: llvm-ifs -action write-ifs -o - %s %S/weak.ifs | FileCheck --check-prefixes=CHECK-MERGE %s
# CHECK-DEFAULT: --- !experimental-ifs-v2
# CHECK-DEFAULT-NEXT: IfsVersion: 2.0
# CHECK-DEFAULT-NEXT: Triple: ''
# CHECK-DEFAULT-NEXT: ObjectFileFormat: ELF
# CHECK-DEFAULT: --- !ifs-v1
# CHECK-DEFAULT-NEXT: IfsVersion: 3.0
# CHECK-DEFAULT-NEXT: Target: ''
# CHECK-DEFAULT-NEXT: Symbols: []
# CHECK-DEFAULT-NEXT: ...
# CHECK-MERGE: --- !experimental-ifs-v2
# CHECK-MERGE-NEXT: IfsVersion: 2.0
# CHECK-MERGE-NEXT: Triple: x86_64-unknown-linux-gnu
# CHECK-MERGE-NEXT: ObjectFileFormat: ELF
# 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: ...
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: ''
ObjectFileFormat: ELF
--- !ifs-v1
IfsVersion: 3.0
Target: ''
Symbols: []
...

View File

@ -1,15 +1,13 @@
# RUN: llvm-ifs -action write-ifs -o - %s | FileCheck %s
# CHECK: --- !experimental-ifs-v2
# CHECK-NEXT: IfsVersion: 2.0
# CHECK-NEXT: Triple: x86_64-unknown-linux-gnu
# CHECK-NEXT: ObjectFileFormat: ELF
# CHECK: --- !ifs-v1
# CHECK-NEXT: IfsVersion: 3.0
# CHECK-NEXT: Target: x86_64-unknown-linux-gnu
# CHECK-NEXT: Symbols: []
# CHECK: ...
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: x86_64-unknown-linux-gnu
ObjectFileFormat: ELF
--- !ifs-v1
IfsVersion: 3.0
Target: x86_64-unknown-linux-gnu
Symbols: []
...

View File

@ -1,15 +1,13 @@
# RUN: llvm-ifs -action write-ifs -o - %s | FileCheck %s
# CHECK: --- !experimental-ifs-v2
# CHECK-NEXT: IfsVersion: 2.0
# CHECK-NEXT: Triple: x86_64-unknown-linux-gnu
# CHECK-NEXT: ObjectFileFormat: ELF
# CHECK: --- !ifs-v1
# CHECK-NEXT: IfsVersion: 3.0
# CHECK-NEXT: Target: x86_64-unknown-linux-gnu
# CHECK-NEXT: Symbols: []
# CHECK: ...
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: x86_64-unknown-linux-gnu
ObjectFileFormat: ELF
--- !ifs-v1
IfsVersion: 3.0
Target: x86_64-unknown-linux-gnu
Symbols:
...

View File

@ -1,4 +1,4 @@
# RUN: not llvm-elfabi --output-format=TBE --output=%t.tbe %s.NotAFileInTestingDir 2>&1 | FileCheck %s
# RUN: not llvm-elfabi --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-elfabi.

View File

@ -8,7 +8,7 @@
# RUN: rm -rf %t.TestFile
--- !ifs-v1
TbeVersion: 1.0
IfsVersion: 3.0
Target: { ObjectFormat: ELF, Arch: AArch64, Endianness: little, BitWidth: 64 }
Symbols: []
...

View File

@ -10,7 +10,7 @@
# RUN: rm -rf %t.TestDir
--- !ifs-v1
TbeVersion: 1.0
IfsVersion: 3.0
Target: { ObjectFormat: ELF, Arch: AArch64, Endianness: little, BitWidth: 64 }
Symbols: []
...

View File

@ -13,10 +13,9 @@
# RUN: llvm-ifs -action write-ifs -o - %s %s | \
# RUN: FileCheck %s --check-prefixes=CHECK-MERGE-IFS
# CHECK-IFS: --- !experimental-ifs-v2
# CHECK-IFS-NEXT: IfsVersion: 2.0
# CHECK-IFS-NEXT: Triple: x86_64-unknown-linux-gnu
# CHECK-IFS-NEXT: ObjectFileFormat: ELF
# 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: a, Type: Func }
# CHECK-IFS-DAG: - { Name: b, Type: Object, Size: 4 }
@ -42,18 +41,16 @@
# CHECK-DARWIN-TBD3-NEXT: ...
# Here we are testing to see if two identical symbols will merge.
# CHECK-MERGE-IFS: --- !experimental-ifs-v2
# CHECK-MERGE-IFS-NEXT: IfsVersion: 2.0
# CHECK-MERGE-IFS-NEXT: Triple: x86_64-unknown-linux-gnu
# CHECK-MERGE-IFS-NEXT: ObjectFileFormat: ELF
# CHECK-MERGE-IFS: --- !ifs-v1
# CHECK-MERGE-IFS-NEXT: IfsVersion: 3.0
# CHECK-MERGE-IFS-NEXT: Target: x86_64-unknown-linux-gnu
# CHECK-MERGE-IFS-NEXT: Symbols:
# CHECK-MERGE-IFS-NEXT: - { Name: a, Type: Func }
# CHECK-MERGE-IFS-NEXT: ...
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: x86_64-unknown-linux-gnu
ObjectFileFormat: ELF
--- !ifs-v1
IfsVersion: 3.0
Target: x86_64-unknown-linux-gnu
Symbols:
- { Name: a, Type: Func }
...

View File

@ -1,7 +1,7 @@
# RUN: llvm-elfabi --output-format=TBE --output=- %s | FileCheck %s
# RUN: llvm-elfabi --output-format=IFS --output=- %s | FileCheck %s
--- !ifs-v1
TbeVersion: 1.0
IfsVersion: 3.0
Target: { ObjectFormat: ELF, Arch: AArch64, Endianness: little, BitWidth: 64 }
Symbols: []
...
@ -10,4 +10,4 @@ Symbols: []
# uses the latest tbe writer by default.
# CHECK: --- !ifs-v1
# CHECK-NEXT: TbeVersion: 1.0
# CHECK-NEXT: IfsVersion: 3.0

View File

@ -1,8 +1,8 @@
# RUN: llvm-elfabi --output-format=TBE --output=- %s | FileCheck %s
# RUN: llvm-elfabi --output-format=IFS --output=- %s | FileCheck %s
--- !ifs-v1
SoName: somelib.so
TbeVersion: 1.0
IfsVersion: 3.0
Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, BitWidth: 64 }
Symbols:
- { Name: foo, Type: Func }
@ -13,7 +13,7 @@ Symbols:
...
# CHECK: --- !ifs-v1
# CHECK-NEXT: TbeVersion: {{[1-9]\d*\.(0|([1-9]\d*))}}
# 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:

View File

@ -1,4 +1,4 @@
# RUN: llvm-ifs --action write-bin -o - %s | FileCheck %s
# RUN: llvm-ifs --action write-bin -force-format TBD -o - %s | FileCheck %s
# CHECK: --- !tapi-tbd-v3
# CHECK-NEXT: archs: [ arm64 ]
@ -13,10 +13,9 @@
# CHECK-NEXT: symbols: [ __Z3fooi ]
# CHECK-NEXT: ...
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: arm64-apple-ios
ObjectFileFormat: TBD
--- !ifs-v1
IfsVersion: 3.0
Target: arm64-apple-ios
Symbols:
- { Name: __Z3fooi, Type: Func }
...

View File

@ -1,4 +1,4 @@
# RUN: llvm-ifs --action write-bin -o - %s | FileCheck %s
# RUN: llvm-ifs --action write-bin -force-format TBD -o - %s | FileCheck %s
# CHECK: --- !tapi-tbd-v3
# CHECK-NEXT: archs: [ arm64 ]
@ -13,10 +13,9 @@
# CHECK-NEXT: symbols: [ __Z3fooi ]
# CHECK-NEXT: ...
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: arm64-apple-macosx
ObjectFileFormat: TBD
--- !ifs-v1
IfsVersion: 3.0
Target: arm64-apple-macosx
Symbols:
- { Name: __Z3fooi, Type: Func }
...

View File

@ -4,10 +4,9 @@
# RUN: llvm-ifs -action write-bin -o - %s %S/func.ifs %S/object.ifs %S/weak.ifs | \
# RUN: llvm-readelf --all - | FileCheck %s --check-prefixes=CHECK-ELF
# CHECK-IFS: --- !experimental-ifs-v2
# CHECK-IFS-NEXT: IfsVersion: 2.0
# CHECK-IFS-NEXT: Triple: x86_64-unknown-linux-gnu
# CHECK-IFS-NEXT: ObjectFileFormat: ELF
# 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: e, Type: Object, Size: 8 }
# CHECK-IFS-DAG: - { Name: a, Type: Func }
@ -24,10 +23,9 @@
# CHECK-ELF: OBJECT GLOBAL DEFAULT 1 e
# CHECK-ELF: OBJECT GLOBAL DEFAULT 1 f
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: x86_64-unknown-linux-gnu
ObjectFileFormat: ELF
--- !ifs-v1
IfsVersion: 3.0
Target: x86_64-unknown-linux-gnu
Symbols:
- { Name: e, Type: Object, Size: 8 }
- { Name: f, Type: Object, Size: 2 }

View File

@ -4,10 +4,9 @@
# RUN: llvm-ifs -action write-bin -o - %s | \
# RUN: llvm-readelf --all - | FileCheck %s --check-prefixes=CHECK-ELF
# CHECK-IFS: --- !experimental-ifs-v2
# CHECK-IFS-NEXT: IfsVersion: 2.0
# CHECK-IFS-NEXT: Triple: x86_64-unknown-linux-gnu
# CHECK-IFS-NEXT: ObjectFileFormat: ELF
# 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-NEXT: - { Name: b, Type: Object, Size: 4 }
# CHECK-IFS-NEXT: ...
@ -19,10 +18,9 @@
# CHECK-ELF-NOT: FUNC GLOBAL DEFAULT 1 a
# CHECK-ELF: OBJECT GLOBAL DEFAULT 1 b
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: x86_64-unknown-linux-gnu
ObjectFileFormat: ELF
--- !ifs-v1
IfsVersion: 3.0
Target: x86_64-unknown-linux-gnu
Symbols:
- { Name: b, Type: Object, Size: 4 }
...

View File

@ -5,7 +5,7 @@
--- !ifs-v1
SoName: somelib.so
TbeVersion: 1.0
IfsVersion: 3.0
Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, BitWidth: 64 }
Symbols: []
...

View File

@ -1,8 +1,8 @@
## Test writing unchanged content to TBE file with --write-if-changed flag.
# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --output=%t %p/Inputs/gnu_hash.so
# RUN: llvm-elfabi --input-format=ELF --output-format=IFS --output=%t %p/Inputs/gnu_hash.so
# RUN: env TZ=GMT touch -m -t 197001010000 %t
# RUN: llvm-elfabi --input-format=ELF --output-format=TBE --output=%t --write-if-changed %p/Inputs/gnu_hash.so
# RUN: llvm-elfabi --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}}

View File

@ -6,7 +6,7 @@
# RUN: env TZ=GMT ls -l %t | FileCheck %s
--- !ifs-v1
TbeVersion: 1.0
IfsVersion: 3.0
Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, BitWidth: 64 }
NeededLibs:
- libc.so.6

View File

@ -5,22 +5,22 @@
## 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 --input-format=ELF --output-format=TBE --output=- %tfull | FileCheck %s
# RUN: llvm-elfabi --input-format=ELF --output-format=IFS --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 --input-format=ELF --output-format=TBE --output=- %tfull 2>&1 | FileCheck %s --check-prefix=BADENTSIZE
# RUN: not llvm-elfabi --input-format=ELF --output-format=IFS --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 --input-format=ELF --output-format=TBE --output=- %tw.gnu.hash | FileCheck %s
# RUN: llvm-elfabi --input-format=ELF --output-format=IFS --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 --input-format=ELF --output-format=TBE --output=- %tw.gnu.hash 2>&1 | FileCheck %s --check-prefix=NOTERMINATOR
# RUN: not llvm-elfabi --input-format=ELF --output-format=IFS --output=- %tw.gnu.hash 2>&1 | FileCheck %s --check-prefix=NOTERMINATOR
# CHECK: --- !ifs-v1
# CHECK-NEXT: TbeVersion: 1.0
# CHECK-NEXT: IfsVersion: 3.0
# CHECK-NEXT: Target: { ObjectFormat: ELF, Arch: AArch64, Endianness: little, BitWidth: 64 }
# CHECK-NEXT: Symbols:
# CHECK-NEXT: - { Name: foo, Type: Func, Undefined: true }

View File

@ -1,8 +1,8 @@
# RUN: not llvm-elfabi --input-format=ELF --output-format=TBE --output=%t %s 2>&1 | FileCheck %s
# RUN: not llvm-elfabi --input-format=ELF --output-format=IFS --output=%t %s 2>&1 | FileCheck %s
--- !ifs-v1
SoName: somelib.so
TbeVersion: 1.0
IfsVersion: 3.0
Target: { ObjectFormat: ELF, Arch: AArch64, Endianness: little, BitWidth: 64 }
Symbols:
- { Name: foo, Type: Func }
@ -13,4 +13,4 @@ Symbols:
...
# CHECK: The file was not recognized as a valid object file
# CHECK: No file readers succeeded reading `{{.*}}read-tbe-as-elf.test` (unsupported/malformed file?)
# CHECK: No file readers succeeded reading `{{.*}}read-ifs-as-elf.test` (unsupported/malformed file?)

View File

@ -1,13 +1,13 @@
# RUN: llvm-elfabi --input-format=TBE --output-format=TBE --output=- %s | FileCheck %s
# RUN: llvm-elfabi --input-format=IFS --output-format=IFS --output=- %s | FileCheck %s
--- !ifs-v1
TbeVersion: 1.0
IfsVersion: 3.0
Target: { ObjectFormat: ELF, Arch: AArch64, Endianness: little, BitWidth: 64 }
Symbols: []
...
# CHECK: --- !ifs-v1
# CHECK-NEXT: TbeVersion: {{[1-9]\d*\.(0|([1-9]\d*))}}
# 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: ...

View File

@ -1,10 +1,10 @@
## Test reading TBE file with bad bit width.
# RUN: not llvm-elfabi --output-format=TBE --output=- %s 2>&1 | FileCheck %s
# RUN: not llvm-elfabi --output-format=IFS --output=- %s 2>&1 | FileCheck %s
--- !ifs-v1
SoName: somelib.so
TbeVersion: 1.0
IfsVersion: 3.0
Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, BitWidth: 65 }
Symbols:
- { Name: foo, Type: Func }

View File

@ -1,10 +1,10 @@
## Test reading TBE file with bad endianness.
# RUN: not llvm-elfabi --output-format=TBE --output=- %s 2>&1 | FileCheck %s
# RUN: not llvm-elfabi --output-format=IFS --output=- %s 2>&1 | FileCheck %s
--- !ifs-v1
SoName: somelib.so
TbeVersion: 1.0
IfsVersion: 3.0
Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: lit, BitWidth: 64 }
Symbols:
- { Name: foo, Type: Func }

View File

@ -1,7 +1,7 @@
# RUN: not llvm-elfabi --output-format=TBE --output=- %s 2>&1| FileCheck %s
# RUN: not llvm-elfabi --output-format=IFS --output=- %s 2>&1| FileCheck %s
This is just some text that cannot be read by llvm-elfabi.
# CHECK: The file was not recognized as a valid object file
# CHECK: YAML failed reading as TBE
# CHECK: YAML failed reading as IFS
# CHECK: No file readers succeeded reading `{{.*}}` (unsupported/malformed file?)

View File

@ -1,14 +1,14 @@
## 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
# RUN: llvm-elfabi --input-format=ELF --output-format=IFS --strip-ifs-target --output=- %p/Inputs/sysv_hash.so | FileCheck %s --check-prefix=NOTARGET
# RUN: llvm-elfabi --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-elfabi --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-elfabi --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-elfabi --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: TbeVersion: 1.0
# CHECK-NEXT: IfsVersion: 3.0
# CHECK-NEXT: SoName: libsomething.so
# CHECK-NEXT: Target: { [[ELFTARGET]] }
# CHECK-NEXT: NeededLibs:
@ -18,7 +18,7 @@
# CHECK-NEXT: Symbols:
# NOTARGET: --- !ifs-v1
# NOTARGET-NEXT: TbeVersion: 1.0
# NOTARGET-NEXT: IfsVersion: 3.0
# NOTARGET-NEXT: SoName: libsomething.so
# NOTARGET-NEXT: NeededLibs:
# NOTARGET-NEXT: - libm.so.6

View File

@ -1,17 +1,15 @@
# RUN: llvm-ifs -action write-ifs -o - %s %S/strong.ifs | FileCheck %s --check-prefixes=CHECK-IFS
# CHECK-IFS: --- !experimental-ifs-v2
# CHECK-IFS-NEXT: IfsVersion: 2.0
# CHECK-IFS-NEXT: Triple: x86_64-unknown-linux-gnu
# CHECK-IFS-NEXT: ObjectFileFormat: ELF
# 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: ...
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: x86_64-unknown-linux-gnu
ObjectFileFormat: ELF
--- !ifs-v1
IfsVersion: 3.0
Target: x86_64-unknown-linux-gnu
Symbols:
- { Name: _Z8weakFuncv, Type: Func }
...

View File

@ -1,4 +1,4 @@
# RUN: llvm-ifs --action write-bin -o - %s | FileCheck %s
# RUN: llvm-ifs --action write-bin -force-format TBD -o - %s | FileCheck %s
# CHECK: --- !tapi-tbd-v3
# CHECK-NEXT: archs: [ arm64 ]
@ -13,10 +13,9 @@
# CHECK-NEXT: symbols: [ __Z3fooi ]
# CHECK-NEXT: ...
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: arm64-apple-tvos
ObjectFileFormat: TBD
--- !ifs-v1
IfsVersion: 3.0
Target: arm64-apple-tvos
Symbols:
- { Name: __Z3fooi, Type: Func }
...

View File

@ -1,9 +1,8 @@
# RUN: llvm-ifs -action write-ifs -o - %s %S/object.ifs
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: x86_64-unknown-linux-gnu
ObjectFileFormat: ELF
--- !ifs-v1
IfsVersion: 3.0
Target: x86_64-unknown-linux-gnu
Symbols:
- { Name: a, Type: Func }
...

View File

@ -1,4 +1,4 @@
# RUN: llvm-ifs --action write-bin -o - %s | FileCheck %s
# RUN: llvm-ifs --action write-bin -force-format TBD -o - %s | FileCheck %s
# CHECK: --- !tapi-tbd-v3
# CHECK-NEXT: archs: [ arm64 ]
@ -13,10 +13,9 @@
# CHECK-NEXT: symbols: [ __Z3fooi ]
# CHECK-NEXT: ...
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: arm64-apple-watchos
ObjectFileFormat: TBD
--- !ifs-v1
IfsVersion: 3.0
Target: arm64-apple-watchos
Symbols:
- { Name: __Z3fooi, Type: Func }
...

View File

@ -10,10 +10,9 @@
# CHECK-TYPE-NEXT: Filename:
# CHECK-TYPE-NEXT: Type Values: Object Func
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: x86_64-unknown-linux-gnu
ObjectFileFormat: ELF
--- !ifs-v1
IfsVersion: 3.0
Target: x86_64-unknown-linux-gnu
Symbols:
- { Name: foobar, Type: Object, Size: 1, Weak: true }
...

View File

@ -1,18 +1,16 @@
# RUN: llvm-ifs -action write-ifs -o - %s | FileCheck %s --check-prefixes=CHECK-IFS
# CHECK-IFS: --- !experimental-ifs-v2
# CHECK-IFS-NEXT: IfsVersion: 2.0
# CHECK-IFS-NEXT: Triple: x86_64-unknown-linux-gnu
# CHECK-IFS-NEXT: ObjectFileFormat: ELF
# 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, Weak: true }
# CHECK-IFS-DAG: - { Name: _Z10strongFuncv, Type: Func }
# CHECK-IFS: ...
--- !experimental-ifs-v2
IfsVersion: 2.0
Triple: x86_64-unknown-linux-gnu
ObjectFileFormat: ELF
--- !ifs-v1
IfsVersion: 3.0
Target: x86_64-unknown-linux-gnu
Symbols:
- { Name: _Z8weakFuncv, Type: Func, Weak: true }
- { Name: _Z10strongFuncv, Type: Func }

View File

@ -4,7 +4,7 @@
# 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
--- !ifs-v1
TbeVersion: 1.0
IfsVersion: 3.0
Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, BitWidth: 64 }
NeededLibs:
- libc.so.6

View File

@ -23,16 +23,16 @@
# 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: llvm-elfabi --output-format=IFS --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: llvm-elfabi --output-format=IFS --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
IfsVersion: 3.0
NeededLibs:
- libc.so.6
Symbols:

View File

@ -8,7 +8,7 @@
#include "ErrorCollector.h"
#include "llvm/InterfaceStub/ELFObjHandler.h"
#include "llvm/InterfaceStub/TBEHandler.h"
#include "llvm/InterfaceStub/IFSHandler.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileOutputBuffer.h"
@ -21,9 +21,9 @@
namespace llvm {
namespace elfabi {
enum class FileFormat { TBE, ELF };
enum class FileFormat { IFS, ELF };
} // end namespace elfabi
} // namespace elfabi
} // end namespace llvm
using namespace llvm;
@ -34,28 +34,28 @@ cl::opt<std::string> InputFilePath(cl::Positional, cl::desc("input"),
cl::Required);
cl::opt<FileFormat> InputFormat(
"input-format", cl::desc("Specify the input file format"),
cl::values(clEnumValN(FileFormat::TBE, "TBE", "Text based ELF stub file"),
cl::values(clEnumValN(FileFormat::IFS, "IFS", "Text based ELF stub file"),
clEnumValN(FileFormat::ELF, "ELF", "ELF object file")));
cl::opt<FileFormat> OutputFormat(
"output-format", cl::desc("Specify the output file format"),
cl::values(clEnumValN(FileFormat::TBE, "TBE", "Text based ELF stub file"),
cl::values(clEnumValN(FileFormat::IFS, "IFS", "Text based ELF stub file"),
clEnumValN(FileFormat::ELF, "ELF", "ELF stub file")),
cl::Required);
cl::opt<std::string> OptArch("arch",
cl::desc("Specify the architecture, e.g. x86_64"));
cl::opt<ELFBitWidthType> OptBitWidth(
cl::opt<IFSBitWidthType> OptBitWidth(
"bitwidth", cl::desc("Specify the bit width"),
cl::values(clEnumValN(ELFBitWidthType::ELF32, "32", "32 bits"),
clEnumValN(ELFBitWidthType::ELF64, "64", "64 bits")));
cl::opt<ELFEndiannessType> OptEndianness(
cl::values(clEnumValN(IFSBitWidthType::IFS32, "32", "32 bits"),
clEnumValN(IFSBitWidthType::IFS64, "64", "64 bits")));
cl::opt<IFSEndiannessType> OptEndianness(
"endianness", cl::desc("Specify the endianness"),
cl::values(clEnumValN(ELFEndiannessType::Little, "little", "Little Endian"),
clEnumValN(ELFEndiannessType::Big, "big", "Big Endian")));
cl::values(clEnumValN(IFSEndiannessType::Little, "little", "Little Endian"),
clEnumValN(IFSEndiannessType::Big, "big", "Big Endian")));
cl::opt<std::string> OptTargetTriple(
"target", cl::desc("Specify the target triple, e.g. x86_64-linux-gnu"));
cl::opt<std::string> OptTargetTripleHint(
"hint-ifs-target",
cl::desc("When --output-format is 'TBE', this flag will hint the expected "
cl::desc("When --output-format is 'IFS', this flag will hint the expected "
"target triple for IFS output"));
cl::opt<bool> StripIFSArch(
"strip-ifs-arch",
@ -78,13 +78,13 @@ cl::opt<bool> WriteIfChanged(
"write-if-changed",
cl::desc("Write the output file only if it is new or has changed."));
/// writeTBE() writes a Text-Based ELF stub to a file using the latest version
/// writeIFS() writes a Text-Based ELF stub to a file using the latest version
/// of the YAML parser.
static Error writeTBE(StringRef FilePath, ELFStub &Stub) {
// Write TBE to memory first.
std::string TBEStr;
raw_string_ostream OutStr(TBEStr);
Error YAMLErr = writeTBEToOutputStream(OutStr, Stub);
static Error writeIFS(StringRef FilePath, IFSStub &Stub) {
// Write IFS to memory first.
std::string IFSStr;
raw_string_ostream OutStr(IFSStr);
Error YAMLErr = writeIFSToOutputStream(OutStr, Stub);
if (YAMLErr)
return YAMLErr;
OutStr.flush();
@ -92,25 +92,25 @@ static Error writeTBE(StringRef FilePath, ELFStub &Stub) {
if (WriteIfChanged) {
if (ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrError =
MemoryBuffer::getFile(FilePath)) {
// Compare TBE output with existing TBE file.
// If TBE file unchanged, abort updating.
if ((*BufOrError)->getBuffer() == TBEStr)
// Compare IFS output with existing IFS file.
// If IFS file unchanged, abort updating.
if ((*BufOrError)->getBuffer() == IFSStr)
return Error::success();
}
}
// Open TBE file for writing.
// Open IFS file for writing.
std::error_code SysErr;
raw_fd_ostream Out(FilePath, SysErr);
if (SysErr)
return createStringError(SysErr, "Couldn't open `%s` for writing",
FilePath.data());
Out << TBEStr;
Out << IFSStr;
return Error::success();
}
/// readInputFile populates an ELFStub by attempting to read the
/// input file using both the TBE and binary ELF parsers.
static Expected<std::unique_ptr<ELFStub>> readInputFile(StringRef FilePath) {
/// readInputFile populates an IFSStub by attempting to read the
/// input file using both the IFS and binary ELF parsers.
static Expected<std::unique_ptr<IFSStub>> readInputFile(StringRef FilePath) {
// Read in file.
ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrError =
MemoryBuffer::getFile(FilePath);
@ -124,7 +124,7 @@ static Expected<std::unique_ptr<ELFStub>> readInputFile(StringRef FilePath) {
// First try to read as a binary (fails fast if not binary).
if (InputFormat.getNumOccurrences() == 0 || InputFormat == FileFormat::ELF) {
Expected<std::unique_ptr<ELFStub>> StubFromELF =
Expected<std::unique_ptr<IFSStub>> StubFromELF =
readELFFile(FileReadBuffer->getMemBufferRef());
if (StubFromELF) {
return std::move(*StubFromELF);
@ -132,14 +132,14 @@ static Expected<std::unique_ptr<ELFStub>> readInputFile(StringRef FilePath) {
EC.addError(StubFromELF.takeError(), "BinaryRead");
}
// Fall back to reading as a tbe.
if (InputFormat.getNumOccurrences() == 0 || InputFormat == FileFormat::TBE) {
Expected<std::unique_ptr<ELFStub>> StubFromTBE =
readTBEFromBuffer(FileReadBuffer->getBuffer());
if (StubFromTBE) {
return std::move(*StubFromTBE);
// Fall back to reading as a ifs.
if (InputFormat.getNumOccurrences() == 0 || InputFormat == FileFormat::IFS) {
Expected<std::unique_ptr<IFSStub>> StubFromIFS =
readIFSFromBuffer(FileReadBuffer->getBuffer());
if (StubFromIFS) {
return std::move(*StubFromIFS);
}
EC.addError(StubFromTBE.takeError(), "YamlParse");
EC.addError(StubFromIFS.takeError(), "YamlParse");
}
// If both readers fail, build a new error that includes all information.
@ -160,18 +160,18 @@ static void fatalError(Error Err) {
int main(int argc, char *argv[]) {
// Parse arguments.
cl::ParseCommandLineOptions(argc, argv);
Expected<std::unique_ptr<ELFStub>> StubOrErr = readInputFile(InputFilePath);
Expected<std::unique_ptr<IFSStub>> StubOrErr = readInputFile(InputFilePath);
if (!StubOrErr)
fatalError(StubOrErr.takeError());
std::unique_ptr<ELFStub> TargetStub = std::move(StubOrErr.get());
std::unique_ptr<IFSStub> TargetStub = std::move(StubOrErr.get());
// Change SoName before emitting stubs.
if (SOName.getNumOccurrences() == 1)
TargetStub->SoName = SOName;
Optional<ELFArch> OverrideArch;
Optional<ELFEndiannessType> OverrideEndianness;
Optional<ELFBitWidthType> OverrideBitWidth;
Optional<IFSArch> OverrideArch;
Optional<IFSEndiannessType> OverrideEndianness;
Optional<IFSBitWidthType> OverrideBitWidth;
Optional<std::string> OverrideTriple;
if (OptArch.getNumOccurrences() == 1) {
OverrideArch = ELF::convertArchNameToEMachine(OptArch.getValue());
@ -183,13 +183,13 @@ int main(int argc, char *argv[]) {
if (OptTargetTriple.getNumOccurrences() == 1)
OverrideTriple = OptTargetTriple.getValue();
Error OverrideError =
overrideTBETarget(*TargetStub, OverrideArch, OverrideEndianness,
overrideIFSTarget(*TargetStub, OverrideArch, OverrideEndianness,
OverrideBitWidth, OverrideTriple);
if (OverrideError)
fatalError(std::move(OverrideError));
switch (OutputFormat.getValue()) {
case FileFormat::TBE: {
TargetStub->TbeVersion = TBEVersionCurrent;
case FileFormat::IFS: {
TargetStub->IfsVersion = IFSVersionCurrent;
if (InputFormat.getValue() == FileFormat::ELF &&
OptTargetTripleHint.getNumOccurrences() == 1) {
std::error_code HintEC(1, std::generic_category());
@ -208,19 +208,19 @@ int main(int argc, char *argv[]) {
fatalError(make_error<StringError>(
"Triple hint does not match the actual bit width", HintEC));
}
stripTBETarget(*TargetStub, true, false, false, false);
stripIFSTarget(*TargetStub, true, false, false, false);
TargetStub->Target.Triple = OptTargetTripleHint.getValue();
} else {
stripTBETarget(*TargetStub, StripIFSTarget, StripIFSArch,
stripIFSTarget(*TargetStub, StripIFSTarget, StripIFSArch,
StripIFSEndiannessWidth, StripIFSBitWidth);
}
Error TBEWriteError = writeTBE(OutputFilePath.getValue(), *TargetStub);
if (TBEWriteError)
fatalError(std::move(TBEWriteError));
Error IFSWriteError = writeIFS(OutputFilePath.getValue(), *TargetStub);
if (IFSWriteError)
fatalError(std::move(IFSWriteError));
break;
}
case FileFormat::ELF: {
Error TargetError = validateTBETarget(*TargetStub, true);
Error TargetError = validateIFSTarget(*TargetStub, true);
if (TargetError)
fatalError(std::move(TargetError));
Error BinaryWriteError =

View File

@ -10,8 +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/InterfaceStub/IFSHandler.h"
#include "llvm/InterfaceStub/IFSStub.h"
#include "llvm/ObjectYAML/yaml2obj.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
@ -38,7 +38,7 @@ using namespace llvm::MachO;
#define DEBUG_TYPE "llvm-ifs"
namespace {
const VersionTuple IFSVersionCurrent(2, 0);
const VersionTuple IFSVersionCurrent(3, 0);
} // end anonymous namespace
static cl::opt<std::string> Action("action", cl::desc("<llvm-ifs action>"),
@ -164,14 +164,13 @@ namespace yaml {
/// YAML traits for IFSStub objects.
template <> struct MappingTraits<IFSStub> {
static void mapping(IO &IO, IFSStub &Stub) {
if (!IO.mapTag("!experimental-ifs-v2", true))
if (!IO.mapTag("!ifs-v1", true))
IO.setError("Not a .ifs YAML file.");
auto OldContext = IO.getContext();
IO.setContext(&Stub);
IO.mapRequired("IfsVersion", Stub.IfsVersion);
IO.mapOptional("Triple", Stub.Triple);
IO.mapOptional("ObjectFileFormat", Stub.ObjectFileFormat);
IO.mapOptional("Target", Stub.Triple);
IO.mapOptional("SOName", Stub.SOName);
IO.mapOptional("NeededLibs", Stub.NeededLibs);
IO.mapRequired("Symbols", Stub.Symbols);
@ -350,25 +349,25 @@ static int writeElfStub(const Triple &T, const std::vector<IFSSymbol> &Symbols,
return convertYAML(YIn, Out, ErrHandler) ? 0 : 1;
}
static Error convertIFSStub(const IFSStub &IfsStub, elfabi::ELFStub &ElfStub) {
ElfStub.TbeVersion = IfsStub.IfsVersion;
static Error convertIFSStub(const IFSStub &IfsStub, elfabi::IFSStub &ElfStub) {
ElfStub.IfsVersion = IfsStub.IfsVersion;
ElfStub.SoName = IfsStub.SOName;
ElfStub.Target.Triple = IfsStub.Triple;
ElfStub.NeededLibs = IfsStub.NeededLibs;
for (const IFSSymbol &IfsSymbol : IfsStub.Symbols) {
elfabi::ELFSymbol ElfSymbol(IfsSymbol.Name);
elfabi::IFSSymbol ElfSymbol(IfsSymbol.Name);
switch (IfsSymbol.Type) {
case IFSSymbolType::Func:
ElfSymbol.Type = elfabi::ELFSymbolType::Func;
ElfSymbol.Type = elfabi::IFSSymbolType::Func;
break;
case IFSSymbolType::NoType:
ElfSymbol.Type = elfabi::ELFSymbolType::NoType;
ElfSymbol.Type = elfabi::IFSSymbolType::NoType;
break;
case IFSSymbolType::Object:
ElfSymbol.Type = elfabi::ELFSymbolType::Object;
ElfSymbol.Type = elfabi::IFSSymbolType::Object;
break;
default:
ElfSymbol.Type = elfabi::ELFSymbolType::Unknown;
ElfSymbol.Type = elfabi::IFSSymbolType::Unknown;
break;
// TODO: Add support for TLS?
}
@ -378,22 +377,22 @@ static Error convertIFSStub(const IFSStub &IfsStub, elfabi::ELFStub &ElfStub) {
ElfSymbol.Warning = IfsSymbol.Warning;
ElfStub.Symbols.push_back(ElfSymbol);
}
return llvm::elfabi::validateTBETarget(ElfStub, true);
return llvm::elfabi::validateIFSTarget(ElfStub, true);
}
static int writeIfso(const IFSStub &Stub, bool IsWriteIfs) {
std::string ObjectFileFormat =
ForceFormat.empty() ? Stub.ObjectFileFormat : ForceFormat;
ForceFormat.empty() ? std::string("ELF") : ForceFormat;
// Use InterfaceStub library if the option is enabled and output
// format is ELF.
if (UseInterfaceStub && (!IsWriteIfs) && ObjectFileFormat != "TBD") {
elfabi::ELFStub ElfStub;
Error ConvertError = convertIFSStub(Stub, ElfStub);
elfabi::IFSStub IfsStub;
Error ConvertError = convertIFSStub(Stub, IfsStub);
if (ConvertError) {
return -1;
}
Error BinaryWriteError = elfabi::writeBinaryStub(OutputFilename, ElfStub);
Error BinaryWriteError = elfabi::writeBinaryStub(OutputFilename, IfsStub);
if (BinaryWriteError) {
return -1;
}

View File

@ -7,8 +7,9 @@
//===-----------------------------------------------------------------------===/
#include "llvm/ADT/StringRef.h"
#include "llvm/InterfaceStub/ELFStub.h"
#include "llvm/InterfaceStub/TBEHandler.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/InterfaceStub/IFSHandler.h"
#include "llvm/InterfaceStub/IFSStub.h"
#include "llvm/Support/Error.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
@ -35,16 +36,16 @@ void compareByLine(StringRef LHS, StringRef RHS) {
TEST(ElfYamlTextAPI, YAMLReadableTBE) {
const char Data[] = "--- !ifs-v1\n"
"TbeVersion: 1.0\n"
"IfsVersion: 1.0\n"
"Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: "
"little, BitWidth: 64 }\n"
"NeededLibs: [libc.so, libfoo.so, libbar.so]\n"
"Symbols:\n"
" - { Name: foo, Type: Func, Undefined: true }\n"
"...\n";
Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
Expected<std::unique_ptr<IFSStub>> StubOrErr = readIFSFromBuffer(Data);
ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded());
std::unique_ptr<ELFStub> Stub = std::move(StubOrErr.get());
std::unique_ptr<IFSStub> Stub = std::move(StubOrErr.get());
EXPECT_NE(Stub.get(), nullptr);
EXPECT_FALSE(Stub->SoName.hasValue());
EXPECT_TRUE(Stub->Target.Arch.hasValue());
@ -58,7 +59,7 @@ TEST(ElfYamlTextAPI, YAMLReadableTBE) {
TEST(ElfYamlTextAPI, YAMLReadsTBESymbols) {
const char Data[] =
"--- !ifs-v1\n"
"TbeVersion: 1.0\n"
"IfsVersion: 1.0\n"
"SoName: test.so\n"
"Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, "
"BitWidth: 64 }\n"
@ -70,52 +71,52 @@ TEST(ElfYamlTextAPI, YAMLReadsTBESymbols) {
" - { Name: not, Type: File, Undefined: true, Size: 111, "
"Weak: true, Warning: \'All fields populated!\' }\n"
"...\n";
Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
Expected<std::unique_ptr<IFSStub>> StubOrErr = readIFSFromBuffer(Data);
ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded());
std::unique_ptr<ELFStub> Stub = std::move(StubOrErr.get());
std::unique_ptr<IFSStub> Stub = std::move(StubOrErr.get());
EXPECT_NE(Stub.get(), nullptr);
EXPECT_TRUE(Stub->SoName.hasValue());
EXPECT_STREQ(Stub->SoName->c_str(), "test.so");
EXPECT_EQ(Stub->Symbols.size(), 5u);
auto Iterator = Stub->Symbols.begin();
ELFSymbol const &SymBar = *Iterator++;
IFSSymbol const &SymBar = *Iterator++;
EXPECT_STREQ(SymBar.Name.c_str(), "bar");
EXPECT_EQ(SymBar.Size, 42u);
EXPECT_EQ(SymBar.Type, ELFSymbolType::Object);
EXPECT_EQ(SymBar.Type, IFSSymbolType::Object);
EXPECT_FALSE(SymBar.Undefined);
EXPECT_FALSE(SymBar.Weak);
EXPECT_FALSE(SymBar.Warning.hasValue());
ELFSymbol const &SymBaz = *Iterator++;
IFSSymbol const &SymBaz = *Iterator++;
EXPECT_STREQ(SymBaz.Name.c_str(), "baz");
EXPECT_EQ(SymBaz.Size, 3u);
EXPECT_EQ(SymBaz.Type, ELFSymbolType::TLS);
EXPECT_EQ(SymBaz.Type, IFSSymbolType::TLS);
EXPECT_FALSE(SymBaz.Undefined);
EXPECT_FALSE(SymBaz.Weak);
EXPECT_FALSE(SymBaz.Warning.hasValue());
ELFSymbol const &SymFoo = *Iterator++;
IFSSymbol const &SymFoo = *Iterator++;
EXPECT_STREQ(SymFoo.Name.c_str(), "foo");
EXPECT_EQ(SymFoo.Size, 0u);
EXPECT_EQ(SymFoo.Type, ELFSymbolType::Func);
EXPECT_EQ(SymFoo.Type, IFSSymbolType::Func);
EXPECT_FALSE(SymFoo.Undefined);
EXPECT_FALSE(SymFoo.Weak);
EXPECT_TRUE(SymFoo.Warning.hasValue());
EXPECT_STREQ(SymFoo.Warning->c_str(), "Deprecated!");
ELFSymbol const &SymNor = *Iterator++;
IFSSymbol const &SymNor = *Iterator++;
EXPECT_STREQ(SymNor.Name.c_str(), "nor");
EXPECT_EQ(SymNor.Size, 0u);
EXPECT_EQ(SymNor.Type, ELFSymbolType::NoType);
EXPECT_EQ(SymNor.Type, IFSSymbolType::NoType);
EXPECT_TRUE(SymNor.Undefined);
EXPECT_FALSE(SymNor.Weak);
EXPECT_FALSE(SymNor.Warning.hasValue());
ELFSymbol const &SymNot = *Iterator++;
IFSSymbol const &SymNot = *Iterator++;
EXPECT_STREQ(SymNot.Name.c_str(), "not");
EXPECT_EQ(SymNot.Size, 111u);
EXPECT_EQ(SymNot.Type, ELFSymbolType::Unknown);
EXPECT_EQ(SymNot.Type, IFSSymbolType::Unknown);
EXPECT_TRUE(SymNot.Undefined);
EXPECT_TRUE(SymNot.Weak);
EXPECT_TRUE(SymNot.Warning.hasValue());
@ -124,15 +125,15 @@ TEST(ElfYamlTextAPI, YAMLReadsTBESymbols) {
TEST(ElfYamlTextAPI, YAMLReadsNoTBESyms) {
const char Data[] = "--- !ifs-v1\n"
"TbeVersion: 1.0\n"
"IfsVersion: 1.0\n"
"SoName: test.so\n"
"Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: "
"little, BitWidth: 64 }\n"
"Symbols: []\n"
"...\n";
Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
Expected<std::unique_ptr<IFSStub>> StubOrErr = readIFSFromBuffer(Data);
ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded());
std::unique_ptr<ELFStub> Stub = std::move(StubOrErr.get());
std::unique_ptr<IFSStub> Stub = std::move(StubOrErr.get());
EXPECT_NE(Stub.get(), nullptr);
EXPECT_EQ(0u, Stub->Symbols.size());
}
@ -140,33 +141,33 @@ TEST(ElfYamlTextAPI, YAMLReadsNoTBESyms) {
TEST(ElfYamlTextAPI, YAMLUnreadableTBE) {
// Can't read: wrong format/version.
const char Data[] = "--- !tapi-tbz\n"
"TbeVersion: z.3\n"
"IfsVersion: z.3\n"
"SoName: test.so\n"
"Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: "
"little, BitWidth: 64 }\n"
"Symbols:\n"
" foo: { Type: Func, Undefined: true }\n";
Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
Expected<std::unique_ptr<IFSStub>> StubOrErr = readIFSFromBuffer(Data);
ASSERT_THAT_ERROR(StubOrErr.takeError(), Failed());
}
TEST(ElfYamlTextAPI, YAMLUnsupportedVersion) {
const char Data[] = "--- !ifs-v1\n"
"TbeVersion: 9.9.9\n"
"IfsVersion: 9.9.9\n"
"SoName: test.so\n"
"Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: "
"little, BitWidth: 64 }\n"
"Symbols: []\n"
"...\n";
Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
Expected<std::unique_ptr<IFSStub>> StubOrErr = readIFSFromBuffer(Data);
std::string ErrorMessage = toString(StubOrErr.takeError());
EXPECT_EQ("TBE version 9.9.9 is unsupported.", ErrorMessage);
EXPECT_EQ("IFS version 9.9.9 is unsupported.", ErrorMessage);
}
TEST(ElfYamlTextAPI, YAMLWritesTBESymbols) {
const char Expected[] =
"--- !ifs-v1\n"
"TbeVersion: 1.0\n"
"IfsVersion: 1.0\n"
"Target: { ObjectFormat: ELF, Arch: AArch64, Endianness: "
"little, BitWidth: 64 }\n"
"Symbols:\n"
@ -175,35 +176,35 @@ TEST(ElfYamlTextAPI, YAMLWritesTBESymbols) {
" - { Name: nor, Type: Func, Undefined: true }\n"
" - { Name: not, Type: Unknown, Size: 12345678901234 }\n"
"...\n";
ELFStub Stub;
Stub.TbeVersion = VersionTuple(1, 0);
IFSStub Stub;
Stub.IfsVersion = VersionTuple(1, 0);
Stub.Target.Arch = ELF::EM_AARCH64;
Stub.Target.BitWidth = ELFBitWidthType::ELF64;
Stub.Target.Endianness = ELFEndiannessType::Little;
Stub.Target.BitWidth = IFSBitWidthType::IFS64;
Stub.Target.Endianness = IFSEndiannessType::Little;
Stub.Target.ObjectFormat = "ELF";
ELFSymbol SymBar("bar");
IFSSymbol SymBar("bar");
SymBar.Size = 128u;
SymBar.Type = ELFSymbolType::Func;
SymBar.Type = IFSSymbolType::Func;
SymBar.Undefined = false;
SymBar.Weak = true;
ELFSymbol SymFoo("foo");
IFSSymbol SymFoo("foo");
SymFoo.Size = 99u;
SymFoo.Type = ELFSymbolType::NoType;
SymFoo.Type = IFSSymbolType::NoType;
SymFoo.Undefined = false;
SymFoo.Weak = false;
SymFoo.Warning = "Does nothing";
ELFSymbol SymNor("nor");
IFSSymbol SymNor("nor");
SymNor.Size = 1234u;
SymNor.Type = ELFSymbolType::Func;
SymNor.Type = IFSSymbolType::Func;
SymNor.Undefined = true;
SymNor.Weak = false;
ELFSymbol SymNot("not");
IFSSymbol SymNot("not");
SymNot.Size = 12345678901234u;
SymNot.Type = ELFSymbolType::Unknown;
SymNot.Type = IFSSymbolType::Unknown;
SymNot.Undefined = false;
SymNot.Weak = false;
@ -214,18 +215,18 @@ TEST(ElfYamlTextAPI, YAMLWritesTBESymbols) {
Stub.Symbols.push_back(SymNot);
// Ensure move constructor works as expected.
ELFStub Moved = std::move(Stub);
IFSStub Moved = std::move(Stub);
std::string Result;
raw_string_ostream OS(Result);
ASSERT_THAT_ERROR(writeTBEToOutputStream(OS, Moved), Succeeded());
ASSERT_THAT_ERROR(writeIFSToOutputStream(OS, Moved), Succeeded());
Result = OS.str();
compareByLine(Result.c_str(), Expected);
}
TEST(ElfYamlTextAPI, YAMLWritesNoTBESyms) {
const char Expected[] = "--- !ifs-v1\n"
"TbeVersion: 1.0\n"
"IfsVersion: 1.0\n"
"SoName: nosyms.so\n"
"Target: { ObjectFormat: ELF, Arch: x86_64, "
"Endianness: little, BitWidth: 64 }\n"
@ -235,12 +236,12 @@ TEST(ElfYamlTextAPI, YAMLWritesNoTBESyms) {
" - libbar.so\n"
"Symbols: []\n"
"...\n";
ELFStub Stub;
Stub.TbeVersion = VersionTuple(1, 0);
IFSStub Stub;
Stub.IfsVersion = VersionTuple(1, 0);
Stub.SoName = "nosyms.so";
Stub.Target.Arch = ELF::EM_X86_64;
Stub.Target.BitWidth = ELFBitWidthType::ELF64;
Stub.Target.Endianness = ELFEndiannessType::Little;
Stub.Target.BitWidth = IFSBitWidthType::IFS64;
Stub.Target.Endianness = IFSEndiannessType::Little;
Stub.Target.ObjectFormat = "ELF";
Stub.NeededLibs.push_back("libc.so");
Stub.NeededLibs.push_back("libfoo.so");
@ -248,7 +249,7 @@ TEST(ElfYamlTextAPI, YAMLWritesNoTBESyms) {
std::string Result;
raw_string_ostream OS(Result);
ASSERT_THAT_ERROR(writeTBEToOutputStream(OS, Stub), Succeeded());
ASSERT_THAT_ERROR(writeIFSToOutputStream(OS, Stub), Succeeded());
Result = OS.str();
compareByLine(Result.c_str(), Expected);
}