xref: /aosp_15_r20/external/google-breakpad/src/common/linux/elf_symbols_to_module_unittest.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
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(&section_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