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

Side by Side Diff: base/debug/stack_trace_posix.cc

Issue 18656004: Added a new SafeSPrintf() function that implements snprintf() in an async-safe-fashion (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed Jeffrey's comments Created 7 years, 4 months 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 | Annotate | Revision Log
OLDNEW
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 <execinfo.h> 8 #include <execinfo.h>
9 #include <fcntl.h> 9 #include <fcntl.h>
10 #include <signal.h> 10 #include <signal.h>
11 #include <stdio.h> 11 #include <stdio.h>
12 #include <stdlib.h> 12 #include <stdlib.h>
13 #include <sys/param.h> 13 #include <sys/param.h>
14 #include <sys/stat.h> 14 #include <sys/stat.h>
15 #include <sys/types.h> 15 #include <sys/types.h>
16 #include <unistd.h> 16 #include <unistd.h>
17 17
18 #include <ostream> 18 #include <ostream>
19 19
20 #if defined(__GLIBCXX__) 20 #if defined(__GLIBCXX__)
21 #include <cxxabi.h> 21 #include <cxxabi.h>
22 #endif 22 #endif
23 23
24 #if defined(OS_MACOSX) 24 #if defined(OS_MACOSX)
25 #include <AvailabilityMacros.h> 25 #include <AvailabilityMacros.h>
26 #endif 26 #endif
27 27
28 #include "base/basictypes.h" 28 #include "base/basictypes.h"
29 #include "base/debug/debugger.h" 29 #include "base/debug/debugger.h"
30 #include "base/debug/format.h"
30 #include "base/logging.h" 31 #include "base/logging.h"
31 #include "base/memory/scoped_ptr.h" 32 #include "base/memory/scoped_ptr.h"
32 #include "base/posix/eintr_wrapper.h" 33 #include "base/posix/eintr_wrapper.h"
33 #include "base/strings/string_number_conversions.h" 34 #include "base/strings/string_number_conversions.h"
34 35
35 #if defined(USE_SYMBOLIZE) 36 #if defined(USE_SYMBOLIZE)
36 #include "base/third_party/symbolize/symbolize.h" 37 #include "base/third_party/symbolize/symbolize.h"
37 #endif 38 #endif
38 39
39 namespace base { 40 namespace base {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 106
106 class BacktraceOutputHandler { 107 class BacktraceOutputHandler {
107 public: 108 public:
108 virtual void HandleOutput(const char* output) = 0; 109 virtual void HandleOutput(const char* output) = 0;
109 110
110 protected: 111 protected:
111 virtual ~BacktraceOutputHandler() {} 112 virtual ~BacktraceOutputHandler() {}
112 }; 113 };
113 114
114 void OutputPointer(void* pointer, BacktraceOutputHandler* handler) { 115 void OutputPointer(void* pointer, BacktraceOutputHandler* handler) {
115 char buf[1024] = { '\0' }; 116 char buf[30];
116 handler->HandleOutput(" [0x"); 117 Format(buf, " [0x%12x]", reinterpret_cast<intptr_t>(pointer));
117 internal::itoa_r(reinterpret_cast<intptr_t>(pointer),
118 buf, sizeof(buf), 16, 12);
119 handler->HandleOutput(buf); 118 handler->HandleOutput(buf);
120 handler->HandleOutput("]");
121 } 119 }
122 120
123 void ProcessBacktrace(void *const *trace, 121 void ProcessBacktrace(void *const *trace,
124 int size, 122 int size,
125 BacktraceOutputHandler* handler) { 123 BacktraceOutputHandler* handler) {
126 // NOTE: This code MUST be async-signal safe (it's used by in-process 124 // NOTE: This code MUST be async-signal safe (it's used by in-process
127 // stack dumping signal handler). NO malloc or stdio is allowed here. 125 // stack dumping signal handler). NO malloc or stdio is allowed here.
128 126
129 #if defined(USE_SYMBOLIZE) 127 #if defined(USE_SYMBOLIZE)
130 for (int i = 0; i < size; ++i) { 128 for (int i = 0; i < size; ++i) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 // NOTE: This code MUST be async-signal safe. 179 // NOTE: This code MUST be async-signal safe.
182 // NO malloc or stdio is allowed here. 180 // NO malloc or stdio is allowed here.
183 181
184 // Record the fact that we are in the signal handler now, so that the rest 182 // Record the fact that we are in the signal handler now, so that the rest
185 // of StackTrace can behave in an async-signal-safe manner. 183 // of StackTrace can behave in an async-signal-safe manner.
186 in_signal_handler = 1; 184 in_signal_handler = 1;
187 185
188 if (BeingDebugged()) 186 if (BeingDebugged())
189 BreakDebugger(); 187 BreakDebugger();
190 188
191 PrintToStderr("Received signal "); 189 char buf[80];
192 char buf[1024] = { 0 }; 190 Format(buf, "Received signal %d ", signal);
193 internal::itoa_r(signal, buf, sizeof(buf), 10, 0);
194 PrintToStderr(buf); 191 PrintToStderr(buf);
195 if (signal == SIGBUS) { 192 if (signal == SIGBUS) {
196 if (info->si_code == BUS_ADRALN) 193 if (info->si_code == BUS_ADRALN)
197 PrintToStderr(" BUS_ADRALN "); 194 PrintToStderr("BUS_ADRALN ");
198 else if (info->si_code == BUS_ADRERR) 195 else if (info->si_code == BUS_ADRERR)
199 PrintToStderr(" BUS_ADRERR "); 196 PrintToStderr("BUS_ADRERR ");
200 else if (info->si_code == BUS_OBJERR) 197 else if (info->si_code == BUS_OBJERR)
201 PrintToStderr(" BUS_OBJERR "); 198 PrintToStderr("BUS_OBJERR ");
202 else 199 else
203 PrintToStderr(" <unknown> "); 200 PrintToStderr("<unknown> ");
204 } else if (signal == SIGFPE) { 201 } else if (signal == SIGFPE) {
205 if (info->si_code == FPE_FLTDIV) 202 if (info->si_code == FPE_FLTDIV)
206 PrintToStderr(" FPE_FLTDIV "); 203 PrintToStderr("FPE_FLTDIV ");
207 else if (info->si_code == FPE_FLTINV) 204 else if (info->si_code == FPE_FLTINV)
208 PrintToStderr(" FPE_FLTINV "); 205 PrintToStderr("FPE_FLTINV ");
209 else if (info->si_code == FPE_FLTOVF) 206 else if (info->si_code == FPE_FLTOVF)
210 PrintToStderr(" FPE_FLTOVF "); 207 PrintToStderr("FPE_FLTOVF ");
211 else if (info->si_code == FPE_FLTRES) 208 else if (info->si_code == FPE_FLTRES)
212 PrintToStderr(" FPE_FLTRES "); 209 PrintToStderr("FPE_FLTRES ");
213 else if (info->si_code == FPE_FLTSUB) 210 else if (info->si_code == FPE_FLTSUB)
214 PrintToStderr(" FPE_FLTSUB "); 211 PrintToStderr("FPE_FLTSUB ");
215 else if (info->si_code == FPE_FLTUND) 212 else if (info->si_code == FPE_FLTUND)
216 PrintToStderr(" FPE_FLTUND "); 213 PrintToStderr("FPE_FLTUND ");
217 else if (info->si_code == FPE_INTDIV) 214 else if (info->si_code == FPE_INTDIV)
218 PrintToStderr(" FPE_INTDIV "); 215 PrintToStderr("FPE_INTDIV ");
219 else if (info->si_code == FPE_INTOVF) 216 else if (info->si_code == FPE_INTOVF)
220 PrintToStderr(" FPE_INTOVF "); 217 PrintToStderr("FPE_INTOVF ");
221 else 218 else
222 PrintToStderr(" <unknown> "); 219 PrintToStderr("<unknown> ");
223 } else if (signal == SIGILL) { 220 } else if (signal == SIGILL) {
224 if (info->si_code == ILL_BADSTK) 221 if (info->si_code == ILL_BADSTK)
225 PrintToStderr(" ILL_BADSTK "); 222 PrintToStderr("ILL_BADSTK ");
226 else if (info->si_code == ILL_COPROC) 223 else if (info->si_code == ILL_COPROC)
227 PrintToStderr(" ILL_COPROC "); 224 PrintToStderr("ILL_COPROC ");
228 else if (info->si_code == ILL_ILLOPN) 225 else if (info->si_code == ILL_ILLOPN)
229 PrintToStderr(" ILL_ILLOPN "); 226 PrintToStderr("ILL_ILLOPN ");
230 else if (info->si_code == ILL_ILLADR) 227 else if (info->si_code == ILL_ILLADR)
231 PrintToStderr(" ILL_ILLADR "); 228 PrintToStderr("ILL_ILLADR ");
232 else if (info->si_code == ILL_ILLTRP) 229 else if (info->si_code == ILL_ILLTRP)
233 PrintToStderr(" ILL_ILLTRP "); 230 PrintToStderr("ILL_ILLTRP ");
234 else if (info->si_code == ILL_PRVOPC) 231 else if (info->si_code == ILL_PRVOPC)
235 PrintToStderr(" ILL_PRVOPC "); 232 PrintToStderr("ILL_PRVOPC ");
236 else if (info->si_code == ILL_PRVREG) 233 else if (info->si_code == ILL_PRVREG)
237 PrintToStderr(" ILL_PRVREG "); 234 PrintToStderr("ILL_PRVREG ");
238 else 235 else
239 PrintToStderr(" <unknown> "); 236 PrintToStderr("<unknown> ");
240 } else if (signal == SIGSEGV) { 237 } else if (signal == SIGSEGV) {
241 if (info->si_code == SEGV_MAPERR) 238 if (info->si_code == SEGV_MAPERR)
242 PrintToStderr(" SEGV_MAPERR "); 239 PrintToStderr("SEGV_MAPERR ");
243 else if (info->si_code == SEGV_ACCERR) 240 else if (info->si_code == SEGV_ACCERR)
244 PrintToStderr(" SEGV_ACCERR "); 241 PrintToStderr("SEGV_ACCERR ");
245 else 242 else
246 PrintToStderr(" <unknown> "); 243 PrintToStderr("<unknown> ");
247 } 244 }
248 if (signal == SIGBUS || signal == SIGFPE || 245 if (signal == SIGBUS || signal == SIGFPE ||
249 signal == SIGILL || signal == SIGSEGV) { 246 signal == SIGILL || signal == SIGSEGV) {
250 internal::itoa_r(reinterpret_cast<intptr_t>(info->si_addr), 247 Format(buf, "%12x", reinterpret_cast<intptr_t>(info->si_addr));
251 buf, sizeof(buf), 16, 12);
252 PrintToStderr(buf); 248 PrintToStderr(buf);
253 } 249 }
254 PrintToStderr("\n"); 250 PrintToStderr("\n");
255 251
256 debug::StackTrace().PrintBacktrace(); 252 debug::StackTrace().PrintBacktrace();
257 253
258 #if defined(OS_LINUX) 254 #if defined(OS_LINUX)
259 #if ARCH_CPU_X86_FAMILY 255 #if ARCH_CPU_X86_FAMILY
260 ucontext_t* context = reinterpret_cast<ucontext_t*>(void_context); 256 ucontext_t* context = reinterpret_cast<ucontext_t*>(void_context);
261 const struct { 257 const struct {
262 const char* label; 258 const char* label;
263 greg_t value; 259 greg_t value;
264 } registers[] = { 260 } registers[] = {
265 #if ARCH_CPU_32_BITS 261 #if ARCH_CPU_32_BITS
266 { " gs: ", context->uc_mcontext.gregs[REG_GS] }, 262 { "gs", context->uc_mcontext.gregs[REG_GS] },
267 { " fs: ", context->uc_mcontext.gregs[REG_FS] }, 263 { "fs", context->uc_mcontext.gregs[REG_FS] },
268 { " es: ", context->uc_mcontext.gregs[REG_ES] }, 264 { "es", context->uc_mcontext.gregs[REG_ES] },
269 { " ds: ", context->uc_mcontext.gregs[REG_DS] }, 265 { "ds", context->uc_mcontext.gregs[REG_DS] },
270 { " edi: ", context->uc_mcontext.gregs[REG_EDI] }, 266 { "edi", context->uc_mcontext.gregs[REG_EDI] },
271 { " esi: ", context->uc_mcontext.gregs[REG_ESI] }, 267 { "esi", context->uc_mcontext.gregs[REG_ESI] },
272 { " ebp: ", context->uc_mcontext.gregs[REG_EBP] }, 268 { "ebp", context->uc_mcontext.gregs[REG_EBP] },
273 { " esp: ", context->uc_mcontext.gregs[REG_ESP] }, 269 { "esp", context->uc_mcontext.gregs[REG_ESP] },
274 { " ebx: ", context->uc_mcontext.gregs[REG_EBX] }, 270 { "ebx", context->uc_mcontext.gregs[REG_EBX] },
275 { " edx: ", context->uc_mcontext.gregs[REG_EDX] }, 271 { "edx", context->uc_mcontext.gregs[REG_EDX] },
276 { " ecx: ", context->uc_mcontext.gregs[REG_ECX] }, 272 { "ecx", context->uc_mcontext.gregs[REG_ECX] },
277 { " eax: ", context->uc_mcontext.gregs[REG_EAX] }, 273 { "eax", context->uc_mcontext.gregs[REG_EAX] },
278 { " trp: ", context->uc_mcontext.gregs[REG_TRAPNO] }, 274 { "trp", context->uc_mcontext.gregs[REG_TRAPNO] },
279 { " err: ", context->uc_mcontext.gregs[REG_ERR] }, 275 { "err", context->uc_mcontext.gregs[REG_ERR] },
280 { " ip: ", context->uc_mcontext.gregs[REG_EIP] }, 276 { "ip", context->uc_mcontext.gregs[REG_EIP] },
281 { " cs: ", context->uc_mcontext.gregs[REG_CS] }, 277 { "cs", context->uc_mcontext.gregs[REG_CS] },
282 { " efl: ", context->uc_mcontext.gregs[REG_EFL] }, 278 { "efl", context->uc_mcontext.gregs[REG_EFL] },
283 { " usp: ", context->uc_mcontext.gregs[REG_UESP] }, 279 { "usp", context->uc_mcontext.gregs[REG_UESP] },
284 { " ss: ", context->uc_mcontext.gregs[REG_SS] }, 280 { "ss", context->uc_mcontext.gregs[REG_SS] },
285 #elif ARCH_CPU_64_BITS 281 #elif ARCH_CPU_64_BITS
286 { " r8: ", context->uc_mcontext.gregs[REG_R8] }, 282 { "r8", context->uc_mcontext.gregs[REG_R8] },
287 { " r9: ", context->uc_mcontext.gregs[REG_R9] }, 283 { "r9", context->uc_mcontext.gregs[REG_R9] },
288 { " r10: ", context->uc_mcontext.gregs[REG_R10] }, 284 { "r10", context->uc_mcontext.gregs[REG_R10] },
289 { " r11: ", context->uc_mcontext.gregs[REG_R11] }, 285 { "r11", context->uc_mcontext.gregs[REG_R11] },
290 { " r12: ", context->uc_mcontext.gregs[REG_R12] }, 286 { "r12", context->uc_mcontext.gregs[REG_R12] },
291 { " r13: ", context->uc_mcontext.gregs[REG_R13] }, 287 { "r13", context->uc_mcontext.gregs[REG_R13] },
292 { " r14: ", context->uc_mcontext.gregs[REG_R14] }, 288 { "r14", context->uc_mcontext.gregs[REG_R14] },
293 { " r15: ", context->uc_mcontext.gregs[REG_R15] }, 289 { "r15", context->uc_mcontext.gregs[REG_R15] },
294 { " di: ", context->uc_mcontext.gregs[REG_RDI] }, 290 { "di", context->uc_mcontext.gregs[REG_RDI] },
295 { " si: ", context->uc_mcontext.gregs[REG_RSI] }, 291 { "si", context->uc_mcontext.gregs[REG_RSI] },
296 { " bp: ", context->uc_mcontext.gregs[REG_RBP] }, 292 { "bp", context->uc_mcontext.gregs[REG_RBP] },
297 { " bx: ", context->uc_mcontext.gregs[REG_RBX] }, 293 { "bx", context->uc_mcontext.gregs[REG_RBX] },
298 { " dx: ", context->uc_mcontext.gregs[REG_RDX] }, 294 { "dx", context->uc_mcontext.gregs[REG_RDX] },
299 { " ax: ", context->uc_mcontext.gregs[REG_RAX] }, 295 { "ax", context->uc_mcontext.gregs[REG_RAX] },
300 { " cx: ", context->uc_mcontext.gregs[REG_RCX] }, 296 { "cx", context->uc_mcontext.gregs[REG_RCX] },
301 { " sp: ", context->uc_mcontext.gregs[REG_RSP] }, 297 { "sp", context->uc_mcontext.gregs[REG_RSP] },
302 { " ip: ", context->uc_mcontext.gregs[REG_RIP] }, 298 { "ip", context->uc_mcontext.gregs[REG_RIP] },
303 { " efl: ", context->uc_mcontext.gregs[REG_EFL] }, 299 { "efl", context->uc_mcontext.gregs[REG_EFL] },
304 { " cgf: ", context->uc_mcontext.gregs[REG_CSGSFS] }, 300 { "cgf", context->uc_mcontext.gregs[REG_CSGSFS] },
305 { " erf: ", context->uc_mcontext.gregs[REG_ERR] }, 301 { "erf", context->uc_mcontext.gregs[REG_ERR] },
306 { " trp: ", context->uc_mcontext.gregs[REG_TRAPNO] }, 302 { "trp", context->uc_mcontext.gregs[REG_TRAPNO] },
307 { " msk: ", context->uc_mcontext.gregs[REG_OLDMASK] }, 303 { "msk", context->uc_mcontext.gregs[REG_OLDMASK] },
308 { " cr2: ", context->uc_mcontext.gregs[REG_CR2] }, 304 { "cr2", context->uc_mcontext.gregs[REG_CR2] },
309 #endif 305 #endif
310 }; 306 };
311 307
312 #if ARCH_CPU_32_BITS 308 #if ARCH_CPU_32_BITS
313 const int kRegisterPadding = 8; 309 #define K_REGISTER_PADDING "8"
314 #elif ARCH_CPU_64_BITS 310 #elif ARCH_CPU_64_BITS
315 const int kRegisterPadding = 16; 311 #define K_REGISTER_PADDING "16"
316 #endif 312 #endif
317 313
318 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(registers); i++) { 314 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(registers); i++) {
319 PrintToStderr(registers[i].label); 315 Format(buf, "%4s: %"K_REGISTER_PADDING"x%s",
320 internal::itoa_r(registers[i].value, buf, sizeof(buf), 316 registers[i].label,
321 16, kRegisterPadding); 317 registers[i].value,
318 (i + 1) % 4 == 0 ? "\n" : "");
322 PrintToStderr(buf); 319 PrintToStderr(buf);
323
324 if ((i + 1) % 4 == 0)
325 PrintToStderr("\n");
326 } 320 }
327 PrintToStderr("\n"); 321 PrintToStderr("\n");
328 #endif 322 #endif
329 #elif defined(OS_MACOSX) 323 #elif defined(OS_MACOSX)
330 // TODO(shess): Port to 64-bit. 324 // TODO(shess): Port to 64-bit.
331 #if ARCH_CPU_X86_FAMILY && ARCH_CPU_32_BITS 325 #if ARCH_CPU_X86_FAMILY && ARCH_CPU_32_BITS
332 ucontext_t* context = reinterpret_cast<ucontext_t*>(void_context); 326 ucontext_t* context = reinterpret_cast<ucontext_t*>(void_context);
333 size_t len; 327 size_t len;
334 328
335 // NOTE: Even |snprintf()| is not on the approved list for signal 329 // NOTE: Even |snprintf()| is not on the approved list for signal
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 474
481 PrintBacktraceOutputHandler handler; 475 PrintBacktraceOutputHandler handler;
482 ProcessBacktrace(trace_, count_, &handler); 476 ProcessBacktrace(trace_, count_, &handler);
483 } 477 }
484 478
485 void StackTrace::OutputToStream(std::ostream* os) const { 479 void StackTrace::OutputToStream(std::ostream* os) const {
486 StreamBacktraceOutputHandler handler(os); 480 StreamBacktraceOutputHandler handler(os);
487 ProcessBacktrace(trace_, count_, &handler); 481 ProcessBacktrace(trace_, count_, &handler);
488 } 482 }
489 483
490 namespace internal {
491
492 // NOTE: code from sandbox/linux/seccomp-bpf/demo.cc.
493 char *itoa_r(intptr_t i, char *buf, size_t sz, int base, size_t padding) {
494 // Make sure we can write at least one NUL byte.
495 size_t n = 1;
496 if (n > sz)
497 return NULL;
498
499 if (base < 2 || base > 16) {
500 buf[0] = '\000';
501 return NULL;
502 }
503
504 char *start = buf;
505
506 uintptr_t j = i;
507
508 // Handle negative numbers (only for base 10).
509 if (i < 0 && base == 10) {
510 j = -i;
511
512 // Make sure we can write the '-' character.
513 if (++n > sz) {
514 buf[0] = '\000';
515 return NULL;
516 }
517 *start++ = '-';
518 }
519
520 // Loop until we have converted the entire number. Output at least one
521 // character (i.e. '0').
522 char *ptr = start;
523 do {
524 // Make sure there is still enough space left in our output buffer.
525 if (++n > sz) {
526 buf[0] = '\000';
527 return NULL;
528 }
529
530 // Output the next digit.
531 *ptr++ = "0123456789abcdef"[j % base];
532 j /= base;
533
534 if (padding > 0)
535 padding--;
536 } while (j > 0 || padding > 0);
537
538 // Terminate the output with a NUL character.
539 *ptr = '\000';
540
541 // Conversion to ASCII actually resulted in the digits being in reverse
542 // order. We can't easily generate them in forward order, as we can't tell
543 // the number of characters needed until we are done converting.
544 // So, now, we reverse the string (except for the possible "-" sign).
545 while (--ptr > start) {
546 char ch = *ptr;
547 *ptr = *start;
548 *start++ = ch;
549 }
550 return buf;
551 }
552
553 } // namespace internal
554
555 } // namespace debug 484 } // namespace debug
556 } // namespace base 485 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698