]>
Commit | Line | Data |
---|---|---|
9fc813e1 | 1 | /* Dynamic loading of the libgcc unwinder. MIPS customization. |
6d7e8eda | 2 | Copyright (C) 2020-2023 Free Software Foundation, Inc. |
6e05978f AZ |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
16 | License along with the GNU C Library; if not, see | |
17 | <https://www.gnu.org/licenses/>. */ | |
18 | ||
9fc813e1 FW |
19 | #ifndef _ARCH_UNWIND_LINK_H |
20 | #define _ARCH_UNWIND_LINK_H | |
6e05978f AZ |
21 | |
22 | #include <stdint.h> | |
9fc813e1 FW |
23 | #include <sys/syscall.h> |
24 | ||
25 | #define UNWIND_LINK_GETIP 1 | |
26 | #define UNWIND_LINK_FRAME_STATE_FOR 1 | |
27 | #define UNWIND_LINK_FRAME_ADJUSTMENT 1 | |
28 | #define UNWIND_LINK_EXTRA_FIELDS | |
29 | #define UNWIND_LINK_EXTRA_INIT | |
6e05978f AZ |
30 | |
31 | /* MIPS fallback code handle a frame where its FDE can not be obtained | |
32 | (for instance a signal frame) by reading the kernel allocated signal frame | |
33 | and adding '2' to the value of 'sc_pc' [1]. The added value is used to | |
34 | recognize an end of an EH region on mips16 [2]. | |
35 | ||
36 | The idea here is to adjust the obtained signal frame ADDR value and remove | |
37 | the libgcc added value by checking if the previous frame is a signal frame | |
38 | one. | |
39 | ||
40 | [1] libgcc/config/mips/linux-unwind.h from gcc code. | |
41 | [2] gcc/config/mips/mips.h from gcc code. */ | |
42 | ||
43 | static inline void * | |
44 | unwind_arch_adjustment (void *prev, void *addr) | |
45 | { | |
46 | uint32_t *pc = (uint32_t *) prev; | |
47 | ||
48 | if (pc == NULL) | |
49 | return addr; | |
50 | ||
51 | /* For MIPS16 or microMIPS frame libgcc makes no adjustment. */ | |
52 | if ((uintptr_t) pc & 0x3) | |
53 | return addr; | |
54 | ||
55 | /* The vDSO containes either | |
56 | ||
57 | 24021061 li v0, 0x1061 (rt_sigreturn) | |
58 | 0000000c syscall | |
9fc813e1 | 59 | or |
6e05978f AZ |
60 | 24021017 li v0, 0x1017 (sigreturn) |
61 | 0000000c syscall */ | |
62 | if (pc[1] != 0x0000000c) | |
63 | return addr; | |
64 | #if _MIPS_SIM == _ABIO32 | |
65 | if (pc[0] == (0x24020000 | __NR_sigreturn)) | |
66 | return (void *) ((uintptr_t) addr - 2); | |
67 | #endif | |
68 | if (pc[0] == (0x24020000 | __NR_rt_sigreturn)) | |
69 | return (void *) ((uintptr_t) addr - 2); | |
70 | ||
71 | return addr; | |
72 | } | |
73 | ||
9fc813e1 | 74 | #endif /* _ARCH_UNWIND_LINK_H */ |