forked from Imagelibrary/binutils-gdb
Add new support for parsing cfront stabs.
This commit is contained in:
118
gdb/dbxread.c
118
gdb/dbxread.c
@@ -1,5 +1,5 @@
|
|||||||
/* Read dbx symbol tables and convert to internal format, for GDB.
|
/* Read dbx symbol tables and convert to internal format, for GDB.
|
||||||
Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995
|
Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
|
||||||
Free Software Foundation, Inc.
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GDB.
|
This file is part of GDB.
|
||||||
@@ -65,6 +65,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||||||
#include "aout/aout64.h"
|
#include "aout/aout64.h"
|
||||||
#include "aout/stab_gnu.h" /* We always use GNU stabs, not native, now */
|
#include "aout/stab_gnu.h" /* We always use GNU stabs, not native, now */
|
||||||
|
|
||||||
|
/* defined in stabsread.c; used for completing cfront stabs strings */
|
||||||
|
extern void resolve_cont PARAMS((struct objfile * objfile, struct symbol * sym, char * p));
|
||||||
|
|
||||||
|
|
||||||
/* We put a pointer to this structure in the read_symtab_private field
|
/* We put a pointer to this structure in the read_symtab_private field
|
||||||
of the psymtab. */
|
of the psymtab. */
|
||||||
@@ -242,7 +245,7 @@ static void
|
|||||||
init_bincl_list PARAMS ((int, struct objfile *));
|
init_bincl_list PARAMS ((int, struct objfile *));
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
dbx_next_symbol_text PARAMS ((void));
|
dbx_next_symbol_text PARAMS ((struct objfile *));
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fill_symbuf PARAMS ((bfd *));
|
fill_symbuf PARAMS ((bfd *));
|
||||||
@@ -706,6 +709,7 @@ dbx_symfile_init (objfile)
|
|||||||
DBX_STRINGTAB (objfile) =
|
DBX_STRINGTAB (objfile) =
|
||||||
(char *) obstack_alloc (&objfile -> psymbol_obstack,
|
(char *) obstack_alloc (&objfile -> psymbol_obstack,
|
||||||
DBX_STRINGTAB_SIZE (objfile));
|
DBX_STRINGTAB_SIZE (objfile));
|
||||||
|
OBJSTAT (objfile, sz_strtab += DBX_STRINGTAB_SIZE (objfile));
|
||||||
|
|
||||||
/* Now read in the string table in one big gulp. */
|
/* Now read in the string table in one big gulp. */
|
||||||
|
|
||||||
@@ -742,6 +746,68 @@ static struct internal_nlist symbuf[4096];
|
|||||||
static int symbuf_idx;
|
static int symbuf_idx;
|
||||||
static int symbuf_end;
|
static int symbuf_end;
|
||||||
|
|
||||||
|
/* cont_elem is used for continuing information in cfront.
|
||||||
|
It saves information about which types need to be fixed up and
|
||||||
|
completed after all the stabs are read. */
|
||||||
|
struct cont_elem
|
||||||
|
{
|
||||||
|
/* sym and stabsstring for continuing information in cfront */
|
||||||
|
struct symbol * sym;
|
||||||
|
char * stabs;
|
||||||
|
/* state dependancies (statics that must be preserved) */
|
||||||
|
int sym_idx;
|
||||||
|
int sym_end;
|
||||||
|
int symnum;
|
||||||
|
/* other state dependancies include:
|
||||||
|
(assumption is that these will not change since process_now FIXME!!)
|
||||||
|
stringtab_global
|
||||||
|
n_stabs
|
||||||
|
objfile
|
||||||
|
symfile_bfd */
|
||||||
|
};
|
||||||
|
static struct cont_elem cont_list[100];
|
||||||
|
static int cont_count = 0;
|
||||||
|
|
||||||
|
void
|
||||||
|
process_later(sym,p)
|
||||||
|
struct symbol * sym;
|
||||||
|
char * p;
|
||||||
|
{
|
||||||
|
/* save state so we can process these stabs later */
|
||||||
|
cont_list[cont_count].sym_idx = symbuf_idx;
|
||||||
|
cont_list[cont_count].sym_end = symbuf_end;
|
||||||
|
cont_list[cont_count].symnum = symnum;
|
||||||
|
cont_list[cont_count].sym = sym;
|
||||||
|
cont_list[cont_count].stabs = p;
|
||||||
|
cont_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
process_now(objfile)
|
||||||
|
struct objfile * objfile;
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
/* save original state */
|
||||||
|
int save_symbuf_idx = symbuf_idx;
|
||||||
|
int save_symbuf_end = symbuf_end;
|
||||||
|
int save_symnum = symnum;
|
||||||
|
for (i=0; i<cont_count; i++)
|
||||||
|
{
|
||||||
|
/* set state as if we were parsing stabs strings
|
||||||
|
for this symbol */
|
||||||
|
symbuf_idx = cont_list[i].sym_idx; /* statics used by gdb */
|
||||||
|
symbuf_end = cont_list[i].sym_end;
|
||||||
|
symnum = cont_list[i].symnum;
|
||||||
|
resolve_cont(objfile,cont_list[i].sym,cont_list[i].stabs);
|
||||||
|
}
|
||||||
|
/* restore original state */
|
||||||
|
symbuf_idx = save_symbuf_idx;
|
||||||
|
symbuf_end = save_symbuf_end;
|
||||||
|
symnum = save_symnum;
|
||||||
|
cont_count=0; /* reset for next run */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Name of last function encountered. Used in Solaris to approximate
|
/* Name of last function encountered. Used in Solaris to approximate
|
||||||
object file boundaries. */
|
object file boundaries. */
|
||||||
static char *last_function_name;
|
static char *last_function_name;
|
||||||
@@ -825,12 +891,14 @@ fill_symbuf (sym_bfd)
|
|||||||
call this function to get the continuation. */
|
call this function to get the continuation. */
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
dbx_next_symbol_text ()
|
dbx_next_symbol_text (objfile)
|
||||||
|
struct objfile *objfile;
|
||||||
{
|
{
|
||||||
if (symbuf_idx == symbuf_end)
|
if (symbuf_idx == symbuf_end)
|
||||||
fill_symbuf (symfile_bfd);
|
fill_symbuf (symfile_bfd);
|
||||||
symnum++;
|
symnum++;
|
||||||
SWAP_SYMBOL(&symbuf[symbuf_idx], symfile_bfd);
|
SWAP_SYMBOL(&symbuf[symbuf_idx], symfile_bfd);
|
||||||
|
OBJSTAT (objfile, n_stabs++);
|
||||||
return symbuf[symbuf_idx++].n_strx + stringtab_global
|
return symbuf[symbuf_idx++].n_strx + stringtab_global
|
||||||
+ file_string_table_offset;
|
+ file_string_table_offset;
|
||||||
}
|
}
|
||||||
@@ -1066,6 +1134,7 @@ read_dbx_symtab (section_offsets, objfile, text_addr, text_size)
|
|||||||
int nsl;
|
int nsl;
|
||||||
int past_first_source_file = 0;
|
int past_first_source_file = 0;
|
||||||
CORE_ADDR last_o_file_start = 0;
|
CORE_ADDR last_o_file_start = 0;
|
||||||
|
CORE_ADDR last_function_start = 0;
|
||||||
struct cleanup *back_to;
|
struct cleanup *back_to;
|
||||||
bfd *abfd;
|
bfd *abfd;
|
||||||
|
|
||||||
@@ -1128,6 +1197,7 @@ read_dbx_symtab (section_offsets, objfile, text_addr, text_size)
|
|||||||
if (bufp->n_type == (unsigned char)N_SLINE) continue;
|
if (bufp->n_type == (unsigned char)N_SLINE) continue;
|
||||||
|
|
||||||
SWAP_SYMBOL (bufp, abfd);
|
SWAP_SYMBOL (bufp, abfd);
|
||||||
|
OBJSTAT (objfile, n_stabs++);
|
||||||
|
|
||||||
/* Ok. There is a lot of code duplicated in the rest of this
|
/* Ok. There is a lot of code duplicated in the rest of this
|
||||||
switch statement (for efficiency reasons). Since I don't
|
switch statement (for efficiency reasons). Since I don't
|
||||||
@@ -1207,8 +1277,8 @@ start_psymtab (objfile, section_offsets,
|
|||||||
char *filename;
|
char *filename;
|
||||||
CORE_ADDR textlow;
|
CORE_ADDR textlow;
|
||||||
int ldsymoff;
|
int ldsymoff;
|
||||||
struct partial_symbol *global_syms;
|
struct partial_symbol **global_syms;
|
||||||
struct partial_symbol *static_syms;
|
struct partial_symbol **static_syms;
|
||||||
{
|
{
|
||||||
struct partial_symtab *result =
|
struct partial_symtab *result =
|
||||||
start_psymtab_common(objfile, section_offsets,
|
start_psymtab_common(objfile, section_offsets,
|
||||||
@@ -1561,6 +1631,7 @@ read_ofile_symtab (pst)
|
|||||||
fill_symbuf (abfd);
|
fill_symbuf (abfd);
|
||||||
bufp = &symbuf[symbuf_idx++];
|
bufp = &symbuf[symbuf_idx++];
|
||||||
SWAP_SYMBOL (bufp, abfd);
|
SWAP_SYMBOL (bufp, abfd);
|
||||||
|
OBJSTAT (objfile, n_stabs++);
|
||||||
|
|
||||||
SET_NAMESTRING ();
|
SET_NAMESTRING ();
|
||||||
|
|
||||||
@@ -1616,6 +1687,7 @@ read_ofile_symtab (pst)
|
|||||||
fill_symbuf(abfd);
|
fill_symbuf(abfd);
|
||||||
bufp = &symbuf[symbuf_idx++];
|
bufp = &symbuf[symbuf_idx++];
|
||||||
SWAP_SYMBOL (bufp, abfd);
|
SWAP_SYMBOL (bufp, abfd);
|
||||||
|
OBJSTAT (objfile, n_stabs++);
|
||||||
|
|
||||||
type = bufp->n_type;
|
type = bufp->n_type;
|
||||||
|
|
||||||
@@ -1669,8 +1741,17 @@ read_ofile_symtab (pst)
|
|||||||
if (last_source_start_addr == 0)
|
if (last_source_start_addr == 0)
|
||||||
last_source_start_addr = text_offset;
|
last_source_start_addr = text_offset;
|
||||||
|
|
||||||
pst->symtab = end_symtab (text_offset + text_size, 0, 0, objfile,
|
/* In reordered executables last_source_start_addr may not be the
|
||||||
SECT_OFF_TEXT);
|
lower bound for this symtab, instead use text_offset which comes
|
||||||
|
from pst->textlow which is correct. */
|
||||||
|
if (last_source_start_addr > text_offset)
|
||||||
|
last_source_start_addr = text_offset;
|
||||||
|
|
||||||
|
pst->symtab = end_symtab (text_offset + text_size, objfile, SECT_OFF_TEXT);
|
||||||
|
|
||||||
|
if (ARM_DEMANGLING) /* process incomplete C++ types now */
|
||||||
|
process_now(objfile);
|
||||||
|
|
||||||
end_stabs ();
|
end_stabs ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1745,6 +1826,21 @@ process_one_symbol (type, desc, valu, name, section_offsets, objfile)
|
|||||||
{
|
{
|
||||||
case N_FUN:
|
case N_FUN:
|
||||||
case N_FNAME:
|
case N_FNAME:
|
||||||
|
|
||||||
|
if (! strcmp (name, ""))
|
||||||
|
{
|
||||||
|
/* This N_FUN marks the end of a function. This closes off the
|
||||||
|
current block. */
|
||||||
|
within_function = 0;
|
||||||
|
new = pop_context ();
|
||||||
|
|
||||||
|
/* Make a block for the local symbols within. */
|
||||||
|
finish_block (new->name, &local_symbols, new->old_blocks,
|
||||||
|
function_start_offset, function_start_offset + valu,
|
||||||
|
objfile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Relocate for dynamic loading */
|
/* Relocate for dynamic loading */
|
||||||
valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
|
valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
|
||||||
goto define_a_symbol;
|
goto define_a_symbol;
|
||||||
@@ -1896,7 +1992,7 @@ process_one_symbol (type, desc, valu, name, section_offsets, objfile)
|
|||||||
patch_subfile_names (current_subfile, name);
|
patch_subfile_names (current_subfile, name);
|
||||||
break; /* Ignore repeated SOs */
|
break; /* Ignore repeated SOs */
|
||||||
}
|
}
|
||||||
end_symtab (valu, 0, 0, objfile, SECT_OFF_TEXT);
|
end_symtab (valu, objfile, SECT_OFF_TEXT);
|
||||||
end_stabs ();
|
end_stabs ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2131,7 +2227,8 @@ process_one_symbol (type, desc, valu, name, section_offsets, objfile)
|
|||||||
&& SYMBOL_NAME (m) [l] == '\0')
|
&& SYMBOL_NAME (m) [l] == '\0')
|
||||||
/* last_pc_address was in this function */
|
/* last_pc_address was in this function */
|
||||||
valu = SYMBOL_VALUE (m);
|
valu = SYMBOL_VALUE (m);
|
||||||
else if (m && STREQN (SYMBOL_NAME (m+1), name, l)
|
else if (m && SYMBOL_NAME (m+1)
|
||||||
|
&& STREQN (SYMBOL_NAME (m+1), name, l)
|
||||||
&& SYMBOL_NAME (m+1) [l] == '\0')
|
&& SYMBOL_NAME (m+1) [l] == '\0')
|
||||||
/* last_pc_address was in last function */
|
/* last_pc_address was in last function */
|
||||||
valu = SYMBOL_VALUE (m+1);
|
valu = SYMBOL_VALUE (m+1);
|
||||||
@@ -2268,6 +2365,7 @@ coffstab_build_psymtabs (objfile, section_offsets, mainline,
|
|||||||
error ("ridiculous string table size: %d bytes", stabstrsize);
|
error ("ridiculous string table size: %d bytes", stabstrsize);
|
||||||
DBX_STRINGTAB (objfile) = (char *)
|
DBX_STRINGTAB (objfile) = (char *)
|
||||||
obstack_alloc (&objfile->psymbol_obstack, stabstrsize+1);
|
obstack_alloc (&objfile->psymbol_obstack, stabstrsize+1);
|
||||||
|
OBJSTAT (objfile, sz_strtab += stabstrsize+1);
|
||||||
|
|
||||||
/* Now read in the string table in one big gulp. */
|
/* Now read in the string table in one big gulp. */
|
||||||
|
|
||||||
@@ -2373,6 +2471,7 @@ elfstab_build_psymtabs (objfile, section_offsets, mainline,
|
|||||||
error ("ridiculous string table size: %d bytes", stabstrsize);
|
error ("ridiculous string table size: %d bytes", stabstrsize);
|
||||||
DBX_STRINGTAB (objfile) = (char *)
|
DBX_STRINGTAB (objfile) = (char *)
|
||||||
obstack_alloc (&objfile->psymbol_obstack, stabstrsize+1);
|
obstack_alloc (&objfile->psymbol_obstack, stabstrsize+1);
|
||||||
|
OBJSTAT (objfile, sz_strtab += stabstrsize+1);
|
||||||
|
|
||||||
/* Now read in the string table in one big gulp. */
|
/* Now read in the string table in one big gulp. */
|
||||||
|
|
||||||
@@ -2460,6 +2559,7 @@ stabsect_build_psymtabs (objfile, section_offsets, mainline, stab_name,
|
|||||||
error ("ridiculous string table size: %d bytes", DBX_STRINGTAB_SIZE (objfile));
|
error ("ridiculous string table size: %d bytes", DBX_STRINGTAB_SIZE (objfile));
|
||||||
DBX_STRINGTAB (objfile) = (char *)
|
DBX_STRINGTAB (objfile) = (char *)
|
||||||
obstack_alloc (&objfile->psymbol_obstack, DBX_STRINGTAB_SIZE (objfile) + 1);
|
obstack_alloc (&objfile->psymbol_obstack, DBX_STRINGTAB_SIZE (objfile) + 1);
|
||||||
|
OBJSTAT (objfile, sz_strtab += DBX_STRINGTAB_SIZE (objfile) + 1);
|
||||||
|
|
||||||
/* Now read in the string table in one big gulp. */
|
/* Now read in the string table in one big gulp. */
|
||||||
|
|
||||||
|
|||||||
196
gdb/gdbtypes.c
196
gdb/gdbtypes.c
@@ -971,6 +971,199 @@ check_typedef (type)
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* New code added to support parsing of Cfront stabs strings */
|
||||||
|
#include <ctype.h>
|
||||||
|
#define INIT_EXTRA { pextras->len=0; pextras->str[0]='\0'; }
|
||||||
|
#define ADD_EXTRA(c) { pextras->str[pextras->len++]=c; }
|
||||||
|
struct extra { char str[128]; int len; }; /* maximum extention is 128! FIXME */
|
||||||
|
void
|
||||||
|
add_name(pextras,n)
|
||||||
|
struct extra * pextras;
|
||||||
|
char * n;
|
||||||
|
{
|
||||||
|
char lenstr[512]; /* FIXME! hardcoded :-( */
|
||||||
|
int nlen, lenstrlen;
|
||||||
|
if ((nlen = (n ? strlen(n) : 0))==0)
|
||||||
|
return;
|
||||||
|
sprintf(pextras->str+pextras->len,"%d%s",nlen,n);
|
||||||
|
pextras->len=strlen(pextras->str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
add_mangled_type(pextras,t)
|
||||||
|
struct extra * pextras;
|
||||||
|
struct type * t;
|
||||||
|
{
|
||||||
|
enum type_code tcode;
|
||||||
|
int tlen, tflags;
|
||||||
|
char * tname;
|
||||||
|
|
||||||
|
tcode = TYPE_CODE(t);
|
||||||
|
tlen = TYPE_LENGTH(t);
|
||||||
|
tflags = TYPE_FLAGS(t);
|
||||||
|
tname = TYPE_NAME(t);
|
||||||
|
/* args of "..." seem to get mangled as "e" */
|
||||||
|
|
||||||
|
switch (tcode)
|
||||||
|
{
|
||||||
|
case TYPE_CODE_INT:
|
||||||
|
if (tflags==1)
|
||||||
|
ADD_EXTRA('U');
|
||||||
|
switch (tlen)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
ADD_EXTRA('c');
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
ADD_EXTRA('s');
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
char* pname;
|
||||||
|
if ((pname=strrchr(tname,'l'),pname) && !strcmp(pname,"long"))
|
||||||
|
ADD_EXTRA('l')
|
||||||
|
else
|
||||||
|
ADD_EXTRA('i')
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
|
||||||
|
static struct complaint msg = {"Bad int type code length x%x\n",0,0};
|
||||||
|
|
||||||
|
complain (&msg, tlen);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TYPE_CODE_FLT:
|
||||||
|
switch (tlen)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
ADD_EXTRA('f');
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
ADD_EXTRA('d');
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
ADD_EXTRA('r');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
static struct complaint msg = {"Bad float type code length x%x\n",0,0};
|
||||||
|
complain (&msg, tlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TYPE_CODE_REF:
|
||||||
|
ADD_EXTRA('R');
|
||||||
|
/* followed by what it's a ref to */
|
||||||
|
break;
|
||||||
|
case TYPE_CODE_PTR:
|
||||||
|
ADD_EXTRA('P');
|
||||||
|
/* followed by what it's a ptr to */
|
||||||
|
break;
|
||||||
|
case TYPE_CODE_TYPEDEF:
|
||||||
|
{
|
||||||
|
static struct complaint msg = {"Typedefs in overloaded functions not yet supported\n",0,0};
|
||||||
|
complain (&msg);
|
||||||
|
}
|
||||||
|
/* followed by type bytes & name */
|
||||||
|
break;
|
||||||
|
case TYPE_CODE_FUNC:
|
||||||
|
ADD_EXTRA('F');
|
||||||
|
/* followed by func's arg '_' & ret types */
|
||||||
|
break;
|
||||||
|
case TYPE_CODE_VOID:
|
||||||
|
ADD_EXTRA('v');
|
||||||
|
break;
|
||||||
|
case TYPE_CODE_METHOD:
|
||||||
|
ADD_EXTRA('M');
|
||||||
|
/* followed by name of class and func's arg '_' & ret types */
|
||||||
|
add_name(pextras,tname);
|
||||||
|
ADD_EXTRA('F'); /* then mangle function */
|
||||||
|
break;
|
||||||
|
case TYPE_CODE_STRUCT: /* C struct */
|
||||||
|
case TYPE_CODE_UNION: /* C union */
|
||||||
|
case TYPE_CODE_ENUM: /* Enumeration type */
|
||||||
|
/* followed by name of type */
|
||||||
|
add_name(pextras,tname);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* errors possible types/not supported */
|
||||||
|
case TYPE_CODE_CHAR:
|
||||||
|
case TYPE_CODE_ARRAY: /* Array type */
|
||||||
|
case TYPE_CODE_MEMBER: /* Member type */
|
||||||
|
case TYPE_CODE_BOOL:
|
||||||
|
case TYPE_CODE_COMPLEX: /* Complex float */
|
||||||
|
case TYPE_CODE_UNDEF:
|
||||||
|
case TYPE_CODE_SET: /* Pascal sets */
|
||||||
|
case TYPE_CODE_RANGE:
|
||||||
|
case TYPE_CODE_STRING:
|
||||||
|
case TYPE_CODE_BITSTRING:
|
||||||
|
case TYPE_CODE_ERROR:
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
static struct complaint msg = {"Unknown type code x%x\n",0,0};
|
||||||
|
complain (&msg, tcode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (t->target_type)
|
||||||
|
add_mangled_type(pextras,t->target_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
cfront_mangle_name(type, i, j)
|
||||||
|
struct type *type;
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
{
|
||||||
|
struct fn_field *f;
|
||||||
|
char *mangled_name = gdb_mangle_name (type, i, j);
|
||||||
|
|
||||||
|
f = TYPE_FN_FIELDLIST1 (type, i); /* moved from below */
|
||||||
|
|
||||||
|
/* kludge to support cfront methods - gdb expects to find "F" for
|
||||||
|
ARM_mangled names, so when we mangle, we have to add it here */
|
||||||
|
if (ARM_DEMANGLING)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
char * arm_mangled_name;
|
||||||
|
struct fn_field *method = &f[j];
|
||||||
|
char *field_name = TYPE_FN_FIELDLIST_NAME (type, i);
|
||||||
|
char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);
|
||||||
|
char *newname = type_name_no_tag (type);
|
||||||
|
|
||||||
|
struct type *ftype = TYPE_FN_FIELD_TYPE (f, j);
|
||||||
|
int nargs = TYPE_NFIELDS(ftype); /* number of args */
|
||||||
|
struct extra extras, * pextras = &extras;
|
||||||
|
INIT_EXTRA
|
||||||
|
|
||||||
|
if (TYPE_FN_FIELD_STATIC_P (f, j)) /* j for sublist within this list */
|
||||||
|
ADD_EXTRA('S')
|
||||||
|
ADD_EXTRA('F')
|
||||||
|
/* add args here! */
|
||||||
|
if (nargs <= 1) /* no args besides this */
|
||||||
|
ADD_EXTRA('v')
|
||||||
|
else {
|
||||||
|
for (k=1; k<nargs; k++)
|
||||||
|
{
|
||||||
|
struct type * t;
|
||||||
|
t = TYPE_FIELD_TYPE(ftype,k);
|
||||||
|
add_mangled_type(pextras,t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ADD_EXTRA('\0')
|
||||||
|
printf("add_mangled_type: %s\n",extras.str); /* FIXME */
|
||||||
|
arm_mangled_name = malloc(strlen(mangled_name)+extras.len);
|
||||||
|
sprintf(arm_mangled_name,"%s%s",mangled_name,extras.str);
|
||||||
|
free(mangled_name);
|
||||||
|
mangled_name = arm_mangled_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#undef ADD_EXTRA
|
||||||
|
/* End of new code added to support parsing of Cfront stabs strings */
|
||||||
|
|
||||||
/* Ugly hack to convert method stubs into method types.
|
/* Ugly hack to convert method stubs into method types.
|
||||||
|
|
||||||
He ain't kiddin'. This demangles the name of the method into a string
|
He ain't kiddin'. This demangles the name of the method into a string
|
||||||
@@ -1075,7 +1268,8 @@ check_stub_method (type, i, j)
|
|||||||
|
|
||||||
free (demangled_name);
|
free (demangled_name);
|
||||||
|
|
||||||
f = TYPE_FN_FIELDLIST1 (type, i);
|
f = TYPE_FN_FIELDLIST1 (type, i);
|
||||||
|
|
||||||
TYPE_FN_FIELD_PHYSNAME (f, j) = mangled_name;
|
TYPE_FN_FIELD_PHYSNAME (f, j) = mangled_name;
|
||||||
|
|
||||||
/* Now update the old "stub" type into a real type. */
|
/* Now update the old "stub" type into a real type. */
|
||||||
|
|||||||
@@ -635,6 +635,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||||||
case '8':
|
case '8':
|
||||||
case '9':
|
case '9':
|
||||||
case '-':
|
case '-':
|
||||||
|
/* added to support cfront stabs strings */
|
||||||
|
case 'Z': /* for definition continuations */
|
||||||
|
case 'P': /* for prototypes */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case ':':
|
case ':':
|
||||||
|
|||||||
513
gdb/stabsread.c
513
gdb/stabsread.c
@@ -497,6 +497,489 @@ read_type_number (pp, typenums)
|
|||||||
#define REG_STRUCT_HAS_ADDR(gcc_p,type) 0
|
#define REG_STRUCT_HAS_ADDR(gcc_p,type) 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define VISIBILITY_PRIVATE '0' /* Stabs character for private field */
|
||||||
|
#define VISIBILITY_PROTECTED '1' /* Stabs character for protected fld */
|
||||||
|
#define VISIBILITY_PUBLIC '2' /* Stabs character for public field */
|
||||||
|
#define VISIBILITY_IGNORE '9' /* Optimized out or zero length */
|
||||||
|
|
||||||
|
#define CFRONT_VISIBILITY_PRIVATE '2' /* Stabs character for private field */
|
||||||
|
#define CFRONT_VISIBILITY_PUBLIC '1' /* Stabs character for public field */
|
||||||
|
|
||||||
|
/* This code added to support parsing of ARM/Cfront stabs strings */
|
||||||
|
|
||||||
|
/* get substring from string up to char c
|
||||||
|
advance string pointer past suibstring */
|
||||||
|
static char *
|
||||||
|
get_substring(p, c)
|
||||||
|
char ** p;
|
||||||
|
char c;
|
||||||
|
{
|
||||||
|
char * str;
|
||||||
|
str = *p;
|
||||||
|
*p = strchr(*p,c);
|
||||||
|
if (*p)
|
||||||
|
{
|
||||||
|
**p = 0;
|
||||||
|
(*p)++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
str = 0;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Physname gets strcat'd onto sname in order to recreate the mangled name
|
||||||
|
(see funtion gdb_mangle_name in gdbtypes.c). For cfront, make the physname
|
||||||
|
look like that of g++ - take out the initial mangling
|
||||||
|
eg: for sname="a" and fname="foo__1aFPFs_i" return "FPFs_i" */
|
||||||
|
static char *
|
||||||
|
get_cfront_method_physname(fname)
|
||||||
|
char * fname;
|
||||||
|
{
|
||||||
|
int len=0;
|
||||||
|
/* FIXME would like to make this generic for g++ too, but
|
||||||
|
that is already handled in read_member_funcctions */
|
||||||
|
char * p = fname;
|
||||||
|
|
||||||
|
/* search ahead to find the start of the mangled suffix */
|
||||||
|
if (*p == '_' && *(p+1)=='_') /* compiler generated; probably a ctor/dtor */
|
||||||
|
p+=2;
|
||||||
|
while (p && ((p+1) - fname) < strlen(fname) && *(p+1)!='_')
|
||||||
|
p = strchr(p,'_');
|
||||||
|
if (!(p && *p=='_' && *(p+1)=='_'))
|
||||||
|
error("Invalid mangled function name %s",fname);
|
||||||
|
p+=2; /* advance past '__' */
|
||||||
|
|
||||||
|
/* struct name length and name of type should come next; advance past it */
|
||||||
|
while (isdigit(*p))
|
||||||
|
{
|
||||||
|
len = len*10 + (*p - '0');
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
p+=len;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read base classes within cfront class definition.
|
||||||
|
eg: class A : Bpri, public Bpub, virtual Bvir
|
||||||
|
A:T(0,27)=s20b__4Bpri:(0,3),0,32;OBpub:(0,25),32,8;a__1A:(0,3),64,32;PBvir:(0,28)=*(0,26),96,32;OBvir:(0,26),128,8;;
|
||||||
|
A:ZcA;2@Bpri 1@Bpub v2@Bvir;foopri__1AFv foopro__1AFv __ct__1AFv __ct__1AFRC1A foopub__1AFv ;;;
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
read_cfront_baseclasses(fip, pp, type, objfile)
|
||||||
|
struct field_info *fip;
|
||||||
|
struct objfile * objfile;
|
||||||
|
char ** pp;
|
||||||
|
struct type * type;
|
||||||
|
{
|
||||||
|
static struct complaint msg_noterm = {"\
|
||||||
|
Base classes not terminated while reading stabs string %s.\n",
|
||||||
|
0, 0};
|
||||||
|
static struct complaint msg_unknown = {"\
|
||||||
|
Unsupported token in stabs string %s.\n",
|
||||||
|
0, 0};
|
||||||
|
static struct complaint msg_notfound = {"\
|
||||||
|
Unable to find base type for %s.\n",
|
||||||
|
0, 0};
|
||||||
|
int bnum=0;
|
||||||
|
char * p;
|
||||||
|
int i;
|
||||||
|
struct nextfield *new;
|
||||||
|
|
||||||
|
if (**pp==';') /* no base classes; return */
|
||||||
|
{
|
||||||
|
*pp++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* first count base classes so we can allocate space before parsing */
|
||||||
|
for (p = *pp; p && *p && *p!=';'; p++)
|
||||||
|
{
|
||||||
|
if (*p==' ') bnum++;
|
||||||
|
}
|
||||||
|
bnum++; /* add one more for last one */
|
||||||
|
|
||||||
|
/* now parse the base classes until we get to the start of the methods
|
||||||
|
(code extracted from read_baseclasses) */
|
||||||
|
TYPE_N_BASECLASSES(type) = bnum;
|
||||||
|
|
||||||
|
/* allocate space */
|
||||||
|
{
|
||||||
|
int num_bytes = B_BYTES (TYPE_N_BASECLASSES (type));
|
||||||
|
char *pointer;
|
||||||
|
pointer = (char *) TYPE_ALLOC (type, num_bytes);
|
||||||
|
TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *) pointer;
|
||||||
|
}
|
||||||
|
B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), TYPE_N_BASECLASSES (type));
|
||||||
|
|
||||||
|
|
||||||
|
for (i = 0; i < TYPE_N_BASECLASSES (type); i++)
|
||||||
|
{
|
||||||
|
new = (struct nextfield *) xmalloc (sizeof (struct nextfield));
|
||||||
|
make_cleanup (free, new);
|
||||||
|
memset (new, 0, sizeof (struct nextfield));
|
||||||
|
new -> next = fip -> list;
|
||||||
|
fip -> list = new;
|
||||||
|
new -> field.bitsize = 0; /* this should be an unpacked field! */
|
||||||
|
|
||||||
|
STABS_CONTINUE (pp, objfile);
|
||||||
|
|
||||||
|
/* virtual? eg: v2@Bvir */
|
||||||
|
if (**pp=='v')
|
||||||
|
{
|
||||||
|
SET_TYPE_FIELD_VIRTUAL (type, i);
|
||||||
|
++(*pp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* access? eg: 2@Bvir */
|
||||||
|
/* Note: protected inheritance not supported in cfront */
|
||||||
|
switch (*(*pp)++)
|
||||||
|
{
|
||||||
|
case CFRONT_VISIBILITY_PRIVATE:
|
||||||
|
new -> visibility = VISIBILITY_PRIVATE;
|
||||||
|
break;
|
||||||
|
case CFRONT_VISIBILITY_PUBLIC:
|
||||||
|
new -> visibility = VISIBILITY_PUBLIC;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Bad visibility format. Complain and treat it as
|
||||||
|
public. */
|
||||||
|
{
|
||||||
|
static struct complaint msg = {
|
||||||
|
"Unknown visibility `%c' for baseclass", 0, 0};
|
||||||
|
complain (&msg, new -> visibility);
|
||||||
|
new -> visibility = VISIBILITY_PUBLIC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "@" comes next - eg: @Bvir */
|
||||||
|
if (**pp!='@')
|
||||||
|
{
|
||||||
|
complain (&msg_unknown, *pp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
++(*pp);
|
||||||
|
|
||||||
|
|
||||||
|
/* Set the bit offset of the portion of the object corresponding
|
||||||
|
to this baseclass. Always zero in the absence of
|
||||||
|
multiple inheritance. */
|
||||||
|
/* Unable to read bit position from stabs;
|
||||||
|
Assuming no multiple inheritance for now FIXME! */
|
||||||
|
/* We may have read this in the structure definition;
|
||||||
|
now we should fixup the members to be the actual base classes */
|
||||||
|
new -> field.bitpos = 0;
|
||||||
|
|
||||||
|
/* Get the base class name and type */
|
||||||
|
{
|
||||||
|
char * bname; /* base class name */
|
||||||
|
struct symbol * bsym; /* base class */
|
||||||
|
char * p1, * p2;
|
||||||
|
p1 = strchr(*pp,' ');
|
||||||
|
p2 = strchr(*pp,';');
|
||||||
|
if (p1<p2)
|
||||||
|
bname = get_substring(pp,' ');
|
||||||
|
else
|
||||||
|
bname = get_substring(pp,';');
|
||||||
|
if (!bname || !*bname)
|
||||||
|
{
|
||||||
|
complain (&msg_unknown, *pp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* FIXME! attach base info to type */
|
||||||
|
bsym = lookup_symbol (bname, 0, STRUCT_NAMESPACE, 0, 0); /*demangled_name*/
|
||||||
|
if (bsym)
|
||||||
|
{
|
||||||
|
struct type * btype = SYMBOL_TYPE(bsym);
|
||||||
|
new -> field.type = btype;
|
||||||
|
new -> field.name = type_name_no_tag (new -> field.type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
complain (&msg_notfound, *pp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If more base classes to parse, loop again.
|
||||||
|
We ate the last ' ' or ';' in get_substring,
|
||||||
|
so on exit we will have skipped the trailing ';' */
|
||||||
|
/* if invalid, return 0; add code to detect - FIXME! */
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
read_cfront_member_functions(fip, pp, type, objfile)
|
||||||
|
struct field_info *fip;
|
||||||
|
char **pp;
|
||||||
|
struct type *type;
|
||||||
|
struct objfile *objfile;
|
||||||
|
{
|
||||||
|
/* This code extracted from read_member_functions
|
||||||
|
so as to do the similar thing for our funcs */
|
||||||
|
|
||||||
|
int nfn_fields = 0;
|
||||||
|
int length = 0;
|
||||||
|
/* Total number of member functions defined in this class. If the class
|
||||||
|
defines two `f' functions, and one `g' function, then this will have
|
||||||
|
the value 3. */
|
||||||
|
int total_length = 0;
|
||||||
|
int i;
|
||||||
|
struct next_fnfield
|
||||||
|
{
|
||||||
|
struct next_fnfield *next;
|
||||||
|
struct fn_field fn_field;
|
||||||
|
} *sublist;
|
||||||
|
struct type *look_ahead_type;
|
||||||
|
struct next_fnfieldlist *new_fnlist;
|
||||||
|
struct next_fnfield *new_sublist;
|
||||||
|
char *main_fn_name;
|
||||||
|
char * fname;
|
||||||
|
struct symbol * ref_func=0;
|
||||||
|
|
||||||
|
/* Process each list until we find something that is not a member function
|
||||||
|
or find the end of the functions. */
|
||||||
|
|
||||||
|
/* eg: p = "__ct__1AFv foo__1AFv ;;;" */
|
||||||
|
STABS_CONTINUE (pp, objfile); /* handle \\ */
|
||||||
|
while (**pp!=';' && (fname = get_substring(pp,' '),fname))
|
||||||
|
{
|
||||||
|
int is_static=0;
|
||||||
|
int sublist_count=0;
|
||||||
|
char * pname;
|
||||||
|
if (fname[0]=='*') /* static member */
|
||||||
|
{
|
||||||
|
is_static=1;
|
||||||
|
sublist_count++;
|
||||||
|
fname++;
|
||||||
|
}
|
||||||
|
ref_func = lookup_symbol (fname, 0, VAR_NAMESPACE, 0, 0); /*demangled_name*/
|
||||||
|
if (!ref_func)
|
||||||
|
{
|
||||||
|
static struct complaint msg = {"\
|
||||||
|
Unable to find function symbol for %s\n",
|
||||||
|
0, 0};
|
||||||
|
complain (&msg, fname);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sublist = NULL;
|
||||||
|
look_ahead_type = NULL;
|
||||||
|
length = 0;
|
||||||
|
|
||||||
|
new_fnlist = (struct next_fnfieldlist *)
|
||||||
|
xmalloc (sizeof (struct next_fnfieldlist));
|
||||||
|
make_cleanup (free, new_fnlist);
|
||||||
|
memset (new_fnlist, 0, sizeof (struct next_fnfieldlist));
|
||||||
|
|
||||||
|
/* The following is code to work around cfront generated stabs.
|
||||||
|
The stabs contains full mangled name for each field.
|
||||||
|
We try to demangle the name and extract the field name out of it. */
|
||||||
|
{
|
||||||
|
char *dem, *dem_p, *dem_args;
|
||||||
|
int dem_len;
|
||||||
|
dem = cplus_demangle (fname, DMGL_ANSI | DMGL_PARAMS);
|
||||||
|
if (dem != NULL)
|
||||||
|
{
|
||||||
|
dem_p = strrchr (dem, ':');
|
||||||
|
if (dem_p != 0 && *(dem_p-1)==':')
|
||||||
|
dem_p++;
|
||||||
|
/* get rid of args */
|
||||||
|
dem_args = strchr (dem_p, '(');
|
||||||
|
if (dem_args == NULL)
|
||||||
|
dem_len = strlen(dem_p);
|
||||||
|
else
|
||||||
|
dem_len = dem_args - dem_p;
|
||||||
|
main_fn_name =
|
||||||
|
obsavestring (dem_p, dem_len, &objfile -> type_obstack);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
main_fn_name =
|
||||||
|
obsavestring (fname, strlen(fname), &objfile -> type_obstack);
|
||||||
|
}
|
||||||
|
} /* end of code for cfront work around */
|
||||||
|
|
||||||
|
new_fnlist -> fn_fieldlist.name = main_fn_name;
|
||||||
|
|
||||||
|
/*-------------------------------------------------*/
|
||||||
|
/* Set up the sublists
|
||||||
|
Sublists are stuff like args, static, visibility, etc.
|
||||||
|
so in ARM, we have to set that info some other way.
|
||||||
|
Multiple sublists happen if overloading
|
||||||
|
eg: foo::26=##1;:;2A.;
|
||||||
|
In g++, we'd loop here thru all the sublists... */
|
||||||
|
new_sublist =
|
||||||
|
(struct next_fnfield *) xmalloc (sizeof (struct next_fnfield));
|
||||||
|
make_cleanup (free, new_sublist);
|
||||||
|
memset (new_sublist, 0, sizeof (struct next_fnfield));
|
||||||
|
|
||||||
|
/* eat 1; from :;2A.; */
|
||||||
|
new_sublist -> fn_field.type = SYMBOL_TYPE(ref_func); /* normally takes a read_type */
|
||||||
|
/* make this type look like a method stub for gdb */
|
||||||
|
TYPE_FLAGS (new_sublist -> fn_field.type) |= TYPE_FLAG_STUB;
|
||||||
|
TYPE_CODE (new_sublist -> fn_field.type) = TYPE_CODE_METHOD;
|
||||||
|
|
||||||
|
/* If this is just a stub, then we don't have the real name here. */
|
||||||
|
if (TYPE_FLAGS (new_sublist -> fn_field.type) & TYPE_FLAG_STUB)
|
||||||
|
{
|
||||||
|
if (!TYPE_DOMAIN_TYPE (new_sublist -> fn_field.type))
|
||||||
|
TYPE_DOMAIN_TYPE (new_sublist -> fn_field.type) = type;
|
||||||
|
new_sublist -> fn_field.is_stub = 1;
|
||||||
|
}
|
||||||
|
/* physname used later in mangling; eg PFs_i,5 for foo__1aFPFs_i
|
||||||
|
physname gets strcat'd in order to recreate the onto mangled name */
|
||||||
|
pname = get_cfront_method_physname(fname);
|
||||||
|
new_sublist -> fn_field.physname = savestring (pname, strlen(pname));
|
||||||
|
|
||||||
|
|
||||||
|
/* Set this member function's visibility fields.
|
||||||
|
Unable to distinguish access from stabs definition!
|
||||||
|
Assuming public for now. FIXME!
|
||||||
|
(for private, set new_sublist->fn_field.is_private = 1,
|
||||||
|
for public, set new_sublist->fn_field.is_protected = 1) */
|
||||||
|
|
||||||
|
/* Unable to distinguish const/volatile from stabs definition!
|
||||||
|
Assuming normal for now. FIXME!
|
||||||
|
new_sublist -> fn_field.is_const = 0;
|
||||||
|
new_sublist -> fn_field.is_volatile = 0; /* volatile not implemented in cfront */
|
||||||
|
|
||||||
|
/* set virtual/static function info
|
||||||
|
How to get vtable offsets ?
|
||||||
|
Assuming normal for now FIXME!!
|
||||||
|
For vtables, figure out from whence this virtual function came.
|
||||||
|
It may belong to virtual function table of
|
||||||
|
one of its baseclasses.
|
||||||
|
set:
|
||||||
|
new_sublist -> fn_field.voffset = vtable offset,
|
||||||
|
new_sublist -> fn_field.fcontext = look_ahead_type;
|
||||||
|
where look_ahead_type is type of baseclass */
|
||||||
|
if (is_static)
|
||||||
|
new_sublist -> fn_field.voffset = VOFFSET_STATIC;
|
||||||
|
else /* normal member function. */
|
||||||
|
new_sublist -> fn_field.voffset = 0;
|
||||||
|
new_sublist -> fn_field.fcontext = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/* prepare new sublist */
|
||||||
|
new_sublist -> next = sublist;
|
||||||
|
sublist = new_sublist;
|
||||||
|
length++;
|
||||||
|
/* In g++, we loop thu sublists - now we set from function */
|
||||||
|
|
||||||
|
new_fnlist -> fn_fieldlist.fn_fields = (struct fn_field *)
|
||||||
|
obstack_alloc (&objfile -> type_obstack,
|
||||||
|
sizeof (struct fn_field) * length);
|
||||||
|
memset (new_fnlist -> fn_fieldlist.fn_fields, 0,
|
||||||
|
sizeof (struct fn_field) * length);
|
||||||
|
for (i = length; (i--, sublist); sublist = sublist -> next)
|
||||||
|
{
|
||||||
|
new_fnlist -> fn_fieldlist.fn_fields[i] = sublist -> fn_field;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_fnlist -> fn_fieldlist.length = length;
|
||||||
|
new_fnlist -> next = fip -> fnlist;
|
||||||
|
fip -> fnlist = new_fnlist;
|
||||||
|
nfn_fields++;
|
||||||
|
total_length += length;
|
||||||
|
STABS_CONTINUE (pp, objfile); /* handle \\ */
|
||||||
|
} /* end of loop */
|
||||||
|
|
||||||
|
if (nfn_fields)
|
||||||
|
{
|
||||||
|
/* type should already have space */
|
||||||
|
TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
|
||||||
|
TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * nfn_fields);
|
||||||
|
memset (TYPE_FN_FIELDLISTS (type), 0,
|
||||||
|
sizeof (struct fn_fieldlist) * nfn_fields);
|
||||||
|
TYPE_NFN_FIELDS (type) = nfn_fields;
|
||||||
|
TYPE_NFN_FIELDS_TOTAL (type) = total_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* end of scope for reading member func */
|
||||||
|
|
||||||
|
/* eg: ";;" */
|
||||||
|
/* skip trailing ';' and bump count of number of fields seen */
|
||||||
|
if (**pp == ';')
|
||||||
|
(*pp)++;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This routine fixes up partial cfront types that were created
|
||||||
|
while parsing the stabs. The main need for this function is
|
||||||
|
to add information such as methods to classes.
|
||||||
|
Examples of "p": "sA;;__ct__1AFv foo__1AFv ;;;" */
|
||||||
|
void
|
||||||
|
resolve_cont(objfile, sym, p)
|
||||||
|
struct objfile * objfile;
|
||||||
|
struct symbol * sym;
|
||||||
|
char * p;
|
||||||
|
{
|
||||||
|
struct symbol * ref_sym=0;
|
||||||
|
char * sname;
|
||||||
|
/* snarfed from read_struct_type */
|
||||||
|
struct field_info fi;
|
||||||
|
struct field_info * fip = &fi;
|
||||||
|
struct type *type;
|
||||||
|
struct cleanup *back_to;
|
||||||
|
|
||||||
|
/* need to make sure that fi isn't gunna conflict with struct
|
||||||
|
in case struct already had some fnfs */
|
||||||
|
fi.list = NULL;
|
||||||
|
fi.fnlist = NULL;
|
||||||
|
back_to = make_cleanup (null_cleanup, 0);
|
||||||
|
|
||||||
|
/* we only accept structs, classes and unions at the moment.
|
||||||
|
Other continuation types include t (typedef), r (long dbl), ...
|
||||||
|
We may want to add support for them as well;
|
||||||
|
right now they are handled by duplicating the symbol information
|
||||||
|
into the type information (see define_symbol) */
|
||||||
|
if (*p != 's' /* structs */
|
||||||
|
&& *p != 'c' /* class */
|
||||||
|
&& *p != 'u') /* union */
|
||||||
|
return; /* only handle C++ types */
|
||||||
|
p++;
|
||||||
|
|
||||||
|
/* get symbol typs name and validate
|
||||||
|
eg: p = "A;;__ct__1AFv foo__1AFv ;;;" */
|
||||||
|
sname = get_substring(&p,';');
|
||||||
|
if (!sname || strcmp(sname,SYMBOL_NAME(sym)))
|
||||||
|
error("Internal error: base symbol type name does not match\n");
|
||||||
|
|
||||||
|
/* find symbol's internal gdb reference */
|
||||||
|
ref_sym = lookup_symbol (SYMBOL_NAME(sym), 0, STRUCT_NAMESPACE, 0, 0); /*demangled_name*/
|
||||||
|
/* This is the real sym that we want;
|
||||||
|
sym was a temp hack to make debugger happy */
|
||||||
|
/* ref_sym should already have space */
|
||||||
|
type = SYMBOL_TYPE(ref_sym);
|
||||||
|
|
||||||
|
|
||||||
|
/* Now read the baseclasses, if any, read the regular C struct or C++
|
||||||
|
class member fields, attach the fields to the type, read the C++
|
||||||
|
member functions, attach them to the type, and then read any tilde
|
||||||
|
field (baseclass specifier for the class holding the main vtable). */
|
||||||
|
|
||||||
|
if (!read_cfront_baseclasses (&fi, &p, type, objfile)
|
||||||
|
/* g++ does this next, but cfront already did this:
|
||||||
|
|| !read_struct_fields (&fi, &p, type, objfile) */
|
||||||
|
|| !attach_fields_to_type (&fi, type, objfile)
|
||||||
|
|| !read_cfront_member_functions (&fi, &p, type, objfile)
|
||||||
|
|| !attach_fn_fields_to_type (&fi, type)
|
||||||
|
/* g++ does this next, but cfront doesn't seem to have this:
|
||||||
|
|| !read_tilde_fields (&fi, &p, type, objfile) */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
type = error_type (&p, objfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
do_cleanups (back_to);
|
||||||
|
}
|
||||||
|
/* End of code added to support parsing of ARM/Cfront stabs strings */
|
||||||
|
|
||||||
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
struct symbol *
|
struct symbol *
|
||||||
define_symbol (valu, string, desc, type, objfile)
|
define_symbol (valu, string, desc, type, objfile)
|
||||||
@@ -1215,6 +1698,30 @@ define_symbol (valu, string, desc, type, objfile)
|
|||||||
add_symbol_to_list (sym, &local_symbols);
|
add_symbol_to_list (sym, &local_symbols);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* New code added to support cfront stabs strings */
|
||||||
|
/* Note: case 'P' already handled above */
|
||||||
|
case 'Z':
|
||||||
|
/* Cfront type continuation coming up!
|
||||||
|
find the original definition and add to it.
|
||||||
|
We'll have to do this for the typedef too,
|
||||||
|
since we clloned the symbol to define a type in read_type.
|
||||||
|
Stabs info examples:
|
||||||
|
__1C :Ztl
|
||||||
|
foo__1CFv :ZtF (first def foo__1CFv:F(0,3);(0,24))
|
||||||
|
C:ZsC;;__ct__1CFv func1__1CFv func2__1CFv ... ;;;
|
||||||
|
where C is the name of the class. */
|
||||||
|
/* can't lookup symbol yet 'cuz symbols not read yet
|
||||||
|
so we save it for processing later */
|
||||||
|
process_later(sym,p);
|
||||||
|
SYMBOL_TYPE (sym) = error_type (&p, objfile); /* FIXME! change later */
|
||||||
|
SYMBOL_CLASS (sym) = LOC_CONST;
|
||||||
|
SYMBOL_VALUE (sym) = 0;
|
||||||
|
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
|
||||||
|
/* don't add to list - we'll delete it later when
|
||||||
|
we add the continuation to the real sym */
|
||||||
|
return sym;
|
||||||
|
/* End of new code added to support cfront stabs strings */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
SYMBOL_TYPE (sym) = error_type (&p, objfile);
|
SYMBOL_TYPE (sym) = error_type (&p, objfile);
|
||||||
SYMBOL_CLASS (sym) = LOC_CONST;
|
SYMBOL_CLASS (sym) = LOC_CONST;
|
||||||
@@ -1349,7 +1856,6 @@ read_type (pp, objfile)
|
|||||||
/* Skip the '='.
|
/* Skip the '='.
|
||||||
Also skip the type descriptor - we get it below with (*pp)[-1]. */
|
Also skip the type descriptor - we get it below with (*pp)[-1]. */
|
||||||
(*pp)+=2;
|
(*pp)+=2;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1897,11 +2403,6 @@ rs6000_builtin_type (typenum)
|
|||||||
|
|
||||||
/* This page contains subroutines of read_type. */
|
/* This page contains subroutines of read_type. */
|
||||||
|
|
||||||
#define VISIBILITY_PRIVATE '0' /* Stabs character for private field */
|
|
||||||
#define VISIBILITY_PROTECTED '1' /* Stabs character for protected fld */
|
|
||||||
#define VISIBILITY_PUBLIC '2' /* Stabs character for public field */
|
|
||||||
#define VISIBILITY_IGNORE '9' /* Optimized out or zero length */
|
|
||||||
|
|
||||||
/* Read member function stabs info for C++ classes. The form of each member
|
/* Read member function stabs info for C++ classes. The form of each member
|
||||||
function data is:
|
function data is:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user