Commit | Line | Data |
---|---|---|
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 | ||
47 | extern char *mktemp (char *template); | |
48 | ||
49 | /* Linked lists of constructor and destructor names. */ | |
50 | ||
51 | struct id | |
52 | { | |
53 | char *name; | |
54 | struct id *next; | |
55 | }; | |
56 | ||
57 | /* Main program. */ | |
58 | ||
59 | main (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 | ||
148 | write_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 | ||
222 | count_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 | ||
235 | write_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 | ||
245 | fatal_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 | ||
255 | fatal (string) | |
256 | { | |
257 | fprintf (stderr, "\n"); | |
258 | fprintf (stderr, string); | |
259 | fprintf (stderr, "\n"); | |
260 | exit (1); | |
261 | } |