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