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