sanitizer_stacktrace_libcdep.cc 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. //===-- sanitizer_stacktrace_libcdep.cc -----------------------------------===//
  2. //
  3. // This file is distributed under the University of Illinois Open Source
  4. // License. See LICENSE.TXT for details.
  5. //
  6. //===----------------------------------------------------------------------===//
  7. //
  8. // This file is shared between AddressSanitizer and ThreadSanitizer
  9. // run-time libraries.
  10. //===----------------------------------------------------------------------===//
  11. #include "sanitizer_common.h"
  12. #include "sanitizer_placement_new.h"
  13. #include "sanitizer_stacktrace.h"
  14. #include "sanitizer_stacktrace_printer.h"
  15. #include "sanitizer_symbolizer.h"
  16. namespace __sanitizer {
  17. void StackTrace::Print() const {
  18. if (trace == nullptr || size == 0) {
  19. Printf(" <empty stack>\n\n");
  20. return;
  21. }
  22. const int kMaxAddrFrames = 64;
  23. InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
  24. for (uptr i = 0; i < kMaxAddrFrames; i++)
  25. new(&addr_frames[i]) AddressInfo();
  26. InternalScopedString frame_desc(GetPageSizeCached() * 2);
  27. uptr frame_num = 0;
  28. for (uptr i = 0; i < size && trace[i]; i++) {
  29. // PCs in stack traces are actually the return addresses, that is,
  30. // addresses of the next instructions after the call.
  31. uptr pc = GetPreviousInstructionPc(trace[i]);
  32. uptr addr_frames_num = Symbolizer::GetOrInit()->SymbolizePC(
  33. pc, addr_frames.data(), kMaxAddrFrames);
  34. if (addr_frames_num == 0) {
  35. addr_frames[0].address = pc;
  36. addr_frames_num = 1;
  37. }
  38. for (uptr j = 0; j < addr_frames_num; j++) {
  39. AddressInfo &info = addr_frames[j];
  40. frame_desc.clear();
  41. RenderFrame(&frame_desc, common_flags()->stack_trace_format, frame_num++,
  42. info, common_flags()->strip_path_prefix);
  43. Printf("%s\n", frame_desc.data());
  44. info.Clear();
  45. }
  46. }
  47. // Always print a trailing empty line after stack trace.
  48. Printf("\n");
  49. }
  50. void BufferedStackTrace::Unwind(uptr max_depth, uptr pc, uptr bp, void *context,
  51. uptr stack_top, uptr stack_bottom,
  52. bool request_fast_unwind) {
  53. top_frame_bp = (max_depth > 0) ? bp : 0;
  54. // Avoid doing any work for small max_depth.
  55. if (max_depth == 0) {
  56. size = 0;
  57. return;
  58. }
  59. if (max_depth == 1) {
  60. size = 1;
  61. trace_buffer[0] = pc;
  62. return;
  63. }
  64. if (!WillUseFastUnwind(request_fast_unwind)) {
  65. if (context)
  66. SlowUnwindStackWithContext(pc, context, max_depth);
  67. else
  68. SlowUnwindStack(pc, max_depth);
  69. } else {
  70. FastUnwindStack(pc, bp, stack_top, stack_bottom, max_depth);
  71. }
  72. }
  73. } // namespace __sanitizer