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
42using google_breakpad::ElfClass32;
43using google_breakpad::ElfClass64;
44using google_breakpad::synth_elf::ELF;
45using google_breakpad::synth_elf::Notes;
46using google_breakpad::synth_elf::Section;
47using google_breakpad::synth_elf::StringTable;
48using google_breakpad::synth_elf::SymbolTable;
49using google_breakpad::test_assembler::Endianness;
50using google_breakpad::test_assembler::kBigEndian;
51using google_breakpad::test_assembler::kLittleEndian;
52using google_breakpad::test_assembler::Label;
53using ::testing::Test;
54using ::testing::Types;
55
56class StringTableTest : public Test {
57public:
58  StringTableTest() : table(kLittleEndian) {}
59
60  StringTable table;
61};
62
63TEST_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
75TEST_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
99TEST_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
119class SymbolTableTest : public Test {};
120
121TEST_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
187template<typename ElfClass>
188class 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
194typedef Types<ElfClass32, ElfClass64> ElfClasses;
195
196TYPED_TEST_CASE(BasicElf, ElfClasses);
197
198TYPED_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
265TYPED_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
373class ElfNotesTest : public Test {};
374
375TEST_F(ElfNotesTest, Empty) {
376  Notes notes(kLittleEndian);
377  string contents;
378  ASSERT_TRUE(notes.GetContents(&contents));
379  EXPECT_EQ(0U, contents.size());
380}
381
382TEST_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