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