/thirdparty/breakpad/common/linux/synth_elf_unittest.cc

http://github.com/tomahawk-player/tomahawk · C++ · 265 lines · 198 code · 26 blank · 41 comment · 1 complexity · f58f407fb64e4c008bc3e969495e82ca MD5 · raw file

  1. // Copyright (c) 2011 Google Inc.
  2. // All rights reserved.
  3. //
  4. // Redistribution and use in source and binary forms, with or without
  5. // modification, are permitted provided that the following conditions are
  6. // met:
  7. //
  8. // * Redistributions of source code must retain the above copyright
  9. // notice, this list of conditions and the following disclaimer.
  10. // * Redistributions in binary form must reproduce the above
  11. // copyright notice, this list of conditions and the following disclaimer
  12. // in the documentation and/or other materials provided with the
  13. // distribution.
  14. // * Neither the name of Google Inc. nor the names of its
  15. // contributors may be used to endorse or promote products derived from
  16. // this software without specific prior written permission.
  17. //
  18. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. // Original author: Ted Mielczarek <ted.mielczarek@gmail.com>
  30. // synth_elf_unittest.cc:
  31. // Unittests for google_breakpad::synth_elf::ELF
  32. #include <elf.h>
  33. #include "breakpad_googletest_includes.h"
  34. #include "common/linux/synth_elf.h"
  35. using google_breakpad::synth_elf::ELF;
  36. using google_breakpad::synth_elf::StringTable;
  37. using google_breakpad::synth_elf::SymbolTable;
  38. using google_breakpad::test_assembler::Endianness;
  39. using google_breakpad::test_assembler::kBigEndian;
  40. using google_breakpad::test_assembler::kLittleEndian;
  41. using google_breakpad::test_assembler::Label;
  42. using std::string;
  43. using ::testing::Test;
  44. class StringTableTest : public Test {
  45. public:
  46. StringTableTest() : table(kLittleEndian) {}
  47. StringTable table;
  48. };
  49. TEST_F(StringTableTest, Empty) {
  50. EXPECT_EQ(1, table.Size());
  51. string contents;
  52. ASSERT_TRUE(table.GetContents(&contents));
  53. const char* kExpectedContents = "\0";
  54. EXPECT_EQ(0, memcmp(kExpectedContents,
  55. contents.c_str(),
  56. contents.size()));
  57. ASSERT_TRUE(table.empty_string.IsKnownConstant());
  58. EXPECT_EQ(0, table.empty_string.Value());
  59. }
  60. TEST_F(StringTableTest, Basic) {
  61. const string s1("table fills with strings");
  62. const string s2("offsets preserved as labels");
  63. const string s3("verified with tests");
  64. const char* kExpectedContents =
  65. "\0table fills with strings\0"
  66. "offsets preserved as labels\0"
  67. "verified with tests\0";
  68. Label l1(table.Add(s1));
  69. Label l2(table.Add(s2));
  70. Label l3(table.Add(s3));
  71. string contents;
  72. ASSERT_TRUE(table.GetContents(&contents));
  73. EXPECT_EQ(0, memcmp(kExpectedContents,
  74. contents.c_str(),
  75. contents.size()));
  76. // empty_string is at zero, other strings start at 1.
  77. ASSERT_TRUE(l1.IsKnownConstant());
  78. EXPECT_EQ(1, l1.Value());
  79. // Each string has an extra byte for a trailing null.
  80. EXPECT_EQ(1 + s1.length() + 1, l2.Value());
  81. EXPECT_EQ(1 + s1.length() + 1 + s2.length() + 1, l3.Value());
  82. }
  83. TEST_F(StringTableTest, Duplicates) {
  84. const string s1("string 1");
  85. const string s2("string 2");
  86. const string s3("");
  87. const char* kExpectedContents = "\0string 1\0string 2\0";
  88. Label l1(table.Add(s1));
  89. Label l2(table.Add(s2));
  90. // Adding strings twice should return the same Label.
  91. Label l3(table.Add(s3));
  92. Label l4(table.Add(s2));
  93. string contents;
  94. ASSERT_TRUE(table.GetContents(&contents));
  95. EXPECT_EQ(0, memcmp(kExpectedContents,
  96. contents.c_str(),
  97. contents.size()));
  98. EXPECT_EQ(0, table.empty_string.Value());
  99. EXPECT_EQ(table.empty_string.Value(), l3.Value());
  100. EXPECT_EQ(l2.Value(), l4.Value());
  101. }
  102. class SymbolTableTest : public Test {};
  103. TEST_F(SymbolTableTest, Simple32) {
  104. StringTable table(kLittleEndian);
  105. SymbolTable syms(kLittleEndian, 4, table);
  106. const string kFuncName1 = "superfunc";
  107. const uint32_t kFuncAddr1 = 0x10001000;
  108. const uint32_t kFuncSize1 = 0x10;
  109. const string kFuncName2 = "awesomefunc";
  110. const uint32_t kFuncAddr2 = 0x20002000;
  111. const uint32_t kFuncSize2 = 0x2f;
  112. const string kFuncName3 = "megafunc";
  113. const uint32_t kFuncAddr3 = 0x30003000;
  114. const uint32_t kFuncSize3 = 0x3c;
  115. syms.AddSymbol(kFuncName1, kFuncAddr1, kFuncSize1,
  116. ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
  117. SHN_UNDEF + 1);
  118. syms.AddSymbol(kFuncName2, kFuncAddr2, kFuncSize2,
  119. ELF32_ST_INFO(STB_LOCAL, STT_FUNC),
  120. SHN_UNDEF + 2);
  121. syms.AddSymbol(kFuncName3, kFuncAddr3, kFuncSize3,
  122. ELF32_ST_INFO(STB_LOCAL, STT_FUNC),
  123. SHN_UNDEF + 3);
  124. const char kExpectedStringTable[] = "\0superfunc\0awesomefunc\0megafunc";
  125. const size_t kExpectedStringTableSize = sizeof(kExpectedStringTable);
  126. EXPECT_EQ(kExpectedStringTableSize, table.Size());
  127. string table_contents;
  128. table.GetContents(&table_contents);
  129. EXPECT_EQ(0, memcmp(kExpectedStringTable,
  130. table_contents.c_str(),
  131. table_contents.size()));
  132. const uint8_t kExpectedSymbolContents[] = {
  133. // Symbol 1
  134. 0x01, 0x00, 0x00, 0x00, // name
  135. 0x00, 0x10, 0x00, 0x10, // value
  136. 0x10, 0x00, 0x00, 0x00, // size
  137. ELF32_ST_INFO(STB_GLOBAL, STT_FUNC), // info
  138. 0x00, // other
  139. 0x01, 0x00, // shndx
  140. // Symbol 2
  141. 0x0B, 0x00, 0x00, 0x00, // name
  142. 0x00, 0x20, 0x00, 0x20, // value
  143. 0x2f, 0x00, 0x00, 0x00, // size
  144. ELF32_ST_INFO(STB_LOCAL, STT_FUNC), // info
  145. 0x00, // other
  146. 0x02, 0x00, // shndx
  147. // Symbol 3
  148. 0x17, 0x00, 0x00, 0x00, // name
  149. 0x00, 0x30, 0x00, 0x30, // value
  150. 0x3c, 0x00, 0x00, 0x00, // size
  151. ELF32_ST_INFO(STB_LOCAL, STT_FUNC), // info
  152. 0x00, // other
  153. 0x03, 0x00, // shndx
  154. };
  155. const size_t kExpectedSymbolSize = sizeof(kExpectedSymbolContents);
  156. EXPECT_EQ(kExpectedSymbolSize, syms.Size());
  157. string symbol_contents;
  158. syms.GetContents(&symbol_contents);
  159. EXPECT_EQ(0, memcmp(kExpectedSymbolContents,
  160. symbol_contents.c_str(),
  161. symbol_contents.size()));
  162. }
  163. class BasicElf : public Test {};
  164. // Doesn't seem worthwhile writing the tests to be endian-independent
  165. // when they're unlikely to ever be run on big-endian systems.
  166. #if defined(__i386__) || defined(__x86_64__)
  167. TEST_F(BasicElf, EmptyLE32) {
  168. const size_t kStringTableSize = sizeof("\0.shstrtab");
  169. const size_t kStringTableAlign = 4 - kStringTableSize % 4;
  170. const size_t kExpectedSize = sizeof(Elf32_Ehdr) +
  171. // Two sections, SHT_NULL + the section header string table.
  172. 2 * sizeof(Elf32_Shdr) +
  173. kStringTableSize + kStringTableAlign;
  174. ELF elf(EM_386, ELFCLASS32, kLittleEndian);
  175. elf.Finish();
  176. EXPECT_EQ(kExpectedSize, elf.Size());
  177. string contents;
  178. ASSERT_TRUE(elf.GetContents(&contents));
  179. ASSERT_EQ(kExpectedSize, contents.size());
  180. const Elf32_Ehdr* header =
  181. reinterpret_cast<const Elf32_Ehdr*>(contents.data());
  182. const uint8_t kIdent[] = {
  183. ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
  184. ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_SYSV,
  185. 0, 0, 0, 0, 0, 0, 0, 0
  186. };
  187. EXPECT_EQ(0, memcmp(kIdent, header->e_ident, sizeof(kIdent)));
  188. EXPECT_EQ(ET_EXEC, header->e_type);
  189. EXPECT_EQ(EM_386, header->e_machine);
  190. EXPECT_EQ(EV_CURRENT, header->e_version);
  191. EXPECT_EQ(0, header->e_entry);
  192. EXPECT_EQ(0, header->e_phoff);
  193. EXPECT_EQ(sizeof(Elf32_Ehdr) + kStringTableSize + kStringTableAlign,
  194. header->e_shoff);
  195. EXPECT_EQ(0, header->e_flags);
  196. EXPECT_EQ(sizeof(Elf32_Ehdr), header->e_ehsize);
  197. EXPECT_EQ(sizeof(Elf32_Phdr), header->e_phentsize);
  198. EXPECT_EQ(0, header->e_phnum);
  199. EXPECT_EQ(sizeof(Elf32_Shdr), header->e_shentsize);
  200. EXPECT_EQ(2, header->e_shnum);
  201. EXPECT_EQ(1, header->e_shstrndx);
  202. }
  203. TEST_F(BasicElf, EmptyLE64) {
  204. const size_t kStringTableSize = sizeof("\0.shstrtab");
  205. const size_t kStringTableAlign = 4 - kStringTableSize % 4;
  206. const size_t kExpectedSize = sizeof(Elf64_Ehdr) +
  207. // Two sections, SHT_NULL + the section header string table.
  208. 2 * sizeof(Elf64_Shdr) +
  209. kStringTableSize + kStringTableAlign;
  210. ELF elf(EM_X86_64, ELFCLASS64, kLittleEndian);
  211. elf.Finish();
  212. EXPECT_EQ(kExpectedSize, elf.Size());
  213. string contents;
  214. ASSERT_TRUE(elf.GetContents(&contents));
  215. ASSERT_EQ(kExpectedSize, contents.size());
  216. const Elf64_Ehdr* header =
  217. reinterpret_cast<const Elf64_Ehdr*>(contents.data());
  218. const uint8_t kIdent[] = {
  219. ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
  220. ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_SYSV,
  221. 0, 0, 0, 0, 0, 0, 0, 0
  222. };
  223. EXPECT_EQ(0, memcmp(kIdent, header->e_ident, sizeof(kIdent)));
  224. EXPECT_EQ(ET_EXEC, header->e_type);
  225. EXPECT_EQ(EM_X86_64, header->e_machine);
  226. EXPECT_EQ(EV_CURRENT, header->e_version);
  227. EXPECT_EQ(0, header->e_entry);
  228. EXPECT_EQ(0, header->e_phoff);
  229. EXPECT_EQ(sizeof(Elf64_Ehdr) + kStringTableSize + kStringTableAlign,
  230. header->e_shoff);
  231. EXPECT_EQ(0, header->e_flags);
  232. EXPECT_EQ(sizeof(Elf64_Ehdr), header->e_ehsize);
  233. EXPECT_EQ(sizeof(Elf64_Phdr), header->e_phentsize);
  234. EXPECT_EQ(0, header->e_phnum);
  235. EXPECT_EQ(sizeof(Elf64_Shdr), header->e_shentsize);
  236. EXPECT_EQ(2, header->e_shnum);
  237. EXPECT_EQ(1, header->e_shstrndx);
  238. }
  239. #endif // defined(__i386__) || defined(__x86_64__)