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