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