home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 7
/
FreshFishVol7.bin
/
bbs
/
gnu
/
gcc-2.3.3-src.lha
/
GNU
/
src
/
amiga
/
gcc-2.3.3
/
collect2.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-02-06
|
48KB
|
1,953 lines
/* Collect static initialization info into data structures
that can be traversed by C++ initialization and finalization
routines.
Copyright (C) 1992 Free Software Foundation, Inc.
Contributed by Chris Smith (csmith@convex.com).
Heavily modified by Michael Meissner (meissner@osf.org),
Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com).
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Build tables of static constructors and destructors and run ld. */
#include <sys/types.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <sys/file.h>
#include <sys/stat.h>
#ifdef NO_WAIT_H
#include <sys/wait.h>
#endif
#ifndef errno
extern int errno;
#endif
#define COLLECT
#include "config.h"
#ifndef __STDC__
#define generic char
#define const
#else
#define generic void
#endif
#ifdef USG
#define vfork fork
#endif
#ifndef R_OK
#define R_OK 4
#define W_OK 2
#define X_OK 1
#endif
/* On MSDOS, write temp files in current dir
because there's no place else we can expect to use. */
#if __MSDOS__
#ifndef P_tmpdir
#define P_tmpdir "./"
#endif
#endif
/* On certain systems, we have code that works by scanning the object file
directly. But this code uses system-specific header files and library
functions, so turn it off in a cross-compiler. */
#ifdef CROSS_COMPILE
#undef OBJECT_FORMAT_COFF
#undef OBJECT_FORMAT_ROSE
#endif
/* If we can't use a special method, use the ordinary one:
run nm to find what symbols are present.
In a cross-compiler, this means you need a cross nm,
but that isn't quite as unpleasant as special headers. */
#if !defined (OBJECT_FORMAT_COFF) && !defined (OBJECT_FORMAT_ROSE)
#define OBJECT_FORMAT_NONE
#endif
#ifdef OBJECT_FORMAT_COFF
#include <a.out.h>
#include <ar.h>
#ifdef UMAX
#include <sgs.h>
#endif
#ifdef _AIX
#define ISCOFF(magic) \
((magic) == U802WRMAGIC || (magic) == U802ROMAGIC || (magic) == U802TOCMAGIC)
#endif
/* Many versions of ldfcn.h define these. */
#ifdef FREAD
#undef FREAD
#undef FWRITE
#endif
#include <ldfcn.h>
/* Mips-news overrides this macro. */
#ifndef MY_ISCOFF
#define MY_ISCOFF(X) ISCOFF (X)
#endif
#endif /* OBJECT_FORMAT_COFF */
#ifdef OBJECT_FORMAT_ROSE
#ifdef _OSF_SOURCE
#define USE_MMAP
#endif
#ifdef USE_MMAP
#include <sys/mman.h>
#endif
#include <unistd.h>
#include <mach_o_format.h>
#include <mach_o_header.h>
#include <mach_o_vals.h>
#include <mach_o_types.h>
#endif /* OBJECT_FORMAT_ROSE */
#ifdef OBJECT_FORMAT_NONE
/* Default flags to pass to nm. */
#ifndef NM_FLAGS
#define NM_FLAGS "-p"
#endif
#endif /* OBJECT_FORMAT_NONE */
/* Linked lists of constructor and destructor names. */
struct id
{
struct id *next;
int sequence;
char name[1];
};
struct head
{
struct id *first;
struct id *last;
int number;
};
/* Enumeration giving which pass this is for scanning the program file. */
enum pass {
PASS_FIRST, /* without constructors */
PASS_SECOND /* with constructors linked in */
};
#ifndef NO_SYS_SIGLIST
extern char *sys_siglist[];
#endif
extern char *version_string;
static int vflag; /* true if -v */
static int rflag; /* true if -r */
static int strip_flag; /* true if -s */
static int debug; /* true if -debug */
static int temp_filename_length; /* Length of temp_filename */
static char *temp_filename; /* Base of temp filenames */
static char *c_file; /* <xxx>.c for constructor/destructor list. */
static char *o_file; /* <xxx>.o for constructor/destructor list. */
static char *nm_file_name; /* pathname of nm */
static char *strip_file_name; /* pathname of strip */
static struct head constructors; /* list of constructors found */
static struct head destructors; /* list of destructors found */
extern char *getenv ();
extern char *mktemp ();
static void add_to_list ();
static void scan_prog_file ();
static void fork_execute ();
static void do_wait ();
static void write_c_file ();
static void my_exit ();
static void handler ();
static void maybe_unlink ();
static void choose_temp_base ();
generic *xcalloc ();
generic *xmalloc ();
extern char *index ();
extern char *rindex ();
#ifdef NO_DUP2
dup2 (oldfd, newfd)
int oldfd;
int newfd;
{
int fdtmp[256];
int fdx = 0;
int fd;
if (oldfd == newfd)
return 0;
close (newfd);
while ((fd = dup (oldfd)) != newfd) /* good enough for low fd's */
fdtmp[fdx++] = fd;
while (fdx > 0)
close (fdtmp[--fdx]);
}
#endif
char *
my_strerror (e)
int e;
{
extern char *sys_errlist[];
extern int sys_nerr;
static char buffer[30];
if (!e)
return "";
if (e > 0 && e < sys_nerr)
return sys_errlist[e];
sprintf (buffer, "Unknown error %d", e);
return buffer;
}
/* Delete tempfiles and exit function. */
static void
my_exit (status)
int status;
{
if (c_file != 0 && c_file[0])
maybe_unlink (c_file);
if (o_file != 0 && o_file[0])
maybe_unlink (o_file);
exit (status);
}
/* Die when sys call fails. */
static void
fatal_perror (string, arg1, arg2, arg3)
char *string;
{
int e = errno;
fprintf (stderr, "collect: ");
fprintf (stderr, string, arg1, arg2, arg3);
fprintf (stderr, ": %s\n", my_strerror (e));
my_exit (1);
}
/* Just die. */
static void
fatal (string, arg1, arg2, arg3)
char *string;
{
fprintf (stderr, "collect: ");
fprintf (stderr, string, arg1, arg2, arg3);
fprintf (stderr, "\n");
my_exit (1);
}
/* Write error message. */
static void
error (string, arg1, arg2, arg3, arg4)
char *string;
{
fprintf (stderr, "collect: ");
fprintf (stderr, string, arg1, arg2, arg3, arg4);
fprintf (stderr, "\n");
}
/* In case obstack is linked in, and abort is defined to fancy_abort,
provide a default entry. */
void
fancy_abort ()
{
fatal ("internal error");
}
static void
handler (signo)
int signo;
{
if (c_file[0])
maybe_unlink (c_file);
if (o_file[0])
maybe_unlink (o_file);
signal (signo, SIG_DFL);
kill (getpid (), signo);
}
generic *
xcalloc (size1, size2)
int size1, size2;
{
generic *ptr = (generic *) calloc (size1, size2);
if (ptr)
return ptr;
fatal ("out of memory");
return (generic *)0;
}
generic *
xmalloc (size)
int size;
{
generic *ptr = (generic *) malloc (size);
if (ptr)
return ptr;
fatal ("out of memory");
return (generic *)0;
}
/* Make a copy of a string INPUT with size SIZE. */
char *
savestring (input, size)
char *input;
int size;
{
char *output = (char *) xmalloc (size + 1);
bcopy (input, output, size);
output[size] = 0;
return output;
}
/* Decide whether the given symbol is:
a constructor (1), a destructor (2), or neither (0). */
static int
is_ctor_dtor (s)
char *s;
{
struct names { char *name; int len; int ret; int two_underscores; };
register struct names *p;
register int ch;
register char *orig_s = s;
static struct names special[] = {
#ifdef NO_DOLLAR_IN_LABEL
{ "GLOBAL_.I.", sizeof ("GLOBAL_.I.")-1, 1, 0 },
{ "GLOBAL_.D.", sizeof ("GLOBAL_.D.")-1, 2, 0 },
#else
{ "GLOBAL_$I$", sizeof ("GLOBAL_$I$")-1, 1, 0 },
{ "GLOBAL_$D$", sizeof ("GLOBAL_$I$")-1, 2, 0 },
#endif
#ifdef CFRONT_LOSSAGE /* Don't collect cfront initialization functions.
cfront has its own linker procedure to collect them;
if collect2 gets them too, they get collected twice
when the cfront procedure is run and the compiler used
for linking happens to be GCC. */
{ "sti__", sizeof ("sti__")-1, 1, 1 },
{ "std__", sizeof ("std__")-1, 2, 1 },
#endif