head	1.4;
access;
symbols
	perseant-exfatfs-base-20261102:1.4
	netbsd-11-1-RELEASE:1.3
	gcc-14-4-0:1.1.1.3
	netbsd-11-0-RELEASE:1.3
	netbsd-11-0-RC7:1.3
	netbsd-11-0-RC6:1.3
	netbsd-11-0-RC5:1.3
	netbsd-11-0-RC4:1.3
	netbsd-11-0-RC3:1.3
	netbsd-11-0-RC2:1.3
	netbsd-11-0-RC1:1.3
	gcc-14-3-0:1.1.1.3
	perseant-exfatfs-base-20250801:1.3
	netbsd-11:1.3.0.4
	netbsd-11-base:1.3
	gcc-12-5-0:1.1.1.2
	perseant-exfatfs-base-20240630:1.3
	gcc-12-4-0:1.1.1.2
	perseant-exfatfs:1.3.0.2
	perseant-exfatfs-base:1.3
	gcc-12-3-0:1.1.1.2
	gcc-10-5-0:1.1.1.1
	gcc-10-4-0:1.1.1.1
	cjep_sun2x:1.2.0.4
	cjep_sun2x-base:1.2
	cjep_staticlib_x-base1:1.2
	cjep_staticlib_x:1.2.0.2
	cjep_staticlib_x-base:1.2
	gcc-10-3-0:1.1.1.1
	FSF:1.1.1;
locks; strict;
comment	@// @;


1.4
date	2025.09.14.00.08.57;	author mrg;	state Exp;
branches;
next	1.3;
commitid	x9D5QEnvbeMI4CaG;

1.3
date	2023.07.31.01.44.57;	author mrg;	state Exp;
branches
	1.3.2.1;
next	1.2;
commitid	q79F5Opf0FLsyTyE;

1.2
date	2021.04.11.23.54.27;	author mrg;	state dead;
branches;
next	1.1;
commitid	wJn7ggfUTEMOWVOC;

1.1
date	2021.04.10.22.09.22;	author mrg;	state Exp;
branches
	1.1.1.1;
next	;
commitid	eC4g0MRpqTvEkNOC;

1.3.2.1
date	2026.11.04.22.51.24;	author perseant;	state Exp;
branches;
next	;
commitid	3QTNojfCEH9lUb2H;

1.1.1.1
date	2021.04.10.22.09.22;	author mrg;	state Exp;
branches;
next	1.1.1.2;
commitid	eC4g0MRpqTvEkNOC;

1.1.1.2
date	2023.07.30.05.20.41;	author mrg;	state Exp;
branches;
next	1.1.1.3;
commitid	tk6nV4mbc9nVEMyE;

1.1.1.3
date	2025.09.13.23.45.04;	author mrg;	state Exp;
branches;
next	;
commitid	KwhwN4krNWa6XBaG;


desc
@@


1.4
log
@merge GCC 14.3.0.
@
text
@//===-- sanitizer_common.cpp ----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file is shared between sanitizers' run-time libraries.
//
//===----------------------------------------------------------------------===//

#include "sanitizer_stacktrace_printer.h"

#include "sanitizer_file.h"
#include "sanitizer_flags.h"
#include "sanitizer_fuchsia.h"

