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