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 // elf_symbols_to_module_unittest.cc:
     33 // Unittests for google_breakpad::ELFSymbolsToModule
     34 
     35 #include <elf.h>
     36 
     37 #include <string>
     38 #include <vector>
     39 
     40 #include "breakpad_googletest_includes.h"
     41 #include "common/linux/elf_symbols_to_module.h"
     42 #include "common/linux/synth_elf.h"
     43 #include "common/module.h"
     44 #include "common/test_assembler.h"
     45 #include "common/using_std_string.h"
     46 
     47 using google_breakpad::Module;
     48 using google_breakpad::synth_elf::StringTable;
     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 google_breakpad::test_assembler::Section;
     54 using ::testing::Test;
     55 using ::testing::TestWithParam;
     56 using std::vector;
     57 
     58 class ELFSymbolsToModuleTestFixture {
     59 public:
     60   ELFSymbolsToModuleTestFixture(Endianness endianness,
     61                                 size_t value_size) : module("a", "b", "c", "d"),
     62                                                      section(endianness),
     63                                                      table(endianness),
     64                                                      value_size(value_size) {}
     65 
     66   bool ProcessSection() {
     67     string section_contents, table_contents;
     68     section.GetContents(&section_contents);
     69     table.GetContents(&table_contents);
     70 
     71     bool ret = ELFSymbolsToModule(reinterpret_cast<const uint8_t*>(section_contents.data()),
     72                                   section_contents.size(),
     73                                   reinterpret_cast<const uint8_t*>(table_contents.data()),
     74                                   table_contents.size(),
     75                                   section.endianness() == kBigEndian,
     76                                   value_size,
     77                                   &module);
     78     module.GetExterns(&externs, externs.end());
     79     return ret;
     80   }
     81 
     82   Module module;
     83   Section section;
     84   StringTable table;
     85   string section_contents;
     86   // 4 or 8 (bytes)
     87   size_t value_size;
     88 
     89   vector<Module::Extern *> externs;
     90 };
     91 
     92 class ELFSymbolsToModuleTest32 : public ELFSymbolsToModuleTestFixture,
     93                                    public TestWithParam<Endianness>  {
     94 public:
     95   ELFSymbolsToModuleTest32() : ELFSymbolsToModuleTestFixture(GetParam(), 4) {}
     96 
     97   void AddElf32Sym(const string& name, uint32_t value,
     98                    uint32_t size, unsigned info, uint16_t shndx) {
     99     section
    100       .D32(table.Add(name))
    101       .D32(value)
    102       .D32(size)
    103       .D8(info)
    104       .D8(0) // other
    105       .D16(shndx);
    106   }
    107 };
    108 
    109 TEST_P(ELFSymbolsToModuleTest32, NoFuncs) {
    110   ProcessSection();
    111 
    112   ASSERT_EQ((size_t)0, externs.size());
    113 }
    114 
    115 TEST_P(ELFSymbolsToModuleTest32, OneFunc) {
    116   const string kFuncName = "superfunc";
    117   const uint32_t kFuncAddr = 0x1000;
    118   const uint32_t kFuncSize = 0x10;
    119 
    120   AddElf32Sym(kFuncName, kFuncAddr, kFuncSize,
    121               ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
    122               // Doesn't really matter, just can't be SHN_UNDEF.
    123               SHN_UNDEF + 1);
    124 
    125   ProcessSection();
    126 
    127   ASSERT_EQ((size_t)1, externs.size());
    128   Module::Extern *extern1 = externs[0];
    129   EXPECT_EQ(kFuncName, extern1->name);
    130   EXPECT_EQ((Module::Address)kFuncAddr, extern1->address);
    131 }
    132 
    133 TEST_P(ELFSymbolsToModuleTest32, NameOutOfBounds) {
    134   const string kFuncName = "";
    135   const uint32_t kFuncAddr = 0x1000;
    136   const uint32_t kFuncSize = 0x10;
    137 
    138   table.Add("Foo");
    139   table.Add("Bar");
    140   // Can't use AddElf32Sym because it puts in a valid string offset.
    141   section
    142     .D32((uint32_t)table.Here().Value() + 1)
    143     .D32(kFuncAddr)
    144     .D32(kFuncSize)
    145     .D8(ELF32_ST_INFO(STB_GLOBAL, STT_FUNC))
    146     .D8(0) // other
    147     .D16(SHN_UNDEF + 1);
    148 
    149   ProcessSection();
    150 
    151   ASSERT_EQ((size_t)1, externs.size());
    152   Module::Extern *extern1 = externs[0];
    153   EXPECT_EQ(kFuncName, extern1->name);
    154   EXPECT_EQ((Module::Address)kFuncAddr, extern1->address);
    155 }
    156 
    157 TEST_P(ELFSymbolsToModuleTest32, NonTerminatedStringTable) {
    158   const string kFuncName = "";
    159   const uint32_t kFuncAddr = 0x1000;
    160   const uint32_t kFuncSize = 0x10;
    161 
    162   table.Add("Foo");
    163   table.Add("Bar");
    164   // Add a non-null-terminated string to the end of the string table
    165   Label l;
    166   table
    167     .Mark(&l)
    168     .Append("Unterminated");
    169   // Can't use AddElf32Sym because it puts in a valid string offset.
    170   section
    171     .D32((uint32_t)l.Value())
    172     .D32(kFuncAddr)
    173     .D32(kFuncSize)
    174     .D8(ELF32_ST_INFO(STB_GLOBAL, STT_FUNC))
    175     .D8(0) // other
    176     .D16(SHN_UNDEF + 1);
    177 
    178   ProcessSection();
    179 
    180   ASSERT_EQ((size_t)1, externs.size());
    181   Module::Extern *extern1 = externs[0];
    182   EXPECT_EQ(kFuncName, extern1->name);
    183   EXPECT_EQ((Module::Address)kFuncAddr, extern1->address);
    184 }
    185 
    186 TEST_P(ELFSymbolsToModuleTest32, MultipleFuncs) {
    187   const string kFuncName1 = "superfunc";
    188   const uint32_t kFuncAddr1 = 0x10001000;
    189   const uint32_t kFuncSize1 = 0x10;
    190   const string kFuncName2 = "awesomefunc";
    191   const uint32_t kFuncAddr2 = 0x20002000;
    192   const uint32_t kFuncSize2 = 0x2f;
    193   const string kFuncName3 = "megafunc";
    194   const uint32_t kFuncAddr3 = 0x30003000;
    195   const uint32_t kFuncSize3 = 0x3c;
    196 
    197   AddElf32Sym(kFuncName1, kFuncAddr1, kFuncSize1,
    198               ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
    199               // Doesn't really matter, just can't be SHN_UNDEF.
    200               SHN_UNDEF + 1);
    201   AddElf32Sym(kFuncName2, kFuncAddr2, kFuncSize2,
    202               ELF32_ST_INFO(STB_LOCAL, STT_FUNC),
    203               // Doesn't really matter, just can't be SHN_UNDEF.
    204               SHN_UNDEF + 2);
    205   AddElf32Sym(kFuncName3, kFuncAddr3, kFuncSize3,
    206               ELF32_ST_INFO(STB_LOCAL, STT_FUNC),
    207               // Doesn't really matter, just can't be SHN_UNDEF.
    208               SHN_UNDEF + 3);
    209 
    210   ProcessSection();
    211 
    212   ASSERT_EQ((size_t)3, externs.size());
    213   Module::Extern *extern1 = externs[0];
    214   EXPECT_EQ(kFuncName1, extern1->name);
    215   EXPECT_EQ((Module::Address)kFuncAddr1, extern1->address);
    216   Module::Extern *extern2 = externs[1];
    217   EXPECT_EQ(kFuncName2, extern2->name);
    218   EXPECT_EQ((Module::Address)kFuncAddr2, extern2->address);
    219   Module::Extern *extern3 = externs[2];
    220   EXPECT_EQ(kFuncName3, extern3->name);
    221   EXPECT_EQ((Module::Address)kFuncAddr3, extern3->address);
    222 }
    223 
    224 TEST_P(ELFSymbolsToModuleTest32, SkipStuff) {
    225   const string kFuncName = "superfunc";
    226   const uint32_t kFuncAddr = 0x1000;
    227   const uint32_t kFuncSize = 0x10;
    228 
    229   // Should skip functions in SHN_UNDEF
    230   AddElf32Sym("skipme", 0xFFFF, 0x10,
    231               ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
    232               SHN_UNDEF);
    233   AddElf32Sym(kFuncName, kFuncAddr, kFuncSize,
    234               ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
    235               // Doesn't really matter, just can't be SHN_UNDEF.
    236               SHN_UNDEF + 1);
    237   // Should skip non-STT_FUNC entries.
    238   AddElf32Sym("skipmetoo", 0xAAAA, 0x10,
    239               ELF32_ST_INFO(STB_GLOBAL, STT_FILE),
    240               SHN_UNDEF + 1);
    241 
    242   ProcessSection();
    243 
    244   ASSERT_EQ((size_t)1, externs.size());
    245   Module::Extern *extern1 = externs[0];
    246   EXPECT_EQ(kFuncName, extern1->name);
    247   EXPECT_EQ((Module::Address)kFuncAddr, extern1->address);
    248 }
    249 
    250 // Run all the 32-bit tests with both endianness
    251 INSTANTIATE_TEST_CASE_P(Endian,
    252                         ELFSymbolsToModuleTest32,
    253                         ::testing::Values(kLittleEndian, kBigEndian));
    254 
    255 // Similar tests, but with 64-bit values. Ostensibly this could be
    256 // shoehorned into the parameterization by using ::testing::Combine,
    257 // but that would make it difficult to get the types right since these
    258 // actual test cases aren't parameterized. This could also be written
    259 // as a type-parameterized test, but combining that with a value-parameterized
    260 // test seemed really ugly, and also makes it harder to test 64-bit
    261 // values.
    262 class ELFSymbolsToModuleTest64 : public ELFSymbolsToModuleTestFixture,
    263                                  public TestWithParam<Endianness>  {
    264 public:
    265   ELFSymbolsToModuleTest64() : ELFSymbolsToModuleTestFixture(GetParam(), 8) {}
    266 
    267   void AddElf64Sym(const string& name, uint64_t value,
    268                    uint64_t size, unsigned info, uint16_t shndx) {
    269     section
    270       .D32(table.Add(name))
    271       .D8(info)
    272       .D8(0) // other
    273       .D16(shndx)
    274       .D64(value)
    275       .D64(size);
    276   }
    277 };
    278 
    279 TEST_P(ELFSymbolsToModuleTest64, NoFuncs) {
    280   ProcessSection();
    281 
    282   ASSERT_EQ((size_t)0, externs.size());
    283 }
    284 
    285 TEST_P(ELFSymbolsToModuleTest64, OneFunc) {
    286   const string kFuncName = "superfunc";
    287   const uint64_t kFuncAddr = 0x1000200030004000ULL;
    288   const uint64_t kFuncSize = 0x1000;
    289 
    290   AddElf64Sym(kFuncName, kFuncAddr, kFuncSize,
    291               ELF64_ST_INFO(STB_GLOBAL, STT_FUNC),
    292               // Doesn't really matter, just can't be SHN_UNDEF.
    293               SHN_UNDEF + 1);
    294 
    295   ProcessSection();
    296 
    297   ASSERT_EQ((size_t)1, externs.size());
    298   Module::Extern *extern1 = externs[0];
    299   EXPECT_EQ(kFuncName, extern1->name);
    300   EXPECT_EQ((Module::Address)kFuncAddr, extern1->address);
    301 }
    302 
    303 TEST_P(ELFSymbolsToModuleTest64, MultipleFuncs) {
    304   const string kFuncName1 = "superfunc";
    305   const uint64_t kFuncAddr1 = 0x1000100010001000ULL;
    306   const uint64_t kFuncSize1 = 0x1000;
    307   const string kFuncName2 = "awesomefunc";
    308   const uint64_t kFuncAddr2 = 0x2000200020002000ULL;
    309   const uint64_t kFuncSize2 = 0x2f00;
    310   const string kFuncName3 = "megafunc";
    311   const uint64_t kFuncAddr3 = 0x3000300030003000ULL;
    312   const uint64_t kFuncSize3 = 0x3c00;
    313 
    314   AddElf64Sym(kFuncName1, kFuncAddr1, kFuncSize1,
    315               ELF64_ST_INFO(STB_GLOBAL, STT_FUNC),
    316               // Doesn't really matter, just can't be SHN_UNDEF.
    317               SHN_UNDEF + 1);
    318   AddElf64Sym(kFuncName2, kFuncAddr2, kFuncSize2,
    319               ELF64_ST_INFO(STB_LOCAL, STT_FUNC),
    320               // Doesn't really matter, just can't be SHN_UNDEF.
    321               SHN_UNDEF + 2);
    322   AddElf64Sym(kFuncName3, kFuncAddr3, kFuncSize3,
    323               ELF64_ST_INFO(STB_LOCAL, STT_FUNC),
    324               // Doesn't really matter, just can't be SHN_UNDEF.
    325               SHN_UNDEF + 3);
    326 
    327   ProcessSection();
    328 
    329   ASSERT_EQ((size_t)3, externs.size());
    330   Module::Extern *extern1 = externs[0];
    331   EXPECT_EQ(kFuncName1, extern1->name);
    332   EXPECT_EQ((Module::Address)kFuncAddr1, extern1->address);
    333   Module::Extern *extern2 = externs[1];
    334   EXPECT_EQ(kFuncName2, extern2->name);
    335   EXPECT_EQ((Module::Address)kFuncAddr2, extern2->address);
    336   Module::Extern *extern3 = externs[2];
    337   EXPECT_EQ(kFuncName3, extern3->name);
    338   EXPECT_EQ((Module::Address)kFuncAddr3, extern3->address);
    339 }
    340 
    341 TEST_P(ELFSymbolsToModuleTest64, SkipStuff) {
    342   const string kFuncName = "superfunc";
    343   const uint64_t kFuncAddr = 0x1000100010001000ULL;
    344   const uint64_t kFuncSize = 0x1000;
    345 
    346   // Should skip functions in SHN_UNDEF
    347   AddElf64Sym("skipme", 0xFFFF, 0x10,
    348               ELF64_ST_INFO(STB_GLOBAL, STT_FUNC),
    349               SHN_UNDEF);
    350   AddElf64Sym(kFuncName, kFuncAddr, kFuncSize,
    351               ELF64_ST_INFO(STB_GLOBAL, STT_FUNC),
    352               // Doesn't really matter, just can't be SHN_UNDEF.
    353               SHN_UNDEF + 1);
    354   // Should skip non-STT_FUNC entries.
    355   AddElf64Sym("skipmetoo", 0xAAAA, 0x10,
    356               ELF64_ST_INFO(STB_GLOBAL, STT_FILE),
    357               SHN_UNDEF + 1);
    358 
    359   ProcessSection();
    360 
    361   ASSERT_EQ((size_t)1, externs.size());
    362   Module::Extern *extern1 = externs[0];
    363   EXPECT_EQ(kFuncName, extern1->name);
    364   EXPECT_EQ((Module::Address)kFuncAddr, extern1->address);
    365 }
    366 
    367 // Run all the 64-bit tests with both endianness
    368 INSTANTIATE_TEST_CASE_P(Endian,
    369                         ELFSymbolsToModuleTest64,
    370                         ::testing::Values(kLittleEndian, kBigEndian));
    371