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