]> gcc.gnu.org Git - gcc.git/blame - gcc/collect2.c
(LINK_SPEC): Pass -shared through; don't
[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
110#undef OBJECT_FORMAT_COFF
111#undef OBJECT_FORMAT_ROSE
bb59f9a6
RS
112#undef MD_EXEC_PREFIX
113#undef REAL_LD_FILE_NAME
114#undef REAL_NM_FILE_NAME
115#undef REAL_STRIP_FILE_NAME
ed5b9462
RS
116#endif
117
118/* If we can't use a special method, use the ordinary one:
119 run nm to find what symbols are present.
120 In a cross-compiler, this means you need a cross nm,
121 but that isn't quite as unpleasant as special headers. */
122
123#if !defined (OBJECT_FORMAT_COFF) && !defined (OBJECT_FORMAT_ROSE)
124#define OBJECT_FORMAT_NONE
125#endif
126
127#ifdef OBJECT_FORMAT_COFF
128
129#include <a.out.h>
130#include <ar.h>
131
132#ifdef UMAX
133#include <sgs.h>
134#endif
135
033ba47c
RS
136/* Many versions of ldfcn.h define these. */
137#ifdef FREAD
ed5b9462
RS
138#undef FREAD
139#undef FWRITE
140#endif
141
142#include <ldfcn.h>
143
7243ba7d
RK
144/* Some systems have an ISCOFF macro, but others do not. In some cases
145 the macro may be wrong. MY_ISCOFF is defined in tm.h files for machines
146 that either do not have an ISCOFF macro in /usr/include or for those
147 where it is wrong. */
148
e99467d2
RS
149#ifndef MY_ISCOFF
150#define MY_ISCOFF(X) ISCOFF (X)
151#endif
152
ed5b9462
RS
153#endif /* OBJECT_FORMAT_COFF */
154
4e81a331
RS
155#ifdef OBJECT_FORMAT_ROSE
156
157#ifdef _OSF_SOURCE
158#define USE_MMAP
159#endif
160
161#ifdef USE_MMAP
162#include <sys/mman.h>
163#endif
164
165#include <unistd.h>
166#include <mach_o_format.h>
167#include <mach_o_header.h>
168#include <mach_o_vals.h>
169#include <mach_o_types.h>
ed5b9462 170
4e81a331
RS
171#endif /* OBJECT_FORMAT_ROSE */
172
ed5b9462
RS
173#ifdef OBJECT_FORMAT_NONE
174
4e81a331
RS
175/* Default flags to pass to nm. */
176#ifndef NM_FLAGS
177#define NM_FLAGS "-p"
178#endif
179
ed5b9462 180#endif /* OBJECT_FORMAT_NONE */
d6cf3187
RS
181
182/* Some systems use __main in a way incompatible with its use in gcc, in these
183 cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
184 give the same symbol without quotes for an alternative entry point. You
185 must define both, or niether. */
186#ifndef NAME__MAIN
187#define NAME__MAIN "__main"
188#define SYMBOL__MAIN __main
189#endif
190
4e81a331
RS
191\f
192/* Linked lists of constructor and destructor names. */
193
194struct id
195{
196 struct id *next;
197 int sequence;
198 char name[1];
199};
200
201struct head
202{
203 struct id *first;
204 struct id *last;
205 int number;
206};
207
208/* Enumeration giving which pass this is for scanning the program file. */
209
210enum pass {
211 PASS_FIRST, /* without constructors */
212 PASS_SECOND /* with constructors linked in */
213};
214
ed5b9462 215#ifndef NO_SYS_SIGLIST
1b7ca660 216#ifndef DONT_DECLARE_SYS_SIGLIST
4e81a331 217extern char *sys_siglist[];
ed5b9462 218#endif
1b7ca660 219#endif
4e81a331
RS
220extern char *version_string;
221
222static int vflag; /* true if -v */
223static int rflag; /* true if -r */
a87104d9 224static int strip_flag; /* true if -s */
4e81a331
RS
225
226static int debug; /* true if -debug */
227
228static int temp_filename_length; /* Length of temp_filename */
229static char *temp_filename; /* Base of temp filenames */
230static char *c_file; /* <xxx>.c for constructor/destructor list. */
231static char *o_file; /* <xxx>.o for constructor/destructor list. */
0cdd3ddd 232static char *output_file; /* Output file for ld. */
4e81a331 233static char *nm_file_name; /* pathname of nm */
a87104d9 234static char *strip_file_name; /* pathname of strip */
4e81a331
RS
235
236static struct head constructors; /* list of constructors found */
237static struct head destructors; /* list of destructors found */
238
ed5b9462
RS
239extern char *getenv ();
240extern char *mktemp ();
4d1a011f
RK
241extern FILE *fdopen ();
242
243/* Structure to hold all the directories in which to search for files to
244 execute. */
245
246struct prefix_list
247{
248 char *prefix; /* String to prepend to the path. */
249 struct prefix_list *next; /* Next in linked list. */
250};
251
252struct path_prefix
253{
254 struct prefix_list *plist; /* List of prefixes to try */
255 int max_len; /* Max length of a prefix in PLIST */
256 char *name; /* Name of this list (used in config stuff) */
257};
258
259static void my_exit PROTO((int));
260static void handler PROTO((int));
261static int is_ctor_dtor PROTO((char *));
262static void choose_temp_base PROTO((void));
263static int is_in_prefix_list PROTO((struct path_prefix *, char *, int));
264static char *find_a_file PROTO((struct path_prefix *, char *));
265static void add_prefix PROTO((struct path_prefix *, char *));
266static void prefix_from_env PROTO((char *, struct path_prefix *));
267static void do_wait PROTO((char *));
268static void fork_execute PROTO((char *, char **));
269static void maybe_unlink PROTO((char *));
270static void add_to_list PROTO((struct head *, char *));
271static void write_list PROTO((FILE *, char *, struct id *));
272static void write_list_with_asm PROTO((FILE *, char *, struct id *));
273static void write_c_file PROTO((FILE *, char *));
274static void scan_prog_file PROTO((char *, enum pass));
ed5b9462
RS
275
276generic *xcalloc ();
277generic *xmalloc ();
3f7cc57a
MS
278
279extern char *index ();
280extern char *rindex ();
4e81a331 281\f
f28e8a68 282#ifdef NO_DUP2
4d1a011f 283int
f28e8a68
RS
284dup2 (oldfd, newfd)
285 int oldfd;
286 int newfd;
287{
288 int fdtmp[256];
289 int fdx = 0;
290 int fd;
291
292 if (oldfd == newfd)
eadbc961 293 return oldfd;
f28e8a68 294 close (newfd);
eadbc961 295 while ((fd = dup (oldfd)) != newfd && fd >= 0) /* good enough for low fd's */
f28e8a68
RS
296 fdtmp[fdx++] = fd;
297 while (fdx > 0)
298 close (fdtmp[--fdx]);
4d1a011f 299
eadbc961 300 return fd;
f28e8a68
RS
301}
302#endif
303
ed5b9462 304char *
1fab8e81 305my_strerror (e)
4e81a331
RS
306 int e;
307{
4e81a331 308
aae807c0
RK
309#ifdef HAVE_STRERROR
310 return strerror (e);
311
312#else
313
314 static char buffer[30];
4e81a331
RS
315 if (!e)
316 return "";
317
318 if (e > 0 && e < sys_nerr)
319 return sys_errlist[e];
320
321 sprintf (buffer, "Unknown error %d", e);
322 return buffer;
aae807c0 323#endif
4e81a331 324}
4e81a331
RS
325\f
326/* Delete tempfiles and exit function. */
327
328static void
329my_exit (status)
330 int status;
331{
ed5b9462 332 if (c_file != 0 && c_file[0])
4e81a331
RS
333 maybe_unlink (c_file);
334
ed5b9462 335 if (o_file != 0 && o_file[0])
4e81a331
RS
336 maybe_unlink (o_file);
337
0cdd3ddd
RS
338 if (status != 0 && output_file != 0 && output_file[0])
339 maybe_unlink (output_file);
340
4e81a331
RS
341 exit (status);
342}
343
344\f
4e81a331
RS
345/* Die when sys call fails. */
346
4e81a331 347static void
1fab8e81 348fatal_perror (string, arg1, arg2, arg3)
bd1a74b1 349 char *string, *arg1, *arg2, *arg3;
4e81a331 350{
4e81a331
RS
351 int e = errno;
352
626e18ea 353 fprintf (stderr, "collect2: ");
1fab8e81
RS
354 fprintf (stderr, string, arg1, arg2, arg3);
355 fprintf (stderr, ": %s\n", my_strerror (e));
4e81a331
RS
356 my_exit (1);
357}
358
359/* Just die. */
360
4e81a331 361static void
1fab8e81 362fatal (string, arg1, arg2, arg3)
bd1a74b1 363 char *string, *arg1, *arg2, *arg3;
4e81a331 364{
626e18ea 365 fprintf (stderr, "collect2: ");
1fab8e81 366 fprintf (stderr, string, arg1, arg2, arg3);
4e81a331 367 fprintf (stderr, "\n");
4e81a331
RS
368 my_exit (1);
369}
370
371/* Write error message. */
372
4e81a331 373static void
1fab8e81 374error (string, arg1, arg2, arg3, arg4)
bd1a74b1 375 char *string, *arg1, *arg2, *arg3, *arg4;
4e81a331 376{
626e18ea 377 fprintf (stderr, "collect2: ");
1fab8e81 378 fprintf (stderr, string, arg1, arg2, arg3, arg4);
4e81a331 379 fprintf (stderr, "\n");
4e81a331
RS
380}
381
4e81a331
RS
382/* In case obstack is linked in, and abort is defined to fancy_abort,
383 provide a default entry. */
384
385void
386fancy_abort ()
387{
388 fatal ("internal error");
389}
390
391\f
392static void
393handler (signo)
394 int signo;
395{
b31a1e3f 396 if (c_file != 0 && c_file[0])
4e81a331
RS
397 maybe_unlink (c_file);
398
b31a1e3f 399 if (o_file != 0 && o_file[0])
4e81a331
RS
400 maybe_unlink (o_file);
401
402 signal (signo, SIG_DFL);
4e81a331
RS
403 kill (getpid (), signo);
404}
405
406\f
407generic *
408xcalloc (size1, size2)
ed5b9462 409 int size1, size2;
4e81a331 410{
ed5b9462 411 generic *ptr = (generic *) calloc (size1, size2);
4e81a331
RS
412 if (ptr)
413 return ptr;
414
1fab8e81 415 fatal ("out of memory");
4e81a331
RS
416 return (generic *)0;
417}
418
419generic *
420xmalloc (size)
ed5b9462 421 int size;
4e81a331 422{
ed5b9462 423 generic *ptr = (generic *) malloc (size);
4e81a331
RS
424 if (ptr)
425 return ptr;
426
1fab8e81 427 fatal ("out of memory");
4e81a331
RS
428 return (generic *)0;
429}
430
ed5b9462
RS
431/* Make a copy of a string INPUT with size SIZE. */
432
433char *
434savestring (input, size)
435 char *input;
436 int size;
437{
438 char *output = (char *) xmalloc (size + 1);
1fab8e81
RS
439 bcopy (input, output, size);
440 output[size] = 0;
ed5b9462
RS
441 return output;
442}
443\f
444/* Decide whether the given symbol is:
445 a constructor (1), a destructor (2), or neither (0). */
446
447static int
448is_ctor_dtor (s)
449 char *s;
450{
451 struct names { char *name; int len; int ret; int two_underscores; };
452
453 register struct names *p;
454 register int ch;
455 register char *orig_s = s;
456
457 static struct names special[] = {
458#ifdef NO_DOLLAR_IN_LABEL
7cbfceab 459#ifdef NO_DOT_IN_LABEL
c52d2678
RS
460 { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, 1, 0 },
461 { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, 2, 0 },
7cbfceab 462#else
ed5b9462
RS
463 { "GLOBAL_.I.", sizeof ("GLOBAL_.I.")-1, 1, 0 },
464 { "GLOBAL_.D.", sizeof ("GLOBAL_.D.")-1, 2, 0 },
7cbfceab 465#endif
ed5b9462
RS
466#else
467 { "GLOBAL_$I$", sizeof ("GLOBAL_$I$")-1, 1, 0 },
5555d6d1 468 { "GLOBAL_$D$", sizeof ("GLOBAL_$D$")-1, 2, 0 },
ed5b9462 469#endif
c1af0346
RS
470#ifdef CFRONT_LOSSAGE /* Don't collect cfront initialization functions.
471 cfront has its own linker procedure to collect them;
472 if collect2 gets them too, they get collected twice
473 when the cfront procedure is run and the compiler used
474 for linking happens to be GCC. */
ed5b9462
RS
475 { "sti__", sizeof ("sti__")-1, 1, 1 },
476 { "std__", sizeof ("std__")-1, 2, 1 },
7a646ee5 477#endif /* CFRONT_LOSSAGE */
ed5b9462
RS
478 { NULL, 0, 0, 0 }
479 };
480
481 while ((ch = *s) == '_')
482 ++s;
483
484 if (s == orig_s)
485 return 0;
486
487 for (p = &special[0]; p->len > 0; p++)
488 {
489 if (ch == p->name[0]
490 && (!p->two_underscores || ((s - orig_s) >= 2))
491 && strncmp(s, p->name, p->len) == 0)
492 {
493 return p->ret;
494 }
495 }
496 return 0;
497}
498
4e81a331
RS
499\f
500/* Compute a string to use as the base of all temporary file names.
501 It is substituted for %g. */
502
503static void
ed5b9462 504choose_temp_base ()
4e81a331
RS
505{
506 char *base = getenv ("TMPDIR");
507 int len;
508
509 if (base == (char *)0)
510 {
511#ifdef P_tmpdir
512 if (access (P_tmpdir, R_OK | W_OK) == 0)
513 base = P_tmpdir;
514#endif
515 if (base == (char *)0)
516 {
517 if (access ("/usr/tmp", R_OK | W_OK) == 0)
518 base = "/usr/tmp/";
519 else
520 base = "/tmp/";
521 }
522 }
523
524 len = strlen (base);
aee42e27 525 temp_filename = xmalloc (len + sizeof("/ccXXXXXX") + 1);
4e81a331
RS
526 strcpy (temp_filename, base);
527 if (len > 0 && temp_filename[len-1] != '/')
528 temp_filename[len++] = '/';
529 strcpy (temp_filename + len, "ccXXXXXX");
530
531 mktemp (temp_filename);
532 temp_filename_length = strlen (temp_filename);
533}
bb59f9a6 534\f
45840c57
RK
535/* Routine to add variables to the environment. */
536
537#ifndef HAVE_PUTENV
538
4d1a011f 539int
45840c57
RK
540putenv (str)
541 char *str;
542{
543#ifndef VMS /* nor about VMS */
544
545 extern char **environ;
546 char **old_environ = environ;
547 char **envp;
548 int num_envs = 0;
549 int name_len = 1;
45840c57
RK
550 char *p = str;
551 int ch;
552
553 while ((ch = *p++) != '\0' && ch != '=')
554 name_len++;
555
556 if (!ch)
557 abort ();
558
559 /* Search for replacing an existing environment variable, and
560 count the number of total environment variables. */
561 for (envp = old_environ; *envp; envp++)
562 {
563 num_envs++;
564 if (!strncmp (str, *envp, name_len))
565 {
566 *envp = str;
4d1a011f 567 return 0;
45840c57
RK
568 }
569 }
570
571 /* Add a new environment variable */
572 environ = (char **) xmalloc (sizeof (char *) * (num_envs+2));
573 *environ = str;
4c9a05bc
RK
574 bcopy ((char *) old_environ, (char *) (environ + 1),
575 sizeof (char *) * (num_envs+1));
576
4d1a011f 577 return 0;
45840c57
RK
578#endif /* VMS */
579}
580
581#endif /* HAVE_PUTENV */
582\f
bb59f9a6
RS
583/* By default, colon separates directories in a path. */
584#ifndef PATH_SEPARATOR
585#define PATH_SEPARATOR ':'
586#endif
587
bb59f9a6
RS
588/* We maintain two prefix lists: one from COMPILER_PATH environment variable
589 and one from the PATH variable. */
590
591static struct path_prefix cpath, path;
592
593#ifdef CROSS_COMPILE
594/* This is the name of the target machine. We use it to form the name
595 of the files to execute. */
596
597static char *target_machine = TARGET_MACHINE;
598#endif
720653a3 599
45840c57 600/* Names under which we were executed. Never return one of those files in our
720653a3
RK
601 searches. */
602
7223feb0 603static struct path_prefix our_file_names;
bb59f9a6 604\f
7223feb0
DE
605/* Determine if STRING is in PPREFIX.
606
607 This utility is currently only used to look up file names. Prefix lists
608 record directory names. This matters to us because the latter has a
609 trailing slash, so I've added a flag to handle both. */
610
611static int
612is_in_prefix_list (pprefix, string, filep)
613 struct path_prefix *pprefix;
614 char *string;
615 int filep;
616{
617 struct prefix_list *pl;
618
619 if (filep)
620 {
621 int len = strlen (string);
622
623 for (pl = pprefix->plist; pl; pl = pl->next)
624 {
625 if (strncmp (pl->prefix, string, len) == 0
626 && strcmp (pl->prefix + len, "/") == 0)
627 return 1;
628 }
629 }
630 else
631 {
632 for (pl = pprefix->plist; pl; pl = pl->next)
633 {
634 if (strcmp (pl->prefix, string) == 0)
635 return 1;
636 }
637 }
638
639 return 0;
640}
641
bb59f9a6
RS
642/* Search for NAME using prefix list PPREFIX. We only look for executable
643 files.
644
645 Return 0 if not found, otherwise return its name, allocated with malloc. */
646
647static char *
648find_a_file (pprefix, name)
649 struct path_prefix *pprefix;
650 char *name;
651{
652 char *temp;
653 struct prefix_list *pl;
654 int len = pprefix->max_len + strlen (name) + 1;
655
656#ifdef EXECUTABLE_SUFFIX
657 len += strlen (EXECUTABLE_SUFFIX);
658#endif
659
660 temp = xmalloc (len);
661
662 /* Determine the filename to execute (special case for absolute paths). */
663
664 if (*name == '/')
665 {
e8fda1f9 666 if (access (name, X_OK) == 0)
bb59f9a6
RS
667 {
668 strcpy (temp, name);
669 return temp;
670 }
671 }
672 else
673 for (pl = pprefix->plist; pl; pl = pl->next)
674 {
675 strcpy (temp, pl->prefix);
676 strcat (temp, name);
7223feb0 677 if (! is_in_prefix_list (&our_file_names, temp, 1)
aee3a549
RK
678 /* This is a kludge, but there seems no way around it. */
679 && strcmp (temp, "./ld") != 0
45840c57 680 && access (temp, X_OK) == 0)
bb59f9a6
RS
681 return temp;
682
683#ifdef EXECUTABLE_SUFFIX
684 /* Some systems have a suffix for executable files.
685 So try appending that. */
686 strcat (temp, EXECUTABLE_SUFFIX);
7223feb0 687 if (! is_in_prefix_list (&our_file_names, temp, 1)
45840c57 688 && access (temp, X_OK) == 0)
bb59f9a6
RS
689 return temp;
690#endif
691 }
692
693 free (temp);
694 return 0;
695}
696
697/* Add an entry for PREFIX to prefix list PPREFIX. */
698
699static void
700add_prefix (pprefix, prefix)
701 struct path_prefix *pprefix;
702 char *prefix;
703{
704 struct prefix_list *pl, **prev;
705 int len;
706
707 if (pprefix->plist)
708 {
709 for (pl = pprefix->plist; pl->next; pl = pl->next)
710 ;
711 prev = &pl->next;
712 }
713 else
714 prev = &pprefix->plist;
715
716 /* Keep track of the longest prefix */
717
718 len = strlen (prefix);
719 if (len > pprefix->max_len)
720 pprefix->max_len = len;
721
722 pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list));
723 pl->prefix = savestring (prefix, len);
724
725 if (*prev)
726 pl->next = *prev;
727 else
728 pl->next = (struct prefix_list *) 0;
729 *prev = pl;
730}
731\f
732/* Take the value of the environment variable ENV, break it into a path, and
733 add of the entries to PPREFIX. */
734
735static void
736prefix_from_env (env, pprefix)
737 char *env;
738 struct path_prefix *pprefix;
739{
740 char *p = getenv (env);
741
742 if (p)
743 {
744 char *startp, *endp;
745 char *nstore = (char *) xmalloc (strlen (p) + 3);
746
747 startp = endp = p;
748 while (1)
749 {
750 if (*endp == PATH_SEPARATOR || *endp == 0)
751 {
752 strncpy (nstore, startp, endp-startp);
753 if (endp == startp)
754 {
755 strcpy (nstore, "./");
756 }
757 else if (endp[-1] != '/')
758 {
759 nstore[endp-startp] = '/';
760 nstore[endp-startp+1] = 0;
761 }
762 else
763 nstore[endp-startp] = 0;
4e81a331 764
bb59f9a6
RS
765 add_prefix (pprefix, nstore);
766 if (*endp == 0)
767 break;
768 endp = startp = endp + 1;
769 }
770 else
771 endp++;
772 }
773 }
774}
4e81a331
RS
775\f
776/* Main program. */
777
778int
779main (argc, argv)
780 int argc;
781 char *argv[];
782{
bb59f9a6
RS
783 char *ld_suffix = "ld";
784 char *full_ld_suffix = ld_suffix;
785 char *real_ld_suffix = "real-ld";
e8fda1f9 786 char *full_real_ld_suffix = real_ld_suffix;
98552524 787#if 0
bb59f9a6
RS
788 char *gld_suffix = "gld";
789 char *full_gld_suffix = gld_suffix;
98552524 790#endif
bb59f9a6
RS
791 char *nm_suffix = "nm";
792 char *full_nm_suffix = nm_suffix;
793 char *gnm_suffix = "gnm";
794 char *full_gnm_suffix = gnm_suffix;
795 char *strip_suffix = "strip";
796 char *full_strip_suffix = strip_suffix;
797 char *gstrip_suffix = "gstrip";
798 char *full_gstrip_suffix = gstrip_suffix;
4e81a331
RS
799 char *arg;
800 FILE *outf;
801 char *ld_file_name;
802 char *c_file_name;
588e387f 803 char *collect_name;
7223feb0 804 char *collect_names;
4e81a331 805 char *p;
ed5b9462
RS
806 char **c_argv;
807 char **c_ptr;
4e81a331
RS
808 char **ld1_argv = (char **) xcalloc (sizeof (char *), argc+2);
809 char **ld1 = ld1_argv;
810 char **ld2_argv = (char **) xcalloc (sizeof (char *), argc+5);
811 char **ld2 = ld2_argv;
812 int first_file;
ed5b9462 813 int num_c_args = argc+7;
4e81a331
RS
814
815#ifdef DEBUG
816 debug = 1;
817 vflag = 1;
818#endif
819
0cdd3ddd
RS
820 output_file = "a.out";
821
45840c57 822 /* We must check that we do not call ourselves in an infinite
588e387f
DE
823 recursion loop. We append the name used for us to the COLLECT_NAMES
824 environment variable.
45840c57 825
7223feb0
DE
826 In practice, collect will rarely invoke itself. This can happen now
827 that we are no longer called gld. A perfect example is when running
828 gcc in a build directory that has been installed. When looking for
829 ld's, we'll find our installed version and believe that's the real ld. */
45840c57 830
588e387f
DE
831 /* We must also append COLLECT_NAME to COLLECT_NAMES to watch for the
832 previous version of collect (the one that used COLLECT_NAME and only
833 handled two levels of recursion). If we don't we may mutually recurse
834 forever. This can happen (I think) when bootstrapping the old version
835 and a new one is installed (rare, but we should handle it).
836 ??? Hopefully references to COLLECT_NAME can be removed at some point. */
837
838 collect_name = (char *) getenv ("COLLECT_NAME");
7223feb0 839 collect_names = (char *) getenv ("COLLECT_NAMES");
45840c57 840
7223feb0 841 p = (char *) xmalloc (strlen ("COLLECT_NAMES=")
588e387f 842 + (collect_name ? strlen (collect_name) + 1 : 0)
7223feb0
DE
843 + (collect_names ? strlen (collect_names) + 1 : 0)
844 + strlen (argv[0]) + 1);
588e387f
DE
845 strcpy (p, "COLLECT_NAMES=");
846 if (collect_name != 0)
847 sprintf (p + strlen (p), "%s%c", collect_name, PATH_SEPARATOR);
7223feb0 848 if (collect_names != 0)
588e387f
DE
849 sprintf (p + strlen (p), "%s%c", collect_names, PATH_SEPARATOR);
850 strcat (p, argv[0]);
45840c57
RK
851 putenv (p);
852
7223feb0
DE
853 prefix_from_env ("COLLECT_NAMES", &our_file_names);
854
588e387f
DE
855 /* Set environment variable COLLECT_NAME to our name so the previous version
856 of collect won't find us. If it does we'll mutually recurse forever.
857 This can happen when bootstrapping the new version and an old version is
858 installed.
859 ??? Hopefully this bit of code can be removed at some point. */
860
861 p = xmalloc (strlen ("COLLECT_NAME=") + strlen (argv[0]) + 1);
862 sprintf (p, "COLLECT_NAME=%s", argv[0]);
863 putenv (p);
864
ed5b9462
RS
865 p = (char *) getenv ("COLLECT_GCC_OPTIONS");
866 if (p)
867 while (*p)
868 {
869 char *q = p;
870 while (*q && *q != ' ') q++;
17704846 871 if (*p == '-' && p[1] == 'm')
ed5b9462
RS
872 num_c_args++;
873
874 if (*q) q++;
875 p = q;
876 }
877
878 c_ptr = c_argv = (char **) xcalloc (sizeof (char *), num_c_args);
879
4e81a331
RS
880 if (argc < 2)
881 fatal ("no arguments");
882
8ab861c7 883#ifdef SIGQUIT
915ee623
JW
884 if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
885 signal (SIGQUIT, handler);
8ab861c7 886#endif
915ee623
JW
887 if (signal (SIGINT, SIG_IGN) != SIG_IGN)
888 signal (SIGINT, handler);
8ab861c7 889#ifdef SIGALRM
915ee623
JW
890 if (signal (SIGALRM, SIG_IGN) != SIG_IGN)
891 signal (SIGALRM, handler);
8ab861c7
RK
892#endif
893#ifdef SIGHUP
915ee623
JW
894 if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
895 signal (SIGHUP, handler);
8ab861c7 896#endif
915ee623
JW
897 if (signal (SIGSEGV, SIG_IGN) != SIG_IGN)
898 signal (SIGSEGV, handler);
8ab861c7 899#ifdef SIGBUS
915ee623
JW
900 if (signal (SIGBUS, SIG_IGN) != SIG_IGN)
901 signal (SIGBUS, handler);
8ab861c7 902#endif
4e81a331 903
bb59f9a6
RS
904 /* Extract COMPILER_PATH and PATH into our prefix list. */
905 prefix_from_env ("COMPILER_PATH", &cpath);
906 prefix_from_env ("PATH", &path);
4e81a331 907
bb59f9a6
RS
908#ifdef CROSS_COMPILE
909 /* If we look for a program in the compiler directories, we just use
910 the short name, since these directories are already system-specific.
911 But it we look for a took in the system directories, we need to
912 qualify the program name with the target machine. */
913
914 full_ld_suffix
aee42e27 915 = xcalloc (strlen (ld_suffix) + strlen (target_machine) + 2, 1);
46c74083 916 strcpy (full_ld_suffix, target_machine);
bb59f9a6 917 strcat (full_ld_suffix, "-");
46c74083 918 strcat (full_ld_suffix, ld_suffix);
bb59f9a6
RS
919
920 full_real_ld_suffix
aee42e27 921 = xcalloc (strlen (real_ld_suffix) + strlen (target_machine) + 2, 1);
46c74083 922 strcpy (full_real_ld_suffix, target_machine);
bb59f9a6 923 strcat (full_real_ld_suffix, "-");
46c74083 924 strcat (full_real_ld_suffix, real_ld_suffix);
bb59f9a6 925
98552524 926#if 0
bb59f9a6 927 full_gld_suffix
aee42e27 928 = xcalloc (strlen (gld_suffix) + strlen (target_machine) + 2, 1);
46c74083 929 strcpy (full_gld_suffix, target_machine);
bb59f9a6 930 strcat (full_gld_suffix, "-");
46c74083 931 strcat (full_gld_suffix, gld_suffix);
98552524 932#endif
bb59f9a6
RS
933
934 full_nm_suffix
aee42e27 935 = xcalloc (strlen (nm_suffix) + strlen (target_machine) + 2, 1);
46c74083 936 strcpy (full_nm_suffix, target_machine);
bb59f9a6 937 strcat (full_nm_suffix, "-");
46c74083 938 strcat (full_nm_suffix, nm_suffix);
bb59f9a6
RS
939
940 full_gnm_suffix
aee42e27 941 = xcalloc (strlen (gnm_suffix) + strlen (target_machine) + 2, 1);
46c74083 942 strcpy (full_gnm_suffix, target_machine);
bb59f9a6 943 strcat (full_gnm_suffix, "-");
46c74083 944 strcat (full_gnm_suffix, gnm_suffix);
bb59f9a6
RS
945
946 full_strip_suffix
aee42e27 947 = xcalloc (strlen (strip_suffix) + strlen (target_machine) + 2, 1);
46c74083 948 strcpy (full_strip_suffix, target_machine);
bb59f9a6 949 strcat (full_strip_suffix, "-");
46c74083 950 strcat (full_strip_suffix, strip_suffix);
bb59f9a6
RS
951
952 full_gstrip_suffix
aee42e27 953 = xcalloc (strlen (gstrip_suffix) + strlen (target_machine) + 2, 1);
46c74083 954 strcpy (full_gstrip_suffix, target_machine);
bb59f9a6 955 strcat (full_gstrip_suffix, "-");
46c74083 956 strcat (full_gstrip_suffix, gstrip_suffix);
bb59f9a6
RS
957#endif /* CROSS_COMPILE */
958
959 /* Try to discover a valid linker/nm/strip to use. */
960
90d326bd
JM
961 /* Maybe we know the right file to use (if not cross). */
962#ifdef REAL_LD_FILE_NAME
963 ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME);
964 if (ld_file_name == 0)
965#endif
98552524 966#if 0
bb59f9a6
RS
967 /* Search the (target-specific) compiler dirs for `gld'. */
968 ld_file_name = find_a_file (&cpath, gld_suffix);
969 /* Search the ordinary system bin directories
46c74083 970 for `gld' (if native linking) or `TARGET-gld' (if cross). */
bb59f9a6
RS
971 if (ld_file_name == 0)
972 ld_file_name = find_a_file (&path, full_gld_suffix);
6c61ac77
DE
973#else
974 ld_file_name = 0;
98552524 975#endif
bb59f9a6
RS
976 /* Likewise for `real-ld'. */
977 if (ld_file_name == 0)
978 ld_file_name = find_a_file (&cpath, real_ld_suffix);
979 if (ld_file_name == 0)
980 ld_file_name = find_a_file (&path, full_real_ld_suffix);
b3a2ef94
RK
981 /* Search the compiler directories for `ld'. We have protection against
982 recursive calls in find_a_file. */
f820b898 983 if (ld_file_name == 0)
b3a2ef94 984 ld_file_name = find_a_file (&cpath, ld_suffix);
bb59f9a6 985 /* Search the ordinary system bin directories
46c74083 986 for `ld' (if native linking) or `TARGET-ld' (if cross). */
bb59f9a6
RS
987 if (ld_file_name == 0)
988 ld_file_name = find_a_file (&path, full_ld_suffix);
989
7223feb0
DE
990 /* If we've invoked ourselves, try again with LD_FILE_NAME. */
991
992 if (collect_names != 0)
993 {
994 if (ld_file_name != 0)
995 {
996 argv[0] = ld_file_name;
997 execvp (argv[0], argv);
998 }
999 fatal ("cannot find `ld'");
1000 }
1001
90d326bd
JM
1002#ifdef REAL_NM_FILE_NAME
1003 nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME);
1004 if (nm_file_name == 0)
1005#endif
bb59f9a6
RS
1006 nm_file_name = find_a_file (&cpath, gnm_suffix);
1007 if (nm_file_name == 0)
1008 nm_file_name = find_a_file (&path, full_gnm_suffix);
1009 if (nm_file_name == 0)
1010 nm_file_name = find_a_file (&cpath, nm_suffix);
bb59f9a6
RS
1011 if (nm_file_name == 0)
1012 nm_file_name = find_a_file (&path, full_nm_suffix);
1013
90d326bd
JM
1014#ifdef REAL_STRIP_FILE_NAME
1015 strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME);
1016 if (strip_file_name == 0)
1017#endif
bb59f9a6
RS
1018 strip_file_name = find_a_file (&cpath, gstrip_suffix);
1019 if (strip_file_name == 0)
1020 strip_file_name = find_a_file (&path, full_gstrip_suffix);
1021 if (strip_file_name == 0)
1022 strip_file_name = find_a_file (&cpath, strip_suffix);
bb59f9a6
RS
1023 if (strip_file_name == 0)
1024 strip_file_name = find_a_file (&path, full_strip_suffix);
4e81a331 1025
a87104d9 1026 /* Determine the full path name of the C compiler to use. */
ed5b9462 1027 c_file_name = getenv ("COLLECT_GCC");
5365d6ee 1028 if (c_file_name == 0)
4e81a331 1029 {
bb59f9a6 1030#ifdef CROSS_COMPILE
aee42e27 1031 c_file_name = xcalloc (sizeof ("gcc-") + strlen (target_machine) + 1, 1);
46c74083
RS
1032 strcpy (c_file_name, target_machine);
1033 strcat (c_file_name, "-gcc");
4e81a331 1034#else
bb59f9a6 1035 c_file_name = "gcc";
a87104d9 1036#endif
a87104d9
MM
1037 }
1038
bb59f9a6
RS
1039 p = find_a_file (&cpath, c_file_name);
1040
1041 /* Here it should be safe to use the system search path since we should have
1042 already qualified the name of the compiler when it is needed. */
1043 if (p == 0)
1044 p = find_a_file (&path, c_file_name);
1045
1046 if (p)
1047 c_file_name = p;
4e81a331 1048
45840c57 1049 *ld1++ = *ld2++ = ld_file_name;
4e81a331
RS
1050
1051 /* Make temp file names. */
1052 choose_temp_base ();
1053 c_file = xcalloc (temp_filename_length + sizeof (".c"), 1);
1054 o_file = xcalloc (temp_filename_length + sizeof (".o"), 1);
1055 sprintf (c_file, "%s.c", temp_filename);
1056 sprintf (o_file, "%s.o", temp_filename);
ed5b9462 1057 *c_ptr++ = c_file_name;
4e81a331
RS
1058 *c_ptr++ = "-c";
1059 *c_ptr++ = "-o";
1060 *c_ptr++ = o_file;
1061
ed5b9462
RS
1062 /* !!! When GCC calls collect2,
1063 it does not know whether it is calling collect2 or ld.
1064 So collect2 cannot meaningfully understand any options
1065 except those ld understands.
1066 If you propose to make GCC pass some other option,
1067 just imagine what will happen if ld is really ld!!! */
1068
4e81a331 1069 /* Parse arguments. Remember output file spec, pass the rest to ld. */
ed5b9462
RS
1070 /* After the first file, put in the c++ rt0. */
1071
4e81a331
RS
1072 first_file = 1;
1073 while ((arg = *++argv) != (char *)0)
1074 {
1075 *ld1++ = *ld2++ = arg;
1076
1077 if (arg[0] == '-')
2d5e74ca 1078 {
4e81a331
RS
1079 switch (arg[1])
1080 {
1081 case 'd':
1082 if (!strcmp (arg, "-debug"))
1083 {
1084 debug = 1;
1085 vflag = 1;
1086 ld1--;
1087 ld2--;
1088 }
1089 break;
1090
4e81a331 1091 case 'o':
0cdd3ddd 1092 output_file = (arg[2] == '\0') ? argv[1] : &arg[2];
4e81a331
RS
1093 break;
1094
1095 case 'r':
1096 if (arg[2] == '\0')
1097 rflag = 1;
1098 break;
1099
a87104d9
MM
1100 case 's':
1101 if (arg[2] == '\0')
1102 {
1103 /* We must strip after the nm run, otherwise C++ linking
1104 won't work. Thus we strip in the second ld run, or
1105 else with strip if there is no second ld run. */
1106 strip_flag = 1;
1107 ld1--;
1108 }
1109 break;
1110
4e81a331
RS
1111 case 'v':
1112 if (arg[2] == '\0')
1113 vflag = 1;
1114 break;
1115 }
2d5e74ca 1116 }
4e81a331 1117 else if (first_file
3f7cc57a 1118 && (p = rindex (arg, '.')) != (char *)0
4e81a331
RS
1119 && strcmp (p, ".o") == 0)
1120 {
1121 first_file = 0;
1122 *ld2++ = o_file;
1123 }
1124 }
1125
ed5b9462
RS
1126 /* Get any options that the upper GCC wants to pass to the sub-GCC. */
1127 p = (char *) getenv ("COLLECT_GCC_OPTIONS");
1128 if (p)
1129 while (*p)
1130 {
1131 char *q = p;
1132 while (*q && *q != ' ') q++;
1133 if (*p == '-' && (p[1] == 'm' || p[1] == 'f'))
1134 *c_ptr++ = savestring (p, q - p);
1135
1136 if (*q) q++;
1137 p = q;
1138 }
1139
4e81a331
RS
1140 *c_ptr++ = c_file;
1141 *c_ptr = *ld1 = *ld2 = (char *)0;
1142
1143 if (vflag)
1144 {
ed5b9462 1145 fprintf (stderr, "collect2 version %s", version_string);
4e81a331
RS
1146#ifdef TARGET_VERSION
1147 TARGET_VERSION;
1148#endif
1149 fprintf (stderr, "\n");
1150 }
1151
1152 if (debug)
1153 {
ed5b9462 1154 char *ptr;
a1549b15
RS
1155 fprintf (stderr, "ld_file_name = %s\n",
1156 (ld_file_name ? ld_file_name : "not found"));
1157 fprintf (stderr, "c_file_name = %s\n",
1158 (c_file_name ? c_file_name : "not found"));
1159 fprintf (stderr, "nm_file_name = %s\n",
1160 (nm_file_name ? nm_file_name : "not found"));
1161 fprintf (stderr, "strip_file_name = %s\n",
1162 (strip_file_name ? strip_file_name : "not found"));
1163 fprintf (stderr, "c_file = %s\n",
1164 (c_file ? c_file : "not found"));
1165 fprintf (stderr, "o_file = %s\n",
1166 (o_file ? o_file : "not found"));
ed5b9462 1167
7223feb0
DE
1168 ptr = getenv ("COLLECT_NAMES");
1169 if (ptr)
1170 fprintf (stderr, "COLLECT_NAMES = %s\n", ptr);
1171
ed5b9462
RS
1172 ptr = getenv ("COLLECT_GCC_OPTIONS");
1173 if (ptr)
1174 fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
1175
1176 ptr = getenv ("COLLECT_GCC");
1177 if (ptr)
1178 fprintf (stderr, "COLLECT_GCC = %s\n", ptr);
1179
1180 ptr = getenv ("COMPILER_PATH");
1181 if (ptr)
1182 fprintf (stderr, "COMPILER_PATH = %s\n", ptr);
1183
1184 ptr = getenv ("LIBRARY_PATH");
1185 if (ptr)
1186 fprintf (stderr, "LIBRARY_PATH = %s\n", ptr);
1187
1188 fprintf (stderr, "\n");
4e81a331
RS
1189 }
1190
1191 /* Load the program, searching all libraries.
1192 Examine the namelist with nm and search it for static constructors
1193 and destructors to call.
1194 Write the constructor and destructor tables to a .s file and reload. */
1195
aee3a549 1196 fork_execute ("ld", ld1_argv);
4e81a331
RS
1197
1198 /* If -r, don't build the constructor or destructor list, just return now. */
1199 if (rflag)
1200 return 0;
1201
0cdd3ddd 1202 scan_prog_file (output_file, PASS_FIRST);
4e81a331
RS
1203
1204 if (debug)
1205 {
1206 fprintf (stderr, "%d constructor(s) found\n", constructors.number);
1207 fprintf (stderr, "%d destructor(s) found\n", destructors.number);
1208 }
1209
1210 if (constructors.number == 0 && destructors.number == 0)
a87104d9
MM
1211 {
1212 /* Strip now if it was requested on the command line. */
1213 if (strip_flag)
1214 {
1215 char **strip_argv = (char **) xcalloc (sizeof (char *), 3);
aee3a549 1216 strip_argv[0] = strip_file_name;
0cdd3ddd 1217 strip_argv[1] = output_file;
a87104d9 1218 strip_argv[2] = (char *) 0;
aee3a549 1219 fork_execute ("strip", strip_argv);
a87104d9
MM
1220 }
1221 return 0;
1222 }
4e81a331 1223
eeed1288 1224 maybe_unlink(output_file);
4e81a331
RS
1225 outf = fopen (c_file, "w");
1226 if (outf == (FILE *)0)
1fab8e81 1227 fatal_perror ("%s", c_file);
4e81a331
RS
1228
1229 write_c_file (outf, c_file);
1230
1231 if (fclose (outf))
1fab8e81 1232 fatal_perror ("closing %s", c_file);
4e81a331
RS
1233
1234 if (debug)
1235 {
0cdd3ddd
RS
1236 fprintf (stderr, "\n========== output_file = %s, c_file = %s\n",
1237 output_file, c_file);
4e81a331
RS
1238 write_c_file (stderr, "stderr");
1239 fprintf (stderr, "========== end of c_file\n\n");
1240 }
1241
1242 /* Assemble the constructor and destructor tables.
1243 Link the tables in with the rest of the program. */
1244
aee3a549
RK
1245 fork_execute ("gcc", c_argv);
1246 fork_execute ("ld", ld2_argv);
4e81a331
RS
1247
1248 /* Let scan_prog_file do any final mods (OSF/rose needs this for
1249 constructors/destructors in shared libraries. */
0cdd3ddd 1250 scan_prog_file (output_file, PASS_SECOND);
4e81a331
RS
1251
1252 maybe_unlink (c_file);
1253 maybe_unlink (o_file);
1254 return 0;
1255}
1256
1257\f
1258/* Wait for a process to finish, and exit if a non-zero status is found. */
1259
1260static void
1261do_wait (prog)
1262 char *prog;
1263{
1264 int status;
1265
1266 wait (&status);
1267 if (status)
1268 {
0b90f9c2 1269 if (WIFSIGNALED (status))
4e81a331 1270 {
0b90f9c2 1271 int sig = WTERMSIG (status);
ed5b9462
RS
1272#ifdef NO_SYS_SIGLIST
1273 error ("%s terminated with signal %d %s",
1274 prog,
1275 sig,
1276 (status & 0200) ? ", core dumped" : "");
1277#else
4e81a331
RS
1278 error ("%s terminated with signal %d [%s]%s",
1279 prog,
1280 sig,
1281 sys_siglist[sig],
1282 (status & 0200) ? ", core dumped" : "");
ed5b9462 1283#endif
4e81a331
RS
1284
1285 my_exit (127);
1286 }
1287
0b90f9c2 1288 if (WIFEXITED (status))
4e81a331 1289 {
0b90f9c2
ILT
1290 int ret = WEXITSTATUS (status);
1291 if (ret != 0)
1292 {
1293 error ("%s returned %d exit status", prog, ret);
1294 my_exit (ret);
1295 }
4e81a331
RS
1296 }
1297 }
1298}
1299
1300\f
1301/* Fork and execute a program, and wait for the reply. */
1302
1303static void
1304fork_execute (prog, argv)
1305 char *prog;
1306 char **argv;
1307{
1308 int pid;
4e81a331
RS
1309
1310 if (vflag || debug)
1311 {
1312 char **p_argv;
1313 char *str;
1314
aee3a549
RK
1315 if (argv[0])
1316 fprintf (stderr, "%s", argv[0]);
bb59f9a6 1317 else
aee3a549 1318 fprintf (stderr, "[cannot find %s]", prog);
bb59f9a6 1319
4e81a331
RS
1320 for (p_argv = &argv[1]; (str = *p_argv) != (char *)0; p_argv++)
1321 fprintf (stderr, " %s", str);
1322
1323 fprintf (stderr, "\n");
1324 }
1325
1326 fflush (stdout);
1327 fflush (stderr);
1328
bb59f9a6
RS
1329 /* If we can't find a program we need, complain error. Do this here
1330 since we might not end up needing something that we couldn't find. */
1331
aee3a549
RK
1332 if (argv[0] == 0)
1333 fatal ("cannot find `%s'", prog);
bb59f9a6 1334
4e81a331
RS
1335 pid = vfork ();
1336 if (pid == -1)
cf0c751a
JW
1337 {
1338#ifdef vfork
1339 fatal_perror ("fork");
1340#else
1341 fatal_perror ("vfork");
1342#endif
1343 }
4e81a331
RS
1344
1345 if (pid == 0) /* child context */
1346 {
aee3a549 1347 execvp (argv[0], argv);
1fab8e81 1348 fatal_perror ("executing %s", prog);
4e81a331
RS
1349 }
1350
4e81a331 1351 do_wait (prog);
4e81a331
RS
1352}
1353
1354\f
1355/* Unlink a file unless we are debugging. */
1356
1357static void
1358maybe_unlink (file)
1359 char *file;
1360{
1361 if (!debug)
1362 unlink (file);
1363 else
1364 fprintf (stderr, "[Leaving %s]\n", file);
1365}
1366
1367\f
1368/* Add a name to a linked list. */
1369
1370static void
1371add_to_list (head_ptr, name)
1372 struct head *head_ptr;
1373 char *name;
1374{
1375 struct id *newid = (struct id *) xcalloc (sizeof (*newid) + strlen (name), 1);
1376 static long sequence_number = 0;
1377 newid->sequence = ++sequence_number;
1378 strcpy (newid->name, name);
1379
1380 if (head_ptr->first)
1381 head_ptr->last->next = newid;
1382 else
1383 head_ptr->first = newid;
1384
1385 head_ptr->last = newid;
1386 head_ptr->number++;
1387}
1388
1389/* Write: `prefix', the names on list LIST, `suffix'. */
1390
1391static void
1392write_list (stream, prefix, list)
1393 FILE *stream;
1394 char *prefix;
1395 struct id *list;
1396{
1397 while (list)
1398 {
1399 fprintf (stream, "%sx%d,\n", prefix, list->sequence);
1400 list = list->next;
1401 }
1402}
1403
1404static void
1405write_list_with_asm (stream, prefix, list)
1406 FILE *stream;
1407 char *prefix;
1408 struct id *list;
1409{
1410 while (list)
1411 {
c7af43d8 1412 fprintf (stream, "%sx%d __asm__ (\"%s\");\n",
4e81a331
RS
1413 prefix, list->sequence, list->name);
1414 list = list->next;
1415 }
1416}
1417
1418/* Write the constructor/destructor tables. */
1419
1420static void
1421write_c_file (stream, name)
1422 FILE *stream;
1423 char *name;
1424{
1425 /* Write the tables as C code */
1426
1427 fprintf (stream, "typedef void entry_pt();\n\n");
1428
17704846 1429 write_list_with_asm (stream, "extern entry_pt ", constructors.first);
4e81a331
RS
1430
1431 fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
1432 fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number);
ed5b9462 1433 write_list (stream, "\t", constructors.first);
4e81a331
RS
1434 fprintf (stream, "\t0\n};\n\n");
1435
17704846 1436 write_list_with_asm (stream, "extern entry_pt ", destructors.first);
4e81a331
RS
1437
1438 fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
1439 fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number);
ed5b9462 1440 write_list (stream, "\t", destructors.first);
4e81a331
RS
1441 fprintf (stream, "\t0\n};\n\n");
1442
d6cf3187
RS
1443 fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
1444 fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);
4e81a331
RS
1445}
1446
1447\f
ed5b9462 1448#ifdef OBJECT_FORMAT_NONE
4e81a331 1449
ed5b9462
RS
1450/* Generic version to scan the name list of the loaded program for
1451 the symbols g++ uses for static constructors and destructors.
4e81a331
RS
1452
1453 The constructor table begins at __CTOR_LIST__ and contains a count
1454 of the number of pointers (or -1 if the constructors are built in a
1455 separate section by the linker), followed by the pointers to the
1456 constructor functions, terminated with a null pointer. The
1457 destructor table has the same format, and begins at __DTOR_LIST__. */
1458
1459static void
1460scan_prog_file (prog_name, which_pass)
1461 char *prog_name;
1462 enum pass which_pass;
1463{
ed5b9462
RS
1464 void (*int_handler) ();
1465 void (*quit_handler) ();
4e81a331
RS
1466 char *nm_argv[4];
1467 int pid;
1468 int argc = 0;
1469 int pipe_fd[2];
1470 char *p, buf[1024];
1471 FILE *inf;
1472
1473 if (which_pass != PASS_FIRST)
1474 return;
1475
bb59f9a6
RS
1476 /* If we don't have an `nm', complain. */
1477 if (nm_file_name == 0)
1478 fatal ("cannot find `nm'");
1479
ed5b9462 1480 nm_argv[argc++] = "nm";
4e81a331 1481 if (NM_FLAGS[0] != '\0')
ed5b9462 1482 nm_argv[argc++] = NM_FLAGS;
4e81a331 1483
ed5b9462
RS
1484 nm_argv[argc++] = prog_name;
1485 nm_argv[argc++] = (char *)0;
4e81a331
RS
1486
1487 if (pipe (pipe_fd) < 0)
1488 fatal_perror ("pipe");
1489
1490 inf = fdopen (pipe_fd[0], "r");
1491 if (inf == (FILE *)0)
1492 fatal_perror ("fdopen");
1493
1494 /* Trace if needed. */
1495 if (vflag)
1496 {
1497 char **p_argv;
1498 char *str;
1499
1500 fprintf (stderr, "%s", nm_file_name);
1501 for (p_argv = &nm_argv[1]; (str = *p_argv) != (char *)0; p_argv++)
1502 fprintf (stderr, " %s", str);
1503
1504 fprintf (stderr, "\n");
1505 }
1506
1507 fflush (stdout);
1508 fflush (stderr);
1509
1510 /* Spawn child nm on pipe */
1511 pid = vfork ();
1512 if (pid == -1)
cf0c751a
JW
1513 {
1514#ifdef vfork
1515 fatal_perror ("fork");
1516#else
1517 fatal_perror ("vfork");
1518#endif
1519 }
4e81a331
RS
1520
1521 if (pid == 0) /* child context */
1522 {
1523 /* setup stdout */
1524 if (dup2 (pipe_fd[1], 1) < 0)
1fab8e81 1525 fatal_perror ("dup2 (%d, 1)", pipe_fd[1]);
4e81a331
RS
1526
1527 if (close (pipe_fd[0]) < 0)
1fab8e81 1528 fatal_perror ("close (%d)", pipe_fd[0]);
4e81a331
RS
1529
1530 if (close (pipe_fd[1]) < 0)
1fab8e81 1531 fatal_perror ("close (%d)", pipe_fd[1]);
4e81a331
RS
1532
1533 execv (nm_file_name, nm_argv);
1fab8e81 1534 fatal_perror ("executing %s", nm_file_name);
4e81a331
RS
1535 }
1536
1537 /* Parent context from here on. */
ed5b9462 1538 int_handler = (void (*) ())signal (SIGINT, SIG_IGN);
8ab861c7 1539#ifdef SIGQUIT
ed5b9462 1540 quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN);
8ab861c7 1541#endif
4e81a331
RS
1542
1543 if (close (pipe_fd[1]) < 0)
1fab8e81 1544 fatal_perror ("close (%d)", pipe_fd[1]);
4e81a331
RS
1545
1546 if (debug)
1547 fprintf (stderr, "\nnm output with constructors/destructors.\n");
1548
1549 /* Read each line of nm output. */
1550 while (fgets (buf, sizeof buf, inf) != (char *)0)
1551 {
1552 int ch, ch2;
ed5b9462 1553 char *name, *end;
4e81a331
RS
1554
1555 /* If it contains a constructor or destructor name, add the name
1556 to the appropriate list. */
1557
1558 for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
1559 ;
1560
1561 if (ch == '\0' || ch == '\n')
1562 continue;
ed5b9462
RS
1563
1564 name = p;
1565 /* Find the end of the symbol name.
1566 Don't include `|', because Encore nm can tack that on the end. */
1567 for (end = p; (ch2 = *end) != '\0' && !isspace (ch2) && ch2 != '|';
1568 end++)
1569 continue;
4e81a331 1570
90d326bd
JM
1571#ifdef COLLECT_QUALIFY_MATCH
1572 COLLECT_QUALIFY_MATCH;
1573#endif
1574
4e81a331 1575 *end = '\0';
ed5b9462 1576 switch (is_ctor_dtor (name))
4e81a331 1577 {
ed5b9462
RS
1578 case 1:
1579 add_to_list (&constructors, name);
1580 break;
4e81a331 1581
ed5b9462
RS
1582 case 2:
1583 add_to_list (&destructors, name);
1584 break;
4e81a331 1585
ed5b9462
RS
1586 default: /* not a constructor or destructor */
1587 continue;
4e81a331
RS
1588 }
1589
4e81a331
RS
1590 if (debug)
1591 fprintf (stderr, "\t%s\n", buf);
1592 }
1593
1594 if (debug)
1595 fprintf (stderr, "\n");
1596
1597 if (fclose (inf) != 0)
1598 fatal_perror ("fclose of pipe");
1599
1600 do_wait (nm_file_name);
1601
1602 signal (SIGINT, int_handler);
8ab861c7 1603#ifdef SIGQUIT
4e81a331 1604 signal (SIGQUIT, quit_handler);
8ab861c7 1605#endif
4e81a331
RS
1606}
1607
ed5b9462
RS
1608#endif /* OBJECT_FORMAT_NONE */
1609
1610\f
1611/*
1612 * COFF specific stuff.
1613 */
1614
1615#ifdef OBJECT_FORMAT_COFF
1616
1617#if defined(EXTENDED_COFF)
17704846
JW
1618# define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
1619# define GCC_SYMENT SYMR
1620# define GCC_OK_SYMBOL(X) ((X).st == stProc && (X).sc == scText)
1621# define GCC_SYMINC(X) (1)
1622# define GCC_SYMZERO(X) (SYMHEADER(X).isymMax)
1623# define GCC_CHECK_HDR(X) (PSYMTAB(X) != 0)
ed5b9462 1624#else
17704846
JW
1625# define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms)
1626# define GCC_SYMENT SYMENT
ed5b9462
RS
1627# define GCC_OK_SYMBOL(X) \
1628 (((X).n_sclass == C_EXT) && \
1629 (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) || \
1630 ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))
17704846
JW
1631# define GCC_SYMINC(X) ((X).n_numaux+1)
1632# define GCC_SYMZERO(X) 0
1633# define GCC_CHECK_HDR(X) (1)
ed5b9462
RS
1634#endif
1635
1636extern char *ldgetname ();
1637
1638/* COFF version to scan the name list of the loaded program for
1639 the symbols g++ uses for static constructors and destructors.
1640
1641 The constructor table begins at __CTOR_LIST__ and contains a count
1642 of the number of pointers (or -1 if the constructors are built in a
1643 separate section by the linker), followed by the pointers to the
1644 constructor functions, terminated with a null pointer. The
1645 destructor table has the same format, and begins at __DTOR_LIST__. */
1646
1647static void
1648scan_prog_file (prog_name, which_pass)
1649 char *prog_name;
1650 enum pass which_pass;
1651{
f3c3d3df 1652 LDFILE *ldptr = NULL;
ed5b9462
RS
1653 int sym_index, sym_count;
1654
1655 if (which_pass != PASS_FIRST)
1656 return;
1657
1658 if ((ldptr = ldopen (prog_name, ldptr)) == NULL)
1659 fatal ("%s: can't open as COFF file", prog_name);
1660
e99467d2 1661 if (!MY_ISCOFF (HEADER (ldptr).f_magic))
ed5b9462
RS
1662 fatal ("%s: not a COFF file", prog_name);
1663
17704846 1664 if (GCC_CHECK_HDR (ldptr))
ed5b9462 1665 {
17704846
JW
1666 sym_count = GCC_SYMBOLS (ldptr);
1667 sym_index = GCC_SYMZERO (ldptr);
1668 while (sym_index < sym_count)
1669 {
1670 GCC_SYMENT symbol;
ed5b9462 1671
17704846
JW
1672 if (ldtbread (ldptr, sym_index, &symbol) <= 0)
1673 break;
1674 sym_index += GCC_SYMINC (symbol);
ed5b9462 1675
17704846
JW
1676 if (GCC_OK_SYMBOL (symbol))
1677 {
1678 char *name;
ed5b9462 1679
17704846
JW
1680 if ((name = ldgetname (ldptr, &symbol)) == NULL)
1681 continue; /* should never happen */
ed5b9462
RS
1682
1683#ifdef _AIX
17704846
JW
1684 /* All AIX function names begin with a dot. */
1685 if (*name++ != '.')
1686 continue;
ed5b9462
RS
1687#endif
1688
17704846
JW
1689 switch (is_ctor_dtor (name))
1690 {
1691 case 1:
1692 add_to_list (&constructors, name);
1693 break;
ed5b9462 1694
17704846
JW
1695 case 2:
1696 add_to_list (&destructors, name);
1697 break;
ed5b9462 1698
17704846
JW
1699 default: /* not a constructor or destructor */
1700 continue;
1701 }
ed5b9462
RS
1702
1703#if !defined(EXTENDED_COFF)
17704846
JW
1704 if (debug)
1705 fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
1706 symbol.n_scnum, symbol.n_sclass,
1707 (symbol.n_type ? "0" : ""), symbol.n_type,
1708 name);
ed5b9462 1709#else
17704846
JW
1710 if (debug)
1711 fprintf (stderr, "\tiss = %5d, value = %5d, index = %5d, name = %s\n",
1712 symbol.iss, symbol.value, symbol.index, name);
ed5b9462 1713#endif
17704846 1714 }
ed5b9462
RS
1715 }
1716 }
1717
1718 (void) ldclose(ldptr);
1719}
1720
1721#endif /* OBJECT_FORMAT_COFF */
4e81a331
RS
1722
1723\f
1724/*
1725 * OSF/rose specific stuff.
1726 */
1727
1728#ifdef OBJECT_FORMAT_ROSE
1729
1730/* Union of the various load commands */
1731
1732typedef union load_union
1733{
1734 ldc_header_t hdr; /* common header */
1735 load_cmd_map_command_t map; /* map indexing other load cmds */
ed5b9462 1736 interpreter_command_t iprtr; /* interpreter pathname */
4e81a331
RS
1737 strings_command_t str; /* load commands strings section */
1738 region_command_t region; /* region load command */
1739 reloc_command_t reloc; /* relocation section */
1740 package_command_t pkg; /* package load command */
1741 symbols_command_t sym; /* symbol sections */
1742 entry_command_t ent; /* program start section */
1743 gen_info_command_t info; /* object information */
1744 func_table_command_t func; /* function constructors/destructors */
1745} load_union_t;
1746
1747/* Structure to point to load command and data section in memory. */
1748
1749typedef struct load_all
1750{
1751 load_union_t *load; /* load command */
1752 char *section; /* pointer to section */
1753} load_all_t;
1754
1755/* Structure to contain information about a file mapped into memory. */
1756
1757struct file_info
1758{
1759 char *start; /* start of map */
1760 char *name; /* filename */
1761 long size; /* size of the file */
1762 long rounded_size; /* size rounded to page boundary */
1763 int fd; /* file descriptor */
1764 int rw; /* != 0 if opened read/write */
1765 int use_mmap; /* != 0 if mmap'ed */
1766};
1767
ed5b9462 1768extern int decode_mach_o_hdr ();
ed5b9462 1769extern int encode_mach_o_hdr ();
4e81a331 1770
4d1a011f
RK
1771static void add_func_table PROTO((mo_header_t *, load_all_t *,
1772 symbol_info_t *, int));
1773static void print_header PROTO((mo_header_t *));
1774static void print_load_command PROTO((load_union_t*, size_t, int));
1775static void bad_header PROTO((int));
357a98f1 1776static struct file_info *read_file PROTO((char *, int, int));
4d1a011f 1777static void end_file PROTO((struct file_info *));
4e81a331
RS
1778\f
1779/* OSF/rose specific version to scan the name list of the loaded
1780 program for the symbols g++ uses for static constructors and
1781 destructors.
1782
1783 The constructor table begins at __CTOR_LIST__ and contains a count
1784 of the number of pointers (or -1 if the constructors are built in a
1785 separate section by the linker), followed by the pointers to the
1786 constructor functions, terminated with a null pointer. The
1787 destructor table has the same format, and begins at __DTOR_LIST__. */
1788
1789static void
1790scan_prog_file (prog_name, which_pass)
1791 char *prog_name;
1792 enum pass which_pass;
1793{
1794 char *obj;
1795 mo_header_t hdr;
1796 load_all_t *load_array;
1797 load_all_t *load_end;
1798 load_all_t *load_cmd;
1799 int symbol_load_cmds;
1800 off_t offset;
1801 int i;
1802 int num_syms;
1803 int status;
1804 char *str_sect;
1805 struct file_info *obj_file;
1806 int prog_fd;
1807 mo_lcid_t cmd_strings = -1;
1808 symbol_info_t *main_sym = 0;
1809 int rw = (which_pass != PASS_FIRST);
1810
1811 prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY);
1812 if (prog_fd < 0)
1fab8e81 1813 fatal_perror ("can't read %s", prog_name);
4e81a331
RS
1814
1815 obj_file = read_file (prog_name, prog_fd, rw);
1816 obj = obj_file->start;
1817
1818 status = decode_mach_o_hdr (obj, MO_SIZEOF_RAW_HDR, MOH_HEADER_VERSION, &hdr);
1819 if (status != MO_HDR_CONV_SUCCESS)
1820 bad_header (status);
1821
1822
1823 /* Do some basic sanity checks. Note we explicitly use the big endian magic number,
1824 since the hardware will automatically swap bytes for us on loading little endian
1825 integers. */
1826
1827#ifndef CROSS_COMPILE
1828 if (hdr.moh_magic != MOH_MAGIC_MSB
1829 || hdr.moh_header_version != MOH_HEADER_VERSION
1830 || hdr.moh_byte_order != OUR_BYTE_ORDER
1831 || hdr.moh_data_rep_id != OUR_DATA_REP_ID
1832 || hdr.moh_cpu_type != OUR_CPU_TYPE
1833 || hdr.moh_cpu_subtype != OUR_CPU_SUBTYPE
1834 || hdr.moh_vendor_type != OUR_VENDOR_TYPE)
1835 {
1fab8e81 1836 fatal ("incompatibilities between object file & expected values");
4e81a331
RS
1837 }
1838#endif
1839
1840 if (debug)
1841 print_header (&hdr);
1842
1843 offset = hdr.moh_first_cmd_off;
1844 load_end = load_array
1845 = (load_all_t *) xcalloc (sizeof (load_all_t), hdr.moh_n_load_cmds + 2);
1846
1847 /* Build array of load commands, calculating the offsets */
1848 for (i = 0; i < hdr.moh_n_load_cmds; i++)
1849 {
1850 load_union_t *load_hdr; /* load command header */
1851
1852 load_cmd = load_end++;
1853 load_hdr = (load_union_t *) (obj + offset);
1854
f72aed24 1855 /* If modifying the program file, copy the header. */
4e81a331
RS
1856 if (rw)
1857 {
1858 load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size);
4c9a05bc 1859 bcopy ((char *)load_hdr, (char *)ptr, load_hdr->hdr.ldci_cmd_size);
4e81a331
RS
1860 load_hdr = ptr;
1861
1862 /* null out old command map, because we will rewrite at the end. */
1863 if (ptr->hdr.ldci_cmd_type == LDC_CMD_MAP)
1864 {
1865 cmd_strings = ptr->map.lcm_ld_cmd_strings;
1866 ptr->hdr.ldci_cmd_type = LDC_UNDEFINED;
1867 }
1868 }
1869
1870 load_cmd->load = load_hdr;
1871 if (load_hdr->hdr.ldci_section_off > 0)
1872 load_cmd->section = obj + load_hdr->hdr.ldci_section_off;
1873
1874 if (debug)
1875 print_load_command (load_hdr, offset, i);
1876
1877 offset += load_hdr->hdr.ldci_cmd_size;
1878 }
1879
1880 /* If the last command is the load command map and is not undefined,
1881 decrement the count of load commands. */
1882 if (rw && load_end[-1].load->hdr.ldci_cmd_type == LDC_UNDEFINED)
1883 {
1884 load_end--;
1885 hdr.moh_n_load_cmds--;
1886 }
1887
1888 /* Go through and process each symbol table section. */
1889 symbol_load_cmds = 0;
1890 for (load_cmd = load_array; load_cmd < load_end; load_cmd++)
1891 {
1892 load_union_t *load_hdr = load_cmd->load;
1893
1894 if (load_hdr->hdr.ldci_cmd_type == LDC_SYMBOLS)
1895 {
1896 symbol_load_cmds++;
1897
1898 if (debug)
1899 {
ed5b9462 1900 char *kind = "unknown";
4e81a331
RS
1901
1902 switch (load_hdr->sym.symc_kind)
1903 {
1904 case SYMC_IMPORTS: kind = "imports"; break;
1905 case SYMC_DEFINED_SYMBOLS: kind = "defined"; break;
1906 case SYMC_STABS: kind = "stabs"; break;
1907 }
1908
1909 fprintf (stderr, "\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
1910 symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
1911 }
1912
1913 if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
1914 continue;
1915
ed5b9462 1916 str_sect = load_array[load_hdr->sym.symc_strings_section].section;
4e81a331
RS
1917 if (str_sect == (char *)0)
1918 fatal ("string section missing");
1919
1920 if (load_cmd->section == (char *)0)
1921 fatal ("section pointer missing");
1922
1923 num_syms = load_hdr->sym.symc_nentries;
1924 for (i = 0; i < num_syms; i++)
1925 {
1926 symbol_info_t *sym = ((symbol_info_t *) load_cmd->section) + i;
1927 char *name = sym->si_name.symbol_name + str_sect;
4e81a331
RS
1928
1929 if (name[0] != '_')
1930 continue;
1931
4e81a331
RS
1932 if (rw)
1933 {
d6cf3187
RS
1934 char *n = name + strlen (name) - strlen (NAME__MAIN);
1935
1936 if ((n - name) < 0 || strcmp (n, NAME__MAIN))
4e81a331 1937 continue;
d6cf3187
RS
1938 while (n != name)
1939 if (*--n != '_')
1940 continue;
4e81a331
RS
1941
1942 main_sym = sym;
1943 }
ed5b9462 1944 else
4e81a331 1945 {
ed5b9462
RS
1946 switch (is_ctor_dtor (name))
1947 {
1948 case 1:
1949 add_to_list (&constructors, name);
1950 break;
1951
1952 case 2:
1953 add_to_list (&destructors, name);
1954 break;
1955
1956 default: /* not a constructor or destructor */
1957 continue;
1958 }
4e81a331
RS
1959 }
1960
4e81a331
RS
1961 if (debug)
1962 fprintf (stderr, "\ttype = 0x%.4x, sc = 0x%.2x, flags = 0x%.8x, name = %.30s\n",
1963 sym->si_type, sym->si_sc_type, sym->si_flags, name);
1964 }
1965 }
1966 }
1967
1968 if (symbol_load_cmds == 0)
1fab8e81 1969 fatal ("no symbol table found");
4e81a331
RS
1970
1971 /* Update the program file now, rewrite header and load commands. At present,
1972 we assume that there is enough space after the last load command to insert
1973 one more. Since the first section written out is page aligned, and the
1974 number of load commands is small, this is ok for the present. */
1975
1976 if (rw)
1977 {
1978 load_union_t *load_map;
1979 size_t size;
1980
1981 if (cmd_strings == -1)
1fab8e81
RS
1982 fatal ("no cmd_strings found");
1983
1984 /* Add __main to initializer list.
1985 If we are building a program instead of a shared library, don't
1986 do anything, since in the current version, you cannot do mallocs
1987 and such in the constructors. */
4e81a331 1988
1fab8e81
RS
1989 if (main_sym != (symbol_info_t *)0
1990 && ((hdr.moh_flags & MOH_EXECABLE_F) == 0))
4e81a331
RS
1991 add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION);
1992
1993 if (debug)
1994 fprintf (stderr, "\nUpdating header and load commands.\n\n");
1995
1996 hdr.moh_n_load_cmds++;
1997 size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1));
1998
1999 /* Create new load command map. */
2000 if (debug)
2001 fprintf (stderr, "load command map, %d cmds, new size %ld.\n",
2002 (int)hdr.moh_n_load_cmds, (long)size);
2003
2004 load_map = (load_union_t *) xcalloc (1, size);
2005 load_map->map.ldc_header.ldci_cmd_type = LDC_CMD_MAP;
2006 load_map->map.ldc_header.ldci_cmd_size = size;
2007 load_map->map.lcm_ld_cmd_strings = cmd_strings;
2008 load_map->map.lcm_nentries = hdr.moh_n_load_cmds;
2009 load_array[hdr.moh_n_load_cmds-1].load = load_map;
2010
2011 offset = hdr.moh_first_cmd_off;
2012 for (i = 0; i < hdr.moh_n_load_cmds; i++)
2013 {
2014 load_map->map.lcm_map[i] = offset;
2015 if (load_array[i].load->hdr.ldci_cmd_type == LDC_CMD_MAP)
2016 hdr.moh_load_map_cmd_off = offset;
2017
2018 offset += load_array[i].load->hdr.ldci_cmd_size;
2019 }
2020
2021 hdr.moh_sizeofcmds = offset - MO_SIZEOF_RAW_HDR;
2022
2023 if (debug)
2024 print_header (&hdr);
2025
2026 /* Write header */
2027 status = encode_mach_o_hdr (&hdr, obj, MO_SIZEOF_RAW_HDR);
2028 if (status != MO_HDR_CONV_SUCCESS)
2029 bad_header (status);
2030
2031 if (debug)
2032 fprintf (stderr, "writing load commands.\n\n");
2033
2034 /* Write load commands */
2035 offset = hdr.moh_first_cmd_off;
2036 for (i = 0; i < hdr.moh_n_load_cmds; i++)
2037 {
2038 load_union_t *load_hdr = load_array[i].load;
2039 size_t size = load_hdr->hdr.ldci_cmd_size;
2040
2041 if (debug)
2042 print_load_command (load_hdr, offset, i);
2043
4c9a05bc 2044 bcopy ((char *)load_hdr, (char *)(obj + offset), size);
4e81a331
RS
2045 offset += size;
2046 }
2047 }
2048
2049 end_file (obj_file);
2050
2051 if (close (prog_fd))
1fab8e81 2052 fatal_perror ("closing %s", prog_name);
4e81a331
RS
2053
2054 if (debug)
2055 fprintf (stderr, "\n");
2056}
2057
2058\f
2059/* Add a function table to the load commands to call a function
ed5b9462 2060 on initiation or termination of the process. */
4e81a331
RS
2061
2062static void
2063add_func_table (hdr_p, load_array, sym, type)
2064 mo_header_t *hdr_p; /* pointer to global header */
2065 load_all_t *load_array; /* array of ptrs to load cmds */
2066 symbol_info_t *sym; /* pointer to symbol entry */
2067 int type; /* fntc_type value */
2068{
2069 /* Add a new load command. */
2070 int num_cmds = ++hdr_p->moh_n_load_cmds;
2071 int load_index = num_cmds - 1;
2072 size_t size = sizeof (func_table_command_t) + sizeof (mo_addr_t);
2073 load_union_t *ptr = xcalloc (1, size);
2074 load_all_t *load_cmd;
2075 int i;
2076
2077 /* Set the unresolved address bit in the header to force the loader to be
2078 used, since kernel exec does not call the initialization functions. */
2079 hdr_p->moh_flags |= MOH_UNRESOLVED_F;
2080
2081 load_cmd = &load_array[load_index];
2082 load_cmd->load = ptr;
2083 load_cmd->section = (char *)0;
2084
2085 /* Fill in func table load command. */
2086 ptr->func.ldc_header.ldci_cmd_type = LDC_FUNC_TABLE;
2087 ptr->func.ldc_header.ldci_cmd_size = size;
2088 ptr->func.ldc_header.ldci_section_off = 0;
2089 ptr->func.ldc_header.ldci_section_len = 0;
2090 ptr->func.fntc_type = type;
2091 ptr->func.fntc_nentries = 1;
2092
2093 /* copy address, turn it from abs. address to (region,offset) if necessary. */
2094 /* Is the symbol already expressed as (region, offset)? */
2095 if ((sym->si_flags & SI_ABSOLUTE_VALUE_F) == 0)
2096 {
2097 ptr->func.fntc_entry_loc[i].adr_lcid = sym->si_value.def_val.adr_lcid;
2098 ptr->func.fntc_entry_loc[i].adr_sctoff = sym->si_value.def_val.adr_sctoff;
2099 }
2100
2101 /* If not, figure out which region it's in. */
2102 else
2103 {
2104 mo_vm_addr_t addr = sym->si_value.abs_val;
2105 int found = 0;
2106
2107 for (i = 0; i < load_index; i++)
2108 {
2109 if (load_array[i].load->hdr.ldci_cmd_type == LDC_REGION)
2110 {
2111 region_command_t *region_ptr = &load_array[i].load->region;
2112
2113 if ((region_ptr->regc_flags & REG_ABS_ADDR_F) != 0
2114 && addr >= region_ptr->regc_addr.vm_addr
2115 && addr <= region_ptr->regc_addr.vm_addr + region_ptr->regc_vm_size)
2116 {
2117 ptr->func.fntc_entry_loc[0].adr_lcid = i;
2118 ptr->func.fntc_entry_loc[0].adr_sctoff = addr - region_ptr->regc_addr.vm_addr;
2119 found++;
2120 break;
2121 }
2122 }
2123 }
2124
2125 if (!found)
2126 fatal ("could not convert 0x%l.8x into a region", addr);
2127 }
2128
2129 if (debug)
2130 fprintf (stderr,
2131 "%s function, region %d, offset = %ld (0x%.8lx)\n",
2132 (type == FNTC_INITIALIZATION) ? "init" : "term",
2133 (int)ptr->func.fntc_entry_loc[i].adr_lcid,
2134 (long)ptr->func.fntc_entry_loc[i].adr_sctoff,
2135 (long)ptr->func.fntc_entry_loc[i].adr_sctoff);
2136
2137}
2138
2139\f
2140/* Print the global header for an OSF/rose object. */
2141
2142static void
2143print_header (hdr_ptr)
2144 mo_header_t *hdr_ptr;
2145{
2146 fprintf (stderr, "\nglobal header:\n");
2147 fprintf (stderr, "\tmoh_magic = 0x%.8lx\n", hdr_ptr->moh_magic);
2148 fprintf (stderr, "\tmoh_major_version = %d\n", (int)hdr_ptr->moh_major_version);
2149 fprintf (stderr, "\tmoh_minor_version = %d\n", (int)hdr_ptr->moh_minor_version);
2150 fprintf (stderr, "\tmoh_header_version = %d\n", (int)hdr_ptr->moh_header_version);
2151 fprintf (stderr, "\tmoh_max_page_size = %d\n", (int)hdr_ptr->moh_max_page_size);
2152 fprintf (stderr, "\tmoh_byte_order = %d\n", (int)hdr_ptr->moh_byte_order);
2153 fprintf (stderr, "\tmoh_data_rep_id = %d\n", (int)hdr_ptr->moh_data_rep_id);
2154 fprintf (stderr, "\tmoh_cpu_type = %d\n", (int)hdr_ptr->moh_cpu_type);
2155 fprintf (stderr, "\tmoh_cpu_subtype = %d\n", (int)hdr_ptr->moh_cpu_subtype);
2156 fprintf (stderr, "\tmoh_vendor_type = %d\n", (int)hdr_ptr->moh_vendor_type);
2157 fprintf (stderr, "\tmoh_load_map_cmd_off = %d\n", (int)hdr_ptr->moh_load_map_cmd_off);
2158 fprintf (stderr, "\tmoh_first_cmd_off = %d\n", (int)hdr_ptr->moh_first_cmd_off);
2159 fprintf (stderr, "\tmoh_sizeofcmds = %d\n", (int)hdr_ptr->moh_sizeofcmds);
2160 fprintf (stderr, "\tmon_n_load_cmds = %d\n", (int)hdr_ptr->moh_n_load_cmds);
2161 fprintf (stderr, "\tmoh_flags = 0x%.8lx", (long)hdr_ptr->moh_flags);
2162
2163 if (hdr_ptr->moh_flags & MOH_RELOCATABLE_F)
2164 fprintf (stderr, ", relocatable");
2165
2166 if (hdr_ptr->moh_flags & MOH_LINKABLE_F)
2167 fprintf (stderr, ", linkable");
2168
2169 if (hdr_ptr->moh_flags & MOH_EXECABLE_F)
2170 fprintf (stderr, ", execable");
2171
2172 if (hdr_ptr->moh_flags & MOH_EXECUTABLE_F)
2173 fprintf (stderr, ", executable");
2174
2175 if (hdr_ptr->moh_flags & MOH_UNRESOLVED_F)
2176 fprintf (stderr, ", unresolved");
2177
2178 fprintf (stderr, "\n\n");
2179 return;
2180}
2181
2182\f
2183/* Print a short summary of a load command. */
2184
2185static void
2186print_load_command (load_hdr, offset, number)
2187 load_union_t *load_hdr;
2188 size_t offset;
2189 int number;
2190{
2191 mo_long_t type = load_hdr->hdr.ldci_cmd_type;
2192 char *type_str = (char *)0;
2193
2194 switch (type)
2195 {
2196 case LDC_UNDEFINED: type_str = "UNDEFINED"; break;
2197 case LDC_CMD_MAP: type_str = "CMD_MAP"; break;
2198 case LDC_INTERPRETER: type_str = "INTERPRETER"; break;
2199 case LDC_STRINGS: type_str = "STRINGS"; break;
2200 case LDC_REGION: type_str = "REGION"; break;
2201 case LDC_RELOC: type_str = "RELOC"; break;
2202 case LDC_PACKAGE: type_str = "PACKAGE"; break;
2203 case LDC_SYMBOLS: type_str = "SYMBOLS"; break;
2204 case LDC_ENTRY: type_str = "ENTRY"; break;
2205 case LDC_FUNC_TABLE: type_str = "FUNC_TABLE"; break;
2206 case LDC_GEN_INFO: type_str = "GEN_INFO"; break;
2207 }
2208
2209 fprintf (stderr,
2210 "cmd %2d, sz: 0x%.2lx, coff: 0x%.3lx, doff: 0x%.6lx, dlen: 0x%.6lx",
2211 number,
2212 (long) load_hdr->hdr.ldci_cmd_size,
2213 (long) offset,
2214 (long) load_hdr->hdr.ldci_section_off,
2215 (long) load_hdr->hdr.ldci_section_len);
2216
2217 if (type_str == (char *)0)
2218 fprintf (stderr, ", ty: unknown (%ld)\n", (long) type);
2219
2220 else if (type != LDC_REGION)
2221 fprintf (stderr, ", ty: %s\n", type_str);
2222
2223 else
2224 {
2225 char *region = "";
2226 switch (load_hdr->region.regc_usage_type)
2227 {
2228 case REG_TEXT_T: region = ", .text"; break;
2229 case REG_DATA_T: region = ", .data"; break;
2230 case REG_BSS_T: region = ", .bss"; break;
2231 case REG_GLUE_T: region = ", .glue"; break;
2232#if defined (REG_RDATA_T) && defined (REG_SDATA_T) && defined (REG_SBSS_T) /*mips*/
2233 case REG_RDATA_T: region = ", .rdata"; break;
2234 case REG_SDATA_T: region = ", .sdata"; break;
2235 case REG_SBSS_T: region = ", .sbss"; break;
2236#endif
2237 }
2238
2239 fprintf (stderr, ", ty: %s, vaddr: 0x%.8lx, vlen: 0x%.6lx%s\n",
2240 type_str,
2241 (long) load_hdr->region.regc_vm_addr,
2242 (long) load_hdr->region.regc_vm_size,
2243 region);
2244 }
2245
2246 return;
2247}
2248
2249\f
2250/* Fatal error when {en,de}code_mach_o_header fails. */
2251
2252static void
2253bad_header (status)
2254 int status;
2255{
2256 char *msg = (char *)0;
2257
2258 switch (status)
2259 {
2260 case MO_ERROR_BAD_MAGIC: msg = "bad magic number"; break;
2261 case MO_ERROR_BAD_HDR_VERS: msg = "bad header version"; break;
2262 case MO_ERROR_BAD_RAW_HDR_VERS: msg = "bad raw header version"; break;
2263 case MO_ERROR_BUF2SML: msg = "raw header buffer too small"; break;
2264 case MO_ERROR_OLD_RAW_HDR_FILE: msg = "old raw header file"; break;
2265 case MO_ERROR_UNSUPPORTED_VERS: msg = "unsupported version"; break;
2266 }
2267
2268 if (msg == (char *)0)
2269 fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
2270 else
2271 fatal ("%s", msg);
2272}
2273
2274\f
2275/* Read a file into a memory buffer. */
2276
2277static struct file_info *
2278read_file (name, fd, rw)
2279 char *name; /* filename */
2280 int fd; /* file descriptor */
2281 int rw; /* read/write */
2282{
2283 struct stat stat_pkt;
2284 struct file_info *p = (struct file_info *) xcalloc (sizeof (struct file_info), 1);
2285#ifdef USE_MMAP
2286 static int page_size;
2287#endif
2288
2289 if (fstat (fd, &stat_pkt) < 0)
2290 fatal_perror ("fstat %s", name);
2291
2292 p->name = name;
2293 p->size = stat_pkt.st_size;
2294 p->rounded_size = stat_pkt.st_size;
2295 p->fd = fd;
2296 p->rw = rw;
2297
2298#ifdef USE_MMAP
2299 if (debug)
2300 fprintf (stderr, "mmap %s, %s\n", name, (rw) ? "read/write" : "read-only");
2301
2302 if (page_size == 0)
2303 page_size = sysconf (_SC_PAGE_SIZE);
2304
2305 p->rounded_size = ((p->size + page_size - 1) / page_size) * page_size;
2306 p->start = mmap ((caddr_t)0,
2307 (rw) ? p->rounded_size : p->size,
2308 (rw) ? (PROT_READ | PROT_WRITE) : PROT_READ,
2309 MAP_FILE | MAP_VARIABLE | MAP_SHARED,
2310 fd,
2311 0L);
2312
2313 if (p->start != (char *)0 && p->start != (char *)-1)
2314 p->use_mmap = 1;
2315
2316 else
2317#endif /* USE_MMAP */
2318 {
2319 long len;
2320
2321 if (debug)
2322 fprintf (stderr, "read %s\n", name);
2323
2324 p->use_mmap = 0;
2325 p->start = xmalloc (p->size);
2326 if (lseek (fd, 0L, SEEK_SET) < 0)
2327 fatal_perror ("lseek to 0 on %s", name);
2328
2329 len = read (fd, p->start, p->size);
2330 if (len < 0)
2331 fatal_perror ("read %s", name);
2332
2333 if (len != p->size)
2334 fatal ("read %ld bytes, expected %ld, from %s", len, p->size, name);
2335 }
2336
2337 return p;
2338}
4e81a331
RS
2339\f
2340/* Do anything necessary to write a file back from memory. */
2341
2342static void
2343end_file (ptr)
2344 struct file_info *ptr; /* file information block */
2345{
2346#ifdef USE_MMAP
2347 if (ptr->use_mmap)
2348 {
2349 if (ptr->rw)
2350 {
2351 if (debug)
2352 fprintf (stderr, "msync %s\n", ptr->name);
2353
2354 if (msync (ptr->start, ptr->rounded_size, MS_ASYNC))
2355 fatal_perror ("msync %s", ptr->name);
2356 }
2357
2358 if (debug)
2359 fprintf (stderr, "munmap %s\n", ptr->name);
2360
2361 if (munmap (ptr->start, ptr->size))
2362 fatal_perror ("munmap %s", ptr->name);
2363 }
2364 else
2365#endif /* USE_MMAP */
2366 {
2367 if (ptr->rw)
2368 {
2369 long len;
2370
2371 if (debug)
2372 fprintf (stderr, "write %s\n", ptr->name);
2373
2374 if (lseek (ptr->fd, 0L, SEEK_SET) < 0)
2375 fatal_perror ("lseek to 0 on %s", ptr->name);
2376
2377 len = write (ptr->fd, ptr->start, ptr->size);
2378 if (len < 0)
2379 fatal_perror ("read %s", ptr->name);
2380
2381 if (len != ptr->size)
2382 fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name);
2383 }
2384
2385 free ((generic *)ptr->start);
2386 }
2387
2388 free ((generic *)ptr);
2389}
2390
2391#endif /* OBJECT_FORMAT_ROSE */
This page took 0.442772 seconds and 5 git commands to generate.