DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T c

⟦4ed2700dc⟧ TextFile

    Length: 4817 (0x12d1)
    Types: TextFile
    Names: »collect2.c«

Derivation

└─⟦a05ed705a⟧ Bits:30007078 DKUUG GNU 2/12/89
    └─⟦6f889378a⟧ »./g++-1.36.1.tar.Z« 
        └─⟦3aa9a3deb⟧ 
            └─⟦this⟧ »g++-1.36.1/collect2.c« 

TextFile

/* Build tables of static constructors and destructors and run ld. */

#include <stdio.h>

#ifdef convex

#define TEXT_SECTION_ASM_OP ".text"
#define DATA_SECTION_ASM_OP ".data"

#define ASM_GLOBALIZE_LABEL(FILE, LABEL) \
  fprintf (FILE, ".globl _%s\n", LABEL)

#define ASM_OUTPUT_LABEL(FILE, LABEL) \
  fprintf (FILE, "_%s:", LABEL)

#define ASM_OUTPUT_LABELREF(FILE, LABEL) \
  fprintf (FILE, "\tds.w _%s\n", LABEL)

#define ASM_OUTPUT_INT(FILE, INT) \
  fprintf (FILE, "\tds.w %d\n", INT)

#endif

#if defined (__GNUC__) || defined (sparc)
#define alloca __builtin_alloca
#endif

extern char *mktemp (char *template);

/* Linked lists of constructor and destructor names. */

struct id 
{
  char *name;
  struct id *next;
};

/* Main program. */

main (int argc, char *argv[])
{
  static char codexxx[] = "/tmp/codeXXXXXX";
  static char asxxx[] = "/tmp/asXXXXXX";
  char *codefile, *hookfile, hooksfile[40], hookofile[40];
  char *outfile = "a.out";
  char *arg, ldargs[1024], cmd[1024];
  FILE *inf, *outf;

  /* Make temp file names. */

  codefile = mktemp (codexxx);
  hookfile = mktemp (asxxx);
  sprintf (hooksfile, "%s.s", hookfile);
  sprintf (hookofile, "%s.o", hookfile);

  /* Parse arguments.  Remove output file spec, pass the rest to ld. */

  ldargs[0] = '\0';
  while (arg = *++argv)
    {
      if (! strcmp (arg, "-o"))
	outfile = *++argv;
      else
	{
	  strcat (ldargs, " ");
	  strcat (ldargs, arg);
	}
    }

  /* Load the program, searching all libraries.
     Use -r to save the output as a relocatable file.
     Examine the namelist with nm and search it for static constructors
     and destructors to call.
     Write the constructor and destructor tables to a .s file. */

  sprintf (cmd, "ld -r -o %s %s && nm -p %s", codefile, ldargs, codefile);

  if (! (inf = popen (cmd, "r")))
    fatal_perror ("Can't open pipe to ld");
  if (! (outf = fopen (hooksfile, "w")))
    fatal_perror ("Can't write %s", hooksfile);

  write_hooks (inf, outf);

  if (pclose (inf) || fclose (outf))
    fatal ("load failed");

  /* Assemble the constructor and destructor tables.
     Link the tables in with the rest of the program. */

  sprintf (cmd, "as -o %s %s && ld -o %s %s %s && rm %s %s %s",
	   hookofile, hooksfile, 
	   outfile, codefile, hookofile,
	   codefile, hooksfile, hookofile);
  exit (system (cmd));
}

/* Scan the name list of the loaded program for the symbols g++ uses
   for static constructors and destructors.  Write their addresses
   into tables which __main and exit will call.

   The constructor table __CTOR_LIST__ is an integer count followed by
   that many pointers to constructor functions.  The destructor table
   __DTOR_LIST__ is the same thing, followed by a zero word. */

write_hooks (FILE *inf, FILE *outf)
{
  char *p, buf[1024];
  struct id *newid;

  struct id *constructors = 0;
  struct id *destructors = 0;

  while (! feof (inf)) {

    /* Read a line of nm output and strip the trailing newline. */

    fgets (buf, sizeof buf, inf);
    p = buf + strlen (buf) - 1;
    if (*p == '\n')
      *p = '\0';

    /* If it contains a constructor or destructor name, add the name
       to the appropriate list. */

    for (p = buf; *p; p++)
      {
	while (*p && *p != '_')
	  p++;
	if (! strncmp (p, "_GLOBAL_$I$", 11))
	  {
	    newid = alloca (sizeof *newid);
	    newid->name = alloca (strlen (p) + 1);
	    strcpy (newid->name, p);
	    newid->next = constructors;
	    constructors = newid;
	    break;
	  }
	else if (! strncmp (p, "_GLOBAL_$D$", 11))
	  {
	    newid = alloca (sizeof *newid);
	    newid->name = alloca (strlen (p) + 1);
	    strcpy (newid->name, p);
	    newid->next = destructors;
	    destructors = newid;
	    break;
	  }
      }
  }

  /* Write the tables. */

  fprintf (outf, "%s\n", TEXT_SECTION_ASM_OP);
  ASM_GLOBALIZE_LABEL (outf, "__CTOR_LIST__");
  ASM_OUTPUT_LABEL (outf, "__CTOR_LIST__");
  ASM_OUTPUT_INT (outf, count_list (constructors));
  write_list (outf, constructors);
  
  fprintf (outf, "%s\n", DATA_SECTION_ASM_OP);
  ASM_GLOBALIZE_LABEL (outf, "__DTOR_LIST__");
  ASM_OUTPUT_LABEL (outf, "__DTOR_LIST__");
  ASM_OUTPUT_INT (outf, count_list (destructors));
  write_list (outf, destructors);
  ASM_OUTPUT_INT (outf, 0);
}
 
/* Length of list LIST. */

count_list (struct id *list)
{
  int count = 0;
  while (list)
    {
      count++;
      list = list->next;
    }
  return count;
}

/* Write the names on list LIST, in reverse order. */

write_list (FILE *outf, struct id *list)
{
  if (! list)
    return;
  write_list (outf, list->next);
  ASM_OUTPUT_LABELREF (outf, list->name);
}

/* Die when sys call fails. */

fatal_perror (string, arg)
{
  char buf[80];
  sprintf (buf, string, arg);
  perror (buf);
  exit (1);
}

/* Just die. */

fatal (string)
{
  fprintf (stderr, string);
  exit (1);
}