summaryrefslogtreecommitdiff
path: root/csu/initfini.c
blob: dc78e84c2d347183c53d26fd600cdc975ebb5ac0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/* Special .init and .fini section support.
   Copyright (C) 1995, 1996 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it
   and/or modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   In addition to the permissions in the GNU Library General Public
   License, the Free Software Foundation gives you unlimited
   permission to link the compiled version of this file with other
   programs, and to distribute those programs without any restriction
   coming from the use of this file.  (The Libraty General Public
   License restrictions do apply in other respects; for example, they
   cover modification of the file, and distribution when not linked
   into another program.)

   The GNU C Library is distributed in the hope that it will be
   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the GNU C Library; see the file COPYING.LIB.  If not,
   write to the Free Software Foundation, 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */

/* This file is compiled into assembly code which is then surrounded by the
   lines `cat > crtcommon.tmp <<\EOF_common' and `EOF_common' and thus
   becomes a shell script which creates three files of assembly code.

   * The first file is crti.s-new; this puts a function prologue at the
   beginning of the .init and .fini sections and defines global symbols for
   those addresses, so they can be called as functions.

   * The second file is crtn.s-new; this puts the corresponding function
   epilogues in the .init and .fini sections.

   * The third file is crtcommon.tmp, which is whatever miscellaneous cruft
   the compiler generated at the end; it should be appended to both crti.s-new
   and crtn.s-new.  */

#include <stdlib.h>


#ifdef HAVE_ELF
/* These declarations make the functions go in the right sections when
   we define them below.  GCC syntax does not allow the attribute
   specifications to be in the function definitions themselves.  */
void _init (void) __attribute__ ((section (".init")));
void _fini (void) __attribute__ ((section (".fini")));

#define SECTION(x)		/* Put nothing extra before the defn.  */

#else
/* Some non-ELF systems support .init and .fini sections,
   but the __attribute__ syntax only works for ELF.  */
#define SECTION(x) asm (".section " x);
#endif

/* End the here document containing the initial common code.
   Then move the output file crtcommon.tmp to crti.s-new and crtn.s-new.  */
asm ("\nEOF_common\n\
rm -f crti.s-new crtn.s-new\n\
mv crtcommon.tmp crti.s-new\n\
cp crti.s-new crtn.s-new");

/* Extract a `.end' if one is produced by the compiler.  */
asm ("fgrep .end >/dev/null 2>&1 <<\\EOF.end && need_end=yes");
void
useless_function (void)
{
  return;
}
asm ("\nEOF.end\n");

/* Find out how much alignment is produced by the compiler.  */
asm ("align=`awk '$1==\".align\" { if ($2>max) max=$2; } END { print max; }' \
<<\\EOF.align");
void
useless_function2 (void (*foo) (void))
{
  if (foo)
    (*foo) ();
}
asm ("\nEOF.align\n`\n");

/* Append the .init prologue to crti.s-new.  */
asm ("cat >> crti.s-new <<\\EOF.crti.init");

SECTION (".init")
void
_init (void)
{
  /* We cannot use the normal constructor mechanism in gcrt1.o because it
     appears before crtbegin.o in the link, so the header elt of .ctors
     would come after the elt for __gmon_start__.  One approach is for
     gcrt1.o to reference a symbol which would be defined by some library
     module which has a constructor; but then user code's constructors
     would come first, and not be profiled.  */
  extern void __gmon_start__ (void); weak_extern (__gmon_start__)
  if (__gmon_start__)
    __gmon_start__ ();

  /* End the here document containing the .init prologue code.
     Then fetch the .section directive just written and append that
     to crtn.s-new, followed by the function epilogue.  */
  asm ("\n\
EOF.crti.init\n\
	test -n \"$align\" && echo .align $align >> crti.s-new\n\
	test -n \"$need_end\" && echo .end _init >> crti.s-new\n\
	fgrep .init crti.s-new >>crtn.s-new\n\
	fgrep -v .end >> crtn.s-new <<\\EOF.crtn.init");
}

/* End the here document containing the .init epilogue code.
   Then append the .fini prologue to crti.s-new.  */
asm ("\nEOF.crtn.init\
\n\
cat >> crti.s-new <<\\EOF.crti.fini");

SECTION (".fini")
void
_fini (void)
{
  /* End the here document containing the .fini prologue code.
     Then fetch the .section directive just written and append that
     to crtn.s-new, followed by the function epilogue.  */
  asm ("\nEOF.crti.fini\n\
test -n \"$align\" && echo .align $align >> crti.s-new\n\
test -n \"$need_end\" && echo .end _fini >> crti.s-new\n\
cat > /dev/null <<\\EOF.fini.skip");

  {
    /* Let GCC know that _fini is not a leaf function by having a dummy
       function call here.  We arrange for this call to be omitted from
       either crt file.  */
    extern void i_am_not_a_leaf (void);
    i_am_not_a_leaf ();
  }

  asm ("\nEOF.fini.skip\
\n\
	fgrep .fini crti.s-new >>crtn.s-new\n\
	fgrep -v .end >> crtn.s-new <<\\EOF.crtn.fini");
}

/* End the here document containing the .fini epilogue code.
   Finally, put the remainder of the generated assembly into crtcommon.tmp.  */
asm ("\nEOF.crtn.fini\
\n\
cat > crtcommon.tmp <<\\EOF_common");