llvm/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp

//===-- sanitizer_unwind_linux_libcdep.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 contains the unwind.h-based (aka "slow") stack unwinding routines
// available to the tools on Linux, Android, NetBSD, FreeBSD, and Solaris.
//===----------------------------------------------------------------------===//

#include "sanitizer_platform.h"
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
    SANITIZER_SOLARIS
#include "sanitizer_common.h"
#include "sanitizer_stacktrace.h"

#if SANITIZER_ANDROID
#include <dlfcn.h>  // for dlopen()
#endif

#if SANITIZER_FREEBSD
#define _GNU_SOURCE
#endif
#include <unwind.h>

namespace __sanitizer {

namespace {

//---------------------------- UnwindSlow --------------------------------------

backtrace_frame_t;

extern "C" {
acquire_my_map_info_list_func;
release_my_map_info_list_func;
unwind_backtrace_signal_arch_func;
acquire_my_map_info_list_func acquire_my_map_info_list;
release_my_map_info_list_func release_my_map_info_list;
unwind_backtrace_signal_arch_func unwind_backtrace_signal_arch;
} // extern "C"

#if defined(__arm__) && !SANITIZER_NETBSD
// NetBSD uses dwarf EH
#define UNWIND_STOP
#define UNWIND_CONTINUE
#else
#define UNWIND_STOP
#define UNWIND_CONTINUE
#endif

uptr Unwind_GetIP(struct _Unwind_Context *ctx) {}

struct UnwindTraceArg {};

_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {}

}  // namespace

#if SANITIZER_ANDROID
void SanitizerInitializeUnwinder() {
  if (AndroidGetApiLevel() >= ANDROID_LOLLIPOP_MR1) return;

  // Pre-lollipop Android can not unwind through signal handler frames with
  // libgcc unwinder, but it has a libcorkscrew.so library with the necessary
  // workarounds.
  void *p = dlopen("libcorkscrew.so", RTLD_LAZY);
  if (!p) {
    VReport(1,
            "Failed to open libcorkscrew.so. You may see broken stack traces "
            "in SEGV reports.");
    return;
  }
  acquire_my_map_info_list =
      (acquire_my_map_info_list_func)(uptr)dlsym(p, "acquire_my_map_info_list");
  release_my_map_info_list =
      (release_my_map_info_list_func)(uptr)dlsym(p, "release_my_map_info_list");
  unwind_backtrace_signal_arch = (unwind_backtrace_signal_arch_func)(uptr)dlsym(
      p, "unwind_backtrace_signal_arch");
  if (!acquire_my_map_info_list || !release_my_map_info_list ||
      !unwind_backtrace_signal_arch) {
    VReport(1,
            "Failed to find one of the required symbols in libcorkscrew.so. "
            "You may see broken stack traces in SEGV reports.");
    acquire_my_map_info_list = 0;
    unwind_backtrace_signal_arch = 0;
    release_my_map_info_list = 0;
  }
}
#endif

void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) {}

void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) {}

}  // namespace __sanitizer

#endif  // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD ||
        // SANITIZER_SOLARIS