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 // dump_symbols_unittest.cc:
33 // Unittests for google_breakpad::DumpSymbols
34
35 #include <elf.h>
36 #include <link.h>
37 #include <stdio.h>
38
39 #include <sstream>
40 #include <vector>
41
42 #include "breakpad_googletest_includes.h"
43 #include "common/linux/dump_symbols.h"
44 #include "common/linux/synth_elf.h"
45 #include "common/module.h"
46 #include "common/using_std_string.h"
47
48 namespace google_breakpad {
49
50 bool ReadSymbolDataInternal(const uint8_t* obj_file,
51 const string& obj_filename,
52 const std::vector<string>& debug_dir,
53 const DumpOptions& options,
54 Module** module);
55
56 using google_breakpad::synth_elf::ELF;
57 using google_breakpad::synth_elf::StringTable;
58 using google_breakpad::synth_elf::SymbolTable;
59 using google_breakpad::test_assembler::kLittleEndian;
60 using google_breakpad::test_assembler::Section;
61 using std::stringstream;
62 using std::vector;
63 using ::testing::Test;
64
65 class DumpSymbols : public Test {
66 public:
GetElfContents(ELF & elf)67 void GetElfContents(ELF& elf) {
68 string contents;
69 ASSERT_TRUE(elf.GetContents(&contents));
70 ASSERT_LT(0U, contents.size());
71
72 elfdata_v.clear();
73 elfdata_v.insert(elfdata_v.begin(), contents.begin(), contents.end());
74 elfdata = &elfdata_v[0];
75 }
76
77 vector<uint8_t> elfdata_v;
78 uint8_t* elfdata;
79 };
80
TEST_F(DumpSymbols,Invalid)81 TEST_F(DumpSymbols, Invalid) {
82 Elf32_Ehdr header;
83 memset(&header, 0, sizeof(header));
84 Module* module;
85 DumpOptions options(ALL_SYMBOL_DATA, true);
86 EXPECT_FALSE(ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(&header),
87 "foo",
88 vector<string>(),
89 options,
90 &module));
91 }
92
TEST_F(DumpSymbols,SimplePublic32)93 TEST_F(DumpSymbols, SimplePublic32) {
94 ELF elf(EM_386, ELFCLASS32, kLittleEndian);
95 // Zero out text section for simplicity.
96 Section text(kLittleEndian);
97 text.Append(4096, 0);
98 elf.AddSection(".text", text, SHT_PROGBITS);
99
100 // Add a public symbol.
101 StringTable table(kLittleEndian);
102 SymbolTable syms(kLittleEndian, 4, table);
103 syms.AddSymbol("superfunc", (uint32_t)0x1000, (uint32_t)0x10,
104 ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
105 SHN_UNDEF + 1);
106 int index = elf.AddSection(".dynstr", table, SHT_STRTAB);
107 elf.AddSection(".dynsym", syms,
108 SHT_DYNSYM, // type
109 SHF_ALLOC, // flags
110 0, // addr
111 index, // link
112 sizeof(Elf32_Sym)); // entsize
113
114 elf.Finish();
115 GetElfContents(elf);
116
117 Module* module;
118 DumpOptions options(ALL_SYMBOL_DATA, true);
119 EXPECT_TRUE(ReadSymbolDataInternal(elfdata,
120 "foo",
121 vector<string>(),
122 options,
123 &module));
124
125 stringstream s;
126 module->Write(s, ALL_SYMBOL_DATA);
127 EXPECT_EQ("MODULE Linux x86 000000000000000000000000000000000 foo\n"
128 "PUBLIC 1000 0 superfunc\n",
129 s.str());
130 delete module;
131 }
132
TEST_F(DumpSymbols,SimplePublic64)133 TEST_F(DumpSymbols, SimplePublic64) {
134 ELF elf(EM_X86_64, ELFCLASS64, kLittleEndian);
135 // Zero out text section for simplicity.
136 Section text(kLittleEndian);
137 text.Append(4096, 0);
138 elf.AddSection(".text", text, SHT_PROGBITS);
139
140 // Add a public symbol.
141 StringTable table(kLittleEndian);
142 SymbolTable syms(kLittleEndian, 8, table);
143 syms.AddSymbol("superfunc", (uint64_t)0x1000, (uint64_t)0x10,
144 ELF64_ST_INFO(STB_GLOBAL, STT_FUNC),
145 SHN_UNDEF + 1);
146 int index = elf.AddSection(".dynstr", table, SHT_STRTAB);
147 elf.AddSection(".dynsym", syms,
148 SHT_DYNSYM, // type
149 SHF_ALLOC, // flags
150 0, // addr
151 index, // link
152 sizeof(Elf64_Sym)); // entsize
153
154 elf.Finish();
155 GetElfContents(elf);
156
157 Module* module;
158 DumpOptions options(ALL_SYMBOL_DATA, true);
159 EXPECT_TRUE(ReadSymbolDataInternal(elfdata,
160 "foo",
161 vector<string>(),
162 options,
163 &module));
164
165 stringstream s;
166 module->Write(s, ALL_SYMBOL_DATA);
167 EXPECT_EQ("MODULE Linux x86_64 000000000000000000000000000000000 foo\n"
168 "PUBLIC 1000 0 superfunc\n",
169 s.str());
170 }
171
172 } // namespace google_breakpad
173