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