namespace __sanitizer {

StackTracePrinter *StackTracePrinter::GetOrInit() {
  static StackTracePrinter *stacktrace_printer;
  static StaticSpinMutex init_mu;
  SpinMutexLock l(&init_mu);
  if (stacktrace_printer)
    return stacktrace_printer;

  stacktrace_printer =
      new (GetGlobalLowLevelAllocator()) FormattedStackTracePrinter();

  CHECK(stacktrace_printer);
  return stacktrace_printer;
}

const char *FormattedStackTracePrinter::StripFunctionName(
    const char *function) {
  if (!common_flags()->demangle)
    return function;
  if (!function)
    return nullptr;
  auto try_strip = [function](const char *prefix) -> const char * {
    const uptr prefix_len = internal_strlen(prefix);
    if (!internal_strncmp(function, prefix, prefix_len))
      return function + prefix_len;
    return nullptr;
  };
  if (SANITIZER_APPLE) {
    if (const char *s = try_strip("wrap_"))
      return s;
  } else if (SANITIZER_WINDOWS) {
    if (const char *s = try_strip("__asan_wrap_"))
      return s;
  } else {
    if (const char *s = try_strip("___interceptor_"))
      return s;
    if (const char *s = try_strip("__interceptor_"))
      return s;
  }
  return function;
}

// sanitizer_symbolizer_markup.cpp implements these differently.
#if !SANITIZER_SYMBOLIZER_MARKUP

static const char *DemangleFunctionName(const char *function) {
  if (!common_flags()->demangle)
    return function;
  if (!function)
    return nullptr;

  // NetBSD uses indirection for old threading functions for historical reasons
  // The mangled names are internal implementation detail and should not be
  // exposed even in backtraces.
#if SANITIZER_NETBSD
  if (!internal_strcmp(function, "__libc_mutex_init"))
    return "pthread_mutex_init";
  if (!internal_strcmp(function, "__libc_mutex_lock"))
    return "pthread_mutex_lock";
  if (!internal_strcmp(function, "__libc_mutex_trylock"))
    return "pthread_mutex_trylock";
  if (!internal_strcmp(function, "__libc_mutex_unlock"))
    return "pthread_mutex_unlock";
  if (!internal_strcmp(function, "__libc_mutex_destroy"))
    return "pthread_mutex_destroy";
  if (!internal_strcmp(function, "__libc_mutexattr_init"))
    return "pthread_mutexattr_init";
  if (!internal_strcmp(function, "__libc_mutexattr_settype"))
    return "pthread_mutexattr_settype";
  if (!internal_strcmp(function, "__libc_mutexattr_destroy"))
    return "pthread_mutexattr_destroy";
  if (!internal_strcmp(function, "__libc_cond_init"))
    return "pthread_cond_init";
  if (!internal_strcmp(function, "__libc_cond_signal"))
    return "pthread_cond_signal";
  if (!internal_strcmp(function, "__libc_cond_broadcast"))
    return "pthread_cond_broadcast";
  if (!internal_strcmp(function, "__libc_cond_wait"))
    return "pthread_cond_wait";
  if (!internal_strcmp(function, "__libc_cond_timedwait"))
    return "pthread_cond_timedwait";
  if (!internal_strcmp(function, "__libc_cond_destroy"))
    return "pthread_cond_destroy";
  if (!internal_strcmp(function, "__libc_rwlock_init"))
    return "pthread_rwlock_init";
  if (!internal_strcmp(function, "__libc_rwlock_rdlock"))
    return "pthread_rwlock_rdlock";
  if (!internal_strcmp(function, "__libc_rwlock_wrlock"))
    return "pthread_rwlock_wrlock";
  if (!internal_strcmp(function, "__libc_rwlock_tryrdlock"))
    return "pthread_rwlock_tryrdlock";
  if (!internal_strcmp(function, "__libc_rwlock_trywrlock"))
    return "pthread_rwlock_trywrlock";
  if (!internal_strcmp(function, "__libc_rwlock_unlock"))
    return "pthread_rwlock_unlock";
  if (!internal_strcmp(function, "__libc_rwlock_destroy"))
    return "pthread_rwlock_destroy";
  if (!internal_strcmp(function, "__libc_thr_keycreate"))
    return "pthread_key_create";
  if (!internal_strcmp(function, "__libc_thr_setspecific"))
    return "pthread_setspecific";
  if (!internal_strcmp(function, "__libc_thr_getspecific"))
    return "pthread_getspecific";
  if (!internal_strcmp(function, "__libc_thr_keydelete"))
    return "pthread_key_delete";
  if (!internal_strcmp(function, "__libc_thr_once"))
    return "pthread_once";
  if (!internal_strcmp(function, "__libc_thr_self"))
    return "pthread_self";
  if (!internal_strcmp(function, "__libc_thr_exit"))
    return "pthread_exit";
  if (!internal_strcmp(function, "__libc_thr_setcancelstate"))
    return "pthread_setcancelstate";
  if (!internal_strcmp(function, "__libc_thr_equal"))
    return "pthread_equal";
  if (!internal_strcmp(function, "__libc_thr_curcpu"))
    return "pthread_curcpu_np";
  if (!internal_strcmp(function, "__libc_thr_sigsetmask"))
    return "pthread_sigmask";
#endif

  return function;
}

static void MaybeBuildIdToBuffer(const AddressInfo &info, bool PrefixSpace,
                                 InternalScopedString *buffer) {
  if (info.uuid_size) {
    if (PrefixSpace)
      buffer->AppendF(" ");
    buffer->AppendF("(BuildId: ");
    for (uptr i = 0; i < info.uuid_size; ++i) {
      buffer->AppendF("%02x", info.uuid[i]);
    }
    buffer->AppendF(")");
  }
}

static const char kDefaultFormat[] = "    #%n %p %F %L";

void FormattedStackTracePrinter::RenderFrame(InternalScopedString *buffer,
                                             const char *format, int frame_no,
                                             uptr address,
                                             const AddressInfo *info,
                                             bool vs_style,
                                             const char *strip_path_prefix) {
  // info will be null in the case where symbolization is not needed for the
  // given format. This ensures that the code below will get a hard failure
  // rather than print incorrect information in case RenderNeedsSymbolization
  // ever ends up out of sync with this function. If non-null, the addresses
  // should match.
  CHECK(!info || address == info->address);
  if (0 == internal_strcmp(format, "DEFAULT"))
    format = kDefaultFormat;
  for (const char *p = format; *p != '\0'; p++) {
    if (*p != '%') {
      buffer->AppendF("%c", *p);
      continue;
    }
    p++;
    switch (*p) {
    case '%':
      buffer->Append("%");
      break;
    // Frame number and all fields of AddressInfo structure.
    case 'n':
      buffer->AppendF("%u", frame_no);
      break;
    case 'p':
      buffer->AppendF("0x%zx", address);
      break;
    case 'm':
      buffer->AppendF("%s", StripPathPrefix(info->module, strip_path_prefix));
      break;
    case 'o':
      buffer->AppendF("0x%zx", info->module_offset);
      break;
    case 'b':
      MaybeBuildIdToBuffer(*info, /*PrefixSpace=*/false, buffer);
      break;
    case 'f':
      buffer->AppendF("%s",
                      DemangleFunctionName(StripFunctionName(info->function)));
      break;
    case 'q':
      buffer->AppendF("0x%zx", info->function_offset != AddressInfo::kUnknown
                                   ? info->function_offset
                                   : 0x0);
      break;
    case 's':
      buffer->AppendF("%s", StripPathPrefix(info->file, strip_path_prefix));
      break;
    case 'l':
      buffer->AppendF("%d", info->line);
      break;
    case 'c':
      buffer->AppendF("%d", info->column);
      break;
    // Smarter special cases.
    case 'F':
      // Function name and offset, if file is unknown.
      if (info->function) {
        buffer->AppendF(
            "in %s", DemangleFunctionName(StripFunctionName(info->function)));
        if (!info->file && info->function_offset != AddressInfo::kUnknown)
          buffer->AppendF("+0x%zx", info->function_offset);
      }
      break;
    case 'S':
      // File/line information.
      RenderSourceLocation(buffer, info->file, info->line, info->column,
                           vs_style, strip_path_prefix);
      break;
    case 'L':
      // Source location, or module location.
      if (info->file) {
        RenderSourceLocation(buffer, info->file, info->line, info->column,
                             vs_style, strip_path_prefix);
      } else if (info->module) {
        RenderModuleLocation(buffer, info->module, info->module_offset,
                             info->module_arch, strip_path_prefix);

#if !SANITIZER_APPLE
        MaybeBuildIdToBuffer(*info, /*PrefixSpace=*/true, buffer);
#endif
      } else {
        buffer->AppendF("(<unknown module>)");
      }
      break;
    case 'M':
      // Module basename and offset, or PC.
      if (address & kExternalPCBit) {
        // There PCs are not meaningful.
      } else if (info->module) {
        // Always strip the module name for %M.
        RenderModuleLocation(buffer, StripModuleName(info->module),
                             info->module_offset, info->module_arch, "");
#if !SANITIZER_APPLE
        MaybeBuildIdToBuffer(*info, /*PrefixSpace=*/true, buffer);
#endif
      } else {
        buffer->AppendF("(%p)", (void *)address);
      }
      break;
    default:
      Report("Unsupported specifier in stack frame format: %c (%p)!\n", *p,
             (void *)p);
      Die();
    }
  }
}

bool FormattedStackTracePrinter::RenderNeedsSymbolization(const char *format) {
  if (0 == internal_strcmp(format, "DEFAULT"))
    format = kDefaultFormat;
  for (const char *p = format; *p != '\0'; p++) {
    if (*p != '%')
      continue;
    p++;
    switch (*p) {
      case '%':
        break;
      case 'n':
        // frame_no
        break;
      case 'p':
        // address
        break;
      default:
        return true;
    }
  }
  return false;
}

void FormattedStackTracePrinter::RenderData(InternalScopedString *buffer,
                                            const char *format,
                                            const DataInfo *DI,
                                            const char *strip_path_prefix) {
  for (const char *p = format; *p != '\0'; p++) {
    if (*p != '%') {
      buffer->AppendF("%c", *p);
      continue;
    }
    p++;
    switch (*p) {
      case '%':
        buffer->Append("%");
        break;
      case 's':
        buffer->AppendF("%s", StripPathPrefix(DI->file, strip_path_prefix));
        break;
      case 'l':
        buffer->AppendF("%zu", DI->line);
        break;
      case 'g':
        buffer->AppendF("%s", DI->name);
        break;
      default:
        Report("Unsupported specifier in stack frame format: %c (%p)!\n", *p,
               (void *)p);
        Die();
    }
  }
}

#endif  // !SANITIZER_SYMBOLIZER_MARKUP

void FormattedStackTracePrinter::RenderSourceLocation(
    InternalScopedString *buffer, const char *file, int line, int column,
    bool vs_style, const char *strip_path_prefix) {
  if (vs_style && line > 0) {
    buffer->AppendF("%s(%d", StripPathPrefix(file, strip_path_prefix), line);
    if (column > 0)
      buffer->AppendF(",%d", column);
    buffer->AppendF(")");
    return;
  }

  buffer->AppendF("%s", StripPathPrefix(file, strip_path_prefix));
  if (line > 0) {
    buffer->AppendF(":%d", line);
    if (column > 0)
      buffer->AppendF(":%d", column);
  }
}

void FormattedStackTracePrinter::RenderModuleLocation(
    InternalScopedString *buffer, const char *module, uptr offset,
    ModuleArch arch, const char *strip_path_prefix) {
  buffer->AppendF("(%s", StripPathPrefix(module, strip_path_prefix));
  if (arch != kModuleArchUnknown) {
    buffer->AppendF(":%s", ModuleArchToString(arch));
  }
  buffer->AppendF("+0x%zx)", offset);
}

} // namespace __sanitizer
@


