1/* .init/.fini section handling + C++ global constructor/destructor handling.
2   This file is based on crtstuff.c, sol2-crti.asm, sol2-crtn.asm.
3
4   Copyright (C) 1995-2020 Free Software Foundation, Inc.
5   Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
6		on behalf of Synopsys Inc.
7
8This file is part of GCC.
9
10GCC is free software; you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation; either version 3, or (at your option)
13any later version.
14
15GCC is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18GNU General Public License for more details.
19
20Under Section 7 of GPL version 3, you are granted additional
21permissions described in the GCC Runtime Library Exception, version
223.1, as published by the Free Software Foundation.
23
24You should have received a copy of the GNU General Public License and
25a copy of the GCC Runtime Library Exception along with this program;
26see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
27<http://www.gnu.org/licenses/>.  */
28
29/*  Declare a pointer to void function type.  */
30typedef void (*func_ptr) (void);
31
32#ifdef CRT_INIT
33
34/* NOTE:  In order to be able to support SVR4 shared libraries, we arrange
35   to have one set of symbols { __CTOR_LIST__, __DTOR_LIST__, __CTOR_END__,
36   __DTOR_END__ } per root executable and also one set of these symbols
37   per shared library.  So in any given whole process image, we may have
38   multiple definitions of each of these symbols.  In order to prevent
39   these definitions from conflicting with one another, and in order to
40   ensure that the proper lists are used for the initialization/finalization
41   of each individual shared library (respectively), we give these symbols
42   only internal (i.e. `static') linkage, and we also make it a point to
43   refer to only the __CTOR_END__ symbol in crtfini.o and the __DTOR_LIST__
44   symbol in crtinit.o, where they are defined.  */
45
46static func_ptr __CTOR_LIST__[1] __attribute__ ((section (".ctors")))
47     = { (func_ptr) (-1) };
48
49static func_ptr __DTOR_LIST__[1] __attribute__ ((section (".dtors")))
50     = { (func_ptr) (-1) };
51
52/* Run all the global destructors on exit from the program.  */
53
54/* Some systems place the number of pointers in the first word of the
55   table.  On SVR4 however, that word is -1.  In all cases, the table is
56   null-terminated.  On SVR4, we start from the beginning of the list and
57   invoke each per-compilation-unit destructor routine in order
58   until we find that null.
59
60   Note that this function MUST be static.  There will be one of these
61   functions in each root executable and one in each shared library, but
62   although they all have the same code, each one is unique in that it
63   refers to one particular associated `__DTOR_LIST__' which belongs to the
64   same particular root executable or shared library file.  */
65
66static void __do_global_dtors (void)
67asm ("__do_global_dtors") __attribute__ ((section (".text")));
68
69static void
70__do_global_dtors (void)
71{
72  func_ptr *p;
73  for (p = __DTOR_LIST__ + 1; *p; p++)
74    (*p) ();
75}
76
77/* .init section start.
78   This must appear at the start of the .init section.  */
79
80asm ("\n\
81	.section .init\n\
82	.global init\n\
83	.word 0\n\
84init:\n\
85	st blink,[sp,4]\n\
86	st fp,[sp]\n\
87	mov fp,sp\n\
88	sub sp,sp,16\n\
89");
90
91/* .fini section start.
92   This must appear at the start of the .init section.  */
93
94asm ("\n\
95	.section .fini\n\
96	.global fini\n\
97	.word 0\n\
98fini:\n\
99	st blink,[sp,4]\n\
100	st fp,[sp]\n\
101	mov fp,sp\n\
102	sub sp,sp,16\n\
103	bl.nd __do_global_dtors\n\
104");
105
106#endif /* CRT_INIT */
107
108#ifdef CRT_FINI
109
110/* Put a word containing zero at the end of each of our two lists of function
111   addresses.  Note that the words defined here go into the .ctors and .dtors
112   sections of the crtend.o file, and since that file is always linked in
113   last, these words naturally end up at the very ends of the two lists
114   contained in these two sections.  */
115
116static func_ptr __CTOR_END__[1] __attribute__ ((section (".ctors")))
117     = { (func_ptr) 0 };
118
119static func_ptr __DTOR_END__[1] __attribute__ ((section (".dtors")))
120     = { (func_ptr) 0 };
121
122/* Run all global constructors for the program.
123   Note that they are run in reverse order.  */
124
125static void __do_global_ctors (void)
126asm ("__do_global_ctors") __attribute__ ((section (".text")));
127
128static void
129__do_global_ctors (void)
130{
131  func_ptr *p;
132  for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
133    (*p) ();
134}
135
136/* .init section end.
137   This must live at the end of the .init section.  */
138
139asm ("\n\
140	.section .init\n\
141	bl.nd __do_global_ctors\n\
142	ld blink,[fp,4]\n\
143	j.d blink\n\
144	ld.a fp,[sp,16]\n\
145");
146
147/* .fini section end.
148   This must live at the end of the .fini section.  */
149
150asm ("\n\
151	.section .fini\n\
152	ld blink,[fp,4]\n\
153	j.d blink\n\
154	ld.a fp,[sp,16]\n\
155");
156
157#endif /* CRT_FINI */
158