PageRenderTime 33ms CodeModel.GetById 11ms app.highlight 19ms RepoModel.GetById 1ms app.codeStats 0ms

/thirdparty/breakpad/common/linux/synth_elf_unittest.cc

http://github.com/tomahawk-player/tomahawk
C++ | 265 lines | 198 code | 26 blank | 41 comment | 1 complexity | f58f407fb64e4c008bc3e969495e82ca MD5 | raw file
  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/synth_elf.h"
 39
 40using google_breakpad::synth_elf::ELF;
 41using google_breakpad::synth_elf::StringTable;
 42using google_breakpad::synth_elf::SymbolTable;
 43using google_breakpad::test_assembler::Endianness;
 44using google_breakpad::test_assembler::kBigEndian;
 45using google_breakpad::test_assembler::kLittleEndian;
 46using google_breakpad::test_assembler::Label;
 47using std::string;
 48using ::testing::Test;
 49
 50class StringTableTest : public Test {
 51public:
 52  StringTableTest() : table(kLittleEndian) {}
 53
 54  StringTable table;
 55};
 56
 57TEST_F(StringTableTest, Empty) {
 58  EXPECT_EQ(1, table.Size());
 59  string contents;
 60  ASSERT_TRUE(table.GetContents(&contents));
 61  const char* kExpectedContents = "\0";
 62  EXPECT_EQ(0, memcmp(kExpectedContents,
 63                      contents.c_str(),
 64                      contents.size()));
 65  ASSERT_TRUE(table.empty_string.IsKnownConstant());
 66  EXPECT_EQ(0, table.empty_string.Value());
 67}
 68
 69TEST_F(StringTableTest, Basic) {
 70  const string s1("table fills with strings");
 71  const string s2("offsets preserved as labels");
 72  const string s3("verified with tests");
 73  const char* kExpectedContents = 
 74    "\0table fills with strings\0"
 75    "offsets preserved as labels\0"
 76    "verified with tests\0";
 77  Label l1(table.Add(s1));
 78  Label l2(table.Add(s2));
 79  Label l3(table.Add(s3));
 80  string contents;
 81  ASSERT_TRUE(table.GetContents(&contents));
 82  EXPECT_EQ(0, memcmp(kExpectedContents,
 83                      contents.c_str(),
 84                      contents.size()));
 85  // empty_string is at zero, other strings start at 1.
 86  ASSERT_TRUE(l1.IsKnownConstant());
 87  EXPECT_EQ(1, l1.Value());
 88  // Each string has an extra byte for a trailing null.
 89  EXPECT_EQ(1 + s1.length() + 1, l2.Value());
 90  EXPECT_EQ(1 + s1.length() + 1 + s2.length() + 1, l3.Value());
 91}
 92
 93TEST_F(StringTableTest, Duplicates) {
 94  const string s1("string 1");
 95  const string s2("string 2");
 96  const string s3("");
 97  const char* kExpectedContents = "\0string 1\0string 2\0";
 98  Label l1(table.Add(s1));
 99  Label l2(table.Add(s2));
100  // Adding strings twice should return the same Label.
101  Label l3(table.Add(s3));
102  Label l4(table.Add(s2));
103  string contents;
104  ASSERT_TRUE(table.GetContents(&contents));
105  EXPECT_EQ(0, memcmp(kExpectedContents,
106                      contents.c_str(),
107                      contents.size()));
108  EXPECT_EQ(0, table.empty_string.Value());
109  EXPECT_EQ(table.empty_string.Value(), l3.Value());
110  EXPECT_EQ(l2.Value(), l4.Value());
111}
112
113class SymbolTableTest : public Test {};
114
115TEST_F(SymbolTableTest, Simple32) {
116  StringTable table(kLittleEndian);
117  SymbolTable syms(kLittleEndian, 4, table);
118
119  const string kFuncName1 = "superfunc";
120  const uint32_t kFuncAddr1 = 0x10001000;
121  const uint32_t kFuncSize1 = 0x10;
122  const string kFuncName2 = "awesomefunc";
123  const uint32_t kFuncAddr2 = 0x20002000;
124  const uint32_t kFuncSize2 = 0x2f;
125  const string kFuncName3 = "megafunc";
126  const uint32_t kFuncAddr3 = 0x30003000;
127  const uint32_t kFuncSize3 = 0x3c;
128
129  syms.AddSymbol(kFuncName1, kFuncAddr1, kFuncSize1,
130                 ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
131                 SHN_UNDEF + 1);
132  syms.AddSymbol(kFuncName2, kFuncAddr2, kFuncSize2,
133                 ELF32_ST_INFO(STB_LOCAL, STT_FUNC),
134                 SHN_UNDEF + 2);
135  syms.AddSymbol(kFuncName3, kFuncAddr3, kFuncSize3,
136                 ELF32_ST_INFO(STB_LOCAL, STT_FUNC),
137                 SHN_UNDEF + 3);
138
139  const char kExpectedStringTable[] = "\0superfunc\0awesomefunc\0megafunc";
140  const size_t kExpectedStringTableSize = sizeof(kExpectedStringTable);
141  EXPECT_EQ(kExpectedStringTableSize, table.Size());
142  string table_contents;
143  table.GetContents(&table_contents);
144  EXPECT_EQ(0, memcmp(kExpectedStringTable,
145                      table_contents.c_str(),
146                      table_contents.size()));
147
148  const uint8_t kExpectedSymbolContents[] = {
149    // Symbol 1
150    0x01, 0x00, 0x00, 0x00, // name
151    0x00, 0x10, 0x00, 0x10, // value
152    0x10, 0x00, 0x00, 0x00, // size
153    ELF32_ST_INFO(STB_GLOBAL, STT_FUNC), // info
154    0x00, // other
155    0x01, 0x00, // shndx
156    // Symbol 2
157    0x0B, 0x00, 0x00, 0x00, // name
158    0x00, 0x20, 0x00, 0x20, // value
159    0x2f, 0x00, 0x00, 0x00, // size
160    ELF32_ST_INFO(STB_LOCAL, STT_FUNC), // info
161    0x00, // other
162    0x02, 0x00, // shndx
163    // Symbol 3
164    0x17, 0x00, 0x00, 0x00, // name
165    0x00, 0x30, 0x00, 0x30, // value
166    0x3c, 0x00, 0x00, 0x00, // size
167    ELF32_ST_INFO(STB_LOCAL, STT_FUNC), // info
168    0x00, // other
169    0x03, 0x00, // shndx
170  };
171  const size_t kExpectedSymbolSize = sizeof(kExpectedSymbolContents);
172  EXPECT_EQ(kExpectedSymbolSize, syms.Size());
173
174  string symbol_contents;
175  syms.GetContents(&symbol_contents);
176  EXPECT_EQ(0, memcmp(kExpectedSymbolContents,
177                      symbol_contents.c_str(),
178                      symbol_contents.size()));
179}
180
181class BasicElf : public Test {};
182
183// Doesn't seem worthwhile writing the tests to be endian-independent
184// when they're unlikely to ever be run on big-endian systems.
185#if defined(__i386__) || defined(__x86_64__)
186
187TEST_F(BasicElf, EmptyLE32) {
188  const size_t kStringTableSize = sizeof("\0.shstrtab");
189  const size_t kStringTableAlign = 4 - kStringTableSize % 4;
190  const size_t kExpectedSize = sizeof(Elf32_Ehdr) +
191    // Two sections, SHT_NULL + the section header string table.
192    2 * sizeof(Elf32_Shdr) +
193    kStringTableSize + kStringTableAlign;
194
195  ELF elf(EM_386, ELFCLASS32, kLittleEndian);
196  elf.Finish();
197  EXPECT_EQ(kExpectedSize, elf.Size());
198
199  string contents;
200  ASSERT_TRUE(elf.GetContents(&contents));
201  ASSERT_EQ(kExpectedSize, contents.size());
202  const Elf32_Ehdr* header =
203    reinterpret_cast<const Elf32_Ehdr*>(contents.data());
204  const uint8_t kIdent[] = {
205    ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
206    ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_SYSV,
207    0, 0, 0, 0, 0, 0, 0, 0
208  };
209  EXPECT_EQ(0, memcmp(kIdent, header->e_ident, sizeof(kIdent)));
210  EXPECT_EQ(ET_EXEC, header->e_type);
211  EXPECT_EQ(EM_386, header->e_machine);
212  EXPECT_EQ(EV_CURRENT, header->e_version);
213  EXPECT_EQ(0, header->e_entry);
214  EXPECT_EQ(0, header->e_phoff);
215  EXPECT_EQ(sizeof(Elf32_Ehdr) + kStringTableSize + kStringTableAlign,
216            header->e_shoff);
217  EXPECT_EQ(0, header->e_flags);
218  EXPECT_EQ(sizeof(Elf32_Ehdr), header->e_ehsize);
219  EXPECT_EQ(sizeof(Elf32_Phdr), header->e_phentsize);
220  EXPECT_EQ(0, header->e_phnum);
221  EXPECT_EQ(sizeof(Elf32_Shdr), header->e_shentsize);
222  EXPECT_EQ(2, header->e_shnum);
223  EXPECT_EQ(1, header->e_shstrndx);
224}
225
226TEST_F(BasicElf, EmptyLE64) {
227  const size_t kStringTableSize = sizeof("\0.shstrtab");
228  const size_t kStringTableAlign = 4 - kStringTableSize % 4;
229  const size_t kExpectedSize = sizeof(Elf64_Ehdr) +
230    // Two sections, SHT_NULL + the section header string table.
231    2 * sizeof(Elf64_Shdr) +
232    kStringTableSize + kStringTableAlign;
233
234  ELF elf(EM_X86_64, ELFCLASS64, kLittleEndian);
235  elf.Finish();
236  EXPECT_EQ(kExpectedSize, elf.Size());
237
238  string contents;
239  ASSERT_TRUE(elf.GetContents(&contents));
240  ASSERT_EQ(kExpectedSize, contents.size());
241  const Elf64_Ehdr* header =
242    reinterpret_cast<const Elf64_Ehdr*>(contents.data());
243  const uint8_t kIdent[] = {
244    ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
245    ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_SYSV,
246    0, 0, 0, 0, 0, 0, 0, 0
247  };
248  EXPECT_EQ(0, memcmp(kIdent, header->e_ident, sizeof(kIdent)));
249  EXPECT_EQ(ET_EXEC, header->e_type);
250  EXPECT_EQ(EM_X86_64, header->e_machine);
251  EXPECT_EQ(EV_CURRENT, header->e_version);
252  EXPECT_EQ(0, header->e_entry);
253  EXPECT_EQ(0, header->e_phoff);
254  EXPECT_EQ(sizeof(Elf64_Ehdr) + kStringTableSize + kStringTableAlign,
255            header->e_shoff);
256  EXPECT_EQ(0, header->e_flags);
257  EXPECT_EQ(sizeof(Elf64_Ehdr), header->e_ehsize);
258  EXPECT_EQ(sizeof(Elf64_Phdr), header->e_phentsize);
259  EXPECT_EQ(0, header->e_phnum);
260  EXPECT_EQ(sizeof(Elf64_Shdr), header->e_shentsize);
261  EXPECT_EQ(2, header->e_shnum);
262  EXPECT_EQ(1, header->e_shstrndx);
263}
264
265#endif  // defined(__i386__) || defined(__x86_64__)