1 // Copyright 2010 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: Jim Blandy <[email protected]> <[email protected]>
30
31 // stackwalker_arm64_unittest.cc: Unit tests for StackwalkerARM64 class.
32
33 #ifdef HAVE_CONFIG_H
34 #include <config.h> // Must come first
35 #endif
36
37 #include <string.h>
38 #include <string>
39 #include <vector>
40
41 #include "breakpad_googletest_includes.h"
42 #include "common/test_assembler.h"
43 #include "common/using_std_string.h"
44 #include "google_breakpad/common/minidump_format.h"
45 #include "google_breakpad/processor/basic_source_line_resolver.h"
46 #include "google_breakpad/processor/call_stack.h"
47 #include "google_breakpad/processor/code_module.h"
48 #include "google_breakpad/processor/source_line_resolver_interface.h"
49 #include "google_breakpad/processor/stack_frame_cpu.h"
50 #include "processor/stackwalker_unittest_utils.h"
51 #include "processor/stackwalker_arm64.h"
52 #include "processor/windows_frame_info.h"
53
54 using google_breakpad::BasicSourceLineResolver;
55 using google_breakpad::CallStack;
56 using google_breakpad::CodeModule;
57 using google_breakpad::StackFrameSymbolizer;
58 using google_breakpad::StackFrame;
59 using google_breakpad::StackFrameARM64;
60 using google_breakpad::Stackwalker;
61 using google_breakpad::StackwalkerARM64;
62 using google_breakpad::SystemInfo;
63 using google_breakpad::WindowsFrameInfo;
64 using google_breakpad::test_assembler::kLittleEndian;
65 using google_breakpad::test_assembler::Label;
66 using google_breakpad::test_assembler::Section;
67 using std::vector;
68 using testing::_;
69 using testing::AnyNumber;
70 using testing::DoAll;
71 using testing::Return;
72 using testing::SetArgumentPointee;
73 using testing::Test;
74
75 class StackwalkerARM64Fixture {
76 public:
StackwalkerARM64Fixture()77 StackwalkerARM64Fixture()
78 : stack_section(kLittleEndian),
79 // Give the two modules reasonable standard locations and names
80 // for tests to play with.
81 module1(0x40000000, 0x10000, "module1", "version1"),
82 module2(0x50000000, 0x10000, "module2", "version2") {
83 // Identify the system as an iOS system.
84 system_info.os = "iOS";
85 system_info.os_short = "ios";
86 system_info.cpu = "arm64";
87 system_info.cpu_info = "";
88
89 // Put distinctive values in the raw CPU context.
90 BrandContext(&raw_context);
91
92 // Create some modules with some stock debugging information.
93 modules.Add(&module1);
94 modules.Add(&module2);
95
96 // By default, none of the modules have symbol info; call
97 // SetModuleSymbols to override this.
98 EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _))
99 .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
100
101 // Avoid GMOCK WARNING "Uninteresting mock function call - returning
102 // directly" for FreeSymbolData().
103 EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber());
104
105 // Reset max_frames_scanned since it's static.
106 Stackwalker::set_max_frames_scanned(1024);
107 }
108
109 // Set the Breakpad symbol information that supplier should return for
110 // MODULE to INFO.
SetModuleSymbols(MockCodeModule * module,const string & info)111 void SetModuleSymbols(MockCodeModule* module, const string& info) {
112 size_t buffer_size;
113 char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size);
114 EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _, _))
115 .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
116 SetArgumentPointee<4>(buffer_size),
117 Return(MockSymbolSupplier::FOUND)));
118 }
119
120 // Populate stack_region with the contents of stack_section. Use
121 // stack_section.start() as the region's starting address.
RegionFromSection()122 void RegionFromSection() {
123 string contents;
124 ASSERT_TRUE(stack_section.GetContents(&contents));
125 stack_region.Init(stack_section.start().Value(), contents);
126 }
127
128 // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking.
BrandContext(MDRawContextARM64 * raw_context)129 void BrandContext(MDRawContextARM64 *raw_context) {
130 uint8_t x = 173;
131 for (size_t i = 0; i < sizeof(*raw_context); i++)
132 reinterpret_cast<uint8_t*>(raw_context)[i] = (x += 17);
133 }
134
135 SystemInfo system_info;
136 MDRawContextARM64 raw_context;
137 Section stack_section;
138 MockMemoryRegion stack_region;
139 MockCodeModule module1;
140 MockCodeModule module2;
141 MockCodeModules modules;
142 MockSymbolSupplier supplier;
143 BasicSourceLineResolver resolver;
144 CallStack call_stack;
145 const vector<StackFrame*>* frames;
146 };
147
148 class SanityCheck: public StackwalkerARM64Fixture, public Test { };
149
TEST_F(SanityCheck,NoResolver)150 TEST_F(SanityCheck, NoResolver) {
151 // Since the context's frame pointer is garbage, the stack walk will end after
152 // the first frame.
153 StackFrameSymbolizer frame_symbolizer(NULL, NULL);
154 StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules,
155 &frame_symbolizer);
156 // This should succeed even without a resolver or supplier.
157 vector<const CodeModule*> modules_without_symbols;
158 vector<const CodeModule*> modules_with_corrupt_symbols;
159 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
160 &modules_with_corrupt_symbols));
161 ASSERT_EQ(0U, modules_without_symbols.size());
162 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
163 frames = call_stack.frames();
164 ASSERT_EQ(1U, frames->size());
165 StackFrameARM64 *frame = static_cast<StackFrameARM64*>(frames->at(0));
166 // Check that the values from the original raw context made it
167 // through to the context in the stack frame.
168 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
169 }
170
171 class GetContextFrame: public StackwalkerARM64Fixture, public Test { };
172
173 // The stackwalker should be able to produce the context frame even
174 // without stack memory present.
TEST_F(GetContextFrame,NoStackMemory)175 TEST_F(GetContextFrame, NoStackMemory) {
176 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
177 StackwalkerARM64 walker(&system_info, &raw_context, NULL, &modules,
178 &frame_symbolizer);
179 vector<const CodeModule*> modules_without_symbols;
180 vector<const CodeModule*> modules_with_corrupt_symbols;
181 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
182 &modules_with_corrupt_symbols));
183 ASSERT_EQ(0U, modules_without_symbols.size());
184 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
185 frames = call_stack.frames();
186 ASSERT_EQ(1U, frames->size());
187 StackFrameARM64 *frame = static_cast<StackFrameARM64*>(frames->at(0));
188 // Check that the values from the original raw context made it
189 // through to the context in the stack frame.
190 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
191 }
192
193 class GetCallerFrame: public StackwalkerARM64Fixture, public Test { };
194
TEST_F(GetCallerFrame,ScanWithoutSymbols)195 TEST_F(GetCallerFrame, ScanWithoutSymbols) {
196 // When the stack walker resorts to scanning the stack,
197 // only addresses located within loaded modules are
198 // considered valid return addresses.
199 // Force scanning through three frames to ensure that the
200 // stack pointer is set properly in scan-recovered frames.
201 stack_section.start() = 0x80000000;
202 uint64_t return_address1 = 0x50000100;
203 uint64_t return_address2 = 0x50000900;
204 Label frame1_sp, frame2_sp;
205 stack_section
206 // frame 0
207 .Append(16, 0) // space
208
209 .D64(0x40090000) // junk that's not
210 .D64(0x60000000) // a return address
211
212 .D64(return_address1) // actual return address
213 // frame 1
214 .Mark(&frame1_sp)
215 .Append(16, 0) // space
216
217 .D64(0xF0000000) // more junk
218 .D64(0x0000000D)
219
220 .D64(return_address2) // actual return address
221 // frame 2
222 .Mark(&frame2_sp)
223 .Append(64, 0); // end of stack
224 RegionFromSection();
225
226 raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x40005510;
227 raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value();
228
229 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
230 StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules,
231 &frame_symbolizer);
232 vector<const CodeModule*> modules_without_symbols;
233 vector<const CodeModule*> modules_with_corrupt_symbols;
234 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
235 &modules_with_corrupt_symbols));
236 ASSERT_EQ(2U, modules_without_symbols.size());
237 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
238 ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
239 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
240 frames = call_stack.frames();
241 ASSERT_EQ(3U, frames->size());
242
243 StackFrameARM64 *frame0 = static_cast<StackFrameARM64*>(frames->at(0));
244 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
245 ASSERT_EQ(StackFrameARM64::CONTEXT_VALID_ALL,
246 frame0->context_validity);
247 EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
248
249 StackFrameARM64 *frame1 = static_cast<StackFrameARM64*>(frames->at(1));
250 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
251 ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC |
252 StackFrameARM64::CONTEXT_VALID_SP),
253 frame1->context_validity);
254 EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM64_REG_PC]);
255 EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM64_REG_SP]);
256
257 StackFrameARM64 *frame2 = static_cast<StackFrameARM64*>(frames->at(2));
258 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame2->trust);
259 ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC |
260 StackFrameARM64::CONTEXT_VALID_SP),
261 frame2->context_validity);
262 EXPECT_EQ(return_address2, frame2->context.iregs[MD_CONTEXT_ARM64_REG_PC]);
263 EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_ARM64_REG_SP]);
264 }
265
TEST_F(GetCallerFrame,ScanWithFunctionSymbols)266 TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
267 // During stack scanning, if a potential return address
268 // is located within a loaded module that has symbols,
269 // it is only considered a valid return address if it
270 // lies within a function's bounds.
271 stack_section.start() = 0x80000000;
272 uint64_t return_address = 0x50000200;
273 Label frame1_sp;
274
275 stack_section
276 // frame 0
277 .Append(16, 0) // space
278
279 .D64(0x40090000) // junk that's not
280 .D64(0x60000000) // a return address
281
282 .D64(0x40001000) // a couple of plausible addresses
283 .D64(0x5000F000) // that are not within functions
284
285 .D64(return_address) // actual return address
286 // frame 1
287 .Mark(&frame1_sp)
288 .Append(64, 0); // end of stack
289 RegionFromSection();
290
291 raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x40000200;
292 raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value();
293
294 SetModuleSymbols(&module1,
295 // The youngest frame's function.
296 "FUNC 100 400 10 monotreme\n");
297 SetModuleSymbols(&module2,
298 // The calling frame's function.
299 "FUNC 100 400 10 marsupial\n");
300
301 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
302 StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules,
303 &frame_symbolizer);
304 vector<const CodeModule*> modules_without_symbols;
305 vector<const CodeModule*> modules_with_corrupt_symbols;
306 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
307 &modules_with_corrupt_symbols));
308 ASSERT_EQ(0U, modules_without_symbols.size());
309 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
310 frames = call_stack.frames();
311 ASSERT_EQ(2U, frames->size());
312
313 StackFrameARM64 *frame0 = static_cast<StackFrameARM64*>(frames->at(0));
314 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
315 ASSERT_EQ(StackFrameARM64::CONTEXT_VALID_ALL,
316 frame0->context_validity);
317 EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
318 EXPECT_EQ("monotreme", frame0->function_name);
319 EXPECT_EQ(0x40000100ULL, frame0->function_base);
320
321 StackFrameARM64 *frame1 = static_cast<StackFrameARM64*>(frames->at(1));
322 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
323 ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC |
324 StackFrameARM64::CONTEXT_VALID_SP),
325 frame1->context_validity);
326 EXPECT_EQ(return_address, frame1->context.iregs[MD_CONTEXT_ARM64_REG_PC]);
327 EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM64_REG_SP]);
328 EXPECT_EQ("marsupial", frame1->function_name);
329 EXPECT_EQ(0x50000100ULL, frame1->function_base);
330 }
331
TEST_F(GetCallerFrame,ScanFirstFrame)332 TEST_F(GetCallerFrame, ScanFirstFrame) {
333 // If the stackwalker resorts to stack scanning, it will scan much
334 // farther to find the caller of the context frame.
335 stack_section.start() = 0x80000000;
336 uint64_t return_address1 = 0x50000100;
337 uint64_t return_address2 = 0x50000900;
338 Label frame1_sp, frame2_sp;
339 stack_section
340 // frame 0
341 .Append(32, 0) // space
342
343 .D64(0x40090000) // junk that's not
344 .D64(0x60000000) // a return address
345
346 .Append(96, 0) // more space
347
348 .D64(return_address1) // actual return address
349 // frame 1
350 .Mark(&frame1_sp)
351 .Append(32, 0) // space
352
353 .D64(0xF0000000) // more junk
354 .D64(0x0000000D)
355
356 .Append(336, 0) // more space
357
358 .D64(return_address2) // actual return address
359 // (won't be found)
360 // frame 2
361 .Mark(&frame2_sp)
362 .Append(64, 0); // end of stack
363 RegionFromSection();
364
365 raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x40005510;
366 raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value();
367
368 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
369 StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules,
370 &frame_symbolizer);
371 vector<const CodeModule*> modules_without_symbols;
372 vector<const CodeModule*> modules_with_corrupt_symbols;
373 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
374 &modules_with_corrupt_symbols));
375 ASSERT_EQ(2U, modules_without_symbols.size());
376 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
377 ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
378 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
379 frames = call_stack.frames();
380 ASSERT_EQ(2U, frames->size());
381
382 StackFrameARM64 *frame0 = static_cast<StackFrameARM64*>(frames->at(0));
383 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
384 ASSERT_EQ(StackFrameARM64::CONTEXT_VALID_ALL,
385 frame0->context_validity);
386 EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
387
388 StackFrameARM64 *frame1 = static_cast<StackFrameARM64*>(frames->at(1));
389 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
390 ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC |
391 StackFrameARM64::CONTEXT_VALID_SP),
392 frame1->context_validity);
393 EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM64_REG_PC]);
394 EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM64_REG_SP]);
395 }
396
397 // Test that set_max_frames_scanned prevents using stack scanning
398 // to find caller frames.
TEST_F(GetCallerFrame,ScanningNotAllowed)399 TEST_F(GetCallerFrame, ScanningNotAllowed) {
400 // When the stack walker resorts to scanning the stack,
401 // only addresses located within loaded modules are
402 // considered valid return addresses.
403 stack_section.start() = 0x80000000;
404 uint64_t return_address1 = 0x50000100;
405 uint64_t return_address2 = 0x50000900;
406 Label frame1_sp, frame2_sp;
407 stack_section
408 // frame 0
409 .Append(16, 0) // space
410
411 .D64(0x40090000) // junk that's not
412 .D64(0x60000000) // a return address
413
414 .D64(return_address1) // actual return address
415 // frame 1
416 .Mark(&frame1_sp)
417 .Append(16, 0) // space
418
419 .D64(0xF0000000) // more junk
420 .D64(0x0000000D)
421
422 .D64(return_address2) // actual return address
423 // frame 2
424 .Mark(&frame2_sp)
425 .Append(64, 0); // end of stack
426 RegionFromSection();
427
428 raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x40005510;
429 raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value();
430
431 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
432 StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules,
433 &frame_symbolizer);
434 Stackwalker::set_max_frames_scanned(0);
435
436 vector<const CodeModule*> modules_without_symbols;
437 vector<const CodeModule*> modules_with_corrupt_symbols;
438 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
439 &modules_with_corrupt_symbols));
440 ASSERT_EQ(1U, modules_without_symbols.size());
441 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
442 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
443 frames = call_stack.frames();
444 ASSERT_EQ(1U, frames->size());
445
446 StackFrameARM64 *frame0 = static_cast<StackFrameARM64*>(frames->at(0));
447 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
448 ASSERT_EQ(StackFrameARM64::CONTEXT_VALID_ALL,
449 frame0->context_validity);
450 EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
451 }
452
453 class GetFramesByFramePointer: public StackwalkerARM64Fixture, public Test { };
454
TEST_F(GetFramesByFramePointer,OnlyFramePointer)455 TEST_F(GetFramesByFramePointer, OnlyFramePointer) {
456 stack_section.start() = 0x80000000;
457 uint64_t return_address1 = 0x50000100;
458 uint64_t return_address2 = 0x50000900;
459 Label frame1_sp, frame2_sp;
460 Label frame1_fp, frame2_fp;
461 stack_section
462 // frame 0
463 .Append(64, 0) // Whatever values on the stack.
464 .D64(0x0000000D) // junk that's not
465 .D64(0xF0000000) // a return address.
466
467 .Mark(&frame1_fp) // Next fp will point to the next value.
468 .D64(frame2_fp) // Save current frame pointer.
469 .D64(return_address2) // Save current link register.
470 .Mark(&frame1_sp)
471
472 // frame 1
473 .Append(64, 0) // Whatever values on the stack.
474 .D64(0x0000000D) // junk that's not
475 .D64(0xF0000000) // a return address.
476
477 .Mark(&frame2_fp)
478 .D64(0)
479 .D64(0)
480 .Mark(&frame2_sp)
481
482 // frame 2
483 .Append(64, 0) // Whatever values on the stack.
484 .D64(0x0000000D) // junk that's not
485 .D64(0xF0000000); // a return address.
486 RegionFromSection();
487
488
489 raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x40005510;
490 raw_context.iregs[MD_CONTEXT_ARM64_REG_LR] = return_address1;
491 raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = frame1_fp.Value();
492 raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value();
493
494 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
495 StackwalkerARM64 walker(&system_info, &raw_context,
496 &stack_region, &modules, &frame_symbolizer);
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(2U, modules_without_symbols.size());
503 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
504 ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
505 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
506 frames = call_stack.frames();
507 ASSERT_EQ(3U, frames->size());
508
509 StackFrameARM64 *frame0 = static_cast<StackFrameARM64*>(frames->at(0));
510 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
511 ASSERT_EQ(StackFrameARM64::CONTEXT_VALID_ALL,
512 frame0->context_validity);
513 EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
514
515 StackFrameARM64 *frame1 = static_cast<StackFrameARM64*>(frames->at(1));
516 EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
517 ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC |
518 StackFrameARM64::CONTEXT_VALID_LR |
519 StackFrameARM64::CONTEXT_VALID_FP |
520 StackFrameARM64::CONTEXT_VALID_SP),
521 frame1->context_validity);
522 EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM64_REG_PC]);
523 EXPECT_EQ(return_address2, frame1->context.iregs[MD_CONTEXT_ARM64_REG_LR]);
524 EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM64_REG_SP]);
525 EXPECT_EQ(frame2_fp.Value(),
526 frame1->context.iregs[MD_CONTEXT_ARM64_REG_FP]);
527
528 StackFrameARM64 *frame2 = static_cast<StackFrameARM64*>(frames->at(2));
529 EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame2->trust);
530 ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC |
531 StackFrameARM64::CONTEXT_VALID_LR |
532 StackFrameARM64::CONTEXT_VALID_FP |
533 StackFrameARM64::CONTEXT_VALID_SP),
534 frame2->context_validity);
535 EXPECT_EQ(return_address2, frame2->context.iregs[MD_CONTEXT_ARM64_REG_PC]);
536 EXPECT_EQ(0U, frame2->context.iregs[MD_CONTEXT_ARM64_REG_LR]);
537 EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_ARM64_REG_SP]);
538 EXPECT_EQ(0U, frame2->context.iregs[MD_CONTEXT_ARM64_REG_FP]);
539 }
540
541 struct CFIFixture: public StackwalkerARM64Fixture {
CFIFixtureCFIFixture542 CFIFixture() {
543 // Provide a bunch of STACK CFI records; we'll walk to the caller
544 // from every point in this series, expecting to find the same set
545 // of register values.
546 SetModuleSymbols(&module1,
547 // The youngest frame's function.
548 "FUNC 4000 1000 10 enchiridion\n"
549 // Initially, nothing has been pushed on the stack,
550 // and the return address is still in the link
551 // register (x30).
552 "STACK CFI INIT 4000 100 .cfa: sp 0 + .ra: x30\n"
553 // Push x19, x20, the frame pointer and the link register.
554 "STACK CFI 4001 .cfa: sp 32 + .ra: .cfa -8 + ^"
555 " x19: .cfa -32 + ^ x20: .cfa -24 + ^ "
556 " x29: .cfa -16 + ^\n"
557 // Save x19..x22 in x0..x3: verify that we populate
558 // the youngest frame with all the values we have.
559 "STACK CFI 4002 x19: x0 x20: x1 x21: x2 x22: x3\n"
560 // Restore x19..x22. Save the non-callee-saves register x1.
561 "STACK CFI 4003 .cfa: sp 40 + x1: .cfa 40 - ^"
562 " x19: x19 x20: x20 x21: x21 x22: x22\n"
563 // Move the .cfa back eight bytes, to point at the return
564 // address, and restore the sp explicitly.
565 "STACK CFI 4005 .cfa: sp 32 + x1: .cfa 32 - ^"
566 " x29: .cfa 8 - ^ .ra: .cfa ^ sp: .cfa 8 +\n"
567 // Recover the PC explicitly from a new stack slot;
568 // provide garbage for the .ra.
569 "STACK CFI 4006 .cfa: sp 40 + pc: .cfa 40 - ^\n"
570
571 // The calling function.
572 "FUNC 5000 1000 10 epictetus\n"
573 // Mark it as end of stack.
574 "STACK CFI INIT 5000 1000 .cfa: 0 .ra: 0\n"
575
576 // A function whose CFI makes the stack pointer
577 // go backwards.
578 "FUNC 6000 1000 20 palinal\n"
579 "STACK CFI INIT 6000 1000 .cfa: sp 8 - .ra: x30\n"
580
581 // A function with CFI expressions that can't be
582 // evaluated.
583 "FUNC 7000 1000 20 rhetorical\n"
584 "STACK CFI INIT 7000 1000 .cfa: moot .ra: ambiguous\n");
585
586 // Provide some distinctive values for the caller's registers.
587 expected.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040005510L;
588 expected.iregs[MD_CONTEXT_ARM64_REG_SP] = 0x0000000080000000L;
589 expected.iregs[19] = 0x5e68b5d5b5d55e68L;
590 expected.iregs[20] = 0x34f3ebd1ebd134f3L;
591 expected.iregs[21] = 0x74bca31ea31e74bcL;
592 expected.iregs[22] = 0x16b32dcb2dcb16b3L;
593 expected.iregs[23] = 0x21372ada2ada2137L;
594 expected.iregs[24] = 0x557dbbbbbbbb557dL;
595 expected.iregs[25] = 0x8ca748bf48bf8ca7L;
596 expected.iregs[26] = 0x21f0ab46ab4621f0L;
597 expected.iregs[27] = 0x146732b732b71467L;
598 expected.iregs[28] = 0xa673645fa673645fL;
599 expected.iregs[MD_CONTEXT_ARM64_REG_FP] = 0xe11081128112e110L;
600
601 // Expect CFI to recover all callee-saves registers. Since CFI is the
602 // only stack frame construction technique we have, aside from the
603 // context frame itself, there's no way for us to have a set of valid
604 // registers smaller than this.
605 expected_validity = (StackFrameARM64::CONTEXT_VALID_PC |
606 StackFrameARM64::CONTEXT_VALID_SP |
607 StackFrameARM64::CONTEXT_VALID_X19 |
608 StackFrameARM64::CONTEXT_VALID_X20 |
609 StackFrameARM64::CONTEXT_VALID_X21 |
610 StackFrameARM64::CONTEXT_VALID_X22 |
611 StackFrameARM64::CONTEXT_VALID_X23 |
612 StackFrameARM64::CONTEXT_VALID_X24 |
613 StackFrameARM64::CONTEXT_VALID_X25 |
614 StackFrameARM64::CONTEXT_VALID_X26 |
615 StackFrameARM64::CONTEXT_VALID_X27 |
616 StackFrameARM64::CONTEXT_VALID_X28 |
617 StackFrameARM64::CONTEXT_VALID_FP);
618
619 // By default, context frames provide all registers, as normal.
620 context_frame_validity = StackFrameARM64::CONTEXT_VALID_ALL;
621
622 // By default, registers are unchanged.
623 raw_context = expected;
624 }
625
626 // Walk the stack, using stack_section as the contents of the stack
627 // and raw_context as the current register values. (Set the stack
628 // pointer to the stack's starting address.) Expect two stack
629 // frames; in the older frame, expect the callee-saves registers to
630 // have values matching those in 'expected'.
CheckWalkCFIFixture631 void CheckWalk() {
632 RegionFromSection();
633 raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value();
634
635 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
636 StackwalkerARM64 walker(&system_info, &raw_context, &stack_region,
637 &modules, &frame_symbolizer);
638 walker.SetContextFrameValidity(context_frame_validity);
639 vector<const CodeModule*> modules_without_symbols;
640 vector<const CodeModule*> modules_with_corrupt_symbols;
641 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
642 &modules_with_corrupt_symbols));
643 ASSERT_EQ(0U, modules_without_symbols.size());
644 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
645 frames = call_stack.frames();
646 ASSERT_EQ(2U, frames->size());
647
648 StackFrameARM64 *frame0 = static_cast<StackFrameARM64*>(frames->at(0));
649 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
650 ASSERT_EQ(context_frame_validity, frame0->context_validity);
651 EXPECT_EQ("enchiridion", frame0->function_name);
652 EXPECT_EQ(0x0000000040004000UL, frame0->function_base);
653
654 StackFrameARM64 *frame1 = static_cast<StackFrameARM64*>(frames->at(1));
655 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
656 ASSERT_EQ(expected_validity, frame1->context_validity);
657 if (expected_validity & StackFrameARM64::CONTEXT_VALID_X1)
658 EXPECT_EQ(expected.iregs[1], frame1->context.iregs[1]);
659 if (expected_validity & StackFrameARM64::CONTEXT_VALID_X19)
660 EXPECT_EQ(expected.iregs[19], frame1->context.iregs[19]);
661 if (expected_validity & StackFrameARM64::CONTEXT_VALID_X20)
662 EXPECT_EQ(expected.iregs[20], frame1->context.iregs[20]);
663 if (expected_validity & StackFrameARM64::CONTEXT_VALID_X21)
664 EXPECT_EQ(expected.iregs[21], frame1->context.iregs[21]);
665 if (expected_validity & StackFrameARM64::CONTEXT_VALID_X22)
666 EXPECT_EQ(expected.iregs[22], frame1->context.iregs[22]);
667 if (expected_validity & StackFrameARM64::CONTEXT_VALID_X23)
668 EXPECT_EQ(expected.iregs[23], frame1->context.iregs[23]);
669 if (expected_validity & StackFrameARM64::CONTEXT_VALID_X24)
670 EXPECT_EQ(expected.iregs[24], frame1->context.iregs[24]);
671 if (expected_validity & StackFrameARM64::CONTEXT_VALID_X25)
672 EXPECT_EQ(expected.iregs[25], frame1->context.iregs[25]);
673 if (expected_validity & StackFrameARM64::CONTEXT_VALID_X26)
674 EXPECT_EQ(expected.iregs[26], frame1->context.iregs[26]);
675 if (expected_validity & StackFrameARM64::CONTEXT_VALID_X27)
676 EXPECT_EQ(expected.iregs[27], frame1->context.iregs[27]);
677 if (expected_validity & StackFrameARM64::CONTEXT_VALID_X28)
678 EXPECT_EQ(expected.iregs[28], frame1->context.iregs[28]);
679 if (expected_validity & StackFrameARM64::CONTEXT_VALID_FP)
680 EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM64_REG_FP],
681 frame1->context.iregs[MD_CONTEXT_ARM64_REG_FP]);
682
683 // We would never have gotten a frame in the first place if the SP
684 // and PC weren't valid or ->instruction weren't set.
685 EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM64_REG_SP],
686 frame1->context.iregs[MD_CONTEXT_ARM64_REG_SP]);
687 EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM64_REG_PC],
688 frame1->context.iregs[MD_CONTEXT_ARM64_REG_PC]);
689 EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM64_REG_PC],
690 frame1->instruction + 4);
691 EXPECT_EQ("epictetus", frame1->function_name);
692 }
693
694 // The values we expect to find for the caller's registers.
695 MDRawContextARM64 expected;
696
697 // The validity mask for expected.
698 uint64_t expected_validity;
699
700 // The validity mask to impose on the context frame.
701 uint64_t context_frame_validity;
702 };
703
704 class CFI: public CFIFixture, public Test { };
705
TEST_F(CFI,At4000)706 TEST_F(CFI, At4000) {
707 stack_section.start() = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
708 raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004000L;
709 raw_context.iregs[MD_CONTEXT_ARM64_REG_LR] = 0x0000000040005510L;
710 CheckWalk();
711 }
712
TEST_F(CFI,At4001)713 TEST_F(CFI, At4001) {
714 Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
715 stack_section
716 .D64(0x5e68b5d5b5d55e68L) // saved x19
717 .D64(0x34f3ebd1ebd134f3L) // saved x20
718 .D64(0xe11081128112e110L) // saved fp
719 .D64(0x0000000040005510L) // return address
720 .Mark(&frame1_sp); // This effectively sets stack_section.start().
721 raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004001L;
722 // distinct callee x19, x20 and fp
723 raw_context.iregs[19] = 0xadc9f635a635adc9L;
724 raw_context.iregs[20] = 0x623135ac35ac6231L;
725 raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = 0x5fc4be14be145fc4L;
726 CheckWalk();
727 }
728
729 // As above, but unwind from a context that has only the PC and SP.
TEST_F(CFI,At4001LimitedValidity)730 TEST_F(CFI, At4001LimitedValidity) {
731 Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
732 stack_section
733 .D64(0x5e68b5d5b5d55e68L) // saved x19
734 .D64(0x34f3ebd1ebd134f3L) // saved x20
735 .D64(0xe11081128112e110L) // saved fp
736 .D64(0x0000000040005510L) // return address
737 .Mark(&frame1_sp); // This effectively sets stack_section.start().
738 context_frame_validity =
739 StackFrameARM64::CONTEXT_VALID_PC | StackFrameARM64::CONTEXT_VALID_SP;
740 raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004001L;
741 raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = 0x5fc4be14be145fc4L;
742
743 expected_validity = (StackFrameARM64::CONTEXT_VALID_PC
744 | StackFrameARM64::CONTEXT_VALID_SP
745 | StackFrameARM64::CONTEXT_VALID_FP
746 | StackFrameARM64::CONTEXT_VALID_X19
747 | StackFrameARM64::CONTEXT_VALID_X20);
748 CheckWalk();
749 }
750
TEST_F(CFI,At4002)751 TEST_F(CFI, At4002) {
752 Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
753 stack_section
754 .D64(0xff3dfb81fb81ff3dL) // no longer saved x19
755 .D64(0x34f3ebd1ebd134f3L) // no longer saved x20
756 .D64(0xe11081128112e110L) // saved fp
757 .D64(0x0000000040005510L) // return address
758 .Mark(&frame1_sp); // This effectively sets stack_section.start().
759 raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004002L;
760 raw_context.iregs[0] = 0x5e68b5d5b5d55e68L; // saved x19
761 raw_context.iregs[1] = 0x34f3ebd1ebd134f3L; // saved x20
762 raw_context.iregs[2] = 0x74bca31ea31e74bcL; // saved x21
763 raw_context.iregs[3] = 0x16b32dcb2dcb16b3L; // saved x22
764 raw_context.iregs[19] = 0xadc9f635a635adc9L; // distinct callee x19
765 raw_context.iregs[20] = 0x623135ac35ac6231L; // distinct callee x20
766 raw_context.iregs[21] = 0xac4543564356ac45L; // distinct callee x21
767 raw_context.iregs[22] = 0x2561562f562f2561L; // distinct callee x22
768 // distinct callee fp
769 raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = 0x5fc4be14be145fc4L;
770 CheckWalk();
771 }
772
TEST_F(CFI,At4003)773 TEST_F(CFI, At4003) {
774 Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
775 stack_section
776 .D64(0xdd5a48c848c8dd5aL) // saved x1 (even though it's not callee-saves)
777 .D64(0xff3dfb81fb81ff3dL) // no longer saved x19
778 .D64(0x34f3ebd1ebd134f3L) // no longer saved x20
779 .D64(0xe11081128112e110L) // saved fp
780 .D64(0x0000000040005510L) // return address
781 .Mark(&frame1_sp); // This effectively sets stack_section.start().
782 raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004003L;
783 // distinct callee x1 and fp
784 raw_context.iregs[1] = 0xfb756319fb756319L;
785 raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = 0x5fc4be14be145fc4L;
786 // caller's x1
787 expected.iregs[1] = 0xdd5a48c848c8dd5aL;
788 expected_validity |= StackFrameARM64::CONTEXT_VALID_X1;
789 CheckWalk();
790 }
791
792 // We have no new rule at module offset 0x4004, so the results here should
793 // be the same as those at module offset 0x4003.
TEST_F(CFI,At4004)794 TEST_F(CFI, At4004) {
795 Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
796 stack_section
797 .D64(0xdd5a48c848c8dd5aL) // saved x1 (even though it's not callee-saves)
798 .D64(0xff3dfb81fb81ff3dL) // no longer saved x19
799 .D64(0x34f3ebd1ebd134f3L) // no longer saved x20
800 .D64(0xe11081128112e110L) // saved fp
801 .D64(0x0000000040005510L) // return address
802 .Mark(&frame1_sp); // This effectively sets stack_section.start().
803 raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004004L;
804 // distinct callee x1 and fp
805 raw_context.iregs[1] = 0xfb756319fb756319L;
806 raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = 0x5fc4be14be145fc4L;
807 // caller's x1
808 expected.iregs[1] = 0xdd5a48c848c8dd5aL;
809 expected_validity |= StackFrameARM64::CONTEXT_VALID_X1;
810 CheckWalk();
811 }
812
813 // Here we move the .cfa, but provide an explicit rule to recover the SP,
814 // so again there should be no change in the registers recovered.
TEST_F(CFI,At4005)815 TEST_F(CFI, At4005) {
816 Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
817 stack_section
818 .D64(0xdd5a48c848c8dd5aL) // saved x1 (even though it's not callee-saves)
819 .D64(0xff3dfb81fb81ff3dL) // no longer saved x19
820 .D64(0x34f3ebd1ebd134f3L) // no longer saved x20
821 .D64(0xe11081128112e110L) // saved fp
822 .D64(0x0000000040005510L) // return address
823 .Mark(&frame1_sp); // This effectively sets stack_section.start().
824 raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004005L;
825 raw_context.iregs[1] = 0xfb756319fb756319L; // distinct callee x1
826 expected.iregs[1] = 0xdd5a48c848c8dd5aL; // caller's x1
827 expected_validity |= StackFrameARM64::CONTEXT_VALID_X1;
828 CheckWalk();
829 }
830
831 // Here we provide an explicit rule for the PC, and have the saved .ra be
832 // bogus.
TEST_F(CFI,At4006)833 TEST_F(CFI, At4006) {
834 Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
835 stack_section
836 .D64(0x0000000040005510L) // saved pc
837 .D64(0xdd5a48c848c8dd5aL) // saved x1 (even though it's not callee-saves)
838 .D64(0xff3dfb81fb81ff3dL) // no longer saved x19
839 .D64(0x34f3ebd1ebd134f3L) // no longer saved x20
840 .D64(0xe11081128112e110L) // saved fp
841 .D64(0xf8d157835783f8d1L) // .ra rule recovers this, which is garbage
842 .Mark(&frame1_sp); // This effectively sets stack_section.start().
843 raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004006L;
844 raw_context.iregs[1] = 0xfb756319fb756319L; // distinct callee x1
845 expected.iregs[1] = 0xdd5a48c848c8dd5aL; // caller's x1
846 expected_validity |= StackFrameARM64::CONTEXT_VALID_X1;
847 CheckWalk();
848 }
849
850 // Check that we reject rules that would cause the stack pointer to
851 // move in the wrong direction.
TEST_F(CFI,RejectBackwards)852 TEST_F(CFI, RejectBackwards) {
853 raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040006000L;
854 raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = 0x0000000080000000L;
855 raw_context.iregs[MD_CONTEXT_ARM64_REG_LR] = 0x0000000040005510L;
856 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
857 StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules,
858 &frame_symbolizer);
859 vector<const CodeModule*> modules_without_symbols;
860 vector<const CodeModule*> modules_with_corrupt_symbols;
861 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
862 &modules_with_corrupt_symbols));
863 ASSERT_EQ(0U, modules_without_symbols.size());
864 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
865 frames = call_stack.frames();
866 ASSERT_EQ(1U, frames->size());
867 }
868
869 // Check that we reject rules whose expressions' evaluation fails.
TEST_F(CFI,RejectBadExpressions)870 TEST_F(CFI, RejectBadExpressions) {
871 raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040007000L;
872 raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = 0x0000000080000000L;
873 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
874 StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules,
875 &frame_symbolizer);
876 vector<const CodeModule*> modules_without_symbols;
877 vector<const CodeModule*> modules_with_corrupt_symbols;
878 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
879 &modules_with_corrupt_symbols));
880 ASSERT_EQ(0U, modules_without_symbols.size());
881 ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
882 frames = call_stack.frames();
883 ASSERT_EQ(1U, frames->size());
884 }
885