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