• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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:
ELFSymbolsToModuleTestFixture(Endianness endianness,size_t value_size)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 
ProcessSection()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:
ELFSymbolsToModuleTest32()95   ELFSymbolsToModuleTest32() : ELFSymbolsToModuleTestFixture(GetParam(), 4) {}
96 
AddElf32Sym(const string & name,uint32_t value,uint32_t size,unsigned info,uint16_t shndx)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 
TEST_P(ELFSymbolsToModuleTest32,NoFuncs)109 TEST_P(ELFSymbolsToModuleTest32, NoFuncs) {
110   ProcessSection();
111 
112   ASSERT_EQ((size_t)0, externs.size());
113 }
114 
TEST_P(ELFSymbolsToModuleTest32,OneFunc)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 
TEST_P(ELFSymbolsToModuleTest32,NameOutOfBounds)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 
TEST_P(ELFSymbolsToModuleTest32,NonTerminatedStringTable)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 
TEST_P(ELFSymbolsToModuleTest32,MultipleFuncs)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 
TEST_P(ELFSymbolsToModuleTest32,SkipStuff)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:
ELFSymbolsToModuleTest64()265   ELFSymbolsToModuleTest64() : ELFSymbolsToModuleTestFixture(GetParam(), 8) {}
266 
AddElf64Sym(const string & name,uint64_t value,uint64_t size,unsigned info,uint16_t shndx)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 
TEST_P(ELFSymbolsToModuleTest64,NoFuncs)279 TEST_P(ELFSymbolsToModuleTest64, NoFuncs) {
280   ProcessSection();
281 
282   ASSERT_EQ((size_t)0, externs.size());
283 }
284 
TEST_P(ELFSymbolsToModuleTest64,OneFunc)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 
TEST_P(ELFSymbolsToModuleTest64,MultipleFuncs)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 
TEST_P(ELFSymbolsToModuleTest64,SkipStuff)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