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