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 <dlfcn.h> |
15 | #include <stdlib.h> |
16 | #include <string.h> |
17 | #include <unwind.h> |
18 | |
19 | _Unwind_Reason_Code frame_handler(struct _Unwind_Context *ctx, void *arg) { |
20 | (void)arg; |
21 | Dl_info info = {.dli_fname: 0, .dli_fbase: 0, .dli_sname: 0, .dli_saddr: 0}; |
22 | |
23 | // Unwind util the main is reached, above frames depend on the platform and |
24 | // architecture. |
25 | if (dladdr(address: reinterpret_cast<void *>(_Unwind_GetIP(ctx)), info: &info) && |
26 | info.dli_sname && !strcmp(s1: "main" , s2: info.dli_sname)) |
27 | _Exit(status: 0); |
28 | |
29 | return _URC_NO_REASON; |
30 | } |
31 | |
32 | __attribute__((noinline)) void foo() { |
33 | // Provide some CFI directives that instructs the unwinder where given |
34 | // float register is. |
35 | #if defined(__aarch64__) |
36 | // DWARF register number for V0-V31 registers are 64-95. |
37 | // Previous value of V0 is saved at offset 0 from CFA. |
38 | asm volatile(".cfi_offset 64, 0" ); |
39 | // From now on the previous value of register can't be restored anymore. |
40 | asm volatile(".cfi_undefined 65" ); |
41 | asm volatile(".cfi_undefined 95" ); |
42 | // Previous value of V2 is in V30. |
43 | asm volatile(".cfi_register 66, 94" ); |
44 | #endif |
45 | _Unwind_Backtrace(frame_handler, NULL); |
46 | } |
47 | |
48 | int main() { |
49 | foo(); |
50 | return -2; |
51 | } |
52 | |