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 30 // Original author: Ted Mielczarek <ted.mielczarek (at) gmail.com> 31 32 // synth_elf_unittest.cc: 33 // Unittests for google_breakpad::synth_elf::ELF 34 35 #include <elf.h> 36 37 #include "breakpad_googletest_includes.h" 38 #include "common/linux/elfutils.h" 39 #include "common/linux/synth_elf.h" 40 #include "common/using_std_string.h" 41 42 using google_breakpad::ElfClass32; 43 using google_breakpad::ElfClass64; 44 using google_breakpad::synth_elf::ELF; 45 using google_breakpad::synth_elf::Notes; 46 using google_breakpad::synth_elf::Section; 47 using google_breakpad::synth_elf::StringTable; 48 using google_breakpad::synth_elf::SymbolTable; 49 using google_breakpad::test_assembler::Endianness; 50 using google_breakpad::test_assembler::kBigEndian; 51 using google_breakpad::test_assembler::kLittleEndian; 52 using google_breakpad::test_assembler::Label; 53 using ::testing::Test; 54 using ::testing::Types; 55 56 class StringTableTest : public Test { 57 public: 58 StringTableTest() : table(kLittleEndian) {} 59 60 StringTable table; 61 }; 62 63 TEST_F(StringTableTest, Empty) { 64 EXPECT_EQ(1U, table.Size()); 65 string contents; 66 ASSERT_TRUE(table.GetContents(&contents)); 67 const char* kExpectedContents = "\0"; 68 EXPECT_EQ(0, memcmp(kExpectedContents, 69 contents.c_str(), 70 contents.size())); 71 ASSERT_TRUE(table.empty_string.IsKnownConstant()); 72 EXPECT_EQ(0U, table.empty_string.Value()); 73 } 74 75 TEST_F(StringTableTest, Basic) { 76 const string s1("table fills with strings"); 77 const string s2("offsets preserved as labels"); 78 const string s3("verified with tests"); 79 const char* kExpectedContents = 80 "\0table fills with strings\0" 81 "offsets preserved as labels\0" 82 "verified with tests\0"; 83 Label l1(table.Add(s1)); 84 Label l2(table.Add(s2)); 85 Label l3(table.Add(s3)); 86 string contents; 87 ASSERT_TRUE(table.GetContents(&contents)); 88 EXPECT_EQ(0, memcmp(kExpectedContents, 89 contents.c_str(), 90 contents.size())); 91 // empty_string is at zero, other strings start at 1. 92 ASSERT_TRUE(l1.IsKnownConstant()); 93 EXPECT_EQ(1U, l1.Value()); 94 // Each string has an extra byte for a trailing null. 95 EXPECT_EQ(1 + s1.length() + 1, l2.Value()); 96 EXPECT_EQ(1 + s1.length() + 1 + s2.length() + 1, l3.Value()); 97 } 98 99 TEST_F(StringTableTest, Duplicates) { 100 const string s1("string 1"); 101 const string s2("string 2"); 102 const string s3(""); 103 const char* kExpectedContents = "\0string 1\0string 2\0"; 104 Label l1(table.Add(s1)); 105 Label l2(table.Add(s2)); 106 // Adding strings twice should return the same Label. 107 Label l3(table.Add(s3)); 108 Label l4(table.Add(s2)); 109 string contents; 110 ASSERT_TRUE(table.GetContents(&contents)); 111 EXPECT_EQ(0, memcmp(kExpectedContents, 112 contents.c_str(), 113 contents.size())); 114 EXPECT_EQ(0U, table.empty_string.Value()); 115 EXPECT_EQ(table.empty_string.Value(), l3.Value()); 116 EXPECT_EQ(l2.Value(), l4.Value()); 117 } 118 119 class SymbolTableTest : public Test {}; 120 121 TEST_F(SymbolTableTest, Simple32) { 122 StringTable table(kLittleEndian); 123 SymbolTable syms(kLittleEndian, 4, table); 124 125 const string kFuncName1 = "superfunc"; 126 const uint32_t kFuncAddr1 = 0x10001000; 127 const uint32_t kFuncSize1 = 0x10; 128 const string kFuncName2 = "awesomefunc"; 129 const uint32_t kFuncAddr2 = 0x20002000; 130 const uint32_t kFuncSize2 = 0x2f; 131 const string kFuncName3 = "megafunc"; 132 const uint32_t kFuncAddr3 = 0x30003000; 133 const uint32_t kFuncSize3 = 0x3c; 134 135 syms.AddSymbol(kFuncName1, kFuncAddr1, kFuncSize1, 136 ELF32_ST_INFO(STB_GLOBAL, STT_FUNC), 137 SHN_UNDEF + 1); 138 syms.AddSymbol(kFuncName2, kFuncAddr2, kFuncSize2, 139 ELF32_ST_INFO(STB_LOCAL, STT_FUNC), 140 SHN_UNDEF + 2); 141 syms.AddSymbol(kFuncName3, kFuncAddr3, kFuncSize3, 142 ELF32_ST_INFO(STB_LOCAL, STT_FUNC), 143 SHN_UNDEF + 3); 144 145 const char kExpectedStringTable[] = "\0superfunc\0awesomefunc\0megafunc"; 146 const size_t kExpectedStringTableSize = sizeof(kExpectedStringTable); 147 EXPECT_EQ(kExpectedStringTableSize, table.Size()); 148 string table_contents; 149 table.GetContents(&table_contents); 150 EXPECT_EQ(0, memcmp(kExpectedStringTable, 151 table_contents.c_str(), 152 table_contents.size())); 153 154 const uint8_t kExpectedSymbolContents[] = { 155 // Symbol 1 156 0x01, 0x00, 0x00, 0x00, // name 157 0x00, 0x10, 0x00, 0x10, // value 158 0x10, 0x00, 0x00, 0x00, // size 159 ELF32_ST_INFO(STB_GLOBAL, STT_FUNC), // info 160 0x00, // other 161 0x01, 0x00, // shndx 162 // Symbol 2 163 0x0B, 0x00, 0x00, 0x00, // name 164 0x00, 0x20, 0x00, 0x20, // value 165 0x2f, 0x00, 0x00, 0x00, // size 166 ELF32_ST_INFO(STB_LOCAL, STT_FUNC), // info 167 0x00, // other 168 0x02, 0x00, // shndx 169 // Symbol 3 170 0x17, 0x00, 0x00, 0x00, // name 171 0x00, 0x30, 0x00, 0x30, // value 172 0x3c, 0x00, 0x00, 0x00, // size 173 ELF32_ST_INFO(STB_LOCAL, STT_FUNC), // info 174 0x00, // other 175 0x03, 0x00, // shndx 176 }; 177 const size_t kExpectedSymbolSize = sizeof(kExpectedSymbolContents); 178 EXPECT_EQ(kExpectedSymbolSize, syms.Size()); 179 180 string symbol_contents; 181 syms.GetContents(&symbol_contents); 182 EXPECT_EQ(0, memcmp(kExpectedSymbolContents, 183 symbol_contents.c_str(), 184 symbol_contents.size())); 185 } 186 187 template<typename ElfClass> 188 class BasicElf : public Test {}; 189 190 // Doesn't seem worthwhile writing the tests to be endian-independent 191 // when they're unlikely to ever be run on big-endian systems. 192 #if defined(__i386__) || defined(__x86_64__) 193 194 typedef Types<ElfClass32, ElfClass64> ElfClasses; 195 196 TYPED_TEST_CASE(BasicElf, ElfClasses); 197 198 TYPED_TEST(BasicElf, EmptyLE) { 199 typedef typename TypeParam::Ehdr Ehdr; 200 typedef typename TypeParam::Phdr Phdr; 201 typedef typename TypeParam::Shdr Shdr; 202 const size_t kStringTableSize = sizeof("\0.shstrtab"); 203 const size_t kStringTableAlign = 4 - kStringTableSize % 4; 204 const size_t kExpectedSize = sizeof(Ehdr) + 205 // Two sections, SHT_NULL + the section header string table. 206 2 * sizeof(Shdr) + 207 kStringTableSize + kStringTableAlign; 208 209 // It doesn't really matter that the machine type is right for the class. 210 ELF elf(EM_386, TypeParam::kClass, kLittleEndian); 211 elf.Finish(); 212 EXPECT_EQ(kExpectedSize, elf.Size()); 213 214 string contents; 215 ASSERT_TRUE(elf.GetContents(&contents)); 216 ASSERT_EQ(kExpectedSize, contents.size()); 217 const Ehdr* header = 218 reinterpret_cast<const Ehdr*>(contents.data()); 219 const uint8_t kIdent[] = { 220 ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, 221 TypeParam::kClass, ELFDATA2LSB, EV_CURRENT, ELFOSABI_SYSV, 222 0, 0, 0, 0, 0, 0, 0, 0 223 }; 224 EXPECT_EQ(0, memcmp(kIdent, header->e_ident, sizeof(kIdent))); 225 EXPECT_EQ(ET_EXEC, header->e_type); 226 EXPECT_EQ(EM_386, header->e_machine); 227 EXPECT_EQ(static_cast<unsigned int>(EV_CURRENT), header->e_version); 228 EXPECT_EQ(0U, header->e_entry); 229 EXPECT_EQ(0U, header->e_phoff); 230 EXPECT_EQ(sizeof(Ehdr) + kStringTableSize + kStringTableAlign, 231 header->e_shoff); 232 EXPECT_EQ(0U, header->e_flags); 233 EXPECT_EQ(sizeof(Ehdr), header->e_ehsize); 234 EXPECT_EQ(sizeof(Phdr), header->e_phentsize); 235 EXPECT_EQ(0, header->e_phnum); 236 EXPECT_EQ(sizeof(Shdr), header->e_shentsize); 237 EXPECT_EQ(2, header->e_shnum); 238 EXPECT_EQ(1, header->e_shstrndx); 239 240 const Shdr* shdr = 241 reinterpret_cast<const Shdr*>(contents.data() + header->e_shoff); 242 EXPECT_EQ(0U, shdr[0].sh_name); 243 EXPECT_EQ(static_cast<unsigned int>(SHT_NULL), shdr[0].sh_type); 244 EXPECT_EQ(0U, shdr[0].sh_flags); 245 EXPECT_EQ(0U, shdr[0].sh_addr); 246 EXPECT_EQ(0U, shdr[0].sh_offset); 247 EXPECT_EQ(0U, shdr[0].sh_size); 248 EXPECT_EQ(0U, shdr[0].sh_link); 249 EXPECT_EQ(0U, shdr[0].sh_info); 250 EXPECT_EQ(0U, shdr[0].sh_addralign); 251 EXPECT_EQ(0U, shdr[0].sh_entsize); 252 253 EXPECT_EQ(1U, shdr[1].sh_name); 254 EXPECT_EQ(static_cast<unsigned int>(SHT_STRTAB), shdr[1].sh_type); 255 EXPECT_EQ(0U, shdr[1].sh_flags); 256 EXPECT_EQ(0U, shdr[1].sh_addr); 257 EXPECT_EQ(sizeof(Ehdr), shdr[1].sh_offset); 258 EXPECT_EQ(kStringTableSize, shdr[1].sh_size); 259 EXPECT_EQ(0U, shdr[1].sh_link); 260 EXPECT_EQ(0U, shdr[1].sh_info); 261 EXPECT_EQ(0U, shdr[1].sh_addralign); 262 EXPECT_EQ(0U, shdr[1].sh_entsize); 263 } 264 265 TYPED_TEST(BasicElf, BasicLE) { 266 typedef typename TypeParam::Ehdr Ehdr; 267 typedef typename TypeParam::Phdr Phdr; 268 typedef typename TypeParam::Shdr Shdr; 269 const size_t kStringTableSize = sizeof("\0.text\0.bss\0.shstrtab"); 270 const size_t kStringTableAlign = 4 - kStringTableSize % 4; 271 const size_t kExpectedSize = sizeof(Ehdr) + 272 // Four sections, SHT_NULL + the section header string table + 273 // 4096 bytes of the size-aligned .text section + one program header. 274 sizeof(Phdr) + 4 * sizeof(Shdr) + 4096 + 275 kStringTableSize + kStringTableAlign; 276 277 // It doesn't really matter that the machine type is right for the class. 278 ELF elf(EM_386, TypeParam::kClass, kLittleEndian); 279 Section text(kLittleEndian); 280 text.Append(4094, 0); 281 int text_idx = elf.AddSection(".text", text, SHT_PROGBITS); 282 Section bss(kLittleEndian); 283 bss.Append(16, 0); 284 int bss_idx = elf.AddSection(".bss", bss, SHT_NOBITS); 285 elf.AddSegment(text_idx, bss_idx, PT_LOAD); 286 elf.Finish(); 287 EXPECT_EQ(kExpectedSize, elf.Size()); 288 289 string contents; 290 ASSERT_TRUE(elf.GetContents(&contents)); 291 ASSERT_EQ(kExpectedSize, contents.size()); 292 const Ehdr* header = 293 reinterpret_cast<const Ehdr*>(contents.data()); 294 const uint8_t kIdent[] = { 295 ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, 296 TypeParam::kClass, ELFDATA2LSB, EV_CURRENT, ELFOSABI_SYSV, 297 0, 0, 0, 0, 0, 0, 0, 0 298 }; 299 EXPECT_EQ(0, memcmp(kIdent, header->e_ident, sizeof(kIdent))); 300 EXPECT_EQ(ET_EXEC, header->e_type); 301 EXPECT_EQ(EM_386, header->e_machine); 302 EXPECT_EQ(static_cast<unsigned int>(EV_CURRENT), header->e_version); 303 EXPECT_EQ(0U, header->e_entry); 304 EXPECT_EQ(sizeof(Ehdr), header->e_phoff); 305 EXPECT_EQ(sizeof(Ehdr) + sizeof(Phdr) + 4096 + kStringTableSize + 306 kStringTableAlign, header->e_shoff); 307 EXPECT_EQ(0U, header->e_flags); 308 EXPECT_EQ(sizeof(Ehdr), header->e_ehsize); 309 EXPECT_EQ(sizeof(Phdr), header->e_phentsize); 310 EXPECT_EQ(1, header->e_phnum); 311 EXPECT_EQ(sizeof(Shdr), header->e_shentsize); 312 EXPECT_EQ(4, header->e_shnum); 313 EXPECT_EQ(3, header->e_shstrndx); 314 315 const Shdr* shdr = 316 reinterpret_cast<const Shdr*>(contents.data() + header->e_shoff); 317 EXPECT_EQ(0U, shdr[0].sh_name); 318 EXPECT_EQ(static_cast<unsigned int>(SHT_NULL), shdr[0].sh_type); 319 EXPECT_EQ(0U, shdr[0].sh_flags); 320 EXPECT_EQ(0U, shdr[0].sh_addr); 321 EXPECT_EQ(0U, shdr[0].sh_offset); 322 EXPECT_EQ(0U, shdr[0].sh_size); 323 EXPECT_EQ(0U, shdr[0].sh_link); 324 EXPECT_EQ(0U, shdr[0].sh_info); 325 EXPECT_EQ(0U, shdr[0].sh_addralign); 326 EXPECT_EQ(0U, shdr[0].sh_entsize); 327 328 EXPECT_EQ(1U, shdr[1].sh_name); 329 EXPECT_EQ(static_cast<unsigned int>(SHT_PROGBITS), shdr[1].sh_type); 330 EXPECT_EQ(0U, shdr[1].sh_flags); 331 EXPECT_EQ(0U, shdr[1].sh_addr); 332 EXPECT_EQ(sizeof(Ehdr) + sizeof(Phdr), shdr[1].sh_offset); 333 EXPECT_EQ(4094U, shdr[1].sh_size); 334 EXPECT_EQ(0U, shdr[1].sh_link); 335 EXPECT_EQ(0U, shdr[1].sh_info); 336 EXPECT_EQ(0U, shdr[1].sh_addralign); 337 EXPECT_EQ(0U, shdr[1].sh_entsize); 338 339 EXPECT_EQ(sizeof("\0.text"), shdr[2].sh_name); 340 EXPECT_EQ(static_cast<unsigned int>(SHT_NOBITS), shdr[2].sh_type); 341 EXPECT_EQ(0U, shdr[2].sh_flags); 342 EXPECT_EQ(0U, shdr[2].sh_addr); 343 EXPECT_EQ(0U, shdr[2].sh_offset); 344 EXPECT_EQ(16U, shdr[2].sh_size); 345 EXPECT_EQ(0U, shdr[2].sh_link); 346 EXPECT_EQ(0U, shdr[2].sh_info); 347 EXPECT_EQ(0U, shdr[2].sh_addralign); 348 EXPECT_EQ(0U, shdr[2].sh_entsize); 349 350 EXPECT_EQ(sizeof("\0.text\0.bss"), shdr[3].sh_name); 351 EXPECT_EQ(static_cast<unsigned int>(SHT_STRTAB), shdr[3].sh_type); 352 EXPECT_EQ(0U, shdr[3].sh_flags); 353 EXPECT_EQ(0U, shdr[3].sh_addr); 354 EXPECT_EQ(sizeof(Ehdr) + sizeof(Phdr) + 4096, shdr[3].sh_offset); 355 EXPECT_EQ(kStringTableSize, shdr[3].sh_size); 356 EXPECT_EQ(0U, shdr[3].sh_link); 357 EXPECT_EQ(0U, shdr[3].sh_info); 358 EXPECT_EQ(0U, shdr[3].sh_addralign); 359 EXPECT_EQ(0U, shdr[3].sh_entsize); 360 361 const Phdr* phdr = 362 reinterpret_cast<const Phdr*>(contents.data() + header->e_phoff); 363 EXPECT_EQ(static_cast<unsigned int>(PT_LOAD), phdr->p_type); 364 EXPECT_EQ(sizeof(Ehdr) + sizeof(Phdr), phdr->p_offset); 365 EXPECT_EQ(0U, phdr->p_vaddr); 366 EXPECT_EQ(0U, phdr->p_paddr); 367 EXPECT_EQ(4096U, phdr->p_filesz); 368 EXPECT_EQ(4096U + 16U, phdr->p_memsz); 369 EXPECT_EQ(0U, phdr->p_flags); 370 EXPECT_EQ(0U, phdr->p_align); 371 } 372 373 class ElfNotesTest : public Test {}; 374 375 TEST_F(ElfNotesTest, Empty) { 376 Notes notes(kLittleEndian); 377 string contents; 378 ASSERT_TRUE(notes.GetContents(&contents)); 379 EXPECT_EQ(0U, contents.size()); 380 } 381 382 TEST_F(ElfNotesTest, Notes) { 383 Notes notes(kLittleEndian); 384 notes.AddNote(1, "Linux", reinterpret_cast<const uint8_t *>("\x42\x02\0\0"), 385 4); 386 notes.AddNote(2, "a", reinterpret_cast<const uint8_t *>("foobar"), 387 sizeof("foobar") - 1); 388 389 const uint8_t kExpectedNotesContents[] = { 390 // Note 1 391 0x06, 0x00, 0x00, 0x00, // name size, including terminating zero 392 0x04, 0x00, 0x00, 0x00, // desc size 393 0x01, 0x00, 0x00, 0x00, // type 394 'L', 'i', 'n', 'u', 'x', 0x00, 0x00, 0x00, // padded "Linux" 395 0x42, 0x02, 0x00, 0x00, // desc 396 // Note 2 397 0x02, 0x00, 0x00, 0x00, // name size 398 0x06, 0x00, 0x00, 0x00, // desc size 399 0x02, 0x00, 0x00, 0x00, // type 400 'a', 0x00, 0x00, 0x00, // padded "a" 401 'f', 'o', 'o', 'b', 'a', 'r', 0x00, 0x00, // padded "foobar" 402 }; 403 const size_t kExpectedNotesSize = sizeof(kExpectedNotesContents); 404 EXPECT_EQ(kExpectedNotesSize, notes.Size()); 405 406 string notes_contents; 407 ASSERT_TRUE(notes.GetContents(¬es_contents)); 408 EXPECT_EQ(0, memcmp(kExpectedNotesContents, 409 notes_contents.data(), 410 notes_contents.size())); 411 } 412 413 #endif // defined(__i386__) || defined(__x86_64__) 414