Add new support for parsing cfront stabs.
This commit is contained in:
parent
50b802e0f5
commit
94f5a25f2e
118
gdb/dbxread.c
118
gdb/dbxread.c
|
@ -1,5 +1,5 @@
|
|||
/* 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.
|
||||
|
||||
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/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
|
||||
of the psymtab. */
|
||||
|
@ -242,7 +245,7 @@ static void
|
|||
init_bincl_list PARAMS ((int, struct objfile *));
|
||||
|
||||
static char *
|
||||
dbx_next_symbol_text PARAMS ((void));
|
||||
dbx_next_symbol_text PARAMS ((struct objfile *));
|
||||
|
||||
static void
|
||||
fill_symbuf PARAMS ((bfd *));
|
||||
|
@ -706,6 +709,7 @@ dbx_symfile_init (objfile)
|
|||
DBX_STRINGTAB (objfile) =
|
||||
(char *) obstack_alloc (&objfile -> psymbol_obstack,
|
||||
DBX_STRINGTAB_SIZE (objfile));
|
||||
OBJSTAT (objfile, sz_strtab += DBX_STRINGTAB_SIZE (objfile));
|
||||
|
||||
/* 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_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
|
||||
object file boundaries. */
|
||||
static char *last_function_name;
|
||||
|
@ -825,12 +891,14 @@ fill_symbuf (sym_bfd)
|
|||
call this function to get the continuation. */
|
||||
|
||||
static char *
|
||||
dbx_next_symbol_text ()
|
||||
dbx_next_symbol_text (objfile)
|
||||
struct objfile *objfile;
|
||||
{
|
||||
if (symbuf_idx == symbuf_end)
|
||||
fill_symbuf (symfile_bfd);
|
||||
symnum++;
|
||||
SWAP_SYMBOL(&symbuf[symbuf_idx], symfile_bfd);
|
||||
OBJSTAT (objfile, n_stabs++);
|
||||
return symbuf[symbuf_idx++].n_strx + stringtab_global
|
||||
+ file_string_table_offset;
|
||||
}
|
||||
|
@ -1066,6 +1134,7 @@ read_dbx_symtab (section_offsets, objfile, text_addr, text_size)
|
|||
int nsl;
|
||||
int past_first_source_file = 0;
|
||||
CORE_ADDR last_o_file_start = 0;
|
||||
CORE_ADDR last_function_start = 0;
|
||||
struct cleanup *back_to;
|
||||
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;
|
||||
|
||||
SWAP_SYMBOL (bufp, abfd);
|
||||
OBJSTAT (objfile, n_stabs++);
|
||||
|
||||
/* Ok. There is a lot of code duplicated in the rest of this
|
||||
switch statement (for efficiency reasons). Since I don't
|
||||
|
@ -1207,8 +1277,8 @@ start_psymtab (objfile, section_offsets,
|
|||
char *filename;
|
||||
CORE_ADDR textlow;
|
||||
int ldsymoff;
|
||||
struct partial_symbol *global_syms;
|
||||
struct partial_symbol *static_syms;
|
||||
struct partial_symbol **global_syms;
|
||||
struct partial_symbol **static_syms;
|
||||
{
|
||||
struct partial_symtab *result =
|
||||
start_psymtab_common(objfile, section_offsets,
|
||||
|
@ -1561,6 +1631,7 @@ read_ofile_symtab (pst)
|
|||
fill_symbuf (abfd);
|
||||
bufp = &symbuf[symbuf_idx++];
|
||||
SWAP_SYMBOL (bufp, abfd);
|
||||
OBJSTAT (objfile, n_stabs++);
|
||||
|
||||
SET_NAMESTRING ();
|
||||
|
||||
|
@ -1616,6 +1687,7 @@ read_ofile_symtab (pst)
|
|||
fill_symbuf(abfd);
|
||||
bufp = &symbuf[symbuf_idx++];
|
||||
SWAP_SYMBOL (bufp, abfd);
|
||||
OBJSTAT (objfile, n_stabs++);
|
||||
|
||||
type = bufp->n_type;
|
||||
|
||||
|
@ -1669,8 +1741,17 @@ read_ofile_symtab (pst)
|
|||
if (last_source_start_addr == 0)
|
||||
last_source_start_addr = text_offset;
|
||||
|
||||
pst->symtab = end_symtab (text_offset + text_size, 0, 0, objfile,
|
||||
SECT_OFF_TEXT);
|
||||
/* In reordered executables last_source_start_addr may not be the
|
||||
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 ();
|
||||
}
|
||||
|
||||
|
@ -1745,6 +1826,21 @@ process_one_symbol (type, desc, valu, name, section_offsets, objfile)
|
|||
{
|
||||
case N_FUN:
|
||||
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 */
|
||||
valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
|
||||
goto define_a_symbol;
|
||||
|
@ -1896,7 +1992,7 @@ process_one_symbol (type, desc, valu, name, section_offsets, objfile)
|
|||
patch_subfile_names (current_subfile, name);
|
||||
break; /* Ignore repeated SOs */
|
||||
}
|
||||
end_symtab (valu, 0, 0, objfile, SECT_OFF_TEXT);
|
||||
end_symtab (valu, objfile, SECT_OFF_TEXT);
|
||||
end_stabs ();
|
||||
}
|
||||
|
||||
|
@ -2131,7 +2227,8 @@ process_one_symbol (type, desc, valu, name, section_offsets, objfile)
|
|||
&& SYMBOL_NAME (m) [l] == '\0')
|
||||
/* last_pc_address was in this function */
|
||||
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')
|
||||
/* last_pc_address was in last function */
|
||||
valu = SYMBOL_VALUE (m+1);
|
||||
|
@ -2268,6 +2365,7 @@ coffstab_build_psymtabs (objfile, section_offsets, mainline,
|
|||
error ("ridiculous string table size: %d bytes", stabstrsize);
|
||||
DBX_STRINGTAB (objfile) = (char *)
|
||||
obstack_alloc (&objfile->psymbol_obstack, stabstrsize+1);
|
||||
OBJSTAT (objfile, sz_strtab += stabstrsize+1);
|
||||
|
||||
/* 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);
|
||||
DBX_STRINGTAB (objfile) = (char *)
|
||||
obstack_alloc (&objfile->psymbol_obstack, stabstrsize+1);
|
||||
OBJSTAT (objfile, sz_strtab += stabstrsize+1);
|
||||
|
||||
/* 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));
|
||||
DBX_STRINGTAB (objfile) = (char *)
|
||||
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. */
|
||||
|
||||
|
|
196
gdb/gdbtypes.c
196
gdb/gdbtypes.c
|
@ -971,6 +971,199 @@ check_typedef (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.
|
||||
|
||||
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);
|
||||
|
||||
f = TYPE_FN_FIELDLIST1 (type, i);
|
||||
f = TYPE_FN_FIELDLIST1 (type, i);
|
||||
|
||||
TYPE_FN_FIELD_PHYSNAME (f, j) = mangled_name;
|
||||
|
||||
/* 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 '9':
|
||||
case '-':
|
||||
/* added to support cfront stabs strings */
|
||||
case 'Z': /* for definition continuations */
|
||||
case 'P': /* for prototypes */
|
||||
continue;
|
||||
|
||||
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
|
||||
#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 */
|
||||
struct symbol *
|
||||
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);
|
||||
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:
|
||||
SYMBOL_TYPE (sym) = error_type (&p, objfile);
|
||||
SYMBOL_CLASS (sym) = LOC_CONST;
|
||||
|
@ -1349,7 +1856,6 @@ read_type (pp, objfile)
|
|||
/* Skip the '='.
|
||||
Also skip the type descriptor - we get it below with (*pp)[-1]. */
|
||||
(*pp)+=2;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1897,11 +2403,6 @@ rs6000_builtin_type (typenum)
|
|||
|
||||
/* 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
|
||||
function data is:
|
||||
|
||||
|
|
Loading…
Reference in New Issue