1 /* Collect static initialization info into data structures
2 that can be traversed by C++ initialization and finalization
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).
10 This file is part of GNU CC.
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)
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.
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. */
27 /* Build tables of static constructors and destructors and run ld. */
29 #include <sys/types.h>
57 #ifdef OBJECT_FORMAT_ROSE
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 */
74 /* Default flags to pass to nm. */
83 /* On MSDOS, write temp files in current dir
84 because there's no place else we can expect to use. */
92 /* Linked lists of constructor and destructor names. */
108 /* Enumeration giving which pass this is for scanning the program file. */
111 PASS_FIRST, /* without constructors */
112 PASS_SECOND /* with constructors linked in */
115 extern char *sys_siglist[];
116 extern char *version_string;
118 static int vflag; /* true if -v */
119 static int rflag; /* true if -r */
121 static int debug; /* true if -debug */
123 static int temp_filename_length; /* Length of temp_filename */
124 static char *temp_filename; /* Base of temp filenames */
125 static char *c_file; /* <xxx>.c for constructor/destructor list. */
126 static char *o_file; /* <xxx>.o for constructor/destructor list. */
127 static char *nm_file_name; /* pathname of nm */
129 static struct head constructors; /* list of constructors found */
130 static struct head destructors; /* list of destructors found */
132 extern char *getenv PROTO(( const char * ));
133 extern char *mktemp PROTO(( char * ));
134 extern int vfork PROTO(( void ));
135 static void add_to_list PROTO(( struct head *headp, char *name ));
136 static void scan_prog_file PROTO(( char *, enum pass ));
137 static void fork_execute PROTO(( char *, char **argv ));
138 static void do_wait PROTO(( char * ));
139 static void write_c_file PROTO(( FILE *, char * ));
140 static void my_exit PROTO(( int ));
141 static void handler PROTO(( int ));
142 static void maybe_unlink PROTO(( char * ));
143 static void choose_temp_base PROTO(( void ));
145 generic *xcalloc PROTO(( size_t, size_t ));
146 generic *xmalloc PROTO(( size_t ));
150 #if !defined(HAVE_STRERROR) && !defined(_OSF_SOURCE)
155 extern char *sys_errlist[];
157 static char buffer[30];
162 if (e > 0 && e < sys_nerr)
163 return sys_errlist[e];
165 sprintf (buffer, "Unknown error %d", e);
172 /* Delete tempfiles and exit function. */
179 maybe_unlink (c_file);
182 maybe_unlink (o_file);
190 /* Die when sys call fails. */
194 fatal_perror (va_alist)
201 string = va_arg (vptr, char *);
202 fprintf (stderr, "collect: ");
203 vfprintf (stderr, string, vptr);
204 fprintf (stderr, ": %s\n", strerror (e));
219 string = va_arg (vptr, char *);
220 fprintf (stderr, "collect: ");
221 vfprintf (stderr, string, vptr);
222 fprintf (stderr, "\n");
227 /* Write error message. */
237 string = va_arg (vptr, char *);
238 fprintf (stderr, "collect: ");
239 vfprintf (stderr, string, vptr);
240 fprintf (stderr, "\n");
247 fatal_perror (char *string, ...)
252 va_start (vptr, string);
253 fprintf (stderr, "collect: ");
254 vfprintf (stderr, string, vptr);
255 fprintf (stderr, ": %s\n", strerror (e));
263 fatal (char *string, ...)
267 va_start (vptr, string);
268 fprintf (stderr, "collect: ");
269 vfprintf (stderr, string, vptr);
270 fprintf (stderr, "\n");
275 /* Write error message. */
278 error (char *string, ...)
282 va_start (vptr, string);
283 fprintf (stderr, "collect: ");
284 vfprintf (stderr, string, vptr);
285 fprintf (stderr, "\n");
291 /* In case obstack is linked in, and abort is defined to fancy_abort,
292 provide a default entry. */
297 fatal ("internal error");
306 maybe_unlink (c_file);
309 maybe_unlink (o_file);
311 signal (signo, SIG_DFL);
313 fatal ("Caught signal %d [%s]", signo, sys_siglist[signo]);
314 kill (getpid (), signo);
319 xcalloc (size1, size2)
322 generic *ptr = calloc (size1, size2);
326 fatal ("Out of memory.");
334 generic *ptr = malloc (size);
338 fatal ("Out of memory.");
343 /* Compute a string to use as the base of all temporary file names.
344 It is substituted for %g. */
347 choose_temp_base PROTO((void))
349 char *base = getenv ("TMPDIR");
352 if (base == (char *)0)
355 if (access (P_tmpdir, R_OK | W_OK) == 0)
358 if (base == (char *)0)
360 if (access ("/usr/tmp", R_OK | W_OK) == 0)
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");
374 mktemp (temp_filename);
375 temp_filename_length = strlen (temp_filename);
386 char *outfile = "a.out";
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;
410 fatal ("no arguments");
412 signal (SIGQUIT, handler);
413 signal (SIGINT, handler);
414 signal (SIGALRM, handler);
415 signal (SIGHUP, handler);
416 signal (SIGSEGV, handler);
417 signal (SIGBUS, handler);
419 /* Try to discover a valid linker/assembler/nm to use. */
420 len = strlen (argv[0]);
422 if (len >= sizeof ("ld")-1)
424 p = argv[0] + len - sizeof ("ld") + 1;
425 if (strcmp (p, "ld") == 0)
432 if (prefix == (char *)0)
434 p = strrchr (argv[0], '/');
441 #ifdef STANDARD_EXEC_PREFIX
442 else if (access (STANDARD_EXEC_PREFIX, X_OK) == 0)
443 prefix = STANDARD_EXEC_PREFIX;
446 #ifdef MD_EXEC_PREFIX
447 else if (access (MD_EXEC_PREFIX, X_OK) == 0)
448 prefix = MD_EXEC_PREFIX;
451 else if (access ("/usr/ccs/gcc", X_OK) == 0)
452 prefix = "/usr/ccs/gcc/";
454 else if (access ("/usr/ccs/bin", X_OK) == 0)
455 prefix = "/usr/ccs/bin/";
461 clen = len = strlen (prefix);
463 #ifdef STANDARD_BIN_PREFIX
464 if (clen < sizeof (STANDARD_BIN_PREFIX) - 1)
465 clen = sizeof (STANDARD_BIN_PREFIX) - 1;
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);
473 memcpy (ld_file_name, prefix, len);
474 strcpy (ld_file_name + len, "real-ld");
475 if (access (ld_file_name, X_OK) < 0)
477 strcpy (ld_file_name + len, "gld");
478 if (access (ld_file_name, X_OK) < 0)
481 #ifdef REAL_LD_FILE_NAME
482 ld_file_name = REAL_LD_FILE_NAME;
484 ld_file_name = (access ("/usr/bin/ld", X_OK) == 0) ? "/usr/bin/ld" : "/bin/ld";
489 memcpy (c_file_name, prefix, len);
490 strcpy (c_file_name + len, "gcc");
491 if (access (c_file_name, X_OK) < 0)
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)
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)
505 strcpy (c_file_name, "gcc");
510 memcpy (nm_file_name, prefix, len);
511 strcpy (nm_file_name + len, "nm");
512 if (access (nm_file_name, X_OK) < 0)
514 strcpy (nm_file_name + len, "gnm");
515 if (access (nm_file_name, X_OK) < 0)
518 #ifdef REAL_NM_FILE_NAME
519 nm_file_name = REAL_NM_FILE_NAME;
521 nm_file_name = (access ("/usr/bin/nm", X_OK) == 0) ? "/usr/bin/nm" : "/bin/nm";
526 strcpy (B_option, "-B");
527 strcpy (B_option + sizeof ("-B") - 1, prefix);
529 *ld1++ = *ld2++ = "ld";
531 /* Make temp file names. */
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);
542 /* Parse arguments. Remember output file spec, pass the rest to ld. */
543 /* After the first file, put in the c++ rt0 */
545 while ((arg = *++argv) != (char *)0)
547 *ld1++ = *ld2++ = arg;
553 if (!strcmp (arg, "-debug"))
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. */
579 outfile = (arg[2] == '\0') ? argv[1] : &arg[2];
594 && (p = strrchr (arg, '.')) != (char *)0
595 && strcmp (p, ".o") == 0)
604 *c_ptr = *ld1 = *ld2 = (char *)0;
608 fprintf (stderr, "GNU COLLECT2 version %s", version_string);
609 #ifdef TARGET_VERSION
612 fprintf (stderr, "\n");
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);
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. */
631 fork_execute (ld_file_name, ld1_argv);
633 /* If -r, don't build the constructor or destructor list, just return now. */
637 scan_prog_file (outfile, PASS_FIRST);
641 fprintf (stderr, "%d constructor(s) found\n", constructors.number);
642 fprintf (stderr, "%d destructor(s) found\n", destructors.number);
645 if (constructors.number == 0 && destructors.number == 0)
648 outf = fopen (c_file, "w");
649 if (outf == (FILE *)0)
650 fatal_perror ("Can't write %s", c_file);
652 write_c_file (outf, c_file);
655 fatal_perror ("Can't close %s", c_file);
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");
664 /* Assemble the constructor and destructor tables.
665 Link the tables in with the rest of the program. */
667 fork_execute (c_file_name, c_argv);
668 fork_execute (ld_file_name, ld2_argv);
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);
674 maybe_unlink (c_file);
675 maybe_unlink (o_file);
680 /* Wait for a process to finish, and exit if a non-zero status is found. */
691 int sig = WTERMSIG (status);
694 if (sig != -1 && sig != 0)
696 error ("%s terminated with signal %d [%s]%s",
700 (status & 0200) ? ", core dumped" : "");
705 ret = WEXITSTATUS (status);
706 if (ret != -1 && ret != 0)
708 error ("%s returned %d exit status", prog, ret);
715 /* Fork and execute a program, and wait for the reply. */
718 fork_execute (prog, argv)
723 void (*int_handler) PROTO((int));
724 void (*quit_handler) PROTO((int));
731 fprintf (stderr, "%s", prog);
732 for (p_argv = &argv[1]; (str = *p_argv) != (char *)0; p_argv++)
733 fprintf (stderr, " %s", str);
735 fprintf (stderr, "\n");
743 fatal_perror ("vfork");
745 if (pid == 0) /* child context */
748 fatal_perror ("Execute %s", prog);
751 int_handler = (void (*)PROTO((int)))signal (SIGINT, SIG_IGN);
752 quit_handler = (void (*)PROTO((int)))signal (SIGQUIT, SIG_IGN);
756 signal (SIGINT, int_handler);
757 signal (SIGQUIT, quit_handler);
761 /* Unlink a file unless we are debugging. */
770 fprintf (stderr, "[Leaving %s]\n", file);
774 /* Add a name to a linked list. */
777 add_to_list (head_ptr, name)
778 struct head *head_ptr;
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);
787 head_ptr->last->next = newid;
789 head_ptr->first = newid;
791 head_ptr->last = newid;
795 /* Write: `prefix', the names on list LIST, `suffix'. */
798 write_list (stream, prefix, list)
805 fprintf (stream, "%sx%d,\n", prefix, list->sequence);
811 write_list_with_asm (stream, prefix, list)
818 fprintf (stream, "%sx%d asm (\"%s\");\n",
819 prefix, list->sequence, list->name);
824 /* Write the constructor/destructor tables. */
827 write_c_file (stream, name)
831 /* Write the tables as C code */
833 fprintf (stream, "typedef void entry_pt();\n\n");
835 write_list_with_asm (stream, "entry_pt ", constructors);
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");
842 write_list_with_asm (stream, "entry_pt ", destructors);
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");
849 fprintf (stream, "extern entry_pt __main;\n");
850 fprintf (stream, "entry_pt *__main_reference = __main;\n\n");
854 #ifndef OBJECT_FORMAT_ROSE
856 /* OSF/rose specific version to scan the name list of the loaded
857 program for the symbols g++ uses for static constructors and
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__. */
867 scan_prog_file (prog_name, which_pass)
869 enum pass which_pass;
871 void (*int_handler) PROTO((int));
872 void (*quit_handler) PROTO((int));
880 if (which_pass != PASS_FIRST)
883 nm_argv[ argc++ ] = "nm";
884 if (NM_FLAGS[0] != '\0')
885 nm_argv[ argc++ ] = NM_FLAGS;
887 nm_argv[ argc++ ] = prog_name;
888 nm_argv[ argc++ ] = (char *)0;
890 if (pipe (pipe_fd) < 0)
891 fatal_perror ("pipe");
893 inf = fdopen (pipe_fd[0], "r");
894 if (inf == (FILE *)0)
895 fatal_perror ("fdopen");
897 /* Trace if needed. */
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);
907 fprintf (stderr, "\n");
913 /* Spawn child nm on pipe */
916 fatal_perror ("vfork");
918 if (pid == 0) /* child context */
921 if (dup2 (pipe_fd[1], 1) < 0)
922 fatal_perror ("Dup2 (%d, 1)", pipe_fd[1]);
924 if (close (pipe_fd[0]) < 0)
925 fatal_perror ("Close (%d)", pipe_fd[0]);
927 if (close (pipe_fd[1]) < 0)
928 fatal_perror ("Close (%d)", pipe_fd[1]);
930 execv (nm_file_name, nm_argv);
931 fatal_perror ("Execute %s", nm_file_name);
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);
938 if (close (pipe_fd[1]) < 0)
939 fatal_perror ("Close (%d)", pipe_fd[1]);
942 fprintf (stderr, "\nnm output with constructors/destructors.\n");
944 /* Read each line of nm output. */
945 while (fgets (buf, sizeof buf, inf) != (char *)0)
951 /* If it contains a constructor or destructor name, add the name
952 to the appropriate list. */
954 for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
957 if (ch == '\0' || ch == '\n')
961 while ((ch = *p) == '_') /* skip any extra '_' inserted */
964 for (end = p; (ch2 = *end) != '\0' && !isspace (ch2); end++)
970 if (! strncmp (p, "GLOBAL_$I$", 10))
971 add_to_list (&constructors, p-1);
973 else if (! strncmp (p, "GLOBAL_$D$", 10))
974 add_to_list (&destructors, p-1);
976 else /* not a constructor or destructor */
980 else if (ch == 's' && (p - start) >= 2)
982 if (! strncmp (p, "sti__", 5))
983 add_to_list (&constructors, p-2);
985 else if (! strncmp (p, "std__", 5))
986 add_to_list (&destructors, p-2);
988 else /* not a constructor or destructor */
996 fprintf (stderr, "\t%s\n", buf);
1000 fprintf (stderr, "\n");
1002 if (fclose (inf) != 0)
1003 fatal_perror ("fclose of pipe");
1005 do_wait (nm_file_name);
1007 signal (SIGINT, int_handler);
1008 signal (SIGQUIT, quit_handler);
1011 #endif /* !OBJECT_FORMAT_ROSE */
1015 * OSF/rose specific stuff.
1018 #ifdef OBJECT_FORMAT_ROSE
1020 /* Union of the various load commands */
1022 typedef union load_union
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 */
1037 /* Structure to point to load command and data section in memory. */
1039 typedef struct load_all
1041 load_union_t *load; /* load command */
1042 char *section; /* pointer to section */
1045 /* Structure to contain information about a file mapped into memory. */
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 */
1058 extern int decode_mach_o_hdr PROTO(( void *in_bufp,
1060 unsigned long hdr_version,
1061 mo_header_t *headerp ));
1063 extern int encode_mach_o_hdr PROTO(( mo_header_t *headerp,
1065 size_t out_bufsize ));
1067 static void bad_header PROTO(( int status ));
1069 static void print_header PROTO(( mo_header_t *hdr_ptr ));
1071 static void print_load_command PROTO(( load_union_t *load_hdr,
1075 static void add_func_table PROTO(( mo_header_t *hdr_p,
1076 load_all_t *load_array,
1080 static struct file_info *read_file PROTO(( char *, int, int ));
1082 static void end_file PROTO(( struct file_info * ));
1085 /* OSF/rose specific version to scan the name list of the loaded
1086 program for the symbols g++ uses for static constructors and
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__. */
1096 scan_prog_file (prog_name, which_pass)
1098 enum pass which_pass;
1102 load_all_t *load_array;
1103 load_all_t *load_end;
1104 load_all_t *load_cmd;
1105 int symbol_load_cmds;
1111 struct file_info *obj_file;
1113 mo_lcid_t cmd_strings = -1;
1114 symbol_info_t *main_sym = 0;
1115 int rw = (which_pass != PASS_FIRST);
1117 prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY);
1119 fatal_perror ("Can't read %s", prog_name);
1121 obj_file = read_file (prog_name, prog_fd, rw);
1122 obj = obj_file->start;
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);
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
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)
1142 fatal ("incompatibilities exist between object file & expected values.");
1147 print_header (&hdr);
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);
1153 /* Build array of load commands, calculating the offsets */
1154 for (i = 0; i < hdr.moh_n_load_cmds; i++)
1156 load_union_t *load_hdr; /* load command header */
1158 load_cmd = load_end++;
1159 load_hdr = (load_union_t *) (obj + offset);
1161 /* If modifing the program file, copy the header. */
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);
1168 /* null out old command map, because we will rewrite at the end. */
1169 if (ptr->hdr.ldci_cmd_type == LDC_CMD_MAP)
1171 cmd_strings = ptr->map.lcm_ld_cmd_strings;
1172 ptr->hdr.ldci_cmd_type = LDC_UNDEFINED;
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;
1181 print_load_command (load_hdr, offset, i);
1183 offset += load_hdr->hdr.ldci_cmd_size;
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)
1191 hdr.moh_n_load_cmds--;
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++)
1198 load_union_t *load_hdr = load_cmd->load;
1200 if (load_hdr->hdr.ldci_cmd_type == LDC_SYMBOLS)
1206 char *kind = "uknown";
1208 switch (load_hdr->sym.symc_kind)
1210 case SYMC_IMPORTS: kind = "imports"; break;
1211 case SYMC_DEFINED_SYMBOLS: kind = "defined"; break;
1212 case SYMC_STABS: kind = "stabs"; break;
1215 fprintf (stderr, "\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
1216 symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
1219 if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
1222 str_sect = load_array[ load_hdr->sym.symc_strings_section ].section;
1223 if (str_sect == (char *)0)
1224 fatal ("string section missing");
1226 if (load_cmd->section == (char *)0)
1227 fatal ("section pointer missing");
1229 num_syms = load_hdr->sym.symc_nentries;
1230 for (i = 0; i < num_syms; i++)
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;
1239 while (*++name == '_') /* skip any extra '_' inserted */
1244 if (*name != 'm' || (name - name_start) < 2
1245 || strcmp (name, "main"))
1251 else if (*name == 'G')
1253 if (! strncmp (name, "GLOBAL_$I$", 10))
1254 add_to_list (&constructors, name_start);
1256 else if (! strncmp (name, "GLOBAL_$D$", 10))
1257 add_to_list (&destructors, name_start);
1259 else /* not a constructor or destructor */
1263 else if (*name == 's' && (name - name_start) > 2)
1265 if (! strncmp (name, "sti__", 5))
1266 add_to_list (&constructors, name_start);
1268 else if (! strncmp (name, "std__", 5))
1269 add_to_list (&destructors, name_start);
1271 else /* not a constructor or destructor */
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);
1285 if (symbol_load_cmds == 0)
1286 fatal ("no symbol table found.");
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. */
1295 load_union_t *load_map;
1298 if (cmd_strings == -1)
1299 fatal ("no cmd_strings found.");
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);
1306 fprintf (stderr, "\nUpdating header and load commands.\n\n");
1308 hdr.moh_n_load_cmds++;
1309 size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1));
1311 /* Create new load command map. */
1313 fprintf (stderr, "load command map, %d cmds, new size %ld.\n",
1314 (int)hdr.moh_n_load_cmds, (long)size);
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;
1323 offset = hdr.moh_first_cmd_off;
1324 for (i = 0; i < hdr.moh_n_load_cmds; i++)
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;
1330 offset += load_array[i].load->hdr.ldci_cmd_size;
1333 hdr.moh_sizeofcmds = offset - MO_SIZEOF_RAW_HDR;
1336 print_header (&hdr);
1339 status = encode_mach_o_hdr (&hdr, obj, MO_SIZEOF_RAW_HDR);
1340 if (status != MO_HDR_CONV_SUCCESS)
1341 bad_header (status);
1344 fprintf (stderr, "writing load commands.\n\n");
1346 /* Write load commands */
1347 offset = hdr.moh_first_cmd_off;
1348 for (i = 0; i < hdr.moh_n_load_cmds; i++)
1350 load_union_t *load_hdr = load_array[i].load;
1351 size_t size = load_hdr->hdr.ldci_cmd_size;
1354 print_load_command (load_hdr, offset, i);
1356 memcpy (obj + offset, load_hdr, size);
1361 end_file (obj_file);
1363 if (close (prog_fd))
1364 fatal_perror ("Can't close %s", prog_name);
1367 fprintf (stderr, "\n");
1371 /* Add a function table to the load commands to call a function
1372 on initition or termination of the process. */
1375 add_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 */
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;
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;
1393 load_cmd = &load_array[load_index];
1394 load_cmd->load = ptr;
1395 load_cmd->section = (char *)0;
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;
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)
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;
1413 /* If not, figure out which region it's in. */
1416 mo_vm_addr_t addr = sym->si_value.abs_val;
1419 for (i = 0; i < load_index; i++)
1421 if (load_array[i].load->hdr.ldci_cmd_type == LDC_REGION)
1423 region_command_t *region_ptr = &load_array[i].load->region;
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)
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;
1438 fatal ("could not convert 0x%l.8x into a region", addr);
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);
1452 /* Print the global header for an OSF/rose object. */
1455 print_header (hdr_ptr)
1456 mo_header_t *hdr_ptr;
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);
1475 if (hdr_ptr->moh_flags & MOH_RELOCATABLE_F)
1476 fprintf (stderr, ", relocatable");
1478 if (hdr_ptr->moh_flags & MOH_LINKABLE_F)
1479 fprintf (stderr, ", linkable");
1481 if (hdr_ptr->moh_flags & MOH_EXECABLE_F)
1482 fprintf (stderr, ", execable");
1484 if (hdr_ptr->moh_flags & MOH_EXECUTABLE_F)
1485 fprintf (stderr, ", executable");
1487 if (hdr_ptr->moh_flags & MOH_UNRESOLVED_F)
1488 fprintf (stderr, ", unresolved");
1490 fprintf (stderr, "\n\n");
1495 /* Print a short summary of a load command. */
1498 print_load_command (load_hdr, offset, number)
1499 load_union_t *load_hdr;
1503 mo_long_t type = load_hdr->hdr.ldci_cmd_type;
1504 char *type_str = (char *)0;
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;
1522 "cmd %2d, sz: 0x%.2lx, coff: 0x%.3lx, doff: 0x%.6lx, dlen: 0x%.6lx",
1524 (long) load_hdr->hdr.ldci_cmd_size,
1526 (long) load_hdr->hdr.ldci_section_off,
1527 (long) load_hdr->hdr.ldci_section_len);
1529 if (type_str == (char *)0)
1530 fprintf (stderr, ", ty: unknown (%ld)\n", (long) type);
1532 else if (type != LDC_REGION)
1533 fprintf (stderr, ", ty: %s\n", type_str);
1538 switch (load_hdr->region.regc_usage_type)
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;
1551 fprintf (stderr, ", ty: %s, vaddr: 0x%.8lx, vlen: 0x%.6lx%s\n",
1553 (long) load_hdr->region.regc_vm_addr,
1554 (long) load_hdr->region.regc_vm_size,
1562 /* Fatal error when {en,de}code_mach_o_header fails. */
1568 char *msg = (char *)0;
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;
1580 if (msg == (char *)0)
1581 fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
1587 /* Read a file into a memory buffer. */
1589 static struct file_info *
1590 read_file (name, fd, rw)
1591 char *name; /* filename */
1592 int fd; /* file descriptor */
1593 int rw; /* read/write */
1595 struct stat stat_pkt;
1596 struct file_info *p = (struct file_info *) xcalloc (sizeof (struct file_info), 1);
1598 static int page_size;
1601 if (fstat (fd, &stat_pkt) < 0)
1602 fatal_perror ("fstat %s", name);
1605 p->size = stat_pkt.st_size;
1606 p->rounded_size = stat_pkt.st_size;
1612 fprintf (stderr, "mmap %s, %s\n", name, (rw) ? "read/write" : "read-only");
1615 page_size = sysconf (_SC_PAGE_SIZE);
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,
1625 if (p->start != (char *)0 && p->start != (char *)-1)
1629 #endif /* USE_MMAP */
1634 fprintf (stderr, "read %s\n", name);
1637 p->start = xmalloc (p->size);
1638 if (lseek (fd, 0L, SEEK_SET) < 0)
1639 fatal_perror ("lseek to 0 on %s", name);
1641 len = read (fd, p->start, p->size);
1643 fatal_perror ("read %s", name);
1646 fatal ("read %ld bytes, expected %ld, from %s", len, p->size, name);
1653 /* Do anything necessary to write a file back from memory. */
1657 struct file_info *ptr; /* file information block */
1665 fprintf (stderr, "msync %s\n", ptr->name);
1667 if (msync (ptr->start, ptr->rounded_size, MS_ASYNC))
1668 fatal_perror ("msync %s", ptr->name);
1672 fprintf (stderr, "munmap %s\n", ptr->name);
1674 if (munmap (ptr->start, ptr->size))
1675 fatal_perror ("munmap %s", ptr->name);
1678 #endif /* USE_MMAP */
1685 fprintf (stderr, "write %s\n", ptr->name);
1687 if (lseek (ptr->fd, 0L, SEEK_SET) < 0)
1688 fatal_perror ("lseek to 0 on %s", ptr->name);
1690 len = write (ptr->fd, ptr->start, ptr->size);
1692 fatal_perror ("read %s", ptr->name);
1694 if (len != ptr->size)
1695 fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name);
1698 free ((generic *)ptr->start);
1701 free ((generic *)ptr);
1704 #endif /* OBJECT_FORMAT_ROSE */