brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.9 KiB · 39aec13 Raw
271 lines · cpp
1//===- llvm/unittests/TextAPI/YAMLTest.cpp --------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===-----------------------------------------------------------------------===/8 9#include "llvm/ADT/StringRef.h"10#include "llvm/BinaryFormat/ELF.h"11#include "llvm/InterfaceStub/IFSHandler.h"12#include "llvm/InterfaceStub/IFSStub.h"13#include "llvm/Support/Error.h"14#include "llvm/Testing/Support/Error.h"15#include "gtest/gtest.h"16#include <string>17 18using namespace llvm;19using namespace llvm::ELF;20using namespace llvm::ifs;21 22void compareByLine(StringRef LHS, StringRef RHS) {23  StringRef Line1;24  StringRef Line2;25  while (LHS.size() > 0 && RHS.size() > 0) {26    std::tie(Line1, LHS) = LHS.split('\n');27    std::tie(Line2, RHS) = RHS.split('\n');28    // Comparing StringRef objects works, but has messy output when not equal.29    // Using STREQ on StringRef.data() doesn't work since these substrings are30    // not null terminated.31    // This is inefficient, but forces null terminated strings that can be32    // cleanly compared.33    EXPECT_STREQ(Line1.str().data(), Line2.str().data());34  }35}36 37TEST(ElfYamlTextAPI, YAMLReadableTBE) {38  const char Data[] = "--- !ifs-v1\n"39                      "IfsVersion: 1.0\n"40                      "Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: "41                      "little, BitWidth: 64 }\n"42                      "NeededLibs: [libc.so, libfoo.so, libbar.so]\n"43                      "Symbols:\n"44                      "  - { Name: foo, Type: Func, Undefined: true }\n"45                      "...\n";46  Expected<std::unique_ptr<IFSStub>> StubOrErr = readIFSFromBuffer(Data);47  ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded());48  std::unique_ptr<IFSStub> Stub = std::move(StubOrErr.get());49  EXPECT_NE(Stub.get(), nullptr);50  EXPECT_FALSE(Stub->SoName.has_value());51  EXPECT_TRUE(Stub->Target.Arch.has_value());52  EXPECT_EQ(*Stub->Target.Arch, (uint16_t)llvm::ELF::EM_X86_64);53  EXPECT_EQ(Stub->NeededLibs.size(), 3u);54  EXPECT_STREQ(Stub->NeededLibs[0].c_str(), "libc.so");55  EXPECT_STREQ(Stub->NeededLibs[1].c_str(), "libfoo.so");56  EXPECT_STREQ(Stub->NeededLibs[2].c_str(), "libbar.so");57}58 59TEST(ElfYamlTextAPI, YAMLReadsInvalidSymbols) {60  const char Data[] =61      "--- !ifs-v1\n"62      "IfsVersion: 1.0\n"63      "SoName: test.so\n"64      "Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, "65      "BitWidth: 64 }\n"66      "Symbols:\n"67      "  - { Name: not, Type: File, Undefined: true, Size: 111, "68      "Weak: true, Warning: \'All fields populated!\' }\n"69      "...\n";70  Expected<std::unique_ptr<IFSStub>> StubOrErr = readIFSFromBuffer(Data);71  ASSERT_THAT_ERROR(72      StubOrErr.takeError(),73      FailedWithMessage("IFS symbol type for symbol 'not' is unsupported"));74}75 76TEST(ElfYamlTextAPI, YAMLReadsTBESymbols) {77  const char Data[] =78      "--- !ifs-v1\n"79      "IfsVersion: 1.0\n"80      "SoName: test.so\n"81      "Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: little, "82      "BitWidth: 64 }\n"83      "Symbols:\n"84      "  - { Name: bar, Type: Object, Size: 42 }\n"85      "  - { Name: baz, Type: TLS, Size: 3 }\n"86      "  - { Name: foo, Type: Func, Warning: \"Deprecated!\" }\n"87      "  - { Name: nor, Type: NoType, Undefined: true }\n"88      "  - { Name: not, Type: NoType, Undefined: true, Size: 111, "89      "Weak: true, Warning: \'All fields populated!\' }\n"90      "...\n";91  Expected<std::unique_ptr<IFSStub>> StubOrErr = readIFSFromBuffer(Data);92  ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded());93  std::unique_ptr<IFSStub> Stub = std::move(StubOrErr.get());94  EXPECT_NE(Stub.get(), nullptr);95  EXPECT_TRUE(Stub->SoName);96  EXPECT_STREQ(Stub->SoName->c_str(), "test.so");97  EXPECT_EQ(Stub->Symbols.size(), 5u);98 99  auto Iterator = Stub->Symbols.begin();100  IFSSymbol const &SymBar = *Iterator++;101  EXPECT_STREQ(SymBar.Name.c_str(), "bar");102  EXPECT_EQ(*SymBar.Size, 42u);103  EXPECT_EQ(SymBar.Type, IFSSymbolType::Object);104  EXPECT_FALSE(SymBar.Undefined);105  EXPECT_FALSE(SymBar.Weak);106  EXPECT_FALSE(SymBar.Warning);107 108  IFSSymbol const &SymBaz = *Iterator++;109  EXPECT_STREQ(SymBaz.Name.c_str(), "baz");110  EXPECT_EQ(*SymBaz.Size, 3u);111  EXPECT_EQ(SymBaz.Type, IFSSymbolType::TLS);112  EXPECT_FALSE(SymBaz.Undefined);113  EXPECT_FALSE(SymBaz.Weak);114  EXPECT_FALSE(SymBaz.Warning.has_value());115 116  IFSSymbol const &SymFoo = *Iterator++;117  EXPECT_STREQ(SymFoo.Name.c_str(), "foo");118  EXPECT_FALSE(SymFoo.Size.has_value());119  EXPECT_EQ(SymFoo.Type, IFSSymbolType::Func);120  EXPECT_FALSE(SymFoo.Undefined);121  EXPECT_FALSE(SymFoo.Weak);122  EXPECT_TRUE(SymFoo.Warning.has_value());123  EXPECT_STREQ(SymFoo.Warning->c_str(), "Deprecated!");124 125  IFSSymbol const &SymNor = *Iterator++;126  EXPECT_STREQ(SymNor.Name.c_str(), "nor");127  EXPECT_FALSE(SymNor.Size.has_value());128  EXPECT_EQ(SymNor.Type, IFSSymbolType::NoType);129  EXPECT_TRUE(SymNor.Undefined);130  EXPECT_FALSE(SymNor.Weak);131  EXPECT_FALSE(SymNor.Warning.has_value());132 133  IFSSymbol const &SymNot = *Iterator++;134  EXPECT_STREQ(SymNot.Name.c_str(), "not");135  EXPECT_EQ(*SymNot.Size, 111u);136  EXPECT_EQ(SymNot.Type, IFSSymbolType::NoType);137  EXPECT_TRUE(SymNot.Undefined);138  EXPECT_TRUE(SymNot.Weak);139  EXPECT_TRUE(SymNot.Warning);140  EXPECT_STREQ(SymNot.Warning->c_str(), "All fields populated!");141}142 143TEST(ElfYamlTextAPI, YAMLReadsNoTBESyms) {144  const char Data[] = "--- !ifs-v1\n"145                      "IfsVersion: 1.0\n"146                      "SoName: test.so\n"147                      "Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: "148                      "little, BitWidth: 64 }\n"149                      "Symbols: []\n"150                      "...\n";151  Expected<std::unique_ptr<IFSStub>> StubOrErr = readIFSFromBuffer(Data);152  ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded());153  std::unique_ptr<IFSStub> Stub = std::move(StubOrErr.get());154  EXPECT_NE(Stub.get(), nullptr);155  EXPECT_EQ(0u, Stub->Symbols.size());156}157 158TEST(ElfYamlTextAPI, YAMLUnreadableTBE) {159  // Can't read: wrong format/version.160  const char Data[] = "--- !tapi-tbz\n"161                      "IfsVersion: z.3\n"162                      "SoName: test.so\n"163                      "Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: "164                      "little, BitWidth: 64 }\n"165                      "Symbols:\n"166                      "  foo: { Type: Func, Undefined: true }\n";167  Expected<std::unique_ptr<IFSStub>> StubOrErr = readIFSFromBuffer(Data);168  ASSERT_THAT_ERROR(StubOrErr.takeError(), Failed());169}170 171TEST(ElfYamlTextAPI, YAMLUnsupportedVersion) {172  const char Data[] = "--- !ifs-v1\n"173                      "IfsVersion: 9.9.9\n"174                      "SoName: test.so\n"175                      "Target: { ObjectFormat: ELF, Arch: x86_64, Endianness: "176                      "little, BitWidth: 64 }\n"177                      "Symbols: []\n"178                      "...\n";179  Expected<std::unique_ptr<IFSStub>> StubOrErr = readIFSFromBuffer(Data);180  std::string ErrorMessage = toString(StubOrErr.takeError());181  EXPECT_EQ("IFS version 9.9.9 is unsupported.", ErrorMessage);182}183 184TEST(ElfYamlTextAPI, YAMLWritesTBESymbols) {185  const char Expected[] =186      "--- !ifs-v1\n"187      "IfsVersion:      1.0\n"188      "Target:          { ObjectFormat: ELF, Arch: AArch64, Endianness: "189      "little, BitWidth: 64 }\n"190      "Symbols:\n"191      "  - { Name: bar, Type: Func, Weak: true }\n"192      "  - { Name: foo, Type: NoType, Size: 99, Warning: Does nothing }\n"193      "  - { Name: nor, Type: Func, Undefined: true }\n"194      "  - { Name: not, Type: Unknown, Size: 12345678901234 }\n"195      "...\n";196  IFSStub Stub;197  Stub.IfsVersion = VersionTuple(1, 0);198  Stub.Target.Arch = ELF::EM_AARCH64;199  Stub.Target.BitWidth = IFSBitWidthType::IFS64;200  Stub.Target.Endianness = IFSEndiannessType::Little;201  Stub.Target.ObjectFormat = "ELF";202 203  IFSSymbol SymBar("bar");204  SymBar.Size = 128u;205  SymBar.Type = IFSSymbolType::Func;206  SymBar.Undefined = false;207  SymBar.Weak = true;208 209  IFSSymbol SymFoo("foo");210  SymFoo.Size = 99u;211  SymFoo.Type = IFSSymbolType::NoType;212  SymFoo.Undefined = false;213  SymFoo.Weak = false;214  SymFoo.Warning = "Does nothing";215 216  IFSSymbol SymNor("nor");217  SymNor.Size = 1234u;218  SymNor.Type = IFSSymbolType::Func;219  SymNor.Undefined = true;220  SymNor.Weak = false;221 222  IFSSymbol SymNot("not");223  SymNot.Size = 12345678901234u;224  SymNot.Type = IFSSymbolType::Unknown;225  SymNot.Undefined = false;226  SymNot.Weak = false;227 228  // Symbol order is preserved instead of being sorted.229  Stub.Symbols.push_back(SymBar);230  Stub.Symbols.push_back(SymFoo);231  Stub.Symbols.push_back(SymNor);232  Stub.Symbols.push_back(SymNot);233 234  // Ensure move constructor works as expected.235  IFSStub Moved = std::move(Stub);236 237  std::string Result;238  raw_string_ostream OS(Result);239  ASSERT_THAT_ERROR(writeIFSToOutputStream(OS, Moved), Succeeded());240  compareByLine(Result.c_str(), Expected);241}242 243TEST(ElfYamlTextAPI, YAMLWritesNoTBESyms) {244  const char Expected[] = "--- !ifs-v1\n"245                          "IfsVersion:      1.0\n"246                          "SoName:          nosyms.so\n"247                          "Target:          { ObjectFormat: ELF, Arch: x86_64, "248                          "Endianness: little, BitWidth: 64 }\n"249                          "NeededLibs:\n"250                          "  - libc.so\n"251                          "  - libfoo.so\n"252                          "  - libbar.so\n"253                          "Symbols:         []\n"254                          "...\n";255  IFSStub Stub;256  Stub.IfsVersion = VersionTuple(1, 0);257  Stub.SoName = "nosyms.so";258  Stub.Target.Arch = ELF::EM_X86_64;259  Stub.Target.BitWidth = IFSBitWidthType::IFS64;260  Stub.Target.Endianness = IFSEndiannessType::Little;261  Stub.Target.ObjectFormat = "ELF";262  Stub.NeededLibs.push_back("libc.so");263  Stub.NeededLibs.push_back("libfoo.so");264  Stub.NeededLibs.push_back("libbar.so");265 266  std::string Result;267  raw_string_ostream OS(Result);268  ASSERT_THAT_ERROR(writeIFSToOutputStream(OS, Stub), Succeeded());269  compareByLine(Result.c_str(), Expected);270}271