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