mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-24 20:49:43 +00:00
* Check in Fred Fish's changes in these modules. Fred
will make ChangeLog entries for all of them.
This commit is contained in:
parent
8e48d87af6
commit
1ab3bf1b14
@ -44,6 +44,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include <sys/user.h> /* After a.out.h */
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
/* Work with core dump and executable files, for GDB.
|
||||
This code would be in core.c if it weren't machine-dependent. */
|
||||
|
@ -63,11 +63,11 @@ examine_prologue (pc, rsize, msize, mfp_used)
|
||||
{
|
||||
long insn;
|
||||
CORE_ADDR p = pc;
|
||||
int misc_index = find_pc_misc_function (pc);
|
||||
struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (pc);
|
||||
struct prologue_info *mi = 0;
|
||||
|
||||
if (misc_index >= 0)
|
||||
mi = (struct prologue_info *)misc_function_vector[misc_index].misc_info;
|
||||
if (msymbol != NULL)
|
||||
mi = (struct prologue_info *) msymbol -> misc_info;
|
||||
|
||||
if (mi != 0)
|
||||
{
|
||||
@ -247,13 +247,13 @@ examine_prologue (pc, rsize, msize, mfp_used)
|
||||
}
|
||||
|
||||
done:
|
||||
if (misc_index >= 0)
|
||||
if (msymbol != NULL)
|
||||
{
|
||||
if (mi == 0)
|
||||
{
|
||||
/* Add a new cache entry. */
|
||||
mi = (struct prologue_info *)xmalloc (sizeof (struct prologue_info));
|
||||
misc_function_vector[misc_index].misc_info = (char *)mi;
|
||||
msymbol -> misc_info = (char *)mi;
|
||||
mi->rsize_valid = 0;
|
||||
mi->msize_valid = 0;
|
||||
mi->mfp_valid = 0;
|
||||
|
@ -43,9 +43,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
void
|
||||
fetch_inferior_registers (regno)
|
||||
int regno;
|
||||
int regno; /* Original value discarded */
|
||||
{
|
||||
register int regno;
|
||||
register unsigned int regaddr;
|
||||
char buf[MAX_REGISTER_RAW_SIZE];
|
||||
register int i;
|
||||
@ -83,6 +82,7 @@ fetch_inferior_registers (regno)
|
||||
If REGNO is -1, do this for all registers.
|
||||
Otherwise, REGNO specifies which register (so we can save time). */
|
||||
|
||||
void
|
||||
store_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
|
539
gdb/buildsym.c
539
gdb/buildsym.c
File diff suppressed because it is too large
Load Diff
113
gdb/buildsym.h
113
gdb/buildsym.h
@ -17,6 +17,9 @@ 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 (BUILDSYM_H)
|
||||
#define BUILDSYM_H 1
|
||||
|
||||
/* This module provides definitions used for creating and adding to
|
||||
the symbol table. These routines are called from various symbol-
|
||||
file-reading routines.
|
||||
@ -33,36 +36,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
extern void add_symbol_to_list ();
|
||||
struct symbol *find_symbol_in_list ();
|
||||
extern void read_type_number ();
|
||||
extern struct type *read_type ();
|
||||
extern struct type *read_range_type ();
|
||||
extern struct type *read_enum_type ();
|
||||
extern struct type *read_struct_type ();
|
||||
extern struct type *read_array_type ();
|
||||
extern struct type **read_args ();
|
||||
extern struct type **dbx_lookup_type ();
|
||||
extern long read_number ();
|
||||
extern void finish_block ();
|
||||
extern struct blockvector *make_blockvector ();
|
||||
extern void add_undefined_type ();
|
||||
extern void really_free_pendings ();
|
||||
extern void start_subfile ();
|
||||
extern void push_subfile ();
|
||||
extern char *pop_subfile ();
|
||||
extern struct symtab *end_symtab ();
|
||||
extern void scan_file_globals ();
|
||||
extern void buildsym_new_init ();
|
||||
extern void buildsym_init ();
|
||||
extern struct context_stack *push_context ();
|
||||
extern void record_line ();
|
||||
extern void start_symtab ();
|
||||
extern struct symbol *define_symbol ();
|
||||
extern struct partial_symtab *start_psymtab ();
|
||||
extern void end_psymtab();
|
||||
|
||||
|
||||
/* Convert stab register number (from `r' declaration) to a gdb REGNUM. */
|
||||
|
||||
#ifndef STAB_REG_TO_REGNUM
|
||||
@ -309,4 +282,82 @@ extern struct complaint unknown_symtype_complaint;
|
||||
|
||||
/* Function to invoke get the next symbol. Return the symbol name. */
|
||||
|
||||
EXTERN char * (*next_symbol_text_func)();
|
||||
EXTERN char *(*next_symbol_text_func) PARAMS ((void));
|
||||
|
||||
extern void
|
||||
add_symbol_to_list PARAMS ((struct symbol *, struct pending **));
|
||||
|
||||
extern struct symbol *
|
||||
find_symbol_in_list PARAMS ((struct pending *, char *, int));
|
||||
|
||||
extern void
|
||||
read_type_number PARAMS ((char **, int *));
|
||||
|
||||
extern struct type *
|
||||
read_type PARAMS ((char **, struct objfile *));
|
||||
|
||||
extern struct type **
|
||||
dbx_lookup_type PARAMS ((int [2]));
|
||||
|
||||
extern long
|
||||
read_number PARAMS ((char **, int));
|
||||
|
||||
extern void
|
||||
finish_block PARAMS ((struct symbol *, struct pending **,
|
||||
struct pending_block *, CORE_ADDR, CORE_ADDR,
|
||||
struct objfile *));
|
||||
|
||||
extern void
|
||||
add_undefined_type PARAMS ((struct type *));
|
||||
|
||||
extern void
|
||||
really_free_pendings PARAMS ((int foo));
|
||||
|
||||
extern void
|
||||
start_subfile PARAMS ((char *, char *));
|
||||
|
||||
extern void
|
||||
push_subfile PARAMS ((void));
|
||||
|
||||
extern char *
|
||||
pop_subfile PARAMS ((void));
|
||||
|
||||
extern struct symtab *
|
||||
end_symtab PARAMS ((CORE_ADDR, int, int,struct objfile *));
|
||||
|
||||
extern void
|
||||
scan_file_globals PARAMS ((struct objfile *));
|
||||
|
||||
extern void
|
||||
buildsym_new_init PARAMS ((void));
|
||||
|
||||
extern void
|
||||
buildsym_init PARAMS ((void));
|
||||
|
||||
extern struct context_stack *
|
||||
push_context PARAMS ((int, CORE_ADDR));
|
||||
|
||||
extern void
|
||||
record_line PARAMS ((struct subfile *, int, CORE_ADDR));
|
||||
|
||||
extern void
|
||||
start_symtab PARAMS ((char *, char *, CORE_ADDR));
|
||||
|
||||
extern struct symbol *
|
||||
define_symbol PARAMS ((unsigned int, char *, int, int, struct objfile *));
|
||||
|
||||
extern struct partial_symtab *
|
||||
start_psymtab PARAMS ((struct objfile *, CORE_ADDR, char *, CORE_ADDR, int,
|
||||
struct partial_symbol *, struct partial_symbol *));
|
||||
|
||||
extern void
|
||||
end_psymtab PARAMS ((struct partial_symtab *, char **, int, int, CORE_ADDR,
|
||||
struct partial_symtab **, int));
|
||||
|
||||
extern void
|
||||
process_one_symbol PARAMS ((int, int, CORE_ADDR, char *, int));
|
||||
|
||||
extern int
|
||||
hashname PARAMS ((char *));
|
||||
|
||||
#endif /* defined (BUILDSYM_H) */
|
||||
|
153
gdb/c-exp.y
153
gdb/c-exp.y
@ -32,6 +32,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include <string.h>
|
||||
#include "defs.h"
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "frame.h"
|
||||
#include "expression.h"
|
||||
#include "parser-defs.h"
|
||||
@ -68,10 +69,17 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#define yyval c_val
|
||||
#define yylloc c_lloc
|
||||
|
||||
/* Forward decls */
|
||||
void yyerror ();
|
||||
static int parse_number ();
|
||||
int yyparse ();
|
||||
static void
|
||||
__yy_bcopy PARAMS ((char *, char *, int));
|
||||
|
||||
int
|
||||
yyparse PARAMS ((void));
|
||||
|
||||
int
|
||||
yylex PARAMS ((void));
|
||||
|
||||
void
|
||||
yyerror PARAMS ((char *));
|
||||
|
||||
/* #define YYDEBUG 1 */
|
||||
|
||||
@ -100,6 +108,12 @@ int yyparse ();
|
||||
int *ivec;
|
||||
}
|
||||
|
||||
%{
|
||||
/* YYSTYPE gets defined by %union */
|
||||
static int
|
||||
parse_number PARAMS ((char *, int, int, YYSTYPE *));
|
||||
%}
|
||||
|
||||
%type <voidval> exp exp1 type_exp start variable
|
||||
%type <tval> type typebase
|
||||
%type <tvec> nonempty_typelist
|
||||
@ -564,7 +578,7 @@ variable: typebase COLONCOLON name
|
||||
{
|
||||
char *name = copy_name ($2);
|
||||
struct symbol *sym;
|
||||
int i;
|
||||
struct minimal_symbol *msymbol;
|
||||
|
||||
sym =
|
||||
lookup_symbol (name, 0, VAR_NAMESPACE, 0, NULL);
|
||||
@ -575,31 +589,27 @@ variable: typebase COLONCOLON name
|
||||
write_exp_elt_opcode (OP_VAR_VALUE);
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < misc_function_count; i++)
|
||||
if (!strcmp (misc_function_vector[i].name, name))
|
||||
break;
|
||||
|
||||
if (i < misc_function_count)
|
||||
msymbol = lookup_minimal_symbol (name,
|
||||
(struct objfile *) NULL);
|
||||
if (msymbol != NULL)
|
||||
{
|
||||
enum misc_function_type mft =
|
||||
misc_function_vector[i].type;
|
||||
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
write_exp_elt_type (builtin_type_int);
|
||||
write_exp_elt_longcst ((LONGEST) misc_function_vector[i].address);
|
||||
write_exp_elt_longcst ((LONGEST) msymbol -> address);
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
write_exp_elt_opcode (UNOP_MEMVAL);
|
||||
if (mft == mf_data || mft == mf_bss)
|
||||
if (msymbol -> type == mst_data ||
|
||||
msymbol -> type == mst_bss)
|
||||
write_exp_elt_type (builtin_type_int);
|
||||
else if (mft == mf_text)
|
||||
else if (msymbol -> type == mst_text)
|
||||
write_exp_elt_type (lookup_function_type (builtin_type_int));
|
||||
else
|
||||
write_exp_elt_type (builtin_type_char);
|
||||
write_exp_elt_opcode (UNOP_MEMVAL);
|
||||
}
|
||||
else
|
||||
if (symtab_list == 0
|
||||
&& partial_symtab_list == 0)
|
||||
if (!have_full_symbols () && !have_partial_symbols ())
|
||||
error ("No symbol table is loaded. Use the \"file\" command.");
|
||||
else
|
||||
error ("No symbol \"%s\" in current context.", name);
|
||||
@ -662,35 +672,28 @@ variable: name_not_typename
|
||||
}
|
||||
else
|
||||
{
|
||||
register int i;
|
||||
struct minimal_symbol *msymbol;
|
||||
register char *arg = copy_name ($1.stoken);
|
||||
|
||||
/* FIXME, this search is linear! At least
|
||||
optimize the strcmp with a 1-char cmp... */
|
||||
for (i = 0; i < misc_function_count; i++)
|
||||
if (!strcmp (misc_function_vector[i].name, arg))
|
||||
break;
|
||||
|
||||
if (i < misc_function_count)
|
||||
msymbol = lookup_minimal_symbol (arg,
|
||||
(struct objfile *) NULL);
|
||||
if (msymbol != NULL)
|
||||
{
|
||||
enum misc_function_type mft =
|
||||
misc_function_vector[i].type;
|
||||
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
write_exp_elt_type (builtin_type_int);
|
||||
write_exp_elt_longcst ((LONGEST) misc_function_vector[i].address);
|
||||
write_exp_elt_longcst ((LONGEST) msymbol -> address);
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
write_exp_elt_opcode (UNOP_MEMVAL);
|
||||
if (mft == mf_data || mft == mf_bss)
|
||||
if (msymbol -> type == mst_data ||
|
||||
msymbol -> type == mst_bss)
|
||||
write_exp_elt_type (builtin_type_int);
|
||||
else if (mft == mf_text)
|
||||
else if (msymbol -> type == mst_text)
|
||||
write_exp_elt_type (lookup_function_type (builtin_type_int));
|
||||
else
|
||||
write_exp_elt_type (builtin_type_char);
|
||||
write_exp_elt_opcode (UNOP_MEMVAL);
|
||||
}
|
||||
else if (symtab_list == 0
|
||||
&& partial_symtab_list == 0)
|
||||
else if (!have_full_symbols () && !have_partial_symbols ())
|
||||
error ("No symbol table is loaded. Use the \"file\" command.");
|
||||
else
|
||||
error ("No symbol \"%s\" in current context.",
|
||||
@ -869,7 +872,7 @@ nonempty_typelist
|
||||
}
|
||||
| nonempty_typelist ',' type
|
||||
{ int len = sizeof (struct type *) * ++($<ivec>1[0]);
|
||||
$$ = (struct type **)xrealloc ($1, len);
|
||||
$$ = (struct type **)xrealloc ((char *) $1, len);
|
||||
$$[$<ivec>$[0]] = $3;
|
||||
}
|
||||
;
|
||||
@ -915,8 +918,6 @@ parse_number (p, len, parsed_float, putithere)
|
||||
register int base = input_radix;
|
||||
int unsigned_p = 0;
|
||||
|
||||
extern double atof ();
|
||||
|
||||
if (parsed_float)
|
||||
{
|
||||
/* It's a float since it contains a point or an exponent. */
|
||||
@ -1535,53 +1536,69 @@ void
|
||||
_initialize_c_exp ()
|
||||
{
|
||||
builtin_type_void =
|
||||
init_type (TYPE_CODE_VOID, 1, 0,
|
||||
"void");
|
||||
init_type (TYPE_CODE_VOID, 1,
|
||||
0,
|
||||
"void", (struct objfile *) NULL);
|
||||
builtin_type_char =
|
||||
init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, 0,
|
||||
"char");
|
||||
init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"char", (struct objfile *) NULL);
|
||||
builtin_type_unsigned_char =
|
||||
init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, 1,
|
||||
"unsigned char");
|
||||
init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED,
|
||||
"unsigned char", (struct objfile *) NULL);
|
||||
builtin_type_short =
|
||||
init_type (TYPE_CODE_INT, TARGET_SHORT_BIT / TARGET_CHAR_BIT, 0,
|
||||
"short");
|
||||
init_type (TYPE_CODE_INT, TARGET_SHORT_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"short", (struct objfile *) NULL);
|
||||
builtin_type_unsigned_short =
|
||||
init_type (TYPE_CODE_INT, TARGET_SHORT_BIT / TARGET_CHAR_BIT, 1,
|
||||
"unsigned short");
|
||||
init_type (TYPE_CODE_INT, TARGET_SHORT_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED,
|
||||
"unsigned short", (struct objfile *) NULL);
|
||||
builtin_type_int =
|
||||
init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT, 0,
|
||||
"int");
|
||||
init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"int", (struct objfile *) NULL);
|
||||
builtin_type_unsigned_int =
|
||||
init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT, 1,
|
||||
"unsigned int");
|
||||
init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED,
|
||||
"unsigned int", (struct objfile *) NULL);
|
||||
builtin_type_long =
|
||||
init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT, 0,
|
||||
"long");
|
||||
init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"long", (struct objfile *) NULL);
|
||||
builtin_type_unsigned_long =
|
||||
init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT, 1,
|
||||
"unsigned long");
|
||||
init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED,
|
||||
"unsigned long", (struct objfile *) NULL);
|
||||
builtin_type_long_long =
|
||||
init_type (TYPE_CODE_INT, TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT, 0,
|
||||
"long long");
|
||||
init_type (TYPE_CODE_INT, TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"long long", (struct objfile *) NULL);
|
||||
builtin_type_unsigned_long_long =
|
||||
init_type (TYPE_CODE_INT, TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT, 1,
|
||||
"unsigned long long");
|
||||
init_type (TYPE_CODE_INT, TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED,
|
||||
"unsigned long long", (struct objfile *) NULL);
|
||||
builtin_type_float =
|
||||
init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT, 0,
|
||||
"float");
|
||||
init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"float", (struct objfile *) NULL);
|
||||
builtin_type_double =
|
||||
init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT, 0,
|
||||
"double");
|
||||
init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"double", (struct objfile *) NULL);
|
||||
builtin_type_long_double =
|
||||
init_type (TYPE_CODE_FLT, TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT, 0,
|
||||
"long double");
|
||||
init_type (TYPE_CODE_FLT, TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"long double", (struct objfile *) NULL);
|
||||
builtin_type_complex =
|
||||
init_type (TYPE_CODE_FLT, TARGET_COMPLEX_BIT / TARGET_CHAR_BIT, 0,
|
||||
"complex");
|
||||
init_type (TYPE_CODE_FLT, TARGET_COMPLEX_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"complex", (struct objfile *) NULL);
|
||||
builtin_type_double_complex =
|
||||
init_type (TYPE_CODE_FLT, TARGET_DOUBLE_COMPLEX_BIT / TARGET_CHAR_BIT, 0,
|
||||
"double complex");
|
||||
init_type (TYPE_CODE_FLT, TARGET_DOUBLE_COMPLEX_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"double complex", (struct objfile *) NULL);
|
||||
|
||||
add_language (&c_language_defn);
|
||||
add_language (&cplus_language_defn);
|
||||
|
@ -23,7 +23,28 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
extern char *getenv ();
|
||||
/* Prototypes for local functions */
|
||||
|
||||
static void
|
||||
undef_cmd_error PARAMS ((char *, char *));
|
||||
|
||||
static void
|
||||
show_user PARAMS ((char *, int));
|
||||
|
||||
static void
|
||||
show_user_1 PARAMS ((struct cmd_list_element *, FILE *));
|
||||
|
||||
static void
|
||||
make_command PARAMS ((char *, int));
|
||||
|
||||
static void
|
||||
shell_escape PARAMS ((char *, int));
|
||||
|
||||
static int
|
||||
parse_binary_operation PARAMS ((char *));
|
||||
|
||||
static void
|
||||
print_doc_line PARAMS ((FILE *, char *));
|
||||
|
||||
/* Add element named NAME to command list *LIST.
|
||||
FUN should be the function to execute the command;
|
||||
@ -39,7 +60,7 @@ struct cmd_list_element *
|
||||
add_cmd (name, class, fun, doc, list)
|
||||
char *name;
|
||||
enum command_class class;
|
||||
void (*fun) ();
|
||||
void (*fun) PARAMS ((char *, int));
|
||||
char *doc;
|
||||
struct cmd_list_element **list;
|
||||
{
|
||||
@ -50,7 +71,7 @@ add_cmd (name, class, fun, doc, list)
|
||||
c->next = *list;
|
||||
c->name = name;
|
||||
c->class = class;
|
||||
c->function = fun;
|
||||
c->function.cfunc = fun;
|
||||
c->doc = doc;
|
||||
c->prefixlist = 0;
|
||||
c->prefixname = (char *)NULL;
|
||||
@ -68,11 +89,13 @@ add_cmd (name, class, fun, doc, list)
|
||||
|
||||
/* Same as above, except that the abbrev_flag is set. */
|
||||
|
||||
#if 0 /* Currently unused */
|
||||
|
||||
struct cmd_list_element *
|
||||
add_abbrev_cmd (name, class, fun, doc, list)
|
||||
char *name;
|
||||
enum command_class class;
|
||||
void (*fun) ();
|
||||
void (*fun) PARAMS ((char *, int));
|
||||
char *doc;
|
||||
struct cmd_list_element **list;
|
||||
{
|
||||
@ -83,6 +106,8 @@ add_abbrev_cmd (name, class, fun, doc, list)
|
||||
return c;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct cmd_list_element *
|
||||
add_alias_cmd (name, oldname, class, abbrev_flag, list)
|
||||
char *name;
|
||||
@ -105,7 +130,7 @@ add_alias_cmd (name, oldname, class, abbrev_flag, list)
|
||||
return 0;
|
||||
}
|
||||
|
||||
c = add_cmd (name, class, old->function, old->doc, list);
|
||||
c = add_cmd (name, class, old->function.cfunc, old->doc, list);
|
||||
c->prefixlist = old->prefixlist;
|
||||
c->prefixname = old->prefixname;
|
||||
c->allow_unknown = old->allow_unknown;
|
||||
@ -124,7 +149,7 @@ add_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
|
||||
allow_unknown, list)
|
||||
char *name;
|
||||
enum command_class class;
|
||||
void (*fun) ();
|
||||
void (*fun) PARAMS ((char *, int));
|
||||
char *doc;
|
||||
struct cmd_list_element **prefixlist;
|
||||
char *prefixname;
|
||||
@ -142,10 +167,10 @@ add_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
|
||||
|
||||
struct cmd_list_element *
|
||||
add_abbrev_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
|
||||
allow_unknown, list)
|
||||
allow_unknown, list)
|
||||
char *name;
|
||||
enum command_class class;
|
||||
void (*fun) ();
|
||||
void (*fun) PARAMS ((char *, int));
|
||||
char *doc;
|
||||
struct cmd_list_element **prefixlist;
|
||||
char *prefixname;
|
||||
@ -175,6 +200,7 @@ not_just_help_class_command (args, from_tty, c)
|
||||
VAR_TYPE is the kind of thing we are setting.
|
||||
VAR is address of the variable being controlled by this command.
|
||||
DOC is the documentation string. */
|
||||
|
||||
struct cmd_list_element *
|
||||
add_set_cmd (name, class, var_type, var, doc, list)
|
||||
char *name;
|
||||
@ -300,7 +326,7 @@ help_cmd (command, stream)
|
||||
fputs_filtered (c->doc, stream);
|
||||
fputs_filtered ("\n", stream);
|
||||
|
||||
if (c->prefixlist == 0 && c->function != 0)
|
||||
if (c->prefixlist == 0 && c->function.cfunc != NULL)
|
||||
return;
|
||||
fprintf_filtered (stream, "\n");
|
||||
|
||||
@ -309,7 +335,7 @@ help_cmd (command, stream)
|
||||
help_list (*c->prefixlist, c->prefixname, all_commands, stream);
|
||||
|
||||
/* If this is a class name, print all of the commands in the class */
|
||||
if (c->function == 0)
|
||||
if (c->function.cfunc == NULL)
|
||||
help_list (cmdlist, "", c->class, stream);
|
||||
}
|
||||
|
||||
@ -413,7 +439,7 @@ print_doc_line (stream, str)
|
||||
* ALL_CLASSES to list all classes in list.
|
||||
*
|
||||
* Note that RECURSE will be active on *all* sublists, not just the
|
||||
* ones seclected by the criteria above (ie. the selection mechanism
|
||||
* ones selected by the criteria above (ie. the selection mechanism
|
||||
* is at the low level, not the high-level).
|
||||
*/
|
||||
void
|
||||
@ -430,8 +456,8 @@ help_cmd_list (list, class, prefix, recurse, stream)
|
||||
{
|
||||
if (c->abbrev_flag == 0 &&
|
||||
(class == all_commands
|
||||
|| (class == all_classes && c->function == 0)
|
||||
|| (class == c->class && c->function != 0)))
|
||||
|| (class == all_classes && c->function.cfunc == NULL)
|
||||
|| (class == c->class && c->function.cfunc != NULL)))
|
||||
{
|
||||
fprintf_filtered (stream, "%s%s -- ", prefix, c->name);
|
||||
print_doc_line (stream, c->doc);
|
||||
@ -519,7 +545,7 @@ lookup_cmd_1 (text, clist, result_list, ignore_help_classes)
|
||||
nfound = 0;
|
||||
for (c = clist; c; c = c->next)
|
||||
if (!strncmp (command, c->name, len)
|
||||
&& (!ignore_help_classes || c->function))
|
||||
&& (!ignore_help_classes || c->function.cfunc))
|
||||
{
|
||||
found = c;
|
||||
nfound++;
|
||||
@ -587,7 +613,7 @@ lookup_cmd_1 (text, clist, result_list, ignore_help_classes)
|
||||
|
||||
/* All this hair to move the space to the front of cmdtype */
|
||||
|
||||
void
|
||||
static void
|
||||
undef_cmd_error (cmdtype, q)
|
||||
char *cmdtype, *q;
|
||||
{
|
||||
@ -881,7 +907,7 @@ complete_on_cmdlist (list, text)
|
||||
for (ptr = list; ptr; ptr = ptr->next)
|
||||
if (!strncmp (ptr->name, text, textlen)
|
||||
&& !ptr->abbrev_flag
|
||||
&& (ptr->function
|
||||
&& (ptr->function.cfunc
|
||||
|| ptr->prefixlist))
|
||||
{
|
||||
if (matches == sizeof_matchlist)
|
||||
@ -967,7 +993,7 @@ do_setshow_command (arg, from_tty, c)
|
||||
arg = "";
|
||||
new = (char *) xmalloc (strlen (arg) + 2);
|
||||
p = arg; q = new;
|
||||
while (ch = *p++)
|
||||
while ((ch = *p++) != '\000')
|
||||
{
|
||||
if (ch == '\\')
|
||||
{
|
||||
@ -1069,7 +1095,7 @@ do_setshow_command (arg, from_tty, c)
|
||||
}
|
||||
else
|
||||
error ("gdb internal error: bad cmd_type in do_setshow_command");
|
||||
(*c->function) (NULL, from_tty, c);
|
||||
(*c->function.sfunc) (NULL, from_tty, c);
|
||||
}
|
||||
|
||||
/* Show all the settings in a list of show commands. */
|
||||
@ -1103,13 +1129,12 @@ shell_escape (arg, from_tty)
|
||||
{
|
||||
int rc, status, pid;
|
||||
char *p, *user_shell;
|
||||
extern char *rindex ();
|
||||
|
||||
if ((user_shell = (char *) getenv ("SHELL")) == NULL)
|
||||
user_shell = "/bin/sh";
|
||||
|
||||
/* Get the name of the shell for arg0 */
|
||||
if ((p = rindex (user_shell, '/')) == NULL)
|
||||
if ((p = strrchr (user_shell, '/')) == NULL)
|
||||
p = user_shell;
|
||||
else
|
||||
p++; /* Get past '/' */
|
||||
|
@ -258,6 +258,7 @@ fetch_inferior_registers (regno)
|
||||
/* Store our register values back into the inferior.
|
||||
For Convex, do this only once, right before resuming inferior. */
|
||||
|
||||
void
|
||||
store_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
|
@ -35,7 +35,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include <sys/ptrace.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* Extract the register values out of the core file and store
|
||||
them where `read_register' will find them.
|
||||
|
||||
|
@ -60,10 +60,6 @@
|
||||
#include <string.h>
|
||||
#else
|
||||
#include <strings.h>
|
||||
#define memcpy(s1, s2, n) bcopy ((s2), (s1), (n))
|
||||
#define memcmp(s1, s2, n) bcmp ((s2), (s1), (n))
|
||||
#define strchr index
|
||||
#define strrchr rindex
|
||||
#endif
|
||||
|
||||
/* This is '$' on systems where the assembler can deal with that.
|
||||
@ -187,49 +183,60 @@ typedef struct string {
|
||||
char *e; /* pointer after end of allocated space */
|
||||
} string;
|
||||
|
||||
#ifdef __STDC__
|
||||
static void string_need (string *s, int n);
|
||||
static void string_delete (string *s);
|
||||
static void string_init (string *s);
|
||||
static void string_clear (string *s);
|
||||
static int string_empty (string *s);
|
||||
static void string_append (string *p, const char *s);
|
||||
static void string_appends (string *p, string *s);
|
||||
static void string_appendn (string *p, const char *s, int n);
|
||||
static void string_prepend (string *p, const char *s);
|
||||
static void
|
||||
string_need PARAMS ((string *, int));
|
||||
|
||||
static void
|
||||
string_delete PARAMS ((string *));
|
||||
|
||||
static void
|
||||
string_init PARAMS ((string *));
|
||||
|
||||
static void
|
||||
string_clear PARAMS ((string *));
|
||||
|
||||
static int
|
||||
string_empty PARAMS ((string *));
|
||||
|
||||
static void
|
||||
string_append PARAMS ((string *, const char *));
|
||||
|
||||
static void
|
||||
string_appends PARAMS ((string *, string *));
|
||||
|
||||
static void
|
||||
string_appendn PARAMS ((string *, const char *, int));
|
||||
|
||||
static void
|
||||
string_prepend PARAMS ((string *, const char *));
|
||||
|
||||
static void
|
||||
string_prependn PARAMS ((string *, const char *, int));
|
||||
|
||||
static int
|
||||
get_count PARAMS ((const char **, int *));
|
||||
|
||||
static int
|
||||
do_args PARAMS ((const char **, string *, int));
|
||||
|
||||
static int
|
||||
do_type PARAMS ((const char **, string *, int));
|
||||
|
||||
static int
|
||||
do_arg PARAMS ((const char **, string *, int));
|
||||
|
||||
static void
|
||||
munge_function_name PARAMS ((string *, int));
|
||||
|
||||
static void
|
||||
remember_type PARAMS ((const char *, int));
|
||||
|
||||
#if 0
|
||||
static void string_prepends (string *p, string *s);
|
||||
#endif
|
||||
static void string_prependn (string *p, const char *s, int n);
|
||||
static int get_count (const char **type, int *count);
|
||||
static int do_args (const char **type, string *decl, int arg_mode);
|
||||
static int do_type (const char **type, string *result, int arg_mode);
|
||||
static int do_arg (const char **type, string *result, int arg_mode);
|
||||
static void munge_function_name (string *name, int arg_mode);
|
||||
static void remember_type (const char *type, int len);
|
||||
#else
|
||||
static void string_need ();
|
||||
static void string_delete ();
|
||||
static void string_init ();
|
||||
static void string_clear ();
|
||||
static int string_empty ();
|
||||
static void string_append ();
|
||||
static void string_appends ();
|
||||
static void string_appendn ();
|
||||
static void string_prepend ();
|
||||
#if 0
|
||||
static void string_prepends ();
|
||||
#endif
|
||||
static void string_prependn ();
|
||||
static int get_count ();
|
||||
static int do_args ();
|
||||
static int do_type ();
|
||||
static int do_arg ();
|
||||
static int do_args ();
|
||||
static void munge_function_name ();
|
||||
static void remember_type ();
|
||||
static void
|
||||
string_prepends PARAMS ((string *, string *));
|
||||
#endif
|
||||
|
||||
|
||||
/* Takes operator name as e.g. "++" and returns mangled
|
||||
operator name (e.g. "postincrement_expr"), or NULL if not found.
|
||||
|
||||
|
933
gdb/dwarfread.c
933
gdb/dwarfread.c
File diff suppressed because it is too large
Load Diff
136
gdb/elfread.c
136
gdb/elfread.c
@ -29,10 +29,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
* FIXME Still needs support for shared libraries. *
|
||||
* FIXME Still needs support for core files. *
|
||||
* FIXME The ".debug" and ".line" section names are hardwired. *
|
||||
* FIXME Still needs support ELF symbol tables (as distinct *
|
||||
* from DWARF support). Can use them to build the misc *
|
||||
* function vector at least. This is fairly trivial once *
|
||||
* bfd is extended to handle ELF symbol tables. *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
@ -43,15 +39,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "elf/external.h"
|
||||
#include "elf/internal.h"
|
||||
#include "bfd.h"
|
||||
#include "symfile.h"
|
||||
#include "symtab.h"
|
||||
#include "ansidecl.h"
|
||||
|
||||
extern int EXFUN (strcmp, (CONST char *a, CONST char *b));
|
||||
extern int EXFUN (dwarf_build_psymtabs,
|
||||
(int desc, char *filename, CORE_ADDR addr, int mainline,
|
||||
unsigned int dbfoff, unsigned int dbsize, unsigned int lnoffset,
|
||||
unsigned int lnsize, struct objfile *objfile));
|
||||
#include "symfile.h"
|
||||
|
||||
#define STREQ(a,b) (strcmp((a),(b))==0)
|
||||
|
||||
@ -62,6 +51,25 @@ struct elfinfo {
|
||||
unsigned int lnsize; /* Size of dwarf line number section */
|
||||
};
|
||||
|
||||
static void
|
||||
elf_symfile_init PARAMS ((struct sym_fns *));
|
||||
|
||||
static void
|
||||
elf_new_init PARAMS ((void));
|
||||
|
||||
static void
|
||||
elf_symfile_read PARAMS ((struct sym_fns *, CORE_ADDR, int));
|
||||
|
||||
static void
|
||||
elf_symtab_read PARAMS ((bfd *, CORE_ADDR, int, struct objfile *));
|
||||
|
||||
static void
|
||||
record_minimal_symbol PARAMS ((char *, CORE_ADDR, enum minimal_symbol_type,
|
||||
struct objfile *));
|
||||
|
||||
static void
|
||||
elf_locate_sections PARAMS ((bfd *, asection *, PTR));
|
||||
|
||||
/* We are called once per section from elf_symfile_read. We
|
||||
need to examine each section we are passed, check to see
|
||||
if it is something we are interested in processing, and
|
||||
@ -76,11 +84,14 @@ struct elfinfo {
|
||||
FIXME: The section names should not be hardwired strings. */
|
||||
|
||||
static void
|
||||
DEFUN(elf_locate_sections, (abfd, sectp, ei),
|
||||
bfd *abfd AND
|
||||
asection *sectp AND
|
||||
struct elfinfo *ei)
|
||||
elf_locate_sections (abfd, sectp, eip)
|
||||
bfd *abfd;
|
||||
asection *sectp;
|
||||
PTR eip;
|
||||
{
|
||||
register struct elfinfo *ei;
|
||||
|
||||
ei = (struct elfinfo *) eip;
|
||||
if (STREQ (sectp -> name, ".debug"))
|
||||
{
|
||||
ei -> dboffset = sectp -> filepos;
|
||||
@ -93,9 +104,11 @@ DEFUN(elf_locate_sections, (abfd, sectp, ei),
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 /* Currently unused */
|
||||
|
||||
char *
|
||||
DEFUN(elf_interpreter, (abfd),
|
||||
bfd *abfd)
|
||||
elf_interpreter (abfd)
|
||||
bfd *abfd;
|
||||
{
|
||||
sec_ptr interp_sec;
|
||||
unsigned size;
|
||||
@ -119,35 +132,35 @@ DEFUN(elf_interpreter, (abfd),
|
||||
return (interp);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
LOCAL FUNCTION
|
||||
|
||||
record_misc_function -- add entry to miscellaneous function vector
|
||||
record_minimal_symbol -- add entry to minimal symbol table
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
static void record_misc_function (char *name, CORE_ADDR address)
|
||||
static void record_minimal_symbol (char *name, CORE_ADDR address)
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
Given a pointer to the name of a symbol that should be added to the
|
||||
miscellaneous function vector, and the address associated with that
|
||||
symbol, records this information for later use in building the
|
||||
miscellaneous function vector.
|
||||
minimal symbol table and the address associated with that symbol, records
|
||||
this information for later use in building the minimal symbol table.
|
||||
|
||||
NOTES
|
||||
|
||||
FIXME: For now we just use mf_unknown as the type. This should be
|
||||
fixed.
|
||||
*/
|
||||
|
||||
static void
|
||||
DEFUN(record_misc_function, (name, address, mf_type),
|
||||
char *name AND CORE_ADDR address AND enum misc_function_type mf_type)
|
||||
record_minimal_symbol (name, address, ms_type, objfile)
|
||||
char *name;
|
||||
CORE_ADDR address;
|
||||
enum minimal_symbol_type ms_type;
|
||||
struct objfile *objfile;
|
||||
{
|
||||
prim_record_misc_function (obsavestring (name, strlen (name)), address,
|
||||
mf_type);
|
||||
name = obsavestring (name, strlen (name), &objfile -> symbol_obstack);
|
||||
prim_record_minimal_symbol (name, address, ms_type);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -158,22 +171,24 @@ LOCAL FUNCTION
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
void elf_symtab_read (bfd *abfd, CORE_ADDR addr, int mainline)
|
||||
void elf_symtab_read (bfd *abfd, CORE_ADDR addr, int mainline,
|
||||
struct objfile *objfile)
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
Given an open bfd, a base address to relocate symbols to, and a
|
||||
flag that specifies whether or not this bfd is for an executable
|
||||
or not (may be shared library for example), add all the global
|
||||
function and data symbols to the miscellaneous function vector.
|
||||
function and data symbols to the minimal symbol table.
|
||||
|
||||
*/
|
||||
|
||||
static void
|
||||
DEFUN (elf_symtab_read, (abfd, addr, mainline),
|
||||
bfd *abfd AND
|
||||
CORE_ADDR addr AND
|
||||
int mainline)
|
||||
elf_symtab_read (abfd, addr, mainline, objfile)
|
||||
bfd *abfd;
|
||||
CORE_ADDR addr;
|
||||
int mainline;
|
||||
struct objfile *objfile;
|
||||
{
|
||||
unsigned int storage_needed;
|
||||
asymbol *sym;
|
||||
@ -182,7 +197,7 @@ DEFUN (elf_symtab_read, (abfd, addr, mainline),
|
||||
unsigned int i;
|
||||
struct cleanup *back_to;
|
||||
CORE_ADDR symaddr;
|
||||
enum misc_function_type mf_type;
|
||||
enum minimal_symbol_type ms_type;
|
||||
|
||||
storage_needed = get_symtab_upper_bound (abfd);
|
||||
|
||||
@ -214,17 +229,17 @@ DEFUN (elf_symtab_read, (abfd, addr, mainline),
|
||||
no way of figuring this out for absolute symbols. */
|
||||
if (sym -> section -> flags & SEC_CODE)
|
||||
{
|
||||
mf_type = mf_text;
|
||||
ms_type = mst_text;
|
||||
}
|
||||
else if (sym -> section -> flags & SEC_DATA)
|
||||
{
|
||||
mf_type = mf_data;
|
||||
ms_type = mst_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
mf_type = mf_unknown;
|
||||
ms_type = mst_unknown;
|
||||
}
|
||||
record_misc_function ((char *) sym -> name, symaddr, mf_type);
|
||||
record_minimal_symbol ((char *) sym -> name, symaddr, ms_type, objfile);
|
||||
}
|
||||
}
|
||||
do_cleanups (back_to);
|
||||
@ -253,32 +268,32 @@ DEFUN (elf_symtab_read, (abfd, addr, mainline),
|
||||
Note that ELF files have a "minimal" symbol table, which looks a lot
|
||||
like a COFF symbol table, but has only the minimal information necessary
|
||||
for linking. We process this also, and just use the information to
|
||||
add to the misc function vector. This gives us some minimal debugging
|
||||
add to gdb's minimal symbol table. This gives us some minimal debugging
|
||||
capability even for files compiled without -g.
|
||||
*/
|
||||
|
||||
static void
|
||||
DEFUN(elf_symfile_read, (sf, addr, mainline),
|
||||
struct sym_fns *sf AND
|
||||
CORE_ADDR addr AND
|
||||
int mainline)
|
||||
elf_symfile_read (sf, addr, mainline)
|
||||
struct sym_fns *sf;
|
||||
CORE_ADDR addr;
|
||||
int mainline;
|
||||
{
|
||||
bfd *abfd = sf->objfile->obfd;
|
||||
struct elfinfo ei;
|
||||
struct cleanup *back_to;
|
||||
|
||||
init_misc_bunches ();
|
||||
back_to = make_cleanup (discard_misc_bunches, 0);
|
||||
init_minimal_symbol_collection ();
|
||||
back_to = make_cleanup (discard_minimal_symbols, 0);
|
||||
|
||||
/* Process the normal ELF symbol table first. */
|
||||
|
||||
elf_symtab_read (abfd, addr, mainline);
|
||||
elf_symtab_read (abfd, addr, mainline, sf->objfile);
|
||||
|
||||
/* Now process the DWARF debugging information, which is contained in
|
||||
special ELF sections. We first have to find them... */
|
||||
|
||||
(void) memset ((char *) &ei, 0, sizeof (ei));
|
||||
bfd_map_over_sections (abfd, elf_locate_sections, &ei);
|
||||
bfd_map_over_sections (abfd, elf_locate_sections, (PTR) &ei);
|
||||
if (ei.dboffset && ei.lnoffset)
|
||||
{
|
||||
dwarf_build_psymtabs (fileno ((FILE *)(abfd -> iostream)),
|
||||
@ -288,17 +303,18 @@ DEFUN(elf_symfile_read, (sf, addr, mainline),
|
||||
ei.lnoffset, ei.lnsize, sf->objfile);
|
||||
}
|
||||
|
||||
if (!partial_symtab_list)
|
||||
if (!have_partial_symbols ())
|
||||
{
|
||||
wrap_here ("");
|
||||
printf_filtered ("(no debugging symbols found)...");
|
||||
wrap_here ("");
|
||||
}
|
||||
|
||||
/* Go over the miscellaneous functions and install them in the
|
||||
miscellaneous function vector. */
|
||||
|
||||
condense_misc_bunches (!mainline);
|
||||
/* Install any minimal symbols that have been collected as the current
|
||||
minimal symbols for this objfile. */
|
||||
|
||||
install_minimal_symbols (!mainline, sf -> objfile);
|
||||
|
||||
do_cleanups (back_to);
|
||||
}
|
||||
|
||||
@ -310,7 +326,7 @@ DEFUN(elf_symfile_read, (sf, addr, mainline),
|
||||
just a stub. */
|
||||
|
||||
static void
|
||||
DEFUN_VOID (elf_new_init)
|
||||
elf_new_init ()
|
||||
{
|
||||
}
|
||||
|
||||
@ -324,8 +340,8 @@ DEFUN_VOID (elf_new_init)
|
||||
just a stub. */
|
||||
|
||||
static void
|
||||
DEFUN(elf_symfile_init, (sf),
|
||||
struct sym_fns *sf)
|
||||
elf_symfile_init (sf)
|
||||
struct sym_fns *sf;
|
||||
{
|
||||
}
|
||||
|
||||
@ -358,7 +374,7 @@ static struct sym_fns elf_sym_fns = {
|
||||
};
|
||||
|
||||
void
|
||||
DEFUN_VOID (_initialize_elfread)
|
||||
_initialize_elfread ()
|
||||
{
|
||||
add_symtab_fns (&elf_sym_fns);
|
||||
}
|
||||
|
956
gdb/gdbtypes.c
Normal file
956
gdb/gdbtypes.c
Normal file
@ -0,0 +1,956 @@
|
||||
/* Support routines for manipulating internal types for GDB.
|
||||
Copyright (C) 1992 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support, using pieces from other GDB modules.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 of the License, 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. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "defs.h"
|
||||
#include "bfd.h"
|
||||
#include "symtab.h"
|
||||
#include "symfile.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "expression.h"
|
||||
#include "language.h"
|
||||
#include "target.h"
|
||||
#include "value.h"
|
||||
|
||||
/* Alloc a new type structure and fill it with some defaults. If
|
||||
OBJFILE is non-NULL, then allocate the space for the type structure
|
||||
in that objfile's type_obstack. */
|
||||
|
||||
struct type *
|
||||
alloc_type (objfile)
|
||||
struct objfile *objfile;
|
||||
{
|
||||
register struct type *type;
|
||||
|
||||
/* Alloc the structure and start off with all fields zeroed. */
|
||||
|
||||
if (objfile == NULL)
|
||||
{
|
||||
type = (struct type *) xmalloc (sizeof (struct type));
|
||||
}
|
||||
else
|
||||
{
|
||||
type = (struct type *) obstack_alloc (&objfile -> type_obstack,
|
||||
sizeof (struct type));
|
||||
}
|
||||
(void) memset (type, 0, sizeof (struct type));
|
||||
|
||||
/* Initialize the fields that might not be zero. */
|
||||
|
||||
TYPE_CODE (type) = TYPE_CODE_UNDEF;
|
||||
TYPE_OBJFILE (type) = objfile;
|
||||
TYPE_VPTR_FIELDNO (type) = -1;
|
||||
|
||||
return (type);
|
||||
}
|
||||
|
||||
/* Given a type TYPE, return a type of pointers to that type.
|
||||
May need to construct such a type if this is the first use. */
|
||||
|
||||
struct type *
|
||||
lookup_pointer_type (type)
|
||||
struct type *type;
|
||||
{
|
||||
register struct type *ptype;
|
||||
|
||||
if ((ptype = TYPE_POINTER_TYPE (type)) == NULL)
|
||||
{
|
||||
/* This is the first time anyone wanted a pointer to a TYPE. */
|
||||
|
||||
ptype = alloc_type (TYPE_OBJFILE (type));
|
||||
TYPE_TARGET_TYPE (ptype) = type;
|
||||
TYPE_POINTER_TYPE (type) = ptype;
|
||||
|
||||
/* We assume the machine has only one representation for pointers! */
|
||||
/* FIXME: This confuses host<->target data representations, and is a
|
||||
poor assumption besides. */
|
||||
|
||||
TYPE_LENGTH (ptype) = sizeof (char *);
|
||||
TYPE_CODE (ptype) = TYPE_CODE_PTR;
|
||||
|
||||
}
|
||||
return (ptype);
|
||||
}
|
||||
|
||||
struct type *
|
||||
lookup_reference_type (type)
|
||||
struct type *type;
|
||||
{
|
||||
register struct type *rtype;
|
||||
|
||||
if ((rtype = TYPE_REFERENCE_TYPE (type)) == NULL)
|
||||
{
|
||||
/* This is the first time anyone wanted a pointer to a TYPE. */
|
||||
|
||||
rtype = alloc_type (TYPE_OBJFILE (type));
|
||||
TYPE_TARGET_TYPE (rtype) = type;
|
||||
TYPE_REFERENCE_TYPE (type) = rtype;
|
||||
|
||||
/* We assume the machine has only one representation for pointers! */
|
||||
/* FIXME: This confuses host<->target data representations, and is a
|
||||
poor assumption besides. */
|
||||
|
||||
TYPE_LENGTH (rtype) = sizeof (char *);
|
||||
TYPE_CODE (rtype) = TYPE_CODE_REF;
|
||||
|
||||
}
|
||||
return (rtype);
|
||||
}
|
||||
|
||||
/* Given a type TYPE, return a type of functions that return that type.
|
||||
May need to construct such a type if this is the first use. */
|
||||
|
||||
struct type *
|
||||
lookup_function_type (type)
|
||||
struct type *type;
|
||||
{
|
||||
register struct type *ptype;
|
||||
|
||||
if ((ptype = TYPE_FUNCTION_TYPE (type)) == NULL)
|
||||
{
|
||||
/* This is the first time anyone wanted a function returning a TYPE. */
|
||||
|
||||
ptype = alloc_type (TYPE_OBJFILE (type));
|
||||
TYPE_TARGET_TYPE (ptype) = type;
|
||||
TYPE_FUNCTION_TYPE (type) = ptype;
|
||||
|
||||
TYPE_LENGTH (ptype) = 1;
|
||||
TYPE_CODE (ptype) = TYPE_CODE_FUNC;
|
||||
}
|
||||
return (ptype);
|
||||
}
|
||||
|
||||
/* Implement direct support for MEMBER_TYPE in GNU C++.
|
||||
May need to construct such a type if this is the first use.
|
||||
The TYPE is the type of the member. The DOMAIN is the type
|
||||
of the aggregate that the member belongs to. */
|
||||
|
||||
struct type *
|
||||
lookup_member_type (type, domain)
|
||||
struct type *type;
|
||||
struct type *domain;
|
||||
{
|
||||
register struct type *mtype;
|
||||
|
||||
mtype = alloc_type (TYPE_OBJFILE (type));
|
||||
smash_to_member_type (mtype, domain, type);
|
||||
return (mtype);
|
||||
}
|
||||
|
||||
/* Allocate a stub method whose return type is TYPE.
|
||||
This apparently happens for speed of symbol reading, since parsing
|
||||
out the arguments to the method is cpu-intensive, the way we are doing
|
||||
it. So, we will fill in arguments later.
|
||||
This always returns a fresh type. */
|
||||
|
||||
struct type *
|
||||
allocate_stub_method (type)
|
||||
struct type *type;
|
||||
{
|
||||
struct type *mtype;
|
||||
|
||||
mtype = alloc_type (TYPE_OBJFILE (type));
|
||||
TYPE_TARGET_TYPE (mtype) = type;
|
||||
/* _DOMAIN_TYPE (mtype) = unknown yet */
|
||||
/* _ARG_TYPES (mtype) = unknown yet */
|
||||
TYPE_FLAGS (mtype) = TYPE_FLAG_STUB;
|
||||
TYPE_CODE (mtype) = TYPE_CODE_METHOD;
|
||||
TYPE_LENGTH (mtype) = 1;
|
||||
return (mtype);
|
||||
}
|
||||
|
||||
/* Create an array type. Elements will be of type TYPE, and there will
|
||||
be NUM of them.
|
||||
|
||||
Eventually this should be extended to take two more arguments which
|
||||
specify the bounds of the array and the type of the index.
|
||||
It should also be changed to be a "lookup" function, with the
|
||||
appropriate data structures added to the type field.
|
||||
Then read array type should call here. */
|
||||
|
||||
struct type *
|
||||
create_array_type (element_type, number)
|
||||
struct type *element_type;
|
||||
int number;
|
||||
{
|
||||
struct type *result_type;
|
||||
struct type *range_type;
|
||||
|
||||
result_type = alloc_type (TYPE_OBJFILE (element_type));
|
||||
|
||||
TYPE_CODE (result_type) = TYPE_CODE_ARRAY;
|
||||
TYPE_TARGET_TYPE (result_type) = element_type;
|
||||
TYPE_LENGTH (result_type) = number * TYPE_LENGTH (element_type);
|
||||
TYPE_NFIELDS (result_type) = 1;
|
||||
TYPE_FIELDS (result_type) = (struct field *)
|
||||
obstack_alloc (&TYPE_OBJFILE (result_type) -> type_obstack,
|
||||
sizeof (struct field));
|
||||
|
||||
{
|
||||
/* Create range type. */
|
||||
range_type = alloc_type (TYPE_OBJFILE (result_type));
|
||||
TYPE_CODE (range_type) = TYPE_CODE_RANGE;
|
||||
TYPE_TARGET_TYPE (range_type) = builtin_type_int; /* FIXME */
|
||||
|
||||
/* This should never be needed. */
|
||||
TYPE_LENGTH (range_type) = sizeof (int);
|
||||
|
||||
TYPE_NFIELDS (range_type) = 2;
|
||||
TYPE_FIELDS (range_type) = (struct field *)
|
||||
obstack_alloc (&TYPE_OBJFILE (range_type) -> type_obstack,
|
||||
2 * sizeof (struct field));
|
||||
TYPE_FIELD_BITPOS (range_type, 0) = 0; /* FIXME */
|
||||
TYPE_FIELD_BITPOS (range_type, 1) = number-1; /* FIXME */
|
||||
TYPE_FIELD_TYPE (range_type, 0) = builtin_type_int; /* FIXME */
|
||||
TYPE_FIELD_TYPE (range_type, 1) = builtin_type_int; /* FIXME */
|
||||
}
|
||||
TYPE_FIELD_TYPE(result_type,0)=range_type;
|
||||
TYPE_VPTR_FIELDNO (result_type) = -1;
|
||||
|
||||
return (result_type);
|
||||
}
|
||||
|
||||
|
||||
/* Smash TYPE to be a type of members of DOMAIN with type TO_TYPE.
|
||||
A MEMBER is a wierd thing -- it amounts to a typed offset into
|
||||
a struct, e.g. "an int at offset 8". A MEMBER TYPE doesn't
|
||||
include the offset (that's the value of the MEMBER itself), but does
|
||||
include the structure type into which it points (for some reason).
|
||||
|
||||
FIXME: When "smashing" the type, we preserve the objfile that the
|
||||
old type pointed to, since we aren't changing where the type is actually
|
||||
allocated. If the two types aren't associated with the same objfile,
|
||||
then we are in deep-s**t anyway... */
|
||||
|
||||
void
|
||||
smash_to_member_type (type, domain, to_type)
|
||||
struct type *type;
|
||||
struct type *domain;
|
||||
struct type *to_type;
|
||||
{
|
||||
struct objfile *objfile;
|
||||
|
||||
objfile = TYPE_OBJFILE (type);
|
||||
|
||||
(void) memset (type, 0, sizeof (struct type));
|
||||
TYPE_OBJFILE (type) = objfile;
|
||||
TYPE_TARGET_TYPE (type) = to_type;
|
||||
TYPE_DOMAIN_TYPE (type) = domain;
|
||||
TYPE_LENGTH (type) = 1; /* In practice, this is never needed. */
|
||||
TYPE_CODE (type) = TYPE_CODE_MEMBER;
|
||||
}
|
||||
|
||||
/* Smash TYPE to be a type of method of DOMAIN with type TO_TYPE.
|
||||
METHOD just means `function that gets an extra "this" argument'.
|
||||
|
||||
FIXME: When "smashing" the type, we preserve the objfile that the
|
||||
old type pointed to, since we aren't changing where the type is actually
|
||||
allocated. If the two types aren't associated with the same objfile,
|
||||
then we are in deep-s**t anyway... */
|
||||
|
||||
void
|
||||
smash_to_method_type (type, domain, to_type, args)
|
||||
struct type *type;
|
||||
struct type *domain;
|
||||
struct type *to_type;
|
||||
struct type **args;
|
||||
{
|
||||
struct objfile *objfile;
|
||||
|
||||
objfile = TYPE_OBJFILE (type);
|
||||
|
||||
(void) memset (type, 0, sizeof (struct type));
|
||||
TYPE_OBJFILE (type) = objfile;
|
||||
TYPE_TARGET_TYPE (type) = to_type;
|
||||
TYPE_DOMAIN_TYPE (type) = domain;
|
||||
TYPE_ARG_TYPES (type) = args;
|
||||
TYPE_LENGTH (type) = 1; /* In practice, this is never needed. */
|
||||
TYPE_CODE (type) = TYPE_CODE_METHOD;
|
||||
}
|
||||
|
||||
/* Return a typename for a struct/union/enum type
|
||||
without the tag qualifier. If the type has a NULL name,
|
||||
NULL is returned. */
|
||||
|
||||
char *
|
||||
type_name_no_tag (type)
|
||||
register const struct type *type;
|
||||
{
|
||||
register char *name;
|
||||
|
||||
if ((name = TYPE_NAME (type)) != NULL)
|
||||
{
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_STRUCT:
|
||||
if(!strncmp (name, "struct ", 7))
|
||||
{
|
||||
name += 7;
|
||||
}
|
||||
break;
|
||||
case TYPE_CODE_UNION:
|
||||
if(!strncmp (name, "union ", 6))
|
||||
{
|
||||
name += 6;
|
||||
}
|
||||
break;
|
||||
case TYPE_CODE_ENUM:
|
||||
if(!strncmp (name, "enum ", 5))
|
||||
{
|
||||
name += 5;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (name);
|
||||
}
|
||||
|
||||
/* Lookup a primitive type named NAME.
|
||||
Return zero if NAME is not a primitive type.*/
|
||||
|
||||
struct type *
|
||||
lookup_primitive_typename (name)
|
||||
char *name;
|
||||
{
|
||||
struct type ** const *p;
|
||||
|
||||
for (p = current_language -> la_builtin_type_vector; *p != NULL; p++)
|
||||
{
|
||||
if (!strcmp ((**p) -> name, name))
|
||||
{
|
||||
return (**p);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Lookup a typedef or primitive type named NAME,
|
||||
visible in lexical block BLOCK.
|
||||
If NOERR is nonzero, return zero if NAME is not suitably defined. */
|
||||
|
||||
struct type *
|
||||
lookup_typename (name, block, noerr)
|
||||
char *name;
|
||||
struct block *block;
|
||||
int noerr;
|
||||
{
|
||||
register struct symbol *sym;
|
||||
register struct type *tmp;
|
||||
|
||||
sym = lookup_symbol (name, block, VAR_NAMESPACE, 0, (struct symtab **) NULL);
|
||||
if (sym == NULL || SYMBOL_CLASS (sym) != LOC_TYPEDEF)
|
||||
{
|
||||
tmp = lookup_primitive_typename (name);
|
||||
if (tmp)
|
||||
{
|
||||
return (tmp);
|
||||
}
|
||||
else if (!tmp && noerr)
|
||||
{
|
||||
return (NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
error ("No type named %s.", name);
|
||||
}
|
||||
}
|
||||
return (SYMBOL_TYPE (sym));
|
||||
}
|
||||
|
||||
struct type *
|
||||
lookup_unsigned_typename (name)
|
||||
char *name;
|
||||
{
|
||||
char *uns = alloca (strlen (name) + 10);
|
||||
|
||||
strcpy (uns, "unsigned ");
|
||||
strcpy (uns + 9, name);
|
||||
return (lookup_typename (uns, (struct block *) NULL, 0));
|
||||
}
|
||||
|
||||
/* Lookup a structure type named "struct NAME",
|
||||
visible in lexical block BLOCK. */
|
||||
|
||||
struct type *
|
||||
lookup_struct (name, block)
|
||||
char *name;
|
||||
struct block *block;
|
||||
{
|
||||
register struct symbol *sym;
|
||||
|
||||
sym = lookup_symbol (name, block, STRUCT_NAMESPACE, 0,
|
||||
(struct symtab **) NULL);
|
||||
|
||||
if (sym == NULL)
|
||||
{
|
||||
error ("No struct type named %s.", name);
|
||||
}
|
||||
if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_STRUCT)
|
||||
{
|
||||
error ("This context has class, union or enum %s, not a struct.", name);
|
||||
}
|
||||
return (SYMBOL_TYPE (sym));
|
||||
}
|
||||
|
||||
/* Lookup a union type named "union NAME",
|
||||
visible in lexical block BLOCK. */
|
||||
|
||||
struct type *
|
||||
lookup_union (name, block)
|
||||
char *name;
|
||||
struct block *block;
|
||||
{
|
||||
register struct symbol *sym;
|
||||
|
||||
sym = lookup_symbol (name, block, STRUCT_NAMESPACE, 0,
|
||||
(struct symtab **) NULL);
|
||||
|
||||
if (sym == NULL)
|
||||
{
|
||||
error ("No union type named %s.", name);
|
||||
}
|
||||
if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_UNION)
|
||||
{
|
||||
error ("This context has class, struct or enum %s, not a union.", name);
|
||||
}
|
||||
return (SYMBOL_TYPE (sym));
|
||||
}
|
||||
|
||||
/* Lookup an enum type named "enum NAME",
|
||||
visible in lexical block BLOCK. */
|
||||
|
||||
struct type *
|
||||
lookup_enum (name, block)
|
||||
char *name;
|
||||
struct block *block;
|
||||
{
|
||||
register struct symbol *sym;
|
||||
|
||||
sym = lookup_symbol (name, block, STRUCT_NAMESPACE, 0,
|
||||
(struct symtab **) NULL);
|
||||
if (sym == NULL)
|
||||
{
|
||||
error ("No enum type named %s.", name);
|
||||
}
|
||||
if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_ENUM)
|
||||
{
|
||||
error ("This context has class, struct or union %s, not an enum.", name);
|
||||
}
|
||||
return (SYMBOL_TYPE (sym));
|
||||
}
|
||||
|
||||
/* Lookup a template type named "template NAME<TYPE>",
|
||||
visible in lexical block BLOCK. */
|
||||
|
||||
struct type *
|
||||
lookup_template_type (name, type, block)
|
||||
char *name;
|
||||
struct type *type;
|
||||
struct block *block;
|
||||
{
|
||||
struct symbol *sym;
|
||||
char *nam = (char*) alloca(strlen(name) + strlen(type->name) + 4);
|
||||
strcpy (nam, name);
|
||||
strcat (nam, "<");
|
||||
strcat (nam, type->name);
|
||||
strcat (nam, " >"); /* FIXME, extra space still introduced in gcc? */
|
||||
|
||||
sym = lookup_symbol (nam, block, VAR_NAMESPACE, 0, (struct symtab **)NULL);
|
||||
|
||||
if (sym == NULL)
|
||||
{
|
||||
error ("No template type named %s.", name);
|
||||
}
|
||||
if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_STRUCT)
|
||||
{
|
||||
error ("This context has class, union or enum %s, not a struct.", name);
|
||||
}
|
||||
return (SYMBOL_TYPE (sym));
|
||||
}
|
||||
|
||||
/* Given a type TYPE, lookup the type of the component of type named
|
||||
NAME.
|
||||
If NOERR is nonzero, return zero if NAME is not suitably defined. */
|
||||
|
||||
struct type *
|
||||
lookup_struct_elt_type (type, name, noerr)
|
||||
struct type *type;
|
||||
char *name;
|
||||
int noerr;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (TYPE_CODE (type) != TYPE_CODE_STRUCT &&
|
||||
TYPE_CODE (type) != TYPE_CODE_UNION)
|
||||
{
|
||||
target_terminal_ours ();
|
||||
fflush (stdout);
|
||||
fprintf (stderr, "Type ");
|
||||
type_print (type, "", stderr, -1);
|
||||
error (" is not a structure or union type.");
|
||||
}
|
||||
|
||||
check_stub_type (type);
|
||||
|
||||
for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)
|
||||
{
|
||||
char *t_field_name = TYPE_FIELD_NAME (type, i);
|
||||
|
||||
if (t_field_name && !strcmp (t_field_name, name))
|
||||
{
|
||||
return TYPE_FIELD_TYPE (type, i);
|
||||
}
|
||||
}
|
||||
|
||||
/* OK, it's not in this class. Recursively check the baseclasses. */
|
||||
for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
|
||||
{
|
||||
struct type *t;
|
||||
|
||||
t = lookup_struct_elt_type (TYPE_BASECLASS (type, i), name, 0);
|
||||
if (t != NULL)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
if (noerr)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
target_terminal_ours ();
|
||||
fflush (stdout);
|
||||
fprintf (stderr, "Type ");
|
||||
type_print (type, "", stderr, -1);
|
||||
fprintf (stderr, " has no component named ");
|
||||
fputs_filtered (name, stderr);
|
||||
error (".");
|
||||
return (struct type *)-1; /* For lint */
|
||||
}
|
||||
|
||||
/* This function is really horrible, but to avoid it, there would need
|
||||
to be more filling in of forward references. */
|
||||
|
||||
void
|
||||
fill_in_vptr_fieldno (type)
|
||||
struct type *type;
|
||||
{
|
||||
if (TYPE_VPTR_FIELDNO (type) < 0)
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i < TYPE_N_BASECLASSES (type); i++)
|
||||
{
|
||||
fill_in_vptr_fieldno (TYPE_BASECLASS (type, i));
|
||||
if (TYPE_VPTR_FIELDNO (TYPE_BASECLASS (type, i)) >= 0)
|
||||
{
|
||||
TYPE_VPTR_FIELDNO (type)
|
||||
= TYPE_VPTR_FIELDNO (TYPE_BASECLASS (type, i));
|
||||
TYPE_VPTR_BASETYPE (type)
|
||||
= TYPE_VPTR_BASETYPE (TYPE_BASECLASS (type, i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Added by Bryan Boreham, Kewill, Sun Sep 17 18:07:17 1989.
|
||||
|
||||
If this is a stubbed struct (i.e. declared as struct foo *), see if
|
||||
we can find a full definition in some other file. If so, copy this
|
||||
definition, so we can use it in future. If not, set a flag so we
|
||||
don't waste too much time in future. (FIXME, this doesn't seem
|
||||
to be happening...)
|
||||
|
||||
This used to be coded as a macro, but I don't think it is called
|
||||
often enough to merit such treatment.
|
||||
*/
|
||||
|
||||
struct complaint stub_noname_complaint =
|
||||
{"stub type has NULL name", 0, 0};
|
||||
|
||||
void
|
||||
check_stub_type (type)
|
||||
struct type *type;
|
||||
{
|
||||
if (TYPE_FLAGS(type) & TYPE_FLAG_STUB)
|
||||
{
|
||||
char* name = type_name_no_tag (type);
|
||||
struct symbol *sym;
|
||||
if (name == NULL)
|
||||
{
|
||||
complain (&stub_noname_complaint, 0);
|
||||
return;
|
||||
}
|
||||
sym = lookup_symbol (name, 0, STRUCT_NAMESPACE, 0,
|
||||
(struct symtab **) NULL);
|
||||
if (sym)
|
||||
{
|
||||
memcpy (type, SYMBOL_TYPE(sym), sizeof (struct type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Ugly hack to convert method stubs into method types.
|
||||
|
||||
He ain't kiddin'. This demangles the name of the method into a string
|
||||
including argument types, parses out each argument type, generates
|
||||
a string casting a zero to that type, evaluates the string, and stuffs
|
||||
the resulting type into an argtype vector!!! Then it knows the type
|
||||
of the whole function (including argument types for overloading),
|
||||
which info used to be in the stab's but was removed to hack back
|
||||
the space required for them. */
|
||||
|
||||
void
|
||||
check_stub_method (type, i, j)
|
||||
struct type *type;
|
||||
int i;
|
||||
int j;
|
||||
{
|
||||
struct fn_field *f;
|
||||
char *mangled_name = gdb_mangle_name (type, i, j);
|
||||
char *demangled_name = cplus_demangle (mangled_name, 0);
|
||||
char *argtypetext, *p;
|
||||
int depth = 0, argcount = 1;
|
||||
struct type **argtypes;
|
||||
struct type *mtype;
|
||||
|
||||
if (demangled_name == NULL)
|
||||
{
|
||||
error ("Internal: Cannot demangle mangled name `%s'.", mangled_name);
|
||||
}
|
||||
|
||||
/* Now, read in the parameters that define this type. */
|
||||
argtypetext = strchr (demangled_name, '(') + 1;
|
||||
p = argtypetext;
|
||||
while (*p)
|
||||
{
|
||||
if (*p == '(')
|
||||
{
|
||||
depth += 1;
|
||||
}
|
||||
else if (*p == ')')
|
||||
{
|
||||
depth -= 1;
|
||||
}
|
||||
else if (*p == ',' && depth == 0)
|
||||
{
|
||||
argcount += 1;
|
||||
}
|
||||
|
||||
p += 1;
|
||||
}
|
||||
|
||||
/* We need two more slots: one for the THIS pointer, and one for the
|
||||
NULL [...] or void [end of arglist]. */
|
||||
|
||||
argtypes = (struct type **)
|
||||
obstack_alloc (&TYPE_OBJFILE (type) -> type_obstack,
|
||||
(argcount+2) * sizeof (struct type *));
|
||||
p = argtypetext;
|
||||
argtypes[0] = lookup_pointer_type (type);
|
||||
argcount = 1;
|
||||
|
||||
if (*p != ')') /* () means no args, skip while */
|
||||
{
|
||||
depth = 0;
|
||||
while (*p)
|
||||
{
|
||||
if (depth <= 0 && (*p == ',' || *p == ')'))
|
||||
{
|
||||
argtypes[argcount] =
|
||||
parse_and_eval_type (argtypetext, p - argtypetext);
|
||||
argcount += 1;
|
||||
argtypetext = p + 1;
|
||||
}
|
||||
|
||||
if (*p == '(')
|
||||
{
|
||||
depth += 1;
|
||||
}
|
||||
else if (*p == ')')
|
||||
{
|
||||
depth -= 1;
|
||||
}
|
||||
|
||||
p += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (p[-2] != '.') /* ... */
|
||||
{
|
||||
argtypes[argcount] = builtin_type_void; /* Ellist terminator */
|
||||
}
|
||||
else
|
||||
{
|
||||
argtypes[argcount] = NULL; /* List terminator */
|
||||
}
|
||||
|
||||
free (demangled_name);
|
||||
|
||||
f = TYPE_FN_FIELDLIST1 (type, i);
|
||||
TYPE_FN_FIELD_PHYSNAME (f, j) = mangled_name;
|
||||
|
||||
/* Now update the old "stub" type into a real type. */
|
||||
mtype = TYPE_FN_FIELD_TYPE (f, j);
|
||||
TYPE_DOMAIN_TYPE (mtype) = type;
|
||||
TYPE_ARG_TYPES (mtype) = argtypes;
|
||||
TYPE_FLAGS (mtype) &= ~TYPE_FLAG_STUB;
|
||||
TYPE_FN_FIELD_STUB (f, j) = 0;
|
||||
}
|
||||
|
||||
const struct cplus_struct_type cplus_struct_default;
|
||||
|
||||
void
|
||||
allocate_cplus_struct_type (type)
|
||||
struct type *type;
|
||||
{
|
||||
if (!HAVE_CPLUS_STRUCT (type))
|
||||
{
|
||||
TYPE_CPLUS_SPECIFIC (type) = (struct cplus_struct_type *)
|
||||
obstack_alloc (¤t_objfile -> type_obstack,
|
||||
sizeof (struct cplus_struct_type));
|
||||
*(TYPE_CPLUS_SPECIFIC(type)) = cplus_struct_default;
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper function to initialize the standard scalar types. */
|
||||
|
||||
struct type *
|
||||
init_type (code, length, flags, name, objfile)
|
||||
enum type_code code;
|
||||
int length;
|
||||
int flags;
|
||||
char *name;
|
||||
struct objfile *objfile;
|
||||
{
|
||||
register struct type *type;
|
||||
|
||||
type = alloc_type (objfile);
|
||||
TYPE_CODE (type) = code;
|
||||
TYPE_LENGTH (type) = length;
|
||||
TYPE_FLAGS (type) |= flags;
|
||||
TYPE_NAME (type) = name;
|
||||
|
||||
/* C++ fancies. */
|
||||
|
||||
if (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
|
||||
{
|
||||
INIT_CPLUS_SPECIFIC (type);
|
||||
}
|
||||
return (type);
|
||||
}
|
||||
|
||||
/* Look up a fundamental type for the specified objfile.
|
||||
May need to construct such a type if this is the first use.
|
||||
|
||||
Some object file formats (ELF, COFF, etc) do not define fundamental
|
||||
types such as "int" or "double". Others (stabs for example), do
|
||||
define fundamental types.
|
||||
|
||||
For the formats which don't provide fundamental types, gdb can create
|
||||
such types, using defaults reasonable for the current target machine. */
|
||||
|
||||
struct type *
|
||||
lookup_fundamental_type (objfile, typeid)
|
||||
struct objfile *objfile;
|
||||
int typeid;
|
||||
{
|
||||
register struct type *type = NULL;
|
||||
register struct type **typep;
|
||||
register int nbytes;
|
||||
|
||||
if (typeid < 0 || typeid >= FT_NUM_MEMBERS)
|
||||
{
|
||||
error ("internal error - invalid fundamental type id %d", typeid);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If this is the first time we */
|
||||
if (objfile -> fundamental_types == NULL)
|
||||
{
|
||||
nbytes = FT_NUM_MEMBERS * sizeof (struct type *);
|
||||
objfile -> fundamental_types = (struct type **)
|
||||
obstack_alloc (&objfile -> type_obstack, nbytes);
|
||||
(void) memset (objfile -> fundamental_types, 0, nbytes);
|
||||
}
|
||||
typep = objfile -> fundamental_types + typeid;
|
||||
if ((type = *typep) == NULL)
|
||||
{
|
||||
switch (typeid)
|
||||
{
|
||||
default:
|
||||
error ("internal error: unhandled type id %d", typeid);
|
||||
break;
|
||||
case FT_VOID:
|
||||
type = init_type (TYPE_CODE_VOID,
|
||||
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"void", objfile);
|
||||
break;
|
||||
case FT_BOOLEAN:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_INT_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED,
|
||||
"boolean", (struct objfile *) NULL);
|
||||
break;
|
||||
case FT_STRING:
|
||||
type = init_type (TYPE_CODE_PASCAL_ARRAY,
|
||||
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"string", (struct objfile *) NULL);
|
||||
break;
|
||||
case FT_CHAR:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"char", (struct objfile *) NULL);
|
||||
break;
|
||||
case FT_SIGNED_CHAR:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_SIGNED,
|
||||
"signed char", (struct objfile *) NULL);
|
||||
break;
|
||||
case FT_UNSIGNED_CHAR:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED,
|
||||
"unsigned char", (struct objfile *) NULL);
|
||||
break;
|
||||
case FT_SHORT:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_SHORT_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"short", (struct objfile *) NULL);
|
||||
break;
|
||||
case FT_SIGNED_SHORT:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_SHORT_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_SIGNED,
|
||||
"signed short", (struct objfile *) NULL);
|
||||
break;
|
||||
case FT_UNSIGNED_SHORT:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_SHORT_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED,
|
||||
"unsigned short", (struct objfile *) NULL);
|
||||
break;
|
||||
case FT_INTEGER:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_INT_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"int", (struct objfile *) NULL);
|
||||
break;
|
||||
case FT_SIGNED_INTEGER:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_INT_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_SIGNED,
|
||||
"signed int", (struct objfile *) NULL);
|
||||
break;
|
||||
case FT_UNSIGNED_INTEGER:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_INT_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED,
|
||||
"unsigned int", (struct objfile *) NULL);
|
||||
break;
|
||||
case FT_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"long", (struct objfile *) NULL);
|
||||
break;
|
||||
case FT_SIGNED_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_SIGNED,
|
||||
"signed long", (struct objfile *) NULL);
|
||||
break;
|
||||
case FT_UNSIGNED_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED,
|
||||
"unsigned long", (struct objfile *) NULL);
|
||||
break;
|
||||
case FT_LONG_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"long long", (struct objfile *) NULL);
|
||||
break;
|
||||
case FT_SIGNED_LONG_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_SIGNED,
|
||||
"signed long long", (struct objfile *) NULL);
|
||||
break;
|
||||
case FT_UNSIGNED_LONG_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED,
|
||||
"unsigned long long",
|
||||
(struct objfile *) NULL);
|
||||
break;
|
||||
case FT_FLOAT:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"float", (struct objfile *) NULL);
|
||||
break;
|
||||
case FT_DBL_PREC_FLOAT:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"double", (struct objfile *) NULL);
|
||||
break;
|
||||
case FT_EXT_PREC_FLOAT:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"long double", (struct objfile *) NULL);
|
||||
break;
|
||||
case FT_COMPLEX:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
TARGET_COMPLEX_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"complex", (struct objfile *) NULL);
|
||||
break;
|
||||
case FT_DBL_PREC_COMPLEX:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
TARGET_DOUBLE_COMPLEX_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"double complex", (struct objfile *) NULL);
|
||||
break;
|
||||
case FT_EXT_PREC_COMPLEX:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
TARGET_DOUBLE_COMPLEX_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"long double complex",
|
||||
(struct objfile *) NULL);
|
||||
break;
|
||||
}
|
||||
/* Install the newly created type in the objfile's fundamental_types
|
||||
vector. */
|
||||
*typep = type;
|
||||
}
|
||||
}
|
||||
return (type);
|
||||
}
|
||||
|
547
gdb/gdbtypes.h
547
gdb/gdbtypes.h
@ -0,0 +1,547 @@
|
||||
/* Internal type definitions for GDB.
|
||||
Copyright (C) 1992 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support, using pieces from other GDB modules.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 of the License, 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 (GDBTYPES_H)
|
||||
#define GDBTYPES_H 1
|
||||
|
||||
/* When gdb creates fundamental types, it uses one of the following
|
||||
type identifiers. The identifiers are used to index a vector of
|
||||
pointers to any types that are created. */
|
||||
|
||||
#define FT_VOID 0
|
||||
#define FT_BOOLEAN 1
|
||||
#define FT_CHAR 2
|
||||
#define FT_SIGNED_CHAR 3
|
||||
#define FT_UNSIGNED_CHAR 4
|
||||
#define FT_SHORT 5
|
||||
#define FT_SIGNED_SHORT 6
|
||||
#define FT_UNSIGNED_SHORT 7
|
||||
#define FT_INTEGER 8
|
||||
#define FT_SIGNED_INTEGER 9
|
||||
#define FT_UNSIGNED_INTEGER 10
|
||||
#define FT_LONG 11
|
||||
#define FT_SIGNED_LONG 12
|
||||
#define FT_UNSIGNED_LONG 13
|
||||
#define FT_LONG_LONG 14
|
||||
#define FT_SIGNED_LONG_LONG 15
|
||||
#define FT_UNSIGNED_LONG_LONG 16
|
||||
#define FT_FLOAT 17
|
||||
#define FT_DBL_PREC_FLOAT 18
|
||||
#define FT_EXT_PREC_FLOAT 19
|
||||
#define FT_COMPLEX 20
|
||||
#define FT_DBL_PREC_COMPLEX 21
|
||||
#define FT_EXT_PREC_COMPLEX 22
|
||||
#define FT_STRING 23
|
||||
|
||||
#define FT_NUM_MEMBERS 24
|
||||
|
||||
/* Different kinds of data types are distinguished by the `code' field. */
|
||||
|
||||
enum type_code
|
||||
{
|
||||
TYPE_CODE_UNDEF, /* Not used; catches errors */
|
||||
TYPE_CODE_PTR, /* Pointer type */
|
||||
TYPE_CODE_ARRAY, /* Array type, lower bound zero */
|
||||
TYPE_CODE_STRUCT, /* C struct or Pascal record */
|
||||
TYPE_CODE_UNION, /* C union or Pascal variant part */
|
||||
TYPE_CODE_ENUM, /* Enumeration type */
|
||||
TYPE_CODE_FUNC, /* Function type */
|
||||
TYPE_CODE_INT, /* Integer type */
|
||||
TYPE_CODE_FLT, /* Floating type */
|
||||
TYPE_CODE_VOID, /* Void type (values zero length) */
|
||||
TYPE_CODE_SET, /* Pascal sets */
|
||||
TYPE_CODE_RANGE, /* Range (integers within spec'd bounds) */
|
||||
TYPE_CODE_PASCAL_ARRAY, /* Array with explicit type of index */
|
||||
TYPE_CODE_ERROR, /* Unknown type */
|
||||
|
||||
/* C++ */
|
||||
TYPE_CODE_MEMBER, /* Member type */
|
||||
TYPE_CODE_METHOD, /* Method type */
|
||||
TYPE_CODE_REF, /* C++ Reference types */
|
||||
|
||||
/* Modula-2 */
|
||||
TYPE_CODE_CHAR, /* *real* character type */
|
||||
TYPE_CODE_BOOL /* Builtin Modula-2 BOOLEAN */
|
||||
};
|
||||
|
||||
/* Some bits for the type's flags word. */
|
||||
|
||||
/* Explicitly unsigned integer type */
|
||||
|
||||
#define TYPE_FLAG_UNSIGNED (1 << 0)
|
||||
|
||||
/* Explicity signed integer type */
|
||||
|
||||
#define TYPE_FLAG_SIGNED (1 << 1)
|
||||
|
||||
/* This appears in a type's flags word if it is a stub type (eg. if
|
||||
someone referenced a type that wasn't defined in a source file
|
||||
via (struct sir_not_appearing_in_this_film *)). */
|
||||
|
||||
#define TYPE_FLAG_STUB (1 << 2)
|
||||
|
||||
struct type
|
||||
{
|
||||
|
||||
/* Code for kind of type */
|
||||
|
||||
enum type_code code;
|
||||
|
||||
/* Name of this type, or NULL if none.
|
||||
This is used for printing only, except by poorly designed C++ code.
|
||||
Type names specified as input are defined by symbols. */
|
||||
|
||||
char *name;
|
||||
|
||||
/* Length in bytes of storage for a value of this type */
|
||||
|
||||
unsigned length;
|
||||
|
||||
/* Every type is now associated with a particular objfile, and the
|
||||
type is allocated on the type_obstack for that objfile. One problem
|
||||
however, is that there are times when gdb allocates new types while
|
||||
it is not in the process of reading symbols from a particular objfile.
|
||||
Fortunately, these happen when the type being created is a derived
|
||||
type of an existing type, such as in lookup_pointer_type(). So
|
||||
we can just allocate the new type using the same objfile as the
|
||||
existing type, but to do this we need a backpointer to the objfile
|
||||
from the existing type. Yes this is somewhat ugly, but without
|
||||
major overhaul of the internal type system, it can't be avoided
|
||||
for now. */
|
||||
|
||||
struct objfile *objfile;
|
||||
|
||||
/* For a pointer type, describes the type of object pointed to.
|
||||
For an array type, describes the type of the elements.
|
||||
For a function or method type, describes the type of the value.
|
||||
For a range type, describes the type of the full range.
|
||||
Unused otherwise. */
|
||||
|
||||
struct type *target_type;
|
||||
|
||||
/* Type that is a pointer to this type.
|
||||
NULL if no such pointer-to type is known yet.
|
||||
The debugger may add the address of such a type
|
||||
if it has to construct one later. */
|
||||
|
||||
struct type *pointer_type;
|
||||
|
||||
/* C++: also need a reference type. */
|
||||
|
||||
struct type *reference_type;
|
||||
|
||||
/* Type that is a function returning this type.
|
||||
NULL if no such function type is known here.
|
||||
The debugger may add the address of such a type
|
||||
if it has to construct one later. */
|
||||
|
||||
struct type *function_type;
|
||||
|
||||
/* Flags about this type. */
|
||||
|
||||
short flags;
|
||||
|
||||
/* Number of fields described for this type */
|
||||
|
||||
short nfields;
|
||||
|
||||
/* For structure and union types, a description of each field.
|
||||
For set and pascal array types, there is one "field",
|
||||
whose type is the domain type of the set or array.
|
||||
For range types, there are two "fields",
|
||||
the minimum and maximum values (both inclusive).
|
||||
For enum types, each possible value is described by one "field".
|
||||
|
||||
Using a pointer to a separate array of fields
|
||||
allows all types to have the same size, which is useful
|
||||
because we can allocate the space for a type before
|
||||
we know what to put in it. */
|
||||
|
||||
struct field
|
||||
{
|
||||
|
||||
/* Position of this field, counting in bits from start of
|
||||
containing structure. For a function type, this is the
|
||||
position in the argument list of this argument.
|
||||
For a range bound or enum value, this is the value itself. */
|
||||
|
||||
int bitpos;
|
||||
|
||||
/* Size of this field, in bits, or zero if not packed.
|
||||
For an unpacked field, the field's type's length
|
||||
says how many bytes the field occupies. */
|
||||
|
||||
int bitsize;
|
||||
|
||||
/* In a struct or enum type, type of this field.
|
||||
In a function type, type of this argument.
|
||||
In an array type, the domain-type of the array. */
|
||||
|
||||
struct type *type;
|
||||
|
||||
/* Name of field, value or argument.
|
||||
NULL for range bounds and array domains. */
|
||||
|
||||
char *name;
|
||||
|
||||
} *fields;
|
||||
|
||||
/* For types with virtual functions, VPTR_BASETYPE is the base class which
|
||||
defined the virtual function table pointer. VPTR_FIELDNO is
|
||||
the field number of that pointer in the structure.
|
||||
|
||||
For types that are pointer to member types, VPTR_BASETYPE
|
||||
is the type that this pointer is a member of.
|
||||
|
||||
Unused otherwise. */
|
||||
|
||||
struct type *vptr_basetype;
|
||||
|
||||
int vptr_fieldno;
|
||||
|
||||
/* Slot to point to additional language-specific fields of this type. */
|
||||
|
||||
union type_specific
|
||||
{
|
||||
|
||||
/* ARG_TYPES is for TYPE_CODE_METHOD and TYPE_CODE_FUNC. */
|
||||
|
||||
struct type **arg_types;
|
||||
|
||||
/* CPLUS_STUFF is for TYPE_CODE_STRUCT. */
|
||||
|
||||
struct cplus_struct_type *cplus_stuff;
|
||||
|
||||
} type_specific;
|
||||
};
|
||||
|
||||
#define NULL_TYPE ((struct type *) 0)
|
||||
|
||||
/* C++ language-specific information for TYPE_CODE_STRUCT and TYPE_CODE_UNION
|
||||
nodes. */
|
||||
|
||||
struct cplus_struct_type
|
||||
{
|
||||
|
||||
B_TYPE *virtual_field_bits; /* if base class is virtual */
|
||||
|
||||
B_TYPE *private_field_bits;
|
||||
|
||||
B_TYPE *protected_field_bits;
|
||||
|
||||
/* Number of methods described for this type */
|
||||
|
||||
short nfn_fields;
|
||||
|
||||
/* Number of base classes this type derives from. */
|
||||
|
||||
short n_baseclasses;
|
||||
|
||||
/* Number of methods described for this type plus all the
|
||||
methods that it derives from. */
|
||||
|
||||
int nfn_fields_total;
|
||||
|
||||
/* For classes, structures, and unions, a description of each field,
|
||||
which consists of an overloaded name, followed by the types of
|
||||
arguments that the method expects, and then the name after it
|
||||
has been renamed to make it distinct. */
|
||||
|
||||
struct fn_fieldlist
|
||||
{
|
||||
|
||||
/* The overloaded name. */
|
||||
|
||||
char *name;
|
||||
|
||||
/* The number of methods with this name. */
|
||||
|
||||
int length;
|
||||
|
||||
/* The list of methods. */
|
||||
|
||||
struct fn_field
|
||||
{
|
||||
|
||||
/* The return value of the method */
|
||||
|
||||
struct type *type;
|
||||
|
||||
/* The argument list */
|
||||
|
||||
struct type **args;
|
||||
|
||||
/* The name after it has been processed */
|
||||
|
||||
char *physname;
|
||||
|
||||
/* For virtual functions. */
|
||||
/* First baseclass that defines this virtual function. */
|
||||
|
||||
struct type *fcontext;
|
||||
|
||||
unsigned int is_const : 1;
|
||||
unsigned int is_volatile : 1;
|
||||
unsigned int is_private : 1;
|
||||
unsigned int is_protected : 1;
|
||||
unsigned int is_stub : 1;
|
||||
unsigned int dummy : 3;
|
||||
|
||||
/* Index into that baseclass's virtual function table,
|
||||
minus 2; else if static: VOFFSET_STATIC; else: 0. */
|
||||
|
||||
unsigned voffset : 24;
|
||||
|
||||
# define VOFFSET_STATIC 1
|
||||
|
||||
} *fn_fields;
|
||||
|
||||
} *fn_fieldlists;
|
||||
|
||||
unsigned char via_protected;
|
||||
|
||||
unsigned char via_public;
|
||||
};
|
||||
|
||||
/* The default value of TYPE_CPLUS_SPECIFIC(T) points to the
|
||||
this shared static structure. */
|
||||
|
||||
extern const struct cplus_struct_type cplus_struct_default;
|
||||
|
||||
extern void
|
||||
allocate_cplus_struct_type PARAMS ((struct type *));
|
||||
|
||||
#define INIT_CPLUS_SPECIFIC(type) \
|
||||
(TYPE_CPLUS_SPECIFIC(type)=(struct cplus_struct_type*)&cplus_struct_default)
|
||||
#define ALLOCATE_CPLUS_STRUCT_TYPE(type) allocate_cplus_struct_type (type)
|
||||
#define HAVE_CPLUS_STRUCT(type) \
|
||||
(TYPE_CPLUS_SPECIFIC(type) != &cplus_struct_default)
|
||||
|
||||
#define TYPE_NAME(thistype) (thistype)->name
|
||||
#define TYPE_TARGET_TYPE(thistype) (thistype)->target_type
|
||||
#define TYPE_POINTER_TYPE(thistype) (thistype)->pointer_type
|
||||
#define TYPE_REFERENCE_TYPE(thistype) (thistype)->reference_type
|
||||
#define TYPE_FUNCTION_TYPE(thistype) (thistype)->function_type
|
||||
#define TYPE_LENGTH(thistype) (thistype)->length
|
||||
#define TYPE_OBJFILE(thistype) (thistype)->objfile
|
||||
#define TYPE_FLAGS(thistype) (thistype)->flags
|
||||
#define TYPE_UNSIGNED(thistype) ((thistype)->flags & TYPE_FLAG_UNSIGNED)
|
||||
#define TYPE_CODE(thistype) (thistype)->code
|
||||
#define TYPE_NFIELDS(thistype) (thistype)->nfields
|
||||
#define TYPE_FIELDS(thistype) (thistype)->fields
|
||||
|
||||
/* C++ */
|
||||
|
||||
#define TYPE_VPTR_BASETYPE(thistype) (thistype)->vptr_basetype
|
||||
#define TYPE_DOMAIN_TYPE(thistype) (thistype)->vptr_basetype
|
||||
#define TYPE_VPTR_FIELDNO(thistype) (thistype)->vptr_fieldno
|
||||
#define TYPE_FN_FIELDS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->fn_fields
|
||||
#define TYPE_NFN_FIELDS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->nfn_fields
|
||||
#define TYPE_NFN_FIELDS_TOTAL(thistype) TYPE_CPLUS_SPECIFIC(thistype)->nfn_fields_total
|
||||
#define TYPE_TYPE_SPECIFIC(thistype) (thistype)->type_specific
|
||||
#define TYPE_ARG_TYPES(thistype) (thistype)->type_specific.arg_types
|
||||
#define TYPE_CPLUS_SPECIFIC(thistype) (thistype)->type_specific.cplus_stuff
|
||||
#define TYPE_BASECLASS(thistype,index) (thistype)->fields[index].type
|
||||
#define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)->n_baseclasses
|
||||
#define TYPE_BASECLASS_NAME(thistype,index) (thistype)->fields[index].name
|
||||
#define TYPE_BASECLASS_BITPOS(thistype,index) (thistype)->fields[index].bitpos
|
||||
#define BASETYPE_VIA_PUBLIC(thistype, index) (!TYPE_FIELD_PRIVATE(thistype, index))
|
||||
#define BASETYPE_VIA_VIRTUAL(thistype, index) \
|
||||
B_TST(TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits, (index))
|
||||
|
||||
#define TYPE_FIELD(thistype, n) (thistype)->fields[n]
|
||||
#define TYPE_FIELD_TYPE(thistype, n) (thistype)->fields[n].type
|
||||
#define TYPE_FIELD_NAME(thistype, n) (thistype)->fields[n].name
|
||||
#define TYPE_FIELD_VALUE(thistype, n) (* (int*) &(thistype)->fields[n].type)
|
||||
#define TYPE_FIELD_BITPOS(thistype, n) (thistype)->fields[n].bitpos
|
||||
#define TYPE_FIELD_BITSIZE(thistype, n) (thistype)->fields[n].bitsize
|
||||
#define TYPE_FIELD_PACKED(thistype, n) (thistype)->fields[n].bitsize
|
||||
|
||||
#define TYPE_FIELD_PRIVATE_BITS(thistype) \
|
||||
TYPE_CPLUS_SPECIFIC(thistype)->private_field_bits
|
||||
#define TYPE_FIELD_PROTECTED_BITS(thistype) \
|
||||
TYPE_CPLUS_SPECIFIC(thistype)->protected_field_bits
|
||||
#define TYPE_FIELD_VIRTUAL_BITS(thistype) \
|
||||
TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits
|
||||
#define SET_TYPE_FIELD_PRIVATE(thistype, n) \
|
||||
B_SET (TYPE_CPLUS_SPECIFIC(thistype)->private_field_bits, (n))
|
||||
#define SET_TYPE_FIELD_PROTECTED(thistype, n) \
|
||||
B_SET (TYPE_CPLUS_SPECIFIC(thistype)->protected_field_bits, (n))
|
||||
#define SET_TYPE_FIELD_VIRTUAL(thistype, n) \
|
||||
B_SET (TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits, (n))
|
||||
#define TYPE_FIELD_PRIVATE(thistype, n) \
|
||||
(TYPE_CPLUS_SPECIFIC(thistype)->private_field_bits == NULL ? 0 \
|
||||
: B_TST(TYPE_CPLUS_SPECIFIC(thistype)->private_field_bits, (n)))
|
||||
#define TYPE_FIELD_PROTECTED(thistype, n) \
|
||||
(TYPE_CPLUS_SPECIFIC(thistype)->protected_field_bits == NULL ? 0 \
|
||||
: B_TST(TYPE_CPLUS_SPECIFIC(thistype)->protected_field_bits, (n)))
|
||||
#define TYPE_FIELD_VIRTUAL(thistype, n) \
|
||||
B_TST(TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits, (n))
|
||||
|
||||
#define TYPE_FIELD_STATIC(thistype, n) ((thistype)->fields[n].bitpos == -1)
|
||||
#define TYPE_FIELD_STATIC_PHYSNAME(thistype, n) ((char *)(thistype)->fields[n].bitsize)
|
||||
|
||||
#define TYPE_FN_FIELDLISTS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->fn_fieldlists
|
||||
#define TYPE_FN_FIELDLIST(thistype, n) TYPE_CPLUS_SPECIFIC(thistype)->fn_fieldlists[n]
|
||||
#define TYPE_FN_FIELDLIST1(thistype, n) TYPE_CPLUS_SPECIFIC(thistype)->fn_fieldlists[n].fn_fields
|
||||
#define TYPE_FN_FIELDLIST_NAME(thistype, n) TYPE_CPLUS_SPECIFIC(thistype)->fn_fieldlists[n].name
|
||||
#define TYPE_FN_FIELDLIST_LENGTH(thistype, n) TYPE_CPLUS_SPECIFIC(thistype)->fn_fieldlists[n].length
|
||||
|
||||
#define TYPE_FN_FIELD(thisfn, n) (thisfn)[n]
|
||||
#define TYPE_FN_FIELD_NAME(thisfn, n) (thisfn)[n].name
|
||||
#define TYPE_FN_FIELD_TYPE(thisfn, n) (thisfn)[n].type
|
||||
#define TYPE_FN_FIELD_ARGS(thisfn, n) TYPE_ARG_TYPES ((thisfn)[n].type)
|
||||
#define TYPE_FN_FIELD_PHYSNAME(thisfn, n) (thisfn)[n].physname
|
||||
#define TYPE_FN_FIELD_VIRTUAL_P(thisfn, n) ((thisfn)[n].voffset > 1)
|
||||
#define TYPE_FN_FIELD_STATIC_P(thisfn, n) ((thisfn)[n].voffset == VOFFSET_STATIC)
|
||||
#define TYPE_FN_FIELD_VOFFSET(thisfn, n) ((thisfn)[n].voffset-2)
|
||||
#define TYPE_FN_FIELD_FCONTEXT(thisfn, n) ((thisfn)[n].fcontext)
|
||||
#define TYPE_FN_FIELD_STUB(thisfn, n) ((thisfn)[n].is_stub)
|
||||
#define TYPE_FN_FIELD_PRIVATE(thisfn, n) ((thisfn)[n].is_private)
|
||||
#define TYPE_FN_FIELD_PROTECTED(thisfn, n) ((thisfn)[n].is_protected)
|
||||
|
||||
extern struct type *builtin_type_void;
|
||||
extern struct type *builtin_type_char;
|
||||
extern struct type *builtin_type_short;
|
||||
extern struct type *builtin_type_int;
|
||||
extern struct type *builtin_type_long;
|
||||
extern struct type *builtin_type_unsigned_char;
|
||||
extern struct type *builtin_type_unsigned_short;
|
||||
extern struct type *builtin_type_unsigned_int;
|
||||
extern struct type *builtin_type_unsigned_long;
|
||||
extern struct type *builtin_type_float;
|
||||
extern struct type *builtin_type_double;
|
||||
extern struct type *builtin_type_long_double;
|
||||
extern struct type *builtin_type_complex;
|
||||
extern struct type *builtin_type_double_complex;
|
||||
|
||||
/* This type represents a type that was unrecognized in symbol
|
||||
read-in. */
|
||||
|
||||
extern struct type *builtin_type_error;
|
||||
|
||||
extern struct type *builtin_type_long_long;
|
||||
extern struct type *builtin_type_unsigned_long_long;
|
||||
|
||||
/* Modula-2 types */
|
||||
|
||||
extern struct type *builtin_type_m2_char;
|
||||
extern struct type *builtin_type_m2_int;
|
||||
extern struct type *builtin_type_m2_card;
|
||||
extern struct type *builtin_type_m2_real;
|
||||
extern struct type *builtin_type_m2_bool;
|
||||
|
||||
/* LONG_LONG is defined if the host has "long long". */
|
||||
|
||||
#ifdef LONG_LONG
|
||||
|
||||
#define BUILTIN_TYPE_LONGEST builtin_type_long_long
|
||||
#define BUILTIN_TYPE_UNSIGNED_LONGEST builtin_type_unsigned_long_long
|
||||
|
||||
#else /* not LONG_LONG. */
|
||||
|
||||
#define BUILTIN_TYPE_LONGEST builtin_type_long
|
||||
#define BUILTIN_TYPE_UNSIGNED_LONGEST builtin_type_unsigned_long
|
||||
|
||||
#endif /* not LONG_LONG. */
|
||||
|
||||
/* Maximum and minimum values of built-in types */
|
||||
|
||||
#define MAX_OF_TYPE(t) \
|
||||
TYPE_UNSIGNED(t) ? UMAX_OF_SIZE(TYPE_LENGTH(t)) \
|
||||
: MAX_OF_SIZE(TYPE_LENGTH(t))
|
||||
|
||||
#define MIN_OF_TYPE(t) \
|
||||
TYPE_UNSIGNED(t) ? UMIN_OF_SIZE(TYPE_LENGTH(t)) \
|
||||
: MIN_OF_SIZE(TYPE_LENGTH(t))
|
||||
|
||||
extern struct type *
|
||||
alloc_type PARAMS ((struct objfile *));
|
||||
|
||||
extern struct type *
|
||||
init_type PARAMS ((enum type_code, int, int, char *, struct objfile *));
|
||||
|
||||
extern struct type *
|
||||
lookup_reference_type PARAMS ((struct type *));
|
||||
|
||||
extern struct type *
|
||||
lookup_member_type PARAMS ((struct type *, struct type *));
|
||||
|
||||
extern void
|
||||
smash_to_method_type PARAMS ((struct type *, struct type *, struct type *,
|
||||
struct type **));
|
||||
|
||||
extern void
|
||||
smash_to_member_type PARAMS ((struct type *, struct type *, struct type *));
|
||||
|
||||
extern struct type *
|
||||
allocate_stub_method PARAMS ((struct type *));
|
||||
|
||||
extern char *
|
||||
type_name_no_tag PARAMS ((const struct type *));
|
||||
|
||||
extern struct type *
|
||||
lookup_struct_elt_type PARAMS ((struct type *, char *, int));
|
||||
|
||||
extern struct type *
|
||||
lookup_pointer_type PARAMS ((struct type *));
|
||||
|
||||
extern struct type *
|
||||
lookup_function_type PARAMS ((struct type *));
|
||||
|
||||
extern struct type *
|
||||
create_array_type PARAMS ((struct type *, int));
|
||||
|
||||
extern struct type *
|
||||
lookup_unsigned_typename PARAMS ((char *));
|
||||
|
||||
extern void
|
||||
check_stub_type PARAMS ((struct type *));
|
||||
|
||||
extern void
|
||||
check_stub_method PARAMS ((struct type *, int, int));
|
||||
|
||||
extern struct type *
|
||||
lookup_primitive_typename PARAMS ((char *));
|
||||
|
||||
extern char *
|
||||
gdb_mangle_name PARAMS ((struct type *, int, int));
|
||||
|
||||
extern struct type *
|
||||
builtin_type PARAMS ((char **));
|
||||
|
||||
extern struct type *
|
||||
error_type PARAMS ((char **));
|
||||
|
||||
extern struct type *
|
||||
lookup_typename PARAMS ((char *, struct block *, int));
|
||||
|
||||
extern struct type *
|
||||
lookup_template_type PARAMS ((char *, struct type *, struct block *));
|
||||
|
||||
extern struct type *
|
||||
lookup_fundamental_type PARAMS ((struct objfile *, int));
|
||||
|
||||
/* printcmd.c */
|
||||
|
||||
extern void
|
||||
print_scalar_formatted PARAMS ((char *, struct type *, int, int, FILE *));
|
||||
|
||||
#endif /* GDBTYPES_H */
|
@ -205,7 +205,7 @@ typedef unsigned long size_t;
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
extern void EXFUN(abort, (void));
|
||||
extern void EXFUN(abort, (NOARGS));
|
||||
extern void EXFUN(free, (PTR));
|
||||
extern PTR EXFUN(malloc, (size_t));
|
||||
extern PTR EXFUN(realloc, (PTR, size_t));
|
||||
@ -267,7 +267,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
fragments in a block have been freed, the block itself is freed. */
|
||||
#define INT_BIT (CHAR_BIT * sizeof(int))
|
||||
#define BLOCKLOG (INT_BIT > 16 ? 12 : 9)
|
||||
#define BLOCKSIZE (1 << BLOCKLOG)
|
||||
#define BLOCKSIZE ((unsigned int) 1 << BLOCKLOG)
|
||||
#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
|
||||
|
||||
/* The difference between two pointers is a signed int. On machines where
|
||||
@ -377,7 +377,7 @@ extern PTR EXFUN((*__malloc_hook), (size_t __size));
|
||||
extern PTR EXFUN((*__realloc_hook), (PTR __ptr, size_t __size));
|
||||
|
||||
/* Activate a standard collection of debugging hooks. */
|
||||
extern void EXFUN(mcheck, (void EXFUN((*func), (void))));
|
||||
extern void EXFUN(mcheck, (void EXFUN((*func), (NOARGS))));
|
||||
|
||||
/* Statistics available to the user. */
|
||||
struct mstats
|
||||
|
@ -143,7 +143,7 @@ extern PTR EXFUN((*__malloc_hook), (size_t __size));
|
||||
extern PTR EXFUN((*__realloc_hook), (PTR __ptr, size_t __size));
|
||||
|
||||
/* Activate a standard collection of debugging hooks. */
|
||||
extern void EXFUN(mcheck, (void EXFUN((*func), (void))));
|
||||
extern void EXFUN(mcheck, (void EXFUN((*func), (NOARGS))));
|
||||
|
||||
/* Statistics available to the user. */
|
||||
struct mstats
|
||||
|
@ -33,6 +33,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
/* Work with core dump and executable files, for GDB.
|
||||
This code would be in core.c if it weren't machine-dependent. */
|
||||
|
@ -135,7 +135,6 @@ fetch_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
struct user u;
|
||||
register int regno;
|
||||
register unsigned int ar0_offset;
|
||||
|
||||
ar0_offset = (INFERIOR_AR0 (u));
|
||||
@ -157,6 +156,7 @@ fetch_inferior_registers (regno)
|
||||
If REGNO is -1, do this for all registers.
|
||||
Otherwise, REGNO specifies which register (so we can save time). */
|
||||
|
||||
void
|
||||
store_inferior_registers (regno)
|
||||
register int regno;
|
||||
{
|
||||
@ -194,10 +194,11 @@ store_inferior_registers (regno)
|
||||
#endif /* HPUX_VERSION_5 */
|
||||
|
||||
void
|
||||
fetch_core_registers (core_reg_sect, core_reg_size, which)
|
||||
fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
|
||||
char *core_reg_sect;
|
||||
int core_reg_size;
|
||||
int which;
|
||||
unsigned int reg_addr; /* Unused in this version */
|
||||
{
|
||||
int val, regno;
|
||||
struct user u;
|
||||
|
@ -43,9 +43,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include "target.h"
|
||||
|
||||
extern void print_387_control_word (); /* i387-tdep.h */
|
||||
extern void print_387_status_word ();
|
||||
|
||||
extern struct ext_format ext_format_i387;
|
||||
|
||||
/* this table must line up with REGISTER_NAMES in m-i386.h */
|
||||
@ -61,7 +58,11 @@ static int regmap[] =
|
||||
/* blockend is the value of u.u_ar0, and points to the
|
||||
* place where GS is stored
|
||||
*/
|
||||
|
||||
int
|
||||
i386_register_u_addr (blockend, regnum)
|
||||
int blockend;
|
||||
int regnum;
|
||||
{
|
||||
#if 0
|
||||
/* this will be needed if fp registers are reinstated */
|
||||
|
@ -48,23 +48,26 @@ struct ext_format ext_format_i387 = {
|
||||
|
||||
/* FIXME: Eliminate these routines when we have the time to change all
|
||||
the callers. */
|
||||
|
||||
void
|
||||
i387_to_double (from, to)
|
||||
char *from, *to;
|
||||
char *from;
|
||||
char *to;
|
||||
{
|
||||
ieee_extended_to_double (&ext_format_i387, from, (double *)to);
|
||||
}
|
||||
|
||||
void
|
||||
double_to_i387 (from, to)
|
||||
char *from, *to;
|
||||
char *from;
|
||||
char *to;
|
||||
{
|
||||
double_to_ieee_extended (&ext_format_i387, (double *)from, to);
|
||||
}
|
||||
|
||||
void
|
||||
print_387_control_word (control)
|
||||
unsigned short control;
|
||||
unsigned int control;
|
||||
{
|
||||
printf ("control %s: ", local_hex_string(control));
|
||||
printf ("compute to ");
|
||||
@ -101,7 +104,7 @@ unsigned short control;
|
||||
|
||||
void
|
||||
print_387_status_word (status)
|
||||
unsigned short status;
|
||||
unsigned int status;
|
||||
{
|
||||
printf ("status %s: ", local_hex_string (status));
|
||||
if (status & 0xff)
|
||||
|
@ -463,20 +463,18 @@ CORE_ADDR
|
||||
leafproc_return (ip)
|
||||
CORE_ADDR ip; /* ip from currently executing function */
|
||||
{
|
||||
int i;
|
||||
register struct misc_function *mf;
|
||||
register struct minimal_symbol *msymbol;
|
||||
char *p;
|
||||
int dst;
|
||||
unsigned int insn1, insn2;
|
||||
CORE_ADDR return_addr;
|
||||
char *index ();
|
||||
|
||||
if ((i = find_pc_misc_function (ip)) >= 0)
|
||||
if ((msymbol = lookup_minimal_symbol_by_pc (ip)) != NULL)
|
||||
{
|
||||
mf = &misc_function_vector[i];
|
||||
if ((p = index (mf->name, '.')) && !strcmp (p, ".lf"))
|
||||
if ((p = index (msymbol -> name, '.')) && !strcmp (p, ".lf"))
|
||||
{
|
||||
if (next_insn (mf->address, &insn1, &insn2)
|
||||
if (next_insn (msymbol -> address, &insn1, &insn2)
|
||||
&& (insn1 & 0xff87ffff) == 0x5c80161e /* mov g14, gx */
|
||||
&& (dst = REG_SRCDST (insn1)) <= G0_REGNUM + 7)
|
||||
{
|
||||
@ -485,7 +483,7 @@ leafproc_return (ip)
|
||||
the return address from g14; otherwise, read it
|
||||
from the register into which g14 was moved. */
|
||||
|
||||
return_addr = read_register ((ip == mf->address)
|
||||
return_addr = read_register ((ip == msymbol->address)
|
||||
? G14_REGNUM : dst);
|
||||
|
||||
/* We know we are in a leaf procedure, but we don't know
|
||||
@ -498,7 +496,7 @@ leafproc_return (ip)
|
||||
|
||||
if (!next_insn (return_addr, &insn1, &insn2)
|
||||
|| (insn1 & 0xff000000) != 0xa000000 /* ret */
|
||||
|| find_pc_misc_function (return_addr) != i)
|
||||
|| lookup_minimal_symbol_by_pc (return_addr) != msymbol)
|
||||
return (return_addr);
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "value.h"
|
||||
#include "gdbcmd.h"
|
||||
#include "frame.h"
|
||||
@ -1112,8 +1113,8 @@ _initialize_language()
|
||||
"Set the current source language.",
|
||||
&setlist);
|
||||
show = add_show_from_set (set, &showlist);
|
||||
set->function = set_language_command;
|
||||
show->function = show_language_command;
|
||||
set->function.cfunc = set_language_command;
|
||||
show->function.cfunc = show_language_command;
|
||||
|
||||
add_prefix_cmd ("check", no_class, set_check,
|
||||
"Set the status of the type/range checker",
|
||||
@ -1132,16 +1133,16 @@ _initialize_language()
|
||||
"Set type checking. (on/warn/off/auto)",
|
||||
&setchecklist);
|
||||
show = add_show_from_set (set, &showchecklist);
|
||||
set->function = set_type_command;
|
||||
show->function = show_type_command;
|
||||
set->function.cfunc = set_type_command;
|
||||
show->function.cfunc = show_type_command;
|
||||
|
||||
set = add_set_cmd ("range", class_support, var_string_noescape,
|
||||
(char *)&range,
|
||||
"Set range checking. (on/warn/off/auto)",
|
||||
&setchecklist);
|
||||
show = add_show_from_set (set, &showchecklist);
|
||||
set->function = set_range_command;
|
||||
show->function = show_range_command;
|
||||
set->function.cfunc = set_range_command;
|
||||
show->function.cfunc = show_range_command;
|
||||
|
||||
add_language (&unknown_language_defn);
|
||||
add_language (&local_language_defn);
|
||||
|
77
gdb/m2-exp.y
77
gdb/m2-exp.y
@ -33,6 +33,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include <string.h>
|
||||
#include "defs.h"
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "frame.h"
|
||||
#include "expression.h"
|
||||
#include "language.h"
|
||||
@ -69,10 +70,23 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#define yyval m2_val
|
||||
#define yylloc m2_lloc
|
||||
|
||||
/* Forward decl's */
|
||||
void yyerror ();
|
||||
static int yylex ();
|
||||
int yyparse ();
|
||||
static char *
|
||||
make_qualname PARAMS ((char *, char *));
|
||||
|
||||
static int
|
||||
parse_number PARAMS ((int));
|
||||
|
||||
static int
|
||||
yylex PARAMS ((void));
|
||||
|
||||
static void
|
||||
yyerror PARAMS ((char *));
|
||||
|
||||
static void
|
||||
__yy_bcopy PARAMS ((char *, char *, int));
|
||||
|
||||
int
|
||||
yyparse PARAMS ((void));
|
||||
|
||||
/* The sign of the number being parsed. */
|
||||
int number_sign = 1;
|
||||
@ -81,8 +95,6 @@ int number_sign = 1;
|
||||
contained in, */
|
||||
struct block *modblock=0;
|
||||
|
||||
char *make_qualname();
|
||||
|
||||
/* #define YYDEBUG 1 */
|
||||
|
||||
%}
|
||||
@ -602,34 +614,28 @@ variable: NAME
|
||||
}
|
||||
else
|
||||
{
|
||||
register int i;
|
||||
struct minimal_symbol *msymbol;
|
||||
register char *arg = copy_name ($1);
|
||||
|
||||
for (i = 0; i < misc_function_count; i++)
|
||||
if (!strcmp (misc_function_vector[i].name, arg))
|
||||
break;
|
||||
|
||||
if (i < misc_function_count)
|
||||
msymbol = lookup_minimal_symbol (arg,
|
||||
(struct objfile *) NULL);
|
||||
if (msymbol != NULL)
|
||||
{
|
||||
enum misc_function_type mft =
|
||||
(enum misc_function_type)
|
||||
misc_function_vector[i].type;
|
||||
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
write_exp_elt_type (builtin_type_int);
|
||||
write_exp_elt_longcst ((LONGEST) misc_function_vector[i].address);
|
||||
write_exp_elt_longcst ((LONGEST) msymbol -> address);
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
write_exp_elt_opcode (UNOP_MEMVAL);
|
||||
if (mft == mf_data || mft == mf_bss)
|
||||
if (msymbol -> type == mst_data ||
|
||||
msymbol -> type == mst_bss)
|
||||
write_exp_elt_type (builtin_type_int);
|
||||
else if (mft == mf_text)
|
||||
else if (msymbol -> type == mst_text)
|
||||
write_exp_elt_type (lookup_function_type (builtin_type_int));
|
||||
else
|
||||
write_exp_elt_type (builtin_type_char);
|
||||
write_exp_elt_opcode (UNOP_MEMVAL);
|
||||
}
|
||||
else if (symtab_list == 0
|
||||
&& partial_symtab_list == 0)
|
||||
else if (!have_full_symbols () && !have_partial_symbols ())
|
||||
error ("No symbol table is loaded. Use the \"symbol-file\" command.");
|
||||
else
|
||||
error ("No symbol \"%s\" in current context.",
|
||||
@ -681,8 +687,6 @@ parse_number (olen)
|
||||
register int len = olen;
|
||||
int unsigned_p = number_sign == 1 ? 1 : 0;
|
||||
|
||||
extern double atof ();
|
||||
|
||||
if(p[len-1] == 'H')
|
||||
{
|
||||
base = 16;
|
||||
@ -1131,7 +1135,7 @@ yylex ()
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
static char *
|
||||
make_qualname(mod,ident)
|
||||
char *mod, *ident;
|
||||
{
|
||||
@ -1144,8 +1148,9 @@ make_qualname(mod,ident)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
yyerror()
|
||||
static void
|
||||
yyerror(msg)
|
||||
char *msg; /* unused */
|
||||
{
|
||||
printf("Parsing: %s\n",lexptr);
|
||||
if (yychar < 256)
|
||||
@ -1223,12 +1228,22 @@ _initialize_m2_exp ()
|
||||
types are the same on the host and target machines!!! */
|
||||
|
||||
/* Modula-2 "pervasive" types. NOTE: these can be redefined!!! */
|
||||
builtin_type_m2_int = init_type (TYPE_CODE_INT, sizeof(int), 0, "INTEGER");
|
||||
builtin_type_m2_card = init_type (TYPE_CODE_INT, sizeof(int), 1, "CARDINAL");
|
||||
builtin_type_m2_real = init_type (TYPE_CODE_FLT, sizeof(float), 0, "REAL");
|
||||
builtin_type_m2_char = init_type (TYPE_CODE_CHAR, sizeof(char), 1, "CHAR");
|
||||
builtin_type_m2_int =
|
||||
init_type (TYPE_CODE_INT, sizeof(int), 0,
|
||||
"INTEGER", (struct objfile *) NULL);
|
||||
builtin_type_m2_card =
|
||||
init_type (TYPE_CODE_INT, sizeof(int), TYPE_FLAG_UNSIGNED,
|
||||
"CARDINAL", (struct objfile *) NULL);
|
||||
builtin_type_m2_real =
|
||||
init_type (TYPE_CODE_FLT, sizeof(float), 0,
|
||||
"REAL", (struct objfile *) NULL);
|
||||
builtin_type_m2_char =
|
||||
init_type (TYPE_CODE_CHAR, sizeof(char), TYPE_FLAG_UNSIGNED,
|
||||
"CHAR", (struct objfile *) NULL);
|
||||
builtin_type_m2_bool =
|
||||
init_type (TYPE_CODE_BOOL, sizeof(int), TYPE_FLAG_UNSIGNED,
|
||||
"BOOLEAN", (struct objfile *) NULL);
|
||||
|
||||
builtin_type_m2_bool = init_type (TYPE_CODE_BOOL, sizeof(int), 1, "BOOLEAN");
|
||||
TYPE_NFIELDS(builtin_type_m2_bool) = 2;
|
||||
TYPE_FIELDS(builtin_type_m2_bool) =
|
||||
(struct field *) malloc (sizeof (struct field) * 2);
|
||||
|
@ -24,6 +24,21 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "opcode/m68k.h"
|
||||
#include "gdbcore.h"
|
||||
|
||||
/* Local function prototypes */
|
||||
|
||||
static int
|
||||
fetch_arg PARAMS ((unsigned char *, int, int));
|
||||
|
||||
static void
|
||||
print_base PARAMS ((int, int, FILE *));
|
||||
|
||||
static unsigned char *
|
||||
print_indexed PARAMS ((int, unsigned char *, CORE_ADDR, FILE *));
|
||||
|
||||
static unsigned char *
|
||||
print_insn_arg PARAMS ((char *, unsigned char *, unsigned char *, CORE_ADDR,
|
||||
FILE *));
|
||||
|
||||
/* 68k instructions are never longer than this many bytes. */
|
||||
#define MAXLEN 22
|
||||
|
||||
@ -34,10 +49,6 @@ extern char *reg_names[];
|
||||
char *fpcr_names[] = { "", "fpiar", "fpsr", "fpiar/fpsr", "fpcr",
|
||||
"fpiar/fpcr", "fpsr/fpcr", "fpiar-fpcr"};
|
||||
|
||||
static unsigned char *print_insn_arg ();
|
||||
static unsigned char *print_indexed ();
|
||||
static void print_base ();
|
||||
static int fetch_arg ();
|
||||
|
||||
#define NEXTBYTE(p) (p += 2, ((char *)p)[-1])
|
||||
|
||||
@ -78,7 +89,7 @@ print_insn (memaddr, stream)
|
||||
register int bestmask;
|
||||
int best;
|
||||
|
||||
read_memory (memaddr, buffer, MAXLEN);
|
||||
read_memory (memaddr, (char *) buffer, MAXLEN);
|
||||
|
||||
bestmask = 0;
|
||||
best = -1;
|
||||
@ -574,7 +585,7 @@ print_insn_arg (d, buffer, p, addr, stream)
|
||||
static int
|
||||
fetch_arg (buffer, code, bits)
|
||||
unsigned char *buffer;
|
||||
char code;
|
||||
int code;
|
||||
int bits;
|
||||
{
|
||||
register int val;
|
||||
@ -674,8 +685,8 @@ static unsigned char *
|
||||
print_indexed (basereg, p, addr, stream)
|
||||
int basereg;
|
||||
unsigned char *p;
|
||||
FILE *stream;
|
||||
CORE_ADDR addr;
|
||||
FILE *stream;
|
||||
{
|
||||
register int word;
|
||||
static char *scales[] = {"", "*2", "*4", "*8"};
|
||||
|
@ -329,7 +329,7 @@ void sprint_address (addr, buffer)
|
||||
char *buffer;
|
||||
|
||||
{
|
||||
register int i;
|
||||
struct minimal_symbol *msymbol;
|
||||
struct symbol *fs;
|
||||
char *name;
|
||||
int name_location;
|
||||
@ -339,13 +339,13 @@ void sprint_address (addr, buffer)
|
||||
fs = find_pc_function (addr);
|
||||
|
||||
if (!fs) {
|
||||
i = find_pc_misc_function (addr);
|
||||
msymbol = lookup_minimal_symbol_by_pc (addr);
|
||||
|
||||
if (i < 0) return; /* If nothing comes through, don't
|
||||
if (i == NULL) return;/* If nothing comes through, don't
|
||||
print anything symbolic */
|
||||
|
||||
name = misc_function_vector[i].name;
|
||||
name_location = misc_function_vector[i].address;
|
||||
name = msymbol -> name;
|
||||
name_location = msymbol -> address;
|
||||
} else {
|
||||
name = fs->name;
|
||||
name_location = BLOCK_START (SYMBOL_BLOCK_VALUE (fs));
|
||||
|
@ -66,9 +66,9 @@ extern int errno;
|
||||
extern char registers[REGISTER_BYTES];
|
||||
|
||||
void
|
||||
fetch_inferior_registers ()
|
||||
fetch_inferior_registers (regno)
|
||||
int regno; /* Original value discarded */
|
||||
{
|
||||
register int regno;
|
||||
register unsigned int regaddr;
|
||||
char buf[MAX_REGISTER_RAW_SIZE];
|
||||
register int i;
|
||||
@ -105,6 +105,7 @@ fetch_inferior_registers ()
|
||||
If REGNO is -1, do this for all registers.
|
||||
Otherwise, REGNO specifies which register (so we can save time). */
|
||||
|
||||
void
|
||||
store_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
|
@ -39,9 +39,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/core.h>
|
||||
|
||||
|
||||
void
|
||||
fetch_inferior_registers ()
|
||||
fetch_inferior_registers (regno)
|
||||
int regno; /* Original value discarded */
|
||||
{
|
||||
struct regs inferior_registers;
|
||||
struct fp_state inferior_fp_registers;
|
||||
@ -65,6 +67,7 @@ fetch_inferior_registers ()
|
||||
If REGNO is -1, do this for all registers.
|
||||
Otherwise, REGNO specifies which register (so we can save time). */
|
||||
|
||||
void
|
||||
store_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
@ -106,12 +109,15 @@ store_inferior_registers (regno)
|
||||
|
||||
/* These functions shouldn't be called when we're cross-debugging. */
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
fetch_inferior_registers ()
|
||||
fetch_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
store_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
@ -122,10 +128,11 @@ store_inferior_registers (regno)
|
||||
/* Work with core files, for GDB. */
|
||||
|
||||
void
|
||||
fetch_core_registers (core_reg_sect, core_reg_size, which)
|
||||
fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
|
||||
char *core_reg_sect;
|
||||
unsigned core_reg_size;
|
||||
int which;
|
||||
unsigned int reg_addr; /* Unused in this version */
|
||||
{
|
||||
int val;
|
||||
extern char registers[];
|
||||
|
@ -34,7 +34,7 @@ static PTR EXFUN((*old_realloc_hook), (PTR ptr, size_t size));
|
||||
|
||||
/* Function to call when something awful happens. */
|
||||
extern void abort();
|
||||
static void EXFUN((*abortfunc), (void)) = (void (*)()) abort;
|
||||
static void EXFUN((*abortfunc), (NOARGS)) = (void (*)()) abort;
|
||||
|
||||
/* Arbitrary magical numbers. */
|
||||
#define MAGICWORD 0xfedabeeb
|
||||
@ -103,7 +103,7 @@ DEFUN(reallochook, (ptr, size), PTR ptr AND size_t size)
|
||||
}
|
||||
|
||||
void
|
||||
DEFUN(mcheck, (func), void EXFUN((*func), (void)))
|
||||
DEFUN(mcheck, (func), void EXFUN((*func), (NOARGS)))
|
||||
{
|
||||
static int mcheck_used = 0;
|
||||
|
||||
|
491
gdb/minsyms.c
Normal file
491
gdb/minsyms.c
Normal file
@ -0,0 +1,491 @@
|
||||
/* GDB routines for manipulating the minimal symbol tables.
|
||||
Copyright 1992 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support, using pieces from other GDB modules.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 of the License, 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. */
|
||||
|
||||
|
||||
/* This file contains support routines for creating, manipulating, and
|
||||
destroying minimal symbol tables.
|
||||
|
||||
Minimal symbol tables are used to hold some very basic information about
|
||||
all defined global symbols (text, data, bss, abs, etc). The only two
|
||||
required pieces of information are the symbol's name and the address
|
||||
associated with that symbol.
|
||||
|
||||
In many cases, even if a file was compiled with no special options for
|
||||
debugging at all, as long as was not stripped it will contain sufficient
|
||||
information to build useful minimal symbol tables using this structure.
|
||||
|
||||
Even when a file contains enough debugging information to build a full
|
||||
symbol table, these minimal symbols are still useful for quickly mapping
|
||||
between names and addresses, and vice versa. They are also sometimes used
|
||||
to figure out what full symbol table entries need to be read in. */
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "defs.h"
|
||||
#include "symtab.h"
|
||||
#include "bfd.h"
|
||||
#include "symfile.h"
|
||||
|
||||
/* Accumulate the minimal symbols for each objfile in bunches of BUNCH_SIZE.
|
||||
At the end, copy them all into one newly allocated location on an objfile's
|
||||
symbol obstack. */
|
||||
|
||||
#define BUNCH_SIZE 127
|
||||
|
||||
struct msym_bunch
|
||||
{
|
||||
struct msym_bunch *next;
|
||||
struct minimal_symbol contents[BUNCH_SIZE];
|
||||
};
|
||||
|
||||
/* Bunch currently being filled up.
|
||||
The next field points to chain of filled bunches. */
|
||||
|
||||
static struct msym_bunch *msym_bunch;
|
||||
|
||||
/* Number of slots filled in current bunch. */
|
||||
|
||||
static int msym_bunch_index;
|
||||
|
||||
/* Total number of minimal symbols recorded so far for the objfile. */
|
||||
|
||||
static int msym_count;
|
||||
|
||||
/* Prototypes for local functions. */
|
||||
|
||||
static int
|
||||
compare_minimal_symbols PARAMS ((const void *, const void *));
|
||||
|
||||
static int
|
||||
compact_minimal_symbols PARAMS ((struct minimal_symbol *, int));
|
||||
|
||||
/* Call the function specified by FUNC for each currently available minimal
|
||||
symbol, for as long as this function continues to return NULL. If the
|
||||
function ever returns non-NULL, then the iteration over the minimal
|
||||
symbols is terminated,, the result is returned to the caller.
|
||||
|
||||
The function called has full control over the form and content of the
|
||||
information returned via the non-NULL result, which may be as simple as a
|
||||
pointer to the minimal symbol that the iteration terminated on, or as
|
||||
complex as a pointer to a private structure containing multiple results. */
|
||||
|
||||
PTR
|
||||
iterate_over_msymbols (func, arg1, arg2, arg3)
|
||||
PTR (*func) PARAMS ((struct objfile *, struct minimal_symbol *,
|
||||
PTR, PTR, PTR));
|
||||
PTR arg1;
|
||||
PTR arg2;
|
||||
PTR arg3;
|
||||
{
|
||||
register struct objfile *objfile;
|
||||
register struct minimal_symbol *msymbol;
|
||||
char *result = NULL;
|
||||
|
||||
for (objfile = object_files;
|
||||
objfile != NULL && result == NULL;
|
||||
objfile = objfile -> next)
|
||||
{
|
||||
for (msymbol = objfile -> msymbols;
|
||||
msymbol != NULL && msymbol -> name != NULL && result == NULL;
|
||||
msymbol++)
|
||||
{
|
||||
result = (*func)(objfile, msymbol, arg1, arg2, arg3);
|
||||
}
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* Look through all the current minimal symbol tables and find the first
|
||||
minimal symbol that matches NAME. If OBJF is non-NULL, it specifies a
|
||||
particular objfile and the search is limited to that objfile. Returns
|
||||
a pointer to the minimal symbol that matches, or NULL if no match is found.
|
||||
|
||||
Note: One instance where their may be duplicate minimal symbols with
|
||||
the same name is when the symbol tables for a shared library and the
|
||||
symbol tables for an executable contain global symbols with the same
|
||||
names (the dynamic linker deals with the duplication). */
|
||||
|
||||
struct minimal_symbol *
|
||||
lookup_minimal_symbol (name, objf)
|
||||
register const char *name;
|
||||
struct objfile *objf;
|
||||
{
|
||||
struct objfile *objfile;
|
||||
struct minimal_symbol *msymbol;
|
||||
struct minimal_symbol *found_symbol = NULL;
|
||||
|
||||
for (objfile = object_files;
|
||||
objfile != NULL && found_symbol == NULL;
|
||||
objfile = objfile -> next)
|
||||
{
|
||||
if (objf == NULL || objf == objfile)
|
||||
{
|
||||
for (msymbol = objfile -> msymbols;
|
||||
msymbol != NULL && msymbol -> name != NULL &&
|
||||
found_symbol == NULL;
|
||||
msymbol++)
|
||||
{
|
||||
if (strcmp (msymbol -> name, name) == 0)
|
||||
{
|
||||
found_symbol = msymbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (found_symbol);
|
||||
}
|
||||
|
||||
|
||||
/* Search through the minimal symbol table for each objfile and find the
|
||||
symbol whose address is the largest address that is still less than or
|
||||
equal to PC. Returns a pointer to the minimal symbol if such a symbol
|
||||
is found, or NULL if PC is not in a suitable range. Note that we need
|
||||
to look through ALL the minimal symbol tables before deciding on the
|
||||
symbol that comes closest to the specified PC. */
|
||||
|
||||
struct minimal_symbol *
|
||||
lookup_minimal_symbol_by_pc (pc)
|
||||
register CORE_ADDR pc;
|
||||
{
|
||||
register int lo;
|
||||
register int hi;
|
||||
register int new;
|
||||
register struct objfile *objfile;
|
||||
register struct minimal_symbol *msymbol;
|
||||
register struct minimal_symbol *best_symbol = NULL;
|
||||
|
||||
for (objfile = object_files;
|
||||
objfile != NULL;
|
||||
objfile = objfile -> next)
|
||||
{
|
||||
/* If this objfile has a minimal symbol table, go search it using
|
||||
a binary search. Note that a minimal symbol table always consists
|
||||
of at least two symbols, a "real" symbol and the terminating
|
||||
"null symbol". If there are no real symbols, then there is no
|
||||
minimal symbol table at all. */
|
||||
|
||||
if ((msymbol = objfile -> msymbols) != NULL)
|
||||
{
|
||||
lo = 0;
|
||||
hi = objfile -> minimal_symbol_count - 2;
|
||||
|
||||
/* This code assumes that the minimal symbols are sorted by
|
||||
ascending address values. If the pc value is greater than or
|
||||
equal to the first symbol's address, then some symbol in this
|
||||
minimal symbol table is a suitable candidate for being the
|
||||
"best" symbol. This includes the last real symbol, for cases
|
||||
where the pc value is larger than any address in this vector.
|
||||
|
||||
By iterating until the address associated with the current
|
||||
hi index (the endpoint of the test interval) is less than
|
||||
or equal to the desired pc value, we accomplish two things:
|
||||
(1) the case where the pc value is larger than any minimal
|
||||
symbol address is trivially solved, (2) the address associated
|
||||
with the hi index is always the one we want when the interation
|
||||
terminates. In essence, we are iterating the test interval
|
||||
down until the pc value is pushed out of it from the high end.
|
||||
|
||||
Warning: this code is trickier than it would appear at first. */
|
||||
|
||||
if (pc >= msymbol[lo].address)
|
||||
{
|
||||
while (msymbol[hi].address > pc)
|
||||
{
|
||||
/* pc is still strictly less than highest address */
|
||||
/* Note "new" will always be >= lo */
|
||||
new = (lo + hi) / 2;
|
||||
if ((msymbol[new].address >= pc) || (lo == new))
|
||||
{
|
||||
hi = new;
|
||||
}
|
||||
else
|
||||
{
|
||||
lo = new;
|
||||
}
|
||||
}
|
||||
/* The minimal symbol indexed by hi now is the best one in this
|
||||
objfile's minimal symbol table. See if it is the best one
|
||||
overall. */
|
||||
|
||||
if ((best_symbol == NULL) ||
|
||||
(best_symbol -> address < msymbol[hi].address))
|
||||
{
|
||||
best_symbol = &msymbol[hi];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (best_symbol);
|
||||
}
|
||||
|
||||
/* Prepare to start collecting minimal symbols. Note that presetting
|
||||
msym_bunch_index to BUNCH_SIZE causes the first call to save a minimal
|
||||
symbol to allocate the memory for the first bunch. */
|
||||
|
||||
void
|
||||
init_minimal_symbol_collection ()
|
||||
{
|
||||
msym_count = 0;
|
||||
msym_bunch = NULL;
|
||||
msym_bunch_index = BUNCH_SIZE;
|
||||
}
|
||||
|
||||
void
|
||||
prim_record_minimal_symbol (name, address, ms_type)
|
||||
const char *name;
|
||||
CORE_ADDR address;
|
||||
enum minimal_symbol_type ms_type;
|
||||
{
|
||||
register struct msym_bunch *new;
|
||||
|
||||
if (msym_bunch_index == BUNCH_SIZE)
|
||||
{
|
||||
new = (struct msym_bunch *) xmalloc (sizeof (struct msym_bunch));
|
||||
msym_bunch_index = 0;
|
||||
new -> next = msym_bunch;
|
||||
msym_bunch = new;
|
||||
}
|
||||
msym_bunch -> contents[msym_bunch_index].name = (char *) name;
|
||||
msym_bunch -> contents[msym_bunch_index].address = address;
|
||||
msym_bunch -> contents[msym_bunch_index].info = NULL;
|
||||
msym_bunch -> contents[msym_bunch_index].type = ms_type;
|
||||
msym_bunch_index++;
|
||||
msym_count++;
|
||||
}
|
||||
|
||||
/* Compare two minimal symbols by address and return a signed result based
|
||||
on unsigned comparisons, so that we sort into unsigned numeric order. */
|
||||
|
||||
static int
|
||||
compare_minimal_symbols (fn1p, fn2p)
|
||||
const PTR fn1p;
|
||||
const PTR fn2p;
|
||||
{
|
||||
register const struct minimal_symbol *fn1;
|
||||
register const struct minimal_symbol *fn2;
|
||||
|
||||
fn1 = (const struct minimal_symbol *) fn1p;
|
||||
fn2 = (const struct minimal_symbol *) fn2p;
|
||||
|
||||
if (fn1 -> address < fn2 -> address)
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
else if (fn1 -> address > fn2 -> address)
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Discard the currently collected minimal symbols, if any. If we wish
|
||||
to save them for later use, we must have already copied them somewhere
|
||||
else before calling this function.
|
||||
|
||||
FIXME: We could allocate the minimal symbol bunches on their own
|
||||
obstack and then simply blow the obstack away when we are done with
|
||||
it. Is it worth the extra trouble though? */
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
discard_minimal_symbols (foo)
|
||||
int foo;
|
||||
{
|
||||
register struct msym_bunch *next;
|
||||
|
||||
while (msym_bunch != NULL)
|
||||
{
|
||||
next = msym_bunch -> next;
|
||||
free (msym_bunch);
|
||||
msym_bunch = next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compact duplicate entries out of a minimal symbol table by walking
|
||||
through the table and compacting out entries with duplicate addresses
|
||||
and matching names.
|
||||
|
||||
When files contain multiple sources of symbol information, it is
|
||||
possible for the minimal symbol table to contain many duplicate entries.
|
||||
As an example, SVR4 systems use ELF formatted object files, which
|
||||
usually contain at least two different types of symbol tables (a
|
||||
standard ELF one and a smaller dynamic linking table), as well as
|
||||
DWARF debugging information for files compiled with -g.
|
||||
|
||||
Without compacting, the minimal symbol table for gdb itself contains
|
||||
over a 1000 duplicates, about a third of the total table size. Aside
|
||||
from the potential trap of not noticing that two successive entries
|
||||
identify the same location, this duplication impacts the time required
|
||||
to linearly scan the table, which is done in a number of places. So
|
||||
just do one linear scan here and toss out the duplicates.
|
||||
|
||||
Note that we are not concerned here about recovering the space that
|
||||
is potentially freed up, because the strings themselves are allocated
|
||||
on the symbol_obstack, and will get automatically freed when the symbol
|
||||
table is freed. Also, the unused minimal symbols at the end of the
|
||||
compacted region will get freed automatically as well by whomever
|
||||
is responsible for deallocating the entire minimal symbol table. We
|
||||
can't diddle with the pointer anywhy, so don't worry about the
|
||||
wasted space.
|
||||
|
||||
Also note we only go up to the next to last entry within the loop
|
||||
and then copy the last entry explicitly after the loop terminates.
|
||||
|
||||
Since the different sources of information for each symbol may
|
||||
have different levels of "completeness", we may have duplicates
|
||||
that have one entry with type "mst_unknown" and the other with a
|
||||
known type. So if the one we are leaving alone has type mst_unknown,
|
||||
overwrite its type with the type from the one we are compacting out. */
|
||||
|
||||
static int
|
||||
compact_minimal_symbols (msymbol, mcount)
|
||||
struct minimal_symbol *msymbol;
|
||||
int mcount;
|
||||
{
|
||||
struct minimal_symbol *copyfrom;
|
||||
struct minimal_symbol *copyto;
|
||||
|
||||
if (mcount > 0)
|
||||
{
|
||||
copyfrom = copyto = msymbol;
|
||||
while (copyfrom < msymbol + mcount - 1)
|
||||
{
|
||||
if (copyfrom -> address == (copyfrom + 1) -> address
|
||||
&& (strcmp (copyfrom -> name, (copyfrom + 1) -> name) == 0))
|
||||
{
|
||||
if ((copyfrom + 1) -> type == mst_unknown)
|
||||
{
|
||||
(copyfrom + 1) -> type = copyfrom -> type;
|
||||
}
|
||||
copyfrom++;
|
||||
}
|
||||
else
|
||||
{
|
||||
*copyto++ = *copyfrom++;
|
||||
}
|
||||
}
|
||||
*copyto++ = *copyfrom++;
|
||||
mcount = copyto - msymbol;
|
||||
}
|
||||
return (mcount);
|
||||
}
|
||||
|
||||
/* INCLINK nonzero means bunches are from an incrementally-linked file.
|
||||
Add them to the existing bunches.
|
||||
Otherwise INCLINK is zero, and we start from scratch.
|
||||
|
||||
FIXME: INCLINK is currently unused, and is a holdover from when all
|
||||
these symbols were stored in a shared, globally available table. If
|
||||
it turns out we still need to be able to incrementally add minimal
|
||||
symbols to an existing minimal symbol table for a given objfile, then
|
||||
we will need to slightly modify this code so that when INCLINK is
|
||||
nonzero we copy the existing table to a work area that is allocated
|
||||
large enough for all the symbols and add the new ones to the end. */
|
||||
|
||||
void
|
||||
install_minimal_symbols (inclink, objfile)
|
||||
int inclink;
|
||||
struct objfile *objfile;
|
||||
{
|
||||
register int bindex;
|
||||
register int mcount;
|
||||
register struct msym_bunch *bunch;
|
||||
register struct minimal_symbol *msymbols;
|
||||
int nbytes;
|
||||
|
||||
if (msym_count > 0)
|
||||
{
|
||||
/* Allocate a temporary work area into which we will gather the
|
||||
bunches of minimal symbols, sort them, and then compact out
|
||||
duplicate entries. Once we have a final table, it will be attached
|
||||
to the specified objfile. */
|
||||
|
||||
msymbols = (struct minimal_symbol *)
|
||||
xmalloc (msym_count * sizeof (struct minimal_symbol));
|
||||
mcount = 0;
|
||||
|
||||
/* Walk through the list of minimal symbol bunches, adding each symbol
|
||||
to the new contiguous array of symbols. Note that we start with the
|
||||
current, possibly partially filled bunch (thus we use the current
|
||||
msym_bunch_index for the first bunch we copy over), and thereafter
|
||||
each bunch is full. */
|
||||
|
||||
for (bunch = msym_bunch; bunch != NULL; bunch = bunch -> next)
|
||||
{
|
||||
for (bindex = 0; bindex < msym_bunch_index; bindex++, mcount++)
|
||||
{
|
||||
msymbols[mcount] = bunch -> contents[bindex];
|
||||
#ifdef NAMES_HAVE_UNDERSCORE
|
||||
if (msymbols[mcount].name[0] == '_')
|
||||
{
|
||||
msymbols[mcount].name++;
|
||||
}
|
||||
#endif
|
||||
#ifdef SOME_NAMES_HAVE_DOT
|
||||
if (msymbols[mcount].name[0] == '.')
|
||||
{
|
||||
msymbols[mcount].name++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
msym_bunch_index = BUNCH_SIZE;
|
||||
}
|
||||
|
||||
/* Sort the minimal symbols by address. */
|
||||
|
||||
qsort (msymbols, mcount, sizeof (struct minimal_symbol),
|
||||
compare_minimal_symbols);
|
||||
|
||||
/* Compact out any duplicates. The table is reallocated to a
|
||||
smaller size, even though it is unnecessary here, as we are just
|
||||
going to move everything to an obstack anyway. */
|
||||
|
||||
mcount = compact_minimal_symbols (msymbols, mcount);
|
||||
|
||||
/* Attach the minimal symbol table to the specified objfile, allocating
|
||||
the table entries in the symbol_obstack. Note that the strings them-
|
||||
selves are already located in the symbol_obstack. We also terminate
|
||||
the minimal symbol table with a "null symbol", which is *not* included
|
||||
in the size of the table. This makes it easier to find the end of
|
||||
the table when we are handed a pointer to some symbol in the middle
|
||||
of it. */
|
||||
|
||||
objfile -> minimal_symbol_count = mcount;
|
||||
nbytes = (mcount + 1) * sizeof (struct minimal_symbol);
|
||||
objfile -> msymbols = (struct minimal_symbol *)
|
||||
obstack_alloc (&objfile -> symbol_obstack, nbytes);
|
||||
memcpy (objfile -> msymbols, msymbols, nbytes);
|
||||
free (msymbols);
|
||||
|
||||
/* Zero out the fields in the "null symbol" allocated at the end
|
||||
of the array. Note that the symbol count does *not* include
|
||||
this null symbol, which is why it is indexed by mcount and not
|
||||
mcount-1. */
|
||||
|
||||
objfile -> msymbols[mcount].name = NULL;
|
||||
objfile -> msymbols[mcount].address = 0;
|
||||
objfile -> msymbols[mcount].info = NULL;
|
||||
objfile -> msymbols[mcount].type = mst_unknown;
|
||||
}
|
||||
}
|
||||
|
@ -57,12 +57,16 @@ fetch_core_registers ()
|
||||
return;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
fetch_inferior_registers ()
|
||||
fetch_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
store_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
@ -88,9 +92,9 @@ store_inferior_registers (regno)
|
||||
/* Get all registers from the inferior */
|
||||
|
||||
void
|
||||
fetch_inferior_registers ()
|
||||
fetch_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
register int regno;
|
||||
register unsigned int regaddr;
|
||||
char buf[MAX_REGISTER_RAW_SIZE];
|
||||
register int i;
|
||||
|
160
gdb/mmap-alloc.c
Executable file
160
gdb/mmap-alloc.c
Executable file
@ -0,0 +1,160 @@
|
||||
/* GDB support for special malloc using mmap.
|
||||
Copyright 1992 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support, using pieces from other GDB modules.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 of the License, 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. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "defs.h"
|
||||
|
||||
#if defined (HAVE_MMAP)
|
||||
|
||||
/* Redefine the external visible symbols in gmalloc.c to be mmap versions */
|
||||
|
||||
#define free _mmap_free
|
||||
#define malloc _mmap_malloc
|
||||
#define realloc _mmap_realloc
|
||||
#define valloc _mmap_valloc
|
||||
|
||||
#define _bytes_free _mmap__bytes_free
|
||||
#define _bytes_used _mmap__bytes_used
|
||||
#define _chunks_free _mmap__chunks_free
|
||||
#define _chunks_used _mmap__chunks_used
|
||||
#define _fraghead _mmap__fraghead
|
||||
#define _heapbase _mmap__heapbase
|
||||
#define _heapindex _mmap__heapindex
|
||||
#define _heapinfo _mmap__heapinfo
|
||||
#define _heaplimit _mmap__heaplimit
|
||||
|
||||
#define __default_morecore _mmap___default_morecore
|
||||
#define __free _mmap___free
|
||||
#define __free_hook _mmap___free_hook
|
||||
#define __malloc_hook _mmap___malloc_hook
|
||||
#define __malloc_initialized _mmap___malloc_initialized
|
||||
#define __morecore _mmap___morecore
|
||||
#define __realloc_hook _mmap___realloc_hook
|
||||
|
||||
/* Arrange that instead of calling sbrk() we call mmap_sbrk() */
|
||||
|
||||
#define sbrk mmap_sbrk
|
||||
|
||||
/* Now simply include the standard GNU malloc source, and all the
|
||||
externally visible symbols will become _mmap_* versions, and
|
||||
_mmap_sbrk will be called to get more core instead of sbrk. */
|
||||
|
||||
#include "gmalloc.c"
|
||||
|
||||
/* Like mmap_malloc but get error if no storage available. */
|
||||
|
||||
PTR
|
||||
mmap_xmalloc (size)
|
||||
long size;
|
||||
{
|
||||
register char *val = NULL;
|
||||
|
||||
/* Protect against gdb wanting to allocate zero bytes. */
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
if ((val = (char *) _mmap_malloc (size)) == NULL)
|
||||
{
|
||||
fatal ("virtual memory exhausted.", 0);
|
||||
}
|
||||
}
|
||||
return (val);
|
||||
}
|
||||
|
||||
/* Like mmap_realloc but get error if no storage available. */
|
||||
|
||||
PTR
|
||||
mmap_xrealloc (ptr, size)
|
||||
PTR ptr;
|
||||
long size;
|
||||
{
|
||||
register char *val;
|
||||
|
||||
if ((val = (char *) _mmap_realloc (ptr, size)) == NULL)
|
||||
{
|
||||
fatal ("virtual memory exhausted.", 0);
|
||||
}
|
||||
return (val);
|
||||
}
|
||||
|
||||
PTR
|
||||
mmap_malloc (size)
|
||||
long size;
|
||||
{
|
||||
return (_mmap_malloc (size));
|
||||
}
|
||||
|
||||
PTR
|
||||
mmap_realloc (ptr, size)
|
||||
PTR ptr;
|
||||
long size;
|
||||
{
|
||||
return (_mmap_realloc (ptr, size));
|
||||
}
|
||||
|
||||
void
|
||||
mmap_free (ptr)
|
||||
PTR ptr;
|
||||
{
|
||||
_mmap_free (ptr);
|
||||
}
|
||||
|
||||
#else /* !defined (HAVE_MMAP) */
|
||||
|
||||
static char *errmsg = "This version of gdb does not support dumpable state.";
|
||||
|
||||
PTR
|
||||
mmap_malloc (size)
|
||||
long size;
|
||||
{
|
||||
error (errmsg);
|
||||
}
|
||||
|
||||
PTR
|
||||
mmap_xmalloc (size)
|
||||
long size;
|
||||
{
|
||||
error (errmsg);
|
||||
}
|
||||
|
||||
PTR
|
||||
mmap_realloc (ptr, size)
|
||||
PTR ptr;
|
||||
long size;
|
||||
{
|
||||
error (errmsg);
|
||||
}
|
||||
|
||||
PTR
|
||||
mmap_xrealloc (ptr, size)
|
||||
PTR ptr;
|
||||
long size;
|
||||
{
|
||||
error (errmsg);
|
||||
}
|
||||
|
||||
void
|
||||
mmap_free (ptr)
|
||||
PTR ptr;
|
||||
{
|
||||
error (errmsg);
|
||||
}
|
||||
|
||||
#endif /* HAVE_MMAP */
|
145
gdb/mmap-sbrk.c
Executable file
145
gdb/mmap-sbrk.c
Executable file
@ -0,0 +1,145 @@
|
||||
/* GDB support for an sbrk-like function that uses mmap.
|
||||
Copyright 1992 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support, using pieces from other GDB modules.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 of the License, 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. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "defs.h"
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#ifdef i386
|
||||
#define MMAP_BASE ((caddr_t) 0x81000000)
|
||||
#define MMAP_PGSZ 0x00002000 /* Must be multiple of real page size */
|
||||
#else
|
||||
#define MMAP_BASE ((caddr_t) 0xC2000000)
|
||||
#define MMAP_PGSZ 0x00002000 /* Must be multiple of real page size */
|
||||
#endif
|
||||
|
||||
#define PAGE_ALIGN(addr) (caddr_t) (((long)(addr) + MMAP_PGSZ - 1) & \
|
||||
~(MMAP_PGSZ - 1))
|
||||
|
||||
static caddr_t mbase = MMAP_BASE; /* Current base of mmap'd region */
|
||||
static caddr_t mbreak = MMAP_BASE; /* Current "break" address */
|
||||
static caddr_t mtop = MMAP_BASE; /* Current top of mmap'd region */
|
||||
|
||||
static int fd = -1; /* Open fd for /dev/zero */
|
||||
|
||||
|
||||
/* Provide a utility routine for other modules to obtain compatible
|
||||
page alignment. */
|
||||
|
||||
PTR
|
||||
mmap_page_align (addr)
|
||||
PTR addr;
|
||||
{
|
||||
return (PAGE_ALIGN (addr));
|
||||
}
|
||||
|
||||
/* Return the base address of the start of the mmap'd region. Note that
|
||||
we can find the end of the region at anytime by calling mmap_sbrk(0) */
|
||||
|
||||
PTR
|
||||
mmap_base ()
|
||||
{
|
||||
return (mbase);
|
||||
}
|
||||
|
||||
/* Works like sbrk(), but uses mmap to add to or subtract from a
|
||||
memory region. */
|
||||
|
||||
PTR
|
||||
mmap_sbrk (size)
|
||||
int size;
|
||||
{
|
||||
PTR result = NULL;
|
||||
int minc;
|
||||
caddr_t moveto;
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
/* Just return the current "break" value. */
|
||||
result = mbreak;
|
||||
}
|
||||
else if (size < 0)
|
||||
{
|
||||
/* We are deallocating memory. If the amount requested would cause
|
||||
us to try to deallocate back past the base of the mmap'd region
|
||||
then do nothing, and return NULL. Otherwise, deallocate the
|
||||
memory and return the old break value. */
|
||||
if (mbreak + size >= mbase)
|
||||
{
|
||||
result = (PTR) mbreak;
|
||||
mbreak += size;
|
||||
moveto = PAGE_ALIGN (mbreak);
|
||||
munmap (moveto, (size_t) (mtop - moveto));
|
||||
mtop = moveto;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We are allocating memory. Make sure we have an open file
|
||||
descriptor and then go on to get the memory. */
|
||||
if ((fd == -1) && (fd = open ("/dev/zero", O_RDONLY)) < 0)
|
||||
{
|
||||
result = NULL;
|
||||
}
|
||||
else if (mbreak + size > mtop)
|
||||
{
|
||||
/* The request would move us past the end of the currently
|
||||
mapped memory, so map in enough more memory to satisfy
|
||||
the request. */
|
||||
moveto = PAGE_ALIGN (mbreak + size);
|
||||
if (mmap (mtop, moveto - mtop, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_FIXED, fd, 0) == mtop)
|
||||
{
|
||||
mtop = moveto;
|
||||
result = (PTR) mbreak;
|
||||
mbreak += size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = (PTR) mbreak;
|
||||
mbreak += size;
|
||||
}
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
PTR
|
||||
mmap_remap (base, mapsize, fd, foffset)
|
||||
PTR base;
|
||||
long mapsize;
|
||||
int fd;
|
||||
long foffset;
|
||||
{
|
||||
/* FIXME: Quick hack, needs error checking and other attention. */
|
||||
munmap (mbase, (size_t) (mtop - mbase));
|
||||
mbase = base;
|
||||
mtop = mbase + mapsize;
|
||||
base = mmap (base, mapsize, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_FIXED, dup (fd), foffset);
|
||||
return (base);
|
||||
}
|
||||
|
||||
|
||||
#endif /* HAVE_MMAP */
|
@ -38,7 +38,7 @@ nindy_frame_chain_valid (chain, curframe)
|
||||
FRAME curframe;
|
||||
{
|
||||
struct symbol *sym;
|
||||
int i;
|
||||
struct minimal_symbol *msymbol;
|
||||
|
||||
/* crtnindy.o is an assembler module that is assumed to be linked
|
||||
* first in an i80960 executable. It contains the true entry point;
|
||||
@ -64,10 +64,10 @@ nindy_frame_chain_valid (chain, curframe)
|
||||
if ( sym != 0 ){
|
||||
a = sym->value.value;
|
||||
} else {
|
||||
i = lookup_misc_func (sf);
|
||||
if (i < 0)
|
||||
msymbol = lookup_minimal_symbol (sf, (struct objfile *) NULL);
|
||||
if (msymbol == NULL)
|
||||
return 0;
|
||||
a = misc_function_vector[i].address;
|
||||
a = msymbol -> address;
|
||||
}
|
||||
|
||||
return ( chain != read_memory_integer(a,4) );
|
||||
|
326
gdb/objfiles.c
Normal file
326
gdb/objfiles.c
Normal file
@ -0,0 +1,326 @@
|
||||
/* GDB routines for manipulating objfiles.
|
||||
Copyright 1992 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support, using pieces from other GDB modules.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 of the License, 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. */
|
||||
|
||||
/* This file contains support routines for creating, manipulating, and
|
||||
destroying objfile structures. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "defs.h"
|
||||
#include "bfd.h" /* Binary File Description */
|
||||
#include "symtab.h"
|
||||
#include "symfile.h"
|
||||
|
||||
#include <obstack.h>
|
||||
|
||||
/* Externally visible variables that are owned by this module. */
|
||||
|
||||
struct objfile *object_files; /* Linked list of all objfiles */
|
||||
|
||||
/* Allocate a new objfile struct, fill it in as best we can, and return it.
|
||||
It is also linked into the list of all known object files. */
|
||||
|
||||
struct objfile *
|
||||
allocate_objfile (abfd, filename, dumpable)
|
||||
bfd *abfd;
|
||||
char *filename;
|
||||
int dumpable;
|
||||
{
|
||||
struct objfile *objfile;
|
||||
|
||||
/* First, if the objfile is to be dumpable, we must malloc the structure
|
||||
itself using the mmap version, and arrange that all memory allocation
|
||||
for the objfile uses the mmap routines. Otherwise, just use the
|
||||
old sbrk'd malloc routines. */
|
||||
|
||||
if (dumpable)
|
||||
{
|
||||
objfile = (struct objfile *) mmap_xmalloc (sizeof (struct objfile));
|
||||
(void) memset (objfile, 0, sizeof (struct objfile));
|
||||
objfile -> malloc = mmap_malloc;
|
||||
objfile -> realloc = mmap_realloc;
|
||||
objfile -> xmalloc = mmap_xmalloc;
|
||||
objfile -> xrealloc = mmap_xrealloc;
|
||||
objfile -> free = mmap_free;
|
||||
objfile -> flags |= OBJF_DUMPABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
objfile = (struct objfile *) xmalloc (sizeof (struct objfile));
|
||||
(void) memset (objfile, 0, sizeof (struct objfile));
|
||||
objfile -> malloc = malloc;
|
||||
objfile -> realloc = realloc;
|
||||
objfile -> xmalloc = xmalloc;
|
||||
objfile -> xrealloc = xrealloc;
|
||||
objfile -> free = free;
|
||||
}
|
||||
|
||||
/* Now, malloc a fresh copy of the filename string using the malloc
|
||||
specified as appropriate for the objfile. */
|
||||
|
||||
objfile -> name = (*objfile -> xmalloc) (strlen (filename) + 1);
|
||||
strcpy (objfile -> name, filename);
|
||||
|
||||
objfile -> obfd = abfd;
|
||||
|
||||
objfile -> mtime = bfd_get_mtime (abfd);
|
||||
|
||||
/* Set up the various obstacks to use the memory allocation/free
|
||||
functions that are appropriate for this objfile. */
|
||||
|
||||
obstack_full_begin (&objfile -> psymbol_obstack, 0, 0,
|
||||
objfile -> xmalloc, objfile -> free);
|
||||
obstack_full_begin (&objfile -> symbol_obstack, 0, 0,
|
||||
objfile -> xmalloc, objfile -> free);
|
||||
obstack_full_begin (&objfile -> type_obstack, 0, 0,
|
||||
objfile -> xmalloc, objfile -> free);
|
||||
|
||||
/* Push this file onto the head of the linked list of other such files. */
|
||||
|
||||
objfile -> next = object_files;
|
||||
object_files = objfile;
|
||||
|
||||
return (objfile);
|
||||
}
|
||||
|
||||
|
||||
/* Destroy an objfile and all the symtabs and psymtabs under it. Note
|
||||
that as much as possible is allocated on the symbol_obstack and
|
||||
psymbol_obstack, so that the memory can be efficiently freed. */
|
||||
|
||||
void
|
||||
free_objfile (objfile)
|
||||
struct objfile *objfile;
|
||||
{
|
||||
struct objfile *ofp;
|
||||
|
||||
if (objfile -> name)
|
||||
{
|
||||
(*objfile -> free) (objfile -> name);
|
||||
}
|
||||
if (objfile -> obfd)
|
||||
{
|
||||
bfd_close (objfile -> obfd);
|
||||
}
|
||||
|
||||
/* Remove it from the chain of all objfiles. */
|
||||
|
||||
if (object_files == objfile)
|
||||
{
|
||||
object_files = objfile -> next;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (ofp = object_files; ofp; ofp = ofp -> next)
|
||||
{
|
||||
if (ofp -> next == objfile)
|
||||
{
|
||||
ofp -> next = objfile -> next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
obstack_free (&objfile -> psymbol_obstack, 0);
|
||||
obstack_free (&objfile -> symbol_obstack, 0);
|
||||
obstack_free (&objfile -> type_obstack, 0);
|
||||
|
||||
#if 0 /* FIXME!! */
|
||||
|
||||
/* Before the symbol table code was redone to make it easier to
|
||||
selectively load and remove information particular to a specific
|
||||
linkage unit, gdb used to do these things whenever the monolithic
|
||||
symbol table was blown away. How much still needs to be done
|
||||
is unknown, but we play it safe for now and keep each action until
|
||||
it is shown to be no longer needed. */
|
||||
|
||||
clear_symtab_users_once ();
|
||||
#if defined (CLEAR_SOLIB)
|
||||
CLEAR_SOLIB ();
|
||||
#endif
|
||||
clear_pc_function_cache ();
|
||||
|
||||
#endif
|
||||
|
||||
/* The last thing we do is free the objfile struct itself, using the
|
||||
free() that is appropriate for the objfile. */
|
||||
|
||||
(*objfile -> free) (objfile);
|
||||
}
|
||||
|
||||
/* Many places in gdb want to test just to see if we have any partial
|
||||
symbols available. This function returns zero if none are currently
|
||||
available, nonzero otherwise. */
|
||||
|
||||
int
|
||||
have_partial_symbols ()
|
||||
{
|
||||
struct objfile *ofp;
|
||||
int havethem = 0;
|
||||
|
||||
for (ofp = object_files; ofp; ofp = ofp -> next)
|
||||
{
|
||||
if (ofp -> psymtabs != NULL)
|
||||
{
|
||||
havethem++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (havethem);
|
||||
}
|
||||
|
||||
/* Many places in gdb want to test just to see if we have any full
|
||||
symbols available. This function returns zero if none are currently
|
||||
available, nonzero otherwise. */
|
||||
|
||||
int
|
||||
have_full_symbols ()
|
||||
{
|
||||
struct objfile *ofp;
|
||||
int havethem = 0;
|
||||
|
||||
for (ofp = object_files; ofp; ofp = ofp -> next)
|
||||
{
|
||||
if (ofp -> symtabs != NULL)
|
||||
{
|
||||
havethem++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (havethem);
|
||||
}
|
||||
|
||||
/* Many places in gdb want to test just to see if we have any minimal
|
||||
symbols available. This function returns zero if none are currently
|
||||
available, nonzero otherwise. */
|
||||
|
||||
int
|
||||
have_minimal_symbols ()
|
||||
{
|
||||
struct objfile *ofp;
|
||||
int havethem = 0;
|
||||
|
||||
for (ofp = object_files; ofp; ofp = ofp -> next)
|
||||
{
|
||||
if (ofp -> msymbols != NULL)
|
||||
{
|
||||
havethem++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (havethem);
|
||||
}
|
||||
|
||||
/* Call the function specified by FUNC for each currently available objfile,
|
||||
for as long as this function continues to return NULL. If the function
|
||||
ever returns non-NULL, then the iteration over the objfiles is terminated,
|
||||
and the result is returned to the caller. The function called has full
|
||||
control over the form and content of the information returned via the
|
||||
non-NULL result, which may be as simple as a pointer to the objfile that
|
||||
the iteration terminated on, or as complex as a pointer to a private
|
||||
structure containing multiple results. */
|
||||
|
||||
PTR
|
||||
iterate_over_objfiles (func, arg1, arg2, arg3)
|
||||
PTR (*func) PARAMS ((struct objfile *, PTR, PTR, PTR));
|
||||
PTR arg1;
|
||||
PTR arg2;
|
||||
PTR arg3;
|
||||
{
|
||||
register struct objfile *objfile;
|
||||
PTR result = NULL;
|
||||
|
||||
for (objfile = object_files;
|
||||
objfile != NULL && result == NULL;
|
||||
objfile = objfile -> next)
|
||||
{
|
||||
result = (*func)(objfile, arg1, arg2, arg3);
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* Call the function specified by FUNC for each currently available symbol
|
||||
table, for as long as this function continues to return NULL. If the
|
||||
function ever returns non-NULL, then the iteration over the symbol tables
|
||||
is terminated, and the result is returned to the caller. The function
|
||||
called has full control over the form and content of the information
|
||||
returned via the non-NULL result, which may be as simple as a pointer
|
||||
to the symtab that the iteration terminated on, or as complex as a
|
||||
pointer to a private structure containing multiple results. */
|
||||
|
||||
PTR
|
||||
iterate_over_symtabs (func, arg1, arg2, arg3)
|
||||
PTR (*func) PARAMS ((struct objfile *, struct symtab *, PTR, PTR, PTR));
|
||||
PTR arg1;
|
||||
PTR arg2;
|
||||
PTR arg3;
|
||||
{
|
||||
register struct objfile *objfile;
|
||||
register struct symtab *symtab;
|
||||
PTR result = NULL;
|
||||
|
||||
for (objfile = object_files;
|
||||
objfile != NULL && result == NULL;
|
||||
objfile = objfile -> next)
|
||||
{
|
||||
for (symtab = objfile -> symtabs;
|
||||
symtab != NULL && result == NULL;
|
||||
symtab = symtab -> next)
|
||||
{
|
||||
result = (*func)(objfile, symtab, arg1, arg2, arg3);
|
||||
}
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* Call the function specified by FUNC for each currently available partial
|
||||
symbol table, for as long as this function continues to return NULL. If
|
||||
the function ever returns non-NULL, then the iteration over the partial
|
||||
symbol tables is terminated, and the result is returned to the caller.
|
||||
|
||||
The function called has full control over the form and content of the
|
||||
information returned via the non-NULL result, which may be as simple as a
|
||||
pointer to the partial symbol table that the iteration terminated on, or
|
||||
as complex as a pointer to a private structure containing multiple
|
||||
results. */
|
||||
|
||||
PTR
|
||||
iterate_over_psymtabs (func, arg1, arg2, arg3)
|
||||
PTR (*func) PARAMS ((struct objfile *, struct partial_symtab *,
|
||||
PTR, PTR, PTR));
|
||||
PTR arg1;
|
||||
PTR arg2;
|
||||
PTR arg3;
|
||||
{
|
||||
register struct objfile *objfile;
|
||||
register struct partial_symtab *psymtab;
|
||||
PTR result = NULL;
|
||||
|
||||
for (objfile = object_files;
|
||||
objfile != NULL && result == NULL;
|
||||
objfile = objfile -> next)
|
||||
{
|
||||
for (psymtab = objfile -> psymtabs;
|
||||
psymtab != NULL && result == NULL;
|
||||
psymtab = psymtab -> next)
|
||||
{
|
||||
result = (*func)(objfile, psymtab, arg1, arg2, arg3);
|
||||
}
|
||||
}
|
||||
return (result);
|
||||
}
|
26
gdb/parse.c
26
gdb/parse.c
@ -31,6 +31,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include <stdio.h>
|
||||
#include "defs.h"
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "frame.h"
|
||||
#include "expression.h"
|
||||
#include "value.h"
|
||||
@ -38,6 +39,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "language.h"
|
||||
#include "parser-defs.h"
|
||||
|
||||
static void
|
||||
prefixify_expression PARAMS ((struct expression *));
|
||||
|
||||
static int
|
||||
length_of_subexp PARAMS ((struct expression *, int));
|
||||
|
||||
static void
|
||||
prefixify_subexp PARAMS ((struct expression *, struct expression *, int, int));
|
||||
|
||||
/* Assign machine-independent names to certain registers
|
||||
(unless overridden by the REGISTER_NAMES table) */
|
||||
|
||||
@ -117,7 +127,7 @@ write_exp_elt (expelt)
|
||||
if (expout_ptr >= expout_size)
|
||||
{
|
||||
expout_size *= 2;
|
||||
expout = (struct expression *) xrealloc (expout,
|
||||
expout = (struct expression *) xrealloc ((char *) expout,
|
||||
sizeof (struct expression)
|
||||
+ expout_size * sizeof (union exp_element));
|
||||
}
|
||||
@ -207,7 +217,7 @@ write_exp_string (str)
|
||||
{
|
||||
expout_size = max (expout_size * 2, expout_ptr + 10);
|
||||
expout = (struct expression *)
|
||||
xrealloc (expout, (sizeof (struct expression)
|
||||
xrealloc ((char *) expout, (sizeof (struct expression)
|
||||
+ (expout_size * sizeof (union exp_element))));
|
||||
}
|
||||
bcopy (str.ptr, (char *) &expout->elts[expout_ptr - lenelt], len);
|
||||
@ -230,9 +240,7 @@ copy_name (token)
|
||||
/* Reverse an expression from suffix form (in which it is constructed)
|
||||
to prefix form (in which we can conveniently print or execute it). */
|
||||
|
||||
static void prefixify_subexp ();
|
||||
|
||||
void
|
||||
static void
|
||||
prefixify_expression (expr)
|
||||
register struct expression *expr;
|
||||
{
|
||||
@ -252,7 +260,7 @@ prefixify_expression (expr)
|
||||
/* Return the number of exp_elements in the subexpression of EXPR
|
||||
whose last exp_element is at index ENDPOS - 1 in EXPR. */
|
||||
|
||||
int
|
||||
static int
|
||||
length_of_subexp (expr, endpos)
|
||||
register struct expression *expr;
|
||||
register int endpos;
|
||||
@ -552,7 +560,7 @@ parse_exp_1 (stringptr, block, comma)
|
||||
discard_cleanups (old_chain);
|
||||
expout->nelts = expout_ptr;
|
||||
expout = (struct expression *)
|
||||
xrealloc (expout,
|
||||
xrealloc ((char *) expout,
|
||||
sizeof (struct expression)
|
||||
+ expout_ptr * sizeof (union exp_element));
|
||||
prefixify_expression (expout);
|
||||
@ -582,7 +590,7 @@ push_type (tp)
|
||||
{
|
||||
type_stack_size *= 2;
|
||||
type_stack = (union type_stack_elt *)
|
||||
xrealloc (type_stack, type_stack_size * sizeof (*type_stack));
|
||||
xrealloc ((char *) type_stack, type_stack_size * sizeof (*type_stack));
|
||||
}
|
||||
type_stack[type_stack_depth++].piece = tp;
|
||||
}
|
||||
@ -595,7 +603,7 @@ push_type_int (n)
|
||||
{
|
||||
type_stack_size *= 2;
|
||||
type_stack = (union type_stack_elt *)
|
||||
xrealloc (type_stack, type_stack_size * sizeof (*type_stack));
|
||||
xrealloc ((char *) type_stack, type_stack_size * sizeof (*type_stack));
|
||||
}
|
||||
type_stack[type_stack_depth++].int_val = n;
|
||||
}
|
||||
|
@ -19,6 +19,9 @@ 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 (PARSER_DEFS_H)
|
||||
#define PARSER_DEFS_H 1
|
||||
|
||||
struct std_regs {
|
||||
char *name;
|
||||
int regnum;
|
||||
@ -31,21 +34,6 @@ struct expression *expout;
|
||||
int expout_size;
|
||||
int expout_ptr;
|
||||
|
||||
extern struct type *init_type ();
|
||||
|
||||
void write_exp_elt ();
|
||||
void write_exp_elt_opcode ();
|
||||
void write_exp_elt_sym ();
|
||||
void write_exp_elt_longcst ();
|
||||
void write_exp_elt_dblcst ();
|
||||
void write_exp_elt_type ();
|
||||
void write_exp_elt_intern ();
|
||||
void write_exp_string ();
|
||||
void start_arglist ();
|
||||
int end_arglist ();
|
||||
void free_funcalls ();
|
||||
char *copy_name ();
|
||||
|
||||
/* If this is nonzero, this block is used as the lexical context
|
||||
for symbol names. */
|
||||
|
||||
@ -106,10 +94,53 @@ union type_stack_elt {
|
||||
union type_stack_elt *type_stack;
|
||||
int type_stack_depth, type_stack_size;
|
||||
|
||||
void push_type ();
|
||||
void push_type_int ();
|
||||
enum type_pieces pop_type ();
|
||||
int pop_type_int ();
|
||||
extern void
|
||||
write_exp_elt PARAMS ((union exp_element));
|
||||
|
||||
extern void
|
||||
write_exp_elt_opcode PARAMS ((enum exp_opcode));
|
||||
|
||||
extern void
|
||||
write_exp_elt_sym PARAMS ((struct symbol *));
|
||||
|
||||
extern void
|
||||
write_exp_elt_longcst PARAMS ((LONGEST));
|
||||
|
||||
extern void
|
||||
write_exp_elt_dblcst PARAMS ((double));
|
||||
|
||||
extern void
|
||||
write_exp_elt_type PARAMS ((struct type *));
|
||||
|
||||
extern void
|
||||
write_exp_elt_intern PARAMS ((struct internalvar *));
|
||||
|
||||
extern void
|
||||
write_exp_string PARAMS ((struct stoken));
|
||||
|
||||
extern void
|
||||
start_arglist PARAMS ((void));
|
||||
|
||||
extern int
|
||||
end_arglist PARAMS ((void));
|
||||
|
||||
extern void
|
||||
free_funcalls PARAMS ((void));
|
||||
|
||||
extern char *
|
||||
copy_name PARAMS ((struct stoken));
|
||||
|
||||
extern void
|
||||
push_type PARAMS ((enum type_pieces));
|
||||
|
||||
extern void
|
||||
push_type_int PARAMS ((int));
|
||||
|
||||
extern enum type_pieces
|
||||
pop_type PARAMS ((void));
|
||||
|
||||
extern int
|
||||
pop_type_int PARAMS ((void));
|
||||
|
||||
/* During parsing of a C expression, the pointer to the next character
|
||||
is in this variable. */
|
||||
@ -160,3 +191,5 @@ struct op_print
|
||||
enum precedence precedence;
|
||||
int right_assoc;
|
||||
};
|
||||
|
||||
#endif /* PARSER_DEFS_H */
|
||||
|
@ -47,8 +47,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
SET_NAMESTRING();
|
||||
|
||||
bss_ext_symbol:
|
||||
record_misc_function (namestring, CUR_SYMBOL_VALUE,
|
||||
CUR_SYMBOL_TYPE); /* Always */
|
||||
record_minimal_symbol (namestring, CUR_SYMBOL_VALUE,
|
||||
CUR_SYMBOL_TYPE, objfile); /* Always */
|
||||
#endif /* DBXREAD_ONLY */
|
||||
continue;
|
||||
|
||||
@ -108,8 +108,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|| VTBL_PREFIX_P ((namestring+HASH_OFFSET)))
|
||||
{
|
||||
/* Not really a function here, but... */
|
||||
record_misc_function (namestring, CUR_SYMBOL_VALUE,
|
||||
CUR_SYMBOL_TYPE); /* Always */
|
||||
record_minimal_symbol (namestring, CUR_SYMBOL_VALUE,
|
||||
CUR_SYMBOL_TYPE, objfile); /* Always */
|
||||
}
|
||||
#endif /* DBXREAD_ONLY */
|
||||
continue;
|
||||
@ -182,15 +182,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
The first one is a directory name; the second the file name.
|
||||
If pst exists, is empty, and has a filename ending in '/',
|
||||
we assume the previous N_SO was a directory name. */
|
||||
if (global_psymbols.next
|
||||
== (global_psymbols.list + pst->globals_offset)
|
||||
&& static_psymbols.next
|
||||
== (static_psymbols.list + pst->statics_offset)
|
||||
if (pst -> objfile -> global_psymbols.next
|
||||
== (pst -> objfile -> global_psymbols.list + pst->globals_offset)
|
||||
&& pst -> objfile -> static_psymbols.next
|
||||
== (pst -> objfile -> static_psymbols.list + pst->statics_offset)
|
||||
&& pst->filename && pst->filename[0]
|
||||
&& pst->filename[strlen(pst->filename)-1] == '/') {
|
||||
/* Just replace the directory name with the real filename. */
|
||||
pst->filename =
|
||||
(char *) obstack_alloc (psymbol_obstack,
|
||||
(char *) obstack_alloc (&pst->objfile->psymbol_obstack,
|
||||
strlen (namestring) + 1);
|
||||
strcpy (pst->filename, namestring);
|
||||
continue;
|
||||
@ -208,7 +208,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
pst = START_PSYMTAB (objfile, addr,
|
||||
namestring, valu,
|
||||
first_symnum * symbol_size,
|
||||
global_psymbols.next, static_psymbols.next);
|
||||
objfile -> global_psymbols.next,
|
||||
objfile -> static_psymbols.next);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -299,20 +300,20 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
case 'T':
|
||||
ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
|
||||
STRUCT_NAMESPACE, LOC_TYPEDEF,
|
||||
static_psymbols, CUR_SYMBOL_VALUE);
|
||||
objfile->static_psymbols, CUR_SYMBOL_VALUE);
|
||||
if (p[2] == 't')
|
||||
{
|
||||
/* Also a typedef with the same name. */
|
||||
ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
|
||||
VAR_NAMESPACE, LOC_TYPEDEF,
|
||||
static_psymbols, CUR_SYMBOL_VALUE);
|
||||
objfile->static_psymbols, CUR_SYMBOL_VALUE);
|
||||
p += 1;
|
||||
}
|
||||
goto check_enum;
|
||||
case 't':
|
||||
ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
|
||||
VAR_NAMESPACE, LOC_TYPEDEF,
|
||||
static_psymbols, CUR_SYMBOL_VALUE);
|
||||
objfile->static_psymbols, CUR_SYMBOL_VALUE);
|
||||
check_enum:
|
||||
/* If this is an enumerated type, we need to
|
||||
add all the enum constants to the partial symbol
|
||||
@ -361,7 +362,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
enum constants in psymtabs, just in symtabs. */
|
||||
ADD_PSYMBOL_TO_LIST (p, q - p,
|
||||
VAR_NAMESPACE, LOC_CONST,
|
||||
static_psymbols, 0);
|
||||
objfile->static_psymbols, 0);
|
||||
/* Point past the name. */
|
||||
p = q;
|
||||
/* Skip over the value. */
|
||||
@ -377,7 +378,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
/* Constant, e.g. from "const" in Pascal. */
|
||||
ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
|
||||
VAR_NAMESPACE, LOC_CONST,
|
||||
static_psymbols, CUR_SYMBOL_VALUE);
|
||||
objfile->static_psymbols, CUR_SYMBOL_VALUE);
|
||||
continue;
|
||||
default:
|
||||
/* Skip if the thing following the : is
|
||||
@ -418,13 +419,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
case 'c':
|
||||
ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
|
||||
VAR_NAMESPACE, LOC_CONST,
|
||||
static_psymbols, CUR_SYMBOL_VALUE);
|
||||
objfile->static_psymbols, CUR_SYMBOL_VALUE);
|
||||
continue;
|
||||
case 'S':
|
||||
CUR_SYMBOL_VALUE += addr; /* Relocate */
|
||||
ADD_PSYMBOL_ADDR_TO_LIST (namestring, p - namestring,
|
||||
VAR_NAMESPACE, LOC_STATIC,
|
||||
static_psymbols, CUR_SYMBOL_VALUE);
|
||||
objfile->static_psymbols, CUR_SYMBOL_VALUE);
|
||||
continue;
|
||||
case 'G':
|
||||
CUR_SYMBOL_VALUE += addr; /* Relocate */
|
||||
@ -432,19 +433,19 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
wrong. See the code that reads 'G's for symtabs. */
|
||||
ADD_PSYMBOL_ADDR_TO_LIST (namestring, p - namestring,
|
||||
VAR_NAMESPACE, LOC_STATIC,
|
||||
global_psymbols, CUR_SYMBOL_VALUE);
|
||||
objfile->global_psymbols, CUR_SYMBOL_VALUE);
|
||||
continue;
|
||||
|
||||
case 't':
|
||||
ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
|
||||
VAR_NAMESPACE, LOC_TYPEDEF,
|
||||
static_psymbols, CUR_SYMBOL_VALUE);
|
||||
objfile->static_psymbols, CUR_SYMBOL_VALUE);
|
||||
continue;
|
||||
|
||||
case 'f':
|
||||
ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
|
||||
VAR_NAMESPACE, LOC_BLOCK,
|
||||
static_psymbols, CUR_SYMBOL_VALUE);
|
||||
objfile->static_psymbols, CUR_SYMBOL_VALUE);
|
||||
continue;
|
||||
|
||||
/* Global functions were ignored here, but now they
|
||||
@ -455,7 +456,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
case 'F':
|
||||
ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
|
||||
VAR_NAMESPACE, LOC_BLOCK,
|
||||
global_psymbols, CUR_SYMBOL_VALUE);
|
||||
objfile->global_psymbols, CUR_SYMBOL_VALUE);
|
||||
continue;
|
||||
|
||||
/* Two things show up here (hopefully); static symbols of
|
||||
|
186
gdb/procfs.c
186
gdb/procfs.c
@ -32,6 +32,7 @@ regardless of whether or not the actual target has floating point hardware.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
@ -42,7 +43,6 @@ regardless of whether or not the actual target has floating point hardware.
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "ansidecl.h"
|
||||
#include "inferior.h"
|
||||
#include "target.h"
|
||||
|
||||
@ -50,14 +50,6 @@ regardless of whether or not the actual target has floating point hardware.
|
||||
#define PROC_NAME_FMT "/proc/%d"
|
||||
#endif
|
||||
|
||||
extern void EXFUN(supply_gregset, (gregset_t *gregsetp));
|
||||
extern void EXFUN(fill_gregset, (gregset_t *gresetp, int regno));
|
||||
|
||||
#if defined (FP0_REGNUM)
|
||||
extern void EXFUN(supply_fpregset, (fpregset_t *fpregsetp));
|
||||
extern void EXFUN(fill_fpregset, (fpregset_t *fpresetp, int regno));
|
||||
#endif
|
||||
|
||||
#if 1 /* FIXME: Gross and ugly hack to resolve coredep.c global */
|
||||
CORE_ADDR kernel_u_addr;
|
||||
#endif
|
||||
@ -89,16 +81,47 @@ struct procinfo {
|
||||
|
||||
static struct procinfo pi; /* Inferior's process information */
|
||||
|
||||
/* Forward declarations of static functions so we don't have to worry
|
||||
about ordering within this file. The EXFUN macro may be slightly
|
||||
misleading. Should probably be called DCLFUN instead, or something
|
||||
more intuitive, since it can be used for both static and external
|
||||
definitions. */
|
||||
/* Prototypes for local functions */
|
||||
|
||||
static int
|
||||
proc_address_to_fd PARAMS ((CORE_ADDR, int));
|
||||
|
||||
static int
|
||||
open_proc_file PARAMS ((int, struct procinfo *));
|
||||
|
||||
static void
|
||||
close_proc_file PARAMS ((struct procinfo *));
|
||||
|
||||
static void
|
||||
unconditionally_kill_inferior PARAMS ((void));
|
||||
|
||||
static void
|
||||
proc_init_failed PARAMS ((char *));
|
||||
|
||||
static void
|
||||
proc_info PARAMS ((char *, int));
|
||||
|
||||
static void
|
||||
proc_info_address_map PARAMS ((struct procinfo *, int));
|
||||
|
||||
static char *
|
||||
mappingflags PARAMS ((long));
|
||||
|
||||
/* External function prototypes that can't be easily included in any
|
||||
header file because the args are typedefs in system include files. */
|
||||
|
||||
extern void
|
||||
supply_gregset PARAMS ((gregset_t *));
|
||||
|
||||
extern void
|
||||
fill_gregset PARAMS ((gregset_t *, int));
|
||||
|
||||
extern void
|
||||
supply_fpregset PARAMS ((fpregset_t *));
|
||||
|
||||
extern void
|
||||
fill_fpregset PARAMS ((fpregset_t *, int));
|
||||
|
||||
static void EXFUN(proc_init_failed, (char *why));
|
||||
static int EXFUN(open_proc_file, (int pid, struct procinfo *pip));
|
||||
static void EXFUN(close_proc_file, (struct procinfo *pip));
|
||||
static void EXFUN(unconditionally_kill_inferior, (void));
|
||||
|
||||
/*
|
||||
|
||||
@ -120,11 +143,11 @@ DESCRIPTION
|
||||
*/
|
||||
|
||||
int
|
||||
DEFUN(ptrace, (request, pid, arg3, arg4),
|
||||
int request AND
|
||||
int pid AND
|
||||
int arg3 AND
|
||||
int arg4)
|
||||
ptrace (request, pid, arg3, arg4)
|
||||
int request;
|
||||
int pid;
|
||||
int arg3;
|
||||
int arg4;
|
||||
{
|
||||
error ("internal error - there is a call to ptrace() somewhere");
|
||||
/*NOTREACHED*/
|
||||
@ -155,7 +178,7 @@ NOTES
|
||||
*/
|
||||
|
||||
void
|
||||
DEFUN_VOID(kill_inferior_fast)
|
||||
kill_inferior_fast ()
|
||||
{
|
||||
if (inferior_pid != 0 && !attach_flag)
|
||||
{
|
||||
@ -186,7 +209,7 @@ NOTES
|
||||
*/
|
||||
|
||||
void
|
||||
DEFUN_VOID(kill_inferior)
|
||||
kill_inferior ()
|
||||
{
|
||||
if (inferior_pid != 0)
|
||||
{
|
||||
@ -219,7 +242,7 @@ NOTE
|
||||
*/
|
||||
|
||||
static void
|
||||
DEFUN_VOID(unconditionally_kill_inferior)
|
||||
unconditionally_kill_inferior ()
|
||||
{
|
||||
int signo;
|
||||
|
||||
@ -258,12 +281,12 @@ NOTES
|
||||
|
||||
|
||||
int
|
||||
DEFUN(child_xfer_memory, (memaddr, myaddr, len, dowrite, target),
|
||||
CORE_ADDR memaddr AND
|
||||
char *myaddr AND
|
||||
int len AND
|
||||
int dowrite AND
|
||||
struct target_ops *target /* ignored */)
|
||||
child_xfer_memory (memaddr, myaddr, len, dowrite, target)
|
||||
CORE_ADDR memaddr;
|
||||
char *myaddr;
|
||||
int len;
|
||||
int dowrite;
|
||||
struct target_ops *target; /* ignored */
|
||||
{
|
||||
int nbytes = 0;
|
||||
|
||||
@ -324,8 +347,8 @@ NOTES
|
||||
*/
|
||||
|
||||
void
|
||||
DEFUN(store_inferior_registers, (regno),
|
||||
int regno)
|
||||
store_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
if (regno != -1)
|
||||
{
|
||||
@ -376,8 +399,8 @@ NOTES
|
||||
*/
|
||||
|
||||
void
|
||||
DEFUN(inferior_proc_init, (pid),
|
||||
int pid)
|
||||
inferior_proc_init (pid)
|
||||
int pid;
|
||||
{
|
||||
if (!open_proc_file (pid, &pi))
|
||||
{
|
||||
@ -432,7 +455,7 @@ NOTE
|
||||
*/
|
||||
|
||||
void
|
||||
DEFUN_VOID(proc_set_exec_trap)
|
||||
proc_set_exec_trap ()
|
||||
{
|
||||
sysset_t exitset;
|
||||
auto char procname[32];
|
||||
@ -476,8 +499,8 @@ DESCRIPTION
|
||||
*/
|
||||
|
||||
int
|
||||
DEFUN(proc_iterate_over_mappings, (func),
|
||||
int (*func)())
|
||||
proc_iterate_over_mappings (func)
|
||||
int (*func) PARAMS ((int, CORE_ADDR));
|
||||
{
|
||||
int nmap;
|
||||
int fd;
|
||||
@ -488,13 +511,13 @@ DEFUN(proc_iterate_over_mappings, (func),
|
||||
|
||||
if (pi.valid && (ioctl (pi.fd, PIOCNMAP, &nmap) == 0))
|
||||
{
|
||||
prmaps = alloca ((nmap + 1) * sizeof (*prmaps));
|
||||
prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
|
||||
if (ioctl (pi.fd, PIOCMAP, prmaps) == 0)
|
||||
{
|
||||
for (prmap = prmaps; prmap -> pr_size && funcstat == 0; ++prmap)
|
||||
{
|
||||
fd = proc_address_to_fd (prmap -> pr_vaddr, 0);
|
||||
funcstat = (*func) (fd, prmap -> pr_vaddr);
|
||||
fd = proc_address_to_fd ((CORE_ADDR) prmap -> pr_vaddr, 0);
|
||||
funcstat = (*func) (fd, (CORE_ADDR) prmap -> pr_vaddr);
|
||||
close (fd);
|
||||
}
|
||||
}
|
||||
@ -524,9 +547,11 @@ DESCRIPTION
|
||||
*/
|
||||
|
||||
|
||||
#if 0 /* Currently unused */
|
||||
|
||||
CORE_ADDR
|
||||
DEFUN(proc_base_address, (addr),
|
||||
CORE_ADDR addr)
|
||||
proc_base_address (addr)
|
||||
CORE_ADDR addr;
|
||||
{
|
||||
int nmap;
|
||||
struct prmap *prmaps;
|
||||
@ -535,7 +560,7 @@ DEFUN(proc_base_address, (addr),
|
||||
|
||||
if (pi.valid && (ioctl (pi.fd, PIOCNMAP, &nmap) == 0))
|
||||
{
|
||||
prmaps = alloca ((nmap + 1) * sizeof (*prmaps));
|
||||
prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
|
||||
if (ioctl (pi.fd, PIOCMAP, prmaps) == 0)
|
||||
{
|
||||
for (prmap = prmaps; prmap -> pr_size; ++prmap)
|
||||
@ -552,6 +577,8 @@ DEFUN(proc_base_address, (addr),
|
||||
return (baseaddr);
|
||||
}
|
||||
|
||||
#endif /* 0 */
|
||||
|
||||
/*
|
||||
|
||||
GLOBAL_FUNCTION
|
||||
@ -572,10 +599,10 @@ DESCRIPTION
|
||||
|
||||
*/
|
||||
|
||||
int
|
||||
DEFUN(proc_address_to_fd, (addr, complain),
|
||||
CORE_ADDR addr AND
|
||||
int complain)
|
||||
static int
|
||||
proc_address_to_fd (addr, complain)
|
||||
CORE_ADDR addr;
|
||||
int complain;
|
||||
{
|
||||
int fd = -1;
|
||||
|
||||
@ -621,8 +648,8 @@ NOTES
|
||||
*/
|
||||
|
||||
int
|
||||
DEFUN(attach, (pid),
|
||||
int pid)
|
||||
attach (pid)
|
||||
int pid;
|
||||
{
|
||||
if (!open_proc_file (pid, &pi))
|
||||
{
|
||||
@ -714,8 +741,8 @@ DESCRIPTION
|
||||
*/
|
||||
|
||||
void
|
||||
DEFUN(detach, (signal),
|
||||
int signal)
|
||||
detach (signal)
|
||||
int signal;
|
||||
{
|
||||
if (signal)
|
||||
{
|
||||
@ -815,8 +842,8 @@ NOTES
|
||||
*/
|
||||
|
||||
int
|
||||
DEFUN(proc_wait, (statloc),
|
||||
int *statloc)
|
||||
proc_wait (statloc)
|
||||
int *statloc;
|
||||
{
|
||||
short what;
|
||||
short why;
|
||||
@ -950,9 +977,9 @@ NOTE
|
||||
*/
|
||||
|
||||
void
|
||||
DEFUN(child_resume, (step, signal),
|
||||
int step AND
|
||||
int signal)
|
||||
child_resume (step, signal)
|
||||
int step;
|
||||
int signal;
|
||||
{
|
||||
errno = 0;
|
||||
pi.prrun.pr_flags = PRSVADDR | PRSTRACE | PRSFAULT | PRCFAULT;
|
||||
@ -991,7 +1018,7 @@ GLOBAL FUNCTION
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
void fetch_inferior_registers (void)
|
||||
void fetch_inferior_registers (int regno)
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
@ -1002,7 +1029,8 @@ DESCRIPTION
|
||||
*/
|
||||
|
||||
void
|
||||
DEFUN_VOID(fetch_inferior_registers)
|
||||
fetch_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
if (ioctl (pi.fd, PIOCGREG, &pi.gregset) != -1)
|
||||
{
|
||||
@ -1025,7 +1053,7 @@ GLOBAL FUNCTION
|
||||
SYNOPSIS
|
||||
|
||||
void fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
|
||||
int which)
|
||||
int which, unsigned in reg_addr)
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
@ -1041,10 +1069,11 @@ NOTES
|
||||
*/
|
||||
|
||||
void
|
||||
fetch_core_registers (core_reg_sect, core_reg_size, which)
|
||||
fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
|
||||
char *core_reg_sect;
|
||||
unsigned core_reg_size;
|
||||
int which;
|
||||
unsigned int reg_addr; /* Unused in this version */
|
||||
{
|
||||
|
||||
if (which == 0)
|
||||
@ -1096,8 +1125,8 @@ DESCRIPTION
|
||||
*/
|
||||
|
||||
static void
|
||||
DEFUN(proc_init_failed, (why),
|
||||
char *why)
|
||||
proc_init_failed (why)
|
||||
char *why;
|
||||
{
|
||||
print_sys_errmsg (pi.pathname, errno);
|
||||
(void) kill (pi.pid, SIGKILL);
|
||||
@ -1126,8 +1155,8 @@ DESCRIPTION
|
||||
*/
|
||||
|
||||
static void
|
||||
DEFUN(close_proc_file, (pip),
|
||||
struct procinfo *pip)
|
||||
close_proc_file (pip)
|
||||
struct procinfo *pip;
|
||||
{
|
||||
pip -> pid = 0;
|
||||
if (pip -> valid)
|
||||
@ -1167,9 +1196,9 @@ DESCRIPTION
|
||||
*/
|
||||
|
||||
static int
|
||||
DEFUN(open_proc_file, (pid, pip),
|
||||
int pid AND
|
||||
struct procinfo *pip)
|
||||
open_proc_file (pid, pip)
|
||||
int pid;
|
||||
struct procinfo *pip;
|
||||
{
|
||||
pip -> valid = 0;
|
||||
if (pip -> valid)
|
||||
@ -1190,8 +1219,8 @@ DEFUN(open_proc_file, (pid, pip),
|
||||
}
|
||||
|
||||
static char *
|
||||
DEFUN (mappingflags, (flags),
|
||||
long flags)
|
||||
mappingflags (flags)
|
||||
long flags;
|
||||
{
|
||||
static char asciiflags[7];
|
||||
|
||||
@ -1206,9 +1235,9 @@ DEFUN (mappingflags, (flags),
|
||||
}
|
||||
|
||||
static void
|
||||
DEFUN(proc_info_address_map, (pip, verbose),
|
||||
struct procinfo *pip AND
|
||||
int verbose)
|
||||
proc_info_address_map (pip, verbose)
|
||||
struct procinfo *pip;
|
||||
int verbose;
|
||||
{
|
||||
int nmap;
|
||||
struct prmap *prmaps;
|
||||
@ -1223,7 +1252,7 @@ DEFUN(proc_info_address_map, (pip, verbose),
|
||||
"Flags");
|
||||
if (ioctl (pip -> fd, PIOCNMAP, &nmap) == 0)
|
||||
{
|
||||
prmaps = alloca ((nmap + 1) * sizeof (*prmaps));
|
||||
prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
|
||||
if (ioctl (pip -> fd, PIOCMAP, prmaps) == 0)
|
||||
{
|
||||
for (prmap = prmaps; prmap -> pr_size; ++prmap)
|
||||
@ -1265,9 +1294,9 @@ DESCRIPTION
|
||||
*/
|
||||
|
||||
static void
|
||||
DEFUN(proc_info, (args, from_tty),
|
||||
char *args AND
|
||||
int from_tty)
|
||||
proc_info (args, from_tty)
|
||||
char *args;
|
||||
int from_tty;
|
||||
{
|
||||
int verbose = 0;
|
||||
int pid;
|
||||
@ -1275,7 +1304,6 @@ DEFUN(proc_info, (args, from_tty),
|
||||
struct procinfo *pip;
|
||||
struct cleanup *old_chain;
|
||||
char *nexttok;
|
||||
extern char *strtok ();
|
||||
|
||||
old_chain = make_cleanup (null_cleanup, 0);
|
||||
|
||||
|
@ -32,11 +32,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include <sys/user.h> /* After a.out.h */
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
void
|
||||
fetch_inferior_registers ()
|
||||
fetch_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
register int regno, datum;
|
||||
register int datum;
|
||||
register unsigned int regaddr;
|
||||
int reg_buf[NUM_REGS+1];
|
||||
struct user u;
|
||||
@ -124,6 +126,7 @@ fetch_inferior_registers ()
|
||||
If REGNO is -1, do this for all registers.
|
||||
Otherwise, REGNO specifies which register (so we can save time). */
|
||||
|
||||
void
|
||||
store_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
|
@ -1083,7 +1083,7 @@ int from_tty;
|
||||
/* You may need to do an init_target_mm() */
|
||||
/* init_target_mm(?,?,?,?,?,?,?,?); */
|
||||
immediate_quit--;
|
||||
/* symbol_file_add (arg_string, from_tty, text_addr, 0); */
|
||||
/* (void) symbol_file_add (arg_string, from_tty, text_addr, 0); */
|
||||
#endif
|
||||
|
||||
}
|
||||
|
@ -301,7 +301,7 @@ nindy_load( filename, from_tty )
|
||||
|
||||
tmpfile = coffstrip(scratch_pathname);
|
||||
if ( tmpfile ){
|
||||
old_chain = make_cleanup(unlink,tmpfile);
|
||||
old_chain = make_cleanup (unlink,tmpfile);
|
||||
immediate_quit++;
|
||||
ninDownload( tmpfile, !from_tty );
|
||||
/* FIXME, don't we want this merged in here? */
|
||||
|
@ -47,10 +47,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "xdr_rdb.h"
|
||||
#include "dbgRpcLib.h"
|
||||
|
||||
/* get rid of value.h if possible */
|
||||
#include <value.h>
|
||||
#include <symtab.h>
|
||||
|
||||
|
||||
extern void symbol_file_command ();
|
||||
extern int stop_soon_quietly; /* for wait_for_inferior */
|
||||
|
||||
@ -718,7 +716,7 @@ vx_load_command (arg_string, from_tty)
|
||||
immediate_quit--;
|
||||
|
||||
/* FIXME, for now we ignore data_addr and bss_addr. */
|
||||
symbol_file_add (arg_string, from_tty, text_addr, 0);
|
||||
(void) symbol_file_add (arg_string, from_tty, text_addr, 0);
|
||||
}
|
||||
|
||||
#ifdef FIXME /* Not ready for prime time */
|
||||
@ -1041,7 +1039,7 @@ add_symbol_stub (arg)
|
||||
struct ldfile *pLoadFile = (struct ldfile *)arg;
|
||||
|
||||
printf("\t%s: ", pLoadFile->name);
|
||||
symbol_file_add (pLoadFile->name, 0, pLoadFile->txt_addr, 0);
|
||||
(void) symbol_file_add (pLoadFile->name, 0, pLoadFile->txt_addr, 0);
|
||||
printf ("ok\n");
|
||||
return 1;
|
||||
}
|
||||
|
@ -60,7 +60,8 @@ static int special_regs[] = {
|
||||
extern int one_stepped;
|
||||
|
||||
|
||||
fetch_inferior_registers ()
|
||||
fetch_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
int ii;
|
||||
extern char registers[];
|
||||
@ -87,6 +88,7 @@ fetch_inferior_registers ()
|
||||
If REGNO is -1, do this for all registers.
|
||||
Otherwise, REGNO specifies which register (so we can save time). */
|
||||
|
||||
void
|
||||
store_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
@ -156,16 +158,15 @@ store_inferior_registers (regno)
|
||||
|
||||
if ( errno ) {
|
||||
perror ("ptrace write"); errno = 0;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
fetch_core_registers (core_reg_sect, core_reg_size, which)
|
||||
fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
|
||||
char *core_reg_sect;
|
||||
unsigned core_reg_size;
|
||||
int which;
|
||||
unsigned int reg_addr; /* Unused in this version */
|
||||
{
|
||||
/* fetch GPRs and special registers from the first register section
|
||||
in core bfd. */
|
||||
@ -230,7 +231,6 @@ unsigned int pid;
|
||||
{
|
||||
#define MAX_LOAD_SEGS 64 /* maximum number of load segments */
|
||||
|
||||
extern int compare_misc_functions ();
|
||||
struct ld_info *ldi;
|
||||
int temp;
|
||||
|
||||
@ -256,7 +256,7 @@ unsigned int pid;
|
||||
&& (ldi = (void *) (ldi->ldinfo_next + (char *) ldi)));
|
||||
|
||||
/* Now that we've jumbled things around, re-sort them. */
|
||||
sort_misc_function_vector ();
|
||||
sort_minimal_symbols ();
|
||||
|
||||
/* relocate the exec and core sections as well. */
|
||||
vmap_exec ();
|
||||
|
777
gdb/state.c
Normal file
777
gdb/state.c
Normal file
@ -0,0 +1,777 @@
|
||||
/* Support for dumping and reloading various pieces of GDB's internal state.
|
||||
Copyright 1992 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support, using pieces from other GDB modules.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 of the License, 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. */
|
||||
|
||||
/* This file provides support for dumping and then later reloading various
|
||||
portions of gdb's internal state. It was originally implemented to
|
||||
support a need for mapping in an image of gdb's symbol table from an
|
||||
external file, where this image was created by an external program, such
|
||||
as an incremental linker. However, it was generalized to enable future
|
||||
support for dumping and reloading various other useful pieces of gdb's
|
||||
internal state.
|
||||
|
||||
State files have a fairly simple form which is intended to be easily
|
||||
extensible. The basic format is:
|
||||
|
||||
<file-header> <state-data> <form-tree>
|
||||
|
||||
Where:
|
||||
|
||||
file-header A simple file-header containing a magic number
|
||||
so that gdb (and other readers) can quickly
|
||||
determine what kind of file this is, and a file
|
||||
offset to the root of the form-tree.
|
||||
|
||||
state-data The "raw" state-data that is referenced by nodes
|
||||
in the form-tree.
|
||||
|
||||
form-tree A tree of arbitrarily sized nodes containing
|
||||
information about gdb's internal state, and
|
||||
possibly referencing data in the state-data section
|
||||
of the file. Resembles DWARF in some respects.
|
||||
|
||||
When writing a state file, a hole is left for the file-header at the
|
||||
beginning of the file, the state data is written immediately after the
|
||||
file header (while storing the file offsets and sizes back into the
|
||||
internal form-tree along the way), the form-tree itself is written
|
||||
at the end of the file, and then the file header is written by seeking
|
||||
back to the beginning of the file. This order is required because
|
||||
the form tree contains file offsets and sizes in the state data portion
|
||||
of the file, and the file header contains the file offset to the start
|
||||
of the form tree.
|
||||
|
||||
Readers simply open the file, validate the magic number, seek to the
|
||||
root of the form-tree, and walk the tree looking for the information that
|
||||
they are interested in (and ignoring things that they aren't, or don't
|
||||
understand).
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "defs.h"
|
||||
#include "symtab.h"
|
||||
#include "bfd.h"
|
||||
#include "symfile.h"
|
||||
#include "state.h"
|
||||
|
||||
#ifndef SEEK_SET
|
||||
#define SEEK_SET 0
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_END
|
||||
#define SEEK_END 2
|
||||
#endif
|
||||
|
||||
/* Inside the state file, the form-tree consists of a series of
|
||||
form-tree entries (FTE's). The parent/child/sibling relationships
|
||||
are implied by the ordering and by an explicit sibling reference
|
||||
in FTE's that have siblings.
|
||||
|
||||
Specifically, given two sequential FTE's, say A and B, if B immediately
|
||||
follows A, and A does not have a sibling reference to B, then B is
|
||||
the first child of A. Otherwise B must be a sibling of A and A must
|
||||
have a sibling reference for it.
|
||||
|
||||
Each FTE is simply an array of long integers, with at least three
|
||||
members. This form was chosen over a packed data form for simplicity
|
||||
in access, not having to worry about the relative sizes of the different
|
||||
integers (short, int, long), and not having to worry about alignment
|
||||
constraints. Also in the name of simplicity, every FTE has a sibling
|
||||
reference slot reserved for it, even if there are no siblings.
|
||||
|
||||
The first value in an FTE is the size of the FTE in bytes, including
|
||||
the size value itself. The second entry contains a tag which indicates
|
||||
the type of the FTE. The third entry is a sibling reference, which either
|
||||
refers to a valid sibling node or is zero. Following is zero or more
|
||||
attributes, each of which consists of one or more long values. */
|
||||
|
||||
/* Tag names and codes. */
|
||||
|
||||
#define TAG_padding 0x0000 /* Padding */
|
||||
#define TAG_objfile 0x0001 /* Dumped objfile */
|
||||
|
||||
/* Form names, codes, and macros. */
|
||||
|
||||
#define FORM_ABSREF 0x01 /* Next long is absolute file offset */
|
||||
#define FORM_RELREF 0x02 /* Next long is relative file offset */
|
||||
#define FORM_IVAL 0x03 /* Next long is int value */
|
||||
#define FORM_ADDR 0x04 /* Next long is mem addr */
|
||||
|
||||
#define FORM_MASK 0xFF
|
||||
#define FORM_X(atr) ((atr) & FORM_MASK)
|
||||
|
||||
/* Attribute names and codes. */
|
||||
|
||||
#define AT_sibling (0x0100 | FORM_RELREF) /* Reference to sibling node */
|
||||
#define AT_name (0x0200 | FORM_ABSREF) /* Reference to a string */
|
||||
#define AT_offset (0x0300 | FORM_ABSREF) /* Reference to generic data */
|
||||
#define AT_size (0x0400 | FORM_IVAL)
|
||||
#define AT_addr (0x0500 | FORM_ADDR)
|
||||
#define AT_aux_addr (0x0600 | FORM_ADDR)
|
||||
|
||||
/* */
|
||||
|
||||
static void
|
||||
load_symbols PARAMS ((FILE *));
|
||||
|
||||
static void
|
||||
dump_state_command PARAMS ((char *, int));
|
||||
|
||||
static void
|
||||
load_state_command PARAMS ((char *, int));
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
|
||||
static void
|
||||
write_header PARAMS ((sfd *));
|
||||
|
||||
static void
|
||||
write_formtree PARAMS ((sfd *));
|
||||
|
||||
static void
|
||||
write_objfile_state PARAMS ((sfd *));
|
||||
|
||||
static void
|
||||
free_subtree PARAMS ((struct formnode *));
|
||||
|
||||
static void
|
||||
size_subtree PARAMS ((struct formnode *));
|
||||
|
||||
#endif
|
||||
|
||||
struct formnode *formtree = NULL;
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
load_symbols (statefile)
|
||||
FILE *statefile;
|
||||
{
|
||||
|
||||
#if 0
|
||||
/* Discard old symbols. FIXME: This is essentially symbol_file_command's
|
||||
body when there is no name. Make it a common function that is
|
||||
called from each place. */
|
||||
|
||||
if (symfile_objfile)
|
||||
{
|
||||
free_objfile (symfile_objfile);
|
||||
}
|
||||
symfile_objfile = NULL;
|
||||
#endif
|
||||
|
||||
#if 0 && defined (HAVE_MMAP)
|
||||
if (mtop > mbase)
|
||||
{
|
||||
warning ("internal error: mbase (%08x) != mtop (%08x)",
|
||||
mbase, mtop);
|
||||
munmap (mbase, mtop - mbase);
|
||||
}
|
||||
#endif /* HAVE_MMAP */
|
||||
|
||||
/* Getting new symbols may change our opinion about what is frameless. */
|
||||
|
||||
reinit_frame_cache ();
|
||||
|
||||
}
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
|
||||
/* Allocate a form node */
|
||||
|
||||
static struct formnode *
|
||||
alloc_formnode ()
|
||||
{
|
||||
struct formnode *fnp;
|
||||
|
||||
fnp = (struct formnode *) xmalloc (sizeof (struct formnode));
|
||||
(void) memset (fnp, 0, sizeof (struct formnode));
|
||||
fnp -> sibling = formtree;
|
||||
formtree = fnp;
|
||||
return (fnp);
|
||||
}
|
||||
|
||||
/* Recursively walk a form-tree from the specified node, freeing
|
||||
nodes from the bottom up. The concept is pretty simple, just free
|
||||
all the child nodes, then all the sibling nodes, then the node
|
||||
itself. */
|
||||
|
||||
static void
|
||||
free_subtree (fnp)
|
||||
struct formnode *fnp;
|
||||
{
|
||||
if (fnp != NULL)
|
||||
{
|
||||
free_subtree (fnp -> child);
|
||||
free_subtree (fnp -> sibling);
|
||||
if (fnp -> nodedata != NULL)
|
||||
{
|
||||
free (fnp -> nodedata);
|
||||
}
|
||||
free (fnp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Recursively walk a form-tree from the specified node, computing the
|
||||
size of each subtree from the bottom up.
|
||||
|
||||
At each node, the file space that will be consumed by the subtree
|
||||
rooted in that node is the sum of all the subtrees rooted in each
|
||||
child node plus the size of the node itself.
|
||||
|
||||
Thus for each node, we size the child subtrees, add to that our
|
||||
size, contribute this size towards the size of any parent node, and
|
||||
then ask any of our siblings to do the same.
|
||||
|
||||
Also, once we know the size of any subtree rooted at this node, we
|
||||
can initialize the offset to the sibling node (if any).
|
||||
|
||||
Since every form-tree node must have valid nodedata at this point,
|
||||
we detect and report a warning for any node that doesn't. */
|
||||
|
||||
static void
|
||||
size_subtree (fnp)
|
||||
struct formnode *fnp;
|
||||
{
|
||||
long *lp;
|
||||
|
||||
if (fnp != NULL)
|
||||
{
|
||||
if (fnp -> nodedata == NULL)
|
||||
{
|
||||
warning ("internal error -- empty form node");
|
||||
}
|
||||
else
|
||||
{
|
||||
size_subtree (fnp -> child);
|
||||
fnp -> treesize += *(long *) fnp -> nodedata;
|
||||
if (fnp -> parent != NULL)
|
||||
{
|
||||
fnp -> parent -> treesize += fnp -> treesize;
|
||||
}
|
||||
if (fnp -> sibling)
|
||||
{
|
||||
size_subtree (fnp -> sibling);
|
||||
lp = (long *) (fnp -> nodedata + 2 * sizeof (long));
|
||||
*lp = fnp -> treesize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Recursively walk a form-tree from the specified node, writing
|
||||
nodes from the top down. */
|
||||
|
||||
static void
|
||||
write_subtree (fnp, asfd)
|
||||
struct formnode *fnp;
|
||||
sfd *asfd;
|
||||
{
|
||||
if (fnp != NULL)
|
||||
{
|
||||
if (fnp -> nodedata != NULL)
|
||||
{
|
||||
fwrite (fnp -> nodedata, *(long *) fnp -> nodedata, 1, asfd -> fp);
|
||||
}
|
||||
write_subtree (fnp -> child, asfd);
|
||||
write_subtree (fnp -> sibling, asfd);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the entire current formtree. Called via do_cleanups, regardless
|
||||
of whether there is an error or not. */
|
||||
|
||||
static void
|
||||
free_formtree ()
|
||||
{
|
||||
free_subtree (formtree);
|
||||
formtree = NULL;
|
||||
}
|
||||
|
||||
/* Write out the file header. Generally this is done last, even though
|
||||
it is located at the start of the file, since we need to have file
|
||||
offset to where the annotated form tree was written, and it's size. */
|
||||
|
||||
static void
|
||||
write_header (asfd)
|
||||
sfd *asfd;
|
||||
{
|
||||
fseek (asfd -> fp, 0L, SEEK_SET);
|
||||
fwrite ((char *) &asfd -> hdr, sizeof (asfd -> hdr), 1, asfd -> fp);
|
||||
}
|
||||
|
||||
/* Write out the annotated form tree. We should already have written out
|
||||
the state data, and noted the file offsets and sizes in each node of
|
||||
the form tree that references part of the state data.
|
||||
|
||||
The form tree can be written anywhere in the file where there is room
|
||||
for it. Since there is always room at the end of the file, we write
|
||||
it there. We also need to record the file offset to the start of the
|
||||
form tree, and it's size, for future use when writing the file header.
|
||||
|
||||
In order to compute the sibling references, we need to know, at
|
||||
each node, how much space will be consumed when all of that node's
|
||||
children nodes have been written. Thus we walk the tree, computing
|
||||
the sizes of the subtrees from the bottom up. At any node, the
|
||||
offset from the start of that node to the start of the sibling node
|
||||
is simply the size of the node plus the size of the subtree rooted
|
||||
in that node. */
|
||||
|
||||
static void
|
||||
write_formtree (asfd)
|
||||
sfd *asfd;
|
||||
{
|
||||
size_subtree (formtree);
|
||||
fseek (asfd -> fp, 0L, SEEK_END);
|
||||
asfd -> hdr.sf_ftoff = ftell (asfd -> fp);
|
||||
write_subtree (formtree, asfd);
|
||||
asfd -> hdr.sf_ftsize = ftell (asfd -> fp) - asfd -> hdr.sf_ftoff;
|
||||
}
|
||||
|
||||
/* Note that we currently only support having one objfile with dumpable
|
||||
state. */
|
||||
|
||||
static void
|
||||
write_objfile_state (asfd)
|
||||
sfd *asfd;
|
||||
{
|
||||
struct objfile *objfile;
|
||||
struct formnode *fnp;
|
||||
PTR base;
|
||||
PTR breakval;
|
||||
long *lp;
|
||||
unsigned int ftesize;
|
||||
long ftebuf[64];
|
||||
long foffset;
|
||||
|
||||
/* First walk through the objfile list looking for the first objfile
|
||||
that is dumpable. */
|
||||
|
||||
for (objfile = object_files; objfile != NULL; objfile = objfile -> next)
|
||||
{
|
||||
if (objfile -> flags & OBJF_DUMPABLE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (objfile == NULL)
|
||||
{
|
||||
warning ("no dumpable objfile was found");
|
||||
}
|
||||
else
|
||||
{
|
||||
fnp = alloc_formnode ();
|
||||
lp = ftebuf;
|
||||
|
||||
lp++; /* Skip FTE size slot, filled in at the end. */
|
||||
*lp++ = TAG_objfile; /* This is an objfile FTE */
|
||||
*lp++ = 0; /* Zero the sibling reference slot. */
|
||||
|
||||
/* Build an AT_name attribute for the objfile's name, and write
|
||||
the name into the state data. */
|
||||
|
||||
*lp++ = AT_name;
|
||||
*lp++ = (long) ftell (asfd -> fp);
|
||||
fwrite (objfile -> name, strlen (objfile -> name) + 1, 1, asfd -> fp);
|
||||
|
||||
/* Build an AT_addr attribute for the virtual address to which the
|
||||
objfile data is mapped (and needs to be remapped when read in). */
|
||||
|
||||
base = mmap_base ();
|
||||
*lp++ = AT_addr;
|
||||
*lp++ = (long) base;
|
||||
|
||||
/* Build an AT_aux_addr attribute for the address of the objfile
|
||||
structure itself, within the dumpable data. When we read the objfile
|
||||
back in, we use this address as the pointer the "struct objfile". */
|
||||
|
||||
*lp++ = AT_aux_addr;
|
||||
*lp++ = (long) objfile;
|
||||
|
||||
/* Reposition in state file to next paging boundry so we can mmap the
|
||||
dumpable objfile data when we reload it. */
|
||||
|
||||
foffset = (long) mmap_page_align ((PTR) ftell (asfd -> fp));
|
||||
fseek (asfd -> fp, foffset, SEEK_SET);
|
||||
|
||||
/* Build an AT_offset attribute for the offset in the state file to
|
||||
the start of the dumped objfile data. */
|
||||
|
||||
*lp++ = AT_offset;
|
||||
*lp++ = (long) ftell (asfd -> fp);
|
||||
|
||||
/* Build an AT_size attribute for the size of the dumped objfile data. */
|
||||
|
||||
breakval = mmap_sbrk (0);
|
||||
*lp++ = AT_size;
|
||||
*lp++ = breakval - base;
|
||||
|
||||
/* Write the dumpable data. */
|
||||
|
||||
fwrite ((char *) base, breakval - base, 1, asfd -> fp);
|
||||
|
||||
/* Now finish up the FTE by filling in the size slot based on
|
||||
how much of the ftebuf we have used, allocate some memory for
|
||||
it hung off the form tree node, and copy it there. */
|
||||
|
||||
ftebuf[0] = (lp - ftebuf) * sizeof (ftebuf[0]);
|
||||
fnp -> nodedata = (char *) xmalloc (ftebuf[0]);
|
||||
memcpy (fnp -> nodedata, ftebuf, ftebuf[0]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
load_state_command (arg_string, from_tty)
|
||||
char *arg_string;
|
||||
int from_tty;
|
||||
{
|
||||
char *filename;
|
||||
char **argv;
|
||||
FILE *fp;
|
||||
struct cleanup *cleanups;
|
||||
|
||||
dont_repeat ();
|
||||
|
||||
if (arg_string == NULL)
|
||||
{
|
||||
error ("load-state takes a file name and optional state specifiers");
|
||||
}
|
||||
else if ((argv = buildargv (arg_string)) == NULL)
|
||||
{
|
||||
fatal ("virtual memory exhausted.", 0);
|
||||
}
|
||||
cleanups = make_cleanup (freeargv, argv);
|
||||
|
||||
filename = tilde_expand (*argv);
|
||||
make_cleanup (free, filename);
|
||||
|
||||
if ((fp = fopen (filename, "r")) == NULL)
|
||||
{
|
||||
perror_with_name (filename);
|
||||
}
|
||||
make_cleanup (fclose, fp);
|
||||
immediate_quit++;
|
||||
|
||||
while (*++argv != NULL)
|
||||
{
|
||||
if (strcmp (*argv, "symbols") == 0)
|
||||
{
|
||||
if (from_tty
|
||||
&& !query ("load symbol table state from file \"%s\"? ",
|
||||
filename))
|
||||
{
|
||||
error ("Not confirmed.");
|
||||
}
|
||||
load_symbols (fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
error ("unknown state specifier '%s'", *argv);
|
||||
}
|
||||
}
|
||||
immediate_quit--;
|
||||
do_cleanups (cleanups);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
dump_state_command (arg_string, from_tty)
|
||||
char *arg_string;
|
||||
int from_tty;
|
||||
{
|
||||
char *filename;
|
||||
char **argv;
|
||||
sfd *asfd;
|
||||
struct cleanup *cleanups;
|
||||
|
||||
dont_repeat ();
|
||||
|
||||
if (arg_string == NULL)
|
||||
{
|
||||
error ("dump-state takes a file name and state specifiers");
|
||||
}
|
||||
else if ((argv = buildargv (arg_string)) == NULL)
|
||||
{
|
||||
fatal ("virtual memory exhausted.", 0);
|
||||
}
|
||||
cleanups = make_cleanup (freeargv, argv);
|
||||
|
||||
filename = tilde_expand (*argv);
|
||||
make_cleanup (free, filename);
|
||||
|
||||
/* Now attempt to create a fresh state file. */
|
||||
|
||||
if ((asfd = sfd_fopen (filename, "w")) == NULL)
|
||||
{
|
||||
perror_with_name (filename);
|
||||
}
|
||||
make_cleanup (sfd_fclose, asfd);
|
||||
make_cleanup (free_formtree, NULL);
|
||||
immediate_quit++;
|
||||
|
||||
/* Now that we have an open and initialized state file, seek to the
|
||||
proper offset to start writing state data and the process the
|
||||
arguments. For each argument, write the state data and initialize
|
||||
a form-tree node for each piece of state data. */
|
||||
|
||||
fseek (asfd -> fp, sizeof (sf_hdr), SEEK_SET);
|
||||
while (*++argv != NULL)
|
||||
{
|
||||
if (strcmp (*argv, "objfile") == 0)
|
||||
{
|
||||
write_objfile_state (asfd);
|
||||
}
|
||||
else
|
||||
{
|
||||
error ("unknown state specifier '%s'", *argv);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* We have written any state data. All that is left to do now is
|
||||
write the form-tree and the file header. */
|
||||
|
||||
write_formtree (asfd);
|
||||
write_header (asfd);
|
||||
|
||||
immediate_quit--;
|
||||
do_cleanups (cleanups);
|
||||
}
|
||||
|
||||
static char *
|
||||
find_fte_by_walk (thisfte, endfte, tag)
|
||||
char *thisfte;
|
||||
char *endfte;
|
||||
long tag;
|
||||
{
|
||||
char *found = NULL;
|
||||
char *nextfte;
|
||||
long thistag;
|
||||
long thissize;
|
||||
long siboffset;
|
||||
|
||||
while (thisfte < endfte)
|
||||
{
|
||||
if ((thistag = *(long *)(thisfte + sizeof (long))) == tag)
|
||||
{
|
||||
found = thisfte;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
thissize = *(long *)(thisfte);
|
||||
siboffset = *(long *)(thisfte + (2 * sizeof (long)));
|
||||
nextfte = thisfte + (siboffset != 0 ? siboffset : thissize);
|
||||
found = find_fte_by_walk (thisfte + thissize, nextfte, tag);
|
||||
thisfte = nextfte;
|
||||
}
|
||||
}
|
||||
return (found);
|
||||
}
|
||||
|
||||
/* Walk the form-tree looking for a specific FTE type. Returns the first
|
||||
one found that matches the specified tag. */
|
||||
|
||||
static char *
|
||||
find_fte (asfd, tag)
|
||||
sfd *asfd;
|
||||
long tag;
|
||||
{
|
||||
char *ftbase;
|
||||
char *ftend;
|
||||
char *ftep;
|
||||
char *found = NULL;
|
||||
|
||||
if (fseek (asfd -> fp, asfd -> hdr.sf_ftoff, SEEK_SET) == 0)
|
||||
{
|
||||
ftbase = xmalloc (asfd -> hdr.sf_ftsize);
|
||||
ftend = ftbase + asfd -> hdr.sf_ftsize;
|
||||
if (fread (ftbase, asfd -> hdr.sf_ftsize, 1, asfd -> fp) == 1)
|
||||
{
|
||||
ftep = find_fte_by_walk (ftbase, ftend, tag);
|
||||
if (ftep != NULL)
|
||||
{
|
||||
found = xmalloc (*(long *)ftep);
|
||||
memcpy (found, ftep, (int) *(long *)ftep);
|
||||
}
|
||||
}
|
||||
free (ftbase);
|
||||
}
|
||||
return (found);
|
||||
}
|
||||
|
||||
struct objfile *
|
||||
objfile_from_statefile (asfd)
|
||||
sfd *asfd;
|
||||
{
|
||||
struct objfile *objfile = NULL;
|
||||
char *ftep;
|
||||
long *thisattr;
|
||||
long *endattr;
|
||||
PTR base;
|
||||
long foffset;
|
||||
long mapsize;
|
||||
|
||||
ftep = find_fte (asfd, TAG_objfile);
|
||||
thisattr = (long *) (ftep + 3 * sizeof (long));
|
||||
endattr = (long *) (ftep + *(long *)ftep);
|
||||
while (thisattr < endattr)
|
||||
{
|
||||
switch (*thisattr++)
|
||||
{
|
||||
case AT_name:
|
||||
/* Ignore for now */
|
||||
thisattr++;
|
||||
break;
|
||||
case AT_addr:
|
||||
base = (PTR) *thisattr++;
|
||||
break;
|
||||
case AT_aux_addr:
|
||||
objfile = (struct objfile *) *thisattr++;
|
||||
break;
|
||||
case AT_offset:
|
||||
foffset = *thisattr++;
|
||||
break;
|
||||
case AT_size:
|
||||
mapsize = *thisattr++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mmap_remap (base, mapsize, (int) fileno (asfd -> fp), foffset) != base)
|
||||
{
|
||||
print_sys_errmsg (asfd -> filename, errno);
|
||||
error ("mapping failed");
|
||||
}
|
||||
|
||||
return (objfile);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct objfile *
|
||||
objfile_from_statefile (asfd)
|
||||
sfd *asfd;
|
||||
{
|
||||
error ("this version of gdb doesn't support reloading symtabs from state files");
|
||||
}
|
||||
|
||||
#endif /* HAVE_MMAP */
|
||||
|
||||
/* Close a state file, freeing all memory that was used by the state
|
||||
file descriptor, closing the raw file pointer, etc. */
|
||||
|
||||
void
|
||||
sfd_fclose (asfd)
|
||||
sfd *asfd;
|
||||
{
|
||||
if (asfd != NULL)
|
||||
{
|
||||
if (asfd -> fp != NULL)
|
||||
{
|
||||
fclose (asfd -> fp);
|
||||
}
|
||||
if (asfd -> filename != NULL)
|
||||
{
|
||||
free (asfd -> filename);
|
||||
}
|
||||
free (asfd);
|
||||
}
|
||||
}
|
||||
|
||||
/* Given the name of a possible statefile, and flags to use to open it,
|
||||
try to open the file and prepare it for use.
|
||||
|
||||
If the flags contain 'r', then we want to read an existing state
|
||||
file, so attempt to read in the state file header and determine if this
|
||||
is a valid state file. If not, return NULL.
|
||||
|
||||
Returns a pointer to a properly initialized state file descriptor if
|
||||
successful. */
|
||||
|
||||
sfd *
|
||||
sfd_fopen (name, flags)
|
||||
char *name;
|
||||
char *flags;
|
||||
{
|
||||
int success = 0;
|
||||
sfd *asfd;
|
||||
|
||||
asfd = (sfd *) xmalloc (sizeof (sfd));
|
||||
(void) memset (asfd, 0, sizeof (sfd));
|
||||
asfd -> filename = xmalloc (strlen (name) + 1);
|
||||
(void) strcpy (asfd -> filename, name);
|
||||
|
||||
if ((asfd -> fp = fopen (asfd -> filename, flags)) != NULL)
|
||||
{
|
||||
/* We have the file, now see if we are reading an existing file
|
||||
or writing to a new file. We don't currently support "rw". */
|
||||
if (strchr (flags, 'r') != NULL)
|
||||
{
|
||||
if (fread ((char *) &asfd -> hdr, sizeof (asfd -> hdr), 1,
|
||||
asfd -> fp) == 1)
|
||||
{
|
||||
if (SF_GOOD_MAGIC (asfd))
|
||||
{
|
||||
success = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is a new state file. Initialize various things. */
|
||||
asfd -> hdr.sf_mag0 = SF_MAG0;
|
||||
asfd -> hdr.sf_mag1 = SF_MAG1;
|
||||
asfd -> hdr.sf_mag2 = SF_MAG2;
|
||||
asfd -> hdr.sf_mag3 = SF_MAG3;
|
||||
success = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
sfd_fclose (asfd);
|
||||
asfd = NULL;
|
||||
}
|
||||
return (asfd);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_initialize_state ()
|
||||
{
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
|
||||
add_com ("load-state", class_support, load_state_command,
|
||||
"Load some saved gdb state from FILE.\n\
|
||||
Select and load some portion of gdb's saved state from the specified file.\n\
|
||||
The dump-state command may be used to save various portions of gdb's\n\
|
||||
internal state.");
|
||||
|
||||
add_com ("dump-state", class_support, dump_state_command,
|
||||
"Dump some of gdb's state to FILE.\n\
|
||||
Select and dump some portion of gdb's internal state to the specified file.\n\
|
||||
The load-state command may be used to reload various portions of gdb's\n\
|
||||
internal state from the file.");
|
||||
|
||||
#endif /* HAVE_MMAP */
|
||||
|
||||
}
|
85
gdb/state.h
Normal file
85
gdb/state.h
Normal file
@ -0,0 +1,85 @@
|
||||
/* Support for dumping and reloading various pieces of GDB's internal state.
|
||||
Copyright 1992 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support, using pieces from other GDB modules.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 of the License, 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. */
|
||||
|
||||
/* This file provides definitions used for reading and writing gdb
|
||||
state files. State files have a fairly simple form which is intended
|
||||
to be easily extensible. See state.c for further documentation. */
|
||||
|
||||
#if !defined (_STATE_H)
|
||||
#define _STATE_H
|
||||
|
||||
/* State file-header */
|
||||
|
||||
typedef struct {
|
||||
unsigned char sf_mag0; /* Magic number byte 0 */
|
||||
unsigned char sf_mag1; /* Magic number byte 1 */
|
||||
unsigned char sf_mag2; /* Magic number byte 2 */
|
||||
unsigned char sf_mag3; /* Magic number byte 3 */
|
||||
unsigned long sf_ftoff; /* File offset to start of form-tree */
|
||||
unsigned long sf_ftsize; /* Size of the form-tree, in bytes */
|
||||
} sf_hdr;
|
||||
|
||||
|
||||
#define SF_MAG0 'g' /* Magic number byte 0 value */
|
||||
#define SF_MAG1 'd' /* Magic number byte 1 value */
|
||||
#define SF_MAG2 'b' /* Magic number byte 2 value */
|
||||
#define SF_MAG3 '\000' /* Magic number byte 3 value */
|
||||
|
||||
#define SF_GOOD_MAGIC(asfd) ((asfd) -> hdr.sf_mag0 == SF_MAG0 && \
|
||||
(asfd) -> hdr.sf_mag1 == SF_MAG1 && \
|
||||
(asfd) -> hdr.sf_mag2 == SF_MAG2 && \
|
||||
(asfd) -> hdr.sf_mag3 == SF_MAG3)
|
||||
|
||||
/* The internal form-tree is formed from nodes that contain pointers
|
||||
to the first sibling, the first child, a backpointer to the parent,
|
||||
and a pointer to the actual data for the node. This allows all
|
||||
tree nodes to have the same sized structure, but support variable
|
||||
numbers of child nodes per parent node. The backpointer for the
|
||||
parent is required for simplier tree walks. */
|
||||
|
||||
struct formnode
|
||||
{
|
||||
struct formnode *sibling; /* Pointer to first sibling */
|
||||
struct formnode *child; /* Pointer to first child */
|
||||
struct formnode *parent; /* Backpointer to parent */
|
||||
char *nodedata; /* Pointer to the nodes data */
|
||||
unsigned long treesize; /* Size of subtree rooted here */
|
||||
};
|
||||
|
||||
/* A state file descriptor is defined by the following structure. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *filename; /* Full pathname of the state file */
|
||||
FILE *fp; /* Open file pointer for the state file */
|
||||
sf_hdr hdr; /* Copy of the state file-header */
|
||||
char *formtree; /* Pointer to in-memory copy of form-tree */
|
||||
} sfd;
|
||||
|
||||
extern sfd *
|
||||
sfd_fopen PARAMS ((char *, char *));
|
||||
|
||||
extern void
|
||||
sfd_fclose PARAMS ((sfd *));
|
||||
|
||||
extern struct objfile *
|
||||
objfile_from_statefile PARAMS ((sfd *));
|
||||
|
||||
#endif /* !defined (_STATE_H) */
|
@ -444,15 +444,12 @@ symmetry_extract_return_value(type, regbuf, valbuf)
|
||||
double d;
|
||||
int l[2];
|
||||
} xd;
|
||||
int i;
|
||||
struct minimal_symbol *msymbol;
|
||||
float f;
|
||||
|
||||
if (TYPE_CODE_FLT == TYPE_CODE(type)) {
|
||||
for (i = 0; i < misc_function_count; i++) {
|
||||
if (!strcmp(misc_function_vector[i].name, "1167_flt"))
|
||||
break;
|
||||
}
|
||||
if (i < misc_function_count) {
|
||||
msymbol = lookup_minimal_symbol ("1167_flt", (struct objfile *) NULL);
|
||||
if (msymbol != NULL) {
|
||||
/* found "1167_flt" means 1167, %fp2-%fp3 */
|
||||
/* float & double; 19= %fp2, 20= %fp3 */
|
||||
/* no single precision on 1167 */
|
||||
|
@ -18,16 +18,4 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/* This is for SunOS version 4, not for earlier versions. */
|
||||
|
||||
#define CLEAR_SOLIB clear_solib
|
||||
extern void clear_solib ();
|
||||
|
||||
#define SOLIB_ADD(filename, from_tty, targ) solib_add (filename, from_tty, targ)
|
||||
extern void solib_add ();
|
||||
|
||||
#define SOLIB_CREATE_INFERIOR_HOOK solib_create_inferior_hook
|
||||
extern void solib_create_inferior_hook();
|
||||
|
||||
/* If we can't set a breakpoint, and it's in a shared library, just
|
||||
disable it. */
|
||||
#define DISABLE_UNSETTABLE_BREAK(addr) solib_address(addr)
|
||||
extern int solib_address (); /* solib.c */
|
||||
#include "solib.h" /* Support for shared libraries. */
|
||||
|
21
gdb/values.c
21
gdb/values.c
@ -21,13 +21,23 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include <string.h>
|
||||
#include "defs.h"
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "value.h"
|
||||
#include "gdbcore.h"
|
||||
#include "frame.h"
|
||||
#include "command.h"
|
||||
#include "gdbcmd.h"
|
||||
|
||||
extern char *cplus_demangle ();
|
||||
/* Local function prototypes. */
|
||||
|
||||
static value
|
||||
value_headof PARAMS ((value, struct type *, struct type *));
|
||||
|
||||
static void
|
||||
show_values PARAMS ((char *, int));
|
||||
|
||||
static void
|
||||
show_convenience PARAMS ((void));
|
||||
|
||||
/* The value-history records all the values printed
|
||||
by print commands during this session. Each chunk
|
||||
@ -1002,6 +1012,8 @@ value_headof (arg, btype, dtype)
|
||||
struct symbol *sym;
|
||||
CORE_ADDR pc_for_sym;
|
||||
char *demangled_name;
|
||||
struct minimal_symbol *msymbol;
|
||||
|
||||
btype = TYPE_VPTR_BASETYPE (dtype);
|
||||
check_stub_type (btype);
|
||||
if (btype != dtype)
|
||||
@ -1011,8 +1023,9 @@ value_headof (arg, btype, dtype)
|
||||
vtbl = value_ind (value_field (value_ind (vtbl), TYPE_VPTR_FIELDNO (btype)));
|
||||
|
||||
/* Check that VTBL looks like it points to a virtual function table. */
|
||||
i = find_pc_misc_function (VALUE_ADDRESS (vtbl));
|
||||
if (i < 0 || ! VTBL_PREFIX_P (demangled_name = misc_function_vector[i].name))
|
||||
msymbol = lookup_minimal_symbol_by_pc (VALUE_ADDRESS (vtbl));
|
||||
if (msymbol == NULL
|
||||
|| !VTBL_PREFIX_P (demangled_name = msymbol -> name))
|
||||
{
|
||||
/* If we expected to find a vtable, but did not, let the user
|
||||
know that we aren't happy, but don't throw an error.
|
||||
@ -1249,7 +1262,7 @@ unpack_field_as_long (type, valaddr, fieldno)
|
||||
char *valaddr;
|
||||
int fieldno;
|
||||
{
|
||||
long val;
|
||||
unsigned long val;
|
||||
int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
|
||||
int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
|
||||
|
||||
|
136
gdb/xcoffexec.c
136
gdb/xcoffexec.c
@ -40,6 +40,17 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include "libbfd.h" /* BFD internals (sigh!) FIXME */
|
||||
|
||||
/* Prototypes for local functions */
|
||||
|
||||
static void
|
||||
add_to_section_table PARAMS ((bfd *, sec_ptr, PTR));
|
||||
|
||||
static void
|
||||
file_command PARAMS ((char *, int));
|
||||
|
||||
static void
|
||||
exec_close PARAMS ((int));
|
||||
|
||||
struct section_table *exec_sections, *exec_sections_end;
|
||||
|
||||
#define eq(s0, s1) !strcmp(s0, s1)
|
||||
@ -90,7 +101,7 @@ extern struct target_ops exec_ops;
|
||||
|
||||
/* exec_close - done with exec file, clean up all resources. */
|
||||
|
||||
void
|
||||
static void
|
||||
exec_close(quitting) {
|
||||
register struct vmap *vp, *nxt;
|
||||
|
||||
@ -124,7 +135,7 @@ char *filename;
|
||||
int scratch_chan;
|
||||
|
||||
filename = tilde_expand(filename);
|
||||
make_cleanup(free, filename);
|
||||
make_cleanup (free, filename);
|
||||
|
||||
scratch_chan = openp(getenv("PATH"), 1, filename, O_RDONLY, 0
|
||||
, &scratch_pathname);
|
||||
@ -177,7 +188,7 @@ char *filename;
|
||||
* novelty. Why did GDB go through four major releases before this
|
||||
* command was added?
|
||||
*/
|
||||
void
|
||||
static void
|
||||
file_command(arg, from_tty)
|
||||
char *arg; {
|
||||
|
||||
@ -189,7 +200,7 @@ char *arg; {
|
||||
table_pp_char is a char * to get it through bfd_map_over_sections;
|
||||
we cast it back to its proper type. */
|
||||
|
||||
void
|
||||
static void
|
||||
add_to_section_table (abfd, asect, table_pp_char)
|
||||
bfd *abfd;
|
||||
sec_ptr asect;
|
||||
@ -283,7 +294,6 @@ map_vmap (bfd *bf, bfd *arch)
|
||||
struct vmap_and_bfd vmap_bfd;
|
||||
struct vmap *vp, **vpp;
|
||||
struct objfile *obj;
|
||||
char *name;
|
||||
|
||||
vp = (void*) xmalloc (sizeof (*vp));
|
||||
vp->nxt = 0;
|
||||
@ -297,8 +307,7 @@ map_vmap (bfd *bf, bfd *arch)
|
||||
|
||||
obj = lookup_objfile_bfd (bf);
|
||||
if (exec_bfd && !obj) {
|
||||
name = savestring (bfd_get_filename (bf), strlen (bfd_get_filename (bf)));
|
||||
obj = allocate_objfile (bf, name);
|
||||
obj = allocate_objfile (bf, bfd_get_filename (bf), 0);
|
||||
syms_from_objfile (obj, 0, 0, 0);
|
||||
}
|
||||
|
||||
@ -308,8 +317,20 @@ map_vmap (bfd *bf, bfd *arch)
|
||||
*vpp = vp;
|
||||
}
|
||||
|
||||
/* Called via iterate_over_msymbols to relocate minimal symbols */
|
||||
|
||||
/* true, if symbol table and misc_function_vector is relocated. */
|
||||
static void
|
||||
relocate_minimal_symbol (objfile, msymbol, arg1, arg2, arg3)
|
||||
struct objfile *objfile;
|
||||
struct minimal_symbol *msymbol;
|
||||
PTR arg1;
|
||||
PTR arg2;
|
||||
PTR arg3;
|
||||
{
|
||||
msymbol -> address += (int) arg1;
|
||||
}
|
||||
|
||||
/* true, if symbol table and minimal symbol table are relocated. */
|
||||
|
||||
int symtab_relocated = 0;
|
||||
|
||||
@ -321,56 +342,61 @@ register struct vmap *vp;
|
||||
CORE_ADDR old_start;
|
||||
struct stat *vip;
|
||||
{
|
||||
register struct symtab *s;
|
||||
|
||||
/*
|
||||
* for each symbol table generated from the vp->bfd
|
||||
*/
|
||||
for (s = symtab_list; s; s = s->next) {
|
||||
|
||||
/* skip over if this is not relocatable and doesn't have a line table */
|
||||
if (s->nonreloc && !LINETABLE (s))
|
||||
register struct symtab *s;
|
||||
register struct objfile *objfile;
|
||||
|
||||
/*
|
||||
* for each symbol table generated from the vp->bfd
|
||||
*/
|
||||
for (objfile = object_files; objfile != NULL; objfile = objfile -> next)
|
||||
{
|
||||
for (s = objfile -> symtabs; s != NULL; s = s -> next) {
|
||||
|
||||
/* skip over if this is not relocatable and doesn't have a line table */
|
||||
if (s->nonreloc && !LINETABLE (s))
|
||||
continue;
|
||||
|
||||
/* matching the symbol table's BFD and the *vp's BFD is hairy.
|
||||
exec_file creates a seperate BFD for possibly the
|
||||
same file as symbol_file.FIXME ALL THIS MUST BE RECTIFIED. */
|
||||
|
||||
if (objfile->obfd == vp->bfd) {
|
||||
/* if they match, we luck out. */
|
||||
;
|
||||
} else if (vp->member[0]) {
|
||||
/* no match, and member present, not this one. */
|
||||
continue;
|
||||
} else {
|
||||
struct stat si;
|
||||
FILE *io;
|
||||
|
||||
/*
|
||||
* no match, and no member. need to be sure.
|
||||
*/
|
||||
io = bfd_cache_lookup(objfile->obfd);
|
||||
if (!io)
|
||||
fatal("cannot find BFD's iostream for sym");
|
||||
/*
|
||||
* see if we are referring to the same file
|
||||
*/
|
||||
if (fstat(fileno(io), &si) < 0)
|
||||
fatal("cannot fstat BFD for sym");
|
||||
|
||||
if (si.st_dev != vip->st_dev
|
||||
|| si.st_ino != vip->st_ino)
|
||||
continue;
|
||||
|
||||
/* matching the symbol table's BFD and the *vp's BFD is hairy.
|
||||
exec_file creates a seperate BFD for possibly the
|
||||
same file as symbol_file.FIXME ALL THIS MUST BE RECTIFIED. */
|
||||
|
||||
if (s->objfile->obfd == vp->bfd) {
|
||||
/* if they match, we luck out. */
|
||||
;
|
||||
} else if (vp->member[0]) {
|
||||
/* no match, and member present, not this one. */
|
||||
continue;
|
||||
} else {
|
||||
struct stat si;
|
||||
FILE *io;
|
||||
|
||||
/*
|
||||
* no match, and no member. need to be sure.
|
||||
*/
|
||||
io = bfd_cache_lookup(s->objfile->obfd);
|
||||
if (!io)
|
||||
fatal("cannot find BFD's iostream for sym");
|
||||
/*
|
||||
* see if we are referring to the same file
|
||||
*/
|
||||
if (fstat(fileno(io), &si) < 0)
|
||||
fatal("cannot fstat BFD for sym");
|
||||
|
||||
if (si.st_dev != vip->st_dev
|
||||
|| si.st_ino != vip->st_ino)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vp->tstart != old_start)
|
||||
vmap_symtab_1(s, vp, old_start);
|
||||
}
|
||||
|
||||
|
||||
if (vp->tstart != old_start)
|
||||
fixup_misc_vector (vp->tstart - old_start);
|
||||
|
||||
symtab_relocated = 1;
|
||||
vmap_symtab_1(s, vp, old_start);
|
||||
}
|
||||
}
|
||||
if (vp->tstart != old_start)
|
||||
iterate_over_msymbols (relocate_minimal_symbol,
|
||||
(PTR) (vp->tstart - old_start),
|
||||
(PTR) NULL, (PTR) NULL);
|
||||
|
||||
symtab_relocated = 1;
|
||||
}
|
||||
|
||||
|
||||
|
369
gdb/xcoffread.c
369
gdb/xcoffread.c
@ -38,6 +38,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "symfile.h"
|
||||
#include "buildsym.h"
|
||||
|
||||
@ -45,14 +46,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "libcoff.h" /* FIXME, internal data from BFD */
|
||||
#include "coff/rs6000.h" /* FIXME, raw file-format guts of xcoff */
|
||||
|
||||
extern char *index();
|
||||
|
||||
static void enter_line_range ();
|
||||
static struct symbol *process_xcoff_symbol ();
|
||||
static int read_symbol_nvalue ();
|
||||
static int read_symbol_lineno ();
|
||||
|
||||
|
||||
/* Simplified internal version of coff symbol table information */
|
||||
|
||||
struct coff_symbol {
|
||||
@ -151,14 +144,106 @@ struct coff_symfile_info {
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
enter_line_range PARAMS ((struct subfile *, unsigned, unsigned, CORE_ADDR,
|
||||
unsigned *));
|
||||
|
||||
static void
|
||||
aixcoff_symfile_read PARAMS ((struct sym_fns *, CORE_ADDR, int));
|
||||
|
||||
static void
|
||||
free_debugsection PARAMS ((void));
|
||||
|
||||
static int
|
||||
init_debugsection PARAMS ((bfd *));
|
||||
|
||||
static int
|
||||
init_stringtab PARAMS ((bfd *, long, struct objfile *));
|
||||
|
||||
static void
|
||||
aixcoff_symfile_init PARAMS ((struct sym_fns *));
|
||||
|
||||
static void
|
||||
aixcoff_new_init PARAMS ((void));
|
||||
|
||||
static void
|
||||
dump_minimal_symbols PARAMS ((struct objfile *));
|
||||
|
||||
static void
|
||||
dump_symtab_lines PARAMS ((struct symtab *));
|
||||
|
||||
static void
|
||||
dump_symtabs PARAMS ((struct symtab *));
|
||||
|
||||
static void
|
||||
dump_last_symtab PARAMS ((struct symtab *));
|
||||
|
||||
static void
|
||||
dump_blockvector PARAMS ((struct blockvector *));
|
||||
|
||||
static void
|
||||
dump_block PARAMS ((struct block *));
|
||||
|
||||
static char *
|
||||
dump_addrclass PARAMS ((int));
|
||||
|
||||
static char *
|
||||
dump_namespace PARAMS ((int));
|
||||
|
||||
static void
|
||||
dump_symbol PARAMS ((struct symbol *));
|
||||
|
||||
static void
|
||||
dump_type PARAMS ((struct type *));
|
||||
|
||||
static void
|
||||
dump_linetable PARAMS ((struct linetable *));
|
||||
|
||||
static void
|
||||
dump_strtbl PARAMS ((void));
|
||||
|
||||
static int
|
||||
init_lineno PARAMS ((bfd *, long, int));
|
||||
|
||||
static void
|
||||
find_linenos PARAMS ((bfd *, sec_ptr, PTR));
|
||||
|
||||
static int
|
||||
read_symbol_lineno PARAMS ((char *, int));
|
||||
|
||||
static int
|
||||
read_symbol_nvalue PARAMS ((char *, int));
|
||||
|
||||
static struct symbol *
|
||||
process_xcoff_symbol PARAMS ((struct coff_symbol *, struct objfile *));
|
||||
|
||||
static void
|
||||
read_xcoff_symtab PARAMS ((struct objfile *, int));
|
||||
|
||||
static void
|
||||
enter_line_range PARAMS ((struct subfile *, unsigned, unsigned, CORE_ADDR,
|
||||
unsigned *));
|
||||
|
||||
static void
|
||||
add_stab_to_list PARAMS ((char *, struct pending_stabs **));
|
||||
|
||||
static void
|
||||
sort_syms PARAMS ((void));
|
||||
|
||||
static int
|
||||
compare_symbols PARAMS ((const void *, const void *));
|
||||
|
||||
/* Call sort_syms to sort alphabetically
|
||||
the symbols of each block of each symtab. */
|
||||
|
||||
static int
|
||||
compare_symbols (s1, s2)
|
||||
struct symbol **s1, **s2;
|
||||
compare_symbols (s1p, s2p)
|
||||
const PTR s1p;
|
||||
const PTR s2p;
|
||||
{
|
||||
/* Names that are less should come first. */
|
||||
register struct symbol **s1 = (struct symbol **) s1p;
|
||||
register struct symbol **s2 = (struct symbol **) s2p;
|
||||
register int namediff = strcmp (SYMBOL_NAME (*s1), SYMBOL_NAME (*s2));
|
||||
if (namediff != 0)
|
||||
return namediff;
|
||||
@ -175,22 +260,28 @@ static void
|
||||
sort_syms ()
|
||||
{
|
||||
register struct symtab *s;
|
||||
register struct objfile *objfile;
|
||||
register int i, nbl;
|
||||
register struct blockvector *bv;
|
||||
register struct block *b;
|
||||
|
||||
for (s = symtab_list; s; s = s->next)
|
||||
{
|
||||
bv = BLOCKVECTOR (s);
|
||||
nbl = BLOCKVECTOR_NBLOCKS (bv);
|
||||
for (i = 0; i < nbl; i++)
|
||||
for (objfile = object_files; objfile != NULL; objfile = objfile -> next)
|
||||
{
|
||||
b = BLOCKVECTOR_BLOCK (bv, i);
|
||||
if (BLOCK_SHOULD_SORT (b))
|
||||
qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b),
|
||||
sizeof (struct symbol *), compare_symbols);
|
||||
for (s = objfile -> symtabs; s != NULL; s = s -> next)
|
||||
{
|
||||
bv = BLOCKVECTOR (s);
|
||||
nbl = BLOCKVECTOR_NBLOCKS (bv);
|
||||
for (i = 0; i < nbl; i++)
|
||||
{
|
||||
b = BLOCKVECTOR_BLOCK (bv, i);
|
||||
if (BLOCK_SHOULD_SORT (b))
|
||||
{
|
||||
qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b),
|
||||
sizeof (struct symbol *), compare_symbols);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -211,47 +302,13 @@ struct pending_stabs **stabvector;
|
||||
else if ((*stabvector)->count >= (*stabvector)->length) {
|
||||
(*stabvector)->length += INITIAL_STABVECTOR_LENGTH;
|
||||
*stabvector = (struct pending_stabs *)
|
||||
xrealloc (*stabvector, sizeof (struct pending_stabs) +
|
||||
xrealloc ((char *) *stabvector, sizeof (struct pending_stabs) +
|
||||
(*stabvector)->length * sizeof (char*));
|
||||
}
|
||||
(*stabvector)->stab [(*stabvector)->count++] = stabname;
|
||||
}
|
||||
|
||||
|
||||
/* for all the stabs in a given stab vector, build appropriate types
|
||||
and fix their symbols in given symbol vector. */
|
||||
|
||||
void
|
||||
patch_block_stabs (symbols, stabs)
|
||||
struct pending *symbols;
|
||||
struct pending_stabs *stabs;
|
||||
{
|
||||
int ii;
|
||||
|
||||
if (!stabs)
|
||||
return;
|
||||
|
||||
/* for all the stab entries, find their corresponding symbols and
|
||||
patch their types! */
|
||||
|
||||
for (ii=0; ii < stabs->count; ++ii) {
|
||||
char *name = stabs->stab[ii];
|
||||
char *pp = (char*) index (name, ':');
|
||||
struct symbol *sym = find_symbol_in_list (symbols, name, pp-name);
|
||||
if (!sym) {
|
||||
printf ("ERROR! stab symbol not found!\n"); /* FIXME */
|
||||
}
|
||||
else {
|
||||
pp += 2;
|
||||
|
||||
if (*(pp-1) == 'F' || *(pp-1) == 'f')
|
||||
SYMBOL_TYPE (sym) = lookup_function_type (read_type (&pp));
|
||||
else
|
||||
SYMBOL_TYPE (sym) = read_type (&pp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Enter a given range of lines into the line vector.
|
||||
can be called in the following two ways:
|
||||
enter_line_range (subfile, beginoffset, endoffset, 0, firstLine) or
|
||||
@ -316,16 +373,16 @@ enter_line_range (subfile, beginoffset, endoffset, endaddr, firstLine)
|
||||
/* Reading symbol table has to be fast! Keep the followings as macros, rather
|
||||
than functions. */
|
||||
|
||||
#define RECORD_MISC_FUNCTION(NAME, ADDR, TYPE, ALLOCED) \
|
||||
#define RECORD_MINIMAL_SYMBOL(NAME, ADDR, TYPE, ALLOCED) \
|
||||
{ \
|
||||
char *namestr; \
|
||||
if (ALLOCED) \
|
||||
namestr = (NAME) + 1; \
|
||||
else { \
|
||||
namestr = obstack_copy0 (symbol_obstack, (NAME) + 1, strlen ((NAME)+1)); \
|
||||
namestr = obstack_copy0 (&objfile->symbol_obstack, (NAME) + 1, strlen ((NAME)+1)); \
|
||||
(ALLOCED) = 1; \
|
||||
} \
|
||||
prim_record_misc_function (namestr, (ADDR), (TYPE)); \
|
||||
prim_record_minimal_symbol (namestr, (ADDR), (TYPE)); \
|
||||
last_recorded_fun = (ADDR); \
|
||||
}
|
||||
|
||||
@ -343,7 +400,7 @@ static int symname_alloced = 0;
|
||||
|
||||
/* read the whole symbol table of a given bfd. */
|
||||
|
||||
void
|
||||
static void
|
||||
read_xcoff_symtab (objfile, nsyms)
|
||||
struct objfile *objfile; /* Object file we're reading from */
|
||||
int nsyms; /* # of symbols */
|
||||
@ -376,6 +433,8 @@ read_xcoff_symtab (objfile, nsyms)
|
||||
char *last_seen_csect;
|
||||
int last_recorded_fun = 0; /* last recorded fun. value */
|
||||
|
||||
current_objfile = objfile;
|
||||
|
||||
/* Get the appropriate COFF "constants" related to the file we're handling. */
|
||||
N_TMASK = coff_data (abfd)->local_n_tmask;
|
||||
N_BTSHFT = coff_data (abfd)->local_n_btshft;
|
||||
@ -522,7 +581,7 @@ read_xcoff_symtab (objfile, nsyms)
|
||||
|
||||
if (cs->c_name && cs->c_name[0] == '.') {
|
||||
last_seen_csect = cs->c_name;
|
||||
RECORD_MISC_FUNCTION (cs->c_name, cs->c_value, mf_text, symname_alloced);
|
||||
RECORD_MINIMAL_SYMBOL (cs->c_name, cs->c_value, mst_text, symname_alloced);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
@ -553,7 +612,7 @@ read_xcoff_symtab (objfile, nsyms)
|
||||
|
||||
function_entry_point:
|
||||
if (cs->c_value != last_recorded_fun)
|
||||
RECORD_MISC_FUNCTION (cs->c_name, cs->c_value, mf_text,
|
||||
RECORD_MINIMAL_SYMBOL (cs->c_name, cs->c_value, mst_text,
|
||||
symname_alloced);
|
||||
|
||||
fcn_line_offset = main_aux->x_sym.x_fcnary.x_fcn.x_lnnoptr;
|
||||
@ -569,7 +628,7 @@ function_entry_point:
|
||||
/* shared library function entry point. */
|
||||
else if (CSECT_SCLAS (main_aux) == XMC_GL) {
|
||||
if (last_recorded_fun != cs->c_value)
|
||||
RECORD_MISC_FUNCTION (cs->c_name, cs->c_value, mf_text,
|
||||
RECORD_MINIMAL_SYMBOL (cs->c_name, cs->c_value, mst_text,
|
||||
symname_alloced);
|
||||
continue;
|
||||
}
|
||||
@ -627,7 +686,7 @@ function_entry_point:
|
||||
/* mark_first_line (fcn_line_offset, cs->c_symnum); */
|
||||
|
||||
new = push_context (0, fcn_start_addr);
|
||||
new->name = process_xcoff_symbol (&fcn_cs_saved);
|
||||
new->name = process_xcoff_symbol (&fcn_cs_saved, objfile);
|
||||
}
|
||||
else if (strcmp (cs->c_name, ".ef") == 0) {
|
||||
|
||||
@ -653,7 +712,7 @@ function_entry_point:
|
||||
finish_block (new->name, &local_symbols, new->old_blocks,
|
||||
new->start_addr,
|
||||
fcn_cs_saved.c_value +
|
||||
fcn_aux_saved.x_sym.x_misc.x_fsize);
|
||||
fcn_aux_saved.x_sym.x_misc.x_fsize, objfile);
|
||||
within_function = 0;
|
||||
}
|
||||
break;
|
||||
@ -690,7 +749,7 @@ function_entry_point:
|
||||
fcn_last_line = cs->c_value; /* Offset to last line number */
|
||||
{ long dummy = 0;
|
||||
enter_line_range (current_subfile, fcn_first_line, cs->c_value, 0,
|
||||
&dummy);
|
||||
(unsigned *) &dummy);
|
||||
}
|
||||
start_subfile (pop_subfile (), (char *)0);
|
||||
break;
|
||||
@ -710,14 +769,14 @@ function_entry_point:
|
||||
if (local_symbols && context_stack_depth > 0) {
|
||||
/* Make a block for the local symbols within. */
|
||||
finish_block (new->name, &local_symbols, new->old_blocks,
|
||||
new->start_addr, cs->c_value);
|
||||
new->start_addr, cs->c_value, objfile);
|
||||
}
|
||||
local_symbols = new->locals;
|
||||
}
|
||||
break;
|
||||
|
||||
default :
|
||||
(void) process_xcoff_symbol (cs);
|
||||
(void) process_xcoff_symbol (cs, objfile);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -727,24 +786,26 @@ function_entry_point:
|
||||
end_symtab (cur_src_end_addr, 1, 1, objfile);
|
||||
|
||||
free (symtbl);
|
||||
current_objfile = NULL;
|
||||
}
|
||||
|
||||
#define SYMBOL_DUP(SYMBOL1, SYMBOL2) \
|
||||
(SYMBOL2) = (struct symbol *) \
|
||||
obstack_alloc (symbol_obstack, sizeof (struct symbol)); \
|
||||
obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol)); \
|
||||
*(SYMBOL2) = *(SYMBOL1);
|
||||
|
||||
|
||||
#define SYMNAME_ALLOC(NAME, ALLOCED) \
|
||||
(ALLOCED) ? (NAME) : obstack_copy0 (symbol_obstack, (NAME), strlen (NAME));
|
||||
(ALLOCED) ? (NAME) : obstack_copy0 (&objfile->symbol_obstack, (NAME), strlen (NAME));
|
||||
|
||||
|
||||
|
||||
/* process one xcoff symbol. */
|
||||
|
||||
static struct symbol *
|
||||
process_xcoff_symbol (cs)
|
||||
process_xcoff_symbol (cs, objfile)
|
||||
register struct coff_symbol *cs;
|
||||
struct objfile *objfile;
|
||||
{
|
||||
struct symbol onesymbol;
|
||||
register struct symbol *sym = &onesymbol;
|
||||
@ -769,7 +830,7 @@ process_xcoff_symbol (cs)
|
||||
on in patch_block_stabs () */
|
||||
|
||||
SYMBOL_NAME (sym) = SYMNAME_ALLOC (name, symname_alloced);
|
||||
SYMBOL_TYPE (sym) = lookup_function_type (builtin_type_int);
|
||||
SYMBOL_TYPE (sym) = lookup_function_type (lookup_fundamental_type (current_objfile, FT_INTEGER));
|
||||
|
||||
SYMBOL_CLASS (sym) = LOC_BLOCK;
|
||||
SYMBOL_DUP (sym, sym2);
|
||||
@ -783,7 +844,7 @@ process_xcoff_symbol (cs)
|
||||
else {
|
||||
|
||||
/* in case we can't figure out the type, default is `int'. */
|
||||
SYMBOL_TYPE (sym) = builtin_type_int;
|
||||
SYMBOL_TYPE (sym) = lookup_fundamental_type (current_objfile, FT_INTEGER);
|
||||
|
||||
switch (cs->c_sclass)
|
||||
{
|
||||
@ -795,12 +856,12 @@ process_xcoff_symbol (cs)
|
||||
break;
|
||||
|
||||
case C_DECL: /* a type decleration?? */
|
||||
qq = (char*) index (name, ':');
|
||||
qq = (char*) strchr (name, ':');
|
||||
if (!qq) /* skip if there is no ':' */
|
||||
return NULL;
|
||||
|
||||
pp = qq + 2;
|
||||
ttype = SYMBOL_TYPE (sym) = read_type (&pp);
|
||||
ttype = SYMBOL_TYPE (sym) = read_type (&pp, objfile);
|
||||
|
||||
/* read_type() will return null if type (or tag) definition was
|
||||
unnnecessarily duplicated. Also, if the symbol doesn't have a name,
|
||||
@ -819,7 +880,7 @@ process_xcoff_symbol (cs)
|
||||
}
|
||||
|
||||
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
|
||||
SYMBOL_NAME (sym) = obsavestring (name, qq-name);
|
||||
SYMBOL_NAME (sym) = obsavestring (name, qq-name, &objfile->symbol_obstack);
|
||||
|
||||
if (SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE)
|
||||
TYPE_NAME (ttype) = concat (
|
||||
@ -840,36 +901,36 @@ process_xcoff_symbol (cs)
|
||||
break;
|
||||
|
||||
case C_PSYM:
|
||||
if (*name == ':' || (pp = (char *) index (name, ':')) == NULL)
|
||||
if (*name == ':' || (pp = (char *) strchr (name, ':')) == NULL)
|
||||
return NULL;
|
||||
SYMBOL_NAME (sym) = obsavestring (name, pp-name);
|
||||
SYMBOL_NAME (sym) = obsavestring (name, pp-name, &objfile -> symbol_obstack);
|
||||
SYMBOL_CLASS (sym) = LOC_ARG;
|
||||
pp += 2;
|
||||
SYMBOL_TYPE (sym) = read_type (&pp);
|
||||
SYMBOL_TYPE (sym) = read_type (&pp, objfile);
|
||||
SYMBOL_DUP (sym, sym2);
|
||||
add_symbol_to_list (sym2, &local_symbols);
|
||||
break;
|
||||
|
||||
case C_STSYM:
|
||||
if (*name == ':' || (pp = (char *) index (name, ':')) == NULL)
|
||||
if (*name == ':' || (pp = (char *) strchr (name, ':')) == NULL)
|
||||
return NULL;
|
||||
SYMBOL_NAME (sym) = obsavestring (name, pp-name);
|
||||
SYMBOL_NAME (sym) = obsavestring (name, pp-name, &objfile -> symbol_obstack);
|
||||
SYMBOL_CLASS (sym) = LOC_STATIC;
|
||||
SYMBOL_VALUE (sym) += static_block_base;
|
||||
pp += 2;
|
||||
SYMBOL_TYPE (sym) = read_type (&pp);
|
||||
SYMBOL_TYPE (sym) = read_type (&pp, objfile);
|
||||
SYMBOL_DUP (sym, sym2);
|
||||
add_symbol_to_list
|
||||
(sym2, within_function ? &local_symbols : &file_symbols);
|
||||
break;
|
||||
|
||||
case C_LSYM:
|
||||
if (*name == ':' || (pp = (char *) index (name, ':')) == NULL)
|
||||
if (*name == ':' || (pp = (char *) strchr (name, ':')) == NULL)
|
||||
return NULL;
|
||||
SYMBOL_NAME (sym) = obsavestring (name, pp-name);
|
||||
SYMBOL_NAME (sym) = obsavestring (name, pp-name, &objfile -> symbol_obstack);
|
||||
SYMBOL_CLASS (sym) = LOC_LOCAL;
|
||||
pp += 1;
|
||||
SYMBOL_TYPE (sym) = read_type (&pp);
|
||||
SYMBOL_TYPE (sym) = read_type (&pp, objfile);
|
||||
SYMBOL_DUP (sym, sym2);
|
||||
add_symbol_to_list (sym2, &local_symbols);
|
||||
break;
|
||||
@ -905,21 +966,22 @@ process_xcoff_symbol (cs)
|
||||
break;
|
||||
|
||||
case C_RSYM:
|
||||
pp = (char*) index (name, ':');
|
||||
pp = (char*) strchr (name, ':');
|
||||
SYMBOL_CLASS (sym) = LOC_REGISTER;
|
||||
SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (cs->c_value);
|
||||
if (pp) {
|
||||
SYMBOL_NAME (sym) = obsavestring (name, pp-name);
|
||||
SYMBOL_NAME (sym) = obsavestring (name, pp-name, &objfile -> symbol_obstack);
|
||||
pp += 2;
|
||||
if (*pp)
|
||||
SYMBOL_TYPE (sym) = read_type (&pp);
|
||||
SYMBOL_TYPE (sym) = read_type (&pp, objfile);
|
||||
}
|
||||
else
|
||||
/* else this is not a stab entry, suppose the type is either
|
||||
`int' or `float', depending on the register class. */
|
||||
|
||||
SYMBOL_TYPE (sym) = (SYMBOL_VALUE (sym) < 32) ?
|
||||
builtin_type_int : builtin_type_float;
|
||||
SYMBOL_TYPE (sym) = (SYMBOL_VALUE (sym) < 32)
|
||||
? lookup_fundamental_type (current_objfile, FT_INTEGER)
|
||||
: lookup_fundamental_type (current_objfile, FT_FLOAT);
|
||||
|
||||
SYMBOL_DUP (sym, sym2);
|
||||
add_symbol_to_list (sym2, &local_symbols);
|
||||
@ -986,7 +1048,7 @@ static void
|
||||
find_linenos(abfd, asect, vpinfo)
|
||||
bfd *abfd;
|
||||
sec_ptr asect;
|
||||
void *vpinfo;
|
||||
PTR vpinfo;
|
||||
{
|
||||
struct coff_symfile_info *info;
|
||||
int size, count;
|
||||
@ -1033,12 +1095,12 @@ init_lineno (abfd, offset, size)
|
||||
|
||||
linetab_offset = offset;
|
||||
linetab_size = size;
|
||||
make_cleanup(free, linetab); /* Be sure it gets de-allocated. */
|
||||
make_cleanup (free, linetab); /* Be sure it gets de-allocated. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
static void
|
||||
dump_strtbl ()
|
||||
{
|
||||
int ii;
|
||||
@ -1048,7 +1110,7 @@ dump_strtbl ()
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
dump_linetable (ltb)
|
||||
struct linetable *ltb;
|
||||
{
|
||||
@ -1057,17 +1119,14 @@ dump_linetable (ltb)
|
||||
printf ("line: %d, addr: 0x%x\n", ltb->item[ii].line, ltb->item[ii].pc);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
dump_type (typeP)
|
||||
struct type *typeP;
|
||||
{
|
||||
printf ("0x%x: name: %s\n", typeP, typeP->name ? typeP->name : "(nil)");
|
||||
}
|
||||
|
||||
char *dump_namespace ();
|
||||
char *dump_addrclass ();
|
||||
|
||||
void
|
||||
static void
|
||||
dump_symbol (pp)
|
||||
struct symbol *pp;
|
||||
{
|
||||
@ -1079,8 +1138,7 @@ dump_symbol (pp)
|
||||
SYMBOL_CLASS(pp) == LOC_BLOCK ? BLOCK_END(SYMBOL_BLOCK_VALUE(pp)) : 0);
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
static char *
|
||||
dump_namespace (ns)
|
||||
int ns;
|
||||
{
|
||||
@ -1098,8 +1156,7 @@ int ns;
|
||||
return "***ERROR***";
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
static char *
|
||||
dump_addrclass (ac)
|
||||
int ac; /* address class */
|
||||
{
|
||||
@ -1137,7 +1194,7 @@ int ac; /* address class */
|
||||
return "***ERROR***";
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
dump_block (pp)
|
||||
struct block *pp;
|
||||
{
|
||||
@ -1147,7 +1204,7 @@ dump_block (pp)
|
||||
dump_symbol (pp->sym[ii]);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
dump_blockvector (pp)
|
||||
struct blockvector *pp;
|
||||
{
|
||||
@ -1156,8 +1213,7 @@ dump_blockvector (pp)
|
||||
dump_block (pp->block [ii]);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
static void
|
||||
dump_last_symtab (pp)
|
||||
struct symtab *pp;
|
||||
{
|
||||
@ -1169,7 +1225,7 @@ dump_last_symtab (pp)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
dump_symtabs (pp)
|
||||
struct symtab *pp;
|
||||
{
|
||||
@ -1181,7 +1237,7 @@ dump_symtabs (pp)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
dump_symtab_lines (pp)
|
||||
struct symtab *pp;
|
||||
{
|
||||
@ -1193,14 +1249,16 @@ dump_symtab_lines (pp)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dump_misc_funcs ()
|
||||
static void
|
||||
dump_minimal_symbols (objfile)
|
||||
struct objfile *objfile;
|
||||
{
|
||||
int ii;
|
||||
for (ii=0; ii < misc_function_count; ++ii)
|
||||
printf ("name: %s, addr: 0x%x\n",
|
||||
misc_function_vector[ii].name,
|
||||
misc_function_vector[ii].address);
|
||||
struct minimal_symbol *msymbol;
|
||||
|
||||
for (msymbol = objfile -> msymbols; msymbol -> name != NULL; msymbol++)
|
||||
{
|
||||
printf ("name: %s, addr: 0x%x\n", msymbol -> name, msymbol -> address);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1235,77 +1293,85 @@ char **pp;
|
||||
/* default types are defined in dbxstclass.h. */
|
||||
switch ( typenums[1] ) {
|
||||
case 1:
|
||||
return builtin_type_int;
|
||||
return lookup_fundamental_type (current_objfile, FT_INTEGER);
|
||||
case 2:
|
||||
return builtin_type_char;
|
||||
return lookup_fundamental_type (current_objfile, FT_CHAR);
|
||||
case 3:
|
||||
return builtin_type_short;
|
||||
return lookup_fundamental_type (current_objfile, FT_SHORT);
|
||||
case 4:
|
||||
return builtin_type_long;
|
||||
return lookup_fundamental_type (current_objfile, FT_LONG);
|
||||
case 5:
|
||||
return builtin_type_unsigned_char;
|
||||
return lookup_fundamental_type (current_objfile, FT_UNSIGNED_CHAR);
|
||||
case 6:
|
||||
return builtin_type_char; /* requires a builtin `signed char' */
|
||||
return lookup_fundamental_type (current_objfile, FT_SIGNED_CHAR);
|
||||
case 7:
|
||||
return builtin_type_unsigned_short;
|
||||
return lookup_fundamental_type (current_objfile, FT_UNSIGNED_SHORT);
|
||||
case 8:
|
||||
return builtin_type_unsigned_int;
|
||||
return lookup_fundamental_type (current_objfile, FT_UNSIGNED_INTEGER);
|
||||
case 9:
|
||||
return builtin_type_unsigned_int;
|
||||
return lookup_fundamental_type (current_objfile, FT_UNSIGNED_INTEGER);
|
||||
case 10:
|
||||
return builtin_type_unsigned_long;
|
||||
return lookup_fundamental_type (current_objfile, FT_UNSIGNED_LONG);
|
||||
case 11:
|
||||
return builtin_type_void;
|
||||
return lookup_fundamental_type (current_objfile, FT_VOID);
|
||||
case 12:
|
||||
return builtin_type_float;
|
||||
return lookup_fundamental_type (current_objfile, FT_FLOAT);
|
||||
case 13:
|
||||
return builtin_type_double;
|
||||
return lookup_fundamental_type (current_objfile, FT_DBL_PREC_FLOAT);
|
||||
case 14:
|
||||
return builtin_type_double; /* requires a builtin `long double' */
|
||||
return lookup_fundamental_type (current_objfile, FT_EXT_PREC_FLOAT);
|
||||
case 15:
|
||||
return builtin_type_int; /* requires a builtin `integer' */
|
||||
/* requires a builtin `integer' */
|
||||
return lookup_fundamental_type (current_objfile, FT_INTEGER);
|
||||
case 16:
|
||||
return builtin_type_int; /* requires builtin `boolean' */
|
||||
return lookup_fundamental_type (current_objfile, FT_BOOLEAN);
|
||||
case 17:
|
||||
return builtin_type_float; /* requires builtin `short real' */
|
||||
/* requires builtin `short real' */
|
||||
return lookup_fundamental_type (current_objfile, FT_FLOAT);
|
||||
case 18:
|
||||
return builtin_type_float; /* requires builtin `real' */
|
||||
/* requires builtin `real' */
|
||||
return lookup_fundamental_type (current_objfile, FT_FLOAT);
|
||||
default :
|
||||
printf ("ERROR! Unknown builtin type -%d\n", typenums[1]);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 /* Seems to be unused, don't bother converting from old misc function
|
||||
vector usage to new minimal symbol tables. FIXME: Delete this? */
|
||||
|
||||
/* if we now nothing about a function but its address, make a function symbol
|
||||
out of it with the limited knowladge you have. This will be used when
|
||||
somebody refers to a function, which doesn't exist in the symbol table,
|
||||
but in misc_function_vector. */
|
||||
but is in the minimal symbol table. */
|
||||
|
||||
struct symbol *
|
||||
build_function_symbol (ind)
|
||||
build_function_symbol (ind, objfile)
|
||||
int ind;
|
||||
struct objfile *objfile;
|
||||
{
|
||||
struct symbol *sym =
|
||||
(struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol));
|
||||
(struct symbol *) obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol));
|
||||
SYMBOL_NAME (sym) = misc_function_vector[ind].name;
|
||||
/* SYMBOL_VALUE (sym) = misc_function_vector[ind].address; */
|
||||
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
|
||||
SYMBOL_CLASS (sym) = LOC_BLOCK;
|
||||
SYMBOL_TYPE (sym) = lookup_function_type (builtin_type_int);
|
||||
SYMBOL_TYPE (sym) = lookup_function_type (lookup_fundamental_type (current_objfile, FT_INTEGER));
|
||||
SYMBOL_BLOCK_VALUE (sym) = (struct block *)
|
||||
obstack_alloc (symbol_obstack, sizeof (struct block));
|
||||
obstack_alloc (&objfile->symbol_obstack, sizeof (struct block));
|
||||
BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) = misc_function_vector[ind].address;
|
||||
return sym;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
static void
|
||||
aixcoff_new_init ()
|
||||
{
|
||||
/* Nothin' to do. */
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
aixcoff_symfile_init (sf)
|
||||
struct sym_fns *sf;
|
||||
{
|
||||
@ -1331,9 +1397,10 @@ struct sym_fns *sf;
|
||||
|
||||
|
||||
static int
|
||||
init_stringtab(abfd, offset)
|
||||
init_stringtab(abfd, offset, objfile)
|
||||
bfd *abfd;
|
||||
long offset;
|
||||
struct objfile *objfile;
|
||||
{
|
||||
long length;
|
||||
int val;
|
||||
@ -1354,7 +1421,7 @@ init_stringtab(abfd, offset)
|
||||
/* Allocate string table from symbol_obstack. We will need this table
|
||||
as long as we have its symbol table around. */
|
||||
|
||||
strtbl = (char*) obstack_alloc (symbol_obstack, length);
|
||||
strtbl = (char*) obstack_alloc (&objfile->symbol_obstack, length);
|
||||
if (strtbl == NULL)
|
||||
return -1;
|
||||
|
||||
@ -1389,7 +1456,7 @@ init_debugsection(abfd)
|
||||
if (!(length = bfd_section_size(abfd, secp)))
|
||||
return 0;
|
||||
|
||||
debugsec = (void *) xmalloc ((unsigned)length);
|
||||
debugsec = (char *) xmalloc ((unsigned)length);
|
||||
if (debugsec == NULL)
|
||||
return -1;
|
||||
|
||||
@ -1411,7 +1478,7 @@ free_debugsection()
|
||||
|
||||
/* aixcoff version of symbol file read. */
|
||||
|
||||
void
|
||||
static void
|
||||
aixcoff_symfile_read (sf, addr, mainline)
|
||||
struct sym_fns *sf;
|
||||
CORE_ADDR addr;
|
||||
@ -1449,7 +1516,7 @@ aixcoff_symfile_read (sf, addr, mainline)
|
||||
error("\"%s\": error reading line numbers\n", name);
|
||||
}
|
||||
|
||||
val = init_stringtab(abfd, stringtab_offset);
|
||||
val = init_stringtab(abfd, stringtab_offset, sf->objfile);
|
||||
if (val < 0) {
|
||||
error ("\"%s\": can't get string table", name);
|
||||
}
|
||||
@ -1466,8 +1533,8 @@ aixcoff_symfile_read (sf, addr, mainline)
|
||||
if (bfd_tell(abfd) != symtab_offset)
|
||||
fatal("bfd? BFD!");
|
||||
|
||||
init_misc_bunches ();
|
||||
make_cleanup(discard_misc_bunches, 0);
|
||||
init_minimal_symbol_collection ();
|
||||
make_cleanup (discard_minimal_symbols, 0);
|
||||
|
||||
#ifdef XCOFF_INIT_LOADINFO
|
||||
if (mainline)
|
||||
@ -1479,13 +1546,15 @@ aixcoff_symfile_read (sf, addr, mainline)
|
||||
|
||||
read_xcoff_symtab(sf->objfile, num_symbols);
|
||||
|
||||
make_cleanup(free_debugsection, 0);
|
||||
make_cleanup (free_debugsection, 0);
|
||||
|
||||
/* Sort symbols alphabetically within each block. */
|
||||
sort_syms ();
|
||||
|
||||
/* Go over the misc functions and install them in vector. */
|
||||
condense_misc_bunches (!mainline);
|
||||
/* Install any minimal symbols that have been collected as the current
|
||||
minimal symbols for this objfile. */
|
||||
|
||||
install_minimal_symbols (!mainline, sf -> objfile);
|
||||
|
||||
/* Make a default for file to list. */
|
||||
select_source_symtab (0);
|
||||
|
Loading…
Reference in New Issue
Block a user