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