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