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