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