BSD 4_3_Net_2 release
[unix-history] / usr / src / usr.bin / g++ / cc1plus / grot / collect2.c
CommitLineData
6c2961cd
C
1/* Build tables of static constructors and destructors and run ld. */
2
3#include <stdio.h>
4
5#ifdef convex
6
7#define TEXT_SECTION_ASM_OP ".text"
8#define DATA_SECTION_ASM_OP ".data"
9
10#define ASM_GLOBALIZE_LABEL(FILE, LABEL) \
11 fprintf (FILE, ".globl _%s\n", LABEL)
12
13#define ASM_OUTPUT_LABEL(FILE, LABEL) \
14 fprintf (FILE, "_%s:", LABEL)
15
16#define ASM_OUTPUT_LABELREF(FILE, LABEL) \
17 fprintf (FILE, "\tds.w _%s\n", LABEL)
18
19#define ASM_OUTPUT_INT(FILE, INT) \
20 fprintf (FILE, "\tds.w %d\n", INT)
21
22#endif
23
24#ifdef MASSCOMP
25
26#define TEXT_SECTION_ASM_OP ".text"
27#define DATA_SECTION_ASM_OP ".data"
28
29#define ASM_GLOBALIZE_LABEL(FILE, LABEL) \
30 fprintf (FILE, ".globl _%s\n", LABEL)
31
32#define ASM_OUTPUT_LABEL(FILE, LABEL) \
33 fprintf (FILE, "_%s:\n", LABEL)
34
35#define ASM_OUTPUT_LABELREF(FILE, LABEL) \
36 fprintf (FILE, "\t.long _%s\n", LABEL)
37
38#define ASM_OUTPUT_INT(FILE, INT) \
39 fprintf (FILE, "\t.long %d\n", INT)
40
41#endif
42
43#if defined (__GNUC__) || defined (sparc)
44#define alloca __builtin_alloca
45#endif
46
47extern char *mktemp (char *template);
48
49/* Linked lists of constructor and destructor names. */
50
51struct id
52{
53 char *name;
54 struct id *next;
55};
56
57/* Main program. */
58
59main (int argc, char *argv[])
60{
61 static char codexxx[] = "/tmp/codeXXXXXX";
62 static char asxxx[] = "/tmp/asXXXXXX";
63 char *codefile, *hookfile, hooksfile[40], hookofile[40];
64 char *outfile = "a.out";
65 char *arg, ldargs[1024], cmd[1024];
66 FILE *inf, *outf;
67
68 /* Make temp file names. */
69
70 codefile = mktemp (codexxx);
71 hookfile = mktemp (asxxx);
72 sprintf (hooksfile, "%s.s", hookfile);
73 sprintf (hookofile, "%s.o", hookfile);
74
75 /* Parse arguments. Remove output file spec, pass the rest to ld. */
76
77 ldargs[0] = '\0';
78 while (arg = *++argv)
79 {
80 if (! strcmp (arg, "-o"))
81 outfile = *++argv;
82 else
83 {
84#ifdef masscomp
85 if ( *arg == '-' && *(arg+1) == 'L' )
86 {
87 strcat (ldargs, " -L ");
88 strcat (ldargs, arg+2);
89 }
90 else
91 {
92 strcat (ldargs, " ");
93 strcat (ldargs, arg);
94 }
95#else
96 strcat (ldargs, " ");
97 strcat (ldargs, arg);
98#endif
99 }
100 }
101
102 /* Load the program, searching all libraries.
103 Use -r to save the output as a relocatable file.
104 Examine the namelist with nm and search it for static constructors
105 and destructors to call.
106 Write the constructor and destructor tables to a .s file. */
107
108#ifdef masscomp
109/*
110 sprintf (cmd, "ld -r -o %s %s", codefile, ldargs);
111 if (system(cmd))
112 fatal( "##F-ld: Cannot perform link." );
113 sprintf (cmd, "nm -p %s", codefile);
114*/
115 sprintf (cmd, "ld -r -o %s %s && nm -p %s", codefile, ldargs, codefile);
116#else
117 sprintf (cmd, "ld -r -o %s %s && nm -p %s", codefile, ldargs, codefile);
118#endif
119
120 if (! (inf = popen (cmd, "r")))
121 fatal_perror ("Can't open pipe to ld\n");
122 if (! (outf = fopen (hooksfile, "w")))
123 fatal_perror ("Can't write %s\n", hooksfile);
124
125 write_hooks (inf, outf);
126
127 if (pclose (inf) || fclose (outf))
128 fatal ("load failed");
129
130 /* Assemble the constructor and destructor tables.
131 Link the tables in with the rest of the program. */
132
133 sprintf (cmd, "as -o %s %s && ld -o %s %s %s && rm %s %s %s",
134 hookofile, hooksfile,
135 outfile, codefile, hookofile,
136 codefile, hooksfile, hookofile);
137 exit (system (cmd));
138}
139
140/* Scan the name list of the loaded program for the symbols g++ uses
141 for static constructors and destructors. Write their addresses
142 into tables which __main and exit will call.
143
144 The constructor table __CTOR_LIST__ is an integer count followed by
145 that many pointers to constructor functions. The destructor table
146 __DTOR_LIST__ is the same thing, followed by a zero word. */
147
148write_hooks (FILE *inf, FILE *outf)
149{
150 char *p, buf[1024];
151 struct id *newid;
152
153 struct id *constructors = 0;
154 struct id *destructors = 0;
155
156 while (! feof (inf)) {
157
158 /* Read a line of nm output and strip the trailing newline. */
159
160 fgets (buf, sizeof buf, inf);
161 p = buf + strlen (buf) - 1;
162 if (*p == '\n')
163 *p = '\0';
164
165#ifdef masscomp
166 /* If loader spits out an error/warning message then
167 ** lets display it.
168 */
169 if (buf[0] == '#' && buf[1] == '#')
170 {
171 fprintf( stderr, "%s\n", buf );
172 buf[0] = '\0';
173 }
174#endif
175
176 /* If it contains a constructor or destructor name, add the name
177 to the appropriate list. */
178
179 for (p = buf; *p; p++)
180 {
181 while (*p && *p != '_')
182 p++;
183 if (! strncmp (p, "_GLOBAL_$I$", 11))
184 {
185 newid = alloca (sizeof *newid);
186 newid->name = alloca (strlen (p) + 1);
187 strcpy (newid->name, p);
188 newid->next = constructors;
189 constructors = newid;
190 break;
191 }
192 else if (! strncmp (p, "_GLOBAL_$D$", 11))
193 {
194 newid = alloca (sizeof *newid);
195 newid->name = alloca (strlen (p) + 1);
196 strcpy (newid->name, p);
197 newid->next = destructors;
198 destructors = newid;
199 break;
200 }
201 }
202 }
203
204 /* Write the tables. */
205
206 fprintf (outf, "%s\n", TEXT_SECTION_ASM_OP);
207 ASM_GLOBALIZE_LABEL (outf, "__CTOR_LIST__");
208 ASM_OUTPUT_LABEL (outf, "__CTOR_LIST__");
209 ASM_OUTPUT_INT (outf, count_list (constructors));
210 write_list (outf, constructors);
211
212 fprintf (outf, "%s\n", DATA_SECTION_ASM_OP);
213 ASM_GLOBALIZE_LABEL (outf, "__DTOR_LIST__");
214 ASM_OUTPUT_LABEL (outf, "__DTOR_LIST__");
215 ASM_OUTPUT_INT (outf, count_list (destructors));
216 write_list (outf, destructors);
217 ASM_OUTPUT_INT (outf, 0);
218}
219
220/* Length of list LIST. */
221
222count_list (struct id *list)
223{
224 int count = 0;
225 while (list)
226 {
227 count++;
228 list = list->next;
229 }
230 return count;
231}
232
233/* Write the names on list LIST, in reverse order. */
234
235write_list (FILE *outf, struct id *list)
236{
237 if (! list)
238 return;
239 write_list (outf, list->next);
240 ASM_OUTPUT_LABELREF (outf, list->name);
241}
242
243/* Die when sys call fails. */
244
245fatal_perror (string, arg)
246{
247 char buf[80];
248 sprintf (buf, string, arg);
249 perror (buf);
250 exit (1);
251}
252
253/* Just die. */
254
255fatal (string)
256{
257 fprintf (stderr, "\n");
258 fprintf (stderr, string);
259 fprintf (stderr, "\n");
260 exit (1);
261}