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