Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(249)

Side by Side Diff: snapshot/mac/process_reader_test.cc

Issue 811823003: Cross platform low level file IO wrappers (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: . Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Crashpad Authors. All rights reserved. 1 // Copyright 2014 The Crashpad Authors. All rights reserved.
2 // 2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License. 4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at 5 // You may obtain a copy of the License at
6 // 6 //
7 // http://www.apache.org/licenses/LICENSE-2.0 7 // http://www.apache.org/licenses/LICENSE-2.0
8 // 8 //
9 // Unless required by applicable law or agreed to in writing, software 9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, 10 // distributed under the License is distributed on an "AS IS" BASIS,
(...skipping 13 matching lines...) Expand all
24 #include <string> 24 #include <string>
25 #include <vector> 25 #include <vector>
26 26
27 #include "base/logging.h" 27 #include "base/logging.h"
28 #include "base/mac/scoped_mach_port.h" 28 #include "base/mac/scoped_mach_port.h"
29 #include "base/posix/eintr_wrapper.h" 29 #include "base/posix/eintr_wrapper.h"
30 #include "base/strings/stringprintf.h" 30 #include "base/strings/stringprintf.h"
31 #include "build/build_config.h" 31 #include "build/build_config.h"
32 #include "gtest/gtest.h" 32 #include "gtest/gtest.h"
33 #include "snapshot/mac/mach_o_image_reader.h" 33 #include "snapshot/mac/mach_o_image_reader.h"
34 #include "util/file/fd_io.h" 34 #include "util/file/file_io.h"
35 #include "util/mach/mach_extensions.h" 35 #include "util/mach/mach_extensions.h"
36 #include "util/stdlib/pointer_container.h" 36 #include "util/stdlib/pointer_container.h"
37 #include "util/synchronization/semaphore.h" 37 #include "util/synchronization/semaphore.h"
38 #include "util/test/errors.h" 38 #include "util/test/errors.h"
39 #include "util/test/mac/dyld.h" 39 #include "util/test/mac/dyld.h"
40 #include "util/test/mac/mach_errors.h" 40 #include "util/test/mac/mach_errors.h"
41 #include "util/test/mac/mach_multiprocess.h" 41 #include "util/test/mac/mach_multiprocess.h"
42 42
43 namespace crashpad { 43 namespace crashpad {
44 namespace test { 44 namespace test {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 #else 84 #else
85 EXPECT_TRUE(process_reader.Is64Bit()); 85 EXPECT_TRUE(process_reader.Is64Bit());
86 #endif 86 #endif
87 87
88 EXPECT_EQ(getpid(), process_reader.ParentProcessID()); 88 EXPECT_EQ(getpid(), process_reader.ParentProcessID());
89 EXPECT_EQ(ChildPID(), process_reader.ProcessID()); 89 EXPECT_EQ(ChildPID(), process_reader.ProcessID());
90 90
91 int read_fd = ReadPipeFD(); 91 int read_fd = ReadPipeFD();
92 92
93 mach_vm_address_t address; 93 mach_vm_address_t address;
94 CheckedReadFD(read_fd, &address, sizeof(address)); 94 CheckedReadFile(read_fd, &address, sizeof(address));
95 95
96 std::string read_string; 96 std::string read_string;
97 ASSERT_TRUE(process_reader.Memory()->ReadCString(address, &read_string)); 97 ASSERT_TRUE(process_reader.Memory()->ReadCString(address, &read_string));
98 EXPECT_EQ(kTestMemory, read_string); 98 EXPECT_EQ(kTestMemory, read_string);
99 } 99 }
100 100
101 void MachMultiprocessChild() override { 101 void MachMultiprocessChild() override {
102 int write_fd = WritePipeFD(); 102 int write_fd = WritePipeFD();
103 103
104 mach_vm_address_t address = 104 mach_vm_address_t address =
105 reinterpret_cast<mach_vm_address_t>(kTestMemory); 105 reinterpret_cast<mach_vm_address_t>(kTestMemory);
106 CheckedWriteFD(write_fd, &address, sizeof(address)); 106 CheckedWriteFile(write_fd, &address, sizeof(address));
107 107
108 // Wait for the parent to signal that it’s OK to exit by closing its end of 108 // Wait for the parent to signal that it’s OK to exit by closing its end of
109 // the pipe. 109 // the pipe.
110 CheckedReadFDAtEOF(ReadPipeFD()); 110 CheckedReadFileAtEOF(ReadPipeFD());
111 } 111 }
112 112
113 DISALLOW_COPY_AND_ASSIGN(ProcessReaderChild); 113 DISALLOW_COPY_AND_ASSIGN(ProcessReaderChild);
114 }; 114 };
115 115
116 TEST(ProcessReader, ChildBasic) { 116 TEST(ProcessReader, ChildBasic) {
117 ProcessReaderChild process_reader_child; 117 ProcessReaderChild process_reader_child;
118 process_reader_child.Run(); 118 process_reader_child.Run();
119 } 119 }
120 120
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 int read_fd = ReadPipeFD(); 427 int read_fd = ReadPipeFD();
428 428
429 // Build a map of all expected threads, keyed by each thread’s ID, and with 429 // Build a map of all expected threads, keyed by each thread’s ID, and with
430 // addresses that should lie somewhere within each thread’s stack as values. 430 // addresses that should lie somewhere within each thread’s stack as values.
431 // These IDs and addresses all come from the child process via the pipe. 431 // These IDs and addresses all come from the child process via the pipe.
432 ThreadMap thread_map; 432 ThreadMap thread_map;
433 for (size_t thread_index = 0; 433 for (size_t thread_index = 0;
434 thread_index < thread_count_ + 1; 434 thread_index < thread_count_ + 1;
435 ++thread_index) { 435 ++thread_index) {
436 uint64_t thread_id; 436 uint64_t thread_id;
437 CheckedReadFD(read_fd, &thread_id, sizeof(thread_id)); 437 CheckedReadFile(read_fd, &thread_id, sizeof(thread_id));
438 438
439 TestThreadPool::ThreadExpectation expectation; 439 TestThreadPool::ThreadExpectation expectation;
440 CheckedReadFD(read_fd, 440 CheckedReadFile(read_fd,
441 &expectation.stack_address, 441 &expectation.stack_address,
442 sizeof(expectation.stack_address)); 442 sizeof(expectation.stack_address));
443 CheckedReadFD(read_fd, 443 CheckedReadFile(read_fd,
444 &expectation.suspend_count, 444 &expectation.suspend_count,
445 sizeof(expectation.suspend_count)); 445 sizeof(expectation.suspend_count));
446 446
447 // There can’t be any duplicate thread IDs. 447 // There can’t be any duplicate thread IDs.
448 EXPECT_EQ(0u, thread_map.count(thread_id)); 448 EXPECT_EQ(0u, thread_map.count(thread_id));
449 449
450 thread_map[thread_id] = expectation; 450 thread_map[thread_id] = expectation;
451 } 451 }
452 452
453 const std::vector<ProcessReader::Thread>& threads = process_reader.Threads() ; 453 const std::vector<ProcessReader::Thread>& threads = process_reader.Threads() ;
454 454
455 // The child shouldn’t have any threads other than its main thread and the 455 // The child shouldn’t have any threads other than its main thread and the
456 // ones it created in its pool, so pass false for |tolerate_extra_threads|. 456 // ones it created in its pool, so pass false for |tolerate_extra_threads|.
457 ExpectSeveralThreads(&thread_map, threads, false); 457 ExpectSeveralThreads(&thread_map, threads, false);
458 } 458 }
459 459
460 void MachMultiprocessChild() override { 460 void MachMultiprocessChild() override {
461 TestThreadPool thread_pool; 461 TestThreadPool thread_pool;
462 ASSERT_NO_FATAL_FAILURE(thread_pool.StartThreads(thread_count_)); 462 ASSERT_NO_FATAL_FAILURE(thread_pool.StartThreads(thread_count_));
463 463
464 int write_fd = WritePipeFD(); 464 int write_fd = WritePipeFD();
465 465
466 // This thread isn’t part of the thread pool, but the parent will be able 466 // This thread isn’t part of the thread pool, but the parent will be able
467 // to inspect it. Write an entry for it. 467 // to inspect it. Write an entry for it.
468 uint64_t thread_id = PthreadToThreadID(pthread_self()); 468 uint64_t thread_id = PthreadToThreadID(pthread_self());
469 469
470 CheckedWriteFD(write_fd, &thread_id, sizeof(thread_id)); 470 CheckedWriteFile(write_fd, &thread_id, sizeof(thread_id));
471 471
472 TestThreadPool::ThreadExpectation expectation; 472 TestThreadPool::ThreadExpectation expectation;
473 expectation.stack_address = reinterpret_cast<mach_vm_address_t>(&thread_id); 473 expectation.stack_address = reinterpret_cast<mach_vm_address_t>(&thread_id);
474 expectation.suspend_count = 0; 474 expectation.suspend_count = 0;
475 475
476 CheckedWriteFD(write_fd, 476 CheckedWriteFile(write_fd,
477 &expectation.stack_address, 477 &expectation.stack_address,
478 sizeof(expectation.stack_address)); 478 sizeof(expectation.stack_address));
479 CheckedWriteFD(write_fd, 479 CheckedWriteFile(write_fd,
480 &expectation.suspend_count, 480 &expectation.suspend_count,
481 sizeof(expectation.suspend_count)); 481 sizeof(expectation.suspend_count));
482 482
483 // Write an entry for everything in the thread pool. 483 // Write an entry for everything in the thread pool.
484 for (size_t thread_index = 0; 484 for (size_t thread_index = 0;
485 thread_index < thread_count_; 485 thread_index < thread_count_;
486 ++thread_index) { 486 ++thread_index) {
487 uint64_t thread_id = 487 uint64_t thread_id =
488 thread_pool.GetThreadInfo(thread_index, &expectation); 488 thread_pool.GetThreadInfo(thread_index, &expectation);
489 489
490 CheckedWriteFD(write_fd, &thread_id, sizeof(thread_id)); 490 CheckedWriteFile(write_fd, &thread_id, sizeof(thread_id));
491 CheckedWriteFD(write_fd, 491 CheckedWriteFile(write_fd,
492 &expectation.stack_address, 492 &expectation.stack_address,
493 sizeof(expectation.stack_address)); 493 sizeof(expectation.stack_address));
494 CheckedWriteFD(write_fd, 494 CheckedWriteFile(write_fd,
495 &expectation.suspend_count, 495 &expectation.suspend_count,
496 sizeof(expectation.suspend_count)); 496 sizeof(expectation.suspend_count));
497 } 497 }
498 498
499 // Wait for the parent to signal that it’s OK to exit by closing its end of 499 // Wait for the parent to signal that it’s OK to exit by closing its end of
500 // the pipe. 500 // the pipe.
501 CheckedReadFDAtEOF(ReadPipeFD()); 501 CheckedReadFileAtEOF(ReadPipeFD());
502 } 502 }
503 503
504 size_t thread_count_; 504 size_t thread_count_;
505 505
506 DISALLOW_COPY_AND_ASSIGN(ProcessReaderThreadedChild); 506 DISALLOW_COPY_AND_ASSIGN(ProcessReaderThreadedChild);
507 }; 507 };
508 508
509 TEST(ProcessReader, ChildOneThread) { 509 TEST(ProcessReader, ChildOneThread) {
510 // The main thread plus zero child threads equals one thread. 510 // The main thread plus zero child threads equals one thread.
511 const size_t kChildThreads = 0; 511 const size_t kChildThreads = 0;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 const std::vector<ProcessReader::Module>& modules = 590 const std::vector<ProcessReader::Module>& modules =
591 process_reader.Modules(); 591 process_reader.Modules();
592 592
593 // There needs to be at least an entry for the main executable, for a dylib, 593 // There needs to be at least an entry for the main executable, for a dylib,
594 // and for dyld. 594 // and for dyld.
595 ASSERT_GE(modules.size(), 3u); 595 ASSERT_GE(modules.size(), 3u);
596 596
597 int read_fd = ReadPipeFD(); 597 int read_fd = ReadPipeFD();
598 598
599 uint32_t expect_modules; 599 uint32_t expect_modules;
600 CheckedReadFD(read_fd, &expect_modules, sizeof(expect_modules)); 600 CheckedReadFile(read_fd, &expect_modules, sizeof(expect_modules));
601 601
602 ASSERT_EQ(expect_modules, modules.size()); 602 ASSERT_EQ(expect_modules, modules.size());
603 603
604 for (size_t index = 0; index < modules.size(); ++index) { 604 for (size_t index = 0; index < modules.size(); ++index) {
605 SCOPED_TRACE(base::StringPrintf( 605 SCOPED_TRACE(base::StringPrintf(
606 "index %zu, name %s", index, modules[index].name.c_str())); 606 "index %zu, name %s", index, modules[index].name.c_str()));
607 607
608 uint32_t expect_name_length; 608 uint32_t expect_name_length;
609 CheckedReadFD( 609 CheckedReadFile(
610 read_fd, &expect_name_length, sizeof(expect_name_length)); 610 read_fd, &expect_name_length, sizeof(expect_name_length));
611 611
612 // The NUL terminator is not read. 612 // The NUL terminator is not read.
613 std::string expect_name(expect_name_length, '\0'); 613 std::string expect_name(expect_name_length, '\0');
614 CheckedReadFD(read_fd, &expect_name[0], expect_name_length); 614 CheckedReadFile(read_fd, &expect_name[0], expect_name_length);
615 EXPECT_EQ(expect_name, modules[index].name); 615 EXPECT_EQ(expect_name, modules[index].name);
616 616
617 mach_vm_address_t expect_address; 617 mach_vm_address_t expect_address;
618 CheckedReadFD(read_fd, &expect_address, sizeof(expect_address)); 618 CheckedReadFile(read_fd, &expect_address, sizeof(expect_address));
619 EXPECT_EQ(expect_address, modules[index].reader->Address()); 619 EXPECT_EQ(expect_address, modules[index].reader->Address());
620 620
621 if (index == 0 || index == modules.size() - 1) { 621 if (index == 0 || index == modules.size() - 1) {
622 // dyld didn’t load the main executable or itself, so it couldn’t record 622 // dyld didn’t load the main executable or itself, so it couldn’t record
623 // these timestamps, and they are reported as 0. 623 // these timestamps, and they are reported as 0.
624 EXPECT_EQ(0, modules[index].timestamp); 624 EXPECT_EQ(0, modules[index].timestamp);
625 } else { 625 } else {
626 // Hope that the module didn’t change on disk. 626 // Hope that the module didn’t change on disk.
627 struct stat stat_buf; 627 struct stat stat_buf;
628 int rv = stat(expect_name.c_str(), &stat_buf); 628 int rv = stat(expect_name.c_str(), &stat_buf);
(...skipping 12 matching lines...) Expand all
641 const struct dyld_all_image_infos* dyld_image_infos = 641 const struct dyld_all_image_infos* dyld_image_infos =
642 _dyld_get_all_image_infos(); 642 _dyld_get_all_image_infos();
643 643
644 uint32_t write_image_count = dyld_image_count; 644 uint32_t write_image_count = dyld_image_count;
645 if (dyld_image_infos->version >= 2) { 645 if (dyld_image_infos->version >= 2) {
646 // dyld_image_count doesn’t include an entry for dyld itself, but one will 646 // dyld_image_count doesn’t include an entry for dyld itself, but one will
647 // be written. 647 // be written.
648 ++write_image_count; 648 ++write_image_count;
649 } 649 }
650 650
651 CheckedWriteFD(write_fd, &write_image_count, sizeof(write_image_count)); 651 CheckedWriteFile(write_fd, &write_image_count, sizeof(write_image_count));
652 652
653 for (size_t index = 0; index < write_image_count; ++index) { 653 for (size_t index = 0; index < write_image_count; ++index) {
654 const char* dyld_image_name; 654 const char* dyld_image_name;
655 mach_vm_address_t dyld_image_address; 655 mach_vm_address_t dyld_image_address;
656 656
657 if (index < dyld_image_count) { 657 if (index < dyld_image_count) {
658 dyld_image_name = _dyld_get_image_name(index); 658 dyld_image_name = _dyld_get_image_name(index);
659 dyld_image_address = 659 dyld_image_address =
660 reinterpret_cast<mach_vm_address_t>(_dyld_get_image_header(index)); 660 reinterpret_cast<mach_vm_address_t>(_dyld_get_image_header(index));
661 } else { 661 } else {
662 dyld_image_name = "/usr/lib/dyld"; 662 dyld_image_name = "/usr/lib/dyld";
663 dyld_image_address = reinterpret_cast<mach_vm_address_t>( 663 dyld_image_address = reinterpret_cast<mach_vm_address_t>(
664 dyld_image_infos->dyldImageLoadAddress); 664 dyld_image_infos->dyldImageLoadAddress);
665 } 665 }
666 666
667 uint32_t dyld_image_name_length = strlen(dyld_image_name); 667 uint32_t dyld_image_name_length = strlen(dyld_image_name);
668 CheckedWriteFD( 668 CheckedWriteFile(
669 write_fd, &dyld_image_name_length, sizeof(dyld_image_name_length)); 669 write_fd, &dyld_image_name_length, sizeof(dyld_image_name_length));
670 670
671 // The NUL terminator is not written. 671 // The NUL terminator is not written.
672 CheckedWriteFD(write_fd, dyld_image_name, dyld_image_name_length); 672 CheckedWriteFile(write_fd, dyld_image_name, dyld_image_name_length);
673 673
674 CheckedWriteFD(write_fd, &dyld_image_address, sizeof(dyld_image_address)); 674 CheckedWriteFile(
675 write_fd, &dyld_image_address, sizeof(dyld_image_address));
675 } 676 }
676 677
677 // Wait for the parent to signal that it’s OK to exit by closing its end of 678 // Wait for the parent to signal that it’s OK to exit by closing its end of
678 // the pipe. 679 // the pipe.
679 CheckedReadFDAtEOF(ReadPipeFD()); 680 CheckedReadFileAtEOF(ReadPipeFD());
680 } 681 }
681 682
682 DISALLOW_COPY_AND_ASSIGN(ProcessReaderModulesChild); 683 DISALLOW_COPY_AND_ASSIGN(ProcessReaderModulesChild);
683 }; 684 };
684 685
685 TEST(ProcessReader, ChildModules) { 686 TEST(ProcessReader, ChildModules) {
686 ProcessReaderModulesChild process_reader_modules_child; 687 ProcessReaderModulesChild process_reader_modules_child;
687 process_reader_modules_child.Run(); 688 process_reader_modules_child.Run();
688 } 689 }
689 690
690 } // namespace 691 } // namespace
691 } // namespace test 692 } // namespace test
692 } // namespace crashpad 693 } // namespace crashpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698