1 //===-- sanitizer_stacktrace_libcdep.cpp ----------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file is shared between AddressSanitizer and ThreadSanitizer 10 // run-time libraries. 11 //===----------------------------------------------------------------------===// 12 13 #include "sanitizer_common.h" 14 #include "sanitizer_placement_new.h" 15 #include "sanitizer_stacktrace.h" 16 #include "sanitizer_stacktrace_printer.h" 17 #include "sanitizer_symbolizer.h" 18 19 namespace __sanitizer { 20 21 void StackTrace::Print() const { 22 if (trace == nullptr || size == 0) { 23 Printf(" <empty stack>\n\n"); 24 return; 25 } 26 InternalScopedString frame_desc(GetPageSizeCached() * 2); 27 InternalScopedString dedup_token(GetPageSizeCached()); 28 int dedup_frames = common_flags()->dedup_token_length; 29 uptr frame_num = 0; 30 for (uptr i = 0; i < size && trace[i]; i++) { 31 // PCs in stack traces are actually the return addresses, that is, 32 // addresses of the next instructions after the call. 33 uptr pc = GetPreviousInstructionPc(trace[i]); 34 SymbolizedStack *frames = Symbolizer::GetOrInit()->SymbolizePC(pc); 35 CHECK(frames); 36 for (SymbolizedStack *cur = frames; cur; cur = cur->next) { 37 frame_desc.clear(); 38 RenderFrame(&frame_desc, common_flags()->stack_trace_format, frame_num++, 39 cur->info, common_flags()->symbolize_vs_style, 40 common_flags()->strip_path_prefix); 41 Printf("%s\n", frame_desc.data()); 42 if (dedup_frames-- > 0) { 43 if (dedup_token.length()) 44 dedup_token.append("--"); 45 if (cur->info.function != nullptr) 46 dedup_token.append(cur->info.function); 47 } 48 } 49 frames->ClearAll(); 50 } 51 // Always print a trailing empty line after stack trace. 52 Printf("\n"); 53 if (dedup_token.length()) 54 Printf("DEDUP_TOKEN: %s\n", dedup_token.data()); 55 } 56 57 void BufferedStackTrace::Unwind(u32 max_depth, uptr pc, uptr bp, void *context, 58 uptr stack_top, uptr stack_bottom, 59 bool request_fast_unwind) { 60 // Ensures all call sites get what they requested. 61 CHECK_EQ(request_fast_unwind, WillUseFastUnwind(request_fast_unwind)); 62 top_frame_bp = (max_depth > 0) ? bp : 0; 63 // Avoid doing any work for small max_depth. 64 if (max_depth == 0) { 65 size = 0; 66 return; 67 } 68 if (max_depth == 1) { 69 size = 1; 70 trace_buffer[0] = pc; 71 return; 72 } 73 if (!WillUseFastUnwind(request_fast_unwind)) { 74 #if SANITIZER_CAN_SLOW_UNWIND 75 if (context) 76 UnwindSlow(pc, context, max_depth); 77 else 78 UnwindSlow(pc, max_depth); 79 #else 80 UNREACHABLE("slow unwind requested but not available"); 81 #endif 82 } else { 83 UnwindFast(pc, bp, stack_top, stack_bottom, max_depth); 84 } 85 } 86 87 static int GetModuleAndOffsetForPc(uptr pc, char *module_name, 88 uptr module_name_len, uptr *pc_offset) { 89 const char *found_module_name = nullptr; 90 bool ok = Symbolizer::GetOrInit()->GetModuleNameAndOffsetForPC( 91 pc, &found_module_name, pc_offset); 92 93 if (!ok) return false; 94 95 if (module_name && module_name_len) { 96 internal_strncpy(module_name, found_module_name, module_name_len); 97 module_name[module_name_len - 1] = '\x00'; 98 } 99 return true; 100 } 101 102 } // namespace __sanitizer 103 using namespace __sanitizer; 104 105 extern "C" { 106 SANITIZER_INTERFACE_ATTRIBUTE 107 void __sanitizer_symbolize_pc(uptr pc, const char *fmt, char *out_buf, 108 uptr out_buf_size) { 109 if (!out_buf_size) return; 110 pc = StackTrace::GetPreviousInstructionPc(pc); 111 SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc); 112 if (!frame) { 113 internal_strncpy(out_buf, "<can't symbolize>", out_buf_size); 114 out_buf[out_buf_size - 1] = 0; 115 return; 116 } 117 InternalScopedString frame_desc(GetPageSizeCached()); 118 uptr frame_num = 0; 119 // Reserve one byte for the final 0. 120 char *out_end = out_buf + out_buf_size - 1; 121 for (SymbolizedStack *cur = frame; cur && out_buf < out_end; 122 cur = cur->next) { 123 frame_desc.clear(); 124 RenderFrame(&frame_desc, fmt, frame_num++, cur->info, 125 common_flags()->symbolize_vs_style, 126 common_flags()->strip_path_prefix); 127 if (!frame_desc.length()) 128 continue; 129 // Reserve one byte for the terminating 0. 130 uptr n = out_end - out_buf - 1; 131 internal_strncpy(out_buf, frame_desc.data(), n); 132 out_buf += __sanitizer::Min<uptr>(n, frame_desc.length()); 133 *out_buf++ = 0; 134 } 135 CHECK(out_buf <= out_end); 136 *out_buf = 0; 137 } 138 139 SANITIZER_INTERFACE_ATTRIBUTE 140 void __sanitizer_symbolize_global(uptr data_addr, const char *fmt, 141 char *out_buf, uptr out_buf_size) { 142 if (!out_buf_size) return; 143 out_buf[0] = 0; 144 DataInfo DI; 145 if (!Symbolizer::GetOrInit()->SymbolizeData(data_addr, &DI)) return; 146 InternalScopedString data_desc(GetPageSizeCached()); 147 RenderData(&data_desc, fmt, &DI, common_flags()->strip_path_prefix); 148 internal_strncpy(out_buf, data_desc.data(), out_buf_size); 149 out_buf[out_buf_size - 1] = 0; 150 } 151 152 SANITIZER_INTERFACE_ATTRIBUTE 153 int __sanitizer_get_module_and_offset_for_pc(uptr pc, char *module_name, 154 uptr module_name_len, 155 uptr *pc_offset) { 156 return __sanitizer::GetModuleAndOffsetForPc(pc, module_name, module_name_len, 157 pc_offset); 158 } 159 } // extern "C" 160