Home | History | Annotate | Download | only in common
      1 // Copyright (c) 2010 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: Jim Blandy <jimb (at) mozilla.com> <jimb (at) red-bean.com>
     31 
     32 // dwarf_line_to_module.cc: Unit tests for google_breakpad::DwarfLineToModule.
     33 
     34 #include <vector>
     35 
     36 #include "breakpad_googletest_includes.h"
     37 #include "common/dwarf_line_to_module.h"
     38 
     39 using std::vector;
     40 
     41 using google_breakpad::DwarfLineToModule;
     42 using google_breakpad::Module;
     43 using google_breakpad::Module;
     44 
     45 TEST(SimpleModule, One) {
     46   Module m("name", "os", "architecture", "id");
     47   vector<Module::Line> lines;
     48   DwarfLineToModule h(&m, "/", &lines);
     49 
     50   h.DefineFile("file1", 0x30bf0f27, 0, 0, 0);
     51   h.AddLine(0x6fd126fbf74f2680LL, 0x63c9a14cf556712bLL, 0x30bf0f27,
     52             0x4c090cbf, 0x1cf9fe0d);
     53 
     54   vector<Module::File *> files;
     55   m.GetFiles(&files);
     56   EXPECT_EQ(1U, files.size());
     57   EXPECT_STREQ("/file1", files[0]->name.c_str());
     58 
     59   EXPECT_EQ(1U, lines.size());
     60   EXPECT_EQ(0x6fd126fbf74f2680ULL, lines[0].address);
     61   EXPECT_EQ(0x63c9a14cf556712bULL, lines[0].size);
     62   EXPECT_TRUE(lines[0].file == files[0]);
     63   EXPECT_EQ(0x4c090cbf, lines[0].number);
     64 }
     65 
     66 TEST(SimpleModule, Many) {
     67   Module m("name", "os", "architecture", "id");
     68   vector<Module::Line> lines;
     69   DwarfLineToModule h(&m, "/", &lines);
     70 
     71   h.DefineDir("directory1", 0x838299ab);
     72   h.DefineDir("directory2", 0xf85de023);
     73   h.DefineFile("file1", 0x2b80377a, 0x838299ab, 0, 0);
     74   h.DefineFile("file1", 0x63beb4a4, 0xf85de023, 0, 0);
     75   h.DefineFile("file2", 0x1d161d56, 0x838299ab, 0, 0);
     76   h.DefineFile("file2", 0x1e7a667c, 0xf85de023, 0, 0);
     77   h.AddLine(0x69900c5d553b7274ULL, 0x90fded183f0d0d3cULL, 0x2b80377a,
     78             0x15b0f0a9U, 0x3ff5abd6U);
     79   h.AddLine(0x45811219a39b7101ULL, 0x25a5e6a924afc41fULL, 0x63beb4a4,
     80             0x4d259ce9U, 0x41c5ee32U);
     81   h.AddLine(0xfa90514c1dc9704bULL, 0x0063efeabc02f313ULL, 0x1d161d56,
     82             0x1ee9fa4fU, 0xbf70e46aU);
     83   h.AddLine(0x556b55fb6a647b10ULL, 0x3f3089ca2bfd80f5ULL, 0x1e7a667c,
     84             0x77fc280eU, 0x2c4a728cU);
     85   h.DefineFile("file3", -1, 0, 0, 0);
     86   h.AddLine(0xe2d72a37f8d9403aULL, 0x034dfab5b0d4d236ULL, 0x63beb4a5,
     87             0x75047044U, 0xb6a0016cU);
     88 
     89   vector<Module::File *> files;
     90   m.GetFiles(&files);
     91   ASSERT_EQ(5U, files.size());
     92   EXPECT_STREQ("/directory1/file1", files[0]->name.c_str());
     93   EXPECT_STREQ("/directory1/file2", files[1]->name.c_str());
     94   EXPECT_STREQ("/directory2/file1", files[2]->name.c_str());
     95   EXPECT_STREQ("/directory2/file2", files[3]->name.c_str());
     96   EXPECT_STREQ("/file3",            files[4]->name.c_str());
     97 
     98   ASSERT_EQ(5U, lines.size());
     99 
    100   EXPECT_EQ(0x69900c5d553b7274ULL, lines[0].address);
    101   EXPECT_EQ(0x90fded183f0d0d3cULL, lines[0].size);
    102   EXPECT_TRUE(lines[0].file == files[0]);
    103   EXPECT_EQ(0x15b0f0a9, lines[0].number);
    104 
    105   EXPECT_EQ(0x45811219a39b7101ULL, lines[1].address);
    106   EXPECT_EQ(0x25a5e6a924afc41fULL, lines[1].size);
    107   EXPECT_TRUE(lines[1].file == files[2]);
    108   EXPECT_EQ(0x4d259ce9, lines[1].number);
    109 
    110   EXPECT_EQ(0xfa90514c1dc9704bULL, lines[2].address);
    111   EXPECT_EQ(0x0063efeabc02f313ULL, lines[2].size);
    112   EXPECT_TRUE(lines[2].file == files[1]);
    113   EXPECT_EQ(0x1ee9fa4f, lines[2].number);
    114 
    115   EXPECT_EQ(0x556b55fb6a647b10ULL, lines[3].address);
    116   EXPECT_EQ(0x3f3089ca2bfd80f5ULL, lines[3].size);
    117   EXPECT_TRUE(lines[3].file == files[3]);
    118   EXPECT_EQ(0x77fc280e, lines[3].number);
    119 
    120   EXPECT_EQ(0xe2d72a37f8d9403aULL, lines[4].address);
    121   EXPECT_EQ(0x034dfab5b0d4d236ULL, lines[4].size);
    122   EXPECT_TRUE(lines[4].file == files[4]);
    123   EXPECT_EQ(0x75047044, lines[4].number);
    124 }
    125 
    126 TEST(Filenames, Absolute) {
    127   Module m("name", "os", "architecture", "id");
    128   vector<Module::Line> lines;
    129   DwarfLineToModule h(&m, "/", &lines);
    130 
    131   h.DefineDir("directory1", 1);
    132   h.DefineFile("/absolute", 1, 1, 0, 0);
    133 
    134   h.AddLine(1, 1, 1, 0, 0);
    135 
    136   vector<Module::File *> files;
    137   m.GetFiles(&files);
    138   ASSERT_EQ(1U, files.size());
    139   EXPECT_STREQ("/absolute", files[0]->name.c_str());
    140   ASSERT_EQ(1U, lines.size());
    141   EXPECT_TRUE(lines[0].file == files[0]);
    142 }
    143 
    144 TEST(Filenames, Relative) {
    145   Module m("name", "os", "architecture", "id");
    146   vector<Module::Line> lines;
    147   DwarfLineToModule h(&m, "/", &lines);
    148 
    149   h.DefineDir("directory1", 1);
    150   h.DefineFile("relative", 1, 1, 0, 0);
    151 
    152   h.AddLine(1, 1, 1, 0, 0);
    153 
    154   vector<Module::File *> files;
    155   m.GetFiles(&files);
    156   ASSERT_EQ(1U, files.size());
    157   EXPECT_STREQ("/directory1/relative", files[0]->name.c_str());
    158   ASSERT_EQ(1U, lines.size());
    159   EXPECT_TRUE(lines[0].file == files[0]);
    160 }
    161 
    162 TEST(Filenames, StrangeFile) {
    163   Module m("name", "os", "architecture", "id");
    164   vector<Module::Line> lines;
    165   DwarfLineToModule h(&m, "/", &lines);
    166 
    167   h.DefineDir("directory1", 1);
    168   h.DefineFile("", 1, 1, 0, 0);
    169   h.AddLine(1, 1, 1, 0, 0);
    170 
    171   ASSERT_EQ(1U, lines.size());
    172   EXPECT_STREQ("/directory1/", lines[0].file->name.c_str());
    173 }
    174 
    175 TEST(Filenames, StrangeDirectory) {
    176   Module m("name", "os", "architecture", "id");
    177   vector<Module::Line> lines;
    178   DwarfLineToModule h(&m, "/", &lines);
    179 
    180   h.DefineDir("", 1);
    181   h.DefineFile("file1", 1, 1, 0, 0);
    182   h.AddLine(1, 1, 1, 0, 0);
    183 
    184   ASSERT_EQ(1U, lines.size());
    185   EXPECT_STREQ("/file1", lines[0].file->name.c_str());
    186 }
    187 
    188 TEST(Filenames, StrangeDirectoryAndFile) {
    189   Module m("name", "os", "architecture", "id");
    190   vector<Module::Line> lines;
    191   DwarfLineToModule h(&m, "/", &lines);
    192 
    193   h.DefineDir("", 1);
    194   h.DefineFile("", 1, 1, 0, 0);
    195   h.AddLine(1, 1, 1, 0, 0);
    196 
    197   ASSERT_EQ(1U, lines.size());
    198   EXPECT_STREQ("/", lines[0].file->name.c_str());
    199 }
    200 
    201 // We should use the compilation directory when encountering a file for
    202 // directory number zero.
    203 TEST(Filenames, DirectoryZeroFileIsRelativeToCompilationDir) {
    204   Module m("name", "os", "architecture", "id");
    205   vector<Module::Line> lines;
    206   DwarfLineToModule h(&m, "src/build", &lines);
    207 
    208   h.DefineDir("Dir", 1);
    209   h.DefineFile("File", 1, 0, 0, 0);
    210 
    211   h.AddLine(1, 1, 1, 0, 0);
    212 
    213   ASSERT_EQ(1U, lines.size());
    214   EXPECT_STREQ("src/build/File", lines[0].file->name.c_str());
    215 }
    216 
    217 // We should treat non-absolute directories as relative to the compilation
    218 // directory.
    219 TEST(Filenames, IncludeDirectoryRelativeToDirectoryZero) {
    220   Module m("name", "os", "architecture", "id");
    221   vector<Module::Line> lines;
    222   DwarfLineToModule h(&m, "src/build", &lines);
    223 
    224   h.DefineDir("Dir", 1);
    225   h.DefineFile("File", 1, 1, 0, 0);
    226 
    227   h.AddLine(1, 1, 1, 0, 0);
    228 
    229   ASSERT_EQ(1U, lines.size());
    230   EXPECT_STREQ("src/build/Dir/File", lines[0].file->name.c_str());
    231 }
    232 
    233 // We should treat absolute directories as absolute, and not relative to
    234 // the compilation dir.
    235 TEST(Filenames, IncludeDirectoryAbsolute) {
    236   Module m("name", "os", "architecture", "id");
    237   vector<Module::Line> lines;
    238   DwarfLineToModule h(&m, "src/build", &lines);
    239 
    240   h.DefineDir("/Dir", 1);
    241   h.DefineFile("File", 1, 1, 0, 0);
    242 
    243   h.AddLine(1, 1, 1, 0, 0);
    244 
    245   ASSERT_EQ(1U, lines.size());
    246   EXPECT_STREQ("/Dir/File", lines[0].file->name.c_str());
    247 }
    248 
    249 // We should silently ignore attempts to define directory number zero,
    250 // since that is always the compilation directory.
    251 TEST(ModuleErrors, DirectoryZero) {
    252   Module m("name", "os", "architecture", "id");
    253   vector<Module::Line> lines;
    254   DwarfLineToModule h(&m, "/", &lines);
    255 
    256   h.DefineDir("directory0", 0); // should be ignored
    257   h.DefineFile("relative", 1, 0, 0, 0);
    258 
    259   h.AddLine(1, 1, 1, 0, 0);
    260 
    261   ASSERT_EQ(1U, lines.size());
    262   EXPECT_STREQ("/relative", lines[0].file->name.c_str());
    263 }
    264 
    265 // We should refuse to add lines with bogus file numbers. We should
    266 // produce only one warning, however.
    267 TEST(ModuleErrors, BadFileNumber) {
    268   Module m("name", "os", "architecture", "id");
    269   vector<Module::Line> lines;
    270   DwarfLineToModule h(&m, "/", &lines);
    271 
    272   h.DefineFile("relative", 1, 0, 0, 0);
    273   h.AddLine(1, 1, 2, 0, 0); // bad file number
    274   h.AddLine(2, 1, 2, 0, 0); // bad file number (no duplicate warning)
    275 
    276   EXPECT_EQ(0U, lines.size());
    277 }
    278 
    279 // We should treat files with bogus directory numbers as relative to
    280 // the compilation unit.
    281 TEST(ModuleErrors, BadDirectoryNumber) {
    282   Module m("name", "os", "architecture", "id");
    283   vector<Module::Line> lines;
    284   DwarfLineToModule h(&m, "/", &lines);
    285 
    286   h.DefineDir("directory1", 1);
    287   h.DefineFile("baddirnumber1", 1, 2, 0, 0); // bad directory number
    288   h.DefineFile("baddirnumber2", 2, 2, 0, 0); // bad dir number (no warning)
    289   h.AddLine(1, 1, 1, 0, 0);
    290 
    291   ASSERT_EQ(1U, lines.size());
    292   EXPECT_STREQ("baddirnumber1", lines[0].file->name.c_str());
    293 }
    294 
    295 // We promise not to report empty lines.
    296 TEST(ModuleErrors, EmptyLine) {
    297   Module m("name", "os", "architecture", "id");
    298   vector<Module::Line> lines;
    299   DwarfLineToModule h(&m, "/", &lines);
    300 
    301   h.DefineFile("filename1", 1, 0, 0, 0);
    302   h.AddLine(1, 0, 1, 0, 0);
    303 
    304   ASSERT_EQ(0U, lines.size());
    305 }
    306 
    307 // We are supposed to clip lines that extend beyond the end of the
    308 // address space.
    309 TEST(ModuleErrors, BigLine) {
    310   Module m("name", "os", "architecture", "id");
    311   vector<Module::Line> lines;
    312   DwarfLineToModule h(&m, "/", &lines);
    313 
    314   h.DefineFile("filename1", 1, 0, 0, 0);
    315   h.AddLine(0xffffffffffffffffULL, 2, 1, 0, 0);
    316 
    317   ASSERT_EQ(1U, lines.size());
    318   EXPECT_EQ(1U, lines[0].size);
    319 }
    320 
    321 // The 'Omitted' tests verify that we correctly omit line information
    322 // for code in sections that the linker has dropped. See "GNU
    323 // toolchain omitted sections support" at the top of the
    324 // DwarfLineToModule class.
    325 
    326 TEST(Omitted, DroppedThenGood) {
    327   Module m("name", "os", "architecture", "id");
    328   vector<Module::Line> lines;
    329   DwarfLineToModule h(&m, "/", &lines);
    330 
    331   h.DefineFile("filename1", 1, 0, 0, 0);
    332   h.AddLine(0,  10, 1, 83816211, 0);   // should be omitted
    333   h.AddLine(20, 10, 1, 13059195, 0);   // should be recorded
    334 
    335   ASSERT_EQ(1U, lines.size());
    336   EXPECT_EQ(13059195, lines[0].number);
    337 }
    338 
    339 TEST(Omitted, GoodThenDropped) {
    340   Module m("name", "os", "architecture", "id");
    341   vector<Module::Line> lines;
    342   DwarfLineToModule h(&m, "/", &lines);
    343 
    344   h.DefineFile("filename1", 1, 0, 0, 0);
    345   h.AddLine(0x9dd6a372, 10, 1, 41454594, 0);   // should be recorded
    346   h.AddLine(0,  10, 1, 44793413, 0);           // should be omitted
    347 
    348   ASSERT_EQ(1U, lines.size());
    349   EXPECT_EQ(41454594, lines[0].number);
    350 }
    351 
    352 TEST(Omitted, Mix1) {
    353   Module m("name", "os", "architecture", "id");
    354   vector<Module::Line> lines;
    355   DwarfLineToModule h(&m, "/", &lines);
    356 
    357   h.DefineFile("filename1", 1, 0, 0, 0);
    358   h.AddLine(0x679ed72f,  10,   1, 58932642, 0);   // should be recorded
    359   h.AddLine(0xdfb5a72d,  10,   1, 39847385, 0);   // should be recorded
    360   h.AddLine(0,           0x78, 1, 23053829, 0);   // should be omitted
    361   h.AddLine(0x78,        0x6a, 1, 65317783, 0);   // should be omitted
    362   h.AddLine(0x78 + 0x6a, 0x2a, 1, 77601423, 0);   // should be omitted
    363   h.AddLine(0x9fe0cea5,  10,   1, 91806582, 0);   // should be recorded
    364   h.AddLine(0x7e41a109,  10,   1, 56169221, 0);   // should be recorded
    365 
    366   ASSERT_EQ(4U, lines.size());
    367   EXPECT_EQ(58932642, lines[0].number);
    368   EXPECT_EQ(39847385, lines[1].number);
    369   EXPECT_EQ(91806582, lines[2].number);
    370   EXPECT_EQ(56169221, lines[3].number);
    371 }
    372 
    373 TEST(Omitted, Mix2) {
    374   Module m("name", "os", "architecture", "id");
    375   vector<Module::Line> lines;
    376   DwarfLineToModule h(&m, "/", &lines);
    377 
    378   h.DefineFile("filename1", 1, 0, 0, 0);
    379   h.AddLine(0,           0xf2, 1, 58802211, 0);   // should be omitted
    380   h.AddLine(0xf2,        0xb9, 1, 78958222, 0);   // should be omitted
    381   h.AddLine(0xf2 + 0xb9, 0xf7, 1, 64861892, 0);   // should be omitted
    382   h.AddLine(0x4e4d271e,  9,    1, 67355743, 0);   // should be recorded
    383   h.AddLine(0xdfb5a72d,  30,   1, 23365776, 0);   // should be recorded
    384   h.AddLine(0,           0x64, 1, 76196762, 0);   // should be omitted
    385   h.AddLine(0x64,        0x33, 1, 71066611, 0);   // should be omitted
    386   h.AddLine(0x64 + 0x33, 0xe3, 1, 61749337, 0);   // should be omitted
    387 
    388   ASSERT_EQ(2U, lines.size());
    389   EXPECT_EQ(67355743, lines[0].number);
    390   EXPECT_EQ(23365776, lines[1].number);
    391 }
    392