1 | /* Special .init and .fini section support for HPPA |
2 | Copyright (C) 2000-2022 Free Software Foundation, Inc. |
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 | In addition to the permissions in the GNU Lesser General Public |
11 | License, the Free Software Foundation gives you unlimited |
12 | permission to link the compiled version of this file with other |
13 | programs, and to distribute those programs without any restriction |
14 | coming from the use of this file. (The GNU Lesser General Public |
15 | License restrictions do apply in other respects; for example, they |
16 | cover modification of the file, and distribution when not linked |
17 | into another program.) |
18 | |
19 | Note that people who make modified versions of this file are not |
20 | obligated to grant this special exception for their modified |
21 | versions; it is their choice whether to do so. The GNU Lesser |
22 | General Public License gives permission to release a modified |
23 | version without this exception; this exception also makes it |
24 | possible to release a modified version which carries forward this |
25 | exception. |
26 | |
27 | The GNU C Library is distributed in the hope that it will be useful, |
28 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
29 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
30 | Lesser General Public License for more details. |
31 | |
32 | You should have received a copy of the GNU Lesser General Public |
33 | License along with the GNU C Library. If not, see |
34 | <https://www.gnu.org/licenses/>. */ |
35 | |
36 | /* crti.S puts a function prologue at the beginning of the .init and |
37 | .fini sections and defines global symbols for those addresses, so |
38 | they can be called as functions. The symbols _init and _fini are |
39 | magic and cause the linker to emit DT_INIT and DT_FINI. */ |
40 | |
41 | #include <libc-symbols.h> |
42 | #include <sysdep.h> |
43 | |
44 | #ifndef PREINIT_FUNCTION |
45 | # define PREINIT_FUNCTION __gmon_start__ |
46 | #endif |
47 | |
48 | #ifndef PREINIT_FUNCTION_WEAK |
49 | # define PREINIT_FUNCTION_WEAK 1 |
50 | #endif |
51 | |
52 | #if PREINIT_FUNCTION_WEAK |
53 | weak_extern (PREINIT_FUNCTION) |
54 | #else |
55 | .hidden PREINIT_FUNCTION |
56 | #endif |
57 | |
58 | |
59 | /* If we have working .init_array support, we want to keep the .init |
60 | section empty (apart from the mandatory prologue/epilogue. This |
61 | ensures that the default unwind conventions (return-pointer in b0, |
62 | frame state in ar.pfs, etc.) will do the Right Thing. To ensure |
63 | an empty .init section, we register gmon_initializer() via the |
64 | .init_array. |
65 | |
66 | --davidm 02/10/29 */ |
67 | |
68 | #if PREINIT_FUNCTION_WEAK |
69 | /* This blob of assembly code is one simple C function: |
70 | |
71 | static void |
72 | __attribute__ ((used)) |
73 | gmon_initializer (void) |
74 | { |
75 | extern void weak_function __gmon_start__ (void); |
76 | |
77 | if (__gmon_start__) |
78 | (*__gmon_start__)(); |
79 | } |
80 | |
81 | In a final executable, PLABEL32 relocations for function pointers are |
82 | resolved at link time. Typically, binutils/ld resolves __gmon_start__ |
83 | using an external shared library. __gmon_start__ is always called if |
84 | it is found at link time. If __gmon_start__ is not found at runtime |
85 | due to a library update, then the function pointer will point at a null |
86 | function descriptor and calling it will cause a segmentation fault. |
87 | So, we call __canonicalize_funcptr_for_compare to obtain the canonicalized |
88 | address of __gmon_start__ and skip calling __gmon_start__ if it is zero. |
89 | |
90 | */ |
91 | .type __canonicalize_funcptr_for_compare,@function |
92 | .type $$dyncall,@function |
93 | |
94 | .section .data.rel.ro,"aw" ,@progbits |
95 | .align 4 |
96 | .LC0: |
97 | .type __gmon_start__,@function |
98 | .word P%__gmon_start__ |
99 | |
100 | .text |
101 | .align 4 |
102 | .type gmon_initializer,@function |
103 | gmon_initializer: |
104 | .PROC |
105 | .CALLINFO FRAME=64,CALLS,SAVE_RP,ENTRY_GR=4 |
106 | .ENTRY |
107 | stw %r2,-20(%r30) |
108 | stwm %r4,64(%r30) |
109 | stw %r3,-60(%r30) |
110 | addil LT'.LC0,%r19 |
111 | ldw RT'.LC0(%r1),%r28 |
112 | ldw 0(%r28),%r3 |
113 | comib,= 0,%r3,1f |
114 | copy %r19,%r4 |
115 | stw %r19,-32(%r30) |
116 | bl __canonicalize_funcptr_for_compare,%r2 |
117 | copy %r3,%r26 |
118 | comib,= 0,%r28,1f |
119 | copy %r4,%r19 |
120 | copy %r3,%r22 |
121 | .CALL ARGW0=GR |
122 | bl $$dyncall,%r31 |
123 | copy %r31,%r2 |
124 | 1: |
125 | ldw -84(%r30),%r2 |
126 | ldw -60(%r30),%r3 |
127 | bv %r0(%r2) |
128 | ldwm -64(%r30),%r4 |
129 | .EXIT |
130 | .PROCEND |
131 | .size gmon_initializer, .-gmon_initializer |
132 | |
133 | # undef PREINIT_FUNCTION |
134 | # define PREINIT_FUNCTION gmon_initializer |
135 | #endif |
136 | |
137 | .section .init_array, "aw" |
138 | .word P% PREINIT_FUNCTION |
139 | |
140 | |
141 | /* _init prologue. */ |
142 | .section .init, "ax" , %progbits |
143 | .align 4 |
144 | .globl _init |
145 | .hidden _init |
146 | .type _init,@function |
147 | _init: |
148 | stw %rp,-20(%sp) |
149 | stwm %r4,64(%sp) |
150 | stw %r19,-32(%sp) |
151 | |
152 | /* _fini prologue. */ |
153 | .section .fini,"ax" ,%progbits |
154 | .align 4 |
155 | .globl _fini |
156 | .hidden _fini |
157 | .type _fini,@function |
158 | _fini: |
159 | stw %rp,-20(%sp) |
160 | stwm %r4,64(%sp) |
161 | stw %r19,-32(%sp) |
162 | copy %r19,%r4 |
163 | |