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