]> gcc.gnu.org Git - gcc.git/blame - gcc/collect2.c
Fix size_t, ptrdiff_t and wchar_t like fixincludes does.
[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] == '-')
1059 switch (arg[1])
1060 {
1061 case 'd':
1062 if (!strcmp (arg, "-debug"))
1063 {
1064 debug = 1;
1065 vflag = 1;
1066 ld1--;
1067 ld2--;
1068 }
1069 break;
1070
4e81a331 1071 case 'o':
0cdd3ddd 1072 output_file = (arg[2] == '\0') ? argv[1] : &arg[2];
4e81a331
RS
1073 break;
1074
1075 case 'r':
1076 if (arg[2] == '\0')
1077 rflag = 1;
1078 break;
1079
a87104d9
MM
1080 case 's':
1081 if (arg[2] == '\0')
1082 {
1083 /* We must strip after the nm run, otherwise C++ linking
1084 won't work. Thus we strip in the second ld run, or
1085 else with strip if there is no second ld run. */
1086 strip_flag = 1;
1087 ld1--;
1088 }
1089 break;
1090
4e81a331
RS
1091 case 'v':
1092 if (arg[2] == '\0')
1093 vflag = 1;
1094 break;
1095 }
1096
1097 else if (first_file
3f7cc57a 1098 && (p = rindex (arg, '.')) != (char *)0
4e81a331
RS
1099 && strcmp (p, ".o") == 0)
1100 {
1101 first_file = 0;
1102 *ld2++ = o_file;
1103 }
1104 }
1105
ed5b9462
RS
1106 /* Get any options that the upper GCC wants to pass to the sub-GCC. */
1107 p = (char *) getenv ("COLLECT_GCC_OPTIONS");
1108 if (p)
1109 while (*p)
1110 {
1111 char *q = p;
1112 while (*q && *q != ' ') q++;
1113 if (*p == '-' && (p[1] == 'm' || p[1] == 'f'))
1114 *c_ptr++ = savestring (p, q - p);
1115
1116 if (*q) q++;
1117 p = q;
1118 }
1119
4e81a331
RS
1120 *c_ptr++ = c_file;
1121 *c_ptr = *ld1 = *ld2 = (char *)0;
1122
1123 if (vflag)
1124 {
ed5b9462 1125 fprintf (stderr, "collect2 version %s", version_string);
4e81a331
RS
1126#ifdef TARGET_VERSION
1127 TARGET_VERSION;
1128#endif
1129 fprintf (stderr, "\n");
1130 }
1131
1132 if (debug)
1133 {
ed5b9462 1134 char *ptr;
a1549b15
RS
1135 fprintf (stderr, "ld_file_name = %s\n",
1136 (ld_file_name ? ld_file_name : "not found"));
1137 fprintf (stderr, "c_file_name = %s\n",
1138 (c_file_name ? c_file_name : "not found"));
1139 fprintf (stderr, "nm_file_name = %s\n",
1140 (nm_file_name ? nm_file_name : "not found"));
1141 fprintf (stderr, "strip_file_name = %s\n",
1142 (strip_file_name ? strip_file_name : "not found"));
1143 fprintf (stderr, "c_file = %s\n",
1144 (c_file ? c_file : "not found"));
1145 fprintf (stderr, "o_file = %s\n",
1146 (o_file ? o_file : "not found"));
ed5b9462 1147
7223feb0
DE
1148 ptr = getenv ("COLLECT_NAMES");
1149 if (ptr)
1150 fprintf (stderr, "COLLECT_NAMES = %s\n", ptr);
1151
ed5b9462
RS
1152 ptr = getenv ("COLLECT_GCC_OPTIONS");
1153 if (ptr)
1154 fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
1155
1156 ptr = getenv ("COLLECT_GCC");
1157 if (ptr)
1158 fprintf (stderr, "COLLECT_GCC = %s\n", ptr);
1159
1160 ptr = getenv ("COMPILER_PATH");
1161 if (ptr)
1162 fprintf (stderr, "COMPILER_PATH = %s\n", ptr);
1163
1164 ptr = getenv ("LIBRARY_PATH");
1165 if (ptr)
1166 fprintf (stderr, "LIBRARY_PATH = %s\n", ptr);
1167
1168 fprintf (stderr, "\n");
4e81a331
RS
1169 }
1170
1171 /* Load the program, searching all libraries.
1172 Examine the namelist with nm and search it for static constructors
1173 and destructors to call.
1174 Write the constructor and destructor tables to a .s file and reload. */
1175
aee3a549 1176 fork_execute ("ld", ld1_argv);
4e81a331
RS
1177
1178 /* If -r, don't build the constructor or destructor list, just return now. */
1179 if (rflag)
1180 return 0;
1181
0cdd3ddd 1182 scan_prog_file (output_file, PASS_FIRST);
4e81a331
RS
1183
1184 if (debug)
1185 {
1186 fprintf (stderr, "%d constructor(s) found\n", constructors.number);
1187 fprintf (stderr, "%d destructor(s) found\n", destructors.number);
1188 }
1189
1190 if (constructors.number == 0 && destructors.number == 0)
a87104d9
MM
1191 {
1192 /* Strip now if it was requested on the command line. */
1193 if (strip_flag)
1194 {
1195 char **strip_argv = (char **) xcalloc (sizeof (char *), 3);
aee3a549 1196 strip_argv[0] = strip_file_name;
0cdd3ddd 1197 strip_argv[1] = output_file;
a87104d9 1198 strip_argv[2] = (char *) 0;
aee3a549 1199 fork_execute ("strip", strip_argv);
a87104d9
MM
1200 }
1201 return 0;
1202 }
4e81a331
RS
1203
1204 outf = fopen (c_file, "w");
1205 if (outf == (FILE *)0)
1fab8e81 1206 fatal_perror ("%s", c_file);
4e81a331
RS
1207
1208 write_c_file (outf, c_file);
1209
1210 if (fclose (outf))
1fab8e81 1211 fatal_perror ("closing %s", c_file);
4e81a331
RS
1212
1213 if (debug)
1214 {
0cdd3ddd
RS
1215 fprintf (stderr, "\n========== output_file = %s, c_file = %s\n",
1216 output_file, c_file);
4e81a331
RS
1217 write_c_file (stderr, "stderr");
1218 fprintf (stderr, "========== end of c_file\n\n");
1219 }
1220
1221 /* Assemble the constructor and destructor tables.
1222 Link the tables in with the rest of the program. */
1223
aee3a549
RK
1224 fork_execute ("gcc", c_argv);
1225 fork_execute ("ld", ld2_argv);
4e81a331
RS
1226
1227 /* Let scan_prog_file do any final mods (OSF/rose needs this for
1228 constructors/destructors in shared libraries. */
0cdd3ddd 1229 scan_prog_file (output_file, PASS_SECOND);
4e81a331
RS
1230
1231 maybe_unlink (c_file);
1232 maybe_unlink (o_file);
1233 return 0;
1234}
1235
1236\f
1237/* Wait for a process to finish, and exit if a non-zero status is found. */
1238
1239static void
1240do_wait (prog)
1241 char *prog;
1242{
1243 int status;
1244
1245 wait (&status);
1246 if (status)
1247 {
ed5b9462 1248 int sig = status & 0x7F;
4e81a331
RS
1249 int ret;
1250
1251 if (sig != -1 && sig != 0)
1252 {
ed5b9462
RS
1253#ifdef NO_SYS_SIGLIST
1254 error ("%s terminated with signal %d %s",
1255 prog,
1256 sig,
1257 (status & 0200) ? ", core dumped" : "");
1258#else
4e81a331
RS
1259 error ("%s terminated with signal %d [%s]%s",
1260 prog,
1261 sig,
1262 sys_siglist[sig],
1263 (status & 0200) ? ", core dumped" : "");
ed5b9462 1264#endif
4e81a331
RS
1265
1266 my_exit (127);
1267 }
1268
ed5b9462 1269 ret = ((status & 0xFF00) >> 8);
4e81a331
RS
1270 if (ret != -1 && ret != 0)
1271 {
1272 error ("%s returned %d exit status", prog, ret);
1273 my_exit (ret);
1274 }
1275 }
1276}
1277
1278\f
1279/* Fork and execute a program, and wait for the reply. */
1280
1281static void
1282fork_execute (prog, argv)
1283 char *prog;
1284 char **argv;
1285{
1286 int pid;
4e81a331
RS
1287
1288 if (vflag || debug)
1289 {
1290 char **p_argv;
1291 char *str;
1292
aee3a549
RK
1293 if (argv[0])
1294 fprintf (stderr, "%s", argv[0]);
bb59f9a6 1295 else
aee3a549 1296 fprintf (stderr, "[cannot find %s]", prog);
bb59f9a6 1297
4e81a331
RS
1298 for (p_argv = &argv[1]; (str = *p_argv) != (char *)0; p_argv++)
1299 fprintf (stderr, " %s", str);
1300
1301 fprintf (stderr, "\n");
1302 }
1303
1304 fflush (stdout);
1305 fflush (stderr);
1306
bb59f9a6
RS
1307 /* If we can't find a program we need, complain error. Do this here
1308 since we might not end up needing something that we couldn't find. */
1309
aee3a549
RK
1310 if (argv[0] == 0)
1311 fatal ("cannot find `%s'", prog);
bb59f9a6 1312
4e81a331
RS
1313 pid = vfork ();
1314 if (pid == -1)
cf0c751a
JW
1315 {
1316#ifdef vfork
1317 fatal_perror ("fork");
1318#else
1319 fatal_perror ("vfork");
1320#endif
1321 }
4e81a331
RS
1322
1323 if (pid == 0) /* child context */
1324 {
aee3a549 1325 execvp (argv[0], argv);
1fab8e81 1326 fatal_perror ("executing %s", prog);
4e81a331
RS
1327 }
1328
4e81a331 1329 do_wait (prog);
4e81a331
RS
1330}
1331
1332\f
1333/* Unlink a file unless we are debugging. */
1334
1335static void
1336maybe_unlink (file)
1337 char *file;
1338{
1339 if (!debug)
1340 unlink (file);
1341 else
1342 fprintf (stderr, "[Leaving %s]\n", file);
1343}
1344
1345\f
1346/* Add a name to a linked list. */
1347
1348static void
1349add_to_list (head_ptr, name)
1350 struct head *head_ptr;
1351 char *name;
1352{
1353 struct id *newid = (struct id *) xcalloc (sizeof (*newid) + strlen (name), 1);
1354 static long sequence_number = 0;
1355 newid->sequence = ++sequence_number;
1356 strcpy (newid->name, name);
1357
1358 if (head_ptr->first)
1359 head_ptr->last->next = newid;
1360 else
1361 head_ptr->first = newid;
1362
1363 head_ptr->last = newid;
1364 head_ptr->number++;
1365}
1366
1367/* Write: `prefix', the names on list LIST, `suffix'. */
1368
1369static void
1370write_list (stream, prefix, list)
1371 FILE *stream;
1372 char *prefix;
1373 struct id *list;
1374{
1375 while (list)
1376 {
1377 fprintf (stream, "%sx%d,\n", prefix, list->sequence);
1378 list = list->next;
1379 }
1380}
1381
1382static void
1383write_list_with_asm (stream, prefix, list)
1384 FILE *stream;
1385 char *prefix;
1386 struct id *list;
1387{
1388 while (list)
1389 {
c7af43d8 1390 fprintf (stream, "%sx%d __asm__ (\"%s\");\n",
4e81a331
RS
1391 prefix, list->sequence, list->name);
1392 list = list->next;
1393 }
1394}
1395
1396/* Write the constructor/destructor tables. */
1397
1398static void
1399write_c_file (stream, name)
1400 FILE *stream;
1401 char *name;
1402{
1403 /* Write the tables as C code */
1404
1405 fprintf (stream, "typedef void entry_pt();\n\n");
1406
17704846 1407 write_list_with_asm (stream, "extern entry_pt ", constructors.first);
4e81a331
RS
1408
1409 fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
1410 fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number);
ed5b9462 1411 write_list (stream, "\t", constructors.first);
4e81a331
RS
1412 fprintf (stream, "\t0\n};\n\n");
1413
17704846 1414 write_list_with_asm (stream, "extern entry_pt ", destructors.first);
4e81a331
RS
1415
1416 fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
1417 fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number);
ed5b9462 1418 write_list (stream, "\t", destructors.first);
4e81a331
RS
1419 fprintf (stream, "\t0\n};\n\n");
1420
d6cf3187
RS
1421 fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
1422 fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);
4e81a331
RS
1423}
1424
1425\f
ed5b9462 1426#ifdef OBJECT_FORMAT_NONE
4e81a331 1427
ed5b9462
RS
1428/* Generic version to scan the name list of the loaded program for
1429 the symbols g++ uses for static constructors and destructors.
4e81a331
RS
1430
1431 The constructor table begins at __CTOR_LIST__ and contains a count
1432 of the number of pointers (or -1 if the constructors are built in a
1433 separate section by the linker), followed by the pointers to the
1434 constructor functions, terminated with a null pointer. The
1435 destructor table has the same format, and begins at __DTOR_LIST__. */
1436
1437static void
1438scan_prog_file (prog_name, which_pass)
1439 char *prog_name;
1440 enum pass which_pass;
1441{
ed5b9462
RS
1442 void (*int_handler) ();
1443 void (*quit_handler) ();
4e81a331
RS
1444 char *nm_argv[4];
1445 int pid;
1446 int argc = 0;
1447 int pipe_fd[2];
1448 char *p, buf[1024];
1449 FILE *inf;
1450
1451 if (which_pass != PASS_FIRST)
1452 return;
1453
bb59f9a6
RS
1454 /* If we don't have an `nm', complain. */
1455 if (nm_file_name == 0)
1456 fatal ("cannot find `nm'");
1457
ed5b9462 1458 nm_argv[argc++] = "nm";
4e81a331 1459 if (NM_FLAGS[0] != '\0')
ed5b9462 1460 nm_argv[argc++] = NM_FLAGS;
4e81a331 1461
ed5b9462
RS
1462 nm_argv[argc++] = prog_name;
1463 nm_argv[argc++] = (char *)0;
4e81a331
RS
1464
1465 if (pipe (pipe_fd) < 0)
1466 fatal_perror ("pipe");
1467
1468 inf = fdopen (pipe_fd[0], "r");
1469 if (inf == (FILE *)0)
1470 fatal_perror ("fdopen");
1471
1472 /* Trace if needed. */
1473 if (vflag)
1474 {
1475 char **p_argv;
1476 char *str;
1477
1478 fprintf (stderr, "%s", nm_file_name);
1479 for (p_argv = &nm_argv[1]; (str = *p_argv) != (char *)0; p_argv++)
1480 fprintf (stderr, " %s", str);
1481
1482 fprintf (stderr, "\n");
1483 }
1484
1485 fflush (stdout);
1486 fflush (stderr);
1487
1488 /* Spawn child nm on pipe */
1489 pid = vfork ();
1490 if (pid == -1)
cf0c751a
JW
1491 {
1492#ifdef vfork
1493 fatal_perror ("fork");
1494#else
1495 fatal_perror ("vfork");
1496#endif
1497 }
4e81a331
RS
1498
1499 if (pid == 0) /* child context */
1500 {
1501 /* setup stdout */
1502 if (dup2 (pipe_fd[1], 1) < 0)
1fab8e81 1503 fatal_perror ("dup2 (%d, 1)", pipe_fd[1]);
4e81a331
RS
1504
1505 if (close (pipe_fd[0]) < 0)
1fab8e81 1506 fatal_perror ("close (%d)", pipe_fd[0]);
4e81a331
RS
1507
1508 if (close (pipe_fd[1]) < 0)
1fab8e81 1509 fatal_perror ("close (%d)", pipe_fd[1]);
4e81a331
RS
1510
1511 execv (nm_file_name, nm_argv);
1fab8e81 1512 fatal_perror ("executing %s", nm_file_name);
4e81a331
RS
1513 }
1514
1515 /* Parent context from here on. */
ed5b9462 1516 int_handler = (void (*) ())signal (SIGINT, SIG_IGN);
8ab861c7 1517#ifdef SIGQUIT
ed5b9462 1518 quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN);
8ab861c7 1519#endif
4e81a331
RS
1520
1521 if (close (pipe_fd[1]) < 0)
1fab8e81 1522 fatal_perror ("close (%d)", pipe_fd[1]);
4e81a331
RS
1523
1524 if (debug)
1525 fprintf (stderr, "\nnm output with constructors/destructors.\n");
1526
1527 /* Read each line of nm output. */
1528 while (fgets (buf, sizeof buf, inf) != (char *)0)
1529 {
1530 int ch, ch2;
ed5b9462 1531 char *name, *end;
4e81a331
RS
1532
1533 /* If it contains a constructor or destructor name, add the name
1534 to the appropriate list. */
1535
1536 for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
1537 ;
1538
1539 if (ch == '\0' || ch == '\n')
1540 continue;
ed5b9462
RS
1541
1542 name = p;
1543 /* Find the end of the symbol name.
1544 Don't include `|', because Encore nm can tack that on the end. */
1545 for (end = p; (ch2 = *end) != '\0' && !isspace (ch2) && ch2 != '|';
1546 end++)
1547 continue;
4e81a331
RS
1548
1549 *end = '\0';
ed5b9462 1550 switch (is_ctor_dtor (name))
4e81a331 1551 {
ed5b9462
RS
1552 case 1:
1553 add_to_list (&constructors, name);
1554 break;
4e81a331 1555
ed5b9462
RS
1556 case 2:
1557 add_to_list (&destructors, name);
1558 break;
4e81a331 1559
ed5b9462
RS
1560 default: /* not a constructor or destructor */
1561 continue;
4e81a331
RS
1562 }
1563
4e81a331
RS
1564 if (debug)
1565 fprintf (stderr, "\t%s\n", buf);
1566 }
1567
1568 if (debug)
1569 fprintf (stderr, "\n");
1570
1571 if (fclose (inf) != 0)
1572 fatal_perror ("fclose of pipe");
1573
1574 do_wait (nm_file_name);
1575
1576 signal (SIGINT, int_handler);
8ab861c7 1577#ifdef SIGQUIT
4e81a331 1578 signal (SIGQUIT, quit_handler);
8ab861c7 1579#endif
4e81a331
RS
1580}
1581
ed5b9462
RS
1582#endif /* OBJECT_FORMAT_NONE */
1583
1584\f
1585/*
1586 * COFF specific stuff.
1587 */
1588
1589#ifdef OBJECT_FORMAT_COFF
1590
1591#if defined(EXTENDED_COFF)
17704846
JW
1592# define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
1593# define GCC_SYMENT SYMR
1594# define GCC_OK_SYMBOL(X) ((X).st == stProc && (X).sc == scText)
1595# define GCC_SYMINC(X) (1)
1596# define GCC_SYMZERO(X) (SYMHEADER(X).isymMax)
1597# define GCC_CHECK_HDR(X) (PSYMTAB(X) != 0)
ed5b9462 1598#else
17704846
JW
1599# define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms)
1600# define GCC_SYMENT SYMENT
ed5b9462
RS
1601# define GCC_OK_SYMBOL(X) \
1602 (((X).n_sclass == C_EXT) && \
1603 (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) || \
1604 ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))
17704846
JW
1605# define GCC_SYMINC(X) ((X).n_numaux+1)
1606# define GCC_SYMZERO(X) 0
1607# define GCC_CHECK_HDR(X) (1)
ed5b9462
RS
1608#endif
1609
1610extern char *ldgetname ();
1611
1612/* COFF version to scan the name list of the loaded program for
1613 the symbols g++ uses for static constructors and destructors.
1614
1615 The constructor table begins at __CTOR_LIST__ and contains a count
1616 of the number of pointers (or -1 if the constructors are built in a
1617 separate section by the linker), followed by the pointers to the
1618 constructor functions, terminated with a null pointer. The
1619 destructor table has the same format, and begins at __DTOR_LIST__. */
1620
1621static void
1622scan_prog_file (prog_name, which_pass)
1623 char *prog_name;
1624 enum pass which_pass;
1625{
f3c3d3df 1626 LDFILE *ldptr = NULL;
ed5b9462
RS
1627 int sym_index, sym_count;
1628
1629 if (which_pass != PASS_FIRST)
1630 return;
1631
1632 if ((ldptr = ldopen (prog_name, ldptr)) == NULL)
1633 fatal ("%s: can't open as COFF file", prog_name);
1634
e99467d2 1635 if (!MY_ISCOFF (HEADER (ldptr).f_magic))
ed5b9462
RS
1636 fatal ("%s: not a COFF file", prog_name);
1637
17704846 1638 if (GCC_CHECK_HDR (ldptr))
ed5b9462 1639 {
17704846
JW
1640 sym_count = GCC_SYMBOLS (ldptr);
1641 sym_index = GCC_SYMZERO (ldptr);
1642 while (sym_index < sym_count)
1643 {
1644 GCC_SYMENT symbol;
ed5b9462 1645
17704846
JW
1646 if (ldtbread (ldptr, sym_index, &symbol) <= 0)
1647 break;
1648 sym_index += GCC_SYMINC (symbol);
ed5b9462 1649
17704846
JW
1650 if (GCC_OK_SYMBOL (symbol))
1651 {
1652 char *name;
ed5b9462 1653
17704846
JW
1654 if ((name = ldgetname (ldptr, &symbol)) == NULL)
1655 continue; /* should never happen */
ed5b9462
RS
1656
1657#ifdef _AIX
17704846
JW
1658 /* All AIX function names begin with a dot. */
1659 if (*name++ != '.')
1660 continue;
ed5b9462
RS
1661#endif
1662
17704846
JW
1663 switch (is_ctor_dtor (name))
1664 {
1665 case 1:
1666 add_to_list (&constructors, name);
1667 break;
ed5b9462 1668
17704846
JW
1669 case 2:
1670 add_to_list (&destructors, name);
1671 break;
ed5b9462 1672
17704846
JW
1673 default: /* not a constructor or destructor */
1674 continue;
1675 }
ed5b9462
RS
1676
1677#if !defined(EXTENDED_COFF)
17704846
JW
1678 if (debug)
1679 fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
1680 symbol.n_scnum, symbol.n_sclass,
1681 (symbol.n_type ? "0" : ""), symbol.n_type,
1682 name);
ed5b9462 1683#else
17704846
JW
1684 if (debug)
1685 fprintf (stderr, "\tiss = %5d, value = %5d, index = %5d, name = %s\n",
1686 symbol.iss, symbol.value, symbol.index, name);
ed5b9462 1687#endif
17704846 1688 }
ed5b9462
RS
1689 }
1690 }
1691
1692 (void) ldclose(ldptr);
1693}
1694
1695#endif /* OBJECT_FORMAT_COFF */
4e81a331
RS
1696
1697\f
1698/*
1699 * OSF/rose specific stuff.
1700 */
1701
1702#ifdef OBJECT_FORMAT_ROSE
1703
1704/* Union of the various load commands */
1705
1706typedef union load_union
1707{
1708 ldc_header_t hdr; /* common header */
1709 load_cmd_map_command_t map; /* map indexing other load cmds */
ed5b9462 1710 interpreter_command_t iprtr; /* interpreter pathname */
4e81a331
RS
1711 strings_command_t str; /* load commands strings section */
1712 region_command_t region; /* region load command */
1713 reloc_command_t reloc; /* relocation section */
1714 package_command_t pkg; /* package load command */
1715 symbols_command_t sym; /* symbol sections */
1716 entry_command_t ent; /* program start section */
1717 gen_info_command_t info; /* object information */
1718 func_table_command_t func; /* function constructors/destructors */
1719} load_union_t;
1720
1721/* Structure to point to load command and data section in memory. */
1722
1723typedef struct load_all
1724{
1725 load_union_t *load; /* load command */
1726 char *section; /* pointer to section */
1727} load_all_t;
1728
1729/* Structure to contain information about a file mapped into memory. */
1730
1731struct file_info
1732{
1733 char *start; /* start of map */
1734 char *name; /* filename */
1735 long size; /* size of the file */
1736 long rounded_size; /* size rounded to page boundary */
1737 int fd; /* file descriptor */
1738 int rw; /* != 0 if opened read/write */
1739 int use_mmap; /* != 0 if mmap'ed */
1740};
1741
ed5b9462 1742extern int decode_mach_o_hdr ();
ed5b9462 1743extern int encode_mach_o_hdr ();
4e81a331 1744
4d1a011f
RK
1745static void add_func_table PROTO((mo_header_t *, load_all_t *,
1746 symbol_info_t *, int));
1747static void print_header PROTO((mo_header_t *));
1748static void print_load_command PROTO((load_union_t*, size_t, int));
1749static void bad_header PROTO((int));
357a98f1 1750static struct file_info *read_file PROTO((char *, int, int));
4d1a011f 1751static void end_file PROTO((struct file_info *));
4e81a331
RS
1752\f
1753/* OSF/rose specific version to scan the name list of the loaded
1754 program for the symbols g++ uses for static constructors and
1755 destructors.
1756
1757 The constructor table begins at __CTOR_LIST__ and contains a count
1758 of the number of pointers (or -1 if the constructors are built in a
1759 separate section by the linker), followed by the pointers to the
1760 constructor functions, terminated with a null pointer. The
1761 destructor table has the same format, and begins at __DTOR_LIST__. */
1762
1763static void
1764scan_prog_file (prog_name, which_pass)
1765 char *prog_name;
1766 enum pass which_pass;
1767{
1768 char *obj;
1769 mo_header_t hdr;
1770 load_all_t *load_array;
1771 load_all_t *load_end;
1772 load_all_t *load_cmd;
1773 int symbol_load_cmds;
1774 off_t offset;
1775 int i;
1776 int num_syms;
1777 int status;
1778 char *str_sect;
1779 struct file_info *obj_file;
1780 int prog_fd;
1781 mo_lcid_t cmd_strings = -1;
1782 symbol_info_t *main_sym = 0;
1783 int rw = (which_pass != PASS_FIRST);
1784
1785 prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY);
1786 if (prog_fd < 0)
1fab8e81 1787 fatal_perror ("can't read %s", prog_name);
4e81a331
RS
1788
1789 obj_file = read_file (prog_name, prog_fd, rw);
1790 obj = obj_file->start;
1791
1792 status = decode_mach_o_hdr (obj, MO_SIZEOF_RAW_HDR, MOH_HEADER_VERSION, &hdr);
1793 if (status != MO_HDR_CONV_SUCCESS)
1794 bad_header (status);
1795
1796
1797 /* Do some basic sanity checks. Note we explicitly use the big endian magic number,
1798 since the hardware will automatically swap bytes for us on loading little endian
1799 integers. */
1800
1801#ifndef CROSS_COMPILE
1802 if (hdr.moh_magic != MOH_MAGIC_MSB
1803 || hdr.moh_header_version != MOH_HEADER_VERSION
1804 || hdr.moh_byte_order != OUR_BYTE_ORDER
1805 || hdr.moh_data_rep_id != OUR_DATA_REP_ID
1806 || hdr.moh_cpu_type != OUR_CPU_TYPE
1807 || hdr.moh_cpu_subtype != OUR_CPU_SUBTYPE
1808 || hdr.moh_vendor_type != OUR_VENDOR_TYPE)
1809 {
1fab8e81 1810 fatal ("incompatibilities between object file & expected values");
4e81a331
RS
1811 }
1812#endif
1813
1814 if (debug)
1815 print_header (&hdr);
1816
1817 offset = hdr.moh_first_cmd_off;
1818 load_end = load_array
1819 = (load_all_t *) xcalloc (sizeof (load_all_t), hdr.moh_n_load_cmds + 2);
1820
1821 /* Build array of load commands, calculating the offsets */
1822 for (i = 0; i < hdr.moh_n_load_cmds; i++)
1823 {
1824 load_union_t *load_hdr; /* load command header */
1825
1826 load_cmd = load_end++;
1827 load_hdr = (load_union_t *) (obj + offset);
1828
f72aed24 1829 /* If modifying the program file, copy the header. */
4e81a331
RS
1830 if (rw)
1831 {
1832 load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size);
4c9a05bc 1833 bcopy ((char *)load_hdr, (char *)ptr, load_hdr->hdr.ldci_cmd_size);
4e81a331
RS
1834 load_hdr = ptr;
1835
1836 /* null out old command map, because we will rewrite at the end. */
1837 if (ptr->hdr.ldci_cmd_type == LDC_CMD_MAP)
1838 {
1839 cmd_strings = ptr->map.lcm_ld_cmd_strings;
1840 ptr->hdr.ldci_cmd_type = LDC_UNDEFINED;
1841 }
1842 }
1843
1844 load_cmd->load = load_hdr;
1845 if (load_hdr->hdr.ldci_section_off > 0)
1846 load_cmd->section = obj + load_hdr->hdr.ldci_section_off;
1847
1848 if (debug)
1849 print_load_command (load_hdr, offset, i);
1850
1851 offset += load_hdr->hdr.ldci_cmd_size;
1852 }
1853
1854 /* If the last command is the load command map and is not undefined,
1855 decrement the count of load commands. */
1856 if (rw && load_end[-1].load->hdr.ldci_cmd_type == LDC_UNDEFINED)
1857 {
1858 load_end--;
1859 hdr.moh_n_load_cmds--;
1860 }
1861
1862 /* Go through and process each symbol table section. */
1863 symbol_load_cmds = 0;
1864 for (load_cmd = load_array; load_cmd < load_end; load_cmd++)
1865 {
1866 load_union_t *load_hdr = load_cmd->load;
1867
1868 if (load_hdr->hdr.ldci_cmd_type == LDC_SYMBOLS)
1869 {
1870 symbol_load_cmds++;
1871
1872 if (debug)
1873 {
ed5b9462 1874 char *kind = "unknown";
4e81a331
RS
1875
1876 switch (load_hdr->sym.symc_kind)
1877 {
1878 case SYMC_IMPORTS: kind = "imports"; break;
1879 case SYMC_DEFINED_SYMBOLS: kind = "defined"; break;
1880 case SYMC_STABS: kind = "stabs"; break;
1881 }
1882
1883 fprintf (stderr, "\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
1884 symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
1885 }
1886
1887 if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
1888 continue;
1889
ed5b9462 1890 str_sect = load_array[load_hdr->sym.symc_strings_section].section;
4e81a331
RS
1891 if (str_sect == (char *)0)
1892 fatal ("string section missing");
1893
1894 if (load_cmd->section == (char *)0)
1895 fatal ("section pointer missing");
1896
1897 num_syms = load_hdr->sym.symc_nentries;
1898 for (i = 0; i < num_syms; i++)
1899 {
1900 symbol_info_t *sym = ((symbol_info_t *) load_cmd->section) + i;
1901 char *name = sym->si_name.symbol_name + str_sect;
4e81a331
RS
1902
1903 if (name[0] != '_')
1904 continue;
1905
4e81a331
RS
1906 if (rw)
1907 {
d6cf3187
RS
1908 char *n = name + strlen (name) - strlen (NAME__MAIN);
1909
1910 if ((n - name) < 0 || strcmp (n, NAME__MAIN))
4e81a331 1911 continue;
d6cf3187
RS
1912 while (n != name)
1913 if (*--n != '_')
1914 continue;
4e81a331
RS
1915
1916 main_sym = sym;
1917 }
ed5b9462 1918 else
4e81a331 1919 {
ed5b9462
RS
1920 switch (is_ctor_dtor (name))
1921 {
1922 case 1:
1923 add_to_list (&constructors, name);
1924 break;
1925
1926 case 2:
1927 add_to_list (&destructors, name);
1928 break;
1929
1930 default: /* not a constructor or destructor */
1931 continue;
1932 }
4e81a331
RS
1933 }
1934
4e81a331
RS
1935 if (debug)
1936 fprintf (stderr, "\ttype = 0x%.4x, sc = 0x%.2x, flags = 0x%.8x, name = %.30s\n",
1937 sym->si_type, sym->si_sc_type, sym->si_flags, name);
1938 }
1939 }
1940 }
1941
1942 if (symbol_load_cmds == 0)
1fab8e81 1943 fatal ("no symbol table found");
4e81a331
RS
1944
1945 /* Update the program file now, rewrite header and load commands. At present,
1946 we assume that there is enough space after the last load command to insert
1947 one more. Since the first section written out is page aligned, and the
1948 number of load commands is small, this is ok for the present. */
1949
1950 if (rw)
1951 {
1952 load_union_t *load_map;
1953 size_t size;
1954
1955 if (cmd_strings == -1)
1fab8e81
RS
1956 fatal ("no cmd_strings found");
1957
1958 /* Add __main to initializer list.
1959 If we are building a program instead of a shared library, don't
1960 do anything, since in the current version, you cannot do mallocs
1961 and such in the constructors. */
4e81a331 1962
1fab8e81
RS
1963 if (main_sym != (symbol_info_t *)0
1964 && ((hdr.moh_flags & MOH_EXECABLE_F) == 0))
4e81a331
RS
1965 add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION);
1966
1967 if (debug)
1968 fprintf (stderr, "\nUpdating header and load commands.\n\n");
1969
1970 hdr.moh_n_load_cmds++;
1971 size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1));
1972
1973 /* Create new load command map. */
1974 if (debug)
1975 fprintf (stderr, "load command map, %d cmds, new size %ld.\n",
1976 (int)hdr.moh_n_load_cmds, (long)size);
1977
1978 load_map = (load_union_t *) xcalloc (1, size);
1979 load_map->map.ldc_header.ldci_cmd_type = LDC_CMD_MAP;
1980 load_map->map.ldc_header.ldci_cmd_size = size;
1981 load_map->map.lcm_ld_cmd_strings = cmd_strings;
1982 load_map->map.lcm_nentries = hdr.moh_n_load_cmds;
1983 load_array[hdr.moh_n_load_cmds-1].load = load_map;
1984
1985 offset = hdr.moh_first_cmd_off;
1986 for (i = 0; i < hdr.moh_n_load_cmds; i++)
1987 {
1988 load_map->map.lcm_map[i] = offset;
1989 if (load_array[i].load->hdr.ldci_cmd_type == LDC_CMD_MAP)
1990 hdr.moh_load_map_cmd_off = offset;
1991
1992 offset += load_array[i].load->hdr.ldci_cmd_size;
1993 }
1994
1995 hdr.moh_sizeofcmds = offset - MO_SIZEOF_RAW_HDR;
1996
1997 if (debug)
1998 print_header (&hdr);
1999
2000 /* Write header */
2001 status = encode_mach_o_hdr (&hdr, obj, MO_SIZEOF_RAW_HDR);
2002 if (status != MO_HDR_CONV_SUCCESS)
2003 bad_header (status);
2004
2005 if (debug)
2006 fprintf (stderr, "writing load commands.\n\n");
2007
2008 /* Write load commands */
2009 offset = hdr.moh_first_cmd_off;
2010 for (i = 0; i < hdr.moh_n_load_cmds; i++)
2011 {
2012 load_union_t *load_hdr = load_array[i].load;
2013 size_t size = load_hdr->hdr.ldci_cmd_size;
2014
2015 if (debug)
2016 print_load_command (load_hdr, offset, i);
2017
4c9a05bc 2018 bcopy ((char *)load_hdr, (char *)(obj + offset), size);
4e81a331
RS
2019 offset += size;
2020 }
2021 }
2022
2023 end_file (obj_file);
2024
2025 if (close (prog_fd))
1fab8e81 2026 fatal_perror ("closing %s", prog_name);
4e81a331
RS
2027
2028 if (debug)
2029 fprintf (stderr, "\n");
2030}
2031
2032\f
2033/* Add a function table to the load commands to call a function
ed5b9462 2034 on initiation or termination of the process. */
4e81a331
RS
2035
2036static void
2037add_func_table (hdr_p, load_array, sym, type)
2038 mo_header_t *hdr_p; /* pointer to global header */
2039 load_all_t *load_array; /* array of ptrs to load cmds */
2040 symbol_info_t *sym; /* pointer to symbol entry */
2041 int type; /* fntc_type value */
2042{
2043 /* Add a new load command. */
2044 int num_cmds = ++hdr_p->moh_n_load_cmds;
2045 int load_index = num_cmds - 1;
2046 size_t size = sizeof (func_table_command_t) + sizeof (mo_addr_t);
2047 load_union_t *ptr = xcalloc (1, size);
2048 load_all_t *load_cmd;
2049 int i;
2050
2051 /* Set the unresolved address bit in the header to force the loader to be
2052 used, since kernel exec does not call the initialization functions. */
2053 hdr_p->moh_flags |= MOH_UNRESOLVED_F;
2054
2055 load_cmd = &load_array[load_index];
2056 load_cmd->load = ptr;
2057 load_cmd->section = (char *)0;
2058
2059 /* Fill in func table load command. */
2060 ptr->func.ldc_header.ldci_cmd_type = LDC_FUNC_TABLE;
2061 ptr->func.ldc_header.ldci_cmd_size = size;
2062 ptr->func.ldc_header.ldci_section_off = 0;
2063 ptr->func.ldc_header.ldci_section_len = 0;
2064 ptr->func.fntc_type = type;
2065 ptr->func.fntc_nentries = 1;
2066
2067 /* copy address, turn it from abs. address to (region,offset) if necessary. */
2068 /* Is the symbol already expressed as (region, offset)? */
2069 if ((sym->si_flags & SI_ABSOLUTE_VALUE_F) == 0)
2070 {
2071 ptr->func.fntc_entry_loc[i].adr_lcid = sym->si_value.def_val.adr_lcid;
2072 ptr->func.fntc_entry_loc[i].adr_sctoff = sym->si_value.def_val.adr_sctoff;
2073 }
2074
2075 /* If not, figure out which region it's in. */
2076 else
2077 {
2078 mo_vm_addr_t addr = sym->si_value.abs_val;
2079 int found = 0;
2080
2081 for (i = 0; i < load_index; i++)
2082 {
2083 if (load_array[i].load->hdr.ldci_cmd_type == LDC_REGION)
2084 {
2085 region_command_t *region_ptr = &load_array[i].load->region;
2086
2087 if ((region_ptr->regc_flags & REG_ABS_ADDR_F) != 0
2088 && addr >= region_ptr->regc_addr.vm_addr
2089 && addr <= region_ptr->regc_addr.vm_addr + region_ptr->regc_vm_size)
2090 {
2091 ptr->func.fntc_entry_loc[0].adr_lcid = i;
2092 ptr->func.fntc_entry_loc[0].adr_sctoff = addr - region_ptr->regc_addr.vm_addr;
2093 found++;
2094 break;
2095 }
2096 }
2097 }
2098
2099 if (!found)
2100 fatal ("could not convert 0x%l.8x into a region", addr);
2101 }
2102
2103 if (debug)
2104 fprintf (stderr,
2105 "%s function, region %d, offset = %ld (0x%.8lx)\n",
2106 (type == FNTC_INITIALIZATION) ? "init" : "term",
2107 (int)ptr->func.fntc_entry_loc[i].adr_lcid,
2108 (long)ptr->func.fntc_entry_loc[i].adr_sctoff,
2109 (long)ptr->func.fntc_entry_loc[i].adr_sctoff);
2110
2111}
2112
2113\f
2114/* Print the global header for an OSF/rose object. */
2115
2116static void
2117print_header (hdr_ptr)
2118 mo_header_t *hdr_ptr;
2119{
2120 fprintf (stderr, "\nglobal header:\n");
2121 fprintf (stderr, "\tmoh_magic = 0x%.8lx\n", hdr_ptr->moh_magic);
2122 fprintf (stderr, "\tmoh_major_version = %d\n", (int)hdr_ptr->moh_major_version);
2123 fprintf (stderr, "\tmoh_minor_version = %d\n", (int)hdr_ptr->moh_minor_version);
2124 fprintf (stderr, "\tmoh_header_version = %d\n", (int)hdr_ptr->moh_header_version);
2125 fprintf (stderr, "\tmoh_max_page_size = %d\n", (int)hdr_ptr->moh_max_page_size);
2126 fprintf (stderr, "\tmoh_byte_order = %d\n", (int)hdr_ptr->moh_byte_order);
2127 fprintf (stderr, "\tmoh_data_rep_id = %d\n", (int)hdr_ptr->moh_data_rep_id);
2128 fprintf (stderr, "\tmoh_cpu_type = %d\n", (int)hdr_ptr->moh_cpu_type);
2129 fprintf (stderr, "\tmoh_cpu_subtype = %d\n", (int)hdr_ptr->moh_cpu_subtype);
2130 fprintf (stderr, "\tmoh_vendor_type = %d\n", (int)hdr_ptr->moh_vendor_type);
2131 fprintf (stderr, "\tmoh_load_map_cmd_off = %d\n", (int)hdr_ptr->moh_load_map_cmd_off);
2132 fprintf (stderr, "\tmoh_first_cmd_off = %d\n", (int)hdr_ptr->moh_first_cmd_off);
2133 fprintf (stderr, "\tmoh_sizeofcmds = %d\n", (int)hdr_ptr->moh_sizeofcmds);
2134 fprintf (stderr, "\tmon_n_load_cmds = %d\n", (int)hdr_ptr->moh_n_load_cmds);
2135 fprintf (stderr, "\tmoh_flags = 0x%.8lx", (long)hdr_ptr->moh_flags);
2136
2137 if (hdr_ptr->moh_flags & MOH_RELOCATABLE_F)
2138 fprintf (stderr, ", relocatable");
2139
2140 if (hdr_ptr->moh_flags & MOH_LINKABLE_F)
2141 fprintf (stderr, ", linkable");
2142
2143 if (hdr_ptr->moh_flags & MOH_EXECABLE_F)
2144 fprintf (stderr, ", execable");
2145
2146 if (hdr_ptr->moh_flags & MOH_EXECUTABLE_F)
2147 fprintf (stderr, ", executable");
2148
2149 if (hdr_ptr->moh_flags & MOH_UNRESOLVED_F)
2150 fprintf (stderr, ", unresolved");
2151
2152 fprintf (stderr, "\n\n");
2153 return;
2154}
2155
2156\f
2157/* Print a short summary of a load command. */
2158
2159static void
2160print_load_command (load_hdr, offset, number)
2161 load_union_t *load_hdr;
2162 size_t offset;
2163 int number;
2164{
2165 mo_long_t type = load_hdr->hdr.ldci_cmd_type;
2166 char *type_str = (char *)0;
2167
2168 switch (type)
2169 {
2170 case LDC_UNDEFINED: type_str = "UNDEFINED"; break;
2171 case LDC_CMD_MAP: type_str = "CMD_MAP"; break;
2172 case LDC_INTERPRETER: type_str = "INTERPRETER"; break;
2173 case LDC_STRINGS: type_str = "STRINGS"; break;
2174 case LDC_REGION: type_str = "REGION"; break;
2175 case LDC_RELOC: type_str = "RELOC"; break;
2176 case LDC_PACKAGE: type_str = "PACKAGE"; break;
2177 case LDC_SYMBOLS: type_str = "SYMBOLS"; break;
2178 case LDC_ENTRY: type_str = "ENTRY"; break;
2179 case LDC_FUNC_TABLE: type_str = "FUNC_TABLE"; break;
2180 case LDC_GEN_INFO: type_str = "GEN_INFO"; break;
2181 }
2182
2183 fprintf (stderr,
2184 "cmd %2d, sz: 0x%.2lx, coff: 0x%.3lx, doff: 0x%.6lx, dlen: 0x%.6lx",
2185 number,
2186 (long) load_hdr->hdr.ldci_cmd_size,
2187 (long) offset,
2188 (long) load_hdr->hdr.ldci_section_off,
2189 (long) load_hdr->hdr.ldci_section_len);
2190
2191 if (type_str == (char *)0)
2192 fprintf (stderr, ", ty: unknown (%ld)\n", (long) type);
2193
2194 else if (type != LDC_REGION)
2195 fprintf (stderr, ", ty: %s\n", type_str);
2196
2197 else
2198 {
2199 char *region = "";
2200 switch (load_hdr->region.regc_usage_type)
2201 {
2202 case REG_TEXT_T: region = ", .text"; break;
2203 case REG_DATA_T: region = ", .data"; break;
2204 case REG_BSS_T: region = ", .bss"; break;
2205 case REG_GLUE_T: region = ", .glue"; break;
2206#if defined (REG_RDATA_T) && defined (REG_SDATA_T) && defined (REG_SBSS_T) /*mips*/
2207 case REG_RDATA_T: region = ", .rdata"; break;
2208 case REG_SDATA_T: region = ", .sdata"; break;
2209 case REG_SBSS_T: region = ", .sbss"; break;
2210#endif
2211 }
2212
2213 fprintf (stderr, ", ty: %s, vaddr: 0x%.8lx, vlen: 0x%.6lx%s\n",
2214 type_str,
2215 (long) load_hdr->region.regc_vm_addr,
2216 (long) load_hdr->region.regc_vm_size,
2217 region);
2218 }
2219
2220 return;
2221}
2222
2223\f
2224/* Fatal error when {en,de}code_mach_o_header fails. */
2225
2226static void
2227bad_header (status)
2228 int status;
2229{
2230 char *msg = (char *)0;
2231
2232 switch (status)
2233 {
2234 case MO_ERROR_BAD_MAGIC: msg = "bad magic number"; break;
2235 case MO_ERROR_BAD_HDR_VERS: msg = "bad header version"; break;
2236 case MO_ERROR_BAD_RAW_HDR_VERS: msg = "bad raw header version"; break;
2237 case MO_ERROR_BUF2SML: msg = "raw header buffer too small"; break;
2238 case MO_ERROR_OLD_RAW_HDR_FILE: msg = "old raw header file"; break;
2239 case MO_ERROR_UNSUPPORTED_VERS: msg = "unsupported version"; break;
2240 }
2241
2242 if (msg == (char *)0)
2243 fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
2244 else
2245 fatal ("%s", msg);
2246}
2247
2248\f
2249/* Read a file into a memory buffer. */
2250
2251static struct file_info *
2252read_file (name, fd, rw)
2253 char *name; /* filename */
2254 int fd; /* file descriptor */
2255 int rw; /* read/write */
2256{
2257 struct stat stat_pkt;
2258 struct file_info *p = (struct file_info *) xcalloc (sizeof (struct file_info), 1);
2259#ifdef USE_MMAP
2260 static int page_size;
2261#endif
2262
2263 if (fstat (fd, &stat_pkt) < 0)
2264 fatal_perror ("fstat %s", name);
2265
2266 p->name = name;
2267 p->size = stat_pkt.st_size;
2268 p->rounded_size = stat_pkt.st_size;
2269 p->fd = fd;
2270 p->rw = rw;
2271
2272#ifdef USE_MMAP
2273 if (debug)
2274 fprintf (stderr, "mmap %s, %s\n", name, (rw) ? "read/write" : "read-only");
2275
2276 if (page_size == 0)
2277 page_size = sysconf (_SC_PAGE_SIZE);
2278
2279 p->rounded_size = ((p->size + page_size - 1) / page_size) * page_size;
2280 p->start = mmap ((caddr_t)0,
2281 (rw) ? p->rounded_size : p->size,
2282 (rw) ? (PROT_READ | PROT_WRITE) : PROT_READ,
2283 MAP_FILE | MAP_VARIABLE | MAP_SHARED,
2284 fd,
2285 0L);
2286
2287 if (p->start != (char *)0 && p->start != (char *)-1)
2288 p->use_mmap = 1;
2289
2290 else
2291#endif /* USE_MMAP */
2292 {
2293 long len;
2294
2295 if (debug)
2296 fprintf (stderr, "read %s\n", name);
2297
2298 p->use_mmap = 0;
2299 p->start = xmalloc (p->size);
2300 if (lseek (fd, 0L, SEEK_SET) < 0)
2301 fatal_perror ("lseek to 0 on %s", name);
2302
2303 len = read (fd, p->start, p->size);
2304 if (len < 0)
2305 fatal_perror ("read %s", name);
2306
2307 if (len != p->size)
2308 fatal ("read %ld bytes, expected %ld, from %s", len, p->size, name);
2309 }
2310
2311 return p;
2312}
4e81a331
RS
2313\f
2314/* Do anything necessary to write a file back from memory. */
2315
2316static void
2317end_file (ptr)
2318 struct file_info *ptr; /* file information block */
2319{
2320#ifdef USE_MMAP
2321 if (ptr->use_mmap)
2322 {
2323 if (ptr->rw)
2324 {
2325 if (debug)
2326 fprintf (stderr, "msync %s\n", ptr->name);
2327
2328 if (msync (ptr->start, ptr->rounded_size, MS_ASYNC))
2329 fatal_perror ("msync %s", ptr->name);
2330 }
2331
2332 if (debug)
2333 fprintf (stderr, "munmap %s\n", ptr->name);
2334
2335 if (munmap (ptr->start, ptr->size))
2336 fatal_perror ("munmap %s", ptr->name);
2337 }
2338 else
2339#endif /* USE_MMAP */
2340 {
2341 if (ptr->rw)
2342 {
2343 long len;
2344
2345 if (debug)
2346 fprintf (stderr, "write %s\n", ptr->name);
2347
2348 if (lseek (ptr->fd, 0L, SEEK_SET) < 0)
2349 fatal_perror ("lseek to 0 on %s", ptr->name);
2350
2351 len = write (ptr->fd, ptr->start, ptr->size);
2352 if (len < 0)
2353 fatal_perror ("read %s", ptr->name);
2354
2355 if (len != ptr->size)
2356 fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name);
2357 }
2358
2359 free ((generic *)ptr->start);
2360 }
2361
2362 free ((generic *)ptr);
2363}
2364
2365#endif /* OBJECT_FORMAT_ROSE */
This page took 0.447686 seconds and 5 git commands to generate.