OLD | NEW |
1 // Copyright (c) 2010, Google Inc. | 1 // Copyright (c) 2010, Google Inc. |
2 // All rights reserved. | 2 // All rights reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 using testing::Return; | 65 using testing::Return; |
66 using testing::SetArgumentPointee; | 66 using testing::SetArgumentPointee; |
67 using testing::Test; | 67 using testing::Test; |
68 | 68 |
69 class StackwalkerAMD64Fixture { | 69 class StackwalkerAMD64Fixture { |
70 public: | 70 public: |
71 StackwalkerAMD64Fixture() | 71 StackwalkerAMD64Fixture() |
72 : stack_section(kLittleEndian), | 72 : stack_section(kLittleEndian), |
73 // Give the two modules reasonable standard locations and names | 73 // Give the two modules reasonable standard locations and names |
74 // for tests to play with. | 74 // for tests to play with. |
75 module1(0x40000000c0000000ULL, 0x10000, "module1", "version1"), | 75 module1(0x00007400c0000000ULL, 0x10000, "module1", "version1"), |
76 module2(0x50000000b0000000ULL, 0x10000, "module2", "version2") { | 76 module2(0x00007500b0000000ULL, 0x10000, "module2", "version2") { |
77 // Identify the system as a Linux system. | 77 // Identify the system as a Linux system. |
78 system_info.os = "Linux"; | 78 system_info.os = "Linux"; |
79 system_info.os_short = "linux"; | 79 system_info.os_short = "linux"; |
80 system_info.os_version = "Horrendous Hippo"; | 80 system_info.os_version = "Horrendous Hippo"; |
81 system_info.cpu = "x86"; | 81 system_info.cpu = "x86"; |
82 system_info.cpu_info = ""; | 82 system_info.cpu_info = ""; |
83 | 83 |
84 // Put distinctive values in the raw CPU context. | 84 // Put distinctive values in the raw CPU context. |
85 BrandContext(&raw_context); | 85 BrandContext(&raw_context); |
86 | 86 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 | 142 |
143 class GetContextFrame: public StackwalkerAMD64Fixture, public Test { }; | 143 class GetContextFrame: public StackwalkerAMD64Fixture, public Test { }; |
144 | 144 |
145 class SanityCheck: public StackwalkerAMD64Fixture, public Test { }; | 145 class SanityCheck: public StackwalkerAMD64Fixture, public Test { }; |
146 | 146 |
147 TEST_F(SanityCheck, NoResolver) { | 147 TEST_F(SanityCheck, NoResolver) { |
148 // There should be no references to the stack in this walk: we don't | 148 // There should be no references to the stack in this walk: we don't |
149 // provide any call frame information, so trying to reconstruct the | 149 // provide any call frame information, so trying to reconstruct the |
150 // context frame's caller should fail. So there's no need for us to | 150 // context frame's caller should fail. So there's no need for us to |
151 // provide stack contents. | 151 // provide stack contents. |
152 raw_context.rip = 0x40000000c0000200ULL; | 152 raw_context.rip = 0x00007400c0000200ULL; |
153 raw_context.rbp = 0x8000000080000000ULL; | 153 raw_context.rbp = 0x8000000080000000ULL; |
154 | 154 |
155 StackFrameSymbolizer frame_symbolizer(NULL, NULL); | 155 StackFrameSymbolizer frame_symbolizer(NULL, NULL); |
156 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, | 156 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, |
157 &frame_symbolizer); | 157 &frame_symbolizer); |
158 // This should succeed even without a resolver or supplier. | 158 // This should succeed even without a resolver or supplier. |
159 vector<const CodeModule*> modules_without_symbols; | 159 vector<const CodeModule*> modules_without_symbols; |
160 vector<const CodeModule*> modules_with_corrupt_symbols; | 160 vector<const CodeModule*> modules_with_corrupt_symbols; |
161 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, | 161 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, |
162 &modules_with_corrupt_symbols)); | 162 &modules_with_corrupt_symbols)); |
163 ASSERT_EQ(1U, modules_without_symbols.size()); | 163 ASSERT_EQ(1U, modules_without_symbols.size()); |
164 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); | 164 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); |
165 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); | 165 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); |
166 frames = call_stack.frames(); | 166 frames = call_stack.frames(); |
167 ASSERT_GE(1U, frames->size()); | 167 ASSERT_GE(1U, frames->size()); |
168 StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0)); | 168 StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0)); |
169 // Check that the values from the original raw context made it | 169 // Check that the values from the original raw context made it |
170 // through to the context in the stack frame. | 170 // through to the context in the stack frame. |
171 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); | 171 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); |
172 } | 172 } |
173 | 173 |
174 TEST_F(GetContextFrame, Simple) { | 174 TEST_F(GetContextFrame, Simple) { |
175 // There should be no references to the stack in this walk: we don't | 175 // There should be no references to the stack in this walk: we don't |
176 // provide any call frame information, so trying to reconstruct the | 176 // provide any call frame information, so trying to reconstruct the |
177 // context frame's caller should fail. So there's no need for us to | 177 // context frame's caller should fail. So there's no need for us to |
178 // provide stack contents. | 178 // provide stack contents. |
179 raw_context.rip = 0x40000000c0000200ULL; | 179 raw_context.rip = 0x00007400c0000200ULL; |
180 raw_context.rbp = 0x8000000080000000ULL; | 180 raw_context.rbp = 0x8000000080000000ULL; |
181 | 181 |
182 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); | 182 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); |
183 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, | 183 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, |
184 &frame_symbolizer); | 184 &frame_symbolizer); |
185 vector<const CodeModule*> modules_without_symbols; | 185 vector<const CodeModule*> modules_without_symbols; |
186 vector<const CodeModule*> modules_with_corrupt_symbols; | 186 vector<const CodeModule*> modules_with_corrupt_symbols; |
187 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, | 187 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, |
188 &modules_with_corrupt_symbols)); | 188 &modules_with_corrupt_symbols)); |
189 ASSERT_EQ(1U, modules_without_symbols.size()); | 189 ASSERT_EQ(1U, modules_without_symbols.size()); |
190 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); | 190 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); |
191 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); | 191 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); |
192 frames = call_stack.frames(); | 192 frames = call_stack.frames(); |
193 ASSERT_GE(1U, frames->size()); | 193 ASSERT_GE(1U, frames->size()); |
194 StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0)); | 194 StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0)); |
195 // Check that the values from the original raw context made it | 195 // Check that the values from the original raw context made it |
196 // through to the context in the stack frame. | 196 // through to the context in the stack frame. |
197 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); | 197 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); |
198 } | 198 } |
199 | 199 |
200 // The stackwalker should be able to produce the context frame even | 200 // The stackwalker should be able to produce the context frame even |
201 // without stack memory present. | 201 // without stack memory present. |
202 TEST_F(GetContextFrame, NoStackMemory) { | 202 TEST_F(GetContextFrame, NoStackMemory) { |
203 raw_context.rip = 0x40000000c0000200ULL; | 203 raw_context.rip = 0x00007400c0000200ULL; |
204 raw_context.rbp = 0x8000000080000000ULL; | 204 raw_context.rbp = 0x8000000080000000ULL; |
205 | 205 |
206 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); | 206 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); |
207 StackwalkerAMD64 walker(&system_info, &raw_context, NULL, &modules, | 207 StackwalkerAMD64 walker(&system_info, &raw_context, NULL, &modules, |
208 &frame_symbolizer); | 208 &frame_symbolizer); |
209 vector<const CodeModule*> modules_without_symbols; | 209 vector<const CodeModule*> modules_without_symbols; |
210 vector<const CodeModule*> modules_with_corrupt_symbols; | 210 vector<const CodeModule*> modules_with_corrupt_symbols; |
211 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, | 211 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, |
212 &modules_with_corrupt_symbols)); | 212 &modules_with_corrupt_symbols)); |
213 ASSERT_EQ(1U, modules_without_symbols.size()); | 213 ASSERT_EQ(1U, modules_without_symbols.size()); |
214 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); | 214 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); |
215 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); | 215 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); |
216 frames = call_stack.frames(); | 216 frames = call_stack.frames(); |
217 ASSERT_GE(1U, frames->size()); | 217 ASSERT_GE(1U, frames->size()); |
218 StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0)); | 218 StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0)); |
219 // Check that the values from the original raw context made it | 219 // Check that the values from the original raw context made it |
220 // through to the context in the stack frame. | 220 // through to the context in the stack frame. |
221 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); | 221 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); |
222 } | 222 } |
223 | 223 |
224 class GetCallerFrame: public StackwalkerAMD64Fixture, public Test { }; | 224 class GetCallerFrame: public StackwalkerAMD64Fixture, public Test { }; |
225 | 225 |
226 TEST_F(GetCallerFrame, ScanWithoutSymbols) { | 226 TEST_F(GetCallerFrame, ScanWithoutSymbols) { |
227 // When the stack walker resorts to scanning the stack, | 227 // When the stack walker resorts to scanning the stack, |
228 // only addresses located within loaded modules are | 228 // only addresses located within loaded modules are |
229 // considered valid return addresses. | 229 // considered valid return addresses. |
230 // Force scanning through three frames to ensure that the | 230 // Force scanning through three frames to ensure that the |
231 // stack pointer is set properly in scan-recovered frames. | 231 // stack pointer is set properly in scan-recovered frames. |
232 stack_section.start() = 0x8000000080000000ULL; | 232 stack_section.start() = 0x8000000080000000ULL; |
233 uint64_t return_address1 = 0x50000000b0000100ULL; | 233 uint64_t return_address1 = 0x00007500b0000100ULL; |
234 uint64_t return_address2 = 0x50000000b0000900ULL; | 234 uint64_t return_address2 = 0x00007500b0000900ULL; |
235 Label frame1_sp, frame2_sp, frame1_rbp; | 235 Label frame1_sp, frame2_sp, frame1_rbp; |
236 stack_section | 236 stack_section |
237 // frame 0 | 237 // frame 0 |
238 .Append(16, 0) // space | 238 .Append(16, 0) // space |
239 | 239 |
240 .D64(0x40000000b0000000ULL) // junk that's not | 240 .D64(0x00007400b0000000ULL) // junk that's not |
241 .D64(0x50000000d0000000ULL) // a return address | 241 .D64(0x00007500d0000000ULL) // a return address |
242 | 242 |
243 .D64(return_address1) // actual return address | 243 .D64(return_address1) // actual return address |
244 // frame 1 | 244 // frame 1 |
245 .Mark(&frame1_sp) | 245 .Mark(&frame1_sp) |
246 .Append(16, 0) // space | 246 .Append(16, 0) // space |
247 | 247 |
248 .D64(0x40000000b0000000ULL) // more junk | 248 .D64(0x00007400b0000000ULL) // more junk |
249 .D64(0x50000000d0000000ULL) | 249 .D64(0x00007500d0000000ULL) |
250 | 250 |
251 .Mark(&frame1_rbp) | 251 .Mark(&frame1_rbp) |
252 .D64(stack_section.start()) // This is in the right place to be | 252 .D64(stack_section.start()) // This is in the right place to be |
253 // a saved rbp, but it's bogus, so | 253 // a saved rbp, but it's bogus, so |
254 // we shouldn't report it. | 254 // we shouldn't report it. |
255 | 255 |
256 .D64(return_address2) // actual return address | 256 .D64(return_address2) // actual return address |
257 // frame 2 | 257 // frame 2 |
258 .Mark(&frame2_sp) | 258 .Mark(&frame2_sp) |
259 .Append(32, 0); // end of stack | 259 .Append(32, 0); // end of stack |
260 | 260 |
261 RegionFromSection(); | 261 RegionFromSection(); |
262 | 262 |
263 raw_context.rip = 0x40000000c0000200ULL; | 263 raw_context.rip = 0x00007400c0000200ULL; |
264 raw_context.rbp = frame1_rbp.Value(); | 264 raw_context.rbp = frame1_rbp.Value(); |
265 raw_context.rsp = stack_section.start().Value(); | 265 raw_context.rsp = stack_section.start().Value(); |
266 | 266 |
267 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); | 267 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); |
268 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, | 268 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, |
269 &frame_symbolizer); | 269 &frame_symbolizer); |
270 vector<const CodeModule*> modules_without_symbols; | 270 vector<const CodeModule*> modules_without_symbols; |
271 vector<const CodeModule*> modules_with_corrupt_symbols; | 271 vector<const CodeModule*> modules_with_corrupt_symbols; |
272 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, | 272 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, |
273 &modules_with_corrupt_symbols)); | 273 &modules_with_corrupt_symbols)); |
(...skipping 27 matching lines...) Expand all Loading... |
301 EXPECT_EQ(return_address2, frame2->context.rip); | 301 EXPECT_EQ(return_address2, frame2->context.rip); |
302 EXPECT_EQ(frame2_sp.Value(), frame2->context.rsp); | 302 EXPECT_EQ(frame2_sp.Value(), frame2->context.rsp); |
303 } | 303 } |
304 | 304 |
305 TEST_F(GetCallerFrame, ScanWithFunctionSymbols) { | 305 TEST_F(GetCallerFrame, ScanWithFunctionSymbols) { |
306 // During stack scanning, if a potential return address | 306 // During stack scanning, if a potential return address |
307 // is located within a loaded module that has symbols, | 307 // is located within a loaded module that has symbols, |
308 // it is only considered a valid return address if it | 308 // it is only considered a valid return address if it |
309 // lies within a function's bounds. | 309 // lies within a function's bounds. |
310 stack_section.start() = 0x8000000080000000ULL; | 310 stack_section.start() = 0x8000000080000000ULL; |
311 uint64_t return_address = 0x50000000b0000110ULL; | 311 uint64_t return_address = 0x00007500b0000110ULL; |
312 Label frame1_sp, frame1_rbp; | 312 Label frame1_sp, frame1_rbp; |
313 | 313 |
314 stack_section | 314 stack_section |
315 // frame 0 | 315 // frame 0 |
316 .Append(16, 0) // space | 316 .Append(16, 0) // space |
317 | 317 |
318 .D64(0x40000000b0000000ULL) // junk that's not | 318 .D64(0x00007400b0000000ULL) // junk that's not |
319 .D64(0x50000000b0000000ULL) // a return address | 319 .D64(0x00007500b0000000ULL) // a return address |
320 | 320 |
321 .D64(0x40000000c0001000ULL) // a couple of plausible addresses | 321 .D64(0x00007400c0001000ULL) // a couple of plausible addresses |
322 .D64(0x50000000b000aaaaULL) // that are not within functions | 322 .D64(0x00007500b000aaaaULL) // that are not within functions |
323 | 323 |
324 .D64(return_address) // actual return address | 324 .D64(return_address) // actual return address |
325 // frame 1 | 325 // frame 1 |
326 .Mark(&frame1_sp) | 326 .Mark(&frame1_sp) |
327 .Append(32, 0) // end of stack | 327 .Append(32, 0) // end of stack |
328 .Mark(&frame1_rbp); | 328 .Mark(&frame1_rbp); |
329 RegionFromSection(); | 329 RegionFromSection(); |
330 | 330 |
331 raw_context.rip = 0x40000000c0000200ULL; | 331 raw_context.rip = 0x00007400c0000200ULL; |
332 raw_context.rbp = frame1_rbp.Value(); | 332 raw_context.rbp = frame1_rbp.Value(); |
333 raw_context.rsp = stack_section.start().Value(); | 333 raw_context.rsp = stack_section.start().Value(); |
334 | 334 |
335 SetModuleSymbols(&module1, | 335 SetModuleSymbols(&module1, |
336 // The youngest frame's function. | 336 // The youngest frame's function. |
337 "FUNC 100 400 10 platypus\n"); | 337 "FUNC 100 400 10 platypus\n"); |
338 SetModuleSymbols(&module2, | 338 SetModuleSymbols(&module2, |
339 // The calling frame's function. | 339 // The calling frame's function. |
340 "FUNC 100 400 10 echidna\n"); | 340 "FUNC 100 400 10 echidna\n"); |
341 | 341 |
342 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); | 342 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); |
343 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, | 343 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, |
344 &frame_symbolizer); | 344 &frame_symbolizer); |
345 vector<const CodeModule*> modules_without_symbols; | 345 vector<const CodeModule*> modules_without_symbols; |
346 vector<const CodeModule*> modules_with_corrupt_symbols; | 346 vector<const CodeModule*> modules_with_corrupt_symbols; |
347 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, | 347 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, |
348 &modules_with_corrupt_symbols)); | 348 &modules_with_corrupt_symbols)); |
349 ASSERT_EQ(0U, modules_without_symbols.size()); | 349 ASSERT_EQ(0U, modules_without_symbols.size()); |
350 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); | 350 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); |
351 frames = call_stack.frames(); | 351 frames = call_stack.frames(); |
352 ASSERT_EQ(2U, frames->size()); | 352 ASSERT_EQ(2U, frames->size()); |
353 | 353 |
354 StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0)); | 354 StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0)); |
355 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); | 355 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); |
356 ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); | 356 ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); |
357 EXPECT_EQ("platypus", frame0->function_name); | 357 EXPECT_EQ("platypus", frame0->function_name); |
358 EXPECT_EQ(0x40000000c0000100ULL, frame0->function_base); | 358 EXPECT_EQ(0x00007400c0000100ULL, frame0->function_base); |
359 | 359 |
360 StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1)); | 360 StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1)); |
361 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); | 361 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); |
362 ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP | | 362 ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP | |
363 StackFrameAMD64::CONTEXT_VALID_RSP | | 363 StackFrameAMD64::CONTEXT_VALID_RSP | |
364 StackFrameAMD64::CONTEXT_VALID_RBP), | 364 StackFrameAMD64::CONTEXT_VALID_RBP), |
365 frame1->context_validity); | 365 frame1->context_validity); |
366 EXPECT_EQ(return_address, frame1->context.rip); | 366 EXPECT_EQ(return_address, frame1->context.rip); |
367 EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp); | 367 EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp); |
368 EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp); | 368 EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp); |
369 EXPECT_EQ("echidna", frame1->function_name); | 369 EXPECT_EQ("echidna", frame1->function_name); |
370 EXPECT_EQ(0x50000000b0000100ULL, frame1->function_base); | 370 EXPECT_EQ(0x00007500b0000100ULL, frame1->function_base); |
371 } | 371 } |
372 | 372 |
373 // StackwalkerAMD64::GetCallerByFramePointerRecovery should never return an | 373 // StackwalkerAMD64::GetCallerByFramePointerRecovery should never return an |
374 // instruction pointer of 0 because IP of 0 is an end of stack marker and the | 374 // instruction pointer of 0 because IP of 0 is an end of stack marker and the |
375 // stack walk may be terminated prematurely. Instead it should return NULL | 375 // stack walk may be terminated prematurely. Instead it should return NULL |
376 // so that the stack walking code can proceed to stack scanning. | 376 // so that the stack walking code can proceed to stack scanning. |
377 TEST_F(GetCallerFrame, GetCallerByFramePointerRecovery) { | 377 TEST_F(GetCallerFrame, GetCallerByFramePointerRecovery) { |
378 MockCodeModule user32_dll(0x00007ff9cb8a0000ULL, 0x14E000, "user32.dll", | 378 MockCodeModule user32_dll(0x00007ff9cb8a0000ULL, 0x14E000, "user32.dll", |
379 "version1"); | 379 "version1"); |
380 SetModuleSymbols(&user32_dll, // user32.dll | 380 SetModuleSymbols(&user32_dll, // user32.dll |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 StackFrameAMD64::CONTEXT_VALID_RBP), | 495 StackFrameAMD64::CONTEXT_VALID_RBP), |
496 frame->context_validity); | 496 frame->context_validity); |
497 EXPECT_EQ("DispatchMessageWorker", frame->function_name); | 497 EXPECT_EQ("DispatchMessageWorker", frame->function_name); |
498 EXPECT_EQ(140710838467591ULL, frame->instruction + 1); | 498 EXPECT_EQ(140710838467591ULL, frame->instruction + 1); |
499 EXPECT_EQ(140710838467591ULL, frame->context.rip); | 499 EXPECT_EQ(140710838467591ULL, frame->context.rip); |
500 EXPECT_EQ(frame2_rsp.Value(), frame->context.rsp); | 500 EXPECT_EQ(frame2_rsp.Value(), frame->context.rsp); |
501 EXPECT_EQ(&user32_dll, frame->module); | 501 EXPECT_EQ(&user32_dll, frame->module); |
502 } | 502 } |
503 } | 503 } |
504 | 504 |
| 505 // Don't use frame pointer recovery if %rbp is not 8-byte aligned, which |
| 506 // indicates that it's not being used as a frame pointer. |
| 507 TEST_F(GetCallerFrame, FramePointerNotAligned) { |
| 508 stack_section.start() = 0x8000000080000000ULL; |
| 509 uint64_t return_address1 = 0x00007500b0000100ULL; |
| 510 Label frame0_rbp, not_frame1_rbp, frame1_sp; |
| 511 stack_section |
| 512 // frame 0 |
| 513 .Align(8, 0) |
| 514 .Append(2, 0) // mis-align the frame pointer |
| 515 .Mark(&frame0_rbp) |
| 516 .D64(not_frame1_rbp) // not the previous frame pointer |
| 517 .D64(0x00007500b0000a00ULL) // plausible but wrong return address |
| 518 .Align(8, 0) |
| 519 .D64(return_address1) // return address |
| 520 // frame 1 |
| 521 .Mark(&frame1_sp) |
| 522 .Mark(¬_frame1_rbp) |
| 523 .Append(32, 0); // end of stack |
| 524 |
| 525 |
| 526 RegionFromSection(); |
| 527 |
| 528 raw_context.rip = 0x00007400c0000200ULL; |
| 529 raw_context.rbp = frame0_rbp.Value(); |
| 530 raw_context.rsp = stack_section.start().Value(); |
| 531 |
| 532 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); |
| 533 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, |
| 534 &frame_symbolizer); |
| 535 vector<const CodeModule*> modules_without_symbols; |
| 536 vector<const CodeModule*> modules_with_corrupt_symbols; |
| 537 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, |
| 538 &modules_with_corrupt_symbols)); |
| 539 frames = call_stack.frames(); |
| 540 ASSERT_EQ(2U, frames->size()); |
| 541 |
| 542 StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0)); |
| 543 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); |
| 544 ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); |
| 545 EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); |
| 546 |
| 547 StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1)); |
| 548 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); |
| 549 ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP | |
| 550 StackFrameAMD64::CONTEXT_VALID_RSP), |
| 551 frame1->context_validity); |
| 552 EXPECT_EQ(return_address1, frame1->context.rip); |
| 553 EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp); |
| 554 } |
| 555 |
| 556 // Don't use frame pointer recovery if the recovered %rip is not |
| 557 // a canonical x86-64 address. |
| 558 TEST_F(GetCallerFrame, NonCanonicalInstructionPointerFromFramePointer) { |
| 559 stack_section.start() = 0x8000000080000000ULL; |
| 560 uint64_t return_address1 = 0x00007500b0000100ULL; |
| 561 Label frame0_rbp, frame1_sp, not_frame1_bp; |
| 562 stack_section |
| 563 // frame 0 |
| 564 .Align(8, 0) |
| 565 .Mark(&frame0_rbp) |
| 566 .D64(not_frame1_bp) // some junk on the stack |
| 567 .D64(0xDADADADADADADADA) // not the return address |
| 568 .D64(return_address1) // return address |
| 569 // frame 1 |
| 570 .Mark(&frame1_sp) |
| 571 .Append(16, 0) |
| 572 .Mark(¬_frame1_bp) |
| 573 .Append(32, 0); // end of stack |
| 574 |
| 575 |
| 576 RegionFromSection(); |
| 577 |
| 578 raw_context.rip = 0x00007400c0000200ULL; |
| 579 raw_context.rbp = frame0_rbp.Value(); |
| 580 raw_context.rsp = stack_section.start().Value(); |
| 581 |
| 582 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); |
| 583 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, |
| 584 &frame_symbolizer); |
| 585 vector<const CodeModule*> modules_without_symbols; |
| 586 vector<const CodeModule*> modules_with_corrupt_symbols; |
| 587 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, |
| 588 &modules_with_corrupt_symbols)); |
| 589 frames = call_stack.frames(); |
| 590 ASSERT_EQ(2U, frames->size()); |
| 591 |
| 592 StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0)); |
| 593 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); |
| 594 ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); |
| 595 EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); |
| 596 |
| 597 StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1)); |
| 598 EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); |
| 599 ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP | |
| 600 StackFrameAMD64::CONTEXT_VALID_RSP), |
| 601 frame1->context_validity); |
| 602 EXPECT_EQ(return_address1, frame1->context.rip); |
| 603 EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp); |
| 604 } |
| 605 |
505 // Test that set_max_frames_scanned prevents using stack scanning | 606 // Test that set_max_frames_scanned prevents using stack scanning |
506 // to find caller frames. | 607 // to find caller frames. |
507 TEST_F(GetCallerFrame, ScanningNotAllowed) { | 608 TEST_F(GetCallerFrame, ScanningNotAllowed) { |
508 // When the stack walker resorts to scanning the stack, | 609 // When the stack walker resorts to scanning the stack, |
509 // only addresses located within loaded modules are | 610 // only addresses located within loaded modules are |
510 // considered valid return addresses. | 611 // considered valid return addresses. |
511 stack_section.start() = 0x8000000080000000ULL; | 612 stack_section.start() = 0x8000000080000000ULL; |
512 uint64_t return_address1 = 0x50000000b0000100ULL; | 613 uint64_t return_address1 = 0x00007500b0000100ULL; |
513 uint64_t return_address2 = 0x50000000b0000900ULL; | 614 uint64_t return_address2 = 0x00007500b0000900ULL; |
514 Label frame1_sp, frame2_sp, frame1_rbp; | 615 Label frame1_sp, frame2_sp, frame1_rbp; |
515 stack_section | 616 stack_section |
516 // frame 0 | 617 // frame 0 |
517 .Append(16, 0) // space | 618 .Append(16, 0) // space |
518 | 619 |
519 .D64(0x40000000b0000000ULL) // junk that's not | 620 .D64(0x00007400b0000000ULL) // junk that's not |
520 .D64(0x50000000d0000000ULL) // a return address | 621 .D64(0x00007500d0000000ULL) // a return address |
521 | 622 |
522 .D64(return_address1) // actual return address | 623 .D64(return_address1) // actual return address |
523 // frame 1 | 624 // frame 1 |
524 .Mark(&frame1_sp) | 625 .Mark(&frame1_sp) |
525 .Append(16, 0) // space | 626 .Append(16, 0) // space |
526 | 627 |
527 .D64(0x40000000b0000000ULL) // more junk | 628 .D64(0x00007400b0000000ULL) // more junk |
528 .D64(0x50000000d0000000ULL) | 629 .D64(0x00007500d0000000ULL) |
529 | 630 |
530 .Mark(&frame1_rbp) | 631 .Mark(&frame1_rbp) |
531 .D64(stack_section.start()) // This is in the right place to be | 632 .D64(stack_section.start()) // This is in the right place to be |
532 // a saved rbp, but it's bogus, so | 633 // a saved rbp, but it's bogus, so |
533 // we shouldn't report it. | 634 // we shouldn't report it. |
534 | 635 |
535 .D64(return_address2) // actual return address | 636 .D64(return_address2) // actual return address |
536 // frame 2 | 637 // frame 2 |
537 .Mark(&frame2_sp) | 638 .Mark(&frame2_sp) |
538 .Append(32, 0); // end of stack | 639 .Append(32, 0); // end of stack |
539 | 640 |
540 RegionFromSection(); | 641 RegionFromSection(); |
541 | 642 |
542 raw_context.rip = 0x40000000c0000200ULL; | 643 raw_context.rip = 0x00007400c0000200ULL; |
543 raw_context.rbp = frame1_rbp.Value(); | 644 raw_context.rbp = frame1_rbp.Value(); |
544 raw_context.rsp = stack_section.start().Value(); | 645 raw_context.rsp = stack_section.start().Value(); |
545 | 646 |
546 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); | 647 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); |
547 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, | 648 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, |
548 &frame_symbolizer); | 649 &frame_symbolizer); |
549 Stackwalker::set_max_frames_scanned(0); | 650 Stackwalker::set_max_frames_scanned(0); |
550 | 651 |
551 vector<const CodeModule*> modules_without_symbols; | 652 vector<const CodeModule*> modules_without_symbols; |
552 vector<const CodeModule*> modules_with_corrupt_symbols; | 653 vector<const CodeModule*> modules_with_corrupt_symbols; |
(...skipping 10 matching lines...) Expand all Loading... |
563 ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); | 664 ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); |
564 EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); | 665 EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); |
565 } | 666 } |
566 | 667 |
567 TEST_F(GetCallerFrame, CallerPushedRBP) { | 668 TEST_F(GetCallerFrame, CallerPushedRBP) { |
568 // Functions typically push their %rbp upon entry and set %rbp pointing | 669 // Functions typically push their %rbp upon entry and set %rbp pointing |
569 // there. If stackwalking finds a plausible address for the next frame's | 670 // there. If stackwalking finds a plausible address for the next frame's |
570 // %rbp directly below the return address, assume that it is indeed the | 671 // %rbp directly below the return address, assume that it is indeed the |
571 // next frame's %rbp. | 672 // next frame's %rbp. |
572 stack_section.start() = 0x8000000080000000ULL; | 673 stack_section.start() = 0x8000000080000000ULL; |
573 uint64_t return_address = 0x50000000b0000110ULL; | 674 uint64_t return_address = 0x00007500b0000110ULL; |
574 Label frame0_rbp, frame1_sp, frame1_rbp; | 675 Label frame0_rbp, frame1_sp, frame1_rbp; |
575 | 676 |
576 stack_section | 677 stack_section |
577 // frame 0 | 678 // frame 0 |
578 .Append(16, 0) // space | 679 .Append(16, 0) // space |
579 | 680 |
580 .D64(0x40000000b0000000ULL) // junk that's not | 681 .D64(0x00007400b0000000ULL) // junk that's not |
581 .D64(0x50000000b0000000ULL) // a return address | 682 .D64(0x00007500b0000000ULL) // a return address |
582 | 683 |
583 .D64(0x40000000c0001000ULL) // a couple of plausible addresses | 684 .D64(0x00007400c0001000ULL) // a couple of plausible addresses |
584 .D64(0x50000000b000aaaaULL) // that are not within functions | 685 .D64(0x00007500b000aaaaULL) // that are not within functions |
585 | 686 |
586 .Mark(&frame0_rbp) | 687 .Mark(&frame0_rbp) |
587 .D64(frame1_rbp) // caller-pushed %rbp | 688 .D64(frame1_rbp) // caller-pushed %rbp |
588 .D64(return_address) // actual return address | 689 .D64(return_address) // actual return address |
589 // frame 1 | 690 // frame 1 |
590 .Mark(&frame1_sp) | 691 .Mark(&frame1_sp) |
591 .Append(32, 0) // body of frame1 | 692 .Append(32, 0) // body of frame1 |
592 .Mark(&frame1_rbp); // end of stack | 693 .Mark(&frame1_rbp); // end of stack |
593 RegionFromSection(); | 694 RegionFromSection(); |
594 | 695 |
595 raw_context.rip = 0x40000000c0000200ULL; | 696 raw_context.rip = 0x00007400c0000200ULL; |
596 raw_context.rbp = frame0_rbp.Value(); | 697 raw_context.rbp = frame0_rbp.Value(); |
597 raw_context.rsp = stack_section.start().Value(); | 698 raw_context.rsp = stack_section.start().Value(); |
598 | 699 |
599 SetModuleSymbols(&module1, | 700 SetModuleSymbols(&module1, |
600 // The youngest frame's function. | 701 // The youngest frame's function. |
601 "FUNC 100 400 10 sasquatch\n"); | 702 "FUNC 100 400 10 sasquatch\n"); |
602 SetModuleSymbols(&module2, | 703 SetModuleSymbols(&module2, |
603 // The calling frame's function. | 704 // The calling frame's function. |
604 "FUNC 100 400 10 yeti\n"); | 705 "FUNC 100 400 10 yeti\n"); |
605 | 706 |
606 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); | 707 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); |
607 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, | 708 StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, |
608 &frame_symbolizer); | 709 &frame_symbolizer); |
609 vector<const CodeModule*> modules_without_symbols; | 710 vector<const CodeModule*> modules_without_symbols; |
610 vector<const CodeModule*> modules_with_corrupt_symbols; | 711 vector<const CodeModule*> modules_with_corrupt_symbols; |
611 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, | 712 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, |
612 &modules_with_corrupt_symbols)); | 713 &modules_with_corrupt_symbols)); |
613 ASSERT_EQ(0U, modules_without_symbols.size()); | 714 ASSERT_EQ(0U, modules_without_symbols.size()); |
614 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); | 715 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); |
615 frames = call_stack.frames(); | 716 frames = call_stack.frames(); |
616 ASSERT_EQ(2U, frames->size()); | 717 ASSERT_EQ(2U, frames->size()); |
617 | 718 |
618 StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0)); | 719 StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0)); |
619 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); | 720 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); |
620 ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); | 721 ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); |
621 EXPECT_EQ(frame0_rbp.Value(), frame0->context.rbp); | 722 EXPECT_EQ(frame0_rbp.Value(), frame0->context.rbp); |
622 EXPECT_EQ("sasquatch", frame0->function_name); | 723 EXPECT_EQ("sasquatch", frame0->function_name); |
623 EXPECT_EQ(0x40000000c0000100ULL, frame0->function_base); | 724 EXPECT_EQ(0x00007400c0000100ULL, frame0->function_base); |
624 | 725 |
625 StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1)); | 726 StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1)); |
626 EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust); | 727 EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust); |
627 ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP | | 728 ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP | |
628 StackFrameAMD64::CONTEXT_VALID_RSP | | 729 StackFrameAMD64::CONTEXT_VALID_RSP | |
629 StackFrameAMD64::CONTEXT_VALID_RBP), | 730 StackFrameAMD64::CONTEXT_VALID_RBP), |
630 frame1->context_validity); | 731 frame1->context_validity); |
631 EXPECT_EQ(return_address, frame1->context.rip); | 732 EXPECT_EQ(return_address, frame1->context.rip); |
632 EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp); | 733 EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp); |
633 EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp); | 734 EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp); |
634 EXPECT_EQ("yeti", frame1->function_name); | 735 EXPECT_EQ("yeti", frame1->function_name); |
635 EXPECT_EQ(0x50000000b0000100ULL, frame1->function_base); | 736 EXPECT_EQ(0x00007500b0000100ULL, frame1->function_base); |
636 } | 737 } |
637 | 738 |
638 struct CFIFixture: public StackwalkerAMD64Fixture { | 739 struct CFIFixture: public StackwalkerAMD64Fixture { |
639 CFIFixture() { | 740 CFIFixture() { |
640 // Provide a bunch of STACK CFI records; we'll walk to the caller | 741 // Provide a bunch of STACK CFI records; we'll walk to the caller |
641 // from every point in this series, expecting to find the same set | 742 // from every point in this series, expecting to find the same set |
642 // of register values. | 743 // of register values. |
643 SetModuleSymbols(&module1, | 744 SetModuleSymbols(&module1, |
644 // The youngest frame's function. | 745 // The youngest frame's function. |
645 "FUNC 4000 1000 10 enchiridion\n" | 746 "FUNC 4000 1000 10 enchiridion\n" |
(...skipping 10 matching lines...) Expand all Loading... |
656 // Save %rbp, and use it as a frame pointer. | 757 // Save %rbp, and use it as a frame pointer. |
657 "STACK CFI 4006 .cfa: $rbp 16 + $rbp: .cfa 24 - ^\n" | 758 "STACK CFI 4006 .cfa: $rbp 16 + $rbp: .cfa 24 - ^\n" |
658 | 759 |
659 // The calling function. | 760 // The calling function. |
660 "FUNC 5000 1000 10 epictetus\n" | 761 "FUNC 5000 1000 10 epictetus\n" |
661 // Mark it as end of stack. | 762 // Mark it as end of stack. |
662 "STACK CFI INIT 5000 1000 .cfa: $rsp .ra 0\n"); | 763 "STACK CFI INIT 5000 1000 .cfa: $rsp .ra 0\n"); |
663 | 764 |
664 // Provide some distinctive values for the caller's registers. | 765 // Provide some distinctive values for the caller's registers. |
665 expected.rsp = 0x8000000080000000ULL; | 766 expected.rsp = 0x8000000080000000ULL; |
666 expected.rip = 0x40000000c0005510ULL; | 767 expected.rip = 0x00007400c0005510ULL; |
667 expected.rbp = 0x68995b1de4700266ULL; | 768 expected.rbp = 0x68995b1de4700266ULL; |
668 expected.rbx = 0x5a5beeb38de23be8ULL; | 769 expected.rbx = 0x5a5beeb38de23be8ULL; |
669 expected.r12 = 0xed1b02e8cc0fc79cULL; | 770 expected.r12 = 0xed1b02e8cc0fc79cULL; |
670 expected.r13 = 0x1d20ad8acacbe930ULL; | 771 expected.r13 = 0x1d20ad8acacbe930ULL; |
671 expected.r14 = 0xe94cffc2f7adaa28ULL; | 772 expected.r14 = 0xe94cffc2f7adaa28ULL; |
672 expected.r15 = 0xb638d17d8da413b5ULL; | 773 expected.r15 = 0xb638d17d8da413b5ULL; |
673 | 774 |
674 // By default, registers are unchanged. | 775 // By default, registers are unchanged. |
675 raw_context = expected; | 776 raw_context = expected; |
676 } | 777 } |
(...skipping 16 matching lines...) Expand all Loading... |
693 &modules_with_corrupt_symbols)); | 794 &modules_with_corrupt_symbols)); |
694 ASSERT_EQ(0U, modules_without_symbols.size()); | 795 ASSERT_EQ(0U, modules_without_symbols.size()); |
695 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); | 796 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); |
696 frames = call_stack.frames(); | 797 frames = call_stack.frames(); |
697 ASSERT_EQ(2U, frames->size()); | 798 ASSERT_EQ(2U, frames->size()); |
698 | 799 |
699 StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0)); | 800 StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0)); |
700 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); | 801 EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); |
701 ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); | 802 ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); |
702 EXPECT_EQ("enchiridion", frame0->function_name); | 803 EXPECT_EQ("enchiridion", frame0->function_name); |
703 EXPECT_EQ(0x40000000c0004000ULL, frame0->function_base); | 804 EXPECT_EQ(0x00007400c0004000ULL, frame0->function_base); |
704 | 805 |
705 StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1)); | 806 StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1)); |
706 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); | 807 EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); |
707 ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP | | 808 ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP | |
708 StackFrameAMD64::CONTEXT_VALID_RSP | | 809 StackFrameAMD64::CONTEXT_VALID_RSP | |
709 StackFrameAMD64::CONTEXT_VALID_RBP | | 810 StackFrameAMD64::CONTEXT_VALID_RBP | |
710 StackFrameAMD64::CONTEXT_VALID_RBX | | 811 StackFrameAMD64::CONTEXT_VALID_RBX | |
711 StackFrameAMD64::CONTEXT_VALID_R12 | | 812 StackFrameAMD64::CONTEXT_VALID_R12 | |
712 StackFrameAMD64::CONTEXT_VALID_R13 | | 813 StackFrameAMD64::CONTEXT_VALID_R13 | |
713 StackFrameAMD64::CONTEXT_VALID_R14 | | 814 StackFrameAMD64::CONTEXT_VALID_R14 | |
(...skipping 12 matching lines...) Expand all Loading... |
726 | 827 |
727 // The values we expect to find for the caller's registers. | 828 // The values we expect to find for the caller's registers. |
728 MDRawContextAMD64 expected; | 829 MDRawContextAMD64 expected; |
729 }; | 830 }; |
730 | 831 |
731 class CFI: public CFIFixture, public Test { }; | 832 class CFI: public CFIFixture, public Test { }; |
732 | 833 |
733 TEST_F(CFI, At4000) { | 834 TEST_F(CFI, At4000) { |
734 Label frame1_rsp = expected.rsp; | 835 Label frame1_rsp = expected.rsp; |
735 stack_section | 836 stack_section |
736 .D64(0x40000000c0005510ULL) // return address | 837 .D64(0x00007400c0005510ULL) // return address |
737 .Mark(&frame1_rsp); // This effectively sets stack_section.start(). | 838 .Mark(&frame1_rsp); // This effectively sets stack_section.start(). |
738 raw_context.rip = 0x40000000c0004000ULL; | 839 raw_context.rip = 0x00007400c0004000ULL; |
739 CheckWalk(); | 840 CheckWalk(); |
740 } | 841 } |
741 | 842 |
742 TEST_F(CFI, At4001) { | 843 TEST_F(CFI, At4001) { |
743 Label frame1_rsp = expected.rsp; | 844 Label frame1_rsp = expected.rsp; |
744 stack_section | 845 stack_section |
745 .D64(0x5a5beeb38de23be8ULL) // saved %rbx | 846 .D64(0x5a5beeb38de23be8ULL) // saved %rbx |
746 .D64(0x40000000c0005510ULL) // return address | 847 .D64(0x00007400c0005510ULL) // return address |
747 .Mark(&frame1_rsp); // This effectively sets stack_section.start(). | 848 .Mark(&frame1_rsp); // This effectively sets stack_section.start(). |
748 raw_context.rip = 0x40000000c0004001ULL; | 849 raw_context.rip = 0x00007400c0004001ULL; |
749 raw_context.rbx = 0xbe0487d2f9eafe29ULL; // callee's (distinct) %rbx value | 850 raw_context.rbx = 0xbe0487d2f9eafe29ULL; // callee's (distinct) %rbx value |
750 CheckWalk(); | 851 CheckWalk(); |
751 } | 852 } |
752 | 853 |
753 TEST_F(CFI, At4002) { | 854 TEST_F(CFI, At4002) { |
754 Label frame1_rsp = expected.rsp; | 855 Label frame1_rsp = expected.rsp; |
755 stack_section | 856 stack_section |
756 .D64(0x5a5beeb38de23be8ULL) // saved %rbx | 857 .D64(0x5a5beeb38de23be8ULL) // saved %rbx |
757 .D64(0x40000000c0005510ULL) // return address | 858 .D64(0x00007400c0005510ULL) // return address |
758 .Mark(&frame1_rsp); // This effectively sets stack_section.start(). | 859 .Mark(&frame1_rsp); // This effectively sets stack_section.start(). |
759 raw_context.rip = 0x40000000c0004002ULL; | 860 raw_context.rip = 0x00007400c0004002ULL; |
760 raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 | 861 raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 |
761 raw_context.r12 = 0xb0118de918a4bceaULL; // callee's (distinct) %r12 value | 862 raw_context.r12 = 0xb0118de918a4bceaULL; // callee's (distinct) %r12 value |
762 CheckWalk(); | 863 CheckWalk(); |
763 } | 864 } |
764 | 865 |
765 TEST_F(CFI, At4003) { | 866 TEST_F(CFI, At4003) { |
766 Label frame1_rsp = expected.rsp; | 867 Label frame1_rsp = expected.rsp; |
767 stack_section | 868 stack_section |
768 .D64(0x0e023828dffd4d81ULL) // garbage | 869 .D64(0x0e023828dffd4d81ULL) // garbage |
769 .D64(0x1d20ad8acacbe930ULL) // saved %r13 | 870 .D64(0x1d20ad8acacbe930ULL) // saved %r13 |
770 .D64(0x319e68b49e3ace0fULL) // garbage | 871 .D64(0x319e68b49e3ace0fULL) // garbage |
771 .D64(0x5a5beeb38de23be8ULL) // saved %rbx | 872 .D64(0x5a5beeb38de23be8ULL) // saved %rbx |
772 .D64(0x40000000c0005510ULL) // return address | 873 .D64(0x00007400c0005510ULL) // return address |
773 .Mark(&frame1_rsp); // This effectively sets stack_section.start(). | 874 .Mark(&frame1_rsp); // This effectively sets stack_section.start(). |
774 raw_context.rip = 0x40000000c0004003ULL; | 875 raw_context.rip = 0x00007400c0004003ULL; |
775 raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 | 876 raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 |
776 raw_context.r12 = 0x89d04fa804c87a43ULL; // callee's (distinct) %r12 | 877 raw_context.r12 = 0x89d04fa804c87a43ULL; // callee's (distinct) %r12 |
777 raw_context.r13 = 0x5118e02cbdb24b03ULL; // callee's (distinct) %r13 | 878 raw_context.r13 = 0x5118e02cbdb24b03ULL; // callee's (distinct) %r13 |
778 CheckWalk(); | 879 CheckWalk(); |
779 } | 880 } |
780 | 881 |
781 // The results here should be the same as those at module offset 0x4003. | 882 // The results here should be the same as those at module offset 0x4003. |
782 TEST_F(CFI, At4004) { | 883 TEST_F(CFI, At4004) { |
783 Label frame1_rsp = expected.rsp; | 884 Label frame1_rsp = expected.rsp; |
784 stack_section | 885 stack_section |
785 .D64(0x0e023828dffd4d81ULL) // garbage | 886 .D64(0x0e023828dffd4d81ULL) // garbage |
786 .D64(0x1d20ad8acacbe930ULL) // saved %r13 | 887 .D64(0x1d20ad8acacbe930ULL) // saved %r13 |
787 .D64(0x319e68b49e3ace0fULL) // garbage | 888 .D64(0x319e68b49e3ace0fULL) // garbage |
788 .D64(0x5a5beeb38de23be8ULL) // saved %rbx | 889 .D64(0x5a5beeb38de23be8ULL) // saved %rbx |
789 .D64(0x40000000c0005510ULL) // return address | 890 .D64(0x00007400c0005510ULL) // return address |
790 .Mark(&frame1_rsp); // This effectively sets stack_section.start(). | 891 .Mark(&frame1_rsp); // This effectively sets stack_section.start(). |
791 raw_context.rip = 0x40000000c0004004ULL; | 892 raw_context.rip = 0x00007400c0004004ULL; |
792 raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 | 893 raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 |
793 raw_context.r12 = 0x89d04fa804c87a43ULL; // callee's (distinct) %r12 | 894 raw_context.r12 = 0x89d04fa804c87a43ULL; // callee's (distinct) %r12 |
794 raw_context.r13 = 0x5118e02cbdb24b03ULL; // callee's (distinct) %r13 | 895 raw_context.r13 = 0x5118e02cbdb24b03ULL; // callee's (distinct) %r13 |
795 CheckWalk(); | 896 CheckWalk(); |
796 } | 897 } |
797 | 898 |
798 TEST_F(CFI, At4005) { | 899 TEST_F(CFI, At4005) { |
799 Label frame1_rsp = expected.rsp; | 900 Label frame1_rsp = expected.rsp; |
800 stack_section | 901 stack_section |
801 .D64(0x4b516dd035745953ULL) // garbage | 902 .D64(0x4b516dd035745953ULL) // garbage |
802 .D64(0x1d20ad8acacbe930ULL) // saved %r13 | 903 .D64(0x1d20ad8acacbe930ULL) // saved %r13 |
803 .D64(0xa6d445e16ae3d872ULL) // garbage | 904 .D64(0xa6d445e16ae3d872ULL) // garbage |
804 .D64(0x5a5beeb38de23be8ULL) // saved %rbx | 905 .D64(0x5a5beeb38de23be8ULL) // saved %rbx |
805 .D64(0xaa95fa054aedfbaeULL) // garbage | 906 .D64(0xaa95fa054aedfbaeULL) // garbage |
806 .Mark(&frame1_rsp); // This effectively sets stack_section.start(). | 907 .Mark(&frame1_rsp); // This effectively sets stack_section.start(). |
807 raw_context.rip = 0x40000000c0004005ULL; | 908 raw_context.rip = 0x00007400c0004005ULL; |
808 raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 | 909 raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 |
809 raw_context.r12 = 0x46b1b8868891b34aULL; // callee's %r12 | 910 raw_context.r12 = 0x46b1b8868891b34aULL; // callee's %r12 |
810 raw_context.r13 = 0x40000000c0005510ULL; // return address | 911 raw_context.r13 = 0x00007400c0005510ULL; // return address |
811 CheckWalk(); | 912 CheckWalk(); |
812 } | 913 } |
813 | 914 |
814 TEST_F(CFI, At4006) { | 915 TEST_F(CFI, At4006) { |
815 Label frame0_rbp; | 916 Label frame0_rbp; |
816 Label frame1_rsp = expected.rsp; | 917 Label frame1_rsp = expected.rsp; |
817 stack_section | 918 stack_section |
818 .D64(0x043c6dfceb91aa34ULL) // garbage | 919 .D64(0x043c6dfceb91aa34ULL) // garbage |
819 .D64(0x1d20ad8acacbe930ULL) // saved %r13 | 920 .D64(0x1d20ad8acacbe930ULL) // saved %r13 |
820 .D64(0x68995b1de4700266ULL) // saved %rbp | 921 .D64(0x68995b1de4700266ULL) // saved %rbp |
821 .Mark(&frame0_rbp) // frame pointer points here | 922 .Mark(&frame0_rbp) // frame pointer points here |
822 .D64(0x5a5beeb38de23be8ULL) // saved %rbx | 923 .D64(0x5a5beeb38de23be8ULL) // saved %rbx |
823 .D64(0xf015ee516ad89eabULL) // garbage | 924 .D64(0xf015ee516ad89eabULL) // garbage |
824 .Mark(&frame1_rsp); // This effectively sets stack_section.start(). | 925 .Mark(&frame1_rsp); // This effectively sets stack_section.start(). |
825 raw_context.rip = 0x40000000c0004006ULL; | 926 raw_context.rip = 0x00007400c0004006ULL; |
826 raw_context.rbp = frame0_rbp.Value(); | 927 raw_context.rbp = frame0_rbp.Value(); |
827 raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 | 928 raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 |
828 raw_context.r12 = 0x26e007b341acfebdULL; // callee's %r12 | 929 raw_context.r12 = 0x26e007b341acfebdULL; // callee's %r12 |
829 raw_context.r13 = 0x40000000c0005510ULL; // return address | 930 raw_context.r13 = 0x00007400c0005510ULL; // return address |
830 CheckWalk(); | 931 CheckWalk(); |
831 } | 932 } |
OLD | NEW |