LEFT | RIGHT |
(no file at all) | |
1 // Copyright (c) 2011 Google Inc. | 1 // Copyright (c) 2011 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 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
494 | 494 |
495 EXPECT_EQ(kMemoryAddress, region->GetBase()); | 495 EXPECT_EQ(kMemoryAddress, region->GetBase()); |
496 EXPECT_EQ(kMemorySize, region->GetSize()); | 496 EXPECT_EQ(kMemorySize, region->GetSize()); |
497 | 497 |
498 // Verify memory contents. | 498 // Verify memory contents. |
499 EXPECT_EQ(0, memcmp(region->GetMemory(), memory, kMemorySize)); | 499 EXPECT_EQ(0, memcmp(region->GetMemory(), memory, kMemorySize)); |
500 | 500 |
501 delete[] memory; | 501 delete[] memory; |
502 close(fds[1]); | 502 close(fds[1]); |
503 } | 503 } |
| 504 |
| 505 // Test that an invalid thread stack pointer still results in a minidump. |
| 506 TEST(MinidumpWriterTest, InvalidStackPointer) { |
| 507 int fds[2]; |
| 508 ASSERT_NE(-1, pipe(fds)); |
| 509 |
| 510 const pid_t child = fork(); |
| 511 if (child == 0) { |
| 512 close(fds[1]); |
| 513 char b; |
| 514 HANDLE_EINTR(read(fds[0], &b, sizeof(b))); |
| 515 close(fds[0]); |
| 516 syscall(__NR_exit); |
| 517 } |
| 518 close(fds[0]); |
| 519 |
| 520 ExceptionHandler::CrashContext context; |
| 521 |
| 522 // This needs a valid context for minidump writing to work, but getting |
| 523 // a useful one from the child is too much work, so just use one from |
| 524 // the parent since the child is just a forked copy anyway. |
| 525 ASSERT_EQ(0, getcontext(&context.context)); |
| 526 context.tid = child; |
| 527 |
| 528 // Fake the child's stack pointer for its crashing thread. NOTE: This must |
| 529 // be an invalid memory address for the child process (stack or otherwise). |
| 530 #if defined(__i386) |
| 531 // Try 1MB below the current stack. |
| 532 uintptr_t invalid_stack_pointer = |
| 533 reinterpret_cast<uintptr_t>(&context) - 1024*1024; |
| 534 context.context.uc_mcontext.gregs[REG_ESP] = invalid_stack_pointer; |
| 535 #elif defined(__x86_64) |
| 536 // Try 1MB below the current stack. |
| 537 uintptr_t invalid_stack_pointer = |
| 538 reinterpret_cast<uintptr_t>(&context) - 1024*1024; |
| 539 context.context.uc_mcontext.gregs[REG_RSP] = invalid_stack_pointer; |
| 540 #elif defined(__ARM_EABI__) |
| 541 // Try 1MB below the current stack. |
| 542 uintptr_t invalid_stack_pointer = |
| 543 reinterpret_cast<uintptr_t>(&context) - 1024*1024; |
| 544 context.context.uc_mcontext.arm_sp = invalid_stack_pointer; |
| 545 #else |
| 546 # error "This code has not been ported to your platform yet." |
| 547 #endif |
| 548 |
| 549 AutoTempDir temp_dir; |
| 550 string templ = temp_dir.path() + "/minidump-writer-unittest"; |
| 551 // NOTE: In previous versions of Breakpad, WriteMinidump() would fail if |
| 552 // presented with an invalid stack pointer. |
| 553 ASSERT_TRUE(WriteMinidump(templ.c_str(), child, &context, sizeof(context))); |
| 554 |
| 555 // Read the minidump. Ensure that the memory region is present |
| 556 Minidump minidump(templ.c_str()); |
| 557 ASSERT_TRUE(minidump.Read()); |
| 558 |
| 559 // TODO(ted.mielczarek,mkrebs): Enable this part of the test once |
| 560 // https://breakpad.appspot.com/413002/ is committed. |
| 561 #if 0 |
| 562 // Make sure there's a thread without a stack. NOTE: It's okay if |
| 563 // GetThreadList() shows the error: "ERROR: MinidumpThread has a memory |
| 564 // region problem". |
| 565 MinidumpThreadList* dump_thread_list = minidump.GetThreadList(); |
| 566 ASSERT_TRUE(dump_thread_list); |
| 567 bool found_empty_stack = false; |
| 568 for (int i = 0; i < dump_thread_list->thread_count(); i++) { |
| 569 MinidumpThread* thread = dump_thread_list->GetThreadAtIndex(i); |
| 570 ASSERT_TRUE(thread->thread() != NULL); |
| 571 // When the stack size is zero bytes, GetMemory() returns NULL. |
| 572 if (thread->GetMemory() == NULL) { |
| 573 found_empty_stack = true; |
| 574 break; |
| 575 } |
| 576 } |
| 577 // NOTE: If you fail this, first make sure that "invalid_stack_pointer" |
| 578 // above is indeed set to an invalid address. |
| 579 ASSERT_TRUE(found_empty_stack); |
| 580 #endif |
| 581 |
| 582 close(fds[1]); |
| 583 } |
LEFT | RIGHT |