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