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