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