PageRenderTime 902ms CodeModel.GetById 101ms app.highlight 662ms RepoModel.GetById 125ms app.codeStats 1ms

/thirdparty/breakpad/common/dwarf_cfi_to_module_unittest.cc

http://github.com/tomahawk-player/tomahawk
C++ | 294 lines | 231 code | 32 blank | 31 comment | 0 complexity | 51b09ff2d7c48b76d7b47e90e1ea1886 MD5 | raw file
  1// Copyright (c) 2010, 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: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
 31
 32// dwarf_cfi_to_module_unittest.cc: Tests for google_breakpad::DwarfCFIToModule.
 33
 34#include <string>
 35#include <vector>
 36
 37#include "breakpad_googletest_includes.h"
 38#include "common/dwarf_cfi_to_module.h"
 39
 40using std::string;
 41using std::vector;
 42
 43using google_breakpad::Module;
 44using google_breakpad::DwarfCFIToModule;
 45using testing::ContainerEq;
 46using testing::Test;
 47using testing::_;
 48
 49struct MockCFIReporter: public DwarfCFIToModule::Reporter {
 50  MockCFIReporter(const string &file, const string &section)
 51      : Reporter(file, section) { }
 52  MOCK_METHOD2(UnnamedRegister, void(size_t offset, int reg));
 53  MOCK_METHOD2(UndefinedNotSupported, void(size_t offset, const string &reg));
 54  MOCK_METHOD2(ExpressionsNotSupported, void(size_t offset, const string &reg));
 55};
 56
 57struct DwarfCFIToModuleFixture {
 58  DwarfCFIToModuleFixture()
 59      : module("module name", "module os", "module arch", "module id"),
 60        reporter("reporter file", "reporter section"),
 61        handler(&module, register_names, &reporter) {
 62    register_names.push_back("reg0");
 63    register_names.push_back("reg1");
 64    register_names.push_back("reg2");
 65    register_names.push_back("reg3");
 66    register_names.push_back("reg4");
 67    register_names.push_back("reg5");
 68    register_names.push_back("reg6");
 69    register_names.push_back("reg7");
 70    register_names.push_back("sp");
 71    register_names.push_back("pc");
 72
 73    EXPECT_CALL(reporter, UnnamedRegister(_, _)).Times(0);
 74    EXPECT_CALL(reporter, UndefinedNotSupported(_, _)).Times(0);
 75    EXPECT_CALL(reporter, ExpressionsNotSupported(_, _)).Times(0);
 76  }
 77
 78  Module module;
 79  vector<string> register_names;
 80  MockCFIReporter reporter;
 81  DwarfCFIToModule handler;
 82  vector<Module::StackFrameEntry *> entries;
 83};
 84
 85class Entry: public DwarfCFIToModuleFixture, public Test { };
 86
 87TEST_F(Entry, Accept) {
 88  ASSERT_TRUE(handler.Entry(0x3b8961b8, 0xa21069698096fc98ULL,
 89                            0xb440ce248169c8d6ULL, 3, "", 0xea93c106));
 90  ASSERT_TRUE(handler.End());
 91  module.GetStackFrameEntries(&entries);
 92  EXPECT_EQ(1U, entries.size());
 93  EXPECT_EQ(0xa21069698096fc98ULL, entries[0]->address);
 94  EXPECT_EQ(0xb440ce248169c8d6ULL, entries[0]->size);
 95  EXPECT_EQ(0U, entries[0]->initial_rules.size());
 96  EXPECT_EQ(0U, entries[0]->rule_changes.size());
 97}
 98
 99TEST_F(Entry, AcceptOldVersion) {
100  ASSERT_TRUE(handler.Entry(0xeb60e0fc, 0x75b8806bb09eab78ULL,
101                            0xc771f44958d40bbcULL, 1, "", 0x093c945e));
102  ASSERT_TRUE(handler.End());
103  module.GetStackFrameEntries(&entries);
104  EXPECT_EQ(1U, entries.size());
105  EXPECT_EQ(0x75b8806bb09eab78ULL, entries[0]->address);
106  EXPECT_EQ(0xc771f44958d40bbcULL, entries[0]->size);
107  EXPECT_EQ(0U, entries[0]->initial_rules.size());
108  EXPECT_EQ(0U, entries[0]->rule_changes.size());
109}
110
111struct RuleFixture: public DwarfCFIToModuleFixture {
112  RuleFixture() : DwarfCFIToModuleFixture() {
113    entry_address = 0x89327ebf86b47492ULL;
114    entry_size    = 0x2f8cd573072fe02aULL;
115    return_reg    = 0x7886a346;
116  }
117  void StartEntry() {
118    ASSERT_TRUE(handler.Entry(0x4445c05c, entry_address, entry_size,
119                              3, "", return_reg));
120  }
121  void CheckEntry() {
122    module.GetStackFrameEntries(&entries);
123    EXPECT_EQ(1U, entries.size());
124    EXPECT_EQ(entry_address, entries[0]->address);
125    EXPECT_EQ(entry_size, entries[0]->size);
126  }
127  uint64 entry_address, entry_size;
128  unsigned return_reg;
129};
130
131class Rule: public RuleFixture, public Test { };
132
133TEST_F(Rule, UndefinedRule) {
134  EXPECT_CALL(reporter, UndefinedNotSupported(_, "reg7"));
135  StartEntry();
136  ASSERT_TRUE(handler.UndefinedRule(entry_address, 7));
137  ASSERT_TRUE(handler.End());
138  CheckEntry();
139  EXPECT_EQ(0U, entries[0]->initial_rules.size());
140  EXPECT_EQ(0U, entries[0]->rule_changes.size());
141}
142
143TEST_F(Rule, SameValueRule) {
144  StartEntry();
145  ASSERT_TRUE(handler.SameValueRule(entry_address, 6));
146  ASSERT_TRUE(handler.End());
147  CheckEntry();
148  Module::RuleMap expected_initial;
149  expected_initial["reg6"] = "reg6";
150  EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial));
151  EXPECT_EQ(0U, entries[0]->rule_changes.size());
152}
153
154TEST_F(Rule, OffsetRule) {
155  StartEntry();
156  ASSERT_TRUE(handler.OffsetRule(entry_address + 1, return_reg,
157                                 DwarfCFIToModule::kCFARegister,
158                                 16927065));
159  ASSERT_TRUE(handler.End());
160  CheckEntry();
161  EXPECT_EQ(0U, entries[0]->initial_rules.size());
162  Module::RuleChangeMap expected_changes;
163  expected_changes[entry_address + 1][".ra"] = ".cfa 16927065 + ^";
164  EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes));
165}
166
167TEST_F(Rule, OffsetRuleNegative) {
168  StartEntry();
169  ASSERT_TRUE(handler.OffsetRule(entry_address + 1,
170                                 DwarfCFIToModule::kCFARegister, 4, -34530721));
171  ASSERT_TRUE(handler.End());
172  CheckEntry();
173  EXPECT_EQ(0U, entries[0]->initial_rules.size());
174  Module::RuleChangeMap expected_changes;
175  expected_changes[entry_address + 1][".cfa"] = "reg4 -34530721 + ^";
176  EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes));
177}
178
179TEST_F(Rule, ValOffsetRule) {
180  // Use an unnamed register number, to exercise that branch of RegisterName.
181  EXPECT_CALL(reporter, UnnamedRegister(_, 10));
182  StartEntry();
183  ASSERT_TRUE(handler.ValOffsetRule(entry_address + 0x5ab7,
184                                    DwarfCFIToModule::kCFARegister,
185                                    10, 61812979));
186  ASSERT_TRUE(handler.End());
187  CheckEntry();
188  EXPECT_EQ(0U, entries[0]->initial_rules.size());
189  Module::RuleChangeMap expected_changes;
190  expected_changes[entry_address + 0x5ab7][".cfa"] =
191      "unnamed_register10 61812979 +";
192  EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes));
193}
194
195TEST_F(Rule, RegisterRule) {
196  StartEntry();
197  ASSERT_TRUE(handler.RegisterRule(entry_address, return_reg, 3));
198  ASSERT_TRUE(handler.End());
199  CheckEntry();
200  Module::RuleMap expected_initial;
201  expected_initial[".ra"] = "reg3";
202  EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial));
203  EXPECT_EQ(0U, entries[0]->rule_changes.size());
204}
205
206TEST_F(Rule, ExpressionRule) {
207  EXPECT_CALL(reporter, ExpressionsNotSupported(_, "reg2"));
208  StartEntry();
209  ASSERT_TRUE(handler.ExpressionRule(entry_address + 0xf326, 2,
210                                     "it takes two to tango"));
211  ASSERT_TRUE(handler.End());
212  CheckEntry();
213  EXPECT_EQ(0U, entries[0]->initial_rules.size());
214  EXPECT_EQ(0U, entries[0]->rule_changes.size());
215}
216
217TEST_F(Rule, ValExpressionRule) {
218  EXPECT_CALL(reporter, ExpressionsNotSupported(_, "reg0"));
219  StartEntry();
220  ASSERT_TRUE(handler.ValExpressionRule(entry_address + 0x6367, 0,
221                                        "bit off more than he could chew"));
222  ASSERT_TRUE(handler.End());
223  CheckEntry();
224  EXPECT_EQ(0U, entries[0]->initial_rules.size());
225  EXPECT_EQ(0U, entries[0]->rule_changes.size());
226}
227
228TEST_F(Rule, DefaultReturnAddressRule) {
229  return_reg = 2;
230  StartEntry();
231  ASSERT_TRUE(handler.RegisterRule(entry_address, 0, 1));
232  ASSERT_TRUE(handler.End());
233  CheckEntry();
234  Module::RuleMap expected_initial;
235  expected_initial[".ra"] = "reg2";
236  expected_initial["reg0"] = "reg1";
237  EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial));
238  EXPECT_EQ(0U, entries[0]->rule_changes.size());
239}
240
241TEST_F(Rule, DefaultReturnAddressRuleOverride) {
242  return_reg = 2;
243  StartEntry();
244  ASSERT_TRUE(handler.RegisterRule(entry_address, return_reg, 1));
245  ASSERT_TRUE(handler.End());
246  CheckEntry();
247  Module::RuleMap expected_initial;
248  expected_initial[".ra"] = "reg1";
249  EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial));
250  EXPECT_EQ(0U, entries[0]->rule_changes.size());
251}
252
253TEST_F(Rule, DefaultReturnAddressRuleLater) {
254  return_reg = 2;
255  StartEntry();
256  ASSERT_TRUE(handler.RegisterRule(entry_address + 1, return_reg, 1));
257  ASSERT_TRUE(handler.End());
258  CheckEntry();
259  Module::RuleMap expected_initial;
260  expected_initial[".ra"] = "reg2";
261  EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial));
262  Module::RuleChangeMap expected_changes;
263  expected_changes[entry_address + 1][".ra"] = "reg1";
264  EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes));
265}
266
267TEST(RegisterNames, I386) {
268  vector<string> names = DwarfCFIToModule::RegisterNames::I386();
269
270  EXPECT_EQ("$eax", names[0]);
271  EXPECT_EQ("$ecx", names[1]);
272  EXPECT_EQ("$esp", names[4]);
273  EXPECT_EQ("$eip", names[8]);
274}
275
276TEST(RegisterNames, ARM) {
277  vector<string> names = DwarfCFIToModule::RegisterNames::ARM();
278
279  EXPECT_EQ("r0", names[0]);
280  EXPECT_EQ("r10", names[10]);
281  EXPECT_EQ("sp", names[13]);
282  EXPECT_EQ("lr", names[14]);
283  EXPECT_EQ("pc", names[15]);
284}
285
286TEST(RegisterNames, X86_64) {
287  vector<string> names = DwarfCFIToModule::RegisterNames::X86_64();
288
289  EXPECT_EQ("$rax", names[0]);
290  EXPECT_EQ("$rdx", names[1]);
291  EXPECT_EQ("$rbp", names[6]);
292  EXPECT_EQ("$rsp", names[7]);
293  EXPECT_EQ("$rip", names[16]);
294}