|
|
1.1 root 1: /* Collect static initialization info into data structures
2: that can be traversed by C++ initialization and finalization
3: routines.
4:
5: Copyright (C) 1992, 1993 Free Software Foundation, Inc.
6: Contributed by Chris Smith ([email protected]).
7: Heavily modified by Michael Meissner ([email protected]),
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
24: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
25:
26:
27: /* Build tables of static constructors and destructors and run ld. */
28:
29: #include <sys/types.h>
30: #include <stdio.h>
31: #include <ctype.h>
32: #include <errno.h>
33: #include <signal.h>
34: #include <sys/file.h>
35: #include <sys/stat.h>
36: #ifdef NO_WAIT_H
37: #include <sys/wait.h>
38: #endif
39:
40: #ifndef errno
41: extern int errno;
42: #endif
43:
44: #if defined(bsd4_4)
45: extern const char *const sys_errlist[];
46: #else
47: extern char *sys_errlist[];
48: #endif
49: extern int sys_nerr;
50:
51: #define COLLECT
52:
53: #include "config.h"
54:
55: #ifndef __STDC__
56: #define generic char
57: #define const
58:
59: #else
60: #define generic void
61: #endif
62:
63: #ifdef USG
64: #define vfork fork
65: #endif
66:
67: /* Add prototype support. */
68: #ifndef PROTO
69: #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
70: #define PROTO(ARGS) ARGS
71: #else
72: #define PROTO(ARGS) ()
73: #endif
74: #endif
75:
76: #ifndef R_OK
77: #define R_OK 4
78: #define W_OK 2
79: #define X_OK 1
80: #endif
81:
82: /* On MSDOS, write temp files in current dir
83: because there's no place else we can expect to use. */
84: #if __MSDOS__
85: #ifndef P_tmpdir
86: #define P_tmpdir "./"
87: #endif
88: #endif
89:
90: /* On certain systems, we have code that works by scanning the object file
91: directly. But this code uses system-specific header files and library
92: functions, so turn it off in a cross-compiler. Likewise, the names of
93: the utilities aren't correct for a cross-compiler; we have to hope that
94: cross-versions are in the proper directories. */
95:
96: #ifdef CROSS_COMPILE
97: #undef OBJECT_FORMAT_COFF
98: #undef OBJECT_FORMAT_ROSE
99: #undef MD_EXEC_PREFIX
100: #undef REAL_LD_FILE_NAME
101: #undef REAL_NM_FILE_NAME
102: #undef REAL_STRIP_FILE_NAME
103: #endif
104:
105: /* If we can't use a special method, use the ordinary one:
106: run nm to find what symbols are present.
107: In a cross-compiler, this means you need a cross nm,
108: but that isn't quite as unpleasant as special headers. */
109:
110: #if !defined (OBJECT_FORMAT_COFF) && !defined (OBJECT_FORMAT_ROSE)
111: #define OBJECT_FORMAT_NONE
112: #endif
113:
114: #ifdef OBJECT_FORMAT_COFF
115:
116: #include <a.out.h>
117: #include <ar.h>
118:
119: #ifdef UMAX
120: #include <sgs.h>
121: #endif
122:
123: /* Many versions of ldfcn.h define these. */
124: #ifdef FREAD
125: #undef FREAD
126: #undef FWRITE
127: #endif
128:
129: #include <ldfcn.h>
130:
131: /* Some systems have an ISCOFF macro, but others do not. In some cases
132: the macro may be wrong. MY_ISCOFF is defined in tm.h files for machines
133: that either do not have an ISCOFF macro in /usr/include or for those
134: where it is wrong. */
135:
136: #ifndef MY_ISCOFF
137: #define MY_ISCOFF(X) ISCOFF (X)
138: #endif
139:
140: #endif /* OBJECT_FORMAT_COFF */
141:
142: #ifdef OBJECT_FORMAT_ROSE
143:
144: #ifdef _OSF_SOURCE
145: #define USE_MMAP
146: #endif
147:
148: #ifdef USE_MMAP
149: #include <sys/mman.h>
150: #endif
151:
152: #include <unistd.h>
153: #include <mach_o_format.h>
154: #include <mach_o_header.h>
155: #include <mach_o_vals.h>
156: #include <mach_o_types.h>
157:
158: #endif /* OBJECT_FORMAT_ROSE */
159:
160: #ifdef OBJECT_FORMAT_NONE
161:
162: /* Default flags to pass to nm. */
163: #ifndef NM_FLAGS
164: #define NM_FLAGS "-p"
165: #endif
166:
167: #endif /* OBJECT_FORMAT_NONE */
168:
169: /* Some systems use __main in a way incompatible with its use in gcc, in these
170: cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
171: give the same symbol without quotes for an alternative entry point. You
172: must define both, or niether. */
173: #ifndef NAME__MAIN
174: #define NAME__MAIN "__main"
175: #define SYMBOL__MAIN __main
176: #endif
177:
178:
179: /* Linked lists of constructor and destructor names. */
180:
181: struct id
182: {
183: struct id *next;
184: int sequence;
185: char name[1];
186: };
187:
188: struct head
189: {
190: struct id *first;
191: struct id *last;
192: int number;
193: };
194:
195: /* Enumeration giving which pass this is for scanning the program file. */
196:
197: enum pass {
198: PASS_FIRST, /* without constructors */
199: PASS_SECOND /* with constructors linked in */
200: };
201:
202: #ifndef NO_SYS_SIGLIST
203: extern char *sys_siglist[];
204: #endif
205: extern char *version_string;
206:
207: static int vflag; /* true if -v */
208: static int rflag; /* true if -r */
209: static int strip_flag; /* true if -s */
210:
211: static int debug; /* true if -debug */
212:
213: static int temp_filename_length; /* Length of temp_filename */
214: static char *temp_filename; /* Base of temp filenames */
215: static char *c_file; /* <xxx>.c for constructor/destructor list. */
216: static char *o_file; /* <xxx>.o for constructor/destructor list. */
217: static char *output_file; /* Output file for ld. */
218: static char *nm_file_name; /* pathname of nm */
219: static char *strip_file_name; /* pathname of strip */
220:
221: static struct head constructors; /* list of constructors found */
222: static struct head destructors; /* list of destructors found */
223:
224: extern char *getenv ();
225: extern char *mktemp ();
226: extern FILE *fdopen ();
227:
228: /* Structure to hold all the directories in which to search for files to
229: execute. */
230:
231: struct prefix_list
232: {
233: char *prefix; /* String to prepend to the path. */
234: struct prefix_list *next; /* Next in linked list. */
235: };
236:
237: struct path_prefix
238: {
239: struct prefix_list *plist; /* List of prefixes to try */
240: int max_len; /* Max length of a prefix in PLIST */
241: char *name; /* Name of this list (used in config stuff) */
242: };
243:
244: static void my_exit PROTO((int));
245: static void handler PROTO((int));
246: static int is_ctor_dtor PROTO((char *));
247: static void choose_temp_base PROTO((void));
248: static int is_in_prefix_list PROTO((struct path_prefix *, char *, int));
249: static char *find_a_file PROTO((struct path_prefix *, char *));
250: static void add_prefix PROTO((struct path_prefix *, char *));
251: static void prefix_from_env PROTO((char *, struct path_prefix *));
252: static void do_wait PROTO((char *));
253: static void fork_execute PROTO((char *, char **));
254: static void maybe_unlink PROTO((char *));
255: static void add_to_list PROTO((struct head *, char *));
256: static void write_list PROTO((FILE *, char *, struct id *));
257: static void write_list_with_asm PROTO((FILE *, char *, struct id *));
258: static void write_c_file PROTO((FILE *, char *));
259: static void scan_prog_file PROTO((char *, enum pass));
260:
261: generic *xcalloc ();
262: generic *xmalloc ();
263:
264: extern char *index ();
265: extern char *rindex ();
266:
267: #ifdef NO_DUP2
268: int
269: dup2 (oldfd, newfd)
270: int oldfd;
271: int newfd;
272: {
273: int fdtmp[256];
274: int fdx = 0;
275: int fd;
276:
277: if (oldfd == newfd)
278: return 0;
279: close (newfd);
280: while ((fd = dup (oldfd)) != newfd) /* good enough for low fd's */
281: fdtmp[fdx++] = fd;
282: while (fdx > 0)
283: close (fdtmp[--fdx]);
284:
285: return 0;
286: }
287: #endif
288:
289: char *
290: my_strerror (e)
291: int e;
292: {
293: static char buffer[30];
294:
295: if (!e)
296: return "";
297:
298: if (e > 0 && e < sys_nerr)
299: return sys_errlist[e];
300:
301: sprintf (buffer, "Unknown error %d", e);
302: return buffer;
303: }
304:
305: /* Delete tempfiles and exit function. */
306:
307: static void
308: my_exit (status)
309: int status;
310: {
311: if (c_file != 0 && c_file[0])
312: maybe_unlink (c_file);
313:
314: if (o_file != 0 && o_file[0])
315: maybe_unlink (o_file);
316:
317: if (status != 0 && output_file != 0 && output_file[0])
318: maybe_unlink (output_file);
319:
320: exit (status);
321: }
322:
323:
324: /* Die when sys call fails. */
325:
326: static void
327: fatal_perror (string, arg1, arg2, arg3)
328: char *string;
329: {
330: int e = errno;
331:
332: fprintf (stderr, "collect2: ");
333: fprintf (stderr, string, arg1, arg2, arg3);
334: fprintf (stderr, ": %s\n", my_strerror (e));
335: my_exit (1);
336: }
337:
338: /* Just die. */
339:
340: static void
341: fatal (string, arg1, arg2, arg3)
342: char *string;
343: {
344: fprintf (stderr, "collect2: ");
345: fprintf (stderr, string, arg1, arg2, arg3);
346: fprintf (stderr, "\n");
347: my_exit (1);
348: }
349:
350: /* Write error message. */
351:
352: static void
353: error (string, arg1, arg2, arg3, arg4)
354: char *string;
355: {
356: fprintf (stderr, "collect2: ");
357: fprintf (stderr, string, arg1, arg2, arg3, arg4);
358: fprintf (stderr, "\n");
359: }
360:
361: /* In case obstack is linked in, and abort is defined to fancy_abort,
362: provide a default entry. */
363:
364: void
365: fancy_abort ()
366: {
367: fatal ("internal error");
368: }
369:
370:
371: static void
372: handler (signo)
373: int signo;
374: {
375: if (c_file != 0 && c_file[0])
376: maybe_unlink (c_file);
377:
378: if (o_file != 0 && o_file[0])
379: maybe_unlink (o_file);
380:
381: signal (signo, SIG_DFL);
382: kill (getpid (), signo);
383: }
384:
385:
386: generic *
387: xcalloc (size1, size2)
388: int size1, size2;
389: {
390: generic *ptr = (generic *) calloc (size1, size2);
391: if (ptr)
392: return ptr;
393:
394: fatal ("out of memory");
395: return (generic *)0;
396: }
397:
398: generic *
399: xmalloc (size)
400: int size;
401: {
402: generic *ptr = (generic *) malloc (size);
403: if (ptr)
404: return ptr;
405:
406: fatal ("out of memory");
407: return (generic *)0;
408: }
409:
410: /* Make a copy of a string INPUT with size SIZE. */
411:
412: char *
413: savestring (input, size)
414: char *input;
415: int size;
416: {
417: char *output = (char *) xmalloc (size + 1);
418: bcopy (input, output, size);
419: output[size] = 0;
420: return output;
421: }
422:
423: /* Decide whether the given symbol is:
424: a constructor (1), a destructor (2), or neither (0). */
425:
426: static int
427: is_ctor_dtor (s)
428: char *s;
429: {
430: struct names { char *name; int len; int ret; int two_underscores; };
431:
432: register struct names *p;
433: register int ch;
434: register char *orig_s = s;
435:
436: static struct names special[] = {
437: #ifdef NO_DOLLAR_IN_LABEL
438: #ifdef NO_DOT_IN_LABEL
439: { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, 1, 0 },
440: { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, 2, 0 },
441: #else
442: { "GLOBAL_.I.", sizeof ("GLOBAL_.I.")-1, 1, 0 },
443: { "GLOBAL_.D.", sizeof ("GLOBAL_.D.")-1, 2, 0 },
444: #endif
445: #else
446: { "GLOBAL_$I$", sizeof ("GLOBAL_$I$")-1, 1, 0 },
447: { "GLOBAL_$D$", sizeof ("GLOBAL_$D$")-1, 2, 0 },
448: #endif
449: #ifdef CFRONT_LOSSAGE /* Don't collect cfront initialization functions.
450: cfront has its own linker procedure to collect them;
451: if collect2 gets them too, they get collected twice
452: when the cfront procedure is run and the compiler used
453: for linking happens to be GCC. */
454: { "sti__", sizeof ("sti__")-1, 1, 1 },
455: { "std__", sizeof ("std__")-1, 2, 1 },
456: #endif /* CFRONT_LOSSAGE */
457: { NULL, 0, 0, 0 }
458: };
459:
460: while ((ch = *s) == '_')
461: ++s;
462:
463: if (s == orig_s)
464: return 0;
465:
466: for (p = &special[0]; p->len > 0; p++)
467: {
468: if (ch == p->name[0]
469: && (!p->two_underscores || ((s - orig_s) >= 2))
470: && strncmp(s, p->name, p->len) == 0)
471: {
472: return p->ret;
473: }
474: }
475: return 0;
476: }
477:
478:
479: /* Compute a string to use as the base of all temporary file names.
480: It is substituted for %g. */
481:
482: static void
483: choose_temp_base ()
484: {
485: char *base = getenv ("TMPDIR");
486: int len;
487:
488: if (base == (char *)0)
489: {
490: #ifdef P_tmpdir
491: if (access (P_tmpdir, R_OK | W_OK) == 0)
492: base = P_tmpdir;
493: #endif
494: if (base == (char *)0)
495: {
496: if (access ("/usr/tmp", R_OK | W_OK) == 0)
497: base = "/usr/tmp/";
498: else
499: base = "/tmp/";
500: }
501: }
502:
503: len = strlen (base);
504: temp_filename = xmalloc (len + sizeof("/ccXXXXXX") + 1);
505: strcpy (temp_filename, base);
506: if (len > 0 && temp_filename[len-1] != '/')
507: temp_filename[len++] = '/';
508: strcpy (temp_filename + len, "ccXXXXXX");
509:
510: mktemp (temp_filename);
511: temp_filename_length = strlen (temp_filename);
512: }
513:
514: /* Routine to add variables to the environment. */
515:
516: #ifndef HAVE_PUTENV
517:
518: int
519: putenv (str)
520: char *str;
521: {
522: #ifndef VMS /* nor about VMS */
523:
524: extern char **environ;
525: char **old_environ = environ;
526: char **envp;
527: int num_envs = 0;
528: int name_len = 1;
529: int str_len = strlen (str);
530: char *p = str;
531: int ch;
532:
533: while ((ch = *p++) != '\0' && ch != '=')
534: name_len++;
535:
536: if (!ch)
537: abort ();
538:
539: /* Search for replacing an existing environment variable, and
540: count the number of total environment variables. */
541: for (envp = old_environ; *envp; envp++)
542: {
543: num_envs++;
544: if (!strncmp (str, *envp, name_len))
545: {
546: *envp = str;
547: return 0;
548: }
549: }
550:
551: /* Add a new environment variable */
552: environ = (char **) xmalloc (sizeof (char *) * (num_envs+2));
553: *environ = str;
554: bcopy (old_environ, environ+1, sizeof (char *) * (num_envs+1));
555: return 0;
556: #endif /* VMS */
557: }
558:
559: #endif /* HAVE_PUTENV */
560:
561: /* By default, colon separates directories in a path. */
562: #ifndef PATH_SEPARATOR
563: #define PATH_SEPARATOR ':'
564: #endif
565:
566: /* We maintain two prefix lists: one from COMPILER_PATH environment variable
567: and one from the PATH variable. */
568:
569: static struct path_prefix cpath, path;
570:
571: #ifdef CROSS_COMPILE
572: /* This is the name of the target machine. We use it to form the name
573: of the files to execute. */
574:
575: static char *target_machine = TARGET_MACHINE;
576: #endif
577:
578: /* Names under which we were executed. Never return one of those files in our
579: searches. */
580:
581: static struct path_prefix our_file_names;
582:
583: /* Determine if STRING is in PPREFIX.
584:
585: This utility is currently only used to look up file names. Prefix lists
586: record directory names. This matters to us because the latter has a
587: trailing slash, so I've added a flag to handle both. */
588:
589: static int
590: is_in_prefix_list (pprefix, string, filep)
591: struct path_prefix *pprefix;
592: char *string;
593: int filep;
594: {
595: struct prefix_list *pl;
596:
597: if (filep)
598: {
599: int len = strlen (string);
600:
601: for (pl = pprefix->plist; pl; pl = pl->next)
602: {
603: if (strncmp (pl->prefix, string, len) == 0
604: && strcmp (pl->prefix + len, "/") == 0)
605: return 1;
606: }
607: }
608: else
609: {
610: for (pl = pprefix->plist; pl; pl = pl->next)
611: {
612: if (strcmp (pl->prefix, string) == 0)
613: return 1;
614: }
615: }
616:
617: return 0;
618: }
619:
620: /* Search for NAME using prefix list PPREFIX. We only look for executable
621: files.
622:
623: Return 0 if not found, otherwise return its name, allocated with malloc. */
624:
625: static char *
626: find_a_file (pprefix, name)
627: struct path_prefix *pprefix;
628: char *name;
629: {
630: char *temp;
631: struct prefix_list *pl;
632: int len = pprefix->max_len + strlen (name) + 1;
633:
634: #ifdef EXECUTABLE_SUFFIX
635: len += strlen (EXECUTABLE_SUFFIX);
636: #endif
637:
638: temp = xmalloc (len);
639:
640: /* Determine the filename to execute (special case for absolute paths). */
641:
642: if (*name == '/')
643: {
644: if (access (name, X_OK) == 0)
645: {
646: strcpy (temp, name);
647: return temp;
648: }
649: }
650: else
651: for (pl = pprefix->plist; pl; pl = pl->next)
652: {
653: strcpy (temp, pl->prefix);
654: strcat (temp, name);
655: if (! is_in_prefix_list (&our_file_names, temp, 1)
656: /* This is a kludge, but there seems no way around it. */
657: && strcmp (temp, "./ld") != 0
658: && access (temp, X_OK) == 0)
659: return temp;
660:
661: #ifdef EXECUTABLE_SUFFIX
662: /* Some systems have a suffix for executable files.
663: So try appending that. */
664: strcat (temp, EXECUTABLE_SUFFIX);
665: if (! is_in_prefix_list (&our_file_names, temp, 1)
666: && access (temp, X_OK) == 0)
667: return temp;
668: #endif
669: }
670:
671: free (temp);
672: return 0;
673: }
674:
675: /* Add an entry for PREFIX to prefix list PPREFIX. */
676:
677: static void
678: add_prefix (pprefix, prefix)
679: struct path_prefix *pprefix;
680: char *prefix;
681: {
682: struct prefix_list *pl, **prev;
683: int len;
684:
685: if (pprefix->plist)
686: {
687: for (pl = pprefix->plist; pl->next; pl = pl->next)
688: ;
689: prev = &pl->next;
690: }
691: else
692: prev = &pprefix->plist;
693:
694: /* Keep track of the longest prefix */
695:
696: len = strlen (prefix);
697: if (len > pprefix->max_len)
698: pprefix->max_len = len;
699:
700: pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list));
701: pl->prefix = savestring (prefix, len);
702:
703: if (*prev)
704: pl->next = *prev;
705: else
706: pl->next = (struct prefix_list *) 0;
707: *prev = pl;
708: }
709:
710: /* Take the value of the environment variable ENV, break it into a path, and
711: add of the entries to PPREFIX. */
712:
713: static void
714: prefix_from_env (env, pprefix)
715: char *env;
716: struct path_prefix *pprefix;
717: {
718: char *p = getenv (env);
719:
720: if (p)
721: {
722: char *startp, *endp;
723: char *nstore = (char *) xmalloc (strlen (p) + 3);
724:
725: startp = endp = p;
726: while (1)
727: {
728: if (*endp == PATH_SEPARATOR || *endp == 0)
729: {
730: strncpy (nstore, startp, endp-startp);
731: if (endp == startp)
732: {
733: strcpy (nstore, "./");
734: }
735: else if (endp[-1] != '/')
736: {
737: nstore[endp-startp] = '/';
738: nstore[endp-startp+1] = 0;
739: }
740: else
741: nstore[endp-startp] = 0;
742:
743: add_prefix (pprefix, nstore);
744: if (*endp == 0)
745: break;
746: endp = startp = endp + 1;
747: }
748: else
749: endp++;
750: }
751: }
752: }
753:
754: /* Main program. */
755:
756: int
757: main (argc, argv)
758: int argc;
759: char *argv[];
760: {
761: char *ld_suffix = "ld";
762: char *full_ld_suffix = ld_suffix;
763: char *real_ld_suffix = "real-ld";
764: char *full_real_ld_suffix = real_ld_suffix;
765: #if 0
766: char *gld_suffix = "gld";
767: char *full_gld_suffix = gld_suffix;
768: #endif
769: char *nm_suffix = "nm";
770: char *full_nm_suffix = nm_suffix;
771: char *gnm_suffix = "gnm";
772: char *full_gnm_suffix = gnm_suffix;
773: char *strip_suffix = "strip";
774: char *full_strip_suffix = strip_suffix;
775: char *gstrip_suffix = "gstrip";
776: char *full_gstrip_suffix = gstrip_suffix;
777: char *arg;
778: FILE *outf;
779: char *ld_file_name;
780: char *c_file_name;
781: char *collect_name;
782: char *collect_names;
783: char *p;
784: char **c_argv;
785: char **c_ptr;
786: char **ld1_argv = (char **) xcalloc (sizeof (char *), argc+2);
787: char **ld1 = ld1_argv;
788: char **ld2_argv = (char **) xcalloc (sizeof (char *), argc+5);
789: char **ld2 = ld2_argv;
790: int first_file;
791: int num_c_args = argc+7;
792: int len;
793: int clen;
794:
795: #ifdef DEBUG
796: debug = 1;
797: vflag = 1;
798: #endif
799:
800: output_file = "a.out";
801:
802: /* We must check that we do not call ourselves in an infinite
803: recursion loop. We append the name used for us to the COLLECT_NAMES
804: environment variable.
805:
806: In practice, collect will rarely invoke itself. This can happen now
807: that we are no longer called gld. A perfect example is when running
808: gcc in a build directory that has been installed. When looking for
809: ld's, we'll find our installed version and believe that's the real ld. */
810:
811: /* We must also append COLLECT_NAME to COLLECT_NAMES to watch for the
812: previous version of collect (the one that used COLLECT_NAME and only
813: handled two levels of recursion). If we don't we may mutually recurse
814: forever. This can happen (I think) when bootstrapping the old version
815: and a new one is installed (rare, but we should handle it).
816: ??? Hopefully references to COLLECT_NAME can be removed at some point. */
817:
818: collect_name = (char *) getenv ("COLLECT_NAME");
819: collect_names = (char *) getenv ("COLLECT_NAMES");
820:
821: p = (char *) xmalloc (strlen ("COLLECT_NAMES=")
822: + (collect_name ? strlen (collect_name) + 1 : 0)
823: + (collect_names ? strlen (collect_names) + 1 : 0)
824: + strlen (argv[0]) + 1);
825: strcpy (p, "COLLECT_NAMES=");
826: if (collect_name != 0)
827: sprintf (p + strlen (p), "%s%c", collect_name, PATH_SEPARATOR);
828: if (collect_names != 0)
829: sprintf (p + strlen (p), "%s%c", collect_names, PATH_SEPARATOR);
830: strcat (p, argv[0]);
831: putenv (p);
832:
833: prefix_from_env ("COLLECT_NAMES", &our_file_names);
834:
835: /* Set environment variable COLLECT_NAME to our name so the previous version
836: of collect won't find us. If it does we'll mutually recurse forever.
837: This can happen when bootstrapping the new version and an old version is
838: installed.
839: ??? Hopefully this bit of code can be removed at some point. */
840:
841: p = xmalloc (strlen ("COLLECT_NAME=") + strlen (argv[0]) + 1);
842: sprintf (p, "COLLECT_NAME=%s", argv[0]);
843: putenv (p);
844:
845: p = (char *) getenv ("COLLECT_GCC_OPTIONS");
846: if (p)
847: while (*p)
848: {
849: char *q = p;
850: while (*q && *q != ' ') q++;
851: if (*p == '-' && p[1] == 'm')
852: num_c_args++;
853:
854: if (*q) q++;
855: p = q;
856: }
857:
858: c_ptr = c_argv = (char **) xcalloc (sizeof (char *), num_c_args);
859:
860: if (argc < 2)
861: fatal ("no arguments");
862:
863: #ifdef SIGQUIT
864: if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
865: signal (SIGQUIT, handler);
866: #endif
867: if (signal (SIGINT, SIG_IGN) != SIG_IGN)
868: signal (SIGINT, handler);
869: #ifdef SIGALRM
870: if (signal (SIGALRM, SIG_IGN) != SIG_IGN)
871: signal (SIGALRM, handler);
872: #endif
873: #ifdef SIGHUP
874: if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
875: signal (SIGHUP, handler);
876: #endif
877: if (signal (SIGSEGV, SIG_IGN) != SIG_IGN)
878: signal (SIGSEGV, handler);
879: #ifdef SIGBUS
880: if (signal (SIGBUS, SIG_IGN) != SIG_IGN)
881: signal (SIGBUS, handler);
882: #endif
883:
884: /* Extract COMPILER_PATH and PATH into our prefix list. */
885: prefix_from_env ("COMPILER_PATH", &cpath);
886: prefix_from_env ("PATH", &path);
887:
888: #ifdef CROSS_COMPILE
889: /* If we look for a program in the compiler directories, we just use
890: the short name, since these directories are already system-specific.
891: But it we look for a took in the system directories, we need to
892: qualify the program name with the target machine. */
893:
894: full_ld_suffix
895: = xcalloc (strlen (ld_suffix) + strlen (target_machine) + 2, 1);
896: strcpy (full_ld_suffix, target_machine);
897: strcat (full_ld_suffix, "-");
898: strcat (full_ld_suffix, ld_suffix);
899:
900: full_real_ld_suffix
901: = xcalloc (strlen (real_ld_suffix) + strlen (target_machine) + 2, 1);
902: strcpy (full_real_ld_suffix, target_machine);
903: strcat (full_real_ld_suffix, "-");
904: strcat (full_real_ld_suffix, real_ld_suffix);
905:
906: #if 0
907: full_gld_suffix
908: = xcalloc (strlen (gld_suffix) + strlen (target_machine) + 2, 1);
909: strcpy (full_gld_suffix, target_machine);
910: strcat (full_gld_suffix, "-");
911: strcat (full_gld_suffix, gld_suffix);
912: #endif
913:
914: full_nm_suffix
915: = xcalloc (strlen (nm_suffix) + strlen (target_machine) + 2, 1);
916: strcpy (full_nm_suffix, target_machine);
917: strcat (full_nm_suffix, "-");
918: strcat (full_nm_suffix, nm_suffix);
919:
920: full_gnm_suffix
921: = xcalloc (strlen (gnm_suffix) + strlen (target_machine) + 2, 1);
922: strcpy (full_gnm_suffix, target_machine);
923: strcat (full_gnm_suffix, "-");
924: strcat (full_gnm_suffix, gnm_suffix);
925:
926: full_strip_suffix
927: = xcalloc (strlen (strip_suffix) + strlen (target_machine) + 2, 1);
928: strcpy (full_strip_suffix, target_machine);
929: strcat (full_strip_suffix, "-");
930: strcat (full_strip_suffix, strip_suffix);
931:
932: full_gstrip_suffix
933: = xcalloc (strlen (gstrip_suffix) + strlen (target_machine) + 2, 1);
934: strcpy (full_gstrip_suffix, target_machine);
935: strcat (full_gstrip_suffix, "-");
936: strcat (full_gstrip_suffix, gstrip_suffix);
937: #endif /* CROSS_COMPILE */
938:
939: /* Try to discover a valid linker/nm/strip to use. */
940:
941: #if 0
942: /* Search the (target-specific) compiler dirs for `gld'. */
943: ld_file_name = find_a_file (&cpath, gld_suffix);
944: /* Search the ordinary system bin directories
945: for `gld' (if native linking) or `TARGET-gld' (if cross). */
946: if (ld_file_name == 0)
947: ld_file_name = find_a_file (&path, full_gld_suffix);
948: #else
949: ld_file_name = 0;
950: #endif
951: /* Likewise for `real-ld'. */
952: if (ld_file_name == 0)
953: ld_file_name = find_a_file (&cpath, real_ld_suffix);
954: if (ld_file_name == 0)
955: ld_file_name = find_a_file (&path, full_real_ld_suffix);
956: /* Maybe we know the right file to use (if not cross). */
957: #ifdef REAL_LD_FILE_NAME
958: if (ld_file_name == 0)
959: ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME);
960: #endif
961: if (ld_file_name == 0)
962: ld_file_name = find_a_file (&cpath, full_ld_suffix);
963: /* Search the ordinary system bin directories
964: for `ld' (if native linking) or `TARGET-ld' (if cross). */
965: if (ld_file_name == 0)
966: ld_file_name = find_a_file (&path, full_ld_suffix);
967:
968: /* If we've invoked ourselves, try again with LD_FILE_NAME. */
969:
970: if (collect_names != 0)
971: {
972: if (ld_file_name != 0)
973: {
974: argv[0] = ld_file_name;
975: execvp (argv[0], argv);
976: }
977: fatal ("cannot find `ld'");
978: }
979:
980: nm_file_name = find_a_file (&cpath, gnm_suffix);
981: if (nm_file_name == 0)
982: nm_file_name = find_a_file (&path, full_gnm_suffix);
983: if (nm_file_name == 0)
984: nm_file_name = find_a_file (&cpath, nm_suffix);
985: #ifdef REAL_NM_FILE_NAME
986: if (nm_file_name == 0)
987: nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME);
988: #endif
989: if (nm_file_name == 0)
990: nm_file_name = find_a_file (&path, full_nm_suffix);
991:
992: strip_file_name = find_a_file (&cpath, gstrip_suffix);
993: if (strip_file_name == 0)
994: strip_file_name = find_a_file (&path, full_gstrip_suffix);
995: if (strip_file_name == 0)
996: strip_file_name = find_a_file (&cpath, strip_suffix);
997: #ifdef REAL_STRIP_FILE_NAME
998: if (strip_file_name == 0)
999: strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME);
1000: #endif
1001: if (strip_file_name == 0)
1002: strip_file_name = find_a_file (&path, full_strip_suffix);
1003:
1004: /* Determine the full path name of the C compiler to use. */
1005: c_file_name = getenv ("COLLECT_GCC");
1006: if (c_file_name == 0)
1007: {
1008: #ifdef CROSS_COMPILE
1009: c_file_name = xcalloc (sizeof ("gcc-") + strlen (target_machine) + 1, 1);
1010: strcpy (c_file_name, target_machine);
1011: strcat (c_file_name, "-gcc");
1012: #else
1013: c_file_name = "gcc";
1014: #endif
1015: }
1016:
1017: p = find_a_file (&cpath, c_file_name);
1018:
1019: /* Here it should be safe to use the system search path since we should have
1020: already qualified the name of the compiler when it is needed. */
1021: if (p == 0)
1022: p = find_a_file (&path, c_file_name);
1023:
1024: if (p)
1025: c_file_name = p;
1026:
1027: *ld1++ = *ld2++ = ld_file_name;
1028:
1029: /* Make temp file names. */
1030: choose_temp_base ();
1031: c_file = xcalloc (temp_filename_length + sizeof (".c"), 1);
1032: o_file = xcalloc (temp_filename_length + sizeof (".o"), 1);
1033: sprintf (c_file, "%s.c", temp_filename);
1034: sprintf (o_file, "%s.o", temp_filename);
1035: *c_ptr++ = c_file_name;
1036: *c_ptr++ = "-c";
1037: *c_ptr++ = "-o";
1038: *c_ptr++ = o_file;
1039:
1040: /* !!! When GCC calls collect2,
1041: it does not know whether it is calling collect2 or ld.
1042: So collect2 cannot meaningfully understand any options
1043: except those ld understands.
1044: If you propose to make GCC pass some other option,
1045: just imagine what will happen if ld is really ld!!! */
1046:
1047: /* Parse arguments. Remember output file spec, pass the rest to ld. */
1048: /* After the first file, put in the c++ rt0. */
1049:
1050: first_file = 1;
1051: while ((arg = *++argv) != (char *)0)
1052: {
1053: *ld1++ = *ld2++ = arg;
1054:
1055: if (arg[0] == '-')
1056: switch (arg[1])
1057: {
1058: case 'd':
1059: if (!strcmp (arg, "-debug"))
1060: {
1061: debug = 1;
1062: vflag = 1;
1063: ld1--;
1064: ld2--;
1065: }
1066: break;
1067:
1068: case 'o':
1069: output_file = (arg[2] == '\0') ? argv[1] : &arg[2];
1070: break;
1071:
1072: case 'r':
1073: if (arg[2] == '\0')
1074: rflag = 1;
1075: break;
1076:
1077: case 's':
1078: if (arg[2] == '\0')
1079: {
1080: /* We must strip after the nm run, otherwise C++ linking
1081: won't work. Thus we strip in the second ld run, or
1082: else with strip if there is no second ld run. */
1083: strip_flag = 1;
1084: ld1--;
1085: }
1086: break;
1087:
1088: case 'v':
1089: if (arg[2] == '\0')
1090: vflag = 1;
1091: break;
1092: }
1093:
1094: else if (first_file
1095: && (p = rindex (arg, '.')) != (char *)0
1096: && strcmp (p, ".o") == 0)
1097: {
1098: first_file = 0;
1099: *ld2++ = o_file;
1100: }
1101: }
1102:
1103: /* Get any options that the upper GCC wants to pass to the sub-GCC. */
1104: p = (char *) getenv ("COLLECT_GCC_OPTIONS");
1105: if (p)
1106: while (*p)
1107: {
1108: char *q = p;
1109: while (*q && *q != ' ') q++;
1110: if (*p == '-' && (p[1] == 'm' || p[1] == 'f'))
1111: *c_ptr++ = savestring (p, q - p);
1112:
1113: if (*q) q++;
1114: p = q;
1115: }
1116:
1117: *c_ptr++ = c_file;
1118: *c_ptr = *ld1 = *ld2 = (char *)0;
1119:
1120: if (vflag)
1121: {
1122: fprintf (stderr, "collect2 version %s", version_string);
1123: #ifdef TARGET_VERSION
1124: TARGET_VERSION;
1125: #endif
1126: fprintf (stderr, "\n");
1127: }
1128:
1129: if (debug)
1130: {
1131: char *ptr;
1132: fprintf (stderr, "ld_file_name = %s\n",
1133: (ld_file_name ? ld_file_name : "not found"));
1134: fprintf (stderr, "c_file_name = %s\n",
1135: (c_file_name ? c_file_name : "not found"));
1136: fprintf (stderr, "nm_file_name = %s\n",
1137: (nm_file_name ? nm_file_name : "not found"));
1138: fprintf (stderr, "strip_file_name = %s\n",
1139: (strip_file_name ? strip_file_name : "not found"));
1140: fprintf (stderr, "c_file = %s\n",
1141: (c_file ? c_file : "not found"));
1142: fprintf (stderr, "o_file = %s\n",
1143: (o_file ? o_file : "not found"));
1144:
1145: ptr = getenv ("COLLECT_NAMES");
1146: if (ptr)
1147: fprintf (stderr, "COLLECT_NAMES = %s\n", ptr);
1148:
1149: ptr = getenv ("COLLECT_GCC_OPTIONS");
1150: if (ptr)
1151: fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
1152:
1153: ptr = getenv ("COLLECT_GCC");
1154: if (ptr)
1155: fprintf (stderr, "COLLECT_GCC = %s\n", ptr);
1156:
1157: ptr = getenv ("COMPILER_PATH");
1158: if (ptr)
1159: fprintf (stderr, "COMPILER_PATH = %s\n", ptr);
1160:
1161: ptr = getenv ("LIBRARY_PATH");
1162: if (ptr)
1163: fprintf (stderr, "LIBRARY_PATH = %s\n", ptr);
1164:
1165: fprintf (stderr, "\n");
1166: }
1167:
1168: /* Load the program, searching all libraries.
1169: Examine the namelist with nm and search it for static constructors
1170: and destructors to call.
1171: Write the constructor and destructor tables to a .s file and reload. */
1172:
1173: fork_execute ("ld", ld1_argv);
1174:
1175: /* If -r, don't build the constructor or destructor list, just return now. */
1176: if (rflag)
1177: return 0;
1178:
1179: scan_prog_file (output_file, PASS_FIRST);
1180:
1181: if (debug)
1182: {
1183: fprintf (stderr, "%d constructor(s) found\n", constructors.number);
1184: fprintf (stderr, "%d destructor(s) found\n", destructors.number);
1185: }
1186:
1187: if (constructors.number == 0 && destructors.number == 0)
1188: {
1189: /* Strip now if it was requested on the command line. */
1190: if (strip_flag)
1191: {
1192: char **strip_argv = (char **) xcalloc (sizeof (char *), 3);
1193: strip_argv[0] = strip_file_name;
1194: strip_argv[1] = output_file;
1195: strip_argv[2] = (char *) 0;
1196: fork_execute ("strip", strip_argv);
1197: }
1198: return 0;
1199: }
1200:
1201: outf = fopen (c_file, "w");
1202: if (outf == (FILE *)0)
1203: fatal_perror ("%s", c_file);
1204:
1205: write_c_file (outf, c_file);
1206:
1207: if (fclose (outf))
1208: fatal_perror ("closing %s", c_file);
1209:
1210: if (debug)
1211: {
1212: fprintf (stderr, "\n========== output_file = %s, c_file = %s\n",
1213: output_file, c_file);
1214: write_c_file (stderr, "stderr");
1215: fprintf (stderr, "========== end of c_file\n\n");
1216: }
1217:
1218: /* Assemble the constructor and destructor tables.
1219: Link the tables in with the rest of the program. */
1220:
1221: fork_execute ("gcc", c_argv);
1222: fork_execute ("ld", ld2_argv);
1223:
1224: /* Let scan_prog_file do any final mods (OSF/rose needs this for
1225: constructors/destructors in shared libraries. */
1226: scan_prog_file (output_file, PASS_SECOND);
1227:
1228: maybe_unlink (c_file);
1229: maybe_unlink (o_file);
1230: return 0;
1231: }
1232:
1233:
1234: /* Wait for a process to finish, and exit if a non-zero status is found. */
1235:
1236: static void
1237: do_wait (prog)
1238: char *prog;
1239: {
1240: int status;
1241:
1242: wait (&status);
1243: if (status)
1244: {
1245: int sig = status & 0x7F;
1246: int ret;
1247:
1248: if (sig != -1 && sig != 0)
1249: {
1250: #ifdef NO_SYS_SIGLIST
1251: error ("%s terminated with signal %d %s",
1252: prog,
1253: sig,
1254: (status & 0200) ? ", core dumped" : "");
1255: #else
1256: error ("%s terminated with signal %d [%s]%s",
1257: prog,
1258: sig,
1259: sys_siglist[sig],
1260: (status & 0200) ? ", core dumped" : "");
1261: #endif
1262:
1263: my_exit (127);
1264: }
1265:
1266: ret = ((status & 0xFF00) >> 8);
1267: if (ret != -1 && ret != 0)
1268: {
1269: error ("%s returned %d exit status", prog, ret);
1270: my_exit (ret);
1271: }
1272: }
1273: }
1274:
1275:
1276: /* Fork and execute a program, and wait for the reply. */
1277:
1278: static void
1279: fork_execute (prog, argv)
1280: char *prog;
1281: char **argv;
1282: {
1283: int pid;
1284:
1285: if (vflag || debug)
1286: {
1287: char **p_argv;
1288: char *str;
1289:
1290: if (argv[0])
1291: fprintf (stderr, "%s", argv[0]);
1292: else
1293: fprintf (stderr, "[cannot find %s]", prog);
1294:
1295: for (p_argv = &argv[1]; (str = *p_argv) != (char *)0; p_argv++)
1296: fprintf (stderr, " %s", str);
1297:
1298: fprintf (stderr, "\n");
1299: }
1300:
1301: fflush (stdout);
1302: fflush (stderr);
1303:
1304: /* If we can't find a program we need, complain error. Do this here
1305: since we might not end up needing something that we couldn't find. */
1306:
1307: if (argv[0] == 0)
1308: fatal ("cannot find `%s'", prog);
1309:
1310: pid = vfork ();
1311: if (pid == -1)
1312: {
1313: #ifdef vfork
1314: fatal_perror ("fork");
1315: #else
1316: fatal_perror ("vfork");
1317: #endif
1318: }
1319:
1320: if (pid == 0) /* child context */
1321: {
1322: execvp (argv[0], argv);
1323: fatal_perror ("executing %s", prog);
1324: }
1325:
1326: do_wait (prog);
1327: }
1328:
1329:
1330: /* Unlink a file unless we are debugging. */
1331:
1332: static void
1333: maybe_unlink (file)
1334: char *file;
1335: {
1336: if (!debug)
1337: unlink (file);
1338: else
1339: fprintf (stderr, "[Leaving %s]\n", file);
1340: }
1341:
1342:
1343: /* Add a name to a linked list. */
1344:
1345: static void
1346: add_to_list (head_ptr, name)
1347: struct head *head_ptr;
1348: char *name;
1349: {
1350: struct id *newid = (struct id *) xcalloc (sizeof (*newid) + strlen (name), 1);
1351: static long sequence_number = 0;
1352: newid->sequence = ++sequence_number;
1353: strcpy (newid->name, name);
1354:
1355: if (head_ptr->first)
1356: head_ptr->last->next = newid;
1357: else
1358: head_ptr->first = newid;
1359:
1360: head_ptr->last = newid;
1361: head_ptr->number++;
1362: }
1363:
1364: /* Write: `prefix', the names on list LIST, `suffix'. */
1365:
1366: static void
1367: write_list (stream, prefix, list)
1368: FILE *stream;
1369: char *prefix;
1370: struct id *list;
1371: {
1372: while (list)
1373: {
1374: fprintf (stream, "%sx%d,\n", prefix, list->sequence);
1375: list = list->next;
1376: }
1377: }
1378:
1379: static void
1380: write_list_with_asm (stream, prefix, list)
1381: FILE *stream;
1382: char *prefix;
1383: struct id *list;
1384: {
1385: while (list)
1386: {
1387: fprintf (stream, "%sx%d __asm__ (\"%s\");\n",
1388: prefix, list->sequence, list->name);
1389: list = list->next;
1390: }
1391: }
1392:
1393: /* Write the constructor/destructor tables. */
1394:
1395: static void
1396: write_c_file (stream, name)
1397: FILE *stream;
1398: char *name;
1399: {
1400: /* Write the tables as C code */
1401:
1402: fprintf (stream, "typedef void entry_pt();\n\n");
1403:
1404: write_list_with_asm (stream, "extern entry_pt ", constructors.first);
1405:
1406: fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
1407: fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number);
1408: write_list (stream, "\t", constructors.first);
1409: fprintf (stream, "\t0\n};\n\n");
1410:
1411: write_list_with_asm (stream, "extern entry_pt ", destructors.first);
1412:
1413: fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
1414: fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number);
1415: write_list (stream, "\t", destructors.first);
1416: fprintf (stream, "\t0\n};\n\n");
1417:
1418: fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
1419: fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);
1420: }
1421:
1422:
1423: #ifdef OBJECT_FORMAT_NONE
1424:
1425: /* Generic version to scan the name list of the loaded program for
1426: the symbols g++ uses for static constructors and destructors.
1427:
1428: The constructor table begins at __CTOR_LIST__ and contains a count
1429: of the number of pointers (or -1 if the constructors are built in a
1430: separate section by the linker), followed by the pointers to the
1431: constructor functions, terminated with a null pointer. The
1432: destructor table has the same format, and begins at __DTOR_LIST__. */
1433:
1434: static void
1435: scan_prog_file (prog_name, which_pass)
1436: char *prog_name;
1437: enum pass which_pass;
1438: {
1439: void (*int_handler) ();
1440: void (*quit_handler) ();
1441: char *nm_argv[4];
1442: int pid;
1443: int argc = 0;
1444: int pipe_fd[2];
1445: char *p, buf[1024];
1446: FILE *inf;
1447:
1448: if (which_pass != PASS_FIRST)
1449: return;
1450:
1451: /* If we don't have an `nm', complain. */
1452: if (nm_file_name == 0)
1453: fatal ("cannot find `nm'");
1454:
1455: nm_argv[argc++] = "nm";
1456: if (NM_FLAGS[0] != '\0')
1457: nm_argv[argc++] = NM_FLAGS;
1458:
1459: nm_argv[argc++] = prog_name;
1460: nm_argv[argc++] = (char *)0;
1461:
1462: if (pipe (pipe_fd) < 0)
1463: fatal_perror ("pipe");
1464:
1465: inf = fdopen (pipe_fd[0], "r");
1466: if (inf == (FILE *)0)
1467: fatal_perror ("fdopen");
1468:
1469: /* Trace if needed. */
1470: if (vflag)
1471: {
1472: char **p_argv;
1473: char *str;
1474:
1475: fprintf (stderr, "%s", nm_file_name);
1476: for (p_argv = &nm_argv[1]; (str = *p_argv) != (char *)0; p_argv++)
1477: fprintf (stderr, " %s", str);
1478:
1479: fprintf (stderr, "\n");
1480: }
1481:
1482: fflush (stdout);
1483: fflush (stderr);
1484:
1485: /* Spawn child nm on pipe */
1486: pid = vfork ();
1487: if (pid == -1)
1488: {
1489: #ifdef vfork
1490: fatal_perror ("fork");
1491: #else
1492: fatal_perror ("vfork");
1493: #endif
1494: }
1495:
1496: if (pid == 0) /* child context */
1497: {
1498: /* setup stdout */
1499: if (dup2 (pipe_fd[1], 1) < 0)
1500: fatal_perror ("dup2 (%d, 1)", pipe_fd[1]);
1501:
1502: if (close (pipe_fd[0]) < 0)
1503: fatal_perror ("close (%d)", pipe_fd[0]);
1504:
1505: if (close (pipe_fd[1]) < 0)
1506: fatal_perror ("close (%d)", pipe_fd[1]);
1507:
1508: execv (nm_file_name, nm_argv);
1509: fatal_perror ("executing %s", nm_file_name);
1510: }
1511:
1512: /* Parent context from here on. */
1513: int_handler = (void (*) ())signal (SIGINT, SIG_IGN);
1514: #ifdef SIGQUIT
1515: quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN);
1516: #endif
1517:
1518: if (close (pipe_fd[1]) < 0)
1519: fatal_perror ("close (%d)", pipe_fd[1]);
1520:
1521: if (debug)
1522: fprintf (stderr, "\nnm output with constructors/destructors.\n");
1523:
1524: /* Read each line of nm output. */
1525: while (fgets (buf, sizeof buf, inf) != (char *)0)
1526: {
1527: int ch, ch2;
1528: char *name, *end;
1529:
1530: /* If it contains a constructor or destructor name, add the name
1531: to the appropriate list. */
1532:
1533: for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
1534: ;
1535:
1536: if (ch == '\0' || ch == '\n')
1537: continue;
1538:
1539: name = p;
1540: /* Find the end of the symbol name.
1541: Don't include `|', because Encore nm can tack that on the end. */
1542: for (end = p; (ch2 = *end) != '\0' && !isspace (ch2) && ch2 != '|';
1543: end++)
1544: continue;
1545:
1546: *end = '\0';
1547: switch (is_ctor_dtor (name))
1548: {
1549: case 1:
1550: add_to_list (&constructors, name);
1551: break;
1552:
1553: case 2:
1554: add_to_list (&destructors, name);
1555: break;
1556:
1557: default: /* not a constructor or destructor */
1558: continue;
1559: }
1560:
1561: if (debug)
1562: fprintf (stderr, "\t%s\n", buf);
1563: }
1564:
1565: if (debug)
1566: fprintf (stderr, "\n");
1567:
1568: if (fclose (inf) != 0)
1569: fatal_perror ("fclose of pipe");
1570:
1571: do_wait (nm_file_name);
1572:
1573: signal (SIGINT, int_handler);
1574: #ifdef SIGQUIT
1575: signal (SIGQUIT, quit_handler);
1576: #endif
1577: }
1578:
1579: #endif /* OBJECT_FORMAT_NONE */
1580:
1581:
1582: /*
1583: * COFF specific stuff.
1584: */
1585:
1586: #ifdef OBJECT_FORMAT_COFF
1587:
1588: #if defined(EXTENDED_COFF)
1589: # define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
1590: # define GCC_SYMENT SYMR
1591: # define GCC_OK_SYMBOL(X) ((X).st == stProc && (X).sc == scText)
1592: # define GCC_SYMINC(X) (1)
1593: # define GCC_SYMZERO(X) (SYMHEADER(X).isymMax)
1594: # define GCC_CHECK_HDR(X) (PSYMTAB(X) != 0)
1595: #else
1596: # define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms)
1597: # define GCC_SYMENT SYMENT
1598: # define GCC_OK_SYMBOL(X) \
1599: (((X).n_sclass == C_EXT) && \
1600: (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) || \
1601: ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))
1602: # define GCC_SYMINC(X) ((X).n_numaux+1)
1603: # define GCC_SYMZERO(X) 0
1604: # define GCC_CHECK_HDR(X) (1)
1605: #endif
1606:
1607: extern char *ldgetname ();
1608:
1609: /* COFF version to scan the name list of the loaded program for
1610: the symbols g++ uses for static constructors and destructors.
1611:
1612: The constructor table begins at __CTOR_LIST__ and contains a count
1613: of the number of pointers (or -1 if the constructors are built in a
1614: separate section by the linker), followed by the pointers to the
1615: constructor functions, terminated with a null pointer. The
1616: destructor table has the same format, and begins at __DTOR_LIST__. */
1617:
1618: static void
1619: scan_prog_file (prog_name, which_pass)
1620: char *prog_name;
1621: enum pass which_pass;
1622: {
1623: LDFILE *ldptr = NULL;
1624: int sym_index, sym_count;
1625:
1626: if (which_pass != PASS_FIRST)
1627: return;
1628:
1629: if ((ldptr = ldopen (prog_name, ldptr)) == NULL)
1630: fatal ("%s: can't open as COFF file", prog_name);
1631:
1632: if (!MY_ISCOFF (HEADER (ldptr).f_magic))
1633: fatal ("%s: not a COFF file", prog_name);
1634:
1635: if (GCC_CHECK_HDR (ldptr))
1636: {
1637: sym_count = GCC_SYMBOLS (ldptr);
1638: sym_index = GCC_SYMZERO (ldptr);
1639: while (sym_index < sym_count)
1640: {
1641: GCC_SYMENT symbol;
1642:
1643: if (ldtbread (ldptr, sym_index, &symbol) <= 0)
1644: break;
1645: sym_index += GCC_SYMINC (symbol);
1646:
1647: if (GCC_OK_SYMBOL (symbol))
1648: {
1649: char *name;
1650:
1651: if ((name = ldgetname (ldptr, &symbol)) == NULL)
1652: continue; /* should never happen */
1653:
1654: #ifdef _AIX
1655: /* All AIX function names begin with a dot. */
1656: if (*name++ != '.')
1657: continue;
1658: #endif
1659:
1660: switch (is_ctor_dtor (name))
1661: {
1662: case 1:
1663: add_to_list (&constructors, name);
1664: break;
1665:
1666: case 2:
1667: add_to_list (&destructors, name);
1668: break;
1669:
1670: default: /* not a constructor or destructor */
1671: continue;
1672: }
1673:
1674: #if !defined(EXTENDED_COFF)
1675: if (debug)
1676: fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
1677: symbol.n_scnum, symbol.n_sclass,
1678: (symbol.n_type ? "0" : ""), symbol.n_type,
1679: name);
1680: #else
1681: if (debug)
1682: fprintf (stderr, "\tiss = %5d, value = %5d, index = %5d, name = %s\n",
1683: symbol.iss, symbol.value, symbol.index, name);
1684: #endif
1685: }
1686: }
1687: }
1688:
1689: (void) ldclose(ldptr);
1690: }
1691:
1692: #endif /* OBJECT_FORMAT_COFF */
1693:
1694:
1695: /*
1696: * OSF/rose specific stuff.
1697: */
1698:
1699: #ifdef OBJECT_FORMAT_ROSE
1700:
1701: /* Union of the various load commands */
1702:
1703: typedef union load_union
1704: {
1705: ldc_header_t hdr; /* common header */
1706: load_cmd_map_command_t map; /* map indexing other load cmds */
1707: interpreter_command_t iprtr; /* interpreter pathname */
1708: strings_command_t str; /* load commands strings section */
1709: region_command_t region; /* region load command */
1710: reloc_command_t reloc; /* relocation section */
1711: package_command_t pkg; /* package load command */
1712: symbols_command_t sym; /* symbol sections */
1713: entry_command_t ent; /* program start section */
1714: gen_info_command_t info; /* object information */
1715: func_table_command_t func; /* function constructors/destructors */
1716: } load_union_t;
1717:
1718: /* Structure to point to load command and data section in memory. */
1719:
1720: typedef struct load_all
1721: {
1722: load_union_t *load; /* load command */
1723: char *section; /* pointer to section */
1724: } load_all_t;
1725:
1726: /* Structure to contain information about a file mapped into memory. */
1727:
1728: struct file_info
1729: {
1730: char *start; /* start of map */
1731: char *name; /* filename */
1732: long size; /* size of the file */
1733: long rounded_size; /* size rounded to page boundary */
1734: int fd; /* file descriptor */
1735: int rw; /* != 0 if opened read/write */
1736: int use_mmap; /* != 0 if mmap'ed */
1737: };
1738:
1739: extern int decode_mach_o_hdr ();
1740: extern int encode_mach_o_hdr ();
1741:
1742: static void add_func_table PROTO((mo_header_t *, load_all_t *,
1743: symbol_info_t *, int));
1744: static void print_header PROTO((mo_header_t *));
1745: static void print_load_command PROTO((load_union_t*, size_t, int));
1746: static void bad_header PROTO((int));
1747: static struct file_info *read_file PROTO((char *, int, int));
1748: static void end_file PROTO((struct file_info *));
1749:
1750: /* OSF/rose specific version to scan the name list of the loaded
1751: program for the symbols g++ uses for static constructors and
1752: destructors.
1753:
1754: The constructor table begins at __CTOR_LIST__ and contains a count
1755: of the number of pointers (or -1 if the constructors are built in a
1756: separate section by the linker), followed by the pointers to the
1757: constructor functions, terminated with a null pointer. The
1758: destructor table has the same format, and begins at __DTOR_LIST__. */
1759:
1760: static void
1761: scan_prog_file (prog_name, which_pass)
1762: char *prog_name;
1763: enum pass which_pass;
1764: {
1765: char *obj;
1766: mo_header_t hdr;
1767: load_all_t *load_array;
1768: load_all_t *load_end;
1769: load_all_t *load_cmd;
1770: int symbol_load_cmds;
1771: off_t offset;
1772: int i;
1773: int num_syms;
1774: int status;
1775: char *str_sect;
1776: struct file_info *obj_file;
1777: int prog_fd;
1778: mo_lcid_t cmd_strings = -1;
1779: symbol_info_t *main_sym = 0;
1780: int rw = (which_pass != PASS_FIRST);
1781:
1782: prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY);
1783: if (prog_fd < 0)
1784: fatal_perror ("can't read %s", prog_name);
1785:
1786: obj_file = read_file (prog_name, prog_fd, rw);
1787: obj = obj_file->start;
1788:
1789: status = decode_mach_o_hdr (obj, MO_SIZEOF_RAW_HDR, MOH_HEADER_VERSION, &hdr);
1790: if (status != MO_HDR_CONV_SUCCESS)
1791: bad_header (status);
1792:
1793:
1794: /* Do some basic sanity checks. Note we explicitly use the big endian magic number,
1795: since the hardware will automatically swap bytes for us on loading little endian
1796: integers. */
1797:
1798: #ifndef CROSS_COMPILE
1799: if (hdr.moh_magic != MOH_MAGIC_MSB
1800: || hdr.moh_header_version != MOH_HEADER_VERSION
1801: || hdr.moh_byte_order != OUR_BYTE_ORDER
1802: || hdr.moh_data_rep_id != OUR_DATA_REP_ID
1803: || hdr.moh_cpu_type != OUR_CPU_TYPE
1804: || hdr.moh_cpu_subtype != OUR_CPU_SUBTYPE
1805: || hdr.moh_vendor_type != OUR_VENDOR_TYPE)
1806: {
1807: fatal ("incompatibilities between object file & expected values");
1808: }
1809: #endif
1810:
1811: if (debug)
1812: print_header (&hdr);
1813:
1814: offset = hdr.moh_first_cmd_off;
1815: load_end = load_array
1816: = (load_all_t *) xcalloc (sizeof (load_all_t), hdr.moh_n_load_cmds + 2);
1817:
1818: /* Build array of load commands, calculating the offsets */
1819: for (i = 0; i < hdr.moh_n_load_cmds; i++)
1820: {
1821: load_union_t *load_hdr; /* load command header */
1822:
1823: load_cmd = load_end++;
1824: load_hdr = (load_union_t *) (obj + offset);
1825:
1826: /* If modifying the program file, copy the header. */
1827: if (rw)
1828: {
1829: load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size);
1830: bcopy ((generic *)load_hdr, (generic *)ptr, load_hdr->hdr.ldci_cmd_size);
1831: load_hdr = ptr;
1832:
1833: /* null out old command map, because we will rewrite at the end. */
1834: if (ptr->hdr.ldci_cmd_type == LDC_CMD_MAP)
1835: {
1836: cmd_strings = ptr->map.lcm_ld_cmd_strings;
1837: ptr->hdr.ldci_cmd_type = LDC_UNDEFINED;
1838: }
1839: }
1840:
1841: load_cmd->load = load_hdr;
1842: if (load_hdr->hdr.ldci_section_off > 0)
1843: load_cmd->section = obj + load_hdr->hdr.ldci_section_off;
1844:
1845: if (debug)
1846: print_load_command (load_hdr, offset, i);
1847:
1848: offset += load_hdr->hdr.ldci_cmd_size;
1849: }
1850:
1851: /* If the last command is the load command map and is not undefined,
1852: decrement the count of load commands. */
1853: if (rw && load_end[-1].load->hdr.ldci_cmd_type == LDC_UNDEFINED)
1854: {
1855: load_end--;
1856: hdr.moh_n_load_cmds--;
1857: }
1858:
1859: /* Go through and process each symbol table section. */
1860: symbol_load_cmds = 0;
1861: for (load_cmd = load_array; load_cmd < load_end; load_cmd++)
1862: {
1863: load_union_t *load_hdr = load_cmd->load;
1864:
1865: if (load_hdr->hdr.ldci_cmd_type == LDC_SYMBOLS)
1866: {
1867: symbol_load_cmds++;
1868:
1869: if (debug)
1870: {
1871: char *kind = "unknown";
1872:
1873: switch (load_hdr->sym.symc_kind)
1874: {
1875: case SYMC_IMPORTS: kind = "imports"; break;
1876: case SYMC_DEFINED_SYMBOLS: kind = "defined"; break;
1877: case SYMC_STABS: kind = "stabs"; break;
1878: }
1879:
1880: fprintf (stderr, "\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
1881: symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
1882: }
1883:
1884: if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
1885: continue;
1886:
1887: str_sect = load_array[load_hdr->sym.symc_strings_section].section;
1888: if (str_sect == (char *)0)
1889: fatal ("string section missing");
1890:
1891: if (load_cmd->section == (char *)0)
1892: fatal ("section pointer missing");
1893:
1894: num_syms = load_hdr->sym.symc_nentries;
1895: for (i = 0; i < num_syms; i++)
1896: {
1897: symbol_info_t *sym = ((symbol_info_t *) load_cmd->section) + i;
1898: char *name = sym->si_name.symbol_name + str_sect;
1899:
1900: if (name[0] != '_')
1901: continue;
1902:
1903: if (rw)
1904: {
1905: char *n = name + strlen (name) - strlen (NAME__MAIN);
1906:
1907: if ((n - name) < 0 || strcmp (n, NAME__MAIN))
1908: continue;
1909: while (n != name)
1910: if (*--n != '_')
1911: continue;
1912:
1913: main_sym = sym;
1914: }
1915: else
1916: {
1917: switch (is_ctor_dtor (name))
1918: {
1919: case 1:
1920: add_to_list (&constructors, name);
1921: break;
1922:
1923: case 2:
1924: add_to_list (&destructors, name);
1925: break;
1926:
1927: default: /* not a constructor or destructor */
1928: continue;
1929: }
1930: }
1931:
1932: if (debug)
1933: fprintf (stderr, "\ttype = 0x%.4x, sc = 0x%.2x, flags = 0x%.8x, name = %.30s\n",
1934: sym->si_type, sym->si_sc_type, sym->si_flags, name);
1935: }
1936: }
1937: }
1938:
1939: if (symbol_load_cmds == 0)
1940: fatal ("no symbol table found");
1941:
1942: /* Update the program file now, rewrite header and load commands. At present,
1943: we assume that there is enough space after the last load command to insert
1944: one more. Since the first section written out is page aligned, and the
1945: number of load commands is small, this is ok for the present. */
1946:
1947: if (rw)
1948: {
1949: load_union_t *load_map;
1950: size_t size;
1951:
1952: if (cmd_strings == -1)
1953: fatal ("no cmd_strings found");
1954:
1955: /* Add __main to initializer list.
1956: If we are building a program instead of a shared library, don't
1957: do anything, since in the current version, you cannot do mallocs
1958: and such in the constructors. */
1959:
1960: if (main_sym != (symbol_info_t *)0
1961: && ((hdr.moh_flags & MOH_EXECABLE_F) == 0))
1962: add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION);
1963:
1964: if (debug)
1965: fprintf (stderr, "\nUpdating header and load commands.\n\n");
1966:
1967: hdr.moh_n_load_cmds++;
1968: size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1));
1969:
1970: /* Create new load command map. */
1971: if (debug)
1972: fprintf (stderr, "load command map, %d cmds, new size %ld.\n",
1973: (int)hdr.moh_n_load_cmds, (long)size);
1974:
1975: load_map = (load_union_t *) xcalloc (1, size);
1976: load_map->map.ldc_header.ldci_cmd_type = LDC_CMD_MAP;
1977: load_map->map.ldc_header.ldci_cmd_size = size;
1978: load_map->map.lcm_ld_cmd_strings = cmd_strings;
1979: load_map->map.lcm_nentries = hdr.moh_n_load_cmds;
1980: load_array[hdr.moh_n_load_cmds-1].load = load_map;
1981:
1982: offset = hdr.moh_first_cmd_off;
1983: for (i = 0; i < hdr.moh_n_load_cmds; i++)
1984: {
1985: load_map->map.lcm_map[i] = offset;
1986: if (load_array[i].load->hdr.ldci_cmd_type == LDC_CMD_MAP)
1987: hdr.moh_load_map_cmd_off = offset;
1988:
1989: offset += load_array[i].load->hdr.ldci_cmd_size;
1990: }
1991:
1992: hdr.moh_sizeofcmds = offset - MO_SIZEOF_RAW_HDR;
1993:
1994: if (debug)
1995: print_header (&hdr);
1996:
1997: /* Write header */
1998: status = encode_mach_o_hdr (&hdr, obj, MO_SIZEOF_RAW_HDR);
1999: if (status != MO_HDR_CONV_SUCCESS)
2000: bad_header (status);
2001:
2002: if (debug)
2003: fprintf (stderr, "writing load commands.\n\n");
2004:
2005: /* Write load commands */
2006: offset = hdr.moh_first_cmd_off;
2007: for (i = 0; i < hdr.moh_n_load_cmds; i++)
2008: {
2009: load_union_t *load_hdr = load_array[i].load;
2010: size_t size = load_hdr->hdr.ldci_cmd_size;
2011:
2012: if (debug)
2013: print_load_command (load_hdr, offset, i);
2014:
2015: bcopy ((generic *)load_hdr, (generic *)(obj + offset), size);
2016: offset += size;
2017: }
2018: }
2019:
2020: end_file (obj_file);
2021:
2022: if (close (prog_fd))
2023: fatal_perror ("closing %s", prog_name);
2024:
2025: if (debug)
2026: fprintf (stderr, "\n");
2027: }
2028:
2029:
2030: /* Add a function table to the load commands to call a function
2031: on initiation or termination of the process. */
2032:
2033: static void
2034: add_func_table (hdr_p, load_array, sym, type)
2035: mo_header_t *hdr_p; /* pointer to global header */
2036: load_all_t *load_array; /* array of ptrs to load cmds */
2037: symbol_info_t *sym; /* pointer to symbol entry */
2038: int type; /* fntc_type value */
2039: {
2040: /* Add a new load command. */
2041: int num_cmds = ++hdr_p->moh_n_load_cmds;
2042: int load_index = num_cmds - 1;
2043: size_t size = sizeof (func_table_command_t) + sizeof (mo_addr_t);
2044: load_union_t *ptr = xcalloc (1, size);
2045: load_all_t *load_cmd;
2046: int i;
2047:
2048: /* Set the unresolved address bit in the header to force the loader to be
2049: used, since kernel exec does not call the initialization functions. */
2050: hdr_p->moh_flags |= MOH_UNRESOLVED_F;
2051:
2052: load_cmd = &load_array[load_index];
2053: load_cmd->load = ptr;
2054: load_cmd->section = (char *)0;
2055:
2056: /* Fill in func table load command. */
2057: ptr->func.ldc_header.ldci_cmd_type = LDC_FUNC_TABLE;
2058: ptr->func.ldc_header.ldci_cmd_size = size;
2059: ptr->func.ldc_header.ldci_section_off = 0;
2060: ptr->func.ldc_header.ldci_section_len = 0;
2061: ptr->func.fntc_type = type;
2062: ptr->func.fntc_nentries = 1;
2063:
2064: /* copy address, turn it from abs. address to (region,offset) if necessary. */
2065: /* Is the symbol already expressed as (region, offset)? */
2066: if ((sym->si_flags & SI_ABSOLUTE_VALUE_F) == 0)
2067: {
2068: ptr->func.fntc_entry_loc[i].adr_lcid = sym->si_value.def_val.adr_lcid;
2069: ptr->func.fntc_entry_loc[i].adr_sctoff = sym->si_value.def_val.adr_sctoff;
2070: }
2071:
2072: /* If not, figure out which region it's in. */
2073: else
2074: {
2075: mo_vm_addr_t addr = sym->si_value.abs_val;
2076: int found = 0;
2077:
2078: for (i = 0; i < load_index; i++)
2079: {
2080: if (load_array[i].load->hdr.ldci_cmd_type == LDC_REGION)
2081: {
2082: region_command_t *region_ptr = &load_array[i].load->region;
2083:
2084: if ((region_ptr->regc_flags & REG_ABS_ADDR_F) != 0
2085: && addr >= region_ptr->regc_addr.vm_addr
2086: && addr <= region_ptr->regc_addr.vm_addr + region_ptr->regc_vm_size)
2087: {
2088: ptr->func.fntc_entry_loc[0].adr_lcid = i;
2089: ptr->func.fntc_entry_loc[0].adr_sctoff = addr - region_ptr->regc_addr.vm_addr;
2090: found++;
2091: break;
2092: }
2093: }
2094: }
2095:
2096: if (!found)
2097: fatal ("could not convert 0x%l.8x into a region", addr);
2098: }
2099:
2100: if (debug)
2101: fprintf (stderr,
2102: "%s function, region %d, offset = %ld (0x%.8lx)\n",
2103: (type == FNTC_INITIALIZATION) ? "init" : "term",
2104: (int)ptr->func.fntc_entry_loc[i].adr_lcid,
2105: (long)ptr->func.fntc_entry_loc[i].adr_sctoff,
2106: (long)ptr->func.fntc_entry_loc[i].adr_sctoff);
2107:
2108: }
2109:
2110:
2111: /* Print the global header for an OSF/rose object. */
2112:
2113: static void
2114: print_header (hdr_ptr)
2115: mo_header_t *hdr_ptr;
2116: {
2117: fprintf (stderr, "\nglobal header:\n");
2118: fprintf (stderr, "\tmoh_magic = 0x%.8lx\n", hdr_ptr->moh_magic);
2119: fprintf (stderr, "\tmoh_major_version = %d\n", (int)hdr_ptr->moh_major_version);
2120: fprintf (stderr, "\tmoh_minor_version = %d\n", (int)hdr_ptr->moh_minor_version);
2121: fprintf (stderr, "\tmoh_header_version = %d\n", (int)hdr_ptr->moh_header_version);
2122: fprintf (stderr, "\tmoh_max_page_size = %d\n", (int)hdr_ptr->moh_max_page_size);
2123: fprintf (stderr, "\tmoh_byte_order = %d\n", (int)hdr_ptr->moh_byte_order);
2124: fprintf (stderr, "\tmoh_data_rep_id = %d\n", (int)hdr_ptr->moh_data_rep_id);
2125: fprintf (stderr, "\tmoh_cpu_type = %d\n", (int)hdr_ptr->moh_cpu_type);
2126: fprintf (stderr, "\tmoh_cpu_subtype = %d\n", (int)hdr_ptr->moh_cpu_subtype);
2127: fprintf (stderr, "\tmoh_vendor_type = %d\n", (int)hdr_ptr->moh_vendor_type);
2128: fprintf (stderr, "\tmoh_load_map_cmd_off = %d\n", (int)hdr_ptr->moh_load_map_cmd_off);
2129: fprintf (stderr, "\tmoh_first_cmd_off = %d\n", (int)hdr_ptr->moh_first_cmd_off);
2130: fprintf (stderr, "\tmoh_sizeofcmds = %d\n", (int)hdr_ptr->moh_sizeofcmds);
2131: fprintf (stderr, "\tmon_n_load_cmds = %d\n", (int)hdr_ptr->moh_n_load_cmds);
2132: fprintf (stderr, "\tmoh_flags = 0x%.8lx", (long)hdr_ptr->moh_flags);
2133:
2134: if (hdr_ptr->moh_flags & MOH_RELOCATABLE_F)
2135: fprintf (stderr, ", relocatable");
2136:
2137: if (hdr_ptr->moh_flags & MOH_LINKABLE_F)
2138: fprintf (stderr, ", linkable");
2139:
2140: if (hdr_ptr->moh_flags & MOH_EXECABLE_F)
2141: fprintf (stderr, ", execable");
2142:
2143: if (hdr_ptr->moh_flags & MOH_EXECUTABLE_F)
2144: fprintf (stderr, ", executable");
2145:
2146: if (hdr_ptr->moh_flags & MOH_UNRESOLVED_F)
2147: fprintf (stderr, ", unresolved");
2148:
2149: fprintf (stderr, "\n\n");
2150: return;
2151: }
2152:
2153:
2154: /* Print a short summary of a load command. */
2155:
2156: static void
2157: print_load_command (load_hdr, offset, number)
2158: load_union_t *load_hdr;
2159: size_t offset;
2160: int number;
2161: {
2162: mo_long_t type = load_hdr->hdr.ldci_cmd_type;
2163: char *type_str = (char *)0;
2164:
2165: switch (type)
2166: {
2167: case LDC_UNDEFINED: type_str = "UNDEFINED"; break;
2168: case LDC_CMD_MAP: type_str = "CMD_MAP"; break;
2169: case LDC_INTERPRETER: type_str = "INTERPRETER"; break;
2170: case LDC_STRINGS: type_str = "STRINGS"; break;
2171: case LDC_REGION: type_str = "REGION"; break;
2172: case LDC_RELOC: type_str = "RELOC"; break;
2173: case LDC_PACKAGE: type_str = "PACKAGE"; break;
2174: case LDC_SYMBOLS: type_str = "SYMBOLS"; break;
2175: case LDC_ENTRY: type_str = "ENTRY"; break;
2176: case LDC_FUNC_TABLE: type_str = "FUNC_TABLE"; break;
2177: case LDC_GEN_INFO: type_str = "GEN_INFO"; break;
2178: }
2179:
2180: fprintf (stderr,
2181: "cmd %2d, sz: 0x%.2lx, coff: 0x%.3lx, doff: 0x%.6lx, dlen: 0x%.6lx",
2182: number,
2183: (long) load_hdr->hdr.ldci_cmd_size,
2184: (long) offset,
2185: (long) load_hdr->hdr.ldci_section_off,
2186: (long) load_hdr->hdr.ldci_section_len);
2187:
2188: if (type_str == (char *)0)
2189: fprintf (stderr, ", ty: unknown (%ld)\n", (long) type);
2190:
2191: else if (type != LDC_REGION)
2192: fprintf (stderr, ", ty: %s\n", type_str);
2193:
2194: else
2195: {
2196: char *region = "";
2197: switch (load_hdr->region.regc_usage_type)
2198: {
2199: case REG_TEXT_T: region = ", .text"; break;
2200: case REG_DATA_T: region = ", .data"; break;
2201: case REG_BSS_T: region = ", .bss"; break;
2202: case REG_GLUE_T: region = ", .glue"; break;
2203: #if defined (REG_RDATA_T) && defined (REG_SDATA_T) && defined (REG_SBSS_T) /*mips*/
2204: case REG_RDATA_T: region = ", .rdata"; break;
2205: case REG_SDATA_T: region = ", .sdata"; break;
2206: case REG_SBSS_T: region = ", .sbss"; break;
2207: #endif
2208: }
2209:
2210: fprintf (stderr, ", ty: %s, vaddr: 0x%.8lx, vlen: 0x%.6lx%s\n",
2211: type_str,
2212: (long) load_hdr->region.regc_vm_addr,
2213: (long) load_hdr->region.regc_vm_size,
2214: region);
2215: }
2216:
2217: return;
2218: }
2219:
2220:
2221: /* Fatal error when {en,de}code_mach_o_header fails. */
2222:
2223: static void
2224: bad_header (status)
2225: int status;
2226: {
2227: char *msg = (char *)0;
2228:
2229: switch (status)
2230: {
2231: case MO_ERROR_BAD_MAGIC: msg = "bad magic number"; break;
2232: case MO_ERROR_BAD_HDR_VERS: msg = "bad header version"; break;
2233: case MO_ERROR_BAD_RAW_HDR_VERS: msg = "bad raw header version"; break;
2234: case MO_ERROR_BUF2SML: msg = "raw header buffer too small"; break;
2235: case MO_ERROR_OLD_RAW_HDR_FILE: msg = "old raw header file"; break;
2236: case MO_ERROR_UNSUPPORTED_VERS: msg = "unsupported version"; break;
2237: }
2238:
2239: if (msg == (char *)0)
2240: fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
2241: else
2242: fatal ("%s", msg);
2243: }
2244:
2245:
2246: /* Read a file into a memory buffer. */
2247:
2248: static struct file_info *
2249: read_file (name, fd, rw)
2250: char *name; /* filename */
2251: int fd; /* file descriptor */
2252: int rw; /* read/write */
2253: {
2254: struct stat stat_pkt;
2255: struct file_info *p = (struct file_info *) xcalloc (sizeof (struct file_info), 1);
2256: #ifdef USE_MMAP
2257: static int page_size;
2258: #endif
2259:
2260: if (fstat (fd, &stat_pkt) < 0)
2261: fatal_perror ("fstat %s", name);
2262:
2263: p->name = name;
2264: p->size = stat_pkt.st_size;
2265: p->rounded_size = stat_pkt.st_size;
2266: p->fd = fd;
2267: p->rw = rw;
2268:
2269: #ifdef USE_MMAP
2270: if (debug)
2271: fprintf (stderr, "mmap %s, %s\n", name, (rw) ? "read/write" : "read-only");
2272:
2273: if (page_size == 0)
2274: page_size = sysconf (_SC_PAGE_SIZE);
2275:
2276: p->rounded_size = ((p->size + page_size - 1) / page_size) * page_size;
2277: p->start = mmap ((caddr_t)0,
2278: (rw) ? p->rounded_size : p->size,
2279: (rw) ? (PROT_READ | PROT_WRITE) : PROT_READ,
2280: MAP_FILE | MAP_VARIABLE | MAP_SHARED,
2281: fd,
2282: 0L);
2283:
2284: if (p->start != (char *)0 && p->start != (char *)-1)
2285: p->use_mmap = 1;
2286:
2287: else
2288: #endif /* USE_MMAP */
2289: {
2290: long len;
2291:
2292: if (debug)
2293: fprintf (stderr, "read %s\n", name);
2294:
2295: p->use_mmap = 0;
2296: p->start = xmalloc (p->size);
2297: if (lseek (fd, 0L, SEEK_SET) < 0)
2298: fatal_perror ("lseek to 0 on %s", name);
2299:
2300: len = read (fd, p->start, p->size);
2301: if (len < 0)
2302: fatal_perror ("read %s", name);
2303:
2304: if (len != p->size)
2305: fatal ("read %ld bytes, expected %ld, from %s", len, p->size, name);
2306: }
2307:
2308: return p;
2309: }
2310:
2311: /* Do anything necessary to write a file back from memory. */
2312:
2313: static void
2314: end_file (ptr)
2315: struct file_info *ptr; /* file information block */
2316: {
2317: #ifdef USE_MMAP
2318: if (ptr->use_mmap)
2319: {
2320: if (ptr->rw)
2321: {
2322: if (debug)
2323: fprintf (stderr, "msync %s\n", ptr->name);
2324:
2325: if (msync (ptr->start, ptr->rounded_size, MS_ASYNC))
2326: fatal_perror ("msync %s", ptr->name);
2327: }
2328:
2329: if (debug)
2330: fprintf (stderr, "munmap %s\n", ptr->name);
2331:
2332: if (munmap (ptr->start, ptr->size))
2333: fatal_perror ("munmap %s", ptr->name);
2334: }
2335: else
2336: #endif /* USE_MMAP */
2337: {
2338: if (ptr->rw)
2339: {
2340: long len;
2341:
2342: if (debug)
2343: fprintf (stderr, "write %s\n", ptr->name);
2344:
2345: if (lseek (ptr->fd, 0L, SEEK_SET) < 0)
2346: fatal_perror ("lseek to 0 on %s", ptr->name);
2347:
2348: len = write (ptr->fd, ptr->start, ptr->size);
2349: if (len < 0)
2350: fatal_perror ("read %s", ptr->name);
2351:
2352: if (len != ptr->size)
2353: fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name);
2354: }
2355:
2356: free ((generic *)ptr->start);
2357: }
2358:
2359: free ((generic *)ptr);
2360: }
2361:
2362: #endif /* OBJECT_FORMAT_ROSE */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.