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