brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.4 KiB · f781d7b Raw
80 lines · cpp
1// -*- C++ -*-2//===----------------------------------------------------------------------===//3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9 10// Ensure that leaf function can be unwund.11// REQUIRES: target={{(aarch64|loongarch64|riscv64|s390x|x86_64)-.+}}12// UNSUPPORTED: target={{.*-windows.*}}13 14// TODO: Figure out why this fails with Memory Sanitizer.15// XFAIL: msan16 17// Note: this test fails on musl because:18//19//  (a) musl disables emission of unwind information for its build, and20//  (b) musl's signal trampolines don't include unwind information21//22// XFAIL: target={{.*}}-musl23 24#undef NDEBUG25#include <assert.h>26#include <signal.h>27#include <stdio.h>28#include <stdlib.h>29#include <string.h>30#include <sys/types.h>31#include <unistd.h>32#include <unwind.h>33 34// Using __attribute__((section("main_func"))) is ELF specific, but then35// this entire test is marked as requiring Linux, so we should be good.36//37// We don't use dladdr() because on musl it's a no-op when statically linked.38extern char __start_main_func;39extern char __stop_main_func;40 41_Unwind_Reason_Code frame_handler(struct _Unwind_Context* ctx, void* arg) {42  (void)arg;43 44  // Unwind until the main is reached, above frames depend on the platform and45  // architecture.46  uintptr_t ip = _Unwind_GetIP(ctx);47  if (ip >= (uintptr_t)&__start_main_func &&48      ip < (uintptr_t)&__stop_main_func) {49    _Exit(0);50  }51 52  return _URC_NO_REASON;53}54 55void signal_handler(int signum) {56  (void)signum;57  _Unwind_Backtrace(frame_handler, NULL);58  _Exit(-1);59}60 61__attribute__((noinline)) void crashing_leaf_func(int do_trap) {62  // libunwind searches for the address before the return address which points63  // to the trap instruction. We make the trap conditional and prevent inlining64  // of the function to ensure that the compiler doesn't remove the `ret`65  // instruction altogether.66  //67  // It's also important that the trap instruction isn't the first instruction68  // in the function (which it isn't because of the branch) for other unwinders69  // that also decrement pc.70  if (do_trap)71    __builtin_trap();72}73 74__attribute__((section("main_func"))) int main(int, char **) {75  signal(SIGTRAP, signal_handler);76  signal(SIGILL, signal_handler);77  crashing_leaf_func(1);78  return -2;79}80