Make collect demangle

From-SVN: r9573
This commit is contained in:
Jason Merrill 1995-05-04 21:25:31 +00:00
parent 1a62528312
commit a31844688a
4 changed files with 3309 additions and 76 deletions

View File

@ -1034,16 +1034,31 @@ ld: collect2
ln collect2$(exeext) ld$(exeext) > /dev/null 2>&1 \
|| cp collect2$(exeext) ld$(exeext)
collect2 : collect2.o version.o $(LIBDEPS)
collect2 : collect2.o cplus-dem.o underscore.o version.o $(LIBDEPS)
# Don't try modifying collect2 (aka ld) in place--it might be linking this.
-rm -f collect2
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o collect2 collect2.o version.o $(LIBS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o collect2 collect2.o cplus-dem.o \
underscore.o version.o $(LIBS)
collect2.o : collect2.c $(CONFIG_H) gstab.h
collect2.o : collect2.c $(CONFIG_H) gstab.h obstack.h demangle.h
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-DTARGET_MACHINE=\"$(target)\" \
-DTARGET_MACHINE=\"$(target)\" $(MAYBE_USE_COLLECT2) \
-c `echo $(srcdir)/collect2.c | sed 's,^\./,,'`
cplus-dem.o: cplus-dem.c demangle.h
underscore.c: $(GCC_PASSES)
echo "int xxy_us_dummy;" >dummy.c
$(GCC_FOR_TARGET) -S dummy.c
echo '/*WARNING: This file is automatically generated!*/' >underscore.t
if grep _xxy_us_dummy dummy.s > /dev/null ; then \
echo "int prepends_underscore = 1;" >>underscore.t; \
else \
echo "int prepends_underscore = 0;" >>underscore.t; \
fi
$(srcdir)/move-if-change underscore.t underscore.c
-rm -f dummy.c dummy.s
# Objective C language specific files.
objc-parse.o : $(srcdir)/objc-parse.c $(CONFIG_H) $(TREE_H) c-lex.h \

View File

@ -55,13 +55,16 @@ char *strerror();
#define COLLECT
#include "config.h"
#include "demangle.h"
#ifndef __STDC__
#define generic char
#include "obstack.h"
/* Obstack allocation and deallocation routines. */
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
#if !defined (__STDC__) && !defined (const)
#define const
#else
#define generic void
#endif
#ifdef USG
@ -193,9 +196,15 @@ char *strerror();
#define SYMBOL__MAIN __main
#endif
#if defined (LDD_SUFFIX) || defined (SUNOS4_SHARED_LIBRARIES)
#if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES
#define SCAN_LIBRARIES
#endif
#ifdef USE_COLLECT2
int do_collecting = 1;
#else
int do_collecting = 0;
#endif
/* Linked lists of constructor and destructor names. */
@ -228,11 +237,11 @@ extern char *sys_siglist[];
#endif
extern char *version_string;
static int vflag; /* true if -v */
int vflag; /* true if -v */
static int rflag; /* true if -r */
static int strip_flag; /* true if -s */
static int debug; /* true if -debug */
int debug; /* true if -debug */
static int shared_obj; /* true if -shared */
@ -240,14 +249,23 @@ 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. */
char *ldout; /* File for ld errors. */
static char *output_file; /* Output file for ld. */
static char *nm_file_name; /* pathname of nm */
static char *ldd_file_name; /* pathname of ldd (or equivalent) */
static char *strip_file_name; /* pathname of strip */
char *c_file_name; /* pathname of gcc */
static struct head constructors; /* list of constructors found */
static struct head destructors; /* list of destructors found */
struct obstack temporary_obstack;
struct obstack permanent_obstack;
char * temporary_firstobj;
/* Defined in the automatically-generated underscore.c. */
extern int prepends_underscore;
extern char *getenv ();
extern char *mktemp ();
extern FILE *fdopen ();
@ -268,7 +286,9 @@ struct path_prefix
char *name; /* Name of this list (used in config stuff) */
};
static void my_exit PROTO((int));
void collect_exit PROTO((int));
void collect_execute PROTO((char *, char **, char *));
void dump_file PROTO((char *));
static void handler PROTO((int));
static int is_ctor_dtor PROTO((char *));
static void choose_temp_base PROTO((void));
@ -286,11 +306,12 @@ static void write_c_file PROTO((FILE *, char *));
static void scan_prog_file PROTO((char *, enum pass));
static void scan_libraries PROTO((char *));
generic *xcalloc ();
generic *xmalloc ();
char *xcalloc ();
char *xmalloc ();
extern char *index ();
extern char *rindex ();
extern void free ();
#ifdef NO_DUP2
int
@ -338,8 +359,8 @@ my_strerror (e)
/* Delete tempfiles and exit function. */
static void
my_exit (status)
void
collect_exit (status)
int status;
{
if (c_file != 0 && c_file[0])
@ -348,6 +369,12 @@ my_exit (status)
if (o_file != 0 && o_file[0])
maybe_unlink (o_file);
if (ldout != 0 && ldout[0])
{
dump_file (ldout);
maybe_unlink (ldout);
}
if (status != 0 && output_file != 0 && output_file[0])
maybe_unlink (output_file);
@ -357,7 +384,7 @@ my_exit (status)
/* Die when sys call fails. */
static void
void
fatal_perror (string, arg1, arg2, arg3)
char *string, *arg1, *arg2, *arg3;
{
@ -366,24 +393,24 @@ fatal_perror (string, arg1, arg2, arg3)
fprintf (stderr, "collect2: ");
fprintf (stderr, string, arg1, arg2, arg3);
fprintf (stderr, ": %s\n", my_strerror (e));
my_exit (1);
collect_exit (1);
}
/* Just die. */
static void
void
fatal (string, arg1, arg2, arg3)
char *string, *arg1, *arg2, *arg3;
{
fprintf (stderr, "collect2: ");
fprintf (stderr, string, arg1, arg2, arg3);
fprintf (stderr, "\n");
my_exit (1);
collect_exit (1);
}
/* Write error message. */
static void
void
error (string, arg1, arg2, arg3, arg4)
char *string, *arg1, *arg2, *arg3, *arg4;
{
@ -412,33 +439,54 @@ handler (signo)
if (o_file != 0 && o_file[0])
maybe_unlink (o_file);
if (ldout != 0 && ldout[0])
maybe_unlink (ldout);
signal (signo, SIG_DFL);
kill (getpid (), signo);
}
generic *
char *
xcalloc (size1, size2)
int size1, size2;
{
generic *ptr = (generic *) calloc (size1, size2);
char *ptr = (char *) calloc (size1, size2);
if (ptr)
return ptr;
fatal ("out of memory");
return (generic *)0;
return (char *)0;
}
generic *
char *
xmalloc (size)
int size;
unsigned size;
{
generic *ptr = (generic *) malloc (size);
char *ptr = (char *) malloc (size);
if (ptr)
return ptr;
fatal ("out of memory");
return (generic *)0;
return (char *)0;
}
char *
xrealloc (ptr, size)
char *ptr;
unsigned size;
{
register char *value = (char *) realloc (ptr, size);
if (value == 0)
fatal ("virtual memory exhausted");
return value;
}
int
file_exists (name)
char *name;
{
return access (name, R_OK) == 0;
}
/* Make a copy of a string INPUT with size SIZE. */
@ -454,6 +502,63 @@ savestring (input, size)
return output;
}
void
dump_file (name)
char *name;
{
FILE *stream = fopen (name, "r");
int no_demangle = !! getenv ("COLLECT_NO_DEMANGLE");
if (stream == 0)
return;
while (1)
{
int c;
while (c = getc (stream),
c != EOF && (isalnum (c) || c == '_' || c == '$' || c == '.'))
obstack_1grow (&temporary_obstack, c);
if (obstack_object_size (&temporary_obstack) > 0)
{
char *word, *p, *result;
obstack_1grow (&temporary_obstack, '\0');
word = obstack_finish (&temporary_obstack);
if (*word == '.')
++word, putc ('.', stderr);
p = word;
if (*p == '_' && prepends_underscore)
++p;
if (no_demangle)
result = 0;
else
result = cplus_demangle (p, DMGL_PARAMS | DMGL_ANSI);
if (result)
{
int diff;
fputs (result, stderr);
diff = strlen (word) - strlen (result);
while (diff > 0)
--diff, putc (' ', stderr);
while (diff < 0 && c == ' ')
++diff, c = getc (stream);
free (result);
}
else
fputs (word, stderr);
fflush (stderr);
obstack_free (&temporary_obstack, temporary_firstobj);
}
if (c == EOF)
break;
putc (c, stderr);
}
}
/* Decide whether the given symbol is:
a constructor (1), a destructor (2), or neither (0). */
@ -799,10 +904,7 @@ main (argc, argv)
char *full_ld_suffix = ld_suffix;
char *real_ld_suffix = "real-ld";
char *full_real_ld_suffix = real_ld_suffix;
#if 0
char *gld_suffix = "gld";
char *full_gld_suffix = gld_suffix;
#endif
char *collect_ld_suffix = "collect-ld";
char *nm_suffix = "nm";
char *full_nm_suffix = nm_suffix;
char *gnm_suffix = "gnm";
@ -818,7 +920,6 @@ main (argc, argv)
char *arg;
FILE *outf;
char *ld_file_name;
char *c_file_name;
char *collect_name;
char *collect_names;
char *p;
@ -840,6 +941,11 @@ main (argc, argv)
output_file = "a.out";
obstack_begin (&temporary_obstack, 0);
obstack_begin (&permanent_obstack, 0);
temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0);
current_demangling_style = gnu_demangling;
/* We must check that we do not call ourselves in an infinite
recursion loop. We append the name used for us to the COLLECT_NAMES
environment variable.
@ -992,21 +1098,11 @@ main (argc, argv)
ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME);
if (ld_file_name == 0)
#endif
#if 0
/* Search the (target-specific) compiler dirs for `gld'. */
ld_file_name = find_a_file (&cpath, gld_suffix);
/* Search the ordinary system bin directories
for `gld' (if native linking) or `TARGET-gld' (if cross). */
/* Search the (target-specific) compiler dirs for ld'. */
ld_file_name = find_a_file (&cpath, real_ld_suffix);
/* Likewise for `collect-ld'. */
if (ld_file_name == 0)
ld_file_name = find_a_file (&path, full_gld_suffix);
#else
ld_file_name = 0;
#endif
/* Likewise for `real-ld'. */
if (ld_file_name == 0)
ld_file_name = find_a_file (&cpath, real_ld_suffix);
if (ld_file_name == 0)
ld_file_name = find_a_file (&path, full_real_ld_suffix);
ld_file_name = find_a_file (&cpath, collect_ld_suffix);
/* Search the compiler directories for `ld'. We have protection against
recursive calls in find_a_file. */
if (ld_file_name == 0)
@ -1087,6 +1183,8 @@ main (argc, argv)
choose_temp_base ();
c_file = xcalloc (temp_filename_length + sizeof (".c"), 1);
o_file = xcalloc (temp_filename_length + sizeof (".o"), 1);
ldout = xmalloc (temp_filename_length + sizeof (".ld"));
sprintf (ldout, "%s.ld", temp_filename);
sprintf (c_file, "%s.c", temp_filename);
sprintf (o_file, "%s.o", temp_filename);
*c_ptr++ = c_file_name;
@ -1144,7 +1242,7 @@ main (argc, argv)
break;
case 's':
if (arg[2] == '\0')
if (arg[2] == '\0' && do_collecting)
{
/* We must strip after the nm run, otherwise C++ linking
won't work. Thus we strip in the second ld run, or
@ -1206,7 +1304,7 @@ main (argc, argv)
}
*c_ptr++ = c_file;
*c_ptr = *ld1 = *ld2 = (char *)0;
*object = *c_ptr = *ld1 = *ld2 = (char *)0;
if (vflag)
{
@ -1260,17 +1358,22 @@ main (argc, argv)
fprintf (stderr, "\n");
}
/* Load the program, searching all libraries.
Examine the namelist with nm and search it for static constructors
/* Load the program, searching all libraries. */
collect_execute ("ld", ld1_argv, ldout);
do_wait ("ld");
dump_file (ldout);
unlink (ldout);
/* If -r or they'll be run via some other method, don't build the
constructor or destructor list, just return now. */
if (rflag || ! do_collecting)
return 0;
/* 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 and reload. */
fork_execute ("ld", ld1_argv);
/* If -r, don't build the constructor or destructor list, just return now. */
if (rflag)
return 0;
#ifdef COLLECT_SCAN_OBJECTS
/* The AIX linker will discard static constructors in object files if
nothing else in the file is referenced, so look at them first. */
@ -1347,8 +1450,8 @@ main (argc, argv)
/* Wait for a process to finish, and exit if a non-zero status is found. */
static void
do_wait (prog)
int
collect_wait (prog)
char *prog;
{
int status;
@ -1372,28 +1475,35 @@ do_wait (prog)
(status & 0200) ? ", core dumped" : "");
#endif
my_exit (127);
collect_exit (127);
}
if (WIFEXITED (status))
{
int ret = WEXITSTATUS (status);
if (ret != 0)
{
error ("%s returned %d exit status", prog, ret);
my_exit (ret);
}
}
return WEXITSTATUS (status);
}
return 0;
}
static void
do_wait (prog)
char *prog;
{
int ret = collect_wait (prog);
if (ret != 0)
{
error ("%s returned %d exit status", prog, ret);
collect_exit (ret);
}
}
/* Fork and execute a program, and wait for the reply. */
static void
fork_execute (prog, argv)
void
collect_execute (prog, argv, redir)
char *prog;
char **argv;
char *redir;
{
int pid;
@ -1434,13 +1544,28 @@ fork_execute (prog, argv)
if (pid == 0) /* child context */
{
if (redir)
{
unlink (redir);
if (freopen (redir, "a", stdout) == NULL)
fatal_perror ("redirecting stdout");
if (freopen (redir, "a", stderr) == NULL)
fatal_perror ("redirecting stderr");
}
execvp (argv[0], argv);
fatal_perror ("executing %s", prog);
}
do_wait (prog);
}
static void
fork_execute (prog, argv)
char *prog;
char **argv;
{
collect_execute (prog, argv, NULL);
do_wait (prog);
}
/* Unlink a file unless we are debugging. */
@ -1831,7 +1956,7 @@ scan_prog_file (prog_name, which_pass)
#endif
}
#ifdef SUNOS4_SHARED_LIBRARIES
#if SUNOS4_SHARED_LIBRARIES
/* Routines to scan the SunOS 4 _DYNAMIC structure to find shared libraries
that the output file depends upon and their initialization/finalization
@ -3000,10 +3125,10 @@ end_file (ptr)
fatal ("wrote %ld bytes, expected %ld, to %s", len, ptr->size, ptr->name);
}
free ((generic *)ptr->start);
free (ptr->start);
}
free ((generic *)ptr);
free (ptr);
}
#endif /* OBJECT_FORMAT_ROSE */

