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