]>
Commit | Line | Data |
---|---|---|
55f31857 EB |
1 | /**************************************************************************** |
2 | * * | |
3 | * GNAT COMPILER COMPONENTS * | |
4 | * * | |
5 | * S I G T R A M P * | |
6 | * * | |
7 | * Asm Implementation File * | |
8 | * * | |
4b490c1e | 9 | * Copyright (C) 2015-2020, Free Software Foundation, Inc. * |
55f31857 EB |
10 | * * |
11 | * GNAT is free software; you can redistribute it and/or modify it under * | |
12 | * terms of the GNU General Public License as published by the Free Soft- * | |
13 | * ware Foundation; either version 3, or (at your option) any later ver- * | |
14 | * sion. GNAT is distributed in the hope that it will be useful, but WITH- * | |
15 | * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * | |
16 | * or FITNESS FOR A PARTICULAR PURPOSE. * | |
17 | * * | |
18 | * As a special exception under Section 7 of GPL version 3, you are granted * | |
19 | * additional permissions described in the GCC Runtime Library Exception, * | |
20 | * version 3.1, as published by the Free Software Foundation. * | |
21 | * * | |
22 | * In particular, you can freely distribute your programs built with the * | |
23 | * GNAT Pro compiler, including any required library run-time units, using * | |
24 | * any licensing terms of your choosing. See the AdaCore Software License * | |
25 | * for full details. * | |
26 | * * | |
27 | * GNAT was originally developed by the GNAT team at New York University. * | |
28 | * Extensive contributions were provided by Ada Core Technologies Inc. * | |
29 | * * | |
30 | ****************************************************************************/ | |
31 | ||
32 | /****************************************************** | |
33 | * ARM-Android version of the __gnat_sigtramp service * | |
34 | ******************************************************/ | |
35 | ||
4e9ee595 AC |
36 | #include <sys/ucontext.h> |
37 | ||
55f31857 EB |
38 | #include "sigtramp.h" |
39 | /* See sigtramp.h for a general explanation of functionality. */ | |
40 | ||
41 | /* ---------------------- | |
42 | -- General comments -- | |
43 | ---------------------- | |
44 | ||
45 | Stubs are generated from toplevel asms, | |
46 | The general idea is to establish CFA as the sigcontext | |
47 | and state where to find the registers as offsets from there. | |
48 | ||
49 | We support stubs for VxWorks and Android, providing unwind info for | |
50 | common registers. We might need variants with support for floating | |
51 | point or altivec registers as well at some point. | |
52 | ||
53 | For Android it would be simpler to write this in Asm since there's only | |
54 | one variant, but to keep it looking like the VxWorks stubs, | |
55 | C is the choice for our toplevel interface. | |
56 | ||
57 | Note that the registers we "restore" here are those to which we have | |
58 | direct access through the system sigcontext structure, which includes | |
59 | only a partial set of the non-volatiles ABI-wise. */ | |
60 | ||
61 | /* ----------------------------------------- | |
62 | -- Protypes for our internal asm stubs -- | |
63 | ----------------------------------------- | |
64 | ||
65 | The registers are expected to be at SIGCONTEXT + 12 (reference the | |
66 | sicontext structure in asm/sigcontext.h which describes the first | |
67 | 3 * 4byte fields.) Even though our symbols will remain local, the | |
68 | prototype claims "extern" and not "static" to prevent compiler complaints | |
69 | about a symbol used but never defined. */ | |
70 | ||
71 | /* sigtramp stub providing unwind info for common registers. */ | |
72 | ||
73 | extern void __gnat_sigtramp_common | |
74 | (int signo, void *siginfo, void *sigcontext, | |
75 | __sigtramphandler_t * handler); | |
76 | ||
77 | void __gnat_sigtramp (int signo, void *si, void *sc, | |
78 | __sigtramphandler_t * handler) | |
79 | __attribute__((optimize(2))); | |
80 | ||
81 | void __gnat_sigtramp (int signo, void *si, void *ucontext, | |
82 | __sigtramphandler_t * handler) | |
83 | { | |
84 | struct sigcontext *mcontext = &((ucontext_t *) ucontext)->uc_mcontext; | |
85 | ||
86 | __gnat_sigtramp_common (signo, si, mcontext, handler); | |
87 | } | |
88 | ||
89 | /* asm string construction helpers. */ | |
90 | ||
91 | #define STR(TEXT) #TEXT | |
92 | /* stringify expanded TEXT, surrounding it with double quotes. */ | |
93 | ||
94 | #define S(E) STR(E) | |
95 | /* stringify E, which will resolve as text but may contain macros | |
96 | still to be expanded. */ | |
97 | ||
98 | /* asm (TEXT) outputs <tab>TEXT. These facilitate the output of | |
99 | multiline contents: */ | |
100 | #define TAB(S) "\t" S | |
101 | #define CR(S) S "\n" | |
102 | ||
103 | #undef TCR | |
104 | #define TCR(S) TAB(CR(S)) | |
105 | ||
106 | /* Trampoline body block | |
107 | --------------------- */ | |
108 | ||
109 | #define SIGTRAMP_BODY \ | |
110 | CR("") \ | |
111 | TCR("# Allocate frame and also save r2 which is the argument register") \ | |
112 | TCR("# containing the sigcontext, so that we can restore it during") \ | |
113 | TCR("# unwinding and thereby load the rest of the desired context.") \ | |
114 | TCR("stmfd sp!, {r2, r3, lr}") \ | |
115 | TCR("# The unwinder undo's these operations in reverse order so starting") \ | |
116 | TCR("# from bottom, restore r2 from the current vsp location, move r2 into") \ | |
117 | TCR("# the vsp, add 12 bytes to get the start of the register save area") \ | |
118 | TCR("# then restore the 15 general purpose registers of the frame which") \ | |
119 | TCR("# raised the signal.") \ | |
746fb0c5 | 120 | TCR(".save {r0-r15}") \ |
55f31857 EB |
121 | TCR(".pad #12") \ |
122 | TCR(".movsp r2") \ | |
123 | TCR(".save {r2}") \ | |
124 | TCR("# Call the real handler. The signo, siginfo and sigcontext") \ | |
125 | TCR("# arguments are the same as those we received in r0, r1 and r2.") \ | |
126 | TCR("blx r3") \ | |
127 | TCR("# Restore our callee-saved items, release our frame and return") \ | |
128 | TCR("# (should never get here!).") \ | |
129 | TCR("ldmfd sp, {r2, r3, pc}") | |
130 | ||
131 | /* Symbol definition block | |
132 | ----------------------- */ | |
133 | ||
134 | #define SIGTRAMP_START(SYM) \ | |
135 | CR("# " S(SYM) " unwind trampoline") \ | |
136 | TCR(".type " S(SYM) ", %function") \ | |
137 | CR("") \ | |
138 | CR(S(SYM) ":") \ | |
139 | TCR(".fnstart") | |
140 | ||
141 | /* Symbol termination block | |
142 | ------------------------ */ | |
143 | ||
144 | #define SIGTRAMP_END(SYM) \ | |
145 | CR(".fnend") \ | |
146 | TCR(".size " S(SYM) ", .-" S(SYM)) | |
147 | ||
148 | /*---------------------------- | |
149 | -- And now, the real code -- | |
150 | ---------------------------- */ | |
151 | ||
152 | /* Text section start. The compiler isn't aware of that switch. */ | |
153 | ||
154 | asm (".text\n" | |
155 | TCR(".align 2")); | |
156 | ||
157 | /* sigtramp stub for common registers. */ | |
158 | ||
159 | #define TRAMP_COMMON __gnat_sigtramp_common | |
160 | ||
161 | asm (SIGTRAMP_START(TRAMP_COMMON)); | |
162 | asm (SIGTRAMP_BODY); | |
163 | asm (SIGTRAMP_END(TRAMP_COMMON)); |