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(¬es_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