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 <stddef.h> | 10 #include <stddef.h> |
11 #include <stdint.h> | 11 #include <stdint.h> |
12 #include <stdio.h> | 12 #include <stdio.h> |
13 #include <stdlib.h> | 13 #include <stdlib.h> |
14 #include <sys/param.h> | 14 #include <sys/param.h> |
15 #include <sys/stat.h> | 15 #include <sys/stat.h> |
16 #include <sys/types.h> | 16 #include <sys/types.h> |
17 #include <unistd.h> | 17 #include <unistd.h> |
18 | 18 |
19 #include <algorithm> | 19 #include <algorithm> |
20 #include <map> | 20 #include <map> |
21 #include <memory> | 21 #include <memory> |
22 #include <ostream> | 22 #include <ostream> |
23 #include <string> | 23 #include <string> |
24 #include <vector> | 24 #include <vector> |
25 | 25 |
26 #if !defined(USE_SYMBOLIZE) | 26 #if !defined(USE_SYMBOLIZE) |
27 #include <cxxabi.h> | 27 #include <cxxabi.h> |
28 #endif | 28 #endif |
29 #if !defined(__UCLIBC__) | 29 #if !defined(__UCLIBC__) && !defined(_AIX) |
30 #include <execinfo.h> | 30 #include <execinfo.h> |
31 #endif | 31 #endif |
32 | 32 |
33 #if defined(OS_MACOSX) | 33 #if defined(OS_MACOSX) |
34 #include <AvailabilityMacros.h> | 34 #include <AvailabilityMacros.h> |
35 #endif | 35 #endif |
36 | 36 |
37 #if defined(OS_LINUX) | 37 #if defined(OS_LINUX) |
38 #include "base/debug/proc_maps_linux.h" | 38 #include "base/debug/proc_maps_linux.h" |
39 #endif | 39 #endif |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 #if !defined(USE_SYMBOLIZE) | 73 #if !defined(USE_SYMBOLIZE) |
74 // Demangles C++ symbols in the given text. Example: | 74 // Demangles C++ symbols in the given text. Example: |
75 // | 75 // |
76 // "out/Debug/base_unittests(_ZN10StackTraceC1Ev+0x20) [0x817778c]" | 76 // "out/Debug/base_unittests(_ZN10StackTraceC1Ev+0x20) [0x817778c]" |
77 // => | 77 // => |
78 // "out/Debug/base_unittests(StackTrace::StackTrace()+0x20) [0x817778c]" | 78 // "out/Debug/base_unittests(StackTrace::StackTrace()+0x20) [0x817778c]" |
79 void DemangleSymbols(std::string* text) { | 79 void DemangleSymbols(std::string* text) { |
80 // Note: code in this function is NOT async-signal safe (std::string uses | 80 // Note: code in this function is NOT async-signal safe (std::string uses |
81 // malloc internally). | 81 // malloc internally). |
82 | 82 |
83 #if !defined(__UCLIBC__) | 83 #if !defined(__UCLIBC__) && !defined(_AIX) |
84 | |
85 std::string::size_type search_from = 0; | 84 std::string::size_type search_from = 0; |
86 while (search_from < text->size()) { | 85 while (search_from < text->size()) { |
87 // Look for the start of a mangled symbol, from search_from. | 86 // Look for the start of a mangled symbol, from search_from. |
88 std::string::size_type mangled_start = | 87 std::string::size_type mangled_start = |
89 text->find(kMangledSymbolPrefix, search_from); | 88 text->find(kMangledSymbolPrefix, search_from); |
90 if (mangled_start == std::string::npos) { | 89 if (mangled_start == std::string::npos) { |
91 break; // Mangled symbol not found. | 90 break; // Mangled symbol not found. |
92 } | 91 } |
93 | 92 |
94 // Look for the end of the mangled symbol. | 93 // Look for the end of the mangled symbol. |
(...skipping 14 matching lines...) Expand all Loading... |
109 text->erase(mangled_start, mangled_end - mangled_start); | 108 text->erase(mangled_start, mangled_end - mangled_start); |
110 // Insert the demangled symbol. | 109 // Insert the demangled symbol. |
111 text->insert(mangled_start, demangled_symbol.get()); | 110 text->insert(mangled_start, demangled_symbol.get()); |
112 // Next time, we'll start right after the demangled symbol we inserted. | 111 // Next time, we'll start right after the demangled symbol we inserted. |
113 search_from = mangled_start + strlen(demangled_symbol.get()); | 112 search_from = mangled_start + strlen(demangled_symbol.get()); |
114 } else { | 113 } else { |
115 // Failed to demangle. Retry after the "_Z" we just found. | 114 // Failed to demangle. Retry after the "_Z" we just found. |
116 search_from = mangled_start + 2; | 115 search_from = mangled_start + 2; |
117 } | 116 } |
118 } | 117 } |
119 #endif // !defined(__UCLIBC__) | 118 #endif // !defined(__UCLIBC__) && !defined(_AIX) |
120 } | 119 } |
121 #endif // !defined(USE_SYMBOLIZE) | 120 #endif // !defined(USE_SYMBOLIZE) |
122 | 121 |
123 class BacktraceOutputHandler { | 122 class BacktraceOutputHandler { |
124 public: | 123 public: |
125 virtual void HandleOutput(const char* output) = 0; | 124 virtual void HandleOutput(const char* output) = 0; |
126 | 125 |
127 protected: | 126 protected: |
128 virtual ~BacktraceOutputHandler() {} | 127 virtual ~BacktraceOutputHandler() {} |
129 }; | 128 }; |
130 | 129 |
131 #if !defined(__UCLIBC__) | 130 #if !defined(__UCLIBC__) && !defined(_AIX) |
132 void OutputPointer(void* pointer, BacktraceOutputHandler* handler) { | 131 void OutputPointer(void* pointer, BacktraceOutputHandler* handler) { |
133 // This should be more than enough to store a 64-bit number in hex: | 132 // This should be more than enough to store a 64-bit number in hex: |
134 // 16 hex digits + 1 for null-terminator. | 133 // 16 hex digits + 1 for null-terminator. |
135 char buf[17] = { '\0' }; | 134 char buf[17] = { '\0' }; |
136 handler->HandleOutput("0x"); | 135 handler->HandleOutput("0x"); |
137 internal::itoa_r(reinterpret_cast<intptr_t>(pointer), | 136 internal::itoa_r(reinterpret_cast<intptr_t>(pointer), |
138 buf, sizeof(buf), 16, 12); | 137 buf, sizeof(buf), 16, 12); |
139 handler->HandleOutput(buf); | 138 handler->HandleOutput(buf); |
140 } | 139 } |
141 | 140 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 | 197 |
199 if (!printed) { | 198 if (!printed) { |
200 for (size_t i = 0; i < size; ++i) { | 199 for (size_t i = 0; i < size; ++i) { |
201 handler->HandleOutput(" ["); | 200 handler->HandleOutput(" ["); |
202 OutputPointer(trace[i], handler); | 201 OutputPointer(trace[i], handler); |
203 handler->HandleOutput("]\n"); | 202 handler->HandleOutput("]\n"); |
204 } | 203 } |
205 } | 204 } |
206 #endif // defined(USE_SYMBOLIZE) | 205 #endif // defined(USE_SYMBOLIZE) |
207 } | 206 } |
208 #endif // !defined(__UCLIBC__) | 207 #endif // !defined(__UCLIBC__) && !defined(_AIX) |
209 | 208 |
210 void PrintToStderr(const char* output) { | 209 void PrintToStderr(const char* output) { |
211 // NOTE: This code MUST be async-signal safe (it's used by in-process | 210 // NOTE: This code MUST be async-signal safe (it's used by in-process |
212 // stack dumping signal handler). NO malloc or stdio is allowed here. | 211 // stack dumping signal handler). NO malloc or stdio is allowed here. |
213 ignore_result(HANDLE_EINTR(write(STDERR_FILENO, output, strlen(output)))); | 212 ignore_result(HANDLE_EINTR(write(STDERR_FILENO, output, strlen(output)))); |
214 } | 213 } |
215 | 214 |
216 void StackDumpSignalHandler(int signal, siginfo_t* info, void* void_context) { | 215 void StackDumpSignalHandler(int signal, siginfo_t* info, void* void_context) { |
217 // NOTE: This code MUST be async-signal safe. | 216 // NOTE: This code MUST be async-signal safe. |
218 // NO malloc or stdio is allowed here. | 217 // NO malloc or stdio is allowed here. |
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
715 success &= (sigaction(SIGSYS, &action, NULL) == 0); | 714 success &= (sigaction(SIGSYS, &action, NULL) == 0); |
716 #endif // !defined(OS_LINUX) | 715 #endif // !defined(OS_LINUX) |
717 | 716 |
718 return success; | 717 return success; |
719 } | 718 } |
720 | 719 |
721 StackTrace::StackTrace(size_t count) { | 720 StackTrace::StackTrace(size_t count) { |
722 // NOTE: This code MUST be async-signal safe (it's used by in-process | 721 // NOTE: This code MUST be async-signal safe (it's used by in-process |
723 // stack dumping signal handler). NO malloc or stdio is allowed here. | 722 // stack dumping signal handler). NO malloc or stdio is allowed here. |
724 | 723 |
725 #if !defined(__UCLIBC__) | 724 #if !defined(__UCLIBC__) && !defined(_AIX) |
726 count = std::min(arraysize(trace_), count); | 725 count = std::min(arraysize(trace_), count); |
727 | 726 |
728 // Though the backtrace API man page does not list any possible negative | 727 // Though the backtrace API man page does not list any possible negative |
729 // return values, we take no chance. | 728 // return values, we take no chance. |
730 count_ = base::saturated_cast<size_t>(backtrace(trace_, count)); | 729 count_ = base::saturated_cast<size_t>(backtrace(trace_, count)); |
731 #else | 730 #else |
732 count_ = 0; | 731 count_ = 0; |
733 #endif | 732 #endif |
734 } | 733 } |
735 | 734 |
736 void StackTrace::Print() const { | 735 void StackTrace::Print() const { |
737 // NOTE: This code MUST be async-signal safe (it's used by in-process | 736 // NOTE: This code MUST be async-signal safe (it's used by in-process |
738 // stack dumping signal handler). NO malloc or stdio is allowed here. | 737 // stack dumping signal handler). NO malloc or stdio is allowed here. |
739 | 738 |
740 #if !defined(__UCLIBC__) | 739 #if !defined(__UCLIBC__) && !defined(_AIX) |
741 PrintBacktraceOutputHandler handler; | 740 PrintBacktraceOutputHandler handler; |
742 ProcessBacktrace(trace_, count_, &handler); | 741 ProcessBacktrace(trace_, count_, &handler); |
743 #endif | 742 #endif |
744 } | 743 } |
745 | 744 |
746 #if !defined(__UCLIBC__) | 745 #if !defined(__UCLIBC__) && !defined(_AIX) |
747 void StackTrace::OutputToStream(std::ostream* os) const { | 746 void StackTrace::OutputToStream(std::ostream* os) const { |
748 StreamBacktraceOutputHandler handler(os); | 747 StreamBacktraceOutputHandler handler(os); |
749 ProcessBacktrace(trace_, count_, &handler); | 748 ProcessBacktrace(trace_, count_, &handler); |
750 } | 749 } |
751 #endif | 750 #endif |
752 | 751 |
753 namespace internal { | 752 namespace internal { |
754 | 753 |
755 // NOTE: code from sandbox/linux/seccomp-bpf/demo.cc. | 754 // NOTE: code from sandbox/linux/seccomp-bpf/demo.cc. |
756 char* itoa_r(intptr_t i, char* buf, size_t sz, int base, size_t padding) { | 755 char* itoa_r(intptr_t i, char* buf, size_t sz, int base, size_t padding) { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
811 *ptr = *start; | 810 *ptr = *start; |
812 *start++ = ch; | 811 *start++ = ch; |
813 } | 812 } |
814 return buf; | 813 return buf; |
815 } | 814 } |
816 | 815 |
817 } // namespace internal | 816 } // namespace internal |
818 | 817 |
819 } // namespace debug | 818 } // namespace debug |
820 } // namespace base | 819 } // namespace base |
OLD | NEW |