collect2.c revision 50397
1/* Collect static initialization info into data structures that can be 2 traversed by C++ initialization and finalization routines. 3 Copyright (C) 1992, 93-97, 1998 Free Software Foundation, Inc. 4 Contributed by Chris Smith (csmith@convex.com). 5 Heavily modified by Michael Meissner (meissner@cygnus.com), 6 Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com). 7 8This file is part of GNU CC. 9 10GNU CC is free software; you can redistribute it and/or modify 11it under the terms of the GNU General Public License as published by 12the Free Software Foundation; either version 2, or (at your option) 13any later version. 14 15GNU CC is distributed in the hope that it will be useful, 16but WITHOUT ANY WARRANTY; without even the implied warranty of 17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18GNU General Public License for more details. 19 20You should have received a copy of the GNU General Public License 21along with GNU CC; see the file COPYING. If not, write to 22the Free Software Foundation, 59 Temple Place - Suite 330, 23Boston, MA 02111-1307, USA. */ 24 25 26/* Build tables of static constructors and destructors and run ld. */ 27 28#include "config.h" 29#include "system.h" 30#include <signal.h> 31#include <sys/stat.h> 32 33#define COLLECT 34 35#include "demangle.h" 36#include "obstack.h" 37#include "gansidecl.h" 38#ifdef __CYGWIN32__ 39#include <process.h> 40#endif 41 42/* Obstack allocation and deallocation routines. */ 43#define obstack_chunk_alloc xmalloc 44#define obstack_chunk_free free 45 46#ifdef USG 47#define vfork fork 48#endif 49 50#ifndef WIFSIGNALED 51#define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f) 52#endif 53#ifndef WTERMSIG 54#define WTERMSIG(S) ((S) & 0x7f) 55#endif 56#ifndef WIFEXITED 57#define WIFEXITED(S) (((S) & 0xff) == 0) 58#endif 59#ifndef WEXITSTATUS 60#define WEXITSTATUS(S) (((S) & 0xff00) >> 8) 61#endif 62 63extern char *make_temp_file PROTO ((char *)); 64 65/* On certain systems, we have code that works by scanning the object file 66 directly. But this code uses system-specific header files and library 67 functions, so turn it off in a cross-compiler. Likewise, the names of 68 the utilities are not correct for a cross-compiler; we have to hope that 69 cross-versions are in the proper directories. */ 70 71#ifdef CROSS_COMPILE 72#undef SUNOS4_SHARED_LIBRARIES 73#undef OBJECT_FORMAT_COFF 74#undef OBJECT_FORMAT_ROSE 75#undef MD_EXEC_PREFIX 76#undef REAL_LD_FILE_NAME 77#undef REAL_NM_FILE_NAME 78#undef REAL_STRIP_FILE_NAME 79#endif 80 81/* If we cannot use a special method, use the ordinary one: 82 run nm to find what symbols are present. 83 In a cross-compiler, this means you need a cross nm, 84 but that is not quite as unpleasant as special headers. */ 85 86#if !defined (OBJECT_FORMAT_COFF) && !defined (OBJECT_FORMAT_ROSE) 87#define OBJECT_FORMAT_NONE 88#endif 89 90#ifdef OBJECT_FORMAT_COFF 91 92#include <a.out.h> 93#include <ar.h> 94 95#ifdef UMAX 96#include <sgs.h> 97#endif 98 99/* Many versions of ldfcn.h define these. */ 100#ifdef FREAD 101#undef FREAD 102#undef FWRITE 103#endif 104 105#include <ldfcn.h> 106 107/* Some systems have an ISCOFF macro, but others do not. In some cases 108 the macro may be wrong. MY_ISCOFF is defined in tm.h files for machines 109 that either do not have an ISCOFF macro in /usr/include or for those 110 where it is wrong. */ 111 112#ifndef MY_ISCOFF 113#define MY_ISCOFF(X) ISCOFF (X) 114#endif 115 116#endif /* OBJECT_FORMAT_COFF */ 117 118#ifdef OBJECT_FORMAT_ROSE 119 120#ifdef _OSF_SOURCE 121#define USE_MMAP 122#endif 123 124#ifdef USE_MMAP 125#include <sys/mman.h> 126#endif 127 128#include <unistd.h> 129#include <mach_o_format.h> 130#include <mach_o_header.h> 131#include <mach_o_vals.h> 132#include <mach_o_types.h> 133 134#endif /* OBJECT_FORMAT_ROSE */ 135 136#ifdef OBJECT_FORMAT_NONE 137 138/* Default flags to pass to nm. */ 139#ifndef NM_FLAGS 140#define NM_FLAGS "-p" 141#endif 142 143#endif /* OBJECT_FORMAT_NONE */ 144 145/* Some systems use __main in a way incompatible with its use in gcc, in these 146 cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to 147 give the same symbol without quotes for an alternative entry point. You 148 must define both, or neither. */ 149#ifndef NAME__MAIN 150#define NAME__MAIN "__main" 151#define SYMBOL__MAIN __main 152#endif 153 154#if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES 155#define SCAN_LIBRARIES 156#endif 157 158#ifdef USE_COLLECT2 159int do_collecting = 1; 160#else 161int do_collecting = 0; 162#endif 163 164/* Linked lists of constructor and destructor names. */ 165 166struct id 167{ 168 struct id *next; 169 int sequence; 170 char name[1]; 171}; 172 173struct head 174{ 175 struct id *first; 176 struct id *last; 177 int number; 178}; 179 180/* Enumeration giving which pass this is for scanning the program file. */ 181 182enum pass { 183 PASS_FIRST, /* without constructors */ 184 PASS_OBJ, /* individual objects */ 185 PASS_LIB, /* looking for shared libraries */ 186 PASS_SECOND /* with constructors linked in */ 187}; 188 189#ifndef NO_SYS_SIGLIST 190#ifndef SYS_SIGLIST_DECLARED 191extern char *sys_siglist[]; 192#endif 193#endif 194extern char *version_string; 195 196int vflag; /* true if -v */ 197static int rflag; /* true if -r */ 198static int strip_flag; /* true if -s */ 199#ifdef COLLECT_EXPORT_LIST 200static int export_flag; /* true if -bE */ 201static int aix64_flag; /* true if -b64 */ 202#endif 203 204int debug; /* true if -debug */ 205 206static int shared_obj; /* true if -shared */ 207 208static char *c_file; /* <xxx>.c for constructor/destructor list. */ 209static char *o_file; /* <xxx>.o for constructor/destructor list. */ 210#ifdef COLLECT_EXPORT_LIST 211static char *export_file; /* <xxx>.x for AIX export list. */ 212static char *import_file; /* <xxx>.p for AIX import list. */ 213#endif 214char *ldout; /* File for ld errors. */ 215static char *output_file; /* Output file for ld. */ 216static char *nm_file_name; /* pathname of nm */ 217#ifdef LDD_SUFFIX 218static char *ldd_file_name; /* pathname of ldd (or equivalent) */ 219#endif 220static char *strip_file_name; /* pathname of strip */ 221char *c_file_name; /* pathname of gcc */ 222static char *initname, *fininame; /* names of init and fini funcs */ 223 224static struct head constructors; /* list of constructors found */ 225static struct head destructors; /* list of destructors found */ 226#ifdef COLLECT_EXPORT_LIST 227static struct head exports; /* list of exported symbols */ 228static struct head imports; /* list of imported symbols */ 229static struct head undefined; /* list of undefined symbols */ 230#endif 231static struct head frame_tables; /* list of frame unwind info tables */ 232 233struct obstack temporary_obstack; 234struct obstack permanent_obstack; 235char * temporary_firstobj; 236 237/* Defined in the automatically-generated underscore.c. */ 238extern int prepends_underscore; 239 240extern char *mktemp (); 241extern FILE *fdopen (); 242 243#ifndef GET_ENVIRONMENT 244#define GET_ENVIRONMENT(ENV_VALUE,ENV_NAME) ENV_VALUE = getenv (ENV_NAME) 245#endif 246 247/* Structure to hold all the directories in which to search for files to 248 execute. */ 249 250struct prefix_list 251{ 252 char *prefix; /* String to prepend to the path. */ 253 struct prefix_list *next; /* Next in linked list. */ 254}; 255 256struct path_prefix 257{ 258 struct prefix_list *plist; /* List of prefixes to try */ 259 int max_len; /* Max length of a prefix in PLIST */ 260 char *name; /* Name of this list (used in config stuff) */ 261}; 262 263#ifdef COLLECT_EXPORT_LIST 264/* Lists to keep libraries to be scanned for global constructors/destructors. */ 265static struct head libs; /* list of libraries */ 266static struct path_prefix cmdline_lib_dirs; /* directories specified with -L */ 267static struct path_prefix libpath_lib_dirs; /* directories in LIBPATH */ 268static struct path_prefix *libpaths[3] = {&cmdline_lib_dirs, 269 &libpath_lib_dirs, NULL}; 270static char *libexts[3] = {"a", "so", NULL}; /* possible library extentions */ 271#endif 272 273static char *my_strerror PROTO((int)); 274static void handler PROTO((int)); 275static int is_ctor_dtor PROTO((char *)); 276static char *find_a_file PROTO((struct path_prefix *, char *)); 277static void add_prefix PROTO((struct path_prefix *, char *)); 278static void prefix_from_env PROTO((char *, struct path_prefix *)); 279static void prefix_from_string PROTO((char *, struct path_prefix *)); 280static void do_wait PROTO((char *)); 281static void fork_execute PROTO((char *, char **)); 282static void maybe_unlink PROTO((char *)); 283static void add_to_list PROTO((struct head *, char *)); 284static void write_list PROTO((FILE *, char *, struct id *)); 285#ifdef COLLECT_EXPORT_LIST 286static void dump_list PROTO((FILE *, char *, struct id *)); 287#endif 288#if 0 289static void dump_prefix_list PROTO((FILE *, char *, struct prefix_list *)); 290#endif 291static void write_list_with_asm PROTO((FILE *, char *, struct id *)); 292static void write_c_file PROTO((FILE *, char *)); 293static void scan_prog_file PROTO((char *, enum pass)); 294#ifdef SCAN_LIBRARIES 295static void scan_libraries PROTO((char *)); 296#endif 297#ifdef COLLECT_EXPORT_LIST 298static int is_in_list PROTO((char *, struct id *)); 299static void write_export_file PROTO((FILE *)); 300static void write_import_file PROTO((FILE *)); 301static char *resolve_lib_name PROTO((char *)); 302static int use_import_list PROTO((char *)); 303static int ignore_library PROTO((char *)); 304#endif 305 306char *xcalloc (); 307char *xmalloc (); 308 309 310#ifdef NO_DUP2 311int 312dup2 (oldfd, newfd) 313 int oldfd; 314 int newfd; 315{ 316 int fdtmp[256]; 317 int fdx = 0; 318 int fd; 319 320 if (oldfd == newfd) 321 return oldfd; 322 close (newfd); 323 while ((fd = dup (oldfd)) != newfd && fd >= 0) /* good enough for low fd's */ 324 fdtmp[fdx++] = fd; 325 while (fdx > 0) 326 close (fdtmp[--fdx]); 327 328 return fd; 329} 330#endif 331 332static char * 333my_strerror (e) 334 int e; 335{ 336 337#ifdef HAVE_STRERROR 338 return strerror (e); 339 340#else 341 342 static char buffer[30]; 343 if (!e) 344 return ""; 345 346 if (e > 0 && e < sys_nerr) 347 return sys_errlist[e]; 348 349 sprintf (buffer, "Unknown error %d", e); 350 return buffer; 351#endif 352} 353 354/* Delete tempfiles and exit function. */ 355 356void 357collect_exit (status) 358 int status; 359{ 360 if (c_file != 0 && c_file[0]) 361 maybe_unlink (c_file); 362 363 if (o_file != 0 && o_file[0]) 364 maybe_unlink (o_file); 365 366#ifdef COLLECT_EXPORT_LIST 367 if (export_file != 0 && export_file[0]) 368 maybe_unlink (export_file); 369 370 if (import_file != 0 && import_file[0]) 371 maybe_unlink (import_file); 372#endif 373 374 if (ldout != 0 && ldout[0]) 375 { 376 dump_file (ldout); 377 maybe_unlink (ldout); 378 } 379 380 if (status != 0 && output_file != 0 && output_file[0]) 381 maybe_unlink (output_file); 382 383 exit (status); 384} 385 386 387/* Die when sys call fails. */ 388 389void 390fatal_perror (string, arg1, arg2, arg3) 391 char *string, *arg1, *arg2, *arg3; 392{ 393 int e = errno; 394 395 fprintf (stderr, "collect2: "); 396 fprintf (stderr, string, arg1, arg2, arg3); 397 fprintf (stderr, ": %s\n", my_strerror (e)); 398 collect_exit (FATAL_EXIT_CODE); 399} 400 401/* Just die. */ 402 403void 404fatal (string, arg1, arg2, arg3) 405 char *string, *arg1, *arg2, *arg3; 406{ 407 fprintf (stderr, "collect2: "); 408 fprintf (stderr, string, arg1, arg2, arg3); 409 fprintf (stderr, "\n"); 410 collect_exit (FATAL_EXIT_CODE); 411} 412 413/* Write error message. */ 414 415void 416error (string, arg1, arg2, arg3, arg4) 417 char *string, *arg1, *arg2, *arg3, *arg4; 418{ 419 fprintf (stderr, "collect2: "); 420 fprintf (stderr, string, arg1, arg2, arg3, arg4); 421 fprintf (stderr, "\n"); 422} 423 424/* In case obstack is linked in, and abort is defined to fancy_abort, 425 provide a default entry. */ 426 427void 428fancy_abort () 429{ 430 fatal ("internal error"); 431} 432 433 434static void 435handler (signo) 436 int signo; 437{ 438 if (c_file != 0 && c_file[0]) 439 maybe_unlink (c_file); 440 441 if (o_file != 0 && o_file[0]) 442 maybe_unlink (o_file); 443 444 if (ldout != 0 && ldout[0]) 445 maybe_unlink (ldout); 446 447#ifdef COLLECT_EXPORT_LIST 448 if (export_file != 0 && export_file[0]) 449 maybe_unlink (export_file); 450 451 if (import_file != 0 && import_file[0]) 452 maybe_unlink (import_file); 453#endif 454 455 signal (signo, SIG_DFL); 456 kill (getpid (), signo); 457} 458 459 460char * 461xcalloc (size1, size2) 462 int size1, size2; 463{ 464 char *ptr = (char *) calloc (size1, size2); 465 if (ptr) 466 return ptr; 467 468 fatal ("out of memory"); 469 return (char *) 0; 470} 471 472char * 473xmalloc (size) 474 unsigned size; 475{ 476 char *ptr = (char *) malloc (size); 477 if (ptr) 478 return ptr; 479 480 fatal ("out of memory"); 481 return (char *) 0; 482} 483 484char * 485xrealloc (ptr, size) 486 char *ptr; 487 unsigned size; 488{ 489 register char *value = (char *) realloc (ptr, size); 490 if (value == 0) 491 fatal ("virtual memory exhausted"); 492 return value; 493} 494 495int 496file_exists (name) 497 char *name; 498{ 499 return access (name, R_OK) == 0; 500} 501 502/* Make a copy of a string INPUT with size SIZE. */ 503 504char * 505savestring (input, size) 506 char *input; 507 int size; 508{ 509 char *output = (char *) xmalloc (size + 1); 510 bcopy (input, output, size); 511 output[size] = 0; 512 return output; 513} 514 515/* Parse a reasonable subset of shell quoting syntax. */ 516 517static char * 518extract_string (pp) 519 char **pp; 520{ 521 char *p = *pp; 522 int backquote = 0; 523 int inside = 0; 524 525 for (;;) 526 { 527 char c = *p; 528 if (c == '\0') 529 break; 530 ++p; 531 if (backquote) 532 obstack_1grow (&temporary_obstack, c); 533 else if (! inside && c == ' ') 534 break; 535 else if (! inside && c == '\\') 536 backquote = 1; 537 else if (c == '\'') 538 inside = !inside; 539 else 540 obstack_1grow (&temporary_obstack, c); 541 } 542 543 obstack_1grow (&temporary_obstack, '\0'); 544 *pp = p; 545 return obstack_finish (&temporary_obstack); 546} 547 548void 549dump_file (name) 550 char *name; 551{ 552 FILE *stream = fopen (name, "r"); 553 int no_demangle = !! getenv ("COLLECT_NO_DEMANGLE"); 554 555 if (stream == 0) 556 return; 557 while (1) 558 { 559 int c; 560 while (c = getc (stream), 561 c != EOF && (ISALNUM (c) || c == '_' || c == '$' || c == '.')) 562 obstack_1grow (&temporary_obstack, c); 563 if (obstack_object_size (&temporary_obstack) > 0) 564 { 565 char *word, *p, *result; 566 obstack_1grow (&temporary_obstack, '\0'); 567 word = obstack_finish (&temporary_obstack); 568 569 if (*word == '.') 570 ++word, putc ('.', stderr); 571 p = word; 572 if (*p == '_' && prepends_underscore) 573 ++p; 574 575 if (no_demangle) 576 result = 0; 577 else 578 result = cplus_demangle (p, DMGL_PARAMS | DMGL_ANSI); 579 580 if (result) 581 { 582 int diff; 583 fputs (result, stderr); 584 585 diff = strlen (word) - strlen (result); 586 while (diff > 0) 587 --diff, putc (' ', stderr); 588 while (diff < 0 && c == ' ') 589 ++diff, c = getc (stream); 590 591 free (result); 592 } 593 else 594 fputs (word, stderr); 595 596 fflush (stderr); 597 obstack_free (&temporary_obstack, temporary_firstobj); 598 } 599 if (c == EOF) 600 break; 601 putc (c, stderr); 602 } 603 fclose (stream); 604} 605 606/* Decide whether the given symbol is: 607 a constructor (1), a destructor (2), or neither (0). */ 608 609static int 610is_ctor_dtor (s) 611 char *s; 612{ 613 struct names { char *name; int len; int ret; int two_underscores; }; 614 615 register struct names *p; 616 register int ch; 617 register char *orig_s = s; 618 619 static struct names special[] = { 620#ifdef NO_DOLLAR_IN_LABEL 621#ifdef NO_DOT_IN_LABEL 622 { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, 1, 0 }, 623 { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, 2, 0 }, 624 { "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, 5, 0 }, 625#else 626 { "GLOBAL_.I.", sizeof ("GLOBAL_.I.")-1, 1, 0 }, 627 { "GLOBAL_.D.", sizeof ("GLOBAL_.D.")-1, 2, 0 }, 628 { "GLOBAL_.F.", sizeof ("GLOBAL_.F.")-1, 5, 0 }, 629#endif 630#else 631 { "GLOBAL_$I$", sizeof ("GLOBAL_$I$")-1, 1, 0 }, 632 { "GLOBAL_$D$", sizeof ("GLOBAL_$D$")-1, 2, 0 }, 633 { "GLOBAL_$F$", sizeof ("GLOBAL_$F$")-1, 5, 0 }, 634#endif 635 { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, 3, 0 }, 636 { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, 4, 0 }, 637#ifdef CFRONT_LOSSAGE /* Do not collect cfront initialization functions. 638 cfront has its own linker procedure to collect them; 639 if collect2 gets them too, they get collected twice 640 when the cfront procedure is run and the compiler used 641 for linking happens to be GCC. */ 642 { "sti__", sizeof ("sti__")-1, 1, 1 }, 643 { "std__", sizeof ("std__")-1, 2, 1 }, 644#endif /* CFRONT_LOSSAGE */ 645 { NULL, 0, 0, 0 } 646 }; 647 648 while ((ch = *s) == '_') 649 ++s; 650 651 if (s == orig_s) 652 return 0; 653 654 for (p = &special[0]; p->len > 0; p++) 655 { 656 if (ch == p->name[0] 657 && (!p->two_underscores || ((s - orig_s) >= 2)) 658 && strncmp(s, p->name, p->len) == 0) 659 { 660 return p->ret; 661 } 662 } 663 return 0; 664} 665 666/* Routine to add variables to the environment. */ 667 668#ifndef HAVE_PUTENV 669 670int 671putenv (str) 672 char *str; 673{ 674#ifndef VMS /* nor about VMS */ 675 676 extern char **environ; 677 char **old_environ = environ; 678 char **envp; 679 int num_envs = 0; 680 int name_len = 1; 681 char *p = str; 682 int ch; 683 684 while ((ch = *p++) != '\0' && ch != '=') 685 name_len++; 686 687 if (!ch) 688 abort (); 689 690 /* Search for replacing an existing environment variable, and 691 count the number of total environment variables. */ 692 for (envp = old_environ; *envp; envp++) 693 { 694 num_envs++; 695 if (!strncmp (str, *envp, name_len)) 696 { 697 *envp = str; 698 return 0; 699 } 700 } 701 702 /* Add a new environment variable */ 703 environ = (char **) xmalloc (sizeof (char *) * (num_envs+2)); 704 *environ = str; 705 bcopy ((char *) old_environ, (char *) (environ + 1), 706 sizeof (char *) * (num_envs+1)); 707 708 return 0; 709#endif /* VMS */ 710} 711 712#endif /* HAVE_PUTENV */ 713 714/* By default, colon separates directories in a path. */ 715#ifndef PATH_SEPARATOR 716#define PATH_SEPARATOR ':' 717#endif 718 719/* We maintain two prefix lists: one from COMPILER_PATH environment variable 720 and one from the PATH variable. */ 721 722static struct path_prefix cpath, path; 723 724#ifdef CROSS_COMPILE 725/* This is the name of the target machine. We use it to form the name 726 of the files to execute. */ 727 728static char *target_machine = TARGET_MACHINE; 729#endif 730 731/* Search for NAME using prefix list PPREFIX. We only look for executable 732 files. 733 734 Return 0 if not found, otherwise return its name, allocated with malloc. */ 735 736static char * 737find_a_file (pprefix, name) 738 struct path_prefix *pprefix; 739 char *name; 740{ 741 char *temp; 742 struct prefix_list *pl; 743 int len = pprefix->max_len + strlen (name) + 1; 744 745 if (debug) 746 fprintf (stderr, "Looking for '%s'\n", name); 747 748#ifdef EXECUTABLE_SUFFIX 749 len += strlen (EXECUTABLE_SUFFIX); 750#endif 751 752 temp = xmalloc (len); 753 754 /* Determine the filename to execute (special case for absolute paths). */ 755 756 if (*name == '/' 757#ifdef DIR_SEPARATOR 758 || (DIR_SEPARATOR == '\\' && name[1] == ':' 759 && (name[2] == DIR_SEPARATOR || name[2] == '/')) 760#endif 761 ) 762 { 763 if (access (name, X_OK) == 0) 764 { 765 strcpy (temp, name); 766 767 if (debug) 768 fprintf (stderr, " - found: absolute path\n"); 769 770 return temp; 771 } 772 773 if (debug) 774 fprintf (stderr, " - failed to locate using absolute path\n"); 775 } 776 else 777 for (pl = pprefix->plist; pl; pl = pl->next) 778 { 779 strcpy (temp, pl->prefix); 780 strcat (temp, name); 781 782 if (access (temp, X_OK) == 0) 783 return temp; 784 785#ifdef EXECUTABLE_SUFFIX 786 /* Some systems have a suffix for executable files. 787 So try appending that. */ 788 strcat (temp, EXECUTABLE_SUFFIX); 789 790 if (access (temp, X_OK) == 0) 791 return temp; 792#endif 793 } 794 795 if (debug && pprefix->plist == NULL) 796 fprintf (stderr, " - failed: no entries in prefix list\n"); 797 798 free (temp); 799 return 0; 800} 801 802/* Add an entry for PREFIX to prefix list PPREFIX. */ 803 804static void 805add_prefix (pprefix, prefix) 806 struct path_prefix *pprefix; 807 char *prefix; 808{ 809 struct prefix_list *pl, **prev; 810 int len; 811 812 if (pprefix->plist) 813 { 814 for (pl = pprefix->plist; pl->next; pl = pl->next) 815 ; 816 prev = &pl->next; 817 } 818 else 819 prev = &pprefix->plist; 820 821 /* Keep track of the longest prefix */ 822 823 len = strlen (prefix); 824 if (len > pprefix->max_len) 825 pprefix->max_len = len; 826 827 pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list)); 828 pl->prefix = savestring (prefix, len); 829 830 if (*prev) 831 pl->next = *prev; 832 else 833 pl->next = (struct prefix_list *) 0; 834 *prev = pl; 835} 836 837/* Take the value of the environment variable ENV, break it into a path, and 838 add of the entries to PPREFIX. */ 839 840static void 841prefix_from_env (env, pprefix) 842 char *env; 843 struct path_prefix *pprefix; 844{ 845 char *p; 846 GET_ENVIRONMENT (p, env); 847 848 if (p) 849 prefix_from_string (p, pprefix); 850} 851 852static void 853prefix_from_string (p, pprefix) 854 char *p; 855 struct path_prefix *pprefix; 856{ 857 char *startp, *endp; 858 char *nstore = (char *) xmalloc (strlen (p) + 3); 859 860 if (debug) 861 fprintf (stderr, "Convert string '%s' into prefixes, separator = '%c'\n", p, PATH_SEPARATOR); 862 863 startp = endp = p; 864 while (1) 865 { 866 if (*endp == PATH_SEPARATOR || *endp == 0) 867 { 868 strncpy (nstore, startp, endp-startp); 869 if (endp == startp) 870 { 871 strcpy (nstore, "./"); 872 } 873 else if (endp[-1] != '/') 874 { 875 nstore[endp-startp] = '/'; 876 nstore[endp-startp+1] = 0; 877 } 878 else 879 nstore[endp-startp] = 0; 880 881 if (debug) 882 fprintf (stderr, " - add prefix: %s\n", nstore); 883 884 add_prefix (pprefix, nstore); 885 if (*endp == 0) 886 break; 887 endp = startp = endp + 1; 888 } 889 else 890 endp++; 891 } 892} 893 894/* Main program. */ 895 896int 897main (argc, argv) 898 int argc; 899 char *argv[]; 900{ 901 char *ld_suffix = "ld"; 902 char *full_ld_suffix = ld_suffix; 903 char *real_ld_suffix = "real-ld"; 904 char *collect_ld_suffix = "collect-ld"; 905 char *nm_suffix = "nm"; 906 char *full_nm_suffix = nm_suffix; 907 char *gnm_suffix = "gnm"; 908 char *full_gnm_suffix = gnm_suffix; 909#ifdef LDD_SUFFIX 910 char *ldd_suffix = LDD_SUFFIX; 911 char *full_ldd_suffix = ldd_suffix; 912#endif 913 char *strip_suffix = "strip"; 914 char *full_strip_suffix = strip_suffix; 915 char *gstrip_suffix = "gstrip"; 916 char *full_gstrip_suffix = gstrip_suffix; 917 char *arg; 918 FILE *outf; 919#ifdef COLLECT_EXPORT_LIST 920 FILE *exportf; 921 FILE *importf; 922#endif 923 char *ld_file_name; 924 char *p; 925 char **c_argv; 926 char **c_ptr; 927 char **ld1_argv = (char **) xcalloc (sizeof (char *), argc+3); 928 char **ld1 = ld1_argv; 929 char **ld2_argv = (char **) xcalloc (sizeof (char *), argc+6); 930 char **ld2 = ld2_argv; 931 char **object_lst = (char **) xcalloc (sizeof (char *), argc); 932 char **object = object_lst; 933 int first_file; 934 int num_c_args = argc+9; 935 936#ifdef DEBUG 937 debug = 1; 938#endif 939 940 /* Parse command line early for instances of -debug. This allows 941 the debug flag to be set before functions like find_a_file() 942 are called. */ 943 { 944 int i; 945 946 for (i = 1; argv[i] != NULL; i ++) 947 if (! strcmp (argv[i], "-debug")) 948 debug = 1; 949 vflag = debug; 950 } 951 952#ifndef DEFAULT_A_OUT_NAME 953 output_file = "a.out"; 954#else 955 output_file = DEFAULT_A_OUT_NAME; 956#endif 957 958 obstack_begin (&temporary_obstack, 0); 959 obstack_begin (&permanent_obstack, 0); 960 temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0); 961 962 current_demangling_style = gnu_demangling; 963 p = getenv ("COLLECT_GCC_OPTIONS"); 964 while (p && *p) 965 { 966 char *q = extract_string (&p); 967 if (*q == '-' && (q[1] == 'm' || q[1] == 'f')) 968 num_c_args++; 969 } 970 obstack_free (&temporary_obstack, temporary_firstobj); 971 ++num_c_args; 972 973 c_ptr = c_argv = (char **) xcalloc (sizeof (char *), num_c_args); 974 975 if (argc < 2) 976 fatal ("no arguments"); 977 978#ifdef SIGQUIT 979 if (signal (SIGQUIT, SIG_IGN) != SIG_IGN) 980 signal (SIGQUIT, handler); 981#endif 982 if (signal (SIGINT, SIG_IGN) != SIG_IGN) 983 signal (SIGINT, handler); 984#ifdef SIGALRM 985 if (signal (SIGALRM, SIG_IGN) != SIG_IGN) 986 signal (SIGALRM, handler); 987#endif 988#ifdef SIGHUP 989 if (signal (SIGHUP, SIG_IGN) != SIG_IGN) 990 signal (SIGHUP, handler); 991#endif 992 if (signal (SIGSEGV, SIG_IGN) != SIG_IGN) 993 signal (SIGSEGV, handler); 994#ifdef SIGBUS 995 if (signal (SIGBUS, SIG_IGN) != SIG_IGN) 996 signal (SIGBUS, handler); 997#endif 998 999 /* Extract COMPILER_PATH and PATH into our prefix list. */ 1000 prefix_from_env ("COMPILER_PATH", &cpath); 1001 prefix_from_env ("PATH", &path); 1002 1003#ifdef CROSS_COMPILE 1004 /* If we look for a program in the compiler directories, we just use 1005 the short name, since these directories are already system-specific. 1006 But it we look for a program in the system directories, we need to 1007 qualify the program name with the target machine. */ 1008 1009 full_ld_suffix 1010 = xcalloc (strlen (ld_suffix) + strlen (target_machine) + 2, 1); 1011 strcpy (full_ld_suffix, target_machine); 1012 strcat (full_ld_suffix, "-"); 1013 strcat (full_ld_suffix, ld_suffix); 1014 1015#if 0 1016 full_gld_suffix 1017 = xcalloc (strlen (gld_suffix) + strlen (target_machine) + 2, 1); 1018 strcpy (full_gld_suffix, target_machine); 1019 strcat (full_gld_suffix, "-"); 1020 strcat (full_gld_suffix, gld_suffix); 1021#endif 1022 1023 full_nm_suffix 1024 = xcalloc (strlen (nm_suffix) + strlen (target_machine) + 2, 1); 1025 strcpy (full_nm_suffix, target_machine); 1026 strcat (full_nm_suffix, "-"); 1027 strcat (full_nm_suffix, nm_suffix); 1028 1029 full_gnm_suffix 1030 = xcalloc (strlen (gnm_suffix) + strlen (target_machine) + 2, 1); 1031 strcpy (full_gnm_suffix, target_machine); 1032 strcat (full_gnm_suffix, "-"); 1033 strcat (full_gnm_suffix, gnm_suffix); 1034 1035#ifdef LDD_SUFFIX 1036 full_ldd_suffix 1037 = xcalloc (strlen (ldd_suffix) + strlen (target_machine) + 2, 1); 1038 strcpy (full_ldd_suffix, target_machine); 1039 strcat (full_ldd_suffix, "-"); 1040 strcat (full_ldd_suffix, ldd_suffix); 1041#endif 1042 1043 full_strip_suffix 1044 = xcalloc (strlen (strip_suffix) + strlen (target_machine) + 2, 1); 1045 strcpy (full_strip_suffix, target_machine); 1046 strcat (full_strip_suffix, "-"); 1047 strcat (full_strip_suffix, strip_suffix); 1048 1049 full_gstrip_suffix 1050 = xcalloc (strlen (gstrip_suffix) + strlen (target_machine) + 2, 1); 1051 strcpy (full_gstrip_suffix, target_machine); 1052 strcat (full_gstrip_suffix, "-"); 1053 strcat (full_gstrip_suffix, gstrip_suffix); 1054#endif /* CROSS_COMPILE */ 1055 1056 /* Try to discover a valid linker/nm/strip to use. */ 1057 1058 /* Maybe we know the right file to use (if not cross). */ 1059#ifdef REAL_LD_FILE_NAME 1060 ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME); 1061 if (ld_file_name == 0) 1062#endif 1063 /* Search the (target-specific) compiler dirs for ld'. */ 1064 ld_file_name = find_a_file (&cpath, real_ld_suffix); 1065 /* Likewise for `collect-ld'. */ 1066 if (ld_file_name == 0) 1067 ld_file_name = find_a_file (&cpath, collect_ld_suffix); 1068 /* Search the compiler directories for `ld'. We have protection against 1069 recursive calls in find_a_file. */ 1070 if (ld_file_name == 0) 1071 ld_file_name = find_a_file (&cpath, ld_suffix); 1072 /* Search the ordinary system bin directories 1073 for `ld' (if native linking) or `TARGET-ld' (if cross). */ 1074 if (ld_file_name == 0) 1075 ld_file_name = find_a_file (&path, full_ld_suffix); 1076 1077#ifdef REAL_NM_FILE_NAME 1078 nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME); 1079 if (nm_file_name == 0) 1080#endif 1081 nm_file_name = find_a_file (&cpath, gnm_suffix); 1082 if (nm_file_name == 0) 1083 nm_file_name = find_a_file (&path, full_gnm_suffix); 1084 if (nm_file_name == 0) 1085 nm_file_name = find_a_file (&cpath, nm_suffix); 1086 if (nm_file_name == 0) 1087 nm_file_name = find_a_file (&path, full_nm_suffix); 1088 1089#ifdef LDD_SUFFIX 1090 ldd_file_name = find_a_file (&cpath, ldd_suffix); 1091 if (ldd_file_name == 0) 1092 ldd_file_name = find_a_file (&path, full_ldd_suffix); 1093#endif 1094 1095#ifdef REAL_STRIP_FILE_NAME 1096 strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME); 1097 if (strip_file_name == 0) 1098#endif 1099 strip_file_name = find_a_file (&cpath, gstrip_suffix); 1100 if (strip_file_name == 0) 1101 strip_file_name = find_a_file (&path, full_gstrip_suffix); 1102 if (strip_file_name == 0) 1103 strip_file_name = find_a_file (&cpath, strip_suffix); 1104 if (strip_file_name == 0) 1105 strip_file_name = find_a_file (&path, full_strip_suffix); 1106 1107 /* Determine the full path name of the C compiler to use. */ 1108 c_file_name = getenv ("COLLECT_GCC"); 1109 if (c_file_name == 0) 1110 { 1111#ifdef CROSS_COMPILE 1112 c_file_name = xcalloc (sizeof ("gcc-") + strlen (target_machine) + 1, 1); 1113 strcpy (c_file_name, target_machine); 1114 strcat (c_file_name, "-gcc"); 1115#else 1116 c_file_name = "gcc"; 1117#endif 1118 } 1119 1120 p = find_a_file (&cpath, c_file_name); 1121 1122 /* Here it should be safe to use the system search path since we should have 1123 already qualified the name of the compiler when it is needed. */ 1124 if (p == 0) 1125 p = find_a_file (&path, c_file_name); 1126 1127 if (p) 1128 c_file_name = p; 1129 1130 *ld1++ = *ld2++ = ld_file_name; 1131 1132 /* Make temp file names. */ 1133 c_file = make_temp_file (".c"); 1134 o_file = make_temp_file (".o"); 1135#ifdef COLLECT_EXPORT_LIST 1136 export_file = make_temp_file (".x"); 1137 import_file = make_temp_file (".p"); 1138#endif 1139 ldout = make_temp_file (".ld"); 1140 *c_ptr++ = c_file_name; 1141 *c_ptr++ = "-x"; 1142 *c_ptr++ = "c"; 1143 *c_ptr++ = "-c"; 1144 *c_ptr++ = "-o"; 1145 *c_ptr++ = o_file; 1146 1147#ifdef COLLECT_EXPORT_LIST 1148 /* Generate a list of directories from LIBPATH. */ 1149 prefix_from_env ("LIBPATH", &libpath_lib_dirs); 1150 /* Add to this list also two standard directories where 1151 AIX loader always searches for libraries. */ 1152 add_prefix (&libpath_lib_dirs, "/lib"); 1153 add_prefix (&libpath_lib_dirs, "/usr/lib"); 1154#endif 1155 1156 /* Get any options that the upper GCC wants to pass to the sub-GCC. 1157 1158 AIX support needs to know if -shared has been specified before 1159 parsing commandline arguments. */ 1160 1161 p = getenv ("COLLECT_GCC_OPTIONS"); 1162 while (p && *p) 1163 { 1164 char *q = extract_string (&p); 1165 if (*q == '-' && (q[1] == 'm' || q[1] == 'f')) 1166 *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q)); 1167 if (strncmp (q, "-shared", sizeof ("-shared") - 1) == 0) 1168 shared_obj = 1; 1169 } 1170 obstack_free (&temporary_obstack, temporary_firstobj); 1171 *c_ptr++ = "-fno-exceptions"; 1172 1173 /* !!! When GCC calls collect2, 1174 it does not know whether it is calling collect2 or ld. 1175 So collect2 cannot meaningfully understand any options 1176 except those ld understands. 1177 If you propose to make GCC pass some other option, 1178 just imagine what will happen if ld is really ld!!! */ 1179 1180 /* Parse arguments. Remember output file spec, pass the rest to ld. */ 1181 /* After the first file, put in the c++ rt0. */ 1182 1183 first_file = 1; 1184 while ((arg = *++argv) != (char *) 0) 1185 { 1186 *ld1++ = *ld2++ = arg; 1187 1188 if (arg[0] == '-') 1189 { 1190 switch (arg[1]) 1191 { 1192#ifdef COLLECT_EXPORT_LIST 1193 /* We want to disable automatic exports on AIX when user 1194 explicitly puts an export list in command line */ 1195 case 'b': 1196 if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0) 1197 export_flag = 1; 1198 if (arg[2] == '6' && arg[3] == '4') 1199 aix64_flag = 1; 1200 break; 1201#endif 1202 1203 case 'd': 1204 if (!strcmp (arg, "-debug")) 1205 { 1206 /* Already parsed. */ 1207 ld1--; 1208 ld2--; 1209 } 1210 break; 1211 1212 case 'l': 1213 if (first_file) 1214 { 1215 /* place o_file BEFORE this argument! */ 1216 first_file = 0; 1217 ld2--; 1218 *ld2++ = o_file; 1219 *ld2++ = arg; 1220 } 1221#ifdef COLLECT_EXPORT_LIST 1222 { 1223 /* Resolving full library name. */ 1224 char *s = resolve_lib_name (arg+2); 1225 1226 /* If we will use an import list for this library, 1227 we should exclude it from ld args. */ 1228 if (use_import_list (s)) 1229 { 1230 ld1--; 1231 ld2--; 1232 } 1233 1234 /* Saving a full library name. */ 1235 add_to_list (&libs, s); 1236 } 1237#endif 1238 break; 1239 1240#ifdef COLLECT_EXPORT_LIST 1241 /* Saving directories where to search for libraries. */ 1242 case 'L': 1243 add_prefix (&cmdline_lib_dirs, arg+2); 1244 break; 1245#endif 1246 1247 case 'o': 1248 if (arg[2] == '\0') 1249 output_file = *ld1++ = *ld2++ = *++argv; 1250 else 1251 output_file = &arg[2]; 1252 break; 1253 1254 case 'r': 1255 if (arg[2] == '\0') 1256 rflag = 1; 1257 break; 1258 1259 case 's': 1260 if (arg[2] == '\0' && do_collecting) 1261 { 1262 /* We must strip after the nm run, otherwise C++ linking 1263 will not work. Thus we strip in the second ld run, or 1264 else with strip if there is no second ld run. */ 1265 strip_flag = 1; 1266 ld1--; 1267 } 1268 break; 1269 1270 case 'v': 1271 if (arg[2] == '\0') 1272 vflag = 1; 1273 break; 1274 } 1275 } 1276 else if ((p = rindex (arg, '.')) != (char *) 0 1277 && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0 1278 || strcmp (p, ".so") == 0)) 1279 { 1280 if (first_file) 1281 { 1282 first_file = 0; 1283 if (p[1] == 'o') 1284 *ld2++ = o_file; 1285 else 1286 { 1287 /* place o_file BEFORE this argument! */ 1288 ld2--; 1289 *ld2++ = o_file; 1290 *ld2++ = arg; 1291 } 1292 } 1293 if (p[1] == 'o') 1294 *object++ = arg; 1295#ifdef COLLECT_EXPORT_LIST 1296 /* libraries can be specified directly, i.e. without -l flag. */ 1297 else 1298 { 1299 /* If we will use an import list for this library, 1300 we should exclude it from ld args. */ 1301 if (use_import_list (arg)) 1302 { 1303 ld1--; 1304 ld2--; 1305 } 1306 1307 /* Saving a full library name. */ 1308 add_to_list (&libs, arg); 1309 } 1310#endif 1311 } 1312 } 1313 1314#ifdef COLLECT_EXPORT_LIST 1315 /* This is added only for debugging purposes. */ 1316 if (debug) 1317 { 1318 fprintf (stderr, "List of libraries:\n"); 1319 dump_list (stderr, "\t", libs.first); 1320 } 1321 1322 /* The AIX linker will discard static constructors in object files if 1323 nothing else in the file is referenced, so look at them first. */ 1324 { 1325 char **export_object_lst = object_lst; 1326 while (export_object_lst < object) 1327 scan_prog_file (*export_object_lst++, PASS_OBJ); 1328 } 1329 { 1330 struct id *list = libs.first; 1331 for (; list; list = list->next) 1332 scan_prog_file (list->name, PASS_FIRST); 1333 } 1334 { 1335 char *buf1 = alloca (strlen (export_file) + 5); 1336 char *buf2 = alloca (strlen (import_file) + 5); 1337 sprintf (buf1, "-bE:%s", export_file); 1338 sprintf (buf2, "-bI:%s", import_file); 1339 *ld1++ = buf1; 1340 *ld2++ = buf1; 1341 *ld1++ = buf2; 1342 *ld2++ = buf2; 1343 exportf = fopen (export_file, "w"); 1344 if (exportf == (FILE *) 0) 1345 fatal_perror ("%s", export_file); 1346 write_export_file (exportf); 1347 if (fclose (exportf)) 1348 fatal_perror ("closing %s", export_file); 1349 importf = fopen (import_file, "w"); 1350 if (importf == (FILE *) 0) 1351 fatal_perror ("%s", import_file); 1352 write_import_file (importf); 1353 if (fclose (importf)) 1354 fatal_perror ("closing %s", import_file); 1355 } 1356#endif 1357 1358 *c_ptr++ = c_file; 1359 *object = *c_ptr = *ld1 = (char *) 0; 1360 1361 if (vflag) 1362 { 1363 fprintf (stderr, "collect2 version %s", version_string); 1364#ifdef TARGET_VERSION 1365 TARGET_VERSION; 1366#endif 1367 fprintf (stderr, "\n"); 1368 } 1369 1370 if (debug) 1371 { 1372 char *ptr; 1373 fprintf (stderr, "ld_file_name = %s\n", 1374 (ld_file_name ? ld_file_name : "not found")); 1375 fprintf (stderr, "c_file_name = %s\n", 1376 (c_file_name ? c_file_name : "not found")); 1377 fprintf (stderr, "nm_file_name = %s\n", 1378 (nm_file_name ? nm_file_name : "not found")); 1379#ifdef LDD_SUFFIX 1380 fprintf (stderr, "ldd_file_name = %s\n", 1381 (ldd_file_name ? ldd_file_name : "not found")); 1382#endif 1383 fprintf (stderr, "strip_file_name = %s\n", 1384 (strip_file_name ? strip_file_name : "not found")); 1385 fprintf (stderr, "c_file = %s\n", 1386 (c_file ? c_file : "not found")); 1387 fprintf (stderr, "o_file = %s\n", 1388 (o_file ? o_file : "not found")); 1389 1390 ptr = getenv ("COLLECT_GCC_OPTIONS"); 1391 if (ptr) 1392 fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr); 1393 1394 ptr = getenv ("COLLECT_GCC"); 1395 if (ptr) 1396 fprintf (stderr, "COLLECT_GCC = %s\n", ptr); 1397 1398 ptr = getenv ("COMPILER_PATH"); 1399 if (ptr) 1400 fprintf (stderr, "COMPILER_PATH = %s\n", ptr); 1401 1402 ptr = getenv ("LIBRARY_PATH"); 1403 if (ptr) 1404 fprintf (stderr, "LIBRARY_PATH = %s\n", ptr); 1405 1406 fprintf (stderr, "\n"); 1407 } 1408 1409 /* Load the program, searching all libraries and attempting to provide 1410 undefined symbols from repository information. */ 1411 1412 /* On AIX we do this later. */ 1413#ifndef COLLECT_EXPORT_LIST 1414 do_tlink (ld1_argv, object_lst); 1415#endif 1416 1417 /* If -r or they will be run via some other method, do not build the 1418 constructor or destructor list, just return now. */ 1419 if (rflag 1420#ifndef COLLECT_EXPORT_LIST 1421 || ! do_collecting 1422#endif 1423 ) 1424 { 1425#ifdef COLLECT_EXPORT_LIST 1426 /* But make sure we delete the export file we may have created. */ 1427 if (export_file != 0 && export_file[0]) 1428 maybe_unlink (export_file); 1429 if (import_file != 0 && import_file[0]) 1430 maybe_unlink (import_file); 1431#endif 1432 maybe_unlink (c_file); 1433 maybe_unlink (o_file); 1434 return 0; 1435 } 1436 1437 /* Examine the namelist with nm and search it for static constructors 1438 and destructors to call. 1439 Write the constructor and destructor tables to a .s file and reload. */ 1440 1441 /* On AIX we already done scanning for global constructors/destructors. */ 1442#ifndef COLLECT_EXPORT_LIST 1443 scan_prog_file (output_file, PASS_FIRST); 1444#endif 1445 1446#ifdef SCAN_LIBRARIES 1447 scan_libraries (output_file); 1448#endif 1449 1450 if (debug) 1451 { 1452 fprintf (stderr, "%d constructor(s) found\n", constructors.number); 1453 fprintf (stderr, "%d destructor(s) found\n", destructors.number); 1454 } 1455 1456 if (constructors.number == 0 && destructors.number == 0 1457 && frame_tables.number == 0 1458#if defined (SCAN_LIBRARIES) || defined (COLLECT_EXPORT_LIST) 1459 /* If we will be running these functions ourselves, we want to emit 1460 stubs into the shared library so that we do not have to relink 1461 dependent programs when we add static objects. */ 1462 && ! shared_obj 1463#endif 1464 ) 1465 { 1466#ifdef COLLECT_EXPORT_LIST 1467 /* Doing tlink without additional code generation */ 1468 do_tlink (ld1_argv, object_lst); 1469#endif 1470 /* Strip now if it was requested on the command line. */ 1471 if (strip_flag) 1472 { 1473 char **strip_argv = (char **) xcalloc (sizeof (char *), 3); 1474 strip_argv[0] = strip_file_name; 1475 strip_argv[1] = output_file; 1476 strip_argv[2] = (char *) 0; 1477 fork_execute ("strip", strip_argv); 1478 } 1479 1480#ifdef COLLECT_EXPORT_LIST 1481 maybe_unlink (export_file); 1482 maybe_unlink (import_file); 1483#endif 1484 maybe_unlink (c_file); 1485 maybe_unlink (o_file); 1486 return 0; 1487 } 1488 1489 maybe_unlink(output_file); 1490 outf = fopen (c_file, "w"); 1491 if (outf == (FILE *) 0) 1492 fatal_perror ("%s", c_file); 1493 1494 write_c_file (outf, c_file); 1495 1496 if (fclose (outf)) 1497 fatal_perror ("closing %s", c_file); 1498 1499 /* Tell the linker that we have initializer and finalizer functions. */ 1500#ifdef LD_INIT_SWITCH 1501 *ld2++ = LD_INIT_SWITCH; 1502 *ld2++ = initname; 1503 *ld2++ = LD_FINI_SWITCH; 1504 *ld2++ = fininame; 1505#endif 1506 *ld2 = (char*) 0; 1507 1508#ifdef COLLECT_EXPORT_LIST 1509 if (shared_obj) 1510 { 1511 add_to_list (&exports, initname); 1512 add_to_list (&exports, fininame); 1513 add_to_list (&exports, "_GLOBAL__DI"); 1514 add_to_list (&exports, "_GLOBAL__DD"); 1515 exportf = fopen (export_file, "w"); 1516 if (exportf == (FILE *) 0) 1517 fatal_perror ("%s", export_file); 1518 write_export_file (exportf); 1519 if (fclose (exportf)) 1520 fatal_perror ("closing %s", export_file); 1521 } 1522#endif 1523 1524 if (debug) 1525 { 1526 fprintf (stderr, "\n========== output_file = %s, c_file = %s\n", 1527 output_file, c_file); 1528 write_c_file (stderr, "stderr"); 1529 fprintf (stderr, "========== end of c_file\n\n"); 1530#ifdef COLLECT_EXPORT_LIST 1531 fprintf (stderr, "\n========== export_file = %s\n", export_file); 1532 write_export_file (stderr); 1533 fprintf (stderr, "========== end of export_file\n\n"); 1534#endif 1535 } 1536 1537 /* Assemble the constructor and destructor tables. 1538 Link the tables in with the rest of the program. */ 1539 1540 fork_execute ("gcc", c_argv); 1541#ifdef COLLECT_EXPORT_LIST 1542 /* On AIX we must call tlink because of possible templates resolution */ 1543 do_tlink (ld2_argv, object_lst); 1544#else 1545 /* Otherwise, simply call ld because tlink is already done */ 1546 fork_execute ("ld", ld2_argv); 1547 1548 /* Let scan_prog_file do any final mods (OSF/rose needs this for 1549 constructors/destructors in shared libraries. */ 1550 scan_prog_file (output_file, PASS_SECOND); 1551#endif 1552 1553 maybe_unlink (c_file); 1554 maybe_unlink (o_file); 1555 1556#ifdef COLLECT_EXPORT_LIST 1557 maybe_unlink (export_file); 1558 maybe_unlink (import_file); 1559#endif 1560 1561 return 0; 1562} 1563 1564 1565/* Wait for a process to finish, and exit if a non-zero status is found. */ 1566 1567int 1568collect_wait (prog) 1569 char *prog; 1570{ 1571 int status; 1572 1573 wait (&status); 1574 if (status) 1575 { 1576 if (WIFSIGNALED (status)) 1577 { 1578 int sig = WTERMSIG (status); 1579#ifdef NO_SYS_SIGLIST 1580 error ("%s terminated with signal %d %s", 1581 prog, 1582 sig, 1583 (status & 0200) ? ", core dumped" : ""); 1584#else 1585 error ("%s terminated with signal %d [%s]%s", 1586 prog, 1587 sig, 1588 sys_siglist[sig], 1589 (status & 0200) ? ", core dumped" : ""); 1590#endif 1591 1592 collect_exit (FATAL_EXIT_CODE); 1593 } 1594 1595 if (WIFEXITED (status)) 1596 return WEXITSTATUS (status); 1597 } 1598 return 0; 1599} 1600 1601static void 1602do_wait (prog) 1603 char *prog; 1604{ 1605 int ret = collect_wait (prog); 1606 if (ret != 0) 1607 { 1608 error ("%s returned %d exit status", prog, ret); 1609 collect_exit (ret); 1610 } 1611} 1612 1613 1614/* Fork and execute a program, and wait for the reply. */ 1615 1616void 1617collect_execute (prog, argv, redir) 1618 char *prog; 1619 char **argv; 1620 char *redir; 1621{ 1622 int pid; 1623 1624 if (vflag || debug) 1625 { 1626 char **p_argv; 1627 char *str; 1628 1629 if (argv[0]) 1630 fprintf (stderr, "%s", argv[0]); 1631 else 1632 fprintf (stderr, "[cannot find %s]", prog); 1633 1634 for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++) 1635 fprintf (stderr, " %s", str); 1636 1637 fprintf (stderr, "\n"); 1638 } 1639 1640 fflush (stdout); 1641 fflush (stderr); 1642 1643 /* If we cannot find a program we need, complain error. Do this here 1644 since we might not end up needing something that we could not find. */ 1645 1646 if (argv[0] == 0) 1647 fatal ("cannot find `%s'", prog); 1648 1649#ifndef __CYGWIN32__ 1650 pid = vfork (); 1651 if (pid == -1) 1652 { 1653#ifdef vfork 1654 fatal_perror ("fork"); 1655#else 1656 fatal_perror ("vfork"); 1657#endif 1658 } 1659 1660 if (pid == 0) /* child context */ 1661 { 1662 if (redir) 1663 { 1664 unlink (redir); 1665 if (freopen (redir, "a", stdout) == NULL) 1666 fatal_perror ("redirecting stdout: %s", redir); 1667 if (freopen (redir, "a", stderr) == NULL) 1668 fatal_perror ("redirecting stderr: %s", redir); 1669 } 1670 1671 execvp (argv[0], argv); 1672 fatal_perror ("executing %s", prog); 1673 } 1674#else 1675 pid = _spawnvp (_P_NOWAIT, argv[0], argv); 1676 if (pid == -1) 1677 fatal ("spawnvp failed"); 1678#endif 1679} 1680 1681static void 1682fork_execute (prog, argv) 1683 char *prog; 1684 char **argv; 1685{ 1686 collect_execute (prog, argv, NULL); 1687 do_wait (prog); 1688} 1689 1690/* Unlink a file unless we are debugging. */ 1691 1692static void 1693maybe_unlink (file) 1694 char *file; 1695{ 1696 if (!debug) 1697 unlink (file); 1698 else 1699 fprintf (stderr, "[Leaving %s]\n", file); 1700} 1701 1702 1703/* Add a name to a linked list. */ 1704 1705static void 1706add_to_list (head_ptr, name) 1707 struct head *head_ptr; 1708 char *name; 1709{ 1710 struct id *newid 1711 = (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1); 1712 struct id *p; 1713 static long sequence_number = 0; 1714 strcpy (newid->name, name); 1715 1716 if (head_ptr->first) 1717 head_ptr->last->next = newid; 1718 else 1719 head_ptr->first = newid; 1720 1721 /* Check for duplicate symbols. */ 1722 for (p = head_ptr->first; 1723 strcmp (name, p->name) != 0; 1724 p = p->next) 1725 ; 1726 if (p != newid) 1727 { 1728 head_ptr->last->next = 0; 1729 free (newid); 1730 return; 1731 } 1732 1733 newid->sequence = ++sequence_number; 1734 head_ptr->last = newid; 1735 head_ptr->number++; 1736} 1737 1738/* Write: `prefix', the names on list LIST, `suffix'. */ 1739 1740static void 1741write_list (stream, prefix, list) 1742 FILE *stream; 1743 char *prefix; 1744 struct id *list; 1745{ 1746 while (list) 1747 { 1748 fprintf (stream, "%sx%d,\n", prefix, list->sequence); 1749 list = list->next; 1750 } 1751} 1752 1753#ifdef COLLECT_EXPORT_LIST 1754/* This function is really used only on AIX, but may be useful. */ 1755static int 1756is_in_list (prefix, list) 1757 char *prefix; 1758 struct id *list; 1759{ 1760 while (list) 1761 { 1762 if (!strcmp (prefix, list->name)) return 1; 1763 list = list->next; 1764 } 1765 return 0; 1766} 1767#endif 1768 1769/* Added for debugging purpose. */ 1770#ifdef COLLECT_EXPORT_LIST 1771static void 1772dump_list (stream, prefix, list) 1773 FILE *stream; 1774 char *prefix; 1775 struct id *list; 1776{ 1777 while (list) 1778 { 1779 fprintf (stream, "%s%s,\n", prefix, list->name); 1780 list = list->next; 1781 } 1782} 1783#endif 1784 1785#if 0 1786static void 1787dump_prefix_list (stream, prefix, list) 1788 FILE *stream; 1789 char *prefix; 1790 struct prefix_list *list; 1791{ 1792 while (list) 1793 { 1794 fprintf (stream, "%s%s,\n", prefix, list->prefix); 1795 list = list->next; 1796 } 1797} 1798#endif 1799 1800static void 1801write_list_with_asm (stream, prefix, list) 1802 FILE *stream; 1803 char *prefix; 1804 struct id *list; 1805{ 1806 while (list) 1807 { 1808 fprintf (stream, "%sx%d __asm__ (\"%s\");\n", 1809 prefix, list->sequence, list->name); 1810 list = list->next; 1811 } 1812} 1813 1814/* Write out the constructor and destructor tables statically (for a shared 1815 object), along with the functions to execute them. */ 1816 1817static void 1818write_c_file_stat (stream, name) 1819 FILE *stream; 1820 char *name; 1821{ 1822 char *prefix, *p, *q; 1823 int frames = (frame_tables.number > 0); 1824 1825 /* Figure out name of output_file, stripping off .so version. */ 1826 p = rindex (output_file, '/'); 1827 if (p == 0) 1828 p = (char *) output_file; 1829 else 1830 p++; 1831 q = p; 1832 while (q) 1833 { 1834 q = index (q,'.'); 1835 if (q == 0) 1836 { 1837 q = p + strlen (p); 1838 break; 1839 } 1840 else 1841 { 1842 if (strncmp (q, ".so", 3) == 0) 1843 { 1844 q += 3; 1845 break; 1846 } 1847 else 1848 q++; 1849 } 1850 } 1851 /* q points to null at end of the string (or . of the .so version) */ 1852 prefix = xmalloc (q - p + 1); 1853 strncpy (prefix, p, q - p); 1854 prefix[q - p] = 0; 1855 for (q = prefix; *q; q++) 1856 if (!ISALNUM (*q)) 1857 *q = '_'; 1858 if (debug) 1859 fprintf (stderr, "\nwrite_c_file - output name is %s, prefix is %s\n", 1860 output_file, prefix); 1861 1862#define INIT_NAME_FORMAT "_GLOBAL__FI_%s" 1863 initname = xmalloc (strlen (prefix) + sizeof (INIT_NAME_FORMAT) - 2); 1864 sprintf (initname, INIT_NAME_FORMAT, prefix); 1865 1866#define FINI_NAME_FORMAT "_GLOBAL__FD_%s" 1867 fininame = xmalloc (strlen (prefix) + sizeof (FINI_NAME_FORMAT) - 2); 1868 sprintf (fininame, FINI_NAME_FORMAT, prefix); 1869 1870 free (prefix); 1871 1872 /* Write the tables as C code */ 1873 1874 fprintf (stream, "static int count;\n"); 1875 fprintf (stream, "typedef void entry_pt();\n"); 1876 write_list_with_asm (stream, "extern entry_pt ", constructors.first); 1877 1878 if (frames) 1879 { 1880 write_list_with_asm (stream, "extern void *", frame_tables.first); 1881 1882 fprintf (stream, "\tstatic void *frame_table[] = {\n"); 1883 write_list (stream, "\t\t&", frame_tables.first); 1884 fprintf (stream, "\t0\n};\n"); 1885 1886 /* This must match what's in frame.h. */ 1887 fprintf (stream, "struct object {\n"); 1888 fprintf (stream, " void *pc_begin;\n"); 1889 fprintf (stream, " void *pc_end;\n"); 1890 fprintf (stream, " void *fde_begin;\n"); 1891 fprintf (stream, " void *fde_array;\n"); 1892 fprintf (stream, " __SIZE_TYPE__ count;\n"); 1893 fprintf (stream, " struct object *next;\n"); 1894 fprintf (stream, "};\n"); 1895 1896 fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n"); 1897 fprintf (stream, "extern void *__deregister_frame_info (void *);\n"); 1898 1899 fprintf (stream, "static void reg_frame () {\n"); 1900 fprintf (stream, "\tstatic struct object ob;\n"); 1901 fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n"); 1902 fprintf (stream, "\t}\n"); 1903 1904 fprintf (stream, "static void dereg_frame () {\n"); 1905 fprintf (stream, "\t__deregister_frame_info (frame_table);\n"); 1906 fprintf (stream, "\t}\n"); 1907 } 1908 1909 fprintf (stream, "void %s() {\n", initname); 1910 if (constructors.number > 0 || frames) 1911 { 1912 fprintf (stream, "\tstatic entry_pt *ctors[] = {\n"); 1913 write_list (stream, "\t\t", constructors.first); 1914 if (frames) 1915 fprintf (stream, "\treg_frame,\n"); 1916 fprintf (stream, "\t};\n"); 1917 fprintf (stream, "\tentry_pt **p;\n"); 1918 fprintf (stream, "\tif (count++ != 0) return;\n"); 1919 fprintf (stream, "\tp = ctors + %d;\n", constructors.number + frames); 1920 fprintf (stream, "\twhile (p > ctors) (*--p)();\n"); 1921 } 1922 else 1923 fprintf (stream, "\t++count;\n"); 1924 fprintf (stream, "}\n"); 1925 write_list_with_asm (stream, "extern entry_pt ", destructors.first); 1926 fprintf (stream, "void %s() {\n", fininame); 1927 if (destructors.number > 0 || frames) 1928 { 1929 fprintf (stream, "\tstatic entry_pt *dtors[] = {\n"); 1930 write_list (stream, "\t\t", destructors.first); 1931 if (frames) 1932 fprintf (stream, "\tdereg_frame,\n"); 1933 fprintf (stream, "\t};\n"); 1934 fprintf (stream, "\tentry_pt **p;\n"); 1935 fprintf (stream, "\tif (--count != 0) return;\n"); 1936 fprintf (stream, "\tp = dtors;\n"); 1937 fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n", 1938 destructors.number + frames); 1939 } 1940 fprintf (stream, "}\n"); 1941 1942 if (shared_obj) 1943 { 1944 fprintf (stream, "void _GLOBAL__DI() {\n\t%s();\n}\n", initname); 1945 fprintf (stream, "void _GLOBAL__DD() {\n\t%s();\n}\n", fininame); 1946 } 1947} 1948 1949/* Write the constructor/destructor tables. */ 1950 1951#ifndef LD_INIT_SWITCH 1952static void 1953write_c_file_glob (stream, name) 1954 FILE *stream; 1955 char *name; 1956{ 1957 /* Write the tables as C code */ 1958 1959 int frames = (frame_tables.number > 0); 1960 1961 fprintf (stream, "typedef void entry_pt();\n\n"); 1962 1963 write_list_with_asm (stream, "extern entry_pt ", constructors.first); 1964 1965 if (frames) 1966 { 1967 write_list_with_asm (stream, "extern void *", frame_tables.first); 1968 1969 fprintf (stream, "\tstatic void *frame_table[] = {\n"); 1970 write_list (stream, "\t\t&", frame_tables.first); 1971 fprintf (stream, "\t0\n};\n"); 1972 1973 /* This must match what's in frame.h. */ 1974 fprintf (stream, "struct object {\n"); 1975 fprintf (stream, " void *pc_begin;\n"); 1976 fprintf (stream, " void *pc_end;\n"); 1977 fprintf (stream, " void *fde_begin;\n"); 1978 fprintf (stream, " void *fde_array;\n"); 1979 fprintf (stream, " __SIZE_TYPE__ count;\n"); 1980 fprintf (stream, " struct object *next;\n"); 1981 fprintf (stream, "};\n"); 1982 1983 fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n"); 1984 fprintf (stream, "extern void *__deregister_frame_info (void *);\n"); 1985 1986 fprintf (stream, "static void reg_frame () {\n"); 1987 fprintf (stream, "\tstatic struct object ob;\n"); 1988 fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n"); 1989 fprintf (stream, "\t}\n"); 1990 1991 fprintf (stream, "static void dereg_frame () {\n"); 1992 fprintf (stream, "\t__deregister_frame_info (frame_table);\n"); 1993 fprintf (stream, "\t}\n"); 1994 } 1995 1996 fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n"); 1997 fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number + frames); 1998 write_list (stream, "\t", constructors.first); 1999 if (frames) 2000 fprintf (stream, "\treg_frame,\n"); 2001 fprintf (stream, "\t0\n};\n\n"); 2002 2003 write_list_with_asm (stream, "extern entry_pt ", destructors.first); 2004 2005 fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n"); 2006 fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number + frames); 2007 write_list (stream, "\t", destructors.first); 2008 if (frames) 2009 fprintf (stream, "\tdereg_frame,\n"); 2010 fprintf (stream, "\t0\n};\n\n"); 2011 2012 fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN); 2013 fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN); 2014} 2015#endif /* ! LD_INIT_SWITCH */ 2016 2017static void 2018write_c_file (stream, name) 2019 FILE *stream; 2020 char *name; 2021{ 2022 fprintf (stream, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n"); 2023#ifndef LD_INIT_SWITCH 2024 if (! shared_obj) 2025 write_c_file_glob (stream, name); 2026 else 2027#endif 2028 write_c_file_stat (stream, name); 2029 fprintf (stream, "#ifdef __cplusplus\n}\n#endif\n"); 2030} 2031 2032#ifdef COLLECT_EXPORT_LIST 2033static void 2034write_export_file (stream) 2035 FILE *stream; 2036{ 2037 struct id *list = exports.first; 2038 for (; list; list = list->next) 2039 fprintf (stream, "%s\n", list->name); 2040} 2041 2042static void 2043write_import_file (stream) 2044 FILE *stream; 2045{ 2046 struct id *list = imports.first; 2047 fprintf (stream, "%s\n", "#! ."); 2048 for (; list; list = list->next) 2049 fprintf (stream, "%s\n", list->name); 2050} 2051#endif 2052 2053#ifdef OBJECT_FORMAT_NONE 2054 2055/* Generic version to scan the name list of the loaded program for 2056 the symbols g++ uses for static constructors and destructors. 2057 2058 The constructor table begins at __CTOR_LIST__ and contains a count 2059 of the number of pointers (or -1 if the constructors are built in a 2060 separate section by the linker), followed by the pointers to the 2061 constructor functions, terminated with a null pointer. The 2062 destructor table has the same format, and begins at __DTOR_LIST__. */ 2063 2064static void 2065scan_prog_file (prog_name, which_pass) 2066 char *prog_name; 2067 enum pass which_pass; 2068{ 2069 void (*int_handler) (); 2070 void (*quit_handler) (); 2071 char *nm_argv[4]; 2072 int pid; 2073 int argc = 0; 2074 int pipe_fd[2]; 2075 char *p, buf[1024]; 2076 FILE *inf; 2077 2078 if (which_pass == PASS_SECOND) 2079 return; 2080 2081 /* If we do not have an `nm', complain. */ 2082 if (nm_file_name == 0) 2083 fatal ("cannot find `nm'"); 2084 2085 nm_argv[argc++] = nm_file_name; 2086 if (NM_FLAGS[0] != '\0') 2087 nm_argv[argc++] = NM_FLAGS; 2088 2089 nm_argv[argc++] = prog_name; 2090 nm_argv[argc++] = (char *) 0; 2091 2092 if (pipe (pipe_fd) < 0) 2093 fatal_perror ("pipe"); 2094 2095 inf = fdopen (pipe_fd[0], "r"); 2096 if (inf == (FILE *) 0) 2097 fatal_perror ("fdopen"); 2098 2099 /* Trace if needed. */ 2100 if (vflag) 2101 { 2102 char **p_argv; 2103 char *str; 2104 2105 for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *) 0; p_argv++) 2106 fprintf (stderr, " %s", str); 2107 2108 fprintf (stderr, "\n"); 2109 } 2110 2111 fflush (stdout); 2112 fflush (stderr); 2113 2114 /* Spawn child nm on pipe */ 2115 pid = vfork (); 2116 if (pid == -1) 2117 { 2118#ifdef vfork 2119 fatal_perror ("fork"); 2120#else 2121 fatal_perror ("vfork"); 2122#endif 2123 } 2124 2125 if (pid == 0) /* child context */ 2126 { 2127 /* setup stdout */ 2128 if (dup2 (pipe_fd[1], 1) < 0) 2129 fatal_perror ("dup2 (%d, 1)", pipe_fd[1]); 2130 2131 if (close (pipe_fd[0]) < 0) 2132 fatal_perror ("close (%d)", pipe_fd[0]); 2133 2134 if (close (pipe_fd[1]) < 0) 2135 fatal_perror ("close (%d)", pipe_fd[1]); 2136 2137 execv (nm_file_name, nm_argv); 2138 fatal_perror ("executing %s", nm_file_name); 2139 } 2140 2141 /* Parent context from here on. */ 2142 int_handler = (void (*) ())signal (SIGINT, SIG_IGN); 2143#ifdef SIGQUIT 2144 quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN); 2145#endif 2146 2147 if (close (pipe_fd[1]) < 0) 2148 fatal_perror ("close (%d)", pipe_fd[1]); 2149 2150 if (debug) 2151 fprintf (stderr, "\nnm output with constructors/destructors.\n"); 2152 2153 /* Read each line of nm output. */ 2154 while (fgets (buf, sizeof buf, inf) != (char *) 0) 2155 { 2156 int ch, ch2; 2157 char *name, *end; 2158 2159 /* If it contains a constructor or destructor name, add the name 2160 to the appropriate list. */ 2161 2162 for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++) 2163 if (ch == ' ' && p[1] == 'U' && p[2] == ' ') 2164 break; 2165 2166 if (ch != '_') 2167 continue; 2168 2169 name = p; 2170 /* Find the end of the symbol name. 2171 Do not include `|', because Encore nm can tack that on the end. */ 2172 for (end = p; (ch2 = *end) != '\0' && !ISSPACE (ch2) && ch2 != '|'; 2173 end++) 2174 continue; 2175 2176 2177 *end = '\0'; 2178 switch (is_ctor_dtor (name)) 2179 { 2180 case 1: 2181 if (which_pass != PASS_LIB) 2182 add_to_list (&constructors, name); 2183 break; 2184 2185 case 2: 2186 if (which_pass != PASS_LIB) 2187 add_to_list (&destructors, name); 2188 break; 2189 2190 case 3: 2191 if (which_pass != PASS_LIB) 2192 fatal ("init function found in object %s", prog_name); 2193#ifndef LD_INIT_SWITCH 2194 add_to_list (&constructors, name); 2195#endif 2196 break; 2197 2198 case 4: 2199 if (which_pass != PASS_LIB) 2200 fatal ("fini function found in object %s", prog_name); 2201#ifndef LD_FINI_SWITCH 2202 add_to_list (&destructors, name); 2203#endif 2204 break; 2205 2206 case 5: 2207 if (which_pass != PASS_LIB) 2208 add_to_list (&frame_tables, name); 2209 2210 default: /* not a constructor or destructor */ 2211 continue; 2212 } 2213 2214 if (debug) 2215 fprintf (stderr, "\t%s\n", buf); 2216 } 2217 2218 if (debug) 2219 fprintf (stderr, "\n"); 2220 2221 if (fclose (inf) != 0) 2222 fatal_perror ("fclose of pipe"); 2223 2224 do_wait (nm_file_name); 2225 2226 signal (SIGINT, int_handler); 2227#ifdef SIGQUIT 2228 signal (SIGQUIT, quit_handler); 2229#endif 2230} 2231 2232#if SUNOS4_SHARED_LIBRARIES 2233 2234/* Routines to scan the SunOS 4 _DYNAMIC structure to find shared libraries 2235 that the output file depends upon and their initialization/finalization 2236 routines, if any. */ 2237 2238#include <a.out.h> 2239#include <fcntl.h> 2240#include <link.h> 2241#include <sys/mman.h> 2242#include <sys/param.h> 2243#include <unistd.h> 2244#include <sys/dir.h> 2245 2246/* pointers to the object file */ 2247unsigned object; /* address of memory mapped file */ 2248unsigned objsize; /* size of memory mapped to file */ 2249char * code; /* pointer to code segment */ 2250char * data; /* pointer to data segment */ 2251struct nlist *symtab; /* pointer to symbol table */ 2252struct link_dynamic *ld; 2253struct link_dynamic_2 *ld_2; 2254struct head libraries; 2255 2256/* Map the file indicated by NAME into memory and store its address. */ 2257 2258static void 2259mapfile (name) 2260 char *name; 2261{ 2262 int fp; 2263 struct stat s; 2264 if ((fp = open (name, O_RDONLY)) == -1) 2265 fatal ("unable to open file '%s'", name); 2266 if (fstat (fp, &s) == -1) 2267 fatal ("unable to stat file '%s'", name); 2268 2269 objsize = s.st_size; 2270 object = (unsigned) mmap (0, objsize, PROT_READ|PROT_WRITE, MAP_PRIVATE, 2271 fp, 0); 2272 if (object == -1) 2273 fatal ("unable to mmap file '%s'", name); 2274 2275 close (fp); 2276} 2277 2278/* Helpers for locatelib. */ 2279 2280static char *libname; 2281 2282static int 2283libselect (d) 2284 struct direct *d; 2285{ 2286 return (strncmp (libname, d->d_name, strlen (libname)) == 0); 2287} 2288 2289/* If one file has an additional numeric extension past LIBNAME, then put 2290 that one first in the sort. If both files have additional numeric 2291 extensions, then put the one with the higher number first in the sort. 2292 2293 We must verify that the extension is numeric, because Sun saves the 2294 original versions of patched libraries with a .FCS extension. Files with 2295 invalid extensions must go last in the sort, so that they will not be used. */ 2296 2297static int 2298libcompare (d1, d2) 2299 struct direct **d1, **d2; 2300{ 2301 int i1, i2 = strlen (libname); 2302 char *e1 = (*d1)->d_name + i2; 2303 char *e2 = (*d2)->d_name + i2; 2304 2305 while (*e1 && *e2 && *e1 == '.' && *e2 == '.' 2306 && e1[1] && ISDIGIT (e1[1]) && e2[1] && ISDIGIT (e2[1])) 2307 { 2308 ++e1; 2309 ++e2; 2310 i1 = strtol (e1, &e1, 10); 2311 i2 = strtol (e2, &e2, 10); 2312 if (i1 != i2) 2313 return i1 - i2; 2314 } 2315 2316 if (*e1) 2317 { 2318 /* It has a valid numeric extension, prefer this one. */ 2319 if (*e1 == '.' && e1[1] && ISDIGIT (e1[1])) 2320 return 1; 2321 /* It has a invalid numeric extension, must prefer the other one. */ 2322 else 2323 return -1; 2324 } 2325 else if (*e2) 2326 { 2327 /* It has a valid numeric extension, prefer this one. */ 2328 if (*e2 == '.' && e2[1] && ISDIGIT (e2[1])) 2329 return -1; 2330 /* It has a invalid numeric extension, must prefer the other one. */ 2331 else 2332 return 1; 2333 } 2334 else 2335 return 0; 2336} 2337 2338/* Given the name NAME of a dynamic dependency, find its pathname and add 2339 it to the list of libraries. */ 2340 2341static void 2342locatelib (name) 2343 char *name; 2344{ 2345 static char **l; 2346 static int cnt; 2347 char buf[MAXPATHLEN]; 2348 char *p, *q; 2349 char **pp; 2350 2351 if (l == 0) 2352 { 2353 char *ld_rules; 2354 char *ldr = 0; 2355 /* counting elements in array, need 1 extra for null */ 2356 cnt = 1; 2357 ld_rules = (char *) (ld_2->ld_rules + code); 2358 if (ld_rules) 2359 { 2360 cnt++; 2361 for (; *ld_rules != 0; ld_rules++) 2362 if (*ld_rules == ':') 2363 cnt++; 2364 ld_rules = (char *) (ld_2->ld_rules + code); 2365 ldr = (char *) malloc (strlen (ld_rules) + 1); 2366 strcpy (ldr, ld_rules); 2367 } 2368 p = getenv ("LD_LIBRARY_PATH"); 2369 q = 0; 2370 if (p) 2371 { 2372 cnt++; 2373 for (q = p ; *q != 0; q++) 2374 if (*q == ':') 2375 cnt++; 2376 q = (char *) malloc (strlen (p) + 1); 2377 strcpy (q, p); 2378 } 2379 l = (char **) malloc ((cnt + 3) * sizeof (char *)); 2380 pp = l; 2381 if (ldr) 2382 { 2383 *pp++ = ldr; 2384 for (; *ldr != 0; ldr++) 2385 if (*ldr == ':') 2386 { 2387 *ldr++ = 0; 2388 *pp++ = ldr; 2389 } 2390 } 2391 if (q) 2392 { 2393 *pp++ = q; 2394 for (; *q != 0; q++) 2395 if (*q == ':') 2396 { 2397 *q++ = 0; 2398 *pp++ = q; 2399 } 2400 } 2401 /* built in directories are /lib, /usr/lib, and /usr/local/lib */ 2402 *pp++ = "/lib"; 2403 *pp++ = "/usr/lib"; 2404 *pp++ = "/usr/local/lib"; 2405 *pp = 0; 2406 } 2407 libname = name; 2408 for (pp = l; *pp != 0 ; pp++) 2409 { 2410 struct direct **namelist; 2411 int entries; 2412 if ((entries = scandir (*pp, &namelist, libselect, libcompare)) > 0) 2413 { 2414 sprintf (buf, "%s/%s", *pp, namelist[entries - 1]->d_name); 2415 add_to_list (&libraries, buf); 2416 if (debug) 2417 fprintf (stderr, "%s\n", buf); 2418 break; 2419 } 2420 } 2421 if (*pp == 0) 2422 { 2423 if (debug) 2424 fprintf (stderr, "not found\n"); 2425 else 2426 fatal ("dynamic dependency %s not found", name); 2427 } 2428} 2429 2430/* Scan the _DYNAMIC structure of the output file to find shared libraries 2431 that it depends upon and any constructors or destructors they contain. */ 2432 2433static void 2434scan_libraries (prog_name) 2435 char *prog_name; 2436{ 2437 struct exec *header; 2438 char *base; 2439 struct link_object *lo; 2440 char buff[MAXPATHLEN]; 2441 struct id *list; 2442 2443 mapfile (prog_name); 2444 header = (struct exec *)object; 2445 if (N_BADMAG (*header)) 2446 fatal ("bad magic number in file '%s'", prog_name); 2447 if (header->a_dynamic == 0) 2448 return; 2449 2450 code = (char *) (N_TXTOFF (*header) + (long) header); 2451 data = (char *) (N_DATOFF (*header) + (long) header); 2452 symtab = (struct nlist *) (N_SYMOFF (*header) + (long) header); 2453 2454 if (header->a_magic == ZMAGIC && header->a_entry == 0x20) 2455 { 2456 /* shared object */ 2457 ld = (struct link_dynamic *) (symtab->n_value + code); 2458 base = code; 2459 } 2460 else 2461 { 2462 /* executable */ 2463 ld = (struct link_dynamic *) data; 2464 base = code-PAGSIZ; 2465 } 2466 2467 if (debug) 2468 fprintf (stderr, "dynamic dependencies.\n"); 2469 2470 ld_2 = (struct link_dynamic_2 *) ((long) ld->ld_un.ld_2 + (long)base); 2471 for (lo = (struct link_object *) ld_2->ld_need; lo; 2472 lo = (struct link_object *) lo->lo_next) 2473 { 2474 char *name; 2475 lo = (struct link_object *) ((long) lo + code); 2476 name = (char *) (code + lo->lo_name); 2477 if (lo->lo_library) 2478 { 2479 if (debug) 2480 fprintf (stderr, "\t-l%s.%d => ", name, lo->lo_major); 2481 sprintf (buff, "lib%s.so.%d.%d", name, lo->lo_major, lo->lo_minor); 2482 locatelib (buff); 2483 } 2484 else 2485 { 2486 if (debug) 2487 fprintf (stderr, "\t%s\n", name); 2488 add_to_list (&libraries, name); 2489 } 2490 } 2491 2492 if (debug) 2493 fprintf (stderr, "\n"); 2494 2495 /* now iterate through the library list adding their symbols to 2496 the list. */ 2497 for (list = libraries.first; list; list = list->next) 2498 scan_prog_file (list->name, PASS_LIB); 2499} 2500 2501#else /* SUNOS4_SHARED_LIBRARIES */ 2502#ifdef LDD_SUFFIX 2503 2504/* Use the List Dynamic Dependencies program to find shared libraries that 2505 the output file depends upon and their initialization/finalization 2506 routines, if any. */ 2507 2508static void 2509scan_libraries (prog_name) 2510 char *prog_name; 2511{ 2512 static struct head libraries; /* list of shared libraries found */ 2513 struct id *list; 2514 void (*int_handler) (); 2515 void (*quit_handler) (); 2516 char *ldd_argv[4]; 2517 int pid; 2518 int argc = 0; 2519 int pipe_fd[2]; 2520 char buf[1024]; 2521 FILE *inf; 2522 2523 /* If we do not have an `ldd', complain. */ 2524 if (ldd_file_name == 0) 2525 { 2526 error ("cannot find `ldd'"); 2527 return; 2528 } 2529 2530 ldd_argv[argc++] = ldd_file_name; 2531 ldd_argv[argc++] = prog_name; 2532 ldd_argv[argc++] = (char *) 0; 2533 2534 if (pipe (pipe_fd) < 0) 2535 fatal_perror ("pipe"); 2536 2537 inf = fdopen (pipe_fd[0], "r"); 2538 if (inf == (FILE *) 0) 2539 fatal_perror ("fdopen"); 2540 2541 /* Trace if needed. */ 2542 if (vflag) 2543 { 2544 char **p_argv; 2545 char *str; 2546 2547 for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++) 2548 fprintf (stderr, " %s", str); 2549 2550 fprintf (stderr, "\n"); 2551 } 2552 2553 fflush (stdout); 2554 fflush (stderr); 2555 2556 /* Spawn child ldd on pipe */ 2557 pid = vfork (); 2558 if (pid == -1) 2559 { 2560#ifdef vfork 2561 fatal_perror ("fork"); 2562#else 2563 fatal_perror ("vfork"); 2564#endif 2565 } 2566 2567 if (pid == 0) /* child context */ 2568 { 2569 /* setup stdout */ 2570 if (dup2 (pipe_fd[1], 1) < 0) 2571 fatal_perror ("dup2 (%d, 1)", pipe_fd[1]); 2572 2573 if (close (pipe_fd[0]) < 0) 2574 fatal_perror ("close (%d)", pipe_fd[0]); 2575 2576 if (close (pipe_fd[1]) < 0) 2577 fatal_perror ("close (%d)", pipe_fd[1]); 2578 2579 execv (ldd_file_name, ldd_argv); 2580 fatal_perror ("executing %s", ldd_file_name); 2581 } 2582 2583 /* Parent context from here on. */ 2584 int_handler = (void (*) ()) signal (SIGINT, SIG_IGN); 2585#ifdef SIGQUIT 2586 quit_handler = (void (*) ()) signal (SIGQUIT, SIG_IGN); 2587#endif 2588 2589 if (close (pipe_fd[1]) < 0) 2590 fatal_perror ("close (%d)", pipe_fd[1]); 2591 2592 if (debug) 2593 fprintf (stderr, "\nldd output with constructors/destructors.\n"); 2594 2595 /* Read each line of ldd output. */ 2596 while (fgets (buf, sizeof buf, inf) != (char *) 0) 2597 { 2598 int ch, ch2; 2599 char *name, *end, *p = buf; 2600 2601 /* Extract names of libraries and add to list. */ 2602 PARSE_LDD_OUTPUT (p); 2603 if (p == 0) 2604 continue; 2605 2606 name = p; 2607 if (strncmp (name, "not found", sizeof ("not found") - 1) == 0) 2608 fatal ("dynamic dependency %s not found", buf); 2609 2610 /* Find the end of the symbol name. */ 2611 for (end = p; 2612 (ch2 = *end) != '\0' && ch2 != '\n' && !ISSPACE (ch2) && ch2 != '|'; 2613 end++) 2614 continue; 2615 *end = '\0'; 2616 2617 if (access (name, R_OK) == 0) 2618 add_to_list (&libraries, name); 2619 else 2620 fatal ("unable to open dynamic dependency '%s'", buf); 2621 2622 if (debug) 2623 fprintf (stderr, "\t%s\n", buf); 2624 } 2625 if (debug) 2626 fprintf (stderr, "\n"); 2627 2628 if (fclose (inf) != 0) 2629 fatal_perror ("fclose of pipe"); 2630 2631 do_wait (ldd_file_name); 2632 2633 signal (SIGINT, int_handler); 2634#ifdef SIGQUIT 2635 signal (SIGQUIT, quit_handler); 2636#endif 2637 2638 /* now iterate through the library list adding their symbols to 2639 the list. */ 2640 for (list = libraries.first; list; list = list->next) 2641 scan_prog_file (list->name, PASS_LIB); 2642} 2643 2644#endif /* LDD_SUFFIX */ 2645#endif /* SUNOS4_SHARED_LIBRARIES */ 2646 2647#endif /* OBJECT_FORMAT_NONE */ 2648 2649 2650/* 2651 * COFF specific stuff. 2652 */ 2653 2654#ifdef OBJECT_FORMAT_COFF 2655 2656#if defined(EXTENDED_COFF) 2657# define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax) 2658# define GCC_SYMENT SYMR 2659# define GCC_OK_SYMBOL(X) ((X).st == stProc && (X).sc == scText) 2660# define GCC_SYMINC(X) (1) 2661# define GCC_SYMZERO(X) (SYMHEADER(X).isymMax) 2662# define GCC_CHECK_HDR(X) (PSYMTAB(X) != 0) 2663#else 2664# define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms) 2665# define GCC_SYMENT SYMENT 2666# define GCC_OK_SYMBOL(X) \ 2667 (((X).n_sclass == C_EXT) && \ 2668 ((X).n_scnum > N_UNDEF) && \ 2669 (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) || \ 2670 ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT))) 2671# define GCC_UNDEF_SYMBOL(X) \ 2672 (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF)) 2673# define GCC_SYMINC(X) ((X).n_numaux+1) 2674# define GCC_SYMZERO(X) 0 2675# define GCC_CHECK_HDR(X) \ 2676 ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \ 2677 || (HEADER (X).f_magic == 0757 && aix64_flag)) 2678#endif 2679 2680extern char *ldgetname (); 2681 2682/* COFF version to scan the name list of the loaded program for 2683 the symbols g++ uses for static constructors and destructors. 2684 2685 The constructor table begins at __CTOR_LIST__ and contains a count 2686 of the number of pointers (or -1 if the constructors are built in a 2687 separate section by the linker), followed by the pointers to the 2688 constructor functions, terminated with a null pointer. The 2689 destructor table has the same format, and begins at __DTOR_LIST__. */ 2690 2691static void 2692scan_prog_file (prog_name, which_pass) 2693 char *prog_name; 2694 enum pass which_pass; 2695{ 2696 LDFILE *ldptr = NULL; 2697 int sym_index, sym_count; 2698 int is_shared = 0; 2699#ifdef COLLECT_EXPORT_LIST 2700 /* Should we generate an import list for given prog_name? */ 2701 int import_flag = (which_pass == PASS_OBJ ? 0 : use_import_list (prog_name)); 2702#endif 2703 2704 if (which_pass != PASS_FIRST && which_pass != PASS_OBJ) 2705 return; 2706 2707#ifdef COLLECT_EXPORT_LIST 2708 /* We do not need scanning for some standard C libraries. */ 2709 if (which_pass == PASS_FIRST && ignore_library (prog_name)) 2710 return; 2711 2712 /* On AIX we have a loop, because there is not much difference 2713 between an object and an archive. This trick allows us to 2714 eliminate scan_libraries() function. */ 2715 do 2716 { 2717#endif 2718 if ((ldptr = ldopen (prog_name, ldptr)) != NULL) 2719 { 2720 if (! MY_ISCOFF (HEADER (ldptr).f_magic)) 2721 fatal ("%s: not a COFF file", prog_name); 2722 2723 if (GCC_CHECK_HDR (ldptr)) 2724 { 2725 sym_count = GCC_SYMBOLS (ldptr); 2726 sym_index = GCC_SYMZERO (ldptr); 2727 2728#ifdef COLLECT_EXPORT_LIST 2729 /* Is current archive member a shared object? */ 2730 is_shared = HEADER (ldptr).f_flags & F_SHROBJ; 2731#endif 2732 2733 while (sym_index < sym_count) 2734 { 2735 GCC_SYMENT symbol; 2736 2737 if (ldtbread (ldptr, sym_index, &symbol) <= 0) 2738 break; 2739 sym_index += GCC_SYMINC (symbol); 2740 2741 if (GCC_OK_SYMBOL (symbol)) 2742 { 2743 char *name; 2744 2745 if ((name = ldgetname (ldptr, &symbol)) == NULL) 2746 continue; /* should never happen */ 2747 2748#ifdef XCOFF_DEBUGGING_INFO 2749 /* All AIX function names have a duplicate entry 2750 beginning with a dot. */ 2751 if (*name == '.') 2752 ++name; 2753#endif 2754 2755 switch (is_ctor_dtor (name)) 2756 { 2757 case 1: 2758 if (! is_shared) add_to_list (&constructors, name); 2759#ifdef COLLECT_EXPORT_LIST 2760 if (which_pass == PASS_OBJ) 2761 add_to_list (&exports, name); 2762 /* If this symbol was undefined and we are building 2763 an import list, we should add a symbol to this 2764 list. */ 2765 else 2766 if (import_flag 2767 && is_in_list (name, undefined.first)) 2768 add_to_list (&imports, name); 2769#endif 2770 break; 2771 2772 case 2: 2773 if (! is_shared) add_to_list (&destructors, name); 2774#ifdef COLLECT_EXPORT_LIST 2775 if (which_pass == PASS_OBJ) 2776 add_to_list (&exports, name); 2777 /* If this symbol was undefined and we are building 2778 an import list, we should add a symbol to this 2779 list. */ 2780 else 2781 if (import_flag 2782 && is_in_list (name, undefined.first)) 2783 add_to_list (&imports, name); 2784#endif 2785 break; 2786 2787#ifdef COLLECT_EXPORT_LIST 2788 case 3: 2789 if (is_shared) 2790 add_to_list (&constructors, name); 2791 break; 2792 2793 case 4: 2794 if (is_shared) 2795 add_to_list (&destructors, name); 2796 break; 2797#endif 2798 2799 default: /* not a constructor or destructor */ 2800#ifdef COLLECT_EXPORT_LIST 2801 /* If we are building a shared object on AIX we need 2802 to explicitly export all global symbols or add 2803 them to import list. */ 2804 if (shared_obj) 2805 { 2806 if (which_pass == PASS_OBJ && (! export_flag)) 2807 add_to_list (&exports, name); 2808 else if (! is_shared && which_pass == PASS_FIRST 2809 && import_flag 2810 && is_in_list(name, undefined.first)) 2811 add_to_list (&imports, name); 2812 } 2813#endif 2814 continue; 2815 } 2816 2817#if !defined(EXTENDED_COFF) 2818 if (debug) 2819 fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n", 2820 symbol.n_scnum, symbol.n_sclass, 2821 (symbol.n_type ? "0" : ""), symbol.n_type, 2822 name); 2823#else 2824 if (debug) 2825 fprintf (stderr, 2826 "\tiss = %5d, value = %5ld, index = %5d, name = %s\n", 2827 symbol.iss, (long) symbol.value, symbol.index, name); 2828#endif 2829 } 2830#ifdef COLLECT_EXPORT_LIST 2831 /* If we are building a shared object we should collect 2832 information about undefined symbols for later 2833 import list generation. */ 2834 else if (shared_obj && GCC_UNDEF_SYMBOL (symbol)) 2835 { 2836 char *name; 2837 2838 if ((name = ldgetname (ldptr, &symbol)) == NULL) 2839 continue; /* should never happen */ 2840 2841 /* All AIX function names have a duplicate entry 2842 beginning with a dot. */ 2843 if (*name == '.') 2844 ++name; 2845 add_to_list (&undefined, name); 2846 } 2847#endif 2848 } 2849 } 2850#ifdef COLLECT_EXPORT_LIST 2851 else 2852 { 2853 /* If archive contains both 32-bit and 64-bit objects, 2854 we want to skip objects in other mode so mismatch normal. */ 2855 if (debug) 2856 fprintf (stderr, "%s : magic=%o aix64=%d mismatch\n", 2857 prog_name, HEADER (ldptr).f_magic, aix64_flag); 2858 } 2859#endif 2860 } 2861 else 2862 { 2863 fatal ("%s: cannot open as COFF file", prog_name); 2864 } 2865#ifdef COLLECT_EXPORT_LIST 2866 /* On AIX loop continues while there are more members in archive. */ 2867 } 2868 while (ldclose (ldptr) == FAILURE); 2869#else 2870 /* Otherwise we simply close ldptr. */ 2871 (void) ldclose(ldptr); 2872#endif 2873} 2874 2875 2876#ifdef COLLECT_EXPORT_LIST 2877 2878/* This new function is used to decide whether we should 2879 generate import list for an object or to use it directly. */ 2880static int 2881use_import_list (prog_name) 2882 char *prog_name; 2883{ 2884 char *p; 2885 2886 /* If we do not build a shared object then import list should not be used. */ 2887 if (! shared_obj) return 0; 2888 2889 /* Currently we check only for libgcc, but this can be changed in future. */ 2890 p = strstr (prog_name, "libgcc.a"); 2891 if (p != 0 && (strlen (p) == sizeof ("libgcc.a") - 1)) 2892 return 1; 2893 return 0; 2894} 2895 2896/* Given a library name without "lib" prefix, this function 2897 returns a full library name including a path. */ 2898static char * 2899resolve_lib_name (name) 2900 char *name; 2901{ 2902 char *lib_buf; 2903 int i, j, l = 0; 2904 2905 for (i = 0; libpaths[i]; i++) 2906 if (libpaths[i]->max_len > l) 2907 l = libpaths[i]->max_len; 2908 2909 lib_buf = xmalloc (l + strlen(name) + 10); 2910 2911 for (i = 0; libpaths[i]; i++) 2912 { 2913 struct prefix_list *list = libpaths[i]->plist; 2914 for (; list; list = list->next) 2915 { 2916 for (j = 0; libexts[j]; j++) 2917 { 2918 /* The following lines are needed because path_prefix list 2919 may contain directories both with trailing '/' and 2920 without it. */ 2921 char *p = ""; 2922 if (list->prefix[strlen(list->prefix)-1] != '/') 2923 p = "/"; 2924 sprintf (lib_buf, "%s%slib%s.%s", 2925 list->prefix, p, name, libexts[j]); 2926if (debug) fprintf (stderr, "searching for: %s\n", lib_buf); 2927 if (file_exists (lib_buf)) 2928 { 2929if (debug) fprintf (stderr, "found: %s\n", lib_buf); 2930 return (lib_buf); 2931 } 2932 } 2933 } 2934 } 2935 if (debug) 2936 fprintf (stderr, "not found\n"); 2937 else 2938 fatal ("Library lib%s not found", name); 2939 return (NULL); 2940} 2941 2942/* Array of standard AIX libraries which should not 2943 be scanned for ctors/dtors. */ 2944static char* aix_std_libs[] = { 2945 "/unix", 2946 "/lib/libc.a", 2947 "/lib/libc_r.a", 2948 "/usr/lib/libc.a", 2949 "/usr/lib/libc_r.a", 2950 "/usr/lib/threads/libc.a", 2951 "/usr/ccs/lib/libc.a", 2952 "/usr/ccs/lib/libc_r.a", 2953 NULL 2954}; 2955 2956/* This function checks the filename and returns 1 2957 if this name matches the location of a standard AIX library. */ 2958static int 2959ignore_library (name) 2960 char *name; 2961{ 2962 char **p = &aix_std_libs[0]; 2963 while (*p++ != NULL) 2964 if (! strcmp (name, *p)) return 1; 2965 return 0; 2966} 2967 2968#endif 2969 2970#endif /* OBJECT_FORMAT_COFF */ 2971 2972 2973/* 2974 * OSF/rose specific stuff. 2975 */ 2976 2977#ifdef OBJECT_FORMAT_ROSE 2978 2979/* Union of the various load commands */ 2980 2981typedef union load_union 2982{ 2983 ldc_header_t hdr; /* common header */ 2984 load_cmd_map_command_t map; /* map indexing other load cmds */ 2985 interpreter_command_t iprtr; /* interpreter pathname */ 2986 strings_command_t str; /* load commands strings section */ 2987 region_command_t region; /* region load command */ 2988 reloc_command_t reloc; /* relocation section */ 2989 package_command_t pkg; /* package load command */ 2990 symbols_command_t sym; /* symbol sections */ 2991 entry_command_t ent; /* program start section */ 2992 gen_info_command_t info; /* object information */ 2993 func_table_command_t func; /* function constructors/destructors */ 2994} load_union_t; 2995 2996/* Structure to point to load command and data section in memory. */ 2997 2998typedef struct load_all 2999{ 3000 load_union_t *load; /* load command */ 3001 char *section; /* pointer to section */ 3002} load_all_t; 3003 3004/* Structure to contain information about a file mapped into memory. */ 3005 3006struct file_info 3007{ 3008 char *start; /* start of map */ 3009 char *name; /* filename */ 3010 long size; /* size of the file */ 3011 long rounded_size; /* size rounded to page boundary */ 3012 int fd; /* file descriptor */ 3013 int rw; /* != 0 if opened read/write */ 3014 int use_mmap; /* != 0 if mmap'ed */ 3015}; 3016 3017extern int decode_mach_o_hdr (); 3018extern int encode_mach_o_hdr (); 3019 3020static void add_func_table PROTO((mo_header_t *, load_all_t *, 3021 symbol_info_t *, int)); 3022static void print_header PROTO((mo_header_t *)); 3023static void print_load_command PROTO((load_union_t *, size_t, int)); 3024static void bad_header PROTO((int)); 3025static struct file_info *read_file PROTO((char *, int, int)); 3026static void end_file PROTO((struct file_info *)); 3027 3028/* OSF/rose specific version to scan the name list of the loaded 3029 program for the symbols g++ uses for static constructors and 3030 destructors. 3031 3032 The constructor table begins at __CTOR_LIST__ and contains a count 3033 of the number of pointers (or -1 if the constructors are built in a 3034 separate section by the linker), followed by the pointers to the 3035 constructor functions, terminated with a null pointer. The 3036 destructor table has the same format, and begins at __DTOR_LIST__. */ 3037 3038static void 3039scan_prog_file (prog_name, which_pass) 3040 char *prog_name; 3041 enum pass which_pass; 3042{ 3043 char *obj; 3044 mo_header_t hdr; 3045 load_all_t *load_array; 3046 load_all_t *load_end; 3047 load_all_t *load_cmd; 3048 int symbol_load_cmds; 3049 off_t offset; 3050 int i; 3051 int num_syms; 3052 int status; 3053 char *str_sect; 3054 struct file_info *obj_file; 3055 int prog_fd; 3056 mo_lcid_t cmd_strings = -1; 3057 symbol_info_t *main_sym = 0; 3058 int rw = (which_pass != PASS_FIRST); 3059 3060 prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY); 3061 if (prog_fd < 0) 3062 fatal_perror ("cannot read %s", prog_name); 3063 3064 obj_file = read_file (prog_name, prog_fd, rw); 3065 obj = obj_file->start; 3066 3067 status = decode_mach_o_hdr (obj, MO_SIZEOF_RAW_HDR, MOH_HEADER_VERSION, &hdr); 3068 if (status != MO_HDR_CONV_SUCCESS) 3069 bad_header (status); 3070 3071 3072 /* Do some basic sanity checks. Note we explicitly use the big endian magic number, 3073 since the hardware will automatically swap bytes for us on loading little endian 3074 integers. */ 3075 3076#ifndef CROSS_COMPILE 3077 if (hdr.moh_magic != MOH_MAGIC_MSB 3078 || hdr.moh_header_version != MOH_HEADER_VERSION 3079 || hdr.moh_byte_order != OUR_BYTE_ORDER 3080 || hdr.moh_data_rep_id != OUR_DATA_REP_ID 3081 || hdr.moh_cpu_type != OUR_CPU_TYPE 3082 || hdr.moh_cpu_subtype != OUR_CPU_SUBTYPE 3083 || hdr.moh_vendor_type != OUR_VENDOR_TYPE) 3084 { 3085 fatal ("incompatibilities between object file & expected values"); 3086 } 3087#endif 3088 3089 if (debug) 3090 print_header (&hdr); 3091 3092 offset = hdr.moh_first_cmd_off; 3093 load_end = load_array 3094 = (load_all_t *) xcalloc (sizeof (load_all_t), hdr.moh_n_load_cmds + 2); 3095 3096 /* Build array of load commands, calculating the offsets */ 3097 for (i = 0; i < hdr.moh_n_load_cmds; i++) 3098 { 3099 load_union_t *load_hdr; /* load command header */ 3100 3101 load_cmd = load_end++; 3102 load_hdr = (load_union_t *) (obj + offset); 3103 3104 /* If modifying the program file, copy the header. */ 3105 if (rw) 3106 { 3107 load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size); 3108 bcopy ((char *)load_hdr, (char *)ptr, load_hdr->hdr.ldci_cmd_size); 3109 load_hdr = ptr; 3110 3111 /* null out old command map, because we will rewrite at the end. */ 3112 if (ptr->hdr.ldci_cmd_type == LDC_CMD_MAP) 3113 { 3114 cmd_strings = ptr->map.lcm_ld_cmd_strings; 3115 ptr->hdr.ldci_cmd_type = LDC_UNDEFINED; 3116 } 3117 } 3118 3119 load_cmd->load = load_hdr; 3120 if (load_hdr->hdr.ldci_section_off > 0) 3121 load_cmd->section = obj + load_hdr->hdr.ldci_section_off; 3122 3123 if (debug) 3124 print_load_command (load_hdr, offset, i); 3125 3126 offset += load_hdr->hdr.ldci_cmd_size; 3127 } 3128 3129 /* If the last command is the load command map and is not undefined, 3130 decrement the count of load commands. */ 3131 if (rw && load_end[-1].load->hdr.ldci_cmd_type == LDC_UNDEFINED) 3132 { 3133 load_end--; 3134 hdr.moh_n_load_cmds--; 3135 } 3136 3137 /* Go through and process each symbol table section. */ 3138 symbol_load_cmds = 0; 3139 for (load_cmd = load_array; load_cmd < load_end; load_cmd++) 3140 { 3141 load_union_t *load_hdr = load_cmd->load; 3142 3143 if (load_hdr->hdr.ldci_cmd_type == LDC_SYMBOLS) 3144 { 3145 symbol_load_cmds++; 3146 3147 if (debug) 3148 { 3149 char *kind = "unknown"; 3150 3151 switch (load_hdr->sym.symc_kind) 3152 { 3153 case SYMC_IMPORTS: kind = "imports"; break; 3154 case SYMC_DEFINED_SYMBOLS: kind = "defined"; break; 3155 case SYMC_STABS: kind = "stabs"; break; 3156 } 3157 3158 fprintf (stderr, "\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n", 3159 symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind); 3160 } 3161 3162 if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS) 3163 continue; 3164 3165 str_sect = load_array[load_hdr->sym.symc_strings_section].section; 3166 if (str_sect == (char *) 0) 3167 fatal ("string section missing"); 3168 3169 if (load_cmd->section == (char *) 0) 3170 fatal ("section pointer missing"); 3171 3172 num_syms = load_hdr->sym.symc_nentries; 3173 for (i = 0; i < num_syms; i++) 3174 { 3175 symbol_info_t *sym = ((symbol_info_t *) load_cmd->section) + i; 3176 char *name = sym->si_name.symbol_name + str_sect; 3177 3178 if (name[0] != '_') 3179 continue; 3180 3181 if (rw) 3182 { 3183 char *n = name + strlen (name) - strlen (NAME__MAIN); 3184 3185 if ((n - name) < 0 || strcmp (n, NAME__MAIN)) 3186 continue; 3187 while (n != name) 3188 if (*--n != '_') 3189 continue; 3190 3191 main_sym = sym; 3192 } 3193 else 3194 { 3195 switch (is_ctor_dtor (name)) 3196 { 3197 case 1: 3198 add_to_list (&constructors, name); 3199 break; 3200 3201 case 2: 3202 add_to_list (&destructors, name); 3203 break; 3204 3205 default: /* not a constructor or destructor */ 3206 continue; 3207 } 3208 } 3209 3210 if (debug) 3211 fprintf (stderr, "\ttype = 0x%.4x, sc = 0x%.2x, flags = 0x%.8x, name = %.30s\n", 3212 sym->si_type, sym->si_sc_type, sym->si_flags, name); 3213 } 3214 } 3215 } 3216 3217 if (symbol_load_cmds == 0) 3218 fatal ("no symbol table found"); 3219 3220 /* Update the program file now, rewrite header and load commands. At present, 3221 we assume that there is enough space after the last load command to insert 3222 one more. Since the first section written out is page aligned, and the 3223 number of load commands is small, this is ok for the present. */ 3224 3225 if (rw) 3226 { 3227 load_union_t *load_map; 3228 size_t size; 3229 3230 if (cmd_strings == -1) 3231 fatal ("no cmd_strings found"); 3232 3233 /* Add __main to initializer list. 3234 If we are building a program instead of a shared library, do not 3235 do anything, since in the current version, you cannot do mallocs 3236 and such in the constructors. */ 3237 3238 if (main_sym != (symbol_info_t *) 0 3239 && ((hdr.moh_flags & MOH_EXECABLE_F) == 0)) 3240 add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION); 3241 3242 if (debug) 3243 fprintf (stderr, "\nUpdating header and load commands.\n\n"); 3244 3245 hdr.moh_n_load_cmds++; 3246 size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1)); 3247 3248 /* Create new load command map. */ 3249 if (debug) 3250 fprintf (stderr, "load command map, %d cmds, new size %ld.\n", 3251 (int)hdr.moh_n_load_cmds, (long)size); 3252 3253 load_map = (load_union_t *) xcalloc (1, size); 3254 load_map->map.ldc_header.ldci_cmd_type = LDC_CMD_MAP; 3255 load_map->map.ldc_header.ldci_cmd_size = size; 3256 load_map->map.lcm_ld_cmd_strings = cmd_strings; 3257 load_map->map.lcm_nentries = hdr.moh_n_load_cmds; 3258 load_array[hdr.moh_n_load_cmds-1].load = load_map; 3259 3260 offset = hdr.moh_first_cmd_off; 3261 for (i = 0; i < hdr.moh_n_load_cmds; i++) 3262 { 3263 load_map->map.lcm_map[i] = offset; 3264 if (load_array[i].load->hdr.ldci_cmd_type == LDC_CMD_MAP) 3265 hdr.moh_load_map_cmd_off = offset; 3266 3267 offset += load_array[i].load->hdr.ldci_cmd_size; 3268 } 3269 3270 hdr.moh_sizeofcmds = offset - MO_SIZEOF_RAW_HDR; 3271 3272 if (debug) 3273 print_header (&hdr); 3274 3275 /* Write header */ 3276 status = encode_mach_o_hdr (&hdr, obj, MO_SIZEOF_RAW_HDR); 3277 if (status != MO_HDR_CONV_SUCCESS) 3278 bad_header (status); 3279 3280 if (debug) 3281 fprintf (stderr, "writing load commands.\n\n"); 3282 3283 /* Write load commands */ 3284 offset = hdr.moh_first_cmd_off; 3285 for (i = 0; i < hdr.moh_n_load_cmds; i++) 3286 { 3287 load_union_t *load_hdr = load_array[i].load; 3288 size_t size = load_hdr->hdr.ldci_cmd_size; 3289 3290 if (debug) 3291 print_load_command (load_hdr, offset, i); 3292 3293 bcopy ((char *) load_hdr, (char *) (obj + offset), size); 3294 offset += size; 3295 } 3296 } 3297 3298 end_file (obj_file); 3299 3300 if (close (prog_fd)) 3301 fatal_perror ("closing %s", prog_name); 3302 3303 if (debug) 3304 fprintf (stderr, "\n"); 3305} 3306 3307 3308/* Add a function table to the load commands to call a function 3309 on initiation or termination of the process. */ 3310 3311static void 3312add_func_table (hdr_p, load_array, sym, type) 3313 mo_header_t *hdr_p; /* pointer to global header */ 3314 load_all_t *load_array; /* array of ptrs to load cmds */ 3315 symbol_info_t *sym; /* pointer to symbol entry */ 3316 int type; /* fntc_type value */ 3317{ 3318 /* Add a new load command. */ 3319 int num_cmds = ++hdr_p->moh_n_load_cmds; 3320 int load_index = num_cmds - 1; 3321 size_t size = sizeof (func_table_command_t) + sizeof (mo_addr_t); 3322 load_union_t *ptr = xcalloc (1, size); 3323 load_all_t *load_cmd; 3324 int i; 3325 3326 /* Set the unresolved address bit in the header to force the loader to be 3327 used, since kernel exec does not call the initialization functions. */ 3328 hdr_p->moh_flags |= MOH_UNRESOLVED_F; 3329 3330 load_cmd = &load_array[load_index]; 3331 load_cmd->load = ptr; 3332 load_cmd->section = (char *) 0; 3333 3334 /* Fill in func table load command. */ 3335 ptr->func.ldc_header.ldci_cmd_type = LDC_FUNC_TABLE; 3336 ptr->func.ldc_header.ldci_cmd_size = size; 3337 ptr->func.ldc_header.ldci_section_off = 0; 3338 ptr->func.ldc_header.ldci_section_len = 0; 3339 ptr->func.fntc_type = type; 3340 ptr->func.fntc_nentries = 1; 3341 3342 /* copy address, turn it from abs. address to (region,offset) if necessary. */ 3343 /* Is the symbol already expressed as (region, offset)? */ 3344 if ((sym->si_flags & SI_ABSOLUTE_VALUE_F) == 0) 3345 { 3346 ptr->func.fntc_entry_loc[i].adr_lcid = sym->si_value.def_val.adr_lcid; 3347 ptr->func.fntc_entry_loc[i].adr_sctoff = sym->si_value.def_val.adr_sctoff; 3348 } 3349 3350 /* If not, figure out which region it's in. */ 3351 else 3352 { 3353 mo_vm_addr_t addr = sym->si_value.abs_val; 3354 int found = 0; 3355 3356 for (i = 0; i < load_index; i++) 3357 { 3358 if (load_array[i].load->hdr.ldci_cmd_type == LDC_REGION) 3359 { 3360 region_command_t *region_ptr = &load_array[i].load->region; 3361 3362 if ((region_ptr->regc_flags & REG_ABS_ADDR_F) != 0 3363 && addr >= region_ptr->regc_addr.vm_addr 3364 && addr <= region_ptr->regc_addr.vm_addr + region_ptr->regc_vm_size) 3365 { 3366 ptr->func.fntc_entry_loc[0].adr_lcid = i; 3367 ptr->func.fntc_entry_loc[0].adr_sctoff = addr - region_ptr->regc_addr.vm_addr; 3368 found++; 3369 break; 3370 } 3371 } 3372 } 3373 3374 if (!found) 3375 fatal ("could not convert 0x%l.8x into a region", addr); 3376 } 3377 3378 if (debug) 3379 fprintf (stderr, 3380 "%s function, region %d, offset = %ld (0x%.8lx)\n", 3381 (type == FNTC_INITIALIZATION) ? "init" : "term", 3382 (int)ptr->func.fntc_entry_loc[i].adr_lcid, 3383 (long)ptr->func.fntc_entry_loc[i].adr_sctoff, 3384 (long)ptr->func.fntc_entry_loc[i].adr_sctoff); 3385 3386} 3387 3388 3389/* Print the global header for an OSF/rose object. */ 3390 3391static void 3392print_header (hdr_ptr) 3393 mo_header_t *hdr_ptr; 3394{ 3395 fprintf (stderr, "\nglobal header:\n"); 3396 fprintf (stderr, "\tmoh_magic = 0x%.8lx\n", hdr_ptr->moh_magic); 3397 fprintf (stderr, "\tmoh_major_version = %d\n", (int)hdr_ptr->moh_major_version); 3398 fprintf (stderr, "\tmoh_minor_version = %d\n", (int)hdr_ptr->moh_minor_version); 3399 fprintf (stderr, "\tmoh_header_version = %d\n", (int)hdr_ptr->moh_header_version); 3400 fprintf (stderr, "\tmoh_max_page_size = %d\n", (int)hdr_ptr->moh_max_page_size); 3401 fprintf (stderr, "\tmoh_byte_order = %d\n", (int)hdr_ptr->moh_byte_order); 3402 fprintf (stderr, "\tmoh_data_rep_id = %d\n", (int)hdr_ptr->moh_data_rep_id); 3403 fprintf (stderr, "\tmoh_cpu_type = %d\n", (int)hdr_ptr->moh_cpu_type); 3404 fprintf (stderr, "\tmoh_cpu_subtype = %d\n", (int)hdr_ptr->moh_cpu_subtype); 3405 fprintf (stderr, "\tmoh_vendor_type = %d\n", (int)hdr_ptr->moh_vendor_type); 3406 fprintf (stderr, "\tmoh_load_map_cmd_off = %d\n", (int)hdr_ptr->moh_load_map_cmd_off); 3407 fprintf (stderr, "\tmoh_first_cmd_off = %d\n", (int)hdr_ptr->moh_first_cmd_off); 3408 fprintf (stderr, "\tmoh_sizeofcmds = %d\n", (int)hdr_ptr->moh_sizeofcmds); 3409 fprintf (stderr, "\tmon_n_load_cmds = %d\n", (int)hdr_ptr->moh_n_load_cmds); 3410 fprintf (stderr, "\tmoh_flags = 0x%.8lx", (long)hdr_ptr->moh_flags); 3411 3412 if (hdr_ptr->moh_flags & MOH_RELOCATABLE_F) 3413 fprintf (stderr, ", relocatable"); 3414 3415 if (hdr_ptr->moh_flags & MOH_LINKABLE_F) 3416 fprintf (stderr, ", linkable"); 3417 3418 if (hdr_ptr->moh_flags & MOH_EXECABLE_F) 3419 fprintf (stderr, ", execable"); 3420 3421 if (hdr_ptr->moh_flags & MOH_EXECUTABLE_F) 3422 fprintf (stderr, ", executable"); 3423 3424 if (hdr_ptr->moh_flags & MOH_UNRESOLVED_F) 3425 fprintf (stderr, ", unresolved"); 3426 3427 fprintf (stderr, "\n\n"); 3428 return; 3429} 3430 3431 3432/* Print a short summary of a load command. */ 3433 3434static void 3435print_load_command (load_hdr, offset, number) 3436 load_union_t *load_hdr; 3437 size_t offset; 3438 int number; 3439{ 3440 mo_long_t type = load_hdr->hdr.ldci_cmd_type; 3441 char *type_str = (char *) 0; 3442 3443 switch (type) 3444 { 3445 case LDC_UNDEFINED: type_str = "UNDEFINED"; break; 3446 case LDC_CMD_MAP: type_str = "CMD_MAP"; break; 3447 case LDC_INTERPRETER: type_str = "INTERPRETER"; break; 3448 case LDC_STRINGS: type_str = "STRINGS"; break; 3449 case LDC_REGION: type_str = "REGION"; break; 3450 case LDC_RELOC: type_str = "RELOC"; break; 3451 case LDC_PACKAGE: type_str = "PACKAGE"; break; 3452 case LDC_SYMBOLS: type_str = "SYMBOLS"; break; 3453 case LDC_ENTRY: type_str = "ENTRY"; break; 3454 case LDC_FUNC_TABLE: type_str = "FUNC_TABLE"; break; 3455 case LDC_GEN_INFO: type_str = "GEN_INFO"; break; 3456 } 3457 3458 fprintf (stderr, 3459 "cmd %2d, sz: 0x%.2lx, coff: 0x%.3lx, doff: 0x%.6lx, dlen: 0x%.6lx", 3460 number, 3461 (long) load_hdr->hdr.ldci_cmd_size, 3462 (long) offset, 3463 (long) load_hdr->hdr.ldci_section_off, 3464 (long) load_hdr->hdr.ldci_section_len); 3465 3466 if (type_str == (char *) 0) 3467 fprintf (stderr, ", ty: unknown (%ld)\n", (long) type); 3468 3469 else if (type != LDC_REGION) 3470 fprintf (stderr, ", ty: %s\n", type_str); 3471 3472 else 3473 { 3474 char *region = ""; 3475 switch (load_hdr->region.regc_usage_type) 3476 { 3477 case REG_TEXT_T: region = ", .text"; break; 3478 case REG_DATA_T: region = ", .data"; break; 3479 case REG_BSS_T: region = ", .bss"; break; 3480 case REG_GLUE_T: region = ", .glue"; break; 3481#if defined (REG_RDATA_T) && defined (REG_SDATA_T) && defined (REG_SBSS_T) /*mips*/ 3482 case REG_RDATA_T: region = ", .rdata"; break; 3483 case REG_SDATA_T: region = ", .sdata"; break; 3484 case REG_SBSS_T: region = ", .sbss"; break; 3485#endif 3486 } 3487 3488 fprintf (stderr, ", ty: %s, vaddr: 0x%.8lx, vlen: 0x%.6lx%s\n", 3489 type_str, 3490 (long) load_hdr->region.regc_vm_addr, 3491 (long) load_hdr->region.regc_vm_size, 3492 region); 3493 } 3494 3495 return; 3496} 3497 3498 3499/* Fatal error when {en,de}code_mach_o_header fails. */ 3500 3501static void 3502bad_header (status) 3503 int status; 3504{ 3505 char *msg = (char *) 0; 3506 3507 switch (status) 3508 { 3509 case MO_ERROR_BAD_MAGIC: msg = "bad magic number"; break; 3510 case MO_ERROR_BAD_HDR_VERS: msg = "bad header version"; break; 3511 case MO_ERROR_BAD_RAW_HDR_VERS: msg = "bad raw header version"; break; 3512 case MO_ERROR_BUF2SML: msg = "raw header buffer too small"; break; 3513 case MO_ERROR_OLD_RAW_HDR_FILE: msg = "old raw header file"; break; 3514 case MO_ERROR_UNSUPPORTED_VERS: msg = "unsupported version"; break; 3515 } 3516 3517 if (msg == (char *) 0) 3518 fatal ("unknown {de,en}code_mach_o_hdr return value %d", status); 3519 else 3520 fatal ("%s", msg); 3521} 3522 3523 3524/* Read a file into a memory buffer. */ 3525 3526static struct file_info * 3527read_file (name, fd, rw) 3528 char *name; /* filename */ 3529 int fd; /* file descriptor */ 3530 int rw; /* read/write */ 3531{ 3532 struct stat stat_pkt; 3533 struct file_info *p = (struct file_info *) xcalloc (sizeof (struct file_info), 1); 3534#ifdef USE_MMAP 3535 static int page_size; 3536#endif 3537 3538 if (fstat (fd, &stat_pkt) < 0) 3539 fatal_perror ("fstat %s", name); 3540 3541 p->name = name; 3542 p->size = stat_pkt.st_size; 3543 p->rounded_size = stat_pkt.st_size; 3544 p->fd = fd; 3545 p->rw = rw; 3546 3547#ifdef USE_MMAP 3548 if (debug) 3549 fprintf (stderr, "mmap %s, %s\n", name, (rw) ? "read/write" : "read-only"); 3550 3551 if (page_size == 0) 3552 page_size = sysconf (_SC_PAGE_SIZE); 3553 3554 p->rounded_size = ((p->size + page_size - 1) / page_size) * page_size; 3555 p->start = mmap ((caddr_t) 0, 3556 (rw) ? p->rounded_size : p->size, 3557 (rw) ? (PROT_READ | PROT_WRITE) : PROT_READ, 3558 MAP_FILE | MAP_VARIABLE | MAP_SHARED, 3559 fd, 3560 0L); 3561 3562 if (p->start != (char *) 0 && p->start != (char *) -1) 3563 p->use_mmap = 1; 3564 3565 else 3566#endif /* USE_MMAP */ 3567 { 3568 long len; 3569 3570 if (debug) 3571 fprintf (stderr, "read %s\n", name); 3572 3573 p->use_mmap = 0; 3574 p->start = xmalloc (p->size); 3575 if (lseek (fd, 0L, SEEK_SET) < 0) 3576 fatal_perror ("lseek to 0 on %s", name); 3577 3578 len = read (fd, p->start, p->size); 3579 if (len < 0) 3580 fatal_perror ("read %s", name); 3581 3582 if (len != p->size) 3583 fatal ("read %ld bytes, expected %ld, from %s", len, p->size, name); 3584 } 3585 3586 return p; 3587} 3588 3589/* Do anything necessary to write a file back from memory. */ 3590 3591static void 3592end_file (ptr) 3593 struct file_info *ptr; /* file information block */ 3594{ 3595#ifdef USE_MMAP 3596 if (ptr->use_mmap) 3597 { 3598 if (ptr->rw) 3599 { 3600 if (debug) 3601 fprintf (stderr, "msync %s\n", ptr->name); 3602 3603 if (msync (ptr->start, ptr->rounded_size, MS_ASYNC)) 3604 fatal_perror ("msync %s", ptr->name); 3605 } 3606 3607 if (debug) 3608 fprintf (stderr, "munmap %s\n", ptr->name); 3609 3610 if (munmap (ptr->start, ptr->size)) 3611 fatal_perror ("munmap %s", ptr->name); 3612 } 3613 else 3614#endif /* USE_MMAP */ 3615 { 3616 if (ptr->rw) 3617 { 3618 long len; 3619 3620 if (debug) 3621 fprintf (stderr, "write %s\n", ptr->name); 3622 3623 if (lseek (ptr->fd, 0L, SEEK_SET) < 0) 3624 fatal_perror ("lseek to 0 on %s", ptr->name); 3625 3626 len = write (ptr->fd, ptr->start, ptr->size); 3627 if (len < 0) 3628 fatal_perror ("write %s", ptr->name); 3629 3630 if (len != ptr->size) 3631 fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name); 3632 } 3633 3634 free (ptr->start); 3635 } 3636 3637 free (ptr); 3638} 3639 3640#endif /* OBJECT_FORMAT_ROSE */ 3641