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