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