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, 2001 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).
9 This file is part of GNU CC.
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)
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.
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. */
27 /* Build tables of static constructors and destructors and run ld. */
32 #if ! defined( SIGCHLD ) && defined( SIGCLD )
33 # define SIGCHLD SIGCLD
36 #ifdef vfork /* Autoconf may define this to fork for us. */
37 # define VFORK_STRING "fork"
39 # define VFORK_STRING "vfork"
45 #define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \
46 lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1)
49 #ifndef LIBRARY_PATH_ENV
50 #define LIBRARY_PATH_ENV "LIBRARY_PATH"
61 /* Obstack allocation and deallocation routines. */
62 #define obstack_chunk_alloc xmalloc
63 #define obstack_chunk_free free
65 /* On certain systems, we have code that works by scanning the object file
66 directly. But this code uses system-specific header files and library
67 functions, so turn it off in a cross-compiler. Likewise, the names of
68 the utilities are not correct for a cross-compiler; we have to hope that
69 cross-versions are in the proper directories. */
72 #undef SUNOS4_SHARED_LIBRARIES
73 #undef OBJECT_FORMAT_COFF
74 #undef OBJECT_FORMAT_ROSE
76 #undef REAL_LD_FILE_NAME
77 #undef REAL_NM_FILE_NAME
78 #undef REAL_STRIP_FILE_NAME
81 /* If we cannot use a special method, use the ordinary one:
82 run nm to find what symbols are present.
83 In a cross-compiler, this means you need a cross nm,
84 but that is not quite as unpleasant as special headers. */
86 #if !defined (OBJECT_FORMAT_COFF) && !defined (OBJECT_FORMAT_ROSE)
87 #define OBJECT_FORMAT_NONE
90 #ifdef OBJECT_FORMAT_COFF
99 /* Many versions of ldfcn.h define these. */
107 /* Some systems have an ISCOFF macro, but others do not. In some cases
108 the macro may be wrong. MY_ISCOFF is defined in tm.h files for machines
109 that either do not have an ISCOFF macro in /usr/include or for those
110 where it is wrong. */
113 #define MY_ISCOFF(X) ISCOFF (X)
116 #endif /* OBJECT_FORMAT_COFF */
118 #ifdef OBJECT_FORMAT_ROSE
125 #include <sys/mman.h>
129 #include <mach_o_format.h>
130 #include <mach_o_header.h>
131 #include <mach_o_vals.h>
132 #include <mach_o_types.h>
134 #endif /* OBJECT_FORMAT_ROSE */
136 #ifdef OBJECT_FORMAT_NONE
138 /* Default flags to pass to nm. */
140 #define NM_FLAGS "-n"
143 #endif /* OBJECT_FORMAT_NONE */
145 /* Some systems use __main in a way incompatible with its use in gcc, in these
146 cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
147 give the same symbol without quotes for an alternative entry point. You
148 must define both, or neither. */
150 #define NAME__MAIN "__main"
151 #define SYMBOL__MAIN __main
154 /* This must match tree.h. */
155 #define DEFAULT_INIT_PRIORITY 65535
157 #if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES
158 #define SCAN_LIBRARIES
162 int do_collecting = 1;
164 int do_collecting = 0;
167 /* Linked lists of constructor and destructor names. */
183 /* Enumeration giving which pass this is for scanning the program file. */
186 PASS_FIRST, /* without constructors */
187 PASS_OBJ, /* individual objects */
188 PASS_LIB, /* looking for shared libraries */
189 PASS_SECOND /* with constructors linked in */
192 int vflag; /* true if -v */
193 static int rflag; /* true if -r */
194 static int strip_flag; /* true if -s */
195 #ifdef COLLECT_EXPORT_LIST
196 static int export_flag; /* true if -bE */
197 static int aix64_flag; /* true if -b64 */
200 int debug; /* true if -debug */
202 static int shared_obj; /* true if -shared */
204 static const char *c_file; /* <xxx>.c for constructor/destructor list. */
205 static const char *o_file; /* <xxx>.o for constructor/destructor list. */
206 #ifdef COLLECT_EXPORT_LIST
207 static const char *export_file; /* <xxx>.x for AIX export list. */
209 const char *ldout; /* File for ld errors. */
210 static const char *output_file; /* Output file for ld. */
211 static const char *nm_file_name; /* pathname of nm */
213 static const char *ldd_file_name; /* pathname of ldd (or equivalent) */
215 static const char *strip_file_name; /* pathname of strip */
216 const char *c_file_name; /* pathname of gcc */
217 static char *initname, *fininame; /* names of init and fini funcs */
219 static struct head constructors; /* list of constructors found */
220 static struct head destructors; /* list of destructors found */
221 #ifdef COLLECT_EXPORT_LIST
222 static struct head exports; /* list of exported symbols */
224 static struct head frame_tables; /* list of frame unwind info tables */
226 struct obstack temporary_obstack;
227 struct obstack permanent_obstack;
228 char * temporary_firstobj;
230 /* Holds the return value of pexecute. */
233 /* Defined in the automatically-generated underscore.c. */
234 extern int prepends_underscore;
236 #ifndef GET_ENV_PATH_LIST
237 #define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0)
240 /* Structure to hold all the directories in which to search for files to
245 const char *prefix; /* String to prepend to the path. */
246 struct prefix_list *next; /* Next in linked list. */
251 struct prefix_list *plist; /* List of prefixes to try */
252 int max_len; /* Max length of a prefix in PLIST */
253 const char *name; /* Name of this list (used in config stuff) */
256 #ifdef COLLECT_EXPORT_LIST
257 /* Lists to keep libraries to be scanned for global constructors/destructors. */
258 static struct head libs; /* list of libraries */
259 static struct path_prefix cmdline_lib_dirs; /* directories specified with -L */
260 static struct path_prefix libpath_lib_dirs; /* directories in LIBPATH */
261 static struct path_prefix *libpaths[3] = {&cmdline_lib_dirs,
262 &libpath_lib_dirs, NULL};
263 static const char *libexts[3] = {"a", "so", NULL}; /* possible library extentions */
266 static void handler PARAMS ((int));
267 static int is_ctor_dtor PARAMS ((const char *));
268 static char *find_a_file PARAMS ((struct path_prefix *, const char *));
269 static void add_prefix PARAMS ((struct path_prefix *, const char *));
270 static void prefix_from_env PARAMS ((const char *, struct path_prefix *));
271 static void prefix_from_string PARAMS ((const char *, struct path_prefix *));
272 static void do_wait PARAMS ((const char *));
273 static void fork_execute PARAMS ((const char *, char **));
274 static void maybe_unlink PARAMS ((const char *));
275 static void add_to_list PARAMS ((struct head *, const char *));
276 static int extract_init_priority PARAMS ((const char *));
277 static void sort_ids PARAMS ((struct head *));
278 static void write_list PARAMS ((FILE *, const char *, struct id *));
279 #ifdef COLLECT_EXPORT_LIST
280 static void dump_list PARAMS ((FILE *, const char *, struct id *));
283 static void dump_prefix_list PARAMS ((FILE *, const char *, struct prefix_list *));
285 static void write_list_with_asm PARAMS ((FILE *, const char *, struct id *));
286 static void write_c_file PARAMS ((FILE *, const char *));
287 static void write_c_file_stat PARAMS ((FILE *, const char *));
288 #ifndef LD_INIT_SWITCH
289 static void write_c_file_glob PARAMS ((FILE *, const char *));
291 static void scan_prog_file PARAMS ((const char *, enum pass));
292 #ifdef SCAN_LIBRARIES
293 static void scan_libraries PARAMS ((const char *));
295 #ifdef COLLECT_EXPORT_LIST
296 static int is_in_list PARAMS ((const char *, struct id *));
297 static void write_aix_file PARAMS ((FILE *, struct id *));
298 static char *resolve_lib_name PARAMS ((const char *));
299 static int ignore_library PARAMS ((const char *));
301 static char *extract_string PARAMS ((const char **));
316 while ((fd = dup (oldfd)) != newfd && fd >= 0) /* good enough for low fd's */
319 close (fdtmp[--fdx]);
325 /* Delete tempfiles and exit function. */
328 collect_exit (status)
331 if (c_file != 0 && c_file[0])
332 maybe_unlink (c_file);
334 if (o_file != 0 && o_file[0])
335 maybe_unlink (o_file);
337 #ifdef COLLECT_EXPORT_LIST
338 if (export_file != 0 && export_file[0])
339 maybe_unlink (export_file);
342 if (ldout != 0 && ldout[0])
345 maybe_unlink (ldout);
348 if (status != 0 && output_file != 0 && output_file[0])
349 maybe_unlink (output_file);
355 /* Notify user of a non-error. */
357 notice VPARAMS ((const char *msgid, ...))
359 #ifndef ANSI_PROTOTYPES
364 VA_START (ap, msgid);
366 #ifndef ANSI_PROTOTYPES
367 msgid = va_arg (ap, const char *);
370 vfprintf (stderr, _(msgid), ap);
374 /* Die when sys call fails. */
377 fatal_perror VPARAMS ((const char * msgid, ...))
379 #ifndef ANSI_PROTOTYPES
385 VA_START (ap, msgid);
387 #ifndef ANSI_PROTOTYPES
388 msgid = va_arg (ap, const char *);
391 fprintf (stderr, "collect2: ");
392 vfprintf (stderr, _(msgid), ap);
393 fprintf (stderr, ": %s\n", xstrerror (e));
396 collect_exit (FATAL_EXIT_CODE);
402 fatal VPARAMS ((const char * msgid, ...))
404 #ifndef ANSI_PROTOTYPES
409 VA_START (ap, msgid);
411 #ifndef ANSI_PROTOTYPES
412 msgid = va_arg (ap, const char *);
415 fprintf (stderr, "collect2: ");
416 vfprintf (stderr, _(msgid), ap);
417 fprintf (stderr, "\n");
420 collect_exit (FATAL_EXIT_CODE);
423 /* Write error message. */
426 error VPARAMS ((const char * msgid, ...))
428 #ifndef ANSI_PROTOTYPES
433 VA_START (ap, msgid);
435 #ifndef ANSI_PROTOTYPES
436 msgid = va_arg (ap, const char *);
439 fprintf (stderr, "collect2: ");
440 vfprintf (stderr, _(msgid), ap);
441 fprintf (stderr, "\n");
445 /* In case obstack is linked in, and abort is defined to fancy_abort,
446 provide a default entry. */
451 fatal ("internal error");
458 if (c_file != 0 && c_file[0])
459 maybe_unlink (c_file);
461 if (o_file != 0 && o_file[0])
462 maybe_unlink (o_file);
464 if (ldout != 0 && ldout[0])
465 maybe_unlink (ldout);
467 #ifdef COLLECT_EXPORT_LIST
468 if (export_file != 0 && export_file[0])
469 maybe_unlink (export_file);
472 signal (signo, SIG_DFL);
473 kill (getpid (), signo);
481 return access (name, R_OK) == 0;
484 /* Parse a reasonable subset of shell quoting syntax. */
501 obstack_1grow (&temporary_obstack, c);
502 else if (! inside && c == ' ')
504 else if (! inside && c == '\\')
509 obstack_1grow (&temporary_obstack, c);
512 obstack_1grow (&temporary_obstack, '\0');
514 return obstack_finish (&temporary_obstack);
521 FILE *stream = fopen (name, "r");
522 int no_demangle = !! getenv ("COLLECT_NO_DEMANGLE");
529 while (c = getc (stream),
530 c != EOF && (ISALNUM (c) || c == '_' || c == '$' || c == '.'))
531 obstack_1grow (&temporary_obstack, c);
532 if (obstack_object_size (&temporary_obstack) > 0)
534 const char *word, *p;
536 obstack_1grow (&temporary_obstack, '\0');
537 word = obstack_finish (&temporary_obstack);
540 ++word, putc ('.', stderr);
542 if (*p == '_' && prepends_underscore)
548 result = cplus_demangle (p, DMGL_PARAMS | DMGL_ANSI);
553 fputs (result, stderr);
555 diff = strlen (word) - strlen (result);
557 --diff, putc (' ', stderr);
558 while (diff < 0 && c == ' ')
559 ++diff, c = getc (stream);
564 fputs (word, stderr);
567 obstack_free (&temporary_obstack, temporary_firstobj);
576 /* Decide whether the given symbol is: a constructor (1), a destructor
577 (2), a routine in a shared object that calls all the constructors
578 (3) or destructors (4), a DWARF exception-handling table (5), or
579 nothing special (0). */
585 struct names { const char *name; int len; int ret; int two_underscores; };
587 register struct names *p;
589 register const char *orig_s = s;
591 static struct names special[] = {
592 #ifdef NO_DOLLAR_IN_LABEL
593 #ifdef NO_DOT_IN_LABEL
594 { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, 1, 0 },
595 { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, 2, 0 },
596 { "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, 5, 0 },
598 { "GLOBAL_.I.", sizeof ("GLOBAL_.I.")-1, 1, 0 },
599 { "GLOBAL_.D.", sizeof ("GLOBAL_.D.")-1, 2, 0 },
600 { "GLOBAL_.F.", sizeof ("GLOBAL_.F.")-1, 5, 0 },
603 { "GLOBAL_$I$", sizeof ("GLOBAL_$I$")-1, 1, 0 },
604 { "GLOBAL_$D$", sizeof ("GLOBAL_$D$")-1, 2, 0 },
605 { "GLOBAL_$F$", sizeof ("GLOBAL_$F$")-1, 5, 0 },
607 { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, 3, 0 },
608 { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, 4, 0 },
609 #ifdef CFRONT_LOSSAGE /* Do not collect cfront initialization functions.
610 cfront has its own linker procedure to collect them;
611 if collect2 gets them too, they get collected twice
612 when the cfront procedure is run and the compiler used
613 for linking happens to be GCC. */
614 { "sti__", sizeof ("sti__")-1, 1, 1 },
615 { "std__", sizeof ("std__")-1, 2, 1 },
616 #endif /* CFRONT_LOSSAGE */
620 while ((ch = *s) == '_')
626 for (p = &special[0]; p->len > 0; p++)
629 && (!p->two_underscores || ((s - orig_s) >= 2))
630 && strncmp(s, p->name, p->len) == 0)
638 /* We maintain two prefix lists: one from COMPILER_PATH environment variable
639 and one from the PATH variable. */
641 static struct path_prefix cpath, path;
644 /* This is the name of the target machine. We use it to form the name
645 of the files to execute. */
647 static const char *const target_machine = TARGET_MACHINE;
650 /* Search for NAME using prefix list PPREFIX. We only look for executable
653 Return 0 if not found, otherwise return its name, allocated with malloc. */
656 find_a_file (pprefix, name)
657 struct path_prefix *pprefix;
661 struct prefix_list *pl;
662 int len = pprefix->max_len + strlen (name) + 1;
665 fprintf (stderr, "Looking for '%s'\n", name);
667 #ifdef EXECUTABLE_SUFFIX
668 len += strlen (EXECUTABLE_SUFFIX);
671 temp = xmalloc (len);
673 /* Determine the filename to execute (special case for absolute paths). */
676 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
677 || (*name && name[1] == ':')
681 if (access (name, X_OK) == 0)
686 fprintf (stderr, " - found: absolute path\n");
691 #ifdef EXECUTABLE_SUFFIX
692 /* Some systems have a suffix for executable files.
693 So try appending that. */
695 strcat (temp, EXECUTABLE_SUFFIX);
697 if (access (temp, X_OK) == 0)
702 fprintf (stderr, " - failed to locate using absolute path\n");
705 for (pl = pprefix->plist; pl; pl = pl->next)
709 strcpy (temp, pl->prefix);
712 if (stat (temp, &st) >= 0
713 && ! S_ISDIR (st.st_mode)
714 && access (temp, X_OK) == 0)
717 #ifdef EXECUTABLE_SUFFIX
718 /* Some systems have a suffix for executable files.
719 So try appending that. */
720 strcat (temp, EXECUTABLE_SUFFIX);
722 if (stat (temp, &st) >= 0
723 && ! S_ISDIR (st.st_mode)
724 && access (temp, X_OK) == 0)
729 if (debug && pprefix->plist == NULL)
730 fprintf (stderr, " - failed: no entries in prefix list\n");
736 /* Add an entry for PREFIX to prefix list PPREFIX. */
739 add_prefix (pprefix, prefix)
740 struct path_prefix *pprefix;
743 struct prefix_list *pl, **prev;
748 for (pl = pprefix->plist; pl->next; pl = pl->next)
753 prev = &pprefix->plist;
755 /* Keep track of the longest prefix */
757 len = strlen (prefix);
758 if (len > pprefix->max_len)
759 pprefix->max_len = len;
761 pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list));
762 pl->prefix = xstrdup (prefix);
767 pl->next = (struct prefix_list *) 0;
771 /* Take the value of the environment variable ENV, break it into a path, and
772 add of the entries to PPREFIX. */
775 prefix_from_env (env, pprefix)
777 struct path_prefix *pprefix;
780 GET_ENV_PATH_LIST (p, env);
783 prefix_from_string (p, pprefix);
787 prefix_from_string (p, pprefix)
789 struct path_prefix *pprefix;
791 const char *startp, *endp;
792 char *nstore = (char *) xmalloc (strlen (p) + 3);
795 fprintf (stderr, "Convert string '%s' into prefixes, separator = '%c'\n", p, PATH_SEPARATOR);
800 if (*endp == PATH_SEPARATOR || *endp == 0)
802 strncpy (nstore, startp, endp-startp);
805 strcpy (nstore, "./");
807 else if (! IS_DIR_SEPARATOR (endp[-1]))
809 nstore[endp-startp] = DIR_SEPARATOR;
810 nstore[endp-startp+1] = 0;
813 nstore[endp-startp] = 0;
816 fprintf (stderr, " - add prefix: %s\n", nstore);
818 add_prefix (pprefix, nstore);
821 endp = startp = endp + 1;
830 int main PARAMS ((int, char *[]));
836 const char *ld_suffix = "ld";
837 const char *full_ld_suffix = ld_suffix;
838 const char *real_ld_suffix = "real-ld";
839 const char *collect_ld_suffix = "collect-ld";
840 const char *nm_suffix = "nm";
841 const char *full_nm_suffix = nm_suffix;
842 const char *gnm_suffix = "gnm";
843 const char *full_gnm_suffix = gnm_suffix;
845 const char *ldd_suffix = LDD_SUFFIX;
846 const char *full_ldd_suffix = ldd_suffix;
848 const char *strip_suffix = "strip";
849 const char *full_strip_suffix = strip_suffix;
850 const char *gstrip_suffix = "gstrip";
851 const char *full_gstrip_suffix = gstrip_suffix;
854 #ifdef COLLECT_EXPORT_LIST
857 const char *ld_file_name;
868 int num_c_args = argc+9;
870 #if defined (COLLECT2_HOST_INITIALIZATION)
871 /* Perform system dependent initialization, if neccessary. */
872 COLLECT2_HOST_INITIALIZATION;
876 /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
877 receive the signal. A different setting is inheritable */
878 signal (SIGCHLD, SIG_DFL);
881 /* LC_CTYPE determines the character set used by the terminal so it has be set
882 to output messages correctly. */
884 #ifdef HAVE_LC_MESSAGES
885 setlocale (LC_CTYPE, "");
886 setlocale (LC_MESSAGES, "");
888 setlocale (LC_ALL, "");
891 (void) bindtextdomain (PACKAGE, localedir);
892 (void) textdomain (PACKAGE);
894 /* Do not invoke xcalloc before this point, since locale needs to be
895 set first, in case a diagnostic is issued. */
897 ld1 = (const char **)(ld1_argv = (char **) xcalloc(sizeof (char *), argc+3));
898 ld2 = (const char **)(ld2_argv = (char **) xcalloc(sizeof (char *), argc+10));
899 object = (const char **)(object_lst = (char **) xcalloc(sizeof (char *), argc));
905 /* Parse command line early for instances of -debug. This allows
906 the debug flag to be set before functions like find_a_file()
911 for (i = 1; argv[i] != NULL; i ++)
912 if (! strcmp (argv[i], "-debug"))
917 #ifndef DEFAULT_A_OUT_NAME
918 output_file = "a.out";
920 output_file = DEFAULT_A_OUT_NAME;
923 obstack_begin (&temporary_obstack, 0);
924 obstack_begin (&permanent_obstack, 0);
925 temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0);
927 current_demangling_style = auto_demangling;
928 p = getenv ("COLLECT_GCC_OPTIONS");
931 const char *q = extract_string (&p);
932 if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
935 obstack_free (&temporary_obstack, temporary_firstobj);
937 /* -fno-exceptions -w */
940 c_ptr = (const char **)
941 (c_argv = (char **) xcalloc (sizeof (char *), num_c_args));
944 fatal ("no arguments");
947 if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
948 signal (SIGQUIT, handler);
950 if (signal (SIGINT, SIG_IGN) != SIG_IGN)
951 signal (SIGINT, handler);
953 if (signal (SIGALRM, SIG_IGN) != SIG_IGN)
954 signal (SIGALRM, handler);
957 if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
958 signal (SIGHUP, handler);
960 if (signal (SIGSEGV, SIG_IGN) != SIG_IGN)
961 signal (SIGSEGV, handler);
963 if (signal (SIGBUS, SIG_IGN) != SIG_IGN)
964 signal (SIGBUS, handler);
967 /* Extract COMPILER_PATH and PATH into our prefix list. */
968 prefix_from_env ("COMPILER_PATH", &cpath);
969 prefix_from_env ("PATH", &path);
972 /* If we look for a program in the compiler directories, we just use
973 the short name, since these directories are already system-specific.
974 But it we look for a program in the system directories, we need to
975 qualify the program name with the target machine. */
977 full_ld_suffix = concat(target_machine, "-", ld_suffix, NULL);
980 full_gld_suffix = concat (target_machine, "-", gld_suffix, NULL);
983 full_nm_suffix = concat (target_machine, "-", nm_suffix, NULL);
985 full_gnm_suffix = concat (target_machine, "-", gnm_suffix, NULL);
988 full_ldd_suffix = concat (target_machine, "-", ldd_suffix, NULL);
991 full_strip_suffix = concat (target_machine, "-", strip_suffix, NULL);
993 full_gstrip_suffix = concat (target_machine, "-", gstrip_suffix, NULL);
994 #endif /* CROSS_COMPILE */
996 /* Try to discover a valid linker/nm/strip to use. */
998 /* Maybe we know the right file to use (if not cross). */
1000 #ifdef DEFAULT_LINKER
1001 if (access (DEFAULT_LINKER, X_OK) == 0)
1002 ld_file_name = DEFAULT_LINKER;
1003 if (ld_file_name == 0)
1005 #ifdef REAL_LD_FILE_NAME
1006 ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME);
1007 if (ld_file_name == 0)
1009 /* Search the (target-specific) compiler dirs for ld'. */
1010 ld_file_name = find_a_file (&cpath, real_ld_suffix);
1011 /* Likewise for `collect-ld'. */
1012 if (ld_file_name == 0)
1013 ld_file_name = find_a_file (&cpath, collect_ld_suffix);
1014 /* Search the compiler directories for `ld'. We have protection against
1015 recursive calls in find_a_file. */
1016 if (ld_file_name == 0)
1017 ld_file_name = find_a_file (&cpath, ld_suffix);
1018 /* Search the ordinary system bin directories
1019 for `ld' (if native linking) or `TARGET-ld' (if cross). */
1020 if (ld_file_name == 0)
1021 ld_file_name = find_a_file (&path, full_ld_suffix);
1023 #ifdef REAL_NM_FILE_NAME
1024 nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME);
1025 if (nm_file_name == 0)
1027 nm_file_name = find_a_file (&cpath, gnm_suffix);
1028 if (nm_file_name == 0)
1029 nm_file_name = find_a_file (&path, full_gnm_suffix);
1030 if (nm_file_name == 0)
1031 nm_file_name = find_a_file (&cpath, nm_suffix);
1032 if (nm_file_name == 0)
1033 nm_file_name = find_a_file (&path, full_nm_suffix);
1036 ldd_file_name = find_a_file (&cpath, ldd_suffix);
1037 if (ldd_file_name == 0)
1038 ldd_file_name = find_a_file (&path, full_ldd_suffix);
1041 #ifdef REAL_STRIP_FILE_NAME
1042 strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME);
1043 if (strip_file_name == 0)
1045 strip_file_name = find_a_file (&cpath, gstrip_suffix);
1046 if (strip_file_name == 0)
1047 strip_file_name = find_a_file (&path, full_gstrip_suffix);
1048 if (strip_file_name == 0)
1049 strip_file_name = find_a_file (&cpath, strip_suffix);
1050 if (strip_file_name == 0)
1051 strip_file_name = find_a_file (&path, full_strip_suffix);
1053 /* Determine the full path name of the C compiler to use. */
1054 c_file_name = getenv ("COLLECT_GCC");
1055 if (c_file_name == 0)
1057 #ifdef CROSS_COMPILE
1058 c_file_name = concat (target_machine, "-gcc", NULL);
1060 c_file_name = "gcc";
1064 p = find_a_file (&cpath, c_file_name);
1066 /* Here it should be safe to use the system search path since we should have
1067 already qualified the name of the compiler when it is needed. */
1069 p = find_a_file (&path, c_file_name);
1074 *ld1++ = *ld2++ = ld_file_name;
1076 /* Make temp file names. */
1077 c_file = make_temp_file (".c");
1078 o_file = make_temp_file (".o");
1079 #ifdef COLLECT_EXPORT_LIST
1080 export_file = make_temp_file (".x");
1082 ldout = make_temp_file (".ld");
1083 *c_ptr++ = c_file_name;
1090 #ifdef COLLECT_EXPORT_LIST
1091 /* Generate a list of directories from LIBPATH. */
1092 prefix_from_env ("LIBPATH", &libpath_lib_dirs);
1093 /* Add to this list also two standard directories where
1094 AIX loader always searches for libraries. */
1095 add_prefix (&libpath_lib_dirs, "/lib");
1096 add_prefix (&libpath_lib_dirs, "/usr/lib");
1099 /* Get any options that the upper GCC wants to pass to the sub-GCC.
1101 AIX support needs to know if -shared has been specified before
1102 parsing commandline arguments. */
1104 p = getenv ("COLLECT_GCC_OPTIONS");
1107 const char *q = extract_string (&p);
1108 if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
1109 *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
1110 if (strcmp (q, "-EL") == 0 || strcmp (q, "-EB") == 0)
1111 *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
1112 if (strncmp (q, "-shared", sizeof ("-shared") - 1) == 0)
1114 if (*q == '-' && q[1] == 'B')
1116 *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
1119 q = extract_string (&p);
1120 *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
1124 obstack_free (&temporary_obstack, temporary_firstobj);
1125 *c_ptr++ = "-fno-exceptions";
1128 /* !!! When GCC calls collect2,
1129 it does not know whether it is calling collect2 or ld.
1130 So collect2 cannot meaningfully understand any options
1131 except those ld understands.
1132 If you propose to make GCC pass some other option,
1133 just imagine what will happen if ld is really ld!!! */
1135 /* Parse arguments. Remember output file spec, pass the rest to ld. */
1136 /* After the first file, put in the c++ rt0. */
1139 while ((arg = *++argv) != (char *) 0)
1141 *ld1++ = *ld2++ = arg;
1147 #ifdef COLLECT_EXPORT_LIST
1148 /* We want to disable automatic exports on AIX when user
1149 explicitly puts an export list in command line */
1151 if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0)
1153 else if (arg[2] == '6' && arg[3] == '4')
1159 if (!strcmp (arg, "-debug"))
1161 /* Already parsed. */
1170 /* place o_file BEFORE this argument! */
1176 #ifdef COLLECT_EXPORT_LIST
1178 /* Resolving full library name. */
1179 const char *s = resolve_lib_name (arg+2);
1181 /* Saving a full library name. */
1182 add_to_list (&libs, s);
1187 #ifdef COLLECT_EXPORT_LIST
1188 /* Saving directories where to search for libraries. */
1190 add_prefix (&cmdline_lib_dirs, arg+2);
1196 output_file = *ld1++ = *ld2++ = *++argv;
1198 #ifdef SWITCHES_NEED_SPACES
1199 && ! strchr (SWITCHES_NEED_SPACES, arg[1])
1203 output_file = &arg[2];
1212 if (arg[2] == '\0' && do_collecting)
1214 /* We must strip after the nm run, otherwise C++ linking
1215 will not work. Thus we strip in the second ld run, or
1216 else with strip if there is no second ld run. */
1228 else if ((p = strrchr (arg, '.')) != (char *) 0
1229 && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0
1230 || strcmp (p, ".so") == 0 || strcmp (p, ".lo") == 0
1231 || strcmp (p, ".obj") == 0))
1240 /* place o_file BEFORE this argument! */
1246 if (p[1] == 'o' || p[1] == 'l')
1248 #ifdef COLLECT_EXPORT_LIST
1249 /* libraries can be specified directly, i.e. without -l flag. */
1252 /* Saving a full library name. */
1253 add_to_list (&libs, arg);
1259 #ifdef COLLECT_EXPORT_LIST
1260 /* This is added only for debugging purposes. */
1263 fprintf (stderr, "List of libraries:\n");
1264 dump_list (stderr, "\t", libs.first);
1267 /* The AIX linker will discard static constructors in object files if
1268 nothing else in the file is referenced, so look at them first. */
1270 const char **export_object_lst = (const char **)object_lst;
1272 while (export_object_lst < object)
1273 scan_prog_file (*export_object_lst++, PASS_OBJ);
1276 struct id *list = libs.first;
1278 for (; list; list = list->next)
1279 scan_prog_file (list->name, PASS_FIRST);
1284 char *buf = xmalloc (strlen (export_file) + 5);
1286 sprintf (buf, "-bE:%s", export_file);
1290 exportf = fopen (export_file, "w");
1291 if (exportf == (FILE *) 0)
1292 fatal_perror ("fopen %s", export_file);
1293 write_aix_file (exportf, exports.first);
1294 if (fclose (exportf))
1295 fatal_perror ("fclose %s", export_file);
1300 *c_ptr = *ld1 = *object = (char *) 0;
1304 notice ("collect2 version %s", version_string);
1305 #ifdef TARGET_VERSION
1308 fprintf (stderr, "\n");
1314 fprintf (stderr, "ld_file_name = %s\n",
1315 (ld_file_name ? ld_file_name : "not found"));
1316 fprintf (stderr, "c_file_name = %s\n",
1317 (c_file_name ? c_file_name : "not found"));
1318 fprintf (stderr, "nm_file_name = %s\n",
1319 (nm_file_name ? nm_file_name : "not found"));
1321 fprintf (stderr, "ldd_file_name = %s\n",
1322 (ldd_file_name ? ldd_file_name : "not found"));
1324 fprintf (stderr, "strip_file_name = %s\n",
1325 (strip_file_name ? strip_file_name : "not found"));
1326 fprintf (stderr, "c_file = %s\n",
1327 (c_file ? c_file : "not found"));
1328 fprintf (stderr, "o_file = %s\n",
1329 (o_file ? o_file : "not found"));
1331 ptr = getenv ("COLLECT_GCC_OPTIONS");
1333 fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
1335 ptr = getenv ("COLLECT_GCC");
1337 fprintf (stderr, "COLLECT_GCC = %s\n", ptr);
1339 ptr = getenv ("COMPILER_PATH");
1341 fprintf (stderr, "COMPILER_PATH = %s\n", ptr);
1343 ptr = getenv (LIBRARY_PATH_ENV);
1345 fprintf (stderr, "%-20s= %s\n", LIBRARY_PATH_ENV, ptr);
1347 fprintf (stderr, "\n");
1350 /* Load the program, searching all libraries and attempting to provide
1351 undefined symbols from repository information. */
1353 /* On AIX we do this later. */
1354 #ifndef COLLECT_EXPORT_LIST
1355 do_tlink (ld1_argv, object_lst);
1358 /* If -r or they will be run via some other method, do not build the
1359 constructor or destructor list, just return now. */
1361 #ifndef COLLECT_EXPORT_LIST
1366 #ifdef COLLECT_EXPORT_LIST
1367 /* Do the link we avoided above if we are exiting. */
1368 do_tlink (ld1_argv, object_lst);
1370 /* But make sure we delete the export file we may have created. */
1371 if (export_file != 0 && export_file[0])
1372 maybe_unlink (export_file);
1374 maybe_unlink (c_file);
1375 maybe_unlink (o_file);
1379 /* Examine the namelist with nm and search it for static constructors
1380 and destructors to call.
1381 Write the constructor and destructor tables to a .s file and reload. */
1383 /* On AIX we already scanned for global constructors/destructors. */
1384 #ifndef COLLECT_EXPORT_LIST
1385 scan_prog_file (output_file, PASS_FIRST);
1388 #ifdef SCAN_LIBRARIES
1389 scan_libraries (output_file);
1394 notice ("%d constructor(s) found\n", constructors.number);
1395 notice ("%d destructor(s) found\n", destructors.number);
1396 notice ("%d frame table(s) found\n", frame_tables.number);
1399 if (constructors.number == 0 && destructors.number == 0
1400 && frame_tables.number == 0
1401 #if defined (SCAN_LIBRARIES) || defined (COLLECT_EXPORT_LIST)
1402 /* If we will be running these functions ourselves, we want to emit
1403 stubs into the shared library so that we do not have to relink
1404 dependent programs when we add static objects. */
1409 #ifdef COLLECT_EXPORT_LIST
1410 /* Do tlink without additional code generation */
1411 do_tlink (ld1_argv, object_lst);
1413 /* Strip now if it was requested on the command line. */
1416 char **real_strip_argv = (char **) xcalloc (sizeof (char *), 3);
1417 const char ** strip_argv = (const char **) real_strip_argv;
1419 strip_argv[0] = strip_file_name;
1420 strip_argv[1] = output_file;
1421 strip_argv[2] = (char *) 0;
1422 fork_execute ("strip", real_strip_argv);
1425 #ifdef COLLECT_EXPORT_LIST
1426 maybe_unlink (export_file);
1428 maybe_unlink (c_file);
1429 maybe_unlink (o_file);
1433 /* Sort ctor and dtor lists by priority. */
1434 sort_ids (&constructors);
1435 sort_ids (&destructors);
1437 maybe_unlink(output_file);
1438 outf = fopen (c_file, "w");
1439 if (outf == (FILE *) 0)
1440 fatal_perror ("fopen %s", c_file);
1442 write_c_file (outf, c_file);
1445 fatal_perror ("fclose %s", c_file);
1447 /* Tell the linker that we have initializer and finalizer functions. */
1448 #ifdef LD_INIT_SWITCH
1449 #ifdef COLLECT_EXPORT_LIST
1451 /* option name + functions + colons + NULL */
1452 char *buf = xmalloc (strlen (LD_INIT_SWITCH)
1453 + strlen(initname) + strlen(fininame) + 3);
1454 sprintf (buf, "%s:%s:%s", LD_INIT_SWITCH, initname, fininame);
1458 *ld2++ = LD_INIT_SWITCH;
1460 *ld2++ = LD_FINI_SWITCH;
1465 #ifdef COLLECT_EXPORT_LIST
1468 /* If we did not add export flag to link arguments before, add it to
1469 second link phase now. No new exports should have been added. */
1470 if (! exports.first)
1472 char *buf = xmalloc (strlen (export_file) + 5);
1474 sprintf (buf, "-bE:%s", export_file);
1478 add_to_list (&exports, initname);
1479 add_to_list (&exports, fininame);
1480 add_to_list (&exports, "_GLOBAL__DI");
1481 add_to_list (&exports, "_GLOBAL__DD");
1482 exportf = fopen (export_file, "w");
1483 if (exportf == (FILE *) 0)
1484 fatal_perror ("fopen %s", export_file);
1485 write_aix_file (exportf, exports.first);
1486 if (fclose (exportf))
1487 fatal_perror ("fclose %s", export_file);
1491 /* End of arguments to second link phase. */
1496 fprintf (stderr, "\n========== output_file = %s, c_file = %s\n",
1497 output_file, c_file);
1498 write_c_file (stderr, "stderr");
1499 fprintf (stderr, "========== end of c_file\n\n");
1500 #ifdef COLLECT_EXPORT_LIST
1501 fprintf (stderr, "\n========== export_file = %s\n", export_file);
1502 write_aix_file (stderr, exports.first);
1503 fprintf (stderr, "========== end of export_file\n\n");
1507 /* Assemble the constructor and destructor tables.
1508 Link the tables in with the rest of the program. */
1510 fork_execute ("gcc", c_argv);
1511 #ifdef COLLECT_EXPORT_LIST
1512 /* On AIX we must call tlink because of possible templates resolution */
1513 do_tlink (ld2_argv, object_lst);
1515 /* Otherwise, simply call ld because tlink is already done */
1516 fork_execute ("ld", ld2_argv);
1518 /* Let scan_prog_file do any final mods (OSF/rose needs this for
1519 constructors/destructors in shared libraries. */
1520 scan_prog_file (output_file, PASS_SECOND);
1523 maybe_unlink (c_file);
1524 maybe_unlink (o_file);
1526 #ifdef COLLECT_EXPORT_LIST
1527 maybe_unlink (export_file);
1534 /* Wait for a process to finish, and exit if a non-zero status is found. */
1542 pwait (pexecute_pid, &status, 0);
1545 if (WIFSIGNALED (status))
1547 int sig = WTERMSIG (status);
1548 error ("%s terminated with signal %d [%s]%s",
1549 prog, sig, strsignal(sig),
1550 status & 0200 ? "" : ", core dumped");
1551 collect_exit (FATAL_EXIT_CODE);
1554 if (WIFEXITED (status))
1555 return WEXITSTATUS (status);
1564 int ret = collect_wait (prog);
1567 error ("%s returned %d exit status", prog, ret);
1573 /* Execute a program, and wait for the reply. */
1576 collect_execute (prog, argv, redir)
1583 int redir_handle = -1;
1584 int stdout_save = -1;
1585 int stderr_save = -1;
1593 fprintf (stderr, "%s", argv[0]);
1595 notice ("[cannot find %s]", prog);
1597 for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++)
1598 fprintf (stderr, " %s", str);
1600 fprintf (stderr, "\n");
1606 /* If we cannot find a program we need, complain error. Do this here
1607 since we might not end up needing something that we could not find. */
1610 fatal ("cannot find `%s'", prog);
1614 /* Open response file. */
1615 redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT);
1617 /* Duplicate the stdout and stderr file handles
1618 so they can be restored later. */
1619 stdout_save = dup (STDOUT_FILENO);
1620 if (stdout_save == -1)
1621 fatal_perror ("redirecting stdout: %s", redir);
1622 stderr_save = dup (STDERR_FILENO);
1623 if (stderr_save == -1)
1624 fatal_perror ("redirecting stdout: %s", redir);
1626 /* Redirect stdout & stderr to our response file. */
1627 dup2 (redir_handle, STDOUT_FILENO);
1628 dup2 (redir_handle, STDERR_FILENO);
1631 pexecute_pid = pexecute (argv[0], argv, argv[0], NULL,
1632 &errmsg_fmt, &errmsg_arg,
1633 (PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH));
1637 /* Restore stdout and stderr to their previous settings. */
1638 dup2 (stdout_save, STDOUT_FILENO);
1639 dup2 (stderr_save, STDERR_FILENO);
1641 /* Close reponse file. */
1642 close (redir_handle);
1645 if (pexecute_pid == -1)
1646 fatal_perror (errmsg_fmt, errmsg_arg);
1650 fork_execute (prog, argv)
1654 collect_execute (prog, argv, NULL);
1658 /* Unlink a file unless we are debugging. */
1667 notice ("[Leaving %s]\n", file);
1671 static long sequence_number = 0;
1673 /* Add a name to a linked list. */
1676 add_to_list (head_ptr, name)
1677 struct head *head_ptr;
1681 = (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1);
1683 strcpy (newid->name, name);
1685 if (head_ptr->first)
1686 head_ptr->last->next = newid;
1688 head_ptr->first = newid;
1690 /* Check for duplicate symbols. */
1691 for (p = head_ptr->first;
1692 strcmp (name, p->name) != 0;
1697 head_ptr->last->next = 0;
1702 newid->sequence = ++sequence_number;
1703 head_ptr->last = newid;
1707 /* Grab the init priority number from an init function name that
1708 looks like "_GLOBAL_.I.12345.foo". */
1711 extract_init_priority (name)
1716 while (name[pos] == '_')
1718 pos += 10; /* strlen ("GLOBAL__X_") */
1720 /* Extract init_p number from ctor/dtor name. */
1721 pri = atoi (name + pos);
1722 return pri ? pri : DEFAULT_INIT_PRIORITY;
1725 /* Insertion sort the ids from ctor/dtor list HEAD_PTR in descending order.
1726 ctors will be run from right to left, dtors from left to right. */
1730 struct head *head_ptr;
1732 /* id holds the current element to insert. id_next holds the next
1733 element to insert. id_ptr iterates through the already sorted elements
1734 looking for the place to insert id. */
1735 struct id *id, *id_next, **id_ptr;
1737 id = head_ptr->first;
1739 /* We don't have any sorted elements yet. */
1740 head_ptr->first = NULL;
1742 for (; id; id = id_next)
1745 id->sequence = extract_init_priority (id->name);
1747 for (id_ptr = &(head_ptr->first); ; id_ptr = &((*id_ptr)->next))
1749 /* If the sequence numbers are the same, we put the id from the
1750 file later on the command line later in the list. */
1751 || id->sequence > (*id_ptr)->sequence
1752 /* Hack: do lexical compare, too.
1753 || (id->sequence == (*id_ptr)->sequence
1754 && strcmp (id->name, (*id_ptr)->name) > 0) */
1763 /* Now set the sequence numbers properly so write_c_file works. */
1764 for (id = head_ptr->first; id; id = id->next)
1765 id->sequence = ++sequence_number;
1768 /* Write: `prefix', the names on list LIST, `suffix'. */
1771 write_list (stream, prefix, list)
1778 fprintf (stream, "%sx%d,\n", prefix, list->sequence);
1783 #ifdef COLLECT_EXPORT_LIST
1784 /* This function is really used only on AIX, but may be useful. */
1786 is_in_list (prefix, list)
1792 if (!strcmp (prefix, list->name)) return 1;
1799 /* Added for debugging purpose. */
1800 #ifdef COLLECT_EXPORT_LIST
1802 dump_list (stream, prefix, list)
1809 fprintf (stream, "%s%s,\n", prefix, list->name);
1817 dump_prefix_list (stream, prefix, list)
1820 struct prefix_list *list;
1824 fprintf (stream, "%s%s,\n", prefix, list->prefix);
1831 write_list_with_asm (stream, prefix, list)
1838 fprintf (stream, "%sx%d __asm__ (\"%s\");\n",
1839 prefix, list->sequence, list->name);
1844 /* Write out the constructor and destructor tables statically (for a shared
1845 object), along with the functions to execute them. */
1848 write_c_file_stat (stream, name)
1850 const char *name ATTRIBUTE_UNUSED;
1854 int frames = (frame_tables.number > 0);
1856 /* Figure out name of output_file, stripping off .so version. */
1857 p = strrchr (output_file, '/');
1873 if (strncmp (q, ".so", 3) == 0)
1882 /* q points to null at end of the string (or . of the .so version) */
1883 prefix = xmalloc (q - p + 1);
1884 strncpy (prefix, p, q - p);
1886 for (r = prefix; *r; r++)
1887 if (!ISALNUM ((unsigned char)*r))
1890 notice ("\nwrite_c_file - output name is %s, prefix is %s\n",
1891 output_file, prefix);
1893 #define INIT_NAME_FORMAT "_GLOBAL__FI_%s"
1894 initname = xmalloc (strlen (prefix) + sizeof (INIT_NAME_FORMAT) - 2);
1895 sprintf (initname, INIT_NAME_FORMAT, prefix);
1897 #define FINI_NAME_FORMAT "_GLOBAL__FD_%s"
1898 fininame = xmalloc (strlen (prefix) + sizeof (FINI_NAME_FORMAT) - 2);
1899 sprintf (fininame, FINI_NAME_FORMAT, prefix);
1903 /* Write the tables as C code */
1905 fprintf (stream, "static int count;\n");
1906 fprintf (stream, "typedef void entry_pt();\n");
1907 write_list_with_asm (stream, "extern entry_pt ", constructors.first);
1911 write_list_with_asm (stream, "extern void *", frame_tables.first);
1913 fprintf (stream, "\tstatic void *frame_table[] = {\n");
1914 write_list (stream, "\t\t&", frame_tables.first);
1915 fprintf (stream, "\t0\n};\n");
1917 /* This must match what's in frame.h. */
1918 fprintf (stream, "struct object {\n");
1919 fprintf (stream, " void *pc_begin;\n");
1920 fprintf (stream, " void *pc_end;\n");
1921 fprintf (stream, " void *fde_begin;\n");
1922 fprintf (stream, " void *fde_array;\n");
1923 fprintf (stream, " __SIZE_TYPE__ count;\n");
1924 fprintf (stream, " struct object *next;\n");
1925 fprintf (stream, "};\n");
1927 fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
1928 fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
1930 fprintf (stream, "static void reg_frame () {\n");
1931 fprintf (stream, "\tstatic struct object ob;\n");
1932 fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
1933 fprintf (stream, "\t}\n");
1935 fprintf (stream, "static void dereg_frame () {\n");
1936 fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
1937 fprintf (stream, "\t}\n");
1940 fprintf (stream, "void %s() {\n", initname);
1941 if (constructors.number > 0 || frames)
1943 fprintf (stream, "\tstatic entry_pt *ctors[] = {\n");
1944 write_list (stream, "\t\t", constructors.first);
1946 fprintf (stream, "\treg_frame,\n");
1947 fprintf (stream, "\t};\n");
1948 fprintf (stream, "\tentry_pt **p;\n");
1949 fprintf (stream, "\tif (count++ != 0) return;\n");
1950 fprintf (stream, "\tp = ctors + %d;\n", constructors.number + frames);
1951 fprintf (stream, "\twhile (p > ctors) (*--p)();\n");
1954 fprintf (stream, "\t++count;\n");
1955 fprintf (stream, "}\n");
1956 write_list_with_asm (stream, "extern entry_pt ", destructors.first);
1957 fprintf (stream, "void %s() {\n", fininame);
1958 if (destructors.number > 0 || frames)
1960 fprintf (stream, "\tstatic entry_pt *dtors[] = {\n");
1961 write_list (stream, "\t\t", destructors.first);
1963 fprintf (stream, "\tdereg_frame,\n");
1964 fprintf (stream, "\t};\n");
1965 fprintf (stream, "\tentry_pt **p;\n");
1966 fprintf (stream, "\tif (--count != 0) return;\n");
1967 fprintf (stream, "\tp = dtors;\n");
1968 fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n",
1969 destructors.number + frames);
1971 fprintf (stream, "}\n");
1975 fprintf (stream, "void _GLOBAL__DI() {\n\t%s();\n}\n", initname);
1976 fprintf (stream, "void _GLOBAL__DD() {\n\t%s();\n}\n", fininame);
1980 /* Write the constructor/destructor tables. */
1982 #ifndef LD_INIT_SWITCH
1984 write_c_file_glob (stream, name)
1986 const char *name ATTRIBUTE_UNUSED;
1988 /* Write the tables as C code */
1990 int frames = (frame_tables.number > 0);
1992 fprintf (stream, "typedef void entry_pt();\n\n");
1994 write_list_with_asm (stream, "extern entry_pt ", constructors.first);
1998 write_list_with_asm (stream, "extern void *", frame_tables.first);
2000 fprintf (stream, "\tstatic void *frame_table[] = {\n");
2001 write_list (stream, "\t\t&", frame_tables.first);
2002 fprintf (stream, "\t0\n};\n");
2004 /* This must match what's in frame.h. */
2005 fprintf (stream, "struct object {\n");
2006 fprintf (stream, " void *pc_begin;\n");
2007 fprintf (stream, " void *pc_end;\n");
2008 fprintf (stream, " void *fde_begin;\n");
2009 fprintf (stream, " void *fde_array;\n");
2010 fprintf (stream, " __SIZE_TYPE__ count;\n");
2011 fprintf (stream, " struct object *next;\n");
2012 fprintf (stream, "};\n");
2014 fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
2015 fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
2017 fprintf (stream, "static void reg_frame () {\n");
2018 fprintf (stream, "\tstatic struct object ob;\n");
2019 fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
2020 fprintf (stream, "\t}\n");
2022 fprintf (stream, "static void dereg_frame () {\n");
2023 fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
2024 fprintf (stream, "\t}\n");
2027 fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
2028 fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number + frames);
2029 write_list (stream, "\t", constructors.first);
2031 fprintf (stream, "\treg_frame,\n");
2032 fprintf (stream, "\t0\n};\n\n");
2034 write_list_with_asm (stream, "extern entry_pt ", destructors.first);
2036 fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
2037 fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number + frames);
2038 write_list (stream, "\t", destructors.first);
2040 fprintf (stream, "\tdereg_frame,\n");
2041 fprintf (stream, "\t0\n};\n\n");
2043 fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
2044 fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);
2046 #endif /* ! LD_INIT_SWITCH */
2049 write_c_file (stream, name)
2053 fprintf (stream, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
2054 #ifndef LD_INIT_SWITCH
2056 write_c_file_glob (stream, name);
2059 write_c_file_stat (stream, name);
2060 fprintf (stream, "#ifdef __cplusplus\n}\n#endif\n");
2063 #ifdef COLLECT_EXPORT_LIST
2065 write_aix_file (stream, list)
2069 for (; list; list = list->next)
2071 fputs (list->name, stream);
2072 putc ('\n', stream);
2077 #ifdef OBJECT_FORMAT_NONE
2079 /* Generic version to scan the name list of the loaded program for
2080 the symbols g++ uses for static constructors and destructors.
2082 The constructor table begins at __CTOR_LIST__ and contains a count
2083 of the number of pointers (or -1 if the constructors are built in a
2084 separate section by the linker), followed by the pointers to the
2085 constructor functions, terminated with a null pointer. The
2086 destructor table has the same format, and begins at __DTOR_LIST__. */
2089 scan_prog_file (prog_name, which_pass)
2090 const char *prog_name;
2091 enum pass which_pass;
2093 void (*int_handler) PARAMS ((int));
2094 void (*quit_handler) PARAMS ((int));
2095 char *real_nm_argv[4];
2096 const char **nm_argv = (const char **) real_nm_argv;
2103 if (which_pass == PASS_SECOND)
2106 /* If we do not have an `nm', complain. */
2107 if (nm_file_name == 0)
2108 fatal ("cannot find `nm'");
2110 nm_argv[argc++] = nm_file_name;
2111 if (NM_FLAGS[0] != '\0')
2112 nm_argv[argc++] = NM_FLAGS;
2114 nm_argv[argc++] = prog_name;
2115 nm_argv[argc++] = (char *) 0;
2117 if (pipe (pipe_fd) < 0)
2118 fatal_perror ("pipe");
2120 inf = fdopen (pipe_fd[0], "r");
2121 if (inf == (FILE *) 0)
2122 fatal_perror ("fdopen");
2124 /* Trace if needed. */
2127 const char **p_argv;
2130 for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
2131 fprintf (stderr, " %s", str);
2133 fprintf (stderr, "\n");
2139 /* Spawn child nm on pipe */
2142 fatal_perror (VFORK_STRING);
2144 if (pid == 0) /* child context */
2147 if (dup2 (pipe_fd[1], 1) < 0)
2148 fatal_perror ("dup2 %d 1", pipe_fd[1]);
2150 if (close (pipe_fd[0]) < 0)
2151 fatal_perror ("close %d", pipe_fd[0]);
2153 if (close (pipe_fd[1]) < 0)
2154 fatal_perror ("close %d", pipe_fd[1]);
2156 execv (nm_file_name, real_nm_argv);
2157 fatal_perror ("execvp %s", nm_file_name);
2160 /* Parent context from here on. */
2161 int_handler = (void (*) PARAMS ((int))) signal (SIGINT, SIG_IGN);
2163 quit_handler = (void (*) PARAMS ((int))) signal (SIGQUIT, SIG_IGN);
2166 if (close (pipe_fd[1]) < 0)
2167 fatal_perror ("close %d", pipe_fd[1]);
2170 fprintf (stderr, "\nnm output with constructors/destructors.\n");
2172 /* Read each line of nm output. */
2173 while (fgets (buf, sizeof buf, inf) != (char *) 0)
2178 /* If it contains a constructor or destructor name, add the name
2179 to the appropriate list. */
2181 for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
2182 if (ch == ' ' && p[1] == 'U' && p[2] == ' ')
2189 /* Find the end of the symbol name.
2190 Do not include `|', because Encore nm can tack that on the end. */
2191 for (end = p; (ch2 = *end) != '\0' && !ISSPACE (ch2) && ch2 != '|';
2197 switch (is_ctor_dtor (name))
2200 if (which_pass != PASS_LIB)
2201 add_to_list (&constructors, name);
2205 if (which_pass != PASS_LIB)
2206 add_to_list (&destructors, name);
2210 if (which_pass != PASS_LIB)
2211 fatal ("init function found in object %s", prog_name);
2212 #ifndef LD_INIT_SWITCH
2213 add_to_list (&constructors, name);
2218 if (which_pass != PASS_LIB)
2219 fatal ("fini function found in object %s", prog_name);
2220 #ifndef LD_FINI_SWITCH
2221 add_to_list (&destructors, name);
2226 if (which_pass != PASS_LIB)
2227 add_to_list (&frame_tables, name);
2230 default: /* not a constructor or destructor */
2235 fprintf (stderr, "\t%s\n", buf);
2239 fprintf (stderr, "\n");
2241 if (fclose (inf) != 0)
2242 fatal_perror ("fclose");
2244 do_wait (nm_file_name);
2246 signal (SIGINT, int_handler);
2248 signal (SIGQUIT, quit_handler);
2252 #if SUNOS4_SHARED_LIBRARIES
2254 /* Routines to scan the SunOS 4 _DYNAMIC structure to find shared libraries
2255 that the output file depends upon and their initialization/finalization
2256 routines, if any. */
2261 #include <sys/mman.h>
2262 #include <sys/param.h>
2264 #include <sys/dir.h>
2266 /* pointers to the object file */
2267 unsigned object; /* address of memory mapped file */
2268 unsigned objsize; /* size of memory mapped to file */
2269 char * code; /* pointer to code segment */
2270 char * data; /* pointer to data segment */
2271 struct nlist *symtab; /* pointer to symbol table */
2272 struct link_dynamic *ld;
2273 struct link_dynamic_2 *ld_2;
2274 struct head libraries;
2276 /* Map the file indicated by NAME into memory and store its address. */
2278 static void mapfile PARAMS ((const char *));
2286 if ((fp = open (name, O_RDONLY)) == -1)
2287 fatal ("unable to open file '%s'", name);
2288 if (fstat (fp, &s) == -1)
2289 fatal ("unable to stat file '%s'", name);
2291 objsize = s.st_size;
2292 object = (unsigned) mmap (0, objsize, PROT_READ|PROT_WRITE, MAP_PRIVATE,
2294 if (object == (unsigned)-1)
2295 fatal ("unable to mmap file '%s'", name);
2300 /* Helpers for locatelib. */
2302 static const char *libname;
2304 static int libselect PARAMS ((struct direct *));
2310 return (strncmp (libname, d->d_name, strlen (libname)) == 0);
2313 /* If one file has an additional numeric extension past LIBNAME, then put
2314 that one first in the sort. If both files have additional numeric
2315 extensions, then put the one with the higher number first in the sort.
2317 We must verify that the extension is numeric, because Sun saves the
2318 original versions of patched libraries with a .FCS extension. Files with
2319 invalid extensions must go last in the sort, so that they will not be used. */
2320 static int libcompare PARAMS ((struct direct **, struct direct **));
2324 struct direct **d1, **d2;
2326 int i1, i2 = strlen (libname);
2327 char *e1 = (*d1)->d_name + i2;
2328 char *e2 = (*d2)->d_name + i2;
2330 while (*e1 && *e2 && *e1 == '.' && *e2 == '.'
2331 && e1[1] && ISDIGIT (e1[1]) && e2[1] && ISDIGIT (e2[1]))
2335 i1 = strtol (e1, &e1, 10);
2336 i2 = strtol (e2, &e2, 10);
2343 /* It has a valid numeric extension, prefer this one. */
2344 if (*e1 == '.' && e1[1] && ISDIGIT (e1[1]))
2346 /* It has a invalid numeric extension, must prefer the other one. */
2352 /* It has a valid numeric extension, prefer this one. */
2353 if (*e2 == '.' && e2[1] && ISDIGIT (e2[1]))
2355 /* It has a invalid numeric extension, must prefer the other one. */
2363 /* Given the name NAME of a dynamic dependency, find its pathname and add
2364 it to the list of libraries. */
2365 static void locatelib PARAMS ((const char *));
2371 static const char **l;
2373 char buf[MAXPATHLEN];
2381 /* counting elements in array, need 1 extra for null */
2383 ld_rules = (char *) (ld_2->ld_rules + code);
2387 for (; *ld_rules != 0; ld_rules++)
2388 if (*ld_rules == ':')
2390 ld_rules = (char *) (ld_2->ld_rules + code);
2391 ldr = xstrdup (ld_rules);
2393 p = getenv ("LD_LIBRARY_PATH");
2398 for (q = p ; *q != 0; q++)
2403 l = (const char **) xmalloc ((cnt + 3) * sizeof (char *));
2408 for (; *ldr != 0; ldr++)
2418 for (; *q != 0; q++)
2425 /* built in directories are /lib, /usr/lib, and /usr/local/lib */
2428 *pp++ = "/usr/local/lib";
2432 for (pp = l; *pp != 0 ; pp++)
2434 struct direct **namelist;
2436 if ((entries = scandir (*pp, &namelist, libselect, libcompare)) > 0)
2438 sprintf (buf, "%s/%s", *pp, namelist[entries - 1]->d_name);
2439 add_to_list (&libraries, buf);
2441 fprintf (stderr, "%s\n", buf);
2448 notice ("not found\n");
2450 fatal ("dynamic dependency %s not found", name);
2454 /* Scan the _DYNAMIC structure of the output file to find shared libraries
2455 that it depends upon and any constructors or destructors they contain. */
2458 scan_libraries (prog_name)
2459 const char *prog_name;
2461 struct exec *header;
2463 struct link_object *lo;
2464 char buff[MAXPATHLEN];
2467 mapfile (prog_name);
2468 header = (struct exec *)object;
2469 if (N_BADMAG (*header))
2470 fatal ("bad magic number in file '%s'", prog_name);
2471 if (header->a_dynamic == 0)
2474 code = (char *) (N_TXTOFF (*header) + (long) header);
2475 data = (char *) (N_DATOFF (*header) + (long) header);
2476 symtab = (struct nlist *) (N_SYMOFF (*header) + (long) header);
2478 if (header->a_magic == ZMAGIC && header->a_entry == 0x20)
2481 ld = (struct link_dynamic *) (symtab->n_value + code);
2487 ld = (struct link_dynamic *) data;
2492 notice ("dynamic dependencies.\n");
2494 ld_2 = (struct link_dynamic_2 *) ((long) ld->ld_un.ld_2 + (long)base);
2495 for (lo = (struct link_object *) ld_2->ld_need; lo;
2496 lo = (struct link_object *) lo->lo_next)
2499 lo = (struct link_object *) ((long) lo + code);
2500 name = (char *) (code + lo->lo_name);
2504 fprintf (stderr, "\t-l%s.%d => ", name, lo->lo_major);
2505 sprintf (buff, "lib%s.so.%d.%d", name, lo->lo_major, lo->lo_minor);
2511 fprintf (stderr, "\t%s\n", name);
2512 add_to_list (&libraries, name);
2517 fprintf (stderr, "\n");
2519 /* now iterate through the library list adding their symbols to
2521 for (list = libraries.first; list; list = list->next)
2522 scan_prog_file (list->name, PASS_LIB);
2525 #else /* SUNOS4_SHARED_LIBRARIES */
2528 /* Use the List Dynamic Dependencies program to find shared libraries that
2529 the output file depends upon and their initialization/finalization
2530 routines, if any. */
2533 scan_libraries (prog_name)
2534 const char *prog_name;
2536 static struct head libraries; /* list of shared libraries found */
2538 void (*int_handler) PARAMS ((int));
2539 void (*quit_handler) PARAMS ((int));
2540 char *real_ldd_argv[4];
2541 const char **ldd_argv = (const char **) real_ldd_argv;
2548 /* If we do not have an `ldd', complain. */
2549 if (ldd_file_name == 0)
2551 error ("cannot find `ldd'");
2555 ldd_argv[argc++] = ldd_file_name;
2556 ldd_argv[argc++] = prog_name;
2557 ldd_argv[argc++] = (char *) 0;
2559 if (pipe (pipe_fd) < 0)
2560 fatal_perror ("pipe");
2562 inf = fdopen (pipe_fd[0], "r");
2563 if (inf == (FILE *) 0)
2564 fatal_perror ("fdopen");
2566 /* Trace if needed. */
2569 const char **p_argv;
2572 for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
2573 fprintf (stderr, " %s", str);
2575 fprintf (stderr, "\n");
2581 /* Spawn child ldd on pipe */
2584 fatal_perror (VFORK_STRING);
2586 if (pid == 0) /* child context */
2589 if (dup2 (pipe_fd[1], 1) < 0)
2590 fatal_perror ("dup2 %d 1", pipe_fd[1]);
2592 if (close (pipe_fd[0]) < 0)
2593 fatal_perror ("close %d", pipe_fd[0]);
2595 if (close (pipe_fd[1]) < 0)
2596 fatal_perror ("close %d", pipe_fd[1]);
2598 execv (ldd_file_name, real_ldd_argv);
2599 fatal_perror ("execv %s", ldd_file_name);
2602 /* Parent context from here on. */
2603 int_handler = (void (*) PARAMS ((int))) signal (SIGINT, SIG_IGN);
2605 quit_handler = (void (*) PARAMS ((int))) signal (SIGQUIT, SIG_IGN);
2608 if (close (pipe_fd[1]) < 0)
2609 fatal_perror ("close %d", pipe_fd[1]);
2612 notice ("\nldd output with constructors/destructors.\n");
2614 /* Read each line of ldd output. */
2615 while (fgets (buf, sizeof buf, inf) != (char *) 0)
2618 char *name, *end, *p = buf;
2620 /* Extract names of libraries and add to list. */
2621 PARSE_LDD_OUTPUT (p);
2626 if (strncmp (name, "not found", sizeof ("not found") - 1) == 0)
2627 fatal ("dynamic dependency %s not found", buf);
2629 /* Find the end of the symbol name. */
2631 (ch2 = *end) != '\0' && ch2 != '\n' && !ISSPACE (ch2) && ch2 != '|';
2636 if (access (name, R_OK) == 0)
2637 add_to_list (&libraries, name);
2639 fatal ("unable to open dynamic dependency '%s'", buf);
2642 fprintf (stderr, "\t%s\n", buf);
2645 fprintf (stderr, "\n");
2647 if (fclose (inf) != 0)
2648 fatal_perror ("fclose");
2650 do_wait (ldd_file_name);
2652 signal (SIGINT, int_handler);
2654 signal (SIGQUIT, quit_handler);
2657 /* now iterate through the library list adding their symbols to
2659 for (list = libraries.first; list; list = list->next)
2660 scan_prog_file (list->name, PASS_LIB);
2663 #endif /* LDD_SUFFIX */
2664 #endif /* SUNOS4_SHARED_LIBRARIES */
2666 #endif /* OBJECT_FORMAT_NONE */
2670 * COFF specific stuff.
2673 #ifdef OBJECT_FORMAT_COFF
2675 #if defined(EXTENDED_COFF)
2677 # define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
2678 # define GCC_SYMENT SYMR
2679 # define GCC_OK_SYMBOL(X) ((X).st == stProc || (X).st == stGlobal)
2680 # define GCC_SYMINC(X) (1)
2681 # define GCC_SYMZERO(X) (SYMHEADER(X).isymMax)
2682 # define GCC_CHECK_HDR(X) (PSYMTAB(X) != 0)
2686 # define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms)
2687 # define GCC_SYMENT SYMENT
2688 # define GCC_OK_SYMBOL(X) \
2689 (((X).n_sclass == C_EXT) && \
2690 ((X).n_scnum > N_UNDEF) && \
2692 || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
2693 || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
2694 # define GCC_UNDEF_SYMBOL(X) \
2695 (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF))
2696 # define GCC_SYMINC(X) ((X).n_numaux+1)
2697 # define GCC_SYMZERO(X) 0
2699 /* 0757 = U803XTOCMAGIC (AIX 4.3) and 0767 = U64_TOCMAGIC (AIX V5) */
2701 # define GCC_CHECK_HDR(X) \
2702 ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
2703 || (HEADER (X).f_magic == 0767 && aix64_flag))
2705 # define GCC_CHECK_HDR(X) \
2706 ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
2707 || (HEADER (X).f_magic == 0757 && aix64_flag))
2712 extern char *ldgetname ();
2714 /* COFF version to scan the name list of the loaded program for
2715 the symbols g++ uses for static constructors and destructors.
2717 The constructor table begins at __CTOR_LIST__ and contains a count
2718 of the number of pointers (or -1 if the constructors are built in a
2719 separate section by the linker), followed by the pointers to the
2720 constructor functions, terminated with a null pointer. The
2721 destructor table has the same format, and begins at __DTOR_LIST__. */
2724 scan_prog_file (prog_name, which_pass)
2725 const char *prog_name;
2726 enum pass which_pass;
2728 LDFILE *ldptr = NULL;
2729 int sym_index, sym_count;
2732 if (which_pass != PASS_FIRST && which_pass != PASS_OBJ)
2735 #ifdef COLLECT_EXPORT_LIST
2736 /* We do not need scanning for some standard C libraries. */
2737 if (which_pass == PASS_FIRST && ignore_library (prog_name))
2740 /* On AIX we have a loop, because there is not much difference
2741 between an object and an archive. This trick allows us to
2742 eliminate scan_libraries() function. */
2746 /* Some platforms (e.g. OSF4) declare ldopen as taking a
2747 non-const char * filename parameter, even though it will not
2748 modify that string. So we must cast away const-ness here,
2749 which will cause -Wcast-qual to burp. */
2750 if ((ldptr = ldopen ((char *)prog_name, ldptr)) != NULL)
2752 if (! MY_ISCOFF (HEADER (ldptr).f_magic))
2753 fatal ("%s: not a COFF file", prog_name);
2755 if (GCC_CHECK_HDR (ldptr))
2757 sym_count = GCC_SYMBOLS (ldptr);
2758 sym_index = GCC_SYMZERO (ldptr);
2760 #ifdef COLLECT_EXPORT_LIST
2761 /* Is current archive member a shared object? */
2762 is_shared = HEADER (ldptr).f_flags & F_SHROBJ;
2765 while (sym_index < sym_count)
2769 if (ldtbread (ldptr, sym_index, &symbol) <= 0)
2771 sym_index += GCC_SYMINC (symbol);
2773 if (GCC_OK_SYMBOL (symbol))
2777 if ((name = ldgetname (ldptr, &symbol)) == NULL)
2778 continue; /* should never happen */
2780 #ifdef XCOFF_DEBUGGING_INFO
2781 /* All AIX function names have a duplicate entry
2782 beginning with a dot. */
2787 switch (is_ctor_dtor (name))
2791 add_to_list (&constructors, name);
2792 #ifdef COLLECT_EXPORT_LIST
2793 if (which_pass == PASS_OBJ)
2794 add_to_list (&exports, name);
2800 add_to_list (&destructors, name);
2801 #ifdef COLLECT_EXPORT_LIST
2802 if (which_pass == PASS_OBJ)
2803 add_to_list (&exports, name);
2807 #ifdef COLLECT_EXPORT_LIST
2809 #ifndef LD_INIT_SWITCH
2811 add_to_list (&constructors, name);
2816 #ifndef LD_INIT_SWITCH
2818 add_to_list (&destructors, name);
2825 add_to_list (&frame_tables, name);
2826 #ifdef COLLECT_EXPORT_LIST
2827 if (which_pass == PASS_OBJ)
2828 add_to_list (&exports, name);
2832 default: /* not a constructor or destructor */
2833 #ifdef COLLECT_EXPORT_LIST
2834 /* If we are building a shared object on AIX we need
2835 to explicitly export all global symbols. */
2838 if (which_pass == PASS_OBJ && (! export_flag))
2839 add_to_list (&exports, name);
2846 #if !defined(EXTENDED_COFF)
2847 fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
2848 symbol.n_scnum, symbol.n_sclass,
2849 (symbol.n_type ? "0" : ""), symbol.n_type,
2853 "\tiss = %5d, value = %5ld, index = %5d, name = %s\n",
2854 symbol.iss, (long) symbol.value, symbol.index, name);
2859 #ifdef COLLECT_EXPORT_LIST
2862 /* If archive contains both 32-bit and 64-bit objects,
2863 we want to skip objects in other mode so mismatch normal. */
2865 fprintf (stderr, "%s : magic=%o aix64=%d mismatch\n",
2866 prog_name, HEADER (ldptr).f_magic, aix64_flag);
2872 fatal ("%s: cannot open as COFF file", prog_name);
2874 #ifdef COLLECT_EXPORT_LIST
2875 /* On AIX loop continues while there are more members in archive. */
2877 while (ldclose (ldptr) == FAILURE);
2879 /* Otherwise we simply close ldptr. */
2880 (void) ldclose(ldptr);
2885 #ifdef COLLECT_EXPORT_LIST
2886 /* Given a library name without "lib" prefix, this function
2887 returns a full library name including a path. */
2889 resolve_lib_name (name)
2895 for (i = 0; libpaths[i]; i++)
2896 if (libpaths[i]->max_len > l)
2897 l = libpaths[i]->max_len;
2899 lib_buf = xmalloc (l + strlen(name) + 10);
2901 for (i = 0; libpaths[i]; i++)
2903 struct prefix_list *list = libpaths[i]->plist;
2904 for (; list; list = list->next)
2906 /* The following lines are needed because path_prefix list
2907 may contain directories both with trailing '/' and
2910 if (list->prefix[strlen(list->prefix)-1] != '/')
2912 for (j = 0; libexts[j]; j++)
2914 sprintf (lib_buf, "%s%slib%s.%s",
2915 list->prefix, p, name, libexts[j]);
2916 if (debug) fprintf (stderr, "searching for: %s\n", lib_buf);
2917 if (file_exists (lib_buf))
2919 if (debug) fprintf (stderr, "found: %s\n", lib_buf);
2926 fprintf (stderr, "not found\n");
2928 fatal ("Library lib%s not found", name);
2932 /* Array of standard AIX libraries which should not
2933 be scanned for ctors/dtors. */
2934 static const char *aix_std_libs[] = {
2942 "/usr/lib/libc_r.a",
2943 "/usr/lib/libm_r.a",
2944 "/usr/lib/threads/libc.a",
2945 "/usr/ccs/lib/libc.a",
2946 "/usr/ccs/lib/libm.a",
2947 "/usr/ccs/lib/libc_r.a",
2948 "/usr/ccs/lib/libm_r.a",
2952 /* This function checks the filename and returns 1
2953 if this name matches the location of a standard AIX library. */
2955 ignore_library (name)
2958 const char **p = &aix_std_libs[0];
2959 while (*p++ != NULL)
2960 if (! strcmp (name, *p)) return 1;
2965 #endif /* OBJECT_FORMAT_COFF */
2969 * OSF/rose specific stuff.
2972 #ifdef OBJECT_FORMAT_ROSE
2974 /* Union of the various load commands */
2976 typedef union load_union
2978 ldc_header_t hdr; /* common header */
2979 load_cmd_map_command_t map; /* map indexing other load cmds */
2980 interpreter_command_t iprtr; /* interpreter pathname */
2981 strings_command_t str; /* load commands strings section */
2982 region_command_t region; /* region load command */
2983 reloc_command_t reloc; /* relocation section */
2984 package_command_t pkg; /* package load command */
2985 symbols_command_t sym; /* symbol sections */
2986 entry_command_t ent; /* program start section */
2987 gen_info_command_t info; /* object information */
2988 func_table_command_t func; /* function constructors/destructors */
2991 /* Structure to point to load command and data section in memory. */
2993 typedef struct load_all
2995 load_union_t *load; /* load command */
2996 char *section; /* pointer to section */
2999 /* Structure to contain information about a file mapped into memory. */
3003 char *start; /* start of map */
3004 char *name; /* filename */
3005 long size; /* size of the file */
3006 long rounded_size; /* size rounded to page boundary */
3007 int fd; /* file descriptor */
3008 int rw; /* != 0 if opened read/write */
3009 int use_mmap; /* != 0 if mmap'ed */
3012 extern int decode_mach_o_hdr ();
3013 extern int encode_mach_o_hdr ();
3015 static void add_func_table PARAMS ((mo_header_t *, load_all_t *,
3016 symbol_info_t *, int));
3017 static void print_header PARAMS ((mo_header_t *));
3018 static void print_load_command PARAMS ((load_union_t *, size_t, int));
3019 static void bad_header PARAMS ((int));
3020 static struct file_info *read_file PARAMS ((const char *, int, int));
3021 static void end_file PARAMS ((struct file_info *));
3023 /* OSF/rose specific version to scan the name list of the loaded
3024 program for the symbols g++ uses for static constructors and
3027 The constructor table begins at __CTOR_LIST__ and contains a count
3028 of the number of pointers (or -1 if the constructors are built in a
3029 separate section by the linker), followed by the pointers to the
3030 constructor functions, terminated with a null pointer. The
3031 destructor table has the same format, and begins at __DTOR_LIST__. */
3034 scan_prog_file (prog_name, which_pass)
3035 const char *prog_name;
3036 enum pass which_pass;
3040 load_all_t *load_array;
3041 load_all_t *load_end;
3042 load_all_t *load_cmd;
3043 int symbol_load_cmds;
3049 struct file_info *obj_file;
3051 mo_lcid_t cmd_strings = -1;
3052 symbol_info_t *main_sym = 0;
3053 int rw = (which_pass != PASS_FIRST);
3055 prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY);
3057 fatal_perror ("open %s", prog_name);
3059 obj_file = read_file (prog_name, prog_fd, rw);
3060 obj = obj_file->start;
3062 status = decode_mach_o_hdr (obj, MO_SIZEOF_RAW_HDR, MOH_HEADER_VERSION, &hdr);
3063 if (status != MO_HDR_CONV_SUCCESS)
3064 bad_header (status);
3067 /* Do some basic sanity checks. Note we explicitly use the big endian magic number,
3068 since the hardware will automatically swap bytes for us on loading little endian
3071 #ifndef CROSS_COMPILE
3072 if (hdr.moh_magic != MOH_MAGIC_MSB
3073 || hdr.moh_header_version != MOH_HEADER_VERSION
3074 || hdr.moh_byte_order != OUR_BYTE_ORDER
3075 || hdr.moh_data_rep_id != OUR_DATA_REP_ID
3076 || hdr.moh_cpu_type != OUR_CPU_TYPE
3077 || hdr.moh_cpu_subtype != OUR_CPU_SUBTYPE
3078 || hdr.moh_vendor_type != OUR_VENDOR_TYPE)
3080 fatal ("incompatibilities between object file & expected values");
3085 print_header (&hdr);
3087 offset = hdr.moh_first_cmd_off;
3088 load_end = load_array
3089 = (load_all_t *) xcalloc (sizeof (load_all_t), hdr.moh_n_load_cmds + 2);
3091 /* Build array of load commands, calculating the offsets */
3092 for (i = 0; i < hdr.moh_n_load_cmds; i++)
3094 load_union_t *load_hdr; /* load command header */
3096 load_cmd = load_end++;
3097 load_hdr = (load_union_t *) (obj + offset);
3099 /* If modifying the program file, copy the header. */
3102 load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size);
3103 memcpy ((char *)ptr, (char *)load_hdr, load_hdr->hdr.ldci_cmd_size);
3106 /* null out old command map, because we will rewrite at the end. */
3107 if (ptr->hdr.ldci_cmd_type == LDC_CMD_MAP)
3109 cmd_strings = ptr->map.lcm_ld_cmd_strings;
3110 ptr->hdr.ldci_cmd_type = LDC_UNDEFINED;
3114 load_cmd->load = load_hdr;
3115 if (load_hdr->hdr.ldci_section_off > 0)
3116 load_cmd->section = obj + load_hdr->hdr.ldci_section_off;
3119 print_load_command (load_hdr, offset, i);
3121 offset += load_hdr->hdr.ldci_cmd_size;
3124 /* If the last command is the load command map and is not undefined,
3125 decrement the count of load commands. */
3126 if (rw && load_end[-1].load->hdr.ldci_cmd_type == LDC_UNDEFINED)
3129 hdr.moh_n_load_cmds--;
3132 /* Go through and process each symbol table section. */
3133 symbol_load_cmds = 0;
3134 for (load_cmd = load_array; load_cmd < load_end; load_cmd++)
3136 load_union_t *load_hdr = load_cmd->load;
3138 if (load_hdr->hdr.ldci_cmd_type == LDC_SYMBOLS)
3144 const char *kind = "unknown";
3146 switch (load_hdr->sym.symc_kind)
3148 case SYMC_IMPORTS: kind = "imports"; break;
3149 case SYMC_DEFINED_SYMBOLS: kind = "defined"; break;
3150 case SYMC_STABS: kind = "stabs"; break;
3153 notice ("\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
3154 symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
3157 if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
3160 str_sect = load_array[load_hdr->sym.symc_strings_section].section;
3161 if (str_sect == (char *) 0)
3162 fatal ("string section missing");
3164 if (load_cmd->section == (char *) 0)
3165 fatal ("section pointer missing");
3167 num_syms = load_hdr->sym.symc_nentries;
3168 for (i = 0; i < num_syms; i++)
3170 symbol_info_t *sym = ((symbol_info_t *) load_cmd->section) + i;
3171 char *name = sym->si_name.symbol_name + str_sect;
3178 char *n = name + strlen (name) - strlen (NAME__MAIN);
3180 if ((n - name) < 0 || strcmp (n, NAME__MAIN))
3190 switch (is_ctor_dtor (name))
3193 add_to_list (&constructors, name);
3197 add_to_list (&destructors, name);
3200 default: /* not a constructor or destructor */
3206 fprintf (stderr, "\ttype = 0x%.4x, sc = 0x%.2x, flags = 0x%.8x, name = %.30s\n",
3207 sym->si_type, sym->si_sc_type, sym->si_flags, name);
3212 if (symbol_load_cmds == 0)
3213 fatal ("no symbol table found");
3215 /* Update the program file now, rewrite header and load commands. At present,
3216 we assume that there is enough space after the last load command to insert
3217 one more. Since the first section written out is page aligned, and the
3218 number of load commands is small, this is ok for the present. */
3222 load_union_t *load_map;
3225 if (cmd_strings == -1)
3226 fatal ("no cmd_strings found");
3228 /* Add __main to initializer list.
3229 If we are building a program instead of a shared library, do not
3230 do anything, since in the current version, you cannot do mallocs
3231 and such in the constructors. */
3233 if (main_sym != (symbol_info_t *) 0
3234 && ((hdr.moh_flags & MOH_EXECABLE_F) == 0))
3235 add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION);
3238 notice ("\nUpdating header and load commands.\n\n");
3240 hdr.moh_n_load_cmds++;
3241 size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1));
3243 /* Create new load command map. */
3245 notice ("load command map, %d cmds, new size %ld.\n",
3246 (int) hdr.moh_n_load_cmds, (long) size);
3248 load_map = (load_union_t *) xcalloc (1, size);
3249 load_map->map.ldc_header.ldci_cmd_type = LDC_CMD_MAP;
3250 load_map->map.ldc_header.ldci_cmd_size = size;
3251 load_map->map.lcm_ld_cmd_strings = cmd_strings;
3252 load_map->map.lcm_nentries = hdr.moh_n_load_cmds;
3253 load_array[hdr.moh_n_load_cmds-1].load = load_map;
3255 offset = hdr.moh_first_cmd_off;
3256 for (i = 0; i < hdr.moh_n_load_cmds; i++)
3258 load_map->map.lcm_map[i] = offset;
3259 if (load_array[i].load->hdr.ldci_cmd_type == LDC_CMD_MAP)
3260 hdr.moh_load_map_cmd_off = offset;
3262 offset += load_array[i].load->hdr.ldci_cmd_size;
3265 hdr.moh_sizeofcmds = offset - MO_SIZEOF_RAW_HDR;
3268 print_header (&hdr);
3271 status = encode_mach_o_hdr (&hdr, obj, MO_SIZEOF_RAW_HDR);
3272 if (status != MO_HDR_CONV_SUCCESS)
3273 bad_header (status);
3276 notice ("writing load commands.\n\n");
3278 /* Write load commands */
3279 offset = hdr.moh_first_cmd_off;
3280 for (i = 0; i < hdr.moh_n_load_cmds; i++)
3282 load_union_t *load_hdr = load_array[i].load;
3283 size_t size = load_hdr->hdr.ldci_cmd_size;
3286 print_load_command (load_hdr, offset, i);
3288 bcopy ((char *) load_hdr, (char *) (obj + offset), size);
3293 end_file (obj_file);
3295 if (close (prog_fd))
3296 fatal_perror ("close %s", prog_name);
3299 fprintf (stderr, "\n");
3303 /* Add a function table to the load commands to call a function
3304 on initiation or termination of the process. */
3307 add_func_table (hdr_p, load_array, sym, type)
3308 mo_header_t *hdr_p; /* pointer to global header */
3309 load_all_t *load_array; /* array of ptrs to load cmds */
3310 symbol_info_t *sym; /* pointer to symbol entry */
3311 int type; /* fntc_type value */
3313 /* Add a new load command. */
3314 int num_cmds = ++hdr_p->moh_n_load_cmds;
3315 int load_index = num_cmds - 1;
3316 size_t size = sizeof (func_table_command_t) + sizeof (mo_addr_t);
3317 load_union_t *ptr = xcalloc (1, size);
3318 load_all_t *load_cmd;
3321 /* Set the unresolved address bit in the header to force the loader to be
3322 used, since kernel exec does not call the initialization functions. */
3323 hdr_p->moh_flags |= MOH_UNRESOLVED_F;
3325 load_cmd = &load_array[load_index];
3326 load_cmd->load = ptr;
3327 load_cmd->section = (char *) 0;
3329 /* Fill in func table load command. */
3330 ptr->func.ldc_header.ldci_cmd_type = LDC_FUNC_TABLE;
3331 ptr->func.ldc_header.ldci_cmd_size = size;
3332 ptr->func.ldc_header.ldci_section_off = 0;
3333 ptr->func.ldc_header.ldci_section_len = 0;
3334 ptr->func.fntc_type = type;
3335 ptr->func.fntc_nentries = 1;
3337 /* copy address, turn it from abs. address to (region,offset) if necessary. */
3338 /* Is the symbol already expressed as (region, offset)? */
3339 if ((sym->si_flags & SI_ABSOLUTE_VALUE_F) == 0)
3341 ptr->func.fntc_entry_loc[i].adr_lcid = sym->si_value.def_val.adr_lcid;
3342 ptr->func.fntc_entry_loc[i].adr_sctoff = sym->si_value.def_val.adr_sctoff;
3345 /* If not, figure out which region it's in. */
3348 mo_vm_addr_t addr = sym->si_value.abs_val;
3351 for (i = 0; i < load_index; i++)
3353 if (load_array[i].load->hdr.ldci_cmd_type == LDC_REGION)
3355 region_command_t *region_ptr = &load_array[i].load->region;
3357 if ((region_ptr->regc_flags & REG_ABS_ADDR_F) != 0
3358 && addr >= region_ptr->regc_addr.vm_addr
3359 && addr <= region_ptr->regc_addr.vm_addr + region_ptr->regc_vm_size)
3361 ptr->func.fntc_entry_loc[0].adr_lcid = i;
3362 ptr->func.fntc_entry_loc[0].adr_sctoff = addr - region_ptr->regc_addr.vm_addr;
3370 fatal ("could not convert 0x%l.8x into a region", addr);
3374 notice ("%s function, region %d, offset = %ld (0x%.8lx)\n",
3375 type == FNTC_INITIALIZATION ? "init" : "term",
3376 (int) ptr->func.fntc_entry_loc[i].adr_lcid,
3377 (long) ptr->func.fntc_entry_loc[i].adr_sctoff,
3378 (long) ptr->func.fntc_entry_loc[i].adr_sctoff);
3383 /* Print the global header for an OSF/rose object. */
3386 print_header (hdr_ptr)
3387 mo_header_t *hdr_ptr;
3389 fprintf (stderr, "\nglobal header:\n");
3390 fprintf (stderr, "\tmoh_magic = 0x%.8lx\n", hdr_ptr->moh_magic);
3391 fprintf (stderr, "\tmoh_major_version = %d\n", (int)hdr_ptr->moh_major_version);
3392 fprintf (stderr, "\tmoh_minor_version = %d\n", (int)hdr_ptr->moh_minor_version);
3393 fprintf (stderr, "\tmoh_header_version = %d\n", (int)hdr_ptr->moh_header_version);
3394 fprintf (stderr, "\tmoh_max_page_size = %d\n", (int)hdr_ptr->moh_max_page_size);
3395 fprintf (stderr, "\tmoh_byte_order = %d\n", (int)hdr_ptr->moh_byte_order);
3396 fprintf (stderr, "\tmoh_data_rep_id = %d\n", (int)hdr_ptr->moh_data_rep_id);
3397 fprintf (stderr, "\tmoh_cpu_type = %d\n", (int)hdr_ptr->moh_cpu_type);
3398 fprintf (stderr, "\tmoh_cpu_subtype = %d\n", (int)hdr_ptr->moh_cpu_subtype);
3399 fprintf (stderr, "\tmoh_vendor_type = %d\n", (int)hdr_ptr->moh_vendor_type);
3400 fprintf (stderr, "\tmoh_load_map_cmd_off = %d\n", (int)hdr_ptr->moh_load_map_cmd_off);
3401 fprintf (stderr, "\tmoh_first_cmd_off = %d\n", (int)hdr_ptr->moh_first_cmd_off);
3402 fprintf (stderr, "\tmoh_sizeofcmds = %d\n", (int)hdr_ptr->moh_sizeofcmds);
3403 fprintf (stderr, "\tmon_n_load_cmds = %d\n", (int)hdr_ptr->moh_n_load_cmds);
3404 fprintf (stderr, "\tmoh_flags = 0x%.8lx", (long)hdr_ptr->moh_flags);
3406 if (hdr_ptr->moh_flags & MOH_RELOCATABLE_F)
3407 fprintf (stderr, ", relocatable");
3409 if (hdr_ptr->moh_flags & MOH_LINKABLE_F)
3410 fprintf (stderr, ", linkable");
3412 if (hdr_ptr->moh_flags & MOH_EXECABLE_F)
3413 fprintf (stderr, ", execable");
3415 if (hdr_ptr->moh_flags & MOH_EXECUTABLE_F)
3416 fprintf (stderr, ", executable");
3418 if (hdr_ptr->moh_flags & MOH_UNRESOLVED_F)
3419 fprintf (stderr, ", unresolved");
3421 fprintf (stderr, "\n\n");
3426 /* Print a short summary of a load command. */
3429 print_load_command (load_hdr, offset, number)
3430 load_union_t *load_hdr;
3434 mo_long_t type = load_hdr->hdr.ldci_cmd_type;
3435 const char *type_str = (char *) 0;
3439 case LDC_UNDEFINED: type_str = "UNDEFINED"; break;
3440 case LDC_CMD_MAP: type_str = "CMD_MAP"; break;
3441 case LDC_INTERPRETER: type_str = "INTERPRETER"; break;
3442 case LDC_STRINGS: type_str = "STRINGS"; break;
3443 case LDC_REGION: type_str = "REGION"; break;
3444 case LDC_RELOC: type_str = "RELOC"; break;
3445 case LDC_PACKAGE: type_str = "PACKAGE"; break;
3446 case LDC_SYMBOLS: type_str = "SYMBOLS"; break;
3447 case LDC_ENTRY: type_str = "ENTRY"; break;
3448 case LDC_FUNC_TABLE: type_str = "FUNC_TABLE"; break;
3449 case LDC_GEN_INFO: type_str = "GEN_INFO"; break;
3453 "cmd %2d, sz: 0x%.2lx, coff: 0x%.3lx, doff: 0x%.6lx, dlen: 0x%.6lx",
3455 (long) load_hdr->hdr.ldci_cmd_size,
3457 (long) load_hdr->hdr.ldci_section_off,
3458 (long) load_hdr->hdr.ldci_section_len);
3460 if (type_str == (char *) 0)
3461 fprintf (stderr, ", ty: unknown (%ld)\n", (long) type);
3463 else if (type != LDC_REGION)
3464 fprintf (stderr, ", ty: %s\n", type_str);
3468 const char *region = "";
3469 switch (load_hdr->region.regc_usage_type)
3471 case REG_TEXT_T: region = ", .text"; break;
3472 case REG_DATA_T: region = ", .data"; break;
3473 case REG_BSS_T: region = ", .bss"; break;
3474 case REG_GLUE_T: region = ", .glue"; break;
3475 #if defined (REG_RDATA_T) && defined (REG_SDATA_T) && defined (REG_SBSS_T) /*mips*/
3476 case REG_RDATA_T: region = ", .rdata"; break;
3477 case REG_SDATA_T: region = ", .sdata"; break;
3478 case REG_SBSS_T: region = ", .sbss"; break;
3482 fprintf (stderr, ", ty: %s, vaddr: 0x%.8lx, vlen: 0x%.6lx%s\n",
3484 (long) load_hdr->region.regc_vm_addr,
3485 (long) load_hdr->region.regc_vm_size,
3493 /* Fatal error when {en,de}code_mach_o_header fails. */
3501 case MO_ERROR_BAD_MAGIC: fatal ("bad magic number");
3502 case MO_ERROR_BAD_HDR_VERS: fatal ("bad header version");
3503 case MO_ERROR_BAD_RAW_HDR_VERS: fatal ("bad raw header version");
3504 case MO_ERROR_BUF2SML: fatal ("raw header buffer too small");
3505 case MO_ERROR_OLD_RAW_HDR_FILE: fatal ("old raw header file");
3506 case MO_ERROR_UNSUPPORTED_VERS: fatal ("unsupported version");
3508 fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
3513 /* Read a file into a memory buffer. */
3515 static struct file_info *
3516 read_file (name, fd, rw)
3517 const char *name; /* filename */
3518 int fd; /* file descriptor */
3519 int rw; /* read/write */
3521 struct stat stat_pkt;
3522 struct file_info *p = (struct file_info *) xcalloc (sizeof (struct file_info), 1);
3524 static int page_size;
3527 if (fstat (fd, &stat_pkt) < 0)
3528 fatal_perror ("fstat %s", name);
3531 p->size = stat_pkt.st_size;
3532 p->rounded_size = stat_pkt.st_size;
3538 fprintf (stderr, "mmap %s, %s\n", name, (rw) ? "read/write" : "read-only");
3541 page_size = sysconf (_SC_PAGE_SIZE);
3543 p->rounded_size = ((p->size + page_size - 1) / page_size) * page_size;
3544 p->start = mmap ((caddr_t) 0,
3545 (rw) ? p->rounded_size : p->size,
3546 (rw) ? (PROT_READ | PROT_WRITE) : PROT_READ,
3547 MAP_FILE | MAP_VARIABLE | MAP_SHARED,
3551 if (p->start != (char *) 0 && p->start != (char *) -1)
3555 #endif /* USE_MMAP */
3560 fprintf (stderr, "read %s\n", name);
3563 p->start = xmalloc (p->size);
3564 if (lseek (fd, 0L, SEEK_SET) < 0)
3565 fatal_perror ("lseek %s 0", name);
3567 len = read (fd, p->start, p->size);
3569 fatal_perror ("read %s", name);
3572 fatal ("read %ld bytes, expected %ld, from %s", len, p->size, name);
3578 /* Do anything necessary to write a file back from memory. */
3582 struct file_info *ptr; /* file information block */
3590 fprintf (stderr, "msync %s\n", ptr->name);
3592 if (msync (ptr->start, ptr->rounded_size, MS_ASYNC))
3593 fatal_perror ("msync %s", ptr->name);
3597 fprintf (stderr, "munmap %s\n", ptr->name);
3599 if (munmap (ptr->start, ptr->size))
3600 fatal_perror ("munmap %s", ptr->name);
3603 #endif /* USE_MMAP */
3610 fprintf (stderr, "write %s\n", ptr->name);
3612 if (lseek (ptr->fd, 0L, SEEK_SET) < 0)
3613 fatal_perror ("lseek %s 0", ptr->name);
3615 len = write (ptr->fd, ptr->start, ptr->size);
3617 fatal_perror ("write %s", ptr->name);
3619 if (len != ptr->size)
3620 fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name);
3629 #endif /* OBJECT_FORMAT_ROSE */