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(§ion_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