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