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