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