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