1 /* Collect static initialization info into data structures that can be
2 traversed by C++ initialization and finalization routines.
3 Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc.
4 Contributed by Chris Smith (csmith@convex.com).
5 Heavily modified by Michael Meissner (meissner@cygnus.com),
6 Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com).
8 This file is part of GNU CC.
10 GNU CC is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
15 GNU CC is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GNU CC; see the file COPYING. If not, write to
22 the Free Software Foundation, 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
26 /* Build tables of static constructors and destructors and run ld. */
32 #ifdef vfork /* Autoconf may define this to fork for us. */
33 # define VFORK_STRING "fork"
35 # define VFORK_STRING "vfork"
41 #define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \
42 lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1)
52 /* Obstack allocation and deallocation routines. */
53 #define obstack_chunk_alloc xmalloc
54 #define obstack_chunk_free free
56 extern char *make_temp_file PROTO ((char *));
58 /* On certain systems, we have code that works by scanning the object file
59 directly. But this code uses system-specific header files and library
60 functions, so turn it off in a cross-compiler. Likewise, the names of
61 the utilities are not correct for a cross-compiler; we have to hope that
62 cross-versions are in the proper directories. */
65 #undef SUNOS4_SHARED_LIBRARIES
66 #undef OBJECT_FORMAT_COFF
67 #undef OBJECT_FORMAT_ROSE
69 #undef REAL_LD_FILE_NAME
70 #undef REAL_NM_FILE_NAME
71 #undef REAL_STRIP_FILE_NAME
74 /* If we cannot use a special method, use the ordinary one:
75 run nm to find what symbols are present.
76 In a cross-compiler, this means you need a cross nm,
77 but that is not quite as unpleasant as special headers. */
79 #if !defined (OBJECT_FORMAT_COFF) && !defined (OBJECT_FORMAT_ROSE)
80 #define OBJECT_FORMAT_NONE
83 #ifdef OBJECT_FORMAT_COFF
92 /* Many versions of ldfcn.h define these. */
100 /* Some systems have an ISCOFF macro, but others do not. In some cases
101 the macro may be wrong. MY_ISCOFF is defined in tm.h files for machines
102 that either do not have an ISCOFF macro in /usr/include or for those
103 where it is wrong. */
106 #define MY_ISCOFF(X) ISCOFF (X)
109 #endif /* OBJECT_FORMAT_COFF */
111 #ifdef OBJECT_FORMAT_ROSE
118 #include <sys/mman.h>
122 #include <mach_o_format.h>
123 #include <mach_o_header.h>
124 #include <mach_o_vals.h>
125 #include <mach_o_types.h>
127 #endif /* OBJECT_FORMAT_ROSE */
129 #ifdef OBJECT_FORMAT_NONE
131 /* Default flags to pass to nm. */
133 #define NM_FLAGS "-n"
136 #endif /* OBJECT_FORMAT_NONE */
138 /* Some systems use __main in a way incompatible with its use in gcc, in these
139 cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
140 give the same symbol without quotes for an alternative entry point. You
141 must define both, or neither. */
143 #define NAME__MAIN "__main"
144 #define SYMBOL__MAIN __main
147 /* This must match tree.h. */
148 #define DEFAULT_INIT_PRIORITY 65535
150 #if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES
151 #define SCAN_LIBRARIES
155 int do_collecting = 1;
157 int do_collecting = 0;
160 /* Linked lists of constructor and destructor names. */
176 /* Enumeration giving which pass this is for scanning the program file. */
179 PASS_FIRST, /* without constructors */
180 PASS_OBJ, /* individual objects */
181 PASS_LIB, /* looking for shared libraries */
182 PASS_SECOND /* with constructors linked in */
185 extern char *version_string;
187 int vflag; /* true if -v */
188 static int rflag; /* true if -r */
189 static int strip_flag; /* true if -s */
190 #ifdef COLLECT_EXPORT_LIST
191 static int export_flag; /* true if -bE */
192 static int aix64_flag; /* true if -b64 */
195 int debug; /* true if -debug */
197 static int shared_obj; /* true if -shared */
199 static char *c_file; /* <xxx>.c for constructor/destructor list. */
200 static char *o_file; /* <xxx>.o for constructor/destructor list. */
201 #ifdef COLLECT_EXPORT_LIST
202 static char *export_file; /* <xxx>.x for AIX export list. */
203 static char *import_file; /* <xxx>.p for AIX import list. */
205 char *ldout; /* File for ld errors. */
206 static char *output_file; /* Output file for ld. */
207 static char *nm_file_name; /* pathname of nm */
209 static char *ldd_file_name; /* pathname of ldd (or equivalent) */
211 static char *strip_file_name; /* pathname of strip */
212 char *c_file_name; /* pathname of gcc */
213 static char *initname, *fininame; /* names of init and fini funcs */
215 static struct head constructors; /* list of constructors found */
216 static struct head destructors; /* list of destructors found */
217 #ifdef COLLECT_EXPORT_LIST
218 static struct head exports; /* list of exported symbols */
219 static struct head imports; /* list of imported symbols */
220 static struct head undefined; /* list of undefined symbols */
222 static struct head frame_tables; /* list of frame unwind info tables */
224 struct obstack temporary_obstack;
225 struct obstack permanent_obstack;
226 char * temporary_firstobj;
228 /* Holds the return value of pexecute. */
231 /* Defined in the automatically-generated underscore.c. */
232 extern int prepends_underscore;
234 extern FILE *fdopen ();
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 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 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 char *libexts[3] = {"a", "so", NULL}; /* possible library extentions */
266 void error PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1;
267 void fatal PVPROTO((const char *, ...))
268 ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
269 void fatal_perror PVPROTO((const char *, ...))
270 ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
271 static char *my_strerror PROTO((int));
272 static const char *my_strsignal PROTO((int));
273 static void handler PROTO((int));
274 static int is_ctor_dtor PROTO((char *));
275 static char *find_a_file PROTO((struct path_prefix *, char *));
276 static void add_prefix PROTO((struct path_prefix *, char *));
277 static void prefix_from_env PROTO((char *, struct path_prefix *));
278 static void prefix_from_string PROTO((char *, struct path_prefix *));
279 static void do_wait PROTO((char *));
280 static void fork_execute PROTO((char *, char **));
281 static void maybe_unlink PROTO((char *));
282 static void add_to_list PROTO((struct head *, char *));
283 static int extract_init_priority PROTO((char *));
284 static void sort_ids PROTO((struct head *));
285 static void write_list PROTO((FILE *, char *, struct id *));
286 #ifdef COLLECT_EXPORT_LIST
287 static void dump_list PROTO((FILE *, char *, struct id *));
290 static void dump_prefix_list PROTO((FILE *, char *, struct prefix_list *));
292 static void write_list_with_asm PROTO((FILE *, char *, struct id *));
293 static void write_c_file PROTO((FILE *, char *));
294 static void scan_prog_file PROTO((char *, enum pass));
295 #ifdef SCAN_LIBRARIES
296 static void scan_libraries PROTO((char *));
298 #ifdef COLLECT_EXPORT_LIST
299 static int is_in_list PROTO((char *, struct id *));
300 static void write_aix_file PROTO((FILE *, struct id *));
301 static char *resolve_lib_name PROTO((char *));
302 static int use_import_list PROTO((char *));
303 static int ignore_library PROTO((char *));
319 while ((fd = dup (oldfd)) != newfd && fd >= 0) /* good enough for low fd's */
322 close (fdtmp[--fdx]);
341 if (e > 0 && e < sys_nerr)
342 return sys_errlist[e];
352 #ifdef HAVE_STRSIGNAL
353 return strsignal (s);
355 if (s >= 0 && s < NSIG)
357 # ifdef NO_SYS_SIGLIST
358 static char buffer[30];
360 sprintf (buffer, "Unknown signal %d", s);
363 return sys_siglist[s];
368 #endif /* HAVE_STRSIGNAL */
371 /* Delete tempfiles and exit function. */
374 collect_exit (status)
377 if (c_file != 0 && c_file[0])
378 maybe_unlink (c_file);
380 if (o_file != 0 && o_file[0])
381 maybe_unlink (o_file);
383 #ifdef COLLECT_EXPORT_LIST
384 if (export_file != 0 && export_file[0])
385 maybe_unlink (export_file);
387 if (import_file != 0 && import_file[0])
388 maybe_unlink (import_file);
391 if (ldout != 0 && ldout[0])
394 maybe_unlink (ldout);
397 if (status != 0 && output_file != 0 && output_file[0])
398 maybe_unlink (output_file);
404 /* Notify user of a non-error. */
406 notice VPROTO((char *msgid, ...))
408 #ifndef ANSI_PROTOTYPES
413 VA_START (ap, msgid);
415 #ifndef ANSI_PROTOTYPES
416 msgid = va_arg (ap, char *);
419 vfprintf (stderr, _(msgid), ap);
423 /* Die when sys call fails. */
426 fatal_perror VPROTO((const char * msgid, ...))
428 #ifndef ANSI_PROTOTYPES
434 VA_START (ap, msgid);
436 #ifndef ANSI_PROTOTYPES
437 msgid = va_arg (ap, const char *);
440 fprintf (stderr, "collect2: ");
441 vfprintf (stderr, _(msgid), ap);
442 fprintf (stderr, ": %s\n", my_strerror (e));
445 collect_exit (FATAL_EXIT_CODE);
451 fatal VPROTO((const char * msgid, ...))
453 #ifndef ANSI_PROTOTYPES
458 VA_START (ap, msgid);
460 #ifndef ANSI_PROTOTYPES
461 msgid = va_arg (ap, const char *);
464 fprintf (stderr, "collect2: ");
465 vfprintf (stderr, _(msgid), ap);
466 fprintf (stderr, "\n");
469 collect_exit (FATAL_EXIT_CODE);
472 /* Write error message. */
475 error VPROTO((const char * msgid, ...))
477 #ifndef ANSI_PROTOTYPES
482 VA_START (ap, msgid);
484 #ifndef ANSI_PROTOTYPES
485 msgid = va_arg (ap, const char *);
488 fprintf (stderr, "collect2: ");
489 vfprintf (stderr, _(msgid), ap);
490 fprintf (stderr, "\n");
494 /* In case obstack is linked in, and abort is defined to fancy_abort,
495 provide a default entry. */
500 fatal ("internal error");
507 if (c_file != 0 && c_file[0])
508 maybe_unlink (c_file);
510 if (o_file != 0 && o_file[0])
511 maybe_unlink (o_file);
513 if (ldout != 0 && ldout[0])
514 maybe_unlink (ldout);
516 #ifdef COLLECT_EXPORT_LIST
517 if (export_file != 0 && export_file[0])
518 maybe_unlink (export_file);
520 if (import_file != 0 && import_file[0])
521 maybe_unlink (import_file);
524 signal (signo, SIG_DFL);
525 kill (getpid (), signo);
530 xcalloc (size1, size2)
533 PTR ptr = (PTR) calloc (size1, size2);
535 fatal ("out of memory");
543 PTR ptr = (PTR) malloc (size);
545 fatal ("out of memory");
556 ptr = (PTR) realloc (old, size);
558 ptr = (PTR) malloc (size);
560 fatal ("virtual memory exhausted");
568 return access (name, R_OK) == 0;
571 /* Make a copy of a string INPUT with size SIZE. */
577 register size_t len = strlen (input) + 1;
578 register char *output = xmalloc (len);
579 memcpy (output, input, len);
583 /* Parse a reasonable subset of shell quoting syntax. */
600 obstack_1grow (&temporary_obstack, c);
601 else if (! inside && c == ' ')
603 else if (! inside && c == '\\')
608 obstack_1grow (&temporary_obstack, c);
611 obstack_1grow (&temporary_obstack, '\0');
613 return obstack_finish (&temporary_obstack);
620 FILE *stream = fopen (name, "r");
621 int no_demangle = !! getenv ("COLLECT_NO_DEMANGLE");
628 while (c = getc (stream),
629 c != EOF && (ISALNUM (c) || c == '_' || c == '$' || c == '.'))
630 obstack_1grow (&temporary_obstack, c);
631 if (obstack_object_size (&temporary_obstack) > 0)
633 char *word, *p, *result;
634 obstack_1grow (&temporary_obstack, '\0');
635 word = obstack_finish (&temporary_obstack);
638 ++word, putc ('.', stderr);
640 if (*p == '_' && prepends_underscore)
646 result = cplus_demangle (p, DMGL_PARAMS | DMGL_ANSI);
651 fputs (result, stderr);
653 diff = strlen (word) - strlen (result);
655 --diff, putc (' ', stderr);
656 while (diff < 0 && c == ' ')
657 ++diff, c = getc (stream);
662 fputs (word, stderr);
665 obstack_free (&temporary_obstack, temporary_firstobj);
674 /* Decide whether the given symbol is:
675 a constructor (1), a destructor (2), or neither (0). */
681 struct names { char *name; int len; int ret; int two_underscores; };
683 register struct names *p;
685 register char *orig_s = s;
687 static struct names special[] = {
688 #ifdef NO_DOLLAR_IN_LABEL
689 #ifdef NO_DOT_IN_LABEL
690 { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, 1, 0 },
691 { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, 2, 0 },
692 { "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, 5, 0 },
694 { "GLOBAL_.I.", sizeof ("GLOBAL_.I.")-1, 1, 0 },
695 { "GLOBAL_.D.", sizeof ("GLOBAL_.D.")-1, 2, 0 },
696 { "GLOBAL_.F.", sizeof ("GLOBAL_.F.")-1, 5, 0 },
699 { "GLOBAL_$I$", sizeof ("GLOBAL_$I$")-1, 1, 0 },
700 { "GLOBAL_$D$", sizeof ("GLOBAL_$D$")-1, 2, 0 },
701 { "GLOBAL_$F$", sizeof ("GLOBAL_$F$")-1, 5, 0 },
703 { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, 3, 0 },
704 { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, 4, 0 },
705 #ifdef CFRONT_LOSSAGE /* Do not collect cfront initialization functions.
706 cfront has its own linker procedure to collect them;
707 if collect2 gets them too, they get collected twice
708 when the cfront procedure is run and the compiler used
709 for linking happens to be GCC. */
710 { "sti__", sizeof ("sti__")-1, 1, 1 },
711 { "std__", sizeof ("std__")-1, 2, 1 },
712 #endif /* CFRONT_LOSSAGE */
716 while ((ch = *s) == '_')
722 for (p = &special[0]; p->len > 0; p++)
725 && (!p->two_underscores || ((s - orig_s) >= 2))
726 && strncmp(s, p->name, p->len) == 0)
734 /* Routine to add variables to the environment. */
742 #ifndef VMS /* nor about VMS */
744 extern char **environ;
745 char **old_environ = environ;
752 while ((ch = *p++) != '\0' && ch != '=')
758 /* Search for replacing an existing environment variable, and
759 count the number of total environment variables. */
760 for (envp = old_environ; *envp; envp++)
763 if (!strncmp (str, *envp, name_len))
770 /* Add a new environment variable */
771 environ = (char **) xmalloc (sizeof (char *) * (num_envs+2));
773 bcopy ((char *) old_environ, (char *) (environ + 1),
774 sizeof (char *) * (num_envs+1));
780 #endif /* HAVE_PUTENV */
782 /* By default, colon separates directories in a path. */
783 #ifndef PATH_SEPARATOR
784 #define PATH_SEPARATOR ':'
787 /* We maintain two prefix lists: one from COMPILER_PATH environment variable
788 and one from the PATH variable. */
790 static struct path_prefix cpath, path;
793 /* This is the name of the target machine. We use it to form the name
794 of the files to execute. */
796 static char *target_machine = TARGET_MACHINE;
799 /* Search for NAME using prefix list PPREFIX. We only look for executable
802 Return 0 if not found, otherwise return its name, allocated with malloc. */
805 find_a_file (pprefix, name)
806 struct path_prefix *pprefix;
810 struct prefix_list *pl;
811 int len = pprefix->max_len + strlen (name) + 1;
814 fprintf (stderr, "Looking for '%s'\n", name);
816 #ifdef EXECUTABLE_SUFFIX
817 len += strlen (EXECUTABLE_SUFFIX);
820 temp = xmalloc (len);
822 /* Determine the filename to execute (special case for absolute paths). */
825 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
826 || (*name && name[1] == ':')
830 if (access (name, X_OK) == 0)
835 fprintf (stderr, " - found: absolute path\n");
840 #ifdef EXECUTABLE_SUFFIX
841 /* Some systems have a suffix for executable files.
842 So try appending that. */
844 strcat (temp, EXECUTABLE_SUFFIX);
846 if (access (temp, X_OK) == 0)
851 fprintf (stderr, " - failed to locate using absolute path\n");
854 for (pl = pprefix->plist; pl; pl = pl->next)
858 strcpy (temp, pl->prefix);
861 if (stat (temp, &st) >= 0
862 && ! S_ISDIR (st.st_mode)
863 && access (temp, X_OK) == 0)
866 #ifdef EXECUTABLE_SUFFIX
867 /* Some systems have a suffix for executable files.
868 So try appending that. */
869 strcat (temp, EXECUTABLE_SUFFIX);
871 if (stat (temp, &st) >= 0
872 && ! S_ISDIR (st.st_mode)
873 && access (temp, X_OK) == 0)
878 if (debug && pprefix->plist == NULL)
879 fprintf (stderr, " - failed: no entries in prefix list\n");
885 /* Add an entry for PREFIX to prefix list PPREFIX. */
888 add_prefix (pprefix, prefix)
889 struct path_prefix *pprefix;
892 struct prefix_list *pl, **prev;
897 for (pl = pprefix->plist; pl->next; pl = pl->next)
902 prev = &pprefix->plist;
904 /* Keep track of the longest prefix */
906 len = strlen (prefix);
907 if (len > pprefix->max_len)
908 pprefix->max_len = len;
910 pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list));
911 pl->prefix = xstrdup (prefix);
916 pl->next = (struct prefix_list *) 0;
920 /* Take the value of the environment variable ENV, break it into a path, and
921 add of the entries to PPREFIX. */
924 prefix_from_env (env, pprefix)
926 struct path_prefix *pprefix;
929 GET_ENV_PATH_LIST (p, env);
932 prefix_from_string (p, pprefix);
936 prefix_from_string (p, pprefix)
938 struct path_prefix *pprefix;
941 char *nstore = (char *) xmalloc (strlen (p) + 3);
944 fprintf (stderr, "Convert string '%s' into prefixes, separator = '%c'\n", p, PATH_SEPARATOR);
949 if (*endp == PATH_SEPARATOR || *endp == 0)
951 strncpy (nstore, startp, endp-startp);
954 strcpy (nstore, "./");
956 else if (endp[-1] != '/')
958 nstore[endp-startp] = '/';
959 nstore[endp-startp+1] = 0;
962 nstore[endp-startp] = 0;
965 fprintf (stderr, " - add prefix: %s\n", nstore);
967 add_prefix (pprefix, nstore);
970 endp = startp = endp + 1;
984 char *ld_suffix = "ld";
985 char *full_ld_suffix = ld_suffix;
986 char *real_ld_suffix = "real-ld";
987 char *collect_ld_suffix = "collect-ld";
988 char *nm_suffix = "nm";
989 char *full_nm_suffix = nm_suffix;
990 char *gnm_suffix = "gnm";
991 char *full_gnm_suffix = gnm_suffix;
993 char *ldd_suffix = LDD_SUFFIX;
994 char *full_ldd_suffix = ldd_suffix;
996 char *strip_suffix = "strip";
997 char *full_strip_suffix = strip_suffix;
998 char *gstrip_suffix = "gstrip";
999 char *full_gstrip_suffix = gstrip_suffix;
1002 #ifdef COLLECT_EXPORT_LIST
1017 int num_c_args = argc+9;
1019 #if defined (COLLECT2_HOST_INITIALIZATION)
1020 /* Perform system dependant initialization, if neccessary. */
1021 COLLECT2_HOST_INITIALIZATION;
1024 #ifdef HAVE_LC_MESSAGES
1025 setlocale (LC_MESSAGES, "");
1027 (void) bindtextdomain (PACKAGE, localedir);
1028 (void) textdomain (PACKAGE);
1030 /* Do not invoke xcalloc before this point, since locale needs to be
1031 set first, in case a diagnostic is issued. */
1033 ld1 = ld1_argv = (char **) xcalloc (sizeof (char *), argc+3);
1034 ld2 = ld2_argv = (char **) xcalloc (sizeof (char *), argc+6);
1035 object = object_lst = (char **) xcalloc (sizeof (char *), argc);
1041 /* Parse command line early for instances of -debug. This allows
1042 the debug flag to be set before functions like find_a_file()
1047 for (i = 1; argv[i] != NULL; i ++)
1048 if (! strcmp (argv[i], "-debug"))
1053 #ifndef DEFAULT_A_OUT_NAME
1054 output_file = "a.out";
1056 output_file = DEFAULT_A_OUT_NAME;
1059 obstack_begin (&temporary_obstack, 0);
1060 obstack_begin (&permanent_obstack, 0);
1061 temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0);
1063 current_demangling_style = gnu_demangling;
1064 p = getenv ("COLLECT_GCC_OPTIONS");
1067 char *q = extract_string (&p);
1068 if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
1071 obstack_free (&temporary_obstack, temporary_firstobj);
1074 c_ptr = c_argv = (char **) xcalloc (sizeof (char *), num_c_args);
1077 fatal ("no arguments");
1080 if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
1081 signal (SIGQUIT, handler);
1083 if (signal (SIGINT, SIG_IGN) != SIG_IGN)
1084 signal (SIGINT, handler);
1086 if (signal (SIGALRM, SIG_IGN) != SIG_IGN)
1087 signal (SIGALRM, handler);
1090 if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
1091 signal (SIGHUP, handler);
1093 if (signal (SIGSEGV, SIG_IGN) != SIG_IGN)
1094 signal (SIGSEGV, handler);
1096 if (signal (SIGBUS, SIG_IGN) != SIG_IGN)
1097 signal (SIGBUS, handler);
1100 /* Extract COMPILER_PATH and PATH into our prefix list. */
1101 prefix_from_env ("COMPILER_PATH", &cpath);
1102 prefix_from_env ("PATH", &path);
1104 #ifdef CROSS_COMPILE
1105 /* If we look for a program in the compiler directories, we just use
1106 the short name, since these directories are already system-specific.
1107 But it we look for a program in the system directories, we need to
1108 qualify the program name with the target machine. */
1111 = xcalloc (strlen (ld_suffix) + strlen (target_machine) + 2, 1);
1112 strcpy (full_ld_suffix, target_machine);
1113 strcat (full_ld_suffix, "-");
1114 strcat (full_ld_suffix, ld_suffix);
1118 = xcalloc (strlen (gld_suffix) + strlen (target_machine) + 2, 1);
1119 strcpy (full_gld_suffix, target_machine);
1120 strcat (full_gld_suffix, "-");
1121 strcat (full_gld_suffix, gld_suffix);
1125 = xcalloc (strlen (nm_suffix) + strlen (target_machine) + 2, 1);
1126 strcpy (full_nm_suffix, target_machine);
1127 strcat (full_nm_suffix, "-");
1128 strcat (full_nm_suffix, nm_suffix);
1131 = xcalloc (strlen (gnm_suffix) + strlen (target_machine) + 2, 1);
1132 strcpy (full_gnm_suffix, target_machine);
1133 strcat (full_gnm_suffix, "-");
1134 strcat (full_gnm_suffix, gnm_suffix);
1138 = xcalloc (strlen (ldd_suffix) + strlen (target_machine) + 2, 1);
1139 strcpy (full_ldd_suffix, target_machine);
1140 strcat (full_ldd_suffix, "-");
1141 strcat (full_ldd_suffix, ldd_suffix);
1145 = xcalloc (strlen (strip_suffix) + strlen (target_machine) + 2, 1);
1146 strcpy (full_strip_suffix, target_machine);
1147 strcat (full_strip_suffix, "-");
1148 strcat (full_strip_suffix, strip_suffix);
1151 = xcalloc (strlen (gstrip_suffix) + strlen (target_machine) + 2, 1);
1152 strcpy (full_gstrip_suffix, target_machine);
1153 strcat (full_gstrip_suffix, "-");
1154 strcat (full_gstrip_suffix, gstrip_suffix);
1155 #endif /* CROSS_COMPILE */
1157 /* Try to discover a valid linker/nm/strip to use. */
1159 /* Maybe we know the right file to use (if not cross). */
1161 #ifdef DEFAULT_LINKER
1162 if (access (DEFAULT_LINKER, X_OK) == 0)
1163 ld_file_name = DEFAULT_LINKER;
1164 if (ld_file_name == 0)
1166 #ifdef REAL_LD_FILE_NAME
1167 ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME);
1168 if (ld_file_name == 0)
1170 /* Search the (target-specific) compiler dirs for ld'. */
1171 ld_file_name = find_a_file (&cpath, real_ld_suffix);
1172 /* Likewise for `collect-ld'. */
1173 if (ld_file_name == 0)
1174 ld_file_name = find_a_file (&cpath, collect_ld_suffix);
1175 /* Search the compiler directories for `ld'. We have protection against
1176 recursive calls in find_a_file. */
1177 if (ld_file_name == 0)
1178 ld_file_name = find_a_file (&cpath, ld_suffix);
1179 /* Search the ordinary system bin directories
1180 for `ld' (if native linking) or `TARGET-ld' (if cross). */
1181 if (ld_file_name == 0)
1182 ld_file_name = find_a_file (&path, full_ld_suffix);
1184 #ifdef REAL_NM_FILE_NAME
1185 nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME);
1186 if (nm_file_name == 0)
1188 nm_file_name = find_a_file (&cpath, gnm_suffix);
1189 if (nm_file_name == 0)
1190 nm_file_name = find_a_file (&path, full_gnm_suffix);
1191 if (nm_file_name == 0)
1192 nm_file_name = find_a_file (&cpath, nm_suffix);
1193 if (nm_file_name == 0)
1194 nm_file_name = find_a_file (&path, full_nm_suffix);
1197 ldd_file_name = find_a_file (&cpath, ldd_suffix);
1198 if (ldd_file_name == 0)
1199 ldd_file_name = find_a_file (&path, full_ldd_suffix);
1202 #ifdef REAL_STRIP_FILE_NAME
1203 strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME);
1204 if (strip_file_name == 0)
1206 strip_file_name = find_a_file (&cpath, gstrip_suffix);
1207 if (strip_file_name == 0)
1208 strip_file_name = find_a_file (&path, full_gstrip_suffix);
1209 if (strip_file_name == 0)
1210 strip_file_name = find_a_file (&cpath, strip_suffix);
1211 if (strip_file_name == 0)
1212 strip_file_name = find_a_file (&path, full_strip_suffix);
1214 /* Determine the full path name of the C compiler to use. */
1215 c_file_name = getenv ("COLLECT_GCC");
1216 if (c_file_name == 0)
1218 #ifdef CROSS_COMPILE
1219 c_file_name = xcalloc (sizeof ("gcc-") + strlen (target_machine) + 1, 1);
1220 strcpy (c_file_name, target_machine);
1221 strcat (c_file_name, "-gcc");
1223 c_file_name = "gcc";
1227 p = find_a_file (&cpath, c_file_name);
1229 /* Here it should be safe to use the system search path since we should have
1230 already qualified the name of the compiler when it is needed. */
1232 p = find_a_file (&path, c_file_name);
1237 *ld1++ = *ld2++ = ld_file_name;
1239 /* Make temp file names. */
1240 c_file = make_temp_file (".c");
1241 o_file = make_temp_file (".o");
1242 #ifdef COLLECT_EXPORT_LIST
1243 export_file = make_temp_file (".x");
1244 import_file = make_temp_file (".p");
1246 ldout = make_temp_file (".ld");
1247 *c_ptr++ = c_file_name;
1254 #ifdef COLLECT_EXPORT_LIST
1255 /* Generate a list of directories from LIBPATH. */
1256 prefix_from_env ("LIBPATH", &libpath_lib_dirs);
1257 /* Add to this list also two standard directories where
1258 AIX loader always searches for libraries. */
1259 add_prefix (&libpath_lib_dirs, "/lib");
1260 add_prefix (&libpath_lib_dirs, "/usr/lib");
1263 /* Get any options that the upper GCC wants to pass to the sub-GCC.
1265 AIX support needs to know if -shared has been specified before
1266 parsing commandline arguments. */
1268 p = getenv ("COLLECT_GCC_OPTIONS");
1271 char *q = extract_string (&p);
1272 if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
1273 *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
1274 if (strcmp (q, "-EL") == 0 || strcmp (q, "-EB") == 0)
1275 *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
1276 if (strncmp (q, "-shared", sizeof ("-shared") - 1) == 0)
1279 obstack_free (&temporary_obstack, temporary_firstobj);
1280 *c_ptr++ = "-fno-exceptions";
1282 /* !!! When GCC calls collect2,
1283 it does not know whether it is calling collect2 or ld.
1284 So collect2 cannot meaningfully understand any options
1285 except those ld understands.
1286 If you propose to make GCC pass some other option,
1287 just imagine what will happen if ld is really ld!!! */
1289 /* Parse arguments. Remember output file spec, pass the rest to ld. */
1290 /* After the first file, put in the c++ rt0. */
1293 while ((arg = *++argv) != (char *) 0)
1295 *ld1++ = *ld2++ = arg;
1301 #ifdef COLLECT_EXPORT_LIST
1302 /* We want to disable automatic exports on AIX when user
1303 explicitly puts an export list in command line */
1305 if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0)
1307 else if (arg[2] == '6' && arg[3] == '4')
1313 if (!strcmp (arg, "-debug"))
1315 /* Already parsed. */
1324 /* place o_file BEFORE this argument! */
1330 #ifdef COLLECT_EXPORT_LIST
1332 /* Resolving full library name. */
1333 char *s = resolve_lib_name (arg+2);
1335 /* If we will use an import list for this library,
1336 we should exclude it from ld args. */
1337 if (use_import_list (s))
1343 /* Saving a full library name. */
1344 add_to_list (&libs, s);
1349 #ifdef COLLECT_EXPORT_LIST
1350 /* Saving directories where to search for libraries. */
1352 add_prefix (&cmdline_lib_dirs, arg+2);
1358 output_file = *ld1++ = *ld2++ = *++argv;
1360 output_file = &arg[2];
1369 if (arg[2] == '\0' && do_collecting)
1371 /* We must strip after the nm run, otherwise C++ linking
1372 will not work. Thus we strip in the second ld run, or
1373 else with strip if there is no second ld run. */
1385 else if ((p = rindex (arg, '.')) != (char *) 0
1386 && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0
1387 || strcmp (p, ".so") == 0))
1396 /* place o_file BEFORE this argument! */
1404 #ifdef COLLECT_EXPORT_LIST
1405 /* libraries can be specified directly, i.e. without -l flag. */
1408 /* If we will use an import list for this library,
1409 we should exclude it from ld args. */
1410 if (use_import_list (arg))
1416 /* Saving a full library name. */
1417 add_to_list (&libs, arg);
1423 #ifdef COLLECT_EXPORT_LIST
1424 /* This is added only for debugging purposes. */
1427 fprintf (stderr, "List of libraries:\n");
1428 dump_list (stderr, "\t", libs.first);
1431 /* The AIX linker will discard static constructors in object files if
1432 nothing else in the file is referenced, so look at them first. */
1434 char **export_object_lst = object_lst;
1436 while (export_object_lst < object)
1437 scan_prog_file (*export_object_lst++, PASS_OBJ);
1440 struct id *list = libs.first;
1442 for (; list; list = list->next)
1443 scan_prog_file (list->name, PASS_FIRST);
1448 char *buf = xmalloc (strlen (export_file) + 5);
1450 sprintf (buf, "-bE:%s", export_file);
1454 exportf = fopen (export_file, "w");
1455 if (exportf == (FILE *) 0)
1456 fatal_perror ("fopen %s", export_file);
1457 write_aix_file (exportf, exports.first);
1458 if (fclose (exportf))
1459 fatal_perror ("fclose %s", export_file);
1464 char *buf = xmalloc (strlen (import_file) + 5);
1466 sprintf (buf, "-bI:%s", import_file);
1470 importf = fopen (import_file, "w");
1471 if (importf == (FILE *) 0)
1472 fatal_perror ("%s", import_file);
1473 fputs ("#! .\n", importf);
1474 write_aix_file (importf, imports.first);
1475 if (fclose (importf))
1476 fatal_perror ("fclose %s", import_file);
1481 *object = *c_ptr = *ld1 = (char *) 0;
1485 notice ("collect2 version %s", version_string);
1486 #ifdef TARGET_VERSION
1489 fprintf (stderr, "\n");
1495 fprintf (stderr, "ld_file_name = %s\n",
1496 (ld_file_name ? ld_file_name : "not found"));
1497 fprintf (stderr, "c_file_name = %s\n",
1498 (c_file_name ? c_file_name : "not found"));
1499 fprintf (stderr, "nm_file_name = %s\n",
1500 (nm_file_name ? nm_file_name : "not found"));
1502 fprintf (stderr, "ldd_file_name = %s\n",
1503 (ldd_file_name ? ldd_file_name : "not found"));
1505 fprintf (stderr, "strip_file_name = %s\n",
1506 (strip_file_name ? strip_file_name : "not found"));
1507 fprintf (stderr, "c_file = %s\n",
1508 (c_file ? c_file : "not found"));
1509 fprintf (stderr, "o_file = %s\n",
1510 (o_file ? o_file : "not found"));
1512 ptr = getenv ("COLLECT_GCC_OPTIONS");
1514 fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
1516 ptr = getenv ("COLLECT_GCC");
1518 fprintf (stderr, "COLLECT_GCC = %s\n", ptr);
1520 ptr = getenv ("COMPILER_PATH");
1522 fprintf (stderr, "COMPILER_PATH = %s\n", ptr);
1524 ptr = getenv ("LIBRARY_PATH");
1526 fprintf (stderr, "LIBRARY_PATH = %s\n", ptr);
1528 fprintf (stderr, "\n");
1531 /* Load the program, searching all libraries and attempting to provide
1532 undefined symbols from repository information. */
1534 /* On AIX we do this later. */
1535 #ifndef COLLECT_EXPORT_LIST
1536 do_tlink (ld1_argv, object_lst);
1539 /* If -r or they will be run via some other method, do not build the
1540 constructor or destructor list, just return now. */
1542 #ifndef COLLECT_EXPORT_LIST
1547 #ifdef COLLECT_EXPORT_LIST
1548 /* But make sure we delete the export file we may have created. */
1549 if (export_file != 0 && export_file[0])
1550 maybe_unlink (export_file);
1551 if (import_file != 0 && import_file[0])
1552 maybe_unlink (import_file);
1554 maybe_unlink (c_file);
1555 maybe_unlink (o_file);
1559 /* Examine the namelist with nm and search it for static constructors
1560 and destructors to call.
1561 Write the constructor and destructor tables to a .s file and reload. */
1563 /* On AIX we already scanned for global constructors/destructors. */
1564 #ifndef COLLECT_EXPORT_LIST
1565 scan_prog_file (output_file, PASS_FIRST);
1568 #ifdef SCAN_LIBRARIES
1569 scan_libraries (output_file);
1574 notice ("%d constructor(s) found\n", constructors.number);
1575 notice ("%d destructor(s) found\n", destructors.number);
1576 notice ("%d frame table(s) found\n", frame_tables.number);
1579 if (constructors.number == 0 && destructors.number == 0
1580 && frame_tables.number == 0
1581 #if defined (SCAN_LIBRARIES) || defined (COLLECT_EXPORT_LIST)
1582 /* If we will be running these functions ourselves, we want to emit
1583 stubs into the shared library so that we do not have to relink
1584 dependent programs when we add static objects. */
1589 #ifdef COLLECT_EXPORT_LIST
1590 /* Do tlink without additional code generation */
1591 do_tlink (ld1_argv, object_lst);
1593 /* Strip now if it was requested on the command line. */
1596 char **strip_argv = (char **) xcalloc (sizeof (char *), 3);
1597 strip_argv[0] = strip_file_name;
1598 strip_argv[1] = output_file;
1599 strip_argv[2] = (char *) 0;
1600 fork_execute ("strip", strip_argv);
1603 #ifdef COLLECT_EXPORT_LIST
1604 maybe_unlink (export_file);
1605 maybe_unlink (import_file);
1607 maybe_unlink (c_file);
1608 maybe_unlink (o_file);
1612 /* Sort ctor and dtor lists by priority. */
1613 sort_ids (&constructors);
1614 sort_ids (&destructors);
1616 maybe_unlink(output_file);
1617 outf = fopen (c_file, "w");
1618 if (outf == (FILE *) 0)
1619 fatal_perror ("fopen %s", c_file);
1621 write_c_file (outf, c_file);
1624 fatal_perror ("fclose %s", c_file);
1626 /* Tell the linker that we have initializer and finalizer functions. */
1627 #ifdef LD_INIT_SWITCH
1628 *ld2++ = LD_INIT_SWITCH;
1630 *ld2++ = LD_FINI_SWITCH;
1634 #ifdef COLLECT_EXPORT_LIST
1637 /* If we did not add export flag to link arguments before, add it to
1638 second link phase now. No new exports should have been added. */
1639 if (! exports.first)
1641 char *buf = xmalloc (strlen (export_file) + 5);
1643 sprintf (buf, "-bE:%s", export_file);
1647 add_to_list (&exports, initname);
1648 add_to_list (&exports, fininame);
1649 add_to_list (&exports, "_GLOBAL__DI");
1650 add_to_list (&exports, "_GLOBAL__DD");
1651 exportf = fopen (export_file, "w");
1652 if (exportf == (FILE *) 0)
1653 fatal_perror ("fopen %s", export_file);
1654 write_aix_file (exportf, exports.first);
1655 if (fclose (exportf))
1656 fatal_perror ("fclose %s", export_file);
1660 /* End of arguments to second link phase. */
1665 fprintf (stderr, "\n========== output_file = %s, c_file = %s\n",
1666 output_file, c_file);
1667 write_c_file (stderr, "stderr");
1668 fprintf (stderr, "========== end of c_file\n\n");
1669 #ifdef COLLECT_EXPORT_LIST
1670 fprintf (stderr, "\n========== export_file = %s\n", export_file);
1671 write_aix_file (stderr, exports.first);
1672 fprintf (stderr, "========== end of export_file\n\n");
1676 /* Assemble the constructor and destructor tables.
1677 Link the tables in with the rest of the program. */
1679 fork_execute ("gcc", c_argv);
1680 #ifdef COLLECT_EXPORT_LIST
1681 /* On AIX we must call tlink because of possible templates resolution */
1682 do_tlink (ld2_argv, object_lst);
1684 /* Otherwise, simply call ld because tlink is already done */
1685 fork_execute ("ld", ld2_argv);
1687 /* Let scan_prog_file do any final mods (OSF/rose needs this for
1688 constructors/destructors in shared libraries. */
1689 scan_prog_file (output_file, PASS_SECOND);
1692 maybe_unlink (c_file);
1693 maybe_unlink (o_file);
1695 #ifdef COLLECT_EXPORT_LIST
1696 maybe_unlink (export_file);
1697 maybe_unlink (import_file);
1704 /* Wait for a process to finish, and exit if a non-zero status is found. */
1712 pwait (pexecute_pid, &status, 0);
1715 if (WIFSIGNALED (status))
1717 int sig = WTERMSIG (status);
1718 error ((status & 0200
1719 ? "%s terminated with signal %d [%s]"
1720 : "%s terminated with signal %d [%s], core dumped"),
1724 collect_exit (FATAL_EXIT_CODE);
1727 if (WIFEXITED (status))
1728 return WEXITSTATUS (status);
1737 int ret = collect_wait (prog);
1740 error ("%s returned %d exit status", prog, ret);
1746 /* Execute a program, and wait for the reply. */
1749 collect_execute (prog, argv, redir)
1756 int redir_handle = -1;
1757 int stdout_save = -1;
1758 int stderr_save = -1;
1766 fprintf (stderr, "%s", argv[0]);
1768 notice ("[cannot find %s]", prog);
1770 for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++)
1771 fprintf (stderr, " %s", str);
1773 fprintf (stderr, "\n");
1779 /* If we cannot find a program we need, complain error. Do this here
1780 since we might not end up needing something that we could not find. */
1783 fatal ("cannot find `%s'", prog);
1787 /* Open response file. */
1788 redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT);
1790 /* Duplicate the stdout and stderr file handles
1791 so they can be restored later. */
1792 stdout_save = dup (STDOUT_FILENO);
1793 if (stdout_save == -1)
1794 fatal_perror ("redirecting stdout: %s", redir);
1795 stderr_save = dup (STDERR_FILENO);
1796 if (stderr_save == -1)
1797 fatal_perror ("redirecting stdout: %s", redir);
1799 /* Redirect stdout & stderr to our response file. */
1800 dup2 (redir_handle, STDOUT_FILENO);
1801 dup2 (redir_handle, STDERR_FILENO);
1804 pexecute_pid = pexecute (argv[0], argv, argv[0], NULL,
1805 &errmsg_fmt, &errmsg_arg,
1806 (PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH));
1810 /* Restore stdout and stderr to their previous settings. */
1811 dup2 (stdout_save, STDOUT_FILENO);
1812 dup2 (stderr_save, STDERR_FILENO);
1814 /* Close reponse file. */
1815 close (redir_handle);
1818 if (pexecute_pid == -1)
1819 fatal_perror (errmsg_fmt, errmsg_arg);
1823 fork_execute (prog, argv)
1827 collect_execute (prog, argv, NULL);
1831 /* Unlink a file unless we are debugging. */
1840 notice ("[Leaving %s]\n", file);
1844 static long sequence_number = 0;
1846 /* Add a name to a linked list. */
1849 add_to_list (head_ptr, name)
1850 struct head *head_ptr;
1854 = (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1);
1856 strcpy (newid->name, name);
1858 if (head_ptr->first)
1859 head_ptr->last->next = newid;
1861 head_ptr->first = newid;
1863 /* Check for duplicate symbols. */
1864 for (p = head_ptr->first;
1865 strcmp (name, p->name) != 0;
1870 head_ptr->last->next = 0;
1875 newid->sequence = ++sequence_number;
1876 head_ptr->last = newid;
1880 /* Grab the init priority number from an init function name that
1881 looks like "_GLOBAL_.I.12345.foo". */
1884 extract_init_priority (name)
1889 while (name[pos] == '_')
1891 pos += 10; /* strlen ("GLOBAL__X_") */
1893 /* Extract init_p number from ctor/dtor name. */
1894 pri = atoi (name + pos);
1895 return pri ? pri : DEFAULT_INIT_PRIORITY;
1898 /* Insertion sort the ids from ctor/dtor list HEAD_PTR in descending order.
1899 ctors will be run from right to left, dtors from left to right. */
1903 struct head *head_ptr;
1905 /* id holds the current element to insert. id_next holds the next
1906 element to insert. id_ptr iterates through the already sorted elements
1907 looking for the place to insert id. */
1908 struct id *id, *id_next, **id_ptr;
1910 id = head_ptr->first;
1912 /* We don't have any sorted elements yet. */
1913 head_ptr->first = NULL;
1915 for (; id; id = id_next)
1918 id->sequence = extract_init_priority (id->name);
1920 for (id_ptr = &(head_ptr->first); ; id_ptr = &((*id_ptr)->next))
1922 /* If the sequence numbers are the same, we put the id from the
1923 file later on the command line later in the list. */
1924 || id->sequence > (*id_ptr)->sequence
1925 /* Hack: do lexical compare, too.
1926 || (id->sequence == (*id_ptr)->sequence
1927 && strcmp (id->name, (*id_ptr)->name) > 0) */
1936 /* Now set the sequence numbers properly so write_c_file works. */
1937 for (id = head_ptr->first; id; id = id->next)
1938 id->sequence = ++sequence_number;
1941 /* Write: `prefix', the names on list LIST, `suffix'. */
1944 write_list (stream, prefix, list)
1951 fprintf (stream, "%sx%d,\n", prefix, list->sequence);
1956 #ifdef COLLECT_EXPORT_LIST
1957 /* This function is really used only on AIX, but may be useful. */
1959 is_in_list (prefix, list)
1965 if (!strcmp (prefix, list->name)) return 1;
1972 /* Added for debugging purpose. */
1973 #ifdef COLLECT_EXPORT_LIST
1975 dump_list (stream, prefix, list)
1982 fprintf (stream, "%s%s,\n", prefix, list->name);
1990 dump_prefix_list (stream, prefix, list)
1993 struct prefix_list *list;
1997 fprintf (stream, "%s%s,\n", prefix, list->prefix);
2004 write_list_with_asm (stream, prefix, list)
2011 fprintf (stream, "%sx%d __asm__ (\"%s\");\n",
2012 prefix, list->sequence, list->name);
2017 /* Write out the constructor and destructor tables statically (for a shared
2018 object), along with the functions to execute them. */
2021 write_c_file_stat (stream, name)
2025 char *prefix, *p, *q;
2026 int frames = (frame_tables.number > 0);
2028 /* Figure out name of output_file, stripping off .so version. */
2029 p = rindex (output_file, '/');
2031 p = (char *) output_file;
2045 if (strncmp (q, ".so", 3) == 0)
2054 /* q points to null at end of the string (or . of the .so version) */
2055 prefix = xmalloc (q - p + 1);
2056 strncpy (prefix, p, q - p);
2058 for (q = prefix; *q; q++)
2059 if (!ISALNUM ((unsigned char)*q))
2062 notice ("\nwrite_c_file - output name is %s, prefix is %s\n",
2063 output_file, prefix);
2065 #define INIT_NAME_FORMAT "_GLOBAL__FI_%s"
2066 initname = xmalloc (strlen (prefix) + sizeof (INIT_NAME_FORMAT) - 2);
2067 sprintf (initname, INIT_NAME_FORMAT, prefix);
2069 #define FINI_NAME_FORMAT "_GLOBAL__FD_%s"
2070 fininame = xmalloc (strlen (prefix) + sizeof (FINI_NAME_FORMAT) - 2);
2071 sprintf (fininame, FINI_NAME_FORMAT, prefix);
2075 /* Write the tables as C code */
2077 fprintf (stream, "static int count;\n");
2078 fprintf (stream, "typedef void entry_pt();\n");
2079 write_list_with_asm (stream, "extern entry_pt ", constructors.first);
2083 write_list_with_asm (stream, "extern void *", frame_tables.first);
2085 fprintf (stream, "\tstatic void *frame_table[] = {\n");
2086 write_list (stream, "\t\t&", frame_tables.first);
2087 fprintf (stream, "\t0\n};\n");
2089 /* This must match what's in frame.h. */
2090 fprintf (stream, "struct object {\n");
2091 fprintf (stream, " void *pc_begin;\n");
2092 fprintf (stream, " void *pc_end;\n");
2093 fprintf (stream, " void *fde_begin;\n");
2094 fprintf (stream, " void *fde_array;\n");
2095 fprintf (stream, " __SIZE_TYPE__ count;\n");
2096 fprintf (stream, " struct object *next;\n");
2097 fprintf (stream, "};\n");
2099 fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
2100 fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
2102 fprintf (stream, "static void reg_frame () {\n");
2103 fprintf (stream, "\tstatic struct object ob;\n");
2104 fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
2105 fprintf (stream, "\t}\n");
2107 fprintf (stream, "static void dereg_frame () {\n");
2108 fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
2109 fprintf (stream, "\t}\n");
2112 fprintf (stream, "void %s() {\n", initname);
2113 if (constructors.number > 0 || frames)
2115 fprintf (stream, "\tstatic entry_pt *ctors[] = {\n");
2116 write_list (stream, "\t\t", constructors.first);
2118 fprintf (stream, "\treg_frame,\n");
2119 fprintf (stream, "\t};\n");
2120 fprintf (stream, "\tentry_pt **p;\n");
2121 fprintf (stream, "\tif (count++ != 0) return;\n");
2122 fprintf (stream, "\tp = ctors + %d;\n", constructors.number + frames);
2123 fprintf (stream, "\twhile (p > ctors) (*--p)();\n");
2126 fprintf (stream, "\t++count;\n");
2127 fprintf (stream, "}\n");
2128 write_list_with_asm (stream, "extern entry_pt ", destructors.first);
2129 fprintf (stream, "void %s() {\n", fininame);
2130 if (destructors.number > 0 || frames)
2132 fprintf (stream, "\tstatic entry_pt *dtors[] = {\n");
2133 write_list (stream, "\t\t", destructors.first);
2135 fprintf (stream, "\tdereg_frame,\n");
2136 fprintf (stream, "\t};\n");
2137 fprintf (stream, "\tentry_pt **p;\n");
2138 fprintf (stream, "\tif (--count != 0) return;\n");
2139 fprintf (stream, "\tp = dtors;\n");
2140 fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n",
2141 destructors.number + frames);
2143 fprintf (stream, "}\n");
2147 fprintf (stream, "void _GLOBAL__DI() {\n\t%s();\n}\n", initname);
2148 fprintf (stream, "void _GLOBAL__DD() {\n\t%s();\n}\n", fininame);
2152 /* Write the constructor/destructor tables. */
2154 #ifndef LD_INIT_SWITCH
2156 write_c_file_glob (stream, name)
2160 /* Write the tables as C code */
2162 int frames = (frame_tables.number > 0);
2164 fprintf (stream, "typedef void entry_pt();\n\n");
2166 write_list_with_asm (stream, "extern entry_pt ", constructors.first);
2170 write_list_with_asm (stream, "extern void *", frame_tables.first);
2172 fprintf (stream, "\tstatic void *frame_table[] = {\n");
2173 write_list (stream, "\t\t&", frame_tables.first);
2174 fprintf (stream, "\t0\n};\n");
2176 /* This must match what's in frame.h. */
2177 fprintf (stream, "struct object {\n");
2178 fprintf (stream, " void *pc_begin;\n");
2179 fprintf (stream, " void *pc_end;\n");
2180 fprintf (stream, " void *fde_begin;\n");
2181 fprintf (stream, " void *fde_array;\n");
2182 fprintf (stream, " __SIZE_TYPE__ count;\n");
2183 fprintf (stream, " struct object *next;\n");
2184 fprintf (stream, "};\n");
2186 fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
2187 fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
2189 fprintf (stream, "static void reg_frame () {\n");
2190 fprintf (stream, "\tstatic struct object ob;\n");
2191 fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
2192 fprintf (stream, "\t}\n");
2194 fprintf (stream, "static void dereg_frame () {\n");
2195 fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
2196 fprintf (stream, "\t}\n");
2199 fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
2200 fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number + frames);
2201 write_list (stream, "\t", constructors.first);
2203 fprintf (stream, "\treg_frame,\n");
2204 fprintf (stream, "\t0\n};\n\n");
2206 write_list_with_asm (stream, "extern entry_pt ", destructors.first);
2208 fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
2209 fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number + frames);
2210 write_list (stream, "\t", destructors.first);
2212 fprintf (stream, "\tdereg_frame,\n");
2213 fprintf (stream, "\t0\n};\n\n");
2215 fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
2216 fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);
2218 #endif /* ! LD_INIT_SWITCH */
2221 write_c_file (stream, name)
2225 fprintf (stream, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
2226 #ifndef LD_INIT_SWITCH
2228 write_c_file_glob (stream, name);
2231 write_c_file_stat (stream, name);
2232 fprintf (stream, "#ifdef __cplusplus\n}\n#endif\n");
2235 #ifdef COLLECT_EXPORT_LIST
2237 write_aix_file (stream, list)
2241 for (; list; list = list->next)
2243 fputs (list->name, stream);
2244 putc ('\n', stream);
2249 #ifdef OBJECT_FORMAT_NONE
2251 /* Generic version to scan the name list of the loaded program for
2252 the symbols g++ uses for static constructors and destructors.
2254 The constructor table begins at __CTOR_LIST__ and contains a count
2255 of the number of pointers (or -1 if the constructors are built in a
2256 separate section by the linker), followed by the pointers to the
2257 constructor functions, terminated with a null pointer. The
2258 destructor table has the same format, and begins at __DTOR_LIST__. */
2261 scan_prog_file (prog_name, which_pass)
2263 enum pass which_pass;
2265 void (*int_handler) ();
2266 void (*quit_handler) ();
2274 if (which_pass == PASS_SECOND)
2277 /* If we do not have an `nm', complain. */
2278 if (nm_file_name == 0)
2279 fatal ("cannot find `nm'");
2281 nm_argv[argc++] = nm_file_name;
2282 if (NM_FLAGS[0] != '\0')
2283 nm_argv[argc++] = NM_FLAGS;
2285 nm_argv[argc++] = prog_name;
2286 nm_argv[argc++] = (char *) 0;
2288 if (pipe (pipe_fd) < 0)
2289 fatal_perror ("pipe");
2291 inf = fdopen (pipe_fd[0], "r");
2292 if (inf == (FILE *) 0)
2293 fatal_perror ("fdopen");
2295 /* Trace if needed. */
2301 for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
2302 fprintf (stderr, " %s", str);
2304 fprintf (stderr, "\n");
2310 /* Spawn child nm on pipe */
2313 fatal_perror (VFORK_STRING);
2315 if (pid == 0) /* child context */
2318 if (dup2 (pipe_fd[1], 1) < 0)
2319 fatal_perror ("dup2 %d 1", pipe_fd[1]);
2321 if (close (pipe_fd[0]) < 0)
2322 fatal_perror ("close %d", pipe_fd[0]);
2324 if (close (pipe_fd[1]) < 0)
2325 fatal_perror ("close %d", pipe_fd[1]);
2327 execv (nm_file_name, nm_argv);
2328 fatal_perror ("execvp %s", nm_file_name);
2331 /* Parent context from here on. */
2332 int_handler = (void (*) ())signal (SIGINT, SIG_IGN);
2334 quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN);
2337 if (close (pipe_fd[1]) < 0)
2338 fatal_perror ("close %d", pipe_fd[1]);
2341 fprintf (stderr, "\nnm output with constructors/destructors.\n");
2343 /* Read each line of nm output. */
2344 while (fgets (buf, sizeof buf, inf) != (char *) 0)
2349 /* If it contains a constructor or destructor name, add the name
2350 to the appropriate list. */
2352 for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
2353 if (ch == ' ' && p[1] == 'U' && p[2] == ' ')
2360 /* Find the end of the symbol name.
2361 Do not include `|', because Encore nm can tack that on the end. */
2362 for (end = p; (ch2 = *end) != '\0' && !ISSPACE (ch2) && ch2 != '|';
2368 switch (is_ctor_dtor (name))
2371 if (which_pass != PASS_LIB)
2372 add_to_list (&constructors, name);
2376 if (which_pass != PASS_LIB)
2377 add_to_list (&destructors, name);
2381 if (which_pass != PASS_LIB)
2382 fatal ("init function found in object %s", prog_name);
2383 #ifndef LD_INIT_SWITCH
2384 add_to_list (&constructors, name);
2389 if (which_pass != PASS_LIB)
2390 fatal ("fini function found in object %s", prog_name);
2391 #ifndef LD_FINI_SWITCH
2392 add_to_list (&destructors, name);
2397 if (which_pass != PASS_LIB)
2398 add_to_list (&frame_tables, name);
2401 default: /* not a constructor or destructor */
2406 fprintf (stderr, "\t%s\n", buf);
2410 fprintf (stderr, "\n");
2412 if (fclose (inf) != 0)
2413 fatal_perror ("fclose");
2415 do_wait (nm_file_name);
2417 signal (SIGINT, int_handler);
2419 signal (SIGQUIT, quit_handler);
2423 #if SUNOS4_SHARED_LIBRARIES
2425 /* Routines to scan the SunOS 4 _DYNAMIC structure to find shared libraries
2426 that the output file depends upon and their initialization/finalization
2427 routines, if any. */
2432 #include <sys/mman.h>
2433 #include <sys/param.h>
2435 #include <sys/dir.h>
2437 /* pointers to the object file */
2438 unsigned object; /* address of memory mapped file */
2439 unsigned objsize; /* size of memory mapped to file */
2440 char * code; /* pointer to code segment */
2441 char * data; /* pointer to data segment */
2442 struct nlist *symtab; /* pointer to symbol table */
2443 struct link_dynamic *ld;
2444 struct link_dynamic_2 *ld_2;
2445 struct head libraries;
2447 /* Map the file indicated by NAME into memory and store its address. */
2455 if ((fp = open (name, O_RDONLY)) == -1)
2456 fatal ("unable to open file '%s'", name);
2457 if (fstat (fp, &s) == -1)
2458 fatal ("unable to stat file '%s'", name);
2460 objsize = s.st_size;
2461 object = (unsigned) mmap (0, objsize, PROT_READ|PROT_WRITE, MAP_PRIVATE,
2464 fatal ("unable to mmap file '%s'", name);
2469 /* Helpers for locatelib. */
2471 static char *libname;
2477 return (strncmp (libname, d->d_name, strlen (libname)) == 0);
2480 /* If one file has an additional numeric extension past LIBNAME, then put
2481 that one first in the sort. If both files have additional numeric
2482 extensions, then put the one with the higher number first in the sort.
2484 We must verify that the extension is numeric, because Sun saves the
2485 original versions of patched libraries with a .FCS extension. Files with
2486 invalid extensions must go last in the sort, so that they will not be used. */
2490 struct direct **d1, **d2;
2492 int i1, i2 = strlen (libname);
2493 char *e1 = (*d1)->d_name + i2;
2494 char *e2 = (*d2)->d_name + i2;
2496 while (*e1 && *e2 && *e1 == '.' && *e2 == '.'
2497 && e1[1] && ISDIGIT (e1[1]) && e2[1] && ISDIGIT (e2[1]))
2501 i1 = strtol (e1, &e1, 10);
2502 i2 = strtol (e2, &e2, 10);
2509 /* It has a valid numeric extension, prefer this one. */
2510 if (*e1 == '.' && e1[1] && ISDIGIT (e1[1]))
2512 /* It has a invalid numeric extension, must prefer the other one. */
2518 /* It has a valid numeric extension, prefer this one. */
2519 if (*e2 == '.' && e2[1] && ISDIGIT (e2[1]))
2521 /* It has a invalid numeric extension, must prefer the other one. */
2529 /* Given the name NAME of a dynamic dependency, find its pathname and add
2530 it to the list of libraries. */
2538 char buf[MAXPATHLEN];
2546 /* counting elements in array, need 1 extra for null */
2548 ld_rules = (char *) (ld_2->ld_rules + code);
2552 for (; *ld_rules != 0; ld_rules++)
2553 if (*ld_rules == ':')
2555 ld_rules = (char *) (ld_2->ld_rules + code);
2556 ldr = (char *) xmalloc (strlen (ld_rules) + 1);
2557 strcpy (ldr, ld_rules);
2559 p = getenv ("LD_LIBRARY_PATH");
2564 for (q = p ; *q != 0; q++)
2567 q = (char *) xmalloc (strlen (p) + 1);
2570 l = (char **) xmalloc ((cnt + 3) * sizeof (char *));
2575 for (; *ldr != 0; ldr++)
2585 for (; *q != 0; q++)
2592 /* built in directories are /lib, /usr/lib, and /usr/local/lib */
2595 *pp++ = "/usr/local/lib";
2599 for (pp = l; *pp != 0 ; pp++)
2601 struct direct **namelist;
2603 if ((entries = scandir (*pp, &namelist, libselect, libcompare)) > 0)
2605 sprintf (buf, "%s/%s", *pp, namelist[entries - 1]->d_name);
2606 add_to_list (&libraries, buf);
2608 fprintf (stderr, "%s\n", buf);
2615 notice ("not found\n");
2617 fatal ("dynamic dependency %s not found", name);
2621 /* Scan the _DYNAMIC structure of the output file to find shared libraries
2622 that it depends upon and any constructors or destructors they contain. */
2625 scan_libraries (prog_name)
2628 struct exec *header;
2630 struct link_object *lo;
2631 char buff[MAXPATHLEN];
2634 mapfile (prog_name);
2635 header = (struct exec *)object;
2636 if (N_BADMAG (*header))
2637 fatal ("bad magic number in file '%s'", prog_name);
2638 if (header->a_dynamic == 0)
2641 code = (char *) (N_TXTOFF (*header) + (long) header);
2642 data = (char *) (N_DATOFF (*header) + (long) header);
2643 symtab = (struct nlist *) (N_SYMOFF (*header) + (long) header);
2645 if (header->a_magic == ZMAGIC && header->a_entry == 0x20)
2648 ld = (struct link_dynamic *) (symtab->n_value + code);
2654 ld = (struct link_dynamic *) data;
2659 notice ("dynamic dependencies.\n");
2661 ld_2 = (struct link_dynamic_2 *) ((long) ld->ld_un.ld_2 + (long)base);
2662 for (lo = (struct link_object *) ld_2->ld_need; lo;
2663 lo = (struct link_object *) lo->lo_next)
2666 lo = (struct link_object *) ((long) lo + code);
2667 name = (char *) (code + lo->lo_name);
2671 fprintf (stderr, "\t-l%s.%d => ", name, lo->lo_major);
2672 sprintf (buff, "lib%s.so.%d.%d", name, lo->lo_major, lo->lo_minor);
2678 fprintf (stderr, "\t%s\n", name);
2679 add_to_list (&libraries, name);
2684 fprintf (stderr, "\n");
2686 /* now iterate through the library list adding their symbols to
2688 for (list = libraries.first; list; list = list->next)
2689 scan_prog_file (list->name, PASS_LIB);
2692 #else /* SUNOS4_SHARED_LIBRARIES */
2695 /* Use the List Dynamic Dependencies program to find shared libraries that
2696 the output file depends upon and their initialization/finalization
2697 routines, if any. */
2700 scan_libraries (prog_name)
2703 static struct head libraries; /* list of shared libraries found */
2705 void (*int_handler) ();
2706 void (*quit_handler) ();
2714 /* If we do not have an `ldd', complain. */
2715 if (ldd_file_name == 0)
2717 error ("cannot find `ldd'");
2721 ldd_argv[argc++] = ldd_file_name;
2722 ldd_argv[argc++] = prog_name;
2723 ldd_argv[argc++] = (char *) 0;
2725 if (pipe (pipe_fd) < 0)
2726 fatal_perror ("pipe");
2728 inf = fdopen (pipe_fd[0], "r");
2729 if (inf == (FILE *) 0)
2730 fatal_perror ("fdopen");
2732 /* Trace if needed. */
2738 for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
2739 fprintf (stderr, " %s", str);
2741 fprintf (stderr, "\n");
2747 /* Spawn child ldd on pipe */
2750 fatal_perror (VFORK_STRING);
2752 if (pid == 0) /* child context */
2755 if (dup2 (pipe_fd[1], 1) < 0)
2756 fatal_perror ("dup2 %d 1", pipe_fd[1]);
2758 if (close (pipe_fd[0]) < 0)
2759 fatal_perror ("close %d", pipe_fd[0]);
2761 if (close (pipe_fd[1]) < 0)
2762 fatal_perror ("close %d", pipe_fd[1]);
2764 execv (ldd_file_name, ldd_argv);
2765 fatal_perror ("execv %s", ldd_file_name);
2768 /* Parent context from here on. */
2769 int_handler = (void (*) ()) signal (SIGINT, SIG_IGN);
2771 quit_handler = (void (*) ()) signal (SIGQUIT, SIG_IGN);
2774 if (close (pipe_fd[1]) < 0)
2775 fatal_perror ("close %d", pipe_fd[1]);
2778 notice ("\nldd output with constructors/destructors.\n");
2780 /* Read each line of ldd output. */
2781 while (fgets (buf, sizeof buf, inf) != (char *) 0)
2784 char *name, *end, *p = buf;
2786 /* Extract names of libraries and add to list. */
2787 PARSE_LDD_OUTPUT (p);
2792 if (strncmp (name, "not found", sizeof ("not found") - 1) == 0)
2793 fatal ("dynamic dependency %s not found", buf);
2795 /* Find the end of the symbol name. */
2797 (ch2 = *end) != '\0' && ch2 != '\n' && !ISSPACE (ch2) && ch2 != '|';
2802 if (access (name, R_OK) == 0)
2803 add_to_list (&libraries, name);
2805 fatal ("unable to open dynamic dependency '%s'", buf);
2808 fprintf (stderr, "\t%s\n", buf);
2811 fprintf (stderr, "\n");
2813 if (fclose (inf) != 0)
2814 fatal_perror ("fclose");
2816 do_wait (ldd_file_name);
2818 signal (SIGINT, int_handler);
2820 signal (SIGQUIT, quit_handler);
2823 /* now iterate through the library list adding their symbols to
2825 for (list = libraries.first; list; list = list->next)
2826 scan_prog_file (list->name, PASS_LIB);
2829 #endif /* LDD_SUFFIX */
2830 #endif /* SUNOS4_SHARED_LIBRARIES */
2832 #endif /* OBJECT_FORMAT_NONE */
2836 * COFF specific stuff.
2839 #ifdef OBJECT_FORMAT_COFF
2841 #if defined(EXTENDED_COFF)
2842 # define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
2843 # define GCC_SYMENT SYMR
2844 # define GCC_OK_SYMBOL(X) ((X).st == stProc || (X).st == stGlobal)
2845 # define GCC_SYMINC(X) (1)
2846 # define GCC_SYMZERO(X) (SYMHEADER(X).isymMax)
2847 # define GCC_CHECK_HDR(X) (PSYMTAB(X) != 0)
2849 # define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms)
2850 # define GCC_SYMENT SYMENT
2851 # define GCC_OK_SYMBOL(X) \
2852 (((X).n_sclass == C_EXT) && \
2853 ((X).n_scnum > N_UNDEF) && \
2855 || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
2856 || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
2857 # define GCC_UNDEF_SYMBOL(X) \
2858 (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF))
2859 # define GCC_SYMINC(X) ((X).n_numaux+1)
2860 # define GCC_SYMZERO(X) 0
2861 # define GCC_CHECK_HDR(X) \
2862 ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
2863 || (HEADER (X).f_magic == 0757 && aix64_flag))
2866 extern char *ldgetname ();
2868 /* COFF version to scan the name list of the loaded program for
2869 the symbols g++ uses for static constructors and destructors.
2871 The constructor table begins at __CTOR_LIST__ and contains a count
2872 of the number of pointers (or -1 if the constructors are built in a
2873 separate section by the linker), followed by the pointers to the
2874 constructor functions, terminated with a null pointer. The
2875 destructor table has the same format, and begins at __DTOR_LIST__. */
2878 scan_prog_file (prog_name, which_pass)
2880 enum pass which_pass;
2882 LDFILE *ldptr = NULL;
2883 int sym_index, sym_count;
2885 #ifdef COLLECT_EXPORT_LIST
2886 /* Should we generate an import list for given prog_name? */
2887 int import_flag = (which_pass == PASS_OBJ ? 0 : use_import_list (prog_name));
2890 if (which_pass != PASS_FIRST && which_pass != PASS_OBJ)
2893 #ifdef COLLECT_EXPORT_LIST
2894 /* We do not need scanning for some standard C libraries. */
2895 if (which_pass == PASS_FIRST && ignore_library (prog_name))
2898 /* On AIX we have a loop, because there is not much difference
2899 between an object and an archive. This trick allows us to
2900 eliminate scan_libraries() function. */
2904 if ((ldptr = ldopen (prog_name, ldptr)) != NULL)
2906 if (! MY_ISCOFF (HEADER (ldptr).f_magic))
2907 fatal ("%s: not a COFF file", prog_name);
2909 if (GCC_CHECK_HDR (ldptr))
2911 sym_count = GCC_SYMBOLS (ldptr);
2912 sym_index = GCC_SYMZERO (ldptr);
2914 #ifdef COLLECT_EXPORT_LIST
2915 /* Is current archive member a shared object? */
2916 is_shared = HEADER (ldptr).f_flags & F_SHROBJ;
2919 while (sym_index < sym_count)
2923 if (ldtbread (ldptr, sym_index, &symbol) <= 0)
2925 sym_index += GCC_SYMINC (symbol);
2927 if (GCC_OK_SYMBOL (symbol))
2931 if ((name = ldgetname (ldptr, &symbol)) == NULL)
2932 continue; /* should never happen */
2934 #ifdef XCOFF_DEBUGGING_INFO
2935 /* All AIX function names have a duplicate entry
2936 beginning with a dot. */
2941 switch (is_ctor_dtor (name))
2944 if (! is_shared) add_to_list (&constructors, name);
2945 #ifdef COLLECT_EXPORT_LIST
2946 if (which_pass == PASS_OBJ)
2947 add_to_list (&exports, name);
2948 /* If this symbol was undefined and we are building
2949 an import list, we should add a symbol to this
2953 && is_in_list (name, undefined.first))
2954 add_to_list (&imports, name);
2959 if (! is_shared) add_to_list (&destructors, name);
2960 #ifdef COLLECT_EXPORT_LIST
2961 if (which_pass == PASS_OBJ)
2962 add_to_list (&exports, name);
2963 /* If this symbol was undefined and we are building
2964 an import list, we should add a symbol to this
2968 && is_in_list (name, undefined.first))
2969 add_to_list (&imports, name);
2973 #ifdef COLLECT_EXPORT_LIST
2976 add_to_list (&constructors, name);
2981 add_to_list (&destructors, name);
2987 add_to_list (&frame_tables, name);
2990 default: /* not a constructor or destructor */
2991 #ifdef COLLECT_EXPORT_LIST
2992 /* If we are building a shared object on AIX we need
2993 to explicitly export all global symbols or add
2994 them to import list. */
2997 if (which_pass == PASS_OBJ && (! export_flag))
2998 add_to_list (&exports, name);
2999 else if (! is_shared && which_pass == PASS_FIRST
3001 && is_in_list(name, undefined.first))
3002 add_to_list (&imports, name);
3008 #if !defined(EXTENDED_COFF)
3010 fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
3011 symbol.n_scnum, symbol.n_sclass,
3012 (symbol.n_type ? "0" : ""), symbol.n_type,
3017 "\tiss = %5d, value = %5ld, index = %5d, name = %s\n",
3018 symbol.iss, (long) symbol.value, symbol.index, name);
3021 #ifdef COLLECT_EXPORT_LIST
3022 /* If we are building a shared object we should collect
3023 information about undefined symbols for later
3024 import list generation. */
3025 else if (shared_obj && GCC_UNDEF_SYMBOL (symbol))
3029 if ((name = ldgetname (ldptr, &symbol)) == NULL)
3030 continue; /* should never happen */
3032 /* All AIX function names have a duplicate entry
3033 beginning with a dot. */
3036 add_to_list (&undefined, name);
3041 #ifdef COLLECT_EXPORT_LIST
3044 /* If archive contains both 32-bit and 64-bit objects,
3045 we want to skip objects in other mode so mismatch normal. */
3047 fprintf (stderr, "%s : magic=%o aix64=%d mismatch\n",
3048 prog_name, HEADER (ldptr).f_magic, aix64_flag);
3054 fatal ("%s: cannot open as COFF file", prog_name);
3056 #ifdef COLLECT_EXPORT_LIST
3057 /* On AIX loop continues while there are more members in archive. */
3059 while (ldclose (ldptr) == FAILURE);
3061 /* Otherwise we simply close ldptr. */
3062 (void) ldclose(ldptr);
3067 #ifdef COLLECT_EXPORT_LIST
3069 /* This new function is used to decide whether we should
3070 generate import list for an object or to use it directly. */
3072 use_import_list (prog_name)
3077 /* If we do not build a shared object then import list should not be used. */
3078 if (! shared_obj) return 0;
3080 /* Currently we check only for libgcc, but this can be changed in future. */
3081 p = strstr (prog_name, "libgcc.a");
3082 if (p != 0 && (strlen (p) == sizeof ("libgcc.a") - 1))
3087 /* Given a library name without "lib" prefix, this function
3088 returns a full library name including a path. */
3090 resolve_lib_name (name)
3096 for (i = 0; libpaths[i]; i++)
3097 if (libpaths[i]->max_len > l)
3098 l = libpaths[i]->max_len;
3100 lib_buf = xmalloc (l + strlen(name) + 10);
3102 for (i = 0; libpaths[i]; i++)
3104 struct prefix_list *list = libpaths[i]->plist;
3105 for (; list; list = list->next)
3107 for (j = 0; libexts[j]; j++)
3109 /* The following lines are needed because path_prefix list
3110 may contain directories both with trailing '/' and
3113 if (list->prefix[strlen(list->prefix)-1] != '/')
3115 sprintf (lib_buf, "%s%slib%s.%s",
3116 list->prefix, p, name, libexts[j]);
3117 if (debug) fprintf (stderr, "searching for: %s\n", lib_buf);
3118 if (file_exists (lib_buf))
3120 if (debug) fprintf (stderr, "found: %s\n", lib_buf);
3127 fprintf (stderr, "not found\n");
3129 fatal ("Library lib%s not found", name);
3133 /* Array of standard AIX libraries which should not
3134 be scanned for ctors/dtors. */
3135 static char* aix_std_libs[] = {
3140 "/usr/lib/libc_r.a",
3141 "/usr/lib/threads/libc.a",
3142 "/usr/ccs/lib/libc.a",
3143 "/usr/ccs/lib/libc_r.a",
3147 /* This function checks the filename and returns 1
3148 if this name matches the location of a standard AIX library. */
3150 ignore_library (name)
3153 char **p = &aix_std_libs[0];
3154 while (*p++ != NULL)
3155 if (! strcmp (name, *p)) return 1;
3161 #endif /* OBJECT_FORMAT_COFF */
3165 * OSF/rose specific stuff.
3168 #ifdef OBJECT_FORMAT_ROSE
3170 /* Union of the various load commands */
3172 typedef union load_union
3174 ldc_header_t hdr; /* common header */
3175 load_cmd_map_command_t map; /* map indexing other load cmds */
3176 interpreter_command_t iprtr; /* interpreter pathname */
3177 strings_command_t str; /* load commands strings section */
3178 region_command_t region; /* region load command */
3179 reloc_command_t reloc; /* relocation section */
3180 package_command_t pkg; /* package load command */
3181 symbols_command_t sym; /* symbol sections */
3182 entry_command_t ent; /* program start section */
3183 gen_info_command_t info; /* object information */
3184 func_table_command_t func; /* function constructors/destructors */
3187 /* Structure to point to load command and data section in memory. */
3189 typedef struct load_all
3191 load_union_t *load; /* load command */
3192 char *section; /* pointer to section */
3195 /* Structure to contain information about a file mapped into memory. */
3199 char *start; /* start of map */
3200 char *name; /* filename */
3201 long size; /* size of the file */
3202 long rounded_size; /* size rounded to page boundary */
3203 int fd; /* file descriptor */
3204 int rw; /* != 0 if opened read/write */
3205 int use_mmap; /* != 0 if mmap'ed */
3208 extern int decode_mach_o_hdr ();
3209 extern int encode_mach_o_hdr ();
3211 static void add_func_table PROTO((mo_header_t *, load_all_t *,
3212 symbol_info_t *, int));
3213 static void print_header PROTO((mo_header_t *));
3214 static void print_load_command PROTO((load_union_t *, size_t, int));
3215 static void bad_header PROTO((int));
3216 static struct file_info *read_file PROTO((char *, int, int));
3217 static void end_file PROTO((struct file_info *));
3219 /* OSF/rose specific version to scan the name list of the loaded
3220 program for the symbols g++ uses for static constructors and
3223 The constructor table begins at __CTOR_LIST__ and contains a count
3224 of the number of pointers (or -1 if the constructors are built in a
3225 separate section by the linker), followed by the pointers to the
3226 constructor functions, terminated with a null pointer. The
3227 destructor table has the same format, and begins at __DTOR_LIST__. */
3230 scan_prog_file (prog_name, which_pass)
3232 enum pass which_pass;
3236 load_all_t *load_array;
3237 load_all_t *load_end;
3238 load_all_t *load_cmd;
3239 int symbol_load_cmds;
3245 struct file_info *obj_file;
3247 mo_lcid_t cmd_strings = -1;
3248 symbol_info_t *main_sym = 0;
3249 int rw = (which_pass != PASS_FIRST);
3251 prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY);
3253 fatal_perror ("open %s", prog_name);
3255 obj_file = read_file (prog_name, prog_fd, rw);
3256 obj = obj_file->start;
3258 status = decode_mach_o_hdr (obj, MO_SIZEOF_RAW_HDR, MOH_HEADER_VERSION, &hdr);
3259 if (status != MO_HDR_CONV_SUCCESS)
3260 bad_header (status);
3263 /* Do some basic sanity checks. Note we explicitly use the big endian magic number,
3264 since the hardware will automatically swap bytes for us on loading little endian
3267 #ifndef CROSS_COMPILE
3268 if (hdr.moh_magic != MOH_MAGIC_MSB
3269 || hdr.moh_header_version != MOH_HEADER_VERSION
3270 || hdr.moh_byte_order != OUR_BYTE_ORDER
3271 || hdr.moh_data_rep_id != OUR_DATA_REP_ID
3272 || hdr.moh_cpu_type != OUR_CPU_TYPE
3273 || hdr.moh_cpu_subtype != OUR_CPU_SUBTYPE
3274 || hdr.moh_vendor_type != OUR_VENDOR_TYPE)
3276 fatal ("incompatibilities between object file & expected values");
3281 print_header (&hdr);
3283 offset = hdr.moh_first_cmd_off;
3284 load_end = load_array
3285 = (load_all_t *) xcalloc (sizeof (load_all_t), hdr.moh_n_load_cmds + 2);
3287 /* Build array of load commands, calculating the offsets */
3288 for (i = 0; i < hdr.moh_n_load_cmds; i++)
3290 load_union_t *load_hdr; /* load command header */
3292 load_cmd = load_end++;
3293 load_hdr = (load_union_t *) (obj + offset);
3295 /* If modifying the program file, copy the header. */
3298 load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size);
3299 bcopy ((char *)load_hdr, (char *)ptr, load_hdr->hdr.ldci_cmd_size);
3302 /* null out old command map, because we will rewrite at the end. */
3303 if (ptr->hdr.ldci_cmd_type == LDC_CMD_MAP)
3305 cmd_strings = ptr->map.lcm_ld_cmd_strings;
3306 ptr->hdr.ldci_cmd_type = LDC_UNDEFINED;
3310 load_cmd->load = load_hdr;
3311 if (load_hdr->hdr.ldci_section_off > 0)
3312 load_cmd->section = obj + load_hdr->hdr.ldci_section_off;
3315 print_load_command (load_hdr, offset, i);
3317 offset += load_hdr->hdr.ldci_cmd_size;
3320 /* If the last command is the load command map and is not undefined,
3321 decrement the count of load commands. */
3322 if (rw && load_end[-1].load->hdr.ldci_cmd_type == LDC_UNDEFINED)
3325 hdr.moh_n_load_cmds--;
3328 /* Go through and process each symbol table section. */
3329 symbol_load_cmds = 0;
3330 for (load_cmd = load_array; load_cmd < load_end; load_cmd++)
3332 load_union_t *load_hdr = load_cmd->load;
3334 if (load_hdr->hdr.ldci_cmd_type == LDC_SYMBOLS)
3340 char *kind = "unknown";
3342 switch (load_hdr->sym.symc_kind)
3344 case SYMC_IMPORTS: kind = "imports"; break;
3345 case SYMC_DEFINED_SYMBOLS: kind = "defined"; break;
3346 case SYMC_STABS: kind = "stabs"; break;
3349 notice ("\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
3350 symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
3353 if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
3356 str_sect = load_array[load_hdr->sym.symc_strings_section].section;
3357 if (str_sect == (char *) 0)
3358 fatal ("string section missing");
3360 if (load_cmd->section == (char *) 0)
3361 fatal ("section pointer missing");
3363 num_syms = load_hdr->sym.symc_nentries;
3364 for (i = 0; i < num_syms; i++)
3366 symbol_info_t *sym = ((symbol_info_t *) load_cmd->section) + i;
3367 char *name = sym->si_name.symbol_name + str_sect;
3374 char *n = name + strlen (name) - strlen (NAME__MAIN);
3376 if ((n - name) < 0 || strcmp (n, NAME__MAIN))
3386 switch (is_ctor_dtor (name))
3389 add_to_list (&constructors, name);
3393 add_to_list (&destructors, name);
3396 default: /* not a constructor or destructor */
3402 fprintf (stderr, "\ttype = 0x%.4x, sc = 0x%.2x, flags = 0x%.8x, name = %.30s\n",
3403 sym->si_type, sym->si_sc_type, sym->si_flags, name);
3408 if (symbol_load_cmds == 0)
3409 fatal ("no symbol table found");
3411 /* Update the program file now, rewrite header and load commands. At present,
3412 we assume that there is enough space after the last load command to insert
3413 one more. Since the first section written out is page aligned, and the
3414 number of load commands is small, this is ok for the present. */
3418 load_union_t *load_map;
3421 if (cmd_strings == -1)
3422 fatal ("no cmd_strings found");
3424 /* Add __main to initializer list.
3425 If we are building a program instead of a shared library, do not
3426 do anything, since in the current version, you cannot do mallocs
3427 and such in the constructors. */
3429 if (main_sym != (symbol_info_t *) 0
3430 && ((hdr.moh_flags & MOH_EXECABLE_F) == 0))
3431 add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION);
3434 notice ("\nUpdating header and load commands.\n\n");
3436 hdr.moh_n_load_cmds++;
3437 size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1));
3439 /* Create new load command map. */
3441 notice ("load command map, %d cmds, new size %ld.\n",
3442 (int) hdr.moh_n_load_cmds, (long) size);
3444 load_map = (load_union_t *) xcalloc (1, size);
3445 load_map->map.ldc_header.ldci_cmd_type = LDC_CMD_MAP;
3446 load_map->map.ldc_header.ldci_cmd_size = size;
3447 load_map->map.lcm_ld_cmd_strings = cmd_strings;
3448 load_map->map.lcm_nentries = hdr.moh_n_load_cmds;
3449 load_array[hdr.moh_n_load_cmds-1].load = load_map;
3451 offset = hdr.moh_first_cmd_off;
3452 for (i = 0; i < hdr.moh_n_load_cmds; i++)
3454 load_map->map.lcm_map[i] = offset;
3455 if (load_array[i].load->hdr.ldci_cmd_type == LDC_CMD_MAP)
3456 hdr.moh_load_map_cmd_off = offset;
3458 offset += load_array[i].load->hdr.ldci_cmd_size;
3461 hdr.moh_sizeofcmds = offset - MO_SIZEOF_RAW_HDR;
3464 print_header (&hdr);
3467 status = encode_mach_o_hdr (&hdr, obj, MO_SIZEOF_RAW_HDR);
3468 if (status != MO_HDR_CONV_SUCCESS)
3469 bad_header (status);
3472 notice ("writing load commands.\n\n");
3474 /* Write load commands */
3475 offset = hdr.moh_first_cmd_off;
3476 for (i = 0; i < hdr.moh_n_load_cmds; i++)
3478 load_union_t *load_hdr = load_array[i].load;
3479 size_t size = load_hdr->hdr.ldci_cmd_size;
3482 print_load_command (load_hdr, offset, i);
3484 bcopy ((char *) load_hdr, (char *) (obj + offset), size);
3489 end_file (obj_file);
3491 if (close (prog_fd))
3492 fatal_perror ("close %s", prog_name);
3495 fprintf (stderr, "\n");
3499 /* Add a function table to the load commands to call a function
3500 on initiation or termination of the process. */
3503 add_func_table (hdr_p, load_array, sym, type)
3504 mo_header_t *hdr_p; /* pointer to global header */
3505 load_all_t *load_array; /* array of ptrs to load cmds */
3506 symbol_info_t *sym; /* pointer to symbol entry */
3507 int type; /* fntc_type value */
3509 /* Add a new load command. */
3510 int num_cmds = ++hdr_p->moh_n_load_cmds;
3511 int load_index = num_cmds - 1;
3512 size_t size = sizeof (func_table_command_t) + sizeof (mo_addr_t);
3513 load_union_t *ptr = xcalloc (1, size);
3514 load_all_t *load_cmd;
3517 /* Set the unresolved address bit in the header to force the loader to be
3518 used, since kernel exec does not call the initialization functions. */
3519 hdr_p->moh_flags |= MOH_UNRESOLVED_F;
3521 load_cmd = &load_array[load_index];
3522 load_cmd->load = ptr;
3523 load_cmd->section = (char *) 0;
3525 /* Fill in func table load command. */
3526 ptr->func.ldc_header.ldci_cmd_type = LDC_FUNC_TABLE;
3527 ptr->func.ldc_header.ldci_cmd_size = size;
3528 ptr->func.ldc_header.ldci_section_off = 0;
3529 ptr->func.ldc_header.ldci_section_len = 0;
3530 ptr->func.fntc_type = type;
3531 ptr->func.fntc_nentries = 1;
3533 /* copy address, turn it from abs. address to (region,offset) if necessary. */
3534 /* Is the symbol already expressed as (region, offset)? */
3535 if ((sym->si_flags & SI_ABSOLUTE_VALUE_F) == 0)
3537 ptr->func.fntc_entry_loc[i].adr_lcid = sym->si_value.def_val.adr_lcid;
3538 ptr->func.fntc_entry_loc[i].adr_sctoff = sym->si_value.def_val.adr_sctoff;
3541 /* If not, figure out which region it's in. */
3544 mo_vm_addr_t addr = sym->si_value.abs_val;
3547 for (i = 0; i < load_index; i++)
3549 if (load_array[i].load->hdr.ldci_cmd_type == LDC_REGION)
3551 region_command_t *region_ptr = &load_array[i].load->region;
3553 if ((region_ptr->regc_flags & REG_ABS_ADDR_F) != 0
3554 && addr >= region_ptr->regc_addr.vm_addr
3555 && addr <= region_ptr->regc_addr.vm_addr + region_ptr->regc_vm_size)
3557 ptr->func.fntc_entry_loc[0].adr_lcid = i;
3558 ptr->func.fntc_entry_loc[0].adr_sctoff = addr - region_ptr->regc_addr.vm_addr;
3566 fatal ("could not convert 0x%l.8x into a region", addr);
3570 notice ("%s function, region %d, offset = %ld (0x%.8lx)\n",
3571 type == FNTC_INITIALIZATION ? "init" : "term",
3572 (int) ptr->func.fntc_entry_loc[i].adr_lcid,
3573 (long) ptr->func.fntc_entry_loc[i].adr_sctoff,
3574 (long) ptr->func.fntc_entry_loc[i].adr_sctoff);
3579 /* Print the global header for an OSF/rose object. */
3582 print_header (hdr_ptr)
3583 mo_header_t *hdr_ptr;
3585 fprintf (stderr, "\nglobal header:\n");
3586 fprintf (stderr, "\tmoh_magic = 0x%.8lx\n", hdr_ptr->moh_magic);
3587 fprintf (stderr, "\tmoh_major_version = %d\n", (int)hdr_ptr->moh_major_version);
3588 fprintf (stderr, "\tmoh_minor_version = %d\n", (int)hdr_ptr->moh_minor_version);
3589 fprintf (stderr, "\tmoh_header_version = %d\n", (int)hdr_ptr->moh_header_version);
3590 fprintf (stderr, "\tmoh_max_page_size = %d\n", (int)hdr_ptr->moh_max_page_size);
3591 fprintf (stderr, "\tmoh_byte_order = %d\n", (int)hdr_ptr->moh_byte_order);
3592 fprintf (stderr, "\tmoh_data_rep_id = %d\n", (int)hdr_ptr->moh_data_rep_id);
3593 fprintf (stderr, "\tmoh_cpu_type = %d\n", (int)hdr_ptr->moh_cpu_type);
3594 fprintf (stderr, "\tmoh_cpu_subtype = %d\n", (int)hdr_ptr->moh_cpu_subtype);
3595 fprintf (stderr, "\tmoh_vendor_type = %d\n", (int)hdr_ptr->moh_vendor_type);
3596 fprintf (stderr, "\tmoh_load_map_cmd_off = %d\n", (int)hdr_ptr->moh_load_map_cmd_off);
3597 fprintf (stderr, "\tmoh_first_cmd_off = %d\n", (int)hdr_ptr->moh_first_cmd_off);
3598 fprintf (stderr, "\tmoh_sizeofcmds = %d\n", (int)hdr_ptr->moh_sizeofcmds);
3599 fprintf (stderr, "\tmon_n_load_cmds = %d\n", (int)hdr_ptr->moh_n_load_cmds);
3600 fprintf (stderr, "\tmoh_flags = 0x%.8lx", (long)hdr_ptr->moh_flags);
3602 if (hdr_ptr->moh_flags & MOH_RELOCATABLE_F)
3603 fprintf (stderr, ", relocatable");
3605 if (hdr_ptr->moh_flags & MOH_LINKABLE_F)
3606 fprintf (stderr, ", linkable");
3608 if (hdr_ptr->moh_flags & MOH_EXECABLE_F)
3609 fprintf (stderr, ", execable");
3611 if (hdr_ptr->moh_flags & MOH_EXECUTABLE_F)
3612 fprintf (stderr, ", executable");
3614 if (hdr_ptr->moh_flags & MOH_UNRESOLVED_F)
3615 fprintf (stderr, ", unresolved");
3617 fprintf (stderr, "\n\n");
3622 /* Print a short summary of a load command. */
3625 print_load_command (load_hdr, offset, number)
3626 load_union_t *load_hdr;
3630 mo_long_t type = load_hdr->hdr.ldci_cmd_type;
3631 char *type_str = (char *) 0;
3635 case LDC_UNDEFINED: type_str = "UNDEFINED"; break;
3636 case LDC_CMD_MAP: type_str = "CMD_MAP"; break;
3637 case LDC_INTERPRETER: type_str = "INTERPRETER"; break;
3638 case LDC_STRINGS: type_str = "STRINGS"; break;
3639 case LDC_REGION: type_str = "REGION"; break;
3640 case LDC_RELOC: type_str = "RELOC"; break;
3641 case LDC_PACKAGE: type_str = "PACKAGE"; break;
3642 case LDC_SYMBOLS: type_str = "SYMBOLS"; break;
3643 case LDC_ENTRY: type_str = "ENTRY"; break;
3644 case LDC_FUNC_TABLE: type_str = "FUNC_TABLE"; break;
3645 case LDC_GEN_INFO: type_str = "GEN_INFO"; break;
3649 "cmd %2d, sz: 0x%.2lx, coff: 0x%.3lx, doff: 0x%.6lx, dlen: 0x%.6lx",
3651 (long) load_hdr->hdr.ldci_cmd_size,
3653 (long) load_hdr->hdr.ldci_section_off,
3654 (long) load_hdr->hdr.ldci_section_len);
3656 if (type_str == (char *) 0)
3657 fprintf (stderr, ", ty: unknown (%ld)\n", (long) type);
3659 else if (type != LDC_REGION)
3660 fprintf (stderr, ", ty: %s\n", type_str);
3665 switch (load_hdr->region.regc_usage_type)
3667 case REG_TEXT_T: region = ", .text"; break;
3668 case REG_DATA_T: region = ", .data"; break;
3669 case REG_BSS_T: region = ", .bss"; break;
3670 case REG_GLUE_T: region = ", .glue"; break;
3671 #if defined (REG_RDATA_T) && defined (REG_SDATA_T) && defined (REG_SBSS_T) /*mips*/
3672 case REG_RDATA_T: region = ", .rdata"; break;
3673 case REG_SDATA_T: region = ", .sdata"; break;
3674 case REG_SBSS_T: region = ", .sbss"; break;
3678 fprintf (stderr, ", ty: %s, vaddr: 0x%.8lx, vlen: 0x%.6lx%s\n",
3680 (long) load_hdr->region.regc_vm_addr,
3681 (long) load_hdr->region.regc_vm_size,
3689 /* Fatal error when {en,de}code_mach_o_header fails. */
3697 case MO_ERROR_BAD_MAGIC: fatal ("bad magic number");
3698 case MO_ERROR_BAD_HDR_VERS: fatal ("bad header version");
3699 case MO_ERROR_BAD_RAW_HDR_VERS: fatal ("bad raw header version");
3700 case MO_ERROR_BUF2SML: fatal ("raw header buffer too small");
3701 case MO_ERROR_OLD_RAW_HDR_FILE: fatal ("old raw header file");
3702 case MO_ERROR_UNSUPPORTED_VERS: fatal ("unsupported version");
3704 fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
3709 /* Read a file into a memory buffer. */
3711 static struct file_info *
3712 read_file (name, fd, rw)
3713 char *name; /* filename */
3714 int fd; /* file descriptor */
3715 int rw; /* read/write */
3717 struct stat stat_pkt;
3718 struct file_info *p = (struct file_info *) xcalloc (sizeof (struct file_info), 1);
3720 static int page_size;
3723 if (fstat (fd, &stat_pkt) < 0)
3724 fatal_perror ("fstat %s", name);
3727 p->size = stat_pkt.st_size;
3728 p->rounded_size = stat_pkt.st_size;
3734 fprintf (stderr, "mmap %s, %s\n", name, (rw) ? "read/write" : "read-only");
3737 page_size = sysconf (_SC_PAGE_SIZE);
3739 p->rounded_size = ((p->size + page_size - 1) / page_size) * page_size;
3740 p->start = mmap ((caddr_t) 0,
3741 (rw) ? p->rounded_size : p->size,
3742 (rw) ? (PROT_READ | PROT_WRITE) : PROT_READ,
3743 MAP_FILE | MAP_VARIABLE | MAP_SHARED,
3747 if (p->start != (char *) 0 && p->start != (char *) -1)
3751 #endif /* USE_MMAP */
3756 fprintf (stderr, "read %s\n", name);
3759 p->start = xmalloc (p->size);
3760 if (lseek (fd, 0L, SEEK_SET) < 0)
3761 fatal_perror ("lseek %s 0", name);
3763 len = read (fd, p->start, p->size);
3765 fatal_perror ("read %s", name);
3768 fatal ("read %ld bytes, expected %ld, from %s", len, p->size, name);
3774 /* Do anything necessary to write a file back from memory. */
3778 struct file_info *ptr; /* file information block */
3786 fprintf (stderr, "msync %s\n", ptr->name);
3788 if (msync (ptr->start, ptr->rounded_size, MS_ASYNC))
3789 fatal_perror ("msync %s", ptr->name);
3793 fprintf (stderr, "munmap %s\n", ptr->name);
3795 if (munmap (ptr->start, ptr->size))
3796 fatal_perror ("munmap %s", ptr->name);
3799 #endif /* USE_MMAP */
3806 fprintf (stderr, "write %s\n", ptr->name);
3808 if (lseek (ptr->fd, 0L, SEEK_SET) < 0)
3809 fatal_perror ("lseek %s 0", ptr->name);
3811 len = write (ptr->fd, ptr->start, ptr->size);
3813 fatal_perror ("write %s", ptr->name);
3815 if (len != ptr->size)
3816 fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name);
3825 #endif /* OBJECT_FORMAT_ROSE */