1 // Copyright (c) 2013, 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 // stackwalker_address_list_unittest.cc: Unit tests for the
31 // StackwalkerAddressList class.
32 //
33 // Author: Chris Hamilton <chrisha@chromium.org>
34
35 #include <string>
36 #include <vector>
37
38 #include "breakpad_googletest_includes.h"
39 #include "common/using_std_string.h"
40 #include "google_breakpad/common/minidump_format.h"
41 #include "google_breakpad/processor/basic_source_line_resolver.h"
42 #include "google_breakpad/processor/call_stack.h"
43 #include "google_breakpad/processor/code_module.h"
44 #include "google_breakpad/processor/source_line_resolver_interface.h"
45 #include "google_breakpad/processor/stack_frame.h"
46 #include "processor/stackwalker_unittest_utils.h"
47 #include "processor/stackwalker_address_list.h"
48
49 using google_breakpad::BasicSourceLineResolver;
50 using google_breakpad::CallStack;
51 using google_breakpad::CodeModule;
52 using google_breakpad::StackFrameSymbolizer;
53 using google_breakpad::StackFrame;
54 using google_breakpad::Stackwalker;
55 using google_breakpad::StackwalkerAddressList;
56 using std::vector;
57 using testing::_;
58 using testing::AnyNumber;
59 using testing::Return;
60 using testing::SetArgumentPointee;
61
62 #define arraysize(f) (sizeof(f) / sizeof(*f))
63
64 // Addresses and sizes of a couple dummy modules.
65 uint64_t kModule1Base = 0x40000000;
66 uint64_t kModule1Size = 0x10000;
67 uint64_t kModule2Base = 0x50000000;
68 uint64_t kModule2Size = 0x10000;
69
70 // A handful of addresses that lie within the modules above.
71 const uint64_t kDummyFrames[] = {
72 0x50003000, 0x50002000, 0x50001000, 0x40002000, 0x40001000 };
73
74 class StackwalkerAddressListTest : public testing::Test {
75 public:
StackwalkerAddressListTest()76 StackwalkerAddressListTest()
77 : // Give the two modules reasonable standard locations and names
78 // for tests to play with.
79 module1(kModule1Base, kModule1Size, "module1", "version1"),
80 module2(kModule2Base, kModule2Size, "module2", "version2") {
81 // Create some modules with some stock debugging information.
82 modules.Add(&module1);
83 modules.Add(&module2);
84
85 // By default, none of the modules have symbol info; call
86 // SetModuleSymbols to override this.
87 EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _))
88 .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
89
90 // Avoid GMOCK WARNING "Uninteresting mock function call - returning
91 // directly" for FreeSymbolData().
92 EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber());
93 }
94
95 // Set the Breakpad symbol information that supplier should return for
96 // MODULE to INFO.
SetModuleSymbols(MockCodeModule * module,const string & info)97 void SetModuleSymbols(MockCodeModule *module, const string &info) {
98 size_t buffer_size;
99 char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size);
100 EXPECT_CALL(supplier, GetCStringSymbolData(module, NULL, _, _, _))
101 .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
102 SetArgumentPointee<4>(buffer_size),
103 Return(MockSymbolSupplier::FOUND)));
104 }
105
CheckCallStack(const CallStack & call_stack)106 void CheckCallStack(const CallStack& call_stack) {
107 const std::vector<StackFrame*>* frames = call_stack.frames();
108 ASSERT_EQ(arraysize(kDummyFrames), frames->size());
109 for (size_t i = 0; i < arraysize(kDummyFrames); ++i) {
110 ASSERT_EQ(kDummyFrames[i], frames->at(i)->instruction);
111 ASSERT_EQ(StackFrame::FRAME_TRUST_PREWALKED, frames->at(i)->trust);
112 }
113 ASSERT_EQ(static_cast<const CodeModule*>(&module2), frames->at(0)->module);
114 ASSERT_EQ(static_cast<const CodeModule*>(&module2), frames->at(1)->module);
115 ASSERT_EQ(static_cast<const CodeModule*>(&module2), frames->at(2)->module);
116 ASSERT_EQ(static_cast<const CodeModule*>(&module1), frames->at(3)->module);
117 ASSERT_EQ(static_cast<const CodeModule*>(&module1), frames->at(4)->module);
118 }
119
120 MockCodeModule module1;
121 MockCodeModule module2;
122 MockCodeModules modules;
123 MockSymbolSupplier supplier;
124 BasicSourceLineResolver resolver;
125 };
126
TEST_F(StackwalkerAddressListTest,ScanWithoutSymbols)127 TEST_F(StackwalkerAddressListTest, ScanWithoutSymbols) {
128 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
129 StackwalkerAddressList walker(kDummyFrames, arraysize(kDummyFrames),
130 &modules, &frame_symbolizer);
131
132 CallStack call_stack;
133 vector<const CodeModule*> modules_without_symbols;
134 vector<const CodeModule*> modules_with_corrupt_symbols;
135 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
136 &modules_with_corrupt_symbols));
137
138 // The stack starts in module2, so we expect that to be the first module
139 // found without symbols.
140 ASSERT_EQ(2U, modules_without_symbols.size());
141 ASSERT_EQ("module2", modules_without_symbols[0]->debug_file());
142 ASSERT_EQ("module1", modules_without_symbols[1]->debug_file());
143 ASSERT_EQ(0u, modules_with_corrupt_symbols.size());
144
145 ASSERT_NO_FATAL_FAILURE(CheckCallStack(call_stack));
146 }
147
TEST_F(StackwalkerAddressListTest,ScanWithSymbols)148 TEST_F(StackwalkerAddressListTest, ScanWithSymbols) {
149 // File : FILE number(dex) name
150 // Function: FUNC address(hex) size(hex) parameter_size(hex) name
151 // Line : address(hex) size(hex) line(dec) filenum(dec)
152 SetModuleSymbols(&module2,
153 "FILE 1 module2.cc\n"
154 "FUNC 3000 100 10 mod2func3\n"
155 "3000 10 1 1\n"
156 "FUNC 2000 200 10 mod2func2\n"
157 "FUNC 1000 300 10 mod2func1\n");
158 SetModuleSymbols(&module1,
159 "FUNC 2000 200 10 mod1func2\n"
160 "FUNC 1000 300 10 mod1func1\n");
161
162 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
163 StackwalkerAddressList walker(kDummyFrames, arraysize(kDummyFrames),
164 &modules, &frame_symbolizer);
165
166 CallStack call_stack;
167 vector<const CodeModule*> modules_without_symbols;
168 vector<const CodeModule*> modules_with_corrupt_symbols;
169 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
170 &modules_with_corrupt_symbols));
171
172 ASSERT_EQ(0u, modules_without_symbols.size());
173 ASSERT_EQ(0u, modules_with_corrupt_symbols.size());
174
175 ASSERT_NO_FATAL_FAILURE(CheckCallStack(call_stack));
176
177 const std::vector<StackFrame*>* frames = call_stack.frames();
178
179 // We have full file/line information for the first function call.
180 ASSERT_EQ("mod2func3", frames->at(0)->function_name);
181 ASSERT_EQ(0x50003000u, frames->at(0)->function_base);
182 ASSERT_EQ("module2.cc", frames->at(0)->source_file_name);
183 ASSERT_EQ(1, frames->at(0)->source_line);
184 ASSERT_EQ(0x50003000u, frames->at(0)->source_line_base);
185
186 ASSERT_EQ("mod2func2", frames->at(1)->function_name);
187 ASSERT_EQ(0x50002000u, frames->at(1)->function_base);
188
189 ASSERT_EQ("mod2func1", frames->at(2)->function_name);
190 ASSERT_EQ(0x50001000u, frames->at(2)->function_base);
191
192 ASSERT_EQ("mod1func2", frames->at(3)->function_name);
193 ASSERT_EQ(0x40002000u, frames->at(3)->function_base);
194
195 ASSERT_EQ("mod1func1", frames->at(4)->function_name);
196 ASSERT_EQ(0x40001000u, frames->at(4)->function_base);
197 }
198