ELFYAMLTest.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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-exception
  6. //
  7. //===-----------------------------------------------------------------------===/
  8. #include "llvm/ADT/StringRef.h"
  9. #include "llvm/TextAPI/ELF/ELFStub.h"
  10. #include "llvm/TextAPI/ELF/TBEHandler.h"
  11. #include "llvm/Support/Error.h"
  12. #include "llvm/Testing/Support/Error.h"
  13. #include "gtest/gtest.h"
  14. #include <string>
  15. using namespace llvm;
  16. using namespace llvm::ELF;
  17. using namespace llvm::elfabi;
  18. void compareByLine(StringRef LHS, StringRef RHS) {
  19. StringRef Line1;
  20. StringRef Line2;
  21. while (LHS.size() > 0 && RHS.size() > 0) {
  22. std::tie(Line1, LHS) = LHS.split('\n');
  23. std::tie(Line2, RHS) = RHS.split('\n');
  24. // Comparing StringRef objects works, but has messy output when not equal.
  25. // Using STREQ on StringRef.data() doesn't work since these substrings are
  26. // not null terminated.
  27. // This is inefficient, but forces null terminated strings that can be
  28. // cleanly compared.
  29. EXPECT_STREQ(Line1.str().data(), Line2.str().data());
  30. }
  31. }
  32. TEST(ElfYamlTextAPI, YAMLReadableTBE) {
  33. const char Data[] = "--- !tapi-tbe\n"
  34. "TbeVersion: 1.0\n"
  35. "Arch: x86_64\n"
  36. "NeededLibs: [libc.so, libfoo.so, libbar.so]\n"
  37. "Symbols:\n"
  38. " foo: { Type: Func, Undefined: true }\n"
  39. "...\n";
  40. Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
  41. ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded());
  42. std::unique_ptr<ELFStub> Stub = std::move(StubOrErr.get());
  43. EXPECT_NE(Stub.get(), nullptr);
  44. EXPECT_FALSE(Stub->SoName.hasValue());
  45. EXPECT_EQ(Stub->Arch, (uint16_t)llvm::ELF::EM_X86_64);
  46. EXPECT_EQ(Stub->NeededLibs.size(), 3u);
  47. EXPECT_STREQ(Stub->NeededLibs[0].c_str(), "libc.so");
  48. EXPECT_STREQ(Stub->NeededLibs[1].c_str(), "libfoo.so");
  49. EXPECT_STREQ(Stub->NeededLibs[2].c_str(), "libbar.so");
  50. }
  51. TEST(ElfYamlTextAPI, YAMLReadsTBESymbols) {
  52. const char Data[] = "--- !tapi-tbe\n"
  53. "TbeVersion: 1.0\n"
  54. "SoName: test.so\n"
  55. "Arch: x86_64\n"
  56. "Symbols:\n"
  57. " bar: { Type: Object, Size: 42 }\n"
  58. " baz: { Type: TLS, Size: 3 }\n"
  59. " foo: { Type: Func, Warning: \"Deprecated!\" }\n"
  60. " nor: { Type: NoType, Undefined: true }\n"
  61. " not: { Type: File, Undefined: true, Size: 111, "
  62. "Weak: true, Warning: \'All fields populated!\' }\n"
  63. "...\n";
  64. Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
  65. ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded());
  66. std::unique_ptr<ELFStub> Stub = std::move(StubOrErr.get());
  67. EXPECT_NE(Stub.get(), nullptr);
  68. EXPECT_TRUE(Stub->SoName.hasValue());
  69. EXPECT_STREQ(Stub->SoName->c_str(), "test.so");
  70. EXPECT_EQ(Stub->Symbols.size(), 5u);
  71. auto Iterator = Stub->Symbols.begin();
  72. ELFSymbol const &SymBar = *Iterator++;
  73. EXPECT_STREQ(SymBar.Name.c_str(), "bar");
  74. EXPECT_EQ(SymBar.Size, 42u);
  75. EXPECT_EQ(SymBar.Type, ELFSymbolType::Object);
  76. EXPECT_FALSE(SymBar.Undefined);
  77. EXPECT_FALSE(SymBar.Weak);
  78. EXPECT_FALSE(SymBar.Warning.hasValue());
  79. ELFSymbol const &SymBaz = *Iterator++;
  80. EXPECT_STREQ(SymBaz.Name.c_str(), "baz");
  81. EXPECT_EQ(SymBaz.Size, 3u);
  82. EXPECT_EQ(SymBaz.Type, ELFSymbolType::TLS);
  83. EXPECT_FALSE(SymBaz.Undefined);
  84. EXPECT_FALSE(SymBaz.Weak);
  85. EXPECT_FALSE(SymBaz.Warning.hasValue());
  86. ELFSymbol const &SymFoo = *Iterator++;
  87. EXPECT_STREQ(SymFoo.Name.c_str(), "foo");
  88. EXPECT_EQ(SymFoo.Size, 0u);
  89. EXPECT_EQ(SymFoo.Type, ELFSymbolType::Func);
  90. EXPECT_FALSE(SymFoo.Undefined);
  91. EXPECT_FALSE(SymFoo.Weak);
  92. EXPECT_TRUE(SymFoo.Warning.hasValue());
  93. EXPECT_STREQ(SymFoo.Warning->c_str(), "Deprecated!");
  94. ELFSymbol const &SymNor = *Iterator++;
  95. EXPECT_STREQ(SymNor.Name.c_str(), "nor");
  96. EXPECT_EQ(SymNor.Size, 0u);
  97. EXPECT_EQ(SymNor.Type, ELFSymbolType::NoType);
  98. EXPECT_TRUE(SymNor.Undefined);
  99. EXPECT_FALSE(SymNor.Weak);
  100. EXPECT_FALSE(SymNor.Warning.hasValue());
  101. ELFSymbol const &SymNot = *Iterator++;
  102. EXPECT_STREQ(SymNot.Name.c_str(), "not");
  103. EXPECT_EQ(SymNot.Size, 111u);
  104. EXPECT_EQ(SymNot.Type, ELFSymbolType::Unknown);
  105. EXPECT_TRUE(SymNot.Undefined);
  106. EXPECT_TRUE(SymNot.Weak);
  107. EXPECT_TRUE(SymNot.Warning.hasValue());
  108. EXPECT_STREQ(SymNot.Warning->c_str(), "All fields populated!");
  109. }
  110. TEST(ElfYamlTextAPI, YAMLReadsNoTBESyms) {
  111. const char Data[] = "--- !tapi-tbe\n"
  112. "TbeVersion: 1.0\n"
  113. "SoName: test.so\n"
  114. "Arch: x86_64\n"
  115. "Symbols: {}\n"
  116. "...\n";
  117. Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
  118. ASSERT_THAT_ERROR(StubOrErr.takeError(), Succeeded());
  119. std::unique_ptr<ELFStub> Stub = std::move(StubOrErr.get());
  120. EXPECT_NE(Stub.get(), nullptr);
  121. EXPECT_EQ(0u, Stub->Symbols.size());
  122. }
  123. TEST(ElfYamlTextAPI, YAMLUnreadableTBE) {
  124. // Can't read: wrong format/version.
  125. const char Data[] = "--- !tapi-tbz\n"
  126. "TbeVersion: z.3\n"
  127. "SoName: test.so\n"
  128. "Arch: x86_64\n"
  129. "Symbols:\n"
  130. " foo: { Type: Func, Undefined: true }\n";
  131. Expected<std::unique_ptr<ELFStub>> StubOrErr = readTBEFromBuffer(Data);
  132. ASSERT_THAT_ERROR(StubOrErr.takeError(), Failed());
  133. }
  134. TEST(ElfYamlTextAPI, YAMLWritesTBESymbols) {
  135. const char Expected[] =
  136. "--- !tapi-tbe\n"
  137. "TbeVersion: 1.0\n"
  138. "Arch: AArch64\n"
  139. "Symbols:\n"
  140. " bar: { Type: Func, Weak: true }\n"
  141. " foo: { Type: NoType, Size: 99, Warning: Does nothing }\n"
  142. " nor: { Type: Func, Undefined: true }\n"
  143. " not: { Type: Unknown, Size: 12345678901234 }\n"
  144. "...\n";
  145. ELFStub Stub;
  146. Stub.TbeVersion = VersionTuple(1, 0);
  147. Stub.Arch = ELF::EM_AARCH64;
  148. ELFSymbol SymFoo("foo");
  149. SymFoo.Size = 99u;
  150. SymFoo.Type = ELFSymbolType::NoType;
  151. SymFoo.Undefined = false;
  152. SymFoo.Weak = false;
  153. SymFoo.Warning = "Does nothing";
  154. ELFSymbol SymBar("bar");
  155. SymBar.Size = 128u;
  156. SymBar.Type = ELFSymbolType::Func;
  157. SymBar.Undefined = false;
  158. SymBar.Weak = true;
  159. ELFSymbol SymNor("nor");
  160. SymNor.Size = 1234u;
  161. SymNor.Type = ELFSymbolType::Func;
  162. SymNor.Undefined = true;
  163. SymNor.Weak = false;
  164. ELFSymbol SymNot("not");
  165. SymNot.Size = 12345678901234u;
  166. SymNot.Type = ELFSymbolType::Unknown;
  167. SymNot.Undefined = false;
  168. SymNot.Weak = false;
  169. // Deliberately not in order to check that result is sorted.
  170. Stub.Symbols.insert(SymNot);
  171. Stub.Symbols.insert(SymBar);
  172. Stub.Symbols.insert(SymFoo);
  173. Stub.Symbols.insert(SymNor);
  174. // Ensure move constructor works as expected.
  175. ELFStub Moved = std::move(Stub);
  176. std::string Result;
  177. raw_string_ostream OS(Result);
  178. ASSERT_THAT_ERROR(writeTBEToOutputStream(OS, Moved), Succeeded());
  179. Result = OS.str();
  180. compareByLine(Result.c_str(), Expected);
  181. }
  182. TEST(ElfYamlTextAPI, YAMLWritesNoTBESyms) {
  183. const char Expected[] = "--- !tapi-tbe\n"
  184. "TbeVersion: 1.0\n"
  185. "SoName: nosyms.so\n"
  186. "Arch: x86_64\n"
  187. "NeededLibs:\n"
  188. " - libc.so\n"
  189. " - libfoo.so\n"
  190. " - libbar.so\n"
  191. "Symbols: {}\n"
  192. "...\n";
  193. ELFStub Stub;
  194. Stub.TbeVersion = VersionTuple(1, 0);
  195. Stub.SoName = "nosyms.so";
  196. Stub.Arch = ELF::EM_X86_64;
  197. Stub.NeededLibs.push_back("libc.so");
  198. Stub.NeededLibs.push_back("libfoo.so");
  199. Stub.NeededLibs.push_back("libbar.so");
  200. std::string Result;
  201. raw_string_ostream OS(Result);
  202. ASSERT_THAT_ERROR(writeTBEToOutputStream(OS, Stub), Succeeded());
  203. Result = OS.str();
  204. compareByLine(Result.c_str(), Expected);
  205. }