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