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 raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL;
149 stack_section.start() = 0x80000000;
150 stack_section.D32(0).D32(0x0);
151 RegionFromSection();
152 raw_context.epc = 0x00400020;
153 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
154
155 StackFrameSymbolizer frame_symbolizer(NULL, NULL);
156 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
157 &frame_symbolizer);
158 // This should succeed, even without a resolver or supplier.
159 vector<const CodeModule*> modules_without_symbols;
160 vector<const CodeModule*> modules_with_corrupt_symbols;
161 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
162 &modules_with_corrupt_symbols));
163 ASSERT_EQ(1U, modules_without_symbols.size());
164 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
165 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
166 frames = call_stack.frames();
167 ASSERT_EQ(1U, frames->size());
168 StackFrameMIPS* frame = static_cast<StackFrameMIPS*>(frames->at(0));
169 // Check that the values from the original raw context made it
170 // through to the context in the stack frame.
171 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
172 }
173
174 class GetContextFrame: public StackwalkerMIPSFixture, public Test { };
175
TEST_F(GetContextFrame,Simple)176 TEST_F(GetContextFrame, Simple) {
177 raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL;
178 stack_section.start() = 0x80000000;
179 stack_section.D32(0).D32(0x0);
180 RegionFromSection();
181 raw_context.epc = 0x00400020;
182 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
183
184 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
185 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
186 &frame_symbolizer);
187 vector<const CodeModule*> modules_without_symbols;
188 vector<const CodeModule*> modules_with_corrupt_symbols;
189 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
190 &modules_with_corrupt_symbols));
191 ASSERT_EQ(1U, modules_without_symbols.size());
192 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
193 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
194 frames = call_stack.frames();
195 StackFrameMIPS* frame = static_cast<StackFrameMIPS*>(frames->at(0));
196 // Check that the values from the original raw context made it
197 // through to the context in the stack frame.
198 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
199 }
200
201 // The stackwalker should be able to produce the context frame even
202 // without stack memory present.
TEST_F(GetContextFrame,NoStackMemory)203 TEST_F(GetContextFrame, NoStackMemory) {
204 raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL;
205 raw_context.epc = 0x00400020;
206 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
207
208 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
209 StackwalkerMIPS walker(&system_info, &raw_context, NULL, &modules,
210 &frame_symbolizer);
211 vector<const CodeModule*> modules_without_symbols;
212 vector<const CodeModule*> modules_with_corrupt_symbols;
213 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
214 &modules_with_corrupt_symbols));
215 ASSERT_EQ(1U, modules_without_symbols.size());
216 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
217 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
218 frames = call_stack.frames();
219 StackFrameMIPS* frame = static_cast<StackFrameMIPS*>(frames->at(0));
220 // Check that the values from the original raw context made it
221 // through to the context in the stack frame.
222 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
223 }
224
225 class GetCallerFrame: public StackwalkerMIPSFixture, public Test { };
226
TEST_F(GetCallerFrame,ScanWithoutSymbols)227 TEST_F(GetCallerFrame, ScanWithoutSymbols) {
228 raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL;
229 // When the stack walker resorts to scanning the stack,
230 // only addresses located within loaded modules are
231 // considered valid return addresses.
232 // Force scanning through three frames to ensure that the
233 // stack pointer is set properly in scan-recovered frames.
234 stack_section.start() = 0x80000000;
235 uint32_t return_address1 = 0x00400100;
236 uint32_t return_address2 = 0x00400900;
237 Label frame1_sp, frame2_sp;
238 stack_section
239 // frame 0
240 .Append(16, 0) // space
241
242 .D32(0x00490000) // junk that's not
243 .D32(0x00600000) // a return address
244
245 .D32(frame1_sp) // stack pointer
246 .D32(return_address1) // actual return address
247 // frame 1
248 .Mark(&frame1_sp)
249 .Append(16, 0) // space
250
251 .D32(0xF0000000) // more junk
252 .D32(0x0000000D)
253
254 .D32(frame2_sp) // stack pointer
255 .D32(return_address2) // actual return address
256 // frame 2
257 .Mark(&frame2_sp)
258 .Append(32, 0); // end of stack
259 RegionFromSection();
260
261 raw_context.epc = 0x00405510;
262 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value();
263 raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address1;
264
265 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
266 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
267 &frame_symbolizer);
268 vector<const CodeModule*> modules_without_symbols;
269 vector<const CodeModule*> modules_with_corrupt_symbols;
270 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
271 &modules_with_corrupt_symbols));
272 ASSERT_EQ(1U, modules_without_symbols.size());
273 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
274 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
275 frames = call_stack.frames();
276 ASSERT_EQ(3U, frames->size());
277
278 StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0));
279 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
280 ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity);
281 EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
282
283 StackFrameMIPS* frame1 = static_cast<StackFrameMIPS*>(frames->at(1));
284 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
285 ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC |
286 StackFrameMIPS::CONTEXT_VALID_SP |
287 StackFrameMIPS::CONTEXT_VALID_FP |
288 StackFrameMIPS::CONTEXT_VALID_RA),
289 frame1->context_validity);
290 EXPECT_EQ(return_address1 - 2 * sizeof(return_address1), frame1->context.epc);
291 EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]);
292
293 StackFrameMIPS* frame2 = static_cast<StackFrameMIPS*>(frames->at(2));
294 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame2->trust);
295 ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC |
296 StackFrameMIPS::CONTEXT_VALID_SP |
297 StackFrameMIPS::CONTEXT_VALID_FP |
298 StackFrameMIPS::CONTEXT_VALID_RA),
299 frame2->context_validity);
300 EXPECT_EQ(return_address2 - 2 * sizeof(return_address2), frame2->context.epc);
301 EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_MIPS_REG_SP]);
302 }
303
TEST_F(GetCallerFrame,ScanWithFunctionSymbols)304 TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
305 raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL;
306 // During stack scanning, if a potential return address
307 // is located within a loaded module that has symbols,
308 // it is only considered a valid return address if it
309 // lies within a function's bounds.
310 stack_section.start() = 0x80000000;
311 uint32_t return_address = 0x00500200;
312 Label frame1_sp;
313 stack_section
314 // frame 0
315 .Append(16, 0) // space
316
317 .D32(0x00490000) // junk that's not
318 .D32(0x00600000) // a return address
319
320 .D32(0x00401000) // a couple of plausible addresses
321 .D32(0x0050F000) // that are not within functions
322
323 .D32(frame1_sp) // stack pointer
324 .D32(return_address) // actual return address
325 // frame 1
326 .Mark(&frame1_sp)
327 .Append(32, 0); // end of stack
328 RegionFromSection();
329
330 raw_context.epc = 0x00400200;
331 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value();
332 raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address;
333
334 SetModuleSymbols(&module1,
335 // The youngest frame's function.
336 "FUNC 100 400 10 monotreme\n");
337 SetModuleSymbols(&module2,
338 // The calling frame's function.
339 "FUNC 100 400 10 marsupial\n");
340
341 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
342 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
343 &frame_symbolizer);
344 vector<const CodeModule*> modules_without_symbols;
345 vector<const CodeModule*> modules_with_corrupt_symbols;
346 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
347 &modules_with_corrupt_symbols));
348 ASSERT_EQ(0U, modules_without_symbols.size());
349 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
350 frames = call_stack.frames();
351 ASSERT_EQ(2U, frames->size());
352
353 StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0));
354 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
355 ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity);
356 EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
357 EXPECT_EQ("monotreme", frame0->function_name);
358 EXPECT_EQ(0x00400100U, frame0->function_base);
359
360 StackFrameMIPS* frame1 = static_cast<StackFrameMIPS*>(frames->at(1));
361 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
362 ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC |
363 StackFrameMIPS::CONTEXT_VALID_SP |
364 StackFrameMIPS::CONTEXT_VALID_FP |
365 StackFrameMIPS::CONTEXT_VALID_RA),
366 frame1->context_validity);
367 EXPECT_EQ(return_address - 2 * sizeof(return_address), frame1->context.epc);
368 EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]);
369 EXPECT_EQ("marsupial", frame1->function_name);
370 EXPECT_EQ(0x00500100U, frame1->function_base);
371 }
372
TEST_F(GetCallerFrame,CheckStackFrameSizeLimit)373 TEST_F(GetCallerFrame, CheckStackFrameSizeLimit) {
374 raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL;
375 // If the stackwalker resorts to stack scanning, it will scan only
376 // 1024 bytes of stack which correspondes to maximum size of stack frame.
377 stack_section.start() = 0x80000000;
378 uint32_t return_address1 = 0x00500100;
379 uint32_t return_address2 = 0x00500900;
380 Label frame1_sp, frame2_sp;
381 stack_section
382 // frame 0
383 .Append(32, 0) // space
384
385 .D32(0x00490000) // junk that's not
386 .D32(0x00600000) // a return address
387
388 .Append(96, 0) // more space
389
390 .D32(frame1_sp) // stack pointer
391 .D32(return_address1) // actual return address
392 // frame 1
393 .Mark(&frame1_sp)
394 .Append(128 * 4, 0) // space
395
396 .D32(0x00F00000) // more junk
397 .D32(0x0000000D)
398
399 .Append(128 * 4, 0) // more space
400
401 .D32(frame2_sp) // stack pointer
402 .D32(return_address2) // actual return address
403 // (won't be found)
404 // frame 2
405 .Mark(&frame2_sp)
406 .Append(32, 0); // end of stack
407 RegionFromSection();
408
409 raw_context.epc = 0x00405510;
410 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value();
411 raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address1;
412
413 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
414 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
415 &frame_symbolizer);
416 vector<const CodeModule*> modules_without_symbols;
417 vector<const CodeModule*> modules_with_corrupt_symbols;
418 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
419 &modules_with_corrupt_symbols));
420 ASSERT_EQ(2U, modules_without_symbols.size());
421 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
422 ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
423 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
424 frames = call_stack.frames();
425 ASSERT_EQ(2U, frames->size());
426
427 StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0));
428 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
429 ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity);
430 EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
431
432 StackFrameMIPS* frame1 = static_cast<StackFrameMIPS*>(frames->at(1));
433 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
434 ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC |
435 StackFrameMIPS::CONTEXT_VALID_SP |
436 StackFrameMIPS::CONTEXT_VALID_FP |
437 StackFrameMIPS::CONTEXT_VALID_RA),
438 frame1->context_validity);
439 EXPECT_EQ(return_address1 - 2 * sizeof(return_address1), frame1->context.epc);
440 EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]);
441 }
442
443 // Test that set_max_frames_scanned prevents using stack scanning
444 // to find caller frames.
TEST_F(GetCallerFrame,ScanningNotAllowed)445 TEST_F(GetCallerFrame, ScanningNotAllowed) {
446 raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL;
447 // When the stack walker resorts to scanning the stack,
448 // only fixed number of frames are allowed to be scanned out from stack
449 stack_section.start() = 0x80000000;
450 uint32_t return_address1 = 0x00500100;
451 uint32_t return_address2 = 0x00500900;
452 Label frame1_sp, frame2_sp;
453 stack_section
454 // frame 0
455 .Append(32, 0) // space
456
457 .D32(0x00490000) // junk that's not
458 .D32(0x00600000) // a return address
459
460 .Append(96, 0) // more space
461
462 .D32(frame1_sp) // stack pointer
463 .D32(return_address1) // actual return address
464 // frame 1
465 .Mark(&frame1_sp)
466 .Append(128 * 4, 0) // space
467
468 .D32(0x00F00000) // more junk
469 .D32(0x0000000D)
470
471 .Append(128 * 4, 0) // more space
472
473 .D32(frame2_sp) // stack pointer
474 .D32(return_address2) // actual return address
475 // (won't be found)
476 // frame 2
477 .Mark(&frame2_sp)
478 .Append(32, 0); // end of stack
479 RegionFromSection();
480
481 raw_context.epc = 0x00405510;
482 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value();
483 raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address1;
484
485 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
486 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
487 &frame_symbolizer);
488 Stackwalker::set_max_frames_scanned(0);
489
490 vector<const CodeModule*> modules_without_symbols;
491 vector<const CodeModule*> modules_with_corrupt_symbols;
492 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
493 &modules_with_corrupt_symbols));
494 ASSERT_EQ(1U, modules_without_symbols.size());
495 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
496 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
497 frames = call_stack.frames();
498 ASSERT_EQ(1U, frames->size());
499
500 StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0));
501 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
502 ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity);
503 EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
504 }
505
506 struct CFIFixture: public StackwalkerMIPSFixture {
CFIFixtureCFIFixture507 CFIFixture() {
508 // Provide some STACK CFI records;
509 SetModuleSymbols(&module1,
510 // The youngest frame's function.
511 "FUNC 4000 1000 0 enchiridion\n"
512 // Initially, nothing has been pushed on the stack,
513 // and the return address is still in the $ra register.
514 "STACK CFI INIT 4000 1000 .cfa: $sp 0 + .ra: $ra\n"
515 // Move stack pointer.
516 "STACK CFI 4004 .cfa: $sp 32 +\n"
517 // store $fp and ra
518 "STACK CFI 4008 $fp: .cfa -8 + ^ .ra: .cfa -4 + ^\n"
519 // restore $fp
520 "STACK CFI 400c .cfa: $fp 32 +\n"
521 // restore $sp
522 "STACK CFI 4018 .cfa: $sp 32 +\n"
523
524 "STACK CFI 4020 $fp: $fp .cfa: $sp 0 + .ra: .ra\n"
525
526 // The calling function.
527 "FUNC 5000 1000 0 epictetus\n"
528 // Mark it as end of stack.
529 "STACK CFI INIT 5000 8 .cfa: $sp 0 + .ra: $ra\n"
530
531 // A function whose CFI makes the stack pointer
532 // go backwards.
533 "FUNC 6000 1000 20 palinal\n"
534 "STACK CFI INIT 6000 1000 .cfa: $sp 4 - .ra: $ra\n"
535
536 // A function with CFI expressions that can't be
537 // evaluated.
538 "FUNC 7000 1000 20 rhetorical\n"
539 "STACK CFI INIT 7000 1000 .cfa: moot .ra: ambiguous\n"
540 );
541
542 // Provide some distinctive values for the caller's registers.
543 expected.epc = 0x00405508;
544 expected.iregs[MD_CONTEXT_MIPS_REG_S0] = 0x0;
545 expected.iregs[MD_CONTEXT_MIPS_REG_S1] = 0x1;
546 expected.iregs[MD_CONTEXT_MIPS_REG_S2] = 0x2;
547 expected.iregs[MD_CONTEXT_MIPS_REG_S3] = 0x3;
548 expected.iregs[MD_CONTEXT_MIPS_REG_S4] = 0x4;
549 expected.iregs[MD_CONTEXT_MIPS_REG_S5] = 0x5;
550 expected.iregs[MD_CONTEXT_MIPS_REG_S6] = 0x6;
551 expected.iregs[MD_CONTEXT_MIPS_REG_S7] = 0x7;
552 expected.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
553 expected.iregs[MD_CONTEXT_MIPS_REG_FP] = 0x80000000;
554 expected.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510;
555
556 // Expect CFI to recover all callee-save registers. Since CFI is the
557 // only stack frame construction technique we have, aside from the
558 // context frame itself, there's no way for us to have a set of valid
559 // registers smaller than this.
560 expected_validity = (StackFrameMIPS::CONTEXT_VALID_PC |
561 StackFrameMIPS::CONTEXT_VALID_S0 |
562 StackFrameMIPS::CONTEXT_VALID_S1 |
563 StackFrameMIPS::CONTEXT_VALID_S2 |
564 StackFrameMIPS::CONTEXT_VALID_S3 |
565 StackFrameMIPS::CONTEXT_VALID_S4 |
566 StackFrameMIPS::CONTEXT_VALID_S5 |
567 StackFrameMIPS::CONTEXT_VALID_S6 |
568 StackFrameMIPS::CONTEXT_VALID_S7 |
569 StackFrameMIPS::CONTEXT_VALID_SP |
570 StackFrameMIPS::CONTEXT_VALID_FP |
571 StackFrameMIPS::CONTEXT_VALID_RA);
572
573 // By default, context frames provide all registers, as normal.
574 context_frame_validity = StackFrameMIPS::CONTEXT_VALID_ALL;
575
576 // By default, registers are unchanged.
577 raw_context = expected;
578 }
579
580 // Walk the stack, using stack_section as the contents of the stack
581 // and raw_context as the current register values. (Set the stack
582 // pointer to the stack's starting address.) Expect two stack
583 // frames; in the older frame, expect the callee-saves registers to
584 // have values matching those in 'expected'.
CheckWalkCFIFixture585 void CheckWalk() {
586 RegionFromSection();
587 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value();
588
589 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
590 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region,
591 &modules, &frame_symbolizer);
592 vector<const CodeModule*> modules_without_symbols;
593 vector<const CodeModule*> modules_with_corrupt_symbols;
594 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
595 &modules_with_corrupt_symbols));
596 ASSERT_EQ(0U, modules_without_symbols.size());
597 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
598 frames = call_stack.frames();
599 ASSERT_EQ(2U, frames->size());
600
601 StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0));
602 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
603 ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity);
604 EXPECT_EQ("enchiridion", frame0->function_name);
605 EXPECT_EQ(0x00404000U, frame0->function_base);
606
607 StackFrameMIPS* frame1 = static_cast<StackFrameMIPS*>(frames->at(1));
608 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
609 ASSERT_EQ(expected_validity, frame1->context_validity);
610 EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S0],
611 frame1->context.iregs[MD_CONTEXT_MIPS_REG_S0]);
612 EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S1],
613 frame1->context.iregs[MD_CONTEXT_MIPS_REG_S1]);
614 EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S2],
615 frame1->context.iregs[MD_CONTEXT_MIPS_REG_S2]);
616 EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S3],
617 frame1->context.iregs[MD_CONTEXT_MIPS_REG_S3]);
618 EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S4],
619 frame1->context.iregs[MD_CONTEXT_MIPS_REG_S4]);
620 EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S5],
621 frame1->context.iregs[MD_CONTEXT_MIPS_REG_S5]);
622 EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S6],
623 frame1->context.iregs[MD_CONTEXT_MIPS_REG_S6]);
624 EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S7],
625 frame1->context.iregs[MD_CONTEXT_MIPS_REG_S7]);
626 EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_FP],
627 frame1->context.iregs[MD_CONTEXT_MIPS_REG_FP]);
628 EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_RA],
629 frame1->context.iregs[MD_CONTEXT_MIPS_REG_RA]);
630 EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_SP],
631 frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]);
632 EXPECT_EQ(expected.epc, frame1->context.epc);
633 EXPECT_EQ(expected.epc, frame1->instruction);
634 EXPECT_EQ("epictetus", frame1->function_name);
635 EXPECT_EQ(0x00405000U, frame1->function_base);
636 }
637
638 // The values we expect to find for the caller's registers.
639 MDRawContextMIPS expected;
640
641 // The validity mask for expected.
642 int expected_validity;
643
644 // The validity mask to impose on the context frame.
645 int context_frame_validity;
646 };
647
648 class CFI: public CFIFixture, public Test { };
649
650 // TODO(gordanac): add CFI tests
651
TEST_F(CFI,At4004)652 TEST_F(CFI, At4004) {
653 raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL;
654 Label frame1_sp = expected.iregs[MD_CONTEXT_MIPS_REG_SP];
655 stack_section
656 // frame0
657 .Append(24, 0) // space
658 .D32(frame1_sp) // stack pointer
659 .D32(0x00405510) // return address
660 .Mark(&frame1_sp); // This effectively sets stack_section.start().
661 raw_context.epc = 0x00404004;
662 CheckWalk();
663 }
664
665 // Check that we reject rules that would cause the stack pointer to
666 // move in the wrong direction.
TEST_F(CFI,RejectBackwards)667 TEST_F(CFI, RejectBackwards) {
668 raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL;
669 raw_context.epc = 0x40005000;
670 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
671 raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510;
672
673 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
674 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
675 &frame_symbolizer);
676 vector<const CodeModule*> modules_without_symbols;
677 vector<const CodeModule*> modules_with_corrupt_symbols;
678 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
679 &modules_with_corrupt_symbols));
680 ASSERT_EQ(0U, modules_without_symbols.size());
681 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
682 frames = call_stack.frames();
683 ASSERT_EQ(1U, frames->size());
684 }
685
686 // Check that we reject rules whose expressions' evaluation fails.
TEST_F(CFI,RejectBadExpressions)687 TEST_F(CFI, RejectBadExpressions) {
688 raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL;
689 raw_context.epc = 0x00407000;
690 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
691 raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510;
692
693 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
694 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
695 &frame_symbolizer);
696 vector<const CodeModule*> modules_without_symbols;
697 vector<const CodeModule*> modules_with_corrupt_symbols;
698 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
699 &modules_with_corrupt_symbols));
700 ASSERT_EQ(0U, modules_without_symbols.size());
701 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
702 frames = call_stack.frames();
703 ASSERT_EQ(1U, frames->size());
704 }
705