| 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 |