ELFYAMLTest.cpp 8.0 KB

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