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