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