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