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