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