]> gcc.gnu.org Git - gcc.git/blob - gcc/collect2.c
5915cf079bbd46fd544a7303805121ad38fc330c
[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 <ctype.h>
32 #include <errno.h>
33 #include <signal.h>
34 #include <sys/file.h>
35 #include <sys/stat.h>
36 #ifdef NO_WAIT_H
37 #include <sys/wait.h>
38 #endif
39
40 #ifndef errno
41 extern int errno;
42 #endif
43
44 #define COLLECT
45
46 #include "config.h"
47
48 #ifndef __STDC__
49 #define generic char
50 #define const
51
52 #else
53 #define generic void
54 #endif
55
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
113 /* Mips-news overrides this macro. */
114 #ifndef MY_ISCOFF
115 #define MY_ISCOFF(X) ISCOFF (X)
116 #endif
117
118 #endif /* OBJECT_FORMAT_COFF */
119
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>
135
136 #endif /* OBJECT_FORMAT_ROSE */
137
138 #ifdef OBJECT_FORMAT_NONE
139
140 /* Default flags to pass to nm. */
141 #ifndef NM_FLAGS
142 #define NM_FLAGS "-p"
143 #endif
144
145 #endif /* OBJECT_FORMAT_NONE */
146 \f
147 /* Linked lists of constructor and destructor names. */
148
149 struct id
150 {
151 struct id *next;
152 int sequence;
153 char name[1];
154 };
155
156 struct 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
165 enum pass {
166 PASS_FIRST, /* without constructors */
167 PASS_SECOND /* with constructors linked in */
168 };
169
170 #ifndef NO_SYS_SIGLIST
171 extern char *sys_siglist[];
172 #endif
173 extern char *version_string;
174
175 static int vflag; /* true if -v */
176 static int rflag; /* true if -r */
177 static int strip_flag; /* true if -s */
178
179 static int debug; /* true if -debug */
180
181 static int temp_filename_length; /* Length of temp_filename */
182 static char *temp_filename; /* Base of temp filenames */
183 static char *c_file; /* <xxx>.c for constructor/destructor list. */
184 static char *o_file; /* <xxx>.o for constructor/destructor list. */
185 static char *nm_file_name; /* pathname of nm */
186 static char *strip_file_name; /* pathname of strip */
187
188 static struct head constructors; /* list of constructors found */
189 static struct head destructors; /* list of destructors found */
190
191 extern char *getenv ();
192 extern char *mktemp ();
193 static void add_to_list ();
194 static void scan_prog_file ();
195 static void fork_execute ();
196 static void do_wait ();
197 static void write_c_file ();
198 static void my_exit ();
199 static void handler ();
200 static void maybe_unlink ();
201 static void choose_temp_base ();
202
203 generic *xcalloc ();
204 generic *xmalloc ();
205
206 extern char *index ();
207 extern char *rindex ();
208 \f
209 char *
210 my_strerror (e)
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 }
226 \f
227 /* Delete tempfiles and exit function. */
228
229 static void
230 my_exit (status)
231 int status;
232 {
233 if (c_file != 0 && c_file[0])
234 maybe_unlink (c_file);
235
236 if (o_file != 0 && o_file[0])
237 maybe_unlink (o_file);
238
239 exit (status);
240 }
241
242 \f
243 /* Die when sys call fails. */
244
245 static void
246 fatal_perror (string, arg1, arg2, arg3)
247 char *string;
248 {
249 int e = errno;
250
251 fprintf (stderr, "collect: ");
252 fprintf (stderr, string, arg1, arg2, arg3);
253 fprintf (stderr, ": %s\n", my_strerror (e));
254 my_exit (1);
255 }
256
257 /* Just die. */
258
259 static void
260 fatal (string, arg1, arg2, arg3)
261 char *string;
262 {
263 fprintf (stderr, "collect: ");
264 fprintf (stderr, string, arg1, arg2, arg3);
265 fprintf (stderr, "\n");
266 my_exit (1);
267 }
268
269 /* Write error message. */
270
271 static void
272 error (string, arg1, arg2, arg3, arg4)
273 char *string;
274 {
275 fprintf (stderr, "collect: ");
276 fprintf (stderr, string, arg1, arg2, arg3, arg4);
277 fprintf (stderr, "\n");
278 }
279
280 /* In case obstack is linked in, and abort is defined to fancy_abort,
281 provide a default entry. */
282
283 void
284 fancy_abort ()
285 {
286 fatal ("internal error");
287 }
288
289 \f
290 static void
291 handler (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);
301 kill (getpid (), signo);
302 }
303
304 \f
305 generic *
306 xcalloc (size1, size2)
307 int size1, size2;
308 {
309 generic *ptr = (generic *) calloc (size1, size2);
310 if (ptr)
311 return ptr;
312
313 fatal ("out of memory");
314 return (generic *)0;
315 }
316
317 generic *
318 xmalloc (size)
319 int size;
320 {
321 generic *ptr = (generic *) malloc (size);
322 if (ptr)
323 return ptr;
324
325 fatal ("out of memory");
326 return (generic *)0;
327 }
328
329 /* Make a copy of a string INPUT with size SIZE. */
330
331 char *
332 savestring (input, size)
333 char *input;
334 int size;
335 {
336 char *output = (char *) xmalloc (size + 1);
337 bcopy (input, output, size);
338 output[size] = 0;
339 return output;
340 }
341 \f
342 /* Decide whether the given symbol is:
343 a constructor (1), a destructor (2), or neither (0). */
344
345 static int
346 is_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
386 \f
387 /* Compute a string to use as the base of all temporary file names.
388 It is substituted for %g. */
389
390 static void
391 choose_temp_base ()
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
425 int
426 main (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;
435 char *p;
436 char *prefix;
437 char **c_argv;
438 char **c_ptr;
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;
444 int num_c_args = argc+7;
445 int len;
446 int clen;
447
448 #ifdef DEBUG
449 debug = 1;
450 vflag = 1;
451 #endif
452
453 p = (char *) getenv ("COLLECT_GCC_OPTIONS");
454 if (p)
455 while (*p)
456 {
457 char *q = p;
458 while (*q && *q != ' ') q++;
459 if (*p == '-' && p[1] == 'm')
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
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
478 /* Try to discover a valid linker/assembler/nm/strip to use. */
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 {
493 p = rindex (argv[0], '/');
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
527 #ifdef STANDARD_EXEC_PREFIX
528 if (clen < sizeof (STANDARD_EXEC_PREFIX) - 1)
529 clen = sizeof (STANDARD_EXEC_PREFIX) - 1;
530 #endif
531
532 /* Allocate enough string space for the longest possible pathnames. */
533 ld_file_name = xcalloc (len + sizeof ("real-ld"), 1);
534 nm_file_name = xcalloc (len + sizeof ("gnm"), 1);
535 strip_file_name = xcalloc (len + sizeof ("gstrip"), 1);
536
537 /* Determine the full path name of the ld program to use. */
538 bcopy (prefix, ld_file_name, len);
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
549 ld_file_name = (access ("/usr/bin/ld", X_OK) == 0
550 ? "/usr/bin/ld" : "/bin/ld");
551 #endif
552 }
553 }
554
555 /* Determine the full path name of the C compiler to use. */
556 c_file_name = getenv ("COLLECT_GCC");
557 if (c_file_name == 0 || c_file_name[0] != '/')
558 {
559 c_file_name = xcalloc (clen + sizeof ("gcc"), 1);
560 bcopy (prefix, c_file_name, len);
561 strcpy (c_file_name + len, "gcc");
562 if (access (c_file_name, X_OK) < 0)
563 {
564 #ifdef STANDARD_BIN_PREFIX
565 strcpy (c_file_name, STANDARD_BIN_PREFIX);
566 strcat (c_file_name, "gcc");
567 if (access (c_file_name, X_OK) < 0)
568 #endif
569 {
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 }
578 }
579 }
580 }
581
582 /* Determine the full path name of the nm to use. */
583 bcopy (prefix, nm_file_name, len);
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
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. */
601 bcopy (prefix, strip_file_name, len);
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");
614 #endif
615 }
616 }
617
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);
626 *c_ptr++ = c_file_name;
627 *c_ptr++ = "-c";
628 *c_ptr++ = "-o";
629 *c_ptr++ = o_file;
630
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
638 /* Parse arguments. Remember output file spec, pass the rest to ld. */
639 /* After the first file, put in the c++ rt0. */
640
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
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
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
679 case 'v':
680 if (arg[2] == '\0')
681 vflag = 1;
682 break;
683 }
684
685 else if (first_file
686 && (p = rindex (arg, '.')) != (char *)0
687 && strcmp (p, ".o") == 0)
688 {
689 first_file = 0;
690 *ld2++ = o_file;
691 }
692 }
693
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
708 *c_ptr++ = c_file;
709 *c_ptr = *ld1 = *ld2 = (char *)0;
710
711 if (vflag)
712 {
713 fprintf (stderr, "collect2 version %s", version_string);
714 #ifdef TARGET_VERSION
715 TARGET_VERSION;
716 #endif
717 fprintf (stderr, "\n");
718 }
719
720 if (debug)
721 {
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");
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)
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 }
781
782 outf = fopen (c_file, "w");
783 if (outf == (FILE *)0)
784 fatal_perror ("%s", c_file);
785
786 write_c_file (outf, c_file);
787
788 if (fclose (outf))
789 fatal_perror ("closing %s", c_file);
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
816 static void
817 do_wait (prog)
818 char *prog;
819 {
820 int status;
821
822 wait (&status);
823 if (status)
824 {
825 int sig = status & 0x7F;
826 int ret;
827
828 if (sig != -1 && sig != 0)
829 {
830 #ifdef NO_SYS_SIGLIST
831 error ("%s terminated with signal %d %s",
832 prog,
833 sig,
834 (status & 0200) ? ", core dumped" : "");
835 #else
836 error ("%s terminated with signal %d [%s]%s",
837 prog,
838 sig,
839 sys_siglist[sig],
840 (status & 0200) ? ", core dumped" : "");
841 #endif
842
843 my_exit (127);
844 }
845
846 ret = ((status & 0xFF00) >> 8);
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
858 static void
859 fork_execute (prog, argv)
860 char *prog;
861 char **argv;
862 {
863 int pid;
864 void (*int_handler) ();
865 void (*quit_handler) ();
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);
889 fatal_perror ("executing %s", prog);
890 }
891
892 int_handler = (void (*) ())signal (SIGINT, SIG_IGN);
893 quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN);
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
904 static void
905 maybe_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
917 static void
918 add_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
938 static void
939 write_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
951 static void
952 write_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
967 static void
968 write_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
976 write_list_with_asm (stream, "extern entry_pt ", constructors.first);
977
978 fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
979 fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number);
980 write_list (stream, "\t", constructors.first);
981 fprintf (stream, "\t0\n};\n\n");
982
983 write_list_with_asm (stream, "extern entry_pt ", destructors.first);
984
985 fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
986 fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number);
987 write_list (stream, "\t", destructors.first);
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
995 #ifdef OBJECT_FORMAT_NONE
996
997 /* Generic version to scan the name list of the loaded program for
998 the symbols g++ uses for static constructors and destructors.
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
1006 static void
1007 scan_prog_file (prog_name, which_pass)
1008 char *prog_name;
1009 enum pass which_pass;
1010 {
1011 void (*int_handler) ();
1012 void (*quit_handler) ();
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
1023 nm_argv[argc++] = "nm";
1024 if (NM_FLAGS[0] != '\0')
1025 nm_argv[argc++] = NM_FLAGS;
1026
1027 nm_argv[argc++] = prog_name;
1028 nm_argv[argc++] = (char *)0;
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)
1062 fatal_perror ("dup2 (%d, 1)", pipe_fd[1]);
1063
1064 if (close (pipe_fd[0]) < 0)
1065 fatal_perror ("close (%d)", pipe_fd[0]);
1066
1067 if (close (pipe_fd[1]) < 0)
1068 fatal_perror ("close (%d)", pipe_fd[1]);
1069
1070 execv (nm_file_name, nm_argv);
1071 fatal_perror ("executing %s", nm_file_name);
1072 }
1073
1074 /* Parent context from here on. */
1075 int_handler = (void (*) ())signal (SIGINT, SIG_IGN);
1076 quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN);
1077
1078 if (close (pipe_fd[1]) < 0)
1079 fatal_perror ("close (%d)", pipe_fd[1]);
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;
1088 char *name, *end;
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;
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;
1105
1106 *end = '\0';
1107 switch (is_ctor_dtor (name))
1108 {
1109 case 1:
1110 add_to_list (&constructors, name);
1111 break;
1112
1113 case 2:
1114 add_to_list (&destructors, name);
1115 break;
1116
1117 default: /* not a constructor or destructor */
1118 continue;
1119 }
1120
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
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)
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)
1153 #else
1154 # define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms)
1155 # define GCC_SYMENT SYMENT
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)))
1160 # define GCC_SYMINC(X) ((X).n_numaux+1)
1161 # define GCC_SYMZERO(X) 0
1162 # define GCC_CHECK_HDR(X) (1)
1163 #endif
1164
1165 extern 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
1176 static void
1177 scan_prog_file (prog_name, which_pass)
1178 char *prog_name;
1179 enum pass which_pass;
1180 {
1181 LDFILE *ldptr = NULL;
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
1190 if (!MY_ISCOFF (HEADER (ldptr).f_magic))
1191 fatal ("%s: not a COFF file", prog_name);
1192
1193 if (GCC_CHECK_HDR (ldptr))
1194 {
1195 sym_count = GCC_SYMBOLS (ldptr);
1196 sym_index = GCC_SYMZERO (ldptr);
1197 while (sym_index < sym_count)
1198 {
1199 GCC_SYMENT symbol;
1200
1201 if (ldtbread (ldptr, sym_index, &symbol) <= 0)
1202 break;
1203 sym_index += GCC_SYMINC (symbol);
1204
1205 if (GCC_OK_SYMBOL (symbol))
1206 {
1207 char *name;
1208
1209 if ((name = ldgetname (ldptr, &symbol)) == NULL)
1210 continue; /* should never happen */
1211
1212 #ifdef _AIX
1213 /* All AIX function names begin with a dot. */
1214 if (*name++ != '.')
1215 continue;
1216 #endif
1217
1218 switch (is_ctor_dtor (name))
1219 {
1220 case 1:
1221 add_to_list (&constructors, name);
1222 break;
1223
1224 case 2:
1225 add_to_list (&destructors, name);
1226 break;
1227
1228 default: /* not a constructor or destructor */
1229 continue;
1230 }
1231
1232 #if !defined(EXTENDED_COFF)
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);
1238 #else
1239 if (debug)
1240 fprintf (stderr, "\tiss = %5d, value = %5d, index = %5d, name = %s\n",
1241 symbol.iss, symbol.value, symbol.index, name);
1242 #endif
1243 }
1244 }
1245 }
1246
1247 (void) ldclose(ldptr);
1248 }
1249
1250 #endif /* OBJECT_FORMAT_COFF */
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
1261 typedef union load_union
1262 {
1263 ldc_header_t hdr; /* common header */
1264 load_cmd_map_command_t map; /* map indexing other load cmds */
1265 interpreter_command_t iprtr; /* interpreter pathname */
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
1278 typedef 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
1286 struct 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
1297 extern int decode_mach_o_hdr ();
1298
1299 extern int encode_mach_o_hdr ();
1300
1301 static void bad_header ();
1302
1303 static void print_header ();
1304
1305 static void print_load_command ();
1306
1307 static void add_func_table ();
1308
1309 static struct file_info *read_file ();
1310
1311 static void end_file ();
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
1324 static void
1325 scan_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)
1348 fatal_perror ("can't read %s", prog_name);
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 {
1371 fatal ("incompatibilities between object file & expected values");
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
1390 /* If modifying the program file, copy the header. */
1391 if (rw)
1392 {
1393 load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size);
1394 bcopy ((generic *)load_hdr, (generic *)ptr, load_hdr->hdr.ldci_cmd_size);
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 {
1435 char *kind = "unknown";
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
1451 str_sect = load_array[load_hdr->sym.symc_strings_section].section;
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;
1463
1464 if (name[0] != '_')
1465 continue;
1466
1467 if (rw)
1468 {
1469 char *n = name;
1470 while (*n == '_')
1471 ++n;
1472 if (*n != 'm' || (n - name) < 2 || strcmp (n, "main"))
1473 continue;
1474
1475 main_sym = sym;
1476 }
1477 else
1478 {
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 }
1492 }
1493
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)
1502 fatal ("no symbol table found");
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)
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. */
1521
1522 if (main_sym != (symbol_info_t *)0
1523 && ((hdr.moh_flags & MOH_EXECABLE_F) == 0))
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
1577 bcopy ((generic *)load_hdr, (generic *)(obj + offset), size);
1578 offset += size;
1579 }
1580 }
1581
1582 end_file (obj_file);
1583
1584 if (close (prog_fd))
1585 fatal_perror ("closing %s", prog_name);
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
1593 on initiation or termination of the process. */
1594
1595 static void
1596 add_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
1675 static void
1676 print_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
1718 static void
1719 print_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
1785 static void
1786 bad_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
1810 static struct file_info *
1811 read_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
1876 static void
1877 end_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.118232 seconds and 4 git commands to generate.