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-exception |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | // REQUIRES: linux && target={{aarch64-.+}} |
11 | |
12 | // Basic test for float registers number are accepted. |
13 | |
14 | #include <stdlib.h> |
15 | #include <string.h> |
16 | #include <unwind.h> |
17 | |
18 | // Using __attribute__((section("main_func"))) is ELF specific, but then |
19 | // this entire test is marked as requiring Linux, so we should be good. |
20 | // |
21 | // We don't use dladdr() because on musl it's a no-op when statically linked. |
22 | extern char __start_main_func; |
23 | extern char __stop_main_func; |
24 | |
25 | _Unwind_Reason_Code frame_handler(struct _Unwind_Context *ctx, void *arg) { |
26 | (void)arg; |
27 | |
28 | // Unwind until the main is reached, above frames depend on the platform and |
29 | // architecture. |
30 | uintptr_t ip = _Unwind_GetIP(ctx); |
31 | if (ip >= (uintptr_t)&__start_main_func && |
32 | ip < (uintptr_t)&__stop_main_func) { |
33 | _Exit(status: 0); |
34 | } |
35 | |
36 | return _URC_NO_REASON; |
37 | } |
38 | |
39 | __attribute__((noinline)) void foo() { |
40 | // Provide some CFI directives that instructs the unwinder where given |
41 | // float register is. |
42 | #if defined(__aarch64__) |
43 | // DWARF register number for V0-V31 registers are 64-95. |
44 | // Previous value of V0 is saved at offset 0 from CFA. |
45 | asm volatile(".cfi_offset 64, 0" ); |
46 | // From now on the previous value of register can't be restored anymore. |
47 | asm volatile(".cfi_undefined 65" ); |
48 | asm volatile(".cfi_undefined 95" ); |
49 | // Previous value of V2 is in V30. |
50 | asm volatile(".cfi_register 66, 94" ); |
51 | #endif |
52 | _Unwind_Backtrace(frame_handler, NULL); |
53 | } |
54 | |
55 | __attribute__((section("main_func" ))) int main() { |
56 | foo(); |
57 | return -2; |
58 | } |
59 | |