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