OSDN Git Service

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