0
|
1 /* Collect static initialization info into data structures that can be
|
|
2 traversed by C++ initialization and finalization routines.
|
|
3 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
|
4 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
|
|
5 Free Software Foundation, Inc.
|
|
6 Contributed by Chris Smith (csmith@convex.com).
|
|
7 Heavily modified by Michael Meissner (meissner@cygnus.com),
|
|
8 Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com).
|
|
9
|
|
10 This file is part of GCC.
|
|
11
|
|
12 GCC is free software; you can redistribute it and/or modify it under
|
|
13 the terms of the GNU General Public License as published by the Free
|
|
14 Software Foundation; either version 3, or (at your option) any later
|
|
15 version.
|
|
16
|
|
17 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
18 WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
19 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
20 for more details.
|
|
21
|
|
22 You should have received a copy of the GNU General Public License
|
|
23 along with GCC; see the file COPYING3. If not see
|
|
24 <http://www.gnu.org/licenses/>. */
|
|
25
|
|
26
|
|
27 /* Build tables of static constructors and destructors and run ld. */
|
|
28
|
|
29 #include "config.h"
|
|
30 #include "system.h"
|
|
31 #include "coretypes.h"
|
|
32 #include "tm.h"
|
|
33 #include <signal.h>
|
|
34 #if ! defined( SIGCHLD ) && defined( SIGCLD )
|
|
35 # define SIGCHLD SIGCLD
|
|
36 #endif
|
|
37
|
|
38 #ifndef LIBRARY_PATH_ENV
|
|
39 #define LIBRARY_PATH_ENV "LIBRARY_PATH"
|
|
40 #endif
|
|
41
|
|
42 #define COLLECT
|
|
43
|
|
44 #include "collect2.h"
|
|
45 #include "demangle.h"
|
|
46 #include "obstack.h"
|
|
47 #include "intl.h"
|
|
48 #include "version.h"
|
|
49
|
|
50 /* On certain systems, we have code that works by scanning the object file
|
|
51 directly. But this code uses system-specific header files and library
|
|
52 functions, so turn it off in a cross-compiler. Likewise, the names of
|
|
53 the utilities are not correct for a cross-compiler; we have to hope that
|
|
54 cross-versions are in the proper directories. */
|
|
55
|
|
56 #ifdef CROSS_DIRECTORY_STRUCTURE
|
|
57 #undef OBJECT_FORMAT_COFF
|
|
58 #undef MD_EXEC_PREFIX
|
|
59 #undef REAL_LD_FILE_NAME
|
|
60 #undef REAL_NM_FILE_NAME
|
|
61 #undef REAL_STRIP_FILE_NAME
|
|
62 #endif
|
|
63
|
|
64 /* If we cannot use a special method, use the ordinary one:
|
|
65 run nm to find what symbols are present.
|
|
66 In a cross-compiler, this means you need a cross nm,
|
|
67 but that is not quite as unpleasant as special headers. */
|
|
68
|
|
69 #if !defined (OBJECT_FORMAT_COFF)
|
|
70 #define OBJECT_FORMAT_NONE
|
|
71 #endif
|
|
72
|
|
73 #ifdef OBJECT_FORMAT_COFF
|
|
74
|
|
75 #include <a.out.h>
|
|
76 #include <ar.h>
|
|
77
|
|
78 #ifdef UMAX
|
|
79 #include <sgs.h>
|
|
80 #endif
|
|
81
|
|
82 /* Many versions of ldfcn.h define these. */
|
|
83 #ifdef FREAD
|
|
84 #undef FREAD
|
|
85 #undef FWRITE
|
|
86 #endif
|
|
87
|
|
88 #include <ldfcn.h>
|
|
89
|
|
90 /* Some systems have an ISCOFF macro, but others do not. In some cases
|
|
91 the macro may be wrong. MY_ISCOFF is defined in tm.h files for machines
|
|
92 that either do not have an ISCOFF macro in /usr/include or for those
|
|
93 where it is wrong. */
|
|
94
|
|
95 #ifndef MY_ISCOFF
|
|
96 #define MY_ISCOFF(X) ISCOFF (X)
|
|
97 #endif
|
|
98
|
|
99 #endif /* OBJECT_FORMAT_COFF */
|
|
100
|
|
101 #ifdef OBJECT_FORMAT_NONE
|
|
102
|
|
103 /* Default flags to pass to nm. */
|
|
104 #ifndef NM_FLAGS
|
|
105 #define NM_FLAGS "-n"
|
|
106 #endif
|
|
107
|
|
108 #endif /* OBJECT_FORMAT_NONE */
|
|
109
|
|
110 /* Some systems use __main in a way incompatible with its use in gcc, in these
|
|
111 cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
|
|
112 give the same symbol without quotes for an alternative entry point. */
|
|
113 #ifndef NAME__MAIN
|
|
114 #define NAME__MAIN "__main"
|
|
115 #endif
|
|
116
|
|
117 /* This must match tree.h. */
|
|
118 #define DEFAULT_INIT_PRIORITY 65535
|
|
119
|
|
120 #ifndef COLLECT_SHARED_INIT_FUNC
|
|
121 #define COLLECT_SHARED_INIT_FUNC(STREAM, FUNC) \
|
|
122 fprintf ((STREAM), "void _GLOBAL__DI() {\n\t%s();\n}\n", (FUNC))
|
|
123 #endif
|
|
124 #ifndef COLLECT_SHARED_FINI_FUNC
|
|
125 #define COLLECT_SHARED_FINI_FUNC(STREAM, FUNC) \
|
|
126 fprintf ((STREAM), "void _GLOBAL__DD() {\n\t%s();\n}\n", (FUNC))
|
|
127 #endif
|
|
128
|
|
129 #ifdef LDD_SUFFIX
|
|
130 #define SCAN_LIBRARIES
|
|
131 #endif
|
|
132
|
|
133 #ifndef SHLIB_SUFFIX
|
|
134 #define SHLIB_SUFFIX ".so"
|
|
135 #endif
|
|
136
|
|
137 #ifdef USE_COLLECT2
|
|
138 int do_collecting = 1;
|
|
139 #else
|
|
140 int do_collecting = 0;
|
|
141 #endif
|
|
142
|
|
143 /* Nonzero if we should suppress the automatic demangling of identifiers
|
|
144 in linker error messages. Set from COLLECT_NO_DEMANGLE. */
|
|
145 int no_demangle;
|
|
146
|
|
147 /* Linked lists of constructor and destructor names. */
|
|
148
|
|
149 struct id
|
|
150 {
|
|
151 struct id *next;
|
|
152 int sequence;
|
|
153 char name[1];
|
|
154 };
|
|
155
|
|
156 struct head
|
|
157 {
|
|
158 struct id *first;
|
|
159 struct id *last;
|
|
160 int number;
|
|
161 };
|
|
162
|
|
163 /* Enumeration giving which pass this is for scanning the program file. */
|
|
164
|
|
165 enum pass {
|
|
166 PASS_FIRST, /* without constructors */
|
|
167 PASS_OBJ, /* individual objects */
|
|
168 PASS_LIB, /* looking for shared libraries */
|
|
169 PASS_SECOND /* with constructors linked in */
|
|
170 };
|
|
171
|
|
172 int vflag; /* true if -v */
|
|
173 static int rflag; /* true if -r */
|
|
174 static int strip_flag; /* true if -s */
|
|
175 static const char *demangle_flag;
|
|
176 #ifdef COLLECT_EXPORT_LIST
|
|
177 static int export_flag; /* true if -bE */
|
|
178 static int aix64_flag; /* true if -b64 */
|
|
179 static int aixrtl_flag; /* true if -brtl */
|
|
180 #endif
|
|
181
|
|
182 int debug; /* true if -debug */
|
|
183
|
|
184 static int shared_obj; /* true if -shared */
|
|
185
|
|
186 static const char *c_file; /* <xxx>.c for constructor/destructor list. */
|
|
187 static const char *o_file; /* <xxx>.o for constructor/destructor list. */
|
|
188 #ifdef COLLECT_EXPORT_LIST
|
|
189 static const char *export_file; /* <xxx>.x for AIX export list. */
|
|
190 #endif
|
|
191 const char *ldout; /* File for ld stdout. */
|
|
192 const char *lderrout; /* File for ld stderr. */
|
|
193 static const char *output_file; /* Output file for ld. */
|
|
194 static const char *nm_file_name; /* pathname of nm */
|
|
195 #ifdef LDD_SUFFIX
|
|
196 static const char *ldd_file_name; /* pathname of ldd (or equivalent) */
|
|
197 #endif
|
|
198 static const char *strip_file_name; /* pathname of strip */
|
|
199 const char *c_file_name; /* pathname of gcc */
|
|
200 static char *initname, *fininame; /* names of init and fini funcs */
|
|
201
|
|
202 static struct head constructors; /* list of constructors found */
|
|
203 static struct head destructors; /* list of destructors found */
|
|
204 #ifdef COLLECT_EXPORT_LIST
|
|
205 static struct head exports; /* list of exported symbols */
|
|
206 #endif
|
|
207 static struct head frame_tables; /* list of frame unwind info tables */
|
|
208
|
|
209 static bool at_file_supplied; /* Whether to use @file arguments */
|
|
210 static char *response_file; /* Name of any current response file */
|
|
211
|
|
212 struct obstack temporary_obstack;
|
|
213 char * temporary_firstobj;
|
|
214
|
|
215 /* Structure to hold all the directories in which to search for files to
|
|
216 execute. */
|
|
217
|
|
218 struct prefix_list
|
|
219 {
|
|
220 const char *prefix; /* String to prepend to the path. */
|
|
221 struct prefix_list *next; /* Next in linked list. */
|
|
222 };
|
|
223
|
|
224 struct path_prefix
|
|
225 {
|
|
226 struct prefix_list *plist; /* List of prefixes to try */
|
|
227 int max_len; /* Max length of a prefix in PLIST */
|
|
228 const char *name; /* Name of this list (used in config stuff) */
|
|
229 };
|
|
230
|
|
231 #ifdef COLLECT_EXPORT_LIST
|
|
232 /* Lists to keep libraries to be scanned for global constructors/destructors. */
|
|
233 static struct head libs; /* list of libraries */
|
|
234 static struct path_prefix cmdline_lib_dirs; /* directories specified with -L */
|
|
235 static struct path_prefix libpath_lib_dirs; /* directories in LIBPATH */
|
|
236 static struct path_prefix *libpaths[3] = {&cmdline_lib_dirs,
|
|
237 &libpath_lib_dirs, NULL};
|
|
238 #endif
|
|
239
|
|
240 /* Special kinds of symbols that a name may denote. */
|
|
241
|
|
242 typedef enum {
|
|
243 SYM_REGULAR = 0, /* nothing special */
|
|
244
|
|
245 SYM_CTOR = 1, /* constructor */
|
|
246 SYM_DTOR = 2, /* destructor */
|
|
247 SYM_INIT = 3, /* shared object routine that calls all the ctors */
|
|
248 SYM_FINI = 4, /* shared object routine that calls all the dtors */
|
|
249 SYM_DWEH = 5 /* DWARF exception handling table */
|
|
250 } symkind;
|
|
251
|
|
252 static symkind is_ctor_dtor (const char *);
|
|
253
|
|
254 static void handler (int);
|
|
255 static char *find_a_file (struct path_prefix *, const char *);
|
|
256 static void add_prefix (struct path_prefix *, const char *);
|
|
257 static void prefix_from_env (const char *, struct path_prefix *);
|
|
258 static void prefix_from_string (const char *, struct path_prefix *);
|
|
259 static void do_wait (const char *, struct pex_obj *);
|
|
260 static void fork_execute (const char *, char **);
|
|
261 static void maybe_unlink (const char *);
|
|
262 static void add_to_list (struct head *, const char *);
|
|
263 static int extract_init_priority (const char *);
|
|
264 static void sort_ids (struct head *);
|
|
265 static void write_list (FILE *, const char *, struct id *);
|
|
266 #ifdef COLLECT_EXPORT_LIST
|
|
267 static void dump_list (FILE *, const char *, struct id *);
|
|
268 #endif
|
|
269 #if 0
|
|
270 static void dump_prefix_list (FILE *, const char *, struct prefix_list *);
|
|
271 #endif
|
|
272 static void write_list_with_asm (FILE *, const char *, struct id *);
|
|
273 static void write_c_file (FILE *, const char *);
|
|
274 static void write_c_file_stat (FILE *, const char *);
|
|
275 #ifndef LD_INIT_SWITCH
|
|
276 static void write_c_file_glob (FILE *, const char *);
|
|
277 #endif
|
|
278 static void scan_prog_file (const char *, enum pass);
|
|
279 #ifdef SCAN_LIBRARIES
|
|
280 static void scan_libraries (const char *);
|
|
281 #endif
|
|
282 #if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
|
|
283 static int is_in_args (const char *, const char **, const char **);
|
|
284 #endif
|
|
285 #ifdef COLLECT_EXPORT_LIST
|
|
286 #if 0
|
|
287 static int is_in_list (const char *, struct id *);
|
|
288 #endif
|
|
289 static void write_aix_file (FILE *, struct id *);
|
|
290 static char *resolve_lib_name (const char *);
|
|
291 #endif
|
|
292 static char *extract_string (const char **);
|
|
293
|
|
294 /* Delete tempfiles and exit function. */
|
|
295
|
|
296 void
|
|
297 collect_exit (int status)
|
|
298 {
|
|
299 if (c_file != 0 && c_file[0])
|
|
300 maybe_unlink (c_file);
|
|
301
|
|
302 if (o_file != 0 && o_file[0])
|
|
303 maybe_unlink (o_file);
|
|
304
|
|
305 #ifdef COLLECT_EXPORT_LIST
|
|
306 if (export_file != 0 && export_file[0])
|
|
307 maybe_unlink (export_file);
|
|
308 #endif
|
|
309
|
|
310 if (ldout != 0 && ldout[0])
|
|
311 {
|
|
312 dump_file (ldout, stdout);
|
|
313 maybe_unlink (ldout);
|
|
314 }
|
|
315
|
|
316 if (lderrout != 0 && lderrout[0])
|
|
317 {
|
|
318 dump_file (lderrout, stderr);
|
|
319 maybe_unlink (lderrout);
|
|
320 }
|
|
321
|
|
322 if (status != 0 && output_file != 0 && output_file[0])
|
|
323 maybe_unlink (output_file);
|
|
324
|
|
325 if (response_file)
|
|
326 maybe_unlink (response_file);
|
|
327
|
|
328 exit (status);
|
|
329 }
|
|
330
|
|
331
|
|
332 /* Notify user of a non-error. */
|
|
333 void
|
|
334 notice (const char *cmsgid, ...)
|
|
335 {
|
|
336 va_list ap;
|
|
337
|
|
338 va_start (ap, cmsgid);
|
|
339 vfprintf (stderr, _(cmsgid), ap);
|
|
340 va_end (ap);
|
|
341 }
|
|
342
|
|
343 /* Die when sys call fails. */
|
|
344
|
|
345 void
|
|
346 fatal_perror (const char * cmsgid, ...)
|
|
347 {
|
|
348 int e = errno;
|
|
349 va_list ap;
|
|
350
|
|
351 va_start (ap, cmsgid);
|
|
352 fprintf (stderr, "collect2: ");
|
|
353 vfprintf (stderr, _(cmsgid), ap);
|
|
354 fprintf (stderr, ": %s\n", xstrerror (e));
|
|
355 va_end (ap);
|
|
356
|
|
357 collect_exit (FATAL_EXIT_CODE);
|
|
358 }
|
|
359
|
|
360 /* Just die. */
|
|
361
|
|
362 void
|
|
363 fatal (const char * cmsgid, ...)
|
|
364 {
|
|
365 va_list ap;
|
|
366
|
|
367 va_start (ap, cmsgid);
|
|
368 fprintf (stderr, "collect2: ");
|
|
369 vfprintf (stderr, _(cmsgid), ap);
|
|
370 fprintf (stderr, "\n");
|
|
371 va_end (ap);
|
|
372
|
|
373 collect_exit (FATAL_EXIT_CODE);
|
|
374 }
|
|
375
|
|
376 /* Write error message. */
|
|
377
|
|
378 void
|
|
379 error (const char * gmsgid, ...)
|
|
380 {
|
|
381 va_list ap;
|
|
382
|
|
383 va_start (ap, gmsgid);
|
|
384 fprintf (stderr, "collect2: ");
|
|
385 vfprintf (stderr, _(gmsgid), ap);
|
|
386 fprintf (stderr, "\n");
|
|
387 va_end(ap);
|
|
388 }
|
|
389
|
|
390 /* In case obstack is linked in, and abort is defined to fancy_abort,
|
|
391 provide a default entry. */
|
|
392
|
|
393 void
|
|
394 fancy_abort (const char *file, int line, const char *func)
|
|
395 {
|
|
396 fatal ("internal gcc abort in %s, at %s:%d", func, file, line);
|
|
397 }
|
|
398
|
|
399 static void
|
|
400 handler (int signo)
|
|
401 {
|
|
402 if (c_file != 0 && c_file[0])
|
|
403 maybe_unlink (c_file);
|
|
404
|
|
405 if (o_file != 0 && o_file[0])
|
|
406 maybe_unlink (o_file);
|
|
407
|
|
408 if (ldout != 0 && ldout[0])
|
|
409 maybe_unlink (ldout);
|
|
410
|
|
411 if (lderrout != 0 && lderrout[0])
|
|
412 maybe_unlink (lderrout);
|
|
413
|
|
414 #ifdef COLLECT_EXPORT_LIST
|
|
415 if (export_file != 0 && export_file[0])
|
|
416 maybe_unlink (export_file);
|
|
417 #endif
|
|
418
|
|
419 if (response_file)
|
|
420 maybe_unlink (response_file);
|
|
421
|
|
422 signal (signo, SIG_DFL);
|
|
423 raise (signo);
|
|
424 }
|
|
425
|
|
426
|
|
427 int
|
|
428 file_exists (const char *name)
|
|
429 {
|
|
430 return access (name, R_OK) == 0;
|
|
431 }
|
|
432
|
|
433 /* Parse a reasonable subset of shell quoting syntax. */
|
|
434
|
|
435 static char *
|
|
436 extract_string (const char **pp)
|
|
437 {
|
|
438 const char *p = *pp;
|
|
439 int backquote = 0;
|
|
440 int inside = 0;
|
|
441
|
|
442 for (;;)
|
|
443 {
|
|
444 char c = *p;
|
|
445 if (c == '\0')
|
|
446 break;
|
|
447 ++p;
|
|
448 if (backquote)
|
|
449 obstack_1grow (&temporary_obstack, c);
|
|
450 else if (! inside && c == ' ')
|
|
451 break;
|
|
452 else if (! inside && c == '\\')
|
|
453 backquote = 1;
|
|
454 else if (c == '\'')
|
|
455 inside = !inside;
|
|
456 else
|
|
457 obstack_1grow (&temporary_obstack, c);
|
|
458 }
|
|
459
|
|
460 obstack_1grow (&temporary_obstack, '\0');
|
|
461 *pp = p;
|
|
462 return XOBFINISH (&temporary_obstack, char *);
|
|
463 }
|
|
464
|
|
465 void
|
|
466 dump_file (const char *name, FILE *to)
|
|
467 {
|
|
468 FILE *stream = fopen (name, "r");
|
|
469
|
|
470 if (stream == 0)
|
|
471 return;
|
|
472 while (1)
|
|
473 {
|
|
474 int c;
|
|
475 while (c = getc (stream),
|
|
476 c != EOF && (ISIDNUM (c) || c == '$' || c == '.'))
|
|
477 obstack_1grow (&temporary_obstack, c);
|
|
478 if (obstack_object_size (&temporary_obstack) > 0)
|
|
479 {
|
|
480 const char *word, *p;
|
|
481 char *result;
|
|
482 obstack_1grow (&temporary_obstack, '\0');
|
|
483 word = XOBFINISH (&temporary_obstack, const char *);
|
|
484
|
|
485 if (*word == '.')
|
|
486 ++word, putc ('.', to);
|
|
487 p = word;
|
|
488 if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
|
|
489 p += strlen (USER_LABEL_PREFIX);
|
|
490
|
|
491 #ifdef HAVE_LD_DEMANGLE
|
|
492 result = 0;
|
|
493 #else
|
|
494 if (no_demangle)
|
|
495 result = 0;
|
|
496 else
|
|
497 result = cplus_demangle (p, DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE);
|
|
498 #endif
|
|
499
|
|
500 if (result)
|
|
501 {
|
|
502 int diff;
|
|
503 fputs (result, to);
|
|
504
|
|
505 diff = strlen (word) - strlen (result);
|
|
506 while (diff > 0 && c == ' ')
|
|
507 --diff, putc (' ', to);
|
|
508 if (diff < 0 && c == ' ')
|
|
509 {
|
|
510 while (diff < 0 && c == ' ')
|
|
511 ++diff, c = getc (stream);
|
|
512 if (!ISSPACE (c))
|
|
513 {
|
|
514 /* Make sure we output at least one space, or
|
|
515 the demangled symbol name will run into
|
|
516 whatever text follows. */
|
|
517 putc (' ', to);
|
|
518 }
|
|
519 }
|
|
520
|
|
521 free (result);
|
|
522 }
|
|
523 else
|
|
524 fputs (word, to);
|
|
525
|
|
526 fflush (to);
|
|
527 obstack_free (&temporary_obstack, temporary_firstobj);
|
|
528 }
|
|
529 if (c == EOF)
|
|
530 break;
|
|
531 putc (c, to);
|
|
532 }
|
|
533 fclose (stream);
|
|
534 }
|
|
535
|
|
536 /* Return the kind of symbol denoted by name S. */
|
|
537
|
|
538 static symkind
|
|
539 is_ctor_dtor (const char *s)
|
|
540 {
|
|
541 struct names { const char *const name; const int len; const int ret;
|
|
542 const int two_underscores; };
|
|
543
|
|
544 const struct names *p;
|
|
545 int ch;
|
|
546 const char *orig_s = s;
|
|
547
|
|
548 static const struct names special[] = {
|
|
549 #ifndef NO_DOLLAR_IN_LABEL
|
|
550 { "GLOBAL__I$", sizeof ("GLOBAL__I$")-1, SYM_CTOR, 0 },
|
|
551 { "GLOBAL__D$", sizeof ("GLOBAL__D$")-1, SYM_DTOR, 0 },
|
|
552 #else
|
|
553 #ifndef NO_DOT_IN_LABEL
|
|
554 { "GLOBAL__I.", sizeof ("GLOBAL__I.")-1, SYM_CTOR, 0 },
|
|
555 { "GLOBAL__D.", sizeof ("GLOBAL__D.")-1, SYM_DTOR, 0 },
|
|
556 #endif /* NO_DOT_IN_LABEL */
|
|
557 #endif /* NO_DOLLAR_IN_LABEL */
|
|
558 { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, SYM_CTOR, 0 },
|
|
559 { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, SYM_DTOR, 0 },
|
|
560 { "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, SYM_DWEH, 0 },
|
|
561 { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, SYM_INIT, 0 },
|
|
562 { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, SYM_FINI, 0 },
|
|
563 { NULL, 0, SYM_REGULAR, 0 }
|
|
564 };
|
|
565
|
|
566 while ((ch = *s) == '_')
|
|
567 ++s;
|
|
568
|
|
569 if (s == orig_s)
|
|
570 return SYM_REGULAR;
|
|
571
|
|
572 for (p = &special[0]; p->len > 0; p++)
|
|
573 {
|
|
574 if (ch == p->name[0]
|
|
575 && (!p->two_underscores || ((s - orig_s) >= 2))
|
|
576 && strncmp(s, p->name, p->len) == 0)
|
|
577 {
|
|
578 return p->ret;
|
|
579 }
|
|
580 }
|
|
581 return SYM_REGULAR;
|
|
582 }
|
|
583
|
|
584 /* We maintain two prefix lists: one from COMPILER_PATH environment variable
|
|
585 and one from the PATH variable. */
|
|
586
|
|
587 static struct path_prefix cpath, path;
|
|
588
|
|
589 #ifdef CROSS_DIRECTORY_STRUCTURE
|
|
590 /* This is the name of the target machine. We use it to form the name
|
|
591 of the files to execute. */
|
|
592
|
|
593 static const char *const target_machine = TARGET_MACHINE;
|
|
594 #endif
|
|
595
|
|
596 /* Search for NAME using prefix list PPREFIX. We only look for executable
|
|
597 files.
|
|
598
|
|
599 Return 0 if not found, otherwise return its name, allocated with malloc. */
|
|
600
|
|
601 static char *
|
|
602 find_a_file (struct path_prefix *pprefix, const char *name)
|
|
603 {
|
|
604 char *temp;
|
|
605 struct prefix_list *pl;
|
|
606 int len = pprefix->max_len + strlen (name) + 1;
|
|
607
|
|
608 if (debug)
|
|
609 fprintf (stderr, "Looking for '%s'\n", name);
|
|
610
|
|
611 #ifdef HOST_EXECUTABLE_SUFFIX
|
|
612 len += strlen (HOST_EXECUTABLE_SUFFIX);
|
|
613 #endif
|
|
614
|
|
615 temp = XNEWVEC (char, len);
|
|
616
|
|
617 /* Determine the filename to execute (special case for absolute paths). */
|
|
618
|
|
619 if (IS_ABSOLUTE_PATH (name))
|
|
620 {
|
|
621 if (access (name, X_OK) == 0)
|
|
622 {
|
|
623 strcpy (temp, name);
|
|
624
|
|
625 if (debug)
|
|
626 fprintf (stderr, " - found: absolute path\n");
|
|
627
|
|
628 return temp;
|
|
629 }
|
|
630
|
|
631 #ifdef HOST_EXECUTABLE_SUFFIX
|
|
632 /* Some systems have a suffix for executable files.
|
|
633 So try appending that. */
|
|
634 strcpy (temp, name);
|
|
635 strcat (temp, HOST_EXECUTABLE_SUFFIX);
|
|
636
|
|
637 if (access (temp, X_OK) == 0)
|
|
638 return temp;
|
|
639 #endif
|
|
640
|
|
641 if (debug)
|
|
642 fprintf (stderr, " - failed to locate using absolute path\n");
|
|
643 }
|
|
644 else
|
|
645 for (pl = pprefix->plist; pl; pl = pl->next)
|
|
646 {
|
|
647 struct stat st;
|
|
648
|
|
649 strcpy (temp, pl->prefix);
|
|
650 strcat (temp, name);
|
|
651
|
|
652 if (stat (temp, &st) >= 0
|
|
653 && ! S_ISDIR (st.st_mode)
|
|
654 && access (temp, X_OK) == 0)
|
|
655 return temp;
|
|
656
|
|
657 #ifdef HOST_EXECUTABLE_SUFFIX
|
|
658 /* Some systems have a suffix for executable files.
|
|
659 So try appending that. */
|
|
660 strcat (temp, HOST_EXECUTABLE_SUFFIX);
|
|
661
|
|
662 if (stat (temp, &st) >= 0
|
|
663 && ! S_ISDIR (st.st_mode)
|
|
664 && access (temp, X_OK) == 0)
|
|
665 return temp;
|
|
666 #endif
|
|
667 }
|
|
668
|
|
669 if (debug && pprefix->plist == NULL)
|
|
670 fprintf (stderr, " - failed: no entries in prefix list\n");
|
|
671
|
|
672 free (temp);
|
|
673 return 0;
|
|
674 }
|
|
675
|
|
676 /* Add an entry for PREFIX to prefix list PPREFIX. */
|
|
677
|
|
678 static void
|
|
679 add_prefix (struct path_prefix *pprefix, const char *prefix)
|
|
680 {
|
|
681 struct prefix_list *pl, **prev;
|
|
682 int len;
|
|
683
|
|
684 if (pprefix->plist)
|
|
685 {
|
|
686 for (pl = pprefix->plist; pl->next; pl = pl->next)
|
|
687 ;
|
|
688 prev = &pl->next;
|
|
689 }
|
|
690 else
|
|
691 prev = &pprefix->plist;
|
|
692
|
|
693 /* Keep track of the longest prefix. */
|
|
694
|
|
695 len = strlen (prefix);
|
|
696 if (len > pprefix->max_len)
|
|
697 pprefix->max_len = len;
|
|
698
|
|
699 pl = XNEW (struct prefix_list);
|
|
700 pl->prefix = xstrdup (prefix);
|
|
701
|
|
702 if (*prev)
|
|
703 pl->next = *prev;
|
|
704 else
|
|
705 pl->next = (struct prefix_list *) 0;
|
|
706 *prev = pl;
|
|
707 }
|
|
708
|
|
709 /* Take the value of the environment variable ENV, break it into a path, and
|
|
710 add of the entries to PPREFIX. */
|
|
711
|
|
712 static void
|
|
713 prefix_from_env (const char *env, struct path_prefix *pprefix)
|
|
714 {
|
|
715 const char *p;
|
|
716 GET_ENVIRONMENT (p, env);
|
|
717
|
|
718 if (p)
|
|
719 prefix_from_string (p, pprefix);
|
|
720 }
|
|
721
|
|
722 static void
|
|
723 prefix_from_string (const char *p, struct path_prefix *pprefix)
|
|
724 {
|
|
725 const char *startp, *endp;
|
|
726 char *nstore = XNEWVEC (char, strlen (p) + 3);
|
|
727
|
|
728 if (debug)
|
|
729 fprintf (stderr, "Convert string '%s' into prefixes, separator = '%c'\n", p, PATH_SEPARATOR);
|
|
730
|
|
731 startp = endp = p;
|
|
732 while (1)
|
|
733 {
|
|
734 if (*endp == PATH_SEPARATOR || *endp == 0)
|
|
735 {
|
|
736 strncpy (nstore, startp, endp-startp);
|
|
737 if (endp == startp)
|
|
738 {
|
|
739 strcpy (nstore, "./");
|
|
740 }
|
|
741 else if (! IS_DIR_SEPARATOR (endp[-1]))
|
|
742 {
|
|
743 nstore[endp-startp] = DIR_SEPARATOR;
|
|
744 nstore[endp-startp+1] = 0;
|
|
745 }
|
|
746 else
|
|
747 nstore[endp-startp] = 0;
|
|
748
|
|
749 if (debug)
|
|
750 fprintf (stderr, " - add prefix: %s\n", nstore);
|
|
751
|
|
752 add_prefix (pprefix, nstore);
|
|
753 if (*endp == 0)
|
|
754 break;
|
|
755 endp = startp = endp + 1;
|
|
756 }
|
|
757 else
|
|
758 endp++;
|
|
759 }
|
|
760 free (nstore);
|
|
761 }
|
|
762
|
|
763 /* Main program. */
|
|
764
|
|
765 int
|
|
766 main (int argc, char **argv)
|
|
767 {
|
|
768 static const char *const ld_suffix = "ld";
|
|
769 static const char *const real_ld_suffix = "real-ld";
|
|
770 static const char *const collect_ld_suffix = "collect-ld";
|
|
771 static const char *const nm_suffix = "nm";
|
|
772 static const char *const gnm_suffix = "gnm";
|
|
773 #ifdef LDD_SUFFIX
|
|
774 static const char *const ldd_suffix = LDD_SUFFIX;
|
|
775 #endif
|
|
776 static const char *const strip_suffix = "strip";
|
|
777 static const char *const gstrip_suffix = "gstrip";
|
|
778
|
|
779 #ifdef CROSS_DIRECTORY_STRUCTURE
|
|
780 /* If we look for a program in the compiler directories, we just use
|
|
781 the short name, since these directories are already system-specific.
|
|
782 But it we look for a program in the system directories, we need to
|
|
783 qualify the program name with the target machine. */
|
|
784
|
|
785 const char *const full_ld_suffix =
|
|
786 concat(target_machine, "-", ld_suffix, NULL);
|
|
787 const char *const full_nm_suffix =
|
|
788 concat (target_machine, "-", nm_suffix, NULL);
|
|
789 const char *const full_gnm_suffix =
|
|
790 concat (target_machine, "-", gnm_suffix, NULL);
|
|
791 #ifdef LDD_SUFFIX
|
|
792 const char *const full_ldd_suffix =
|
|
793 concat (target_machine, "-", ldd_suffix, NULL);
|
|
794 #endif
|
|
795 const char *const full_strip_suffix =
|
|
796 concat (target_machine, "-", strip_suffix, NULL);
|
|
797 const char *const full_gstrip_suffix =
|
|
798 concat (target_machine, "-", gstrip_suffix, NULL);
|
|
799 #else
|
|
800 const char *const full_ld_suffix = ld_suffix;
|
|
801 const char *const full_nm_suffix = nm_suffix;
|
|
802 const char *const full_gnm_suffix = gnm_suffix;
|
|
803 #ifdef LDD_SUFFIX
|
|
804 const char *const full_ldd_suffix = ldd_suffix;
|
|
805 #endif
|
|
806 const char *const full_strip_suffix = strip_suffix;
|
|
807 const char *const full_gstrip_suffix = gstrip_suffix;
|
|
808 #endif /* CROSS_DIRECTORY_STRUCTURE */
|
|
809
|
|
810 const char *arg;
|
|
811 FILE *outf;
|
|
812 #ifdef COLLECT_EXPORT_LIST
|
|
813 FILE *exportf;
|
|
814 #endif
|
|
815 const char *ld_file_name;
|
|
816 const char *p;
|
|
817 char **c_argv;
|
|
818 const char **c_ptr;
|
|
819 char **ld1_argv;
|
|
820 const char **ld1;
|
|
821 char **ld2_argv;
|
|
822 const char **ld2;
|
|
823 char **object_lst;
|
|
824 const char **object;
|
|
825 int first_file;
|
|
826 int num_c_args;
|
|
827 char **old_argv;
|
|
828
|
|
829 old_argv = argv;
|
|
830 expandargv (&argc, &argv);
|
|
831 if (argv != old_argv)
|
|
832 at_file_supplied = 1;
|
|
833
|
|
834 num_c_args = argc + 9;
|
|
835
|
|
836 no_demangle = !! getenv ("COLLECT_NO_DEMANGLE");
|
|
837
|
|
838 /* Suppress demangling by the real linker, which may be broken. */
|
|
839 putenv (xstrdup ("COLLECT_NO_DEMANGLE="));
|
|
840
|
|
841 #if defined (COLLECT2_HOST_INITIALIZATION)
|
|
842 /* Perform system dependent initialization, if necessary. */
|
|
843 COLLECT2_HOST_INITIALIZATION;
|
|
844 #endif
|
|
845
|
|
846 #ifdef SIGCHLD
|
|
847 /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
|
|
848 receive the signal. A different setting is inheritable */
|
|
849 signal (SIGCHLD, SIG_DFL);
|
|
850 #endif
|
|
851
|
|
852 /* Unlock the stdio streams. */
|
|
853 unlock_std_streams ();
|
|
854
|
|
855 gcc_init_libintl ();
|
|
856
|
|
857 /* Do not invoke xcalloc before this point, since locale needs to be
|
|
858 set first, in case a diagnostic is issued. */
|
|
859
|
|
860 ld1 = (const char **)(ld1_argv = XCNEWVEC (char *, argc+4));
|
|
861 ld2 = (const char **)(ld2_argv = XCNEWVEC (char *, argc+11));
|
|
862 object = (const char **)(object_lst = XCNEWVEC (char *, argc));
|
|
863
|
|
864 #ifdef DEBUG
|
|
865 debug = 1;
|
|
866 #endif
|
|
867
|
|
868 /* Parse command line early for instances of -debug. This allows
|
|
869 the debug flag to be set before functions like find_a_file()
|
|
870 are called. */
|
|
871 {
|
|
872 int i;
|
|
873
|
|
874 for (i = 1; argv[i] != NULL; i ++)
|
|
875 {
|
|
876 if (! strcmp (argv[i], "-debug"))
|
|
877 debug = 1;
|
|
878 }
|
|
879 vflag = debug;
|
|
880 }
|
|
881
|
|
882 #ifndef DEFAULT_A_OUT_NAME
|
|
883 output_file = "a.out";
|
|
884 #else
|
|
885 output_file = DEFAULT_A_OUT_NAME;
|
|
886 #endif
|
|
887
|
|
888 obstack_begin (&temporary_obstack, 0);
|
|
889 temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0);
|
|
890
|
|
891 #ifndef HAVE_LD_DEMANGLE
|
|
892 current_demangling_style = auto_demangling;
|
|
893 #endif
|
|
894 p = getenv ("COLLECT_GCC_OPTIONS");
|
|
895 while (p && *p)
|
|
896 {
|
|
897 const char *q = extract_string (&p);
|
|
898 if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
|
|
899 num_c_args++;
|
|
900 }
|
|
901 obstack_free (&temporary_obstack, temporary_firstobj);
|
|
902
|
|
903 /* -fno-profile-arcs -fno-test-coverage -fno-branch-probabilities
|
|
904 -fno-exceptions -w */
|
|
905 num_c_args += 5;
|
|
906
|
|
907 c_ptr = (const char **) (c_argv = XCNEWVEC (char *, num_c_args));
|
|
908
|
|
909 if (argc < 2)
|
|
910 fatal ("no arguments");
|
|
911
|
|
912 #ifdef SIGQUIT
|
|
913 if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
|
|
914 signal (SIGQUIT, handler);
|
|
915 #endif
|
|
916 if (signal (SIGINT, SIG_IGN) != SIG_IGN)
|
|
917 signal (SIGINT, handler);
|
|
918 #ifdef SIGALRM
|
|
919 if (signal (SIGALRM, SIG_IGN) != SIG_IGN)
|
|
920 signal (SIGALRM, handler);
|
|
921 #endif
|
|
922 #ifdef SIGHUP
|
|
923 if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
|
|
924 signal (SIGHUP, handler);
|
|
925 #endif
|
|
926 if (signal (SIGSEGV, SIG_IGN) != SIG_IGN)
|
|
927 signal (SIGSEGV, handler);
|
|
928 #ifdef SIGBUS
|
|
929 if (signal (SIGBUS, SIG_IGN) != SIG_IGN)
|
|
930 signal (SIGBUS, handler);
|
|
931 #endif
|
|
932
|
|
933 /* Extract COMPILER_PATH and PATH into our prefix list. */
|
|
934 prefix_from_env ("COMPILER_PATH", &cpath);
|
|
935 prefix_from_env ("PATH", &path);
|
|
936
|
|
937 /* Try to discover a valid linker/nm/strip to use. */
|
|
938
|
|
939 /* Maybe we know the right file to use (if not cross). */
|
|
940 ld_file_name = 0;
|
|
941 #ifdef DEFAULT_LINKER
|
|
942 if (access (DEFAULT_LINKER, X_OK) == 0)
|
|
943 ld_file_name = DEFAULT_LINKER;
|
|
944 if (ld_file_name == 0)
|
|
945 #endif
|
|
946 #ifdef REAL_LD_FILE_NAME
|
|
947 ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME);
|
|
948 if (ld_file_name == 0)
|
|
949 #endif
|
|
950 /* Search the (target-specific) compiler dirs for ld'. */
|
|
951 ld_file_name = find_a_file (&cpath, real_ld_suffix);
|
|
952 /* Likewise for `collect-ld'. */
|
|
953 if (ld_file_name == 0)
|
|
954 ld_file_name = find_a_file (&cpath, collect_ld_suffix);
|
|
955 /* Search the compiler directories for `ld'. We have protection against
|
|
956 recursive calls in find_a_file. */
|
|
957 if (ld_file_name == 0)
|
|
958 ld_file_name = find_a_file (&cpath, ld_suffix);
|
|
959 /* Search the ordinary system bin directories
|
|
960 for `ld' (if native linking) or `TARGET-ld' (if cross). */
|
|
961 if (ld_file_name == 0)
|
|
962 ld_file_name = find_a_file (&path, full_ld_suffix);
|
|
963
|
|
964 #ifdef REAL_NM_FILE_NAME
|
|
965 nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME);
|
|
966 if (nm_file_name == 0)
|
|
967 #endif
|
|
968 nm_file_name = find_a_file (&cpath, gnm_suffix);
|
|
969 if (nm_file_name == 0)
|
|
970 nm_file_name = find_a_file (&path, full_gnm_suffix);
|
|
971 if (nm_file_name == 0)
|
|
972 nm_file_name = find_a_file (&cpath, nm_suffix);
|
|
973 if (nm_file_name == 0)
|
|
974 nm_file_name = find_a_file (&path, full_nm_suffix);
|
|
975
|
|
976 #ifdef LDD_SUFFIX
|
|
977 ldd_file_name = find_a_file (&cpath, ldd_suffix);
|
|
978 if (ldd_file_name == 0)
|
|
979 ldd_file_name = find_a_file (&path, full_ldd_suffix);
|
|
980 #endif
|
|
981
|
|
982 #ifdef REAL_STRIP_FILE_NAME
|
|
983 strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME);
|
|
984 if (strip_file_name == 0)
|
|
985 #endif
|
|
986 strip_file_name = find_a_file (&cpath, gstrip_suffix);
|
|
987 if (strip_file_name == 0)
|
|
988 strip_file_name = find_a_file (&path, full_gstrip_suffix);
|
|
989 if (strip_file_name == 0)
|
|
990 strip_file_name = find_a_file (&cpath, strip_suffix);
|
|
991 if (strip_file_name == 0)
|
|
992 strip_file_name = find_a_file (&path, full_strip_suffix);
|
|
993
|
|
994 /* Determine the full path name of the C compiler to use. */
|
|
995 c_file_name = getenv ("COLLECT_GCC");
|
|
996 if (c_file_name == 0)
|
|
997 {
|
|
998 #ifdef CROSS_DIRECTORY_STRUCTURE
|
|
999 c_file_name = concat (target_machine, "-gcc", NULL);
|
|
1000 #else
|
|
1001 c_file_name = "gcc";
|
|
1002 #endif
|
|
1003 }
|
|
1004
|
|
1005 p = find_a_file (&cpath, c_file_name);
|
|
1006
|
|
1007 /* Here it should be safe to use the system search path since we should have
|
|
1008 already qualified the name of the compiler when it is needed. */
|
|
1009 if (p == 0)
|
|
1010 p = find_a_file (&path, c_file_name);
|
|
1011
|
|
1012 if (p)
|
|
1013 c_file_name = p;
|
|
1014
|
|
1015 *ld1++ = *ld2++ = ld_file_name;
|
|
1016
|
|
1017 /* Make temp file names. */
|
|
1018 c_file = make_temp_file (".c");
|
|
1019 o_file = make_temp_file (".o");
|
|
1020 #ifdef COLLECT_EXPORT_LIST
|
|
1021 export_file = make_temp_file (".x");
|
|
1022 #endif
|
|
1023 ldout = make_temp_file (".ld");
|
|
1024 lderrout = make_temp_file (".le");
|
|
1025 *c_ptr++ = c_file_name;
|
|
1026 *c_ptr++ = "-x";
|
|
1027 *c_ptr++ = "c";
|
|
1028 *c_ptr++ = "-c";
|
|
1029 *c_ptr++ = "-o";
|
|
1030 *c_ptr++ = o_file;
|
|
1031
|
|
1032 #ifdef COLLECT_EXPORT_LIST
|
|
1033 /* Generate a list of directories from LIBPATH. */
|
|
1034 prefix_from_env ("LIBPATH", &libpath_lib_dirs);
|
|
1035 /* Add to this list also two standard directories where
|
|
1036 AIX loader always searches for libraries. */
|
|
1037 add_prefix (&libpath_lib_dirs, "/lib");
|
|
1038 add_prefix (&libpath_lib_dirs, "/usr/lib");
|
|
1039 #endif
|
|
1040
|
|
1041 /* Get any options that the upper GCC wants to pass to the sub-GCC.
|
|
1042
|
|
1043 AIX support needs to know if -shared has been specified before
|
|
1044 parsing commandline arguments. */
|
|
1045
|
|
1046 p = getenv ("COLLECT_GCC_OPTIONS");
|
|
1047 while (p && *p)
|
|
1048 {
|
|
1049 const char *q = extract_string (&p);
|
|
1050 if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
|
|
1051 *c_ptr++ = xstrdup (q);
|
|
1052 if (strcmp (q, "-EL") == 0 || strcmp (q, "-EB") == 0)
|
|
1053 *c_ptr++ = xstrdup (q);
|
|
1054 if (strcmp (q, "-shared") == 0)
|
|
1055 shared_obj = 1;
|
|
1056 if (*q == '-' && q[1] == 'B')
|
|
1057 {
|
|
1058 *c_ptr++ = xstrdup (q);
|
|
1059 if (q[2] == 0)
|
|
1060 {
|
|
1061 q = extract_string (&p);
|
|
1062 *c_ptr++ = xstrdup (q);
|
|
1063 }
|
|
1064 }
|
|
1065 }
|
|
1066 obstack_free (&temporary_obstack, temporary_firstobj);
|
|
1067 *c_ptr++ = "-fno-profile-arcs";
|
|
1068 *c_ptr++ = "-fno-test-coverage";
|
|
1069 *c_ptr++ = "-fno-branch-probabilities";
|
|
1070 *c_ptr++ = "-fno-exceptions";
|
|
1071 *c_ptr++ = "-w";
|
|
1072
|
|
1073 /* !!! When GCC calls collect2,
|
|
1074 it does not know whether it is calling collect2 or ld.
|
|
1075 So collect2 cannot meaningfully understand any options
|
|
1076 except those ld understands.
|
|
1077 If you propose to make GCC pass some other option,
|
|
1078 just imagine what will happen if ld is really ld!!! */
|
|
1079
|
|
1080 /* Parse arguments. Remember output file spec, pass the rest to ld. */
|
|
1081 /* After the first file, put in the c++ rt0. */
|
|
1082
|
|
1083 first_file = 1;
|
|
1084 #ifdef HAVE_LD_DEMANGLE
|
|
1085 if (!demangle_flag && !no_demangle)
|
|
1086 demangle_flag = "--demangle";
|
|
1087 if (demangle_flag)
|
|
1088 *ld1++ = *ld2++ = demangle_flag;
|
|
1089 #endif
|
|
1090 while ((arg = *++argv) != (char *) 0)
|
|
1091 {
|
|
1092 *ld1++ = *ld2++ = arg;
|
|
1093
|
|
1094 if (arg[0] == '-')
|
|
1095 {
|
|
1096 switch (arg[1])
|
|
1097 {
|
|
1098 #ifdef COLLECT_EXPORT_LIST
|
|
1099 /* We want to disable automatic exports on AIX when user
|
|
1100 explicitly puts an export list in command line */
|
|
1101 case 'b':
|
|
1102 if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0)
|
|
1103 export_flag = 1;
|
|
1104 else if (arg[2] == '6' && arg[3] == '4')
|
|
1105 aix64_flag = 1;
|
|
1106 else if (arg[2] == 'r' && arg[3] == 't' && arg[4] == 'l')
|
|
1107 aixrtl_flag = 1;
|
|
1108 break;
|
|
1109 #endif
|
|
1110
|
|
1111 case 'd':
|
|
1112 if (!strcmp (arg, "-debug"))
|
|
1113 {
|
|
1114 /* Already parsed. */
|
|
1115 ld1--;
|
|
1116 ld2--;
|
|
1117 }
|
|
1118 if (!strcmp (arg, "-dynamic-linker") && argv[1])
|
|
1119 {
|
|
1120 ++argv;
|
|
1121 *ld1++ = *ld2++ = *argv;
|
|
1122 }
|
|
1123 break;
|
|
1124
|
|
1125 case 'l':
|
|
1126 if (first_file)
|
|
1127 {
|
|
1128 /* place o_file BEFORE this argument! */
|
|
1129 first_file = 0;
|
|
1130 ld2--;
|
|
1131 *ld2++ = o_file;
|
|
1132 *ld2++ = arg;
|
|
1133 }
|
|
1134 #ifdef COLLECT_EXPORT_LIST
|
|
1135 {
|
|
1136 /* Resolving full library name. */
|
|
1137 const char *s = resolve_lib_name (arg+2);
|
|
1138
|
|
1139 /* Saving a full library name. */
|
|
1140 add_to_list (&libs, s);
|
|
1141 }
|
|
1142 #endif
|
|
1143 break;
|
|
1144
|
|
1145 #ifdef COLLECT_EXPORT_LIST
|
|
1146 /* Saving directories where to search for libraries. */
|
|
1147 case 'L':
|
|
1148 add_prefix (&cmdline_lib_dirs, arg+2);
|
|
1149 break;
|
|
1150 #else
|
|
1151 #if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
|
|
1152 case 'L':
|
|
1153 if (is_in_args (arg, (const char **) ld1_argv, ld1-1))
|
|
1154 --ld1;
|
|
1155 break;
|
|
1156 #endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */
|
|
1157 #endif
|
|
1158
|
|
1159 case 'o':
|
|
1160 if (arg[2] == '\0')
|
|
1161 output_file = *ld1++ = *ld2++ = *++argv;
|
|
1162 else if (1
|
|
1163 #ifdef SWITCHES_NEED_SPACES
|
|
1164 && ! strchr (SWITCHES_NEED_SPACES, arg[1])
|
|
1165 #endif
|
|
1166 )
|
|
1167
|
|
1168 output_file = &arg[2];
|
|
1169 break;
|
|
1170
|
|
1171 case 'r':
|
|
1172 if (arg[2] == '\0')
|
|
1173 rflag = 1;
|
|
1174 break;
|
|
1175
|
|
1176 case 's':
|
|
1177 if (arg[2] == '\0' && do_collecting)
|
|
1178 {
|
|
1179 /* We must strip after the nm run, otherwise C++ linking
|
|
1180 will not work. Thus we strip in the second ld run, or
|
|
1181 else with strip if there is no second ld run. */
|
|
1182 strip_flag = 1;
|
|
1183 ld1--;
|
|
1184 }
|
|
1185 break;
|
|
1186
|
|
1187 case 'v':
|
|
1188 if (arg[2] == '\0')
|
|
1189 vflag = 1;
|
|
1190 break;
|
|
1191
|
|
1192 case '-':
|
|
1193 if (strcmp (arg, "--no-demangle") == 0)
|
|
1194 {
|
|
1195 demangle_flag = arg;
|
|
1196 no_demangle = 1;
|
|
1197 ld1--;
|
|
1198 ld2--;
|
|
1199 }
|
|
1200 else if (strncmp (arg, "--demangle", 10) == 0)
|
|
1201 {
|
|
1202 demangle_flag = arg;
|
|
1203 no_demangle = 0;
|
|
1204 #ifndef HAVE_LD_DEMANGLE
|
|
1205 if (arg[10] == '=')
|
|
1206 {
|
|
1207 enum demangling_styles style
|
|
1208 = cplus_demangle_name_to_style (arg+11);
|
|
1209 if (style == unknown_demangling)
|
|
1210 error ("unknown demangling style '%s'", arg+11);
|
|
1211 else
|
|
1212 current_demangling_style = style;
|
|
1213 }
|
|
1214 #endif
|
|
1215 ld1--;
|
|
1216 ld2--;
|
|
1217 }
|
|
1218 break;
|
|
1219 }
|
|
1220 }
|
|
1221 else if ((p = strrchr (arg, '.')) != (char *) 0
|
|
1222 && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0
|
|
1223 || strcmp (p, ".so") == 0 || strcmp (p, ".lo") == 0
|
|
1224 || strcmp (p, ".obj") == 0))
|
|
1225 {
|
|
1226 if (first_file)
|
|
1227 {
|
|
1228 first_file = 0;
|
|
1229 if (p[1] == 'o')
|
|
1230 *ld2++ = o_file;
|
|
1231 else
|
|
1232 {
|
|
1233 /* place o_file BEFORE this argument! */
|
|
1234 ld2--;
|
|
1235 *ld2++ = o_file;
|
|
1236 *ld2++ = arg;
|
|
1237 }
|
|
1238 }
|
|
1239 if (p[1] == 'o' || p[1] == 'l')
|
|
1240 *object++ = arg;
|
|
1241 #ifdef COLLECT_EXPORT_LIST
|
|
1242 /* libraries can be specified directly, i.e. without -l flag. */
|
|
1243 else
|
|
1244 {
|
|
1245 /* Saving a full library name. */
|
|
1246 add_to_list (&libs, arg);
|
|
1247 }
|
|
1248 #endif
|
|
1249 }
|
|
1250 }
|
|
1251
|
|
1252 #ifdef COLLECT_EXPORT_LIST
|
|
1253 /* This is added only for debugging purposes. */
|
|
1254 if (debug)
|
|
1255 {
|
|
1256 fprintf (stderr, "List of libraries:\n");
|
|
1257 dump_list (stderr, "\t", libs.first);
|
|
1258 }
|
|
1259
|
|
1260 /* The AIX linker will discard static constructors in object files if
|
|
1261 nothing else in the file is referenced, so look at them first. */
|
|
1262 {
|
|
1263 const char **export_object_lst = (const char **)object_lst;
|
|
1264
|
|
1265 while (export_object_lst < object)
|
|
1266 scan_prog_file (*export_object_lst++, PASS_OBJ);
|
|
1267 }
|
|
1268 {
|
|
1269 struct id *list = libs.first;
|
|
1270
|
|
1271 for (; list; list = list->next)
|
|
1272 scan_prog_file (list->name, PASS_FIRST);
|
|
1273 }
|
|
1274
|
|
1275 if (exports.first)
|
|
1276 {
|
|
1277 char *buf = concat ("-bE:", export_file, NULL);
|
|
1278
|
|
1279 *ld1++ = buf;
|
|
1280 *ld2++ = buf;
|
|
1281
|
|
1282 exportf = fopen (export_file, "w");
|
|
1283 if (exportf == (FILE *) 0)
|
|
1284 fatal_perror ("fopen %s", export_file);
|
|
1285 write_aix_file (exportf, exports.first);
|
|
1286 if (fclose (exportf))
|
|
1287 fatal_perror ("fclose %s", export_file);
|
|
1288 }
|
|
1289 #endif
|
|
1290
|
|
1291 *c_ptr++ = c_file;
|
|
1292 *c_ptr = *ld1 = *object = (char *) 0;
|
|
1293
|
|
1294 if (vflag)
|
|
1295 {
|
|
1296 notice ("collect2 version %s", version_string);
|
|
1297 #ifdef TARGET_VERSION
|
|
1298 TARGET_VERSION;
|
|
1299 #endif
|
|
1300 fprintf (stderr, "\n");
|
|
1301 }
|
|
1302
|
|
1303 if (debug)
|
|
1304 {
|
|
1305 const char *ptr;
|
|
1306 fprintf (stderr, "ld_file_name = %s\n",
|
|
1307 (ld_file_name ? ld_file_name : "not found"));
|
|
1308 fprintf (stderr, "c_file_name = %s\n",
|
|
1309 (c_file_name ? c_file_name : "not found"));
|
|
1310 fprintf (stderr, "nm_file_name = %s\n",
|
|
1311 (nm_file_name ? nm_file_name : "not found"));
|
|
1312 #ifdef LDD_SUFFIX
|
|
1313 fprintf (stderr, "ldd_file_name = %s\n",
|
|
1314 (ldd_file_name ? ldd_file_name : "not found"));
|
|
1315 #endif
|
|
1316 fprintf (stderr, "strip_file_name = %s\n",
|
|
1317 (strip_file_name ? strip_file_name : "not found"));
|
|
1318 fprintf (stderr, "c_file = %s\n",
|
|
1319 (c_file ? c_file : "not found"));
|
|
1320 fprintf (stderr, "o_file = %s\n",
|
|
1321 (o_file ? o_file : "not found"));
|
|
1322
|
|
1323 ptr = getenv ("COLLECT_GCC_OPTIONS");
|
|
1324 if (ptr)
|
|
1325 fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
|
|
1326
|
|
1327 ptr = getenv ("COLLECT_GCC");
|
|
1328 if (ptr)
|
|
1329 fprintf (stderr, "COLLECT_GCC = %s\n", ptr);
|
|
1330
|
|
1331 ptr = getenv ("COMPILER_PATH");
|
|
1332 if (ptr)
|
|
1333 fprintf (stderr, "COMPILER_PATH = %s\n", ptr);
|
|
1334
|
|
1335 ptr = getenv (LIBRARY_PATH_ENV);
|
|
1336 if (ptr)
|
|
1337 fprintf (stderr, "%-20s= %s\n", LIBRARY_PATH_ENV, ptr);
|
|
1338
|
|
1339 fprintf (stderr, "\n");
|
|
1340 }
|
|
1341
|
|
1342 /* Load the program, searching all libraries and attempting to provide
|
|
1343 undefined symbols from repository information. */
|
|
1344
|
|
1345 /* On AIX we do this later. */
|
|
1346 #ifndef COLLECT_EXPORT_LIST
|
|
1347 do_tlink (ld1_argv, object_lst);
|
|
1348 #endif
|
|
1349
|
|
1350 /* If -r or they will be run via some other method, do not build the
|
|
1351 constructor or destructor list, just return now. */
|
|
1352 if (rflag
|
|
1353 #ifndef COLLECT_EXPORT_LIST
|
|
1354 || ! do_collecting
|
|
1355 #endif
|
|
1356 )
|
|
1357 {
|
|
1358 #ifdef COLLECT_EXPORT_LIST
|
|
1359 /* Do the link we avoided above if we are exiting. */
|
|
1360 do_tlink (ld1_argv, object_lst);
|
|
1361
|
|
1362 /* But make sure we delete the export file we may have created. */
|
|
1363 if (export_file != 0 && export_file[0])
|
|
1364 maybe_unlink (export_file);
|
|
1365 #endif
|
|
1366 maybe_unlink (c_file);
|
|
1367 maybe_unlink (o_file);
|
|
1368 return 0;
|
|
1369 }
|
|
1370
|
|
1371 /* Examine the namelist with nm and search it for static constructors
|
|
1372 and destructors to call.
|
|
1373 Write the constructor and destructor tables to a .s file and reload. */
|
|
1374
|
|
1375 /* On AIX we already scanned for global constructors/destructors. */
|
|
1376 #ifndef COLLECT_EXPORT_LIST
|
|
1377 scan_prog_file (output_file, PASS_FIRST);
|
|
1378 #endif
|
|
1379
|
|
1380 #ifdef SCAN_LIBRARIES
|
|
1381 scan_libraries (output_file);
|
|
1382 #endif
|
|
1383
|
|
1384 if (debug)
|
|
1385 {
|
|
1386 notice ("%d constructor(s) found\n", constructors.number);
|
|
1387 notice ("%d destructor(s) found\n", destructors.number);
|
|
1388 notice ("%d frame table(s) found\n", frame_tables.number);
|
|
1389 }
|
|
1390
|
|
1391 if (constructors.number == 0 && destructors.number == 0
|
|
1392 && frame_tables.number == 0
|
|
1393 #if defined (SCAN_LIBRARIES) || defined (COLLECT_EXPORT_LIST)
|
|
1394 /* If we will be running these functions ourselves, we want to emit
|
|
1395 stubs into the shared library so that we do not have to relink
|
|
1396 dependent programs when we add static objects. */
|
|
1397 && ! shared_obj
|
|
1398 #endif
|
|
1399 )
|
|
1400 {
|
|
1401 #ifdef COLLECT_EXPORT_LIST
|
|
1402 /* Do tlink without additional code generation. */
|
|
1403 do_tlink (ld1_argv, object_lst);
|
|
1404 #endif
|
|
1405 /* Strip now if it was requested on the command line. */
|
|
1406 if (strip_flag)
|
|
1407 {
|
|
1408 char **real_strip_argv = XCNEWVEC (char *, 3);
|
|
1409 const char ** strip_argv = (const char **) real_strip_argv;
|
|
1410
|
|
1411 strip_argv[0] = strip_file_name;
|
|
1412 strip_argv[1] = output_file;
|
|
1413 strip_argv[2] = (char *) 0;
|
|
1414 fork_execute ("strip", real_strip_argv);
|
|
1415 }
|
|
1416
|
|
1417 #ifdef COLLECT_EXPORT_LIST
|
|
1418 maybe_unlink (export_file);
|
|
1419 #endif
|
|
1420 maybe_unlink (c_file);
|
|
1421 maybe_unlink (o_file);
|
|
1422 return 0;
|
|
1423 }
|
|
1424
|
|
1425 /* Sort ctor and dtor lists by priority. */
|
|
1426 sort_ids (&constructors);
|
|
1427 sort_ids (&destructors);
|
|
1428
|
|
1429 maybe_unlink(output_file);
|
|
1430 outf = fopen (c_file, "w");
|
|
1431 if (outf == (FILE *) 0)
|
|
1432 fatal_perror ("fopen %s", c_file);
|
|
1433
|
|
1434 write_c_file (outf, c_file);
|
|
1435
|
|
1436 if (fclose (outf))
|
|
1437 fatal_perror ("fclose %s", c_file);
|
|
1438
|
|
1439 /* Tell the linker that we have initializer and finalizer functions. */
|
|
1440 #ifdef LD_INIT_SWITCH
|
|
1441 #ifdef COLLECT_EXPORT_LIST
|
|
1442 *ld2++ = concat (LD_INIT_SWITCH, ":", initname, ":", fininame, NULL);
|
|
1443 #else
|
|
1444 *ld2++ = LD_INIT_SWITCH;
|
|
1445 *ld2++ = initname;
|
|
1446 *ld2++ = LD_FINI_SWITCH;
|
|
1447 *ld2++ = fininame;
|
|
1448 #endif
|
|
1449 #endif
|
|
1450
|
|
1451 #ifdef COLLECT_EXPORT_LIST
|
|
1452 if (shared_obj)
|
|
1453 {
|
|
1454 /* If we did not add export flag to link arguments before, add it to
|
|
1455 second link phase now. No new exports should have been added. */
|
|
1456 if (! exports.first)
|
|
1457 *ld2++ = concat ("-bE:", export_file, NULL);
|
|
1458
|
|
1459 #ifndef LD_INIT_SWITCH
|
|
1460 add_to_list (&exports, initname);
|
|
1461 add_to_list (&exports, fininame);
|
|
1462 add_to_list (&exports, "_GLOBAL__DI");
|
|
1463 add_to_list (&exports, "_GLOBAL__DD");
|
|
1464 #endif
|
|
1465 exportf = fopen (export_file, "w");
|
|
1466 if (exportf == (FILE *) 0)
|
|
1467 fatal_perror ("fopen %s", export_file);
|
|
1468 write_aix_file (exportf, exports.first);
|
|
1469 if (fclose (exportf))
|
|
1470 fatal_perror ("fclose %s", export_file);
|
|
1471 }
|
|
1472 #endif
|
|
1473
|
|
1474 /* End of arguments to second link phase. */
|
|
1475 *ld2 = (char*) 0;
|
|
1476
|
|
1477 if (debug)
|
|
1478 {
|
|
1479 fprintf (stderr, "\n========== output_file = %s, c_file = %s\n",
|
|
1480 output_file, c_file);
|
|
1481 write_c_file (stderr, "stderr");
|
|
1482 fprintf (stderr, "========== end of c_file\n\n");
|
|
1483 #ifdef COLLECT_EXPORT_LIST
|
|
1484 fprintf (stderr, "\n========== export_file = %s\n", export_file);
|
|
1485 write_aix_file (stderr, exports.first);
|
|
1486 fprintf (stderr, "========== end of export_file\n\n");
|
|
1487 #endif
|
|
1488 }
|
|
1489
|
|
1490 /* Assemble the constructor and destructor tables.
|
|
1491 Link the tables in with the rest of the program. */
|
|
1492
|
|
1493 fork_execute ("gcc", c_argv);
|
|
1494 #ifdef COLLECT_EXPORT_LIST
|
|
1495 /* On AIX we must call tlink because of possible templates resolution. */
|
|
1496 do_tlink (ld2_argv, object_lst);
|
|
1497 #else
|
|
1498 /* Otherwise, simply call ld because tlink is already done. */
|
|
1499 fork_execute ("ld", ld2_argv);
|
|
1500
|
|
1501 /* Let scan_prog_file do any final mods (OSF/rose needs this for
|
|
1502 constructors/destructors in shared libraries. */
|
|
1503 scan_prog_file (output_file, PASS_SECOND);
|
|
1504 #endif
|
|
1505
|
|
1506 maybe_unlink (c_file);
|
|
1507 maybe_unlink (o_file);
|
|
1508
|
|
1509 #ifdef COLLECT_EXPORT_LIST
|
|
1510 maybe_unlink (export_file);
|
|
1511 #endif
|
|
1512
|
|
1513 return 0;
|
|
1514 }
|
|
1515
|
|
1516
|
|
1517 /* Wait for a process to finish, and exit if a nonzero status is found. */
|
|
1518
|
|
1519 int
|
|
1520 collect_wait (const char *prog, struct pex_obj *pex)
|
|
1521 {
|
|
1522 int status;
|
|
1523
|
|
1524 if (!pex_get_status (pex, 1, &status))
|
|
1525 fatal_perror ("can't get program status");
|
|
1526 pex_free (pex);
|
|
1527
|
|
1528 if (status)
|
|
1529 {
|
|
1530 if (WIFSIGNALED (status))
|
|
1531 {
|
|
1532 int sig = WTERMSIG (status);
|
|
1533 error ("%s terminated with signal %d [%s]%s",
|
|
1534 prog, sig, strsignal(sig),
|
|
1535 WCOREDUMP(status) ? ", core dumped" : "");
|
|
1536 collect_exit (FATAL_EXIT_CODE);
|
|
1537 }
|
|
1538
|
|
1539 if (WIFEXITED (status))
|
|
1540 return WEXITSTATUS (status);
|
|
1541 }
|
|
1542 return 0;
|
|
1543 }
|
|
1544
|
|
1545 static void
|
|
1546 do_wait (const char *prog, struct pex_obj *pex)
|
|
1547 {
|
|
1548 int ret = collect_wait (prog, pex);
|
|
1549 if (ret != 0)
|
|
1550 {
|
|
1551 error ("%s returned %d exit status", prog, ret);
|
|
1552 collect_exit (ret);
|
|
1553 }
|
|
1554
|
|
1555 if (response_file)
|
|
1556 {
|
|
1557 unlink (response_file);
|
|
1558 response_file = NULL;
|
|
1559 }
|
|
1560 }
|
|
1561
|
|
1562
|
|
1563 /* Execute a program, and wait for the reply. */
|
|
1564
|
|
1565 struct pex_obj *
|
|
1566 collect_execute (const char *prog, char **argv, const char *outname,
|
|
1567 const char *errname)
|
|
1568 {
|
|
1569 struct pex_obj *pex;
|
|
1570 const char *errmsg;
|
|
1571 int err;
|
|
1572 char *response_arg = NULL;
|
|
1573 char *response_argv[3] ATTRIBUTE_UNUSED;
|
|
1574
|
|
1575 if (HAVE_GNU_LD && at_file_supplied && argv[0] != NULL)
|
|
1576 {
|
|
1577 /* If using @file arguments, create a temporary file and put the
|
|
1578 contents of argv into it. Then change argv to an array corresponding
|
|
1579 to a single argument @FILE, where FILE is the temporary filename. */
|
|
1580
|
|
1581 char **current_argv = argv + 1;
|
|
1582 char *argv0 = argv[0];
|
|
1583 int status;
|
|
1584 FILE *f;
|
|
1585
|
|
1586 /* Note: we assume argv contains at least one element; this is
|
|
1587 checked above. */
|
|
1588
|
|
1589 response_file = make_temp_file ("");
|
|
1590
|
|
1591 f = fopen (response_file, "w");
|
|
1592
|
|
1593 if (f == NULL)
|
|
1594 fatal ("could not open response file %s", response_file);
|
|
1595
|
|
1596 status = writeargv (current_argv, f);
|
|
1597
|
|
1598 if (status)
|
|
1599 fatal ("could not write to response file %s", response_file);
|
|
1600
|
|
1601 status = fclose (f);
|
|
1602
|
|
1603 if (EOF == status)
|
|
1604 fatal ("could not close response file %s", response_file);
|
|
1605
|
|
1606 response_arg = concat ("@", response_file, NULL);
|
|
1607 response_argv[0] = argv0;
|
|
1608 response_argv[1] = response_arg;
|
|
1609 response_argv[2] = NULL;
|
|
1610
|
|
1611 argv = response_argv;
|
|
1612 }
|
|
1613
|
|
1614 if (vflag || debug)
|
|
1615 {
|
|
1616 char **p_argv;
|
|
1617 const char *str;
|
|
1618
|
|
1619 if (argv[0])
|
|
1620 fprintf (stderr, "%s", argv[0]);
|
|
1621 else
|
|
1622 notice ("[cannot find %s]", prog);
|
|
1623
|
|
1624 for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++)
|
|
1625 fprintf (stderr, " %s", str);
|
|
1626
|
|
1627 fprintf (stderr, "\n");
|
|
1628 }
|
|
1629
|
|
1630 fflush (stdout);
|
|
1631 fflush (stderr);
|
|
1632
|
|
1633 /* If we cannot find a program we need, complain error. Do this here
|
|
1634 since we might not end up needing something that we could not find. */
|
|
1635
|
|
1636 if (argv[0] == 0)
|
|
1637 fatal ("cannot find '%s'", prog);
|
|
1638
|
|
1639 pex = pex_init (0, "collect2", NULL);
|
|
1640 if (pex == NULL)
|
|
1641 fatal_perror ("pex_init failed");
|
|
1642
|
|
1643 errmsg = pex_run (pex, PEX_LAST | PEX_SEARCH, argv[0], argv, outname,
|
|
1644 errname, &err);
|
|
1645 if (errmsg != NULL)
|
|
1646 {
|
|
1647 if (err != 0)
|
|
1648 {
|
|
1649 errno = err;
|
|
1650 fatal_perror (errmsg);
|
|
1651 }
|
|
1652 else
|
|
1653 fatal (errmsg);
|
|
1654 }
|
|
1655
|
|
1656 if (response_arg)
|
|
1657 free (response_arg);
|
|
1658
|
|
1659 return pex;
|
|
1660 }
|
|
1661
|
|
1662 static void
|
|
1663 fork_execute (const char *prog, char **argv)
|
|
1664 {
|
|
1665 struct pex_obj *pex;
|
|
1666
|
|
1667 pex = collect_execute (prog, argv, NULL, NULL);
|
|
1668 do_wait (prog, pex);
|
|
1669 }
|
|
1670
|
|
1671 /* Unlink a file unless we are debugging. */
|
|
1672
|
|
1673 static void
|
|
1674 maybe_unlink (const char *file)
|
|
1675 {
|
|
1676 if (!debug)
|
|
1677 unlink_if_ordinary (file);
|
|
1678 else
|
|
1679 notice ("[Leaving %s]\n", file);
|
|
1680 }
|
|
1681
|
|
1682
|
|
1683 static long sequence_number = 0;
|
|
1684
|
|
1685 /* Add a name to a linked list. */
|
|
1686
|
|
1687 static void
|
|
1688 add_to_list (struct head *head_ptr, const char *name)
|
|
1689 {
|
|
1690 struct id *newid
|
|
1691 = (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1);
|
|
1692 struct id *p;
|
|
1693 strcpy (newid->name, name);
|
|
1694
|
|
1695 if (head_ptr->first)
|
|
1696 head_ptr->last->next = newid;
|
|
1697 else
|
|
1698 head_ptr->first = newid;
|
|
1699
|
|
1700 /* Check for duplicate symbols. */
|
|
1701 for (p = head_ptr->first;
|
|
1702 strcmp (name, p->name) != 0;
|
|
1703 p = p->next)
|
|
1704 ;
|
|
1705 if (p != newid)
|
|
1706 {
|
|
1707 head_ptr->last->next = 0;
|
|
1708 free (newid);
|
|
1709 return;
|
|
1710 }
|
|
1711
|
|
1712 newid->sequence = ++sequence_number;
|
|
1713 head_ptr->last = newid;
|
|
1714 head_ptr->number++;
|
|
1715 }
|
|
1716
|
|
1717 /* Grab the init priority number from an init function name that
|
|
1718 looks like "_GLOBAL_.I.12345.foo". */
|
|
1719
|
|
1720 static int
|
|
1721 extract_init_priority (const char *name)
|
|
1722 {
|
|
1723 int pos = 0, pri;
|
|
1724
|
|
1725 while (name[pos] == '_')
|
|
1726 ++pos;
|
|
1727 pos += 10; /* strlen ("GLOBAL__X_") */
|
|
1728
|
|
1729 /* Extract init_p number from ctor/dtor name. */
|
|
1730 pri = atoi (name + pos);
|
|
1731 return pri ? pri : DEFAULT_INIT_PRIORITY;
|
|
1732 }
|
|
1733
|
|
1734 /* Insertion sort the ids from ctor/dtor list HEAD_PTR in descending order.
|
|
1735 ctors will be run from right to left, dtors from left to right. */
|
|
1736
|
|
1737 static void
|
|
1738 sort_ids (struct head *head_ptr)
|
|
1739 {
|
|
1740 /* id holds the current element to insert. id_next holds the next
|
|
1741 element to insert. id_ptr iterates through the already sorted elements
|
|
1742 looking for the place to insert id. */
|
|
1743 struct id *id, *id_next, **id_ptr;
|
|
1744
|
|
1745 id = head_ptr->first;
|
|
1746
|
|
1747 /* We don't have any sorted elements yet. */
|
|
1748 head_ptr->first = NULL;
|
|
1749
|
|
1750 for (; id; id = id_next)
|
|
1751 {
|
|
1752 id_next = id->next;
|
|
1753 id->sequence = extract_init_priority (id->name);
|
|
1754
|
|
1755 for (id_ptr = &(head_ptr->first); ; id_ptr = &((*id_ptr)->next))
|
|
1756 if (*id_ptr == NULL
|
|
1757 /* If the sequence numbers are the same, we put the id from the
|
|
1758 file later on the command line later in the list. */
|
|
1759 || id->sequence > (*id_ptr)->sequence
|
|
1760 /* Hack: do lexical compare, too.
|
|
1761 || (id->sequence == (*id_ptr)->sequence
|
|
1762 && strcmp (id->name, (*id_ptr)->name) > 0) */
|
|
1763 )
|
|
1764 {
|
|
1765 id->next = *id_ptr;
|
|
1766 *id_ptr = id;
|
|
1767 break;
|
|
1768 }
|
|
1769 }
|
|
1770
|
|
1771 /* Now set the sequence numbers properly so write_c_file works. */
|
|
1772 for (id = head_ptr->first; id; id = id->next)
|
|
1773 id->sequence = ++sequence_number;
|
|
1774 }
|
|
1775
|
|
1776 /* Write: `prefix', the names on list LIST, `suffix'. */
|
|
1777
|
|
1778 static void
|
|
1779 write_list (FILE *stream, const char *prefix, struct id *list)
|
|
1780 {
|
|
1781 while (list)
|
|
1782 {
|
|
1783 fprintf (stream, "%sx%d,\n", prefix, list->sequence);
|
|
1784 list = list->next;
|
|
1785 }
|
|
1786 }
|
|
1787
|
|
1788 #if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
|
|
1789 /* Given a STRING, return nonzero if it occurs in the list in range
|
|
1790 [ARGS_BEGIN,ARGS_END). */
|
|
1791
|
|
1792 static int
|
|
1793 is_in_args (const char *string, const char **args_begin,
|
|
1794 const char **args_end)
|
|
1795 {
|
|
1796 const char **args_pointer;
|
|
1797 for (args_pointer = args_begin; args_pointer != args_end; ++args_pointer)
|
|
1798 if (strcmp (string, *args_pointer) == 0)
|
|
1799 return 1;
|
|
1800 return 0;
|
|
1801 }
|
|
1802 #endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */
|
|
1803
|
|
1804 #ifdef COLLECT_EXPORT_LIST
|
|
1805 /* This function is really used only on AIX, but may be useful. */
|
|
1806 #if 0
|
|
1807 static int
|
|
1808 is_in_list (const char *prefix, struct id *list)
|
|
1809 {
|
|
1810 while (list)
|
|
1811 {
|
|
1812 if (!strcmp (prefix, list->name)) return 1;
|
|
1813 list = list->next;
|
|
1814 }
|
|
1815 return 0;
|
|
1816 }
|
|
1817 #endif
|
|
1818 #endif /* COLLECT_EXPORT_LIST */
|
|
1819
|
|
1820 /* Added for debugging purpose. */
|
|
1821 #ifdef COLLECT_EXPORT_LIST
|
|
1822 static void
|
|
1823 dump_list (FILE *stream, const char *prefix, struct id *list)
|
|
1824 {
|
|
1825 while (list)
|
|
1826 {
|
|
1827 fprintf (stream, "%s%s,\n", prefix, list->name);
|
|
1828 list = list->next;
|
|
1829 }
|
|
1830 }
|
|
1831 #endif
|
|
1832
|
|
1833 #if 0
|
|
1834 static void
|
|
1835 dump_prefix_list (FILE *stream, const char *prefix, struct prefix_list *list)
|
|
1836 {
|
|
1837 while (list)
|
|
1838 {
|
|
1839 fprintf (stream, "%s%s,\n", prefix, list->prefix);
|
|
1840 list = list->next;
|
|
1841 }
|
|
1842 }
|
|
1843 #endif
|
|
1844
|
|
1845 static void
|
|
1846 write_list_with_asm (FILE *stream, const char *prefix, struct id *list)
|
|
1847 {
|
|
1848 while (list)
|
|
1849 {
|
|
1850 fprintf (stream, "%sx%d __asm__ (\"%s\");\n",
|
|
1851 prefix, list->sequence, list->name);
|
|
1852 list = list->next;
|
|
1853 }
|
|
1854 }
|
|
1855
|
|
1856 /* Write out the constructor and destructor tables statically (for a shared
|
|
1857 object), along with the functions to execute them. */
|
|
1858
|
|
1859 static void
|
|
1860 write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED)
|
|
1861 {
|
|
1862 const char *p, *q;
|
|
1863 char *prefix, *r;
|
|
1864 int frames = (frame_tables.number > 0);
|
|
1865
|
|
1866 /* Figure out name of output_file, stripping off .so version. */
|
|
1867 p = strrchr (output_file, '/');
|
|
1868 if (p == 0)
|
|
1869 p = output_file;
|
|
1870 else
|
|
1871 p++;
|
|
1872 q = p;
|
|
1873 while (q)
|
|
1874 {
|
|
1875 q = strchr (q,'.');
|
|
1876 if (q == 0)
|
|
1877 {
|
|
1878 q = p + strlen (p);
|
|
1879 break;
|
|
1880 }
|
|
1881 else
|
|
1882 {
|
|
1883 if (strncmp (q, SHLIB_SUFFIX, strlen (SHLIB_SUFFIX)) == 0)
|
|
1884 {
|
|
1885 q += strlen (SHLIB_SUFFIX);
|
|
1886 break;
|
|
1887 }
|
|
1888 else
|
|
1889 q++;
|
|
1890 }
|
|
1891 }
|
|
1892 /* q points to null at end of the string (or . of the .so version) */
|
|
1893 prefix = XNEWVEC (char, q - p + 1);
|
|
1894 strncpy (prefix, p, q - p);
|
|
1895 prefix[q - p] = 0;
|
|
1896 for (r = prefix; *r; r++)
|
|
1897 if (!ISALNUM ((unsigned char)*r))
|
|
1898 *r = '_';
|
|
1899 if (debug)
|
|
1900 notice ("\nwrite_c_file - output name is %s, prefix is %s\n",
|
|
1901 output_file, prefix);
|
|
1902
|
|
1903 initname = concat ("_GLOBAL__FI_", prefix, NULL);
|
|
1904 fininame = concat ("_GLOBAL__FD_", prefix, NULL);
|
|
1905
|
|
1906 free (prefix);
|
|
1907
|
|
1908 /* Write the tables as C code. */
|
|
1909
|
|
1910 fprintf (stream, "static int count;\n");
|
|
1911 fprintf (stream, "typedef void entry_pt();\n");
|
|
1912 write_list_with_asm (stream, "extern entry_pt ", constructors.first);
|
|
1913
|
|
1914 if (frames)
|
|
1915 {
|
|
1916 write_list_with_asm (stream, "extern void *", frame_tables.first);
|
|
1917
|
|
1918 fprintf (stream, "\tstatic void *frame_table[] = {\n");
|
|
1919 write_list (stream, "\t\t&", frame_tables.first);
|
|
1920 fprintf (stream, "\t0\n};\n");
|
|
1921
|
|
1922 /* This must match what's in frame.h. */
|
|
1923 fprintf (stream, "struct object {\n");
|
|
1924 fprintf (stream, " void *pc_begin;\n");
|
|
1925 fprintf (stream, " void *pc_end;\n");
|
|
1926 fprintf (stream, " void *fde_begin;\n");
|
|
1927 fprintf (stream, " void *fde_array;\n");
|
|
1928 fprintf (stream, " __SIZE_TYPE__ count;\n");
|
|
1929 fprintf (stream, " struct object *next;\n");
|
|
1930 fprintf (stream, "};\n");
|
|
1931
|
|
1932 fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
|
|
1933 fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
|
|
1934
|
|
1935 fprintf (stream, "static void reg_frame () {\n");
|
|
1936 fprintf (stream, "\tstatic struct object ob;\n");
|
|
1937 fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
|
|
1938 fprintf (stream, "\t}\n");
|
|
1939
|
|
1940 fprintf (stream, "static void dereg_frame () {\n");
|
|
1941 fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
|
|
1942 fprintf (stream, "\t}\n");
|
|
1943 }
|
|
1944
|
|
1945 fprintf (stream, "void %s() {\n", initname);
|
|
1946 if (constructors.number > 0 || frames)
|
|
1947 {
|
|
1948 fprintf (stream, "\tstatic entry_pt *ctors[] = {\n");
|
|
1949 write_list (stream, "\t\t", constructors.first);
|
|
1950 if (frames)
|
|
1951 fprintf (stream, "\treg_frame,\n");
|
|
1952 fprintf (stream, "\t};\n");
|
|
1953 fprintf (stream, "\tentry_pt **p;\n");
|
|
1954 fprintf (stream, "\tif (count++ != 0) return;\n");
|
|
1955 fprintf (stream, "\tp = ctors + %d;\n", constructors.number + frames);
|
|
1956 fprintf (stream, "\twhile (p > ctors) (*--p)();\n");
|
|
1957 }
|
|
1958 else
|
|
1959 fprintf (stream, "\t++count;\n");
|
|
1960 fprintf (stream, "}\n");
|
|
1961 write_list_with_asm (stream, "extern entry_pt ", destructors.first);
|
|
1962 fprintf (stream, "void %s() {\n", fininame);
|
|
1963 if (destructors.number > 0 || frames)
|
|
1964 {
|
|
1965 fprintf (stream, "\tstatic entry_pt *dtors[] = {\n");
|
|
1966 write_list (stream, "\t\t", destructors.first);
|
|
1967 if (frames)
|
|
1968 fprintf (stream, "\tdereg_frame,\n");
|
|
1969 fprintf (stream, "\t};\n");
|
|
1970 fprintf (stream, "\tentry_pt **p;\n");
|
|
1971 fprintf (stream, "\tif (--count != 0) return;\n");
|
|
1972 fprintf (stream, "\tp = dtors;\n");
|
|
1973 fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n",
|
|
1974 destructors.number + frames);
|
|
1975 }
|
|
1976 fprintf (stream, "}\n");
|
|
1977
|
|
1978 if (shared_obj)
|
|
1979 {
|
|
1980 COLLECT_SHARED_INIT_FUNC(stream, initname);
|
|
1981 COLLECT_SHARED_FINI_FUNC(stream, fininame);
|
|
1982 }
|
|
1983 }
|
|
1984
|
|
1985 /* Write the constructor/destructor tables. */
|
|
1986
|
|
1987 #ifndef LD_INIT_SWITCH
|
|
1988 static void
|
|
1989 write_c_file_glob (FILE *stream, const char *name ATTRIBUTE_UNUSED)
|
|
1990 {
|
|
1991 /* Write the tables as C code. */
|
|
1992
|
|
1993 int frames = (frame_tables.number > 0);
|
|
1994
|
|
1995 fprintf (stream, "typedef void entry_pt();\n\n");
|
|
1996
|
|
1997 write_list_with_asm (stream, "extern entry_pt ", constructors.first);
|
|
1998
|
|
1999 if (frames)
|
|
2000 {
|
|
2001 write_list_with_asm (stream, "extern void *", frame_tables.first);
|
|
2002
|
|
2003 fprintf (stream, "\tstatic void *frame_table[] = {\n");
|
|
2004 write_list (stream, "\t\t&", frame_tables.first);
|
|
2005 fprintf (stream, "\t0\n};\n");
|
|
2006
|
|
2007 /* This must match what's in frame.h. */
|
|
2008 fprintf (stream, "struct object {\n");
|
|
2009 fprintf (stream, " void *pc_begin;\n");
|
|
2010 fprintf (stream, " void *pc_end;\n");
|
|
2011 fprintf (stream, " void *fde_begin;\n");
|
|
2012 fprintf (stream, " void *fde_array;\n");
|
|
2013 fprintf (stream, " __SIZE_TYPE__ count;\n");
|
|
2014 fprintf (stream, " struct object *next;\n");
|
|
2015 fprintf (stream, "};\n");
|
|
2016
|
|
2017 fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
|
|
2018 fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
|
|
2019
|
|
2020 fprintf (stream, "static void reg_frame () {\n");
|
|
2021 fprintf (stream, "\tstatic struct object ob;\n");
|
|
2022 fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
|
|
2023 fprintf (stream, "\t}\n");
|
|
2024
|
|
2025 fprintf (stream, "static void dereg_frame () {\n");
|
|
2026 fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
|
|
2027 fprintf (stream, "\t}\n");
|
|
2028 }
|
|
2029
|
|
2030 fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
|
|
2031 fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number + frames);
|
|
2032 write_list (stream, "\t", constructors.first);
|
|
2033 if (frames)
|
|
2034 fprintf (stream, "\treg_frame,\n");
|
|
2035 fprintf (stream, "\t0\n};\n\n");
|
|
2036
|
|
2037 write_list_with_asm (stream, "extern entry_pt ", destructors.first);
|
|
2038
|
|
2039 fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
|
|
2040 fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number + frames);
|
|
2041 write_list (stream, "\t", destructors.first);
|
|
2042 if (frames)
|
|
2043 fprintf (stream, "\tdereg_frame,\n");
|
|
2044 fprintf (stream, "\t0\n};\n\n");
|
|
2045
|
|
2046 fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
|
|
2047 fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);
|
|
2048 }
|
|
2049 #endif /* ! LD_INIT_SWITCH */
|
|
2050
|
|
2051 static void
|
|
2052 write_c_file (FILE *stream, const char *name)
|
|
2053 {
|
|
2054 #ifndef LD_INIT_SWITCH
|
|
2055 if (! shared_obj)
|
|
2056 write_c_file_glob (stream, name);
|
|
2057 else
|
|
2058 #endif
|
|
2059 write_c_file_stat (stream, name);
|
|
2060 }
|
|
2061
|
|
2062 #ifdef COLLECT_EXPORT_LIST
|
|
2063 static void
|
|
2064 write_aix_file (FILE *stream, struct id *list)
|
|
2065 {
|
|
2066 for (; list; list = list->next)
|
|
2067 {
|
|
2068 fputs (list->name, stream);
|
|
2069 putc ('\n', stream);
|
|
2070 }
|
|
2071 }
|
|
2072 #endif
|
|
2073
|
|
2074 #ifdef OBJECT_FORMAT_NONE
|
|
2075
|
|
2076 /* Generic version to scan the name list of the loaded program for
|
|
2077 the symbols g++ uses for static constructors and destructors.
|
|
2078
|
|
2079 The constructor table begins at __CTOR_LIST__ and contains a count
|
|
2080 of the number of pointers (or -1 if the constructors are built in a
|
|
2081 separate section by the linker), followed by the pointers to the
|
|
2082 constructor functions, terminated with a null pointer. The
|
|
2083 destructor table has the same format, and begins at __DTOR_LIST__. */
|
|
2084
|
|
2085 static void
|
|
2086 scan_prog_file (const char *prog_name, enum pass which_pass)
|
|
2087 {
|
|
2088 void (*int_handler) (int);
|
|
2089 #ifdef SIGQUIT
|
|
2090 void (*quit_handler) (int);
|
|
2091 #endif
|
|
2092 char *real_nm_argv[4];
|
|
2093 const char **nm_argv = (const char **) real_nm_argv;
|
|
2094 int argc = 0;
|
|
2095 struct pex_obj *pex;
|
|
2096 const char *errmsg;
|
|
2097 int err;
|
|
2098 char *p, buf[1024];
|
|
2099 FILE *inf;
|
|
2100
|
|
2101 if (which_pass == PASS_SECOND)
|
|
2102 return;
|
|
2103
|
|
2104 /* If we do not have an `nm', complain. */
|
|
2105 if (nm_file_name == 0)
|
|
2106 fatal ("cannot find 'nm'");
|
|
2107
|
|
2108 nm_argv[argc++] = nm_file_name;
|
|
2109 if (NM_FLAGS[0] != '\0')
|
|
2110 nm_argv[argc++] = NM_FLAGS;
|
|
2111
|
|
2112 nm_argv[argc++] = prog_name;
|
|
2113 nm_argv[argc++] = (char *) 0;
|
|
2114
|
|
2115 /* Trace if needed. */
|
|
2116 if (vflag)
|
|
2117 {
|
|
2118 const char **p_argv;
|
|
2119 const char *str;
|
|
2120
|
|
2121 for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
|
|
2122 fprintf (stderr, " %s", str);
|
|
2123
|
|
2124 fprintf (stderr, "\n");
|
|
2125 }
|
|
2126
|
|
2127 fflush (stdout);
|
|
2128 fflush (stderr);
|
|
2129
|
|
2130 pex = pex_init (PEX_USE_PIPES, "collect2", NULL);
|
|
2131 if (pex == NULL)
|
|
2132 fatal_perror ("pex_init failed");
|
|
2133
|
|
2134 errmsg = pex_run (pex, 0, nm_file_name, real_nm_argv, NULL, NULL, &err);
|
|
2135 if (errmsg != NULL)
|
|
2136 {
|
|
2137 if (err != 0)
|
|
2138 {
|
|
2139 errno = err;
|
|
2140 fatal_perror (errmsg);
|
|
2141 }
|
|
2142 else
|
|
2143 fatal (errmsg);
|
|
2144 }
|
|
2145
|
|
2146 int_handler = (void (*) (int)) signal (SIGINT, SIG_IGN);
|
|
2147 #ifdef SIGQUIT
|
|
2148 quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN);
|
|
2149 #endif
|
|
2150
|
|
2151 inf = pex_read_output (pex, 0);
|
|
2152 if (inf == NULL)
|
|
2153 fatal_perror ("can't open nm output");
|
|
2154
|
|
2155 if (debug)
|
|
2156 fprintf (stderr, "\nnm output with constructors/destructors.\n");
|
|
2157
|
|
2158 /* Read each line of nm output. */
|
|
2159 while (fgets (buf, sizeof buf, inf) != (char *) 0)
|
|
2160 {
|
|
2161 int ch, ch2;
|
|
2162 char *name, *end;
|
|
2163
|
|
2164 /* If it contains a constructor or destructor name, add the name
|
|
2165 to the appropriate list. */
|
|
2166
|
|
2167 for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
|
|
2168 if (ch == ' ' && p[1] == 'U' && p[2] == ' ')
|
|
2169 break;
|
|
2170
|
|
2171 if (ch != '_')
|
|
2172 continue;
|
|
2173
|
|
2174 name = p;
|
|
2175 /* Find the end of the symbol name.
|
|
2176 Do not include `|', because Encore nm can tack that on the end. */
|
|
2177 for (end = p; (ch2 = *end) != '\0' && !ISSPACE (ch2) && ch2 != '|';
|
|
2178 end++)
|
|
2179 continue;
|
|
2180
|
|
2181
|
|
2182 *end = '\0';
|
|
2183 switch (is_ctor_dtor (name))
|
|
2184 {
|
|
2185 case SYM_CTOR:
|
|
2186 if (which_pass != PASS_LIB)
|
|
2187 add_to_list (&constructors, name);
|
|
2188 break;
|
|
2189
|
|
2190 case SYM_DTOR:
|
|
2191 if (which_pass != PASS_LIB)
|
|
2192 add_to_list (&destructors, name);
|
|
2193 break;
|
|
2194
|
|
2195 case SYM_INIT:
|
|
2196 if (which_pass != PASS_LIB)
|
|
2197 fatal ("init function found in object %s", prog_name);
|
|
2198 #ifndef LD_INIT_SWITCH
|
|
2199 add_to_list (&constructors, name);
|
|
2200 #endif
|
|
2201 break;
|
|
2202
|
|
2203 case SYM_FINI:
|
|
2204 if (which_pass != PASS_LIB)
|
|
2205 fatal ("fini function found in object %s", prog_name);
|
|
2206 #ifndef LD_FINI_SWITCH
|
|
2207 add_to_list (&destructors, name);
|
|
2208 #endif
|
|
2209 break;
|
|
2210
|
|
2211 case SYM_DWEH:
|
|
2212 if (which_pass != PASS_LIB)
|
|
2213 add_to_list (&frame_tables, name);
|
|
2214 break;
|
|
2215
|
|
2216 default: /* not a constructor or destructor */
|
|
2217 continue;
|
|
2218 }
|
|
2219
|
|
2220 if (debug)
|
|
2221 fprintf (stderr, "\t%s\n", buf);
|
|
2222 }
|
|
2223
|
|
2224 if (debug)
|
|
2225 fprintf (stderr, "\n");
|
|
2226
|
|
2227 do_wait (nm_file_name, pex);
|
|
2228
|
|
2229 signal (SIGINT, int_handler);
|
|
2230 #ifdef SIGQUIT
|
|
2231 signal (SIGQUIT, quit_handler);
|
|
2232 #endif
|
|
2233 }
|
|
2234
|
|
2235 #ifdef LDD_SUFFIX
|
|
2236
|
|
2237 /* Use the List Dynamic Dependencies program to find shared libraries that
|
|
2238 the output file depends upon and their initialization/finalization
|
|
2239 routines, if any. */
|
|
2240
|
|
2241 static void
|
|
2242 scan_libraries (const char *prog_name)
|
|
2243 {
|
|
2244 static struct head libraries; /* list of shared libraries found */
|
|
2245 struct id *list;
|
|
2246 void (*int_handler) (int);
|
|
2247 #ifdef SIGQUIT
|
|
2248 void (*quit_handler) (int);
|
|
2249 #endif
|
|
2250 char *real_ldd_argv[4];
|
|
2251 const char **ldd_argv = (const char **) real_ldd_argv;
|
|
2252 int argc = 0;
|
|
2253 struct pex_obj *pex;
|
|
2254 const char *errmsg;
|
|
2255 int err;
|
|
2256 char buf[1024];
|
|
2257 FILE *inf;
|
|
2258
|
|
2259 /* If we do not have an `ldd', complain. */
|
|
2260 if (ldd_file_name == 0)
|
|
2261 {
|
|
2262 error ("cannot find 'ldd'");
|
|
2263 return;
|
|
2264 }
|
|
2265
|
|
2266 ldd_argv[argc++] = ldd_file_name;
|
|
2267 ldd_argv[argc++] = prog_name;
|
|
2268 ldd_argv[argc++] = (char *) 0;
|
|
2269
|
|
2270 /* Trace if needed. */
|
|
2271 if (vflag)
|
|
2272 {
|
|
2273 const char **p_argv;
|
|
2274 const char *str;
|
|
2275
|
|
2276 for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
|
|
2277 fprintf (stderr, " %s", str);
|
|
2278
|
|
2279 fprintf (stderr, "\n");
|
|
2280 }
|
|
2281
|
|
2282 fflush (stdout);
|
|
2283 fflush (stderr);
|
|
2284
|
|
2285 pex = pex_init (PEX_USE_PIPES, "collect2", NULL);
|
|
2286 if (pex == NULL)
|
|
2287 fatal_perror ("pex_init failed");
|
|
2288
|
|
2289 errmsg = pex_run (pex, 0, ldd_file_name, real_ldd_argv, NULL, NULL, &err);
|
|
2290 if (errmsg != NULL)
|
|
2291 {
|
|
2292 if (err != 0)
|
|
2293 {
|
|
2294 errno = err;
|
|
2295 fatal_perror (errmsg);
|
|
2296 }
|
|
2297 else
|
|
2298 fatal (errmsg);
|
|
2299 }
|
|
2300
|
|
2301 int_handler = (void (*) (int)) signal (SIGINT, SIG_IGN);
|
|
2302 #ifdef SIGQUIT
|
|
2303 quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN);
|
|
2304 #endif
|
|
2305
|
|
2306 inf = pex_read_output (pex, 0);
|
|
2307 if (inf == NULL)
|
|
2308 fatal_perror ("can't open ldd output");
|
|
2309
|
|
2310 if (debug)
|
|
2311 notice ("\nldd output with constructors/destructors.\n");
|
|
2312
|
|
2313 /* Read each line of ldd output. */
|
|
2314 while (fgets (buf, sizeof buf, inf) != (char *) 0)
|
|
2315 {
|
|
2316 int ch2;
|
|
2317 char *name, *end, *p = buf;
|
|
2318
|
|
2319 /* Extract names of libraries and add to list. */
|
|
2320 PARSE_LDD_OUTPUT (p);
|
|
2321 if (p == 0)
|
|
2322 continue;
|
|
2323
|
|
2324 name = p;
|
|
2325 if (strncmp (name, "not found", sizeof ("not found") - 1) == 0)
|
|
2326 fatal ("dynamic dependency %s not found", buf);
|
|
2327
|
|
2328 /* Find the end of the symbol name. */
|
|
2329 for (end = p;
|
|
2330 (ch2 = *end) != '\0' && ch2 != '\n' && !ISSPACE (ch2) && ch2 != '|';
|
|
2331 end++)
|
|
2332 continue;
|
|
2333 *end = '\0';
|
|
2334
|
|
2335 if (access (name, R_OK) == 0)
|
|
2336 add_to_list (&libraries, name);
|
|
2337 else
|
|
2338 fatal ("unable to open dynamic dependency '%s'", buf);
|
|
2339
|
|
2340 if (debug)
|
|
2341 fprintf (stderr, "\t%s\n", buf);
|
|
2342 }
|
|
2343 if (debug)
|
|
2344 fprintf (stderr, "\n");
|
|
2345
|
|
2346 do_wait (ldd_file_name, pex);
|
|
2347
|
|
2348 signal (SIGINT, int_handler);
|
|
2349 #ifdef SIGQUIT
|
|
2350 signal (SIGQUIT, quit_handler);
|
|
2351 #endif
|
|
2352
|
|
2353 /* Now iterate through the library list adding their symbols to
|
|
2354 the list. */
|
|
2355 for (list = libraries.first; list; list = list->next)
|
|
2356 scan_prog_file (list->name, PASS_LIB);
|
|
2357 }
|
|
2358
|
|
2359 #endif /* LDD_SUFFIX */
|
|
2360
|
|
2361 #endif /* OBJECT_FORMAT_NONE */
|
|
2362
|
|
2363
|
|
2364 /*
|
|
2365 * COFF specific stuff.
|
|
2366 */
|
|
2367
|
|
2368 #ifdef OBJECT_FORMAT_COFF
|
|
2369
|
|
2370 #if defined (EXTENDED_COFF)
|
|
2371
|
|
2372 # define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
|
|
2373 # define GCC_SYMENT SYMR
|
|
2374 # define GCC_OK_SYMBOL(X) ((X).st == stProc || (X).st == stGlobal)
|
|
2375 # define GCC_SYMINC(X) (1)
|
|
2376 # define GCC_SYMZERO(X) (SYMHEADER(X).isymMax)
|
|
2377 # define GCC_CHECK_HDR(X) (PSYMTAB(X) != 0)
|
|
2378
|
|
2379 #else
|
|
2380
|
|
2381 # define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms)
|
|
2382 # define GCC_SYMENT SYMENT
|
|
2383 # if defined (C_WEAKEXT)
|
|
2384 # define GCC_OK_SYMBOL(X) \
|
|
2385 (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \
|
|
2386 ((X).n_scnum > N_UNDEF) && \
|
|
2387 (aix64_flag \
|
|
2388 || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
|
|
2389 || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
|
|
2390 # define GCC_UNDEF_SYMBOL(X) \
|
|
2391 (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \
|
|
2392 ((X).n_scnum == N_UNDEF))
|
|
2393 # else
|
|
2394 # define GCC_OK_SYMBOL(X) \
|
|
2395 (((X).n_sclass == C_EXT) && \
|
|
2396 ((X).n_scnum > N_UNDEF) && \
|
|
2397 (aix64_flag \
|
|
2398 || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
|
|
2399 || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
|
|
2400 # define GCC_UNDEF_SYMBOL(X) \
|
|
2401 (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF))
|
|
2402 # endif
|
|
2403 # define GCC_SYMINC(X) ((X).n_numaux+1)
|
|
2404 # define GCC_SYMZERO(X) 0
|
|
2405
|
|
2406 /* 0757 = U803XTOCMAGIC (AIX 4.3) and 0767 = U64_TOCMAGIC (AIX V5) */
|
|
2407 #ifdef _AIX51
|
|
2408 # define GCC_CHECK_HDR(X) \
|
|
2409 ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
|
|
2410 || (HEADER (X).f_magic == 0767 && aix64_flag))
|
|
2411 #else
|
|
2412 # define GCC_CHECK_HDR(X) \
|
|
2413 ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
|
|
2414 || (HEADER (X).f_magic == 0757 && aix64_flag))
|
|
2415 #endif
|
|
2416
|
|
2417 #endif
|
|
2418
|
|
2419 #ifdef COLLECT_EXPORT_LIST
|
|
2420 /* Array of standard AIX libraries which should not
|
|
2421 be scanned for ctors/dtors. */
|
|
2422 static const char *const aix_std_libs[] = {
|
|
2423 "/unix",
|
|
2424 "/lib/libc.a",
|
|
2425 "/lib/libm.a",
|
|
2426 "/lib/libc_r.a",
|
|
2427 "/lib/libm_r.a",
|
|
2428 "/usr/lib/libc.a",
|
|
2429 "/usr/lib/libm.a",
|
|
2430 "/usr/lib/libc_r.a",
|
|
2431 "/usr/lib/libm_r.a",
|
|
2432 "/usr/lib/threads/libc.a",
|
|
2433 "/usr/ccs/lib/libc.a",
|
|
2434 "/usr/ccs/lib/libm.a",
|
|
2435 "/usr/ccs/lib/libc_r.a",
|
|
2436 "/usr/ccs/lib/libm_r.a",
|
|
2437 NULL
|
|
2438 };
|
|
2439
|
|
2440 /* This function checks the filename and returns 1
|
|
2441 if this name matches the location of a standard AIX library. */
|
|
2442 static int ignore_library (const char *);
|
|
2443 static int
|
|
2444 ignore_library (const char *name)
|
|
2445 {
|
|
2446 const char *const *p = &aix_std_libs[0];
|
|
2447 while (*p++ != NULL)
|
|
2448 if (! strcmp (name, *p)) return 1;
|
|
2449 return 0;
|
|
2450 }
|
|
2451 #endif /* COLLECT_EXPORT_LIST */
|
|
2452
|
|
2453 #if defined (HAVE_DECL_LDGETNAME) && !HAVE_DECL_LDGETNAME
|
|
2454 extern char *ldgetname (LDFILE *, GCC_SYMENT *);
|
|
2455 #endif
|
|
2456
|
|
2457 /* COFF version to scan the name list of the loaded program for
|
|
2458 the symbols g++ uses for static constructors and destructors.
|
|
2459
|
|
2460 The constructor table begins at __CTOR_LIST__ and contains a count
|
|
2461 of the number of pointers (or -1 if the constructors are built in a
|
|
2462 separate section by the linker), followed by the pointers to the
|
|
2463 constructor functions, terminated with a null pointer. The
|
|
2464 destructor table has the same format, and begins at __DTOR_LIST__. */
|
|
2465
|
|
2466 static void
|
|
2467 scan_prog_file (const char *prog_name, enum pass which_pass)
|
|
2468 {
|
|
2469 LDFILE *ldptr = NULL;
|
|
2470 int sym_index, sym_count;
|
|
2471 int is_shared = 0;
|
|
2472
|
|
2473 if (which_pass != PASS_FIRST && which_pass != PASS_OBJ)
|
|
2474 return;
|
|
2475
|
|
2476 #ifdef COLLECT_EXPORT_LIST
|
|
2477 /* We do not need scanning for some standard C libraries. */
|
|
2478 if (which_pass == PASS_FIRST && ignore_library (prog_name))
|
|
2479 return;
|
|
2480
|
|
2481 /* On AIX we have a loop, because there is not much difference
|
|
2482 between an object and an archive. This trick allows us to
|
|
2483 eliminate scan_libraries() function. */
|
|
2484 do
|
|
2485 {
|
|
2486 #endif
|
|
2487 /* Some platforms (e.g. OSF4) declare ldopen as taking a
|
|
2488 non-const char * filename parameter, even though it will not
|
|
2489 modify that string. So we must cast away const-ness here,
|
|
2490 using CONST_CAST to prevent complaints from -Wcast-qual. */
|
|
2491 if ((ldptr = ldopen (CONST_CAST (char *, prog_name), ldptr)) != NULL)
|
|
2492 {
|
|
2493 if (! MY_ISCOFF (HEADER (ldptr).f_magic))
|
|
2494 fatal ("%s: not a COFF file", prog_name);
|
|
2495
|
|
2496 if (GCC_CHECK_HDR (ldptr))
|
|
2497 {
|
|
2498 sym_count = GCC_SYMBOLS (ldptr);
|
|
2499 sym_index = GCC_SYMZERO (ldptr);
|
|
2500
|
|
2501 #ifdef COLLECT_EXPORT_LIST
|
|
2502 /* Is current archive member a shared object? */
|
|
2503 is_shared = HEADER (ldptr).f_flags & F_SHROBJ;
|
|
2504 #endif
|
|
2505
|
|
2506 while (sym_index < sym_count)
|
|
2507 {
|
|
2508 GCC_SYMENT symbol;
|
|
2509
|
|
2510 if (ldtbread (ldptr, sym_index, &symbol) <= 0)
|
|
2511 break;
|
|
2512 sym_index += GCC_SYMINC (symbol);
|
|
2513
|
|
2514 if (GCC_OK_SYMBOL (symbol))
|
|
2515 {
|
|
2516 char *name;
|
|
2517
|
|
2518 if ((name = ldgetname (ldptr, &symbol)) == NULL)
|
|
2519 continue; /* Should never happen. */
|
|
2520
|
|
2521 #ifdef XCOFF_DEBUGGING_INFO
|
|
2522 /* All AIX function names have a duplicate entry
|
|
2523 beginning with a dot. */
|
|
2524 if (*name == '.')
|
|
2525 ++name;
|
|
2526 #endif
|
|
2527
|
|
2528 switch (is_ctor_dtor (name))
|
|
2529 {
|
|
2530 case SYM_CTOR:
|
|
2531 if (! is_shared)
|
|
2532 add_to_list (&constructors, name);
|
|
2533 #if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH)
|
|
2534 if (which_pass == PASS_OBJ)
|
|
2535 add_to_list (&exports, name);
|
|
2536 #endif
|
|
2537 break;
|
|
2538
|
|
2539 case SYM_DTOR:
|
|
2540 if (! is_shared)
|
|
2541 add_to_list (&destructors, name);
|
|
2542 #if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH)
|
|
2543 if (which_pass == PASS_OBJ)
|
|
2544 add_to_list (&exports, name);
|
|
2545 #endif
|
|
2546 break;
|
|
2547
|
|
2548 #ifdef COLLECT_EXPORT_LIST
|
|
2549 case SYM_INIT:
|
|
2550 #ifndef LD_INIT_SWITCH
|
|
2551 if (is_shared)
|
|
2552 add_to_list (&constructors, name);
|
|
2553 #endif
|
|
2554 break;
|
|
2555
|
|
2556 case SYM_FINI:
|
|
2557 #ifndef LD_INIT_SWITCH
|
|
2558 if (is_shared)
|
|
2559 add_to_list (&destructors, name);
|
|
2560 #endif
|
|
2561 break;
|
|
2562 #endif
|
|
2563
|
|
2564 case SYM_DWEH:
|
|
2565 if (! is_shared)
|
|
2566 add_to_list (&frame_tables, name);
|
|
2567 #if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH)
|
|
2568 if (which_pass == PASS_OBJ)
|
|
2569 add_to_list (&exports, name);
|
|
2570 #endif
|
|
2571 break;
|
|
2572
|
|
2573 default: /* not a constructor or destructor */
|
|
2574 #ifdef COLLECT_EXPORT_LIST
|
|
2575 /* Explicitly export all global symbols when
|
|
2576 building a shared object on AIX, but do not
|
|
2577 re-export symbols from another shared object
|
|
2578 and do not export symbols if the user
|
|
2579 provides an explicit export list. */
|
|
2580 if (shared_obj && !is_shared
|
|
2581 && which_pass == PASS_OBJ && !export_flag)
|
|
2582 add_to_list (&exports, name);
|
|
2583 #endif
|
|
2584 continue;
|
|
2585 }
|
|
2586
|
|
2587 if (debug)
|
|
2588 #if !defined(EXTENDED_COFF)
|
|
2589 fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
|
|
2590 symbol.n_scnum, symbol.n_sclass,
|
|
2591 (symbol.n_type ? "0" : ""), symbol.n_type,
|
|
2592 name);
|
|
2593 #else
|
|
2594 fprintf (stderr,
|
|
2595 "\tiss = %5d, value = %5ld, index = %5d, name = %s\n",
|
|
2596 symbol.iss, (long) symbol.value, symbol.index, name);
|
|
2597 #endif
|
|
2598 }
|
|
2599 }
|
|
2600 }
|
|
2601 #ifdef COLLECT_EXPORT_LIST
|
|
2602 else
|
|
2603 {
|
|
2604 /* If archive contains both 32-bit and 64-bit objects,
|
|
2605 we want to skip objects in other mode so mismatch normal. */
|
|
2606 if (debug)
|
|
2607 fprintf (stderr, "%s : magic=%o aix64=%d mismatch\n",
|
|
2608 prog_name, HEADER (ldptr).f_magic, aix64_flag);
|
|
2609 }
|
|
2610 #endif
|
|
2611 }
|
|
2612 else
|
|
2613 {
|
|
2614 fatal ("%s: cannot open as COFF file", prog_name);
|
|
2615 }
|
|
2616 #ifdef COLLECT_EXPORT_LIST
|
|
2617 /* On AIX loop continues while there are more members in archive. */
|
|
2618 }
|
|
2619 while (ldclose (ldptr) == FAILURE);
|
|
2620 #else
|
|
2621 /* Otherwise we simply close ldptr. */
|
|
2622 (void) ldclose(ldptr);
|
|
2623 #endif
|
|
2624 }
|
|
2625 #endif /* OBJECT_FORMAT_COFF */
|
|
2626
|
|
2627 #ifdef COLLECT_EXPORT_LIST
|
|
2628 /* Given a library name without "lib" prefix, this function
|
|
2629 returns a full library name including a path. */
|
|
2630 static char *
|
|
2631 resolve_lib_name (const char *name)
|
|
2632 {
|
|
2633 char *lib_buf;
|
|
2634 int i, j, l = 0;
|
|
2635 /* Library extensions for AIX dynamic linking. */
|
|
2636 const char * const libexts[2] = {"a", "so"};
|
|
2637
|
|
2638 for (i = 0; libpaths[i]; i++)
|
|
2639 if (libpaths[i]->max_len > l)
|
|
2640 l = libpaths[i]->max_len;
|
|
2641
|
|
2642 lib_buf = XNEWVEC (char, l + strlen(name) + 10);
|
|
2643
|
|
2644 for (i = 0; libpaths[i]; i++)
|
|
2645 {
|
|
2646 struct prefix_list *list = libpaths[i]->plist;
|
|
2647 for (; list; list = list->next)
|
|
2648 {
|
|
2649 /* The following lines are needed because path_prefix list
|
|
2650 may contain directories both with trailing '/' and
|
|
2651 without it. */
|
|
2652 const char *p = "";
|
|
2653 if (list->prefix[strlen(list->prefix)-1] != '/')
|
|
2654 p = "/";
|
|
2655 for (j = 0; j < 2; j++)
|
|
2656 {
|
|
2657 sprintf (lib_buf, "%s%slib%s.%s",
|
|
2658 list->prefix, p, name,
|
|
2659 libexts[(j + aixrtl_flag) % 2]);
|
|
2660 if (debug) fprintf (stderr, "searching for: %s\n", lib_buf);
|
|
2661 if (file_exists (lib_buf))
|
|
2662 {
|
|
2663 if (debug) fprintf (stderr, "found: %s\n", lib_buf);
|
|
2664 return (lib_buf);
|
|
2665 }
|
|
2666 }
|
|
2667 }
|
|
2668 }
|
|
2669 if (debug)
|
|
2670 fprintf (stderr, "not found\n");
|
|
2671 else
|
|
2672 fatal ("library lib%s not found", name);
|
|
2673 return (NULL);
|
|
2674 }
|
|
2675 #endif /* COLLECT_EXPORT_LIST */
|