xref: /aosp_15_r20/external/google-breakpad/src/common/linux/synth_elf_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 // synth_elf_unittest.cc:
32 // Unittests for google_breakpad::synth_elf::ELF
33 
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>  // Must come first
36 #endif
37 
38 #include <elf.h>
39 
40 #include "breakpad_googletest_includes.h"
41 #include "common/linux/elfutils.h"
42 #include "common/linux/synth_elf.h"
43 #include "common/using_std_string.h"
44 
45 using google_breakpad::ElfClass32;
46 using google_breakpad::ElfClass64;
47 using google_breakpad::synth_elf::ELF;
48 using google_breakpad::synth_elf::Notes;
49 using google_breakpad::synth_elf::Section;
50 using google_breakpad::synth_elf::StringTable;
51 using google_breakpad::synth_elf::SymbolTable;
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 ::testing::Test;
57 using ::testing::Types;
58 
59 class StringTableTest : public Test {
60 public:
StringTableTest()61   StringTableTest() : table(kLittleEndian) {}
62 
63   StringTable table;
64 };
65 
TEST_F(StringTableTest,Empty)66 TEST_F(StringTableTest, Empty) {
67   EXPECT_EQ(1U, table.Size());
68   string contents;
69   ASSERT_TRUE(table.GetContents(&contents));
70   const char* kExpectedContents = "\0";
71   EXPECT_EQ(0, memcmp(kExpectedContents,
72                       contents.c_str(),
73                       contents.size()));
74   ASSERT_TRUE(table.empty_string.IsKnownConstant());
75   EXPECT_EQ(0U, table.empty_string.Value());
76 }
77 
TEST_F(StringTableTest,Basic)78 TEST_F(StringTableTest, Basic) {
79   const string s1("table fills with strings");
80   const string s2("offsets preserved as labels");
81   const string s3("verified with tests");
82   const char* kExpectedContents =
83     "\0table fills with strings\0"
84     "offsets preserved as labels\0"
85     "verified with tests\0";
86   Label l1(table.Add(s1));
87   Label l2(table.Add(s2));
88   Label l3(table.Add(s3));
89   string contents;
90   ASSERT_TRUE(table.GetContents(&contents));
91   EXPECT_EQ(0, memcmp(kExpectedContents,
92                       contents.c_str(),
93                       contents.size()));
94   // empty_string is at zero, other strings start at 1.
95   ASSERT_TRUE(l1.IsKnownConstant());
96   EXPECT_EQ(1U, l1.Value());
97   // Each string has an extra byte for a trailing null.
98   EXPECT_EQ(1 + s1.length() + 1, l2.Value());
99   EXPECT_EQ(1 + s1.length() + 1 + s2.length() + 1, l3.Value());
100 }
101 
TEST_F(StringTableTest,Duplicates)102 TEST_F(StringTableTest, Duplicates) {
103   const string s1("string 1");
104   const string s2("string 2");
105   const string s3("");
106   const char* kExpectedContents = "\0string 1\0string 2\0";
107   Label l1(table.Add(s1));
108   Label l2(table.Add(s2));
109   // Adding strings twice should return the same Label.
110   Label l3(table.Add(s3));
111   Label l4(table.Add(s2));
112   string contents;
113   ASSERT_TRUE(table.GetContents(&contents));
114   EXPECT_EQ(0, memcmp(kExpectedContents,
115                       contents.c_str(),
116                       contents.size()));
117   EXPECT_EQ(0U, table.empty_string.Value());
118   EXPECT_EQ(table.empty_string.Value(), l3.Value());
119   EXPECT_EQ(l2.Value(), l4.Value());
120 }
121 
122 class SymbolTableTest : public Test {};
123 
TEST_F(SymbolTableTest,Simple32)124 TEST_F(SymbolTableTest, Simple32) {
125   StringTable table(kLittleEndian);
126   SymbolTable syms(kLittleEndian, 4, table);
127 
128   const string kFuncName1 = "superfunc";
129   const uint32_t kFuncAddr1 = 0x10001000;
130   const uint32_t kFuncSize1 = 0x10;
131   const string kFuncName2 = "awesomefunc";
132   const uint32_t kFuncAddr2 = 0x20002000;
133   const uint32_t kFuncSize2 = 0x2f;
134   const string kFuncName3 = "megafunc";
135   const uint32_t kFuncAddr3 = 0x30003000;
136   const uint32_t kFuncSize3 = 0x3c;
137 
138   syms.AddSymbol(kFuncName1, kFuncAddr1, kFuncSize1,
139                  ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
140                  SHN_UNDEF + 1);
141   syms.AddSymbol(kFuncName2, kFuncAddr2, kFuncSize2,
142                  ELF32_ST_INFO(STB_LOCAL, STT_FUNC),
143                  SHN_UNDEF + 2);
144   syms.AddSymbol(kFuncName3, kFuncAddr3, kFuncSize3,
145                  ELF32_ST_INFO(STB_LOCAL, STT_FUNC),
146                  SHN_UNDEF + 3);
147 
148   const char kExpectedStringTable[] = "\0superfunc\0awesomefunc\0megafunc";
149   const size_t kExpectedStringTableSize = sizeof(kExpectedStringTable);
150   EXPECT_EQ(kExpectedStringTableSize, table.Size());
151   string table_contents;
152   table.GetContents(&table_contents);
153   EXPECT_EQ(0, memcmp(kExpectedStringTable,
154                       table_contents.c_str(),
155                       table_contents.size()));
156 
157   const uint8_t kExpectedSymbolContents[] = {
158     // Symbol 1
159     0x01, 0x00, 0x00, 0x00, // name
160     0x00, 0x10, 0x00, 0x10, // value
161     0x10, 0x00, 0x00, 0x00, // size
162     ELF32_ST_INFO(STB_GLOBAL, STT_FUNC), // info
163     0x00, // other
164     0x01, 0x00, // shndx
165     // Symbol 2
166     0x0B, 0x00, 0x00, 0x00, // name
167     0x00, 0x20, 0x00, 0x20, // value
168     0x2f, 0x00, 0x00, 0x00, // size
169     ELF32_ST_INFO(STB_LOCAL, STT_FUNC), // info
170     0x00, // other
171     0x02, 0x00, // shndx
172     // Symbol 3
173     0x17, 0x00, 0x00, 0x00, // name
174     0x00, 0x30, 0x00, 0x30, // value
175     0x3c, 0x00, 0x00, 0x00, // size
176     ELF32_ST_INFO(STB_LOCAL, STT_FUNC), // info
177     0x00, // other
178     0x03, 0x00, // shndx
179   };
180   const size_t kExpectedSymbolSize = sizeof(kExpectedSymbolContents);
181   EXPECT_EQ(kExpectedSymbolSize, syms.Size());
182 
183   string symbol_contents;
184   syms.GetContents(&symbol_contents);
185   EXPECT_EQ(0, memcmp(kExpectedSymbolContents,
186                       symbol_contents.c_str(),
187                       symbol_contents.size()));
188 }
189 
190 template<typename ElfClass>
191 class BasicElf : public Test {};
192 
193 // Doesn't seem worthwhile writing the tests to be endian-independent
194 // when they're unlikely to ever be run on big-endian systems.
195 #if defined(__i386__) || defined(__x86_64__)
196 
197 typedef Types<ElfClass32, ElfClass64> ElfClasses;
198 
199 TYPED_TEST_SUITE(BasicElf, ElfClasses);
200 
TYPED_TEST(BasicElf,EmptyLE)201 TYPED_TEST(BasicElf, EmptyLE) {
202   typedef typename TypeParam::Ehdr Ehdr;
203   typedef typename TypeParam::Phdr Phdr;
204   typedef typename TypeParam::Shdr Shdr;
205   const size_t kStringTableSize = sizeof("\0.shstrtab");
206   const size_t kStringTableAlign = 4 - kStringTableSize % 4;
207   const size_t kExpectedSize = sizeof(Ehdr) +
208     // Two sections, SHT_NULL + the section header string table.
209     2 * sizeof(Shdr) +
210     kStringTableSize + kStringTableAlign;
211 
212   // It doesn't really matter that the machine type is right for the class.
213   ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
214   elf.Finish();
215   EXPECT_EQ(kExpectedSize, elf.Size());
216 
217   string contents;
218   ASSERT_TRUE(elf.GetContents(&contents));
219   ASSERT_EQ(kExpectedSize, contents.size());
220   const Ehdr* header =
221     reinterpret_cast<const Ehdr*>(contents.data());
222   const uint8_t kIdent[] = {
223     ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
224     TypeParam::kClass, ELFDATA2LSB, EV_CURRENT, ELFOSABI_SYSV,
225     0, 0, 0, 0, 0, 0, 0, 0
226   };
227   EXPECT_EQ(0, memcmp(kIdent, header->e_ident, sizeof(kIdent)));
228   EXPECT_EQ(ET_EXEC, header->e_type);
229   EXPECT_EQ(EM_386, header->e_machine);
230   EXPECT_EQ(static_cast<unsigned int>(EV_CURRENT), header->e_version);
231   EXPECT_EQ(0U, header->e_entry);
232   EXPECT_EQ(0U, header->e_phoff);
233   EXPECT_EQ(sizeof(Ehdr) + kStringTableSize + kStringTableAlign,
234             header->e_shoff);
235   EXPECT_EQ(0U, header->e_flags);
236   EXPECT_EQ(sizeof(Ehdr), header->e_ehsize);
237   EXPECT_EQ(sizeof(Phdr), header->e_phentsize);
238   EXPECT_EQ(0, header->e_phnum);
239   EXPECT_EQ(sizeof(Shdr), header->e_shentsize);
240   EXPECT_EQ(2, header->e_shnum);
241   EXPECT_EQ(1, header->e_shstrndx);
242 
243   const Shdr* shdr =
244     reinterpret_cast<const Shdr*>(contents.data() + header->e_shoff);
245   EXPECT_EQ(0U, shdr[0].sh_name);
246   EXPECT_EQ(static_cast<unsigned int>(SHT_NULL), shdr[0].sh_type);
247   EXPECT_EQ(0U, shdr[0].sh_flags);
248   EXPECT_EQ(0U, shdr[0].sh_addr);
249   EXPECT_EQ(0U, shdr[0].sh_offset);
250   EXPECT_EQ(0U, shdr[0].sh_size);
251   EXPECT_EQ(0U, shdr[0].sh_link);
252   EXPECT_EQ(0U, shdr[0].sh_info);
253   EXPECT_EQ(0U, shdr[0].sh_addralign);
254   EXPECT_EQ(0U, shdr[0].sh_entsize);
255 
256   EXPECT_EQ(1U, shdr[1].sh_name);
257   EXPECT_EQ(static_cast<unsigned int>(SHT_STRTAB), shdr[1].sh_type);
258   EXPECT_EQ(0U, shdr[1].sh_flags);
259   EXPECT_EQ(0U, shdr[1].sh_addr);
260   EXPECT_EQ(sizeof(Ehdr), shdr[1].sh_offset);
261   EXPECT_EQ(kStringTableSize, shdr[1].sh_size);
262   EXPECT_EQ(0U, shdr[1].sh_link);
263   EXPECT_EQ(0U, shdr[1].sh_info);
264   EXPECT_EQ(0U, shdr[1].sh_addralign);
265   EXPECT_EQ(0U, shdr[1].sh_entsize);
266 }
267 
TYPED_TEST(BasicElf,BasicLE)268 TYPED_TEST(BasicElf, BasicLE) {
269   typedef typename TypeParam::Ehdr Ehdr;
270   typedef typename TypeParam::Phdr Phdr;
271   typedef typename TypeParam::Shdr Shdr;
272   const size_t kStringTableSize = sizeof("\0.text\0.bss\0.shstrtab");
273   const size_t kStringTableAlign = 4 - kStringTableSize % 4;
274   const size_t kExpectedSize = sizeof(Ehdr) +
275     // Four sections, SHT_NULL + the section header string table +
276     // 4096 bytes of the size-aligned .text section + one program header.
277     sizeof(Phdr) + 4 * sizeof(Shdr) + 4096 +
278     kStringTableSize + kStringTableAlign;
279 
280   // It doesn't really matter that the machine type is right for the class.
281   ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
282   Section text(kLittleEndian);
283   text.Append(4094, 0);
284   int text_idx = elf.AddSection(".text", text, SHT_PROGBITS);
285   Section bss(kLittleEndian);
286   bss.Append(16, 0);
287   int bss_idx = elf.AddSection(".bss", bss, SHT_NOBITS);
288   elf.AddSegment(text_idx, bss_idx, PT_LOAD);
289   elf.Finish();
290   EXPECT_EQ(kExpectedSize, elf.Size());
291 
292   string contents;
293   ASSERT_TRUE(elf.GetContents(&contents));
294   ASSERT_EQ(kExpectedSize, contents.size());
295   const Ehdr* header =
296     reinterpret_cast<const Ehdr*>(contents.data());
297   const uint8_t kIdent[] = {
298     ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
299     TypeParam::kClass, ELFDATA2LSB, EV_CURRENT, ELFOSABI_SYSV,
300     0, 0, 0, 0, 0, 0, 0, 0
301   };
302   EXPECT_EQ(0, memcmp(kIdent, header->e_ident, sizeof(kIdent)));
303   EXPECT_EQ(ET_EXEC, header->e_type);
304   EXPECT_EQ(EM_386, header->e_machine);
305   EXPECT_EQ(static_cast<unsigned int>(EV_CURRENT), header->e_version);
306   EXPECT_EQ(0U, header->e_entry);
307   EXPECT_EQ(sizeof(Ehdr), header->e_phoff);
308   EXPECT_EQ(sizeof(Ehdr) + sizeof(Phdr) + 4096 + kStringTableSize +
309             kStringTableAlign, header->e_shoff);
310   EXPECT_EQ(0U, header->e_flags);
311   EXPECT_EQ(sizeof(Ehdr), header->e_ehsize);
312   EXPECT_EQ(sizeof(Phdr), header->e_phentsize);
313   EXPECT_EQ(1, header->e_phnum);
314   EXPECT_EQ(sizeof(Shdr), header->e_shentsize);
315   EXPECT_EQ(4, header->e_shnum);
316   EXPECT_EQ(3, header->e_shstrndx);
317 
318   const Shdr* shdr =
319     reinterpret_cast<const Shdr*>(contents.data() + header->e_shoff);
320   EXPECT_EQ(0U, shdr[0].sh_name);
321   EXPECT_EQ(static_cast<unsigned int>(SHT_NULL), shdr[0].sh_type);
322   EXPECT_EQ(0U, shdr[0].sh_flags);
323   EXPECT_EQ(0U, shdr[0].sh_addr);
324   EXPECT_EQ(0U, shdr[0].sh_offset);
325   EXPECT_EQ(0U, shdr[0].sh_size);
326   EXPECT_EQ(0U, shdr[0].sh_link);
327   EXPECT_EQ(0U, shdr[0].sh_info);
328   EXPECT_EQ(0U, shdr[0].sh_addralign);
329   EXPECT_EQ(0U, shdr[0].sh_entsize);
330 
331   EXPECT_EQ(1U, shdr[1].sh_name);
332   EXPECT_EQ(static_cast<unsigned int>(SHT_PROGBITS), shdr[1].sh_type);
333   EXPECT_EQ(0U, shdr[1].sh_flags);
334   EXPECT_EQ(0U, shdr[1].sh_addr);
335   EXPECT_EQ(sizeof(Ehdr) + sizeof(Phdr), shdr[1].sh_offset);
336   EXPECT_EQ(4094U, shdr[1].sh_size);
337   EXPECT_EQ(0U, shdr[1].sh_link);
338   EXPECT_EQ(0U, shdr[1].sh_info);
339   EXPECT_EQ(0U, shdr[1].sh_addralign);
340   EXPECT_EQ(0U, shdr[1].sh_entsize);
341 
342   EXPECT_EQ(sizeof("\0.text"), shdr[2].sh_name);
343   EXPECT_EQ(static_cast<unsigned int>(SHT_NOBITS), shdr[2].sh_type);
344   EXPECT_EQ(0U, shdr[2].sh_flags);
345   EXPECT_EQ(0U, shdr[2].sh_addr);
346   EXPECT_EQ(0U, shdr[2].sh_offset);
347   EXPECT_EQ(16U, shdr[2].sh_size);
348   EXPECT_EQ(0U, shdr[2].sh_link);
349   EXPECT_EQ(0U, shdr[2].sh_info);
350   EXPECT_EQ(0U, shdr[2].sh_addralign);
351   EXPECT_EQ(0U, shdr[2].sh_entsize);
352 
353   EXPECT_EQ(sizeof("\0.text\0.bss"), shdr[3].sh_name);
354   EXPECT_EQ(static_cast<unsigned int>(SHT_STRTAB), shdr[3].sh_type);
355   EXPECT_EQ(0U, shdr[3].sh_flags);
356   EXPECT_EQ(0U, shdr[3].sh_addr);
357   EXPECT_EQ(sizeof(Ehdr) + sizeof(Phdr) + 4096, shdr[3].sh_offset);
358   EXPECT_EQ(kStringTableSize, shdr[3].sh_size);
359   EXPECT_EQ(0U, shdr[3].sh_link);
360   EXPECT_EQ(0U, shdr[3].sh_info);
361   EXPECT_EQ(0U, shdr[3].sh_addralign);
362   EXPECT_EQ(0U, shdr[3].sh_entsize);
363 
364   const Phdr* phdr =
365     reinterpret_cast<const Phdr*>(contents.data() + header->e_phoff);
366   EXPECT_EQ(static_cast<unsigned int>(PT_LOAD), phdr->p_type);
367   EXPECT_EQ(sizeof(Ehdr) + sizeof(Phdr), phdr->p_offset);
368   EXPECT_EQ(0U, phdr->p_vaddr);
369   EXPECT_EQ(0U, phdr->p_paddr);
370   EXPECT_EQ(4096U, phdr->p_filesz);
371   EXPECT_EQ(4096U + 16U, phdr->p_memsz);
372   EXPECT_EQ(0U, phdr->p_flags);
373   EXPECT_EQ(0U, phdr->p_align);
374 }
375 
376 class ElfNotesTest : public Test {};
377 
TEST_F(ElfNotesTest,Empty)378 TEST_F(ElfNotesTest, Empty) {
379   Notes notes(kLittleEndian);
380   string contents;
381   ASSERT_TRUE(notes.GetContents(&contents));
382   EXPECT_EQ(0U, contents.size());
383 }
384 
TEST_F(ElfNotesTest,Notes)385 TEST_F(ElfNotesTest, Notes) {
386   Notes notes(kLittleEndian);
387   notes.AddNote(1, "Linux", reinterpret_cast<const uint8_t*>("\x42\x02\0\0"),
388                 4);
389   notes.AddNote(2, "a", reinterpret_cast<const uint8_t*>("foobar"),
390                 sizeof("foobar") - 1);
391 
392   const uint8_t kExpectedNotesContents[] = {
393     // Note 1
394     0x06, 0x00, 0x00, 0x00, // name size, including terminating zero
395     0x04, 0x00, 0x00, 0x00, // desc size
396     0x01, 0x00, 0x00, 0x00, // type
397     'L', 'i', 'n', 'u', 'x', 0x00, 0x00, 0x00, // padded "Linux"
398     0x42, 0x02, 0x00, 0x00, // desc
399     // Note 2
400     0x02, 0x00, 0x00, 0x00, // name size
401     0x06, 0x00, 0x00, 0x00, // desc size
402     0x02, 0x00, 0x00, 0x00, // type
403     'a',  0x00, 0x00, 0x00, // padded "a"
404     'f', 'o', 'o', 'b', 'a', 'r', 0x00, 0x00, // padded "foobar"
405   };
406   const size_t kExpectedNotesSize = sizeof(kExpectedNotesContents);
407   EXPECT_EQ(kExpectedNotesSize, notes.Size());
408 
409   string notes_contents;
410   ASSERT_TRUE(notes.GetContents(&notes_contents));
411   EXPECT_EQ(0, memcmp(kExpectedNotesContents,
412                       notes_contents.data(),
413                       notes_contents.size()));
414 }
415 
416 #endif  // defined(__i386__) || defined(__x86_64__)
417