Home | History | Annotate | Download | only in linux
      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(&notes_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