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