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