00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "config.h"
00034 #include "system.h"
00035 #include <signal.h>
00036 #if ! defined( SIGCHLD ) && defined( SIGCLD )
00037 # define SIGCHLD SIGCLD
00038 #endif
00039
00040 #ifdef vfork
00041 # define VFORK_STRING "fork"
00042 #else
00043 # define VFORK_STRING "vfork"
00044 #endif
00045 #ifdef HAVE_VFORK_H
00046 #include <vfork.h>
00047 #endif
00048 #ifdef VMS
00049 #define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \
00050 lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1)
00051 #endif
00052
00053 #ifndef LIBRARY_PATH_ENV
00054 #define LIBRARY_PATH_ENV "LIBRARY_PATH"
00055 #endif
00056
00057 #define COLLECT
00058
00059 #include "collect2.h"
00060 #include "demangle.h"
00061 #include "obstack.h"
00062 #include "intl.h"
00063 #include "version.h"
00064
00065
00066
00067
00068
00069
00070
00071 #ifdef CROSS_COMPILE
00072 #undef SUNOS4_SHARED_LIBRARIES
00073 #undef OBJECT_FORMAT_COFF
00074 #undef OBJECT_FORMAT_ROSE
00075 #undef MD_EXEC_PREFIX
00076 #undef REAL_LD_FILE_NAME
00077 #undef REAL_NM_FILE_NAME
00078 #undef REAL_STRIP_FILE_NAME
00079 #endif
00080
00081
00082
00083
00084
00085
00086 #if !defined (OBJECT_FORMAT_COFF) && !defined (OBJECT_FORMAT_ROSE)
00087 #define OBJECT_FORMAT_NONE
00088 #endif
00089
00090 #ifdef OBJECT_FORMAT_COFF
00091
00092 #include <a.out.h>
00093 #include <ar.h>
00094
00095 #ifdef UMAX
00096 #include <sgs.h>
00097 #endif
00098
00099
00100 #ifdef FREAD
00101 #undef FREAD
00102 #undef FWRITE
00103 #endif
00104
00105 #include <ldfcn.h>
00106
00107
00108
00109
00110
00111
00112 #ifndef MY_ISCOFF
00113 #define MY_ISCOFF(X) ISCOFF (X)
00114 #endif
00115
00116 #endif
00117
00118 #ifdef OBJECT_FORMAT_ROSE
00119
00120 #ifdef _OSF_SOURCE
00121 #define USE_MMAP
00122 #endif
00123
00124 #ifdef USE_MMAP
00125 #include <sys/mman.h>
00126 #endif
00127
00128 #include <unistd.h>
00129 #include <mach_o_format.h>
00130 #include <mach_o_header.h>
00131 #include <mach_o_vals.h>
00132 #include <mach_o_types.h>
00133
00134 #endif
00135
00136 #ifdef OBJECT_FORMAT_NONE
00137
00138
00139 #ifndef NM_FLAGS
00140 #define NM_FLAGS "-n"
00141 #endif
00142
00143 #endif
00144
00145
00146
00147
00148 #ifndef NAME__MAIN
00149 #define NAME__MAIN "__main"
00150 #endif
00151
00152
00153 #define DEFAULT_INIT_PRIORITY 65535
00154
00155 #ifndef COLLECT_SHARED_INIT_FUNC
00156 #define COLLECT_SHARED_INIT_FUNC(STREAM, FUNC) \
00157 fprintf ((STREAM), "void _GLOBAL__DI() {\n\t%s();\n}\n", (FUNC))
00158 #endif
00159 #ifndef COLLECT_SHARED_FINI_FUNC
00160 #define COLLECT_SHARED_FINI_FUNC(STREAM, FUNC) \
00161 fprintf ((STREAM), "void _GLOBAL__DD() {\n\t%s();\n}\n", (FUNC))
00162 #endif
00163
00164 #if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES
00165 #define SCAN_LIBRARIES
00166 #endif
00167
00168 #ifdef USE_COLLECT2
00169 int do_collecting = 1;
00170 #else
00171 int do_collecting = 0;
00172 #endif
00173
00174
00175
00176 int no_demangle;
00177
00178
00179
00180 struct id
00181 {
00182 struct id *next;
00183 int sequence;
00184 char name[1];
00185 };
00186
00187 struct head
00188 {
00189 struct id *first;
00190 struct id *last;
00191 int number;
00192 };
00193
00194
00195
00196 enum pass {
00197 PASS_FIRST,
00198 PASS_OBJ,
00199 PASS_LIB,
00200 PASS_SECOND
00201 };
00202
00203 int vflag;
00204 static int rflag;
00205 static int strip_flag;
00206 #ifdef COLLECT_EXPORT_LIST
00207 static int export_flag;
00208 static int aix64_flag;
00209 #endif
00210
00211 int debug;
00212
00213 static int shared_obj;
00214
00215 static const char *c_file;
00216 static const char *o_file;
00217 #ifdef COLLECT_EXPORT_LIST
00218 static const char *export_file;
00219 #endif
00220 const char *ldout;
00221 static const char *output_file;
00222 static const char *nm_file_name;
00223 #ifdef LDD_SUFFIX
00224 static const char *ldd_file_name;
00225 #endif
00226 static const char *strip_file_name;
00227 const char *c_file_name;
00228 static char *initname, *fininame;
00229
00230 static struct head constructors;
00231 static struct head destructors;
00232 #ifdef COLLECT_EXPORT_LIST
00233 static struct head exports;
00234 #endif
00235 static struct head frame_tables;
00236
00237 struct obstack temporary_obstack;
00238 char * temporary_firstobj;
00239
00240
00241 int pexecute_pid;
00242
00243
00244
00245
00246 struct prefix_list
00247 {
00248 const char *prefix;
00249 struct prefix_list *next;
00250 };
00251
00252 struct path_prefix
00253 {
00254 struct prefix_list *plist;
00255 int max_len;
00256 const char *name;
00257 };
00258
00259 #ifdef COLLECT_EXPORT_LIST
00260
00261 static struct head libs;
00262 static struct path_prefix cmdline_lib_dirs;
00263 static struct path_prefix libpath_lib_dirs;
00264 static struct path_prefix *libpaths[3] = {&cmdline_lib_dirs,
00265 &libpath_lib_dirs, NULL};
00266 static const char *const libexts[3] = {"a", "so", NULL};
00267 #endif
00268
00269 static void handler PARAMS ((int));
00270 static int is_ctor_dtor PARAMS ((const char *));
00271 static char *find_a_file PARAMS ((struct path_prefix *, const char *));
00272 static void add_prefix PARAMS ((struct path_prefix *, const char *));
00273 static void prefix_from_env PARAMS ((const char *, struct path_prefix *));
00274 static void prefix_from_string PARAMS ((const char *, struct path_prefix *));
00275 static void do_wait PARAMS ((const char *));
00276 static void fork_execute PARAMS ((const char *, char **));
00277 static void maybe_unlink PARAMS ((const char *));
00278 static void add_to_list PARAMS ((struct head *, const char *));
00279 static int extract_init_priority PARAMS ((const char *));
00280 static void sort_ids PARAMS ((struct head *));
00281 static void write_list PARAMS ((FILE *, const char *, struct id *));
00282 #ifdef COLLECT_EXPORT_LIST
00283 static void dump_list PARAMS ((FILE *, const char *, struct id *));
00284 #endif
00285 #if 0
00286 static void dump_prefix_list PARAMS ((FILE *, const char *, struct prefix_list *));
00287 #endif
00288 static void write_list_with_asm PARAMS ((FILE *, const char *, struct id *));
00289 static void write_c_file PARAMS ((FILE *, const char *));
00290 static void write_c_file_stat PARAMS ((FILE *, const char *));
00291 #ifndef LD_INIT_SWITCH
00292 static void write_c_file_glob PARAMS ((FILE *, const char *));
00293 #endif
00294 static void scan_prog_file PARAMS ((const char *, enum pass));
00295 #ifdef SCAN_LIBRARIES
00296 static void scan_libraries PARAMS ((const char *));
00297 #endif
00298 #if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
00299 static int is_in_args PARAMS ((const char *, const char **, const char **));
00300 #endif
00301 #ifdef COLLECT_EXPORT_LIST
00302 #if 0
00303 static int is_in_list PARAMS ((const char *, struct id *));
00304 #endif
00305 static void write_aix_file PARAMS ((FILE *, struct id *));
00306 static char *resolve_lib_name PARAMS ((const char *));
00307 static int ignore_library PARAMS ((const char *));
00308 #endif
00309 static char *extract_string PARAMS ((const char **));
00310
00311 #ifndef SGI_MONGOOSE
00312 #ifndef HAVE_DUP2
00313 static int dup2 PARAMS ((int, int));
00314 static int
00315 dup2 (oldfd, newfd)
00316 int oldfd;
00317 int newfd;
00318 {
00319 int fdtmp[256];
00320 int fdx = 0;
00321 int fd;
00322
00323 if (oldfd == newfd)
00324 return oldfd;
00325 close (newfd);
00326 while ((fd = dup (oldfd)) != newfd && fd >= 0)
00327 fdtmp[fdx++] = fd;
00328 while (fdx > 0)
00329 close (fdtmp[--fdx]);
00330
00331 return fd;
00332 }
00333 #endif
00334 #endif
00335
00336
00337
00338 void
00339 collect_exit (status)
00340 int status;
00341 {
00342 if (c_file != 0 && c_file[0])
00343 maybe_unlink (c_file);
00344
00345 if (o_file != 0 && o_file[0])
00346 maybe_unlink (o_file);
00347
00348 #ifdef COLLECT_EXPORT_LIST
00349 if (export_file != 0 && export_file[0])
00350 maybe_unlink (export_file);
00351 #endif
00352
00353 if (ldout != 0 && ldout[0])
00354 {
00355 dump_file (ldout);
00356 maybe_unlink (ldout);
00357 }
00358
00359 if (status != 0 && output_file != 0 && output_file[0])
00360 maybe_unlink (output_file);
00361
00362 exit (status);
00363 }
00364
00365
00366
00367 void
00368 notice VPARAMS ((const char *msgid, ...))
00369 {
00370 #ifndef SGI_MONGOOSE
00371 VA_OPEN (ap, msgid);
00372 VA_FIXEDARG (ap, const char *, msgid);
00373 #else
00374 va_list ap;
00375
00376 VA_START (ap, msgid);
00377 #endif
00378
00379 vfprintf (stderr, _(msgid), ap);
00380 #ifndef SGI_MONGOOSE
00381 VA_CLOSE (ap);
00382 #else
00383 va_end (ap);
00384 #endif
00385 }
00386
00387
00388
00389 void
00390 fatal_perror VPARAMS ((const char * msgid, ...))
00391 {
00392 int e = errno;
00393
00394 #ifndef SGI_MONGOOSE
00395 VA_OPEN (ap, msgid);
00396 VA_FIXEDARG (ap, const char *, msgid);
00397 #else
00398 va_list ap;
00399
00400 VA_START (ap, msgid);
00401 #endif
00402
00403 fprintf (stderr, "collect2: ");
00404 vfprintf (stderr, _(msgid), ap);
00405 fprintf (stderr, ": %s\n", xstrerror (e));
00406 #ifndef SGI_MONGOOSE
00407 VA_CLOSE (ap);
00408 #else
00409 va_end (ap);
00410 #endif
00411
00412 collect_exit (FATAL_EXIT_CODE);
00413 }
00414
00415
00416
00417 void
00418 fatal VPARAMS ((const char * msgid, ...))
00419 {
00420 #ifndef SGI_MONGOOSE
00421 VA_OPEN (ap, msgid);
00422 VA_FIXEDARG (ap, const char *, msgid);
00423 #else
00424 va_list ap;
00425
00426 VA_START (ap, msgid);
00427 #endif
00428
00429 fprintf (stderr, "collect2: ");
00430 vfprintf (stderr, _(msgid), ap);
00431 fprintf (stderr, "\n");
00432 #ifndef SGI_MONGOOSE
00433 VA_CLOSE (ap);
00434 #else
00435 va_end (ap);
00436 #endif
00437
00438 collect_exit (FATAL_EXIT_CODE);
00439 }
00440
00441
00442
00443 void
00444 error VPARAMS ((const char * msgid, ...))
00445 {
00446 #ifndef SGI_MONGOOSE
00447 VA_OPEN (ap, msgid);
00448 VA_FIXEDARG (ap, const char *, msgid);
00449 #else
00450 va_list ap;
00451
00452 VA_START (ap, msgid);
00453 #endif
00454
00455 fprintf (stderr, "collect2: ");
00456 vfprintf (stderr, _(msgid), ap);
00457 fprintf (stderr, "\n");
00458 #ifndef SGI_MONGOOSE
00459 VA_CLOSE(ap);
00460 #else
00461 va_end (ap);
00462 #endif
00463 }
00464
00465
00466
00467
00468 void
00469 fancy_abort ()
00470 {
00471 fatal ("internal error");
00472 }
00473
00474 static void
00475 handler (signo)
00476 int signo;
00477 {
00478 if (c_file != 0 && c_file[0])
00479 maybe_unlink (c_file);
00480
00481 if (o_file != 0 && o_file[0])
00482 maybe_unlink (o_file);
00483
00484 if (ldout != 0 && ldout[0])
00485 maybe_unlink (ldout);
00486
00487 #ifdef COLLECT_EXPORT_LIST
00488 if (export_file != 0 && export_file[0])
00489 maybe_unlink (export_file);
00490 #endif
00491
00492 signal (signo, SIG_DFL);
00493 kill (getpid (), signo);
00494 }
00495
00496
00497 int
00498 file_exists (name)
00499 const char *name;
00500 {
00501 return access (name, R_OK) == 0;
00502 }
00503
00504
00505
00506 static char *
00507 extract_string (pp)
00508 const char **pp;
00509 {
00510 const char *p = *pp;
00511 int backquote = 0;
00512 int inside = 0;
00513
00514 for (;;)
00515 {
00516 char c = *p;
00517 if (c == '\0')
00518 break;
00519 ++p;
00520 if (backquote)
00521 obstack_1grow (&temporary_obstack, c);
00522 else if (! inside && c == ' ')
00523 break;
00524 else if (! inside && c == '\\')
00525 backquote = 1;
00526 else if (c == '\'')
00527 inside = !inside;
00528 else
00529 obstack_1grow (&temporary_obstack, c);
00530 }
00531
00532 obstack_1grow (&temporary_obstack, '\0');
00533 *pp = p;
00534 return obstack_finish (&temporary_obstack);
00535 }
00536
00537 void
00538 dump_file (name)
00539 const char *name;
00540 {
00541 FILE *stream = fopen (name, "r");
00542
00543 if (stream == 0)
00544 return;
00545 while (1)
00546 {
00547 int c;
00548 while (c = getc (stream),
00549 #ifndef SGI_MONGOOSE
00550 c != EOF && (ISIDNUM (c) || c == '$' || c == '.'))
00551 #else
00552
00553 c != EOF && (ISALNUM (c) || c == '_' || c == '$' || c == '.'))
00554 #endif
00555 obstack_1grow (&temporary_obstack, c);
00556 if (obstack_object_size (&temporary_obstack) > 0)
00557 {
00558 const char *word, *p;
00559 char *result;
00560 obstack_1grow (&temporary_obstack, '\0');
00561 word = obstack_finish (&temporary_obstack);
00562
00563 if (*word == '.')
00564 ++word, putc ('.', stderr);
00565 p = word;
00566 if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
00567 p += strlen (USER_LABEL_PREFIX);
00568
00569 if (no_demangle)
00570 result = 0;
00571 else
00572 result = cplus_demangle (p, DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE);
00573
00574 if (result)
00575 {
00576 int diff;
00577 fputs (result, stderr);
00578
00579 diff = strlen (word) - strlen (result);
00580 while (diff > 0 && c == ' ')
00581 --diff, putc (' ', stderr);
00582 while (diff < 0 && c == ' ')
00583 ++diff, c = getc (stream);
00584
00585 free (result);
00586 }
00587 else
00588 fputs (word, stderr);
00589
00590 fflush (stderr);
00591 obstack_free (&temporary_obstack, temporary_firstobj);
00592 }
00593 if (c == EOF)
00594 break;
00595 putc (c, stderr);
00596 }
00597 fclose (stream);
00598 }
00599
00600
00601
00602
00603
00604
00605 static int
00606 is_ctor_dtor (s)
00607 const char *s;
00608 {
00609 struct names { const char *const name; const int len; const int ret;
00610 const int two_underscores; };
00611
00612 const struct names *p;
00613 int ch;
00614 const char *orig_s = s;
00615
00616 static const struct names special[] = {
00617 #ifndef NO_DOLLAR_IN_LABEL
00618 { "GLOBAL__I$", sizeof ("GLOBAL__I$")-1, 1, 0 },
00619 { "GLOBAL__D$", sizeof ("GLOBAL__D$")-1, 2, 0 },
00620 #else
00621 #ifndef NO_DOT_IN_LABEL
00622 { "GLOBAL__I.", sizeof ("GLOBAL__I.")-1, 1, 0 },
00623 { "GLOBAL__D.", sizeof ("GLOBAL__D.")-1, 2, 0 },
00624 #endif
00625 #endif
00626 { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, 1, 0 },
00627 { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, 2, 0 },
00628 { "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, 5, 0 },
00629 { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, 3, 0 },
00630 { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, 4, 0 },
00631 #ifdef CFRONT_LOSSAGE
00632
00633
00634
00635
00636 { "sti__", sizeof ("sti__")-1, 1, 1 },
00637 { "std__", sizeof ("std__")-1, 2, 1 },
00638 #endif
00639 { NULL, 0, 0, 0 }
00640 };
00641
00642 while ((ch = *s) == '_')
00643 ++s;
00644
00645 if (s == orig_s)
00646 return 0;
00647
00648 for (p = &special[0]; p->len > 0; p++)
00649 {
00650 if (ch == p->name[0]
00651 && (!p->two_underscores || ((s - orig_s) >= 2))
00652 && strncmp(s, p->name, p->len) == 0)
00653 {
00654 return p->ret;
00655 }
00656 }
00657 return 0;
00658 }
00659
00660
00661
00662
00663 static struct path_prefix cpath, path;
00664
00665 #ifdef CROSS_COMPILE
00666
00667
00668
00669 static const char *const target_machine = TARGET_MACHINE;
00670 #endif
00671
00672
00673
00674
00675
00676
00677 static char *
00678 find_a_file (pprefix, name)
00679 struct path_prefix *pprefix;
00680 const char *name;
00681 {
00682 char *temp;
00683 struct prefix_list *pl;
00684 int len = pprefix->max_len + strlen (name) + 1;
00685
00686 if (debug)
00687 fprintf (stderr, "Looking for '%s'\n", name);
00688
00689 #ifdef HOST_EXECUTABLE_SUFFIX
00690 len += strlen (HOST_EXECUTABLE_SUFFIX);
00691 #endif
00692
00693 temp = xmalloc (len);
00694
00695
00696
00697 if (*name == '/'
00698 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
00699 || (*name && name[1] == ':')
00700 #endif
00701 )
00702 {
00703 if (access (name, X_OK) == 0)
00704 {
00705 strcpy (temp, name);
00706
00707 if (debug)
00708 fprintf (stderr, " - found: absolute path\n");
00709
00710 return temp;
00711 }
00712
00713 #ifdef HOST_EXECUTABLE_SUFFIX
00714
00715
00716 strcpy (temp, name);
00717 strcat (temp, HOST_EXECUTABLE_SUFFIX);
00718
00719 if (access (temp, X_OK) == 0)
00720 return temp;
00721 #endif
00722
00723 if (debug)
00724 fprintf (stderr, " - failed to locate using absolute path\n");
00725 }
00726 else
00727 for (pl = pprefix->plist; pl; pl = pl->next)
00728 {
00729 struct stat st;
00730
00731 strcpy (temp, pl->prefix);
00732 strcat (temp, name);
00733
00734 if (stat (temp, &st) >= 0
00735 && ! S_ISDIR (st.st_mode)
00736 && access (temp, X_OK) == 0)
00737 return temp;
00738
00739 #ifdef HOST_EXECUTABLE_SUFFIX
00740
00741
00742 strcat (temp, HOST_EXECUTABLE_SUFFIX);
00743
00744 if (stat (temp, &st) >= 0
00745 && ! S_ISDIR (st.st_mode)
00746 && access (temp, X_OK) == 0)
00747 return temp;
00748 #endif
00749 }
00750
00751 if (debug && pprefix->plist == NULL)
00752 fprintf (stderr, " - failed: no entries in prefix list\n");
00753
00754 free (temp);
00755 return 0;
00756 }
00757
00758
00759
00760 static void
00761 add_prefix (pprefix, prefix)
00762 struct path_prefix *pprefix;
00763 const char *prefix;
00764 {
00765 struct prefix_list *pl, **prev;
00766 int len;
00767
00768 if (pprefix->plist)
00769 {
00770 for (pl = pprefix->plist; pl->next; pl = pl->next)
00771 ;
00772 prev = &pl->next;
00773 }
00774 else
00775 prev = &pprefix->plist;
00776
00777
00778
00779 len = strlen (prefix);
00780 if (len > pprefix->max_len)
00781 pprefix->max_len = len;
00782
00783 pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list));
00784 pl->prefix = xstrdup (prefix);
00785
00786 if (*prev)
00787 pl->next = *prev;
00788 else
00789 pl->next = (struct prefix_list *) 0;
00790 *prev = pl;
00791 }
00792
00793
00794
00795
00796 static void
00797 prefix_from_env (env, pprefix)
00798 const char *env;
00799 struct path_prefix *pprefix;
00800 {
00801 const char *p;
00802 GET_ENVIRONMENT (p, env);
00803
00804 if (p)
00805 prefix_from_string (p, pprefix);
00806 }
00807
00808 static void
00809 prefix_from_string (p, pprefix)
00810 const char *p;
00811 struct path_prefix *pprefix;
00812 {
00813 const char *startp, *endp;
00814 char *nstore = (char *) xmalloc (strlen (p) + 3);
00815
00816 if (debug)
00817 fprintf (stderr, "Convert string '%s' into prefixes, separator = '%c'\n", p, PATH_SEPARATOR);
00818
00819 startp = endp = p;
00820 while (1)
00821 {
00822 if (*endp == PATH_SEPARATOR || *endp == 0)
00823 {
00824 strncpy (nstore, startp, endp-startp);
00825 if (endp == startp)
00826 {
00827 strcpy (nstore, "./");
00828 }
00829 else if (! IS_DIR_SEPARATOR (endp[-1]))
00830 {
00831 nstore[endp-startp] = DIR_SEPARATOR;
00832 nstore[endp-startp+1] = 0;
00833 }
00834 else
00835 nstore[endp-startp] = 0;
00836
00837 if (debug)
00838 fprintf (stderr, " - add prefix: %s\n", nstore);
00839
00840 add_prefix (pprefix, nstore);
00841 if (*endp == 0)
00842 break;
00843 endp = startp = endp + 1;
00844 }
00845 else
00846 endp++;
00847 }
00848 }
00849
00850
00851
00852 int main PARAMS ((int, char *[]));
00853 int
00854 main (argc, argv)
00855 int argc;
00856 char *argv[];
00857 {
00858 static const char *const ld_suffix = "ld";
00859 static const char *const real_ld_suffix = "real-ld";
00860 static const char *const collect_ld_suffix = "collect-ld";
00861 static const char *const nm_suffix = "nm";
00862 static const char *const gnm_suffix = "gnm";
00863 #ifdef LDD_SUFFIX
00864 static const char *const ldd_suffix = LDD_SUFFIX;
00865 #endif
00866 static const char *const strip_suffix = "strip";
00867 static const char *const gstrip_suffix = "gstrip";
00868
00869 #ifdef CROSS_COMPILE
00870
00871
00872
00873
00874
00875 const char *const full_ld_suffix =
00876 concat(target_machine, "-", ld_suffix, NULL);
00877 const char *const full_nm_suffix =
00878 concat (target_machine, "-", nm_suffix, NULL);
00879 const char *const full_gnm_suffix =
00880 concat (target_machine, "-", gnm_suffix, NULL);
00881 #ifdef LDD_SUFFIX
00882 const char *const full_ldd_suffix =
00883 concat (target_machine, "-", ldd_suffix, NULL);
00884 #endif
00885 const char *const full_strip_suffix =
00886 concat (target_machine, "-", strip_suffix, NULL);
00887 const char *const full_gstrip_suffix =
00888 concat (target_machine, "-", gstrip_suffix, NULL);
00889 #else
00890 const char *const full_ld_suffix = ld_suffix;
00891 const char *const full_nm_suffix = nm_suffix;
00892 const char *const full_gnm_suffix = gnm_suffix;
00893 #ifdef LDD_SUFFIX
00894 const char *const full_ldd_suffix = ldd_suffix;
00895 #endif
00896 const char *const full_strip_suffix = strip_suffix;
00897 const char *const full_gstrip_suffix = gstrip_suffix;
00898 #endif
00899
00900 const char *arg;
00901 FILE *outf;
00902 #ifdef COLLECT_EXPORT_LIST
00903 FILE *exportf;
00904 #endif
00905 const char *ld_file_name;
00906 const char *p;
00907 char **c_argv;
00908 const char **c_ptr;
00909 char **ld1_argv;
00910 const char **ld1;
00911 char **ld2_argv;
00912 const char **ld2;
00913 char **object_lst;
00914 const char **object;
00915 int first_file;
00916 int num_c_args = argc+9;
00917
00918 no_demangle = !! getenv ("COLLECT_NO_DEMANGLE");
00919
00920
00921 putenv (xstrdup ("COLLECT_NO_DEMANGLE="));
00922
00923 #if defined (COLLECT2_HOST_INITIALIZATION)
00924
00925 COLLECT2_HOST_INITIALIZATION;
00926 #endif
00927
00928 #ifdef SIGCHLD
00929
00930
00931 signal (SIGCHLD, SIG_DFL);
00932 #endif
00933
00934 gcc_init_libintl ();
00935
00936
00937
00938
00939 ld1 = (const char **)(ld1_argv = (char **) xcalloc(sizeof (char *), argc+3));
00940 ld2 = (const char **)(ld2_argv = (char **) xcalloc(sizeof (char *), argc+10));
00941 object = (const char **)(object_lst = (char **) xcalloc(sizeof (char *), argc));
00942
00943 #ifdef DEBUG
00944 debug = 1;
00945 #endif
00946
00947
00948
00949
00950 {
00951 int i;
00952
00953 for (i = 1; argv[i] != NULL; i ++)
00954 if (! strcmp (argv[i], "-debug"))
00955 debug = 1;
00956 vflag = debug;
00957 }
00958
00959 #ifndef DEFAULT_A_OUT_NAME
00960 output_file = "a.out";
00961 #else
00962 output_file = DEFAULT_A_OUT_NAME;
00963 #endif
00964
00965 obstack_begin (&temporary_obstack, 0);
00966 temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0);
00967
00968 current_demangling_style = auto_demangling;
00969 p = getenv ("COLLECT_GCC_OPTIONS");
00970 while (p && *p)
00971 {
00972 const char *q = extract_string (&p);
00973 if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
00974 num_c_args++;
00975 }
00976 obstack_free (&temporary_obstack, temporary_firstobj);
00977
00978
00979 num_c_args += 2;
00980
00981 c_ptr = (const char **)
00982 (c_argv = (char **) xcalloc (sizeof (char *), num_c_args));
00983
00984 if (argc < 2)
00985 fatal ("no arguments");
00986
00987 #ifdef SIGQUIT
00988 if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
00989 signal (SIGQUIT, handler);
00990 #endif
00991 if (signal (SIGINT, SIG_IGN) != SIG_IGN)
00992 signal (SIGINT, handler);
00993 #ifdef SIGALRM
00994 if (signal (SIGALRM, SIG_IGN) != SIG_IGN)
00995 signal (SIGALRM, handler);
00996 #endif
00997 #ifdef SIGHUP
00998 if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
00999 signal (SIGHUP, handler);
01000 #endif
01001 if (signal (SIGSEGV, SIG_IGN) != SIG_IGN)
01002 signal (SIGSEGV, handler);
01003 #ifdef SIGBUS
01004 if (signal (SIGBUS, SIG_IGN) != SIG_IGN)
01005 signal (SIGBUS, handler);
01006 #endif
01007
01008
01009 prefix_from_env ("COMPILER_PATH", &cpath);
01010 prefix_from_env ("PATH", &path);
01011
01012
01013
01014
01015 ld_file_name = 0;
01016 #ifdef DEFAULT_LINKER
01017 if (access (DEFAULT_LINKER, X_OK) == 0)
01018 ld_file_name = DEFAULT_LINKER;
01019 if (ld_file_name == 0)
01020 #endif
01021 #ifdef REAL_LD_FILE_NAME
01022 ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME);
01023 if (ld_file_name == 0)
01024 #endif
01025
01026 ld_file_name = find_a_file (&cpath, real_ld_suffix);
01027
01028 if (ld_file_name == 0)
01029 ld_file_name = find_a_file (&cpath, collect_ld_suffix);
01030
01031
01032 if (ld_file_name == 0)
01033 ld_file_name = find_a_file (&cpath, ld_suffix);
01034
01035
01036 if (ld_file_name == 0)
01037 ld_file_name = find_a_file (&path, full_ld_suffix);
01038
01039 #ifdef REAL_NM_FILE_NAME
01040 nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME);
01041 if (nm_file_name == 0)
01042 #endif
01043 nm_file_name = find_a_file (&cpath, gnm_suffix);
01044 if (nm_file_name == 0)
01045 nm_file_name = find_a_file (&path, full_gnm_suffix);
01046 if (nm_file_name == 0)
01047 nm_file_name = find_a_file (&cpath, nm_suffix);
01048 if (nm_file_name == 0)
01049 nm_file_name = find_a_file (&path, full_nm_suffix);
01050
01051 #ifdef LDD_SUFFIX
01052 ldd_file_name = find_a_file (&cpath, ldd_suffix);
01053 if (ldd_file_name == 0)
01054 ldd_file_name = find_a_file (&path, full_ldd_suffix);
01055 #endif
01056
01057 #ifdef REAL_STRIP_FILE_NAME
01058 strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME);
01059 if (strip_file_name == 0)
01060 #endif
01061 strip_file_name = find_a_file (&cpath, gstrip_suffix);
01062 if (strip_file_name == 0)
01063 strip_file_name = find_a_file (&path, full_gstrip_suffix);
01064 if (strip_file_name == 0)
01065 strip_file_name = find_a_file (&cpath, strip_suffix);
01066 if (strip_file_name == 0)
01067 strip_file_name = find_a_file (&path, full_strip_suffix);
01068
01069
01070 c_file_name = getenv ("COLLECT_GCC");
01071 if (c_file_name == 0)
01072 {
01073 #ifdef CROSS_COMPILE
01074 c_file_name = concat (target_machine, "-gcc", NULL);
01075 #else
01076 c_file_name = "gcc";
01077 #endif
01078 }
01079
01080 p = find_a_file (&cpath, c_file_name);
01081
01082
01083
01084 if (p == 0)
01085 p = find_a_file (&path, c_file_name);
01086
01087 if (p)
01088 c_file_name = p;
01089
01090 *ld1++ = *ld2++ = ld_file_name;
01091
01092
01093 c_file = make_temp_file (".c");
01094 o_file = make_temp_file (".o");
01095 #ifdef COLLECT_EXPORT_LIST
01096 export_file = make_temp_file (".x");
01097 #endif
01098 ldout = make_temp_file (".ld");
01099 *c_ptr++ = c_file_name;
01100 *c_ptr++ = "-x";
01101 *c_ptr++ = "c";
01102 *c_ptr++ = "-c";
01103 *c_ptr++ = "-o";
01104 *c_ptr++ = o_file;
01105
01106 #ifdef COLLECT_EXPORT_LIST
01107
01108 prefix_from_env ("LIBPATH", &libpath_lib_dirs);
01109
01110
01111 add_prefix (&libpath_lib_dirs, "/lib");
01112 add_prefix (&libpath_lib_dirs, "/usr/lib");
01113 #endif
01114
01115
01116
01117
01118
01119
01120 p = getenv ("COLLECT_GCC_OPTIONS");
01121 while (p && *p)
01122 {
01123 const char *q = extract_string (&p);
01124 if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
01125 *c_ptr++ = xstrdup (q);
01126 if (strcmp (q, "-EL") == 0 || strcmp (q, "-EB") == 0)
01127 *c_ptr++ = xstrdup (q);
01128 if (strcmp (q, "-shared") == 0)
01129 shared_obj = 1;
01130 if (*q == '-' && q[1] == 'B')
01131 {
01132 *c_ptr++ = xstrdup (q);
01133 if (q[2] == 0)
01134 {
01135 q = extract_string (&p);
01136 *c_ptr++ = xstrdup (q);
01137 }
01138 }
01139 }
01140 obstack_free (&temporary_obstack, temporary_firstobj);
01141 *c_ptr++ = "-fno-exceptions";
01142 *c_ptr++ = "-w";
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154 first_file = 1;
01155 while ((arg = *++argv) != (char *) 0)
01156 {
01157 *ld1++ = *ld2++ = arg;
01158
01159 if (arg[0] == '-')
01160 {
01161 switch (arg[1])
01162 {
01163 #ifdef COLLECT_EXPORT_LIST
01164
01165
01166 case 'b':
01167 if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0)
01168 export_flag = 1;
01169 else if (arg[2] == '6' && arg[3] == '4')
01170 aix64_flag = 1;
01171 break;
01172 #endif
01173
01174 case 'd':
01175 if (!strcmp (arg, "-debug"))
01176 {
01177
01178 ld1--;
01179 ld2--;
01180 }
01181 break;
01182
01183 case 'l':
01184 if (first_file)
01185 {
01186
01187 first_file = 0;
01188 ld2--;
01189 *ld2++ = o_file;
01190 *ld2++ = arg;
01191 }
01192 #ifdef COLLECT_EXPORT_LIST
01193 {
01194
01195 const char *s = resolve_lib_name (arg+2);
01196
01197
01198 add_to_list (&libs, s);
01199 }
01200 #endif
01201 break;
01202
01203 #ifdef COLLECT_EXPORT_LIST
01204
01205 case 'L':
01206 add_prefix (&cmdline_lib_dirs, arg+2);
01207 break;
01208 #else
01209 #if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
01210 case 'L':
01211 if (is_in_args (arg, (const char **) ld1_argv, ld1-1))
01212 --ld1;
01213 break;
01214 #endif
01215 #endif
01216
01217 case 'o':
01218 if (arg[2] == '\0')
01219 output_file = *ld1++ = *ld2++ = *++argv;
01220 else if (1
01221 #ifdef SWITCHES_NEED_SPACES
01222 && ! strchr (SWITCHES_NEED_SPACES, arg[1])
01223 #endif
01224 )
01225
01226 output_file = &arg[2];
01227 break;
01228
01229 case 'r':
01230 if (arg[2] == '\0')
01231 rflag = 1;
01232 break;
01233
01234 case 's':
01235 if (arg[2] == '\0' && do_collecting)
01236 {
01237
01238
01239
01240 strip_flag = 1;
01241 ld1--;
01242 }
01243 break;
01244
01245 case 'v':
01246 if (arg[2] == '\0')
01247 vflag = 1;
01248 break;
01249 }
01250 }
01251 else if ((p = strrchr (arg, '.')) != (char *) 0
01252 && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0
01253 || strcmp (p, ".so") == 0 || strcmp (p, ".lo") == 0
01254 || strcmp (p, ".obj") == 0))
01255 {
01256 if (first_file)
01257 {
01258 first_file = 0;
01259 if (p[1] == 'o')
01260 *ld2++ = o_file;
01261 else
01262 {
01263
01264 ld2--;
01265 *ld2++ = o_file;
01266 *ld2++ = arg;
01267 }
01268 }
01269 if (p[1] == 'o' || p[1] == 'l')
01270 *object++ = arg;
01271 #ifdef COLLECT_EXPORT_LIST
01272
01273 else
01274 {
01275
01276 add_to_list (&libs, arg);
01277 }
01278 #endif
01279 }
01280 }
01281
01282 #ifdef COLLECT_EXPORT_LIST
01283
01284 if (debug)
01285 {
01286 fprintf (stderr, "List of libraries:\n");
01287 dump_list (stderr, "\t", libs.first);
01288 }
01289
01290
01291
01292 {
01293 const char **export_object_lst = (const char **)object_lst;
01294
01295 while (export_object_lst < object)
01296 scan_prog_file (*export_object_lst++, PASS_OBJ);
01297 }
01298 {
01299 struct id *list = libs.first;
01300
01301 for (; list; list = list->next)
01302 scan_prog_file (list->name, PASS_FIRST);
01303 }
01304
01305 if (exports.first)
01306 {
01307 char *buf = concat ("-bE:", export_file, NULL);
01308
01309 *ld1++ = buf;
01310 *ld2++ = buf;
01311
01312 exportf = fopen (export_file, "w");
01313 if (exportf == (FILE *) 0)
01314 fatal_perror ("fopen %s", export_file);
01315 write_aix_file (exportf, exports.first);
01316 if (fclose (exportf))
01317 fatal_perror ("fclose %s", export_file);
01318 }
01319 #endif
01320
01321 *c_ptr++ = c_file;
01322 *c_ptr = *ld1 = *object = (char *) 0;
01323
01324 if (vflag)
01325 {
01326 notice ("collect2 version %s", version_string);
01327 #ifdef TARGET_VERSION
01328 TARGET_VERSION;
01329 #endif
01330 fprintf (stderr, "\n");
01331 }
01332
01333 if (debug)
01334 {
01335 const char *ptr;
01336 fprintf (stderr, "ld_file_name = %s\n",
01337 (ld_file_name ? ld_file_name : "not found"));
01338 fprintf (stderr, "c_file_name = %s\n",
01339 (c_file_name ? c_file_name : "not found"));
01340 fprintf (stderr, "nm_file_name = %s\n",
01341 (nm_file_name ? nm_file_name : "not found"));
01342 #ifdef LDD_SUFFIX
01343 fprintf (stderr, "ldd_file_name = %s\n",
01344 (ldd_file_name ? ldd_file_name : "not found"));
01345 #endif
01346 fprintf (stderr, "strip_file_name = %s\n",
01347 (strip_file_name ? strip_file_name : "not found"));
01348 fprintf (stderr, "c_file = %s\n",
01349 (c_file ? c_file : "not found"));
01350 fprintf (stderr, "o_file = %s\n",
01351 (o_file ? o_file : "not found"));
01352
01353 ptr = getenv ("COLLECT_GCC_OPTIONS");
01354 if (ptr)
01355 fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
01356
01357 ptr = getenv ("COLLECT_GCC");
01358 if (ptr)
01359 fprintf (stderr, "COLLECT_GCC = %s\n", ptr);
01360
01361 ptr = getenv ("COMPILER_PATH");
01362 if (ptr)
01363 fprintf (stderr, "COMPILER_PATH = %s\n", ptr);
01364
01365 ptr = getenv (LIBRARY_PATH_ENV);
01366 if (ptr)
01367 fprintf (stderr, "%-20s= %s\n", LIBRARY_PATH_ENV, ptr);
01368
01369 fprintf (stderr, "\n");
01370 }
01371
01372
01373
01374
01375
01376 #ifndef COLLECT_EXPORT_LIST
01377 do_tlink (ld1_argv, object_lst);
01378 #endif
01379
01380
01381
01382 if (rflag
01383 #ifndef COLLECT_EXPORT_LIST
01384 || ! do_collecting
01385 #endif
01386 )
01387 {
01388 #ifdef COLLECT_EXPORT_LIST
01389
01390 do_tlink (ld1_argv, object_lst);
01391
01392
01393 if (export_file != 0 && export_file[0])
01394 maybe_unlink (export_file);
01395 #endif
01396 maybe_unlink (c_file);
01397 maybe_unlink (o_file);
01398 return 0;
01399 }
01400
01401
01402
01403
01404
01405
01406 #ifndef COLLECT_EXPORT_LIST
01407 scan_prog_file (output_file, PASS_FIRST);
01408 #endif
01409
01410 #ifdef SCAN_LIBRARIES
01411 scan_libraries (output_file);
01412 #endif
01413
01414 if (debug)
01415 {
01416 notice ("%d constructor(s) found\n", constructors.number);
01417 notice ("%d destructor(s) found\n", destructors.number);
01418 notice ("%d frame table(s) found\n", frame_tables.number);
01419 }
01420
01421 if (constructors.number == 0 && destructors.number == 0
01422 && frame_tables.number == 0
01423 #if defined (SCAN_LIBRARIES) || defined (COLLECT_EXPORT_LIST)
01424
01425
01426
01427 && ! shared_obj
01428 #endif
01429 )
01430 {
01431 #ifdef COLLECT_EXPORT_LIST
01432
01433 do_tlink (ld1_argv, object_lst);
01434 #endif
01435
01436 if (strip_flag)
01437 {
01438 char **real_strip_argv = (char **) xcalloc (sizeof (char *), 3);
01439 const char ** strip_argv = (const char **) real_strip_argv;
01440
01441 strip_argv[0] = strip_file_name;
01442 strip_argv[1] = output_file;
01443 strip_argv[2] = (char *) 0;
01444 fork_execute ("strip", real_strip_argv);
01445 }
01446
01447 #ifdef COLLECT_EXPORT_LIST
01448 maybe_unlink (export_file);
01449 #endif
01450 maybe_unlink (c_file);
01451 maybe_unlink (o_file);
01452 return 0;
01453 }
01454
01455
01456 sort_ids (&constructors);
01457 sort_ids (&destructors);
01458
01459 maybe_unlink(output_file);
01460 outf = fopen (c_file, "w");
01461 if (outf == (FILE *) 0)
01462 fatal_perror ("fopen %s", c_file);
01463
01464 write_c_file (outf, c_file);
01465
01466 if (fclose (outf))
01467 fatal_perror ("fclose %s", c_file);
01468
01469
01470 #ifdef LD_INIT_SWITCH
01471 #ifdef COLLECT_EXPORT_LIST
01472 *ld2++ = concat (LD_INIT_SWITCH, ":", initname, ":", fininame, NULL);
01473 #else
01474 *ld2++ = LD_INIT_SWITCH;
01475 *ld2++ = initname;
01476 *ld2++ = LD_FINI_SWITCH;
01477 *ld2++ = fininame;
01478 #endif
01479 #endif
01480
01481 #ifdef COLLECT_EXPORT_LIST
01482 if (shared_obj)
01483 {
01484
01485
01486 if (! exports.first)
01487 *ld2++ = concat ("-bE:", export_file, NULL);
01488
01489 add_to_list (&exports, initname);
01490 add_to_list (&exports, fininame);
01491 add_to_list (&exports, "_GLOBAL__DI");
01492 add_to_list (&exports, "_GLOBAL__DD");
01493 exportf = fopen (export_file, "w");
01494 if (exportf == (FILE *) 0)
01495 fatal_perror ("fopen %s", export_file);
01496 write_aix_file (exportf, exports.first);
01497 if (fclose (exportf))
01498 fatal_perror ("fclose %s", export_file);
01499 }
01500 #endif
01501
01502
01503 *ld2 = (char*) 0;
01504
01505 if (debug)
01506 {
01507 fprintf (stderr, "\n========== output_file = %s, c_file = %s\n",
01508 output_file, c_file);
01509 write_c_file (stderr, "stderr");
01510 fprintf (stderr, "========== end of c_file\n\n");
01511 #ifdef COLLECT_EXPORT_LIST
01512 fprintf (stderr, "\n========== export_file = %s\n", export_file);
01513 write_aix_file (stderr, exports.first);
01514 fprintf (stderr, "========== end of export_file\n\n");
01515 #endif
01516 }
01517
01518
01519
01520
01521 fork_execute ("gcc", c_argv);
01522 #ifdef COLLECT_EXPORT_LIST
01523
01524 do_tlink (ld2_argv, object_lst);
01525 #else
01526
01527 fork_execute ("ld", ld2_argv);
01528
01529
01530
01531 scan_prog_file (output_file, PASS_SECOND);
01532 #endif
01533
01534 maybe_unlink (c_file);
01535 maybe_unlink (o_file);
01536
01537 #ifdef COLLECT_EXPORT_LIST
01538 maybe_unlink (export_file);
01539 #endif
01540
01541 return 0;
01542 }
01543
01544
01545
01546
01547 int
01548 collect_wait (prog)
01549 const char *prog;
01550 {
01551 int status;
01552
01553 pwait (pexecute_pid, &status, 0);
01554 if (status)
01555 {
01556 if (WIFSIGNALED (status))
01557 {
01558 int sig = WTERMSIG (status);
01559 error ("%s terminated with signal %d [%s]%s",
01560 prog, sig, strsignal(sig),
01561 WCOREDUMP(status) ? ", core dumped" : "");
01562 collect_exit (FATAL_EXIT_CODE);
01563 }
01564
01565 if (WIFEXITED (status))
01566 return WEXITSTATUS (status);
01567 }
01568 return 0;
01569 }
01570
01571 static void
01572 do_wait (prog)
01573 const char *prog;
01574 {
01575 int ret = collect_wait (prog);
01576 if (ret != 0)
01577 {
01578 error ("%s returned %d exit status", prog, ret);
01579 collect_exit (ret);
01580 }
01581 }
01582
01583
01584
01585
01586 void
01587 collect_execute (prog, argv, redir)
01588 const char *prog;
01589 char **argv;
01590 const char *redir;
01591 {
01592 char *errmsg_fmt;
01593 char *errmsg_arg;
01594 int redir_handle = -1;
01595 int stdout_save = -1;
01596 int stderr_save = -1;
01597
01598 if (vflag || debug)
01599 {
01600 char **p_argv;
01601 const char *str;
01602
01603 if (argv[0])
01604 fprintf (stderr, "%s", argv[0]);
01605 else
01606 notice ("[cannot find %s]", prog);
01607
01608 for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++)
01609 fprintf (stderr, " %s", str);
01610
01611 fprintf (stderr, "\n");
01612 }
01613
01614 fflush (stdout);
01615 fflush (stderr);
01616
01617
01618
01619
01620 if (argv[0] == 0)
01621 fatal ("cannot find `%s'", prog);
01622
01623 if (redir)
01624 {
01625
01626 redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT);
01627
01628
01629
01630 stdout_save = dup (STDOUT_FILENO);
01631 if (stdout_save == -1)
01632 fatal_perror ("redirecting stdout: %s", redir);
01633 stderr_save = dup (STDERR_FILENO);
01634 if (stderr_save == -1)
01635 fatal_perror ("redirecting stdout: %s", redir);
01636
01637
01638 dup2 (redir_handle, STDOUT_FILENO);
01639 dup2 (redir_handle, STDERR_FILENO);
01640 }
01641
01642 pexecute_pid = pexecute (argv[0], argv, argv[0], NULL,
01643 &errmsg_fmt, &errmsg_arg,
01644 (PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH));
01645
01646 if (redir)
01647 {
01648
01649 dup2 (stdout_save, STDOUT_FILENO);
01650 dup2 (stderr_save, STDERR_FILENO);
01651
01652
01653 close (redir_handle);
01654 }
01655
01656 if (pexecute_pid == -1)
01657 fatal_perror (errmsg_fmt, errmsg_arg);
01658 }
01659
01660 static void
01661 fork_execute (prog, argv)
01662 const char *prog;
01663 char **argv;
01664 {
01665 collect_execute (prog, argv, NULL);
01666 do_wait (prog);
01667 }
01668
01669
01670
01671 static void
01672 maybe_unlink (file)
01673 const char *file;
01674 {
01675 if (!debug)
01676 unlink (file);
01677 else
01678 notice ("[Leaving %s]\n", file);
01679 }
01680
01681
01682 static long sequence_number = 0;
01683
01684
01685
01686 static void
01687 add_to_list (head_ptr, name)
01688 struct head *head_ptr;
01689 const char *name;
01690 {
01691 struct id *newid
01692 = (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1);
01693 struct id *p;
01694 strcpy (newid->name, name);
01695
01696 if (head_ptr->first)
01697 head_ptr->last->next = newid;
01698 else
01699 head_ptr->first = newid;
01700
01701
01702 for (p = head_ptr->first;
01703 strcmp (name, p->name) != 0;
01704 p = p->next)
01705 ;
01706 if (p != newid)
01707 {
01708 head_ptr->last->next = 0;
01709 free (newid);
01710 return;
01711 }
01712
01713 newid->sequence = ++sequence_number;
01714 head_ptr->last = newid;
01715 head_ptr->number++;
01716 }
01717
01718
01719
01720
01721 static int
01722 extract_init_priority (name)
01723 const char *name;
01724 {
01725 int pos = 0, pri;
01726
01727 while (name[pos] == '_')
01728 ++pos;
01729 pos += 10;
01730
01731
01732 pri = atoi (name + pos);
01733 return pri ? pri : DEFAULT_INIT_PRIORITY;
01734 }
01735
01736
01737
01738
01739 static void
01740 sort_ids (head_ptr)
01741 struct head *head_ptr;
01742 {
01743
01744
01745
01746 struct id *id, *id_next, **id_ptr;
01747
01748 id = head_ptr->first;
01749
01750
01751 head_ptr->first = NULL;
01752
01753 for (; id; id = id_next)
01754 {
01755 id_next = id->next;
01756 id->sequence = extract_init_priority (id->name);
01757
01758 for (id_ptr = &(head_ptr->first); ; id_ptr = &((*id_ptr)->next))
01759 if (*id_ptr == NULL
01760
01761
01762 || id->sequence > (*id_ptr)->sequence
01763
01764
01765
01766 )
01767 {
01768 id->next = *id_ptr;
01769 *id_ptr = id;
01770 break;
01771 }
01772 }
01773
01774
01775 for (id = head_ptr->first; id; id = id->next)
01776 id->sequence = ++sequence_number;
01777 }
01778
01779
01780
01781 static void
01782 write_list (stream, prefix, list)
01783 FILE *stream;
01784 const char *prefix;
01785 struct id *list;
01786 {
01787 while (list)
01788 {
01789 fprintf (stream, "%sx%d,\n", prefix, list->sequence);
01790 list = list->next;
01791 }
01792 }
01793
01794 #if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
01795
01796
01797
01798 static int
01799 is_in_args (string, args_begin, args_end)
01800 const char *string;
01801 const char **args_begin;
01802 const char **args_end;
01803 {
01804 const char **args_pointer;
01805 for (args_pointer = args_begin; args_pointer != args_end; ++args_pointer)
01806 if (strcmp (string, *args_pointer) == 0)
01807 return 1;
01808 return 0;
01809 }
01810 #endif
01811
01812 #ifdef COLLECT_EXPORT_LIST
01813
01814 #if 0
01815 static int
01816 is_in_list (prefix, list)
01817 const char *prefix;
01818 struct id *list;
01819 {
01820 while (list)
01821 {
01822 if (!strcmp (prefix, list->name)) return 1;
01823 list = list->next;
01824 }
01825 return 0;
01826 }
01827 #endif
01828 #endif
01829
01830
01831 #ifdef COLLECT_EXPORT_LIST
01832 static void
01833 dump_list (stream, prefix, list)
01834 FILE *stream;
01835 const char *prefix;
01836 struct id *list;
01837 {
01838 while (list)
01839 {
01840 fprintf (stream, "%s%s,\n", prefix, list->name);
01841 list = list->next;
01842 }
01843 }
01844 #endif
01845
01846 #if 0
01847 static void
01848 dump_prefix_list (stream, prefix, list)
01849 FILE *stream;
01850 const char *prefix;
01851 struct prefix_list *list;
01852 {
01853 while (list)
01854 {
01855 fprintf (stream, "%s%s,\n", prefix, list->prefix);
01856 list = list->next;
01857 }
01858 }
01859 #endif
01860
01861 static void
01862 write_list_with_asm (stream, prefix, list)
01863 FILE *stream;
01864 const char *prefix;
01865 struct id *list;
01866 {
01867 while (list)
01868 {
01869 fprintf (stream, "%sx%d __asm__ (\"%s\");\n",
01870 prefix, list->sequence, list->name);
01871 list = list->next;
01872 }
01873 }
01874
01875
01876
01877
01878 static void
01879 write_c_file_stat (stream, name)
01880 FILE *stream;
01881 const char *name ATTRIBUTE_UNUSED;
01882 {
01883 const char *p, *q;
01884 char *prefix, *r;
01885 int frames = (frame_tables.number > 0);
01886
01887
01888 p = strrchr (output_file, '/');
01889 if (p == 0)
01890 p = output_file;
01891 else
01892 p++;
01893 q = p;
01894 while (q)
01895 {
01896 q = strchr (q,'.');
01897 if (q == 0)
01898 {
01899 q = p + strlen (p);
01900 break;
01901 }
01902 else
01903 {
01904 if (strncmp (q, ".so", 3) == 0)
01905 {
01906 q += 3;
01907 break;
01908 }
01909 else
01910 q++;
01911 }
01912 }
01913
01914 prefix = xmalloc (q - p + 1);
01915 strncpy (prefix, p, q - p);
01916 prefix[q - p] = 0;
01917 for (r = prefix; *r; r++)
01918 if (!ISALNUM ((unsigned char)*r))
01919 *r = '_';
01920 if (debug)
01921 notice ("\nwrite_c_file - output name is %s, prefix is %s\n",
01922 output_file, prefix);
01923
01924 initname = concat ("_GLOBAL__FI_", prefix, NULL);
01925 fininame = concat ("_GLOBAL__FD_", prefix, NULL);
01926
01927 free (prefix);
01928
01929
01930
01931 fprintf (stream, "static int count;\n");
01932 fprintf (stream, "typedef void entry_pt();\n");
01933 write_list_with_asm (stream, "extern entry_pt ", constructors.first);
01934
01935 if (frames)
01936 {
01937 write_list_with_asm (stream, "extern void *", frame_tables.first);
01938
01939 fprintf (stream, "\tstatic void *frame_table[] = {\n");
01940 write_list (stream, "\t\t&", frame_tables.first);
01941 fprintf (stream, "\t0\n};\n");
01942
01943
01944 fprintf (stream, "struct object {\n");
01945 fprintf (stream, " void *pc_begin;\n");
01946 fprintf (stream, " void *pc_end;\n");
01947 fprintf (stream, " void *fde_begin;\n");
01948 fprintf (stream, " void *fde_array;\n");
01949 fprintf (stream, " __SIZE_TYPE__ count;\n");
01950 fprintf (stream, " struct object *next;\n");
01951 fprintf (stream, "};\n");
01952
01953 fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
01954 fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
01955
01956 fprintf (stream, "static void reg_frame () {\n");
01957 fprintf (stream, "\tstatic struct object ob;\n");
01958 fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
01959 fprintf (stream, "\t}\n");
01960
01961 fprintf (stream, "static void dereg_frame () {\n");
01962 fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
01963 fprintf (stream, "\t}\n");
01964 }
01965
01966 fprintf (stream, "void %s() {\n", initname);
01967 if (constructors.number > 0 || frames)
01968 {
01969 fprintf (stream, "\tstatic entry_pt *ctors[] = {\n");
01970 write_list (stream, "\t\t", constructors.first);
01971 if (frames)
01972 fprintf (stream, "\treg_frame,\n");
01973 fprintf (stream, "\t};\n");
01974 fprintf (stream, "\tentry_pt **p;\n");
01975 fprintf (stream, "\tif (count++ != 0) return;\n");
01976 fprintf (stream, "\tp = ctors + %d;\n", constructors.number + frames);
01977 fprintf (stream, "\twhile (p > ctors) (*--p)();\n");
01978 }
01979 else
01980 fprintf (stream, "\t++count;\n");
01981 fprintf (stream, "}\n");
01982 write_list_with_asm (stream, "extern entry_pt ", destructors.first);
01983 fprintf (stream, "void %s() {\n", fininame);
01984 if (destructors.number > 0 || frames)
01985 {
01986 fprintf (stream, "\tstatic entry_pt *dtors[] = {\n");
01987 write_list (stream, "\t\t", destructors.first);
01988 if (frames)
01989 fprintf (stream, "\tdereg_frame,\n");
01990 fprintf (stream, "\t};\n");
01991 fprintf (stream, "\tentry_pt **p;\n");
01992 fprintf (stream, "\tif (--count != 0) return;\n");
01993 fprintf (stream, "\tp = dtors;\n");
01994 fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n",
01995 destructors.number + frames);
01996 }
01997 fprintf (stream, "}\n");
01998
01999 if (shared_obj)
02000 {
02001 COLLECT_SHARED_INIT_FUNC(stream, initname);
02002 COLLECT_SHARED_FINI_FUNC(stream, fininame);
02003 }
02004 }
02005
02006
02007
02008 #ifndef LD_INIT_SWITCH
02009 static void
02010 write_c_file_glob (stream, name)
02011 FILE *stream;
02012 const char *name ATTRIBUTE_UNUSED;
02013 {
02014
02015
02016 int frames = (frame_tables.number > 0);
02017
02018 fprintf (stream, "typedef void entry_pt();\n\n");
02019
02020 write_list_with_asm (stream, "extern entry_pt ", constructors.first);
02021
02022 if (frames)
02023 {
02024 write_list_with_asm (stream, "extern void *", frame_tables.first);
02025
02026 fprintf (stream, "\tstatic void *frame_table[] = {\n");
02027 write_list (stream, "\t\t&", frame_tables.first);
02028 fprintf (stream, "\t0\n};\n");
02029
02030
02031 fprintf (stream, "struct object {\n");
02032 fprintf (stream, " void *pc_begin;\n");
02033 fprintf (stream, " void *pc_end;\n");
02034 fprintf (stream, " void *fde_begin;\n");
02035 fprintf (stream, " void *fde_array;\n");
02036 fprintf (stream, " __SIZE_TYPE__ count;\n");
02037 fprintf (stream, " struct object *next;\n");
02038 fprintf (stream, "};\n");
02039
02040 fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
02041 fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
02042
02043 fprintf (stream, "static void reg_frame () {\n");
02044 fprintf (stream, "\tstatic struct object ob;\n");
02045 fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
02046 fprintf (stream, "\t}\n");
02047
02048 fprintf (stream, "static void dereg_frame () {\n");
02049 fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
02050 fprintf (stream, "\t}\n");
02051 }
02052
02053 fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
02054 fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number + frames);
02055 write_list (stream, "\t", constructors.first);
02056 if (frames)
02057 fprintf (stream, "\treg_frame,\n");
02058 fprintf (stream, "\t0\n};\n\n");
02059
02060 write_list_with_asm (stream, "extern entry_pt ", destructors.first);
02061
02062 fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
02063 fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number + frames);
02064 write_list (stream, "\t", destructors.first);
02065 if (frames)
02066 fprintf (stream, "\tdereg_frame,\n");
02067 fprintf (stream, "\t0\n};\n\n");
02068
02069 fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
02070 fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);
02071 }
02072 #endif
02073
02074 static void
02075 write_c_file (stream, name)
02076 FILE *stream;
02077 const char *name;
02078 {
02079 fprintf (stream, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
02080 #ifndef LD_INIT_SWITCH
02081 if (! shared_obj)
02082 write_c_file_glob (stream, name);
02083 else
02084 #endif
02085 write_c_file_stat (stream, name);
02086 fprintf (stream, "#ifdef __cplusplus\n}\n#endif\n");
02087 }
02088
02089 #ifdef COLLECT_EXPORT_LIST
02090 static void
02091 write_aix_file (stream, list)
02092 FILE *stream;
02093 struct id *list;
02094 {
02095 for (; list; list = list->next)
02096 {
02097 fputs (list->name, stream);
02098 putc ('\n', stream);
02099 }
02100 }
02101 #endif
02102
02103 #ifdef OBJECT_FORMAT_NONE
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114 static void
02115 scan_prog_file (prog_name, which_pass)
02116 const char *prog_name;
02117 enum pass which_pass;
02118 {
02119 void (*int_handler) PARAMS ((int));
02120 void (*quit_handler) PARAMS ((int));
02121 char *real_nm_argv[4];
02122 const char **nm_argv = (const char **) real_nm_argv;
02123 int pid;
02124 int argc = 0;
02125 int pipe_fd[2];
02126 char *p, buf[1024];
02127 FILE *inf;
02128
02129 if (which_pass == PASS_SECOND)
02130 return;
02131
02132
02133 if (nm_file_name == 0)
02134 fatal ("cannot find `nm'");
02135
02136 nm_argv[argc++] = nm_file_name;
02137 if (NM_FLAGS[0] != '\0')
02138 nm_argv[argc++] = NM_FLAGS;
02139
02140 nm_argv[argc++] = prog_name;
02141 nm_argv[argc++] = (char *) 0;
02142
02143 if (pipe (pipe_fd) < 0)
02144 fatal_perror ("pipe");
02145
02146 inf = fdopen (pipe_fd[0], "r");
02147 if (inf == (FILE *) 0)
02148 fatal_perror ("fdopen");
02149
02150
02151 if (vflag)
02152 {
02153 const char **p_argv;
02154 const char *str;
02155
02156 for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
02157 fprintf (stderr, " %s", str);
02158
02159 fprintf (stderr, "\n");
02160 }
02161
02162 fflush (stdout);
02163 fflush (stderr);
02164
02165
02166 pid = vfork ();
02167 if (pid == -1)
02168 fatal_perror (VFORK_STRING);
02169
02170 if (pid == 0)
02171 {
02172
02173 if (dup2 (pipe_fd[1], 1) < 0)
02174 fatal_perror ("dup2 %d 1", pipe_fd[1]);
02175
02176 if (close (pipe_fd[0]) < 0)
02177 fatal_perror ("close %d", pipe_fd[0]);
02178
02179 if (close (pipe_fd[1]) < 0)
02180 fatal_perror ("close %d", pipe_fd[1]);
02181
02182 execv (nm_file_name, real_nm_argv);
02183 fatal_perror ("execv %s", nm_file_name);
02184 }
02185
02186
02187 int_handler = (void (*) PARAMS ((int))) signal (SIGINT, SIG_IGN);
02188 #ifdef SIGQUIT
02189 quit_handler = (void (*) PARAMS ((int))) signal (SIGQUIT, SIG_IGN);
02190 #endif
02191
02192 if (close (pipe_fd[1]) < 0)
02193 fatal_perror ("close %d", pipe_fd[1]);
02194
02195 if (debug)
02196 fprintf (stderr, "\nnm output with constructors/destructors.\n");
02197
02198
02199 while (fgets (buf, sizeof buf, inf) != (char *) 0)
02200 {
02201 int ch, ch2;
02202 char *name, *end;
02203
02204
02205
02206
02207 for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
02208 if (ch == ' ' && p[1] == 'U' && p[2] == ' ')
02209 break;
02210
02211 if (ch != '_')
02212 continue;
02213
02214 name = p;
02215
02216
02217 for (end = p; (ch2 = *end) != '\0' && !ISSPACE (ch2) && ch2 != '|';
02218 end++)
02219 continue;
02220
02221
02222 *end = '\0';
02223 switch (is_ctor_dtor (name))
02224 {
02225 case 1:
02226 if (which_pass != PASS_LIB)
02227 add_to_list (&constructors, name);
02228 break;
02229
02230 case 2:
02231 if (which_pass != PASS_LIB)
02232 add_to_list (&destructors, name);
02233 break;
02234
02235 case 3:
02236 if (which_pass != PASS_LIB)
02237 fatal ("init function found in object %s", prog_name);
02238 #ifndef LD_INIT_SWITCH
02239 add_to_list (&constructors, name);
02240 #endif
02241 break;
02242
02243 case 4:
02244 if (which_pass != PASS_LIB)
02245 fatal ("fini function found in object %s", prog_name);
02246 #ifndef LD_FINI_SWITCH
02247 add_to_list (&destructors, name);
02248 #endif
02249 break;
02250
02251 case 5:
02252 if (which_pass != PASS_LIB)
02253 add_to_list (&frame_tables, name);
02254 break;
02255
02256 default:
02257 continue;
02258 }
02259
02260 if (debug)
02261 fprintf (stderr, "\t%s\n", buf);
02262 }
02263
02264 if (debug)
02265 fprintf (stderr, "\n");
02266
02267 if (fclose (inf) != 0)
02268 fatal_perror ("fclose");
02269
02270 do_wait (nm_file_name);
02271
02272 signal (SIGINT, int_handler);
02273 #ifdef SIGQUIT
02274 signal (SIGQUIT, quit_handler);
02275 #endif
02276 }
02277
02278 #if SUNOS4_SHARED_LIBRARIES
02279
02280
02281
02282
02283
02284 #include <a.out.h>
02285 #include <fcntl.h>
02286 #include <link.h>
02287 #include <sys/mman.h>
02288 #include <sys/param.h>
02289 #include <unistd.h>
02290 #include <sys/dir.h>
02291
02292
02293 unsigned object;
02294 unsigned objsize;
02295 char * code;
02296 char * data;
02297 struct nlist *symtab;
02298 struct link_dynamic *ld;
02299 struct link_dynamic_2 *ld_2;
02300 struct head libraries;
02301
02302
02303
02304 static void mapfile PARAMS ((const char *));
02305
02306 static void
02307 mapfile (name)
02308 const char *name;
02309 {
02310 int fp;
02311 struct stat s;
02312 if ((fp = open (name, O_RDONLY)) == -1)
02313 fatal ("unable to open file '%s'", name);
02314 if (fstat (fp, &s) == -1)
02315 fatal ("unable to stat file '%s'", name);
02316
02317 objsize = s.st_size;
02318 object = (unsigned) mmap (0, objsize, PROT_READ|PROT_WRITE, MAP_PRIVATE,
02319 fp, 0);
02320 if (object == (unsigned)-1)
02321 fatal ("unable to mmap file '%s'", name);
02322
02323 close (fp);
02324 }
02325
02326
02327
02328 static const char *libname;
02329
02330 static int libselect PARAMS ((struct direct *));
02331
02332 static int
02333 libselect (d)
02334 struct direct *d;
02335 {
02336 return (strncmp (libname, d->d_name, strlen (libname)) == 0);
02337 }
02338
02339
02340
02341
02342
02343
02344
02345
02346 static int libcompare PARAMS ((struct direct **, struct direct **));
02347
02348 static int
02349 libcompare (d1, d2)
02350 struct direct **d1, **d2;
02351 {
02352 int i1, i2 = strlen (libname);
02353 char *e1 = (*d1)->d_name + i2;
02354 char *e2 = (*d2)->d_name + i2;
02355
02356 while (*e1 && *e2 && *e1 == '.' && *e2 == '.'
02357 && e1[1] && ISDIGIT (e1[1]) && e2[1] && ISDIGIT (e2[1]))
02358 {
02359 ++e1;
02360 ++e2;
02361 i1 = strtol (e1, &e1, 10);
02362 i2 = strtol (e2, &e2, 10);
02363 if (i1 != i2)
02364 return i1 - i2;
02365 }
02366
02367 if (*e1)
02368 {
02369
02370 if (*e1 == '.' && e1[1] && ISDIGIT (e1[1]))
02371 return 1;
02372
02373 else
02374 return -1;
02375 }
02376 else if (*e2)
02377 {
02378
02379 if (*e2 == '.' && e2[1] && ISDIGIT (e2[1]))
02380 return -1;
02381
02382 else
02383 return 1;
02384 }
02385 else
02386 return 0;
02387 }
02388
02389
02390
02391 static void locatelib PARAMS ((const char *));
02392
02393 static void
02394 locatelib (name)
02395 const char *name;
02396 {
02397 static const char **l;
02398 static int cnt;
02399 char buf[MAXPATHLEN];
02400 char *p, *q;
02401 const char **pp;
02402
02403 if (l == 0)
02404 {
02405 char *ld_rules;
02406 char *ldr = 0;
02407
02408 cnt = 1;
02409 ld_rules = (char *) (ld_2->ld_rules + code);
02410 if (ld_rules)
02411 {
02412 cnt++;
02413 for (; *ld_rules != 0; ld_rules++)
02414 if (*ld_rules == ':')
02415 cnt++;
02416 ld_rules = (char *) (ld_2->ld_rules + code);
02417 ldr = xstrdup (ld_rules);
02418 }
02419 p = getenv ("LD_LIBRARY_PATH");
02420 q = 0;
02421 if (p)
02422 {
02423 cnt++;
02424 for (q = p ; *q != 0; q++)
02425 if (*q == ':')
02426 cnt++;
02427 q = xstrdup (p);
02428 }
02429 l = (const char **) xmalloc ((cnt + 3) * sizeof (char *));
02430 pp = l;
02431 if (ldr)
02432 {
02433 *pp++ = ldr;
02434 for (; *ldr != 0; ldr++)
02435 if (*ldr == ':')
02436 {
02437 *ldr++ = 0;
02438 *pp++ = ldr;
02439 }
02440 }
02441 if (q)
02442 {
02443 *pp++ = q;
02444 for (; *q != 0; q++)
02445 if (*q == ':')
02446 {
02447 *q++ = 0;
02448 *pp++ = q;
02449 }
02450 }
02451
02452 *pp++ = "/lib";
02453 *pp++ = "/usr/lib";
02454 *pp++ = "/usr/local/lib";
02455 *pp = 0;
02456 }
02457 libname = name;
02458 for (pp = l; *pp != 0 ; pp++)
02459 {
02460 struct direct **namelist;
02461 int entries;
02462 if ((entries = scandir (*pp, &namelist, libselect, libcompare)) > 0)
02463 {
02464 sprintf (buf, "%s/%s", *pp, namelist[entries - 1]->d_name);
02465 add_to_list (&libraries, buf);
02466 if (debug)
02467 fprintf (stderr, "%s\n", buf);
02468 break;
02469 }
02470 }
02471 if (*pp == 0)
02472 {
02473 if (debug)
02474 notice ("not found\n");
02475 else
02476 fatal ("dynamic dependency %s not found", name);
02477 }
02478 }
02479
02480
02481
02482
02483 static void
02484 scan_libraries (prog_name)
02485 const char *prog_name;
02486 {
02487 struct exec *header;
02488 char *base;
02489 struct link_object *lo;
02490 char buff[MAXPATHLEN];
02491 struct id *list;
02492
02493 mapfile (prog_name);
02494 header = (struct exec *)object;
02495 if (N_BADMAG (*header))
02496 fatal ("bad magic number in file '%s'", prog_name);
02497 if (header->a_dynamic == 0)
02498 return;
02499
02500 code = (char *) (N_TXTOFF (*header) + (long) header);
02501 data = (char *) (N_DATOFF (*header) + (long) header);
02502 symtab = (struct nlist *) (N_SYMOFF (*header) + (long) header);
02503
02504 if (header->a_magic == ZMAGIC && header->a_entry == 0x20)
02505 {
02506
02507 ld = (struct link_dynamic *) (symtab->n_value + code);
02508 base = code;
02509 }
02510 else
02511 {
02512
02513 ld = (struct link_dynamic *) data;
02514 base = code-PAGSIZ;
02515 }
02516
02517 if (debug)
02518 notice ("dynamic dependencies.\n");
02519
02520 ld_2 = (struct link_dynamic_2 *) ((long) ld->ld_un.ld_2 + (long)base);
02521 for (lo = (struct link_object *) ld_2->ld_need; lo;
02522 lo = (struct link_object *) lo->lo_next)
02523 {
02524 char *name;
02525 lo = (struct link_object *) ((long) lo + code);
02526 name = (char *) (code + lo->lo_name);
02527 if (lo->lo_library)
02528 {
02529 if (debug)
02530 fprintf (stderr, "\t-l%s.%d => ", name, lo->lo_major);
02531 sprintf (buff, "lib%s.so.%d.%d", name, lo->lo_major, lo->lo_minor);
02532 locatelib (buff);
02533 }
02534 else
02535 {
02536 if (debug)
02537 fprintf (stderr, "\t%s\n", name);
02538 add_to_list (&libraries, name);
02539 }
02540 }
02541
02542 if (debug)
02543 fprintf (stderr, "\n");
02544
02545
02546
02547 for (list = libraries.first; list; list = list->next)
02548 scan_prog_file (list->name, PASS_LIB);
02549 }
02550
02551 #else
02552 #ifdef LDD_SUFFIX
02553
02554
02555
02556
02557
02558 static void
02559 scan_libraries (prog_name)
02560 const char *prog_name;
02561 {
02562 static struct head libraries;
02563 struct id *list;
02564 void (*int_handler) PARAMS ((int));
02565 void (*quit_handler) PARAMS ((int));
02566 char *real_ldd_argv[4];
02567 const char **ldd_argv = (const char **) real_ldd_argv;
02568 int pid;
02569 int argc = 0;
02570 int pipe_fd[2];
02571 char buf[1024];
02572 FILE *inf;
02573
02574
02575 if (ldd_file_name == 0)
02576 {
02577 error ("cannot find `ldd'");
02578 return;
02579 }
02580
02581 ldd_argv[argc++] = ldd_file_name;
02582 ldd_argv[argc++] = prog_name;
02583 ldd_argv[argc++] = (char *) 0;
02584
02585 if (pipe (pipe_fd) < 0)
02586 fatal_perror ("pipe");
02587
02588 inf = fdopen (pipe_fd[0], "r");
02589 if (inf == (FILE *) 0)
02590 fatal_perror ("fdopen");
02591
02592
02593 if (vflag)
02594 {
02595 const char **p_argv;
02596 const char *str;
02597
02598 for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
02599 fprintf (stderr, " %s", str);
02600
02601 fprintf (stderr, "\n");
02602 }
02603
02604 fflush (stdout);
02605 fflush (stderr);
02606
02607
02608 pid = vfork ();
02609 if (pid == -1)
02610 fatal_perror (VFORK_STRING);
02611
02612 if (pid == 0)
02613 {
02614
02615 if (dup2 (pipe_fd[1], 1) < 0)
02616 fatal_perror ("dup2 %d 1", pipe_fd[1]);
02617
02618 if (close (pipe_fd[0]) < 0)
02619 fatal_perror ("close %d", pipe_fd[0]);
02620
02621 if (close (pipe_fd[1]) < 0)
02622 fatal_perror ("close %d", pipe_fd[1]);
02623
02624 execv (ldd_file_name, real_ldd_argv);
02625 fatal_perror ("execv %s", ldd_file_name);
02626 }
02627
02628
02629 int_handler = (void (*) PARAMS ((int))) signal (SIGINT, SIG_IGN);
02630 #ifdef SIGQUIT
02631 quit_handler = (void (*) PARAMS ((int))) signal (SIGQUIT, SIG_IGN);
02632 #endif
02633
02634 if (close (pipe_fd[1]) < 0)
02635 fatal_perror ("close %d", pipe_fd[1]);
02636
02637 if (debug)
02638 notice ("\nldd output with constructors/destructors.\n");
02639
02640
02641 while (fgets (buf, sizeof buf, inf) != (char *) 0)
02642 {
02643 int ch2;
02644 char *name, *end, *p = buf;
02645
02646
02647 PARSE_LDD_OUTPUT (p);
02648 if (p == 0)
02649 continue;
02650
02651 name = p;
02652 if (strncmp (name, "not found", sizeof ("not found") - 1) == 0)
02653 fatal ("dynamic dependency %s not found", buf);
02654
02655
02656 for (end = p;
02657 (ch2 = *end) != '\0' && ch2 != '\n' && !ISSPACE (ch2) && ch2 != '|';
02658 end++)
02659 continue;
02660 *end = '\0';
02661
02662 if (access (name, R_OK) == 0)
02663 add_to_list (&libraries, name);
02664 else
02665 fatal ("unable to open dynamic dependency '%s'", buf);
02666
02667 if (debug)
02668 fprintf (stderr, "\t%s\n", buf);
02669 }
02670 if (debug)
02671 fprintf (stderr, "\n");
02672
02673 if (fclose (inf) != 0)
02674 fatal_perror ("fclose");
02675
02676 do_wait (ldd_file_name);
02677
02678 signal (SIGINT, int_handler);
02679 #ifdef SIGQUIT
02680 signal (SIGQUIT, quit_handler);
02681 #endif
02682
02683
02684
02685 for (list = libraries.first; list; list = list->next)
02686 scan_prog_file (list->name, PASS_LIB);
02687 }
02688
02689 #endif
02690 #endif
02691
02692 #endif
02693
02694
02695
02696
02697
02698
02699 #ifdef OBJECT_FORMAT_COFF
02700
02701 #if defined(EXTENDED_COFF)
02702
02703 # define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
02704 # define GCC_SYMENT SYMR
02705 # define GCC_OK_SYMBOL(X) ((X).st == stProc || (X).st == stGlobal)
02706 # define GCC_SYMINC(X) (1)
02707 # define GCC_SYMZERO(X) (SYMHEADER(X).isymMax)
02708 # define GCC_CHECK_HDR(X) (PSYMTAB(X) != 0)
02709
02710 #else
02711
02712 # define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms)
02713 # define GCC_SYMENT SYMENT
02714 # define GCC_OK_SYMBOL(X) \
02715 (((X).n_sclass == C_EXT) && \
02716 ((X).n_scnum > N_UNDEF) && \
02717 (aix64_flag \
02718 || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
02719 || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
02720 # define GCC_UNDEF_SYMBOL(X) \
02721 (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF))
02722 # define GCC_SYMINC(X) ((X).n_numaux+1)
02723 # define GCC_SYMZERO(X) 0
02724
02725
02726 #ifdef _AIX51
02727 # define GCC_CHECK_HDR(X) \
02728 ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
02729 || (HEADER (X).f_magic == 0767 && aix64_flag))
02730 #else
02731 # define GCC_CHECK_HDR(X) \
02732 ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
02733 || (HEADER (X).f_magic == 0757 && aix64_flag))
02734 #endif
02735
02736 #endif
02737
02738 extern char *ldgetname ();
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749 static void
02750 scan_prog_file (prog_name, which_pass)
02751 const char *prog_name;
02752 enum pass which_pass;
02753 {
02754 LDFILE *ldptr = NULL;
02755 int sym_index, sym_count;
02756 int is_shared = 0;
02757
02758 if (which_pass != PASS_FIRST && which_pass != PASS_OBJ)
02759 return;
02760
02761 #ifdef COLLECT_EXPORT_LIST
02762
02763 if (which_pass == PASS_FIRST && ignore_library (prog_name))
02764 return;
02765
02766
02767
02768
02769 do
02770 {
02771 #endif
02772
02773
02774
02775
02776 if ((ldptr = ldopen ((char *)prog_name, ldptr)) != NULL)
02777 {
02778 if (! MY_ISCOFF (HEADER (ldptr).f_magic))
02779 fatal ("%s: not a COFF file", prog_name);
02780
02781 if (GCC_CHECK_HDR (ldptr))
02782 {
02783 sym_count = GCC_SYMBOLS (ldptr);
02784 sym_index = GCC_SYMZERO (ldptr);
02785
02786 #ifdef COLLECT_EXPORT_LIST
02787
02788 is_shared = HEADER (ldptr).f_flags & F_SHROBJ;
02789 #endif
02790
02791 while (sym_index < sym_count)
02792 {
02793 GCC_SYMENT symbol;
02794
02795 if (ldtbread (ldptr, sym_index, &symbol) <= 0)
02796 break;
02797 sym_index += GCC_SYMINC (symbol);
02798
02799 if (GCC_OK_SYMBOL (symbol))
02800 {
02801 char *name;
02802
02803 if ((name = ldgetname (ldptr, &symbol)) == NULL)
02804 continue;
02805
02806 #ifdef XCOFF_DEBUGGING_INFO
02807
02808
02809 if (*name == '.')
02810 ++name;
02811 #endif
02812
02813 switch (is_ctor_dtor (name))
02814 {
02815 case 1:
02816 if (! is_shared)
02817 add_to_list (&constructors, name);
02818 #ifdef COLLECT_EXPORT_LIST
02819 if (which_pass == PASS_OBJ)
02820 add_to_list (&exports, name);
02821 #endif
02822 break;
02823
02824 case 2:
02825 if (! is_shared)
02826 add_to_list (&destructors, name);
02827 #ifdef COLLECT_EXPORT_LIST
02828 if (which_pass == PASS_OBJ)
02829 add_to_list (&exports, name);
02830 #endif
02831 break;
02832
02833 #ifdef COLLECT_EXPORT_LIST
02834 case 3:
02835 #ifndef LD_INIT_SWITCH
02836 if (is_shared)
02837 add_to_list (&constructors, name);
02838 #endif
02839 break;
02840
02841 case 4:
02842 #ifndef LD_INIT_SWITCH
02843 if (is_shared)
02844 add_to_list (&destructors, name);
02845 #endif
02846 break;
02847 #endif
02848
02849 case 5:
02850 if (! is_shared)
02851 add_to_list (&frame_tables, name);
02852 #ifdef COLLECT_EXPORT_LIST
02853 if (which_pass == PASS_OBJ)
02854 add_to_list (&exports, name);
02855 #endif
02856 break;
02857
02858 default:
02859 #ifdef COLLECT_EXPORT_LIST
02860
02861
02862 if (shared_obj)
02863 {
02864 if (which_pass == PASS_OBJ && (! export_flag))
02865 add_to_list (&exports, name);
02866 }
02867 #endif
02868 continue;
02869 }
02870
02871 if (debug)
02872 #if !defined(EXTENDED_COFF)
02873 fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
02874 symbol.n_scnum, symbol.n_sclass,
02875 (symbol.n_type ? "0" : ""), symbol.n_type,
02876 name);
02877 #else
02878 fprintf (stderr,
02879 "\tiss = %5d, value = %5ld, index = %5d, name = %s\n",
02880 symbol.iss, (long) symbol.value, symbol.index, name);
02881 #endif
02882 }
02883 }
02884 }
02885 #ifdef COLLECT_EXPORT_LIST
02886 else
02887 {
02888
02889
02890 if (debug)
02891 fprintf (stderr, "%s : magic=%o aix64=%d mismatch\n",
02892 prog_name, HEADER (ldptr).f_magic, aix64_flag);
02893 }
02894 #endif
02895 }
02896 else
02897 {
02898 fatal ("%s: cannot open as COFF file", prog_name);
02899 }
02900 #ifdef COLLECT_EXPORT_LIST
02901
02902 }
02903 while (ldclose (ldptr) == FAILURE);
02904 #else
02905
02906 (void) ldclose(ldptr);
02907 #endif
02908 }
02909 #endif
02910
02911 #ifdef COLLECT_EXPORT_LIST
02912
02913
02914 static char *
02915 resolve_lib_name (name)
02916 const char *name;
02917 {
02918 char *lib_buf;
02919 int i, j, l = 0;
02920
02921 for (i = 0; libpaths[i]; i++)
02922 if (libpaths[i]->max_len > l)
02923 l = libpaths[i]->max_len;
02924
02925 lib_buf = xmalloc (l + strlen(name) + 10);
02926
02927 for (i = 0; libpaths[i]; i++)
02928 {
02929 struct prefix_list *list = libpaths[i]->plist;
02930 for (; list; list = list->next)
02931 {
02932
02933
02934
02935 const char *p = "";
02936 if (list->prefix[strlen(list->prefix)-1] != '/')
02937 p = "/";
02938 for (j = 0; libexts[j]; j++)
02939 {
02940 sprintf (lib_buf, "%s%slib%s.%s",
02941 list->prefix, p, name, libexts[j]);
02942 if (debug) fprintf (stderr, "searching for: %s\n", lib_buf);
02943 if (file_exists (lib_buf))
02944 {
02945 if (debug) fprintf (stderr, "found: %s\n", lib_buf);
02946 return (lib_buf);
02947 }
02948 }
02949 }
02950 }
02951 if (debug)
02952 fprintf (stderr, "not found\n");
02953 else
02954 fatal ("library lib%s not found", name);
02955 return (NULL);
02956 }
02957
02958
02959
02960 static const char *const aix_std_libs[] = {
02961 "/unix",
02962 "/lib/libc.a",
02963 "/lib/libm.a",
02964 "/lib/libc_r.a",
02965 "/lib/libm_r.a",
02966 "/usr/lib/libc.a",
02967 "/usr/lib/libm.a",
02968 "/usr/lib/libc_r.a",
02969 "/usr/lib/libm_r.a",
02970 "/usr/lib/threads/libc.a",
02971 "/usr/ccs/lib/libc.a",
02972 "/usr/ccs/lib/libm.a",
02973 "/usr/ccs/lib/libc_r.a",
02974 "/usr/ccs/lib/libm_r.a",
02975 NULL
02976 };
02977
02978
02979
02980 static int
02981 ignore_library (name)
02982 const char *name;
02983 {
02984 const char *const *p = &aix_std_libs[0];
02985 while (*p++ != NULL)
02986 if (! strcmp (name, *p)) return 1;
02987 return 0;
02988 }
02989 #endif
02990
02991
02992
02993
02994
02995
02996 #ifdef OBJECT_FORMAT_ROSE
02997
02998
02999
03000 typedef union load_union
03001 {
03002 ldc_header_t hdr;
03003 load_cmd_map_command_t map;
03004 interpreter_command_t iprtr;
03005 strings_command_t str;
03006 region_command_t region;
03007 reloc_command_t reloc;
03008 package_command_t pkg;
03009 symbols_command_t sym;
03010 entry_command_t ent;
03011 gen_info_command_t info;
03012 func_table_command_t func;
03013 } load_union_t;
03014
03015
03016
03017 typedef struct load_all
03018 {
03019 load_union_t *load;
03020 char *section;
03021 } load_all_t;
03022
03023
03024
03025 struct file_info
03026 {
03027 char *start;
03028 char *name;
03029 long size;
03030 long rounded_size;
03031 int fd;
03032 int rw;
03033 int use_mmap;
03034 };
03035
03036 extern int decode_mach_o_hdr ();
03037 extern int encode_mach_o_hdr ();
03038
03039 static void add_func_table PARAMS ((mo_header_t *, load_all_t *,
03040 symbol_info_t *, int));
03041 static void print_header PARAMS ((mo_header_t *));
03042 static void print_load_command PARAMS ((load_union_t *, size_t, int));
03043 static void bad_header PARAMS ((int));
03044 static struct file_info *read_file PARAMS ((const char *, int, int));
03045 static void end_file PARAMS ((struct file_info *));
03046
03047
03048
03049
03050
03051
03052
03053
03054
03055
03056
03057 static void
03058 scan_prog_file (prog_name, which_pass)
03059 const char *prog_name;
03060 enum pass which_pass;
03061 {
03062 char *obj;
03063 mo_header_t hdr;
03064 load_all_t *load_array;
03065 load_all_t *load_end;
03066 load_all_t *load_cmd;
03067 int symbol_load_cmds;
03068 off_t offset;
03069 int i;
03070 int num_syms;
03071 int status;
03072 char *str_sect;
03073 struct file_info *obj_file;
03074 int prog_fd;
03075 mo_lcid_t cmd_strings = -1;
03076 symbol_info_t *main_sym = 0;
03077 int rw = (which_pass != PASS_FIRST);
03078
03079 prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY);
03080 if (prog_fd < 0)
03081 fatal_perror ("open %s", prog_name);
03082
03083 obj_file = read_file (prog_name, prog_fd, rw);
03084 obj = obj_file->start;
03085
03086 status = decode_mach_o_hdr (obj, MO_SIZEOF_RAW_HDR, MOH_HEADER_VERSION, &hdr);
03087 if (status != MO_HDR_CONV_SUCCESS)
03088 bad_header (status);
03089
03090
03091
03092
03093
03094
03095 #ifndef CROSS_COMPILE
03096 if (hdr.moh_magic != MOH_MAGIC_MSB
03097 || hdr.moh_header_version != MOH_HEADER_VERSION
03098 || hdr.moh_byte_order != OUR_BYTE_ORDER
03099 || hdr.moh_data_rep_id != OUR_DATA_REP_ID
03100 || hdr.moh_cpu_type != OUR_CPU_TYPE
03101 || hdr.moh_cpu_subtype != OUR_CPU_SUBTYPE
03102 || hdr.moh_vendor_type != OUR_VENDOR_TYPE)
03103 {
03104 fatal ("incompatibilities between object file & expected values");
03105 }
03106 #endif
03107
03108 if (debug)
03109 print_header (&hdr);
03110
03111 offset = hdr.moh_first_cmd_off;
03112 load_end = load_array
03113 = (load_all_t *) xcalloc (sizeof (load_all_t), hdr.moh_n_load_cmds + 2);
03114
03115
03116 for (i = 0; i < hdr.moh_n_load_cmds; i++)
03117 {
03118 load_union_t *load_hdr;
03119
03120 load_cmd = load_end++;
03121 load_hdr = (load_union_t *) (obj + offset);
03122
03123
03124 if (rw)
03125 {
03126 load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size);
03127 memcpy ((char *)ptr, (char *)load_hdr, load_hdr->hdr.ldci_cmd_size);
03128 load_hdr = ptr;
03129
03130
03131 if (ptr->hdr.ldci_cmd_type == LDC_CMD_MAP)
03132 {
03133 cmd_strings = ptr->map.lcm_ld_cmd_strings;
03134 ptr->hdr.ldci_cmd_type = LDC_UNDEFINED;
03135 }
03136 }
03137
03138 load_cmd->load = load_hdr;
03139 if (load_hdr->hdr.ldci_section_off > 0)
03140 load_cmd->section = obj + load_hdr->hdr.ldci_section_off;
03141
03142 if (debug)
03143 print_load_command (load_hdr, offset, i);
03144
03145 offset += load_hdr->hdr.ldci_cmd_size;
03146 }
03147
03148
03149
03150 if (rw && load_end[-1].load->hdr.ldci_cmd_type == LDC_UNDEFINED)
03151 {
03152 load_end--;
03153 hdr.moh_n_load_cmds--;
03154 }
03155
03156
03157 symbol_load_cmds = 0;
03158 for (load_cmd = load_array; load_cmd < load_end; load_cmd++)
03159 {
03160 load_union_t *load_hdr = load_cmd->load;
03161
03162 if (load_hdr->hdr.ldci_cmd_type == LDC_SYMBOLS)
03163 {
03164 symbol_load_cmds++;
03165
03166 if (debug)
03167 {
03168 const char *kind = "unknown";
03169
03170 switch (load_hdr->sym.symc_kind)
03171 {
03172 case SYMC_IMPORTS: kind = "imports"; break;
03173 case SYMC_DEFINED_SYMBOLS: kind = "defined"; break;
03174 case SYMC_STABS: kind = "stabs"; break;
03175 }
03176
03177 notice ("\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
03178 symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
03179 }
03180
03181 if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
03182 continue;
03183
03184 str_sect = load_array[load_hdr->sym.symc_strings_section].section;
03185 if (str_sect == (char *) 0)
03186 fatal ("string section missing");
03187
03188 if (load_cmd->section == (char *) 0)
03189 fatal ("section pointer missing");
03190
03191 num_syms = load_hdr->sym.symc_nentries;
03192 for (i = 0; i < num_syms; i++)
03193 {
03194 symbol_info_t *sym = ((symbol_info_t *) load_cmd->section) + i;
03195 char *name = sym->si_name.symbol_name + str_sect;
03196
03197 if (name[0] != '_')
03198 continue;
03199
03200 if (rw)
03201 {
03202 char *n = name + strlen (name) - strlen (NAME__MAIN);
03203
03204 if ((n - name) < 0 || strcmp (n, NAME__MAIN))
03205 continue;
03206 while (n != name)
03207 if (*--n != '_')
03208 continue;
03209
03210 main_sym = sym;
03211 }
03212 else
03213 {
03214 switch (is_ctor_dtor (name))
03215 {
03216 case 1:
03217 add_to_list (&constructors, name);
03218 break;
03219
03220 case 2:
03221 add_to_list (&destructors, name);
03222 break;
03223
03224 default:
03225 continue;
03226 }
03227 }
03228
03229 if (debug)
03230 fprintf (stderr, "\ttype = 0x%.4x, sc = 0x%.2x, flags = 0x%.8x, name = %.30s\n",
03231 sym->si_type, sym->si_sc_type, sym->si_flags, name);
03232 }
03233 }
03234 }
03235
03236 if (symbol_load_cmds == 0)
03237 fatal ("no symbol table found");
03238
03239
03240
03241
03242
03243
03244 if (rw)
03245 {
03246 load_union_t *load_map;
03247 size_t size;
03248
03249 if (cmd_strings == -1)
03250 fatal ("no cmd_strings found");
03251
03252
03253
03254
03255
03256
03257 if (main_sym != (symbol_info_t *) 0
03258 && ((hdr.moh_flags & MOH_EXECABLE_F) == 0))
03259 add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION);
03260
03261 if (debug)
03262 notice ("\nUpdating header and load commands.\n\n");
03263
03264 hdr.moh_n_load_cmds++;
03265 size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1));
03266
03267
03268 if (debug)
03269 notice ("load command map, %d cmds, new size %ld.\n",
03270 (int) hdr.moh_n_load_cmds, (long) size);
03271
03272 load_map = (load_union_t *) xcalloc (1, size);
03273 load_map->map.ldc_header.ldci_cmd_type = LDC_CMD_MAP;
03274 load_map->map.ldc_header.ldci_cmd_size = size;
03275 load_map->map.lcm_ld_cmd_strings = cmd_strings;
03276 load_map->map.lcm_nentries = hdr.moh_n_load_cmds;
03277 load_array[hdr.moh_n_load_cmds-1].load = load_map;
03278
03279 offset = hdr.moh_first_cmd_off;
03280 for (i = 0; i < hdr.moh_n_load_cmds; i++)
03281 {
03282 load_map->map.lcm_map[i] = offset;
03283 if (load_array[i].load->hdr.ldci_cmd_type == LDC_CMD_MAP)
03284 hdr.moh_load_map_cmd_off = offset;
03285
03286 offset += load_array[i].load->hdr.ldci_cmd_size;
03287 }
03288
03289 hdr.moh_sizeofcmds = offset - MO_SIZEOF_RAW_HDR;
03290
03291 if (debug)
03292 print_header (&hdr);
03293
03294
03295 status = encode_mach_o_hdr (&hdr, obj, MO_SIZEOF_RAW_HDR);
03296 if (status != MO_HDR_CONV_SUCCESS)
03297 bad_header (status);
03298
03299 if (debug)
03300 notice ("writing load commands.\n\n");
03301
03302
03303 offset = hdr.moh_first_cmd_off;
03304 for (i = 0; i < hdr.moh_n_load_cmds; i++)
03305 {
03306 load_union_t *load_hdr = load_array[i].load;
03307 size_t size = load_hdr->hdr.ldci_cmd_size;
03308
03309 if (debug)
03310 print_load_command (load_hdr, offset, i);
03311
03312 bcopy ((char *) load_hdr, (char *) (obj + offset), size);
03313 offset += size;
03314 }
03315 }
03316
03317 end_file (obj_file);
03318
03319 if (close (prog_fd))
03320 fatal_perror ("close %s", prog_name);
03321
03322 if (debug)
03323 fprintf (stderr, "\n");
03324 }
03325
03326
03327
03328
03329
03330 static void
03331 add_func_table (hdr_p, load_array, sym, type)
03332 mo_header_t *hdr_p;
03333 load_all_t *load_array;
03334 symbol_info_t *sym;
03335 int type;
03336 {
03337
03338 int num_cmds = ++hdr_p->moh_n_load_cmds;
03339 int load_index = num_cmds - 1;
03340 size_t size = sizeof (func_table_command_t) + sizeof (mo_addr_t);
03341 load_union_t *ptr = xcalloc (1, size);
03342 load_all_t *load_cmd;
03343 int i;
03344
03345
03346
03347 hdr_p->moh_flags |= MOH_UNRESOLVED_F;
03348
03349 load_cmd = &load_array[load_index];
03350 load_cmd->load = ptr;
03351 load_cmd->section = (char *) 0;
03352
03353
03354 ptr->func.ldc_header.ldci_cmd_type = LDC_FUNC_TABLE;
03355 ptr->func.ldc_header.ldci_cmd_size = size;
03356 ptr->func.ldc_header.ldci_section_off = 0;
03357 ptr->func.ldc_header.ldci_section_len = 0;
03358 ptr->func.fntc_type = type;
03359 ptr->func.fntc_nentries = 1;
03360
03361
03362
03363 if ((sym->si_flags & SI_ABSOLUTE_VALUE_F) == 0)
03364 {
03365 ptr->func.fntc_entry_loc[i].adr_lcid = sym->si_value.def_val.adr_lcid;
03366 ptr->func.fntc_entry_loc[i].adr_sctoff = sym->si_value.def_val.adr_sctoff;
03367 }
03368
03369
03370 else
03371 {
03372 mo_vm_addr_t addr = sym->si_value.abs_val;
03373 int found = 0;
03374
03375 for (i = 0; i < load_index; i++)
03376 {
03377 if (load_array[i].load->hdr.ldci_cmd_type == LDC_REGION)
03378 {
03379 region_command_t *region_ptr = &load_array[i].load->region;
03380
03381 if ((region_ptr->regc_flags & REG_ABS_ADDR_F) != 0
03382 && addr >= region_ptr->regc_addr.vm_addr
03383 && addr <= region_ptr->regc_addr.vm_addr + region_ptr->regc_vm_size)
03384 {
03385 ptr->func.fntc_entry_loc[0].adr_lcid = i;
03386 ptr->func.fntc_entry_loc[0].adr_sctoff = addr - region_ptr->regc_addr.vm_addr;
03387 found++;
03388 break;
03389 }
03390 }
03391 }
03392
03393 if (!found)
03394 fatal ("could not convert 0x%l.8x into a region", addr);
03395 }
03396
03397 if (debug)
03398 notice ("%s function, region %d, offset = %ld (0x%.8lx)\n",
03399 type == FNTC_INITIALIZATION ? "init" : "term",
03400 (int) ptr->func.fntc_entry_loc[i].adr_lcid,
03401 (long) ptr->func.fntc_entry_loc[i].adr_sctoff,
03402 (long) ptr->func.fntc_entry_loc[i].adr_sctoff);
03403
03404 }
03405
03406
03407
03408
03409 static void
03410 print_header (hdr_ptr)
03411 mo_header_t *hdr_ptr;
03412 {
03413 fprintf (stderr, "\nglobal header:\n");
03414 fprintf (stderr, "\tmoh_magic = 0x%.8lx\n", hdr_ptr->moh_magic);
03415 fprintf (stderr, "\tmoh_major_version = %d\n", (int)hdr_ptr->moh_major_version);
03416 fprintf (stderr, "\tmoh_minor_version = %d\n", (int)hdr_ptr->moh_minor_version);
03417 fprintf (stderr, "\tmoh_header_version = %d\n", (int)hdr_ptr->moh_header_version);
03418 fprintf (stderr, "\tmoh_max_page_size = %d\n", (int)hdr_ptr->moh_max_page_size);
03419 fprintf (stderr, "\tmoh_byte_order = %d\n", (int)hdr_ptr->moh_byte_order);
03420 fprintf (stderr, "\tmoh_data_rep_id = %d\n", (int)hdr_ptr->moh_data_rep_id);
03421 fprintf (stderr, "\tmoh_cpu_type = %d\n", (int)hdr_ptr->moh_cpu_type);
03422 fprintf (stderr, "\tmoh_cpu_subtype = %d\n", (int)hdr_ptr->moh_cpu_subtype);
03423 fprintf (stderr, "\tmoh_vendor_type = %d\n", (int)hdr_ptr->moh_vendor_type);
03424 fprintf (stderr, "\tmoh_load_map_cmd_off = %d\n", (int)hdr_ptr->moh_load_map_cmd_off);
03425 fprintf (stderr, "\tmoh_first_cmd_off = %d\n", (int)hdr_ptr->moh_first_cmd_off);
03426 fprintf (stderr, "\tmoh_sizeofcmds = %d\n", (int)hdr_ptr->moh_sizeofcmds);
03427 fprintf (stderr, "\tmon_n_load_cmds = %d\n", (int)hdr_ptr->moh_n_load_cmds);
03428 fprintf (stderr, "\tmoh_flags = 0x%.8lx", (long)hdr_ptr->moh_flags);
03429
03430 if (hdr_ptr->moh_flags & MOH_RELOCATABLE_F)
03431 fprintf (stderr, ", relocatable");
03432
03433 if (hdr_ptr->moh_flags & MOH_LINKABLE_F)
03434 fprintf (stderr, ", linkable");
03435
03436 if (hdr_ptr->moh_flags & MOH_EXECABLE_F)
03437 fprintf (stderr, ", execable");
03438
03439 if (hdr_ptr->moh_flags & MOH_EXECUTABLE_F)
03440 fprintf (stderr, ", executable");
03441
03442 if (hdr_ptr->moh_flags & MOH_UNRESOLVED_F)
03443 fprintf (stderr, ", unresolved");
03444
03445 fprintf (stderr, "\n\n");
03446 return;
03447 }
03448
03449
03450
03451
03452 static void
03453 print_load_command (load_hdr, offset, number)
03454 load_union_t *load_hdr;
03455 size_t offset;
03456 int number;
03457 {
03458 mo_long_t type = load_hdr->hdr.ldci_cmd_type;
03459 const char *type_str = (char *) 0;
03460
03461 switch (type)
03462 {
03463 case LDC_UNDEFINED: type_str = "UNDEFINED"; break;
03464 case LDC_CMD_MAP: type_str = "CMD_MAP"; break;
03465 case LDC_INTERPRETER: type_str = "INTERPRETER"; break;
03466 case LDC_STRINGS: type_str = "STRINGS"; break;
03467 case LDC_REGION: type_str = "REGION"; break;
03468 case LDC_RELOC: type_str = "RELOC"; break;
03469 case LDC_PACKAGE: type_str = "PACKAGE"; break;
03470 case LDC_SYMBOLS: type_str = "SYMBOLS"; break;
03471 case LDC_ENTRY: type_str = "ENTRY"; break;
03472 case LDC_FUNC_TABLE: type_str = "FUNC_TABLE"; break;
03473 case LDC_GEN_INFO: type_str = "GEN_INFO"; break;
03474 }
03475
03476 fprintf (stderr,
03477 "cmd %2d, sz: 0x%.2lx, coff: 0x%.3lx, doff: 0x%.6lx, dlen: 0x%.6lx",
03478 number,
03479 (long) load_hdr->hdr.ldci_cmd_size,
03480 (long) offset,
03481 (long) load_hdr->hdr.ldci_section_off,
03482 (long) load_hdr->hdr.ldci_section_len);
03483
03484 if (type_str == (char *) 0)
03485 fprintf (stderr, ", ty: unknown (%ld)\n", (long) type);
03486
03487 else if (type != LDC_REGION)
03488 fprintf (stderr, ", ty: %s\n", type_str);
03489
03490 else
03491 {
03492 const char *region = "";
03493 switch (load_hdr->region.regc_usage_type)
03494 {
03495 case REG_TEXT_T: region = ", .text"; break;
03496 case REG_DATA_T: region = ", .data"; break;
03497 case REG_BSS_T: region = ", .bss"; break;
03498 case REG_GLUE_T: region = ", .glue"; break;
03499 #if defined (REG_RDATA_T) && defined (REG_SDATA_T) && defined (REG_SBSS_T)
03500 case REG_RDATA_T: region = ", .rdata"; break;
03501 case REG_SDATA_T: region = ", .sdata"; break;
03502 case REG_SBSS_T: region = ", .sbss"; break;
03503 #endif
03504 }
03505
03506 fprintf (stderr, ", ty: %s, vaddr: 0x%.8lx, vlen: 0x%.6lx%s\n",
03507 type_str,
03508 (long) load_hdr->region.regc_vm_addr,
03509 (long) load_hdr->region.regc_vm_size,
03510 region);
03511 }
03512
03513 return;
03514 }
03515
03516
03517
03518
03519 static void
03520 bad_header (status)
03521 int status;
03522 {
03523 switch (status)
03524 {
03525 case MO_ERROR_BAD_MAGIC: fatal ("bad magic number");
03526 case MO_ERROR_BAD_HDR_VERS: fatal ("bad header version");
03527 case MO_ERROR_BAD_RAW_HDR_VERS: fatal ("bad raw header version");
03528 case MO_ERROR_BUF2SML: fatal ("raw header buffer too small");
03529 case MO_ERROR_OLD_RAW_HDR_FILE: fatal ("old raw header file");
03530 case MO_ERROR_UNSUPPORTED_VERS: fatal ("unsupported version");
03531 default:
03532 fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
03533 }
03534 }
03535
03536
03537
03538
03539 static struct file_info *
03540 read_file (name, fd, rw)
03541 const char *name;
03542 int fd;
03543 int rw;
03544 {
03545 struct stat stat_pkt;
03546 struct file_info *p = (struct file_info *) xcalloc (sizeof (struct file_info), 1);
03547 #ifdef USE_MMAP
03548 static int page_size;
03549 #endif
03550
03551 if (fstat (fd, &stat_pkt) < 0)
03552 fatal_perror ("fstat %s", name);
03553
03554 p->name = name;
03555 p->size = stat_pkt.st_size;
03556 p->rounded_size = stat_pkt.st_size;
03557 p->fd = fd;
03558 p->rw = rw;
03559
03560 #ifdef USE_MMAP
03561 if (debug)
03562 fprintf (stderr, "mmap %s, %s\n", name, (rw) ? "read/write" : "read-only");
03563
03564 if (page_size == 0)
03565 page_size = sysconf (_SC_PAGE_SIZE);
03566
03567 p->rounded_size = ((p->size + page_size - 1) / page_size) * page_size;
03568 p->start = mmap ((caddr_t) 0,
03569 (rw) ? p->rounded_size : p->size,
03570 (rw) ? (PROT_READ | PROT_WRITE) : PROT_READ,
03571 MAP_FILE | MAP_VARIABLE | MAP_SHARED,
03572 fd,
03573 0L);
03574
03575 if (p->start != (char *) 0 && p->start != (char *) -1)
03576 p->use_mmap = 1;
03577
03578 else
03579 #endif
03580 {
03581 long len;
03582
03583 if (debug)
03584 fprintf (stderr, "read %s\n", name);
03585
03586 p->use_mmap = 0;
03587 p->start = xmalloc (p->size);
03588 if (lseek (fd, 0L, SEEK_SET) < 0)
03589 fatal_perror ("lseek %s 0", name);
03590
03591 len = read (fd, p->start, p->size);
03592 if (len < 0)
03593 fatal_perror ("read %s", name);
03594
03595 if (len != p->size)
03596 fatal ("read %ld bytes, expected %ld, from %s", len, p->size, name);
03597 }
03598
03599 return p;
03600 }
03601
03602
03603
03604 static void
03605 end_file (ptr)
03606 struct file_info *ptr;
03607 {
03608 #ifdef USE_MMAP
03609 if (ptr->use_mmap)
03610 {
03611 if (ptr->rw)
03612 {
03613 if (debug)
03614 fprintf (stderr, "msync %s\n", ptr->name);
03615
03616 if (msync (ptr->start, ptr->rounded_size, MS_ASYNC))
03617 fatal_perror ("msync %s", ptr->name);
03618 }
03619
03620 if (debug)
03621 fprintf (stderr, "munmap %s\n", ptr->name);
03622
03623 if (munmap (ptr->start, ptr->size))
03624 fatal_perror ("munmap %s", ptr->name);
03625 }
03626 else
03627 #endif
03628 {
03629 if (ptr->rw)
03630 {
03631 long len;
03632
03633 if (debug)
03634 fprintf (stderr, "write %s\n", ptr->name);
03635
03636 if (lseek (ptr->fd, 0L, SEEK_SET) < 0)
03637 fatal_perror ("lseek %s 0", ptr->name);
03638
03639 len = write (ptr->fd, ptr->start, ptr->size);
03640 if (len < 0)
03641 fatal_perror ("write %s", ptr->name);
03642
03643 if (len != ptr->size)
03644 fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name);
03645 }
03646
03647 free (ptr->start);
03648 }
03649
03650 free (ptr);
03651 }
03652
03653 #endif