home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / gnu / g__src1 / collect.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-23  |  13.6 KB  |  590 lines

  1. /* Output tables which say what global initializers need
  2.    to be called at program startup, and what global destructors
  3.    need to be called at program termination, for GNU C++ compiler.
  4.    Copyright (C) 1987 Free Software Foundation, Inc.
  5.    Hacked by Michael Tiemann (tiemann@mcc.com)
  6.    COFF Changes by Dirk Grunwald (grunwald@flute.cs.uiuc.edu)
  7.  
  8. This file is part of GNU CC.
  9.  
  10. GNU CC is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY.  No author or distributor
  12. accepts responsibility to anyone for the consequences of using it
  13. or for whether it serves any particular purpose or works at all,
  14. unless he says so in writing.  Refer to the GNU CC General Public
  15. License for full details.
  16.  
  17. Everyone is granted permission to copy, modify and redistribute
  18. GNU CC, but only under the conditions described in the
  19. GNU CC General Public License.   A copy of this license is
  20. supposed to have been given to you along with GNU CC so you
  21. can know your rights and responsibilities.  It should be in a
  22. file named COPYING.  Among other things, the copyright notice
  23. and this notice must be preserved on all copies.  */
  24.  
  25.  
  26. /* This file contains all the code needed for the program `collect'.
  27.  
  28.    `collect' is run on all object files that are processed
  29.    by GNU C++, to create a list of all the file-level
  30.    initialization and destruction that need to be performed.
  31.    It generates an assembly file which holds the tables
  32.    which are walked by the global init and delete routines.
  33.    The format of the tables are an integer length,
  34.    followed by the list of function pointers for the
  35.    routines to be called.
  36.  
  37.    Constructors are called in the order they are laid out
  38.    in the table.  Destructors are called in the reverse order
  39.    of the way they lie in the table.  */
  40.  
  41. #include "config.h"
  42.  
  43. /*
  44.  *    This may not always be true, but I can't find another flag
  45.  *    to use.
  46.  */
  47. #ifdef SDB_DEBUGGING_INFO
  48. #define COFF
  49. #define UMAX    /* need to define this conditionally */
  50. #endif
  51.  
  52. /* For this file, some special macros.  These should be merged
  53.    into tm.h some time.  */
  54.  
  55. #undef ASM_OUTPUT_INT
  56. #undef ASM_OUTPUT_LABELREF
  57.  
  58. #if defined(COFF)
  59.  
  60. #define ASM_OUTPUT_INT(FILE,VALUE)  \
  61.   fprintf (FILE, "\t.double %d\n", VALUE)
  62.  
  63. #define ASM_OUTPUT_PTR_INT_SUM(FILE,PTRNAME,VALUE)    \
  64.   fprintf (FILE, "\t.double _%s+%d\n", PTRNAME, VALUE)
  65.  
  66. #define ASM_OUTPUT_LABELREF(FILE,NAME)    \
  67.   fprintf (FILE, "\t.double _%s\n", NAME);
  68.  
  69.  
  70. #else
  71.  
  72. #if    defined(hp9000s300)
  73. #define ASM_OUTPUT_INT(FILE,VALUE)  \
  74.   fprintf (FILE, "\tlong %d\n", VALUE)
  75. #define ASM_OUTPUT_PTR_INT_SUM(FILE,PTRNAME,VALUE)    \
  76.   fprintf (FILE, "\tlong _%s+%d\n", PTRNAME, VALUE)
  77. #define ASM_OUTPUT_LABELREF(FILE,NAME)    \
  78.   fprintf (FILE, "\tlong _%s\n", NAME);
  79.  
  80.  
  81. #else
  82. #define ASM_OUTPUT_INT(FILE,VALUE)  \
  83.   fprintf (FILE, "\t.long %d\n", VALUE)
  84.  
  85. #define ASM_OUTPUT_PTR_INT_SUM(FILE,PTRNAME,VALUE)    \
  86.   fprintf (FILE, "\t.long _%s+%d\n", PTRNAME, VALUE)
  87.  
  88. #define ASM_OUTPUT_LABELREF(FILE,NAME)    \
  89.   fprintf (FILE, "\t.long _%s\n", NAME);
  90. #endif /* hp9000s300 */
  91. #endif /* COFF */
  92.  
  93. #include <sys/types.h>
  94. #include <sys/stat.h>
  95.  
  96. #include <stdio.h>
  97. #include <a.out.h>
  98. #include <ar.h>
  99.  
  100. #ifdef UMAX
  101. #include <sgs.h>
  102. #endif
  103.  
  104. extern int xmalloc ();
  105. extern void free ();
  106.  
  107. #ifndef CTOR_TABLE_NAME
  108. #define CTOR_TABLE_NAME "__CTOR_LIST__"
  109. #endif
  110.  
  111. #ifndef DTOR_TABLE_NAME
  112. #define DTOR_TABLE_NAME "__DTOR_LIST__"
  113. #endif
  114.  
  115. enum error_code { OK, BAD_MAGIC, NO_NAMELIST,
  116.           FOPEN_ERROR, FREAD_ERROR, FWRITE_ERROR,
  117.           RANDOM_ERROR, };
  118.  
  119. enum error_code process ();
  120. enum error_code process_a (), process_o ();
  121. enum error_code coalesce ();
  122. void assemble_name ();
  123.  
  124. /* Files for holding the assembly code for table of constructor
  125.    function pointer addresses and list of destructor
  126.    function pointer addresses.  */
  127. static FILE *outfile;
  128.  
  129. /* Default outfile name, or take name from argv with -o option.  */
  130. static char *outfile_name = "a.out";
  131.  
  132. /* The table of destructors elements must be laid out in the reverse
  133.    order that the table of constructors is laid out.  Thus,
  134.    is easiest to just cons up a list of destructors to call,
  135.    and then write them out when they have all been collected.  */
  136.  
  137. struct dtor_list_elem
  138. {
  139.   struct dtor_list_elem *next;
  140.   char *name;
  141. } *dtor_chain;
  142.  
  143. main (argc, argv)
  144.      int argc;
  145.      char *argv[];
  146. {
  147.   int i, nerrs = 0;
  148.   enum error_code code;
  149.   FILE *fp;
  150.   char *main_input_filename;
  151.  
  152.   if (argc > 2 && !strcmp (argv[1], "-o"))
  153.     {
  154.       outfile_name = argv[2];
  155.       i = 3;
  156.     }
  157.   else
  158.     i = 1;
  159.  
  160.   if ((outfile = fopen (outfile_name, "w")) == NULL)
  161.     {
  162.       perror ("collect");
  163.       exit (-1);
  164.     }
  165.  
  166.   main_input_filename = outfile_name;
  167.   ASM_FILE_START(outfile);
  168.  
  169.   fprintf (outfile, "%s\n", TEXT_SECTION_ASM_OP);
  170.   ASM_GLOBALIZE_LABEL (outfile, CTOR_TABLE_NAME);
  171.   ASM_OUTPUT_LABEL (outfile, CTOR_TABLE_NAME);
  172.  
  173.   for (; i < argc; i++)
  174.     {
  175.       char buf[80];
  176.  
  177.       /* This is a library, skip it.  */
  178.       if (argv[i][0] == '-' && argv[i][1] == 'l')
  179.     continue;
  180.  
  181.       if ((fp = fopen (argv[i], "r")) == NULL)
  182.     {
  183.       sprintf (buf, "collect `%s'", argv[i]);
  184.       perror (buf);
  185.       exit (-1);
  186.     }
  187.  
  188.       switch (code = process (fp, argv[i]))
  189.     {
  190.     case OK:
  191.       break;
  192.  
  193.     case BAD_MAGIC:
  194.       fprintf (stderr, "file `%s' has a bad magic number for collect\n",
  195.            argv[i]);
  196.       exit (-1);
  197.  
  198.     case NO_NAMELIST:
  199.       fprintf (stderr, "file `%s' has a no namelist for collect\n",
  200.            argv[i]);
  201.       exit (-1);
  202.  
  203.     case RANDOM_ERROR:
  204.       fprintf (stderr, "random error while processing file `%s':\n",
  205.            argv[i]);
  206.       perror ("collect");
  207.       exit (-1);
  208.  
  209.     case FOPEN_ERROR:
  210.       fprintf (stderr, "fopen(3S) error while processing file `%s' in collect\n",
  211.            argv[i]);
  212.       exit (-1);
  213.  
  214.     case FREAD_ERROR:
  215.       fprintf (stderr, "fread(3S) error while processing file `%s' in collect\n",
  216.            argv[i]);
  217.       exit (-1);
  218.  
  219.     case FWRITE_ERROR:
  220.       fprintf (stderr, "fwrite(3S) error while processing file `%s' in collect\n",
  221.            argv[i]);
  222.       exit (-1);
  223.  
  224.     default:
  225.       abort ();
  226.     }
  227.  
  228.       fclose (fp);
  229.  
  230.     }
  231.  
  232.   switch (code = coalesce ())
  233.     {
  234.     case OK:
  235.       fclose (outfile);
  236.       exit (0);
  237.     case FREAD_ERROR:
  238.       perror ("fread(3S) failed in collect, at end");
  239.       break;
  240.     case FWRITE_ERROR:
  241.       perror ("fwrite(3S) failed in collect, at end");
  242.       break;
  243.     case FOPEN_ERROR:
  244.       perror ("fopen(3S) failed in collect, at end");
  245.       break;
  246.     case RANDOM_ERROR:
  247.       fprintf (stderr, "random error in collect, at end");
  248.       break;
  249.     }
  250.   exit (-1);
  251. }
  252.  
  253. #ifdef COFF
  254.  
  255. #include <ldfcn.h>
  256.  
  257. enum error_code
  258. process (fp, filename)
  259.      FILE *fp;
  260.      char *filename;
  261. {
  262.   LDFILE *ldptr;
  263.   do {
  264.     if ((ldptr = ldopen(filename, ldptr)) != NULL ) {
  265.       
  266.       if (!ISCOFF( HEADER(ldptr).f_magic ) ) {
  267.     return BAD_MAGIC;
  268.       }
  269.       else {
  270.     int symbols = HEADER(ldptr).f_nsyms;
  271.     int symindex;
  272.     
  273.     for (symindex = 0; symindex < symbols; symindex++ ) {
  274.  
  275.       SYMENT symbol;
  276.       char *symbol_name;
  277.       extern char *ldgetname();
  278.       
  279.       ldtbread(ldptr, symindex, &symbol);
  280.       symbol_name = ldgetname(ldptr, &symbol);
  281.       
  282.       if (! strncmp ("__GLOBAL_$", symbol_name, 10)) {
  283.         
  284.         if (symbol_name[10] == 'I') {
  285.           ASM_OUTPUT_LABELREF (outfile, symbol_name+1);
  286.         }
  287.         else {
  288.           struct dtor_list_elem *new
  289.         = (struct dtor_list_elem *)
  290.           xmalloc (sizeof (struct dtor_list_elem));
  291.           new->next = dtor_chain;
  292.           new->name = (char *)xmalloc (strlen (symbol_name));
  293.           strcpy (new->name, symbol_name+1);
  294.           dtor_chain = new;
  295.         }
  296.       }
  297.     }
  298.       }
  299.     }
  300.     else {
  301.       return( RANDOM_ERROR );
  302.     }
  303.   } while ( ldclose(ldptr) == FAILURE ) ;
  304.   return ( OK );
  305. }
  306.  
  307. /****** taken from sdbout.c ******/
  308.  
  309.  
  310. /* Tell the assembler the source file name.
  311.    On systems that use SDB, this is done whether or not -g,
  312.    so it is called by ASM_FILE_START.
  313.  
  314.    ASM_FILE is the assembler code output file,
  315.    INPUT_NAME is the name of the main input file.  */
  316.  
  317. /* void */
  318. sdbout_filename (asm_file, input_name)
  319.      FILE *asm_file;
  320.      char *input_name;
  321. {
  322.   int len = strlen (input_name);
  323.   char *na = input_name + len;
  324.  
  325.   /* NA gets INPUT_NAME sans directory names.  */
  326.   while (na > input_name)
  327.     {
  328.       if (na[-1] == '/')
  329.     break;
  330.       na--;
  331.     }
  332.  
  333. #ifdef ASM_OUTPUT_SOURCE_FILENAME
  334.   ASM_OUTPUT_SOURCE_FILENAME (asm_file, na);
  335. #else
  336.   fprintf (asm_file, "\t.file\t\"%s\"\n", na);
  337. #endif
  338. }
  339.  
  340. #else
  341.  
  342. /* Figure out the type of file we need to process.
  343.    Currently, only .o and .a formats are acceptable.  */
  344. enum error_code
  345. process (fp, filename)
  346.      FILE *fp;
  347.      char *filename;
  348. {
  349.   struct stat file_stat;
  350.   union
  351.     {
  352.       char ar_form[SARMAG];
  353.       struct exec a_out_form;
  354.     } header;
  355.   int size;
  356.  
  357.   if (fstat (fp->_file, &file_stat))
  358.     return RANDOM_ERROR;
  359.  
  360.   size = file_stat.st_size;
  361.  
  362.   if (fread (header.ar_form, SARMAG, 1, fp) < 1)
  363.     return RANDOM_ERROR;
  364.  
  365.   if (strncmp (ARMAG, header.ar_form, SARMAG))
  366.     {
  367.       fseek (fp, 0, 0);
  368.       if (fread (&header.a_out_form, sizeof (struct exec), 1, fp) < 1)
  369.     return RANDOM_ERROR;
  370.  
  371.       if (N_BADMAG (header.a_out_form))
  372.     return BAD_MAGIC;
  373.  
  374.       return process_o (fp, &header.a_out_form, size);
  375.     }
  376.   return process_a (fp);
  377. }
  378.  
  379. enum error_code
  380. process_o (fp, header, size)
  381.      FILE *fp;
  382.      struct exec *header;
  383.      int size;
  384. {
  385.   int symoff, symend;
  386. #ifndef hp9000s300
  387.   struct nlist *nelem, *nelems, *nend;
  388.   char *strtab;
  389. #else
  390.   struct nlist_ *nelem, *nelems, *nend;
  391. #endif /* hp9000s300 */
  392.  
  393.   if (N_BADMAG (*header))
  394.     return BAD_MAGIC;
  395.  
  396. #ifndef hp9000s300
  397.   symoff = N_SYMOFF (*header);
  398.   symend = N_STROFF (*header);
  399. #else
  400.   symoff = LESYM_OFFSET (*header);
  401.   symend = DNTT_OFFSET (*header);
  402. #endif /* hp9000s300 */
  403.   if (symoff == symend)
  404.     return NO_NAMELIST;
  405.   fseek (fp, symoff - sizeof (struct exec), 1);
  406. #ifndef hp9000s300
  407.   nelems = (struct nlist *)alloca (symend - symoff);
  408. #else
  409.   nelems = (struct nlist_ *)alloca (symend - symoff);
  410. #endif /* hp9000s300 */
  411.   if (fread (nelems, sizeof (char), symend - symoff, fp) < symend - symoff)
  412.     return FREAD_ERROR;
  413.  
  414. #ifndef hp9000s300
  415.   strtab = (char *)alloca ((char *)size - (char *)symend);
  416.   if (fread (strtab, sizeof (char), (char *)size - (char *)symend, fp)
  417.       < ((char *)size - (char *)symend) * sizeof (char))
  418.     return FREAD_ERROR;
  419.  
  420.   nend = (struct nlist *)((char *)nelems + symend - symoff);
  421.   for (nelem = nelems; nelem < nend; nelem++)
  422. #else
  423.   nend = (struct nlist_ *)((char *)nelems + symend - symoff);
  424.   for (nelem = nelems; nelem < nend; )
  425. #endif /* hp9000s300 */
  426.     {
  427. #ifndef hp9000s300
  428.       int strindex = nelem->n_un.n_strx;
  429. #else
  430.       int symlen = nelem->n_length;
  431.       char p[255];
  432.       memcpy(p, (char *) (++nelem), symlen);
  433.       p[symlen]='\0';
  434.      
  435.       /* printf("'%s'\n",p);   */
  436. #endif /* hp9000s300 */
  437.  
  438. #ifndef hp9000s300
  439.       if (strindex)
  440. #else
  441.       nelem   = (struct nlist_ *)((char *)nelem + symlen);
  442.       
  443.       if (symlen)
  444. #endif /* hp9000s300 */
  445.     {
  446. #ifndef hp9000s300
  447.       char *p = strtab+strindex;
  448. #endif /* hp9000s300 */
  449.  
  450.       if (! strncmp ("__GLOBAL_$", p, 10))
  451.         {
  452.           if (p[10] == 'I')
  453.         {
  454.           ASM_OUTPUT_LABELREF (outfile, p+1);
  455.         }
  456.           else
  457.         {
  458.           struct dtor_list_elem *new = (struct dtor_list_elem *)xmalloc (sizeof (struct dtor_list_elem));
  459.           new->next = dtor_chain;
  460.           new->name = (char *)xmalloc (strlen (p));
  461.           strcpy (new->name, p+1);
  462.           dtor_chain = new;
  463.         }
  464.     }
  465.     }
  466.   return OK;
  467. }
  468.  
  469. enum error_code
  470. process_a (fp)
  471.      FILE *fp;
  472. {
  473.   struct ar_hdr header;
  474.   struct exec exec_header;
  475.   int size;
  476.   enum error_code code;
  477.  
  478.   while (! feof (fp))
  479.     {
  480.       char c;
  481. #ifdef hp9000s300
  482.       int curpos;
  483. #endif /* hp9000s300 */
  484.  
  485.       if (fread (&header, sizeof (struct ar_hdr), 1, fp) < 1)
  486.     return RANDOM_ERROR;
  487.  
  488.       size = atoi (header.ar_size);
  489. #ifdef hp9000s300
  490.       curpos = ftell(fp);
  491. #endif /* hp9000s300 */
  492.  
  493. #ifndef hp9000s300
  494.       if (fread (&exec_header, sizeof (struct exec), 1, fp) < 1)
  495.     return RANDOM_ERROR;
  496. #else
  497.       /* if the name starts with /, it's an index file */
  498.       if (header.ar_name[0] != '/') {
  499.       
  500.         if (fread (&exec_header, sizeof (struct exec), 1, fp) < 1)
  501.       return RANDOM_ERROR;
  502. #endif /* hp9000s300 */
  503.  
  504.       code = process_o (fp, &exec_header, size);
  505.       if (code != OK)
  506.     return code;
  507. #ifdef hp9000s300
  508.       } 
  509.       
  510.       if (fseek(fp,(long) curpos + size,0))
  511.     return RANDOM_ERROR;
  512. #endif /* hp9000s300 */
  513.       if ((c = getc (fp)) == '\n')
  514.     ;
  515.       else
  516.     ungetc (c, fp);
  517.       c = getc (fp);
  518.       if (c != EOF)
  519.     ungetc (c, fp);
  520.     }
  521.   return OK;
  522. }
  523. #endif
  524.  
  525. enum error_code
  526. coalesce ()
  527. {
  528.   int dtor_offset;
  529.  
  530.   /* NULL-terminate the list of constructors.  */
  531.   ASM_OUTPUT_INT (outfile, 0);
  532.  
  533.   /* Now layout the destructors.  */
  534.   fprintf (outfile, "%s\n", DATA_SECTION_ASM_OP);
  535.   ASM_GLOBALIZE_LABEL (outfile, DTOR_TABLE_NAME);
  536.   ASM_OUTPUT_LABEL (outfile, DTOR_TABLE_NAME);
  537.   if (dtor_chain)
  538.     {
  539.       ASM_OUTPUT_PTR_INT_SUM (outfile, DTOR_TABLE_NAME, sizeof (int));
  540.       dtor_offset = 3 * sizeof (int);
  541.       while (dtor_chain)
  542.     {
  543.       if (dtor_chain->next)
  544.         ASM_OUTPUT_PTR_INT_SUM (outfile, DTOR_TABLE_NAME, dtor_offset);
  545.       else
  546.         ASM_OUTPUT_INT (outfile, 0);
  547.       dtor_offset += 2 * sizeof (int);
  548.  
  549.       ASM_OUTPUT_LABELREF (outfile, dtor_chain->name);
  550.       dtor_chain = dtor_chain->next;
  551.     }
  552.     }
  553.   ASM_OUTPUT_INT (outfile, 0);
  554.  
  555.   fclose (outfile);
  556.   return OK;
  557. }
  558.  
  559. /* Output to FILE a reference to the assembler name of a C-level name NAME.
  560.    If NAME starts with a *, the rest of NAME is output verbatim.
  561.    Otherwise NAME is transformed in an implementation-defined way
  562.    (usually by the addition of an underscore).
  563.    Many macros in the tm file are defined to call this function.
  564.  
  565.    Swiped from `varasm.c'  */
  566.  
  567. void
  568. assemble_name (file, name)
  569.      FILE *file;
  570.      char *name;
  571. {
  572.   if (name[0] == '*')
  573.     fputs (&name[1], file);
  574.   else
  575.     fprintf (file, "_%s", name);
  576. }
  577.  
  578. int
  579. xmalloc (size)
  580.      int size;
  581. {
  582.   int result = malloc (size);
  583.   if (! result)
  584.     {
  585.       fprintf (stderr, "Virtual memory exhausted\n");
  586.       exit (-1);
  587.     }
  588.   return result;
  589. }
  590.