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