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