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