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 #include "config.h"
00030 #include "system.h"
00031 #include "coretypes.h"
00032 #include "tm.h"
00033 #include <signal.h>
00034 #if ! defined( SIGCHLD ) && defined( SIGCLD )
00035 # define SIGCHLD SIGCLD
00036 #endif
00037
00038 #ifdef vfork
00039 # define VFORK_STRING "fork"
00040 #else
00041 # define VFORK_STRING "vfork"
00042 #endif
00043 #ifdef HAVE_VFORK_H
00044 #include <vfork.h>
00045 #endif
00046 #ifdef VMS
00047 #define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \
00048 lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1)
00049 #endif
00050
00051 #ifndef LIBRARY_PATH_ENV
00052 #define LIBRARY_PATH_ENV "LIBRARY_PATH"
00053 #endif
00054
00055 #define COLLECT
00056
00057 #include "collect2.h"
00058 #include "demangle.h"
00059 #include "obstack.h"
00060 #include "intl.h"
00061 #include "version.h"
00062
00063
00064
00065
00066
00067
00068
00069 #ifdef CROSS_COMPILE
00070 #undef OBJECT_FORMAT_COFF
00071 #undef MD_EXEC_PREFIX
00072 #undef REAL_LD_FILE_NAME
00073 #undef REAL_NM_FILE_NAME
00074 #undef REAL_STRIP_FILE_NAME
00075 #endif
00076
00077
00078
00079
00080
00081
00082 #if !defined (OBJECT_FORMAT_COFF)
00083 #define OBJECT_FORMAT_NONE
00084 #endif
00085
00086 #ifdef OBJECT_FORMAT_COFF
00087
00088 #include <a.out.h>
00089 #include <ar.h>
00090
00091 #ifdef UMAX
00092 #include <sgs.h>
00093 #endif
00094
00095
00096 #ifdef FREAD
00097 #undef FREAD
00098 #undef FWRITE
00099 #endif
00100
00101 #include <ldfcn.h>
00102
00103
00104
00105
00106
00107
00108 #ifndef MY_ISCOFF
00109 #define MY_ISCOFF(X) ISCOFF (X)
00110 #endif
00111
00112 #endif
00113
00114 #ifdef OBJECT_FORMAT_NONE
00115
00116
00117 #ifndef NM_FLAGS
00118 #define NM_FLAGS "-n"
00119 #endif
00120
00121 #endif
00122
00123
00124
00125
00126 #ifndef NAME__MAIN
00127 #define NAME__MAIN "__main"
00128 #endif
00129
00130
00131 #define DEFAULT_INIT_PRIORITY 65535
00132
00133 #ifndef COLLECT_SHARED_INIT_FUNC
00134 #define COLLECT_SHARED_INIT_FUNC(STREAM, FUNC) \
00135 fprintf ((STREAM), "void _GLOBAL__DI() {\n\t%s();\n}\n", (FUNC))
00136 #endif
00137 #ifndef COLLECT_SHARED_FINI_FUNC
00138 #define COLLECT_SHARED_FINI_FUNC(STREAM, FUNC) \
00139 fprintf ((STREAM), "void _GLOBAL__DD() {\n\t%s();\n}\n", (FUNC))
00140 #endif
00141
00142 #ifdef LDD_SUFFIX
00143 #define SCAN_LIBRARIES
00144 #endif
00145
00146 #ifdef USE_COLLECT2
00147 int do_collecting = 1;
00148 #else
00149 int do_collecting = 0;
00150 #endif
00151
00152
00153
00154 int no_demangle;
00155
00156
00157
00158 struct id
00159 {
00160 struct id *next;
00161 int sequence;
00162 char name[1];
00163 };
00164
00165 struct head
00166 {
00167 struct id *first;
00168 struct id *last;
00169 int number;
00170 };
00171
00172
00173
00174 enum pass {
00175 PASS_FIRST,
00176 PASS_OBJ,
00177 PASS_LIB,
00178 PASS_SECOND
00179 };
00180
00181 int vflag;
00182 static int rflag;
00183 static int strip_flag;
00184 static const char *demangle_flag;
00185 #ifdef COLLECT_EXPORT_LIST
00186 static int export_flag;
00187 static int aix64_flag;
00188 static int aixrtl_flag;
00189 #endif
00190
00191 int debug;
00192
00193 static int shared_obj;
00194
00195 static const char *c_file;
00196 static const char *o_file;
00197 #ifdef COLLECT_EXPORT_LIST
00198 static const char *export_file;
00199 #endif
00200 const char *ldout;
00201 static const char *output_file;
00202 static const char *nm_file_name;
00203 #ifdef LDD_SUFFIX
00204 static const char *ldd_file_name;
00205 #endif
00206 static const char *strip_file_name;
00207 const char *c_file_name;
00208 static char *initname, *fininame;
00209
00210 static struct head constructors;
00211 static struct head destructors;
00212 #ifdef COLLECT_EXPORT_LIST
00213 static struct head exports;
00214 #endif
00215 static struct head frame_tables;
00216
00217 struct obstack temporary_obstack;
00218 char * temporary_firstobj;
00219
00220
00221 int pid;
00222
00223
00224
00225
00226 struct prefix_list
00227 {
00228 const char *prefix;
00229 struct prefix_list *next;
00230 };
00231
00232 struct path_prefix
00233 {
00234 struct prefix_list *plist;
00235 int max_len;
00236 const char *name;
00237 };
00238
00239 #ifdef COLLECT_EXPORT_LIST
00240
00241 static struct head libs;
00242 static struct path_prefix cmdline_lib_dirs;
00243 static struct path_prefix libpath_lib_dirs;
00244 static struct path_prefix *libpaths[3] = {&cmdline_lib_dirs,
00245 &libpath_lib_dirs, NULL};
00246 #endif
00247
00248 static void handler (int);
00249 static int is_ctor_dtor (const char *);
00250 static char *find_a_file (struct path_prefix *, const char *);
00251 static void add_prefix (struct path_prefix *, const char *);
00252 static void prefix_from_env (const char *, struct path_prefix *);
00253 static void prefix_from_string (const char *, struct path_prefix *);
00254 static void do_wait (const char *);
00255 static void fork_execute (const char *, char **);
00256 static void maybe_unlink (const char *);
00257 static void add_to_list (struct head *, const char *);
00258 static int extract_init_priority (const char *);
00259 static void sort_ids (struct head *);
00260 static void write_list (FILE *, const char *, struct id *);
00261 #ifdef COLLECT_EXPORT_LIST
00262 static void dump_list (FILE *, const char *, struct id *);
00263 #endif
00264 #if 0
00265 static void dump_prefix_list (FILE *, const char *, struct prefix_list *);
00266 #endif
00267 static void write_list_with_asm (FILE *, const char *, struct id *);
00268 static void write_c_file (FILE *, const char *);
00269 static void write_c_file_stat (FILE *, const char *);
00270 #ifndef LD_INIT_SWITCH
00271 static void write_c_file_glob (FILE *, const char *);
00272 #endif
00273 static void scan_prog_file (const char *, enum pass);
00274 #ifdef SCAN_LIBRARIES
00275 static void scan_libraries (const char *);
00276 #endif
00277 #if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
00278 static int is_in_args (const char *, const char **, const char **);
00279 #endif
00280 #ifdef COLLECT_EXPORT_LIST
00281 #if 0
00282 static int is_in_list (const char *, struct id *);
00283 #endif
00284 static void write_aix_file (FILE *, struct id *);
00285 static char *resolve_lib_name (const char *);
00286 #endif
00287 static char *extract_string (const char **);
00288
00289 #ifndef HAVE_DUP2
00290 static int
00291 dup2 (int oldfd, int newfd)
00292 {
00293 int fdtmp[256];
00294 int fdx = 0;
00295 int fd;
00296
00297 if (oldfd == newfd)
00298 return oldfd;
00299 close (newfd);
00300 while ((fd = dup (oldfd)) != newfd && fd >= 0)
00301 fdtmp[fdx++] = fd;
00302 while (fdx > 0)
00303 close (fdtmp[--fdx]);
00304
00305 return fd;
00306 }
00307 #endif
00308
00309
00310
00311 void
00312 collect_exit (int status)
00313 {
00314 if (c_file != 0 && c_file[0])
00315 maybe_unlink (c_file);
00316
00317 if (o_file != 0 && o_file[0])
00318 maybe_unlink (o_file);
00319
00320 #ifdef COLLECT_EXPORT_LIST
00321 if (export_file != 0 && export_file[0])
00322 maybe_unlink (export_file);
00323 #endif
00324
00325 if (ldout != 0 && ldout[0])
00326 {
00327 dump_file (ldout);
00328 maybe_unlink (ldout);
00329 }
00330
00331 if (status != 0 && output_file != 0 && output_file[0])
00332 maybe_unlink (output_file);
00333
00334 exit (status);
00335 }
00336
00337
00338
00339 void
00340 notice (const char *cmsgid, ...)
00341 {
00342 va_list ap;
00343
00344 va_start (ap, cmsgid);
00345 vfprintf (stderr, _(cmsgid), ap);
00346 va_end (ap);
00347 }
00348
00349
00350
00351 void
00352 fatal_perror (const char * cmsgid, ...)
00353 {
00354 int e = errno;
00355 va_list ap;
00356
00357 va_start (ap, cmsgid);
00358 fprintf (stderr, "collect2: ");
00359 vfprintf (stderr, _(cmsgid), ap);
00360 fprintf (stderr, ": %s\n", xstrerror (e));
00361 va_end (ap);
00362
00363 collect_exit (FATAL_EXIT_CODE);
00364 }
00365
00366
00367
00368 void
00369 fatal (const char * cmsgid, ...)
00370 {
00371 va_list ap;
00372
00373 va_start (ap, cmsgid);
00374 fprintf (stderr, "collect2: ");
00375 vfprintf (stderr, _(cmsgid), ap);
00376 fprintf (stderr, "\n");
00377 va_end (ap);
00378
00379 collect_exit (FATAL_EXIT_CODE);
00380 }
00381
00382
00383
00384 void
00385 error (const char * gmsgid, ...)
00386 {
00387 va_list ap;
00388
00389 va_start (ap, gmsgid);
00390 fprintf (stderr, "collect2: ");
00391 vfprintf (stderr, _(gmsgid), ap);
00392 fprintf (stderr, "\n");
00393 va_end(ap);
00394 }
00395
00396
00397
00398
00399 void
00400 fancy_abort (const char *file, int line, const char *func)
00401 {
00402 fatal ("internal gcc abort in %s, at %s:%d", func, file, line);
00403 }
00404
00405 static void
00406 handler (int signo)
00407 {
00408 if (c_file != 0 && c_file[0])
00409 maybe_unlink (c_file);
00410
00411 if (o_file != 0 && o_file[0])
00412 maybe_unlink (o_file);
00413
00414 if (ldout != 0 && ldout[0])
00415 maybe_unlink (ldout);
00416
00417 #ifdef COLLECT_EXPORT_LIST
00418 if (export_file != 0 && export_file[0])
00419 maybe_unlink (export_file);
00420 #endif
00421
00422 signal (signo, SIG_DFL);
00423 kill (getpid (), signo);
00424 }
00425
00426
00427 int
00428 file_exists (const char *name)
00429 {
00430 return access (name, R_OK) == 0;
00431 }
00432
00433
00434
00435 static char *
00436 extract_string (const char **pp)
00437 {
00438 const char *p = *pp;
00439 int backquote = 0;
00440 int inside = 0;
00441
00442 for (;;)
00443 {
00444 char c = *p;
00445 if (c == '\0')
00446 break;
00447 ++p;
00448 if (backquote)
00449 obstack_1grow (&temporary_obstack, c);
00450 else if (! inside && c == ' ')
00451 break;
00452 else if (! inside && c == '\\')
00453 backquote = 1;
00454 else if (c == '\'')
00455 inside = !inside;
00456 else
00457 obstack_1grow (&temporary_obstack, c);
00458 }
00459
00460 obstack_1grow (&temporary_obstack, '\0');
00461 *pp = p;
00462 return obstack_finish (&temporary_obstack);
00463 }
00464
00465 void
00466 dump_file (const char *name)
00467 {
00468 FILE *stream = fopen (name, "r");
00469
00470 if (stream == 0)
00471 return;
00472 while (1)
00473 {
00474 int c;
00475 while (c = getc (stream),
00476 c != EOF && (ISIDNUM (c) || c == '$' || c == '.'))
00477 obstack_1grow (&temporary_obstack, c);
00478 if (obstack_object_size (&temporary_obstack) > 0)
00479 {
00480 const char *word, *p;
00481 char *result;
00482 obstack_1grow (&temporary_obstack, '\0');
00483 word = obstack_finish (&temporary_obstack);
00484
00485 if (*word == '.')
00486 ++word, putc ('.', stderr);
00487 p = word;
00488 if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
00489 p += strlen (USER_LABEL_PREFIX);
00490
00491 #ifdef HAVE_LD_DEMANGLE
00492 result = 0;
00493 #else
00494 if (no_demangle)
00495 result = 0;
00496 else
00497 result = cplus_demangle (p, DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE);
00498 #endif
00499
00500 if (result)
00501 {
00502 int diff;
00503 fputs (result, stderr);
00504
00505 diff = strlen (word) - strlen (result);
00506 while (diff > 0 && c == ' ')
00507 --diff, putc (' ', stderr);
00508 while (diff < 0 && c == ' ')
00509 ++diff, c = getc (stream);
00510
00511 free (result);
00512 }
00513 else
00514 fputs (word, stderr);
00515
00516 fflush (stderr);
00517 obstack_free (&temporary_obstack, temporary_firstobj);
00518 }
00519 if (c == EOF)
00520 break;
00521 putc (c, stderr);
00522 }
00523 fclose (stream);
00524 }
00525
00526
00527
00528
00529
00530
00531 static int
00532 is_ctor_dtor (const char *s)
00533 {
00534 struct names { const char *const name; const int len; const int ret;
00535 const int two_underscores; };
00536
00537 const struct names *p;
00538 int ch;
00539 const char *orig_s = s;
00540
00541 static const struct names special[] = {
00542 #ifndef NO_DOLLAR_IN_LABEL
00543 { "GLOBAL__I$", sizeof ("GLOBAL__I$")-1, 1, 0 },
00544 { "GLOBAL__D$", sizeof ("GLOBAL__D$")-1, 2, 0 },
00545 #else
00546 #ifndef NO_DOT_IN_LABEL
00547 { "GLOBAL__I.", sizeof ("GLOBAL__I.")-1, 1, 0 },
00548 { "GLOBAL__D.", sizeof ("GLOBAL__D.")-1, 2, 0 },
00549 #endif
00550 #endif
00551 { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, 1, 0 },
00552 { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, 2, 0 },
00553 { "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, 5, 0 },
00554 { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, 3, 0 },
00555 { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, 4, 0 },
00556 { NULL, 0, 0, 0 }
00557 };
00558
00559 while ((ch = *s) == '_')
00560 ++s;
00561
00562 if (s == orig_s)
00563 return 0;
00564
00565 for (p = &special[0]; p->len > 0; p++)
00566 {
00567 if (ch == p->name[0]
00568 && (!p->two_underscores || ((s - orig_s) >= 2))
00569 && strncmp(s, p->name, p->len) == 0)
00570 {
00571 return p->ret;
00572 }
00573 }
00574 return 0;
00575 }
00576
00577
00578
00579
00580 static struct path_prefix cpath, path;
00581
00582 #ifdef CROSS_COMPILE
00583
00584
00585
00586 static const char *const target_machine = TARGET_MACHINE;
00587 #endif
00588
00589
00590
00591
00592
00593
00594 static char *
00595 find_a_file (struct path_prefix *pprefix, const char *name)
00596 {
00597 char *temp;
00598 struct prefix_list *pl;
00599 int len = pprefix->max_len + strlen (name) + 1;
00600
00601 if (debug)
00602 fprintf (stderr, "Looking for '%s'\n", name);
00603
00604 #ifdef HOST_EXECUTABLE_SUFFIX
00605 len += strlen (HOST_EXECUTABLE_SUFFIX);
00606 #endif
00607
00608 temp = xmalloc (len);
00609
00610
00611
00612 if (*name == '/'
00613 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
00614 || (*name && name[1] == ':')
00615 #endif
00616 )
00617 {
00618 if (access (name, X_OK) == 0)
00619 {
00620 strcpy (temp, name);
00621
00622 if (debug)
00623 fprintf (stderr, " - found: absolute path\n");
00624
00625 return temp;
00626 }
00627
00628 #ifdef HOST_EXECUTABLE_SUFFIX
00629
00630
00631 strcpy (temp, name);
00632 strcat (temp, HOST_EXECUTABLE_SUFFIX);
00633
00634 if (access (temp, X_OK) == 0)
00635 return temp;
00636 #endif
00637
00638 if (debug)
00639 fprintf (stderr, " - failed to locate using absolute path\n");
00640 }
00641 else
00642 for (pl = pprefix->plist; pl; pl = pl->next)
00643 {
00644 struct stat st;
00645
00646 strcpy (temp, pl->prefix);
00647 strcat (temp, name);
00648
00649 if (stat (temp, &st) >= 0
00650 && ! S_ISDIR (st.st_mode)
00651 && access (temp, X_OK) == 0)
00652 return temp;
00653
00654 #ifdef HOST_EXECUTABLE_SUFFIX
00655
00656
00657 strcat (temp, HOST_EXECUTABLE_SUFFIX);
00658
00659 if (stat (temp, &st) >= 0
00660 && ! S_ISDIR (st.st_mode)
00661 && access (temp, X_OK) == 0)
00662 return temp;
00663 #endif
00664 }
00665
00666 if (debug && pprefix->plist == NULL)
00667 fprintf (stderr, " - failed: no entries in prefix list\n");
00668
00669 free (temp);
00670 return 0;
00671 }
00672
00673
00674
00675 static void
00676 add_prefix (struct path_prefix *pprefix, const char *prefix)
00677 {
00678 struct prefix_list *pl, **prev;
00679 int len;
00680
00681 if (pprefix->plist)
00682 {
00683 for (pl = pprefix->plist; pl->next; pl = pl->next)
00684 ;
00685 prev = &pl->next;
00686 }
00687 else
00688 prev = &pprefix->plist;
00689
00690
00691
00692 len = strlen (prefix);
00693 if (len > pprefix->max_len)
00694 pprefix->max_len = len;
00695
00696 pl = xmalloc (sizeof (struct prefix_list));
00697 pl->prefix = xstrdup (prefix);
00698
00699 if (*prev)
00700 pl->next = *prev;
00701 else
00702 pl->next = (struct prefix_list *) 0;
00703 *prev = pl;
00704 }
00705
00706
00707
00708
00709 static void
00710 prefix_from_env (const char *env, struct path_prefix *pprefix)
00711 {
00712 const char *p;
00713 GET_ENVIRONMENT (p, env);
00714
00715 if (p)
00716 prefix_from_string (p, pprefix);
00717 }
00718
00719 static void
00720 prefix_from_string (const char *p, struct path_prefix *pprefix)
00721 {
00722 const char *startp, *endp;
00723 char *nstore = xmalloc (strlen (p) + 3);
00724
00725 if (debug)
00726 fprintf (stderr, "Convert string '%s' into prefixes, separator = '%c'\n", p, PATH_SEPARATOR);
00727
00728 startp = endp = p;
00729 while (1)
00730 {
00731 if (*endp == PATH_SEPARATOR || *endp == 0)
00732 {
00733 strncpy (nstore, startp, endp-startp);
00734 if (endp == startp)
00735 {
00736 strcpy (nstore, "./");
00737 }
00738 else if (! IS_DIR_SEPARATOR (endp[-1]))
00739 {
00740 nstore[endp-startp] = DIR_SEPARATOR;
00741 nstore[endp-startp+1] = 0;
00742 }
00743 else
00744 nstore[endp-startp] = 0;
00745
00746 if (debug)
00747 fprintf (stderr, " - add prefix: %s\n", nstore);
00748
00749 add_prefix (pprefix, nstore);
00750 if (*endp == 0)
00751 break;
00752 endp = startp = endp + 1;
00753 }
00754 else
00755 endp++;
00756 }
00757 }
00758
00759
00760
00761 int
00762 main (int argc, char **argv)
00763 {
00764 static const char *const ld_suffix = "ld";
00765 static const char *const real_ld_suffix = "real-ld";
00766 static const char *const collect_ld_suffix = "collect-ld";
00767 static const char *const nm_suffix = "nm";
00768 static const char *const gnm_suffix = "gnm";
00769 #ifdef LDD_SUFFIX
00770 static const char *const ldd_suffix = LDD_SUFFIX;
00771 #endif
00772 static const char *const strip_suffix = "strip";
00773 static const char *const gstrip_suffix = "gstrip";
00774
00775 #ifdef CROSS_COMPILE
00776
00777
00778
00779
00780
00781 const char *const full_ld_suffix =
00782 concat(target_machine, "-", ld_suffix, NULL);
00783 const char *const full_nm_suffix =
00784 concat (target_machine, "-", nm_suffix, NULL);
00785 const char *const full_gnm_suffix =
00786 concat (target_machine, "-", gnm_suffix, NULL);
00787 #ifdef LDD_SUFFIX
00788 const char *const full_ldd_suffix =
00789 concat (target_machine, "-", ldd_suffix, NULL);
00790 #endif
00791 const char *const full_strip_suffix =
00792 concat (target_machine, "-", strip_suffix, NULL);
00793 const char *const full_gstrip_suffix =
00794 concat (target_machine, "-", gstrip_suffix, NULL);
00795 #else
00796 const char *const full_ld_suffix = ld_suffix;
00797 const char *const full_nm_suffix = nm_suffix;
00798 const char *const full_gnm_suffix = gnm_suffix;
00799 #ifdef LDD_SUFFIX
00800 const char *const full_ldd_suffix = ldd_suffix;
00801 #endif
00802 const char *const full_strip_suffix = strip_suffix;
00803 const char *const full_gstrip_suffix = gstrip_suffix;
00804 #endif
00805
00806 const char *arg;
00807 FILE *outf;
00808 #ifdef COLLECT_EXPORT_LIST
00809 FILE *exportf;
00810 #endif
00811 const char *ld_file_name;
00812 const char *p;
00813 char **c_argv;
00814 const char **c_ptr;
00815 char **ld1_argv;
00816 const char **ld1;
00817 char **ld2_argv;
00818 const char **ld2;
00819 char **object_lst;
00820 const char **object;
00821 int first_file;
00822 int num_c_args = argc+9;
00823
00824 no_demangle = !! getenv ("COLLECT_NO_DEMANGLE");
00825
00826
00827 putenv (xstrdup ("COLLECT_NO_DEMANGLE="));
00828
00829 #if defined (COLLECT2_HOST_INITIALIZATION)
00830
00831 COLLECT2_HOST_INITIALIZATION;
00832 #endif
00833
00834 #ifdef SIGCHLD
00835
00836
00837 signal (SIGCHLD, SIG_DFL);
00838 #endif
00839
00840
00841 unlock_std_streams ();
00842
00843 gcc_init_libintl ();
00844
00845
00846
00847
00848 ld1 = (const char **)(ld1_argv = xcalloc(sizeof (char *), argc+4));
00849 ld2 = (const char **)(ld2_argv = xcalloc(sizeof (char *), argc+11));
00850 object = (const char **)(object_lst = xcalloc(sizeof (char *), argc));
00851
00852 #ifdef DEBUG
00853 debug = 1;
00854 #endif
00855
00856
00857
00858
00859 {
00860 int i;
00861
00862 for (i = 1; argv[i] != NULL; i ++)
00863 {
00864 if (! strcmp (argv[i], "-debug"))
00865 debug = 1;
00866 }
00867 vflag = debug;
00868 }
00869
00870 #ifndef DEFAULT_A_OUT_NAME
00871 output_file = "a.out";
00872 #else
00873 output_file = DEFAULT_A_OUT_NAME;
00874 #endif
00875
00876 obstack_begin (&temporary_obstack, 0);
00877 temporary_firstobj = obstack_alloc (&temporary_obstack, 0);
00878
00879 #ifndef HAVE_LD_DEMANGLE
00880 current_demangling_style = auto_demangling;
00881 #endif
00882 p = getenv ("COLLECT_GCC_OPTIONS");
00883 while (p && *p)
00884 {
00885 const char *q = extract_string (&p);
00886 if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
00887 num_c_args++;
00888 }
00889 obstack_free (&temporary_obstack, temporary_firstobj);
00890
00891
00892
00893 num_c_args += 5;
00894
00895 c_ptr = (const char **) (c_argv = xcalloc (sizeof (char *), num_c_args));
00896
00897 if (argc < 2)
00898 fatal ("no arguments");
00899
00900 #ifdef SIGQUIT
00901 if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
00902 signal (SIGQUIT, handler);
00903 #endif
00904 if (signal (SIGINT, SIG_IGN) != SIG_IGN)
00905 signal (SIGINT, handler);
00906 #ifdef SIGALRM
00907 if (signal (SIGALRM, SIG_IGN) != SIG_IGN)
00908 signal (SIGALRM, handler);
00909 #endif
00910 #ifdef SIGHUP
00911 if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
00912 signal (SIGHUP, handler);
00913 #endif
00914 if (signal (SIGSEGV, SIG_IGN) != SIG_IGN)
00915 signal (SIGSEGV, handler);
00916 #ifdef SIGBUS
00917 if (signal (SIGBUS, SIG_IGN) != SIG_IGN)
00918 signal (SIGBUS, handler);
00919 #endif
00920
00921
00922 prefix_from_env ("COMPILER_PATH", &cpath);
00923 prefix_from_env ("PATH", &path);
00924
00925
00926
00927
00928 ld_file_name = 0;
00929 #ifdef DEFAULT_LINKER
00930 if (access (DEFAULT_LINKER, X_OK) == 0)
00931 ld_file_name = DEFAULT_LINKER;
00932 if (ld_file_name == 0)
00933 #endif
00934 #ifdef REAL_LD_FILE_NAME
00935 ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME);
00936 if (ld_file_name == 0)
00937 #endif
00938
00939 ld_file_name = find_a_file (&cpath, real_ld_suffix);
00940
00941 if (ld_file_name == 0)
00942 ld_file_name = find_a_file (&cpath, collect_ld_suffix);
00943
00944
00945 if (ld_file_name == 0)
00946 ld_file_name = find_a_file (&cpath, ld_suffix);
00947
00948
00949 if (ld_file_name == 0)
00950 ld_file_name = find_a_file (&path, full_ld_suffix);
00951
00952 #ifdef REAL_NM_FILE_NAME
00953 nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME);
00954 if (nm_file_name == 0)
00955 #endif
00956 nm_file_name = find_a_file (&cpath, gnm_suffix);
00957 if (nm_file_name == 0)
00958 nm_file_name = find_a_file (&path, full_gnm_suffix);
00959 if (nm_file_name == 0)
00960 nm_file_name = find_a_file (&cpath, nm_suffix);
00961 if (nm_file_name == 0)
00962 nm_file_name = find_a_file (&path, full_nm_suffix);
00963
00964 #ifdef LDD_SUFFIX
00965 ldd_file_name = find_a_file (&cpath, ldd_suffix);
00966 if (ldd_file_name == 0)
00967 ldd_file_name = find_a_file (&path, full_ldd_suffix);
00968 #endif
00969
00970 #ifdef REAL_STRIP_FILE_NAME
00971 strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME);
00972 if (strip_file_name == 0)
00973 #endif
00974 strip_file_name = find_a_file (&cpath, gstrip_suffix);
00975 if (strip_file_name == 0)
00976 strip_file_name = find_a_file (&path, full_gstrip_suffix);
00977 if (strip_file_name == 0)
00978 strip_file_name = find_a_file (&cpath, strip_suffix);
00979 if (strip_file_name == 0)
00980 strip_file_name = find_a_file (&path, full_strip_suffix);
00981
00982
00983 c_file_name = getenv ("COLLECT_GCC");
00984 if (c_file_name == 0)
00985 {
00986 #ifdef CROSS_COMPILE
00987 c_file_name = concat (target_machine, "-gcc", NULL);
00988 #else
00989 c_file_name = "gcc";
00990 #endif
00991 }
00992
00993 p = find_a_file (&cpath, c_file_name);
00994
00995
00996
00997 if (p == 0)
00998 p = find_a_file (&path, c_file_name);
00999
01000 if (p)
01001 c_file_name = p;
01002
01003 *ld1++ = *ld2++ = ld_file_name;
01004
01005
01006 c_file = make_temp_file (".c");
01007 o_file = make_temp_file (".o");
01008 #ifdef COLLECT_EXPORT_LIST
01009 export_file = make_temp_file (".x");
01010 #endif
01011 ldout = make_temp_file (".ld");
01012 *c_ptr++ = c_file_name;
01013 *c_ptr++ = "-x";
01014 *c_ptr++ = "c";
01015 *c_ptr++ = "-c";
01016 *c_ptr++ = "-o";
01017 *c_ptr++ = o_file;
01018
01019 #ifdef COLLECT_EXPORT_LIST
01020
01021 prefix_from_env ("LIBPATH", &libpath_lib_dirs);
01022
01023
01024 add_prefix (&libpath_lib_dirs, "/lib");
01025 add_prefix (&libpath_lib_dirs, "/usr/lib");
01026 #endif
01027
01028
01029
01030
01031
01032
01033 p = getenv ("COLLECT_GCC_OPTIONS");
01034 while (p && *p)
01035 {
01036 const char *q = extract_string (&p);
01037 if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
01038 *c_ptr++ = xstrdup (q);
01039 if (strcmp (q, "-EL") == 0 || strcmp (q, "-EB") == 0)
01040 *c_ptr++ = xstrdup (q);
01041 if (strcmp (q, "-shared") == 0)
01042 shared_obj = 1;
01043 if (*q == '-' && q[1] == 'B')
01044 {
01045 *c_ptr++ = xstrdup (q);
01046 if (q[2] == 0)
01047 {
01048 q = extract_string (&p);
01049 *c_ptr++ = xstrdup (q);
01050 }
01051 }
01052 }
01053 obstack_free (&temporary_obstack, temporary_firstobj);
01054 *c_ptr++ = "-fno-profile-arcs";
01055 *c_ptr++ = "-fno-test-coverage";
01056 *c_ptr++ = "-fno-branch-probabilities";
01057 *c_ptr++ = "-fno-exceptions";
01058 *c_ptr++ = "-w";
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070 first_file = 1;
01071 #ifdef HAVE_LD_DEMANGLE
01072 if (!demangle_flag && !no_demangle)
01073 demangle_flag = "--demangle";
01074 if (demangle_flag)
01075 *ld1++ = *ld2++ = demangle_flag;
01076 #endif
01077 while ((arg = *++argv) != (char *) 0)
01078 {
01079 *ld1++ = *ld2++ = arg;
01080
01081 if (arg[0] == '-')
01082 {
01083 switch (arg[1])
01084 {
01085 #ifdef COLLECT_EXPORT_LIST
01086
01087
01088 case 'b':
01089 if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0)
01090 export_flag = 1;
01091 else if (arg[2] == '6' && arg[3] == '4')
01092 aix64_flag = 1;
01093 else if (arg[2] == 'r' && arg[3] == 't' && arg[4] == 'l')
01094 aixrtl_flag = 1;
01095 break;
01096 #endif
01097
01098 case 'd':
01099 if (!strcmp (arg, "-debug"))
01100 {
01101
01102 ld1--;
01103 ld2--;
01104 }
01105 if (!strcmp (arg, "-dynamic-linker") && argv[1])
01106 {
01107 ++argv;
01108 *ld1++ = *ld2++ = *argv;
01109 }
01110 break;
01111
01112 case 'l':
01113 if (first_file)
01114 {
01115
01116 first_file = 0;
01117 ld2--;
01118 *ld2++ = o_file;
01119 *ld2++ = arg;
01120 }
01121 #ifdef COLLECT_EXPORT_LIST
01122 {
01123
01124 const char *s = resolve_lib_name (arg+2);
01125
01126
01127 add_to_list (&libs, s);
01128 }
01129 #endif
01130 break;
01131
01132 #ifdef COLLECT_EXPORT_LIST
01133
01134 case 'L':
01135 add_prefix (&cmdline_lib_dirs, arg+2);
01136 break;
01137 #else
01138 #if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
01139 case 'L':
01140 if (is_in_args (arg, (const char **) ld1_argv, ld1-1))
01141 --ld1;
01142 break;
01143 #endif
01144 #endif
01145
01146 case 'o':
01147 if (arg[2] == '\0')
01148 output_file = *ld1++ = *ld2++ = *++argv;
01149 else if (1
01150 #ifdef SWITCHES_NEED_SPACES
01151 && ! strchr (SWITCHES_NEED_SPACES, arg[1])
01152 #endif
01153 )
01154
01155 output_file = &arg[2];
01156 break;
01157
01158 case 'r':
01159 if (arg[2] == '\0')
01160 rflag = 1;
01161 break;
01162
01163 case 's':
01164 if (arg[2] == '\0' && do_collecting)
01165 {
01166
01167
01168
01169 strip_flag = 1;
01170 ld1--;
01171 }
01172 break;
01173
01174 case 'v':
01175 if (arg[2] == '\0')
01176 vflag = 1;
01177 break;
01178
01179 case '-':
01180 if (strcmp (arg, "--no-demangle") == 0)
01181 {
01182 demangle_flag = arg;
01183 no_demangle = 1;
01184 ld1--;
01185 ld2--;
01186 }
01187 else if (strncmp (arg, "--demangle", 10) == 0)
01188 {
01189 demangle_flag = arg;
01190 no_demangle = 0;
01191 #ifndef HAVE_LD_DEMANGLE
01192 if (arg[10] == '=')
01193 {
01194 enum demangling_styles style
01195 = cplus_demangle_name_to_style (arg+11);
01196 if (style == unknown_demangling)
01197 error ("unknown demangling style '%s'", arg+11);
01198 else
01199 current_demangling_style = style;
01200 }
01201 #endif
01202 ld1--;
01203 ld2--;
01204 }
01205 break;
01206 }
01207 }
01208 else if ((p = strrchr (arg, '.')) != (char *) 0
01209 && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0
01210 || strcmp (p, ".so") == 0 || strcmp (p, ".lo") == 0
01211 || strcmp (p, ".obj") == 0))
01212 {
01213 if (first_file)
01214 {
01215 first_file = 0;
01216 if (p[1] == 'o')
01217 *ld2++ = o_file;
01218 else
01219 {
01220
01221 ld2--;
01222 *ld2++ = o_file;
01223 *ld2++ = arg;
01224 }
01225 }
01226 if (p[1] == 'o' || p[1] == 'l')
01227 *object++ = arg;
01228 #ifdef COLLECT_EXPORT_LIST
01229
01230 else
01231 {
01232
01233 add_to_list (&libs, arg);
01234 }
01235 #endif
01236 }
01237 }
01238
01239 #ifdef COLLECT_EXPORT_LIST
01240
01241 if (debug)
01242 {
01243 fprintf (stderr, "List of libraries:\n");
01244 dump_list (stderr, "\t", libs.first);
01245 }
01246
01247
01248
01249 {
01250 const char **export_object_lst = (const char **)object_lst;
01251
01252 while (export_object_lst < object)
01253 scan_prog_file (*export_object_lst++, PASS_OBJ);
01254 }
01255 {
01256 struct id *list = libs.first;
01257
01258 for (; list; list = list->next)
01259 scan_prog_file (list->name, PASS_FIRST);
01260 }
01261
01262 if (exports.first)
01263 {
01264 char *buf = concat ("-bE:", export_file, NULL);
01265
01266 *ld1++ = buf;
01267 *ld2++ = buf;
01268
01269 exportf = fopen (export_file, "w");
01270 if (exportf == (FILE *) 0)
01271 fatal_perror ("fopen %s", export_file);
01272 write_aix_file (exportf, exports.first);
01273 if (fclose (exportf))
01274 fatal_perror ("fclose %s", export_file);
01275 }
01276 #endif
01277
01278 *c_ptr++ = c_file;
01279 *c_ptr = *ld1 = *object = (char *) 0;
01280
01281 if (vflag)
01282 {
01283 notice ("collect2 version %s", version_string);
01284 #ifdef TARGET_VERSION
01285 TARGET_VERSION;
01286 #endif
01287 fprintf (stderr, "\n");
01288 }
01289
01290 if (debug)
01291 {
01292 const char *ptr;
01293 fprintf (stderr, "ld_file_name = %s\n",
01294 (ld_file_name ? ld_file_name : "not found"));
01295 fprintf (stderr, "c_file_name = %s\n",
01296 (c_file_name ? c_file_name : "not found"));
01297 fprintf (stderr, "nm_file_name = %s\n",
01298 (nm_file_name ? nm_file_name : "not found"));
01299 #ifdef LDD_SUFFIX
01300 fprintf (stderr, "ldd_file_name = %s\n",
01301 (ldd_file_name ? ldd_file_name : "not found"));
01302 #endif
01303 fprintf (stderr, "strip_file_name = %s\n",
01304 (strip_file_name ? strip_file_name : "not found"));
01305 fprintf (stderr, "c_file = %s\n",
01306 (c_file ? c_file : "not found"));
01307 fprintf (stderr, "o_file = %s\n",
01308 (o_file ? o_file : "not found"));
01309
01310 ptr = getenv ("COLLECT_GCC_OPTIONS");
01311 if (ptr)
01312 fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr);
01313
01314 ptr = getenv ("COLLECT_GCC");
01315 if (ptr)
01316 fprintf (stderr, "COLLECT_GCC = %s\n", ptr);
01317
01318 ptr = getenv ("COMPILER_PATH");
01319 if (ptr)
01320 fprintf (stderr, "COMPILER_PATH = %s\n", ptr);
01321
01322 ptr = getenv (LIBRARY_PATH_ENV);
01323 if (ptr)
01324 fprintf (stderr, "%-20s= %s\n", LIBRARY_PATH_ENV, ptr);
01325
01326 fprintf (stderr, "\n");
01327 }
01328
01329
01330
01331
01332
01333 #ifndef COLLECT_EXPORT_LIST
01334 do_tlink (ld1_argv, object_lst);
01335 #endif
01336
01337
01338
01339 if (rflag
01340 #ifndef COLLECT_EXPORT_LIST
01341 || ! do_collecting
01342 #endif
01343 )
01344 {
01345 #ifdef COLLECT_EXPORT_LIST
01346
01347 do_tlink (ld1_argv, object_lst);
01348
01349
01350 if (export_file != 0 && export_file[0])
01351 maybe_unlink (export_file);
01352 #endif
01353 maybe_unlink (c_file);
01354 maybe_unlink (o_file);
01355 return 0;
01356 }
01357
01358
01359
01360
01361
01362
01363 #ifndef COLLECT_EXPORT_LIST
01364 scan_prog_file (output_file, PASS_FIRST);
01365 #endif
01366
01367 #ifdef SCAN_LIBRARIES
01368 scan_libraries (output_file);
01369 #endif
01370
01371 if (debug)
01372 {
01373 notice ("%d constructor(s) found\n", constructors.number);
01374 notice ("%d destructor(s) found\n", destructors.number);
01375 notice ("%d frame table(s) found\n", frame_tables.number);
01376 }
01377
01378 if (constructors.number == 0 && destructors.number == 0
01379 && frame_tables.number == 0
01380 #if defined (SCAN_LIBRARIES) || defined (COLLECT_EXPORT_LIST)
01381
01382
01383
01384 && ! shared_obj
01385 #endif
01386 )
01387 {
01388 #ifdef COLLECT_EXPORT_LIST
01389
01390 do_tlink (ld1_argv, object_lst);
01391 #endif
01392
01393 if (strip_flag)
01394 {
01395 char **real_strip_argv = xcalloc (sizeof (char *), 3);
01396 const char ** strip_argv = (const char **) real_strip_argv;
01397
01398 strip_argv[0] = strip_file_name;
01399 strip_argv[1] = output_file;
01400 strip_argv[2] = (char *) 0;
01401 fork_execute ("strip", real_strip_argv);
01402 }
01403
01404 #ifdef COLLECT_EXPORT_LIST
01405 maybe_unlink (export_file);
01406 #endif
01407 maybe_unlink (c_file);
01408 maybe_unlink (o_file);
01409 return 0;
01410 }
01411
01412
01413 sort_ids (&constructors);
01414 sort_ids (&destructors);
01415
01416 maybe_unlink(output_file);
01417 outf = fopen (c_file, "w");
01418 if (outf == (FILE *) 0)
01419 fatal_perror ("fopen %s", c_file);
01420
01421 write_c_file (outf, c_file);
01422
01423 if (fclose (outf))
01424 fatal_perror ("fclose %s", c_file);
01425
01426
01427 #ifdef LD_INIT_SWITCH
01428 #ifdef COLLECT_EXPORT_LIST
01429 *ld2++ = concat (LD_INIT_SWITCH, ":", initname, ":", fininame, NULL);
01430 #else
01431 *ld2++ = LD_INIT_SWITCH;
01432 *ld2++ = initname;
01433 *ld2++ = LD_FINI_SWITCH;
01434 *ld2++ = fininame;
01435 #endif
01436 #endif
01437
01438 #ifdef COLLECT_EXPORT_LIST
01439 if (shared_obj)
01440 {
01441
01442
01443 if (! exports.first)
01444 *ld2++ = concat ("-bE:", export_file, NULL);
01445
01446 #ifndef LD_INIT_SWITCH
01447 add_to_list (&exports, initname);
01448 add_to_list (&exports, fininame);
01449 add_to_list (&exports, "_GLOBAL__DI");
01450 add_to_list (&exports, "_GLOBAL__DD");
01451 #endif
01452 exportf = fopen (export_file, "w");
01453 if (exportf == (FILE *) 0)
01454 fatal_perror ("fopen %s", export_file);
01455 write_aix_file (exportf, exports.first);
01456 if (fclose (exportf))
01457 fatal_perror ("fclose %s", export_file);
01458 }
01459 #endif
01460
01461
01462 *ld2 = (char*) 0;
01463
01464 if (debug)
01465 {
01466 fprintf (stderr, "\n========== output_file = %s, c_file = %s\n",
01467 output_file, c_file);
01468 write_c_file (stderr, "stderr");
01469 fprintf (stderr, "========== end of c_file\n\n");
01470 #ifdef COLLECT_EXPORT_LIST
01471 fprintf (stderr, "\n========== export_file = %s\n", export_file);
01472 write_aix_file (stderr, exports.first);
01473 fprintf (stderr, "========== end of export_file\n\n");
01474 #endif
01475 }
01476
01477
01478
01479
01480 fork_execute ("gcc", c_argv);
01481 #ifdef COLLECT_EXPORT_LIST
01482
01483 do_tlink (ld2_argv, object_lst);
01484 #else
01485
01486 fork_execute ("ld", ld2_argv);
01487
01488
01489
01490 scan_prog_file (output_file, PASS_SECOND);
01491 #endif
01492
01493 maybe_unlink (c_file);
01494 maybe_unlink (o_file);
01495
01496 #ifdef COLLECT_EXPORT_LIST
01497 maybe_unlink (export_file);
01498 #endif
01499
01500 return 0;
01501 }
01502
01503
01504
01505
01506 int
01507 collect_wait (const char *prog)
01508 {
01509 int status;
01510
01511 pwait (pid, &status, 0);
01512 if (status)
01513 {
01514 if (WIFSIGNALED (status))
01515 {
01516 int sig = WTERMSIG (status);
01517 error ("%s terminated with signal %d [%s]%s",
01518 prog, sig, strsignal(sig),
01519 WCOREDUMP(status) ? ", core dumped" : "");
01520 collect_exit (FATAL_EXIT_CODE);
01521 }
01522
01523 if (WIFEXITED (status))
01524 return WEXITSTATUS (status);
01525 }
01526 return 0;
01527 }
01528
01529 static void
01530 do_wait (const char *prog)
01531 {
01532 int ret = collect_wait (prog);
01533 if (ret != 0)
01534 {
01535 error ("%s returned %d exit status", prog, ret);
01536 collect_exit (ret);
01537 }
01538 }
01539
01540
01541
01542
01543 void
01544 collect_execute (const char *prog, char **argv, const char *redir)
01545 {
01546 char *errmsg_fmt;
01547 char *errmsg_arg;
01548 int redir_handle = -1;
01549 int stdout_save = -1;
01550 int stderr_save = -1;
01551
01552 if (vflag || debug)
01553 {
01554 char **p_argv;
01555 const char *str;
01556
01557 if (argv[0])
01558 fprintf (stderr, "%s", argv[0]);
01559 else
01560 notice ("[cannot find %s]", prog);
01561
01562 for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++)
01563 fprintf (stderr, " %s", str);
01564
01565 fprintf (stderr, "\n");
01566 }
01567
01568 fflush (stdout);
01569 fflush (stderr);
01570
01571
01572
01573
01574 if (argv[0] == 0)
01575 fatal ("cannot find '%s'", prog);
01576
01577 if (redir)
01578 {
01579
01580 redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT);
01581
01582
01583
01584 stdout_save = dup (STDOUT_FILENO);
01585 if (stdout_save == -1)
01586 fatal_perror ("redirecting stdout: %s", redir);
01587 stderr_save = dup (STDERR_FILENO);
01588 if (stderr_save == -1)
01589 fatal_perror ("redirecting stdout: %s", redir);
01590
01591
01592 dup2 (redir_handle, STDOUT_FILENO);
01593 dup2 (redir_handle, STDERR_FILENO);
01594 }
01595
01596 pid = pexecute (argv[0], argv, argv[0], NULL, &errmsg_fmt, &errmsg_arg,
01597 (PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH));
01598
01599 if (redir)
01600 {
01601
01602 dup2 (stdout_save, STDOUT_FILENO);
01603 dup2 (stderr_save, STDERR_FILENO);
01604
01605
01606 close (redir_handle);
01607 }
01608
01609 if (pid == -1)
01610 fatal_perror (errmsg_fmt, errmsg_arg);
01611 }
01612
01613 static void
01614 fork_execute (const char *prog, char **argv)
01615 {
01616 collect_execute (prog, argv, NULL);
01617 do_wait (prog);
01618 }
01619
01620
01621
01622 static void
01623 maybe_unlink (const char *file)
01624 {
01625 if (!debug)
01626 unlink (file);
01627 else
01628 notice ("[Leaving %s]\n", file);
01629 }
01630
01631
01632 static long sequence_number = 0;
01633
01634
01635
01636 static void
01637 add_to_list (struct head *head_ptr, const char *name)
01638 {
01639 struct id *newid = xcalloc (sizeof (struct id) + strlen (name), 1);
01640 struct id *p;
01641 strcpy (newid->name, name);
01642
01643 if (head_ptr->first)
01644 head_ptr->last->next = newid;
01645 else
01646 head_ptr->first = newid;
01647
01648
01649 for (p = head_ptr->first;
01650 strcmp (name, p->name) != 0;
01651 p = p->next)
01652 ;
01653 if (p != newid)
01654 {
01655 head_ptr->last->next = 0;
01656 free (newid);
01657 return;
01658 }
01659
01660 newid->sequence = ++sequence_number;
01661 head_ptr->last = newid;
01662 head_ptr->number++;
01663 }
01664
01665
01666
01667
01668 static int
01669 extract_init_priority (const char *name)
01670 {
01671 int pos = 0, pri;
01672
01673 while (name[pos] == '_')
01674 ++pos;
01675 pos += 10;
01676
01677
01678 pri = atoi (name + pos);
01679 return pri ? pri : DEFAULT_INIT_PRIORITY;
01680 }
01681
01682
01683
01684
01685 static void
01686 sort_ids (struct head *head_ptr)
01687 {
01688
01689
01690
01691 struct id *id, *id_next, **id_ptr;
01692
01693 id = head_ptr->first;
01694
01695
01696 head_ptr->first = NULL;
01697
01698 for (; id; id = id_next)
01699 {
01700 id_next = id->next;
01701 id->sequence = extract_init_priority (id->name);
01702
01703 for (id_ptr = &(head_ptr->first); ; id_ptr = &((*id_ptr)->next))
01704 if (*id_ptr == NULL
01705
01706
01707 || id->sequence > (*id_ptr)->sequence
01708
01709
01710
01711 )
01712 {
01713 id->next = *id_ptr;
01714 *id_ptr = id;
01715 break;
01716 }
01717 }
01718
01719
01720 for (id = head_ptr->first; id; id = id->next)
01721 id->sequence = ++sequence_number;
01722 }
01723
01724
01725
01726 static void
01727 write_list (FILE *stream, const char *prefix, struct id *list)
01728 {
01729 while (list)
01730 {
01731 fprintf (stream, "%sx%d,\n", prefix, list->sequence);
01732 list = list->next;
01733 }
01734 }
01735
01736 #if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
01737
01738
01739
01740 static int
01741 is_in_args (const char *string, const char **args_begin,
01742 const char **args_end)
01743 {
01744 const char **args_pointer;
01745 for (args_pointer = args_begin; args_pointer != args_end; ++args_pointer)
01746 if (strcmp (string, *args_pointer) == 0)
01747 return 1;
01748 return 0;
01749 }
01750 #endif
01751
01752 #ifdef COLLECT_EXPORT_LIST
01753
01754 #if 0
01755 static int
01756 is_in_list (const char *prefix, struct id *list)
01757 {
01758 while (list)
01759 {
01760 if (!strcmp (prefix, list->name)) return 1;
01761 list = list->next;
01762 }
01763 return 0;
01764 }
01765 #endif
01766 #endif
01767
01768
01769 #ifdef COLLECT_EXPORT_LIST
01770 static void
01771 dump_list (FILE *stream, const char *prefix, struct id *list)
01772 {
01773 while (list)
01774 {
01775 fprintf (stream, "%s%s,\n", prefix, list->name);
01776 list = list->next;
01777 }
01778 }
01779 #endif
01780
01781 #if 0
01782 static void
01783 dump_prefix_list (FILE *stream, const char *prefix, struct prefix_list *list)
01784 {
01785 while (list)
01786 {
01787 fprintf (stream, "%s%s,\n", prefix, list->prefix);
01788 list = list->next;
01789 }
01790 }
01791 #endif
01792
01793 static void
01794 write_list_with_asm (FILE *stream, const char *prefix, struct id *list)
01795 {
01796 while (list)
01797 {
01798 fprintf (stream, "%sx%d __asm__ (\"%s\");\n",
01799 prefix, list->sequence, list->name);
01800 list = list->next;
01801 }
01802 }
01803
01804
01805
01806
01807 static void
01808 write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED)
01809 {
01810 const char *p, *q;
01811 char *prefix, *r;
01812 int frames = (frame_tables.number > 0);
01813
01814
01815 p = strrchr (output_file, '/');
01816 if (p == 0)
01817 p = output_file;
01818 else
01819 p++;
01820 q = p;
01821 while (q)
01822 {
01823 q = strchr (q,'.');
01824 if (q == 0)
01825 {
01826 q = p + strlen (p);
01827 break;
01828 }
01829 else
01830 {
01831 if (strncmp (q, ".so", 3) == 0)
01832 {
01833 q += 3;
01834 break;
01835 }
01836 else
01837 q++;
01838 }
01839 }
01840
01841 prefix = xmalloc (q - p + 1);
01842 strncpy (prefix, p, q - p);
01843 prefix[q - p] = 0;
01844 for (r = prefix; *r; r++)
01845 if (!ISALNUM ((unsigned char)*r))
01846 *r = '_';
01847 if (debug)
01848 notice ("\nwrite_c_file - output name is %s, prefix is %s\n",
01849 output_file, prefix);
01850
01851 initname = concat ("_GLOBAL__FI_", prefix, NULL);
01852 fininame = concat ("_GLOBAL__FD_", prefix, NULL);
01853
01854 free (prefix);
01855
01856
01857
01858 fprintf (stream, "static int count;\n");
01859 fprintf (stream, "typedef void entry_pt();\n");
01860 write_list_with_asm (stream, "extern entry_pt ", constructors.first);
01861
01862 if (frames)
01863 {
01864 write_list_with_asm (stream, "extern void *", frame_tables.first);
01865
01866 fprintf (stream, "\tstatic void *frame_table[] = {\n");
01867 write_list (stream, "\t\t&", frame_tables.first);
01868 fprintf (stream, "\t0\n};\n");
01869
01870
01871 fprintf (stream, "struct object {\n");
01872 fprintf (stream, " void *pc_begin;\n");
01873 fprintf (stream, " void *pc_end;\n");
01874 fprintf (stream, " void *fde_begin;\n");
01875 fprintf (stream, " void *fde_array;\n");
01876 fprintf (stream, " __SIZE_TYPE__ count;\n");
01877 fprintf (stream, " struct object *next;\n");
01878 fprintf (stream, "};\n");
01879
01880 fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
01881 fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
01882
01883 fprintf (stream, "static void reg_frame () {\n");
01884 fprintf (stream, "\tstatic struct object ob;\n");
01885 fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
01886 fprintf (stream, "\t}\n");
01887
01888 fprintf (stream, "static void dereg_frame () {\n");
01889 fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
01890 fprintf (stream, "\t}\n");
01891 }
01892
01893 fprintf (stream, "void %s() {\n", initname);
01894 if (constructors.number > 0 || frames)
01895 {
01896 fprintf (stream, "\tstatic entry_pt *ctors[] = {\n");
01897 write_list (stream, "\t\t", constructors.first);
01898 if (frames)
01899 fprintf (stream, "\treg_frame,\n");
01900 fprintf (stream, "\t};\n");
01901 fprintf (stream, "\tentry_pt **p;\n");
01902 fprintf (stream, "\tif (count++ != 0) return;\n");
01903 fprintf (stream, "\tp = ctors + %d;\n", constructors.number + frames);
01904 fprintf (stream, "\twhile (p > ctors) (*--p)();\n");
01905 }
01906 else
01907 fprintf (stream, "\t++count;\n");
01908 fprintf (stream, "}\n");
01909 write_list_with_asm (stream, "extern entry_pt ", destructors.first);
01910 fprintf (stream, "void %s() {\n", fininame);
01911 if (destructors.number > 0 || frames)
01912 {
01913 fprintf (stream, "\tstatic entry_pt *dtors[] = {\n");
01914 write_list (stream, "\t\t", destructors.first);
01915 if (frames)
01916 fprintf (stream, "\tdereg_frame,\n");
01917 fprintf (stream, "\t};\n");
01918 fprintf (stream, "\tentry_pt **p;\n");
01919 fprintf (stream, "\tif (--count != 0) return;\n");
01920 fprintf (stream, "\tp = dtors;\n");
01921 fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n",
01922 destructors.number + frames);
01923 }
01924 fprintf (stream, "}\n");
01925
01926 if (shared_obj)
01927 {
01928 COLLECT_SHARED_INIT_FUNC(stream, initname);
01929 COLLECT_SHARED_FINI_FUNC(stream, fininame);
01930 }
01931 }
01932
01933
01934
01935 #ifndef LD_INIT_SWITCH
01936 static void
01937 write_c_file_glob (FILE *stream, const char *name ATTRIBUTE_UNUSED)
01938 {
01939
01940
01941 int frames = (frame_tables.number > 0);
01942
01943 fprintf (stream, "typedef void entry_pt();\n\n");
01944
01945 write_list_with_asm (stream, "extern entry_pt ", constructors.first);
01946
01947 if (frames)
01948 {
01949 write_list_with_asm (stream, "extern void *", frame_tables.first);
01950
01951 fprintf (stream, "\tstatic void *frame_table[] = {\n");
01952 write_list (stream, "\t\t&", frame_tables.first);
01953 fprintf (stream, "\t0\n};\n");
01954
01955
01956 fprintf (stream, "struct object {\n");
01957 fprintf (stream, " void *pc_begin;\n");
01958 fprintf (stream, " void *pc_end;\n");
01959 fprintf (stream, " void *fde_begin;\n");
01960 fprintf (stream, " void *fde_array;\n");
01961 fprintf (stream, " __SIZE_TYPE__ count;\n");
01962 fprintf (stream, " struct object *next;\n");
01963 fprintf (stream, "};\n");
01964
01965 fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n");
01966 fprintf (stream, "extern void *__deregister_frame_info (void *);\n");
01967
01968 fprintf (stream, "static void reg_frame () {\n");
01969 fprintf (stream, "\tstatic struct object ob;\n");
01970 fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n");
01971 fprintf (stream, "\t}\n");
01972
01973 fprintf (stream, "static void dereg_frame () {\n");
01974 fprintf (stream, "\t__deregister_frame_info (frame_table);\n");
01975 fprintf (stream, "\t}\n");
01976 }
01977
01978 fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n");
01979 fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number + frames);
01980 write_list (stream, "\t", constructors.first);
01981 if (frames)
01982 fprintf (stream, "\treg_frame,\n");
01983 fprintf (stream, "\t0\n};\n\n");
01984
01985 write_list_with_asm (stream, "extern entry_pt ", destructors.first);
01986
01987 fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n");
01988 fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number + frames);
01989 write_list (stream, "\t", destructors.first);
01990 if (frames)
01991 fprintf (stream, "\tdereg_frame,\n");
01992 fprintf (stream, "\t0\n};\n\n");
01993
01994 fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN);
01995 fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN);
01996 }
01997 #endif
01998
01999 static void
02000 write_c_file (FILE *stream, const char *name)
02001 {
02002 fprintf (stream, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
02003 #ifndef LD_INIT_SWITCH
02004 if (! shared_obj)
02005 write_c_file_glob (stream, name);
02006 else
02007 #endif
02008 write_c_file_stat (stream, name);
02009 fprintf (stream, "#ifdef __cplusplus\n}\n#endif\n");
02010 }
02011
02012 #ifdef COLLECT_EXPORT_LIST
02013 static void
02014 write_aix_file (FILE *stream, struct id *list)
02015 {
02016 for (; list; list = list->next)
02017 {
02018 fputs (list->name, stream);
02019 putc ('\n', stream);
02020 }
02021 }
02022 #endif
02023
02024 #ifdef OBJECT_FORMAT_NONE
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035 static void
02036 scan_prog_file (const char *prog_name, enum pass which_pass)
02037 {
02038 void (*int_handler) (int);
02039 void (*quit_handler) (int);
02040 char *real_nm_argv[4];
02041 const char **nm_argv = (const char **) real_nm_argv;
02042 int argc = 0;
02043 int pipe_fd[2];
02044 char *p, buf[1024];
02045 FILE *inf;
02046
02047 if (which_pass == PASS_SECOND)
02048 return;
02049
02050
02051 if (nm_file_name == 0)
02052 fatal ("cannot find 'nm'");
02053
02054 nm_argv[argc++] = nm_file_name;
02055 if (NM_FLAGS[0] != '\0')
02056 nm_argv[argc++] = NM_FLAGS;
02057
02058 nm_argv[argc++] = prog_name;
02059 nm_argv[argc++] = (char *) 0;
02060
02061 if (pipe (pipe_fd) < 0)
02062 fatal_perror ("pipe");
02063
02064 inf = fdopen (pipe_fd[0], "r");
02065 if (inf == (FILE *) 0)
02066 fatal_perror ("fdopen");
02067
02068
02069 if (vflag)
02070 {
02071 const char **p_argv;
02072 const char *str;
02073
02074 for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
02075 fprintf (stderr, " %s", str);
02076
02077 fprintf (stderr, "\n");
02078 }
02079
02080 fflush (stdout);
02081 fflush (stderr);
02082
02083
02084 pid = vfork ();
02085 if (pid == -1)
02086 fatal_perror (VFORK_STRING);
02087
02088 if (pid == 0)
02089 {
02090
02091 if (dup2 (pipe_fd[1], 1) < 0)
02092 fatal_perror ("dup2 %d 1", pipe_fd[1]);
02093
02094 if (close (pipe_fd[0]) < 0)
02095 fatal_perror ("close %d", pipe_fd[0]);
02096
02097 if (close (pipe_fd[1]) < 0)
02098 fatal_perror ("close %d", pipe_fd[1]);
02099
02100 execv (nm_file_name, real_nm_argv);
02101 fatal_perror ("execv %s", nm_file_name);
02102 }
02103
02104
02105 int_handler = (void (*) (int)) signal (SIGINT, SIG_IGN);
02106 #ifdef SIGQUIT
02107 quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN);
02108 #endif
02109
02110 if (close (pipe_fd[1]) < 0)
02111 fatal_perror ("close %d", pipe_fd[1]);
02112
02113 if (debug)
02114 fprintf (stderr, "\nnm output with constructors/destructors.\n");
02115
02116
02117 while (fgets (buf, sizeof buf, inf) != (char *) 0)
02118 {
02119 int ch, ch2;
02120 char *name, *end;
02121
02122
02123
02124
02125 for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
02126 if (ch == ' ' && p[1] == 'U' && p[2] == ' ')
02127 break;
02128
02129 if (ch != '_')
02130 continue;
02131
02132 name = p;
02133
02134
02135 for (end = p; (ch2 = *end) != '\0' && !ISSPACE (ch2) && ch2 != '|';
02136 end++)
02137 continue;
02138
02139
02140 *end = '\0';
02141 switch (is_ctor_dtor (name))
02142 {
02143 case 1:
02144 if (which_pass != PASS_LIB)
02145 add_to_list (&constructors, name);
02146 break;
02147
02148 case 2:
02149 if (which_pass != PASS_LIB)
02150 add_to_list (&destructors, name);
02151 break;
02152
02153 case 3:
02154 if (which_pass != PASS_LIB)
02155 fatal ("init function found in object %s", prog_name);
02156 #ifndef LD_INIT_SWITCH
02157 add_to_list (&constructors, name);
02158 #endif
02159 break;
02160
02161 case 4:
02162 if (which_pass != PASS_LIB)
02163 fatal ("fini function found in object %s", prog_name);
02164 #ifndef LD_FINI_SWITCH
02165 add_to_list (&destructors, name);
02166 #endif
02167 break;
02168
02169 case 5:
02170 if (which_pass != PASS_LIB)
02171 add_to_list (&frame_tables, name);
02172 break;
02173
02174 default:
02175 continue;
02176 }
02177
02178 if (debug)
02179 fprintf (stderr, "\t%s\n", buf);
02180 }
02181
02182 if (debug)
02183 fprintf (stderr, "\n");
02184
02185 if (fclose (inf) != 0)
02186 fatal_perror ("fclose");
02187
02188 do_wait (nm_file_name);
02189
02190 signal (SIGINT, int_handler);
02191 #ifdef SIGQUIT
02192 signal (SIGQUIT, quit_handler);
02193 #endif
02194 }
02195
02196 #ifdef LDD_SUFFIX
02197
02198
02199
02200
02201
02202 static void
02203 scan_libraries (const char *prog_name)
02204 {
02205 static struct head libraries;
02206 struct id *list;
02207 void (*int_handler) (int);
02208 void (*quit_handler) (int);
02209 char *real_ldd_argv[4];
02210 const char **ldd_argv = (const char **) real_ldd_argv;
02211 int argc = 0;
02212 int pipe_fd[2];
02213 char buf[1024];
02214 FILE *inf;
02215
02216
02217 if (ldd_file_name == 0)
02218 {
02219 error ("cannot find 'ldd'");
02220 return;
02221 }
02222
02223 ldd_argv[argc++] = ldd_file_name;
02224 ldd_argv[argc++] = prog_name;
02225 ldd_argv[argc++] = (char *) 0;
02226
02227 if (pipe (pipe_fd) < 0)
02228 fatal_perror ("pipe");
02229
02230 inf = fdopen (pipe_fd[0], "r");
02231 if (inf == (FILE *) 0)
02232 fatal_perror ("fdopen");
02233
02234
02235 if (vflag)
02236 {
02237 const char **p_argv;
02238 const char *str;
02239
02240 for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
02241 fprintf (stderr, " %s", str);
02242
02243 fprintf (stderr, "\n");
02244 }
02245
02246 fflush (stdout);
02247 fflush (stderr);
02248
02249
02250 pid = vfork ();
02251 if (pid == -1)
02252 fatal_perror (VFORK_STRING);
02253
02254 if (pid == 0)
02255 {
02256
02257 if (dup2 (pipe_fd[1], 1) < 0)
02258 fatal_perror ("dup2 %d 1", pipe_fd[1]);
02259
02260 if (close (pipe_fd[0]) < 0)
02261 fatal_perror ("close %d", pipe_fd[0]);
02262
02263 if (close (pipe_fd[1]) < 0)
02264 fatal_perror ("close %d", pipe_fd[1]);
02265
02266 execv (ldd_file_name, real_ldd_argv);
02267 fatal_perror ("execv %s", ldd_file_name);
02268 }
02269
02270
02271 int_handler = (void (*) (int)) signal (SIGINT, SIG_IGN);
02272 #ifdef SIGQUIT
02273 quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN);
02274 #endif
02275
02276 if (close (pipe_fd[1]) < 0)
02277 fatal_perror ("close %d", pipe_fd[1]);
02278
02279 if (debug)
02280 notice ("\nldd output with constructors/destructors.\n");
02281
02282
02283 while (fgets (buf, sizeof buf, inf) != (char *) 0)
02284 {
02285 int ch2;
02286 char *name, *end, *p = buf;
02287
02288
02289 PARSE_LDD_OUTPUT (p);
02290 if (p == 0)
02291 continue;
02292
02293 name = p;
02294 if (strncmp (name, "not found", sizeof ("not found") - 1) == 0)
02295 fatal ("dynamic dependency %s not found", buf);
02296
02297
02298 for (end = p;
02299 (ch2 = *end) != '\0' && ch2 != '\n' && !ISSPACE (ch2) && ch2 != '|';
02300 end++)
02301 continue;
02302 *end = '\0';
02303
02304 if (access (name, R_OK) == 0)
02305 add_to_list (&libraries, name);
02306 else
02307 fatal ("unable to open dynamic dependency '%s'", buf);
02308
02309 if (debug)
02310 fprintf (stderr, "\t%s\n", buf);
02311 }
02312 if (debug)
02313 fprintf (stderr, "\n");
02314
02315 if (fclose (inf) != 0)
02316 fatal_perror ("fclose");
02317
02318 do_wait (ldd_file_name);
02319
02320 signal (SIGINT, int_handler);
02321 #ifdef SIGQUIT
02322 signal (SIGQUIT, quit_handler);
02323 #endif
02324
02325
02326
02327 for (list = libraries.first; list; list = list->next)
02328 scan_prog_file (list->name, PASS_LIB);
02329 }
02330
02331 #endif
02332
02333 #endif
02334
02335
02336
02337
02338
02339
02340 #ifdef OBJECT_FORMAT_COFF
02341
02342 #if defined (EXTENDED_COFF)
02343
02344 # define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
02345 # define GCC_SYMENT SYMR
02346 # define GCC_OK_SYMBOL(X) ((X).st == stProc || (X).st == stGlobal)
02347 # define GCC_SYMINC(X) (1)
02348 # define GCC_SYMZERO(X) (SYMHEADER(X).isymMax)
02349 # define GCC_CHECK_HDR(X) (PSYMTAB(X) != 0)
02350
02351 #else
02352
02353 # define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms)
02354 # define GCC_SYMENT SYMENT
02355 # if defined (C_WEAKEXT)
02356 # define GCC_OK_SYMBOL(X) \
02357 (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \
02358 ((X).n_scnum > N_UNDEF) && \
02359 (aix64_flag \
02360 || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
02361 || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
02362 # define GCC_UNDEF_SYMBOL(X) \
02363 (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \
02364 ((X).n_scnum == N_UNDEF))
02365 # else
02366 # define GCC_OK_SYMBOL(X) \
02367 (((X).n_sclass == C_EXT) && \
02368 ((X).n_scnum > N_UNDEF) && \
02369 (aix64_flag \
02370 || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \
02371 || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))))
02372 # define GCC_UNDEF_SYMBOL(X) \
02373 (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF))
02374 # endif
02375 # define GCC_SYMINC(X) ((X).n_numaux+1)
02376 # define GCC_SYMZERO(X) 0
02377
02378
02379 #ifdef _AIX51
02380 # define GCC_CHECK_HDR(X) \
02381 ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
02382 || (HEADER (X).f_magic == 0767 && aix64_flag))
02383 #else
02384 # define GCC_CHECK_HDR(X) \
02385 ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
02386 || (HEADER (X).f_magic == 0757 && aix64_flag))
02387 #endif
02388
02389 #endif
02390
02391 #ifdef COLLECT_EXPORT_LIST
02392
02393
02394 static const char *const aix_std_libs[] = {
02395 "/unix",
02396 "/lib/libc.a",
02397 "/lib/libm.a",
02398 "/lib/libc_r.a",
02399 "/lib/libm_r.a",
02400 "/usr/lib/libc.a",
02401 "/usr/lib/libm.a",
02402 "/usr/lib/libc_r.a",
02403 "/usr/lib/libm_r.a",
02404 "/usr/lib/threads/libc.a",
02405 "/usr/ccs/lib/libc.a",
02406 "/usr/ccs/lib/libm.a",
02407 "/usr/ccs/lib/libc_r.a",
02408 "/usr/ccs/lib/libm_r.a",
02409 NULL
02410 };
02411
02412
02413
02414 static int ignore_library (const char *);
02415 static int
02416 ignore_library (const char *name)
02417 {
02418 const char *const *p = &aix_std_libs[0];
02419 while (*p++ != NULL)
02420 if (! strcmp (name, *p)) return 1;
02421 return 0;
02422 }
02423 #endif
02424
02425 #if defined (HAVE_DECL_LDGETNAME) && !HAVE_DECL_LDGETNAME
02426 extern char *ldgetname (LDFILE *, GCC_SYMENT *);
02427 #endif
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438 static void
02439 scan_prog_file (const char *prog_name, enum pass which_pass)
02440 {
02441 LDFILE *ldptr = NULL;
02442 int sym_index, sym_count;
02443 int is_shared = 0;
02444
02445 if (which_pass != PASS_FIRST && which_pass != PASS_OBJ)
02446 return;
02447
02448 #ifdef COLLECT_EXPORT_LIST
02449
02450 if (which_pass == PASS_FIRST && ignore_library (prog_name))
02451 return;
02452
02453
02454
02455
02456 do
02457 {
02458 #endif
02459
02460
02461
02462
02463 if ((ldptr = ldopen ((char *)prog_name, ldptr)) != NULL)
02464 {
02465 if (! MY_ISCOFF (HEADER (ldptr).f_magic))
02466 fatal ("%s: not a COFF file", prog_name);
02467
02468 if (GCC_CHECK_HDR (ldptr))
02469 {
02470 sym_count = GCC_SYMBOLS (ldptr);
02471 sym_index = GCC_SYMZERO (ldptr);
02472
02473 #ifdef COLLECT_EXPORT_LIST
02474
02475 is_shared = HEADER (ldptr).f_flags & F_SHROBJ;
02476 #endif
02477
02478 while (sym_index < sym_count)
02479 {
02480 GCC_SYMENT symbol;
02481
02482 if (ldtbread (ldptr, sym_index, &symbol) <= 0)
02483 break;
02484 sym_index += GCC_SYMINC (symbol);
02485
02486 if (GCC_OK_SYMBOL (symbol))
02487 {
02488 char *name;
02489
02490 if ((name = ldgetname (ldptr, &symbol)) == NULL)
02491 continue;
02492
02493 #ifdef XCOFF_DEBUGGING_INFO
02494
02495
02496 if (*name == '.')
02497 ++name;
02498 #endif
02499
02500 switch (is_ctor_dtor (name))
02501 {
02502 case 1:
02503 if (! is_shared)
02504 add_to_list (&constructors, name);
02505 #if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH)
02506 if (which_pass == PASS_OBJ)
02507 add_to_list (&exports, name);
02508 #endif
02509 break;
02510
02511 case 2:
02512 if (! is_shared)
02513 add_to_list (&destructors, name);
02514 #if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH)
02515 if (which_pass == PASS_OBJ)
02516 add_to_list (&exports, name);
02517 #endif
02518 break;
02519
02520 #ifdef COLLECT_EXPORT_LIST
02521 case 3:
02522 #ifndef LD_INIT_SWITCH
02523 if (is_shared)
02524 add_to_list (&constructors, name);
02525 #endif
02526 break;
02527
02528 case 4:
02529 #ifndef LD_INIT_SWITCH
02530 if (is_shared)
02531 add_to_list (&destructors, name);
02532 #endif
02533 break;
02534 #endif
02535
02536 case 5:
02537 if (! is_shared)
02538 add_to_list (&frame_tables, name);
02539 #if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH)
02540 if (which_pass == PASS_OBJ)
02541 add_to_list (&exports, name);
02542 #endif
02543 break;
02544
02545 default:
02546 #ifdef COLLECT_EXPORT_LIST
02547
02548
02549
02550
02551
02552 if (shared_obj && !is_shared
02553 && which_pass == PASS_OBJ && !export_flag)
02554 add_to_list (&exports, name);
02555 #endif
02556 continue;
02557 }
02558
02559 if (debug)
02560 #if !defined(EXTENDED_COFF)
02561 fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n",
02562 symbol.n_scnum, symbol.n_sclass,
02563 (symbol.n_type ? "0" : ""), symbol.n_type,
02564 name);
02565 #else
02566 fprintf (stderr,
02567 "\tiss = %5d, value = %5ld, index = %5d, name = %s\n",
02568 symbol.iss, (long) symbol.value, symbol.index, name);
02569 #endif
02570 }
02571 }
02572 }
02573 #ifdef COLLECT_EXPORT_LIST
02574 else
02575 {
02576
02577
02578 if (debug)
02579 fprintf (stderr, "%s : magic=%o aix64=%d mismatch\n",
02580 prog_name, HEADER (ldptr).f_magic, aix64_flag);
02581 }
02582 #endif
02583 }
02584 else
02585 {
02586 fatal ("%s: cannot open as COFF file", prog_name);
02587 }
02588 #ifdef COLLECT_EXPORT_LIST
02589
02590 }
02591 while (ldclose (ldptr) == FAILURE);
02592 #else
02593
02594 (void) ldclose(ldptr);
02595 #endif
02596 }
02597 #endif
02598
02599 #ifdef COLLECT_EXPORT_LIST
02600
02601
02602 static char *
02603 resolve_lib_name (const char *name)
02604 {
02605 char *lib_buf;
02606 int i, j, l = 0;
02607
02608 const char * const libexts[2] = {"a", "so"};
02609
02610 for (i = 0; libpaths[i]; i++)
02611 if (libpaths[i]->max_len > l)
02612 l = libpaths[i]->max_len;
02613
02614 lib_buf = xmalloc (l + strlen(name) + 10);
02615
02616 for (i = 0; libpaths[i]; i++)
02617 {
02618 struct prefix_list *list = libpaths[i]->plist;
02619 for (; list; list = list->next)
02620 {
02621
02622
02623
02624 const char *p = "";
02625 if (list->prefix[strlen(list->prefix)-1] != '/')
02626 p = "/";
02627 for (j = 0; j < 2; j++)
02628 {
02629 sprintf (lib_buf, "%s%slib%s.%s",
02630 list->prefix, p, name,
02631 libexts[(j + aixrtl_flag) % 2]);
02632 if (debug) fprintf (stderr, "searching for: %s\n", lib_buf);
02633 if (file_exists (lib_buf))
02634 {
02635 if (debug) fprintf (stderr, "found: %s\n", lib_buf);
02636 return (lib_buf);
02637 }
02638 }
02639 }
02640 }
02641 if (debug)
02642 fprintf (stderr, "not found\n");
02643 else
02644 fatal ("library lib%s not found", name);
02645 return (NULL);
02646 }
02647 #endif