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