|
|
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 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 <string.h>
32: #include <ctype.h>
33: #include <errno.h>
34: #include <signal.h>
35: #include <sys/file.h>
36: #include <sys/stat.h>
37: #include <sys/wait.h>
38:
39: #ifndef errno
40: extern int errno;
41: #endif
42:
43: #define COLLECT
44:
45: #include "config.h"
46:
47: #ifndef __STDC__
48: #include "gvarargs.h"
49: #define generic char
50: #define const
51:
52: #else
53: #include "gstdarg.h"
54: #define generic void
55: #endif
56:
1.1.1.2 ! root 57: #ifdef USG
! 58: #define vfork fork
! 59: #endif
! 60:
! 61: #ifndef R_OK
! 62: #define R_OK 4
! 63: #define W_OK 2
! 64: #define X_OK 1
! 65: #endif
! 66:
! 67: /* On MSDOS, write temp files in current dir
! 68: because there's no place else we can expect to use. */
! 69: #if __MSDOS__
! 70: #ifndef P_tmpdir
! 71: #define P_tmpdir "./"
! 72: #endif
! 73: #endif
! 74:
! 75: /* On certain systems, we have code that works by scanning the object file
! 76: directly. But this code uses system-specific header files and library
! 77: functions, so turn it off in a cross-compiler. */
! 78:
! 79: #ifdef CROSS_COMPILE
! 80: #undef OBJECT_FORMAT_COFF
! 81: #undef OBJECT_FORMAT_ROSE
! 82: #endif
! 83:
! 84: /* If we can't use a special method, use the ordinary one:
! 85: run nm to find what symbols are present.
! 86: In a cross-compiler, this means you need a cross nm,
! 87: but that isn't quite as unpleasant as special headers. */
! 88:
! 89: #if !defined (OBJECT_FORMAT_COFF) && !defined (OBJECT_FORMAT_ROSE)
! 90: #define OBJECT_FORMAT_NONE
! 91: #endif
! 92:
! 93: #ifdef OBJECT_FORMAT_COFF
! 94:
! 95: #include <a.out.h>
! 96: #include <ar.h>
! 97:
! 98: #ifdef UMAX
! 99: #include <sgs.h>
! 100: #endif
! 101:
! 102: #ifdef _AIX
! 103: #define ISCOFF(magic) \
! 104: ((magic) == U802WRMAGIC || (magic) == U802ROMAGIC || (magic) == U802TOCMAGIC)
! 105: #endif
! 106:
! 107: #if defined (_AIX) || defined (USG)
! 108: #undef FREAD
! 109: #undef FWRITE
! 110: #endif
! 111:
! 112: #include <ldfcn.h>
! 113:
! 114: #endif /* OBJECT_FORMAT_COFF */
! 115:
1.1 root 116: #ifdef OBJECT_FORMAT_ROSE
117:
118: #ifdef _OSF_SOURCE
119: #define USE_MMAP
120: #endif
121:
122: #ifdef USE_MMAP
123: #include <sys/mman.h>
124: #endif
125:
126: #include <unistd.h>
127: #include <mach_o_format.h>
128: #include <mach_o_header.h>
129: #include <mach_o_vals.h>
130: #include <mach_o_types.h>
1.1.1.2 ! root 131:
1.1 root 132: #endif /* OBJECT_FORMAT_ROSE */
133:
1.1.1.2 ! root 134: #ifdef OBJECT_FORMAT_NONE
! 135:
1.1 root 136: /* Default flags to pass to nm. */
137: #ifndef NM_FLAGS
138: #define NM_FLAGS "-p"
139: #endif
140:
1.1.1.2 ! root 141: #endif /* OBJECT_FORMAT_NONE */
1.1 root 142:
143: /* Linked lists of constructor and destructor names. */
144:
145: struct id
146: {
147: struct id *next;
148: int sequence;
149: char name[1];
150: };
151:
152: struct head
153: {
154: struct id *first;
155: struct id *last;
156: int number;
157: };
158:
159: /* Enumeration giving which pass this is for scanning the program file. */
160:
161: enum pass {
162: PASS_FIRST, /* without constructors */
163: PASS_SECOND /* with constructors linked in */
164: };
165:
1.1.1.2 ! root 166: #ifndef NO_SYS_SIGLIST
1.1 root 167: extern char *sys_siglist[];
1.1.1.2 ! root 168: #endif
1.1 root 169: extern char *version_string;
170:
171: static int vflag; /* true if -v */
172: static int rflag; /* true if -r */
173:
174: static int debug; /* true if -debug */
175:
176: static int temp_filename_length; /* Length of temp_filename */
177: static char *temp_filename; /* Base of temp filenames */
178: static char *c_file; /* <xxx>.c for constructor/destructor list. */
179: static char *o_file; /* <xxx>.o for constructor/destructor list. */
180: static char *nm_file_name; /* pathname of nm */
181:
182: static struct head constructors; /* list of constructors found */
183: static struct head destructors; /* list of destructors found */
184:
185: extern char *getenv ();
186: extern char *mktemp ();
187: extern int vfork ();
188: static void add_to_list ();
189: static void scan_prog_file ();
190: static void fork_execute ();
191: static void do_wait ();
192: static void write_c_file ();
193: static void my_exit ();
194: static void handler ();
195: static void maybe_unlink ();
196: static void choose_temp_base ();
197:
198: generic *xcalloc ();
199: generic *xmalloc ();
200:
201:
202: #if !defined(HAVE_STRERROR) && !defined(_OSF_SOURCE)
203:
1.1.1.2 ! root 204: char *
! 205: strerror (e)
1.1 root 206: int e;
207: {
208: extern char *sys_errlist[];
209: extern int sys_nerr;
210: static char buffer[30];
211:
212: if (!e)
213: return "";
214:
215: if (e > 0 && e < sys_nerr)
216: return sys_errlist[e];
217:
218: sprintf (buffer, "Unknown error %d", e);
219: return buffer;
220: }
221:
222: #endif
223:
224:
225: /* Delete tempfiles and exit function. */
226:
227: static void
228: my_exit (status)
229: int status;
230: {
1.1.1.2 ! root 231: if (c_file != 0 && c_file[0])
1.1 root 232: maybe_unlink (c_file);
233:
1.1.1.2 ! root 234: if (o_file != 0 && o_file[0])
1.1 root 235: maybe_unlink (o_file);
236:
237: exit (status);
238: }
239:
240:
241: #ifndef __STDC__
242:
243: /* Die when sys call fails. */
244:
245: /*VARARGS*/
246: static void
247: fatal_perror (va_alist)
248: {
249: char *string;
250: va_list vptr;
251: int e = errno;
252:
253: va_start (vptr);
254: string = va_arg (vptr, char *);
255: fprintf (stderr, "collect: ");
256: vfprintf (stderr, string, vptr);
257: fprintf (stderr, ": %s\n", strerror (e));
258: va_end (vptr);
259: my_exit (1);
260: }
261:
262: /* Just die. */
263:
264: /*VARARGS*/
265: static void
266: fatal (va_alist)
267: {
268: char *string;
269: va_list vptr;
270:
271: va_start (vptr);
272: string = va_arg (vptr, char *);
273: fprintf (stderr, "collect: ");
274: vfprintf (stderr, string, vptr);
275: fprintf (stderr, "\n");
276: va_end (vptr);
277: my_exit (1);
278: }
279:
280: /* Write error message. */
281:
282: /*VARARGS*/
283: static void
284: error (va_alist)
285: {
286: char *string;
287: va_list vptr;
288:
289: va_start (vptr);
290: string = va_arg (vptr, char *);
291: fprintf (stderr, "collect: ");
292: vfprintf (stderr, string, vptr);
293: fprintf (stderr, "\n");
294: va_end (vptr);
295: }
296:
297: #else
298:
299: static void
300: fatal_perror (char *string, ...)
301: {
302: va_list vptr;
303: int e = errno;
304:
305: va_start (vptr, string);
306: fprintf (stderr, "collect: ");
307: vfprintf (stderr, string, vptr);
308: fprintf (stderr, ": %s\n", strerror (e));
309: va_end (vptr);
310: my_exit (1);
311: }
312:
313: /* Just die. */
314:
315: static void
316: fatal (char *string, ...)
317: {
318: va_list vptr;
319:
320: va_start (vptr, string);
321: fprintf (stderr, "collect: ");
322: vfprintf (stderr, string, vptr);
323: fprintf (stderr, "\n");
324: va_end (vptr);
325: my_exit (1);
326: }
327:
328: /* Write error message. */
329:
330: static void
331: error (char *string, ...)
332: {
333: va_list vptr;
334:
335: va_start (vptr, string);
336: fprintf (stderr, "collect: ");
337: vfprintf (stderr, string, vptr);
338: fprintf (stderr, "\n");
339: va_end (vptr);
340: }
341: #endif
342:
343:
344: /* In case obstack is linked in, and abort is defined to fancy_abort,
345: provide a default entry. */
346:
347: void
348: fancy_abort ()
349: {
350: fatal ("internal error");
351: }
352:
353:
354: static void
355: handler (signo)
356: int signo;
357: {
358: if (c_file[0])
359: maybe_unlink (c_file);
360:
361: if (o_file[0])
362: maybe_unlink (o_file);
363:
364: signal (signo, SIG_DFL);
365: kill (getpid (), signo);
366: }
367:
368:
369: generic *
370: xcalloc (size1, size2)
371: int size1, size2;
372: {
373: generic *ptr = (generic *) calloc (size1, size2);
374: if (ptr)
375: return ptr;
376:
377: fatal ("Out of memory.");
378: return (generic *)0;
379: }
380:
381: generic *
382: xmalloc (size)
383: int size;
384: {
385: generic *ptr = (generic *) malloc (size);
386: if (ptr)
387: return ptr;
388:
389: fatal ("Out of memory.");
390: return (generic *)0;
391: }
392:
1.1.1.2 ! root 393: /* Make a copy of a string INPUT with size SIZE. */
! 394:
! 395: char *
! 396: savestring (input, size)
! 397: char *input;
! 398: int size;
! 399: {
! 400: char *output = (char *) xmalloc (size + 1);
! 401: strcpy (output, input);
! 402: return output;
! 403: }
! 404:
! 405: /* Decide whether the given symbol is:
! 406: a constructor (1), a destructor (2), or neither (0). */
! 407:
! 408: static int
! 409: is_ctor_dtor (s)
! 410: char *s;
! 411: {
! 412: struct names { char *name; int len; int ret; int two_underscores; };
! 413:
! 414: register struct names *p;
! 415: register int ch;
! 416: register char *orig_s = s;
! 417:
! 418: static struct names special[] = {
! 419: #ifdef NO_DOLLAR_IN_LABEL
! 420: { "GLOBAL_.I.", sizeof ("GLOBAL_.I.")-1, 1, 0 },
! 421: { "GLOBAL_.D.", sizeof ("GLOBAL_.D.")-1, 2, 0 },
! 422: #else
! 423: { "GLOBAL_$I$", sizeof ("GLOBAL_$I$")-1, 1, 0 },
! 424: { "GLOBAL_$D$", sizeof ("GLOBAL_$I$")-1, 2, 0 },
! 425: #endif
! 426: { "sti__", sizeof ("sti__")-1, 1, 1 },
! 427: { "std__", sizeof ("std__")-1, 2, 1 },
! 428: { NULL, 0, 0, 0 }
! 429: };
! 430:
! 431: while ((ch = *s) == '_')
! 432: ++s;
! 433:
! 434: if (s == orig_s)
! 435: return 0;
! 436:
! 437: for (p = &special[0]; p->len > 0; p++)
! 438: {
! 439: if (ch == p->name[0]
! 440: && (!p->two_underscores || ((s - orig_s) >= 2))
! 441: && strncmp(s, p->name, p->len) == 0)
! 442: {
! 443: return p->ret;
! 444: }
! 445: }
! 446: return 0;
! 447: }
! 448:
1.1 root 449:
450: /* Compute a string to use as the base of all temporary file names.
451: It is substituted for %g. */
452:
453: static void
454: choose_temp_base ()
455: {
456: char *base = getenv ("TMPDIR");
457: int len;
458:
459: if (base == (char *)0)
460: {
461: #ifdef P_tmpdir
462: if (access (P_tmpdir, R_OK | W_OK) == 0)
463: base = P_tmpdir;
464: #endif
465: if (base == (char *)0)
466: {
467: if (access ("/usr/tmp", R_OK | W_OK) == 0)
468: base = "/usr/tmp/";
469: else
470: base = "/tmp/";
471: }
472: }
473:
474: len = strlen (base);
475: temp_filename = xmalloc (len + sizeof("/ccXXXXXX"));
476: strcpy (temp_filename, base);
477: if (len > 0 && temp_filename[len-1] != '/')
478: temp_filename[len++] = '/';
479: strcpy (temp_filename + len, "ccXXXXXX");
480:
481: mktemp (temp_filename);
482: temp_filename_length = strlen (temp_filename);
483: }
484:
485:
486: /* Main program. */
487:
488: int
489: main (argc, argv)
490: int argc;
491: char *argv[];
492: {
493: char *outfile = "a.out";
494: char *arg;
495: FILE *outf;
496: char *ld_file_name;
497: char *c_file_name;
498: char *p;
499: char *prefix;
1.1.1.2 ! root 500: char **c_argv;
! 501: char **c_ptr;
1.1 root 502: char **ld1_argv = (char **) xcalloc (sizeof (char *), argc+2);
503: char **ld1 = ld1_argv;
504: char **ld2_argv = (char **) xcalloc (sizeof (char *), argc+5);
505: char **ld2 = ld2_argv;
506: int first_file;
1.1.1.2 ! root 507: int num_c_args = argc+7;
1.1 root 508: int len;
509: int clen;
510:
511: #ifdef DEBUG
512: debug = 1;
513: vflag = 1;
514: #endif
515:
1.1.1.2 ! root 516: p = (char *) getenv ("COLLECT_GCC_OPTIONS");
! 517: if (p)
! 518: while (*p)
! 519: {
! 520: char *q = p;
! 521: while (*q && *q != ' ') q++;
! 522: if (*p == '-' && (p[1] == 'm' || p[1] == 'f'))
! 523: num_c_args++;
! 524:
! 525: if (*q) q++;
! 526: p = q;
! 527: }
! 528:
! 529: c_ptr = c_argv = (char **) xcalloc (sizeof (char *), num_c_args);
! 530:
1.1 root 531: if (argc < 2)
532: fatal ("no arguments");
533:
534: signal (SIGQUIT, handler);
535: signal (SIGINT, handler);
536: signal (SIGALRM, handler);
537: signal (SIGHUP, handler);
538: signal (SIGSEGV, handler);
539: signal (SIGBUS, handler);
540:
541: /* Try to discover a valid linker/assembler/nm to use. */
542: len = strlen (argv[0]);
543: prefix = (char *)0;
544: if (len >= sizeof ("ld")-1)
545: {
546: p = argv[0] + len - sizeof ("ld") + 1;
547: if (strcmp (p, "ld") == 0)
548: {
549: prefix = argv[0];
550: *p = '\0';
551: }
552: }
553:
554: if (prefix == (char *)0)
555: {
556: p = strrchr (argv[0], '/');
557: if (p != (char *)0)
558: {
559: prefix = argv[0];
560: p[1] = '\0';
561: }
562:
563: #ifdef STANDARD_EXEC_PREFIX
564: else if (access (STANDARD_EXEC_PREFIX, X_OK) == 0)
565: prefix = STANDARD_EXEC_PREFIX;
566: #endif
567:
568: #ifdef MD_EXEC_PREFIX
569: else if (access (MD_EXEC_PREFIX, X_OK) == 0)
570: prefix = MD_EXEC_PREFIX;
571: #endif
572:
573: else if (access ("/usr/ccs/gcc", X_OK) == 0)
574: prefix = "/usr/ccs/gcc/";
575:
576: else if (access ("/usr/ccs/bin", X_OK) == 0)
577: prefix = "/usr/ccs/bin/";
578:
579: else
580: prefix = "/bin/";
581: }
582:
583: clen = len = strlen (prefix);
584:
585: #ifdef STANDARD_BIN_PREFIX
586: if (clen < sizeof (STANDARD_BIN_PREFIX) - 1)
587: clen = sizeof (STANDARD_BIN_PREFIX) - 1;
588: #endif
589:
590: ld_file_name = xcalloc (len + sizeof ("real-ld"), 1);
591: nm_file_name = xcalloc (len + sizeof ("gnm"), 1);
592:
593: memcpy (ld_file_name, prefix, len);
594: strcpy (ld_file_name + len, "real-ld");
595: if (access (ld_file_name, X_OK) < 0)
596: {
597: strcpy (ld_file_name + len, "gld");
598: if (access (ld_file_name, X_OK) < 0)
599: {
600: free (ld_file_name);
601: #ifdef REAL_LD_FILE_NAME
602: ld_file_name = REAL_LD_FILE_NAME;
603: #else
604: ld_file_name = (access ("/usr/bin/ld", X_OK) == 0) ? "/usr/bin/ld" : "/bin/ld";
605: #endif
606: }
607: }
608:
1.1.1.2 ! root 609: c_file_name = getenv ("COLLECT_GCC");
! 610: if (c_file_name == 0 || c_file_name[0] != '/')
1.1 root 611: {
1.1.1.2 ! root 612: c_file_name = xcalloc (clen + sizeof ("gcc"), 1);
! 613: memcpy (c_file_name, prefix, len);
! 614: strcpy (c_file_name + len, "gcc");
1.1 root 615: if (access (c_file_name, X_OK) < 0)
616: {
1.1.1.2 ! root 617: #ifdef STANDARD_BIN_PREFIX
! 618: strcpy (c_file_name, STANDARD_BIN_PREFIX);
1.1 root 619: strcat (c_file_name, "gcc");
620: if (access (c_file_name, X_OK) < 0)
621: #endif
622: {
1.1.1.2 ! root 623: #ifdef STANDARD_EXEC_PREFIX
! 624: strcpy (c_file_name, STANDARD_EXEC_PREFIX);
! 625: strcat (c_file_name, "gcc");
! 626: if (access (c_file_name, X_OK) < 0)
! 627: #endif
! 628: {
! 629: strcpy (c_file_name, "gcc");
! 630: }
1.1 root 631: }
632: }
633: }
634:
635: memcpy (nm_file_name, prefix, len);
636: strcpy (nm_file_name + len, "nm");
637: if (access (nm_file_name, X_OK) < 0)
638: {
639: strcpy (nm_file_name + len, "gnm");
640: if (access (nm_file_name, X_OK) < 0)
641: {
642: free (nm_file_name);
643: #ifdef REAL_NM_FILE_NAME
644: nm_file_name = REAL_NM_FILE_NAME;
645: #else
646: nm_file_name = (access ("/usr/bin/nm", X_OK) == 0) ? "/usr/bin/nm" : "/bin/nm";
647: #endif
648: }
649: }
650:
651: *ld1++ = *ld2++ = "ld";
652:
653: /* Make temp file names. */
654: choose_temp_base ();
655: c_file = xcalloc (temp_filename_length + sizeof (".c"), 1);
656: o_file = xcalloc (temp_filename_length + sizeof (".o"), 1);
657: sprintf (c_file, "%s.c", temp_filename);
658: sprintf (o_file, "%s.o", temp_filename);
1.1.1.2 ! root 659: *c_ptr++ = c_file_name;
1.1 root 660: *c_ptr++ = "-c";
661: *c_ptr++ = "-o";
662: *c_ptr++ = o_file;
663:
1.1.1.2 ! root 664: /* !!! When GCC calls collect2,
! 665: it does not know whether it is calling collect2 or ld.
! 666: So collect2 cannot meaningfully understand any options
! 667: except those ld understands.
! 668: If you propose to make GCC pass some other option,
! 669: just imagine what will happen if ld is really ld!!! */
! 670:
1.1 root 671: /* Parse arguments. Remember output file spec, pass the rest to ld. */
1.1.1.2 ! root 672: /* After the first file, put in the c++ rt0. */
! 673:
1.1 root 674: first_file = 1;
675: while ((arg = *++argv) != (char *)0)
676: {
677: *ld1++ = *ld2++ = arg;
678:
679: if (arg[0] == '-')
680: switch (arg[1])
681: {
682: case 'd':
683: if (!strcmp (arg, "-debug"))
684: {
685: debug = 1;
686: vflag = 1;
687: ld1--;
688: ld2--;
689: }
690: break;
691:
692: case 'o':
693: outfile = (arg[2] == '\0') ? argv[1] : &arg[2];
694: break;
695:
696: case 'r':
697: if (arg[2] == '\0')
698: rflag = 1;
699: break;
700:
701: case 'v':
702: if (arg[2] == '\0')
703: vflag = 1;
704: break;
705: }
706:
707: else if (first_file
708: && (p = strrchr (arg, '.')) != (char *)0
709: && strcmp (p, ".o") == 0)
710: {
711: first_file = 0;
712: *ld2++ = o_file;
713: }
714: }
715:
1.1.1.2 ! root 716: /* Get any options that the upper GCC wants to pass to the sub-GCC. */
! 717: p = (char *) getenv ("COLLECT_GCC_OPTIONS");
! 718: if (p)
! 719: while (*p)
! 720: {
! 721: char *q = p;
! 722: while (*q && *q != ' ') q++;
! 723: if (*p == '-' && (p[1] == 'm' || p[1] == 'f'))
! 724: *c_ptr++ = savestring (p, q - p);
! 725:
! 726: if (*q) q++;
! 727: p = q;
! 728: }
! 729:
1.1 root 730: *c_ptr++ = c_file;
731: *c_ptr = *ld1 = *ld2 = (char *)0;
732:
733: if (vflag)
734: {
1.1.1.2 ! root 735: fprintf (stderr, "collect2 version %s", version_string);
1.1 root 736: #ifdef TARGET_VERSION
737: TARGET_VERSION;
738: #endif
739: fprintf (stderr, "\n");
740: }
741:
742: if (debug)
743: {
1.1.1.2 ! root 744: char *ptr;
! 745: fprintf (stderr, "prefix = %s\n", prefix);
! 746: fprintf (stderr, "ld_file_name = %s\n", ld_file_name);
! 747: fprintf (stderr, "c_file_name = %s\n", c_file_name);
! 748: fprintf (stderr, "nm_file_name = %s\n", nm_file_name);
! 749: fprintf (stderr, "c_file = %s\n", c_file);
! 750: fprintf (stderr, "o_file = %s\n", o_file);
! 751:
! 752: ptr = getenv ("COLLECT_GCC_OPTIONS");
! 753: if (ptr)
! 754: fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
! 755:
! 756: ptr = getenv ("COLLECT_GCC");
! 757: if (ptr)
! 758: fprintf (stderr, "COLLECT_GCC = %s\n", ptr);
! 759:
! 760: ptr = getenv ("COMPILER_PATH");
! 761: if (ptr)
! 762: fprintf (stderr, "COMPILER_PATH = %s\n", ptr);
! 763:
! 764: ptr = getenv ("LIBRARY_PATH");
! 765: if (ptr)
! 766: fprintf (stderr, "LIBRARY_PATH = %s\n", ptr);
! 767:
! 768: fprintf (stderr, "\n");
1.1 root 769: }
770:
771: /* Load the program, searching all libraries.
772: Examine the namelist with nm and search it for static constructors
773: and destructors to call.
774: Write the constructor and destructor tables to a .s file and reload. */
775:
776: fork_execute (ld_file_name, ld1_argv);
777:
778: /* If -r, don't build the constructor or destructor list, just return now. */
779: if (rflag)
780: return 0;
781:
782: scan_prog_file (outfile, PASS_FIRST);
783:
784: if (debug)
785: {
786: fprintf (stderr, "%d constructor(s) found\n", constructors.number);
787: fprintf (stderr, "%d destructor(s) found\n", destructors.number);
788: }
789:
790: if (constructors.number == 0 && destructors.number == 0)
791: return 0;
792:
793: outf = fopen (c_file, "w");
794: if (outf == (FILE *)0)
795: fatal_perror ("Can't write %s", c_file);
796:
797: write_c_file (outf, c_file);
798:
799: if (fclose (outf))
800: fatal_perror ("Can't close %s", c_file);
801:
802: if (debug)
803: {
804: fprintf (stderr, "\n========== outfile = %s, c_file = %s\n", outfile, c_file);
805: write_c_file (stderr, "stderr");
806: fprintf (stderr, "========== end of c_file\n\n");
807: }
808:
809: /* Assemble the constructor and destructor tables.
810: Link the tables in with the rest of the program. */
811:
812: fork_execute (c_file_name, c_argv);
813: fork_execute (ld_file_name, ld2_argv);
814:
815: /* Let scan_prog_file do any final mods (OSF/rose needs this for
816: constructors/destructors in shared libraries. */
817: scan_prog_file (outfile, PASS_SECOND);
818:
819: maybe_unlink (c_file);
820: maybe_unlink (o_file);
821: return 0;
822: }
823:
824:
825: /* Wait for a process to finish, and exit if a non-zero status is found. */
826:
827: static void
828: do_wait (prog)
829: char *prog;
830: {
831: int status;
832:
833: wait (&status);
834: if (status)
835: {
836: int sig = status & 0x7F;
837: int ret;
838:
839: if (sig != -1 && sig != 0)
840: {
1.1.1.2 ! root 841: #ifdef NO_SYS_SIGLIST
! 842: error ("%s terminated with signal %d %s",
! 843: prog,
! 844: sig,
! 845: (status & 0200) ? ", core dumped" : "");
! 846: #else
1.1 root 847: error ("%s terminated with signal %d [%s]%s",
848: prog,
849: sig,
850: sys_siglist[sig],
851: (status & 0200) ? ", core dumped" : "");
1.1.1.2 ! root 852: #endif
1.1 root 853:
854: my_exit (127);
855: }
856:
857: ret = ((status & 0xFF00) >> 8);
858: if (ret != -1 && ret != 0)
859: {
860: error ("%s returned %d exit status", prog, ret);
861: my_exit (ret);
862: }
863: }
864: }
865:
866:
867: /* Fork and execute a program, and wait for the reply. */
868:
869: static void
870: fork_execute (prog, argv)
871: char *prog;
872: char **argv;
873: {
874: int pid;
875: void (*int_handler) ();
876: void (*quit_handler) ();
877:
878: if (vflag || debug)
879: {
880: char **p_argv;
881: char *str;
882:
883: fprintf (stderr, "%s", prog);
884: for (p_argv = &argv[1]; (str = *p_argv) != (char *)0; p_argv++)
885: fprintf (stderr, " %s", str);
886:
887: fprintf (stderr, "\n");
888: }
889:
890: fflush (stdout);
891: fflush (stderr);
892:
893: pid = vfork ();
894: if (pid == -1)
895: fatal_perror ("vfork");
896:
897: if (pid == 0) /* child context */
898: {
899: execvp (prog, argv);
900: fatal_perror ("Execute %s", prog);
901: }
902:
903: int_handler = (void (*) ())signal (SIGINT, SIG_IGN);
904: quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN);
905:
906: do_wait (prog);
907:
908: signal (SIGINT, int_handler);
909: signal (SIGQUIT, quit_handler);
910: }
911:
912:
913: /* Unlink a file unless we are debugging. */
914:
915: static void
916: maybe_unlink (file)
917: char *file;
918: {
919: if (!debug)
920: unlink (file);
921: else
922: fprintf (stderr, "[Leaving %s]\n", file);
923: }
924:
925:
926: /* Add a name to a linked list. */
927:
928: static void
929: add_to_list (head_ptr, name)
930: struct head *head_ptr;
931: char *name;
932: {
933: struct id *newid = (struct id *) xcalloc (sizeof (*newid) + strlen (name), 1);
934: static long sequence_number = 0;
935: newid->sequence = ++sequence_number;
936: strcpy (newid->name, name);
937:
938: if (head_ptr->first)
939: head_ptr->last->next = newid;
940: else
941: head_ptr->first = newid;
942:
943: head_ptr->last = newid;
944: head_ptr->number++;
945: }
946:
947: /* Write: `prefix', the names on list LIST, `suffix'. */
948:
949: static void
950: write_list (stream, prefix, list)
951: FILE *stream;
952: char *prefix;
953: struct id *list;
954: {
955: while (list)
956: {
957: fprintf (stream, "%sx%d,\n", prefix, list->sequence);
958: list = list->next;
959: }
960: }
961:
962: static void
963: write_list_with_asm (stream, prefix, list)
964: FILE *stream;
965: char *prefix;
966: struct id *list;
967: {
968: while (list)
969: {
970: fprintf (stream, "%sx%d asm (\"%s\");\n",
971: prefix, list->sequence, list->name);
972: list = list->next;
973: }
974: }
975:
976: /* Write the constructor/destructor tables. */
977:
978: static void
979: write_c_file (stream, name)
980: FILE *stream;
981: char *name;
982: {
983: /* Write the tables as C code */
984:
985: fprintf (stream, "typedef void entry_pt();\n\n");
986:
987: write_list_with_asm (stream, "entry_pt ", constructors.first);
988:
989: fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
990: fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number);
991: write_list (stream, "\t", constructors.first);
992: fprintf (stream, "\t0\n};\n\n");
993:
994: write_list_with_asm (stream, "entry_pt ", destructors.first);
995:
996: fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
997: fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number);
998: write_list (stream, "\t", destructors.first);
999: fprintf (stream, "\t0\n};\n\n");
1000:
1001: fprintf (stream, "extern entry_pt __main;\n");
1002: fprintf (stream, "entry_pt *__main_reference = __main;\n\n");
1003: }
1004:
1005:
1.1.1.2 ! root 1006: #ifdef OBJECT_FORMAT_NONE
1.1 root 1007:
1.1.1.2 ! root 1008: /* Generic version to scan the name list of the loaded program for
! 1009: the symbols g++ uses for static constructors and destructors.
1.1 root 1010:
1011: The constructor table begins at __CTOR_LIST__ and contains a count
1012: of the number of pointers (or -1 if the constructors are built in a
1013: separate section by the linker), followed by the pointers to the
1014: constructor functions, terminated with a null pointer. The
1015: destructor table has the same format, and begins at __DTOR_LIST__. */
1016:
1017: static void
1018: scan_prog_file (prog_name, which_pass)
1019: char *prog_name;
1020: enum pass which_pass;
1021: {
1022: void (*int_handler) ();
1023: void (*quit_handler) ();
1024: char *nm_argv[4];
1025: int pid;
1026: int argc = 0;
1027: int pipe_fd[2];
1028: char *p, buf[1024];
1029: FILE *inf;
1030:
1031: if (which_pass != PASS_FIRST)
1032: return;
1033:
1034: nm_argv[argc++] = "nm";
1035: if (NM_FLAGS[0] != '\0')
1036: nm_argv[argc++] = NM_FLAGS;
1037:
1038: nm_argv[argc++] = prog_name;
1039: nm_argv[argc++] = (char *)0;
1040:
1041: if (pipe (pipe_fd) < 0)
1042: fatal_perror ("pipe");
1043:
1044: inf = fdopen (pipe_fd[0], "r");
1045: if (inf == (FILE *)0)
1046: fatal_perror ("fdopen");
1047:
1048: /* Trace if needed. */
1049: if (vflag)
1050: {
1051: char **p_argv;
1052: char *str;
1053:
1054: fprintf (stderr, "%s", nm_file_name);
1055: for (p_argv = &nm_argv[1]; (str = *p_argv) != (char *)0; p_argv++)
1056: fprintf (stderr, " %s", str);
1057:
1058: fprintf (stderr, "\n");
1059: }
1060:
1061: fflush (stdout);
1062: fflush (stderr);
1063:
1064: /* Spawn child nm on pipe */
1065: pid = vfork ();
1066: if (pid == -1)
1067: fatal_perror ("vfork");
1068:
1069: if (pid == 0) /* child context */
1070: {
1071: /* setup stdout */
1072: if (dup2 (pipe_fd[1], 1) < 0)
1073: fatal_perror ("Dup2 (%d, 1)", pipe_fd[1]);
1074:
1075: if (close (pipe_fd[0]) < 0)
1076: fatal_perror ("Close (%d)", pipe_fd[0]);
1077:
1078: if (close (pipe_fd[1]) < 0)
1079: fatal_perror ("Close (%d)", pipe_fd[1]);
1080:
1081: execv (nm_file_name, nm_argv);
1082: fatal_perror ("Execute %s", nm_file_name);
1083: }
1084:
1085: /* Parent context from here on. */
1086: int_handler = (void (*) ())signal (SIGINT, SIG_IGN);
1087: quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN);
1088:
1089: if (close (pipe_fd[1]) < 0)
1090: fatal_perror ("Close (%d)", pipe_fd[1]);
1091:
1092: if (debug)
1093: fprintf (stderr, "\nnm output with constructors/destructors.\n");
1094:
1095: /* Read each line of nm output. */
1096: while (fgets (buf, sizeof buf, inf) != (char *)0)
1097: {
1098: int ch, ch2;
1.1.1.2 ! root 1099: char *name, *end;
1.1 root 1100:
1101: /* If it contains a constructor or destructor name, add the name
1102: to the appropriate list. */
1103:
1104: for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
1105: ;
1106:
1107: if (ch == '\0' || ch == '\n')
1108: continue;
1.1.1.2 ! root 1109:
! 1110: name = p;
! 1111: /* Find the end of the symbol name.
! 1112: Don't include `|', because Encore nm can tack that on the end. */
! 1113: for (end = p; (ch2 = *end) != '\0' && !isspace (ch2) && ch2 != '|';
! 1114: end++)
! 1115: continue;
1.1 root 1116:
1117: *end = '\0';
1.1.1.2 ! root 1118: switch (is_ctor_dtor (name))
1.1 root 1119: {
1.1.1.2 ! root 1120: case 1:
! 1121: add_to_list (&constructors, name);
! 1122: break;
! 1123:
! 1124: case 2:
! 1125: add_to_list (&destructors, name);
! 1126: break;
1.1 root 1127:
1.1.1.2 ! root 1128: default: /* not a constructor or destructor */
! 1129: continue;
1.1 root 1130: }
1131:
1132: if (debug)
1133: fprintf (stderr, "\t%s\n", buf);
1134: }
1135:
1136: if (debug)
1137: fprintf (stderr, "\n");
1138:
1139: if (fclose (inf) != 0)
1140: fatal_perror ("fclose of pipe");
1141:
1142: do_wait (nm_file_name);
1143:
1144: signal (SIGINT, int_handler);
1145: signal (SIGQUIT, quit_handler);
1146: }
1147:
1.1.1.2 ! root 1148: #endif /* OBJECT_FORMAT_NONE */
! 1149:
! 1150:
! 1151: /*
! 1152: * COFF specific stuff.
! 1153: */
! 1154:
! 1155: #ifdef OBJECT_FORMAT_COFF
! 1156:
! 1157: #if defined(EXTENDED_COFF)
! 1158: # define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax+SYMHEADER(X).iextMax)
! 1159: # define GCC_SYMENT SYMR
! 1160: # define GCC_OK_SYMBOL(X) ((X).st == stProc && (X).sc == scText)
! 1161: # define GCC_SYMINC(X) (1)
! 1162: # define GCC_SYMZERO(X) (SYMHEADER(X).isymMax)
! 1163: #else
! 1164: # define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms)
! 1165: # define GCC_SYMENT SYMENT
! 1166: # define GCC_OK_SYMBOL(X) \
! 1167: (((X).n_sclass == C_EXT) && \
! 1168: (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) || \
! 1169: ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))
! 1170: # define GCC_SYMINC(X) ((X).n_numaux+1)
! 1171: # define GCC_SYMZERO(X) 0
! 1172: #endif
! 1173:
! 1174: extern char *ldgetname ();
! 1175:
! 1176: /* COFF version to scan the name list of the loaded program for
! 1177: the symbols g++ uses for static constructors and destructors.
! 1178:
! 1179: The constructor table begins at __CTOR_LIST__ and contains a count
! 1180: of the number of pointers (or -1 if the constructors are built in a
! 1181: separate section by the linker), followed by the pointers to the
! 1182: constructor functions, terminated with a null pointer. The
! 1183: destructor table has the same format, and begins at __DTOR_LIST__. */
! 1184:
! 1185: static void
! 1186: scan_prog_file (prog_name, which_pass)
! 1187: char *prog_name;
! 1188: enum pass which_pass;
! 1189: {
! 1190: LDFILE *ldptr;
! 1191: int sym_index, sym_count;
! 1192:
! 1193: if (which_pass != PASS_FIRST)
! 1194: return;
! 1195:
! 1196: if ((ldptr = ldopen (prog_name, ldptr)) == NULL)
! 1197: fatal ("%s: can't open as COFF file", prog_name);
! 1198:
! 1199: if (!ISCOFF (HEADER(ldptr).f_magic))
! 1200: fatal ("%s: not a COFF file", prog_name);
! 1201:
! 1202: sym_count = GCC_SYMBOLS (ldptr);
! 1203: sym_index = GCC_SYMZERO (ldptr);
! 1204: while (sym_index < sym_count)
! 1205: {
! 1206: GCC_SYMENT symbol;
! 1207:
! 1208: if (ldtbread (ldptr, sym_index, &symbol) <= 0)
! 1209: break;
! 1210: sym_index += GCC_SYMINC (symbol);
! 1211:
! 1212: if (GCC_OK_SYMBOL (symbol))
! 1213: {
! 1214: char *name;
! 1215:
! 1216: if ((name = ldgetname (ldptr, &symbol)) == NULL)
! 1217: continue; /* should never happen */
! 1218:
! 1219: #ifdef _AIX
! 1220: /* All AIX function names begin with a dot. */
! 1221: if (*name++ != '.')
! 1222: continue;
! 1223: #endif
! 1224:
! 1225: switch (is_ctor_dtor (name))
! 1226: {
! 1227: case 1:
! 1228: add_to_list (&constructors, name);
! 1229: break;
! 1230:
! 1231: case 2:
! 1232: add_to_list (&destructors, name);
! 1233: break;
! 1234:
! 1235: default: /* not a constructor or destructor */
! 1236: continue;
! 1237: }
! 1238:
! 1239: #if !defined(EXTENDED_COFF)
! 1240: if (debug)
! 1241: fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
! 1242: symbol.n_scnum, symbol.n_sclass,
! 1243: (symbol.n_type ? "0" : ""), symbol.n_type,
! 1244: name);
! 1245: #else
! 1246: if (debug)
! 1247: fprintf (stderr, "\tiss = %5d, value = %5d, index = %5d, name = %s\n",
! 1248: symbol.iss, symbol.value, symbol.index, name);
! 1249: #endif
! 1250: }
! 1251: }
! 1252:
! 1253: (void) ldclose(ldptr);
! 1254: }
! 1255:
! 1256: #endif /* OBJECT_FORMAT_COFF */
1.1 root 1257:
1258:
1259: /*
1260: * OSF/rose specific stuff.
1261: */
1262:
1263: #ifdef OBJECT_FORMAT_ROSE
1264:
1265: /* Union of the various load commands */
1266:
1267: typedef union load_union
1268: {
1269: ldc_header_t hdr; /* common header */
1270: load_cmd_map_command_t map; /* map indexing other load cmds */
1.1.1.2 ! root 1271: interpreter_command_t iprtr; /* interpreter pathname */
1.1 root 1272: strings_command_t str; /* load commands strings section */
1273: region_command_t region; /* region load command */
1274: reloc_command_t reloc; /* relocation section */
1275: package_command_t pkg; /* package load command */
1276: symbols_command_t sym; /* symbol sections */
1277: entry_command_t ent; /* program start section */
1278: gen_info_command_t info; /* object information */
1279: func_table_command_t func; /* function constructors/destructors */
1280: } load_union_t;
1281:
1282: /* Structure to point to load command and data section in memory. */
1283:
1284: typedef struct load_all
1285: {
1286: load_union_t *load; /* load command */
1287: char *section; /* pointer to section */
1288: } load_all_t;
1289:
1290: /* Structure to contain information about a file mapped into memory. */
1291:
1292: struct file_info
1293: {
1294: char *start; /* start of map */
1295: char *name; /* filename */
1296: long size; /* size of the file */
1297: long rounded_size; /* size rounded to page boundary */
1298: int fd; /* file descriptor */
1299: int rw; /* != 0 if opened read/write */
1300: int use_mmap; /* != 0 if mmap'ed */
1301: };
1302:
1303: extern int decode_mach_o_hdr ();
1304:
1305: extern int encode_mach_o_hdr ();
1306:
1307: static void bad_header ();
1308:
1309: static void print_header ();
1310:
1311: static void print_load_command ();
1312:
1313: static void add_func_table ();
1314:
1315: static struct file_info *read_file ();
1316:
1317: static void end_file ();
1318:
1319:
1320: /* OSF/rose specific version to scan the name list of the loaded
1321: program for the symbols g++ uses for static constructors and
1322: destructors.
1323:
1324: The constructor table begins at __CTOR_LIST__ and contains a count
1325: of the number of pointers (or -1 if the constructors are built in a
1326: separate section by the linker), followed by the pointers to the
1327: constructor functions, terminated with a null pointer. The
1328: destructor table has the same format, and begins at __DTOR_LIST__. */
1329:
1330: static void
1331: scan_prog_file (prog_name, which_pass)
1332: char *prog_name;
1333: enum pass which_pass;
1334: {
1335: char *obj;
1336: mo_header_t hdr;
1337: load_all_t *load_array;
1338: load_all_t *load_end;
1339: load_all_t *load_cmd;
1340: int symbol_load_cmds;
1341: off_t offset;
1342: int i;
1343: int num_syms;
1344: int status;
1345: char *str_sect;
1346: struct file_info *obj_file;
1347: int prog_fd;
1348: mo_lcid_t cmd_strings = -1;
1349: symbol_info_t *main_sym = 0;
1350: int rw = (which_pass != PASS_FIRST);
1351:
1352: prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY);
1353: if (prog_fd < 0)
1354: fatal_perror ("Can't read %s", prog_name);
1355:
1356: obj_file = read_file (prog_name, prog_fd, rw);
1357: obj = obj_file->start;
1358:
1359: status = decode_mach_o_hdr (obj, MO_SIZEOF_RAW_HDR, MOH_HEADER_VERSION, &hdr);
1360: if (status != MO_HDR_CONV_SUCCESS)
1361: bad_header (status);
1362:
1363:
1364: /* Do some basic sanity checks. Note we explicitly use the big endian magic number,
1365: since the hardware will automatically swap bytes for us on loading little endian
1366: integers. */
1367:
1368: #ifndef CROSS_COMPILE
1369: if (hdr.moh_magic != MOH_MAGIC_MSB
1370: || hdr.moh_header_version != MOH_HEADER_VERSION
1371: || hdr.moh_byte_order != OUR_BYTE_ORDER
1372: || hdr.moh_data_rep_id != OUR_DATA_REP_ID
1373: || hdr.moh_cpu_type != OUR_CPU_TYPE
1374: || hdr.moh_cpu_subtype != OUR_CPU_SUBTYPE
1375: || hdr.moh_vendor_type != OUR_VENDOR_TYPE)
1376: {
1377: fatal ("incompatibilities exist between object file & expected values.");
1378: }
1379: #endif
1380:
1381: if (debug)
1382: print_header (&hdr);
1383:
1384: offset = hdr.moh_first_cmd_off;
1385: load_end = load_array
1386: = (load_all_t *) xcalloc (sizeof (load_all_t), hdr.moh_n_load_cmds + 2);
1387:
1388: /* Build array of load commands, calculating the offsets */
1389: for (i = 0; i < hdr.moh_n_load_cmds; i++)
1390: {
1391: load_union_t *load_hdr; /* load command header */
1392:
1393: load_cmd = load_end++;
1394: load_hdr = (load_union_t *) (obj + offset);
1395:
1396: /* If modifing the program file, copy the header. */
1397: if (rw)
1398: {
1399: load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size);
1400: memcpy (ptr, load_hdr, load_hdr->hdr.ldci_cmd_size);
1401: load_hdr = ptr;
1402:
1403: /* null out old command map, because we will rewrite at the end. */
1404: if (ptr->hdr.ldci_cmd_type == LDC_CMD_MAP)
1405: {
1406: cmd_strings = ptr->map.lcm_ld_cmd_strings;
1407: ptr->hdr.ldci_cmd_type = LDC_UNDEFINED;
1408: }
1409: }
1410:
1411: load_cmd->load = load_hdr;
1412: if (load_hdr->hdr.ldci_section_off > 0)
1413: load_cmd->section = obj + load_hdr->hdr.ldci_section_off;
1414:
1415: if (debug)
1416: print_load_command (load_hdr, offset, i);
1417:
1418: offset += load_hdr->hdr.ldci_cmd_size;
1419: }
1420:
1421: /* If the last command is the load command map and is not undefined,
1422: decrement the count of load commands. */
1423: if (rw && load_end[-1].load->hdr.ldci_cmd_type == LDC_UNDEFINED)
1424: {
1425: load_end--;
1426: hdr.moh_n_load_cmds--;
1427: }
1428:
1429: /* Go through and process each symbol table section. */
1430: symbol_load_cmds = 0;
1431: for (load_cmd = load_array; load_cmd < load_end; load_cmd++)
1432: {
1433: load_union_t *load_hdr = load_cmd->load;
1434:
1435: if (load_hdr->hdr.ldci_cmd_type == LDC_SYMBOLS)
1436: {
1437: symbol_load_cmds++;
1438:
1439: if (debug)
1440: {
1.1.1.2 ! root 1441: char *kind = "unknown";
1.1 root 1442:
1443: switch (load_hdr->sym.symc_kind)
1444: {
1445: case SYMC_IMPORTS: kind = "imports"; break;
1446: case SYMC_DEFINED_SYMBOLS: kind = "defined"; break;
1447: case SYMC_STABS: kind = "stabs"; break;
1448: }
1449:
1450: fprintf (stderr, "\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
1451: symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
1452: }
1453:
1454: if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
1455: continue;
1456:
1457: str_sect = load_array[load_hdr->sym.symc_strings_section].section;
1458: if (str_sect == (char *)0)
1459: fatal ("string section missing");
1460:
1461: if (load_cmd->section == (char *)0)
1462: fatal ("section pointer missing");
1463:
1464: num_syms = load_hdr->sym.symc_nentries;
1465: for (i = 0; i < num_syms; i++)
1466: {
1467: symbol_info_t *sym = ((symbol_info_t *) load_cmd->section) + i;
1468: char *name = sym->si_name.symbol_name + str_sect;
1469:
1470: if (name[0] != '_')
1471: continue;
1472:
1473: if (rw)
1474: {
1.1.1.2 ! root 1475: char *n = name;
! 1476: while (*n == '_')
! 1477: ++n;
! 1478: if (*n != 'm' || (n - name) < 2 || strcmp (n, "main"))
1.1 root 1479: continue;
1480:
1481: main_sym = sym;
1482: }
1.1.1.2 ! root 1483: else
1.1 root 1484: {
1.1.1.2 ! root 1485: switch (is_ctor_dtor (name))
! 1486: {
! 1487: case 1:
! 1488: add_to_list (&constructors, name);
! 1489: break;
! 1490:
! 1491: case 2:
! 1492: add_to_list (&destructors, name);
! 1493: break;
! 1494:
! 1495: default: /* not a constructor or destructor */
! 1496: continue;
! 1497: }
1.1 root 1498: }
1499:
1500: if (debug)
1501: fprintf (stderr, "\ttype = 0x%.4x, sc = 0x%.2x, flags = 0x%.8x, name = %.30s\n",
1502: sym->si_type, sym->si_sc_type, sym->si_flags, name);
1503: }
1504: }
1505: }
1506:
1507: if (symbol_load_cmds == 0)
1508: fatal ("no symbol table found.");
1509:
1510: /* Update the program file now, rewrite header and load commands. At present,
1511: we assume that there is enough space after the last load command to insert
1512: one more. Since the first section written out is page aligned, and the
1513: number of load commands is small, this is ok for the present. */
1514:
1515: if (rw)
1516: {
1517: load_union_t *load_map;
1518: size_t size;
1519:
1520: if (cmd_strings == -1)
1521: fatal ("no cmd_strings found.");
1522:
1523: /* Add __main to initializer list. */
1524: if (main_sym != (symbol_info_t *)0)
1525: add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION);
1526:
1527: if (debug)
1528: fprintf (stderr, "\nUpdating header and load commands.\n\n");
1529:
1530: hdr.moh_n_load_cmds++;
1531: size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1));
1532:
1533: /* Create new load command map. */
1534: if (debug)
1535: fprintf (stderr, "load command map, %d cmds, new size %ld.\n",
1536: (int)hdr.moh_n_load_cmds, (long)size);
1537:
1538: load_map = (load_union_t *) xcalloc (1, size);
1539: load_map->map.ldc_header.ldci_cmd_type = LDC_CMD_MAP;
1540: load_map->map.ldc_header.ldci_cmd_size = size;
1541: load_map->map.lcm_ld_cmd_strings = cmd_strings;
1542: load_map->map.lcm_nentries = hdr.moh_n_load_cmds;
1543: load_array[hdr.moh_n_load_cmds-1].load = load_map;
1544:
1545: offset = hdr.moh_first_cmd_off;
1546: for (i = 0; i < hdr.moh_n_load_cmds; i++)
1547: {
1548: load_map->map.lcm_map[i] = offset;
1549: if (load_array[i].load->hdr.ldci_cmd_type == LDC_CMD_MAP)
1550: hdr.moh_load_map_cmd_off = offset;
1551:
1552: offset += load_array[i].load->hdr.ldci_cmd_size;
1553: }
1554:
1555: hdr.moh_sizeofcmds = offset - MO_SIZEOF_RAW_HDR;
1556:
1557: if (debug)
1558: print_header (&hdr);
1559:
1560: /* Write header */
1561: status = encode_mach_o_hdr (&hdr, obj, MO_SIZEOF_RAW_HDR);
1562: if (status != MO_HDR_CONV_SUCCESS)
1563: bad_header (status);
1564:
1565: if (debug)
1566: fprintf (stderr, "writing load commands.\n\n");
1567:
1568: /* Write load commands */
1569: offset = hdr.moh_first_cmd_off;
1570: for (i = 0; i < hdr.moh_n_load_cmds; i++)
1571: {
1572: load_union_t *load_hdr = load_array[i].load;
1573: size_t size = load_hdr->hdr.ldci_cmd_size;
1574:
1575: if (debug)
1576: print_load_command (load_hdr, offset, i);
1577:
1578: memcpy (obj + offset, load_hdr, size);
1579: offset += size;
1580: }
1581: }
1582:
1583: end_file (obj_file);
1584:
1585: if (close (prog_fd))
1586: fatal_perror ("Can't close %s", prog_name);
1587:
1588: if (debug)
1589: fprintf (stderr, "\n");
1590: }
1591:
1592:
1593: /* Add a function table to the load commands to call a function
1.1.1.2 ! root 1594: on initiation or termination of the process. */
1.1 root 1595:
1596: static void
1597: add_func_table (hdr_p, load_array, sym, type)
1598: mo_header_t *hdr_p; /* pointer to global header */
1599: load_all_t *load_array; /* array of ptrs to load cmds */
1600: symbol_info_t *sym; /* pointer to symbol entry */
1601: int type; /* fntc_type value */
1602: {
1603: /* Add a new load command. */
1604: int num_cmds = ++hdr_p->moh_n_load_cmds;
1605: int load_index = num_cmds - 1;
1606: size_t size = sizeof (func_table_command_t) + sizeof (mo_addr_t);
1607: load_union_t *ptr = xcalloc (1, size);
1608: load_all_t *load_cmd;
1609: int i;
1610:
1611: /* Set the unresolved address bit in the header to force the loader to be
1612: used, since kernel exec does not call the initialization functions. */
1613: hdr_p->moh_flags |= MOH_UNRESOLVED_F;
1614:
1615: load_cmd = &load_array[load_index];
1616: load_cmd->load = ptr;
1617: load_cmd->section = (char *)0;
1618:
1619: /* Fill in func table load command. */
1620: ptr->func.ldc_header.ldci_cmd_type = LDC_FUNC_TABLE;
1621: ptr->func.ldc_header.ldci_cmd_size = size;
1622: ptr->func.ldc_header.ldci_section_off = 0;
1623: ptr->func.ldc_header.ldci_section_len = 0;
1624: ptr->func.fntc_type = type;
1625: ptr->func.fntc_nentries = 1;
1626:
1627: /* copy address, turn it from abs. address to (region,offset) if necessary. */
1628: /* Is the symbol already expressed as (region, offset)? */
1629: if ((sym->si_flags & SI_ABSOLUTE_VALUE_F) == 0)
1630: {
1631: ptr->func.fntc_entry_loc[i].adr_lcid = sym->si_value.def_val.adr_lcid;
1632: ptr->func.fntc_entry_loc[i].adr_sctoff = sym->si_value.def_val.adr_sctoff;
1633: }
1634:
1635: /* If not, figure out which region it's in. */
1636: else
1637: {
1638: mo_vm_addr_t addr = sym->si_value.abs_val;
1639: int found = 0;
1640:
1641: for (i = 0; i < load_index; i++)
1642: {
1643: if (load_array[i].load->hdr.ldci_cmd_type == LDC_REGION)
1644: {
1645: region_command_t *region_ptr = &load_array[i].load->region;
1646:
1647: if ((region_ptr->regc_flags & REG_ABS_ADDR_F) != 0
1648: && addr >= region_ptr->regc_addr.vm_addr
1649: && addr <= region_ptr->regc_addr.vm_addr + region_ptr->regc_vm_size)
1650: {
1651: ptr->func.fntc_entry_loc[0].adr_lcid = i;
1652: ptr->func.fntc_entry_loc[0].adr_sctoff = addr - region_ptr->regc_addr.vm_addr;
1653: found++;
1654: break;
1655: }
1656: }
1657: }
1658:
1659: if (!found)
1660: fatal ("could not convert 0x%l.8x into a region", addr);
1661: }
1662:
1663: if (debug)
1664: fprintf (stderr,
1665: "%s function, region %d, offset = %ld (0x%.8lx)\n",
1666: (type == FNTC_INITIALIZATION) ? "init" : "term",
1667: (int)ptr->func.fntc_entry_loc[i].adr_lcid,
1668: (long)ptr->func.fntc_entry_loc[i].adr_sctoff,
1669: (long)ptr->func.fntc_entry_loc[i].adr_sctoff);
1670:
1671: }
1672:
1673:
1674: /* Print the global header for an OSF/rose object. */
1675:
1676: static void
1677: print_header (hdr_ptr)
1678: mo_header_t *hdr_ptr;
1679: {
1680: fprintf (stderr, "\nglobal header:\n");
1681: fprintf (stderr, "\tmoh_magic = 0x%.8lx\n", hdr_ptr->moh_magic);
1682: fprintf (stderr, "\tmoh_major_version = %d\n", (int)hdr_ptr->moh_major_version);
1683: fprintf (stderr, "\tmoh_minor_version = %d\n", (int)hdr_ptr->moh_minor_version);
1684: fprintf (stderr, "\tmoh_header_version = %d\n", (int)hdr_ptr->moh_header_version);
1685: fprintf (stderr, "\tmoh_max_page_size = %d\n", (int)hdr_ptr->moh_max_page_size);
1686: fprintf (stderr, "\tmoh_byte_order = %d\n", (int)hdr_ptr->moh_byte_order);
1687: fprintf (stderr, "\tmoh_data_rep_id = %d\n", (int)hdr_ptr->moh_data_rep_id);
1688: fprintf (stderr, "\tmoh_cpu_type = %d\n", (int)hdr_ptr->moh_cpu_type);
1689: fprintf (stderr, "\tmoh_cpu_subtype = %d\n", (int)hdr_ptr->moh_cpu_subtype);
1690: fprintf (stderr, "\tmoh_vendor_type = %d\n", (int)hdr_ptr->moh_vendor_type);
1691: fprintf (stderr, "\tmoh_load_map_cmd_off = %d\n", (int)hdr_ptr->moh_load_map_cmd_off);
1692: fprintf (stderr, "\tmoh_first_cmd_off = %d\n", (int)hdr_ptr->moh_first_cmd_off);
1693: fprintf (stderr, "\tmoh_sizeofcmds = %d\n", (int)hdr_ptr->moh_sizeofcmds);
1694: fprintf (stderr, "\tmon_n_load_cmds = %d\n", (int)hdr_ptr->moh_n_load_cmds);
1695: fprintf (stderr, "\tmoh_flags = 0x%.8lx", (long)hdr_ptr->moh_flags);
1696:
1697: if (hdr_ptr->moh_flags & MOH_RELOCATABLE_F)
1698: fprintf (stderr, ", relocatable");
1699:
1700: if (hdr_ptr->moh_flags & MOH_LINKABLE_F)
1701: fprintf (stderr, ", linkable");
1702:
1703: if (hdr_ptr->moh_flags & MOH_EXECABLE_F)
1704: fprintf (stderr, ", execable");
1705:
1706: if (hdr_ptr->moh_flags & MOH_EXECUTABLE_F)
1707: fprintf (stderr, ", executable");
1708:
1709: if (hdr_ptr->moh_flags & MOH_UNRESOLVED_F)
1710: fprintf (stderr, ", unresolved");
1711:
1712: fprintf (stderr, "\n\n");
1713: return;
1714: }
1715:
1716:
1717: /* Print a short summary of a load command. */
1718:
1719: static void
1720: print_load_command (load_hdr, offset, number)
1721: load_union_t *load_hdr;
1722: size_t offset;
1723: int number;
1724: {
1725: mo_long_t type = load_hdr->hdr.ldci_cmd_type;
1726: char *type_str = (char *)0;
1727:
1728: switch (type)
1729: {
1730: case LDC_UNDEFINED: type_str = "UNDEFINED"; break;
1731: case LDC_CMD_MAP: type_str = "CMD_MAP"; break;
1732: case LDC_INTERPRETER: type_str = "INTERPRETER"; break;
1733: case LDC_STRINGS: type_str = "STRINGS"; break;
1734: case LDC_REGION: type_str = "REGION"; break;
1735: case LDC_RELOC: type_str = "RELOC"; break;
1736: case LDC_PACKAGE: type_str = "PACKAGE"; break;
1737: case LDC_SYMBOLS: type_str = "SYMBOLS"; break;
1738: case LDC_ENTRY: type_str = "ENTRY"; break;
1739: case LDC_FUNC_TABLE: type_str = "FUNC_TABLE"; break;
1740: case LDC_GEN_INFO: type_str = "GEN_INFO"; break;
1741: }
1742:
1743: fprintf (stderr,
1744: "cmd %2d, sz: 0x%.2lx, coff: 0x%.3lx, doff: 0x%.6lx, dlen: 0x%.6lx",
1745: number,
1746: (long) load_hdr->hdr.ldci_cmd_size,
1747: (long) offset,
1748: (long) load_hdr->hdr.ldci_section_off,
1749: (long) load_hdr->hdr.ldci_section_len);
1750:
1751: if (type_str == (char *)0)
1752: fprintf (stderr, ", ty: unknown (%ld)\n", (long) type);
1753:
1754: else if (type != LDC_REGION)
1755: fprintf (stderr, ", ty: %s\n", type_str);
1756:
1757: else
1758: {
1759: char *region = "";
1760: switch (load_hdr->region.regc_usage_type)
1761: {
1762: case REG_TEXT_T: region = ", .text"; break;
1763: case REG_DATA_T: region = ", .data"; break;
1764: case REG_BSS_T: region = ", .bss"; break;
1765: case REG_GLUE_T: region = ", .glue"; break;
1766: #if defined (REG_RDATA_T) && defined (REG_SDATA_T) && defined (REG_SBSS_T) /*mips*/
1767: case REG_RDATA_T: region = ", .rdata"; break;
1768: case REG_SDATA_T: region = ", .sdata"; break;
1769: case REG_SBSS_T: region = ", .sbss"; break;
1770: #endif
1771: }
1772:
1773: fprintf (stderr, ", ty: %s, vaddr: 0x%.8lx, vlen: 0x%.6lx%s\n",
1774: type_str,
1775: (long) load_hdr->region.regc_vm_addr,
1776: (long) load_hdr->region.regc_vm_size,
1777: region);
1778: }
1779:
1780: return;
1781: }
1782:
1783:
1784: /* Fatal error when {en,de}code_mach_o_header fails. */
1785:
1786: static void
1787: bad_header (status)
1788: int status;
1789: {
1790: char *msg = (char *)0;
1791:
1792: switch (status)
1793: {
1794: case MO_ERROR_BAD_MAGIC: msg = "bad magic number"; break;
1795: case MO_ERROR_BAD_HDR_VERS: msg = "bad header version"; break;
1796: case MO_ERROR_BAD_RAW_HDR_VERS: msg = "bad raw header version"; break;
1797: case MO_ERROR_BUF2SML: msg = "raw header buffer too small"; break;
1798: case MO_ERROR_OLD_RAW_HDR_FILE: msg = "old raw header file"; break;
1799: case MO_ERROR_UNSUPPORTED_VERS: msg = "unsupported version"; break;
1800: }
1801:
1802: if (msg == (char *)0)
1803: fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
1804: else
1805: fatal ("%s", msg);
1806: }
1807:
1808:
1809: /* Read a file into a memory buffer. */
1810:
1811: static struct file_info *
1812: read_file (name, fd, rw)
1813: char *name; /* filename */
1814: int fd; /* file descriptor */
1815: int rw; /* read/write */
1816: {
1817: struct stat stat_pkt;
1818: struct file_info *p = (struct file_info *) xcalloc (sizeof (struct file_info), 1);
1819: #ifdef USE_MMAP
1820: static int page_size;
1821: #endif
1822:
1823: if (fstat (fd, &stat_pkt) < 0)
1824: fatal_perror ("fstat %s", name);
1825:
1826: p->name = name;
1827: p->size = stat_pkt.st_size;
1828: p->rounded_size = stat_pkt.st_size;
1829: p->fd = fd;
1830: p->rw = rw;
1831:
1832: #ifdef USE_MMAP
1833: if (debug)
1834: fprintf (stderr, "mmap %s, %s\n", name, (rw) ? "read/write" : "read-only");
1835:
1836: if (page_size == 0)
1837: page_size = sysconf (_SC_PAGE_SIZE);
1838:
1839: p->rounded_size = ((p->size + page_size - 1) / page_size) * page_size;
1840: p->start = mmap ((caddr_t)0,
1841: (rw) ? p->rounded_size : p->size,
1842: (rw) ? (PROT_READ | PROT_WRITE) : PROT_READ,
1843: MAP_FILE | MAP_VARIABLE | MAP_SHARED,
1844: fd,
1845: 0L);
1846:
1847: if (p->start != (char *)0 && p->start != (char *)-1)
1848: p->use_mmap = 1;
1849:
1850: else
1851: #endif /* USE_MMAP */
1852: {
1853: long len;
1854:
1855: if (debug)
1856: fprintf (stderr, "read %s\n", name);
1857:
1858: p->use_mmap = 0;
1859: p->start = xmalloc (p->size);
1860: if (lseek (fd, 0L, SEEK_SET) < 0)
1861: fatal_perror ("lseek to 0 on %s", name);
1862:
1863: len = read (fd, p->start, p->size);
1864: if (len < 0)
1865: fatal_perror ("read %s", name);
1866:
1867: if (len != p->size)
1868: fatal ("read %ld bytes, expected %ld, from %s", len, p->size, name);
1869: }
1870:
1871: return p;
1872: }
1873:
1874:
1875: /* Do anything necessary to write a file back from memory. */
1876:
1877: static void
1878: end_file (ptr)
1879: struct file_info *ptr; /* file information block */
1880: {
1881: #ifdef USE_MMAP
1882: if (ptr->use_mmap)
1883: {
1884: if (ptr->rw)
1885: {
1886: if (debug)
1887: fprintf (stderr, "msync %s\n", ptr->name);
1888:
1889: if (msync (ptr->start, ptr->rounded_size, MS_ASYNC))
1890: fatal_perror ("msync %s", ptr->name);
1891: }
1892:
1893: if (debug)
1894: fprintf (stderr, "munmap %s\n", ptr->name);
1895:
1896: if (munmap (ptr->start, ptr->size))
1897: fatal_perror ("munmap %s", ptr->name);
1898: }
1899: else
1900: #endif /* USE_MMAP */
1901: {
1902: if (ptr->rw)
1903: {
1904: long len;
1905:
1906: if (debug)
1907: fprintf (stderr, "write %s\n", ptr->name);
1908:
1909: if (lseek (ptr->fd, 0L, SEEK_SET) < 0)
1910: fatal_perror ("lseek to 0 on %s", ptr->name);
1911:
1912: len = write (ptr->fd, ptr->start, ptr->size);
1913: if (len < 0)
1914: fatal_perror ("read %s", ptr->name);
1915:
1916: if (len != ptr->size)
1917: fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name);
1918: }
1919:
1920: free ((generic *)ptr->start);
1921: }
1922:
1923: free ((generic *)ptr);
1924: }
1925:
1926: #endif /* OBJECT_FORMAT_ROSE */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.