1 // Copyright 2011 Google LLC
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 // * Neither the name of Google LLC nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 // Original author: Ted Mielczarek <[email protected]>
30
31 // elf_symbols_to_module_unittest.cc:
32 // Unittests for google_breakpad::ELFSymbolsToModule
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h> // Must come first
36 #endif
37
38 #include <elf.h>
39
40 #include <string>
41 #include <vector>
42
43 #include "breakpad_googletest_includes.h"
44 #include "common/linux/elf_symbols_to_module.h"
45 #include "common/linux/synth_elf.h"
46 #include "common/module.h"
47 #include "common/test_assembler.h"
48 #include "common/using_std_string.h"
49
50 using google_breakpad::Module;
51 using google_breakpad::synth_elf::StringTable;
52 using google_breakpad::test_assembler::Endianness;
53 using google_breakpad::test_assembler::kBigEndian;
54 using google_breakpad::test_assembler::kLittleEndian;
55 using google_breakpad::test_assembler::Label;
56 using google_breakpad::test_assembler::Section;
57 using ::testing::Test;
58 using ::testing::TestWithParam;
59 using std::vector;
60
61 class ELFSymbolsToModuleTestFixture {
62 public:
ELFSymbolsToModuleTestFixture(Endianness endianness,size_t value_size)63 ELFSymbolsToModuleTestFixture(Endianness endianness,
64 size_t value_size) : module("a", "b", "c", "d"),
65 section(endianness),
66 table(endianness),
67 value_size(value_size) {}
68
ProcessSection()69 bool ProcessSection() {
70 string section_contents, table_contents;
71 section.GetContents(§ion_contents);
72 table.GetContents(&table_contents);
73
74 bool ret = ELFSymbolsToModule(reinterpret_cast<const uint8_t*>(section_contents.data()),
75 section_contents.size(),
76 reinterpret_cast<const uint8_t*>(table_contents.data()),
77 table_contents.size(),
78 section.endianness() == kBigEndian,
79 value_size,
80 &module);
81 module.GetExterns(&externs, externs.end());
82 return ret;
83 }
84
85 Module module;
86 Section section;
87 StringTable table;
88 string section_contents;
89 // 4 or 8 (bytes)
90 size_t value_size;
91
92 vector<Module::Extern*> externs;
93 };
94
95 class ELFSymbolsToModuleTest32 : public ELFSymbolsToModuleTestFixture,
96 public TestWithParam<Endianness> {
97 public:
ELFSymbolsToModuleTest32()98 ELFSymbolsToModuleTest32() : ELFSymbolsToModuleTestFixture(GetParam(), 4) {}
99
AddElf32Sym(const string & name,uint32_t value,uint32_t size,unsigned info,uint16_t shndx)100 void AddElf32Sym(const string& name, uint32_t value,
101 uint32_t size, unsigned info, uint16_t shndx) {
102 section
103 .D32(table.Add(name))
104 .D32(value)
105 .D32(size)
106 .D8(info)
107 .D8(0) // other
108 .D16(shndx);
109 }
110 };
111
TEST_P(ELFSymbolsToModuleTest32,NoFuncs)112 TEST_P(ELFSymbolsToModuleTest32, NoFuncs) {
113 ProcessSection();
114
115 ASSERT_EQ((size_t)0, externs.size());
116 }
117
TEST_P(ELFSymbolsToModuleTest32,OneFunc)118 TEST_P(ELFSymbolsToModuleTest32, OneFunc) {
119 const string kFuncName = "superfunc";
120 const uint32_t kFuncAddr = 0x1000;
121 const uint32_t kFuncSize = 0x10;
122
123 AddElf32Sym(kFuncName, kFuncAddr, kFuncSize,
124 ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
125 // Doesn't really matter, just can't be SHN_UNDEF.
126 SHN_UNDEF + 1);
127
128 ProcessSection();
129
130 ASSERT_EQ((size_t)1, externs.size());
131 Module::Extern *extern1 = externs[0];
132 EXPECT_EQ(kFuncName, extern1->name);
133 EXPECT_EQ((Module::Address)kFuncAddr, extern1->address);
134 }
135
TEST_P(ELFSymbolsToModuleTest32,NameOutOfBounds)136 TEST_P(ELFSymbolsToModuleTest32, NameOutOfBounds) {
137 const string kFuncName = "";
138 const uint32_t kFuncAddr = 0x1000;
139 const uint32_t kFuncSize = 0x10;
140
141 table.Add("Foo");
142 table.Add("Bar");
143 // Can't use AddElf32Sym because it puts in a valid string offset.
144 section
145 .D32((uint32_t)table.Here().Value() + 1)
146 .D32(kFuncAddr)
147 .D32(kFuncSize)
148 .D8(ELF32_ST_INFO(STB_GLOBAL, STT_FUNC))
149 .D8(0) // other
150 .D16(SHN_UNDEF + 1);
151
152 ProcessSection();
153
154 ASSERT_EQ((size_t)1, externs.size());
155 Module::Extern *extern1 = externs[0];
156 EXPECT_EQ(kFuncName, extern1->name);
157 EXPECT_EQ((Module::Address)kFuncAddr, extern1->address);
158 }
159
TEST_P(ELFSymbolsToModuleTest32,NonTerminatedStringTable)160 TEST_P(ELFSymbolsToModuleTest32, NonTerminatedStringTable) {
161 const string kFuncName = "";
162 const uint32_t kFuncAddr = 0x1000;
163 const uint32_t kFuncSize = 0x10;
164
165 table.Add("Foo");
166 table.Add("Bar");
167 // Add a non-null-terminated string to the end of the string table
168 Label l;
169 table
170 .Mark(&l)
171 .Append("Unterminated");
172 // Can't use AddElf32Sym because it puts in a valid string offset.
173 section
174 .D32((uint32_t)l.Value())
175 .D32(kFuncAddr)
176 .D32(kFuncSize)
177 .D8(ELF32_ST_INFO(STB_GLOBAL, STT_FUNC))
178 .D8(0) // other
179 .D16(SHN_UNDEF + 1);
180
181 ProcessSection();
182
183 ASSERT_EQ((size_t)1, externs.size());
184 Module::Extern *extern1 = externs[0];
185 EXPECT_EQ(kFuncName, extern1->name);
186 EXPECT_EQ((Module::Address)kFuncAddr, extern1->address);
187 }
188
TEST_P(ELFSymbolsToModuleTest32,MultipleFuncs)189 TEST_P(ELFSymbolsToModuleTest32, MultipleFuncs) {
190 const string kFuncName1 = "superfunc";
191 const uint32_t kFuncAddr1 = 0x10001000;
192 const uint32_t kFuncSize1 = 0x10;
193 const string kFuncName2 = "awesomefunc";
194 const uint32_t kFuncAddr2 = 0x20002000;
195 const uint32_t kFuncSize2 = 0x2f;
196 const string kFuncName3 = "megafunc";
197 const uint32_t kFuncAddr3 = 0x30003000;
198 const uint32_t kFuncSize3 = 0x3c;
199
200 AddElf32Sym(kFuncName1, kFuncAddr1, kFuncSize1,
201 ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
202 // Doesn't really matter, just can't be SHN_UNDEF.
203 SHN_UNDEF + 1);
204 AddElf32Sym(kFuncName2, kFuncAddr2, kFuncSize2,
205 ELF32_ST_INFO(STB_LOCAL, STT_FUNC),
206 // Doesn't really matter, just can't be SHN_UNDEF.
207 SHN_UNDEF + 2);
208 AddElf32Sym(kFuncName3, kFuncAddr3, kFuncSize3,
209 ELF32_ST_INFO(STB_LOCAL, STT_FUNC),
210 // Doesn't really matter, just can't be SHN_UNDEF.
211 SHN_UNDEF + 3);
212
213 ProcessSection();
214
215 ASSERT_EQ((size_t)3, externs.size());
216 Module::Extern *extern1 = externs[0];
217 EXPECT_EQ(kFuncName1, extern1->name);
218 EXPECT_EQ((Module::Address)kFuncAddr1, extern1->address);
219 Module::Extern *extern2 = externs[1];
220 EXPECT_EQ(kFuncName2, extern2->name);
221 EXPECT_EQ((Module::Address)kFuncAddr2, extern2->address);
222 Module::Extern *extern3 = externs[2];
223 EXPECT_EQ(kFuncName3, extern3->name);
224 EXPECT_EQ((Module::Address)kFuncAddr3, extern3->address);
225 }
226
TEST_P(ELFSymbolsToModuleTest32,SkipStuff)227 TEST_P(ELFSymbolsToModuleTest32, SkipStuff) {
228 const string kFuncName = "superfunc";
229 const uint32_t kFuncAddr = 0x1000;
230 const uint32_t kFuncSize = 0x10;
231
232 // Should skip functions in SHN_UNDEF
233 AddElf32Sym("skipme", 0xFFFF, 0x10,
234 ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
235 SHN_UNDEF);
236 AddElf32Sym(kFuncName, kFuncAddr, kFuncSize,
237 ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
238 // Doesn't really matter, just can't be SHN_UNDEF.
239 SHN_UNDEF + 1);
240 // Should skip non-STT_FUNC entries.
241 AddElf32Sym("skipmetoo", 0xAAAA, 0x10,
242 ELF32_ST_INFO(STB_GLOBAL, STT_FILE),
243 SHN_UNDEF + 1);
244
245 ProcessSection();
246
247 ASSERT_EQ((size_t)1, externs.size());
248 Module::Extern *extern1 = externs[0];
249 EXPECT_EQ(kFuncName, extern1->name);
250 EXPECT_EQ((Module::Address)kFuncAddr, extern1->address);
251 }
252
253 // Run all the 32-bit tests with both endianness
254 INSTANTIATE_TEST_SUITE_P(Endian,
255 ELFSymbolsToModuleTest32,
256 ::testing::Values(kLittleEndian, kBigEndian));
257
258 // Similar tests, but with 64-bit values. Ostensibly this could be
259 // shoehorned into the parameterization by using ::testing::Combine,
260 // but that would make it difficult to get the types right since these
261 // actual test cases aren't parameterized. This could also be written
262 // as a type-parameterized test, but combining that with a value-parameterized
263 // test seemed really ugly, and also makes it harder to test 64-bit
264 // values.
265 class ELFSymbolsToModuleTest64 : public ELFSymbolsToModuleTestFixture,
266 public TestWithParam<Endianness> {
267 public:
ELFSymbolsToModuleTest64()268 ELFSymbolsToModuleTest64() : ELFSymbolsToModuleTestFixture(GetParam(), 8) {}
269
AddElf64Sym(const string & name,uint64_t value,uint64_t size,unsigned info,uint16_t shndx)270 void AddElf64Sym(const string& name, uint64_t value,
271 uint64_t size, unsigned info, uint16_t shndx) {
272 section
273 .D32(table.Add(name))
274 .D8(info)
275 .D8(0) // other
276 .D16(shndx)
277 .D64(value)
278 .D64(size);
279 }
280 };
281
TEST_P(ELFSymbolsToModuleTest64,NoFuncs)282 TEST_P(ELFSymbolsToModuleTest64, NoFuncs) {
283 ProcessSection();
284
285 ASSERT_EQ((size_t)0, externs.size());
286 }
287
TEST_P(ELFSymbolsToModuleTest64,OneFunc)288 TEST_P(ELFSymbolsToModuleTest64, OneFunc) {
289 const string kFuncName = "superfunc";
290 const uint64_t kFuncAddr = 0x1000200030004000ULL;
291 const uint64_t kFuncSize = 0x1000;
292
293 AddElf64Sym(kFuncName, kFuncAddr, kFuncSize,
294 ELF64_ST_INFO(STB_GLOBAL, STT_FUNC),
295 // Doesn't really matter, just can't be SHN_UNDEF.
296 SHN_UNDEF + 1);
297
298 ProcessSection();
299
300 ASSERT_EQ((size_t)1, externs.size());
301 Module::Extern *extern1 = externs[0];
302 EXPECT_EQ(kFuncName, extern1->name);
303 EXPECT_EQ((Module::Address)kFuncAddr, extern1->address);
304 }
305
TEST_P(ELFSymbolsToModuleTest64,MultipleFuncs)306 TEST_P(ELFSymbolsToModuleTest64, MultipleFuncs) {
307 const string kFuncName1 = "superfunc";
308 const uint64_t kFuncAddr1 = 0x1000100010001000ULL;
309 const uint64_t kFuncSize1 = 0x1000;
310 const string kFuncName2 = "awesomefunc";
311 const uint64_t kFuncAddr2 = 0x2000200020002000ULL;
312 const uint64_t kFuncSize2 = 0x2f00;
313 const string kFuncName3 = "megafunc";
314 const uint64_t kFuncAddr3 = 0x3000300030003000ULL;
315 const uint64_t kFuncSize3 = 0x3c00;
316
317 AddElf64Sym(kFuncName1, kFuncAddr1, kFuncSize1,
318 ELF64_ST_INFO(STB_GLOBAL, STT_FUNC),
319 // Doesn't really matter, just can't be SHN_UNDEF.
320 SHN_UNDEF + 1);
321 AddElf64Sym(kFuncName2, kFuncAddr2, kFuncSize2,
322 ELF64_ST_INFO(STB_LOCAL, STT_FUNC),
323 // Doesn't really matter, just can't be SHN_UNDEF.
324 SHN_UNDEF + 2);
325 AddElf64Sym(kFuncName3, kFuncAddr3, kFuncSize3,
326 ELF64_ST_INFO(STB_LOCAL, STT_FUNC),
327 // Doesn't really matter, just can't be SHN_UNDEF.
328 SHN_UNDEF + 3);
329
330 ProcessSection();
331
332 ASSERT_EQ((size_t)3, externs.size());
333 Module::Extern *extern1 = externs[0];
334 EXPECT_EQ(kFuncName1, extern1->name);
335 EXPECT_EQ((Module::Address)kFuncAddr1, extern1->address);
336 Module::Extern *extern2 = externs[1];
337 EXPECT_EQ(kFuncName2, extern2->name);
338 EXPECT_EQ((Module::Address)kFuncAddr2, extern2->address);
339 Module::Extern *extern3 = externs[2];
340 EXPECT_EQ(kFuncName3, extern3->name);
341 EXPECT_EQ((Module::Address)kFuncAddr3, extern3->address);
342 }
343
TEST_P(ELFSymbolsToModuleTest64,SkipStuff)344 TEST_P(ELFSymbolsToModuleTest64, SkipStuff) {
345 const string kFuncName = "superfunc";
346 const uint64_t kFuncAddr = 0x1000100010001000ULL;
347 const uint64_t kFuncSize = 0x1000;
348
349 // Should skip functions in SHN_UNDEF
350 AddElf64Sym("skipme", 0xFFFF, 0x10,
351 ELF64_ST_INFO(STB_GLOBAL, STT_FUNC),
352 SHN_UNDEF);
353 AddElf64Sym(kFuncName, kFuncAddr, kFuncSize,
354 ELF64_ST_INFO(STB_GLOBAL, STT_FUNC),
355 // Doesn't really matter, just can't be SHN_UNDEF.
356 SHN_UNDEF + 1);
357 // Should skip non-STT_FUNC entries.
358 AddElf64Sym("skipmetoo", 0xAAAA, 0x10,
359 ELF64_ST_INFO(STB_GLOBAL, STT_FILE),
360 SHN_UNDEF + 1);
361
362 ProcessSection();
363
364 ASSERT_EQ((size_t)1, externs.size());
365 Module::Extern *extern1 = externs[0];
366 EXPECT_EQ(kFuncName, extern1->name);
367 EXPECT_EQ((Module::Address)kFuncAddr, extern1->address);
368 }
369
370 // Run all the 64-bit tests with both endianness
371 INSTANTIATE_TEST_SUITE_P(Endian,
372 ELFSymbolsToModuleTest64,
373 ::testing::Values(kLittleEndian, kBigEndian));
374