1353944Sdim//===-- sanitizer_stacktrace_libcdep.cpp ----------------------------------===// 2353944Sdim// 3353944Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353944Sdim// See https://llvm.org/LICENSE.txt for license information. 5353944Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6353944Sdim// 7353944Sdim//===----------------------------------------------------------------------===// 8353944Sdim// 9353944Sdim// This file is shared between AddressSanitizer and ThreadSanitizer 10353944Sdim// run-time libraries. 11353944Sdim//===----------------------------------------------------------------------===// 12353944Sdim 13353944Sdim#include "sanitizer_common.h" 14353944Sdim#include "sanitizer_placement_new.h" 15353944Sdim#include "sanitizer_stacktrace.h" 16353944Sdim#include "sanitizer_stacktrace_printer.h" 17353944Sdim#include "sanitizer_symbolizer.h" 18353944Sdim 19353944Sdimnamespace __sanitizer { 20353944Sdim 21353944Sdimvoid StackTrace::Print() const { 22353944Sdim if (trace == nullptr || size == 0) { 23353944Sdim Printf(" <empty stack>\n\n"); 24353944Sdim return; 25353944Sdim } 26353944Sdim InternalScopedString frame_desc(GetPageSizeCached() * 2); 27353944Sdim InternalScopedString dedup_token(GetPageSizeCached()); 28353944Sdim int dedup_frames = common_flags()->dedup_token_length; 29353944Sdim uptr frame_num = 0; 30353944Sdim for (uptr i = 0; i < size && trace[i]; i++) { 31353944Sdim // PCs in stack traces are actually the return addresses, that is, 32353944Sdim // addresses of the next instructions after the call. 33353944Sdim uptr pc = GetPreviousInstructionPc(trace[i]); 34353944Sdim SymbolizedStack *frames = Symbolizer::GetOrInit()->SymbolizePC(pc); 35353944Sdim CHECK(frames); 36353944Sdim for (SymbolizedStack *cur = frames; cur; cur = cur->next) { 37353944Sdim frame_desc.clear(); 38353944Sdim RenderFrame(&frame_desc, common_flags()->stack_trace_format, frame_num++, 39353944Sdim cur->info, common_flags()->symbolize_vs_style, 40353944Sdim common_flags()->strip_path_prefix); 41353944Sdim Printf("%s\n", frame_desc.data()); 42353944Sdim if (dedup_frames-- > 0) { 43353944Sdim if (dedup_token.length()) 44353944Sdim dedup_token.append("--"); 45353944Sdim if (cur->info.function != nullptr) 46353944Sdim dedup_token.append(cur->info.function); 47353944Sdim } 48353944Sdim } 49353944Sdim frames->ClearAll(); 50353944Sdim } 51353944Sdim // Always print a trailing empty line after stack trace. 52353944Sdim Printf("\n"); 53353944Sdim if (dedup_token.length()) 54353944Sdim Printf("DEDUP_TOKEN: %s\n", dedup_token.data()); 55353944Sdim} 56353944Sdim 57353944Sdimvoid BufferedStackTrace::Unwind(u32 max_depth, uptr pc, uptr bp, void *context, 58353944Sdim uptr stack_top, uptr stack_bottom, 59353944Sdim bool request_fast_unwind) { 60353944Sdim // Ensures all call sites get what they requested. 61353944Sdim CHECK_EQ(request_fast_unwind, WillUseFastUnwind(request_fast_unwind)); 62353944Sdim top_frame_bp = (max_depth > 0) ? bp : 0; 63353944Sdim // Avoid doing any work for small max_depth. 64353944Sdim if (max_depth == 0) { 65353944Sdim size = 0; 66353944Sdim return; 67353944Sdim } 68353944Sdim if (max_depth == 1) { 69353944Sdim size = 1; 70353944Sdim trace_buffer[0] = pc; 71353944Sdim return; 72353944Sdim } 73353944Sdim if (!WillUseFastUnwind(request_fast_unwind)) { 74353944Sdim#if SANITIZER_CAN_SLOW_UNWIND 75353944Sdim if (context) 76353944Sdim UnwindSlow(pc, context, max_depth); 77353944Sdim else 78353944Sdim UnwindSlow(pc, max_depth); 79353944Sdim#else 80353944Sdim UNREACHABLE("slow unwind requested but not available"); 81353944Sdim#endif 82353944Sdim } else { 83353944Sdim UnwindFast(pc, bp, stack_top, stack_bottom, max_depth); 84353944Sdim } 85353944Sdim} 86353944Sdim 87353944Sdimstatic int GetModuleAndOffsetForPc(uptr pc, char *module_name, 88353944Sdim uptr module_name_len, uptr *pc_offset) { 89353944Sdim const char *found_module_name = nullptr; 90353944Sdim bool ok = Symbolizer::GetOrInit()->GetModuleNameAndOffsetForPC( 91353944Sdim pc, &found_module_name, pc_offset); 92353944Sdim 93353944Sdim if (!ok) return false; 94353944Sdim 95353944Sdim if (module_name && module_name_len) { 96353944Sdim internal_strncpy(module_name, found_module_name, module_name_len); 97353944Sdim module_name[module_name_len - 1] = '\x00'; 98353944Sdim } 99353944Sdim return true; 100353944Sdim} 101353944Sdim 102353944Sdim} // namespace __sanitizer 103353944Sdimusing namespace __sanitizer; 104353944Sdim 105353944Sdimextern "C" { 106353944SdimSANITIZER_INTERFACE_ATTRIBUTE 107353944Sdimvoid __sanitizer_symbolize_pc(uptr pc, const char *fmt, char *out_buf, 108353944Sdim uptr out_buf_size) { 109353944Sdim if (!out_buf_size) return; 110353944Sdim pc = StackTrace::GetPreviousInstructionPc(pc); 111353944Sdim SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc); 112353944Sdim if (!frame) { 113353944Sdim internal_strncpy(out_buf, "<can't symbolize>", out_buf_size); 114353944Sdim out_buf[out_buf_size - 1] = 0; 115353944Sdim return; 116353944Sdim } 117353944Sdim InternalScopedString frame_desc(GetPageSizeCached()); 118353944Sdim uptr frame_num = 0; 119353944Sdim // Reserve one byte for the final 0. 120353944Sdim char *out_end = out_buf + out_buf_size - 1; 121353944Sdim for (SymbolizedStack *cur = frame; cur && out_buf < out_end; 122353944Sdim cur = cur->next) { 123353944Sdim frame_desc.clear(); 124353944Sdim RenderFrame(&frame_desc, fmt, frame_num++, cur->info, 125353944Sdim common_flags()->symbolize_vs_style, 126353944Sdim common_flags()->strip_path_prefix); 127353944Sdim if (!frame_desc.length()) 128353944Sdim continue; 129353944Sdim // Reserve one byte for the terminating 0. 130353944Sdim uptr n = out_end - out_buf - 1; 131353944Sdim internal_strncpy(out_buf, frame_desc.data(), n); 132353944Sdim out_buf += __sanitizer::Min<uptr>(n, frame_desc.length()); 133353944Sdim *out_buf++ = 0; 134353944Sdim } 135353944Sdim CHECK(out_buf <= out_end); 136353944Sdim *out_buf = 0; 137353944Sdim} 138353944Sdim 139353944SdimSANITIZER_INTERFACE_ATTRIBUTE 140353944Sdimvoid __sanitizer_symbolize_global(uptr data_addr, const char *fmt, 141353944Sdim char *out_buf, uptr out_buf_size) { 142353944Sdim if (!out_buf_size) return; 143353944Sdim out_buf[0] = 0; 144353944Sdim DataInfo DI; 145353944Sdim if (!Symbolizer::GetOrInit()->SymbolizeData(data_addr, &DI)) return; 146353944Sdim InternalScopedString data_desc(GetPageSizeCached()); 147353944Sdim RenderData(&data_desc, fmt, &DI, common_flags()->strip_path_prefix); 148353944Sdim internal_strncpy(out_buf, data_desc.data(), out_buf_size); 149353944Sdim out_buf[out_buf_size - 1] = 0; 150353944Sdim} 151353944Sdim 152353944SdimSANITIZER_INTERFACE_ATTRIBUTE 153353944Sdimint __sanitizer_get_module_and_offset_for_pc(uptr pc, char *module_name, 154353944Sdim uptr module_name_len, 155353944Sdim uptr *pc_offset) { 156353944Sdim return __sanitizer::GetModuleAndOffsetForPc(pc, module_name, module_name_len, 157353944Sdim pc_offset); 158353944Sdim} 159353944Sdim} // extern "C" 160