]> gcc.gnu.org Git - gcc.git/blame - gcc/collect2.c
(integrate_decl_tree): Set DECL_ABTRACT_ORIGIN before pushdecl call
[gcc.git] / gcc / collect2.c
CommitLineData
4e81a331
RS
1/* Collect static initialization info into data structures
2 that can be traversed by C++ initialization and finalization
3 routines.
4
96317659 5 Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
4e81a331 6 Contributed by Chris Smith (csmith@convex.com).
96317659 7 Heavily modified by Michael Meissner (meissner@cygnus.com),
4e81a331
RS
8 Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com).
9
10This file is part of GNU CC.
11
12GNU CC is free software; you can redistribute it and/or modify
13it under the terms of the GNU General Public License as published by
14the Free Software Foundation; either version 2, or (at your option)
15any later version.
16
17GNU CC is distributed in the hope that it will be useful,
18but WITHOUT ANY WARRANTY; without even the implied warranty of
19MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20GNU General Public License for more details.
21
22You should have received a copy of the GNU General Public License
23along with GNU CC; see the file COPYING. If not, write to
940d9d63
RK
24the Free Software Foundation, 59 Temple Place - Suite 330,
25Boston, MA 02111-1307, USA. */
4e81a331
RS
26
27
28/* Build tables of static constructors and destructors and run ld. */
29
c102bba0 30#include "config.h"
4e81a331
RS
31#include <sys/types.h>
32#include <stdio.h>
4e81a331 33#include <ctype.h>
4e81a331
RS
34#include <errno.h>
35#include <signal.h>
36#include <sys/file.h>
37#include <sys/stat.h>
e6701a47 38#ifdef NO_WAIT_H
4e81a331 39#include <sys/wait.h>
e6701a47 40#endif
4e81a331 41
c102bba0
RK
42#define COLLECT
43
44#include "demangle.h"
45#include "obstack.h"
46
ed5b9462
RS
47#ifndef errno
48extern int errno;
49#endif
50
96317659
RK
51#ifndef HAVE_STRERROR
52#if defined(bsd4_4)
5d672cd7
JW
53extern const char *const sys_errlist[];
54#else
55extern char *sys_errlist[];
56#endif
57extern int sys_nerr;
96317659
RK
58#else
59char *strerror();
60#endif
5d672cd7 61
a3184468
JM
62/* Obstack allocation and deallocation routines. */
63#define obstack_chunk_alloc xmalloc
64#define obstack_chunk_free free
65
66#if !defined (__STDC__) && !defined (const)
67#define const
4e81a331
RS
68#endif
69
ed5b9462
RS
70#ifdef USG
71#define vfork fork
72#endif
73
4d1a011f
RK
74/* Add prototype support. */
75#ifndef PROTO
76#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
77#define PROTO(ARGS) ARGS
78#else
79#define PROTO(ARGS) ()
80#endif
81#endif
82
ed5b9462
RS
83#ifndef R_OK
84#define R_OK 4
85#define W_OK 2
86#define X_OK 1
87#endif
88
0b90f9c2
ILT
89#ifndef WIFSIGNALED
90#define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f)
91#endif
92#ifndef WTERMSIG
93#define WTERMSIG(S) ((S) & 0x7f)
94#endif
95#ifndef WIFEXITED
96#define WIFEXITED(S) (((S) & 0xff) == 0)
97#endif
98#ifndef WEXITSTATUS
99#define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
100#endif
101
ed5b9462
RS
102/* On MSDOS, write temp files in current dir
103 because there's no place else we can expect to use. */
4b19dee8 104#ifdef __MSDOS__
ed5b9462
RS
105#ifndef P_tmpdir
106#define P_tmpdir "./"
107#endif
108#endif
109\f
110/* On certain systems, we have code that works by scanning the object file
111 directly. But this code uses system-specific header files and library
bb59f9a6
RS
112 functions, so turn it off in a cross-compiler. Likewise, the names of
113 the utilities aren't correct for a cross-compiler; we have to hope that
114 cross-versions are in the proper directories. */
ed5b9462
RS
115
116#ifdef CROSS_COMPILE
68d69835 117#undef SUNOS4_SHARED_LIBRARIES
ed5b9462
RS
118#undef OBJECT_FORMAT_COFF
119#undef OBJECT_FORMAT_ROSE
bb59f9a6
RS
120#undef MD_EXEC_PREFIX
121#undef REAL_LD_FILE_NAME
122#undef REAL_NM_FILE_NAME
123#undef REAL_STRIP_FILE_NAME
ed5b9462
RS
124#endif
125
126/* If we can't use a special method, use the ordinary one:
127 run nm to find what symbols are present.
128 In a cross-compiler, this means you need a cross nm,
129 but that isn't quite as unpleasant as special headers. */
130
131#if !defined (OBJECT_FORMAT_COFF) && !defined (OBJECT_FORMAT_ROSE)
132#define OBJECT_FORMAT_NONE
133#endif
134
135#ifdef OBJECT_FORMAT_COFF
136
137#include <a.out.h>
138#include <ar.h>
139
140#ifdef UMAX
141#include <sgs.h>
142#endif
143
033ba47c
RS
144/* Many versions of ldfcn.h define these. */
145#ifdef FREAD
ed5b9462
RS
146#undef FREAD
147#undef FWRITE
148#endif
149
150#include <ldfcn.h>
151
7243ba7d
RK
152/* Some systems have an ISCOFF macro, but others do not. In some cases
153 the macro may be wrong. MY_ISCOFF is defined in tm.h files for machines
154 that either do not have an ISCOFF macro in /usr/include or for those
155 where it is wrong. */
156
e99467d2
RS
157#ifndef MY_ISCOFF
158#define MY_ISCOFF(X) ISCOFF (X)
159#endif
160
ed5b9462
RS
161#endif /* OBJECT_FORMAT_COFF */
162
4e81a331
RS
163#ifdef OBJECT_FORMAT_ROSE
164
165#ifdef _OSF_SOURCE
166#define USE_MMAP
167#endif
168
169#ifdef USE_MMAP
170#include <sys/mman.h>
171#endif
172
173#include <unistd.h>
174#include <mach_o_format.h>
175#include <mach_o_header.h>
176#include <mach_o_vals.h>
177#include <mach_o_types.h>
ed5b9462 178
4e81a331
RS
179#endif /* OBJECT_FORMAT_ROSE */
180
ed5b9462
RS
181#ifdef OBJECT_FORMAT_NONE
182
4e81a331
RS
183/* Default flags to pass to nm. */
184#ifndef NM_FLAGS
185#define NM_FLAGS "-p"
186#endif
187
ed5b9462 188#endif /* OBJECT_FORMAT_NONE */
d6cf3187
RS
189
190/* Some systems use __main in a way incompatible with its use in gcc, in these
191 cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
192 give the same symbol without quotes for an alternative entry point. You
ddd5a7c1 193 must define both, or neither. */
d6cf3187
RS
194#ifndef NAME__MAIN
195#define NAME__MAIN "__main"
196#define SYMBOL__MAIN __main
197#endif
198
a3184468 199#if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES
68d69835
JM
200#define SCAN_LIBRARIES
201#endif
a3184468
JM
202
203#ifdef USE_COLLECT2
204int do_collecting = 1;
205#else
206int do_collecting = 0;
207#endif
4e81a331
RS
208\f
209/* Linked lists of constructor and destructor names. */
210
211struct id
212{
213 struct id *next;
214 int sequence;
215 char name[1];
216};
217
218struct head
219{
220 struct id *first;
221 struct id *last;
222 int number;
223};
224
225/* Enumeration giving which pass this is for scanning the program file. */
226
227enum pass {
228 PASS_FIRST, /* without constructors */
cbbbd917 229 PASS_OBJ, /* individual objects */
68d69835 230 PASS_LIB, /* looking for shared libraries */
4e81a331
RS
231 PASS_SECOND /* with constructors linked in */
232};
233
ed5b9462 234#ifndef NO_SYS_SIGLIST
1b7ca660 235#ifndef DONT_DECLARE_SYS_SIGLIST
4e81a331 236extern char *sys_siglist[];
ed5b9462 237#endif
1b7ca660 238#endif
4e81a331
RS
239extern char *version_string;
240
a3184468 241int vflag; /* true if -v */
4e81a331 242static int rflag; /* true if -r */
a87104d9 243static int strip_flag; /* true if -s */
4e81a331 244
a3184468 245int debug; /* true if -debug */
4e81a331 246
68d69835
JM
247static int shared_obj; /* true if -shared */
248
4e81a331
RS
249static int temp_filename_length; /* Length of temp_filename */
250static char *temp_filename; /* Base of temp filenames */
251static char *c_file; /* <xxx>.c for constructor/destructor list. */
252static char *o_file; /* <xxx>.o for constructor/destructor list. */
cbbbd917
JM
253static char *export_file; /* <xxx>.x for AIX export list. */
254static int auto_export = 1; /* true if exporting everything. */
a3184468 255char *ldout; /* File for ld errors. */
0cdd3ddd 256static char *output_file; /* Output file for ld. */
4e81a331 257static char *nm_file_name; /* pathname of nm */
68d69835 258static char *ldd_file_name; /* pathname of ldd (or equivalent) */
a87104d9 259static char *strip_file_name; /* pathname of strip */
a3184468 260char *c_file_name; /* pathname of gcc */
cbbbd917 261static char *initname, *fininame; /* names of init and fini funcs */
4e81a331
RS
262
263static struct head constructors; /* list of constructors found */
264static struct head destructors; /* list of destructors found */
cbbbd917 265static struct head exports; /* list of exported symbols */
4e81a331 266
a3184468
JM
267struct obstack temporary_obstack;
268struct obstack permanent_obstack;
269char * temporary_firstobj;
270
271/* Defined in the automatically-generated underscore.c. */
272extern int prepends_underscore;
273
ed5b9462
RS
274extern char *getenv ();
275extern char *mktemp ();
4d1a011f
RK
276extern FILE *fdopen ();
277
278/* Structure to hold all the directories in which to search for files to
279 execute. */
280
281struct prefix_list
282{
283 char *prefix; /* String to prepend to the path. */
284 struct prefix_list *next; /* Next in linked list. */
285};
286
287struct path_prefix
288{
289 struct prefix_list *plist; /* List of prefixes to try */
290 int max_len; /* Max length of a prefix in PLIST */
291 char *name; /* Name of this list (used in config stuff) */
292};
293
a3184468
JM
294void collect_exit PROTO((int));
295void collect_execute PROTO((char *, char **, char *));
296void dump_file PROTO((char *));
4d1a011f
RK
297static void handler PROTO((int));
298static int is_ctor_dtor PROTO((char *));
299static void choose_temp_base PROTO((void));
300static int is_in_prefix_list PROTO((struct path_prefix *, char *, int));
301static char *find_a_file PROTO((struct path_prefix *, char *));
302static void add_prefix PROTO((struct path_prefix *, char *));
303static void prefix_from_env PROTO((char *, struct path_prefix *));
cbbbd917 304static void prefix_from_string PROTO((char *, struct path_prefix *));
4d1a011f
RK
305static void do_wait PROTO((char *));
306static void fork_execute PROTO((char *, char **));
307static void maybe_unlink PROTO((char *));
308static void add_to_list PROTO((struct head *, char *));
309static void write_list PROTO((FILE *, char *, struct id *));
310static void write_list_with_asm PROTO((FILE *, char *, struct id *));
311static void write_c_file PROTO((FILE *, char *));
cbbbd917 312static void write_export_file PROTO((FILE *));
4d1a011f 313static void scan_prog_file PROTO((char *, enum pass));
68d69835 314static void scan_libraries PROTO((char *));
ed5b9462 315
a3184468
JM
316char *xcalloc ();
317char *xmalloc ();
3f7cc57a
MS
318
319extern char *index ();
320extern char *rindex ();
a3184468 321extern void free ();
4e81a331 322\f
f28e8a68 323#ifdef NO_DUP2
4d1a011f 324int
f28e8a68
RS
325dup2 (oldfd, newfd)
326 int oldfd;
327 int newfd;
328{
329 int fdtmp[256];
330 int fdx = 0;
331 int fd;
332
333 if (oldfd == newfd)
eadbc961 334 return oldfd;
f28e8a68 335 close (newfd);
eadbc961 336 while ((fd = dup (oldfd)) != newfd && fd >= 0) /* good enough for low fd's */
f28e8a68
RS
337 fdtmp[fdx++] = fd;
338 while (fdx > 0)
339 close (fdtmp[--fdx]);
4d1a011f 340
eadbc961 341 return fd;
f28e8a68
RS
342}
343#endif
344
ed5b9462 345char *
1fab8e81 346my_strerror (e)
4e81a331
RS
347 int e;
348{
4e81a331 349
aae807c0
RK
350#ifdef HAVE_STRERROR
351 return strerror (e);
352
353#else
354
355 static char buffer[30];
4e81a331
RS
356 if (!e)
357 return "";
358
359 if (e > 0 && e < sys_nerr)
360 return sys_errlist[e];
361
362 sprintf (buffer, "Unknown error %d", e);
363 return buffer;
aae807c0 364#endif
4e81a331 365}
4e81a331
RS
366\f
367/* Delete tempfiles and exit function. */
368
a3184468
JM
369void
370collect_exit (status)
4e81a331
RS
371 int status;
372{
ed5b9462 373 if (c_file != 0 && c_file[0])
4e81a331
RS
374 maybe_unlink (c_file);
375
ed5b9462 376 if (o_file != 0 && o_file[0])
4e81a331
RS
377 maybe_unlink (o_file);
378
cbbbd917
JM
379 if (export_file != 0 && export_file[0])
380 maybe_unlink (export_file);
381
a3184468
JM
382 if (ldout != 0 && ldout[0])
383 {
384 dump_file (ldout);
385 maybe_unlink (ldout);
386 }
387
0cdd3ddd
RS
388 if (status != 0 && output_file != 0 && output_file[0])
389 maybe_unlink (output_file);
390
4e81a331
RS
391 exit (status);
392}
393
394\f
4e81a331
RS
395/* Die when sys call fails. */
396
a3184468 397void
1fab8e81 398fatal_perror (string, arg1, arg2, arg3)
bd1a74b1 399 char *string, *arg1, *arg2, *arg3;
4e81a331 400{
4e81a331
RS
401 int e = errno;
402
626e18ea 403 fprintf (stderr, "collect2: ");
1fab8e81
RS
404 fprintf (stderr, string, arg1, arg2, arg3);
405 fprintf (stderr, ": %s\n", my_strerror (e));
a3184468 406 collect_exit (1);
4e81a331
RS
407}
408
409/* Just die. */
410
a3184468 411void
1fab8e81 412fatal (string, arg1, arg2, arg3)
bd1a74b1 413 char *string, *arg1, *arg2, *arg3;
4e81a331 414{
626e18ea 415 fprintf (stderr, "collect2: ");
1fab8e81 416 fprintf (stderr, string, arg1, arg2, arg3);
4e81a331 417 fprintf (stderr, "\n");
a3184468 418 collect_exit (1);
4e81a331
RS
419}
420
421/* Write error message. */
422
a3184468 423void
1fab8e81 424error (string, arg1, arg2, arg3, arg4)
bd1a74b1 425 char *string, *arg1, *arg2, *arg3, *arg4;
4e81a331 426{
626e18ea 427 fprintf (stderr, "collect2: ");
1fab8e81 428 fprintf (stderr, string, arg1, arg2, arg3, arg4);
4e81a331 429 fprintf (stderr, "\n");
4e81a331
RS
430}
431
4e81a331
RS
432/* In case obstack is linked in, and abort is defined to fancy_abort,
433 provide a default entry. */
434
435void
436fancy_abort ()
437{
438 fatal ("internal error");
439}
440
441\f
442static void
443handler (signo)
444 int signo;
445{
b31a1e3f 446 if (c_file != 0 && c_file[0])
4e81a331
RS
447 maybe_unlink (c_file);
448
b31a1e3f 449 if (o_file != 0 && o_file[0])
4e81a331
RS
450 maybe_unlink (o_file);
451
a3184468
JM
452 if (ldout != 0 && ldout[0])
453 maybe_unlink (ldout);
454
4e81a331 455 signal (signo, SIG_DFL);
4e81a331
RS
456 kill (getpid (), signo);
457}
458
459\f
a3184468 460char *
4e81a331 461xcalloc (size1, size2)
ed5b9462 462 int size1, size2;
4e81a331 463{
a3184468 464 char *ptr = (char *) calloc (size1, size2);
4e81a331
RS
465 if (ptr)
466 return ptr;
467
1fab8e81 468 fatal ("out of memory");
a3184468 469 return (char *)0;
4e81a331
RS
470}
471
a3184468 472char *
4e81a331 473xmalloc (size)
a3184468 474 unsigned size;
4e81a331 475{
a3184468 476 char *ptr = (char *) malloc (size);
4e81a331
RS
477 if (ptr)
478 return ptr;
479
1fab8e81 480 fatal ("out of memory");
a3184468
JM
481 return (char *)0;
482}
483
484char *
485xrealloc (ptr, size)
486 char *ptr;
487 unsigned size;
488{
489 register char *value = (char *) realloc (ptr, size);
490 if (value == 0)
491 fatal ("virtual memory exhausted");
492 return value;
493}
494
495int
496file_exists (name)
497 char *name;
498{
499 return access (name, R_OK) == 0;
4e81a331
RS
500}
501
ed5b9462
RS
502/* Make a copy of a string INPUT with size SIZE. */
503
504char *
505savestring (input, size)
506 char *input;
507 int size;
508{
509 char *output = (char *) xmalloc (size + 1);
1fab8e81
RS
510 bcopy (input, output, size);
511 output[size] = 0;
ed5b9462
RS
512 return output;
513}
514\f
a3184468
JM
515void
516dump_file (name)
517 char *name;
518{
519 FILE *stream = fopen (name, "r");
520 int no_demangle = !! getenv ("COLLECT_NO_DEMANGLE");
521
522 if (stream == 0)
523 return;
524 while (1)
525 {
526 int c;
527 while (c = getc (stream),
528 c != EOF && (isalnum (c) || c == '_' || c == '$' || c == '.'))
529 obstack_1grow (&temporary_obstack, c);
530 if (obstack_object_size (&temporary_obstack) > 0)
531 {
532 char *word, *p, *result;
533 obstack_1grow (&temporary_obstack, '\0');
534 word = obstack_finish (&temporary_obstack);
535
536 if (*word == '.')
537 ++word, putc ('.', stderr);
538 p = word;
539 if (*p == '_' && prepends_underscore)
540 ++p;
541
542 if (no_demangle)
543 result = 0;
544 else
545 result = cplus_demangle (p, DMGL_PARAMS | DMGL_ANSI);
546
547 if (result)
548 {
549 int diff;
550 fputs (result, stderr);
551
552 diff = strlen (word) - strlen (result);
553 while (diff > 0)
554 --diff, putc (' ', stderr);
555 while (diff < 0 && c == ' ')
556 ++diff, c = getc (stream);
557
558 free (result);
559 }
560 else
561 fputs (word, stderr);
562
563 fflush (stderr);
564 obstack_free (&temporary_obstack, temporary_firstobj);
565 }
566 if (c == EOF)
567 break;
568 putc (c, stderr);
569 }
570}
571\f
ed5b9462
RS
572/* Decide whether the given symbol is:
573 a constructor (1), a destructor (2), or neither (0). */
574
575static int
576is_ctor_dtor (s)
577 char *s;
578{
579 struct names { char *name; int len; int ret; int two_underscores; };
580
581 register struct names *p;
582 register int ch;
583 register char *orig_s = s;
584
585 static struct names special[] = {
586#ifdef NO_DOLLAR_IN_LABEL
7cbfceab 587#ifdef NO_DOT_IN_LABEL
c52d2678
RS
588 { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, 1, 0 },
589 { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, 2, 0 },
7cbfceab 590#else
ed5b9462
RS
591 { "GLOBAL_.I.", sizeof ("GLOBAL_.I.")-1, 1, 0 },
592 { "GLOBAL_.D.", sizeof ("GLOBAL_.D.")-1, 2, 0 },
7cbfceab 593#endif
ed5b9462
RS
594#else
595 { "GLOBAL_$I$", sizeof ("GLOBAL_$I$")-1, 1, 0 },
5555d6d1 596 { "GLOBAL_$D$", sizeof ("GLOBAL_$D$")-1, 2, 0 },
ed5b9462 597#endif
68d69835
JM
598 { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, 3, 0 },
599 { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, 4, 0 },
c1af0346
RS
600#ifdef CFRONT_LOSSAGE /* Don't collect cfront initialization functions.
601 cfront has its own linker procedure to collect them;
602 if collect2 gets them too, they get collected twice
603 when the cfront procedure is run and the compiler used
604 for linking happens to be GCC. */
ed5b9462
RS
605 { "sti__", sizeof ("sti__")-1, 1, 1 },
606 { "std__", sizeof ("std__")-1, 2, 1 },
7a646ee5 607#endif /* CFRONT_LOSSAGE */
ed5b9462
RS
608 { NULL, 0, 0, 0 }
609 };
610
611 while ((ch = *s) == '_')
612 ++s;
613
614 if (s == orig_s)
615 return 0;
616
617 for (p = &special[0]; p->len > 0; p++)
618 {
619 if (ch == p->name[0]
620 && (!p->two_underscores || ((s - orig_s) >= 2))
621 && strncmp(s, p->name, p->len) == 0)
622 {
623 return p->ret;
624 }
625 }
626 return 0;
627}
628
4e81a331
RS
629\f
630/* Compute a string to use as the base of all temporary file names.
631 It is substituted for %g. */
632
633static void
ed5b9462 634choose_temp_base ()
4e81a331
RS
635{
636 char *base = getenv ("TMPDIR");
637 int len;
638
639 if (base == (char *)0)
640 {
641#ifdef P_tmpdir
642 if (access (P_tmpdir, R_OK | W_OK) == 0)
643 base = P_tmpdir;
644#endif
645 if (base == (char *)0)
646 {
647 if (access ("/usr/tmp", R_OK | W_OK) == 0)
648 base = "/usr/tmp/";
649 else
650 base = "/tmp/";
651 }
652 }
653
654 len = strlen (base);
aee42e27 655 temp_filename = xmalloc (len + sizeof("/ccXXXXXX") + 1);
4e81a331
RS
656 strcpy (temp_filename, base);
657 if (len > 0 && temp_filename[len-1] != '/')
658 temp_filename[len++] = '/';
659 strcpy (temp_filename + len, "ccXXXXXX");
660
661 mktemp (temp_filename);
662 temp_filename_length = strlen (temp_filename);
663}
bb59f9a6 664\f
45840c57
RK
665/* Routine to add variables to the environment. */
666
667#ifndef HAVE_PUTENV
668
4d1a011f 669int
45840c57
RK
670putenv (str)
671 char *str;
672{
673#ifndef VMS /* nor about VMS */
674
675 extern char **environ;
676 char **old_environ = environ;
677 char **envp;
678 int num_envs = 0;
679 int name_len = 1;
45840c57
RK
680 char *p = str;
681 int ch;
682
683 while ((ch = *p++) != '\0' && ch != '=')
684 name_len++;
685
686 if (!ch)
687 abort ();
688
689 /* Search for replacing an existing environment variable, and
690 count the number of total environment variables. */
691 for (envp = old_environ; *envp; envp++)
692 {
693 num_envs++;
694 if (!strncmp (str, *envp, name_len))
695 {
696 *envp = str;
4d1a011f 697 return 0;
45840c57
RK
698 }
699 }
700
701 /* Add a new environment variable */
702 environ = (char **) xmalloc (sizeof (char *) * (num_envs+2));
703 *environ = str;
4c9a05bc
RK
704 bcopy ((char *) old_environ, (char *) (environ + 1),
705 sizeof (char *) * (num_envs+1));
706
4d1a011f 707 return 0;
45840c57
RK
708#endif /* VMS */
709}
710
711#endif /* HAVE_PUTENV */
712\f
bb59f9a6
RS
713/* By default, colon separates directories in a path. */
714#ifndef PATH_SEPARATOR
715#define PATH_SEPARATOR ':'
716#endif
717
bb59f9a6
RS
718/* We maintain two prefix lists: one from COMPILER_PATH environment variable
719 and one from the PATH variable. */
720
721static struct path_prefix cpath, path;
722
723#ifdef CROSS_COMPILE
724/* This is the name of the target machine. We use it to form the name
725 of the files to execute. */
726
727static char *target_machine = TARGET_MACHINE;
728#endif
720653a3 729
45840c57 730/* Names under which we were executed. Never return one of those files in our
720653a3
RK
731 searches. */
732
7223feb0 733static struct path_prefix our_file_names;
bb59f9a6 734\f
7223feb0
DE
735/* Determine if STRING is in PPREFIX.
736
737 This utility is currently only used to look up file names. Prefix lists
738 record directory names. This matters to us because the latter has a
739 trailing slash, so I've added a flag to handle both. */
740
741static int
742is_in_prefix_list (pprefix, string, filep)
743 struct path_prefix *pprefix;
744 char *string;
745 int filep;
746{
747 struct prefix_list *pl;
748
749 if (filep)
750 {
751 int len = strlen (string);
752
753 for (pl = pprefix->plist; pl; pl = pl->next)
754 {
755 if (strncmp (pl->prefix, string, len) == 0
756 && strcmp (pl->prefix + len, "/") == 0)
757 return 1;
758 }
759 }
760 else
761 {
762 for (pl = pprefix->plist; pl; pl = pl->next)
763 {
764 if (strcmp (pl->prefix, string) == 0)
765 return 1;
766 }
767 }
768
769 return 0;
770}
771
bb59f9a6
RS
772/* Search for NAME using prefix list PPREFIX. We only look for executable
773 files.
774
775 Return 0 if not found, otherwise return its name, allocated with malloc. */
776
777static char *
778find_a_file (pprefix, name)
779 struct path_prefix *pprefix;
780 char *name;
781{
782 char *temp;
783 struct prefix_list *pl;
784 int len = pprefix->max_len + strlen (name) + 1;
785
786#ifdef EXECUTABLE_SUFFIX
787 len += strlen (EXECUTABLE_SUFFIX);
788#endif
789
790 temp = xmalloc (len);
791
792 /* Determine the filename to execute (special case for absolute paths). */
793
794 if (*name == '/')
795 {
e8fda1f9 796 if (access (name, X_OK) == 0)
bb59f9a6
RS
797 {
798 strcpy (temp, name);
799 return temp;
800 }
801 }
802 else
803 for (pl = pprefix->plist; pl; pl = pl->next)
804 {
805 strcpy (temp, pl->prefix);
806 strcat (temp, name);
7223feb0 807 if (! is_in_prefix_list (&our_file_names, temp, 1)
aee3a549
RK
808 /* This is a kludge, but there seems no way around it. */
809 && strcmp (temp, "./ld") != 0
45840c57 810 && access (temp, X_OK) == 0)
bb59f9a6
RS
811 return temp;
812
813#ifdef EXECUTABLE_SUFFIX
814 /* Some systems have a suffix for executable files.
815 So try appending that. */
816 strcat (temp, EXECUTABLE_SUFFIX);
7223feb0 817 if (! is_in_prefix_list (&our_file_names, temp, 1)
45840c57 818 && access (temp, X_OK) == 0)
bb59f9a6
RS
819 return temp;
820#endif
821 }
822
823 free (temp);
824 return 0;
825}
826
827/* Add an entry for PREFIX to prefix list PPREFIX. */
828
829static void
830add_prefix (pprefix, prefix)
831 struct path_prefix *pprefix;
832 char *prefix;
833{
834 struct prefix_list *pl, **prev;
835 int len;
836
837 if (pprefix->plist)
838 {
839 for (pl = pprefix->plist; pl->next; pl = pl->next)
840 ;
841 prev = &pl->next;
842 }
843 else
844 prev = &pprefix->plist;
845
846 /* Keep track of the longest prefix */
847
848 len = strlen (prefix);
849 if (len > pprefix->max_len)
850 pprefix->max_len = len;
851
852 pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list));
853 pl->prefix = savestring (prefix, len);
854
855 if (*prev)
856 pl->next = *prev;
857 else
858 pl->next = (struct prefix_list *) 0;
859 *prev = pl;
860}
861\f
862/* Take the value of the environment variable ENV, break it into a path, and
863 add of the entries to PPREFIX. */
864
865static void
866prefix_from_env (env, pprefix)
867 char *env;
868 struct path_prefix *pprefix;
869{
870 char *p = getenv (env);
871
872 if (p)
cbbbd917
JM
873 prefix_from_string (p, pprefix);
874}
bb59f9a6 875
cbbbd917
JM
876static void
877prefix_from_string (p, pprefix)
878 char *p;
879 struct path_prefix *pprefix;
880{
881 char *startp, *endp;
882 char *nstore = (char *) xmalloc (strlen (p) + 3);
883
884 startp = endp = p;
885 while (1)
886 {
887 if (*endp == PATH_SEPARATOR || *endp == 0)
bb59f9a6 888 {
cbbbd917
JM
889 strncpy (nstore, startp, endp-startp);
890 if (endp == startp)
bb59f9a6 891 {
cbbbd917
JM
892 strcpy (nstore, "./");
893 }
894 else if (endp[-1] != '/')
895 {
896 nstore[endp-startp] = '/';
897 nstore[endp-startp+1] = 0;
bb59f9a6
RS
898 }
899 else
cbbbd917
JM
900 nstore[endp-startp] = 0;
901
902 add_prefix (pprefix, nstore);
903 if (*endp == 0)
904 break;
905 endp = startp = endp + 1;
bb59f9a6 906 }
cbbbd917
JM
907 else
908 endp++;
bb59f9a6
RS
909 }
910}
4e81a331
RS
911\f
912/* Main program. */
913
914int
915main (argc, argv)
916 int argc;
917 char *argv[];
918{
bb59f9a6
RS
919 char *ld_suffix = "ld";
920 char *full_ld_suffix = ld_suffix;
921 char *real_ld_suffix = "real-ld";
e8fda1f9 922 char *full_real_ld_suffix = real_ld_suffix;
a3184468 923 char *collect_ld_suffix = "collect-ld";
bb59f9a6
RS
924 char *nm_suffix = "nm";
925 char *full_nm_suffix = nm_suffix;
926 char *gnm_suffix = "gnm";
927 char *full_gnm_suffix = gnm_suffix;
68d69835
JM
928#ifdef LDD_SUFFIX
929 char *ldd_suffix = LDD_SUFFIX;
930 char *full_ldd_suffix = ldd_suffix;
931#endif
bb59f9a6
RS
932 char *strip_suffix = "strip";
933 char *full_strip_suffix = strip_suffix;
934 char *gstrip_suffix = "gstrip";
935 char *full_gstrip_suffix = gstrip_suffix;
4e81a331 936 char *arg;
cbbbd917 937 FILE *outf, *exportf;
4e81a331 938 char *ld_file_name;
588e387f 939 char *collect_name;
7223feb0 940 char *collect_names;
4e81a331 941 char *p;
ed5b9462
RS
942 char **c_argv;
943 char **c_ptr;
cbbbd917 944 char **ld1_argv = (char **) xcalloc (sizeof (char *), argc+3);
4e81a331 945 char **ld1 = ld1_argv;
cbbbd917 946 char **ld2_argv = (char **) xcalloc (sizeof (char *), argc+6);
4e81a331 947 char **ld2 = ld2_argv;
9f21696b
JM
948 char **object_lst = (char **) xcalloc (sizeof (char *), argc);
949 char **object = object_lst;
4e81a331 950 int first_file;
ed5b9462 951 int num_c_args = argc+7;
4e81a331
RS
952
953#ifdef DEBUG
954 debug = 1;
955 vflag = 1;
956#endif
957
0cdd3ddd
RS
958 output_file = "a.out";
959
a3184468
JM
960 obstack_begin (&temporary_obstack, 0);
961 obstack_begin (&permanent_obstack, 0);
962 temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0);
963 current_demangling_style = gnu_demangling;
964
45840c57 965 /* We must check that we do not call ourselves in an infinite
588e387f
DE
966 recursion loop. We append the name used for us to the COLLECT_NAMES
967 environment variable.
45840c57 968
7223feb0
DE
969 In practice, collect will rarely invoke itself. This can happen now
970 that we are no longer called gld. A perfect example is when running
971 gcc in a build directory that has been installed. When looking for
972 ld's, we'll find our installed version and believe that's the real ld. */
45840c57 973
588e387f
DE
974 /* We must also append COLLECT_NAME to COLLECT_NAMES to watch for the
975 previous version of collect (the one that used COLLECT_NAME and only
976 handled two levels of recursion). If we don't we may mutually recurse
977 forever. This can happen (I think) when bootstrapping the old version
978 and a new one is installed (rare, but we should handle it).
979 ??? Hopefully references to COLLECT_NAME can be removed at some point. */
980
981 collect_name = (char *) getenv ("COLLECT_NAME");
7223feb0 982 collect_names = (char *) getenv ("COLLECT_NAMES");
45840c57 983
7223feb0 984 p = (char *) xmalloc (strlen ("COLLECT_NAMES=")
588e387f 985 + (collect_name ? strlen (collect_name) + 1 : 0)
7223feb0
DE
986 + (collect_names ? strlen (collect_names) + 1 : 0)
987 + strlen (argv[0]) + 1);
588e387f
DE
988 strcpy (p, "COLLECT_NAMES=");
989 if (collect_name != 0)
990 sprintf (p + strlen (p), "%s%c", collect_name, PATH_SEPARATOR);
7223feb0 991 if (collect_names != 0)
588e387f
DE
992 sprintf (p + strlen (p), "%s%c", collect_names, PATH_SEPARATOR);
993 strcat (p, argv[0]);
45840c57
RK
994 putenv (p);
995
7223feb0
DE
996 prefix_from_env ("COLLECT_NAMES", &our_file_names);
997
588e387f
DE
998 /* Set environment variable COLLECT_NAME to our name so the previous version
999 of collect won't find us. If it does we'll mutually recurse forever.
1000 This can happen when bootstrapping the new version and an old version is
1001 installed.
1002 ??? Hopefully this bit of code can be removed at some point. */
1003
1004 p = xmalloc (strlen ("COLLECT_NAME=") + strlen (argv[0]) + 1);
1005 sprintf (p, "COLLECT_NAME=%s", argv[0]);
1006 putenv (p);
1007
ed5b9462
RS
1008 p = (char *) getenv ("COLLECT_GCC_OPTIONS");
1009 if (p)
1010 while (*p)
1011 {
1012 char *q = p;
1013 while (*q && *q != ' ') q++;
17704846 1014 if (*p == '-' && p[1] == 'm')
ed5b9462
RS
1015 num_c_args++;
1016
1017 if (*q) q++;
1018 p = q;
1019 }
1020
1021 c_ptr = c_argv = (char **) xcalloc (sizeof (char *), num_c_args);
1022
4e81a331
RS
1023 if (argc < 2)
1024 fatal ("no arguments");
1025
8ab861c7 1026#ifdef SIGQUIT
915ee623
JW
1027 if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
1028 signal (SIGQUIT, handler);
8ab861c7 1029#endif
915ee623
JW
1030 if (signal (SIGINT, SIG_IGN) != SIG_IGN)
1031 signal (SIGINT, handler);
8ab861c7 1032#ifdef SIGALRM
915ee623
JW
1033 if (signal (SIGALRM, SIG_IGN) != SIG_IGN)
1034 signal (SIGALRM, handler);
8ab861c7
RK
1035#endif
1036#ifdef SIGHUP
915ee623
JW
1037 if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
1038 signal (SIGHUP, handler);
8ab861c7 1039#endif
915ee623
JW
1040 if (signal (SIGSEGV, SIG_IGN) != SIG_IGN)
1041 signal (SIGSEGV, handler);
8ab861c7 1042#ifdef SIGBUS
915ee623
JW
1043 if (signal (SIGBUS, SIG_IGN) != SIG_IGN)
1044 signal (SIGBUS, handler);
8ab861c7 1045#endif
4e81a331 1046
bb59f9a6
RS
1047 /* Extract COMPILER_PATH and PATH into our prefix list. */
1048 prefix_from_env ("COMPILER_PATH", &cpath);
1049 prefix_from_env ("PATH", &path);
4e81a331 1050
bb59f9a6
RS
1051#ifdef CROSS_COMPILE
1052 /* If we look for a program in the compiler directories, we just use
1053 the short name, since these directories are already system-specific.
1054 But it we look for a took in the system directories, we need to
1055 qualify the program name with the target machine. */
1056
1057 full_ld_suffix
aee42e27 1058 = xcalloc (strlen (ld_suffix) + strlen (target_machine) + 2, 1);
46c74083 1059 strcpy (full_ld_suffix, target_machine);
bb59f9a6 1060 strcat (full_ld_suffix, "-");
46c74083 1061 strcat (full_ld_suffix, ld_suffix);
bb59f9a6
RS
1062
1063 full_real_ld_suffix
aee42e27 1064 = xcalloc (strlen (real_ld_suffix) + strlen (target_machine) + 2, 1);
46c74083 1065 strcpy (full_real_ld_suffix, target_machine);
bb59f9a6 1066 strcat (full_real_ld_suffix, "-");
46c74083 1067 strcat (full_real_ld_suffix, real_ld_suffix);
bb59f9a6 1068
98552524 1069#if 0
bb59f9a6 1070 full_gld_suffix
aee42e27 1071 = xcalloc (strlen (gld_suffix) + strlen (target_machine) + 2, 1);
46c74083 1072 strcpy (full_gld_suffix, target_machine);
bb59f9a6 1073 strcat (full_gld_suffix, "-");
46c74083 1074 strcat (full_gld_suffix, gld_suffix);
98552524 1075#endif
bb59f9a6
RS
1076
1077 full_nm_suffix
aee42e27 1078 = xcalloc (strlen (nm_suffix) + strlen (target_machine) + 2, 1);
46c74083 1079 strcpy (full_nm_suffix, target_machine);
bb59f9a6 1080 strcat (full_nm_suffix, "-");
46c74083 1081 strcat (full_nm_suffix, nm_suffix);
bb59f9a6
RS
1082
1083 full_gnm_suffix
aee42e27 1084 = xcalloc (strlen (gnm_suffix) + strlen (target_machine) + 2, 1);
46c74083 1085 strcpy (full_gnm_suffix, target_machine);
bb59f9a6 1086 strcat (full_gnm_suffix, "-");
46c74083 1087 strcat (full_gnm_suffix, gnm_suffix);
bb59f9a6 1088
68d69835
JM
1089#ifdef LDD_SUFFIX
1090 full_ldd_suffix
1091 = xcalloc (strlen (ldd_suffix) + strlen (target_machine) + 2, 1);
1092 strcpy (full_ldd_suffix, target_machine);
1093 strcat (full_ldd_suffix, "-");
1094 strcat (full_ldd_suffix, ldd_suffix);
1095#endif
1096
bb59f9a6 1097 full_strip_suffix
aee42e27 1098 = xcalloc (strlen (strip_suffix) + strlen (target_machine) + 2, 1);
46c74083 1099 strcpy (full_strip_suffix, target_machine);
bb59f9a6 1100 strcat (full_strip_suffix, "-");
46c74083 1101 strcat (full_strip_suffix, strip_suffix);
bb59f9a6
RS
1102
1103 full_gstrip_suffix
aee42e27 1104 = xcalloc (strlen (gstrip_suffix) + strlen (target_machine) + 2, 1);
46c74083 1105 strcpy (full_gstrip_suffix, target_machine);
bb59f9a6 1106 strcat (full_gstrip_suffix, "-");
46c74083 1107 strcat (full_gstrip_suffix, gstrip_suffix);
bb59f9a6
RS
1108#endif /* CROSS_COMPILE */
1109
1110 /* Try to discover a valid linker/nm/strip to use. */
1111
90d326bd
JM
1112 /* Maybe we know the right file to use (if not cross). */
1113#ifdef REAL_LD_FILE_NAME
1114 ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME);
1115 if (ld_file_name == 0)
1116#endif
a3184468
JM
1117 /* Search the (target-specific) compiler dirs for ld'. */
1118 ld_file_name = find_a_file (&cpath, real_ld_suffix);
1119 /* Likewise for `collect-ld'. */
bb59f9a6 1120 if (ld_file_name == 0)
a3184468 1121 ld_file_name = find_a_file (&cpath, collect_ld_suffix);
b3a2ef94
RK
1122 /* Search the compiler directories for `ld'. We have protection against
1123 recursive calls in find_a_file. */
f820b898 1124 if (ld_file_name == 0)
b3a2ef94 1125 ld_file_name = find_a_file (&cpath, ld_suffix);
bb59f9a6 1126 /* Search the ordinary system bin directories
46c74083 1127 for `ld' (if native linking) or `TARGET-ld' (if cross). */
bb59f9a6
RS
1128 if (ld_file_name == 0)
1129 ld_file_name = find_a_file (&path, full_ld_suffix);
1130
7223feb0
DE
1131 /* If we've invoked ourselves, try again with LD_FILE_NAME. */
1132
1133 if (collect_names != 0)
1134 {
1135 if (ld_file_name != 0)
1136 {
1137 argv[0] = ld_file_name;
1138 execvp (argv[0], argv);
1139 }
1140 fatal ("cannot find `ld'");
1141 }
1142
90d326bd
JM
1143#ifdef REAL_NM_FILE_NAME
1144 nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME);
1145 if (nm_file_name == 0)
1146#endif
bb59f9a6
RS
1147 nm_file_name = find_a_file (&cpath, gnm_suffix);
1148 if (nm_file_name == 0)
1149 nm_file_name = find_a_file (&path, full_gnm_suffix);
1150 if (nm_file_name == 0)
1151 nm_file_name = find_a_file (&cpath, nm_suffix);
bb59f9a6
RS
1152 if (nm_file_name == 0)
1153 nm_file_name = find_a_file (&path, full_nm_suffix);
1154
68d69835
JM
1155#ifdef LDD_SUFFIX
1156 ldd_file_name = find_a_file (&cpath, ldd_suffix);
1157 if (ldd_file_name == 0)
1158 ldd_file_name = find_a_file (&path, full_ldd_suffix);
1159#endif
1160
90d326bd
JM
1161#ifdef REAL_STRIP_FILE_NAME
1162 strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME);
1163 if (strip_file_name == 0)
1164#endif
bb59f9a6
RS
1165 strip_file_name = find_a_file (&cpath, gstrip_suffix);
1166 if (strip_file_name == 0)
1167 strip_file_name = find_a_file (&path, full_gstrip_suffix);
1168 if (strip_file_name == 0)
1169 strip_file_name = find_a_file (&cpath, strip_suffix);
bb59f9a6
RS
1170 if (strip_file_name == 0)
1171 strip_file_name = find_a_file (&path, full_strip_suffix);
4e81a331 1172
a87104d9 1173 /* Determine the full path name of the C compiler to use. */
ed5b9462 1174 c_file_name = getenv ("COLLECT_GCC");
5365d6ee 1175 if (c_file_name == 0)
4e81a331 1176 {
bb59f9a6 1177#ifdef CROSS_COMPILE
aee42e27 1178 c_file_name = xcalloc (sizeof ("gcc-") + strlen (target_machine) + 1, 1);
46c74083
RS
1179 strcpy (c_file_name, target_machine);
1180 strcat (c_file_name, "-gcc");
4e81a331 1181#else
bb59f9a6 1182 c_file_name = "gcc";
a87104d9 1183#endif
a87104d9
MM
1184 }
1185
bb59f9a6
RS
1186 p = find_a_file (&cpath, c_file_name);
1187
1188 /* Here it should be safe to use the system search path since we should have
1189 already qualified the name of the compiler when it is needed. */
1190 if (p == 0)
1191 p = find_a_file (&path, c_file_name);
1192
1193 if (p)
1194 c_file_name = p;
4e81a331 1195
45840c57 1196 *ld1++ = *ld2++ = ld_file_name;
4e81a331
RS
1197
1198 /* Make temp file names. */
1199 choose_temp_base ();
1200 c_file = xcalloc (temp_filename_length + sizeof (".c"), 1);
1201 o_file = xcalloc (temp_filename_length + sizeof (".o"), 1);
cbbbd917 1202 export_file = xmalloc (temp_filename_length + sizeof (".x"));
a3184468
JM
1203 ldout = xmalloc (temp_filename_length + sizeof (".ld"));
1204 sprintf (ldout, "%s.ld", temp_filename);
4e81a331
RS
1205 sprintf (c_file, "%s.c", temp_filename);
1206 sprintf (o_file, "%s.o", temp_filename);
cbbbd917 1207 sprintf (export_file, "%s.x", temp_filename);
ed5b9462 1208 *c_ptr++ = c_file_name;
4e81a331
RS
1209 *c_ptr++ = "-c";
1210 *c_ptr++ = "-o";
1211 *c_ptr++ = o_file;
1212
ed5b9462
RS
1213 /* !!! When GCC calls collect2,
1214 it does not know whether it is calling collect2 or ld.
1215 So collect2 cannot meaningfully understand any options
1216 except those ld understands.
1217 If you propose to make GCC pass some other option,
1218 just imagine what will happen if ld is really ld!!! */
1219
4e81a331 1220 /* Parse arguments. Remember output file spec, pass the rest to ld. */
ed5b9462
RS
1221 /* After the first file, put in the c++ rt0. */
1222
4e81a331
RS
1223 first_file = 1;
1224 while ((arg = *++argv) != (char *)0)
1225 {
1226 *ld1++ = *ld2++ = arg;
1227
1228 if (arg[0] == '-')
2d5e74ca 1229 {
4e81a331
RS
1230 switch (arg[1])
1231 {
1232 case 'd':
1233 if (!strcmp (arg, "-debug"))
1234 {
1235 debug = 1;
1236 vflag = 1;
1237 ld1--;
1238 ld2--;
1239 }
1240 break;
1241
cbbbd917
JM
1242#ifdef COLLECT_EXPORT_LIST
1243 case 'b':
603b4064
RK
1244 if ((!strncmp (arg, "-bE:", 4)
1245 || !strncmp (arg, "-bexport:", 9))
1246 && strcmp (arg, "-bexport:/usr/lib/libg.exp"))
cbbbd917
JM
1247 auto_export = 0;
1248 break;
1249#endif
1250
68d69835
JM
1251 case 'l':
1252 if (first_file)
1253 {
1254 /* place o_file BEFORE this argument! */
1255 first_file = 0;
1256 ld2--;
1257 *ld2++ = o_file;
1258 *ld2++ = arg;
1259 }
1260 break;
1261
4e81a331 1262 case 'o':
603b4064
RK
1263 if (arg[2] == '\0')
1264 output_file = *ld1++ = *ld2++ = *++argv;
1265 else
1266 output_file = &arg[2];
4e81a331
RS
1267 break;
1268
1269 case 'r':
1270 if (arg[2] == '\0')
1271 rflag = 1;
1272 break;
1273
a87104d9 1274 case 's':
a3184468 1275 if (arg[2] == '\0' && do_collecting)
a87104d9
MM
1276 {
1277 /* We must strip after the nm run, otherwise C++ linking
1278 won't work. Thus we strip in the second ld run, or
1279 else with strip if there is no second ld run. */
1280 strip_flag = 1;
1281 ld1--;
1282 }
1283 break;
1284
4e81a331
RS
1285 case 'v':
1286 if (arg[2] == '\0')
1287 vflag = 1;
1288 break;
1289 }
2d5e74ca 1290 }
9f21696b 1291 else if ((p = rindex (arg, '.')) != (char *)0
68d69835 1292 && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0))
4e81a331 1293 {
9f21696b
JM
1294 if (first_file)
1295 {
1296 first_file = 0;
603b4064
RK
1297 if (p[1] == 'o')
1298 *ld2++ = o_file;
1299 else
1300 {
1301 /* place o_file BEFORE this argument! */
1302 ld2--;
1303 *ld2++ = o_file;
1304 *ld2++ = arg;
1305 }
9f21696b
JM
1306 }
1307 if (p[1] == 'o')
1308 *object++ = arg;
4e81a331
RS
1309 }
1310 }
1311
ed5b9462
RS
1312 /* Get any options that the upper GCC wants to pass to the sub-GCC. */
1313 p = (char *) getenv ("COLLECT_GCC_OPTIONS");
1314 if (p)
1315 while (*p)
1316 {
1317 char *q = p;
1318 while (*q && *q != ' ') q++;
1319 if (*p == '-' && (p[1] == 'm' || p[1] == 'f'))
1320 *c_ptr++ = savestring (p, q - p);
68d69835
JM
1321 if (strncmp (p, "-shared", sizeof ("shared") - 1) == 0)
1322 shared_obj = 1;
ed5b9462
RS
1323
1324 if (*q) q++;
1325 p = q;
1326 }
1327
cbbbd917
JM
1328#ifdef COLLECT_EXPORT_LIST
1329 /* The AIX linker will discard static constructors in object files if
1330 nothing else in the file is referenced, so look at them first. */
1331 while (object_lst < object)
1332 scan_prog_file (*object_lst++, PASS_OBJ);
1333
1334 {
1335 char *buf = alloca (strlen (export_file) + 5);
1336 sprintf (buf, "-bE:%s", export_file);
1337 *ld1++ = buf;
1338 *ld2++ = buf;
1339 exportf = fopen (export_file, "w");
1340 if (exportf == (FILE *)0)
1341 fatal_perror ("%s", export_file);
1342 write_export_file (exportf);
1343 if (fclose (exportf))
1344 fatal_perror ("closing %s", export_file);
1345 }
1346#endif
1347
4e81a331 1348 *c_ptr++ = c_file;
603b4064 1349 *object = *c_ptr = *ld1 = (char *)0;
4e81a331
RS
1350
1351 if (vflag)
1352 {
ed5b9462 1353 fprintf (stderr, "collect2 version %s", version_string);
4e81a331
RS
1354#ifdef TARGET_VERSION
1355 TARGET_VERSION;
1356#endif
1357 fprintf (stderr, "\n");
1358 }
1359
1360 if (debug)
1361 {
ed5b9462 1362 char *ptr;
a1549b15
RS
1363 fprintf (stderr, "ld_file_name = %s\n",
1364 (ld_file_name ? ld_file_name : "not found"));
1365 fprintf (stderr, "c_file_name = %s\n",
1366 (c_file_name ? c_file_name : "not found"));
1367 fprintf (stderr, "nm_file_name = %s\n",
1368 (nm_file_name ? nm_file_name : "not found"));
68d69835
JM
1369#ifdef LDD_SUFFIX
1370 fprintf (stderr, "ldd_file_name = %s\n",
1371 (ldd_file_name ? ldd_file_name : "not found"));
1372#endif
a1549b15
RS
1373 fprintf (stderr, "strip_file_name = %s\n",
1374 (strip_file_name ? strip_file_name : "not found"));
1375 fprintf (stderr, "c_file = %s\n",
1376 (c_file ? c_file : "not found"));
1377 fprintf (stderr, "o_file = %s\n",
1378 (o_file ? o_file : "not found"));
ed5b9462 1379
7223feb0
DE
1380 ptr = getenv ("COLLECT_NAMES");
1381 if (ptr)
1382 fprintf (stderr, "COLLECT_NAMES = %s\n", ptr);
1383
ed5b9462
RS
1384 ptr = getenv ("COLLECT_GCC_OPTIONS");
1385 if (ptr)
1386 fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
1387
1388 ptr = getenv ("COLLECT_GCC");
1389 if (ptr)
1390 fprintf (stderr, "COLLECT_GCC = %s\n", ptr);
1391
1392 ptr = getenv ("COMPILER_PATH");
1393 if (ptr)
1394 fprintf (stderr, "COMPILER_PATH = %s\n", ptr);
1395
1396 ptr = getenv ("LIBRARY_PATH");
1397 if (ptr)
1398 fprintf (stderr, "LIBRARY_PATH = %s\n", ptr);
1399
1400 fprintf (stderr, "\n");
4e81a331
RS
1401 }
1402
a3184468 1403 /* Load the program, searching all libraries. */
4e81a331 1404
a3184468
JM
1405 collect_execute ("ld", ld1_argv, ldout);
1406 do_wait ("ld");
1407 dump_file (ldout);
1408 unlink (ldout);
4e81a331 1409
a3184468
JM
1410 /* If -r or they'll be run via some other method, don't build the
1411 constructor or destructor list, just return now. */
1412 if (rflag || ! do_collecting)
4e81a331
RS
1413 return 0;
1414
a3184468
JM
1415 /* Examine the namelist with nm and search it for static constructors
1416 and destructors to call.
1417 Write the constructor and destructor tables to a .s file and reload. */
1418
0cdd3ddd 1419 scan_prog_file (output_file, PASS_FIRST);
4e81a331 1420
68d69835
JM
1421#ifdef SCAN_LIBRARIES
1422 scan_libraries (output_file);
1423#endif
1424
4e81a331
RS
1425 if (debug)
1426 {
1427 fprintf (stderr, "%d constructor(s) found\n", constructors.number);
1428 fprintf (stderr, "%d destructor(s) found\n", destructors.number);
1429 }
1430
68d69835
JM
1431 if (constructors.number == 0 && destructors.number == 0
1432#ifdef LDD_SUFFIX
1433 /* If we will be running these functions ourselves, we want to emit
1434 stubs into the shared library so that we don't have to relink
1435 dependent programs when we add static objects. */
1436 && ! shared_obj
1437#endif
1438 )
a87104d9
MM
1439 {
1440 /* Strip now if it was requested on the command line. */
1441 if (strip_flag)
1442 {
1443 char **strip_argv = (char **) xcalloc (sizeof (char *), 3);
aee3a549 1444 strip_argv[0] = strip_file_name;
0cdd3ddd 1445 strip_argv[1] = output_file;
a87104d9 1446 strip_argv[2] = (char *) 0;
aee3a549 1447 fork_execute ("strip", strip_argv);
a87104d9 1448 }
eccd41bb
RK
1449
1450#ifdef COLLECT_EXPORT_LIST
1451 maybe_unlink (export_file);
1452#endif
a87104d9
MM
1453 return 0;
1454 }
4e81a331 1455
eeed1288 1456 maybe_unlink(output_file);
4e81a331
RS
1457 outf = fopen (c_file, "w");
1458 if (outf == (FILE *)0)
1fab8e81 1459 fatal_perror ("%s", c_file);
4e81a331
RS
1460
1461 write_c_file (outf, c_file);
1462
1463 if (fclose (outf))
1fab8e81 1464 fatal_perror ("closing %s", c_file);
4e81a331 1465
603b4064
RK
1466 /* Tell the linker that we have initializer and finalizer functions. */
1467#ifdef LD_INIT_SWITCH
1468 *ld2++ = LD_INIT_SWITCH;
1469 *ld2++ = initname;
1470 *ld2++ = LD_FINI_SWITCH;
1471 *ld2++ = fininame;
1472#endif
1473 *ld2 = (char*)0;
1474
cbbbd917
JM
1475#ifdef COLLECT_EXPORT_LIST
1476 if (shared_obj)
1477 {
1478 add_to_list (&exports, initname);
1479 add_to_list (&exports, fininame);
603b4064
RK
1480 add_to_list (&exports, "_GLOBAL__DI");
1481 add_to_list (&exports, "_GLOBAL__DD");
cbbbd917
JM
1482 exportf = fopen (export_file, "w");
1483 if (exportf == (FILE *)0)
1484 fatal_perror ("%s", export_file);
1485 write_export_file (exportf);
1486 if (fclose (exportf))
1487 fatal_perror ("closing %s", export_file);
1488 }
1489#endif
1490
4e81a331
RS
1491 if (debug)
1492 {
0cdd3ddd
RS
1493 fprintf (stderr, "\n========== output_file = %s, c_file = %s\n",
1494 output_file, c_file);
4e81a331
RS
1495 write_c_file (stderr, "stderr");
1496 fprintf (stderr, "========== end of c_file\n\n");
cbbbd917
JM
1497#ifdef COLLECT_EXPORT_LIST
1498 fprintf (stderr, "\n========== export_file = %s\n", export_file);
1499 write_export_file (stderr);
1500 fprintf (stderr, "========== end of export_file\n\n");
1501#endif
4e81a331
RS
1502 }
1503
1504 /* Assemble the constructor and destructor tables.
1505 Link the tables in with the rest of the program. */
1506
aee3a549
RK
1507 fork_execute ("gcc", c_argv);
1508 fork_execute ("ld", ld2_argv);
4e81a331
RS
1509
1510 /* Let scan_prog_file do any final mods (OSF/rose needs this for
1511 constructors/destructors in shared libraries. */
0cdd3ddd 1512 scan_prog_file (output_file, PASS_SECOND);
4e81a331
RS
1513
1514 maybe_unlink (c_file);
1515 maybe_unlink (o_file);
cbbbd917 1516 maybe_unlink (export_file);
4e81a331
RS
1517 return 0;
1518}
1519
1520\f
1521/* Wait for a process to finish, and exit if a non-zero status is found. */
1522
a3184468
JM
1523int
1524collect_wait (prog)
4e81a331
RS
1525 char *prog;
1526{
1527 int status;
1528
1529 wait (&status);
1530 if (status)
1531 {
0b90f9c2 1532 if (WIFSIGNALED (status))
4e81a331 1533 {
0b90f9c2 1534 int sig = WTERMSIG (status);
ed5b9462
RS
1535#ifdef NO_SYS_SIGLIST
1536 error ("%s terminated with signal %d %s",
1537 prog,
1538 sig,
1539 (status & 0200) ? ", core dumped" : "");
1540#else
4e81a331
RS
1541 error ("%s terminated with signal %d [%s]%s",
1542 prog,
1543 sig,
1544 sys_siglist[sig],
1545 (status & 0200) ? ", core dumped" : "");
ed5b9462 1546#endif
4e81a331 1547
a3184468 1548 collect_exit (127);
4e81a331
RS
1549 }
1550
0b90f9c2 1551 if (WIFEXITED (status))
a3184468
JM
1552 return WEXITSTATUS (status);
1553 }
1554 return 0;
1555}
1556
1557static void
1558do_wait (prog)
1559 char *prog;
1560{
1561 int ret = collect_wait (prog);
1562 if (ret != 0)
1563 {
1564 error ("%s returned %d exit status", prog, ret);
1565 collect_exit (ret);
4e81a331
RS
1566 }
1567}
1568
1569\f
1570/* Fork and execute a program, and wait for the reply. */
1571
a3184468
JM
1572void
1573collect_execute (prog, argv, redir)
4e81a331
RS
1574 char *prog;
1575 char **argv;
a3184468 1576 char *redir;
4e81a331
RS
1577{
1578 int pid;
4e81a331
RS
1579
1580 if (vflag || debug)
1581 {
1582 char **p_argv;
1583 char *str;
1584
aee3a549
RK
1585 if (argv[0])
1586 fprintf (stderr, "%s", argv[0]);
bb59f9a6 1587 else
aee3a549 1588 fprintf (stderr, "[cannot find %s]", prog);
bb59f9a6 1589
4e81a331
RS
1590 for (p_argv = &argv[1]; (str = *p_argv) != (char *)0; p_argv++)
1591 fprintf (stderr, " %s", str);
1592
1593 fprintf (stderr, "\n");
1594 }
1595
1596 fflush (stdout);
1597 fflush (stderr);
1598
bb59f9a6
RS
1599 /* If we can't find a program we need, complain error. Do this here
1600 since we might not end up needing something that we couldn't find. */
1601
aee3a549
RK
1602 if (argv[0] == 0)
1603 fatal ("cannot find `%s'", prog);
bb59f9a6 1604
4e81a331
RS
1605 pid = vfork ();
1606 if (pid == -1)
cf0c751a
JW
1607 {
1608#ifdef vfork
1609 fatal_perror ("fork");
1610#else
1611 fatal_perror ("vfork");
1612#endif
1613 }
4e81a331
RS
1614
1615 if (pid == 0) /* child context */
1616 {
a3184468
JM
1617 if (redir)
1618 {
1619 unlink (redir);
1620 if (freopen (redir, "a", stdout) == NULL)
1621 fatal_perror ("redirecting stdout");
1622 if (freopen (redir, "a", stderr) == NULL)
1623 fatal_perror ("redirecting stderr");
1624 }
1625
aee3a549 1626 execvp (argv[0], argv);
1fab8e81 1627 fatal_perror ("executing %s", prog);
4e81a331 1628 }
a3184468 1629}
4e81a331 1630
a3184468
JM
1631static void
1632fork_execute (prog, argv)
1633 char *prog;
1634 char **argv;
1635{
1636 collect_execute (prog, argv, NULL);
4e81a331 1637 do_wait (prog);
4e81a331 1638}
4e81a331
RS
1639\f
1640/* Unlink a file unless we are debugging. */
1641
1642static void
1643maybe_unlink (file)
1644 char *file;
1645{
1646 if (!debug)
1647 unlink (file);
1648 else
1649 fprintf (stderr, "[Leaving %s]\n", file);
1650}
1651
1652\f
1653/* Add a name to a linked list. */
1654
1655static void
1656add_to_list (head_ptr, name)
1657 struct head *head_ptr;
1658 char *name;
1659{
0393b857
JM
1660 struct id *newid
1661 = (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1);
1662 struct id *p;
4e81a331 1663 static long sequence_number = 0;
4e81a331
RS
1664 strcpy (newid->name, name);
1665
1666 if (head_ptr->first)
1667 head_ptr->last->next = newid;
1668 else
1669 head_ptr->first = newid;
1670
0393b857
JM
1671 /* Check for duplicate symbols. */
1672 for (p = head_ptr->first;
1673 strcmp (name, p->name) != 0;
1674 p = p->next)
1675 ;
1676 if (p != newid)
1677 {
1678 head_ptr->last->next = 0;
1679 free (newid);
1680 return;
1681 }
1682
1683 newid->sequence = ++sequence_number;
4e81a331
RS
1684 head_ptr->last = newid;
1685 head_ptr->number++;
1686}
1687
1688/* Write: `prefix', the names on list LIST, `suffix'. */
1689
1690static void
1691write_list (stream, prefix, list)
1692 FILE *stream;
1693 char *prefix;
1694 struct id *list;
1695{
1696 while (list)
1697 {
1698 fprintf (stream, "%sx%d,\n", prefix, list->sequence);
1699 list = list->next;
1700 }
1701}
1702
1703static void
1704write_list_with_asm (stream, prefix, list)
1705 FILE *stream;
1706 char *prefix;
1707 struct id *list;
1708{
1709 while (list)
1710 {
c7af43d8 1711 fprintf (stream, "%sx%d __asm__ (\"%s\");\n",
4e81a331
RS
1712 prefix, list->sequence, list->name);
1713 list = list->next;
1714 }
1715}
1716
68d69835
JM
1717/* Write out the constructor and destructor tables statically (for a shared
1718 object), along with the functions to execute them. */
1719
1720static void
1721write_c_file_stat (stream, name)
1722 FILE *stream;
1723 char *name;
1724{
1725 char *prefix, *p, *q;
68d69835
JM
1726
1727 /* Figure out name of output_file, stripping off .so version. */
1728 p = rindex (output_file, '/');
1729 if (p == 0)
1730 p = (char *) output_file;
1731 else
1732 p++;
1733 q = p;
1734 while (q)
1735 {
1736 q = index (q,'.');
1737 if (q == 0)
1738 {
1739 q = p + strlen (p);
1740 break;
1741 }
1742 else
1743 {
1744 if (strncmp (q, ".so", 3) == 0)
1745 {
1746 q += 3;
1747 break;
1748 }
1749 else
1750 q++;
1751 }
1752 }
1753 /* q points to null at end of the string (or . of the .so version) */
1754 prefix = xmalloc (q - p + 1);
1755 strncpy (prefix, p, q - p);
1756 prefix[q - p] = 0;
1757 for (q = prefix; *q; q++)
1758 if (!isalnum (*q))
1759 *q = '_';
1760 if (debug)
1761 fprintf (stderr, "\nwrite_c_file - output name is %s, prefix is %s\n",
1762 output_file, prefix);
1763
1764#define INIT_NAME_FORMAT "_GLOBAL__FI_%s"
1765 initname = xmalloc (strlen (prefix) + sizeof (INIT_NAME_FORMAT) - 2);
1766 sprintf (initname, INIT_NAME_FORMAT, prefix);
1767
1768#define FINI_NAME_FORMAT "_GLOBAL__FD_%s"
1769 fininame = xmalloc (strlen (prefix) + sizeof (FINI_NAME_FORMAT) - 2);
1770 sprintf (fininame, FINI_NAME_FORMAT, prefix);
1771
1772 free (prefix);
1773
1774 /* Write the tables as C code */
1775
1776 fprintf (stream, "static int count;\n");
1777 fprintf (stream, "typedef void entry_pt();\n");
1778 write_list_with_asm (stream, "extern entry_pt ", constructors.first);
1779 fprintf (stream, "void %s() {\n", initname);
1780 if (constructors.number > 0)
1781 {
1782 fprintf (stream, "\tstatic entry_pt *ctors[] = {\n");
1783 write_list (stream, "\t\t", constructors.first);
1784 fprintf (stream, "\t};\n");
1785 fprintf (stream, "\tentry_pt **p;\n");
1786 fprintf (stream, "\tif (count++ != 0) return;\n");
1787 fprintf (stream, "\tp = ctors + %d;\n", constructors.number);
1788 fprintf (stream, "\twhile (p > ctors) (*--p)();\n");
1789 }
603b4064
RK
1790 else
1791 fprintf (stream, "\t++count;\n");
68d69835
JM
1792 fprintf (stream, "}\n");
1793 write_list_with_asm (stream, "extern entry_pt ", destructors.first);
1794 fprintf (stream, "void %s() {\n", fininame);
1795 if (destructors.number > 0)
1796 {
1797 fprintf (stream, "\tstatic entry_pt *dtors[] = {\n");
1798 write_list (stream, "\t\t", destructors.first);
1799 fprintf (stream, "\t};\n");
1800 fprintf (stream, "\tentry_pt **p;\n");
1801 fprintf (stream, "\tif (--count != 0) return;\n");
1802 fprintf (stream, "\tp = dtors;\n");
1803 fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n",
1804 destructors.number);
1805 }
1806 fprintf (stream, "}\n");
1807
603b4064
RK
1808 if (shared_obj)
1809 {
1810 fprintf (stream, "void _GLOBAL__DI() {\n\t%s();\n}\n", initname);
1811 fprintf (stream, "void _GLOBAL__DD() {\n\t%s();\n}\n", fininame);
1812 }
68d69835
JM
1813}
1814
4e81a331
RS
1815/* Write the constructor/destructor tables. */
1816
1817static void
68d69835 1818write_c_file_glob (stream, name)
4e81a331
RS
1819 FILE *stream;
1820 char *name;
1821{
1822 /* Write the tables as C code */
1823
1824 fprintf (stream, "typedef void entry_pt();\n\n");
1825
17704846 1826 write_list_with_asm (stream, "extern entry_pt ", constructors.first);
4e81a331
RS
1827
1828 fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
1829 fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number);
ed5b9462 1830 write_list (stream, "\t", constructors.first);
4e81a331
RS
1831 fprintf (stream, "\t0\n};\n\n");
1832
17704846 1833 write_list_with_asm (stream, "extern entry_pt ", destructors.first);
4e81a331
RS
1834
1835 fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
1836 fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number);
ed5b9462 1837 write_list (stream, "\t", destructors.first);
4e81a331
RS
1838 fprintf (stream, "\t0\n};\n\n");
1839
d6cf3187
RS
1840 fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
1841 fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);
4e81a331
RS
1842}
1843
68d69835
JM
1844static void
1845write_c_file (stream, name)
1846 FILE *stream;
1847 char *name;
1848{
603b4064
RK
1849#ifndef LD_INIT_SWITCH
1850 if (! shared_obj)
68d69835 1851 write_c_file_glob (stream, name);
603b4064
RK
1852 else
1853#endif
1854 write_c_file_stat (stream, name);
68d69835 1855}
cbbbd917
JM
1856
1857static void
1858write_export_file (stream)
1859 FILE *stream;
1860{
1861 struct id *list = exports.first;
1862 for (; list; list = list->next)
1863 fprintf (stream, "%s\n", list->name);
1864}
4e81a331 1865\f
ed5b9462 1866#ifdef OBJECT_FORMAT_NONE
4e81a331 1867
ed5b9462
RS
1868/* Generic version to scan the name list of the loaded program for
1869 the symbols g++ uses for static constructors and destructors.
4e81a331
RS
1870
1871 The constructor table begins at __CTOR_LIST__ and contains a count
1872 of the number of pointers (or -1 if the constructors are built in a
1873 separate section by the linker), followed by the pointers to the
1874 constructor functions, terminated with a null pointer. The
1875 destructor table has the same format, and begins at __DTOR_LIST__. */
1876
1877static void
1878scan_prog_file (prog_name, which_pass)
1879 char *prog_name;
1880 enum pass which_pass;
1881{
ed5b9462
RS
1882 void (*int_handler) ();
1883 void (*quit_handler) ();
4e81a331
RS
1884 char *nm_argv[4];
1885 int pid;
1886 int argc = 0;
1887 int pipe_fd[2];
1888 char *p, buf[1024];
1889 FILE *inf;
1890
68d69835 1891 if (which_pass == PASS_SECOND)
4e81a331
RS
1892 return;
1893
bb59f9a6
RS
1894 /* If we don't have an `nm', complain. */
1895 if (nm_file_name == 0)
1896 fatal ("cannot find `nm'");
1897
68d69835 1898 nm_argv[argc++] = nm_file_name;
4e81a331 1899 if (NM_FLAGS[0] != '\0')
ed5b9462 1900 nm_argv[argc++] = NM_FLAGS;
4e81a331 1901
ed5b9462
RS
1902 nm_argv[argc++] = prog_name;
1903 nm_argv[argc++] = (char *)0;
4e81a331
RS
1904
1905 if (pipe (pipe_fd) < 0)
1906 fatal_perror ("pipe");
1907
1908 inf = fdopen (pipe_fd[0], "r");
1909 if (inf == (FILE *)0)
1910 fatal_perror ("fdopen");
1911
1912 /* Trace if needed. */
1913 if (vflag)
1914 {
1915 char **p_argv;
1916 char *str;
1917
68d69835 1918 for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *)0; p_argv++)
4e81a331
RS
1919 fprintf (stderr, " %s", str);
1920
1921 fprintf (stderr, "\n");
1922 }
1923
1924 fflush (stdout);
1925 fflush (stderr);
1926
1927 /* Spawn child nm on pipe */
1928 pid = vfork ();
1929 if (pid == -1)
cf0c751a
JW
1930 {
1931#ifdef vfork
1932 fatal_perror ("fork");
1933#else
1934 fatal_perror ("vfork");
1935#endif
1936 }
4e81a331
RS
1937
1938 if (pid == 0) /* child context */
1939 {
1940 /* setup stdout */
1941 if (dup2 (pipe_fd[1], 1) < 0)
1fab8e81 1942 fatal_perror ("dup2 (%d, 1)", pipe_fd[1]);
4e81a331
RS
1943
1944 if (close (pipe_fd[0]) < 0)
1fab8e81 1945 fatal_perror ("close (%d)", pipe_fd[0]);
4e81a331
RS
1946
1947 if (close (pipe_fd[1]) < 0)
1fab8e81 1948 fatal_perror ("close (%d)", pipe_fd[1]);
4e81a331
RS
1949
1950 execv (nm_file_name, nm_argv);
1fab8e81 1951 fatal_perror ("executing %s", nm_file_name);
4e81a331
RS
1952 }
1953
1954 /* Parent context from here on. */
ed5b9462 1955 int_handler = (void (*) ())signal (SIGINT, SIG_IGN);
8ab861c7 1956#ifdef SIGQUIT
ed5b9462 1957 quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN);
8ab861c7 1958#endif
4e81a331
RS
1959
1960 if (close (pipe_fd[1]) < 0)
1fab8e81 1961 fatal_perror ("close (%d)", pipe_fd[1]);
4e81a331
RS
1962
1963 if (debug)
1964 fprintf (stderr, "\nnm output with constructors/destructors.\n");
1965
1966 /* Read each line of nm output. */
1967 while (fgets (buf, sizeof buf, inf) != (char *)0)
1968 {
1969 int ch, ch2;
ed5b9462 1970 char *name, *end;
4e81a331
RS
1971
1972 /* If it contains a constructor or destructor name, add the name
1973 to the appropriate list. */
1974
1975 for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
68d69835
JM
1976 if (ch == ' ' && p[1] == 'U' && p[2] == ' ')
1977 break;
4e81a331 1978
68d69835 1979 if (ch != '_')
4e81a331 1980 continue;
ed5b9462
RS
1981
1982 name = p;
1983 /* Find the end of the symbol name.
1984 Don't include `|', because Encore nm can tack that on the end. */
1985 for (end = p; (ch2 = *end) != '\0' && !isspace (ch2) && ch2 != '|';
1986 end++)
1987 continue;
4e81a331 1988
90d326bd 1989
4e81a331 1990 *end = '\0';
ed5b9462 1991 switch (is_ctor_dtor (name))
4e81a331 1992 {
ed5b9462 1993 case 1:
68d69835
JM
1994 if (which_pass != PASS_LIB)
1995 add_to_list (&constructors, name);
ed5b9462 1996 break;
4e81a331 1997
ed5b9462 1998 case 2:
68d69835
JM
1999 if (which_pass != PASS_LIB)
2000 add_to_list (&destructors, name);
2001 break;
2002
2003 case 3:
2004 if (which_pass != PASS_LIB)
2005 fatal ("init function found in object %s", prog_name);
35e530c5 2006#ifndef LD_INIT_SWITCH
68d69835 2007 add_to_list (&constructors, name);
35e530c5 2008#endif
68d69835
JM
2009 break;
2010
2011 case 4:
2012 if (which_pass != PASS_LIB)
35e530c5
JM
2013 fatal ("fini function found in object %s", prog_name);
2014#ifndef LD_FINI_SWITCH
ed5b9462 2015 add_to_list (&destructors, name);
35e530c5 2016#endif
ed5b9462 2017 break;
4e81a331 2018
ed5b9462
RS
2019 default: /* not a constructor or destructor */
2020 continue;
4e81a331
RS
2021 }
2022
4e81a331
RS
2023 if (debug)
2024 fprintf (stderr, "\t%s\n", buf);
2025 }
2026
2027 if (debug)
2028 fprintf (stderr, "\n");
2029
2030 if (fclose (inf) != 0)
2031 fatal_perror ("fclose of pipe");
2032
2033 do_wait (nm_file_name);
2034
2035 signal (SIGINT, int_handler);
8ab861c7 2036#ifdef SIGQUIT
4e81a331 2037 signal (SIGQUIT, quit_handler);
8ab861c7 2038#endif
4e81a331
RS
2039}
2040
a3184468 2041#if SUNOS4_SHARED_LIBRARIES
68d69835
JM
2042
2043/* Routines to scan the SunOS 4 _DYNAMIC structure to find shared libraries
2044 that the output file depends upon and their initialization/finalization
2045 routines, if any. */
2046
2047#include <a.out.h>
2048#include <fcntl.h>
2049#include <link.h>
2050#include <sys/mman.h>
2051#include <sys/param.h>
2052#include <sys/unistd.h>
28aaf32b 2053#include <sys/dir.h>
68d69835
JM
2054
2055/* pointers to the object file */
2056unsigned object; /* address of memory mapped file */
2057unsigned objsize; /* size of memory mapped to file */
2058char * code; /* pointer to code segment */
2059char * data; /* pointer to data segment */
2060struct nlist *symtab; /* pointer to symbol table */
2061struct link_dynamic *ld;
2062struct link_dynamic_2 *ld_2;
2063struct head libraries;
2064
2065/* Map the file indicated by NAME into memory and store its address. */
2066
2067static void
2068mapfile (name)
2069 char *name;
2070{
2071 int fp;
2072 struct stat s;
2073 if ((fp = open (name, O_RDONLY)) == -1)
2074 fatal ("unable to open file '%s'", name);
2075 if (fstat (fp, &s) == -1)
2076 fatal ("unable to stat file '%s'", name);
2077
2078 objsize = s.st_size;
2079 object = (unsigned) mmap (0, objsize, PROT_READ|PROT_WRITE, MAP_PRIVATE,
2080 fp, 0);
2081 if (object == -1)
2082 fatal ("unable to mmap file '%s'", name);
2083
2084 close (fp);
2085}
2086
28aaf32b
JM
2087/* Helpers for locatelib. */
2088
2089static char *libname;
2090
2091static int
2092libselect (d)
2093 struct direct *d;
2094{
2095 return (strncmp (libname, d->d_name, strlen (libname)) == 0);
2096}
2097
2098static int
2099libcompare (d1, d2)
2100 struct direct **d1, **d2;
2101{
2102 int i1, i2 = strlen (libname);
2103 char *e1 = (*d1)->d_name + i2;
2104 char *e2 = (*d2)->d_name + i2;
2105
2106 while (*e1 && *e2)
2107 {
2108 ++e1;
2109 ++e2;
2110 i1 = strtol (e1, &e1, 10);
2111 i2 = strtol (e2, &e2, 10);
2112 if (i1 != i2)
2113 return i1 - i2;
2114 }
2115
2116 if (*e1)
2117 return 1;
2118 else if (*e2)
2119 return -1;
2120 else
2121 return 0;
2122}
2123
68d69835
JM
2124/* Given the name NAME of a dynamic dependency, find its pathname and add
2125 it to the list of libraries. */
2126
2127static void
2128locatelib (name)
2129 char *name;
2130{
2131 static char **l;
2132 static int cnt;
2133 char buf[MAXPATHLEN];
2134 char *p, *q;
2135 char **pp;
2136
2137 if (l == 0)
2138 {
2139 char *ld_rules;
2140 char *ldr = 0;
2141 /* counting elements in array, need 1 extra for null */
2142 cnt = 1;
2143 ld_rules = (char *) (ld_2->ld_rules + code);
2144 if (ld_rules)
2145 {
2146 cnt++;
2147 for (; *ld_rules != 0; ld_rules++)
2148 if (*ld_rules == ':')
2149 cnt++;
2150 ld_rules = (char *) (ld_2->ld_rules + code);
2151 ldr = (char *) malloc (strlen (ld_rules) + 1);
2152 strcpy (ldr, ld_rules);
2153 }
2154 p = getenv ("LD_LIBRARY_PATH");
2155 q = 0;
2156 if (p)
2157 {
2158 cnt++;
2159 for (q = p ; *q != 0; q++)
2160 if (*q == ':')
2161 cnt++;
2162 q = (char *) malloc (strlen (p) + 1);
2163 strcpy (q, p);
2164 }
2165 l = (char **) malloc ((cnt + 3) * sizeof (char *));
2166 pp = l;
2167 if (ldr)
2168 {
2169 *pp++ = ldr;
2170 for (; *ldr != 0; ldr++)
2171 if (*ldr == ':')
2172 {
2173 *ldr++ = 0;
2174 *pp++ = ldr;
2175 }
2176 }
2177 if (q)
2178 {
2179 *pp++ = q;
2180 for (; *q != 0; q++)
2181 if (*q == ':')
2182 {
2183 *q++ = 0;
245c3e25 2184 *pp++ = q;
68d69835
JM
2185 }
2186 }
2187 /* built in directories are /lib, /usr/lib, and /usr/local/lib */
2188 *pp++ = "/lib";
2189 *pp++ = "/usr/lib";
2190 *pp++ = "/usr/local/lib";
2191 *pp = 0;
2192 }
28aaf32b 2193 libname = name;
68d69835
JM
2194 for (pp = l; *pp != 0 ; pp++)
2195 {
28aaf32b
JM
2196 struct direct **namelist;
2197 int entries;
2198 if ((entries = scandir (*pp, &namelist, libselect, libcompare)) > 0)
68d69835 2199 {
28aaf32b 2200 sprintf (buf, "%s/%s", *pp, namelist[entries - 1]->d_name);
68d69835
JM
2201 add_to_list (&libraries, buf);
2202 if (debug)
2203 fprintf (stderr, "%s\n", buf);
2204 break;
2205 }
2206 }
2207 if (*pp == 0)
2208 {
2209 if (debug)
2210 fprintf (stderr, "not found\n");
2211 else
2212 fatal ("dynamic dependency %s not found", name);
2213 }
2214}
2215
2216/* Scan the _DYNAMIC structure of the output file to find shared libraries
2217 that it depends upon and any constructors or destructors they contain. */
2218
2219static void
2220scan_libraries (prog_name)
2221 char *prog_name;
2222{
2223 struct exec *header;
2224 char *base;
2225 struct link_object *lo;
2226 char buff[MAXPATHLEN];
2227 struct id *list;
2228
2229 mapfile (prog_name);
2230 header = (struct exec *)object;
2231 if (N_BADMAG (*header))
2232 fatal ("bad magic number in file '%s'", prog_name);
2233 if (header->a_dynamic == 0)
2234 return;
2235
2236 code = (char *) (N_TXTOFF (*header) + (long) header);
2237 data = (char *) (N_DATOFF (*header) + (long) header);
2238 symtab = (struct nlist *) (N_SYMOFF (*header) + (long) header);
2239
2240 if (header->a_magic == ZMAGIC && header->a_entry == 0x20)
2241 {
2242 /* shared object */
2243 ld = (struct link_dynamic *) (symtab->n_value + code);
2244 base = code;
2245 }
2246 else
2247 {
2248 /* executable */
2249 ld = (struct link_dynamic *) data;
2250 base = code-PAGSIZ;
2251 }
2252
2253 if (debug)
2254 fprintf (stderr, "dynamic dependencies.\n");
2255
2256 ld_2 = (struct link_dynamic_2 *) ((long) ld->ld_un.ld_2 + (long)base);
2257 for (lo = (struct link_object *) ld_2->ld_need; lo;
2258 lo = (struct link_object *) lo->lo_next)
2259 {
2260 char *name;
2261 lo = (struct link_object *) ((long) lo + code);
2262 name = (char *) (code + lo->lo_name);
2263 if (lo->lo_library)
2264 {
2265 if (debug)
2266 fprintf (stderr, "\t-l%s.%d => ", name, lo->lo_major);
2267 sprintf (buff, "lib%s.so.%d.%d", name, lo->lo_major, lo->lo_minor);
2268 locatelib (buff);
2269 }
2270 else
2271 {
2272 if (debug)
2273 fprintf (stderr, "\t%s\n", name);
2274 add_to_list (&libraries, name);
2275 }
2276 }
2277
2278 if (debug)
2279 fprintf (stderr, "\n");
2280
2281 /* now iterate through the library list adding their symbols to
2282 the list. */
2283 for (list = libraries.first; list; list = list->next)
2284 scan_prog_file (list->name, PASS_LIB);
2285}
2286
2287#else /* SUNOS4_SHARED_LIBRARIES */
2288#ifdef LDD_SUFFIX
2289
2290/* Use the List Dynamic Dependencies program to find shared libraries that
2291 the output file depends upon and their initialization/finalization
2292 routines, if any. */
2293
2294static void
2295scan_libraries (prog_name)
2296 char *prog_name;
2297{
2298 static struct head libraries; /* list of shared libraries found */
2299 struct id *list;
2300 void (*int_handler) ();
2301 void (*quit_handler) ();
2302 char *ldd_argv[4];
2303 int pid;
2304 int argc = 0;
2305 int pipe_fd[2];
2306 char buf[1024];
2307 FILE *inf;
2308
2309 /* If we don't have an `ldd', complain. */
2310 if (ldd_file_name == 0)
2311 {
2312 error ("cannot find `ldd'");
2313 return;
2314 }
2315
2316 ldd_argv[argc++] = ldd_file_name;
2317 ldd_argv[argc++] = prog_name;
2318 ldd_argv[argc++] = (char *) 0;
2319
2320 if (pipe (pipe_fd) < 0)
2321 fatal_perror ("pipe");
2322
2323 inf = fdopen (pipe_fd[0], "r");
2324 if (inf == (FILE *) 0)
2325 fatal_perror ("fdopen");
2326
2327 /* Trace if needed. */
2328 if (vflag)
2329 {
2330 char **p_argv;
2331 char *str;
2332
2333 for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
2334 fprintf (stderr, " %s", str);
2335
2336 fprintf (stderr, "\n");
2337 }
2338
2339 fflush (stdout);
2340 fflush (stderr);
2341
2342 /* Spawn child ldd on pipe */
2343 pid = vfork ();
2344 if (pid == -1)
2345 {
2346#ifdef vfork
2347 fatal_perror ("fork");
2348#else
2349 fatal_perror ("vfork");
2350#endif
2351 }
2352
2353 if (pid == 0) /* child context */
2354 {
2355 /* setup stdout */
2356 if (dup2 (pipe_fd[1], 1) < 0)
2357 fatal_perror ("dup2 (%d, 1)", pipe_fd[1]);
2358
2359 if (close (pipe_fd[0]) < 0)
2360 fatal_perror ("close (%d)", pipe_fd[0]);
2361
2362 if (close (pipe_fd[1]) < 0)
2363 fatal_perror ("close (%d)", pipe_fd[1]);
2364
2365 execv (ldd_file_name, ldd_argv);
2366 fatal_perror ("executing %s", ldd_file_name);
2367 }
2368
2369 /* Parent context from here on. */
2370 int_handler = (void (*) ()) signal (SIGINT, SIG_IGN);
2371#ifdef SIGQUIT
2372 quit_handler = (void (*) ()) signal (SIGQUIT, SIG_IGN);
2373#endif
2374
2375 if (close (pipe_fd[1]) < 0)
2376 fatal_perror ("close (%d)", pipe_fd[1]);
2377
2378 if (debug)
2379 fprintf (stderr, "\nldd output with constructors/destructors.\n");
2380
2381 /* Read each line of ldd output. */
2382 while (fgets (buf, sizeof buf, inf) != (char *) 0)
2383 {
2384 int ch, ch2;
2385 char *name, *end, *p = buf;
2386
2387 /* Extract names of libraries and add to list. */
2388 PARSE_LDD_OUTPUT (p);
2389 if (p == 0)
2390 continue;
2391
2392 name = p;
2393 if (strncmp (name, "not found", sizeof ("not found") - 1) == 0)
2394 fatal ("dynamic dependency %s not found", buf);
2395
2396 /* Find the end of the symbol name. */
2397 for (end = p;
2398 (ch2 = *end) != '\0' && ch2 != '\n' && !isspace (ch2) && ch2 != '|';
2399 end++)
2400 continue;
2401 *end = '\0';
2402
2403 if (access (name, R_OK) == 0)
2404 add_to_list (&libraries, name);
2405 else
2406 fatal ("unable to open dynamic dependency '%s'", buf);
2407
2408 if (debug)
2409 fprintf (stderr, "\t%s\n", buf);
2410 }
2411 if (debug)
2412 fprintf (stderr, "\n");
2413
2414 if (fclose (inf) != 0)
2415 fatal_perror ("fclose of pipe");
2416
2417 do_wait (ldd_file_name);
2418
2419 signal (SIGINT, int_handler);
2420#ifdef SIGQUIT
2421 signal (SIGQUIT, quit_handler);
2422#endif
2423
2424 /* now iterate through the library list adding their symbols to
2425 the list. */
2426 for (list = libraries.first; list; list = list->next)
2427 scan_prog_file (list->name, PASS_LIB);
2428}
2429
2430#endif /* LDD_SUFFIX */
2431#endif /* SUNOS4_SHARED_LIBRARIES */
2432
ed5b9462
RS
2433#endif /* OBJECT_FORMAT_NONE */
2434
2435\f
2436/*
2437 * COFF specific stuff.
2438 */
2439
2440#ifdef OBJECT_FORMAT_COFF
2441
2442#if defined(EXTENDED_COFF)
17704846
JW
2443# define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
2444# define GCC_SYMENT SYMR
2445# define GCC_OK_SYMBOL(X) ((X).st == stProc && (X).sc == scText)
2446# define GCC_SYMINC(X) (1)
2447# define GCC_SYMZERO(X) (SYMHEADER(X).isymMax)
2448# define GCC_CHECK_HDR(X) (PSYMTAB(X) != 0)
ed5b9462 2449#else
17704846
JW
2450# define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms)
2451# define GCC_SYMENT SYMENT
ed5b9462
RS
2452# define GCC_OK_SYMBOL(X) \
2453 (((X).n_sclass == C_EXT) && \
2454 (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) || \
2455 ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))
17704846
JW
2456# define GCC_SYMINC(X) ((X).n_numaux+1)
2457# define GCC_SYMZERO(X) 0
2458# define GCC_CHECK_HDR(X) (1)
ed5b9462
RS
2459#endif
2460
2461extern char *ldgetname ();
2462
2463/* COFF version to scan the name list of the loaded program for
2464 the symbols g++ uses for static constructors and destructors.
2465
2466 The constructor table begins at __CTOR_LIST__ and contains a count
2467 of the number of pointers (or -1 if the constructors are built in a
2468 separate section by the linker), followed by the pointers to the
2469 constructor functions, terminated with a null pointer. The
2470 destructor table has the same format, and begins at __DTOR_LIST__. */
2471
2472static void
2473scan_prog_file (prog_name, which_pass)
2474 char *prog_name;
2475 enum pass which_pass;
2476{
f3c3d3df 2477 LDFILE *ldptr = NULL;
ed5b9462
RS
2478 int sym_index, sym_count;
2479
cbbbd917 2480 if (which_pass != PASS_FIRST && which_pass != PASS_OBJ)
ed5b9462
RS
2481 return;
2482
2483 if ((ldptr = ldopen (prog_name, ldptr)) == NULL)
2484 fatal ("%s: can't open as COFF file", prog_name);
2485
e99467d2 2486 if (!MY_ISCOFF (HEADER (ldptr).f_magic))
ed5b9462
RS
2487 fatal ("%s: not a COFF file", prog_name);
2488
17704846 2489 if (GCC_CHECK_HDR (ldptr))
ed5b9462 2490 {
17704846
JW
2491 sym_count = GCC_SYMBOLS (ldptr);
2492 sym_index = GCC_SYMZERO (ldptr);
2493 while (sym_index < sym_count)
2494 {
2495 GCC_SYMENT symbol;
ed5b9462 2496
17704846
JW
2497 if (ldtbread (ldptr, sym_index, &symbol) <= 0)
2498 break;
2499 sym_index += GCC_SYMINC (symbol);
ed5b9462 2500
17704846
JW
2501 if (GCC_OK_SYMBOL (symbol))
2502 {
2503 char *name;
ed5b9462 2504
17704846
JW
2505 if ((name = ldgetname (ldptr, &symbol)) == NULL)
2506 continue; /* should never happen */
ed5b9462 2507
cbbbd917
JM
2508#ifdef XCOFF_DEBUGGING_INFO
2509 /* All AIX function names have a duplicate entry beginning
2510 with a dot. */
2511 if (*name == '.')
d36c3fe2 2512 ++name;
ed5b9462
RS
2513#endif
2514
17704846
JW
2515 switch (is_ctor_dtor (name))
2516 {
2517 case 1:
2518 add_to_list (&constructors, name);
cbbbd917
JM
2519 if (which_pass == PASS_OBJ)
2520 add_to_list (&exports, name);
17704846 2521 break;
ed5b9462 2522
17704846
JW
2523 case 2:
2524 add_to_list (&destructors, name);
cbbbd917
JM
2525 if (which_pass == PASS_OBJ)
2526 add_to_list (&exports, name);
17704846 2527 break;
ed5b9462 2528
17704846 2529 default: /* not a constructor or destructor */
cbbbd917
JM
2530 if (which_pass == PASS_OBJ && auto_export)
2531 add_to_list (&exports, name);
17704846
JW
2532 continue;
2533 }
ed5b9462
RS
2534
2535#if !defined(EXTENDED_COFF)
17704846
JW
2536 if (debug)
2537 fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
2538 symbol.n_scnum, symbol.n_sclass,
2539 (symbol.n_type ? "0" : ""), symbol.n_type,
2540 name);
ed5b9462 2541#else
17704846
JW
2542 if (debug)
2543 fprintf (stderr, "\tiss = %5d, value = %5d, index = %5d, name = %s\n",
2544 symbol.iss, symbol.value, symbol.index, name);
ed5b9462 2545#endif
17704846 2546 }
ed5b9462
RS
2547 }
2548 }
2549
2550 (void) ldclose(ldptr);
2551}
2552
2553#endif /* OBJECT_FORMAT_COFF */
4e81a331
RS
2554
2555\f
2556/*
2557 * OSF/rose specific stuff.
2558 */
2559
2560#ifdef OBJECT_FORMAT_ROSE
2561
2562/* Union of the various load commands */
2563
2564typedef union load_union
2565{
2566 ldc_header_t hdr; /* common header */
2567 load_cmd_map_command_t map; /* map indexing other load cmds */
ed5b9462 2568 interpreter_command_t iprtr; /* interpreter pathname */
4e81a331
RS
2569 strings_command_t str; /* load commands strings section */
2570 region_command_t region; /* region load command */
2571 reloc_command_t reloc; /* relocation section */
2572 package_command_t pkg; /* package load command */
2573 symbols_command_t sym; /* symbol sections */
2574 entry_command_t ent; /* program start section */
2575 gen_info_command_t info; /* object information */
2576 func_table_command_t func; /* function constructors/destructors */
2577} load_union_t;
2578
2579/* Structure to point to load command and data section in memory. */
2580
2581typedef struct load_all
2582{
2583 load_union_t *load; /* load command */
2584 char *section; /* pointer to section */
2585} load_all_t;
2586
2587/* Structure to contain information about a file mapped into memory. */
2588
2589struct file_info
2590{
2591 char *start; /* start of map */
2592 char *name; /* filename */
2593 long size; /* size of the file */
2594 long rounded_size; /* size rounded to page boundary */
2595 int fd; /* file descriptor */
2596 int rw; /* != 0 if opened read/write */
2597 int use_mmap; /* != 0 if mmap'ed */
2598};
2599
ed5b9462 2600extern int decode_mach_o_hdr ();
ed5b9462 2601extern int encode_mach_o_hdr ();
4e81a331 2602
4d1a011f
RK
2603static void add_func_table PROTO((mo_header_t *, load_all_t *,
2604 symbol_info_t *, int));
2605static void print_header PROTO((mo_header_t *));
2606static void print_load_command PROTO((load_union_t*, size_t, int));
2607static void bad_header PROTO((int));
357a98f1 2608static struct file_info *read_file PROTO((char *, int, int));
4d1a011f 2609static void end_file PROTO((struct file_info *));
4e81a331
RS
2610\f
2611/* OSF/rose specific version to scan the name list of the loaded
2612 program for the symbols g++ uses for static constructors and
2613 destructors.
2614
2615 The constructor table begins at __CTOR_LIST__ and contains a count
2616 of the number of pointers (or -1 if the constructors are built in a
2617 separate section by the linker), followed by the pointers to the
2618 constructor functions, terminated with a null pointer. The
2619 destructor table has the same format, and begins at __DTOR_LIST__. */
2620
2621static void
2622scan_prog_file (prog_name, which_pass)
2623 char *prog_name;
2624 enum pass which_pass;
2625{
2626 char *obj;
2627 mo_header_t hdr;
2628 load_all_t *load_array;
2629 load_all_t *load_end;
2630 load_all_t *load_cmd;
2631 int symbol_load_cmds;
2632 off_t offset;
2633 int i;
2634 int num_syms;
2635 int status;
2636 char *str_sect;
2637 struct file_info *obj_file;
2638 int prog_fd;
2639 mo_lcid_t cmd_strings = -1;
2640 symbol_info_t *main_sym = 0;
2641 int rw = (which_pass != PASS_FIRST);
2642
2643 prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY);
2644 if (prog_fd < 0)
1fab8e81 2645 fatal_perror ("can't read %s", prog_name);
4e81a331
RS
2646
2647 obj_file = read_file (prog_name, prog_fd, rw);
2648 obj = obj_file->start;
2649
2650 status = decode_mach_o_hdr (obj, MO_SIZEOF_RAW_HDR, MOH_HEADER_VERSION, &hdr);
2651 if (status != MO_HDR_CONV_SUCCESS)
2652 bad_header (status);
2653
2654
2655 /* Do some basic sanity checks. Note we explicitly use the big endian magic number,
2656 since the hardware will automatically swap bytes for us on loading little endian
2657 integers. */
2658
2659#ifndef CROSS_COMPILE
2660 if (hdr.moh_magic != MOH_MAGIC_MSB
2661 || hdr.moh_header_version != MOH_HEADER_VERSION
2662 || hdr.moh_byte_order != OUR_BYTE_ORDER
2663 || hdr.moh_data_rep_id != OUR_DATA_REP_ID
2664 || hdr.moh_cpu_type != OUR_CPU_TYPE
2665 || hdr.moh_cpu_subtype != OUR_CPU_SUBTYPE
2666 || hdr.moh_vendor_type != OUR_VENDOR_TYPE)
2667 {
1fab8e81 2668 fatal ("incompatibilities between object file & expected values");
4e81a331
RS
2669 }
2670#endif
2671
2672 if (debug)
2673 print_header (&hdr);
2674
2675 offset = hdr.moh_first_cmd_off;
2676 load_end = load_array
2677 = (load_all_t *) xcalloc (sizeof (load_all_t), hdr.moh_n_load_cmds + 2);
2678
2679 /* Build array of load commands, calculating the offsets */
2680 for (i = 0; i < hdr.moh_n_load_cmds; i++)
2681 {
2682 load_union_t *load_hdr; /* load command header */
2683
2684 load_cmd = load_end++;
2685 load_hdr = (load_union_t *) (obj + offset);
2686
f72aed24 2687 /* If modifying the program file, copy the header. */
4e81a331
RS
2688 if (rw)
2689 {
2690 load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size);
4c9a05bc 2691 bcopy ((char *)load_hdr, (char *)ptr, load_hdr->hdr.ldci_cmd_size);
4e81a331
RS
2692 load_hdr = ptr;
2693
2694 /* null out old command map, because we will rewrite at the end. */
2695 if (ptr->hdr.ldci_cmd_type == LDC_CMD_MAP)
2696 {
2697 cmd_strings = ptr->map.lcm_ld_cmd_strings;
2698 ptr->hdr.ldci_cmd_type = LDC_UNDEFINED;
2699 }
2700 }
2701
2702 load_cmd->load = load_hdr;
2703 if (load_hdr->hdr.ldci_section_off > 0)
2704 load_cmd->section = obj + load_hdr->hdr.ldci_section_off;
2705
2706 if (debug)
2707 print_load_command (load_hdr, offset, i);
2708
2709 offset += load_hdr->hdr.ldci_cmd_size;
2710 }
2711
2712 /* If the last command is the load command map and is not undefined,
2713 decrement the count of load commands. */
2714 if (rw && load_end[-1].load->hdr.ldci_cmd_type == LDC_UNDEFINED)
2715 {
2716 load_end--;
2717 hdr.moh_n_load_cmds--;
2718 }
2719
2720 /* Go through and process each symbol table section. */
2721 symbol_load_cmds = 0;
2722 for (load_cmd = load_array; load_cmd < load_end; load_cmd++)
2723 {
2724 load_union_t *load_hdr = load_cmd->load;
2725
2726 if (load_hdr->hdr.ldci_cmd_type == LDC_SYMBOLS)
2727 {
2728 symbol_load_cmds++;
2729
2730 if (debug)
2731 {
ed5b9462 2732 char *kind = "unknown";
4e81a331
RS
2733
2734 switch (load_hdr->sym.symc_kind)
2735 {
2736 case SYMC_IMPORTS: kind = "imports"; break;
2737 case SYMC_DEFINED_SYMBOLS: kind = "defined"; break;
2738 case SYMC_STABS: kind = "stabs"; break;
2739 }
2740
2741 fprintf (stderr, "\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
2742 symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
2743 }
2744
2745 if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
2746 continue;
2747
ed5b9462 2748 str_sect = load_array[load_hdr->sym.symc_strings_section].section;
4e81a331
RS
2749 if (str_sect == (char *)0)
2750 fatal ("string section missing");
2751
2752 if (load_cmd->section == (char *)0)
2753 fatal ("section pointer missing");
2754
2755 num_syms = load_hdr->sym.symc_nentries;
2756 for (i = 0; i < num_syms; i++)
2757 {
2758 symbol_info_t *sym = ((symbol_info_t *) load_cmd->section) + i;
2759 char *name = sym->si_name.symbol_name + str_sect;
4e81a331
RS
2760
2761 if (name[0] != '_')
2762 continue;
2763
4e81a331
RS
2764 if (rw)
2765 {
d6cf3187
RS
2766 char *n = name + strlen (name) - strlen (NAME__MAIN);
2767
2768 if ((n - name) < 0 || strcmp (n, NAME__MAIN))
4e81a331 2769 continue;
d6cf3187
RS
2770 while (n != name)
2771 if (*--n != '_')
2772 continue;
4e81a331
RS
2773
2774 main_sym = sym;
2775 }
ed5b9462 2776 else
4e81a331 2777 {
ed5b9462
RS
2778 switch (is_ctor_dtor (name))
2779 {
2780 case 1:
2781 add_to_list (&constructors, name);
2782 break;
2783
2784 case 2:
2785 add_to_list (&destructors, name);
2786 break;
2787
2788 default: /* not a constructor or destructor */
2789 continue;
2790 }
4e81a331
RS
2791 }
2792
4e81a331
RS
2793 if (debug)
2794 fprintf (stderr, "\ttype = 0x%.4x, sc = 0x%.2x, flags = 0x%.8x, name = %.30s\n",
2795 sym->si_type, sym->si_sc_type, sym->si_flags, name);
2796 }
2797 }
2798 }
2799
2800 if (symbol_load_cmds == 0)
1fab8e81 2801 fatal ("no symbol table found");
4e81a331
RS
2802
2803 /* Update the program file now, rewrite header and load commands. At present,
2804 we assume that there is enough space after the last load command to insert
2805 one more. Since the first section written out is page aligned, and the
2806 number of load commands is small, this is ok for the present. */
2807
2808 if (rw)
2809 {
2810 load_union_t *load_map;
2811 size_t size;
2812
2813 if (cmd_strings == -1)
1fab8e81
RS
2814 fatal ("no cmd_strings found");
2815
2816 /* Add __main to initializer list.
2817 If we are building a program instead of a shared library, don't
2818 do anything, since in the current version, you cannot do mallocs
2819 and such in the constructors. */
4e81a331 2820
1fab8e81
RS
2821 if (main_sym != (symbol_info_t *)0
2822 && ((hdr.moh_flags & MOH_EXECABLE_F) == 0))
4e81a331
RS
2823 add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION);
2824
2825 if (debug)
2826 fprintf (stderr, "\nUpdating header and load commands.\n\n");
2827
2828 hdr.moh_n_load_cmds++;
2829 size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1));
2830
2831 /* Create new load command map. */
2832 if (debug)
2833 fprintf (stderr, "load command map, %d cmds, new size %ld.\n",
2834 (int)hdr.moh_n_load_cmds, (long)size);
2835
2836 load_map = (load_union_t *) xcalloc (1, size);
2837 load_map->map.ldc_header.ldci_cmd_type = LDC_CMD_MAP;
2838 load_map->map.ldc_header.ldci_cmd_size = size;
2839 load_map->map.lcm_ld_cmd_strings = cmd_strings;
2840 load_map->map.lcm_nentries = hdr.moh_n_load_cmds;
2841 load_array[hdr.moh_n_load_cmds-1].load = load_map;
2842
2843 offset = hdr.moh_first_cmd_off;
2844 for (i = 0; i < hdr.moh_n_load_cmds; i++)
2845 {
2846 load_map->map.lcm_map[i] = offset;
2847 if (load_array[i].load->hdr.ldci_cmd_type == LDC_CMD_MAP)
2848 hdr.moh_load_map_cmd_off = offset;
2849
2850 offset += load_array[i].load->hdr.ldci_cmd_size;
2851 }
2852
2853 hdr.moh_sizeofcmds = offset - MO_SIZEOF_RAW_HDR;
2854
2855 if (debug)
2856 print_header (&hdr);
2857
2858 /* Write header */
2859 status = encode_mach_o_hdr (&hdr, obj, MO_SIZEOF_RAW_HDR);
2860 if (status != MO_HDR_CONV_SUCCESS)
2861 bad_header (status);
2862
2863 if (debug)
2864 fprintf (stderr, "writing load commands.\n\n");
2865
2866 /* Write load commands */
2867 offset = hdr.moh_first_cmd_off;
2868 for (i = 0; i < hdr.moh_n_load_cmds; i++)
2869 {
2870 load_union_t *load_hdr = load_array[i].load;
2871 size_t size = load_hdr->hdr.ldci_cmd_size;
2872
2873 if (debug)
2874 print_load_command (load_hdr, offset, i);
2875
4c9a05bc 2876 bcopy ((char *)load_hdr, (char *)(obj + offset), size);
4e81a331
RS
2877 offset += size;
2878 }
2879 }
2880
2881 end_file (obj_file);
2882
2883 if (close (prog_fd))
1fab8e81 2884 fatal_perror ("closing %s", prog_name);
4e81a331
RS
2885
2886 if (debug)
2887 fprintf (stderr, "\n");
2888}
2889
2890\f
2891/* Add a function table to the load commands to call a function
ed5b9462 2892 on initiation or termination of the process. */
4e81a331
RS
2893
2894static void
2895add_func_table (hdr_p, load_array, sym, type)
2896 mo_header_t *hdr_p; /* pointer to global header */
2897 load_all_t *load_array; /* array of ptrs to load cmds */
2898 symbol_info_t *sym; /* pointer to symbol entry */
2899 int type; /* fntc_type value */
2900{
2901 /* Add a new load command. */
2902 int num_cmds = ++hdr_p->moh_n_load_cmds;
2903 int load_index = num_cmds - 1;
2904 size_t size = sizeof (func_table_command_t) + sizeof (mo_addr_t);
2905 load_union_t *ptr = xcalloc (1, size);
2906 load_all_t *load_cmd;
2907 int i;
2908
2909 /* Set the unresolved address bit in the header to force the loader to be
2910 used, since kernel exec does not call the initialization functions. */
2911 hdr_p->moh_flags |= MOH_UNRESOLVED_F;
2912
2913 load_cmd = &load_array[load_index];
2914 load_cmd->load = ptr;
2915 load_cmd->section = (char *)0;
2916
2917 /* Fill in func table load command. */
2918 ptr->func.ldc_header.ldci_cmd_type = LDC_FUNC_TABLE;
2919 ptr->func.ldc_header.ldci_cmd_size = size;
2920 ptr->func.ldc_header.ldci_section_off = 0;
2921 ptr->func.ldc_header.ldci_section_len = 0;
2922 ptr->func.fntc_type = type;
2923 ptr->func.fntc_nentries = 1;
2924
2925 /* copy address, turn it from abs. address to (region,offset) if necessary. */
2926 /* Is the symbol already expressed as (region, offset)? */
2927 if ((sym->si_flags & SI_ABSOLUTE_VALUE_F) == 0)
2928 {
2929 ptr->func.fntc_entry_loc[i].adr_lcid = sym->si_value.def_val.adr_lcid;
2930 ptr->func.fntc_entry_loc[i].adr_sctoff = sym->si_value.def_val.adr_sctoff;
2931 }
2932
2933 /* If not, figure out which region it's in. */
2934 else
2935 {
2936 mo_vm_addr_t addr = sym->si_value.abs_val;
2937 int found = 0;
2938
2939 for (i = 0; i < load_index; i++)
2940 {
2941 if (load_array[i].load->hdr.ldci_cmd_type == LDC_REGION)
2942 {
2943 region_command_t *region_ptr = &load_array[i].load->region;
2944
2945 if ((region_ptr->regc_flags & REG_ABS_ADDR_F) != 0
2946 && addr >= region_ptr->regc_addr.vm_addr
2947 && addr <= region_ptr->regc_addr.vm_addr + region_ptr->regc_vm_size)
2948 {
2949 ptr->func.fntc_entry_loc[0].adr_lcid = i;
2950 ptr->func.fntc_entry_loc[0].adr_sctoff = addr - region_ptr->regc_addr.vm_addr;
2951 found++;
2952 break;
2953 }
2954 }
2955 }
2956
2957 if (!found)
2958 fatal ("could not convert 0x%l.8x into a region", addr);
2959 }
2960
2961 if (debug)
2962 fprintf (stderr,
2963 "%s function, region %d, offset = %ld (0x%.8lx)\n",
2964 (type == FNTC_INITIALIZATION) ? "init" : "term",
2965 (int)ptr->func.fntc_entry_loc[i].adr_lcid,
2966 (long)ptr->func.fntc_entry_loc[i].adr_sctoff,
2967 (long)ptr->func.fntc_entry_loc[i].adr_sctoff);
2968
2969}
2970
2971\f
2972/* Print the global header for an OSF/rose object. */
2973
2974static void
2975print_header (hdr_ptr)
2976 mo_header_t *hdr_ptr;
2977{
2978 fprintf (stderr, "\nglobal header:\n");
2979 fprintf (stderr, "\tmoh_magic = 0x%.8lx\n", hdr_ptr->moh_magic);
2980 fprintf (stderr, "\tmoh_major_version = %d\n", (int)hdr_ptr->moh_major_version);
2981 fprintf (stderr, "\tmoh_minor_version = %d\n", (int)hdr_ptr->moh_minor_version);
2982 fprintf (stderr, "\tmoh_header_version = %d\n", (int)hdr_ptr->moh_header_version);
2983 fprintf (stderr, "\tmoh_max_page_size = %d\n", (int)hdr_ptr->moh_max_page_size);
2984 fprintf (stderr, "\tmoh_byte_order = %d\n", (int)hdr_ptr->moh_byte_order);
2985 fprintf (stderr, "\tmoh_data_rep_id = %d\n", (int)hdr_ptr->moh_data_rep_id);
2986 fprintf (stderr, "\tmoh_cpu_type = %d\n", (int)hdr_ptr->moh_cpu_type);
2987 fprintf (stderr, "\tmoh_cpu_subtype = %d\n", (int)hdr_ptr->moh_cpu_subtype);
2988 fprintf (stderr, "\tmoh_vendor_type = %d\n", (int)hdr_ptr->moh_vendor_type);
2989 fprintf (stderr, "\tmoh_load_map_cmd_off = %d\n", (int)hdr_ptr->moh_load_map_cmd_off);
2990 fprintf (stderr, "\tmoh_first_cmd_off = %d\n", (int)hdr_ptr->moh_first_cmd_off);
2991 fprintf (stderr, "\tmoh_sizeofcmds = %d\n", (int)hdr_ptr->moh_sizeofcmds);
2992 fprintf (stderr, "\tmon_n_load_cmds = %d\n", (int)hdr_ptr->moh_n_load_cmds);
2993 fprintf (stderr, "\tmoh_flags = 0x%.8lx", (long)hdr_ptr->moh_flags);
2994
2995 if (hdr_ptr->moh_flags & MOH_RELOCATABLE_F)
2996 fprintf (stderr, ", relocatable");
2997
2998 if (hdr_ptr->moh_flags & MOH_LINKABLE_F)
2999 fprintf (stderr, ", linkable");
3000
3001 if (hdr_ptr->moh_flags & MOH_EXECABLE_F)
3002 fprintf (stderr, ", execable");
3003
3004 if (hdr_ptr->moh_flags & MOH_EXECUTABLE_F)
3005 fprintf (stderr, ", executable");
3006
3007 if (hdr_ptr->moh_flags & MOH_UNRESOLVED_F)
3008 fprintf (stderr, ", unresolved");
3009
3010 fprintf (stderr, "\n\n");
3011 return;
3012}
3013
3014\f
3015/* Print a short summary of a load command. */
3016
3017static void
3018print_load_command (load_hdr, offset, number)
3019 load_union_t *load_hdr;
3020 size_t offset;
3021 int number;
3022{
3023 mo_long_t type = load_hdr->hdr.ldci_cmd_type;
3024 char *type_str = (char *)0;
3025
3026 switch (type)
3027 {
3028 case LDC_UNDEFINED: type_str = "UNDEFINED"; break;
3029 case LDC_CMD_MAP: type_str = "CMD_MAP"; break;
3030 case LDC_INTERPRETER: type_str = "INTERPRETER"; break;
3031 case LDC_STRINGS: type_str = "STRINGS"; break;
3032 case LDC_REGION: type_str = "REGION"; break;
3033 case LDC_RELOC: type_str = "RELOC"; break;
3034 case LDC_PACKAGE: type_str = "PACKAGE"; break;
3035 case LDC_SYMBOLS: type_str = "SYMBOLS"; break;
3036 case LDC_ENTRY: type_str = "ENTRY"; break;
3037 case LDC_FUNC_TABLE: type_str = "FUNC_TABLE"; break;
3038 case LDC_GEN_INFO: type_str = "GEN_INFO"; break;
3039 }
3040
3041 fprintf (stderr,
3042 "cmd %2d, sz: 0x%.2lx, coff: 0x%.3lx, doff: 0x%.6lx, dlen: 0x%.6lx",
3043 number,
3044 (long) load_hdr->hdr.ldci_cmd_size,
3045 (long) offset,
3046 (long) load_hdr->hdr.ldci_section_off,
3047 (long) load_hdr->hdr.ldci_section_len);
3048
3049 if (type_str == (char *)0)
3050 fprintf (stderr, ", ty: unknown (%ld)\n", (long) type);
3051
3052 else if (type != LDC_REGION)
3053 fprintf (stderr, ", ty: %s\n", type_str);
3054
3055 else
3056 {
3057 char *region = "";
3058 switch (load_hdr->region.regc_usage_type)
3059 {
3060 case REG_TEXT_T: region = ", .text"; break;
3061 case REG_DATA_T: region = ", .data"; break;
3062 case REG_BSS_T: region = ", .bss"; break;
3063 case REG_GLUE_T: region = ", .glue"; break;
3064#if defined (REG_RDATA_T) && defined (REG_SDATA_T) && defined (REG_SBSS_T) /*mips*/
3065 case REG_RDATA_T: region = ", .rdata"; break;
3066 case REG_SDATA_T: region = ", .sdata"; break;
3067 case REG_SBSS_T: region = ", .sbss"; break;
3068#endif
3069 }
3070
3071 fprintf (stderr, ", ty: %s, vaddr: 0x%.8lx, vlen: 0x%.6lx%s\n",
3072 type_str,
3073 (long) load_hdr->region.regc_vm_addr,
3074 (long) load_hdr->region.regc_vm_size,
3075 region);
3076 }
3077
3078 return;
3079}
3080
3081\f
3082/* Fatal error when {en,de}code_mach_o_header fails. */
3083
3084static void
3085bad_header (status)
3086 int status;
3087{
3088 char *msg = (char *)0;
3089
3090 switch (status)
3091 {
3092 case MO_ERROR_BAD_MAGIC: msg = "bad magic number"; break;
3093 case MO_ERROR_BAD_HDR_VERS: msg = "bad header version"; break;
3094 case MO_ERROR_BAD_RAW_HDR_VERS: msg = "bad raw header version"; break;
3095 case MO_ERROR_BUF2SML: msg = "raw header buffer too small"; break;
3096 case MO_ERROR_OLD_RAW_HDR_FILE: msg = "old raw header file"; break;
3097 case MO_ERROR_UNSUPPORTED_VERS: msg = "unsupported version"; break;
3098 }
3099
3100 if (msg == (char *)0)
3101 fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
3102 else
3103 fatal ("%s", msg);
3104}
3105
3106\f
3107/* Read a file into a memory buffer. */
3108
3109static struct file_info *
3110read_file (name, fd, rw)
3111 char *name; /* filename */
3112 int fd; /* file descriptor */
3113 int rw; /* read/write */
3114{
3115 struct stat stat_pkt;
3116 struct file_info *p = (struct file_info *) xcalloc (sizeof (struct file_info), 1);
3117#ifdef USE_MMAP
3118 static int page_size;
3119#endif
3120
3121 if (fstat (fd, &stat_pkt) < 0)
3122 fatal_perror ("fstat %s", name);
3123
3124 p->name = name;
3125 p->size = stat_pkt.st_size;
3126 p->rounded_size = stat_pkt.st_size;
3127 p->fd = fd;
3128 p->rw = rw;
3129
3130#ifdef USE_MMAP
3131 if (debug)
3132 fprintf (stderr, "mmap %s, %s\n", name, (rw) ? "read/write" : "read-only");
3133
3134 if (page_size == 0)
3135 page_size = sysconf (_SC_PAGE_SIZE);
3136
3137 p->rounded_size = ((p->size + page_size - 1) / page_size) * page_size;
3138 p->start = mmap ((caddr_t)0,
3139 (rw) ? p->rounded_size : p->size,
3140 (rw) ? (PROT_READ | PROT_WRITE) : PROT_READ,
3141 MAP_FILE | MAP_VARIABLE | MAP_SHARED,
3142 fd,
3143 0L);
3144
3145 if (p->start != (char *)0 && p->start != (char *)-1)
3146 p->use_mmap = 1;
3147
3148 else
3149#endif /* USE_MMAP */
3150 {
3151 long len;
3152
3153 if (debug)
3154 fprintf (stderr, "read %s\n", name);
3155
3156 p->use_mmap = 0;
3157 p->start = xmalloc (p->size);
3158 if (lseek (fd, 0L, SEEK_SET) < 0)
3159 fatal_perror ("lseek to 0 on %s", name);
3160
3161 len = read (fd, p->start, p->size);
3162 if (len < 0)
3163 fatal_perror ("read %s", name);
3164
3165 if (len != p->size)
3166 fatal ("read %ld bytes, expected %ld, from %s", len, p->size, name);
3167 }
3168
3169 return p;
3170}
4e81a331
RS
3171\f
3172/* Do anything necessary to write a file back from memory. */
3173
3174static void
3175end_file (ptr)
3176 struct file_info *ptr; /* file information block */
3177{
3178#ifdef USE_MMAP
3179 if (ptr->use_mmap)
3180 {
3181 if (ptr->rw)
3182 {
3183 if (debug)
3184 fprintf (stderr, "msync %s\n", ptr->name);
3185
3186 if (msync (ptr->start, ptr->rounded_size, MS_ASYNC))
3187 fatal_perror ("msync %s", ptr->name);
3188 }
3189
3190 if (debug)
3191 fprintf (stderr, "munmap %s\n", ptr->name);
3192
3193 if (munmap (ptr->start, ptr->size))
3194 fatal_perror ("munmap %s", ptr->name);
3195 }
3196 else
3197#endif /* USE_MMAP */
3198 {
3199 if (ptr->rw)
3200 {
3201 long len;
3202
3203 if (debug)
3204 fprintf (stderr, "write %s\n", ptr->name);
3205
3206 if (lseek (ptr->fd, 0L, SEEK_SET) < 0)
3207 fatal_perror ("lseek to 0 on %s", ptr->name);
3208
3209 len = write (ptr->fd, ptr->start, ptr->size);
3210 if (len < 0)
3211 fatal_perror ("read %s", ptr->name);
3212
3213 if (len != ptr->size)
3214 fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name);
3215 }
3216
a3184468 3217 free (ptr->start);
4e81a331
RS
3218 }
3219
a3184468 3220 free (ptr);
4e81a331
RS
3221}
3222
3223#endif /* OBJECT_FORMAT_ROSE */
This page took 0.577472 seconds and 5 git commands to generate.