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