/ src / common / linux / synth_elf_unittest.cc
synth_elf_unittest.cc
  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 <ted.mielczarek@gmail.com>
 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:
 61    StringTableTest() : table(kLittleEndian) {}
 62  
 63    StringTable table;
 64  };
 65  
 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  
 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  
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  
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  
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  
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  
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  
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__)