/ src / processor / stackwalker_mips64_unittest.cc
stackwalker_mips64_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  // Original author: Veljko Mihailovic <veljko.mihailovic@imgtec.com>
 30  
 31  // stackwalker_mips64_unittest.cc: Unit tests for StackwalkerMIPS class for
 32  // mips64 platforms.
 33  
 34  #ifdef HAVE_CONFIG_H
 35  #include <config.h>  // Must come first
 36  #endif
 37  
 38  #include <string.h>
 39  #include <string>
 40  #include <vector>
 41  
 42  #include "breakpad_googletest_includes.h"
 43  #include "common/test_assembler.h"
 44  #include "common/using_std_string.h"
 45  #include "google_breakpad/common/minidump_format.h"
 46  #include "google_breakpad/processor/basic_source_line_resolver.h"
 47  #include "google_breakpad/processor/call_stack.h"
 48  #include "google_breakpad/processor/code_module.h"
 49  #include "google_breakpad/processor/source_line_resolver_interface.h"
 50  #include "google_breakpad/processor/stack_frame_cpu.h"
 51  #include "processor/stackwalker_unittest_utils.h"
 52  #include "processor/stackwalker_mips.h"
 53  #include "processor/windows_frame_info.h"
 54  
 55  using google_breakpad::BasicSourceLineResolver;
 56  using google_breakpad::CallStack;
 57  using google_breakpad::CodeModule;
 58  using google_breakpad::StackFrameSymbolizer;
 59  using google_breakpad::StackFrame;
 60  using google_breakpad::StackFrameMIPS;
 61  using google_breakpad::Stackwalker;
 62  using google_breakpad::StackwalkerMIPS;
 63  using google_breakpad::SystemInfo;
 64  using google_breakpad::WindowsFrameInfo;
 65  using google_breakpad::test_assembler::kLittleEndian;
 66  using google_breakpad::test_assembler::Label;
 67  using google_breakpad::test_assembler::Section;
 68  using std::vector;
 69  using testing::_;
 70  using testing::AnyNumber;
 71  using testing::DoAll;
 72  using testing::Return;
 73  using testing::SetArgumentPointee;
 74  using testing::Test;
 75  
 76  class StackwalkerMIPSFixture {
 77   public:
 78    StackwalkerMIPSFixture()
 79      : stack_section(kLittleEndian),
 80        // Give the two modules reasonable standard locations and names
 81        // for tests to play with.
 82        module1(0x00400000, 0x10000, "module1", "version1"),
 83        module2(0x00500000, 0x10000, "module2", "version2") {
 84      // Identify the system as a Linux system.
 85      system_info.os = "Linux";
 86      system_info.os_short = "linux";
 87      system_info.os_version = "Observant Opossum";  // Jealous Jellyfish
 88      system_info.cpu = "mips64";
 89      system_info.cpu_info = "";
 90  
 91      // Put distinctive values in the raw CPU context.
 92      BrandContext(&raw_context);
 93  
 94      // Create some modules with some stock debugging information.
 95      modules.Add(&module1);
 96      modules.Add(&module2);
 97  
 98      // By default, none of the modules have symbol info; call
 99      // SetModuleSymbols to override this.
100      EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _))
101        .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
102  
103      // Avoid GMOCK WARNING "Uninteresting mock function call - returning
104      // directly" for FreeSymbolData().
105      EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber());
106  
107      // Reset max_frames_scanned since it's static.
108      Stackwalker::set_max_frames_scanned(1024);
109    }
110  
111    // Set the Breakpad symbol information that supplier should return for
112    // MODULE to INFO.
113    void SetModuleSymbols(MockCodeModule* module, const string& info) {
114      size_t buffer_size;
115      char* buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size);
116      EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _, _))
117        .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
118                              SetArgumentPointee<4>(buffer_size),
119                              Return(MockSymbolSupplier::FOUND)));
120    }
121  
122    // Populate stack_region with the contents of stack_section. Use
123    // stack_section.start() as the region's starting address.
124    void RegionFromSection() {
125      string contents;
126      ASSERT_TRUE(stack_section.GetContents(&contents));
127      stack_region.Init(stack_section.start().Value(), contents);
128    }
129  
130    // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking.
131    void BrandContext(MDRawContextMIPS* raw_context) {
132      uint8_t x = 173;
133      for (size_t i = 0; i < sizeof(*raw_context); ++i)
134        reinterpret_cast<uint8_t*>(raw_context)[i] = (x += 17);
135    }
136  
137    SystemInfo system_info;
138    MDRawContextMIPS raw_context;
139    Section stack_section;
140    MockMemoryRegion stack_region;
141    MockCodeModule module1;
142    MockCodeModule module2;
143    MockCodeModules modules;
144    MockSymbolSupplier supplier;
145    BasicSourceLineResolver resolver;
146    CallStack call_stack;
147    const vector<StackFrame*>* frames;
148  };
149  
150  class SanityCheck: public StackwalkerMIPSFixture, public Test { };
151  
152  TEST_F(SanityCheck, NoResolver) {
153    raw_context.context_flags =
154        raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
155    stack_section.start() = 0x80000000;
156    stack_section.D64(0).D64(0x0);
157    RegionFromSection();
158    raw_context.epc = 0x00400020;
159    raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
160  
161    StackFrameSymbolizer frame_symbolizer(NULL, NULL);
162    StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
163                          &frame_symbolizer);
164    // This should succeed, even without a resolver or supplier.
165    vector<const CodeModule*> modules_without_symbols;
166    vector<const CodeModule*> modules_with_corrupt_symbols;
167    ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
168                            &modules_with_corrupt_symbols));
169    ASSERT_EQ(1U, modules_without_symbols.size());
170    ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
171    ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
172    frames = call_stack.frames();
173    ASSERT_EQ(1U, frames->size());
174    StackFrameMIPS* frame = static_cast<StackFrameMIPS*>(frames->at(0));
175    // Check that the values from the original raw context made it
176    // through to the context in the stack frame.
177    EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
178  }
179  
180  class GetContextFrame: public StackwalkerMIPSFixture, public Test { };
181  
182  TEST_F(GetContextFrame, Simple) {
183    raw_context.context_flags =
184        raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
185    stack_section.start() = 0x80000000;
186    stack_section.D64(0).D64(0x0);
187    RegionFromSection();
188    raw_context.epc = 0x00400020;
189    raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
190  
191    StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
192    StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
193                           &frame_symbolizer);
194    vector<const CodeModule*> modules_without_symbols;
195    vector<const CodeModule*> modules_with_corrupt_symbols;
196    ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
197                            &modules_with_corrupt_symbols));
198    ASSERT_EQ(1U, modules_without_symbols.size());
199    ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
200    ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
201    frames = call_stack.frames();
202    StackFrameMIPS* frame = static_cast<StackFrameMIPS*>(frames->at(0));
203    // Check that the values from the original raw context made it
204    // through to the context in the stack frame.
205    EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
206  }
207  
208  // The stackwalker should be able to produce the context frame even
209  // without stack memory present.
210  TEST_F(GetContextFrame, NoStackMemory) {
211    raw_context.context_flags =
212        raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
213    raw_context.epc = 0x00400020;
214    raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
215  
216    StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
217    StackwalkerMIPS walker(&system_info, &raw_context, NULL, &modules,
218                           &frame_symbolizer);
219    vector<const CodeModule*> modules_without_symbols;
220    vector<const CodeModule*> modules_with_corrupt_symbols;
221    ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
222                            &modules_with_corrupt_symbols));
223    ASSERT_EQ(1U, modules_without_symbols.size());
224    ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
225    ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
226    frames = call_stack.frames();
227    StackFrameMIPS* frame = static_cast<StackFrameMIPS*>(frames->at(0));
228    // Check that the values from the original raw context made it
229    // through to the context in the stack frame.
230    EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
231  }
232  
233  class GetCallerFrame: public StackwalkerMIPSFixture, public Test { };
234  
235  TEST_F(GetCallerFrame, ScanWithoutSymbols) {
236    raw_context.context_flags =
237        raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
238    // When the stack walker resorts to scanning the stack,
239    // only addresses located within loaded modules are
240    // considered valid return addresses.
241    // Force scanning through three frames to ensure that the
242    // stack pointer is set properly in scan-recovered frames.
243    stack_section.start() = 0x80000000;
244    uint64_t return_address1 = 0x00400100;
245    uint64_t return_address2 = 0x00400900;
246    Label frame1_sp, frame2_sp;
247    stack_section
248      // frame 0
249      .Append(32, 0)                      // space
250  
251      .D64(0x00490000)                    // junk that's not
252      .D64(0x00600000)                    // a return address
253  
254      .D64(frame1_sp)                     // stack pointer
255      .D64(return_address1)               // actual return address
256      // frame 1
257      .Mark(&frame1_sp)
258      .Append(32, 0)                      // space
259  
260      .D64(0xF0000000)                    // more junk
261      .D64(0x0000000D)
262  
263      .D64(frame2_sp)                     // stack pointer
264      .D64(return_address2)               // actual return address
265      // frame 2
266      .Mark(&frame2_sp)
267      .Append(64, 0);                     // end of stack
268    RegionFromSection();
269  
270    raw_context.epc = 0x00405510;
271    raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value();
272    raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address1;
273  
274    StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
275    StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
276                           &frame_symbolizer);
277    vector<const CodeModule*> modules_without_symbols;
278    vector<const CodeModule*> modules_with_corrupt_symbols;
279    ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
280                            &modules_with_corrupt_symbols));
281    ASSERT_EQ(1U, modules_without_symbols.size());
282    ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
283    ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
284    frames = call_stack.frames();
285    ASSERT_EQ(3U, frames->size());
286  
287    StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0));
288    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
289    ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity);
290    EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
291  
292    StackFrameMIPS* frame1 = static_cast<StackFrameMIPS*>(frames->at(1));
293    EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
294    ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC |
295               StackFrameMIPS::CONTEXT_VALID_SP |
296               StackFrameMIPS::CONTEXT_VALID_FP |
297               StackFrameMIPS::CONTEXT_VALID_RA),
298              frame1->context_validity);
299    EXPECT_EQ(return_address1 - 2 * sizeof(return_address1), frame1->context.epc);
300    EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]);
301  
302    StackFrameMIPS* frame2 = static_cast<StackFrameMIPS*>(frames->at(2));
303    EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame2->trust);
304    ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC |
305               StackFrameMIPS::CONTEXT_VALID_SP |
306               StackFrameMIPS::CONTEXT_VALID_FP |
307               StackFrameMIPS::CONTEXT_VALID_RA),
308              frame2->context_validity);
309    EXPECT_EQ(return_address2 - 2 * sizeof(return_address2), frame2->context.epc);
310    EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_MIPS_REG_SP]);
311  }
312  
313  TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
314    raw_context.context_flags =
315        raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
316    // During stack scanning, if a potential return address
317    // is located within a loaded module that has symbols,
318    // it is only considered a valid return address if it
319    // lies within a function's bounds.
320    stack_section.start() = 0x80000000;
321    uint64_t return_address = 0x00500200;
322    Label frame1_sp;
323    stack_section
324      // frame 0
325      .Append(16, 0)                      // space
326  
327      .D64(0x00490000)                    // junk that's not
328      .D64(0x00600000)                    // a return address
329  
330      .D64(0x00401000)                    // a couple of plausible addresses
331      .D64(0x0050F000)                    // that are not within functions
332  
333      .D64(frame1_sp)                     // stack pointer
334      .D64(return_address)                // actual return address
335      // frame 1
336      .Mark(&frame1_sp)
337      .Append(64, 0);                     // end of stack
338    RegionFromSection();
339  
340    raw_context.epc = 0x00400200;
341    raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value();
342    raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address;
343  
344    SetModuleSymbols(&module1,
345                     // The youngest frame's function.
346                     "FUNC 100 400 10 monotreme\n");
347    SetModuleSymbols(&module2,
348                     // The calling frame's function.
349                     "FUNC 100 400 10 marsupial\n");
350  
351    StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
352    StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
353                           &frame_symbolizer);
354    vector<const CodeModule*> modules_without_symbols;
355    vector<const CodeModule*> modules_with_corrupt_symbols;
356    ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
357                            &modules_with_corrupt_symbols));
358    ASSERT_EQ(0U, modules_without_symbols.size());
359    ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
360    frames = call_stack.frames();
361    ASSERT_EQ(2U, frames->size());
362  
363    StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0));
364    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
365    ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity);
366    EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
367    EXPECT_EQ("monotreme", frame0->function_name);
368    EXPECT_EQ(0x00400100U, frame0->function_base);
369  
370    StackFrameMIPS* frame1 = static_cast<StackFrameMIPS*>(frames->at(1));
371    EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
372    ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC |
373               StackFrameMIPS::CONTEXT_VALID_SP |
374               StackFrameMIPS::CONTEXT_VALID_FP |
375               StackFrameMIPS::CONTEXT_VALID_RA),
376              frame1->context_validity);
377    EXPECT_EQ(return_address - 2 * sizeof(return_address), frame1->context.epc);
378    EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]);
379    EXPECT_EQ("marsupial", frame1->function_name);
380    EXPECT_EQ(0x00500100U, frame1->function_base);
381  }
382  
383  TEST_F(GetCallerFrame, CheckStackFrameSizeLimit) {
384    raw_context.context_flags =
385        raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
386    // If the stackwalker resorts to stack scanning, it will scan only
387    // 1024 bytes of stack which correspondes to maximum size of stack frame.
388    stack_section.start() = 0x80000000;
389    uint64_t return_address1 = 0x00500100;
390    uint64_t return_address2 = 0x00500900;
391    Label frame1_sp, frame2_sp;
392    stack_section
393      // frame 0
394      .Append(32, 0)                      // space
395  
396      .D64(0x00490000)                    // junk that's not
397      .D64(0x00600000)                    // a return address
398  
399      .Append(96, 0)                      // more space
400  
401      .D64(frame1_sp)                     // stack pointer
402      .D64(return_address1)               // actual return address
403      // frame 1
404      .Mark(&frame1_sp)
405      .Append(128 * 4, 0)                 // space
406  
407      .D64(0x00F00000)                    // more junk
408      .D64(0x0000000D)
409  
410      .Append(128 * 4, 0)                 // more space
411  
412      .D64(frame2_sp)                     // stack pointer
413      .D64(return_address2)               // actual return address
414                                          // (won't be found)
415      // frame 2
416      .Mark(&frame2_sp)
417      .Append(64, 0);                     // end of stack
418    RegionFromSection();
419  
420    raw_context.epc = 0x00405510;
421    raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value();
422    raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address1;
423  
424    StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
425    StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
426                           &frame_symbolizer);
427    vector<const CodeModule*> modules_without_symbols;
428    vector<const CodeModule*> modules_with_corrupt_symbols;
429    ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
430                            &modules_with_corrupt_symbols));
431    ASSERT_EQ(2U, modules_without_symbols.size());
432    ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
433    ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
434    ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
435    frames = call_stack.frames();
436    ASSERT_EQ(2U, frames->size());
437  
438    StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0));
439    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
440    ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity);
441    EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
442  
443    StackFrameMIPS* frame1 = static_cast<StackFrameMIPS*>(frames->at(1));
444    EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
445    ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC |
446               StackFrameMIPS::CONTEXT_VALID_SP |
447               StackFrameMIPS::CONTEXT_VALID_FP |
448               StackFrameMIPS::CONTEXT_VALID_RA),
449              frame1->context_validity);
450    EXPECT_EQ(return_address1 - 2 * sizeof(return_address1), frame1->context.epc);
451    EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]);
452  }
453  
454  // Test that set_max_frames_scanned prevents using stack scanning
455  // to find caller frames.
456  TEST_F(GetCallerFrame, ScanningNotAllowed) {
457    raw_context.context_flags =
458        raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
459    // When the stack walker resorts to scanning the stack,
460    // only fixed number of frames are allowed to be scanned out from stack
461    stack_section.start() = 0x80000000;
462    uint64_t return_address1 = 0x00500100;
463    uint64_t return_address2 = 0x00500900;
464    Label frame1_sp, frame2_sp;
465    stack_section
466      // frame 0
467      .Append(32, 0)                      // space
468  
469      .D64(0x00490000)                    // junk that's not
470      .D64(0x00600000)                    // a return address
471  
472      .Append(96, 0)                      // more space
473  
474      .D64(frame1_sp)                     // stack pointer
475      .D64(return_address1)               // actual return address
476      // frame 1
477      .Mark(&frame1_sp)
478      .Append(128 * 4, 0)                 // space
479  
480      .D64(0x00F00000)                    // more junk
481      .D64(0x0000000D)
482  
483      .Append(128 * 4, 0)                 // more space
484  
485      .D64(frame2_sp)                     // stack pointer
486      .D64(return_address2)               // actual return address
487                                          // (won't be found)
488      // frame 2
489      .Mark(&frame2_sp)
490      .Append(64, 0);                     // end of stack
491    RegionFromSection();
492  
493    raw_context.epc = 0x00405510;
494    raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value();
495    raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address1;
496  
497    StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
498    StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
499                           &frame_symbolizer);
500    Stackwalker::set_max_frames_scanned(0);
501  
502    vector<const CodeModule*> modules_without_symbols;
503    vector<const CodeModule*> modules_with_corrupt_symbols;
504    ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
505                            &modules_with_corrupt_symbols));
506    ASSERT_EQ(1U, modules_without_symbols.size());
507    ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
508    ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
509    frames = call_stack.frames();
510    ASSERT_EQ(1U, frames->size());
511  
512    StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0));
513    EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
514    ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity);
515    EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
516  }
517  
518  struct CFIFixture: public StackwalkerMIPSFixture {
519    CFIFixture() {
520      // Provide some STACK CFI records;
521      SetModuleSymbols(&module1,
522                       // The youngest frame's function.
523                       "FUNC 4000 1000 0 enchiridion\n"
524                       // Initially, nothing has been pushed on the stack,
525                       // and the return address is still in the $ra register.
526                       "STACK CFI INIT 4000 1000 .cfa: $sp 0 + .ra: $ra\n"
527                       // Move stack pointer.
528                       "STACK CFI 4004 .cfa: $sp 32 +\n"
529                       // store $fp and ra
530                       "STACK CFI 4008 $fp: .cfa -8 + ^ .ra: .cfa -4 + ^\n"
531                       // restore $fp
532                       "STACK CFI 400c .cfa: $fp 32 +\n"
533                       // restore $sp
534                       "STACK CFI 4018 .cfa: $sp 32 +\n"
535  
536                       "STACK CFI 4020 $fp: $fp .cfa: $sp 0 + .ra: .ra\n"
537  
538                       // The calling function.
539                       "FUNC 5000 1000 0 epictetus\n"
540                       // Mark it as end of stack.
541                       "STACK CFI INIT 5000 8 .cfa: $sp 0 + .ra: $ra\n"
542  
543                       // A function whose CFI makes the stack pointer
544                       // go backwards.
545                       "FUNC 6000 1000 20 palinal\n"
546                       "STACK CFI INIT 6000 1000 .cfa: $sp 4 - .ra: $ra\n"
547  
548                       // A function with CFI expressions that can't be
549                       // evaluated.
550                       "FUNC 7000 1000 20 rhetorical\n"
551                       "STACK CFI INIT 7000 1000 .cfa: moot .ra: ambiguous\n"
552                     );
553  
554      // Provide some distinctive values for the caller's registers.
555      expected.epc = 0x00405500;
556      expected.iregs[MD_CONTEXT_MIPS_REG_S0] = 0x0;
557      expected.iregs[MD_CONTEXT_MIPS_REG_S1] = 0x1;
558      expected.iregs[MD_CONTEXT_MIPS_REG_S2] = 0x2;
559      expected.iregs[MD_CONTEXT_MIPS_REG_S3] = 0x3;
560      expected.iregs[MD_CONTEXT_MIPS_REG_S4] = 0x4;
561      expected.iregs[MD_CONTEXT_MIPS_REG_S5] = 0x5;
562      expected.iregs[MD_CONTEXT_MIPS_REG_S6] = 0x6;
563      expected.iregs[MD_CONTEXT_MIPS_REG_S7] = 0x7;
564      expected.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
565      expected.iregs[MD_CONTEXT_MIPS_REG_FP] = 0x80000000;
566      expected.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510;
567  
568      // Expect CFI to recover all callee-save registers. Since CFI is the
569      // only stack frame construction technique we have, aside from the
570      // context frame itself, there's no way for us to have a set of valid
571      // registers smaller than this.
572      expected_validity = (StackFrameMIPS::CONTEXT_VALID_PC |
573                           StackFrameMIPS::CONTEXT_VALID_S0 |
574                           StackFrameMIPS::CONTEXT_VALID_S1 |
575                           StackFrameMIPS::CONTEXT_VALID_S2 |
576                           StackFrameMIPS::CONTEXT_VALID_S3 |
577                           StackFrameMIPS::CONTEXT_VALID_S4 |
578                           StackFrameMIPS::CONTEXT_VALID_S5 |
579                           StackFrameMIPS::CONTEXT_VALID_S6 |
580                           StackFrameMIPS::CONTEXT_VALID_S7 |
581                           StackFrameMIPS::CONTEXT_VALID_SP |
582                           StackFrameMIPS::CONTEXT_VALID_FP |
583                           StackFrameMIPS::CONTEXT_VALID_GP |
584                           StackFrameMIPS::CONTEXT_VALID_RA);
585  
586      // By default, context frames provide all registers, as normal.
587      context_frame_validity = StackFrameMIPS::CONTEXT_VALID_ALL;
588  
589      // By default, registers are unchanged.
590      raw_context = expected;
591    }
592  
593    // Walk the stack, using stack_section as the contents of the stack
594    // and raw_context as the current register values. (Set the stack
595    // pointer to the stack's starting address.) Expect two stack
596    // frames; in the older frame, expect the callee-saves registers to
597    // have values matching those in 'expected'.
598    void CheckWalk() {
599      RegionFromSection();
600      raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value();
601  
602      StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
603      StackwalkerMIPS walker(&system_info, &raw_context, &stack_region,
604                             &modules, &frame_symbolizer);
605      vector<const CodeModule*> modules_without_symbols;
606      vector<const CodeModule*> modules_with_corrupt_symbols;
607      ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
608                              &modules_with_corrupt_symbols));
609      ASSERT_EQ(0U, modules_without_symbols.size());
610      ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
611      frames = call_stack.frames();
612      ASSERT_EQ(2U, frames->size());
613  
614      StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0));
615      EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
616      ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity);
617      EXPECT_EQ("enchiridion", frame0->function_name);
618      EXPECT_EQ(0x00404000U, frame0->function_base);
619  
620      StackFrameMIPS* frame1 = static_cast<StackFrameMIPS*>(frames->at(1));
621      EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
622      ASSERT_EQ(expected_validity, frame1->context_validity);
623      EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S0],
624                frame1->context.iregs[MD_CONTEXT_MIPS_REG_S0]);
625      EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S1],
626                frame1->context.iregs[MD_CONTEXT_MIPS_REG_S1]);
627      EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S2],
628                frame1->context.iregs[MD_CONTEXT_MIPS_REG_S2]);
629      EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S3],
630                frame1->context.iregs[MD_CONTEXT_MIPS_REG_S3]);
631      EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S4],
632                frame1->context.iregs[MD_CONTEXT_MIPS_REG_S4]);
633      EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S5],
634                frame1->context.iregs[MD_CONTEXT_MIPS_REG_S5]);
635      EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S6],
636                frame1->context.iregs[MD_CONTEXT_MIPS_REG_S6]);
637      EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S7],
638                frame1->context.iregs[MD_CONTEXT_MIPS_REG_S7]);
639      EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_FP],
640                frame1->context.iregs[MD_CONTEXT_MIPS_REG_FP]);
641      EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_RA],
642                frame1->context.iregs[MD_CONTEXT_MIPS_REG_RA]);
643      EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_SP],
644                frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]);
645      EXPECT_EQ(expected.epc, frame1->context.epc);
646      EXPECT_EQ(expected.epc, frame1->instruction);
647      EXPECT_EQ("epictetus", frame1->function_name);
648      EXPECT_EQ(0x00405000U, frame1->function_base);
649    }
650  
651    // The values we expect to find for the caller's registers. Forcibly
652    // default-init it, since it's POD and not all bits are always overwritten by
653    // the constructor.
654    MDRawContextMIPS expected{};
655  
656    // The validity mask for expected.
657    int expected_validity;
658  
659    // The validity mask to impose on the context frame.
660    int context_frame_validity;
661  };
662  
663  class CFI: public CFIFixture, public Test { };
664  
665  // TODO(gordanac): add CFI tests
666  
667  TEST_F(CFI, At4004) {
668    raw_context.context_flags =
669        raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
670    Label frame1_sp = expected.iregs[MD_CONTEXT_MIPS_REG_SP];
671    stack_section
672      // frame0
673      .Append(16, 0)               // space
674      .D64(frame1_sp)              // stack pointer
675      .D64(0x00405510)             // return address
676      .Mark(&frame1_sp);           // This effectively sets stack_section.start().
677    raw_context.epc = 0x00404004;
678    CheckWalk();
679  }
680  
681  // Check that we reject rules that would cause the stack pointer to
682  // move in the wrong direction.
683  TEST_F(CFI, RejectBackwards) {
684    raw_context.context_flags =
685        raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
686    raw_context.epc = 0x40005000;
687    raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
688    raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510;
689  
690    StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
691    StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
692                           &frame_symbolizer);
693    vector<const CodeModule*> modules_without_symbols;
694    vector<const CodeModule*> modules_with_corrupt_symbols;
695    ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
696                            &modules_with_corrupt_symbols));
697    ASSERT_EQ(0U, modules_without_symbols.size());
698    ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
699    frames = call_stack.frames();
700    ASSERT_EQ(1U, frames->size());
701  }
702  
703  // Check that we reject rules whose expressions' evaluation fails.
704  TEST_F(CFI, RejectBadExpressions) {
705    raw_context.context_flags =
706        raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
707    raw_context.epc = 0x00407000;
708    raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
709    raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510;
710  
711    StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
712    StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
713                           &frame_symbolizer);
714    vector<const CodeModule*> modules_without_symbols;
715    vector<const CodeModule*> modules_with_corrupt_symbols;
716    ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
717                            &modules_with_corrupt_symbols));
718    ASSERT_EQ(0U, modules_without_symbols.size());
719    ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
720    frames = call_stack.frames();
721    ASSERT_EQ(1U, frames->size());
722  }