2986
gcc/cplus-dem.c Normal file

File diff suppressed because it is too large Load Diff

107
gcc/demangle.h Normal file
View File

@ -0,0 +1,107 @@
/* Defs for interface to demanglers.
Copyright 1992, 1995 Free Software Foundation, Inc.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#if !defined (DEMANGLE_H)
#define DEMANGLE_H
#ifdef IN_GCC
/* Add prototype support. */
#ifndef PROTO
#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
#define PROTO(ARGS) ARGS
#else
#define PROTO(ARGS) ()
#endif
#endif
#define PARAMS(ARGS) PROTO(ARGS)
#ifdef __STDC__
#define PTR void *
#else
#ifndef const
#define const
#endif
#define PTR char *
#endif
#else /* ! IN_GCC */
#include <ansidecl.h>
#endif /* IN_GCC */
/* Options passed to cplus_demangle (in 2nd parameter). */
#define DMGL_NO_OPTS 0 /* For readability... */
#define DMGL_PARAMS (1 << 0) /* Include function args */
#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
#define DMGL_AUTO (1 << 8)
#define DMGL_GNU (1 << 9)
#define DMGL_LUCID (1 << 10)
#define DMGL_ARM (1 << 11)
/* If none of these are set, use 'current_demangling_style' as the default. */
#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM)
/* Enumeration of possible demangling styles.
Lucid and ARM styles are still kept logically distinct, even though
they now both behave identically. The resulting style is actual the
union of both. I.E. either style recognizes both "__pt__" and "__rf__"
for operator "->", even though the first is lucid style and the second
is ARM style. (FIXME?) */
extern enum demangling_styles
{
unknown_demangling = 0,
auto_demangling = DMGL_AUTO,
gnu_demangling = DMGL_GNU,
lucid_demangling = DMGL_LUCID,
arm_demangling = DMGL_ARM
} current_demangling_style;
/* Define string names for the various demangling styles. */
#define AUTO_DEMANGLING_STYLE_STRING "auto"
#define GNU_DEMANGLING_STYLE_STRING "gnu"
#define LUCID_DEMANGLING_STYLE_STRING "lucid"
#define ARM_DEMANGLING_STYLE_STRING "arm"
/* Some macros to test what demangling style is active. */
#define CURRENT_DEMANGLING_STYLE current_demangling_style
#define AUTO_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_AUTO)
#define GNU_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU)
#define LUCID_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_LUCID)
#define ARM_DEMANGLING (CURRENT_DEMANGLING_STYLE & DMGL_ARM)
extern char *
cplus_demangle PARAMS ((const char *mangled, int options));
extern int
cplus_demangle_opname PARAMS ((char *opname, char *result, int options));
extern char *
cplus_mangle_opname PARAMS ((char *opname, int options));
/* Note: This sets global state. FIXME if you care about multi-threading. */
extern void
set_cplus_marker_for_demangling PARAMS ((int ch));
#endif /* DEMANGLE_H */