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