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