]> gcc.gnu.org Git - gcc.git/blame - gcc/collect2.c
(GO_IF_NONINDEXED_ADDRESS): Delete spurious space in prev change.
[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
4e81a331 280 fprintf (stderr, "collect: ");
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{
4e81a331 292 fprintf (stderr, "collect: ");
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{
4e81a331 304 fprintf (stderr, "collect: ");
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);
98552524 847#endif
bb59f9a6
RS
848 /* Likewise for `real-ld'. */
849 if (ld_file_name == 0)
850 ld_file_name = find_a_file (&cpath, real_ld_suffix);
851 if (ld_file_name == 0)
852 ld_file_name = find_a_file (&path, full_real_ld_suffix);
853 /* Maybe we know the right file to use (if not cross). */
854#ifdef REAL_LD_FILE_NAME
855 if (ld_file_name == 0)
856 ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME);
4e81a331 857#endif
bb59f9a6
RS
858 /* This would be the right place to search the compiler dirs
859 for `ld', but we don't do that, since this program is installed
860 there as `ld'. */
861 /* Search the ordinary system bin directories
46c74083 862 for `ld' (if native linking) or `TARGET-ld' (if cross). */
bb59f9a6
RS
863 if (ld_file_name == 0)
864 ld_file_name = find_a_file (&path, full_ld_suffix);
865
866 nm_file_name = find_a_file (&cpath, gnm_suffix);
867 if (nm_file_name == 0)
868 nm_file_name = find_a_file (&path, full_gnm_suffix);
869 if (nm_file_name == 0)
870 nm_file_name = find_a_file (&cpath, nm_suffix);
871#ifdef REAL_NM_FILE_NAME
872 if (nm_file_name == 0)
873 nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME);
aaf625e5 874#endif
bb59f9a6
RS
875 if (nm_file_name == 0)
876 nm_file_name = find_a_file (&path, full_nm_suffix);
877
878 strip_file_name = find_a_file (&cpath, gstrip_suffix);
879 if (strip_file_name == 0)
880 strip_file_name = find_a_file (&path, full_gstrip_suffix);
881 if (strip_file_name == 0)
882 strip_file_name = find_a_file (&cpath, strip_suffix);
883#ifdef REAL_STRIP_FILE_NAME
884 if (strip_file_name == 0)
885 strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME);
4e81a331 886#endif
bb59f9a6
RS
887 if (strip_file_name == 0)
888 strip_file_name = find_a_file (&path, full_strip_suffix);
4e81a331 889
a87104d9 890 /* Determine the full path name of the C compiler to use. */
ed5b9462 891 c_file_name = getenv ("COLLECT_GCC");
5365d6ee 892 if (c_file_name == 0)
4e81a331 893 {
bb59f9a6 894#ifdef CROSS_COMPILE
aee42e27 895 c_file_name = xcalloc (sizeof ("gcc-") + strlen (target_machine) + 1, 1);
46c74083
RS
896 strcpy (c_file_name, target_machine);
897 strcat (c_file_name, "-gcc");
4e81a331 898#else
bb59f9a6 899 c_file_name = "gcc";
a87104d9 900#endif
a87104d9
MM
901 }
902
bb59f9a6
RS
903 p = find_a_file (&cpath, c_file_name);
904
905 /* Here it should be safe to use the system search path since we should have
906 already qualified the name of the compiler when it is needed. */
907 if (p == 0)
908 p = find_a_file (&path, c_file_name);
909
910 if (p)
911 c_file_name = p;
4e81a331 912
45840c57 913 *ld1++ = *ld2++ = ld_file_name;
4e81a331
RS
914
915 /* Make temp file names. */
916 choose_temp_base ();
917 c_file = xcalloc (temp_filename_length + sizeof (".c"), 1);
918 o_file = xcalloc (temp_filename_length + sizeof (".o"), 1);
919 sprintf (c_file, "%s.c", temp_filename);
920 sprintf (o_file, "%s.o", temp_filename);
ed5b9462 921 *c_ptr++ = c_file_name;
4e81a331
RS
922 *c_ptr++ = "-c";
923 *c_ptr++ = "-o";
924 *c_ptr++ = o_file;
925
ed5b9462
RS
926 /* !!! When GCC calls collect2,
927 it does not know whether it is calling collect2 or ld.
928 So collect2 cannot meaningfully understand any options
929 except those ld understands.
930 If you propose to make GCC pass some other option,
931 just imagine what will happen if ld is really ld!!! */
932
4e81a331 933 /* Parse arguments. Remember output file spec, pass the rest to ld. */
ed5b9462
RS
934 /* After the first file, put in the c++ rt0. */
935
4e81a331
RS
936 first_file = 1;
937 while ((arg = *++argv) != (char *)0)
938 {
939 *ld1++ = *ld2++ = arg;
940
941 if (arg[0] == '-')
942 switch (arg[1])
943 {
944 case 'd':
945 if (!strcmp (arg, "-debug"))
946 {
947 debug = 1;
948 vflag = 1;
949 ld1--;
950 ld2--;
951 }
952 break;
953
4e81a331 954 case 'o':
0cdd3ddd 955 output_file = (arg[2] == '\0') ? argv[1] : &arg[2];
4e81a331
RS
956 break;
957
958 case 'r':
959 if (arg[2] == '\0')
960 rflag = 1;
961 break;
962
a87104d9
MM
963 case 's':
964 if (arg[2] == '\0')
965 {
966 /* We must strip after the nm run, otherwise C++ linking
967 won't work. Thus we strip in the second ld run, or
968 else with strip if there is no second ld run. */
969 strip_flag = 1;
970 ld1--;
971 }
972 break;
973
4e81a331
RS
974 case 'v':
975 if (arg[2] == '\0')
976 vflag = 1;
977 break;
978 }
979
980 else if (first_file
3f7cc57a 981 && (p = rindex (arg, '.')) != (char *)0
4e81a331
RS
982 && strcmp (p, ".o") == 0)
983 {
984 first_file = 0;
985 *ld2++ = o_file;
986 }
987 }
988
ed5b9462
RS
989 /* Get any options that the upper GCC wants to pass to the sub-GCC. */
990 p = (char *) getenv ("COLLECT_GCC_OPTIONS");
991 if (p)
992 while (*p)
993 {
994 char *q = p;
995 while (*q && *q != ' ') q++;
996 if (*p == '-' && (p[1] == 'm' || p[1] == 'f'))
997 *c_ptr++ = savestring (p, q - p);
998
999 if (*q) q++;
1000 p = q;
1001 }
1002
4e81a331
RS
1003 *c_ptr++ = c_file;
1004 *c_ptr = *ld1 = *ld2 = (char *)0;
1005
1006 if (vflag)
1007 {
ed5b9462 1008 fprintf (stderr, "collect2 version %s", version_string);
4e81a331
RS
1009#ifdef TARGET_VERSION
1010 TARGET_VERSION;
1011#endif
1012 fprintf (stderr, "\n");
1013 }
1014
1015 if (debug)
1016 {
ed5b9462 1017 char *ptr;
a1549b15
RS
1018 fprintf (stderr, "ld_file_name = %s\n",
1019 (ld_file_name ? ld_file_name : "not found"));
1020 fprintf (stderr, "c_file_name = %s\n",
1021 (c_file_name ? c_file_name : "not found"));
1022 fprintf (stderr, "nm_file_name = %s\n",
1023 (nm_file_name ? nm_file_name : "not found"));
1024 fprintf (stderr, "strip_file_name = %s\n",
1025 (strip_file_name ? strip_file_name : "not found"));
1026 fprintf (stderr, "c_file = %s\n",
1027 (c_file ? c_file : "not found"));
1028 fprintf (stderr, "o_file = %s\n",
1029 (o_file ? o_file : "not found"));
ed5b9462
RS
1030
1031 ptr = getenv ("COLLECT_GCC_OPTIONS");
1032 if (ptr)
1033 fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
1034
1035 ptr = getenv ("COLLECT_GCC");
1036 if (ptr)
1037 fprintf (stderr, "COLLECT_GCC = %s\n", ptr);
1038
1039 ptr = getenv ("COMPILER_PATH");
1040 if (ptr)
1041 fprintf (stderr, "COMPILER_PATH = %s\n", ptr);
1042
1043 ptr = getenv ("LIBRARY_PATH");
1044 if (ptr)
1045 fprintf (stderr, "LIBRARY_PATH = %s\n", ptr);
1046
1047 fprintf (stderr, "\n");
4e81a331
RS
1048 }
1049
1050 /* Load the program, searching all libraries.
1051 Examine the namelist with nm and search it for static constructors
1052 and destructors to call.
1053 Write the constructor and destructor tables to a .s file and reload. */
1054
aee3a549 1055 fork_execute ("ld", ld1_argv);
4e81a331
RS
1056
1057 /* If -r, don't build the constructor or destructor list, just return now. */
1058 if (rflag)
1059 return 0;
1060
0cdd3ddd 1061 scan_prog_file (output_file, PASS_FIRST);
4e81a331
RS
1062
1063 if (debug)
1064 {
1065 fprintf (stderr, "%d constructor(s) found\n", constructors.number);
1066 fprintf (stderr, "%d destructor(s) found\n", destructors.number);
1067 }
1068
1069 if (constructors.number == 0 && destructors.number == 0)
a87104d9
MM
1070 {
1071 /* Strip now if it was requested on the command line. */
1072 if (strip_flag)
1073 {
1074 char **strip_argv = (char **) xcalloc (sizeof (char *), 3);
aee3a549 1075 strip_argv[0] = strip_file_name;
0cdd3ddd 1076 strip_argv[1] = output_file;
a87104d9 1077 strip_argv[2] = (char *) 0;
aee3a549 1078 fork_execute ("strip", strip_argv);
a87104d9
MM
1079 }
1080 return 0;
1081 }
4e81a331
RS
1082
1083 outf = fopen (c_file, "w");
1084 if (outf == (FILE *)0)
1fab8e81 1085 fatal_perror ("%s", c_file);
4e81a331
RS
1086
1087 write_c_file (outf, c_file);
1088
1089 if (fclose (outf))
1fab8e81 1090 fatal_perror ("closing %s", c_file);
4e81a331
RS
1091
1092 if (debug)
1093 {
0cdd3ddd
RS
1094 fprintf (stderr, "\n========== output_file = %s, c_file = %s\n",
1095 output_file, c_file);
4e81a331
RS
1096 write_c_file (stderr, "stderr");
1097 fprintf (stderr, "========== end of c_file\n\n");
1098 }
1099
1100 /* Assemble the constructor and destructor tables.
1101 Link the tables in with the rest of the program. */
1102
aee3a549
RK
1103 fork_execute ("gcc", c_argv);
1104 fork_execute ("ld", ld2_argv);
4e81a331
RS
1105
1106 /* Let scan_prog_file do any final mods (OSF/rose needs this for
1107 constructors/destructors in shared libraries. */
0cdd3ddd 1108 scan_prog_file (output_file, PASS_SECOND);
4e81a331
RS
1109
1110 maybe_unlink (c_file);
1111 maybe_unlink (o_file);
1112 return 0;
1113}
1114
1115\f
1116/* Wait for a process to finish, and exit if a non-zero status is found. */
1117
1118static void
1119do_wait (prog)
1120 char *prog;
1121{
1122 int status;
1123
1124 wait (&status);
1125 if (status)
1126 {
ed5b9462 1127 int sig = status & 0x7F;
4e81a331
RS
1128 int ret;
1129
1130 if (sig != -1 && sig != 0)
1131 {
ed5b9462
RS
1132#ifdef NO_SYS_SIGLIST
1133 error ("%s terminated with signal %d %s",
1134 prog,
1135 sig,
1136 (status & 0200) ? ", core dumped" : "");
1137#else
4e81a331
RS
1138 error ("%s terminated with signal %d [%s]%s",
1139 prog,
1140 sig,
1141 sys_siglist[sig],
1142 (status & 0200) ? ", core dumped" : "");
ed5b9462 1143#endif
4e81a331
RS
1144
1145 my_exit (127);
1146 }
1147
ed5b9462 1148 ret = ((status & 0xFF00) >> 8);
4e81a331
RS
1149 if (ret != -1 && ret != 0)
1150 {
1151 error ("%s returned %d exit status", prog, ret);
1152 my_exit (ret);
1153 }
1154 }
1155}
1156
1157\f
1158/* Fork and execute a program, and wait for the reply. */
1159
1160static void
1161fork_execute (prog, argv)
1162 char *prog;
1163 char **argv;
1164{
1165 int pid;
4e81a331
RS
1166
1167 if (vflag || debug)
1168 {
1169 char **p_argv;
1170 char *str;
1171
aee3a549
RK
1172 if (argv[0])
1173 fprintf (stderr, "%s", argv[0]);
bb59f9a6 1174 else
aee3a549 1175 fprintf (stderr, "[cannot find %s]", prog);
bb59f9a6 1176
4e81a331
RS
1177 for (p_argv = &argv[1]; (str = *p_argv) != (char *)0; p_argv++)
1178 fprintf (stderr, " %s", str);
1179
1180 fprintf (stderr, "\n");
1181 }
1182
1183 fflush (stdout);
1184 fflush (stderr);
1185
bb59f9a6
RS
1186 /* If we can't find a program we need, complain error. Do this here
1187 since we might not end up needing something that we couldn't find. */
1188
aee3a549
RK
1189 if (argv[0] == 0)
1190 fatal ("cannot find `%s'", prog);
bb59f9a6 1191
4e81a331
RS
1192 pid = vfork ();
1193 if (pid == -1)
1194 fatal_perror ("vfork");
1195
1196 if (pid == 0) /* child context */
1197 {
aee3a549 1198 execvp (argv[0], argv);
1fab8e81 1199 fatal_perror ("executing %s", prog);
4e81a331
RS
1200 }
1201
4e81a331 1202 do_wait (prog);
4e81a331
RS
1203}
1204
1205\f
1206/* Unlink a file unless we are debugging. */
1207
1208static void
1209maybe_unlink (file)
1210 char *file;
1211{
1212 if (!debug)
1213 unlink (file);
1214 else
1215 fprintf (stderr, "[Leaving %s]\n", file);
1216}
1217
1218\f
1219/* Add a name to a linked list. */
1220
1221static void
1222add_to_list (head_ptr, name)
1223 struct head *head_ptr;
1224 char *name;
1225{
1226 struct id *newid = (struct id *) xcalloc (sizeof (*newid) + strlen (name), 1);
1227 static long sequence_number = 0;
1228 newid->sequence = ++sequence_number;
1229 strcpy (newid->name, name);
1230
1231 if (head_ptr->first)
1232 head_ptr->last->next = newid;
1233 else
1234 head_ptr->first = newid;
1235
1236 head_ptr->last = newid;
1237 head_ptr->number++;
1238}
1239
1240/* Write: `prefix', the names on list LIST, `suffix'. */
1241
1242static void
1243write_list (stream, prefix, list)
1244 FILE *stream;
1245 char *prefix;
1246 struct id *list;
1247{
1248 while (list)
1249 {
1250 fprintf (stream, "%sx%d,\n", prefix, list->sequence);
1251 list = list->next;
1252 }
1253}
1254
1255static void
1256write_list_with_asm (stream, prefix, list)
1257 FILE *stream;
1258 char *prefix;
1259 struct id *list;
1260{
1261 while (list)
1262 {
c7af43d8 1263 fprintf (stream, "%sx%d __asm__ (\"%s\");\n",
4e81a331
RS
1264 prefix, list->sequence, list->name);
1265 list = list->next;
1266 }
1267}
1268
1269/* Write the constructor/destructor tables. */
1270
1271static void
1272write_c_file (stream, name)
1273 FILE *stream;
1274 char *name;
1275{
1276 /* Write the tables as C code */
1277
1278 fprintf (stream, "typedef void entry_pt();\n\n");
1279
17704846 1280 write_list_with_asm (stream, "extern entry_pt ", constructors.first);
4e81a331
RS
1281
1282 fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
1283 fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number);
ed5b9462 1284 write_list (stream, "\t", constructors.first);
4e81a331
RS
1285 fprintf (stream, "\t0\n};\n\n");
1286
17704846 1287 write_list_with_asm (stream, "extern entry_pt ", destructors.first);
4e81a331
RS
1288
1289 fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
1290 fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number);
ed5b9462 1291 write_list (stream, "\t", destructors.first);
4e81a331
RS
1292 fprintf (stream, "\t0\n};\n\n");
1293
1294 fprintf (stream, "extern entry_pt __main;\n");
1295 fprintf (stream, "entry_pt *__main_reference = __main;\n\n");
1296}
1297
1298\f
ed5b9462 1299#ifdef OBJECT_FORMAT_NONE
4e81a331 1300
ed5b9462
RS
1301/* Generic version to scan the name list of the loaded program for
1302 the symbols g++ uses for static constructors and destructors.
4e81a331
RS
1303
1304 The constructor table begins at __CTOR_LIST__ and contains a count
1305 of the number of pointers (or -1 if the constructors are built in a
1306 separate section by the linker), followed by the pointers to the
1307 constructor functions, terminated with a null pointer. The
1308 destructor table has the same format, and begins at __DTOR_LIST__. */
1309
1310static void
1311scan_prog_file (prog_name, which_pass)
1312 char *prog_name;
1313 enum pass which_pass;
1314{
ed5b9462
RS
1315 void (*int_handler) ();
1316 void (*quit_handler) ();
4e81a331
RS
1317 char *nm_argv[4];
1318 int pid;
1319 int argc = 0;
1320 int pipe_fd[2];
1321 char *p, buf[1024];
1322 FILE *inf;
1323
1324 if (which_pass != PASS_FIRST)
1325 return;
1326
bb59f9a6
RS
1327 /* If we don't have an `nm', complain. */
1328 if (nm_file_name == 0)
1329 fatal ("cannot find `nm'");
1330
ed5b9462 1331 nm_argv[argc++] = "nm";
4e81a331 1332 if (NM_FLAGS[0] != '\0')
ed5b9462 1333 nm_argv[argc++] = NM_FLAGS;
4e81a331 1334
ed5b9462
RS
1335 nm_argv[argc++] = prog_name;
1336 nm_argv[argc++] = (char *)0;
4e81a331
RS
1337
1338 if (pipe (pipe_fd) < 0)
1339 fatal_perror ("pipe");
1340
1341 inf = fdopen (pipe_fd[0], "r");
1342 if (inf == (FILE *)0)
1343 fatal_perror ("fdopen");
1344
1345 /* Trace if needed. */
1346 if (vflag)
1347 {
1348 char **p_argv;
1349 char *str;
1350
1351 fprintf (stderr, "%s", nm_file_name);
1352 for (p_argv = &nm_argv[1]; (str = *p_argv) != (char *)0; p_argv++)
1353 fprintf (stderr, " %s", str);
1354
1355 fprintf (stderr, "\n");
1356 }
1357
1358 fflush (stdout);
1359 fflush (stderr);
1360
1361 /* Spawn child nm on pipe */
1362 pid = vfork ();
1363 if (pid == -1)
1364 fatal_perror ("vfork");
1365
1366 if (pid == 0) /* child context */
1367 {
1368 /* setup stdout */
1369 if (dup2 (pipe_fd[1], 1) < 0)
1fab8e81 1370 fatal_perror ("dup2 (%d, 1)", pipe_fd[1]);
4e81a331
RS
1371
1372 if (close (pipe_fd[0]) < 0)
1fab8e81 1373 fatal_perror ("close (%d)", pipe_fd[0]);
4e81a331
RS
1374
1375 if (close (pipe_fd[1]) < 0)
1fab8e81 1376 fatal_perror ("close (%d)", pipe_fd[1]);
4e81a331
RS
1377
1378 execv (nm_file_name, nm_argv);
1fab8e81 1379 fatal_perror ("executing %s", nm_file_name);
4e81a331
RS
1380 }
1381
1382 /* Parent context from here on. */
ed5b9462 1383 int_handler = (void (*) ())signal (SIGINT, SIG_IGN);
8ab861c7 1384#ifdef SIGQUIT
ed5b9462 1385 quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN);
8ab861c7 1386#endif
4e81a331
RS
1387
1388 if (close (pipe_fd[1]) < 0)
1fab8e81 1389 fatal_perror ("close (%d)", pipe_fd[1]);
4e81a331
RS
1390
1391 if (debug)
1392 fprintf (stderr, "\nnm output with constructors/destructors.\n");
1393
1394 /* Read each line of nm output. */
1395 while (fgets (buf, sizeof buf, inf) != (char *)0)
1396 {
1397 int ch, ch2;
ed5b9462 1398 char *name, *end;
4e81a331
RS
1399
1400 /* If it contains a constructor or destructor name, add the name
1401 to the appropriate list. */
1402
1403 for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
1404 ;
1405
1406 if (ch == '\0' || ch == '\n')
1407 continue;
ed5b9462
RS
1408
1409 name = p;
1410 /* Find the end of the symbol name.
1411 Don't include `|', because Encore nm can tack that on the end. */
1412 for (end = p; (ch2 = *end) != '\0' && !isspace (ch2) && ch2 != '|';
1413 end++)
1414 continue;
4e81a331
RS
1415
1416 *end = '\0';
ed5b9462 1417 switch (is_ctor_dtor (name))
4e81a331 1418 {
ed5b9462
RS
1419 case 1:
1420 add_to_list (&constructors, name);
1421 break;
4e81a331 1422
ed5b9462
RS
1423 case 2:
1424 add_to_list (&destructors, name);
1425 break;
4e81a331 1426
ed5b9462
RS
1427 default: /* not a constructor or destructor */
1428 continue;
4e81a331
RS
1429 }
1430
4e81a331
RS
1431 if (debug)
1432 fprintf (stderr, "\t%s\n", buf);
1433 }
1434
1435 if (debug)
1436 fprintf (stderr, "\n");
1437
1438 if (fclose (inf) != 0)
1439 fatal_perror ("fclose of pipe");
1440
1441 do_wait (nm_file_name);
1442
1443 signal (SIGINT, int_handler);
8ab861c7 1444#ifdef SIGQUIT
4e81a331 1445 signal (SIGQUIT, quit_handler);
8ab861c7 1446#endif
4e81a331
RS
1447}
1448
ed5b9462
RS
1449#endif /* OBJECT_FORMAT_NONE */
1450
1451\f
1452/*
1453 * COFF specific stuff.
1454 */
1455
1456#ifdef OBJECT_FORMAT_COFF
1457
1458#if defined(EXTENDED_COFF)
17704846
JW
1459# define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
1460# define GCC_SYMENT SYMR
1461# define GCC_OK_SYMBOL(X) ((X).st == stProc && (X).sc == scText)
1462# define GCC_SYMINC(X) (1)
1463# define GCC_SYMZERO(X) (SYMHEADER(X).isymMax)
1464# define GCC_CHECK_HDR(X) (PSYMTAB(X) != 0)
ed5b9462 1465#else
17704846
JW
1466# define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms)
1467# define GCC_SYMENT SYMENT
ed5b9462
RS
1468# define GCC_OK_SYMBOL(X) \
1469 (((X).n_sclass == C_EXT) && \
1470 (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) || \
1471 ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))
17704846
JW
1472# define GCC_SYMINC(X) ((X).n_numaux+1)
1473# define GCC_SYMZERO(X) 0
1474# define GCC_CHECK_HDR(X) (1)
ed5b9462
RS
1475#endif
1476
1477extern char *ldgetname ();
1478
1479/* COFF version to scan the name list of the loaded program for
1480 the symbols g++ uses for static constructors and destructors.
1481
1482 The constructor table begins at __CTOR_LIST__ and contains a count
1483 of the number of pointers (or -1 if the constructors are built in a
1484 separate section by the linker), followed by the pointers to the
1485 constructor functions, terminated with a null pointer. The
1486 destructor table has the same format, and begins at __DTOR_LIST__. */
1487
1488static void
1489scan_prog_file (prog_name, which_pass)
1490 char *prog_name;
1491 enum pass which_pass;
1492{
f3c3d3df 1493 LDFILE *ldptr = NULL;
ed5b9462
RS
1494 int sym_index, sym_count;
1495
1496 if (which_pass != PASS_FIRST)
1497 return;
1498
1499 if ((ldptr = ldopen (prog_name, ldptr)) == NULL)
1500 fatal ("%s: can't open as COFF file", prog_name);
1501
e99467d2 1502 if (!MY_ISCOFF (HEADER (ldptr).f_magic))
ed5b9462
RS
1503 fatal ("%s: not a COFF file", prog_name);
1504
17704846 1505 if (GCC_CHECK_HDR (ldptr))
ed5b9462 1506 {
17704846
JW
1507 sym_count = GCC_SYMBOLS (ldptr);
1508 sym_index = GCC_SYMZERO (ldptr);
1509 while (sym_index < sym_count)
1510 {
1511 GCC_SYMENT symbol;
ed5b9462 1512
17704846
JW
1513 if (ldtbread (ldptr, sym_index, &symbol) <= 0)
1514 break;
1515 sym_index += GCC_SYMINC (symbol);
ed5b9462 1516
17704846
JW
1517 if (GCC_OK_SYMBOL (symbol))
1518 {
1519 char *name;
ed5b9462 1520
17704846
JW
1521 if ((name = ldgetname (ldptr, &symbol)) == NULL)
1522 continue; /* should never happen */
ed5b9462
RS
1523
1524#ifdef _AIX
17704846
JW
1525 /* All AIX function names begin with a dot. */
1526 if (*name++ != '.')
1527 continue;
ed5b9462
RS
1528#endif
1529
17704846
JW
1530 switch (is_ctor_dtor (name))
1531 {
1532 case 1:
1533 add_to_list (&constructors, name);
1534 break;
ed5b9462 1535
17704846
JW
1536 case 2:
1537 add_to_list (&destructors, name);
1538 break;
ed5b9462 1539
17704846
JW
1540 default: /* not a constructor or destructor */
1541 continue;
1542 }
ed5b9462
RS
1543
1544#if !defined(EXTENDED_COFF)
17704846
JW
1545 if (debug)
1546 fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
1547 symbol.n_scnum, symbol.n_sclass,
1548 (symbol.n_type ? "0" : ""), symbol.n_type,
1549 name);
ed5b9462 1550#else
17704846
JW
1551 if (debug)
1552 fprintf (stderr, "\tiss = %5d, value = %5d, index = %5d, name = %s\n",
1553 symbol.iss, symbol.value, symbol.index, name);
ed5b9462 1554#endif
17704846 1555 }
ed5b9462
RS
1556 }
1557 }
1558
1559 (void) ldclose(ldptr);
1560}
1561
1562#endif /* OBJECT_FORMAT_COFF */
4e81a331
RS
1563
1564\f
1565/*
1566 * OSF/rose specific stuff.
1567 */
1568
1569#ifdef OBJECT_FORMAT_ROSE
1570
1571/* Union of the various load commands */
1572
1573typedef union load_union
1574{
1575 ldc_header_t hdr; /* common header */
1576 load_cmd_map_command_t map; /* map indexing other load cmds */
ed5b9462 1577 interpreter_command_t iprtr; /* interpreter pathname */
4e81a331
RS
1578 strings_command_t str; /* load commands strings section */
1579 region_command_t region; /* region load command */
1580 reloc_command_t reloc; /* relocation section */
1581 package_command_t pkg; /* package load command */
1582 symbols_command_t sym; /* symbol sections */
1583 entry_command_t ent; /* program start section */
1584 gen_info_command_t info; /* object information */
1585 func_table_command_t func; /* function constructors/destructors */
1586} load_union_t;
1587
1588/* Structure to point to load command and data section in memory. */
1589
1590typedef struct load_all
1591{
1592 load_union_t *load; /* load command */
1593 char *section; /* pointer to section */
1594} load_all_t;
1595
1596/* Structure to contain information about a file mapped into memory. */
1597
1598struct file_info
1599{
1600 char *start; /* start of map */
1601 char *name; /* filename */
1602 long size; /* size of the file */
1603 long rounded_size; /* size rounded to page boundary */
1604 int fd; /* file descriptor */
1605 int rw; /* != 0 if opened read/write */
1606 int use_mmap; /* != 0 if mmap'ed */
1607};
1608
ed5b9462 1609extern int decode_mach_o_hdr ();
4e81a331 1610
ed5b9462 1611extern int encode_mach_o_hdr ();
4e81a331 1612
ed5b9462 1613static void bad_header ();
4e81a331 1614
ed5b9462 1615static void print_header ();
4e81a331 1616
ed5b9462 1617static void print_load_command ();
4e81a331 1618
ed5b9462 1619static void add_func_table ();
4e81a331 1620
ed5b9462 1621static struct file_info *read_file ();
4e81a331 1622
ed5b9462 1623static void end_file ();
4e81a331
RS
1624
1625\f
1626/* OSF/rose specific version to scan the name list of the loaded
1627 program for the symbols g++ uses for static constructors and
1628 destructors.
1629
1630 The constructor table begins at __CTOR_LIST__ and contains a count
1631 of the number of pointers (or -1 if the constructors are built in a
1632 separate section by the linker), followed by the pointers to the
1633 constructor functions, terminated with a null pointer. The
1634 destructor table has the same format, and begins at __DTOR_LIST__. */
1635
1636static void
1637scan_prog_file (prog_name, which_pass)
1638 char *prog_name;
1639 enum pass which_pass;
1640{
1641 char *obj;
1642 mo_header_t hdr;
1643 load_all_t *load_array;
1644 load_all_t *load_end;
1645 load_all_t *load_cmd;
1646 int symbol_load_cmds;
1647 off_t offset;
1648 int i;
1649 int num_syms;
1650 int status;
1651 char *str_sect;
1652 struct file_info *obj_file;
1653 int prog_fd;
1654 mo_lcid_t cmd_strings = -1;
1655 symbol_info_t *main_sym = 0;
1656 int rw = (which_pass != PASS_FIRST);
1657
1658 prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY);
1659 if (prog_fd < 0)
1fab8e81 1660 fatal_perror ("can't read %s", prog_name);
4e81a331
RS
1661
1662 obj_file = read_file (prog_name, prog_fd, rw);
1663 obj = obj_file->start;
1664
1665 status = decode_mach_o_hdr (obj, MO_SIZEOF_RAW_HDR, MOH_HEADER_VERSION, &hdr);
1666 if (status != MO_HDR_CONV_SUCCESS)
1667 bad_header (status);
1668
1669
1670 /* Do some basic sanity checks. Note we explicitly use the big endian magic number,
1671 since the hardware will automatically swap bytes for us on loading little endian
1672 integers. */
1673
1674#ifndef CROSS_COMPILE
1675 if (hdr.moh_magic != MOH_MAGIC_MSB
1676 || hdr.moh_header_version != MOH_HEADER_VERSION
1677 || hdr.moh_byte_order != OUR_BYTE_ORDER
1678 || hdr.moh_data_rep_id != OUR_DATA_REP_ID
1679 || hdr.moh_cpu_type != OUR_CPU_TYPE
1680 || hdr.moh_cpu_subtype != OUR_CPU_SUBTYPE
1681 || hdr.moh_vendor_type != OUR_VENDOR_TYPE)
1682 {
1fab8e81 1683 fatal ("incompatibilities between object file & expected values");
4e81a331
RS
1684 }
1685#endif
1686
1687 if (debug)
1688 print_header (&hdr);
1689
1690 offset = hdr.moh_first_cmd_off;
1691 load_end = load_array
1692 = (load_all_t *) xcalloc (sizeof (load_all_t), hdr.moh_n_load_cmds + 2);
1693
1694 /* Build array of load commands, calculating the offsets */
1695 for (i = 0; i < hdr.moh_n_load_cmds; i++)
1696 {
1697 load_union_t *load_hdr; /* load command header */
1698
1699 load_cmd = load_end++;
1700 load_hdr = (load_union_t *) (obj + offset);
1701
f72aed24 1702 /* If modifying the program file, copy the header. */
4e81a331
RS
1703 if (rw)
1704 {
1705 load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size);
7c0891a1 1706 bcopy ((generic *)load_hdr, (generic *)ptr, load_hdr->hdr.ldci_cmd_size);
4e81a331
RS
1707 load_hdr = ptr;
1708
1709 /* null out old command map, because we will rewrite at the end. */
1710 if (ptr->hdr.ldci_cmd_type == LDC_CMD_MAP)
1711 {
1712 cmd_strings = ptr->map.lcm_ld_cmd_strings;
1713 ptr->hdr.ldci_cmd_type = LDC_UNDEFINED;
1714 }
1715 }
1716
1717 load_cmd->load = load_hdr;
1718 if (load_hdr->hdr.ldci_section_off > 0)
1719 load_cmd->section = obj + load_hdr->hdr.ldci_section_off;
1720
1721 if (debug)
1722 print_load_command (load_hdr, offset, i);
1723
1724 offset += load_hdr->hdr.ldci_cmd_size;
1725 }
1726
1727 /* If the last command is the load command map and is not undefined,
1728 decrement the count of load commands. */
1729 if (rw && load_end[-1].load->hdr.ldci_cmd_type == LDC_UNDEFINED)
1730 {
1731 load_end--;
1732 hdr.moh_n_load_cmds--;
1733 }
1734
1735 /* Go through and process each symbol table section. */
1736 symbol_load_cmds = 0;
1737 for (load_cmd = load_array; load_cmd < load_end; load_cmd++)
1738 {
1739 load_union_t *load_hdr = load_cmd->load;
1740
1741 if (load_hdr->hdr.ldci_cmd_type == LDC_SYMBOLS)
1742 {
1743 symbol_load_cmds++;
1744
1745 if (debug)
1746 {
ed5b9462 1747 char *kind = "unknown";
4e81a331
RS
1748
1749 switch (load_hdr->sym.symc_kind)
1750 {
1751 case SYMC_IMPORTS: kind = "imports"; break;
1752 case SYMC_DEFINED_SYMBOLS: kind = "defined"; break;
1753 case SYMC_STABS: kind = "stabs"; break;
1754 }
1755
1756 fprintf (stderr, "\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
1757 symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
1758 }
1759
1760 if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
1761 continue;
1762
ed5b9462 1763 str_sect = load_array[load_hdr->sym.symc_strings_section].section;
4e81a331
RS
1764 if (str_sect == (char *)0)
1765 fatal ("string section missing");
1766
1767 if (load_cmd->section == (char *)0)
1768 fatal ("section pointer missing");
1769
1770 num_syms = load_hdr->sym.symc_nentries;
1771 for (i = 0; i < num_syms; i++)
1772 {
1773 symbol_info_t *sym = ((symbol_info_t *) load_cmd->section) + i;
1774 char *name = sym->si_name.symbol_name + str_sect;
4e81a331
RS
1775
1776 if (name[0] != '_')
1777 continue;
1778
4e81a331
RS
1779 if (rw)
1780 {
ed5b9462
RS
1781 char *n = name;
1782 while (*n == '_')
1783 ++n;
1784 if (*n != 'm' || (n - name) < 2 || strcmp (n, "main"))
4e81a331
RS
1785 continue;
1786
1787 main_sym = sym;
1788 }
ed5b9462 1789 else
4e81a331 1790 {
ed5b9462
RS
1791 switch (is_ctor_dtor (name))
1792 {
1793 case 1:
1794 add_to_list (&constructors, name);
1795 break;
1796
1797 case 2:
1798 add_to_list (&destructors, name);
1799 break;
1800
1801 default: /* not a constructor or destructor */
1802 continue;
1803 }
4e81a331
RS
1804 }
1805
4e81a331
RS
1806 if (debug)
1807 fprintf (stderr, "\ttype = 0x%.4x, sc = 0x%.2x, flags = 0x%.8x, name = %.30s\n",
1808 sym->si_type, sym->si_sc_type, sym->si_flags, name);
1809 }
1810 }
1811 }
1812
1813 if (symbol_load_cmds == 0)
1fab8e81 1814 fatal ("no symbol table found");
4e81a331
RS
1815
1816 /* Update the program file now, rewrite header and load commands. At present,
1817 we assume that there is enough space after the last load command to insert
1818 one more. Since the first section written out is page aligned, and the
1819 number of load commands is small, this is ok for the present. */
1820
1821 if (rw)
1822 {
1823 load_union_t *load_map;
1824 size_t size;
1825
1826 if (cmd_strings == -1)
1fab8e81
RS
1827 fatal ("no cmd_strings found");
1828
1829 /* Add __main to initializer list.
1830 If we are building a program instead of a shared library, don't
1831 do anything, since in the current version, you cannot do mallocs
1832 and such in the constructors. */
4e81a331 1833
1fab8e81
RS
1834 if (main_sym != (symbol_info_t *)0
1835 && ((hdr.moh_flags & MOH_EXECABLE_F) == 0))
4e81a331
RS
1836 add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION);
1837
1838 if (debug)
1839 fprintf (stderr, "\nUpdating header and load commands.\n\n");
1840
1841 hdr.moh_n_load_cmds++;
1842 size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1));
1843
1844 /* Create new load command map. */
1845 if (debug)
1846 fprintf (stderr, "load command map, %d cmds, new size %ld.\n",
1847 (int)hdr.moh_n_load_cmds, (long)size);
1848
1849 load_map = (load_union_t *) xcalloc (1, size);
1850 load_map->map.ldc_header.ldci_cmd_type = LDC_CMD_MAP;
1851 load_map->map.ldc_header.ldci_cmd_size = size;
1852 load_map->map.lcm_ld_cmd_strings = cmd_strings;
1853 load_map->map.lcm_nentries = hdr.moh_n_load_cmds;
1854 load_array[hdr.moh_n_load_cmds-1].load = load_map;
1855
1856 offset = hdr.moh_first_cmd_off;
1857 for (i = 0; i < hdr.moh_n_load_cmds; i++)
1858 {
1859 load_map->map.lcm_map[i] = offset;
1860 if (load_array[i].load->hdr.ldci_cmd_type == LDC_CMD_MAP)
1861 hdr.moh_load_map_cmd_off = offset;
1862
1863 offset += load_array[i].load->hdr.ldci_cmd_size;
1864 }
1865
1866 hdr.moh_sizeofcmds = offset - MO_SIZEOF_RAW_HDR;
1867
1868 if (debug)
1869 print_header (&hdr);
1870
1871 /* Write header */
1872 status = encode_mach_o_hdr (&hdr, obj, MO_SIZEOF_RAW_HDR);
1873 if (status != MO_HDR_CONV_SUCCESS)
1874 bad_header (status);
1875
1876 if (debug)
1877 fprintf (stderr, "writing load commands.\n\n");
1878
1879 /* Write load commands */
1880 offset = hdr.moh_first_cmd_off;
1881 for (i = 0; i < hdr.moh_n_load_cmds; i++)
1882 {
1883 load_union_t *load_hdr = load_array[i].load;
1884 size_t size = load_hdr->hdr.ldci_cmd_size;
1885
1886 if (debug)
1887 print_load_command (load_hdr, offset, i);
1888
7c0891a1 1889 bcopy ((generic *)load_hdr, (generic *)(obj + offset), size);
4e81a331
RS
1890 offset += size;
1891 }
1892 }
1893
1894 end_file (obj_file);
1895
1896 if (close (prog_fd))
1fab8e81 1897 fatal_perror ("closing %s", prog_name);
4e81a331
RS
1898
1899 if (debug)
1900 fprintf (stderr, "\n");
1901}
1902
1903\f
1904/* Add a function table to the load commands to call a function
ed5b9462 1905 on initiation or termination of the process. */
4e81a331
RS
1906
1907static void
1908add_func_table (hdr_p, load_array, sym, type)
1909 mo_header_t *hdr_p; /* pointer to global header */
1910 load_all_t *load_array; /* array of ptrs to load cmds */
1911 symbol_info_t *sym; /* pointer to symbol entry */
1912 int type; /* fntc_type value */
1913{
1914 /* Add a new load command. */
1915 int num_cmds = ++hdr_p->moh_n_load_cmds;
1916 int load_index = num_cmds - 1;
1917 size_t size = sizeof (func_table_command_t) + sizeof (mo_addr_t);
1918 load_union_t *ptr = xcalloc (1, size);
1919 load_all_t *load_cmd;
1920 int i;
1921
1922 /* Set the unresolved address bit in the header to force the loader to be
1923 used, since kernel exec does not call the initialization functions. */
1924 hdr_p->moh_flags |= MOH_UNRESOLVED_F;
1925
1926 load_cmd = &load_array[load_index];
1927 load_cmd->load = ptr;
1928 load_cmd->section = (char *)0;
1929
1930 /* Fill in func table load command. */
1931 ptr->func.ldc_header.ldci_cmd_type = LDC_FUNC_TABLE;
1932 ptr->func.ldc_header.ldci_cmd_size = size;
1933 ptr->func.ldc_header.ldci_section_off = 0;
1934 ptr->func.ldc_header.ldci_section_len = 0;
1935 ptr->func.fntc_type = type;
1936 ptr->func.fntc_nentries = 1;
1937
1938 /* copy address, turn it from abs. address to (region,offset) if necessary. */
1939 /* Is the symbol already expressed as (region, offset)? */
1940 if ((sym->si_flags & SI_ABSOLUTE_VALUE_F) == 0)
1941 {
1942 ptr->func.fntc_entry_loc[i].adr_lcid = sym->si_value.def_val.adr_lcid;
1943 ptr->func.fntc_entry_loc[i].adr_sctoff = sym->si_value.def_val.adr_sctoff;
1944 }
1945
1946 /* If not, figure out which region it's in. */
1947 else
1948 {
1949 mo_vm_addr_t addr = sym->si_value.abs_val;
1950 int found = 0;
1951
1952 for (i = 0; i < load_index; i++)
1953 {
1954 if (load_array[i].load->hdr.ldci_cmd_type == LDC_REGION)
1955 {
1956 region_command_t *region_ptr = &load_array[i].load->region;
1957
1958 if ((region_ptr->regc_flags & REG_ABS_ADDR_F) != 0
1959 && addr >= region_ptr->regc_addr.vm_addr
1960 && addr <= region_ptr->regc_addr.vm_addr + region_ptr->regc_vm_size)
1961 {
1962 ptr->func.fntc_entry_loc[0].adr_lcid = i;
1963 ptr->func.fntc_entry_loc[0].adr_sctoff = addr - region_ptr->regc_addr.vm_addr;
1964 found++;
1965 break;
1966 }
1967 }
1968 }
1969
1970 if (!found)
1971 fatal ("could not convert 0x%l.8x into a region", addr);
1972 }
1973
1974 if (debug)
1975 fprintf (stderr,
1976 "%s function, region %d, offset = %ld (0x%.8lx)\n",
1977 (type == FNTC_INITIALIZATION) ? "init" : "term",
1978 (int)ptr->func.fntc_entry_loc[i].adr_lcid,
1979 (long)ptr->func.fntc_entry_loc[i].adr_sctoff,
1980 (long)ptr->func.fntc_entry_loc[i].adr_sctoff);
1981
1982}
1983
1984\f
1985/* Print the global header for an OSF/rose object. */
1986
1987static void
1988print_header (hdr_ptr)
1989 mo_header_t *hdr_ptr;
1990{
1991 fprintf (stderr, "\nglobal header:\n");
1992 fprintf (stderr, "\tmoh_magic = 0x%.8lx\n", hdr_ptr->moh_magic);
1993 fprintf (stderr, "\tmoh_major_version = %d\n", (int)hdr_ptr->moh_major_version);
1994 fprintf (stderr, "\tmoh_minor_version = %d\n", (int)hdr_ptr->moh_minor_version);
1995 fprintf (stderr, "\tmoh_header_version = %d\n", (int)hdr_ptr->moh_header_version);
1996 fprintf (stderr, "\tmoh_max_page_size = %d\n", (int)hdr_ptr->moh_max_page_size);
1997 fprintf (stderr, "\tmoh_byte_order = %d\n", (int)hdr_ptr->moh_byte_order);
1998 fprintf (stderr, "\tmoh_data_rep_id = %d\n", (int)hdr_ptr->moh_data_rep_id);
1999 fprintf (stderr, "\tmoh_cpu_type = %d\n", (int)hdr_ptr->moh_cpu_type);
2000 fprintf (stderr, "\tmoh_cpu_subtype = %d\n", (int)hdr_ptr->moh_cpu_subtype);
2001 fprintf (stderr, "\tmoh_vendor_type = %d\n", (int)hdr_ptr->moh_vendor_type);
2002 fprintf (stderr, "\tmoh_load_map_cmd_off = %d\n", (int)hdr_ptr->moh_load_map_cmd_off);
2003 fprintf (stderr, "\tmoh_first_cmd_off = %d\n", (int)hdr_ptr->moh_first_cmd_off);
2004 fprintf (stderr, "\tmoh_sizeofcmds = %d\n", (int)hdr_ptr->moh_sizeofcmds);
2005 fprintf (stderr, "\tmon_n_load_cmds = %d\n", (int)hdr_ptr->moh_n_load_cmds);
2006 fprintf (stderr, "\tmoh_flags = 0x%.8lx", (long)hdr_ptr->moh_flags);
2007
2008 if (hdr_ptr->moh_flags & MOH_RELOCATABLE_F)
2009 fprintf (stderr, ", relocatable");
2010
2011 if (hdr_ptr->moh_flags & MOH_LINKABLE_F)
2012 fprintf (stderr, ", linkable");
2013
2014 if (hdr_ptr->moh_flags & MOH_EXECABLE_F)
2015 fprintf (stderr, ", execable");
2016
2017 if (hdr_ptr->moh_flags & MOH_EXECUTABLE_F)
2018 fprintf (stderr, ", executable");
2019
2020 if (hdr_ptr->moh_flags & MOH_UNRESOLVED_F)
2021 fprintf (stderr, ", unresolved");
2022
2023 fprintf (stderr, "\n\n");
2024 return;
2025}
2026
2027\f
2028/* Print a short summary of a load command. */
2029
2030static void
2031print_load_command (load_hdr, offset, number)
2032 load_union_t *load_hdr;
2033 size_t offset;
2034 int number;
2035{
2036 mo_long_t type = load_hdr->hdr.ldci_cmd_type;
2037 char *type_str = (char *)0;
2038
2039 switch (type)
2040 {
2041 case LDC_UNDEFINED: type_str = "UNDEFINED"; break;
2042 case LDC_CMD_MAP: type_str = "CMD_MAP"; break;
2043 case LDC_INTERPRETER: type_str = "INTERPRETER"; break;
2044 case LDC_STRINGS: type_str = "STRINGS"; break;
2045 case LDC_REGION: type_str = "REGION"; break;
2046 case LDC_RELOC: type_str = "RELOC"; break;
2047 case LDC_PACKAGE: type_str = "PACKAGE"; break;
2048 case LDC_SYMBOLS: type_str = "SYMBOLS"; break;
2049 case LDC_ENTRY: type_str = "ENTRY"; break;
2050 case LDC_FUNC_TABLE: type_str = "FUNC_TABLE"; break;
2051 case LDC_GEN_INFO: type_str = "GEN_INFO"; break;
2052 }
2053
2054 fprintf (stderr,
2055 "cmd %2d, sz: 0x%.2lx, coff: 0x%.3lx, doff: 0x%.6lx, dlen: 0x%.6lx",
2056 number,
2057 (long) load_hdr->hdr.ldci_cmd_size,
2058 (long) offset,
2059 (long) load_hdr->hdr.ldci_section_off,
2060 (long) load_hdr->hdr.ldci_section_len);
2061
2062 if (type_str == (char *)0)
2063 fprintf (stderr, ", ty: unknown (%ld)\n", (long) type);
2064
2065 else if (type != LDC_REGION)
2066 fprintf (stderr, ", ty: %s\n", type_str);
2067
2068 else
2069 {
2070 char *region = "";
2071 switch (load_hdr->region.regc_usage_type)
2072 {
2073 case REG_TEXT_T: region = ", .text"; break;
2074 case REG_DATA_T: region = ", .data"; break;
2075 case REG_BSS_T: region = ", .bss"; break;
2076 case REG_GLUE_T: region = ", .glue"; break;
2077#if defined (REG_RDATA_T) && defined (REG_SDATA_T) && defined (REG_SBSS_T) /*mips*/
2078 case REG_RDATA_T: region = ", .rdata"; break;
2079 case REG_SDATA_T: region = ", .sdata"; break;
2080 case REG_SBSS_T: region = ", .sbss"; break;
2081#endif
2082 }
2083
2084 fprintf (stderr, ", ty: %s, vaddr: 0x%.8lx, vlen: 0x%.6lx%s\n",
2085 type_str,
2086 (long) load_hdr->region.regc_vm_addr,
2087 (long) load_hdr->region.regc_vm_size,
2088 region);
2089 }
2090
2091 return;
2092}
2093
2094\f
2095/* Fatal error when {en,de}code_mach_o_header fails. */
2096
2097static void
2098bad_header (status)
2099 int status;
2100{
2101 char *msg = (char *)0;
2102
2103 switch (status)
2104 {
2105 case MO_ERROR_BAD_MAGIC: msg = "bad magic number"; break;
2106 case MO_ERROR_BAD_HDR_VERS: msg = "bad header version"; break;
2107 case MO_ERROR_BAD_RAW_HDR_VERS: msg = "bad raw header version"; break;
2108 case MO_ERROR_BUF2SML: msg = "raw header buffer too small"; break;
2109 case MO_ERROR_OLD_RAW_HDR_FILE: msg = "old raw header file"; break;
2110 case MO_ERROR_UNSUPPORTED_VERS: msg = "unsupported version"; break;
2111 }
2112
2113 if (msg == (char *)0)
2114 fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
2115 else
2116 fatal ("%s", msg);
2117}
2118
2119\f
2120/* Read a file into a memory buffer. */
2121
2122static struct file_info *
2123read_file (name, fd, rw)
2124 char *name; /* filename */
2125 int fd; /* file descriptor */
2126 int rw; /* read/write */
2127{
2128 struct stat stat_pkt;
2129 struct file_info *p = (struct file_info *) xcalloc (sizeof (struct file_info), 1);
2130#ifdef USE_MMAP
2131 static int page_size;
2132#endif
2133
2134 if (fstat (fd, &stat_pkt) < 0)
2135 fatal_perror ("fstat %s", name);
2136
2137 p->name = name;
2138 p->size = stat_pkt.st_size;
2139 p->rounded_size = stat_pkt.st_size;
2140 p->fd = fd;
2141 p->rw = rw;
2142
2143#ifdef USE_MMAP
2144 if (debug)
2145 fprintf (stderr, "mmap %s, %s\n", name, (rw) ? "read/write" : "read-only");
2146
2147 if (page_size == 0)
2148 page_size = sysconf (_SC_PAGE_SIZE);
2149
2150 p->rounded_size = ((p->size + page_size - 1) / page_size) * page_size;
2151 p->start = mmap ((caddr_t)0,
2152 (rw) ? p->rounded_size : p->size,
2153 (rw) ? (PROT_READ | PROT_WRITE) : PROT_READ,
2154 MAP_FILE | MAP_VARIABLE | MAP_SHARED,
2155 fd,
2156 0L);
2157
2158 if (p->start != (char *)0 && p->start != (char *)-1)
2159 p->use_mmap = 1;
2160
2161 else
2162#endif /* USE_MMAP */
2163 {
2164 long len;
2165
2166 if (debug)
2167 fprintf (stderr, "read %s\n", name);
2168
2169 p->use_mmap = 0;
2170 p->start = xmalloc (p->size);
2171 if (lseek (fd, 0L, SEEK_SET) < 0)
2172 fatal_perror ("lseek to 0 on %s", name);
2173
2174 len = read (fd, p->start, p->size);
2175 if (len < 0)
2176 fatal_perror ("read %s", name);
2177
2178 if (len != p->size)
2179 fatal ("read %ld bytes, expected %ld, from %s", len, p->size, name);
2180 }
2181
2182 return p;
2183}
2184
2185\f
2186/* Do anything necessary to write a file back from memory. */
2187
2188static void
2189end_file (ptr)
2190 struct file_info *ptr; /* file information block */
2191{
2192#ifdef USE_MMAP
2193 if (ptr->use_mmap)
2194 {
2195 if (ptr->rw)
2196 {
2197 if (debug)
2198 fprintf (stderr, "msync %s\n", ptr->name);
2199
2200 if (msync (ptr->start, ptr->rounded_size, MS_ASYNC))
2201 fatal_perror ("msync %s", ptr->name);
2202 }
2203
2204 if (debug)
2205 fprintf (stderr, "munmap %s\n", ptr->name);
2206
2207 if (munmap (ptr->start, ptr->size))
2208 fatal_perror ("munmap %s", ptr->name);
2209 }
2210 else
2211#endif /* USE_MMAP */
2212 {
2213 if (ptr->rw)
2214 {
2215 long len;
2216
2217 if (debug)
2218 fprintf (stderr, "write %s\n", ptr->name);
2219
2220 if (lseek (ptr->fd, 0L, SEEK_SET) < 0)
2221 fatal_perror ("lseek to 0 on %s", ptr->name);
2222
2223 len = write (ptr->fd, ptr->start, ptr->size);
2224 if (len < 0)
2225 fatal_perror ("read %s", ptr->name);
2226
2227 if (len != ptr->size)
2228 fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name);
2229 }
2230
2231 free ((generic *)ptr->start);
2232 }
2233
2234 free ((generic *)ptr);
2235}
2236
2237#endif /* OBJECT_FORMAT_ROSE */
This page took 0.320036 seconds and 5 git commands to generate.