1.3
log
@make this actually be GCC 12.3.0's libsanitizer.

the libsanitizer we used with GCC 9 and GCC 10 was significantly
ahead of the GCC 9 and GCC 10 provided versions.
@
text
@d14 1
d16 1
d21 13
a33 2
// sanitizer_symbolizer_markup.cpp implements these differently.
#if !SANITIZER_SYMBOLIZER_MARKUP
d35 24
a58 6
static const char *StripFunctionName(const char *function, const char *prefix) {
  if (!function) return nullptr;
  if (!prefix) return function;
  uptr prefix_len = internal_strlen(prefix);
  if (0 == internal_strncmp(function, prefix, prefix_len))
    return function + prefix_len;
d62 3
d66 4
a69 1
  if (!function) return nullptr;
d144 13
d159 6
a164 3
void 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) {
d175 1
a175 1
      buffer->append("%c", *p);
d181 1
a181 1
      buffer->append("%%");
d185 1
a185 1
      buffer->append("%u", frame_no);
d188 1
a188 1
      buffer->append("0x%zx", address);
d191 1
a191 1
      buffer->append("%s", StripPathPrefix(info->module, strip_path_prefix));
d194 4
a197 1
      buffer->append("0x%zx", info->module_offset);
d200 2
a201 2
      buffer->append("%s", DemangleFunctionName(StripFunctionName(
                               info->function, strip_func_prefix)));
d204 3
a206 3
      buffer->append("0x%zx", info->function_offset != AddressInfo::kUnknown
                                  ? info->function_offset
                                  : 0x0);
d209 1
a209 1
      buffer->append("%s", StripPathPrefix(info->file, strip_path_prefix));
d212 1
a212 1
      buffer->append("%d", info->line);
d215 1
a215 1
      buffer->append("%d", info->column);
d221 2
a222 2
        buffer->append("in %s", DemangleFunctionName(StripFunctionName(
                                    info->function, strip_func_prefix)));
d224 1
a224 1
          buffer->append("+0x%zx", info->function_offset);
d240 4
d245 1
a245 1
        buffer->append("(<unknown module>)");
d256 3
d260 1
a260 1
        buffer->append("(%p)", (void *)address);
d271 1
a271 1
bool RenderNeedsSymbolization(const char *format) {
d294 4
a297 2
void RenderData(InternalScopedString *buffer, const char *format,
                const DataInfo *DI, const char *strip_path_prefix) {
d300 1
a300 1
      buffer->append("%c", *p);
d306 1
a306 1
        buffer->append("%%");
d309 1
a309 1
        buffer->append("%s", StripPathPrefix(DI->file, strip_path_prefix));
d312 1
a312 1
        buffer->append("%zu", DI->line);
d315 1
a315 1
        buffer->append("%s", DI->name);
d327 3
a329 3
void RenderSourceLocation(InternalScopedString *buffer, const char *file,
                          int line, int column, bool vs_style,
                          const char *strip_path_prefix) {
d331 1
a331 1
    buffer->append("%s(%d", StripPathPrefix(file, strip_path_prefix), line);
d333 2
a334 2
      buffer->append(",%d", column);
    buffer->append(")");
d338 1
a338 1
  buffer->append("%s", StripPathPrefix(file, strip_path_prefix));
d340 1
a340 1
    buffer->append(":%d", line);
d342 1
a342 1
      buffer->append(":%d", column);
d346 4
a349 4
void RenderModuleLocation(InternalScopedString *buffer, const char *module,
                          uptr offset, ModuleArch arch,
                          const char *strip_path_prefix) {
  buffer->append("(%s", StripPathPrefix(module, strip_path_prefix));
d351 1
a351 1
    buffer->append(":%s", ModuleArchToString(arch));
d353 1
a353 1
  buffer->append("+0x%zx)", offset);
@


1.3.2.1
log
@Sync with HEAD
@
text
@a13 1

a14 1
#include "sanitizer_flags.h"
d19 2
a20 6
StackTracePrinter *StackTracePrinter::GetOrInit() {
  static StackTracePrinter *stacktrace_printer;
  static StaticSpinMutex init_mu;
  SpinMutexLock l(&init_mu);
  if (stacktrace_printer)
    return stacktrace_printer;
d22 6
a27 31
  stacktrace_printer =
      new (GetGlobalLowLevelAllocator()) FormattedStackTracePrinter();

  CHECK(stacktrace_printer);
  return stacktrace_printer;
}

const char *FormattedStackTracePrinter::StripFunctionName(
    const char *function) {
  if (!common_flags()->demangle)
    return function;
  if (!function)
    return nullptr;
  auto try_strip = [function](const char *prefix) -> const char * {
    const uptr prefix_len = internal_strlen(prefix);
    if (!internal_strncmp(function, prefix, prefix_len))
      return function + prefix_len;
    return nullptr;
  };
  if (SANITIZER_APPLE) {
    if (const char *s = try_strip("wrap_"))
      return s;
  } else if (SANITIZER_WINDOWS) {
    if (const char *s = try_strip("__asan_wrap_"))
      return s;
  } else {
    if (const char *s = try_strip("___interceptor_"))
      return s;
    if (const char *s = try_strip("__interceptor_"))
      return s;
  }
a30 3
// sanitizer_symbolizer_markup.cpp implements these differently.
#if !SANITIZER_SYMBOLIZER_MARKUP

d32 1
a32 4
  if (!common_flags()->demangle)
    return function;
  if (!function)
    return nullptr;
a106 13
static void MaybeBuildIdToBuffer(const AddressInfo &info, bool PrefixSpace,
                                 InternalScopedString *buffer) {
  if (info.uuid_size) {
    if (PrefixSpace)
      buffer->AppendF(" ");
    buffer->AppendF("(BuildId: ");
    for (uptr i = 0; i < info.uuid_size; ++i) {
      buffer->AppendF("%02x", info.uuid[i]);
    }
    buffer->AppendF(")");
  }
}

d109 3
a111 6
void FormattedStackTracePrinter::RenderFrame(InternalScopedString *buffer,
                                             const char *format, int frame_no,
                                             uptr address,
                                             const AddressInfo *info,
                                             bool vs_style,
                                             const char *strip_path_prefix) {
d122 1
a122 1
      buffer->AppendF("%c", *p);
d128 1
a128 1
      buffer->Append("%");
d132 1
a132 1
      buffer->AppendF("%u", frame_no);
d135 1
a135 1
      buffer->AppendF("0x%zx", address);
d138 1
a138 1
      buffer->AppendF("%s", StripPathPrefix(info->module, strip_path_prefix));
d141 1
a141 4
      buffer->AppendF("0x%zx", info->module_offset);
      break;
    case 'b':
      MaybeBuildIdToBuffer(*info, /*PrefixSpace=*/false, buffer);
d144 2
a145 2
      buffer->AppendF("%s",
                      DemangleFunctionName(StripFunctionName(info->function)));
d148 3
a150 3
      buffer->AppendF("0x%zx", info->function_offset != AddressInfo::kUnknown
                                   ? info->function_offset
                                   : 0x0);
d153 1
a153 1
      buffer->AppendF("%s", StripPathPrefix(info->file, strip_path_prefix));
d156 1
a156 1
      buffer->AppendF("%d", info->line);
d159 1
a159 1
      buffer->AppendF("%d", info->column);
d165 2
a166 2
        buffer->AppendF(
            "in %s", DemangleFunctionName(StripFunctionName(info->function)));
d168 1
a168 1
          buffer->AppendF("+0x%zx", info->function_offset);
a183 4

#if !SANITIZER_APPLE
        MaybeBuildIdToBuffer(*info, /*PrefixSpace=*/true, buffer);
#endif
d185 1
a185 1
        buffer->AppendF("(<unknown module>)");
a195 3
#if !SANITIZER_APPLE
        MaybeBuildIdToBuffer(*info, /*PrefixSpace=*/true, buffer);
#endif
d197 1
a197 1
        buffer->AppendF("(%p)", (void *)address);
d208 1
a208 1
bool FormattedStackTracePrinter::RenderNeedsSymbolization(const char *format) {
d231 2
a232 4
void FormattedStackTracePrinter::RenderData(InternalScopedString *buffer,
                                            const char *format,
                                            const DataInfo *DI,
                                            const char *strip_path_prefix) {
d235 1
a235 1
      buffer->AppendF("%c", *p);
d241 1
a241 1
        buffer->Append("%");
d244 1
a244 1
        buffer->AppendF("%s", StripPathPrefix(DI->file, strip_path_prefix));
d247 1
a247 1
        buffer->AppendF("%zu", DI->line);
d250 1
a250 1
        buffer->AppendF("%s", DI->name);
d262 3
a264 3
void FormattedStackTracePrinter::RenderSourceLocation(
    InternalScopedString *buffer, const char *file, int line, int column,
    bool vs_style, const char *strip_path_prefix) {
d266 1
a266 1
    buffer->AppendF("%s(%d", StripPathPrefix(file, strip_path_prefix), line);
d268 2
a269 2
      buffer->AppendF(",%d", column);
    buffer->AppendF(")");
d273 1
a273 1
  buffer->AppendF("%s", StripPathPrefix(file, strip_path_prefix));
d275 1
a275 1
    buffer->AppendF(":%d", line);
d277 1
a277 1
      buffer->AppendF(":%d", column);
d281 4
a284 4
void FormattedStackTracePrinter::RenderModuleLocation(
    InternalScopedString *buffer, const char *module, uptr offset,
    ModuleArch arch, const char *strip_path_prefix) {
  buffer->AppendF("(%s", StripPathPrefix(module, strip_path_prefix));
d286 1
a286 1
    buffer->AppendF(":%s", ModuleArchToString(arch));
d288 1
a288 1
  buffer->AppendF("+0x%zx)", offset);
@


1.2
log
@revert sanitizer back to the version we were using with GCC 9, since
that one was already newer than the GCC 10 version.
@
text
@d110 1
a110 1
                 const AddressInfo &info, bool vs_style,
d112 6
d132 1
a132 1
      buffer->append("%zu", frame_no);
d135 1
a135 1
      buffer->append("0x%zx", info.address);
d138 1
a138 1
      buffer->append("%s", StripPathPrefix(info.module, strip_path_prefix));
d141 1
a141 1
      buffer->append("0x%zx", info.module_offset);
d144 2
a145 3
      buffer->append("%s",
        DemangleFunctionName(
          StripFunctionName(info.function, strip_func_prefix)));
d148 2
a149 2
      buffer->append("0x%zx", info.function_offset != AddressInfo::kUnknown
                                  ? info.function_offset
d153 1
a153 1
      buffer->append("%s", StripPathPrefix(info.file, strip_path_prefix));
d156 1
a156 1
      buffer->append("%d", info.line);
d159 1
a159 1
      buffer->append("%d", info.column);
d164 5
a168 6
      if (info.function) {
        buffer->append("in %s",
                       DemangleFunctionName(
                         StripFunctionName(info.function, strip_func_prefix)));
        if (!info.file && info.function_offset != AddressInfo::kUnknown)
          buffer->append("+0x%zx", info.function_offset);
d173 2
a174 2
      RenderSourceLocation(buffer, info.file, info.line, info.column, vs_style,
                           strip_path_prefix);
d178 2
a179 2
      if (info.file) {
        RenderSourceLocation(buffer, info.file, info.line, info.column,
d181 3
a183 3
      } else if (info.module) {
        RenderModuleLocation(buffer, info.module, info.module_offset,
                             info.module_arch, strip_path_prefix);
d190 3
a192 3
      if (info.address & kExternalPCBit)
        {} // There PCs are not meaningful.
      else if (info.module)
d194 5
a198 4
        RenderModuleLocation(buffer, StripModuleName(info.module),
                             info.module_offset, info.module_arch, "");
      else
        buffer->append("(%p)", (void *)info.address);
d201 2
a202 2
      Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n", *p,
             *p);
d208 23
d247 1
a247 1
        buffer->append("%d", DI->line);
d253 2
a254 2
        Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n", *p,
               *p);
@


1.1
log
@Initial revision
@
text
@@


1.1.1.1
log
@initial import of GCC 10.3.0.  main changes include:

caveats:
- ABI issue between c++14 and c++17 fixed
- profile mode is removed from libstdc++
- -fno-common is now the default

new features:
- new flags -fallocation-dce, -fprofile-partial-training,
  -fprofile-reproducible, -fprofile-prefix-path, and -fanalyzer
- many new compile and link time optimisations
- enhanced drive optimisations
- openacc 2.6 support
- openmp 5.0 features
- new warnings: -Wstring-compare and -Wzero-length-bounds
- extended warnings: -Warray-bounds, -Wformat-overflow,
  -Wrestrict, -Wreturn-local-addr, -Wstringop-overflow,
  -Warith-conversion, -Wmismatched-tags, and -Wredundant-tags
- some likely C2X features implemented
- more C++20 implemented
- many new arm & intel CPUs known

hundreds of reported bugs are fixed.  full list of changes
can be found at:

   https://gcc.gnu.org/gcc-10/changes.html
@
text
@@


1.1.1.2
log
@initial import of GCC 12.3.0.

major changes in GCC 11 included:

- The default mode for C++ is now -std=gnu++17 instead of -std=gnu++14.
- When building GCC itself, the host compiler must now support C++11,
  rather than C++98.
- Some short options of the gcov tool have been renamed: -i to -j and
  -j to -H.
- ThreadSanitizer improvements.
- Introduce Hardware-assisted AddressSanitizer support.
- For targets that produce DWARF debugging information GCC now defaults
  to DWARF version 5. This can produce up to 25% more compact debug
  information compared to earlier versions.
- Many optimisations.
- The existing malloc attribute has been extended so that it can be
  used to identify allocator/deallocator API pairs. A pair of new
  -Wmismatched-dealloc and -Wmismatched-new-delete warnings are added.
- Other new warnings:
  -Wsizeof-array-div, enabled by -Wall, warns about divisions of two
    sizeof operators when the first one is applied to an array and the
    divisor does not equal the size of the array element.
  -Wstringop-overread, enabled by default, warns about calls to string
    functions reading past the end of the arrays passed to them as
    arguments.
  -Wtsan, enabled by default, warns about unsupported features in
    ThreadSanitizer (currently std::atomic_thread_fence).
- Enchanced warnings:
  -Wfree-nonheap-object detects many more instances of calls to
    deallocation functions with pointers not returned from a dynamic
    memory allocation function.
  -Wmaybe-uninitialized diagnoses passing pointers or references to
    uninitialized memory to functions taking const-qualified arguments.
  -Wuninitialized detects reads from uninitialized dynamically
    allocated memory.
  -Warray-parameter warns about functions with inconsistent array forms.
  -Wvla-parameter warns about functions with inconsistent VLA forms.
- Several new features from the upcoming C2X revision of the ISO C
  standard are supported with -std=c2x and -std=gnu2x.
- Several C++20 features have been implemented.
- The C++ front end has experimental support for some of the upcoming
  C++23 draft.
- Several new C++ warnings.
- Enhanced Arm, AArch64, x86, and RISC-V CPU support.
- The implementation of how program state is tracked within
  -fanalyzer has been completely rewritten with many enhancements.

see https://gcc.gnu.org/gcc-11/changes.html for a full list.

major changes in GCC 12 include:

- An ABI incompatibility between C and C++ when passing or returning
  by value certain aggregates containing zero width bit-fields has
  been discovered on various targets. x86-64, ARM and AArch64
  will always ignore them (so there is a C ABI incompatibility
  between GCC 11 and earlier with GCC 12 or later), PowerPC64 ELFv2
  always take them into account (so there is a C++ ABI
  incompatibility, GCC 4.4 and earlier compatible with GCC 12 or
  later, incompatible with GCC 4.5 through GCC 11). RISC-V has
  changed the handling of these already starting with GCC 10. As
  the ABI requires, MIPS takes them into account handling function
  return values so there is a C++ ABI incompatibility with GCC 4.5
  through 11.
- STABS: Support for emitting the STABS debugging format is
  deprecated and will be removed in the next release. All ports now
  default to emit DWARF (version 2 or later) debugging info or are
  obsoleted.
- Vectorization is enabled at -O2 which is now equivalent to the
  original -O2 -ftree-vectorize -fvect-cost-model=very-cheap.
- GCC now supports the ShadowCallStack sanitizer.
- Support for __builtin_shufflevector compatible with the clang
  language extension was added.
- Support for attribute unavailable was added.
- Support for __builtin_dynamic_object_size compatible with the
  clang language extension was added.
- New warnings:
  -Wbidi-chars warns about potentially misleading UTF-8
    bidirectional control characters.
  -Warray-compare warns about comparisons between two operands of
    array type.
- Some new features from the upcoming C2X revision of the ISO C
  standard are supported with -std=c2x and -std=gnu2x.
- Several C++23 features have been implemented.
- Many C++ enhancements across warnings and -f options.

see https://gcc.gnu.org/gcc-12/changes.html for a full list.
@
text
@d110 1
a110 1
                 uptr address, const AddressInfo *info, bool vs_style,
a111 6
  // info will be null in the case where symbolization is not needed for the
  // given format. This ensures that the code below will get a hard failure
  // rather than print incorrect information in case RenderNeedsSymbolization
  // ever ends up out of sync with this function. If non-null, the addresses
  // should match.
  CHECK(!info || address == info->address);
d126 1
a126 1
      buffer->append("%u", frame_no);
d129 1
a129 1
      buffer->append("0x%zx", address);
d132 1
a132 1
      buffer->append("%s", StripPathPrefix(info->module, strip_path_prefix));
d135 1
a135 1
      buffer->append("0x%zx", info->module_offset);
d138 3
a140 2
      buffer->append("%s", DemangleFunctionName(StripFunctionName(
                               info->function, strip_func_prefix)));
d143 2
a144 2
      buffer->append("0x%zx", info->function_offset != AddressInfo::kUnknown
                                  ? info->function_offset
d148 1
a148 1
      buffer->append("%s", StripPathPrefix(info->file, strip_path_prefix));
d151 1
a151 1
      buffer->append("%d", info->line);
d154 1
a154 1
      buffer->append("%d", info->column);
d159 6
a164 5
      if (info->function) {
        buffer->append("in %s", DemangleFunctionName(StripFunctionName(
                                    info->function, strip_func_prefix)));
        if (!info->file && info->function_offset != AddressInfo::kUnknown)
          buffer->append("+0x%zx", info->function_offset);
d169 2
a170 2
      RenderSourceLocation(buffer, info->file, info->line, info->column,
                           vs_style, strip_path_prefix);
d174 2
a175 2
      if (info->file) {
        RenderSourceLocation(buffer, info->file, info->line, info->column,
d177 3
a179 3
      } else if (info->module) {
        RenderModuleLocation(buffer, info->module, info->module_offset,
                             info->module_arch, strip_path_prefix);
d186 3
a188 3
      if (address & kExternalPCBit) {
        // There PCs are not meaningful.
      } else if (info->module) {
d190 4
a193 5
        RenderModuleLocation(buffer, StripModuleName(info->module),
                             info->module_offset, info->module_arch, "");
      } else {
        buffer->append("(%p)", (void *)address);
      }
d196 2
a197 2
      Report("Unsupported specifier in stack frame format: %c (%p)!\n", *p,
             (void *)p);
a202 23
bool RenderNeedsSymbolization(const char *format) {
  if (0 == internal_strcmp(format, "DEFAULT"))
    format = kDefaultFormat;
  for (const char *p = format; *p != '\0'; p++) {
    if (*p != '%')
      continue;
    p++;
    switch (*p) {
      case '%':
        break;
      case 'n':
        // frame_no
        break;
      case 'p':
        // address
        break;
      default:
        return true;
    }
  }
  return false;
}

d219 1
a219 1
        buffer->append("%zu", DI->line);
d225 2
a226 2
        Report("Unsupported specifier in stack frame format: %c (%p)!\n", *p,
               (void *)p);
@


1.1.1.3
log
@initial import of GCC 14.3.0.

major changes in GCC 13:
- improved sanitizer
- zstd debug info compression
- LTO improvements
- SARIF based diagnostic support
- new warnings: -Wxor-used-as-pow, -Wenum-int-mismatch, -Wself-move,
  -Wdangling-reference
- many new -Wanalyzer* specific warnings
- enhanced warnings: -Wpessimizing-move, -Wredundant-move
- new attributes to mark file descriptors, c++23 "assume"
- several C23 features added
- several C++23 features added
- many new features for Arm, x86, RISC-V

major changes in GCC 14:
- more strict C99 or newer support
- ia64* marked deprecated (but seemingly still in GCC 15.)
- several new hardening features
- support for "hardbool", which can have user supplied values of true/false
- explicit support for stack scrubbing upon function exit
- better auto-vectorisation support
- added clang-compatible __has_feature and __has_extension
- more C23, including -std=c23
- several C++26 features added
- better diagnostics in C++ templates
- new warnings: -Wnrvo, Welaborated-enum-base
- many new features for Arm, x86, RISC-V
- possible ABI breaking change for SPARC64 and small structures with arrays
  of floats.
@
text
@a13 1

a14 1
#include "sanitizer_flags.h"
d19 2
a20 6
StackTracePrinter *StackTracePrinter::GetOrInit() {
  static StackTracePrinter *stacktrace_printer;
  static StaticSpinMutex init_mu;
  SpinMutexLock l(&init_mu);
  if (stacktrace_printer)
    return stacktrace_printer;
d22 6
a27 31
  stacktrace_printer =
      new (GetGlobalLowLevelAllocator()) FormattedStackTracePrinter();

  CHECK(stacktrace_printer);
  return stacktrace_printer;
}

const char *FormattedStackTracePrinter::StripFunctionName(
    const char *function) {
  if (!common_flags()->demangle)
    return function;
  if (!function)
    return nullptr;
  auto try_strip = [function](const char *prefix) -> const char * {
    const uptr prefix_len = internal_strlen(prefix);
    if (!internal_strncmp(function, prefix, prefix_len))
      return function + prefix_len;
    return nullptr;
  };
  if (SANITIZER_APPLE) {
    if (const char *s = try_strip("wrap_"))
      return s;
  } else if (SANITIZER_WINDOWS) {
    if (const char *s = try_strip("__asan_wrap_"))
      return s;
  } else {
    if (const char *s = try_strip("___interceptor_"))
      return s;
    if (const char *s = try_strip("__interceptor_"))
      return s;
  }
a30 3
// sanitizer_symbolizer_markup.cpp implements these differently.
#if !SANITIZER_SYMBOLIZER_MARKUP

d32 1
a32 4
  if (!common_flags()->demangle)
    return function;
  if (!function)
    return nullptr;
a106 13
static void MaybeBuildIdToBuffer(const AddressInfo &info, bool PrefixSpace,
                                 InternalScopedString *buffer) {
  if (info.uuid_size) {
    if (PrefixSpace)
      buffer->AppendF(" ");
    buffer->AppendF("(BuildId: ");
    for (uptr i = 0; i < info.uuid_size; ++i) {
      buffer->AppendF("%02x", info.uuid[i]);
    }
    buffer->AppendF(")");
  }
}

d109 3
a111 6
void FormattedStackTracePrinter::RenderFrame(InternalScopedString *buffer,
                                             const char *format, int frame_no,
                                             uptr address,
                                             const AddressInfo *info,
                                             bool vs_style,
                                             const char *strip_path_prefix) {
d122 1
a122 1
      buffer->AppendF("%c", *p);
d128 1
a128 1
      buffer->Append("%");
d132 1
a132 1
      buffer->AppendF("%u", frame_no);
d135 1
a135 1
      buffer->AppendF("0x%zx", address);
d138 1
a138 1
      buffer->AppendF("%s", StripPathPrefix(info->module, strip_path_prefix));
d141 1
a141 4
      buffer->AppendF("0x%zx", info->module_offset);
      break;
    case 'b':
      MaybeBuildIdToBuffer(*info, /*PrefixSpace=*/false, buffer);
d144 2
a145 2
      buffer->AppendF("%s",
                      DemangleFunctionName(StripFunctionName(info->function)));
d148 3
a150 3
      buffer->AppendF("0x%zx", info->function_offset != AddressInfo::kUnknown
                                   ? info->function_offset
                                   : 0x0);
d153 1
a153 1
      buffer->AppendF("%s", StripPathPrefix(info->file, strip_path_prefix));
d156 1
a156 1
      buffer->AppendF("%d", info->line);
d159 1
a159 1
      buffer->AppendF("%d", info->column);
d165 2
a166 2
        buffer->AppendF(
            "in %s", DemangleFunctionName(StripFunctionName(info->function)));
d168 1
a168 1
          buffer->AppendF("+0x%zx", info->function_offset);
a183 4

#if !SANITIZER_APPLE
        MaybeBuildIdToBuffer(*info, /*PrefixSpace=*/true, buffer);
#endif
d185 1
a185 1
        buffer->AppendF("(<unknown module>)");
a195 3
#if !SANITIZER_APPLE
        MaybeBuildIdToBuffer(*info, /*PrefixSpace=*/true, buffer);
#endif
d197 1
a197 1
        buffer->AppendF("(%p)", (void *)address);
d208 1
a208 1
bool FormattedStackTracePrinter::RenderNeedsSymbolization(const char *format) {
d231 2
a232 4
void FormattedStackTracePrinter::RenderData(InternalScopedString *buffer,
                                            const char *format,
                                            const DataInfo *DI,
                                            const char *strip_path_prefix) {
d235 1
a235 1
      buffer->AppendF("%c", *p);
d241 1
a241 1
        buffer->Append("%");
d244 1
a244 1
        buffer->AppendF("%s", StripPathPrefix(DI->file, strip_path_prefix));
d247 1
a247 1
        buffer->AppendF("%zu", DI->line);
d250 1
a250 1
        buffer->AppendF("%s", DI->name);
d262 3
a264 3
void FormattedStackTracePrinter::RenderSourceLocation(
    InternalScopedString *buffer, const char *file, int line, int column,
    bool vs_style, const char *strip_path_prefix) {
d266 1
a266 1
    buffer->AppendF("%s(%d", StripPathPrefix(file, strip_path_prefix), line);
d268 2
a269 2
      buffer->AppendF(",%d", column);
    buffer->AppendF(")");
d273 1
a273 1
  buffer->AppendF("%s", StripPathPrefix(file, strip_path_prefix));
d275 1
a275 1
    buffer->AppendF(":%d", line);
d277 1
a277 1
      buffer->AppendF(":%d", column);
d281 4
a284 4
void FormattedStackTracePrinter::RenderModuleLocation(
    InternalScopedString *buffer, const char *module, uptr offset,
    ModuleArch arch, const char *strip_path_prefix) {
  buffer->AppendF("(%s", StripPathPrefix(module, strip_path_prefix));
d286 1
a286 1
    buffer->AppendF(":%s", ModuleArchToString(arch));
d288 1
a288 1
  buffer->AppendF("+0x%zx)", offset);
@


