OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/debug/stack_trace.h" | 5 #include "base/debug/stack_trace.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <signal.h> | 9 #include <signal.h> |
10 #include <stdio.h> | 10 #include <stdio.h> |
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
505 } | 505 } |
506 | 506 |
507 // Returns a O_RDONLY file descriptor for |file_path| if it was opened | 507 // Returns a O_RDONLY file descriptor for |file_path| if it was opened |
508 // sucessfully during the initialization. The file is repositioned at | 508 // sucessfully during the initialization. The file is repositioned at |
509 // offset 0. | 509 // offset 0. |
510 // IMPORTANT: This function must be async-signal-safe because it can be | 510 // IMPORTANT: This function must be async-signal-safe because it can be |
511 // called from a signal handler (symbolizing stack frames for a crash). | 511 // called from a signal handler (symbolizing stack frames for a crash). |
512 int GetFileDescriptor(const char* file_path) { | 512 int GetFileDescriptor(const char* file_path) { |
513 int fd = -1; | 513 int fd = -1; |
514 | 514 |
515 #if !defined(NDEBUG) | 515 #if !defined(OFFICIAL_BUILD) |
516 if (file_path) { | 516 if (file_path) { |
517 // The assumption here is that iterating over std::map<std::string, int> | 517 // The assumption here is that iterating over std::map<std::string, int> |
518 // using a const_iterator does not allocate dynamic memory, hense it is | 518 // using a const_iterator does not allocate dynamic memory, hense it is |
519 // async-signal-safe. | 519 // async-signal-safe. |
520 std::map<std::string, int>::const_iterator it; | 520 std::map<std::string, int>::const_iterator it; |
521 for (it = modules_.begin(); it != modules_.end(); ++it) { | 521 for (it = modules_.begin(); it != modules_.end(); ++it) { |
522 if (strcmp((it->first).c_str(), file_path) == 0) { | 522 if (strcmp((it->first).c_str(), file_path) == 0) { |
523 // POSIX.1-2004 requires an implementation to guarantee that dup() | 523 // POSIX.1-2004 requires an implementation to guarantee that dup() |
524 // is async-signal-safe. | 524 // is async-signal-safe. |
525 fd = dup(it->second); | 525 fd = dup(it->second); |
526 break; | 526 break; |
527 } | 527 } |
528 } | 528 } |
529 // POSIX.1-2004 requires an implementation to guarantee that lseek() | 529 // POSIX.1-2004 requires an implementation to guarantee that lseek() |
530 // is async-signal-safe. | 530 // is async-signal-safe. |
531 if (fd >= 0 && lseek(fd, 0, SEEK_SET) < 0) { | 531 if (fd >= 0 && lseek(fd, 0, SEEK_SET) < 0) { |
532 // Failed to seek. | 532 // Failed to seek. |
533 fd = -1; | 533 fd = -1; |
534 } | 534 } |
535 } | 535 } |
536 #endif // !defined(NDEBUG) | 536 #endif // !defined(OFFICIAL_BUILD) |
537 | 537 |
538 return fd; | 538 return fd; |
539 } | 539 } |
540 | 540 |
541 // Searches for the object file (from /proc/self/maps) that contains | 541 // Searches for the object file (from /proc/self/maps) that contains |
542 // the specified pc. If found, sets |start_address| to the start address | 542 // the specified pc. If found, sets |start_address| to the start address |
543 // of where this object file is mapped in memory, sets the module base | 543 // of where this object file is mapped in memory, sets the module base |
544 // address into |base_address|, copies the object file name into | 544 // address into |base_address|, copies the object file name into |
545 // |out_file_name|, and attempts to open the object file. If the object | 545 // |out_file_name|, and attempts to open the object file. If the object |
546 // file is opened successfully, returns the file descriptor. Otherwise, | 546 // file is opened successfully, returns the file descriptor. Otherwise, |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
612 return false; | 612 return false; |
613 } | 613 } |
614 | 614 |
615 is_initialized_ = true; | 615 is_initialized_ = true; |
616 return true; | 616 return true; |
617 } | 617 } |
618 | 618 |
619 // Opens all object files and caches their file descriptors. | 619 // Opens all object files and caches their file descriptors. |
620 void OpenSymbolFiles() { | 620 void OpenSymbolFiles() { |
621 // Pre-opening and caching the file descriptors of all loaded modules is | 621 // Pre-opening and caching the file descriptors of all loaded modules is |
622 // not considered safe for retail builds. Hence it is only done in debug | 622 // not safe for production builds. Hence it is only done in non-official |
623 // builds. For more details, take a look at: http://crbug.com/341966 | 623 // builds. For more details, take a look at: http://crbug.com/341966. |
624 // Enabling this to release mode would require approval from the security | 624 #if !defined(OFFICIAL_BUILD) |
625 // team. | |
626 #if !defined(NDEBUG) | |
627 // Open the object files for all read-only executable regions and cache | 625 // Open the object files for all read-only executable regions and cache |
628 // their file descriptors. | 626 // their file descriptors. |
629 std::vector<MappedMemoryRegion>::const_iterator it; | 627 std::vector<MappedMemoryRegion>::const_iterator it; |
630 for (it = regions_.begin(); it != regions_.end(); ++it) { | 628 for (it = regions_.begin(); it != regions_.end(); ++it) { |
631 const MappedMemoryRegion& region = *it; | 629 const MappedMemoryRegion& region = *it; |
632 // Only interesed in read-only executable regions. | 630 // Only interesed in read-only executable regions. |
633 if ((region.permissions & MappedMemoryRegion::READ) == | 631 if ((region.permissions & MappedMemoryRegion::READ) == |
634 MappedMemoryRegion::READ && | 632 MappedMemoryRegion::READ && |
635 (region.permissions & MappedMemoryRegion::WRITE) == 0 && | 633 (region.permissions & MappedMemoryRegion::WRITE) == 0 && |
636 (region.permissions & MappedMemoryRegion::EXECUTE) == | 634 (region.permissions & MappedMemoryRegion::EXECUTE) == |
(...skipping 11 matching lines...) Expand all Loading... |
648 int fd = open(region.path.c_str(), O_RDONLY | O_CLOEXEC); | 646 int fd = open(region.path.c_str(), O_RDONLY | O_CLOEXEC); |
649 if (fd >= 0) { | 647 if (fd >= 0) { |
650 modules_.insert(std::make_pair(region.path, fd)); | 648 modules_.insert(std::make_pair(region.path, fd)); |
651 } else { | 649 } else { |
652 LOG(WARNING) << "Failed to open file: " << region.path | 650 LOG(WARNING) << "Failed to open file: " << region.path |
653 << "\n Error: " << strerror(errno); | 651 << "\n Error: " << strerror(errno); |
654 } | 652 } |
655 } | 653 } |
656 } | 654 } |
657 } | 655 } |
658 #endif // !defined(NDEBUG) | 656 #endif // !defined(OFFICIAL_BUILD) |
659 } | 657 } |
660 | 658 |
661 // Initializes and installs the symbolization callback. | 659 // Initializes and installs the symbolization callback. |
662 void Init() { | 660 void Init() { |
663 if (CacheMemoryRegions()) { | 661 if (CacheMemoryRegions()) { |
664 OpenSymbolFiles(); | 662 OpenSymbolFiles(); |
665 google::InstallSymbolizeOpenObjectFileCallback( | 663 google::InstallSymbolizeOpenObjectFileCallback( |
666 &OpenObjectFileContainingPc); | 664 &OpenObjectFileContainingPc); |
667 } | 665 } |
668 } | 666 } |
669 | 667 |
670 // Unregister symbolization callback. | 668 // Unregister symbolization callback. |
671 void UnregisterCallback() { | 669 void UnregisterCallback() { |
672 if (is_initialized_) { | 670 if (is_initialized_) { |
673 google::InstallSymbolizeOpenObjectFileCallback(NULL); | 671 google::InstallSymbolizeOpenObjectFileCallback(NULL); |
674 is_initialized_ = false; | 672 is_initialized_ = false; |
675 } | 673 } |
676 } | 674 } |
677 | 675 |
678 // Closes all file descriptors owned by this instance. | 676 // Closes all file descriptors owned by this instance. |
679 void CloseObjectFiles() { | 677 void CloseObjectFiles() { |
680 #if !defined(NDEBUG) | 678 #if !defined(OFFICIAL_BUILD) |
681 std::map<std::string, int>::iterator it; | 679 std::map<std::string, int>::iterator it; |
682 for (it = modules_.begin(); it != modules_.end(); ++it) { | 680 for (it = modules_.begin(); it != modules_.end(); ++it) { |
683 int ret = IGNORE_EINTR(close(it->second)); | 681 int ret = IGNORE_EINTR(close(it->second)); |
684 DCHECK(!ret); | 682 DCHECK(!ret); |
685 it->second = -1; | 683 it->second = -1; |
686 } | 684 } |
687 modules_.clear(); | 685 modules_.clear(); |
688 #endif // !defined(NDEBUG) | 686 #endif // !defined(OFFICIAL_BUILD) |
689 } | 687 } |
690 | 688 |
691 // Set to true upon successful initialization. | 689 // Set to true upon successful initialization. |
692 bool is_initialized_; | 690 bool is_initialized_; |
693 | 691 |
694 #if !defined(NDEBUG) | 692 #if !defined(OFFICIAL_BUILD) |
695 // Mapping from file name to file descriptor. Includes file descriptors | 693 // Mapping from file name to file descriptor. Includes file descriptors |
696 // for all successfully opened object files and the file descriptor for | 694 // for all successfully opened object files and the file descriptor for |
697 // /proc/self/maps. This code is not safe for release builds so | 695 // /proc/self/maps. This code is not safe for production builds. |
698 // this is only done for DEBUG builds. | |
699 std::map<std::string, int> modules_; | 696 std::map<std::string, int> modules_; |
700 #endif // !defined(NDEBUG) | 697 #endif // !defined(OFFICIAL_BUILD) |
701 | 698 |
702 // Cache for the process memory regions. Produced by parsing the contents | 699 // Cache for the process memory regions. Produced by parsing the contents |
703 // of /proc/self/maps cache. | 700 // of /proc/self/maps cache. |
704 std::vector<MappedMemoryRegion> regions_; | 701 std::vector<MappedMemoryRegion> regions_; |
705 | 702 |
706 DISALLOW_COPY_AND_ASSIGN(SandboxSymbolizeHelper); | 703 DISALLOW_COPY_AND_ASSIGN(SandboxSymbolizeHelper); |
707 }; | 704 }; |
708 #endif // USE_SYMBOLIZE | 705 #endif // USE_SYMBOLIZE |
709 | 706 |
710 bool EnableInProcessStackDumpingForSandbox() { | 707 bool EnableInProcessStackDumpingForSandbox() { |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
838 *ptr = *start; | 835 *ptr = *start; |
839 *start++ = ch; | 836 *start++ = ch; |
840 } | 837 } |
841 return buf; | 838 return buf; |
842 } | 839 } |
843 | 840 |
844 } // namespace internal | 841 } // namespace internal |
845 | 842 |
846 } // namespace debug | 843 } // namespace debug |
847 } // namespace base | 844 } // namespace base |
OLD | NEW |