/ src / processor / stackwalker_address_list_unittest.cc
stackwalker_address_list_unittest.cc
  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 <chrisha@chromium.org>
 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:
 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.
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  
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  
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  
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  }