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