xref: /aosp_15_r20/external/google-breakpad/src/processor/stackwalker_mips_unittest.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1 // Copyright 2013 Google LLC
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 //     * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //     * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 //     * Neither the name of Google LLC nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 // Original author: Gordana Cmiljanovic <[email protected]>
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:
StackwalkerMIPSFixture()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.
SetModuleSymbols(MockCodeModule * module,const string & 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.
RegionFromSection()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.
BrandContext(MDRawContextMIPS * raw_context)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 
TEST_F(SanityCheck,NoResolver)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 
TEST_F(GetContextFrame,Simple)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.
TEST_F(GetContextFrame,NoStackMemory)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 
TEST_F(GetCallerFrame,ScanWithoutSymbols)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 
TEST_F(GetCallerFrame,ScanWithFunctionSymbols)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 
TEST_F(GetCallerFrame,CheckStackFrameSizeLimit)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.
TEST_F(GetCallerFrame,ScanningNotAllowed)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 {
CFIFixtureCFIFixture511   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'.
CheckWalkCFIFixture589   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 
TEST_F(CFI,At4004)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.
TEST_F(CFI,RejectBackwards)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.
TEST_F(CFI,RejectBadExpressions)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 }
709