xref: /netbsd-src/external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_symbolizer_markup.cpp (revision ff6d591ca308ed13e9c5ae142cf113a246c2cdc6)
1*ff6d591cSmrg //===-- sanitizer_symbolizer_markup.cpp -----------------------------------===//
2*ff6d591cSmrg //
3*ff6d591cSmrg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*ff6d591cSmrg // See https://llvm.org/LICENSE.txt for license information.
5*ff6d591cSmrg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*ff6d591cSmrg //
7*ff6d591cSmrg //===----------------------------------------------------------------------===//
8*ff6d591cSmrg //
9*ff6d591cSmrg // This file is shared between various sanitizers' runtime libraries.
10*ff6d591cSmrg //
11*ff6d591cSmrg // Implementation of offline markup symbolizer.
12*ff6d591cSmrg //===----------------------------------------------------------------------===//
13*ff6d591cSmrg 
14*ff6d591cSmrg #include "sanitizer_platform.h"
15*ff6d591cSmrg #if SANITIZER_SYMBOLIZER_MARKUP
16*ff6d591cSmrg 
17*ff6d591cSmrg #if SANITIZER_FUCHSIA
18*ff6d591cSmrg #include "sanitizer_symbolizer_fuchsia.h"
19*ff6d591cSmrg #  endif
20*ff6d591cSmrg 
21*ff6d591cSmrg #  include <limits.h>
22*ff6d591cSmrg #  include <unwind.h>
23*ff6d591cSmrg 
24*ff6d591cSmrg #  include "sanitizer_stacktrace.h"
25*ff6d591cSmrg #  include "sanitizer_symbolizer.h"
26*ff6d591cSmrg 
27*ff6d591cSmrg namespace __sanitizer {
28*ff6d591cSmrg 
29*ff6d591cSmrg // This generic support for offline symbolizing is based on the
30*ff6d591cSmrg // Fuchsia port.  We don't do any actual symbolization per se.
31*ff6d591cSmrg // Instead, we emit text containing raw addresses and raw linkage
32*ff6d591cSmrg // symbol names, embedded in Fuchsia's symbolization markup format.
33*ff6d591cSmrg // Fuchsia's logging infrastructure emits enough information about
34*ff6d591cSmrg // process memory layout that a post-processing filter can do the
35*ff6d591cSmrg // symbolization and pretty-print the markup.  See the spec at:
36*ff6d591cSmrg // https://fuchsia.googlesource.com/zircon/+/master/docs/symbolizer_markup.md
37*ff6d591cSmrg 
38*ff6d591cSmrg // This is used by UBSan for type names, and by ASan for global variable names.
39*ff6d591cSmrg // It's expected to return a static buffer that will be reused on each call.
Demangle(const char * name)40*ff6d591cSmrg const char *Symbolizer::Demangle(const char *name) {
41*ff6d591cSmrg   static char buffer[kFormatDemangleMax];
42*ff6d591cSmrg   internal_snprintf(buffer, sizeof(buffer), kFormatDemangle, name);
43*ff6d591cSmrg   return buffer;
44*ff6d591cSmrg }
45*ff6d591cSmrg 
46*ff6d591cSmrg // This is used mostly for suppression matching.  Making it work
47*ff6d591cSmrg // would enable "interceptor_via_lib" suppressions.  It's also used
48*ff6d591cSmrg // once in UBSan to say "in module ..." in a message that also
49*ff6d591cSmrg // includes an address in the module, so post-processing can already
50*ff6d591cSmrg // pretty-print that so as to indicate the module.
GetModuleNameAndOffsetForPC(uptr pc,const char ** module_name,uptr * module_address)51*ff6d591cSmrg bool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
52*ff6d591cSmrg                                              uptr *module_address) {
53*ff6d591cSmrg   return false;
54*ff6d591cSmrg }
55*ff6d591cSmrg 
56*ff6d591cSmrg // This is mainly used by hwasan for online symbolization. This isn't needed
57*ff6d591cSmrg // since hwasan can always just dump stack frames for offline symbolization.
SymbolizeFrame(uptr addr,FrameInfo * info)58*ff6d591cSmrg bool Symbolizer::SymbolizeFrame(uptr addr, FrameInfo *info) { return false; }
59*ff6d591cSmrg 
60*ff6d591cSmrg // This is used in some places for suppression checking, which we
61*ff6d591cSmrg // don't really support for Fuchsia.  It's also used in UBSan to
62*ff6d591cSmrg // identify a PC location to a function name, so we always fill in
63*ff6d591cSmrg // the function member with a string containing markup around the PC
64*ff6d591cSmrg // value.
65*ff6d591cSmrg // TODO(mcgrathr): Under SANITIZER_GO, it's currently used by TSan
66*ff6d591cSmrg // to render stack frames, but that should be changed to use
67*ff6d591cSmrg // RenderStackFrame.
SymbolizePC(uptr addr)68*ff6d591cSmrg SymbolizedStack *Symbolizer::SymbolizePC(uptr addr) {
69*ff6d591cSmrg   SymbolizedStack *s = SymbolizedStack::New(addr);
70*ff6d591cSmrg   char buffer[kFormatFunctionMax];
71*ff6d591cSmrg   internal_snprintf(buffer, sizeof(buffer), kFormatFunction, addr);
72*ff6d591cSmrg   s->info.function = internal_strdup(buffer);
73*ff6d591cSmrg   return s;
74*ff6d591cSmrg }
75*ff6d591cSmrg 
76*ff6d591cSmrg // Always claim we succeeded, so that RenderDataInfo will be called.
SymbolizeData(uptr addr,DataInfo * info)77*ff6d591cSmrg bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) {
78*ff6d591cSmrg   info->Clear();
79*ff6d591cSmrg   info->start = addr;
80*ff6d591cSmrg   return true;
81*ff6d591cSmrg }
82*ff6d591cSmrg 
83*ff6d591cSmrg // We ignore the format argument to __sanitizer_symbolize_global.
RenderData(InternalScopedString * buffer,const char * format,const DataInfo * DI,const char * strip_path_prefix)84*ff6d591cSmrg void RenderData(InternalScopedString *buffer, const char *format,
85*ff6d591cSmrg                 const DataInfo *DI, const char *strip_path_prefix) {
86*ff6d591cSmrg   buffer->append(kFormatData, DI->start);
87*ff6d591cSmrg }
88*ff6d591cSmrg 
RenderNeedsSymbolization(const char * format)89*ff6d591cSmrg bool RenderNeedsSymbolization(const char *format) { return false; }
90*ff6d591cSmrg 
91*ff6d591cSmrg // We don't support the stack_trace_format flag at all.
RenderFrame(InternalScopedString * buffer,const char * format,int frame_no,uptr address,const AddressInfo * info,bool vs_style,const char * strip_path_prefix,const char * strip_func_prefix)92*ff6d591cSmrg void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
93*ff6d591cSmrg                  uptr address, const AddressInfo *info, bool vs_style,
94*ff6d591cSmrg                  const char *strip_path_prefix, const char *strip_func_prefix) {
95*ff6d591cSmrg   CHECK(!RenderNeedsSymbolization(format));
96*ff6d591cSmrg   buffer->append(kFormatFrame, frame_no, address);
97*ff6d591cSmrg }
98*ff6d591cSmrg 
PlatformInit()99*ff6d591cSmrg Symbolizer *Symbolizer::PlatformInit() {
100*ff6d591cSmrg   return new (symbolizer_allocator_) Symbolizer({});
101*ff6d591cSmrg }
102*ff6d591cSmrg 
LateInitialize()103*ff6d591cSmrg void Symbolizer::LateInitialize() {
104*ff6d591cSmrg   Symbolizer::GetOrInit()->LateInitializeTools();
105*ff6d591cSmrg }
106*ff6d591cSmrg 
StartReportDeadlySignal()107*ff6d591cSmrg void StartReportDeadlySignal() {}
ReportDeadlySignal(const SignalContext & sig,u32 tid,UnwindSignalStackCallbackType unwind,const void * unwind_context)108*ff6d591cSmrg void ReportDeadlySignal(const SignalContext &sig, u32 tid,
109*ff6d591cSmrg                         UnwindSignalStackCallbackType unwind,
110*ff6d591cSmrg                         const void *unwind_context) {}
111*ff6d591cSmrg 
112*ff6d591cSmrg #if SANITIZER_CAN_SLOW_UNWIND
113*ff6d591cSmrg struct UnwindTraceArg {
114*ff6d591cSmrg   BufferedStackTrace *stack;
115*ff6d591cSmrg   u32 max_depth;
116*ff6d591cSmrg };
117*ff6d591cSmrg 
Unwind_Trace(struct _Unwind_Context * ctx,void * param)118*ff6d591cSmrg _Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
119*ff6d591cSmrg   UnwindTraceArg *arg = static_cast<UnwindTraceArg *>(param);
120*ff6d591cSmrg   CHECK_LT(arg->stack->size, arg->max_depth);
121*ff6d591cSmrg   uptr pc = _Unwind_GetIP(ctx);
122*ff6d591cSmrg   if (pc < PAGE_SIZE) return _URC_NORMAL_STOP;
123*ff6d591cSmrg   arg->stack->trace_buffer[arg->stack->size++] = pc;
124*ff6d591cSmrg   return (arg->stack->size == arg->max_depth ? _URC_NORMAL_STOP
125*ff6d591cSmrg                                              : _URC_NO_REASON);
126*ff6d591cSmrg }
127*ff6d591cSmrg 
UnwindSlow(uptr pc,u32 max_depth)128*ff6d591cSmrg void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) {
129*ff6d591cSmrg   CHECK_GE(max_depth, 2);
130*ff6d591cSmrg   size = 0;
131*ff6d591cSmrg   UnwindTraceArg arg = {this, Min(max_depth + 1, kStackTraceMax)};
132*ff6d591cSmrg   _Unwind_Backtrace(Unwind_Trace, &arg);
133*ff6d591cSmrg   CHECK_GT(size, 0);
134*ff6d591cSmrg   // We need to pop a few frames so that pc is on top.
135*ff6d591cSmrg   uptr to_pop = LocatePcInTrace(pc);
136*ff6d591cSmrg   // trace_buffer[0] belongs to the current function so we always pop it,
137*ff6d591cSmrg   // unless there is only 1 frame in the stack trace (1 frame is always better
138*ff6d591cSmrg   // than 0!).
139*ff6d591cSmrg   PopStackFrames(Min(to_pop, static_cast<uptr>(1)));
140*ff6d591cSmrg   trace_buffer[0] = pc;
141*ff6d591cSmrg }
142*ff6d591cSmrg 
UnwindSlow(uptr pc,void * context,u32 max_depth)143*ff6d591cSmrg void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) {
144*ff6d591cSmrg   CHECK(context);
145*ff6d591cSmrg   CHECK_GE(max_depth, 2);
146*ff6d591cSmrg   UNREACHABLE("signal context doesn't exist");
147*ff6d591cSmrg }
148*ff6d591cSmrg #endif  // SANITIZER_CAN_SLOW_UNWIND
149*ff6d591cSmrg 
150*ff6d591cSmrg }  // namespace __sanitizer
151*ff6d591cSmrg 
152*ff6d591cSmrg #endif  // SANITIZER_SYMBOLIZER_MARKUP
153